利用ROS2实现串口通信


1.下载虚拟串口模拟器socat

参考链接

sudo apt-get install socat

2.步骤

参考链接

1.新建一个serial_test文件夹

mkdir -p serial_test/src

2.新建一个cpp_header的包

cd serial_test/src
ros2 pkg create --build-type ament_cmake cpp_header

3.添加别人的serial头文件与源文件

参考链接
eqProj-main/eq-hmi20191219/header/drive/pub_serialport.hpp添加到serial_test/src/cpp_header/include/cpp_header/路径下;将eqProj-main/eq-hmi20191219/sources/drive/pub_serialport.cpp添加到serial_test/src/cpp_header/src/路径下,并将文件第一行改成#include "pub_serialport.hpp";之后新建两个cpp文件,分别用来发布和订阅话题。

cd serial_test/src/cpp_header/src/
touch serial_subscribe1_node.cpp
touch serial_publisher1_node.cpp

serial_subscribe1_node.cpp

#include "cpp_header/pub_serialport.hpp"
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"


int fp;
unsigned char Msg[128] = {
    
     0 };
const char* constc = nullptr;
Serial sp;
class TopicSuscribe01 : public rclcpp::Node
{
    
    
public:
    TopicSuscribe01(std::string name) : Node(name)
    {
    
    
        RCLCPP_INFO(this->get_logger(),"我是%s,订阅话题为:/subscribe_and_publish.",name.c_str());
        command_subscribe_ = this->create_subscription<std_msgs::msg::String>("subscribe_and_publish",10,std::bind(&TopicSuscribe01::command_callback,this,std::placeholders::_1));
    }
private:
    rclcpp::Subscription<std_msgs::msg::String>::SharedPtr command_subscribe_;
    void command_callback(const std_msgs::msg::String::SharedPtr msg)
    {
    
    
        double speed = 0.0f;
        // if(msg->data == "9999")
        // {
    
    
        //     speed = 0.2f;

        // }
        RCLCPP_INFO(this->get_logger(),"收到的[%s]指令,发送速度%f",msg->data.c_str(),speed);
        
        constc = msg->data.c_str();
        
        sp.WriteData(fp,constc,10);
    }

};


int main(int argc, char **argv)
{
    
    
    /* code */
    rclcpp::init(argc, argv);
    /*产生一个Wang2的节点*/
    // auto node = std::make_shared<rclcpp::Node>("pub_serial");
    auto node = std::make_shared<TopicSuscribe01>("subscribe1");
    // 打印一句自我介绍
    // int fp;
    // Serial sp;
    sp.BaudRate(115200);
    fp = sp.OpenPort(COM4);
    if(fp>0){
    
    
      RCLCPP_INFO(node->get_logger(), "serial success!.");
    }
    sp.WriteData(fp,"1024",10);
    // cout<<fp<<endl;

    RCLCPP_INFO(node->get_logger(), "大家好,我是subscribe1.");
    /* 运行节点,并检测退出信号*/
    rclcpp::spin(node);
    rclcpp::shutdown();
    sp.ClosePort(fp);
    return 0;
    
    return 0;
}

serial_publisher1_node.cpp

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

class Publisher : public rclcpp::Node
{
    
    
public:
    // 构造函数,有一个参数为节点名称
    Publisher(std::string name) : Node(name)
    {
    
    
        RCLCPP_INFO(this->get_logger(), "大家好,我是%s.", name.c_str());
        // 创建发布者
        subscribe_and_publish_publisher_ = this->create_publisher<std_msgs::msg::String>("subscribe_and_publish", 10);
        // 创建定时器,500ms为周期,定时发布
        timer_ = this->create_wall_timer(std::chrono::milliseconds(500), std::bind(&Publisher::timer_callback, this));
    }

private:
    void timer_callback()
    {
    
    
        // 创建消息
        std_msgs::msg::String message;
        message.data = "1234";
        // 日志打印
        RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
        // 发布消息
        subscribe_and_publish_publisher_->publish(message);
    }
    // 声名定时器指针
    rclcpp::TimerBase::SharedPtr timer_;
    // 声明话题发布者指针
    rclcpp::Publisher<std_msgs::msg::String>::SharedPtr subscribe_and_publish_publisher_;
};

int main(int argc, char **argv)
{
    
    
    rclcpp::init(argc, argv);
    /*产生一个的节点*/
    auto node = std::make_shared<Publisher>("publisher");
    /* 运行节点,并检测退出信号*/
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

4 修改CmakeLists.txtpackage.xml

打开CmakeLists.txt文件,在中间添加下面两行

find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)

在这里插入图片描述

在最后面添加下面内容

add_executable(serial_subscribe1_node src/serial_subscribe1_node.cpp src/pub_serialport.cpp) 
ament_target_dependencies(serial_subscribe1_node rclcpp std_msgs)
add_executable(serial_publisher1_node src/serial_publisher1_node.cpp)
ament_target_dependencies(serial_publisher1_node rclcpp std_msgs)

install(TARGETS
serial_subscribe1_node
serial_publisher1_node
DESTINATION lib/${PROJECT_NAME})

打开package.xml文件,在中间添加

<depend>rclcpp</depend>
<depend>std_msgs</depend>

在这里插入图片描述

5.测试

首先打开输入指令,生成虚拟串口

socat -d -d pty,raw,echo=0 pty,raw,echo=0

在这里插入图片描述
/dev/pts/1串口用来发送数据,/dev/pts/2串口用来接收数据
打开serial_subscribe1_node.cpp文件,修改串口名;之后用colcon build编译;接着新建一个终端,输入以下指令,监听/dev/pts/2中的数据

cat < /dev/pts/2

接着开启订阅节点

source install/setup.bash
ros2 run cpp_header serial_subscribe1_node

接着开启发布节点

source install/setup.bash
ros2 run cpp_header serial_publisher1_node

在这里插入图片描述终端1的serial_publisher1_node通过话题发布数据,被终端2serial_subscribe1_node接收,然后通过/dev/pts/1串口发送接收来的数据,最终终端3的/dev/pts/2串口可以接收到接收数据

猜你喜欢

转载自blog.csdn.net/m0_60355964/article/details/126647182