zoukankan      html  css  js  c++  java
  • ROS下串口通信

    原理与结构

    我们需要在ROS下写一个串口节点,该节点订阅talker控制节点发来的命令主题,将命令通过串口设备发送到移动底座;同时串口节点实时接收移动底座通过串口发送过来的传感器实时数据,并将该数据封装后以 sensor (常是imu)主题的模式进行发布, listenner 节点可以实现订阅该主题。这样就实现了 ROS 与移动底座的串口通信过程。

    P2.通信原理图

    ROS下的serial包

    mkdir -p ~/catkin_ws/src/my_serial/
    cd ~/catkin_ws/src/my_serial/
    git clone https://github.com/wjwwood/serial.git

    再下载我写好的代码

    git clone https://github.com/threefruits/ros_serial_code.git
    cd ~/catkin_ws
    catkin_make
    

    下面是cpp代码原码与注释

    #include <ros/ros.h>
    #include <serial/serial.h>
    #include <std_msgs/String.h>
    #include <std_msgs/Empty.h>
    #include <geometry_msgs/Twist.h>
    
    serial::Serial ros_ser;
    #define	sBUFFERSIZE	10//send buffer size 串口发送缓存长度
    unsigned char s_buffer[sBUFFERSIZE];//发送缓存
    int l_v=0;
    int r_v=0;
    int l_d=1;
    int r_d=1;
    const float d_between=0.165;//半轮间距
    const float d=0.125;//轮子半径
    
    typedef union{
    	unsigned char cvalue[4];
    	int ivalue;
    }int_union;
    
    void cmd_to_serial(const geometry_msgs::Twist msg)
    {
        r_v=27*(msg.linear.x + msg.angular.z * d_between)/(3.1416*d);
        l_v=27*(msg.linear.x - msg.angular.z * d_between)/(3.1416*d);
        if(r_v>=0)
        {
            r_d=0;
            r_v=r_v;
        }             //电机正转
        else
        {
            r_d=1;
            r_v=-r_v;
        }           //电机反转
    
        if(l_v>=0)
        {
            l_d=0;
            l_v=l_v;
        }
        else
        {
            l_d=1;
            l_v=-l_v;
        }
    
    }
    
    void data_to_serial(const int left, const int right, const int left_d, const int right_d)
    {
         int_union left_v,right_v,left_v_d,right_v_d;
         left_v.ivalue=left;
         right_v.ivalue=right;
         memset(s_buffer,0,sizeof(s_buffer));
         s_buffer[0]=0xff;
         s_buffer[1]=0xfe;
    
         s_buffer[2]=left_v.cvalue[0];
         s_buffer[3]=right_v.cvalue[0];
    
         left_v_d.ivalue=left_d;
         right_v_d.ivalue=right_d;
         s_buffer[4]=left_v_d.cvalue[0];
         s_buffer[5]=right_v_d.cvalue[0];
    
         s_buffer[6]=0x00;
         s_buffer[7]=0x00;
         s_buffer[8]=0x00;
         s_buffer[9]=0x00;
         ros_ser.write(s_buffer,sBUFFERSIZE);
    }
    //回调函数
    void callback(const geometry_msgs::Twist& msg){
         cmd_to_serial(msg);
         data_to_serial(l_v,r_v,l_d,r_d);
     }
    int main (int argc, char** argv){
         ros::init(argc, argv, "my_serial_node");
         ros::NodeHandle n;
         //订阅主题command
         ros::Subscriber command_sub = n.subscribe("/cmd_vel", 1000, callback);
         //发布主题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::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();
         }
     }
    
     
  • 相关阅读:
    [个人]工作中的死亡陷阱
    [阮一峰]在软件开发中,一旦这些技术被取代,你的知识将变得毫无价值,因为它们大部分都是实施的细节。
    [原文 + 补充] 当你在浏览器中输入Google.com并且按下回车之后发生了什么?
    安全的知识点总结
    purge旧的ubuntu 的linux内核
    【个人】运维常识
    windows数字证书管理器
    在mobaxterm内连接deb使用lrzsz进行文件传输
    网络安全常见考试题
    linux deb系 rpm系 配置路由
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/15788542.html
Copyright © 2011-2022 走看看