在订阅joint_states话题,获取到position和velocity的数据之后,如何将这些信息发给下位机呢?下位机都具备串口,我们通过串口实现与下位机的通讯。在本篇中,我们采用ROS内嵌的Serial功能包实现串口通讯,当然还有其他方式来实现。
这里参考各位大神的文章,在这里表示感谢:
1、ROS中串口的使用——serial功能包:点击链接
2、ROS串口通信:点击链接
一、建立工作目录并下载serial功能包
$mkdir -p ~/catkin_ws2/src/mypackage/ $cd ~/catkin_ws2/src/mypackage/ $git clone https://github.com/wjwwood/serial.git
二、创建串口节点
1、在mypackage目录下建立串口节点程序包:
$catkin_create_pkg my_serial_node std_msgs rospy roscpp
生成文件效果如下:
2、修改 CMakeLists.txt,修改后内容如下:
cmake_minimum_required(VERSION 2.8.3) project( my_serial_node ) find_package(catkin REQUIRED COMPONENTS roscpp serial std_msgs ) catkin_package( CATKIN_DEPENDS serial std_msgs ) include_directories( ${catkin_INCLUDE_DIRS} ) add_executable( my_serial_node src/my_serial_node.cpp) target_link_libraries( my_serial_node ${catkin_LIBRARIES} ) add_executable(talker src/talker.cpp) target_link_libraries(talker ${catkin_LIBRARIES}) add_executable(listener src/listener.cpp) target_link_libraries(listener ${catkin_LIBRARIES})
3、修改package.xml,添加刚刚下载的serial 依赖
<?xml version="1.0"?> <package> <name> my_serial_node</name> <version>0.0.0</version> <description>my serial node </description> <maintainer email="[email protected]">xs</maintainer> <license>BSD</license> <buildtool_depend>catkin</buildtool_depend> <build_depend>serial</build_depend> <build_depend>std_msgs</build_depend> <run_depend>serial</run_depend> <run_depend>std_msgs</run_depend> </package>
4、在 mypackage/my_serial_node/src目录下创建my_serial_node.cpp 文件
#include "ros/ros.h" #include <serial/serial.h> #include <std_msgs/String.h> #include <std_msgs/Empty.h> #include "sensor_msgs/JointState.h" #include <string> #include <sstream> serial::Serial ros_ser; //声明串口对象 //回调函数 void jointstatesCallback(const sensor_msgs::JointStateConstPtr& msg) { std::stringstream str; str<<"joint1: pos:"<<msg->position[2]<<" vel:"<<msg->velocity[2] <<" joint2: pos:"<<msg->position[0]<<" vel:"<<msg->velocity[0] <<" joint3: pos:"<<msg->position[1]<<" vel:"<<msg->velocity[1]<<std::endl; ROS_INFO_STREAM("Writing to serial port" ); ros_ser.write(str.str()); //发送串口数据 } /*void callback(const std_msgs::String::ConstPtr& msg) { std::stringstream str; str<<"joint1: pos:"<<1.0<<" vel:"<<2.0<<std::endl; ROS_INFO_STREAM("Write to serial port" << msg->data); ros_ser.write(str.str()); //发送串口数据 }*/ int main (int argc, char** argv){ ros::init(argc, argv, "my_serial_node"); //初始化节点 ros::NodeHandle n; //声明节点句柄 //订阅主题/joint_states,并配置回调函数 ros::Subscriber command_sub = n.subscribe("/joint_states", 1000, jointstatesCallback); //发布主题sensor ros::Publisher sensor_pub = n.advertise<std_msgs::String>("sensor", 1000); try { //设置串口属性,并打开串口 ros_ser.setPort("/dev/ttyUSB0"); ros_ser.setBaudrate(115200); serial::Timeout to = serial::Timeout::simpleTimeout(1000); ros_ser.setTimeout(to); ros_ser.open(); } catch (serial::IOException& e) { ROS_ERROR_STREAM("Unable to open port "); return -1; } //检测串口是否已经打开,并给出提示信息 if(ros_ser.isOpen()){ ROS_INFO_STREAM("Serial Port opened"); }else{ return -1; } //指定循环的频率 ros::Rate loop_rate(10); while(ros::ok()){ //处理ROS的信息,比如订阅消息,并调用回调函数 ros::spinOnce(); if(ros_ser.available()){ ROS_INFO_STREAM("Reading from serial port"); std_msgs::String serial_data; //获取串口数据 serial_data.data = ros_ser.read(ros_ser.available()); ROS_INFO_STREAM("Read: " << serial_data.data); //将串口数据发布到主题sensor sensor_pub.publish(serial_data); } loop_rate.sleep(); } }
5、关于话题的发布者:由my_serial_node.cpp文件中的回调函数可知, ros::Subscriber command_sub = n.subscribe("/joint_states", 1000, jointstatesCallback);
我们订阅的是/joint_states话题。(做机械臂导航时遇到的问题4:如何订阅joint_states话题(输出关节状态))
6、创建listener节点,接收串口助手发送的信息
在 mypackage/my_serial_node/src目录下新建文件 listener.cpp ,并在 CMakeLists.txt 中添加以下内容(已在上述CMakeList中添加):
add_executable(listener src/listener.cpp) target_link_libraries(listener ${catkin_LIBRARIES})
listener.cpp文件内容如下:
#include "ros/ros.h" #include "std_msgs/String.h" //回调函数 void callback(const std_msgs::String::ConstPtr& msg) { ROS_INFO("I heard: [%s]", msg->data.c_str()); } int main(int argc, char **argv) { ros::init(argc, argv, "listener"); ros::NodeHandle n; //订阅主题,接收串口数据 ros::Subscriber sub = n.subscribe("sensor", 1000, callback); ros::spin(); return 0; }
7、编译
$cd ~/catkin_ws2/ $catkin_make编译成功后输入 source /devel/setup.bash
三、串口助手
在另一台笔记本上下载安装串口调试助手,我们选择的是sscom33,百度云链接https://pan.baidu.com/s/1bo7WRrL
用串口线连接两台电脑。
四、测试
1、先运行用arbotix来模拟控制机械臂,这会启动/joint_states话题。参考(做机械臂导航遇到的问题3:如何用arbotix接口控制机械臂 做机械臂导航时遇到的问题4:如何订阅joint_states话题(输出关节状态))
2、在新终端运行$roscore
3、在新终端运行$rosrun my_serial_node my_serial_node
4、在新终端运行$rosrun my_serial_node listenner
my_serial_node终端效果如下
listener终端效果如下,可以接收串口助手发送的信息
另一台电脑串口助手效果如下,在arbotix gui窗口控制滑块时,可以看到相应joint1、joint2、joint3的数据发生变化,如果连接了下位机和电机,便可手动控制真实机械臂。