一、前期工作
1.安装joy库
sudo apt install ros-$ROS_DISTRO-joy
2.查看设备信息
在命令行中,输入如下命令查看当前连接的输入设备。
ls /dev/input/
一般而言,罗技手柄设备的命名都以 js 开头,此处博主的输入即为 js0。
为了确保之后在ROS中使用手柄控制,此处需要将用户所在族添加至该串口的所有者。
sudo chgrp usrname /dev/input/js0
ls -l /dev/input/js0
3.查看当前按键
安装完joy包后,可以使用jstest命令查看当前按键情况。
sudo jstest /dev/input/js0
4.启动节点
除了使用jytest指令外,还可以直接运行joy节点进行查看。
roscore
rosrun joy joy_node
rostopic echo /joy
通过不断改变按键,可以发现对应的数据将进行改变。
二、ROS手柄差速控制(C++版)
1.新建功能包
此处编写代码用到了 geometry_msgs、std_msgs、sensor_msgs三个库,需要在创建功能包时,同时添加依赖。
# 新建功能包
catkin_create_pkg logitech_teleop_key roscpp rospy geometry_msgs std_msgs sensor_msgs
2.编写节点代码
在上一步创建的功能包中继续编写添加节点代码
# 添加控制代码
cd logitech_teleop_key/src/
touch logitech_teleop_key.cpp
vim logitech_teleop_key.cpp
此处用到的代码内容如下所示,主要控制的效果有如下几条:
- 在使用手柄进行控制时,必须按下手柄的6号键 不放,同时使用摇杆进行调速。
- 如若不知道手柄上各个建对应的序号,可以通过jstest命令查看。
- 左侧摇杆控制线速度,右侧摇杆控制角速度。
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <std_msgs/String.h>
#include <sensor_msgs/Joy.h>using namespace std;class LogTeleop
{
public:LogTeleop();private:/* data */void LogCallback(const sensor_msgs::Joy::ConstPtr& Joy);ros::NodeHandle n;ros::Subscriber sub ;ros::Publisher pub ;double vel_linear,vel_angular;int axis_angular,axis_linear,ton;
};LogTeleop::LogTeleop()
{// 手柄摇杆的转动幅度n.param<int>("axis_linear",axis_linear,1);n.param<int>("axis_angular",axis_angular,2);// 线速度和角速度n.param<double>("vel_linear",vel_linear,0.1);n.param<double>("vel_angular",vel_angular,0.4);n.param<int>("button",ton,6);// 发布与订阅pub = n.advertise<geometry_msgs::Twist>("cmd_vel", 1, true);;sub = n.subscribe<sensor_msgs::Joy>("joy",10,&LogTeleop::LogCallback,this);
}void LogTeleop::LogCallback(const sensor_msgs::Joy::ConstPtr& Joy)
{geometry_msgs::Twist twist;vel_linear = vel_linear * (1 + (Joy->axes[5] * 0.1));if(vel_linear>=0.2)vel_linear = 0.2;else if (vel_linear<=0)vel_linear = 0;elsevel_linear = vel_linear;vel_angular = vel_angular * (1 + (Joy->axes[4] * 0.1));if(vel_angular>=0.6)vel_angular = 0.6;else if(vel_angular<=0)vel_angular = 0;elsevel_angular = vel_angular;// 控制时,需要同时按住6号键if(Joy->buttons[ton]){twist.linear.x =(Joy->axes[axis_linear])*vel_linear;twist.linear.y = 0;twist.linear.z = 0;twist.angular.x = 0;twist.angular.y = 0;twist.angular.z =(Joy->axes[axis_angular])*vel_angular;ROS_INFO("linear:%.3lf angular:%.3lf",twist.linear.x,twist.angular.z);pub.publish(twist);}
}int main(int argc,char** argv)
{ros::init(argc, argv, "logitech_teleop_key");LogTeleop logteleop;ros::spin();return 0;
}
3.添加依赖
编写完成节点代码后,还需要在功能包下的CMakeList.txt文件中添加依赖。
add_executable(logitech_teleop_key src/logitech_teleop_key.cpp)
target_link_libraries(logitech_teleop_key ${catkin_LIBRARIES})
下
4.launch文件
为了快捷启动节点,此处使用launch文件进行配置。
# 功能包根目录下
mkdir launch
touch launch/logitech_teleop_key.launch
vim launch/logitech_teleop_key.launch
文件内容如下:
<launch><arg name="joy_dev" default="/dev/input/js0" /><node pkg="joy" type="joy_node" name="joy_node"><param name="dev" value="$(arg joy_dev)" /><param name="deadzone" value="0.05" /><param name="autorepeat_rate" value="10" /> <!--检测到键值时键值发送频率单位Hz,10为0.1m发送一次--></node><node pkg="logitech_teleop_key" type="logitech_teleop_key" name="logitech_teleop_key" output="screen"><!--input axis --><param name="axis_linear" value="1" type="int"/><param name="axis_angular" value="4" type="int"/><!--input vel --><param name="vel_linear" value="0.2" type="double"/><param name="vel_angular" value="0.5" type="double"/><param name="button" value="6" type="int"/></node>
</launch>
5.编译并运行
# 工作空间根目录下
catkin_make
source devel/setup.bash
# 运行launch文件
roslaunch logitech_teleop_key logitech_teleop_key.launch
运行效果如下:
此时,如果按住手柄上的6号键,则将自动发送消息。同时控制摇杆,即可修改速度。
三、ROS手柄差速控制(Pyhon版)
1.新建功能包
此处编写代码用到了 geometry_msgs、std_msgs、sensor_msgs三个库,需要在创建功能包时,同时添加依赖。
# 新建功能包
catkin_create_pkg logitech_teleop_key roscpp rospy geometry_msgs std_msgs sensor_msgs
2.编写节点代码
博主使用的ROS版本为Noetic版,所以使用的为python3。低于此版本的用户可以将第一行修改为如下内容
# Noetic版本如下:
#! /usr/bin/env python3
# encoding: utf-8# Melodic版本、Kinetic版本如下:
#! /usr/bin/env python
# encoding: utf-8
全部代码如下:
#! /usr/bin/env python3
# encoding: utf-8import rospy
from geometry_msgs.msg import Twist
from std_msgs.msg import String
from sensor_msgs.msg import Joydef joyCallback(msg):if not isinstance(msg, Joy): return 0# 手柄摇杆的转动幅度axis_linear_x = 1axis_angular_z = 2# 角速度和线速度vel_linear_x = 0.1vel_angular_z = 0.4twist = Twist()# linear speed valuevel_linear_x *= 1 + (msg.axes[5]*0.1)if vel_angular_z >= 0.2:vel_linear_x = 0.2elif vel_linear_x <= 0:vel_linear_x = 0else:vel_linear_x = vel_linear_x# angular speed valuevel_angular_z *= 1 + (msg.axes[4] *0.1)if vel_angular_z >= 0.6:vel_angular_z = 0.6elif vel_angular_z <= 0:vel_angular_z = 0else:vel_angular_z = vel_angular_z# controlif msg.buttons[6]:twist.linear.x = msg.axes[axis_linear_x] * vel_linear_xtwist.linear.y = 0twist.linear.z = 0twist.angular.x = 0twist.angular.y = 0twist.angular.z = msg.axes[axis_angular_z] * vel_angular_zpublisher.publish(twist)rospy.loginfo("linear:{} angular:{}".format(twist.linear.x,twist.angular.z))def onShutdown():rospy.loginfo("stop using teleop")twist = Twist()twist.linear.x = 0twist.angular.z = 0publisher.publish(twist)if __name__ == '__main__':# ros nodenode_name = "logitech_teleop_key"rospy.init_node(node_name)rospy.on_shutdown(onShutdown)# pubilsher /cmd_velpublisher = rospy.Publisher("/cmd_vel", Twist,queue_size=59)# subscriber /joyrospy.Subscriber("/joy", Joy, joyCallback)rospy.spin()
3.编写launch文件
<launch><arg name="joy_dev" default="/dev/input/js0" /><node pkg="joy" type="joy_node" name="joy_node"><param name="dev" value="$(arg joy_dev)" /><param name="deadzone" value="0.05" /><param name="autorepeat_rate" value="10" /> <!--检测到键值时键值发送频率单位Hz,10为0.1m发送一次--></node><node pkg="logitech_teleop_key" type="logitech_teleop_key.py" name="logitech_teleop_key" output="screen"></node>
</launch>