# 机器人接入

我们先把直线读数对应到滑台位置或夹爪开口，然后再把角度读数对应到关节。开始时手动移动，只记录反馈；方向、单位、零点和断链处理检查清楚后，再设计电机控制。

本页的机构映射和 ROS 2 节点是扩展作业，仓库还没有机器人控制器或 ROS 2 驱动。

## 先测滑台或夹爪

先把直线 PCB 固定好，让磁铁随滑块移动，导向上放参考刻度。然后手动走几个位置，比较刻度、原码和输出值。

固件默认直线模型中，U1/U2/U4 等间距 10 mm，U2 为 0，朝 U4 为正方向。它根据零磁场基线和相邻信号比值估算磁铁位置。`0x07` 切换到直线测量类型后，原来的角度零点与校准会清除；必须按直线方法重新采基线。依据：[机械约定](../software/firmware/inc/hall_line.h#L5)，[测量类型切换](../software/firmware/src/rs485_proto.c#L902)。

接下来按这个顺序进行测试和记录：

1. 用刻度尺或位移台标出若干参考位置，固定磁铁高度、姿态和导向。
2. 拿开磁铁采集基线；放回后在参考位置反复读取三路 ADC 和位置。
3. 检查移动方向；在选定的机械参考位设零，写清“零是夹爪全开、全闭还是滑台中心”。
4. 把相同参考位置从正向和反向各走一遍，记录重复性、偏差及是否触发弱磁/越界。
5. 先观察位置，再用有时间间隔的差分估速度。最后才讨论把反馈接入运动控制器。

模型默认宽度 8 mm、内部限幅 ±15 mm。磁铁移出阵列后，输出可能不再跟随运动；先按[测量方法](Calibration-and-Measurement.md)确定能用的范围。

依据：[模型常量](../software/firmware/inc/hall_line.h#L18)，[插值与限幅](../software/firmware/src/hall_line.c#L121)。

### 单侧位移和总开口

若一侧夹爪移动、另一侧固定，传感器位移可以按机构方向直接映射到开口变化；若两侧对称移动，单侧位移的变化通常要乘 2 才是总开口变化。连杆、楔块或丝杆传动还可能有另外的比例或非线性关系。

先确定要测的是哪个量，再写公式。例如正方向为开合机构的“张开”，单侧直线位移为 `x_sensor_m`：

```text
单侧移动：opening_m = opening_at_zero_m + sign × x_sensor_m
对称移动：opening_m = opening_at_zero_m + 2 × sign × x_sensor_m
sign 只取 +1 或 -1，须由实际装配验证。
```

先检查机构是否符合上述运动关系，再使用公式。

## 再测旋转关节

把传感器按角度构型安装，并让径向充磁磁铁绕轴旋转，三路信号就可以用相位关系解算角度。固件给出的角度约定是：从上往下看逆时针为正，U1/U2/U4 分别在 0°/120°/240°；实际装配必须对照磁铁和 PCB 验证方向。

通信仍使用 `GET_INFO`、`GET_DATA`、零点与校准命令。区别是 `TYPE=1`，整数单位变成 0.01°，校准要转满至少一圈。切换测量类型会清零点和校准，不能把直线基线当作角度偏置使用。依据：[角度安装约定](../software/firmware/inc/hall_encoder.h#L11)，[模式切换清理](../software/firmware/src/rs485_proto.c#L251)。

角度结果为一圈内 `0..35999`。它适合在已知机械范围内观察关节角度，但源码没有保存多圈计数。主机连续展开只在相邻采样足够密、单次角位移小于半圈且没有长时间丢包时才能正确推断方向；重新启动或断链后不能据此恢复圈数。

依据：[角度结果结构](../software/firmware/inc/hall_encoder.h#L45)，[原 GUI 展开与速度估算](../software/host/app.py#L193)。

### 装在减速器哪一边

设减速比 `N = 电机轴转角 / 输出轴转角`，例如 N=50 表示电机转 50 圈、关节输出转 1 圈。在同一单位下、已正确获得连续电机轴角度的前提下：

```text
电机侧测量：q_joint_rad = sign × (theta_motor_unwrapped_rad - theta_motor_zero_rad) / N
输出侧测量：q_joint_rad = sign × (theta_output_rad - theta_output_zero_rad)
```

电机侧单圈角度不能直接唯一确定多圈输出关节角：减速器输出一圈时电机可已转 N 圈；还需要回零、圈数管理或另一绝对位置依据。输出侧直接测角能观察减速器后的运动，但装配弹性、回差、轴偏心和磁铁安装误差仍需验证。输出侧读数不再除以 N；电机侧也不能把单圈回卷值直接除以 N 当成绝对关节位置。

## 单位、方向和零点

读取完整帧后，先检查 TYPE，再换单位。解码后统一换成机器人使用的单位，日志里同时保留原始整数：

```text
直线：x_mm  = raw / 100
      x_m   = raw × 0.00001
角度：a_deg = raw / 100
      a_rad = raw × π / 18000

例如：raw=-1250、TYPE=2 → -12.50 mm → -0.0125 m
      raw=9000、TYPE=1  → 90.00°   → π/2 rad
```

固件两种模式复用 `angle_cdeg` 字段，字段名不能决定单位。把机械安装符号、传感器零点、关节模型零位分别记录；如果已经在设备设零，适配层不要再次减掉同一个零点。改变安装方向、磁铁高度、测量类型或校准后，都应重新检查映射。

ROS 使用 SI 单位与右手坐标系；长度为 m、角度为 rad。系统适配层应把板上“朝 U4 为正”或“俯视逆时针为正”映射到机器人实际关节轴定义。依据：[ROS 官方 REP-103 源文档](https://github.com/ros-infrastructure/rep/blob/master/rep-0103.rst)。

## 时间和速度

协议采样没有硬件时间戳。原 GUI 在收到并解析时调用 `time.perf_counter()`；新增示例同时给出主机 Unix 时间和单调时间，明确标记为主机接收解码时间。这些时间包含 USB、串口、设备处理和系统调度的延迟，与 ADC 采样时刻不同，也不能用于证明多传感器同步。

用于本机超时和速度差分时，使用单调时钟计算 `dt`；跨进程、记录或发布消息时，使用系统约定的时钟。若后续使用 ROS 的仿真时间，不能把 Python 单调时钟的秒数直接填入 ROS Header。

直线速度可以用 `(x_now-x_prev)/dt`；角速度先处理一圈回卷再差分。速度会放大位置噪声与接收间隔抖动，滤波会增加延迟。必须处理 `dt≤0`、时间跨度过大、断链恢复和相邻跳变。原 GUI 的平滑速度适合观察，未提供控制环延迟保证。

依据：[主机接收时间](../software/host/bus.py#L159)，[速度计算](../software/host/app.py#L193)，[新示例时间标记](../software/examples/hall_protocol.py)。

## 断链和异常

接收数据时依次检查：

```text
字节层：帧头、长度、CRC、地址、类型、命令、序号是否一致？
测量层：状态成功？弱磁、校准中、越界？量程和跳变是否合理？
应用层：数据多旧？机构单位、方向和零点是否与当前实验一致？
```

主机程序可用等待（WAITING）、正常（READY）、过期或故障（STALE/FAULT）四种状态：只有收到匹配且满足实验条件的新帧，才更新“最后接收时间”；超过设定的数据过期时间，标记 STALE，不把最后值当作新测量不断发布。通信恢复后先重新读信息并确认类型、ID和配置，再恢复位置流；多圈展开与差分速度重新初始化。

数据过期时间需结合运动风险、采集间隔和实测延迟来定。例如在课堂演示中可先观察 20 ms 请求周期的实际分布，再选择测试阈值；不能把未经验证的固定 100 ms 阈值当作安全指标。真实机器人断链后的限速、停机、保持或制动，应由运动控制系统的故障策略决定。

板上没有电机停机接口或独立保护通道。接电机前先只记录反馈，与已有位置依据比较，测过误差、延迟和异常行为后再设计闭环。

原 GUI 拔串口时会断开，但轮询超时仅记录日志；它不是机器人断链保护层。新命令行示例遇错停止输出，便于学习“没有新数据”与“位置没变”之间的差别。依据：[原 GUI 超时行为](../software/host/bus.py#L421)，[独立示例](../software/examples/read_sensor.py)。

## ROS 2 扩展作业

可以写一个串口节点：配置 joint name、设备 ID、方向、零位和传动比，复用字节解析；按类型输出 rad 或 m，另行发布 flags 和通信状态。

位置可用 `sensor_msgs/msg/JointState` 发布。其 `position` 对旋转关节用 rad、移动关节用 m；`velocity` 对应 rad/s 或 m/s。消息 Header 表示记录时刻，各数组应按名字对应、长度相同或留空。本项目没有测力或转矩测量，`effort` 应留空；`velocity` 在未实现并验证估算前也可留空。来源：[ROS 2 官方 JointState 消息定义](https://github.com/ros2/common_interfaces/blob/rolling/sensor_msgs/msg/JointState.msg)。

第一版节点应只接一台设备、发布一个关节，并注明时间是主机接收时间。轮询多设备时各帧并非同时采样，不要把不同时间的数据组合后声称同时记录。若继续做同步、多轴控制或 `ros2_control`，还需设计采样时间、通信负载和接口状态，并在整机上测试。

完成后检查四件事：移动正方向与模型一致；-12.50 mm 转成 -0.0125 m；手动拔线会出现明确失效状态且不重复新鲜读数；更换为角度 PCB 后需重校准、单位变为 rad，并能解释减速器测量位置的差别。

继续阅读：[上位机操作](Host-Tools.md) · [协议参考与十六进制样例](Protocol-Reference.md)。
