14 #include <ros/package.h> 18 #include <sensor_msgs/Joy.h> 21 #include <geometry_msgs/TwistStamped.h> 22 #include <geometry_msgs/Vector3.h> 25 #include <mavros_msgs/CommandBool.h> 26 #include <mavros_msgs/CommandHome.h> 27 #include <mavros_msgs/CommandTOL.h> 28 #include <mavros_msgs/SetMode.h> 29 #include <mavros_msgs/State.h> 35 #include <yaml-cpp/yaml.h> 52 void state_cb(
const mavros_msgs::State::ConstPtr& msg)
87 void joy_cb(
const sensor_msgs::Joy::ConstPtr& msg)
92 int main(
int argc,
char** argv)
94 ros::init(argc, argv,
"px4_teleop_joy");
95 ros::NodeHandle nh(
"~");
100 ros::Publisher cmd_vel_pub = nh.advertise<geometry_msgs::TwistStamped>(
"/mavros/setpoint_velocity/cmd_vel", 100);
103 ros::Subscriber joy_sub = nh.subscribe<sensor_msgs::Joy>(
"/joy", 100,
joy_cb);
104 ros::Subscriber state_sub = nh.subscribe<mavros_msgs::State>(
"/mavros/state", 100,
state_cb);
105 ros::Subscriber curr_gpos_sub =
106 nh.subscribe<sensor_msgs::NavSatFix>(
"/mavros/global_position/pose", 10,
curr_gpos_cb);
107 ros::Subscriber local_pos_sub =
108 nh.subscribe<geometry_msgs::PoseStamped>(
"/mavros/local_position/pose", 100,
local_pos_cb);
111 ros::ServiceClient set_hp_client = nh.serviceClient<mavros_msgs::CommandHome>(
"/mavros/cmd/set_home");
112 ros::ServiceClient arming_client = nh.serviceClient<mavros_msgs::CommandBool>(
"/mavros/cmd/arming");
113 ros::ServiceClient takeoff_client = nh.serviceClient<mavros_msgs::CommandTOL>(
"/mavros/cmd/takeoff");
114 ros::ServiceClient landing_client = nh.serviceClient<mavros_msgs::CommandTOL>(
"/mavros/cmd/land");
115 ros::ServiceClient set_mode_client = nh.serviceClient<mavros_msgs::SetMode>(
"/mavros/set_mode");
118 std::string joy_config_path;
119 nh.param<std::string>(
"joy_config_path", joy_config_path,
px4_teleop_path +
"/config/f710.yaml");
122 std::string joy_binding_path;
123 nh.param<std::string>(
"joy_binding_path", joy_binding_path,
px4_teleop_path +
"/config/f310_binding.yaml");
127 nh.param<
int>(
"joy_rc_mode", joy_rc_mode, 1);
130 float takeoff_height;
131 nh.param<
float>(
"takeoff_height", takeoff_height, 2.0);
134 std::string mav_frame;
135 nh.param<std::string>(
"/mavros/setpoint_velocity/mav_frame", mav_frame,
"LOCAL_NED");
137 ROS_INFO(
"RC Mode: %d", joy_rc_mode);
138 ROS_INFO(
"Config: %s", joy_config_path.c_str());
139 ROS_INFO(
"MAV_FRAME: %s", mav_frame.c_str());
145 config = YAML::LoadFile(joy_config_path);
147 catch (YAML::Exception& e)
149 ROS_ERROR(
"Failed to read config file");
157 binding = YAML::LoadFile(joy_binding_path);
159 catch (YAML::Exception& e)
161 ROS_ERROR(
"Failed to read binding file");
169 config = config[
"mode1"];
172 config = config[
"mode2"];
184 ROS_INFO(
"Waiting for message from /mavros/global_position/global");
185 const std::string topic =
"/mavros/global_position/global";
186 sensor_msgs::NavSatFix init_gpos = *ros::topic::waitForMessage<sensor_msgs::NavSatFix>(topic);
187 double init_latitude = init_gpos.latitude;
188 double init_longitude = init_gpos.longitude;
189 double init_altitude = init_gpos.altitude;
190 ROS_INFO(
"Initial Lat:%f Lon:%f Alt:%f", init_latitude, init_longitude, init_altitude);
193 mavros_msgs::CommandHome set_hp_cmd;
194 set_hp_cmd.request.current_gps =
true;
195 while (not(set_hp_client.call(set_hp_cmd)) and set_hp_cmd.response.success)
203 mavros_msgs::SetMode offb_set_mode;
204 offb_set_mode.request.custom_mode =
"OFFBOARD";
206 while (not(set_mode_client.call(offb_set_mode)))
211 ROS_INFO(
"Offboard enabled.");
213 ros::Time last_request = ros::Time::now();
214 ros::Time button_last_event = ros::Time::now();
218 ROS_INFO(
"===== BUTTON BINDING =====");
219 ROS_INFO(
"ARM \t: %s",
220 binding[
"buttons"][config[
"button_map"][
"arm"].as<std::string>()].as<std::string>().c_str());
221 ROS_INFO(
"TAKEOFF \t: %s",
222 binding[
"buttons"][config[
"button_map"][
"takeoff"].as<std::string>()].as<std::string>().c_str());
223 ROS_INFO(
"LAND \t: %s",
224 binding[
"buttons"][config[
"button_map"][
"land"].as<std::string>()].as<std::string>().c_str());
225 ROS_INFO(
"DISARM \t: %s",
226 binding[
"buttons"][config[
"button_map"][
"disarm"].as<std::string>()].as<std::string>().c_str());
227 ROS_INFO(
"DEADMAN \t: %s",
228 binding[
"buttons"][config[
"button_map"][
"deadman"].as<std::string>()].as<std::string>().c_str());
231 ROS_INFO(
"===== AXES BINDING =====");
232 ROS_INFO(
"PITCH \t: %s", binding[
"axes"][config[
"axes_map"][
"pitch"].as<std::string>()].as<std::string>().c_str());
233 ROS_INFO(
"YAW \t: %s", binding[
"axes"][config[
"axes_map"][
"yaw"].as<std::string>()].as<std::string>().c_str());
234 ROS_INFO(
"ROLL \t: %s", binding[
"axes"][config[
"axes_map"][
"roll"].as<std::string>()].as<std::string>().c_str());
235 ROS_INFO(
"THROTTLE\t: %s",
236 binding[
"axes"][config[
"axes_map"][
"throttle"].as<std::string>()].as<std::string>().c_str());
239 ROS_INFO(
"===== AXES SCALING =====");
240 ROS_INFO(
"PITCH \t: %f", config[
"axes_scale"][
"pitch"].as<double>());
241 ROS_INFO(
"YAW \t: %f", config[
"axes_scale"][
"yaw"].as<double>());
242 ROS_INFO(
"ROLL \t: %f", config[
"axes_scale"][
"roll"].as<double>());
243 ROS_INFO(
"THROTTLE\t: %f", config[
"axes_scale"][
"throttle"].as<double>());
247 std::vector<float> joy_axes;
248 std::vector<int32_t> joy_button;
258 if (
current_state.mode !=
"OFFBOARD" and (ros::Time::now() - last_request > ros::Duration(0.1)))
260 if ((set_mode_client.call(offb_set_mode)))
262 ROS_DEBUG(
"Offboard enabled.");
264 last_request = ros::Time::now();
267 if(joy_axes.size()==0 or joy_button.size()==0)
272 geometry_msgs::TwistStamped cmd_vel_msg;
276 double lin_x = config[
"axes_scale"][
"pitch"].as<
double>() * joy_axes.at(config[
"axes_map"][
"pitch"].as<
int>());
277 double lin_y = config[
"axes_scale"][
"roll"].as<
double>() * joy_axes.at(config[
"axes_map"][
"roll"].as<
int>());
279 config[
"axes_scale"][
"throttle"].as<
double>() * joy_axes.at(config[
"axes_map"][
"throttle"].as<
int>());
280 double ang_z = config[
"axes_scale"][
"yaw"].as<
double>() * joy_axes.at(config[
"axes_map"][
"yaw"].as<
int>());
282 cmd_vel_msg.twist.linear.x = lin_x;
283 cmd_vel_msg.twist.linear.y = lin_y;
284 cmd_vel_msg.twist.linear.z = lin_z;
285 cmd_vel_msg.twist.angular.z = ang_z;
287 cmd_vel_pub.publish(cmd_vel_msg);
289 if (ros::Time::now() - button_last_event > ros::Duration(0.1))
291 if (joy_button.at(config[
"button_map"][
"deadman"].as<
int>()))
293 if (joy_button.at(config[
"button_map"][
"arm"].as<
int>()))
297 else if (joy_button.at(config[
"button_map"][
"disarm"].as<
int>()))
301 else if (joy_button.at(config[
"button_map"][
"takeoff"].as<
int>()))
305 else if (joy_button.at(config[
"button_map"][
"land"].as<
int>()))
309 else if (joy_button.at(config[
"button_map"][
"exit"].as<
int>()))
313 button_last_event = ros::Time::now();
317 catch (std::out_of_range& e)
319 ROS_ERROR(
"%s", e.what());
324 ROS_INFO(
"Exitting px4_teleop.");
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.
void land(ros::ServiceClient &client, geometry_msgs::PoseStamped &lpos, sensor_msgs::NavSatFix &gpos, sensor_msgs::NavSatFix &hp)
Land vehicle.
mavros_msgs::State current_state
Storage for vehicle state.
int main(int argc, char **argv)
void state_cb(const mavros_msgs::State::ConstPtr &msg)
Callback function for state subscriber.
const int RC_MODE_TWO
Rc mode constant.
sensor_msgs::NavSatFix curr_gpos
Storage for current global position.
const int RC_MODE_ONE
Rc mode constant.
void arm(ros::ServiceClient &client, mavros_msgs::State &state)
Arm vehicle.
geometry_msgs::PoseStamped local_pos
Storage for local position.
void joy_cb(const sensor_msgs::Joy::ConstPtr &msg)
Callback function for joystick input subscriber.
sensor_msgs::Joy joy_msg
Storage for joystick input.
const std::string px4_teleop_path
Storage for path of this package.
void curr_gpos_cb(const sensor_msgs::NavSatFix::ConstPtr &msg)
Callback function for global position subscriber.
Command functions for px4_teleop package.