CANalyst-II 与 ROS Melodic 集成:Ubuntu 18.04 下 USB 权限配置与 2 通道数据转发实战
2026/7/10 7:18:15 网站建设 项目流程

CANalyst-II 与 ROS Melodic 深度集成:Ubuntu 18.04 双通道通信全栈指南

1. 硬件识别与权限配置实战

当CANalyst-II通过USB接口连接到Ubuntu 18.04系统时,设备识别是第一步。执行lsusb命令后,我们通常会看到类似这样的输出:

Bus 001 Device 004: ID 04d8:0053 Microchip Technology, Inc.

这个04d8:0053就是设备的厂商ID和产品ID。但此时直接运行ROS节点会遇到经典的Operation not permitted错误,这是因为Linux系统默认限制普通用户直接访问USB设备。

永久解决方案是创建udev规则。在/etc/udev/rules.d/目录下新建99-myusb.rules文件,内容如下:

ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="0053", GROUP="users", MODE="0777"

关键参数说明:

  • GROUP="users":将设备访问权限赋予users组
  • MODE="0777":设置完全访问权限
  • ATTRS匹配项:确保规则仅针对特定设备生效

应用规则后需要重新加载udev服务:

sudo udevadm control --reload-rules sudo udevadm trigger

提示:如果规则未立即生效,尝试重新插拔设备或重启系统。可通过ls -l /dev/bus/usb/*验证设备权限是否已变更。

2. ROS工作环境构建

2.1 创建工作空间与功能包

标准的Catkin工作空间初始化流程:

mkdir -p ~/can_ws/src cd ~/can_ws catkin_make source devel/setup.bash

创建专用功能包时,需包含必要的依赖项:

cd src catkin_create_pkg can_pkg roscpp rospy std_msgs

2.2 关键文件部署

将厂商提供的开发文件放置到正确位置:

can_ws/ └── src/ └── can_pkg/ ├── include/ │ └── can_pkg/ │ └── controlcan.h ├── lib/ │ └── libcontrolcan.so └── src/ └── mycan_node.cpp

CMakeLists.txt关键配置

include_directories( include ${catkin_INCLUDE_DIRS} ) link_directories( lib ${catkin_LIB_DIRS} ) add_executable(mycan_node src/mycan_node.cpp) target_link_libraries(mycan_node ${catkin_LIBRARIES} controlcan )

3. 双通道通信节点实现

3.1 设备初始化框架

bool initCANChannel(int deviceType, int deviceInd, int channelInd, VCI_INIT_CONFIG config) { if (VCI_InitCAN(deviceType, deviceInd, channelInd, &config) != 1) { ROS_ERROR("CAN%d init failed", channelInd + 1); return false; } if (VCI_StartCAN(deviceType, deviceInd, channelInd) != 1) { ROS_ERROR("CAN%d start failed", channelInd + 1); return false; } ROS_INFO("CAN%d initialized successfully", channelInd + 1); return true; }

3.2 数据收发核心逻辑

接收线程(CAN1):

VCI_CAN_OBJ recvFrames[50]; int recvLen = VCI_Receive(VCI_USBCAN2, 0, 0, recvFrames, 50, 200); if (recvLen > 0) { for (int i = 0; i < recvLen; i++) { ROS_INFO("CAN1 Received: ID=0x%X Data=[%02X %02X %02X %02X %02X %02X %02X %02X]", recvFrames[i].ID, recvFrames[i].Data[0], recvFrames[i].Data[1], recvFrames[i].Data[2], recvFrames[i].Data[3], recvFrames[i].Data[4], recvFrames[i].Data[5], recvFrames[i].Data[6], recvFrames[i].Data[7]); } }

发送逻辑(CAN2):

VCI_CAN_OBJ sendFrame; sendFrame.ID = 0x123; sendFrame.SendType = 0; sendFrame.RemoteFlag = 0; sendFrame.ExternFlag = 0; sendFrame.DataLen = 8; memcpy(sendFrame.Data, transmitData, 8); if (VCI_Transmit(VCI_USBCAN2, 0, 1, &sendFrame, 1) == 1) { ROS_DEBUG("Message sent to CAN2 successfully"); } else { ROS_WARN("CAN2 transmission failed"); }

4. 系统集成与调试技巧

4.1 硬件连接验证表

检查项预期状态异常处理方案
CAN1终端电阻至少一个120Ω处于ON调整拨码开关位置
USB连接状态lsusb显示设备更换USB端口或线缆
电源指示灯稳定绿色检查供电电压(5V±10%)
CAN2环路测试自发自收数据一致检查波特率配置(需两端匹配)

4.2 常见故障排查指南

  1. 节点启动失败

    • 现象:error setting config #1: could not set config 1
    • 解决方案:
      sudo ip link set can0 down sudo ip link set can0 type can bitrate 250000 sudo ip link set can0 up
  2. 数据接收异常

    • 检查步骤:
      1. 确认终端电阻配置
      2. 使用candump can0验证物理层通信
      3. 检查波特率配置(本例使用250kbps)
  3. ROS节点权限问题

    • 进阶方案:将用户加入dialout组
      sudo usermod -aG dialout $USER

5. 性能优化与扩展

5.1 实时性提升方案

#include <sched.h> void setRealtimePriority() { struct sched_param param; param.sched_priority = sched_get_priority_max(SCHED_FIFO); if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) { ROS_WARN("Failed to set realtime scheduler"); } }

5.2 多设备管理架构

对于需要管理多个CANalyst-II设备的场景,建议采用如下架构:

+-----------------+ | Master Node | +--------+--------+ | +--------------+--------------+ | | +-------+-------+ +---------+---------+ | CAN Manager | | Data Processor | +-------+-------+ +---------+---------+ | | +----------+----------+ +---------+---------+ | Device Controller 1 | | Protocol Parser | +----------+----------+ +---------+---------+ | | +----------+----------+ +---------+---------+ | Device Controller N | | Data Publisher | +---------------------+ +-------------------+

实际项目中,我们发现CANalyst-II在持续高负载(>2000帧/秒)时可能出现USB缓冲区溢出。通过以下措施可显著改善:

  1. 增加USB读取频率至10ms
  2. 使用双缓冲机制减少数据丢失
  3. 在硬件层面添加CAN总线加速器
// 双缓冲实现示例 std::vector<VCI_CAN_OBJ> bufferA, bufferB; std::vector<VCI_CAN_OBJ>* activeBuffer = &bufferA; void receiveThread() { while (ros::ok()) { VCI_CAN_OBJ temp[100]; int received = VCI_Receive(device, index, channel, temp, 100, 10); if (received > 0) { std::unique_lock<std::mutex> lock(bufferMutex); activeBuffer->insert(activeBuffer->end(), temp, temp + received); } } }

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询