PX4 Teleop
px4_teleop_com.cpp
Go to the documentation of this file.
1 
7 // C/C++ libraries
8 #include <iostream>
9 #include <string>
10 #include <vector>
11 #include <sstream>
12 #include <csignal>
13 
14 // roscpp
15 #include <ros/ros.h>
16 
17 // geometry_msgs
18 #include <geometry_msgs/TwistStamped.h>
19 #include <geometry_msgs/PoseStamped.h>
20 
21 // sensor_msgs
22 #include <sensor_msgs/NavSatFix.h>
23 
24 // mavros_msgs
25 #include <mavros_msgs/CommandBool.h>
26 #include <mavros_msgs/SetMode.h>
27 #include <mavros_msgs/State.h>
28 #include <mavros_msgs/CommandTOL.h>
29 #include <mavros_msgs/CommandHome.h>
30 
31 // Header from px4_teleop
32 #include <px4_teleop_cmds.hpp>
33 
34 // Set signal handler
35 // std::signal() returns a pointer to the handler function
36 // that was in charge of handling this signal before the call of std::signal()
38 void (*old)(int);
39 
40 
42 mavros_msgs::State current_state;
43 
48 void state_cb(const mavros_msgs::State::ConstPtr& msg){
49  current_state = *msg;
50 }
51 
52 
54 sensor_msgs::NavSatFix curr_gpos;
55 
60 void curr_gpos_cb(const sensor_msgs::NavSatFix::ConstPtr& msg){
61  curr_gpos = *msg;
62 }
63 
64 
66 geometry_msgs::PoseStamped local_pos;
71 void local_pos_cb(const geometry_msgs::PoseStamped::ConstPtr& msg){
72  local_pos = *msg;
73 }
74 
78 void printUsage(){
79  std::cout << "Available Commands:" << std::endl;
80  std::cout << "\tarm" << std::endl;
81  std::cout << "\tdisarm" << std::endl;
82  std::cout << "\ttakeoff" << std::endl;
83  std::cout << "\tland" << std::endl;
84  std::cout << "\tcmd_vel" << std::endl;
85  std::cout << "\thelp" << std::endl;
86  std::cout << "\tquit" << std::endl;
87 }
88 
93 void interrupt_handler(int sig){
94  std::signal(sig, old);
95  exit(0);
96 }
97 
98 int main(int argc, char** argv){
99 
100  ros::init(argc, argv, "px4_teleop_com");
101  ros::NodeHandle nh;
102 
103  // Subscriber
104  ros::Subscriber state_sub = nh.subscribe<mavros_msgs::State>
105  ("mavros/state", 100, state_cb);
106  ros::Subscriber curr_gpos_sub = nh.subscribe<sensor_msgs::NavSatFix>
107  ("mavros/global_position/pose", 10, curr_gpos_cb);
108  ros::Subscriber local_pos_sub = nh.subscribe<geometry_msgs::PoseStamped>
109  ("mavros/local_position/pose", 100, local_pos_cb);
110 
111  // Publisher
112  ros::Publisher target_vel_pub = nh.advertise<geometry_msgs::TwistStamped>
113  ("mavros/setpoint_velocity/cmd_vel", 100);
114 
115  // Survice Client
116  ros::ServiceClient arming_client = nh.serviceClient<mavros_msgs::CommandBool>
117  ("mavros/cmd/arming");
118  ros::ServiceClient set_hp_client = nh.serviceClient<mavros_msgs::CommandHome>
119  ("mavros/cmd/set_home");
120  ros::ServiceClient takeoff_client = nh.serviceClient<mavros_msgs::CommandTOL>
121  ("mavros/cmd/takeoff");
122  ros::ServiceClient landing_client = nh.serviceClient<mavros_msgs::CommandTOL>
123  ("mavros/cmd/land");
124  ros::ServiceClient set_mode_client = nh.serviceClient<mavros_msgs::SetMode>
125  ("mavros/set_mode");
126 
127  ros::Rate rate(20);
128 
129  // Command string and vector of commands
130  std::string command, buffer;
131  std::vector<std::string> command_args;
132 
133  // Set signal handler
134  // std::signal() returns a pointer to the handler function
135  // that was in charge of handling this signal before the call of std::signal()
136  old = std::signal(SIGINT, interrupt_handler);
137 
138  // Wait for connection
139  while(ros::ok() and current_state.connected){
140  ros::spinOnce();
141  rate.sleep();
142  }
143 
144  // Wait for /mavros/global_position/global
145  ROS_INFO("Waiting for message from /mavros/global_position/global");
146  const std::string topic = "mavros/global_position/global";
147  sensor_msgs::NavSatFix init_gpos = *ros::topic::waitForMessage<sensor_msgs::NavSatFix>(topic);
148  double init_latitude = init_gpos.latitude;
149  double init_longitude = init_gpos.longitude;
150  double init_altitude = init_gpos.altitude;
151  ROS_INFO("Initial Lat:%f Lon:%f Alt:%f", init_latitude, init_longitude, init_altitude);
152 
153  // set home position as current position
154  mavros_msgs::CommandHome set_hp_cmd;
155  set_hp_cmd.request.current_gps = true;
156  while( not(set_hp_client.call(set_hp_cmd)) and
157  set_hp_cmd.response.success){
158  ros::spinOnce();
159  rate.sleep();
160  }
161  ROS_INFO("HP set.");
162 
163  // set mode as offboard
164  mavros_msgs::SetMode offb_set_mode;
165  offb_set_mode.request.custom_mode = "OFFBOARD";
166 
167  while( not(set_mode_client.call(offb_set_mode))){
168  ros::spinOnce();
169  rate.sleep();
170  }
171  ROS_INFO("Offboard enabled.");
172 
173 
174  while(ros::ok()){
175 
176  // Wait for input
177  std::cout << "com> ";
178  std::getline(std::cin, command);
179  if(std::cin.fail() or std::cin.eof()){
180  std::cin.clear();
181  }
182 
183  std::stringstream ss(command);
184 
185  command_args.clear();
186  command_args.shrink_to_fit();
187 
188  while(not ss.eof()){
189  ss >> buffer;
190  command_args.push_back(buffer);
191  }
192 
193  if(command_args[0]=="arm" and command_args.size()==1)
194  {
195  arm(arming_client, current_state);
196  }
197  else if(command_args[0]=="takeoff" and command_args.size()<3)
198  {
199  try{
200  takeoff(takeoff_client, current_state,
201  local_pos, init_gpos,
202  std::stod(command_args.at(1)));
203  }catch(...){
204  std::cout << "Invalid argument." << std::endl;
205  std::cout << "Usage:\n\ttakeoff height" << std::endl;
206  }
207  }
208  else if(command_args[0]=="land" and command_args.size()==1)
209  {
210  land(landing_client, local_pos, curr_gpos, init_gpos);
211  }
212  else if(command_args[0]=="disarm" and command_args.size()==1)
213  {
214  disarm(arming_client);
215  }
216  else if(command_args[0]=="help" and command_args.size()==1)
217  {
218  printUsage();
219  }
220  else if(command_args[0]=="quit" and command_args.size()==1)
221  {
222  exit(0);
223  }
224  else if(command_args[0]=="cmd_vel" and command_args.size()<8)
225  {
226  try{
227  cmd_vel(target_vel_pub, set_mode_client,
229  std::stod(command_args.at(1)),
230  std::stod(command_args.at(2)),
231  std::stod(command_args.at(3)),
232  std::stod(command_args.at(4)),
233  std::stod(command_args.at(5)));
234  }catch(...){
235  std::cout << "Invalid argument." << std::endl;
236  std::cout << "Usage:\n\tcmd_vel dt vx vy vz ang_z" << std::endl;
237  }
238  }
239  else
240  {
241  std::cout << "Invalid command." << std::endl;
242  std::cout << "Type \"help\" to print available commands." << std::endl;
243  }
244 
245  ros::spinOnce();
246  rate.sleep();
247  }
248 
249  // Restore initial handler
250  std::signal(SIGINT, old);
251  return 0;
252 }
void local_pos_cb(const geometry_msgs::PoseStamped::ConstPtr &msg)
Callback function for local position subscriber.
void disarm(ros::ServiceClient &client)
Disarm vehicle.
void takeoff(ros::ServiceClient &client, mavros_msgs::State &state, geometry_msgs::PoseStamped &lpos, sensor_msgs::NavSatFix &hp, double height)
Take off vehicle.
geometry_msgs::PoseStamped local_pos
Storage for local position.
void land(ros::ServiceClient &client, geometry_msgs::PoseStamped &lpos, sensor_msgs::NavSatFix &gpos, sensor_msgs::NavSatFix &hp)
Land vehicle.
int main(int argc, char **argv)
sensor_msgs::NavSatFix curr_gpos
Storage for current global position.
mavros_msgs::State current_state
Storage for vehicle state.
void printUsage()
Prints a list of available commands.
void arm(ros::ServiceClient &client, mavros_msgs::State &state)
Arm vehicle.
void cmd_vel(ros::Publisher &pub, ros::ServiceClient &client, mavros_msgs::State &state, double dt, double vx, double vy, double vz, double ang_z)
Send velocity command to vehicle.
void state_cb(const mavros_msgs::State::ConstPtr &msg)
Callback function for state subscriber.
void(* old)(int)
Pointer to old handler function.
Command functions for px4_teleop package.
void interrupt_handler(int sig)
Handles interrupt signal from kyeboard.
void curr_gpos_cb(const sensor_msgs::NavSatFix::ConstPtr &msg)
Callback function for global position subscriber.