)
嵌入式ROS开发实战Jetson NX串口通信全流程解析在嵌入式机器人开发中串口通信扮演着连接传感器、执行器和计算单元的关键角色。NVIDIA Jetson NX凭借其强大的AI算力和紧凑的尺寸成为众多机器人开发者的首选平台。本文将带你从零开始在Jetson NX上搭建完整的ROS Melodic串口通信系统涵盖从环境配置到实际测试的全过程。1. 环境准备与驱动安装在开始之前确保你的Jetson NX已经安装了Ubuntu 18.04和ROS Melodic。这是ROS Melodic官方支持的操作系统版本能够提供最稳定的运行环境。安装ROS串口包sudo apt-get install ros-melodic-serial验证安装是否成功roscd serial/如果能够正常进入/opt/ros/melodic/share/serial目录说明串口驱动安装成功。提示Jetson NX的板载串口设备通常以ttyTHS开头这与普通PC上的ttyUSB或ttyACM有所不同。2. 创建工作空间与功能包ROS开发通常从创建工作空间开始。我们将创建一个专门用于串口通信的工作空间mkdir -p ~/serial_ws/src cd ~/serial_ws/src/ catkin_init_workspace cd ~/serial_ws/ catkin_make将工作空间添加到环境变量echo source ~/serial_ws/devel/setup.bash ~/.bashrc source ~/.bashrc创建功能包cd ~/serial_ws/src/ catkin_create_pkg serial_test roscpp rospy std_msgs serial3. 自定义消息类型在ROS中自定义消息类型可以让我们灵活地定义数据传输格式。以下是创建自定义消息的步骤在功能包中创建msg目录cd ~/serial_ws/src/serial_test mkdir msg cd msg gedit serial_test.msg编辑消息文件内容std_msgs/Header header float32 test1 int32 test2修改package.xml文件确保包含以下内容build_dependmessage_generation/build_depend exec_dependmessage_runtime/exec_depend更新CMakeLists.txt文件find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs serial message_generation ) add_message_files( FILES serial_test.msg ) generate_messages( DEPENDENCIES std_msgs ) catkin_package( CATKIN_DEPENDS message_runtime )4. 编写串口通信节点我们将创建两个ROS节点一个负责接收串口数据并发布到ROS话题另一个负责订阅话题并通过串口发送数据。4.1 串口接收节点(serial_test1.cpp)#include ros/ros.h #include serial/serial.h #include iostream #include string #include cstring #include serial_test/serial_test.h serial::Serial sp; ros::Publisher pub_serial_RX; ros::Subscriber sub_serial_TX; serial_test::serial_test serial_RX; void serial_tx_cb(const serial_test::serial_testConstPtr serial_tx_ptr) { uint8_t buffer[4]; buffer[0] 0xfd; buffer[1] 0x88; buffer[2] serial_tx_ptr-test1; buffer[3] serial_tx_ptr-test2; sp.write(buffer, sizeof(buffer)); } int main(int argc, char** argv) { ros::init(argc, argv, serial_test1); ros::NodeHandle n; sub_serial_TX n.subscribe(/serial_test_TX, 10, serial_tx_cb); pub_serial_RX n.advertiseserial_test::serial_test(/serial_test_RX, 10); serial::Timeout to serial::Timeout::simpleTimeout(100); sp.setPort(/dev/ttyTHS0); sp.setBaudrate(115200); sp.setTimeout(to); try { sp.open(); } catch(serial::IOException e) { ROS_ERROR_STREAM(Unable to open port.); return -1; } if(sp.isOpen()) { ROS_INFO_STREAM(/dev/ttyTHS0 is opened.); } else { return -1; } ros::Rate loop_rate(50); while(ros::ok()) { size_t n sp.available(); if(n 0) { uint8_t buffer[n]; sp.read(buffer, n); if(n 4 buffer[0] 0xfd buffer[1] 0x88) { serial_RX.test1 buffer[2]; serial_RX.test2 buffer[3]; pub_serial_RX.publish(serial_RX); } } ros::spinOnce(); loop_rate.sleep(); } sp.close(); return 0; }4.2 串口发送节点(serial_test2.cpp)#include ros/ros.h #include serial_test/serial_test.h ros::Publisher pub_serial_TX; ros::Subscriber sub_serial_RX; serial_test::serial_test serial_TX; void serial_rx_cb(const serial_test::serial_testConstPtr serial_rx_ptr) { ROS_INFO(Received data: test1%f, test2%d, serial_rx_ptr-test1, serial_rx_ptr-test2); } int main(int argc, char** argv) { ros::init(argc, argv, serial_test2); ros::NodeHandle n; sub_serial_RX n.subscribe(/serial_test_RX, 10, serial_rx_cb); pub_serial_TX n.advertiseserial_test::serial_test(/serial_test_TX, 10); ros::Rate loop_rate(1); // 1Hz for demonstration while(ros::ok()) { serial_TX.test1 1.0; serial_TX.test2 1; pub_serial_TX.publish(serial_TX); ros::spinOnce(); loop_rate.sleep(); } return 0; }5. 编译与测试5.1 编译配置更新CMakeLists.txt文件添加可执行文件add_executable(serial_test1 src/serial_test1.cpp) target_link_libraries(serial_test1 ${catkin_LIBRARIES}) add_dependencies(serial_test1 ${PROJECT_NAME}_generate_messages_cpp) add_executable(serial_test2 src/serial_test2.cpp) target_link_libraries(serial_test2 ${catkin_LIBRARIES}) add_dependencies(serial_test2 ${PROJECT_NAME}_generate_messages_cpp)编译工作空间cd ~/serial_ws catkin_make source devel/setup.bash5.2 硬件连接Jetson NX的板载串口引脚定义如下引脚编号功能8TX10RX6GND连接方式NX的TX(引脚8) → USB转串口模块的RXNX的RX(引脚10) → USB转串口模块的TXNX的GND(引脚6) → USB转串口模块的GND5.3 运行测试首先赋予串口权限sudo chmod 777 /dev/ttyTHS0启动ROS核心roscore在新终端中运行串口节点rosrun serial_test serial_test1在另一个终端中运行测试节点rosrun serial_test serial_test2使用rqt_graph查看节点关系图确认通信正常。6. 常见问题与解决方案问题1无法打开串口设备检查串口设备权限ls -l /dev/ttyTHS0确保没有其他程序占用串口尝试重新插拔USB转串口设备问题2数据接收不完整检查波特率设置是否一致确认硬件连接是否正确TX-RX交叉连接增加数据包头尾校验问题3ROS节点通信延迟调整发布/订阅队列大小优化循环频率ros::Rate参数检查系统负载情况注意在Jetson NX上板载串口的性能通常优于USB转串口建议优先使用ttyTHS系列端口。在实际项目中我发现为串口通信添加超时重连机制非常必要。以下是一个简单的重连实现示例void reconnect_serial() { if(!sp.isOpen()) { try { sp.open(); ROS_INFO(Serial port reconnected.); } catch(serial::IOException e) { ROS_WARN(Reconnection attempt failed.); } } }可以将此函数添加到主循环中定期检查串口连接状态。