ROS中使用游戏手柄操控turtle
在ROS中,使用键盘控制turtle运动比较简单,下面主要对游戏手柄操控turtle进行代码说明和演示。
手柄如下:

上图中手柄上有两个操作杆。后面内容分为两个部分,一部分是单个操作杆(单轴)控制,另一部分是双操作杆(双轴)控制。但是这两部分内容主要不同在于轴的配置不同,体现在之后的.cpp代码有差异,其他并无差异。
一、基础的准备工作:
(1)创建工作空间
$ mkdir -p ~/catkin_workspace/src
$ cd ~/catkin_workspace/src
$ catkin_init_workspace
运行后在catkin_workspace--->src中会产生CMakeLists.txt文件,结果如下:

(2)编译工作空间
$ cd ~/catkin_workspace/
$ catkin_make
在终端中运行结果为:

在工作区间catkin_workspace中会产生build、devel文件夹和 .catkin_workspace文件,如下图所示:

(3)设置环境变量
$ source devel/setup.bash
运行结果为:

(4)检查环境变量
$ echo $ROS_PACKAGE_PATH
运行结果:

以上就是准备工作,在这个基础上,就可以在这个workspace上继续后续的代码编写了。
二、手柄连接测试
系统是Ubuntu18.04,在终端输入:
$ lsusb
运行结果:

红色框显示的正好是我的手柄的型号,说明手柄连接成功。
另一种测试是否连接成功的方法是,在终端输入:
$ ls /dev/input
运行结果为:

结果中出现了js0,也可能出现的是js1,不管是哪个,都说明手柄连接成功。
接下来,检验手柄上各个轴和键的对应关系,运行:
$ sudo jstest /dev/input/js0
运行结果为:

sudo 命令可以提高用户权限,因此要先输入密码。输入密码后,回车,就可以看到很多个Axes(轴)和Buttons(按钮),可以按手柄上的按钮或者摇动操作杆,就会看到终端上对应位置的数字的改变。
或者使用命令jstest-gtk,可以从可视化图上看到轴和按钮的个数以及对应关系。

运行结果为:


