ros_canopen使用心得

近期开始准备上位机与机器人底盘进行CAN通讯,花了很长时间在网上整理学习资料,现将自己的心得和参考的链接整理如下。

首先,机器人操作系统中有ros_canopen可以去调用,其中socketcan-bridg功能包帮我们省却了很多底层工作,其socketcan_to_topicnode,topic_to_socketcannode这两个节点,可以将上位机发布的can消息转为话题发布,反之可以将底盘发送的信息转为话题进行订阅。

 具体可以参考下面链接:

ROS中CANopen的使用(1)_zyf_to_utopia的博客-优快云博客

一、安装canopen

1.1开始准备工作(下载):

$ mkdir -p /xxx_ws/src

$ cd /xxx_ws

$ git clone git https://github.com/ros-industrial/ros_canopen.git

最后一行代码可以改为git clone git://github.com/ros-industrial/ros_canopen.git

就是新建工作空间,在工作空间中下载ros_canopen

1.2 开始安装ros_canopen

$ sudo apt-get install libmuparser-dev

上述链接中提到上一步安装出现问题的话,执行下面这一步:

$ sudo apt-get install  libmuparser libmuparser2v5     libmuparser-doc    libmuparserx-dev   libmuparser-dev    libmuparserx4.0.7 

1.3 开始编译

cd xxx_ws 进入工作空间

开始运行 catkin_make

个人习惯一次一敲 source ./devel/setup.bash 所以跳过了后续

笔者当时参考的链接:

ubuntu ros melodic 安装 canopen - xyyh - 博客园 (cnblogs.com)

二、创建虚拟can口进行调试

本文主要针对笔记本电脑等设备,因为该设备通常没有can卡,所以需要创建并调用虚拟can口,步骤如下:

下面创建虚拟CAN。只做粗体部分即可。

1.sudo modprobe vcan //加载虚拟can模块

2.sudo ip link add dev can0 type vcan //添加can0网卡

3.ifconfig -a  //查看can0

4.sudo ip link set dev can0 up //开启can0

5.sudo ip link set dev can0 down //关闭can0

6. sudo ip link del dev can0 //删除can0

roscore //启动roscore

rosrun socketcan_bridge socketcan_to_topic_node//启动节点

rostopic echo /received_messages   (这里的数据是ROS MSG格式)---打印通道内容

candump can0            (原样的数据显示)接受CAN数据

cansend can0 7ff#123456 //发送CAN数据测试

执行到第四步开启can口就好了,因为后续可以自己写程序和launch文件进行集成运行。

笔者当时参考的链接:

ROS中使用CAN通信的调查记录_学习笔记-优快云博客

三、笔者写的简单调试代码

canopen_test.cpp:

#include <ros/ros.h>

#include <ros/spinner.h>

#include <std_msgs/String.h>

#include<tf/transform_broadcaster.h>

#include<nav_msgs/Odometry.h>

#include<geometry_msgs/Twist.h>

#include <std_msgs/String.h>

#include <socketcan_bridge/topic_to_socketcan.h>

#include <socketcan_bridge/socketcan_to_topic.h>

#include <can_msgs/Frame.h>

#include <socketcan_interface/socketcan.h>


void send_can_message(int motor_1,int motor_2,int motor_3,int motor_4)

{

while(ros::ok())

{

ROS_INFO("start send can_message");

setlocale(LC_ALL,"");

uint8_t transition[8];//中间传递转速变量数组

can_msgs::Frame can_frame;

memset(&transition,0,sizeof(transition));//初始化数组元素为0


transition[0]=motor_1 >> 8;

transition[1]=motor_1 & 0xFF;

transition[2]=motor_2 >> 8;

transition[3]=motor_2 & 0xFF;

transition[4]=motor_3 >> 8;

transition[5]=motor_3 & 0xFF;

transition[6]=motor_4 >> 8;

transition[7]=motor_4 & 0xFF8;


can_frame.id=0x07ff1234;//需要修改

can_frame.is_extended = true;

can_frame.is_rtr = false;

can_frame.is_error = false;

can_frame.dlc = 8;//有效数据长度

for(uint8_t i =0; i<can_frame.dlc; i++)

{

can_frame.data[i] = transition[i];

}

ros::NodeHandle roscan("~");

ros::Publisher roscan_send_message;

roscan_send_message = roscan.advertise<can_msgs::Frame>("sent_messages",100);

roscan_send_message.publish(can_frame);

ROS_INFO("has sent messages to motor 1-4");

ros::Duration(0.5).sleep();

ros::spinOnce();

}

}


int main(int argc, char**argv)

{

ros::init(argc, argv, "robotx4");

ros::NodeHandle n("~");

send_can_message(100,200,300,400);

}

.launch文件:

<launch>

    <node pkg="socketcan_bridge" name="topic_to_socketcan_node" type="topic_to_socketcan_node" output="screen">
    </node>

    <node pkg="socketcan_bridge" name="socketcan_to_topic_node" type="socketcan_to_topic_node" output="screen">
    </node>
    
    <node pkg="robotx4_bringup" name="canopen_test" type="canopen_test" output="screen">
    </node>

</launch>

四、实验验证

1、执行第二部分前4步,打开虚拟can口

2、启动launch文件

3、观察话题发布信息

 4、额外测试(直接can口写和收,和ros 接口应该是独立的):

补充:个人理解的---ros接口的话题发布,其消息需要rostopic echo 话题名 打印出来,candump是无法显示的。

