forked from METUrone/ROSAPI
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommander.cpp
More file actions
308 lines (253 loc) · 9.53 KB
/
commander.cpp
File metadata and controls
308 lines (253 loc) · 9.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#include <ros/ros.h>
#include <geometry_msgs/PoseStamped.h>
#include <geometry_msgs/Twist.h>
#include <geometry_msgs/TwistStamped.h>
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>
#include <sensor_msgs/BatteryState.h>
#include <sensor_msgs/Image.h>
#include <move/PositionCommand.h>
#include <move/Battery.h>
#include <move/Position.h>
#include <move/Camera.h>
#include<vector>
// Holds the given command by the services provided
// Then sends the commands to drone in the main function
geometry_msgs::TwistStamped pose_command;
// Holds the pose of the drone
std::vector<geometry_msgs::PoseStamped> poses;
void setPoses(){
for(int i=0;i<10;i++){
geometry_msgs::PoseStamped pose;
poses.push_back(pose);
}
}
bool service_get_position(
move::Position::Request &req,
move::Position::Response &res
) {
//res.x = pose0.pose.position.x;
//res.y = pose0.pose.position.y;
//res.z = pose0.pose.position.z;
return true;
}
// When the service called,
// the requested x,y,z and t is put to the pose_command.
bool service_command_global_position(
move::PositionCommand::Request &req,
move::PositionCommand::Response &res
) {
ROS_INFO_STREAM("Move service is called");
/*
pose_command.pose.position.x = req.x;
pose_command.pose.position.y = req.y;
pose_command.pose.position.z = req.z;
*/
return true;
}
// When the service called,
// the requested x,y,z and t is added to the pose_command.
bool service_command_relative_position(
move::PositionCommand::Request &req,
move::PositionCommand::Response &res
) {
ROS_INFO_STREAM("Move service is called");
/*
pose_command.pose.position.x += req.x;
pose_command.pose.position.y += req.y;
pose_command.pose.position.z += req.z;
*/
return true;
}
// Holds the battery state.
sensor_msgs::BatteryState battery;
// Responses the voltage, current and remaining percentage of battery when the service called.
bool service_get_battery(
move::Battery::Request &req,
move::Battery::Response &res
) {
ROS_INFO_STREAM("Battery service is called");
res.voltage = battery.voltage;
res.current = battery.current;
res.remaining = battery.percentage;
return true;
}
// Holds the camera frame if there is a camera connected and running.
sensor_msgs::Image frame;
// True if camera is connected, false otherwise.
bool camera_connected=false;
// Responses the frame of the camera
// In response, gives height and width of the frame,
// frame step, the representation is big endian or not, and the actual data.
bool service_get_camera_frame(
move::Camera::Request &req,
move::Camera::Response &res
) {
if(!camera_connected){
ROS_ERROR_STREAM("You are using drone without a camera. Please use correct drone(3dr iris with fpv camera");
}
else{
res.height= frame.height;
res.width= frame.width;
res.step= frame.step;
res.is_bigendian= frame.is_bigendian ;
res.data= frame.data;
ROS_INFO_STREAM("Data size = step*rows"); //WTF is that really working?
ROS_INFO_STREAM("Encoding RGB8");
}
}
// This holds the current state of the drone
// Connected, the flight mode etc.
mavros_msgs::State current_state;
// Saves the state of the drone
void state_tracker(const mavros_msgs::State::ConstPtr& _current_state){
current_state = *_current_state;
}
// Saves the battery state of the drone
void battery_tracker(const sensor_msgs::BatteryState::ConstPtr& _battery){
battery = *_battery;
}
// Saves the frames of the FPV camera
void frame_save(const sensor_msgs::Image &_frame){
frame = _frame;
camera_connected=true; // Are there any other way to detect if camera is running?
}
// Saves the pose of the drone
void pose_tracker0(const geometry_msgs::PoseStamped::ConstPtr& _pose){
poses[0] = *_pose;
}
void pose_tracker1(const geometry_msgs::PoseStamped::ConstPtr& _pose){
poses[1] = *_pose;
}
void pose_tracker2(const geometry_msgs::PoseStamped::ConstPtr& _pose){
poses[2] = *_pose;
}
void pose_tracker3(const geometry_msgs::PoseStamped::ConstPtr& _pose){
poses[3] = *_pose;
}
void pose_tracker4(const geometry_msgs::PoseStamped::ConstPtr& _pose){
poses[4] = *_pose;
}
int main(int argc, char **argv){
// Initializing node
// ros::init(argc, argv, "commander");
std::string uav_number_str = argv[1];
ROS_INFO_STREAM(uav_number_str);
int uav_number = std::stoi(uav_number_str);
int dumb = 0;
ros::init(dumb,NULL,"UAV" + uav_number_str);
ros::NodeHandle nh;
pose_command.twist.linear.x = 0;
pose_command.twist.linear.y = 0;
pose_command.twist.linear.z = 5;
pose_command.twist.angular.x = 0;
pose_command.twist.angular.y = 0;
pose_command.twist.angular.z = 0;
// Subscriber topics
// Current state of the drone
ros::Subscriber state_sub = nh.subscribe<mavros_msgs::State>
("/uav" + uav_number_str +"/mavros/state", 10, state_tracker);
// FPV_cam connection
// ros::Subscriber camera_sub = nh.subscribe
// ("/iris_fpv_cam/usb_cam/image_raw", 10, frame_save);
// Current battery of the drone
ros::Subscriber battery_status = nh.subscribe<sensor_msgs::BatteryState>
("/uav" + uav_number_str +"/mavros/battery",10, battery_tracker);
// Current pose of the drone
setPoses();
ros::Subscriber position0 = nh.subscribe<geometry_msgs::PoseStamped>
("/uav0/mavros/local_position/pose",10, pose_tracker0);
ros::Subscriber position1 = nh.subscribe<geometry_msgs::PoseStamped>
("/uav1/mavros/local_position/pose",10, pose_tracker1);
ros::Subscriber position2 = nh.subscribe<geometry_msgs::PoseStamped>
("/uav2/mavros/local_position/pose",10, pose_tracker2);
ros::Subscriber position3 = nh.subscribe<geometry_msgs::PoseStamped>
("/uav3/mavros/local_position/pose",10, pose_tracker3);
ros::Subscriber position4 = nh.subscribe<geometry_msgs::PoseStamped>
("/uav4/mavros/local_position/pose",10, pose_tracker4);
// Advertised topics
// Used for giving commands to drone.
ros::Publisher relative_position_command_publisher = nh.advertise<geometry_msgs::TwistStamped>
("/uav" + uav_number_str +"/mavros/setpoint_velocity/cmd_vel", 10);
ROS_INFO_STREAM("/uav" + uav_number_str +"/mavros/setpoint_velocity/cmd_vel");
// Service Clients
// Changes arming status
ros::ServiceClient arm_command = nh.serviceClient<mavros_msgs::CommandBool>
("/uav" + uav_number_str +"/mavros/cmd/arming");
// Set flight mode
ros::ServiceClient set_flight_mode = nh.serviceClient<mavros_msgs::SetMode>
("/uav" + uav_number_str +"/mavros/set_mode");
// Service Servers
// These services are for external call.
// If you call these services from this file, you probably are doing something wrong.
ros::ServiceServer server_battery = nh.advertiseService(
"/uav" + uav_number_str + "/battery_status",
&service_get_battery
);
ros::ServiceServer server_camera_frame = nh.advertiseService(
"/uav" + uav_number_str + "/camera",
&service_get_camera_frame
);
ros::ServiceServer server_global_move_command = nh.advertiseService(
"/uav" + uav_number_str + "/position/command_global",
&service_command_global_position
);
ros::ServiceServer server_relative_move_command = nh.advertiseService(
"/uav" + uav_number_str + "/position/command_relative",
&service_command_relative_position
);
ros::ServiceServer server_position = nh.advertiseService(
"/uav" + uav_number_str + "/position/position",
&service_get_position
);
//the setpoint publishing rate MUST be faster than 2Hz
ros::Rate rate(20.0);
// wait for FCU connection
while(ros::ok() && !current_state.connected){
ros::spinOnce();
rate.sleep();
}
ROS_INFO_STREAM("came here");
//send a few setpoints before starting
for(int i = 100; ros::ok() && i > 0; --i){ // The number of loops may be decreased probably.
relative_position_command_publisher.publish(pose_command);
ros::spinOnce();
rate.sleep();
}
// Used for setting the flight mode
mavros_msgs::SetMode set_mode;
set_mode.request.custom_mode = "OFFBOARD";
// Used for sending arm command
mavros_msgs::CommandBool arm;
arm.request.value = true;
ros::Time last_request_time = ros::Time::now();
while(ros::ok()){
ROS_INFO_STREAM("in loop");
ROS_INFO_STREAM(current_state.mode);
ROS_INFO_STREAM(current_state.armed);
if( (current_state.mode != "AUTO.LOITER") && (ros::Time::now()-last_request_time > ros::Duration(5.0)) ){
if( set_flight_mode.call(set_mode) && set_mode.response.mode_sent){
ROS_INFO_STREAM("Offboard enabled");
}
last_request_time = ros::Time::now();
}
else{
if( !current_state.armed && (ros::Time::now() - last_request_time > ros::Duration(5.0)) ){
if( arm_command.call(arm) && arm.response.success){
ROS_INFO_STREAM("Vehicle armed");
}
last_request_time = ros::Time::now();
}
}
//Here we are constantly publishing the position.
relative_position_command_publisher.publish(pose_command);
ROS_INFO_STREAM("pose 0 ");
ROS_INFO_STREAM(poses[0].pose.position.z);
ROS_INFO_STREAM("pose 1 ");
ROS_INFO_STREAM(poses[1].pose.position.z);
ros::spinOnce();
rate.sleep();
}
return 0;
}