做机械臂导航时遇到的问题5:如何使用ROS内嵌serial功能包实现串口通信

    在订阅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的数据发生变化,如果连接了下位机和电机,便可手动控制真实机械臂。


猜你喜欢

转载自blog.csdn.net/weixin_39579805/article/details/78809681
今日推荐