<think>好的,用户想在ROS2中实现上位机通过串口转CAN通讯的方法,需要找相关的教程或示例代码。首先,我需要理清这个问题的关键点。 用户提到了ROS2、上位机、串口转CAN,可能的场景是上位机(比如运行ROS2的计算机)需要通过串口与某个硬件设备通信,而该设备可能使用CAN协议。或者可能需要一个串口到CAN的转换器,比如使用USB转CAN模块,然后在ROS2中处理数据转换。 首先,ROS2本身并没有直接支持串口转CAN的包,所以可能需要自己开发节点来处理。通常的做法是使用串口库读取数据,然后转换成CAN消息,或者反过来。这里可能需要用到一些现有的库,比如python的serial库或者C++的serial库来处理串口通信,以及socketcan之类的库来处理CAN部分。 接下来,用户可能需要硬件方面的指导,比如使用什么转换模块。常见的USB转CAN设备有PCAN、USB2CAN等,这些通常有Linux内核驱动,可以通过SocketCAN接口访问。所以,在ROS2中,可能需要使用socketcan包来发送和接收CAN帧,同时通过串口与其他设备通信。 然后,用户可能需要示例代码的结构。例如,创建一个ROS2节点,该节点同时订阅CAN总线的消息,并通过串口发送出去,或者监听串口数据并发布到CAN总线上。这涉及到串口数据的解析和封装成CAN帧,或者反过来。需要注意数据格式的转换,比如将串口接收的字节流按照特定协议解析成CAN ID和数据部分。 另外,用户提供的引用内容中提到了Arduino相关的代码,比如encoder_driver和motor_driver,可能用户是在机器人控制中使用,比如通过ROS2控制带有CAN接口的电机驱动器,而上位机可能通过串口转CAN与这些驱动器通信。这种情况下,可能需要编写一个中间节点,负责协议转换。 可能的步骤是:1. 确认硬件连接,比如使用串口转CAN适配器;2. 在ROS2中创建串口通信节点;3. 创建CAN通信节点;4. 实现协议转换逻辑,将串口数据解析并打包成CAN消息,或反之;5. 测试和调试。 还需要考虑数据处理的实时性和效率,可能需要使用异步IO或多线程处理串口和CAN的数据流。此外,数据协议的设计也很重要,比如定义消息的起始符、长度、CAN ID、数据部分、校验等,以确保可靠传输。 最后,用户可能需要具体的代码示例,比如如何使用ROS2的serial库和CAN库来读写数据,如何处理数据帧,以及如何将这些整合到ROS2的节点中。可能需要参考现有的ROS2串口或CAN包,比如ros2_serial或socketcan_interface,但需要确认是否支持ROS2。</think>在ROS2中实现串口转CAN通讯需要硬件转换模块与软件协议解析相结合,以下是具体实现步骤: ### 一、硬件准备 1. 选择串口转CAN模块(如ZLG USBCAN-2E-U、周立功CANalyst-II) 2. 连接方式: $$PC \xrightarrow{USB/TTL} CAN转换器 \xrightarrow{CAN总线} 执行设备$$ 3. 确认Linux系统识别设备: ```bash $ dmesg | grep ttyUSB [ 485.487232] usb 1-2: FTDI USB Serial Device converter now attached to ttyUSB0 ``` ### 二、软件架构 ```python [ROS2节点] <--(ROS2 Topic)--> [协议转换层] <--(串口/CAN)--> [硬件层] ``` ### 三、核心实现代码(基于rclpy) ```python import serial import can from rclpy.node import Node from can_interfaces.msg import CanFrame class SerialCanBridge(Node): def __init__(self): super().__init__('serial_can_bridge') # 串口配置(参数需根据硬件调整) self.ser = serial.Serial( port='/dev/ttyUSB0', baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE ) # CAN配置 self.can_bus = can.interface.Bus( channel='can0', bustype='socketcan' ) # 创建ROS2话题 self.publisher = self.create_publisher(CanFrame, 'can_tx', 10) self.subscription = self.create_subscription( CanFrame, 'can_rx', self.can_callback, 10) # 启动串口监听线程 self.serial_thread = threading.Thread(target=self.serial_listener) self.serial_thread.start() def serial_listener(self): while rclpy.ok(): data = self.ser.read_until(b'\xAA\x55') # 自定义帧尾 if data: self.process_serial_data(data) def process_serial_data(self, data): # 示例协议:帧头(2B) | CAN ID(4B) | 数据长度(1B) | 数据(8B) | 校验(1B) if len(data) < 8: return frame = CanFrame() frame.id = int.from_bytes(data[2:6], 'big') frame.data = data[6:-1] self.can_bus.send(can.Message( arbitration_id=frame.id, data=frame.data, is_extended_id=True )) def can_callback(self, msg): # 转换CAN帧为串口数据 packet = bytearray() packet += b'\xAA\x55' # 帧头 packet += msg.id.to_bytes(4, 'big') packet += bytes(msg.data) packet += self.calculate_checksum(packet) self.ser.write(packet) ``` ### 四、部署流程 1. 安装依赖: ```bash $ sudo apt install python3-can $ pip install pyserial ``` 2. 配置CAN接口: ```bash $ sudo ip link set can0 type can bitrate 500000 $ sudo ip link set up can0 ``` 3. 消息接口定义(can_interfaces/msg/CanFrame.msg): ``` uint32 id uint8[8] data ``` ### 五、测试方法 1. 发送CAN数据: ```bash $ ros2 topic pub /can_rx can_interfaces/msg/CanFrame "{id: 0x123, data: [1,2,3,4,5,6,7,8]}" ``` 2. 监听转换结果: ```bash $ candump can0 ```
评论 40
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值