三、安装joy相关的包
需要订阅/joy话题,获取手柄上的信息,因此需要安装joy相关的包。
终端输入:
sudo apt-get install ros-melodic-joy
sudo apt-get install ros-melodic-joystick-drivers
注意要安装Ubuntu版本对应的Ros版本。本文中使用的Ubuntu18.04对应的Ros版本是melodic,可以在网上查询一下自己安装的Ubuntu对应的Ros版本,然后将其替换上述命令行中的“melodic”。
运行结果为:(因为我之前已经安装过,所以显示的是
接下来,运行代码验证以下joy包是否安装成功。
运行命令:
$ roscore
启动Ros Master,也就是启动节点管理器,这是必要的,启动Master之后节点才可以在Master上注册节点信息、设置话题类型等。
启动Ros Master的界面如下:

之后,运行joy_node命令:
$ rosrun joy joy_node
四、(单操作杆)手柄控制海龟
在catkin_workspace的src目录下创建control_turtle功能包,使用命令为:
$ catkin_create_pkg control_turtle roscpp rospy std_msgs geometry_msgs turtlesim
roscpp rospy std_msgs geometry_msgs turtlesim均为所需的依赖包。
运行结果为:(successfully出现即创建成功)

单个遥杆控制的.cpp代码为:
Single_teleop_turtle.cpp代码:
#include
#include
#include class TeleopTurtle
{
public:TeleopTurtle();private:// 处理手柄发送过来的信息void callback(const sensor_msgs::Joy::ConstPtr &joy);// 实例化ROS句柄ros::NodeHandle nh;// 定义订阅者对象,用来订阅手柄发送的数据ros::Subscriber sub;// 定义发布者对象,用来将手柄数据发布到乌龟控制话题上ros::Publisher pub;// 用来接收launch文件中设置的参数,绑定手柄摇杆、轴的映射int axis_linear, axis_angular;
};TeleopTurtle::TeleopTurtle()
{// 从参数服务器读取的参数nh.param("axis_linear", axis_linear, 1);nh.param("axis_angular", axis_angular, 2);pub = nh.advertise("/turtle1/cmd_vel", 1);sub = nh.subscribe("joy", 10, &TeleopTurtle::callback, this);
}void TeleopTurtle::callback(const sensor_msgs::Joy::ConstPtr &joy)
{geometry_msgs::Twist vel;// 将手柄摇杆轴拨动时值的输出赋值给乌龟的线速度和角速度vel.linear.x = joy->axes[axis_linear];vel.angular.z = joy->axes[axis_angular];ROS_INFO("当前线速度为:%.3lf ; 角速度为:%.3lf", vel.linear.x, vel.angular.z);pub.publish(vel);
}int main(int argc, char **argv)
{// 设置编码setlocale(LC_ALL, "");// 初始化ROS节点ros::init(argc, argv, "teleop_turtle");TeleopTurtle teleopTurtle;ros::spin();return 0;
}
双摇杆控制的.cpp代码为:
Double_teleop_turtle.cpp代码:
#include
#include
#include class TeleopTurtle
{
public:TeleopTurtle();private:// 处理手柄发送过来的信息void callback(const sensor_msgs::Joy::ConstPtr &joy);// 实例化ROS句柄ros::NodeHandle nh;// 定义订阅者对象,用来订阅手柄发送的数据ros::Subscriber sub;// 定义发布者对象,用来将手柄数据发布到乌龟控制话题上ros::Publisher pub;// 用来接收launch文件中设置的参数,绑定手柄摇杆、轴的映射int axis_linear, axis_angular;int sticks_left, sticks_right;
};TeleopTurtle::TeleopTurtle()
{// 从参数服务器读取的参数// 按手柄摇杆分配nh.param("sticks_left", sticks_left, 1);nh.param("sticks_right", sticks_right, 3);// 按键分配nh.param("axis_linear", axis_linear, 1);nh.param("axis_angular", axis_angular, 2);// Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 // 对应:0: 左摇杆轴左右// 1: 左摇杆轴前后// 2: 默认全不开放// 3: 右摇杆轴左右// 4: 右摇杆轴前后// 5: 默认全不开放// 6: 方向按键左+右// 7: 方向按键前+后 pub = nh.advertise("/turtle1/cmd_vel", 10);sub = nh.subscribe("joy", 10, &TeleopTurtle::callback, this);
}void TeleopTurtle::callback(const sensor_msgs::Joy::ConstPtr &joy)
{geometry_msgs::Twist vel;// 将手柄摇杆轴拨动时值的输出赋值给乌龟的线速度和角速度if(joy->axes[axis_linear] || joy->axes[axis_angular]){vel.linear.x = joy->axes[axis_linear];vel.angular.z = joy->axes[axis_angular];}else if(joy->axes[sticks_left] || joy->axes[sticks_right]){vel.linear.x = joy->axes[sticks_left];vel.angular.z = joy->axes[sticks_right];}// // 将手柄摇杆轴拨动时值的输出赋值给乌龟的线速度和角速度// vel.linear.x = joy->axes[axis_linear];// vel.angular.z = joy->axes[axis_angular];// // 按键按动时也可以输出乌龟的线速度和角速度// vel.linear.x = joy->axes[sticks_left];// vel.angular.z = joy->axes[sticks_right];ROS_INFO("当前线速度为:%.3lf ; 角速度为:%.3lf", vel.linear.x, vel.angular.z);pub.publish(vel);
}int main(int argc, char **argv)
{// 设置编码setlocale(LC_ALL, "");// 初始化ROS节点ros::init(argc, argv, "teleop_turtle");TeleopTurtle teleopTurtle;ros::spin();return 0;
}
之后,在control_turtle--->src下创建Single_teleop_turtle.cpp / Double_teleop_turtle.cpp,命令为:
$ touch Single_teleop_turtle.cpp
结果为:


在catkin_workspace的src目录下创建launch_turtle功能包,
$ catkin_create_pkg launch_turtle
运行结果为:

看到 successfully ,则创建成功!
接着,在launch_turtle功能包下,右键创建launch文件夹(一般默认创建的文件夹为launch,其他当然也可以)

最后在launch文件夹下创建turtlelaunch.launch,命令为:
$ touch turtlelaunch.launch

turtlelaunch.launch中的代码为:
修改CMakeLists.txt配置文件,将下面代码添加到该文件中:
# 节点构建选项,配置可执行文件
add_executable(Single_teleop_turtle src/Single_teleop_turtle.cpp)
# 节点构建选项,配置目标链接库
target_link_libraries(Single_teleop_turtle ${catkin_LIBRARIES}
)
五、结果
手柄单遥感控制turtle运动
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
