00001
00025 #include "geometry_msgs/Twist.h"
00026 #include "ros/ros.h"
00027 #include "sensor_msgs/Joy.h"
00028 #include "teleop_twist_joy/teleop_twist_joy.h"
00029
00030 #include <map>
00031 #include <string>
00032
00033
00034 namespace teleop_twist_joy
00035 {
00036
00042 struct TeleopTwistJoy::Impl
00043 {
00044 void joyCallback(const sensor_msgs::Joy::ConstPtr& joy);
00045 void sendCmdVelMsg(const sensor_msgs::Joy::ConstPtr& joy_msg, const std::string& which_map);
00046
00047 ros::Subscriber joy_sub;
00048 ros::Publisher cmd_vel_pub;
00049
00050 int enable_button;
00051 int enable_turbo_button;
00052
00053 std::map<std::string, int> axis_linear_map;
00054 std::map< std::string, std::map<std::string, double> > scale_linear_map;
00055
00056 std::map<std::string, int> axis_angular_map;
00057 std::map< std::string, std::map<std::string, double> > scale_angular_map;
00058
00059 bool sent_disable_msg;
00060 };
00061
00067 TeleopTwistJoy::TeleopTwistJoy(ros::NodeHandle* nh, ros::NodeHandle* nh_param)
00068 {
00069 pimpl_ = new Impl;
00070
00071 pimpl_->cmd_vel_pub = nh->advertise<geometry_msgs::Twist>("cmd_vel", 1, true);
00072 pimpl_->joy_sub = nh->subscribe<sensor_msgs::Joy>("joy", 1, &TeleopTwistJoy::Impl::joyCallback, pimpl_);
00073
00074 nh_param->param<int>("enable_button", pimpl_->enable_button, 0);
00075 nh_param->param<int>("enable_turbo_button", pimpl_->enable_turbo_button, -1);
00076
00077 if (nh_param->getParam("axis_linear", pimpl_->axis_linear_map))
00078 {
00079 nh_param->getParam("scale_linear", pimpl_->scale_linear_map["normal"]);
00080 nh_param->getParam("scale_linear_turbo", pimpl_->scale_linear_map["turbo"]);
00081 }
00082 else
00083 {
00084 nh_param->param<int>("axis_linear", pimpl_->axis_linear_map["x"], 1);
00085 nh_param->param<double>("scale_linear", pimpl_->scale_linear_map["normal"]["x"], 0.5);
00086 nh_param->param<double>("scale_linear_turbo", pimpl_->scale_linear_map["turbo"]["x"], 1.0);
00087 }
00088
00089 if (nh_param->getParam("axis_angular", pimpl_->axis_angular_map))
00090 {
00091 nh_param->getParam("scale_angular", pimpl_->scale_angular_map["normal"]);
00092 nh_param->getParam("scale_angular_turbo", pimpl_->scale_angular_map["turbo"]);
00093 }
00094 else
00095 {
00096 nh_param->param<int>("axis_angular", pimpl_->axis_angular_map["yaw"], 0);
00097 nh_param->param<double>("scale_angular", pimpl_->scale_angular_map["normal"]["yaw"], 0.5);
00098 nh_param->param<double>("scale_angular_turbo",
00099 pimpl_->scale_angular_map["turbo"]["yaw"], pimpl_->scale_angular_map["normal"]["yaw"]);
00100 }
00101
00102 ROS_INFO_NAMED("TeleopTwistJoy", "Teleop enable button %i.", pimpl_->enable_button);
00103 ROS_INFO_COND_NAMED(pimpl_->enable_turbo_button >= 0, "TeleopTwistJoy",
00104 "Turbo on button %i.", pimpl_->enable_turbo_button);
00105
00106 for (std::map<std::string, int>::iterator it = pimpl_->axis_linear_map.begin();
00107 it != pimpl_->axis_linear_map.end(); ++it)
00108 {
00109 ROS_INFO_NAMED("TeleopTwistJoy", "Linear axis %s on %i at scale %f.",
00110 it->first.c_str(), it->second, pimpl_->scale_linear_map["normal"][it->first]);
00111 ROS_INFO_COND_NAMED(pimpl_->enable_turbo_button >= 0, "TeleopTwistJoy",
00112 "Turbo for linear axis %s is scale %f.", it->first.c_str(), pimpl_->scale_linear_map["turbo"][it->first]);
00113 }
00114
00115 for (std::map<std::string, int>::iterator it = pimpl_->axis_angular_map.begin();
00116 it != pimpl_->axis_angular_map.end(); ++it)
00117 {
00118 ROS_INFO_NAMED("TeleopTwistJoy", "Angular axis %s on %i at scale %f.",
00119 it->first.c_str(), it->second, pimpl_->scale_angular_map["normal"][it->first]);
00120 ROS_INFO_COND_NAMED(pimpl_->enable_turbo_button >= 0, "TeleopTwistJoy",
00121 "Turbo for angular axis %s is scale %f.", it->first.c_str(), pimpl_->scale_angular_map["turbo"][it->first]);
00122 }
00123
00124 pimpl_->sent_disable_msg = false;
00125 }
00126
00127 double getVal(const sensor_msgs::Joy::ConstPtr& joy_msg, const std::map<std::string, int>& axis_map,
00128 const std::map<std::string, double>& scale_map, const std::string& fieldname)
00129 {
00130 if (axis_map.find(fieldname) == axis_map.end() ||
00131 scale_map.find(fieldname) == scale_map.end() ||
00132 joy_msg->axes.size() <= axis_map.at(fieldname))
00133 {
00134 return 0.0;
00135 }
00136
00137 return joy_msg->axes[axis_map.at(fieldname)] * scale_map.at(fieldname);
00138 }
00139
00140 void TeleopTwistJoy::Impl::sendCmdVelMsg(const sensor_msgs::Joy::ConstPtr& joy_msg,
00141 const std::string& which_map)
00142 {
00143
00144 geometry_msgs::Twist cmd_vel_msg;
00145
00146 cmd_vel_msg.linear.x = getVal(joy_msg, axis_linear_map, scale_linear_map[which_map], "x");
00147 cmd_vel_msg.linear.y = getVal(joy_msg, axis_linear_map, scale_linear_map[which_map], "y");
00148 cmd_vel_msg.linear.z = getVal(joy_msg, axis_linear_map, scale_linear_map[which_map], "z");
00149 cmd_vel_msg.angular.z = getVal(joy_msg, axis_angular_map, scale_angular_map[which_map], "yaw");
00150 cmd_vel_msg.angular.y = getVal(joy_msg, axis_angular_map, scale_angular_map[which_map], "pitch");
00151 cmd_vel_msg.angular.x = getVal(joy_msg, axis_angular_map, scale_angular_map[which_map], "roll");
00152
00153 cmd_vel_pub.publish(cmd_vel_msg);
00154 sent_disable_msg = false;
00155 }
00156
00157 void TeleopTwistJoy::Impl::joyCallback(const sensor_msgs::Joy::ConstPtr& joy_msg)
00158 {
00159 if (enable_turbo_button >= 0 &&
00160 joy_msg->buttons.size() > enable_turbo_button &&
00161 joy_msg->buttons[enable_turbo_button])
00162 {
00163 sendCmdVelMsg(joy_msg, "turbo");
00164 }
00165 else if (joy_msg->buttons.size() > enable_button &&
00166 joy_msg->buttons[enable_button])
00167 {
00168 sendCmdVelMsg(joy_msg, "normal");
00169 }
00170 else
00171 {
00172
00173
00174 if (!sent_disable_msg)
00175 {
00176
00177 geometry_msgs::Twist cmd_vel_msg;
00178 cmd_vel_pub.publish(cmd_vel_msg);
00179 sent_disable_msg = true;
00180 }
00181 }
00182 }
00183
00184 }