ESP32S3使用micro_ros_arduino实现ROS2通信差速底盘控制
目录
环境准备
硬件清单
| 硬件 | 说明 |
|---|---|
| ESP32-S3 开发板 | 推荐 DevKitC-1,带 USB OTG |
| USB-C 数据线 | 能传数据的,不是仅充电线 |
| LED(可选) | 用于状态指示 |
软件版本要求
| 软件 | 版本 | 备注 |
|---|---|---|
| Arduino IDE | ≥ 2.0 | 或 VS Code + PlatformIO |
| ESP32 Board Package | 2.0.11 | 不要用 3.x! |
| micro_ros_arduino | humble 分支 | 必须 Git 克隆完整版 |
| ROS2 | Humble | Ubuntu 22.04 |
| micro-ROS Agent | humble | 通过 Snap 安装 |
ESP32-S3 机器人控制器 · 使用文档
适用固件版本:
v1.0.0
已验证环境:Arduino IDE 2.x + esp32 core 2.0.11 + micro_ros_arduino 2.0.8-humble + ROS 2 Humble
实测构建结果:Flash 790,785 B(60%)、静态 RAM 111,140 B(33%)
0. 30 秒快速上手
1 | ① 接线 → 见 §2(电机 UART1 / 雷达 UART2 / 共地) |
先读 §9 安全须知。这台机器会动。
1. 硬件清单
| 部件 | 规格 | 说明 |
|---|---|---|
| 主控 | ESP32-S3(DevKitC-1 等,N8R2/N8R8 均可) | 双核,本工程用了 Core0/Core1 分工 |
| 电机 | JGB37-520 ×4,12V | 减速比 1:13,编码器 11 PPR(霍尔 A/B 相) |
| 驱动 | 串口四路电机驱动板 | ASCII 协议 $指令:参数#,板载速度闭环 PID + 编码器采集 + 电池电压采集 |
| 雷达 | YDLIDAR X2 | 三角测距,5V 约 400mA,TTL 3.3V 串口 115200 |
| 轮子 | 麦克纳姆轮 ×4,直径 60mm | 也支持四轮差速(改一个矩阵即可,见 §5.6) |
| 电池 | 12V(3S 锂电等) | 驱动板直接供电;雷达需 5V |
2. 接线
2.1 引脚表(默认值,可在 config.h §2 修改)
| 信号 | ESP32-S3 引脚 | 对端 | 备注 |
|---|---|---|---|
| 电机串口 RX | GPIO4 | 驱动板 TX | 交叉接线 |
| 电机串口 TX | GPIO5 | 驱动板 RX | 交叉接线 |
| 雷达串口 RX | GPIO6 | 雷达 TX | 交叉接线 |
| 雷达串口 TX | GPIO7 | 雷达 RX | X2 正常扫描时不需要,仅供查询 |
| 状态 LED | GPIO48 | 板载 WS2812 | STATUS_LED_IS_WS2812 1 |
| 电池 ADC | GPIO1 | 分压电路 | 默认关闭,见 §2.4 |
2.2 电源与共地(最容易忽略、后果最严重)
- 所有 GND 必须连在一起:ESP32、驱动板、雷达、电池负极。串口电平以地为参考,不共地会出现”时好时坏的乱码”。
- 雷达单独确认 5V 能力:X2 启动瞬间电流较大,若从驱动板的 5V 取电后雷达转不起来或反复重启,改用独立 5V/1A 模块。
- 电机电源与逻辑电源:电机启停会在电源上产生尖峰。若出现 ESP32 随机重启,优先怀疑电源跌落,在电机电源端并 470µF 以上电解电容。
- ESP32-S3 的
GPIO0/3/45/46是 strapping 脚、GPIO19/20是原生 USB、GPIO26~37可能被 Flash/PSRAM 占用,本工程已避开,不要随意改到这些脚上。
2.3 X2 雷达接口
| X2 引脚 | 接到 |
|---|---|
| 5V | 5V 电源 |
| GND | 共地 |
| TX | ESP32 GPIO6 |
| RX | ESP32 GPIO7(可悬空) |
标准 X2 是 4pin,上电即自动旋转并连续输出数据,不需要任何启动命令。
若你的是 X2L(多一个电机控制脚),把 config.h 的 LIDAR_MOTOR_PIN 填上对应 GPIO——
注意 X2L 是「悬空=转,拉高=停」,与常见的高电平使能相反,驱动里已按此处理。
2.4 电池电压:两种方式二选一
方式 A(推荐,默认):让驱动板自己测。固件每秒发一次 $read_vol#,解析回包。
什么都不用接。
方式 B:ESP32 自己分压采样。改 config.h:
1 |
⚠️ 上电前必须算清楚分压比。ESP32-S3 的 ADC 在 11dB 衰减下满量程约 3.1V,
12V 电池经 5:1 分压后是 2.4V,安全。直接接 12V 会立刻烧掉引脚。
分压电阻建议 100k / 24k(比值 5.17),并在 ADC 脚对地并 0.1µF 电容。
3. 软件环境准备
3.1 版本要求(重要)
| 组件 | 必须的版本 | 原因 |
|---|---|---|
| esp32 core | 2.0.x(实测 2.0.11) | micro_ros_arduino 2.0.8-humble 的预编译库 libmicroros.a 是针对 2.0.x 编译的。换成 core 3.x 会出现大量未定义符号,必须同时更换 micro_ros_arduino 版本 |
| micro_ros_arduino | 2.0.8-humble | 与 ROS 2 Humble 的 Agent 配套 |
| ROS 2 | Humble | Agent 与客户端版本需一致 |
查看已装 core 版本:开发板管理器里搜 esp32。
3.2 安装 micro_ros_arduino 库
库必须放在用户库目录:<你的文档目录>\Arduino\libraries\micro_ros_arduino\
安装后自检这三项必须都存在(缺任何一项都会编译失败):
1 | libraries\micro_ros_arduino\library.properties |
装完重启 Arduino IDE(IDE 只在启动时扫描库)。
3.3 PC 端启动 micro-ROS Agent
1 | # 方式一:原生安装(推荐) |
-v6是详细日志,排障时一定要加,能看到 ESP32 的握手过程。- 放行 UDP 8888:Windows 首次运行会弹防火墙询问,必须选「允许」。
- 确认 PC 的局域网 IP:Windows
ipconfig,Linuxip addr。
WSL2 用户的常见坑:若 ROS 2 装在 WSL2 里,Agent 也在 WSL2 里,
那么AGENT_IP要填 WSL2 的 IP(ip addr里的 eth0 地址,通常 172.x.x.x),
而不是 Windows 的 IP。并且 WSL2 默认 NAT 模式下 ESP32 无法直接访问 WSL2,
需要配置镜像网络(.wslconfig里networkingMode=mirrored)或做端口转发。
如果一直连不上,先把 Agent 放到能直连的机器/树莓派上验证。
4. 配置 config.h
config.h 是整个工程唯一需要按硬件修改的文件。按下面四档处理:
4.1 必须改(不改就连不上)
| 宏 | 说明 |
|---|---|
WIFI_SSID |
WiFi 名(ESP32 只支持 2.4GHz,不支持 5GHz) |
WIFI_PASSWORD |
WiFi 密码 |
AGENT_IP |
PC 的局域网 IP,不是 ESP32 的 IP,也不是 127.0.0.1 |
AGENT_PORT |
默认 8888,与 Agent 启动参数一致 |
4.2 首次上车建议先收紧(跑通再放开)
| 宏 | 默认 | 建议首次 |
|---|---|---|
MAX_LINEAR_SPEED_MPS |
0.80 | 0.30 |
MAX_ANGULAR_SPEED_RPS |
2.00 | 1.00 |
MAX_LATERAL_SPEED_MPS |
0.60 | 0.20 |
CMD_TIMEOUT_MS |
500 | 500(别调大,这是失联保护) |
4.3 标定时改(见 §6)
| 宏 | 默认 | 什么时候改 |
|---|---|---|
WHEEL_DIAMETER_MM |
60.0 | 实测轮径后 |
ENCODER_EDGES_PER_PPR |
4.0 | 确认编码器倍频后(1/2/4) |
MOTOR_WIRE_FL/FR/RL/RR |
0/1/2/3 | 接线顺序与丝印不一致时 |
MOTOR_DIR_SIGN_FL/FR/RL/RR |
全 +1 | 某个轮子转向相反时 |
WHEEL_TRACK_MM |
200.0 | 实测左右轮中心距后 |
KINEMATICS_MATRIX |
麦克纳姆 X 型 | 横移/自转方向不对时 |
MOTOR_DEADZONE |
1650 | 电机低速抖动或起步困难时(0~3600) |
LIDAR_REVERSE_DIRECTION |
0 | RViz 里地图左右镜像时改 1 |
4.4 一般不用改
引脚、波特率、发布频率、看门狗阈值、LIDAR_SCAN_BINS、调试等级 DEBUG_LEVEL。
调试输出等级:DEBUG_LEVEL 0=静默 1=只错误 2=常规(默认)3=每帧收发明细。
查协议问题时设 3。
5. 编译、烧录、上电自检
5.1 Arduino IDE 板子设置
| 选项 | 值 |
|---|---|
| Board | ESP32S3 Dev Module |
| Flash Size | 按模组(常见 4MB / 8MB / 16MB) |
| PSRAM | 按模组(N8R8 选 OPI PSRAM,N8R2 选 QSPI) |
| Partition Scheme | 默认(Default 4MB with spiffs)→ App 空间 1,310,720 B |
| Upload Speed | 921600 |
5.2 编译
直接点编译即可。占用(实测):
1 | Sketch uses 790785 bytes (60%) of program storage space. Maximum is 1310720 bytes. |
其中约 21KB 是雷达的双缓冲和原始点缓存。RAM 余量充足。
5.3 上电后应该看到什么
打开串口监视器(115200),正常启动日志长这样:
1 | ================================================================== |
状态 LED(GPIO48 板载 WS2812)一眼判断工况:
| 颜色 | 含义 |
|---|---|
| 白色常亮 | 启动中 |
| 蓝色慢闪(1Hz) | 等待 ROS 连接 |
| 绿色常亮 | 正常运行 |
| 黄色快闪(5Hz) | ROS 掉线,降级模式(电机已停,后台自动重连) |
| 红色急促闪(10Hz) | 故障(通常是编码器遥测丢失) |
5.4 关键自检项
每 5 秒打印一次状态摘要,重点看这几行:
1 | 编码器: 1000 -2000 3000 -4000 (12ms 前) ← 有数据且在刷新 = 驱动板通信正常 |
帧头 AA55或55AA都正常,未同步才是问题。包 x/y(坏)里 y 应该接近 0(偶发几个是正常的)。
6. 标定流程(★ 必须做,约 20 分钟 ★)
全程把车架空,轮子离地。 标定过程中电机会突然转动。
① 编码器倍频确认
轮子上贴个标记,手动缓慢转 10 圈,看串口摘要里 编码器 第 1 个数的增量 Δ。
1 | ENCODER_EDGES_PER_PPR = Δ / (11 × 10) |
| 实测 Δ | 结论 | 填写 |
|---|---|---|
| ≈ 5720 | 四倍频 | ENCODER_EDGES_PER_PPR 4.0f(默认) |
| ≈ 2860 | 二倍频 | 2.0f |
| ≈ 1430 | 单相单沿 | 1.0f |
这项错了,里程计会按整数倍偏差——这是最常见的”走 1 米显示 0.25 米”的原因。
② 轮径实测
让车直线走 2 米(地上画线),记录 encoder_data 的总计数 Δc。
1 | 实际轮周长(mm) = 2000 / (Δc / ENCODER_COUNTS_PER_REV) |
把算出的轮径填回 WHEEL_DIAMETER_MM。
③ 速度满量程标定
1 | ros2 topic pub --once /motor_speeds std_msgs/msg/Int32MultiArray "{data: [500, 500, 500, 500]}" |
用秒表+卷尺实测车速 v。理论值 = 0.5 × WHEEL_MAX_LINEAR_MPS = 0.575 m/s。
若实测偏小,按比例调小 MOTOR_RATED_RPM(例:实测 0.46 m/s → 366 × 0.46/0.575 ≈ 293)。
注意:
/motor_speeds是直通模式,不受MAX_LINEAR_SPEED_MPS限制,且 500ms
内没有新指令就会自动停车。测试时用--once发一次即可,安全。
④ 轮序与方向(四步测试法)
逐个轮子发指令,记录哪个物理轮子转、朝哪个方向转:
1 | ros2 topic pub --once /motor_speeds std_msgs/msg/Int32MultiArray "{data: [100, 0, 0, 0]}" |
数组下标约定固定为 [0]=左前 1=右前 2=左后 3=右后(车头朝前、从上往下看)。
- 第 i 个位置转的不是对应轮子 → 改
MOTOR_WIRE_FL/FR/RL/RR(逻辑轮位 → 驱动板 M 口,0 基)。 - 某个轮子「正指令时朝后转」→ 把该轮的
MOTOR_DIR_SIGN_*改成-1.0f。
改完复测,直到 4 个位置各自对应正确轮子且都朝前。
⑤ 运动学矩阵校验
三个单向测试,每个都必须”纯”:
1 | # 只发前进 → 必须严格直行,不能斜着走 |
哪个不对,就改 config.h §4 的 KINEMATICS_MATRIX 对应行的 vy 或 wz 列符号。
辊子朝向不同,试这几种组合即可(不用改算法代码):
1 | [1,+1,-1] / [1,-1,+1] / [1,+1,+1] / [1,-1,-1] |
⑥ 原地转 360° 验证
1 | ros2 topic pub -r 10 /cmd_vel geometry_msgs/msg/Twist "{angular: {z: 0.5}}" |
实际转过的角度与 /odom 的偏航角应基本一致(差 10% 以内)。
差得多 → 回 ④⑤ 检查;系统性偏大/偏小 → 检查 WHEEL_TRACK_MM 与 KINEMATICS_WZ_SCALE_MM。
7. ROS 2 接口
7.1 话题总览
订阅(PC → ESP32)
| 话题 | 类型 | 元素含义 | 说明 |
|---|---|---|---|
/cmd_vel |
geometry_msgs/Twist |
linear.x 前后 m/s,linear.y 横移 m/s,angular.z rad/s |
正常导航用这个,走完整运动学 |
/motor_speeds |
std_msgs/Int32MultiArray |
4 个 ±1000,顺序 FL,FR,RL,RR | 直通,不经运动学、不限速。标定/排障用 |
/motor_pwm |
std_msgs/Int32MultiArray |
4 个 ±3600 | 开环 PWM,绕过驱动板速度闭环。警告见 §7.4 |
/motor_config |
std_msgs/Float32MultiArray |
见 §7.3 下标表 | 运行期改参数 |
发布(ESP32 → PC)
| 话题 | 类型 | 频率 | 说明 |
|---|---|---|---|
/encoder_data |
std_msgs/Int32MultiArray |
20 Hz | 4 个轮子累计编码器计数(顺序 FL,FR,RL,RR) |
/battery_voltage |
std_msgs/Float32 |
1 Hz | 电池电压 V |
/odom |
nav_msgs/Odometry |
20 Hz | 里程计位姿与速度 |
/scan |
sensor_msgs/LaserScan |
10 Hz | 720 格,0.5°/格,量程 0.1~8m |
/lidar_points |
sensor_msgs/PointCloud2 |
10 Hz | x/y/z float32,2D 平面点云 |
7.2 模式仲裁规则(重要)
四个订阅话题都能控制电机,规则是「谁最后到,谁生效」:
- 任意模式下,超过
CMD_TIMEOUT_MS(默认 500ms)没有新指令 → 自动停车并回到空闲。 /cmd_vel与直通模式互斥:发了/motor_speeds之后,下一帧/cmd_vel会夺回控制权。- 遥测故障(4 秒收不到编码器)会强制进入故障态停车,需要遥测恢复 + 收到新指令才自动解除。
7.3 /motor_config 下标表
发 Float32MultiArray,按需填前缀,没填的下标保持不变(值为 0 表示”本次不改”,PID 用 -1 表示不改):
| 下标 | 含义 | 单位 | 生效方式 |
|---|---|---|---|
| 0 | 最大线速度 | m/s | 立即 |
| 1 | 最大角速度 | rad/s | 立即 |
| 2 | 最大横移速度 | m/s | 立即 |
| 3 | 线加速度限幅 | m/s² | 立即 |
| 4 | 角加速度限幅 | rad/s² | 立即 |
| 5 | 指令超时 | ms | 立即 |
| 6 | 轮径 | mm | 写入驱动板 $wdiameter |
| 7 | 减速比 | — | 写入驱动板 $mline |
| 8 | PWM 死区 | — | 写入驱动板 $deadzone |
| 9 | PID-P | — | 写入驱动板 $MPID ⚠️ |
| 10 | PID-I | — | 同上 ⚠️ |
| 11 | PID-D | — | 同上 ⚠️ |
1 | # 例:把限速降到 0.3 m/s、角速度 1.0 rad/s |
⚠️ 下标 9/10/11 会让驱动板重启约 0.6 秒并把电机停掉(驱动板文档明确说明)。
这是正常现象,但不要带着目标速度去改 PID——固件会在写完后强制回到空闲态。
7.4 开环 PWM 的警告
/motor_pwm 绕过驱动板的速度闭环,没有速度反馈,坡道上会溜车。
只用于测死区、测电机极性、做阶跃响应实验。导航中不要使用。
7.5 RViz2 配置要点
1 | rviz2 |
| 设置 | 值 |
|---|---|
| Fixed Frame | odom(或 base_footprint,取决于你补的 TF) |
| 添加 LaserScan | Topic /scan,Size 0.03,Style Points |
| 添加 PointCloud2 | Topic /lidar_points,Size 0.02 |
| 添加 Odometry | Topic /odom |
7.6 TF 树(必须自己补)
本固件只发布 /odom 数据,不发布 TF。 TF 由 PC 端提供,两条链:
1 | odom ──(动态,随车移动)──> base_footprint ──(静态,安装位置)──> laser_frame |
静态链(雷达安装位置,z 填雷达实际离地高度,Nav2 避障正确性依赖它):
1 | ros2 run tf2_ros static_transform_publisher \ |
动态链(odom → base_footprint)二选一:
- 方案 A(推荐,同时融合其他传感器):用
robot_localization的 EKF,订阅/odom,设publish_tf: true。 - 方案 B(最简):写一个 10 行的小节点订阅
/odom,用tf2_ros TransformBroadcaster转发。
为什么不在 ESP32 上直接发 TF:会额外占用带宽和消息类型,而且 TF 的权威源
通常应该在上位机(便于融合 IMU 等)。代码里FRAME_ID_*常量已经按这套约定命名。
7.7 接 Nav2
只要 /scan + /odom + TF 三条链齐全,Nav2 就能用。建议:
- 先用
slam_toolbox建图,确认/scan在 RViz 里方向正确(见 §8 镜像问题)。 - 把
MAX_LINEAR_SPEED_MPS调到与 Nav2 的max_vel_x匹配,避免指令被固件截断产生”跟不上路径”的假象。
8. 故障排查
8.1 编译类
| 报错 | 原因 | 处理 |
|---|---|---|
geometry_msgs/msg/twist.h: No such file or directory |
Arduino 的库依赖探测按源码顺序扫描,遇到解析不了的 include 就中断,导致 micro_ros_arduino 库没被识别 | 已修复。请确认 ESP32S3_Robot.ino 顶部保留了 #include <micro_ros_arduino.h> 且在所有头文件之前;motor_ros_bridge.h/lidar_ros_bridge.h 里也各有一行。不要删、不要调顺序 |
micro_ros_arduino.h: No such file or directory |
库没装或没重启 IDE | 见 §3.2,装完重启 IDE |
大量 undefined reference to ... |
core 版本不是 2.0.x,或用了非 esp32s3 的预编译库 | 换回 core 2.0.11(见 §3.1) |
region dram0_0_seg overflowed |
RAM 不够(一般是自己加了很大的静态数组) | 减小 LIDAR_CLOUD_MAX_POINTS 或 LIDAR_SCAN_BINS |
8.2 连接类
| 现象 | 排查 |
|---|---|
| LED 一直蓝色慢闪,串口停在「连接 WiFi」 | SSID/密码错;路由器是 5GHz(ESP32 不支持);信号太弱 |
| WiFi 连上了但「Agent 无响应」 | ① Agent 没启动 → 在 PC 上跑 §3.3 的命令;② AGENT_IP 填错(必须是 PC 的局域网 IP,不是 127.0.0.1);③ PC 防火墙拦了 UDP 8888;④ PC 和 ESP32 不在同一网段 |
| 连上一次后频繁掉线(LED 黄闪) | 信号弱;把 AGENT_PING_INTERVAL_MS 调大;检查是否有多个 Agent 抢同一个端口 |
| 一直提示「ROS 时间同步失败」 | Agent 侧时钟异常;不影响控制,但 RViz 可能报时间戳过旧 |
8.3 电机类
| 现象 | 原因与处理 |
|---|---|
完全不动,/encoder_data 无数据 |
电机串口接线反了(TX/RX 要交叉);波特率不是 115200;驱动板没供电 |
| 上电后电机「嗡」一下或抖动 | MOTOR_DEADZONE 不合适。从 1650 起,每次 ±100 试,直到低速不抖、起步顺畅 |
| 发前进车往后走 / 原地打转 | 轮序或方向没标定。做 §6 ④ |
| 发前进车斜着走 | 运动学矩阵与辊子朝向不符。做 §6 ⑤ |
| 发横移车不动或很慢 | 麦克纳姆横移效率天然低于纵向;确认 MAX_LATERAL_SPEED_MPS 不是 0;确认矩阵 vy 列符号 |
| 一给速度就进入故障态 | 驱动板不上报编码器。检查 $upload 设置、串口线、以及是否打开了 MOTOR_PROTOCOL_SNIFF 看板子到底发了什么 |
| 电机偶尔自己停一下 | 500ms 指令超时触发。用 -r 10 以上频率持续发指令;或网络卡顿 |
| 驱动板每次上电都重启一次 | MOTOR_WRITE_PID_ON_BOOT 被设成了 1。写 PID 必然重启,确认参数后改回 0 |
8.4 雷达类
| 现象 | 原因与处理 |
|---|---|
| 串口提示「已连续收到 N 字节仍未同步」 | ① 雷达 TX 没接到 GPIO6;② 波特率不是 115200;③ 少数固件帧头顺序不同 → 把 LIDAR_HEADER_ORDER 显式设为 1 或 2 |
帧头 未同步 但有点数 |
只是还没确认顺序,不影响;若 包 0/大量坏 才是真问题 |
| 扫描有规律的空洞 | 串口丢数据。X2 每秒 6.5KB,确认没有长时间关中断的操作;LIDAR_TASK_PRIO 不要降低 |
| RViz 里地图左右镜像 | LIDAR_REVERSE_DIRECTION 改 1(注意:这个开关同时作用于 /scan 与点云,改完两者仍然一致) |
| 近处物体角度偏 | 距离相关角度校正默认开启(LIDAR_DIST_CORRECTION 1),若你自行标定过可关掉 |
| 雷达不转 | 5V 供电能力不足(X2 启动电流大);X2L 的电机脚被拉高了 |
/scan 没有数据但串口显示雷达在线 |
TF/坐标系没配,RViz 显示不出来;或 LIDAR_MIN_VALID_POINTS 门限(40 点)没达到 |
8.5 里程计类
| 现象 | 排查 |
|---|---|
| 走 1 米显示 1.25 / 0.8 米 | 编码器倍频错(§6 ①)或轮径不准(§6 ②) |
| 转 360° 显示 300° | WHEEL_TRACK_MM / KINEMATICS_WZ_SCALE_MM 不准;地面打滑 |
| 里程计不动 | /encoder_data 没数据,或数据不刷新 |
| 里程计跳变 | 编码器数据间隔超过 1 秒(固件会重设基准并告警),检查通信质量 |
9. 安全须知(★ 必读 ★)
- 上电前把车架空,或放在足够空旷的地面并确认没人。
- 首次运行务必先收紧限速(§4.2),跑通后再逐步放开。
- 指令看门狗是您的主要保护:500ms 无指令自动停车。不要为了”跑得更顺”把它调大 —— WiFi 一断,ROS 就再也发不出停止指令了。
- 调试时用
--once或低频-r,不要用-r 100长时间狂发速度。 - 改 PID 会让驱动板重启停车,不要在车跑动时改。
/motor_pwm是开环的,坡道会溜车,仅用于台架测试。- 串口/电源接线改动后必须重新上电,不要带电插拔电机线(反电动势可能损坏驱动板)。
- 出现异常行为时,最快的安全动作是直接断电池,而不是去点 RViz 的停止按钮。
10. 目录结构与附加工具
10.1 草稿根目录(正好 12 个标签页)
| 文件 | 职责 |
|---|---|
ESP32S3_Robot.ino |
主程序:系统状态机、三任务创建、状态 LED、卡死自恢复 |
config.h |
全部可调参数(含参数传递链推导与标定流程说明) |
micro_ros_handler.h/.cpp |
通信层:连接状态机、4 订阅 / 5 发布、时间同步 |
motor_protocol.h/.cpp |
驱动层:串口协议、物理量换算、麦克纳姆运动学、里程计 |
motor_ros_bridge.h/.cpp |
语义层:速度策略、模式仲裁、双重看门狗 |
ydlidar_x2.h/.cpp |
雷达驱动:X2 协议解析、分圈、分箱、双缓冲 |
lidar_ros_bridge.h/.cpp |
语义层:LaserScan / PointCloud2 构造 |
10.2 附加目录(不是标签页,不参与编译)
| 路径 | 内容 |
|---|---|
data/docs/ |
本使用文档 + 修改文档 |
data/host_test/ |
宿主机单元测试(Arduino 替身头文件 + 76 项断言) |
tools/check_compile.ps1 |
用真实 xtensa 工具链做语法/类型校验 |
tools/run_host_tests.ps1 |
在 PC 上编译并运行单元测试 |
为什么放在
data/里:Arduino 官方规范规定data/目录不被编译、
不显示为标签页,而且文件 > 另存为时会连同一起复制。
10.3 改动代码后如何自查
1 | # 语法/类型校验(需要本机装有 esp32 core 2.0.11 与对应工具链) |
两个脚本都会打印逐项结果并给出总数,改完代码跑一遍能挡掉绝大多数低级错误。
11. 命令速查
1 | # ---- 启动 Agent ---- |
12. 已知限制
- 驱动板的上传帧格式未在协议文档中给出。固件实现了容错解析(多别名 + “未知指令但恰好 4 个整数按编码器处理” + 裸 CSV 支持)并带嗅探日志。
首次上电请看串口有没有未知帧 #n: "xxx:yyy"的告警——若有,把那个指令名加进motor_protocol.cpp的别名表即可(10 秒的事)。 - 不发布 TF,需在 PC 端补
odom → base_footprint(见 §7.6)。 - X2 不提供每点强度,
LaserScan.intensities填的是常数(协议本身没有该字段)。 - X2 的距离相关角度校正系数(基线 21.8mm / 焦距 155.3mm)取自 YDLidar SDK,对 X2 是通用值;若你需要更高的角度精度,可关掉该校正后自行标定。
- 固件只支持单 Agent,不支持多机命名空间隔离(
ROS_NAMESPACE可改但未做多实例验证)。