文章借鉴了这边博客https://blog.csdn.net/u014587147/article/details/75673110。
这篇文章记录下自己操作过程中遇到的问题,更加适合新手。
1、使用终端分别运行下面三个命令,启动小乌龟和键盘操控。
roscore rosrun turtlesim turtlesim_node rosrun turtlesim turtle_teleop_key
接下来,查看节点与话题之间的关系
rqt_graph
界面如下
椭圆内的是节点,横线上是话题。通过rqt_graph可以看到,小乌龟turtlesim节点订阅/turtle1/cmd_vel话题.那么,我们可以通过向这个话题发布消息来控制小乌龟。接下来查看话题的类型
rostopic type /turtle1/cmd_vel
结果如下
geometry_msgs/Twist
再查看这个话题发布哪些消息来控制乌龟
rosmsg show geometry_msgs/Twist
结果如下
geometry_msgs/Vector3 linear float64 x float64 y float64 z geometry_msgs/Vector3 angular float64 x float64 y float64 z
由之前的经验,小乌龟的运动主要有线速度和角速度来控制,即通过linear x和angular z控制。这在后面的编程中会用到。
2、下面要查看手柄各个按键的作用。
首先,查看手柄的接入端口
ls /dev/input/
很有可能会出现很多端口,手柄的端口主要是js0或者js1,想要确定到底是哪个,把手柄的蓝牙接收器拔了,看哪个端口没了就能确定了。然后安装手柄测试工具并测试手柄按键
sudo apt-get install jstest-gtk sudo jstest /dev/input/js0
Joystick (BETOP CONTROLLER) has 6 axes (X, Y, Z, Rz, Hat0X, Hat0Y) and 12 buttons (BtnX, BtnY, BtnZ, BtnTL, BtnTR, BtnTL2, BtnTR2, BtnSelect, BtnStart, BtnMode, BtnThumbL, BtnThumbR). Testing ... (interrupt to exit) Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off 9:off 10:off 11:off
终端显示阿修罗手柄有6个轴和12个按键(一个转动轴的上下和左右各算一个轴,由一个Axes显示。手柄实际按键只有11个)。
接下来,要自己动手测试每个按键所对应的点,按下手柄上的按键,终端数据会有相应的变化。
这里,我将用Axes[1]用来控制速度,Axes[2]用来控制角速度。即将Axes[1]赋值给linear x,Axes[2]赋值给angular z。
3、下面查看ROS手柄话题的类型
这里joy功能包可能需要自己下载,如果没有joy_node节点,请自行百度下载,然后编译运行
rosrun joy joy_node rostopic type /joy
结果:
sensor_msgs/Joy
rosmsg show sensor_msgs/Joy
结果:
std_msgs/Header header uint32 seq time stamp string frame_id float32[] axes int32[] buttons
4、接下来,编写代码,运行节点
首先
catkin_create_pkg js_turtle std_msgs roscpp
创建ROS包,进入包的src文件夹,创建js_turtle.cpp文件,写入以下代码,记得根据实际情况更改。
#include<ros/ros.h> #include<geometry_msgs/Twist.h> #include <sensor_msgs/Joy.h> #include<iostream> using namespace std; class Teleop { public: Teleop(); private: /* data */ void callback(const sensor_msgs::Joy::ConstPtr& Joy); ros::NodeHandle n; //实例化节点 ros::Subscriber sub ; ros::Publisher pub ; double vlinear,vangular;//我们控制乌龟的速度,是通过这两个变量调整 int axis_ang,axis_lin; //axes[]的键 }; Teleop::Teleop() { //下面按键的设置,一定要根据自己的实际情况来更改 n.param<int>("axis_linear",axis_lin,1); //默认axes[1]接收速度 n.param<int>("axis_angular",axis_ang,2);//默认axes[2]接收角度 n.param<double>("vel_linear",vlinear,1);//默认线速度1 m/s n.param<double>("vel_angular",vangular,1);//默认角速度1 单位rad/s pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",1);//将速度发给乌龟 sub = n.subscribe<sensor_msgs::Joy>("joy",10,&Teleop::callback,this); //订阅游戏手柄发来的数据 } void Teleop::callback(const sensor_msgs::Joy::ConstPtr& Joy) { geometry_msgs::Twist v; v.linear.x =Joy->axes[axis_lin]*vlinear; //将游戏手柄的数据乘以你想要的速度,然后发给乌龟 v.angular.z =Joy->axes[axis_ang]*vangular; ROS_INFO("linear:%.3lf angular:%.3lf",v.linear.x,v.angular.z); pub.publish(v); } int main(int argc,char** argv) { ros::init(argc, argv, "logteleop"); Teleop telelog; ros::spin(); return 0; }
然后,修改包的Cmake文件,找到以下两行代码,将代码前面的注释符删掉。
catkin_create_pkg js_turtle std_msgs roscpp target_link_libraries(${PROJECT_NAME}_node ${catkin_LIBRARIES} )
再到包目录下,创建luanch文件夹,进入文件夹,创建js_turtle.launch启动文件,将所有需要用的节点直接集合在一起,launch文件的内容如下,请根据实际情况修改
<launch> <node pkg="turtlesim" type="turtlesim_node" name="turtlesim" /> <node pkg="joy" type="joy_node" name="joystick"> <param name="dev" type="string" value="/dev/input/js0" /> <param name="deadzone" value="0.12" /> </node> <node pkg="js_turtle" type="js_turtle_node" name="js_turtle_node" /> </launch>
最后,编译运行,界面如下
https://github.com/bingo1766/js_turtle.git
这里仍然存在一个问题,就是没有办法一直按着手柄操控乌龟,大概一两秒就会停下,需要放开按键然后重新按下。
希望有大佬可以帮忙解答这个问题。