This repository has been archived on 2024-06-28. You can view files and clone it, but cannot push or open issues/pull-requests.
Autolabor_m2/car/CustomAutocan.md

214 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# AutolaborM2串口通讯协议
AutolaborM2采用串口通讯通讯波特率为***115200***。通讯消息分为无数据域和有数据域两种类型。其中无数据域类型主要用于查询指令。
串口连接成功后,能收到机器人上报的里程计消息和车辆速度、转角消息,可依此作为机器人连接的判断。当前车辆上报得到左轮轮速和右轮轮速是直接从编码器给出的***角速度***单位为rad。如果需要知道车轮线速度则需要查询车辆轮半径根据轮半径计算出车轮线速度。比如角速度10rad/s车轮半径0.15m则线速度v = 10 * 0.15 = 1.5m/s
机器人有三种急停方式:硬件开关急停、手柄远程急停、软件消息急停。三种急停均可使得车辆立即停止。其中***硬件急停优先级最高***,直接切断电机供电。在发送急停消息后,可根据查询机器人状态信息来判断是否成功进入急停。如果发现机器人进入急停状态,可根据查询消息,判定急停触发的来源。
M2底盘为阿卡曼转向结构机器人的运动控制采用***两轮自行车模型***,控制量为***前轮转角和后轮转速***。其中转速为***相对速度***需要用户根据查询到的车辆最大速度计算出相对速度大小。比如查询到车辆最大速度为2m/s想要让车辆按照1m/s的速度运行则需要发送 v = 1/2 = 0.5。
机器人速度控制时会检查TCU左电机ECU右电机ECU状态如果状态异常则不会执行控制指令。此时会向上位机报告异常状态异常状态中包括急停、编码器数据异常、电流保护和机械刹车。
## 1、两种数据消息
* 无数据域消息
* 长度6个字节(1个字节帧头FE + 4字节消息类型 + CRC8校验)
![NoDataPackage.png](./img/NoDataPackage.png)
* 有数据域消息
* 长度14个字节(1个字节帧头FE + 4字节消息类型 + 8字节数据(小端模式) + CRC8校验)
![WithDataPackage.png](./img/WithDataPackage.png)
## 2、查询指令
* 查询指令:无数据域包
* 反馈指令:有数据域包
| 消息ID | 内容 | 反馈数据(8字节) | 数据含义 |
|------------|---------------|---------------------------------|------------------------------------------------|
| 0D 00 80 00| 状态 | [0]运行状态[1]-[7]保留 |10:正常运行 ff急停状态 |
| 0D 00 11 00| 剩余容量百分比 | [0] uint8 [1]-[7]保留 | [0 100]% (采样频率=1Hz |
| 0D 00 12 00| 剩余可用时间 | [0]-[3] uint32 [4]-[7]保留 | [0 360000]s (采样频率=1Hz |
| 0D 00 13 00| 剩余容量 | [0]-[3] uint32 [4]-[7]保留 | [0 5000000]mAh (采样频率=1Hz |
| 0D 00 14 00| 电池电压 | [0][1] uint16 [2]-[7]保留 | [0 500000]mV (采样频率=1Hz |
| 0D 00 15 00| 电池电流 | [0]-[3] uint32 [4]-[7]保留 |[-750000 750000]mA 正:电池充电,负:电池放电(采样频率=1Hz |
| 0D 00 17 00| 急停开关 | [0]bool[1]-[7]保留 |0正常 1急停 |
| 0D 00 18 00| 查询软急停 | [0]bool[1]-[7]保留 |0正常 1急停 |
| 0D 00 19 00| 查询手柄急停 | [0]bool[1]-[7]保留 | 0正常 1急停 |
| 0D 00 1a 00| 查询最大线速度 | [0]-[3]float [4]-[7]保留 |根据车轮大小计算出的最大线速度(m/s) |
| 0D 00 1b 00| 查询最大转角 | [0]-[3]float [4]-[7]保留 |根据机械结构得到的最大转角(rad) |
| 0D 00 1c 00| 查询车辆宽度 | [0]-[3]float [4]-[7]保留 |根据机械结构得到的车宽(m) |
| 0D 00 1d 00| 查询车辆长度 | [0]-[3]float [4]-[7]保留 |根据机械结构得到的车长(m) |
| 0D 00 1e 00| 查询轮半径 | [0]-[3]float [4]-[7]保留 |根据机械结构得到的车轮半径(m) |
***查询范例***
| 指令 | 单位 | 写字节流 |
|---------|------|----------------------|
| 状态查询 | | `FE 0D 00 08 00 B2`|
| 剩余容量百分比 | |`FE 0D 00 11 00 B5`|
| 剩余可用时间 | 秒 |`FE 0D 00 12 00 E0`|
| 剩余容量 | mAh | `FE 0D 00 13 00 2A`|
| 电池电压 | 10mV | `FE 0D 00 14 00 4A`|
| 电池电流 | 1mA | `FE 0D 00 15 00 8E`|
| 急停开关 | | `FE 0D 00 17 00 1F`|
| 查询软急停 | | `FE 0D 00 18 00 07` |
| 查询手柄急停 | | `FE 0D 00 19 00 C3` |
| 查询最大线速度 | m/s | `FE 0D 00 1A 00 96` |
| 查询最大转角 | rad | `FE 0D 00 1B 00 52` |
| 查询车辆宽度 | m | `FE 0D 00 1C 00 3C` |
| 查询车辆长度 | m | `FE 0D 00 1D 00 F8` |
| 查询轮半径 | m | `FE 0D 00 1E 00 AD` |
***查询结果:***
| 指令 | 反馈字节流 | 含义 |
|---------|-----------------------------------------------------------------------|---------------|
| 状态查询 | `FE 2D 00 80 00 10 00 00 00 00 00 00 00 09` | 状态正常 |
| 剩余容量百分比 | `FE 2D 00 11 00 64 00 00 00 00 00 00 00 79` | 容量100% |
| 剩余可用时间 | `FE 2D 00 12 00 50 C3 00 00 00 00 00 00 CC` | 剩余50000s |
| 剩余容量 | `FE 2D 00 13 00 50 C3 00 00 00 00 00 00 02` | 剩余50000mAh |
| 电池电压 | `FE 2D 00 14 00 7D 00 00 00 00 00 00 00 99` | 1.25V |
| 电池电流 | `FE 2D 00 15 00 4D 08 00 00 00 00 00 00 5A` | 2.125A |
| 急停开关 | `FE 2D 00 17 00 01 00 00 00 00 00 00 00 58` | 急停开关按下 |
| 查询软急停 | `FE 2D 00 18 00 01 00 00 00 00 00 00 00 26` | 软急停触发 |
| 查询手柄急停 | `FE 2D 00 19 00 01 00 00 00 00 00 00 00 E8` | 手柄急停按下 |
| 查询最大线速度 | `FE 2D 00 1A 00 00 00 C0 3F 00 00 00 00 94` | 最大线速度1.5m/s |
| 查询最大转角 | `FE 2D 00 1B 00 92 0A 06 3F 00 00 00 00 BC` | 最大转角0.523Rad |
| 查询车辆宽度 | `FE 2D 00 1C 00 00 00 00 3F 00 00 00 00 9D` | 0.5m |
| 查询车辆长度 | `FE 2D 00 1D 00 66 66 26 3F 00 00 00 00 83` | 0.65m |
| 查询轮半径 | `FE 2D 00 1E 00 9A 99 19 3E 00 00 00 00 D2` | 0.15m |
## 3、控制指令(有数据域消息类型)
* 运动控制(v theta)
* 运动控制具有超时机制需要在200ms内发送一帧数据否则会认为数据超时车辆停止运动。
* v: 车辆最大速度的百分比,取值范围[-1 -1],对应从倒退最大速度到前进最大速度。
* theta: 前轮转角单位rad弧度制。车辆向左转为正。
* 4字节消息类型`2D 00 01 00`
* 8字节数据前4字节表示v后4字节表示theta
* 数据类型float
* 范例:`FE 2D 00 01 00 CD CC CC 3D CD CC 4C 3E 82`
* 指令含义v:0.1相对速度theta:0.2rad
* 重置里程计
* 4字节消息类型`0D 00 02 00`
* 范例:`FE 0D 00 02 00 0C`
* 驻车控制
* 发送机械刹车指令
* 4字节消息类型: `2D 00 03 00`
* 8字节数据第一个字节表示是否刹车1为刹车0为释放
* 刹车指令:`FE 2D 00 03 00 01 00 00 00 00 00 00 00 07`
* 释放刹车:`FE 2D 00 03 00 00 00 00 00 00 00 00 00 44`
* 调整零位
* 4字节消息类型: `2D 00 04 00`
* 8字节数据前4个字节表示float偏移量
* 逆时针偏移1度: `FE 2D 00 04 00 00 00 80 BF 00 00 00 00 D6`
* 顺时针偏移1度: `FE 2D 00 04 00 00 00 80 3F 00 00 00 00 1D`
* 紧急停止指令(Emergency)
* 4字节消息类型`2F FF FF 00`
* 8字节数据第1个字节表示急停类型FF表示急停10表示解除急停
* 急停触发:`FE 2F FF FF 00 FF 00 00 00 00 00 00 00 DA`
* 急停解除:`FE 2F FF FF 00 10 00 00 00 00 00 00 00 53`
* 该消息可以直接关停底盘的电机输出。
## 4、反馈消息
反馈消息将持续发送40ms间隔。可以使用反馈消息作为车辆连接的依据。
* 整车速度和转角
* 4字节消息类型`2D 00 20 00`
* 8字节数据内容前4字节为车辆速度v单位m/s。后4字节为前轮转角单位rad。
* 数据类型float
* 里程计xy坐标
* 车辆上电后的位置为里程计原点车头方向为x车左侧为y。
* 4字节消息类型`2D 00 21 00`
* 8字节数据内容前4个字节为x坐标单位m。后4字节为y坐标单位m。
* 数据类型为float
* 范例:`FE 2D 00 21 00 CD CC CC 3D CD CC 4C 3E 1A`
* 说明x:0.1m y:0.2m
* 里程计朝向
* 车辆上电后的朝向为0度逆时针为正。
* 4字节消息类型`2D 00 22 00`
* 8字节数据内容前4个字节为朝向角单位为rad。
* 数据类型为float
* 范例:`FE 2D 00 22 00 9A 99 99 3E 00 00 00 00 D9`
* 说明0.3rad
* 左电机速度
* 4字节消息类型`2D 11 11 00`
* 8字节数据内容前4个字节为速度单位rad/s
* 数据类型float
* 范例:`FE 2D 11 11 00 CD CC CC 3D 00 00 00 00 C5`
* 含义0.1rad/s如果要转换为m/s需要乘以车轮半径
* 右电机速度:
* 4字节消息类型:`2D 10 11 00`
* 8字节数据内容前4个字节为速度单位rad/s
* 数据类型float
* 范例:`FE 2D 10 11 00 CD CC 4C 3E 00 00 00 00 B4`
* 含义0.2rad/s如果要转换为m/s需要乘以车轮半径
* 转向角度:
* 4字节消息类型`2D 20 11 00`
* 8字节数据内容前4个字节为角度单位rad
* 数据类型float
范例:`FE 2D 20 11 00 CD CC CC 3D 00 00 00 00 26`
* 含义0.1rad,正方向为向左转
* 异常状态报告:
* 4字节消息`2D 00 23 00`
* 8字节数据内容[0]:TCU状态[1]:左轮ECU状态 [2]:右轮ECU状态。每个字节0位为急停1位为数据超时2位为电流超限3位为刹车状态
* 范例:`FE 2D 00 23 00 01 02 05 00 00 00 00 00 0E`
* 含义TCU节点急停状态左轮ECU编码器数据超时右轮ECU急停状态且电流超限。
## 5、CRC8校验
* 使用CRC-8/MAXIM方式计算
* 示例在线计算crc8(http://www.ip33.com/crc.html)
![img](./img/crc8-maxim.png)
<span id = "crc8-table"></span>
* 查表法计算crc8
```
const uint8_t CRC8Table[]={
0 94 188 226 97 63 221 131 194 156 126 32 163 253 31 65
157 195 33 127 252 162 64 30 95 1 227 189 62 96 130 220
35 125 159 193 66 28 254 160 225 191 93 3 128 222 60 98
190 224 2 92 223 129 99 61 124 34 192 158 29 67 161 255
70 24 250 164 39 121 155 197 132 218 56 102 229 187 89 7
219 133 103 57 186 228 6 88 25 71 165 251 120 38 196 154
101 59 217 135 4 90 184 230 167 249 27 69 198 152 122 36
248 166 68 26 153 199 37 123 58 100 134 216 91 5 231 185
140 210 48 110 237 179 81 15 78 16 242 172 47 113 147 205
17 79 173 243 112 46 204 146 211 141 111 49 178 236 14 80
175 241 19 77 206 144 114 44 109 51 209 143 12 82 176 238
50 108 142 208 83 13 239 177 240 174 76 18 145 207 45 115
202 148 118 40 171 245 23 73 8 86 180 234 105 55 213 139
87 9 235 181 54 104 138 212 149 203 41 119 244 170 72 22
233 183 85 11 136 214 52 106 43 117 151 201 74 20 246 168
116 42 200 150 21 75 169 247 182 232 10 84 215 137 107 53 };
uint8_t can_crc8_calculate(uint8_t *p uint8_t counter)
{
uint8_t crc8 = 0;
for( ; counter > 0; counter--){
crc8 = CRC8Table[crc8^*p];
p++;
}
return(crc8);
}
```