鱼香ROS社区
    • 版块
    • 最新
    • 未解决
    • 已解决
    • 群组
    • 注册
    • 登录
    紧急通知:禁止一切关于政治&VPN翻墙等话题,发现相关帖子会立马删除封号
    提问前必看的发帖注意事项: 社区问答规则(小鱼个人)更新 | 高质量帖子发布指南

    serial串口通信

    已定时 已固定 已锁定 已移动
    ROS 2相关问题
    串口 通信
    5
    15
    2.9k
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • 凌云凌
      凌云
      最后由 编辑

      请问,在ROS2下的串口通信包是哪个呢?没有找到ros-eloquent-serial包。
      搜索到一个ros-eloquent-swri-serial-util,这个能用吗?
      有其它方法来使用串口?

      小鱼小 1 条回复 最后回复 回复 引用 0
      • 小鱼小
        小鱼 技术大佬 @凌云
        最后由 编辑

        @凌云这个你问对人啦,小鱼前几天才做了一个开源库,支持在ROS2下几行代码使用串口。

        在写FishBot的SDK时,小鱼打算以多种方式进行数据的通信的,包括串口、UDP、TCP等,所以就对通信模块进行了封装,实现简单的更换配置,完成协议的切换。

        因为前段时间总有小伙伴问如何在ROS2中调用串口,就想着要不把这部分代码抽出来给大家,二来后续的更新和维护可以从FishBot中抽离出来,方便更多的小伙伴一起Work。同时小鱼顺手写了一个ROS2的例程,当然还有g++和CMake版本的使用样例代码。

        开源地址:https://github.com/fishros/fish_protocol

        FishProtocol

        FishProtocol是一个方便的C++多协议(串口/UDP/TCP)通信库。

        FishProtocol是从FishBot的Driver中抽离出的,采用boost库作为核心进行了二次封装,可以简单快速的通过几行代码建立串口/UDP等通信。随着FishBot的不断完善,该库也将不断的更新完善,后续将同时支持对多端进行同时连接,实现多机控制等功能。

        同时该库也可以在ROS2中使用,工程中提供有相关例程,见examples文件夹。

        1.快速安装

        sudo apt install libboost-dev
        git clone https://gh.api.99988866.xyz/https://github.com/fishros/fish_protocol.git 
        cd fish_protocol && mkdir build  && cd build
        cmake .. && sudo make install # 将安装到系统库
        

        2.快速使用/串口通信

        fish_protocol::ProtocolConfig proto_config;
        proto_config.protocol_type_ = PROTOCOL_TYPE::SERIAL;
        proto_config.serial_baut_ = 115200;
        proto_config.serial_address_ = "/dev/ttyS12";
        
        // 初始化
        auto protocol = GetProtocolByConfig(proto_config);
        
        // 发送数据
        protocol->ProtocolSendRawData("Hello FishBot!");
        
        // 接收数据
        protocol->SetDataRecvCallback([](const std::string& data) -> void {
            std::cout<<"recv"<<data<<std:endl;
        });
        
        // 销毁
        protocol->ProtocolDestory();
        

        3.快速上手/UDPServer通信

        fish_protocol::ProtocolConfig proto_config;
        proto_config.protocol_type_ = PROTOCOL_TYPE::UDP_SERVER;
        proto_config.udp_server_ip_ = "0.0.0.0";
        proto_config.udp_server_port_ = 3474;
        
        // 初始化
        auto protocol = GetProtocolByConfig(proto_config);
        
        // 发送数据
        protocol->ProtocolSendRawData("Hello FishBot!");
        
        // 接收数据
        protocol->SetDataRecvCallback([](const std::string& data) -> void {
            std::cout<<"recv"<<data<<std:endl;
        });
        
        // 销毁
        protocol->ProtocolDestory();
        

        4.在ROS2中使用-串口通信

        #include "fish_protocol/fish_protocol.h"
        #include "rclcpp/rclcpp.hpp"
        
        int main(int argc, char** argv) {
          /* 初始化rclcpp  */
          rclcpp::init(argc, argv);
          /*产生一个node_01的节点*/
          auto node = std::make_shared<rclcpp::Node>("example_fish_protocol");
          // 打印一句自我介绍
          RCLCPP_INFO(node->get_logger(), "example_fish_protocol节点已经启动.");
        
          fish_protocol::ProtocolConfig proto_config;
          proto_config.protocol_type_ = fish_protocol::PROTOCOL_TYPE::SERIAL;
          proto_config.serial_baut_ = 115200;
          proto_config.serial_address_ = "/dev/ttyS12";
          // 初始化
          auto protocol = GetProtocolByConfig(proto_config);
          // 发送数据
          protocol->ProtocolSendRawData("Hello FishBot!");
          // 接收数据
          protocol->SetDataRecvCallback([](const std::string& data) -> void {
            std::cout << "recv" << data << std::endl;
          });
          // 销毁
          protocol->ProtocolDestory();
        
          /* 运行节点,并检测退出信号 Ctrl+C*/
          rclcpp::spin(node);
          /* 停止运行 */
          rclcpp::shutdown();
          return 0;
        }
        

        新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

        毛哥成山轮胎机油保养毛 32904162883 2 条回复 最后回复 回复 引用 0
        • 凌云凌
          凌云
          最后由 编辑

          看起来不错,我试试。谢谢。

          1 条回复 最后回复 回复 引用 0
          • 凌云凌
            凌云
            最后由 凌云 编辑

            谢谢你的轮子!
            但是我想要通过串口发送字节数组,而非字符串,有相关的接口函数可用吗?
            另外,接收回调函数如何写成独立函数的形式?

            小鱼小 1 条回复 最后回复 回复 引用 0
            • 小鱼小
              小鱼 技术大佬 @凌云
              最后由 编辑

              @凌云

              1. 字节数组和字符串可以直接互转的
              2. 可以直接使用std::bind将普通函数变为回调函数形式

              新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

              凌云凌 1 条回复 最后回复 回复 引用 0
              • 凌云凌
                凌云 @小鱼
                最后由 编辑

                @小鱼 thanks!

                1 条回复 最后回复 回复 引用 0
                • 毛哥成山轮胎机油保养毛
                  毛哥成山轮胎机油保养 活跃VIP @小鱼
                  最后由 编辑

                  @小鱼 最近入手了一个JY_ 95t imu ,只找到了python的程序,没有c++的,这个imu在接收数据以前,需要发送一段16进制的数据:0xA4 0x03 0x08 0x23 0xD2配置imu 我看了你的程序,protocol->ProtocolSendRawData("Hello FishBot!"); 只能发送字符串,怎样才能发送16进制的数据呢?这是你的示例程序返回的结果:open with/dev/ttyUSB0
                  send14
                  start send******
                  0x48 0x65 0x6C 0x6C 0x6F 0x20 0x46 0x69 0x73 0x68 0x42 0x6F 0x74 0x21

                  小鱼小 1 条回复 最后回复 回复 引用 0
                  • 小鱼小
                    小鱼 技术大佬 @毛哥成山轮胎机油保养
                    最后由 编辑

                    @毛哥成山轮胎机油保养 一个字符串刚好是一个byte,8个bit。
                    所以bytes可以和string可以互相转换


                    当你想要在 C++ 中将 std::string 和字节数组之间进行转换时,可以使用 reinterpret_cast 进行转换。下面是一个示例代码,展示了如何在两者之间进行互相转换:

                    #include <iostream>
                    #include <string>
                    #include <vector>
                    
                    // 将字节数组转换为 std::string
                    std::string ByteArrayToString(const std::vector<unsigned char>& byteArray) {
                        return std::string(reinterpret_cast<const char*>(byteArray.data()), byteArray.size());
                    }
                    
                    // 将 std::string 转换为字节数组
                    std::vector<unsigned char> StringToByteArray(const std::string& str) {
                        std::vector<unsigned char> byteArray(str.begin(), str.end());
                        return byteArray;
                    }
                    
                    int main() {
                        // 示例:将字节数组转换为 std::string
                        std::vector<unsigned char> byteArray = {72, 101, 108, 108, 111, 33};
                        std::string str = ByteArrayToString(byteArray);
                        std::cout << "String: " << str << std::endl;
                    
                        // 示例:将 std::string 转换为字节数组
                        std::string message = "Hello, world!";
                        std::vector<unsigned char> convertedArray = StringToByteArray(message);
                        std::cout << "Byte Array: ";
                        for (unsigned char byte : convertedArray) {
                            std::cout << static_cast<int>(byte) << " ";
                        }
                        std::cout << std::endl;
                    
                        return 0;
                    }
                    

                    上述代码中,ByteArrayToString 函数接收一个字节数组(std::vector<unsigned char>),并使用 reinterpret_cast 将其转换为 const char*,然后通过构造函数将其转换为 std::string。

                    StringToByteArray 函数接收一个 std::string,并通过使用迭代器将其转换为 std::vector<unsigned char>。

                    请注意,这种方法假设字节数组中的每个字节都对应一个有效的字符,且字符编码没有发生变化。在某些情况下,这种转换可能不是无损的,因此在实际应用中要小心处理。

                    新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

                    毛哥成山轮胎机油保养毛 1 条回复 最后回复 回复 引用 0
                    • 毛哥成山轮胎机油保养毛
                      毛哥成山轮胎机油保养 活跃VIP @小鱼
                      最后由 编辑

                      @小鱼 在 serial串口通信 中说:

                      // 示例:将 std::string 转换为字节数组
                      std::string message = "Hello, world!";
                      std::vector<unsigned char> convertedArray = StringToByteArray(message);
                      std::cout << "Byte Array: ";
                      for (unsigned char byte : convertedArray) {
                      std::cout << static_cast<int>(byte) << " ";
                      }
                      std::cout << std::endl;

                      #include "fish_protocol/fish_protocol.h"
                      //#include <iostream>
                      //#include <string>
                      //#include <vector>

                      // 将字节数组转换为 std::string
                      std::string ByteArrayToString(const std::vector<unsigned char>& byteArray) {
                      return std::string(reinterpret_cast<const char*>(byteArray.data()), byteArray.size());
                      }

                      // 将 std::string 转换为字节数组
                      std::vector<unsigned char> StringToByteArray(const std::string& str) {
                      std::vector<unsigned char> byteArray(str.begin(), str.end());
                      return byteArray;
                      }

                      int main(int argc, char const* argv[]) {
                      fish_protocol::ProtocolConfig proto_config;
                      proto_config.protocol_type_ = fish_protocol::PROTOCOL_TYPE::SERIAL;
                      proto_config.serial_baut_ = 115200;
                      proto_config.serial_address_ = "/dev/ttyUSB0";

                      // 初始化
                      auto protocol = GetProtocolByConfig(proto_config);

                      //send_data = [0xA4,0x03,0x08,0x23,0xD2]
                      // 将字节数组转换为 std::string
                      std::vector<unsigned char> byteArray = {0xA4,0x03,0x08,0x23,0xD2};
                      std::string str = ByteArrayToString(byteArray);

                      // 发送数据
                      protocol->ProtocolSendRawData(str);

                      // 接收数据
                      protocol->SetDataRecvCallback([](const std::string& data) -> void {

                      //将接收到的 std::string & data转换为字节数组
                      std::vector<unsigned char> convertedArray = StringToByteArray(data);
                      std::cout << "Byte Array: ";
                      for (unsigned char byte : convertedArray) {
                          std::cout << static_cast<int>(byte) << " ";
                      }
                      std::cout << std::endl;
                      

                      });

                      // 销毁
                      protocol->ProtocolDestory();
                      return 0;
                      }

                      可以正常发送16进制数据了,可是为什么没有读到imu发回的数据呢?
                      open with/dev/ttyUSB0
                      send5
                      start send******
                      0xA4 0x03 0x08 0x23 0xD2
                      end send******

                      小鱼小 1 条回复 最后回复 回复 引用 0
                      • 小鱼小
                        小鱼 技术大佬 @毛哥成山轮胎机油保养
                        最后由 编辑

                        @毛哥成山轮胎机油保养 在 serial串口通信 中说:

                        // 销毁
                        protocol->ProtocolDestory();

                        这句之前加上个delay,还没来得及接受到数据就exit了

                        新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

                        8679758198 2 条回复 最后回复 回复 引用 0
                        • 8679758198
                          圆梦 @小鱼
                          最后由 编辑

                          @小鱼 那我想发送一个uint8或者float型的数据该怎么办?

                          1 条回复 最后回复 回复 引用 0
                          • 8679758198
                            圆梦 @小鱼
                            最后由 编辑

                            @小鱼 他只能发送一种类型?

                            小鱼小 1 条回复 最后回复 回复 引用 0
                            • 小鱼小
                              小鱼 技术大佬 @867975819
                              最后由 编辑

                              @867975819 bytes可以代表一切类型

                              新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

                              1 条回复 最后回复 回复 引用 0
                              • 32904162883
                                鲜橙多 @小鱼
                                最后由 编辑

                                @小鱼 41af58e1-ce07-4033-88dc-37071021ba29-image.png 为什么在容器中安装,执行cpp文件一直显示无法找到对应的package呢

                                小鱼小 1 条回复 最后回复 回复 引用 0
                                • 小鱼小
                                  小鱼 技术大佬 @3290416288
                                  最后由 编辑

                                  @3290416288 只支持ROS2

                                  新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

                                  1 条回复 最后回复 回复 引用 0
                                  • 第一个帖子
                                    最后一个帖子
                                  皖ICP备16016415号-7
                                  Powered by NodeBB | 鱼香ROS