crazyflie-CRTP协议
概述
本文主要分析CRTP协议的结构,对该协议结构的理解,有助于后续的数据扩展和对软件架构的理解。为了和Crazyflie通信,Crazyflie 飞控中提出一种高层次的协议叫做 CRTP (Crazy RealTime Protocol
)。这种简单的协议使用一些可以收发数据的双向目标端口,但是大都时候通信由主机发起。
物理载体
当前CRTP同时支持 Crazyradio 和 USB(只针对Crazyflie 2.0)模式。
物理载体 | 支持的飞控 |
---|---|
Crazyradio (PA) | Crazyflie 1.0/2.0 |
USB | Crazyflie 2.0 |
协议头
每个数据包拥有1字节的数据头和31字节有效数据载荷,数据头布局如下:
1 | 7 6 5 4 3 2 1 0 |
其中:
- Port: 用来区别与消息相关的功能和任务
- Link: 为以后使用预留
- Channel: 用来识别子任务和子功能
端口分配
当前端口分配如下:
端口 | 目标 | 用途 |
---|---|---|
0 | Console | 读取使用consoleprintf打印到Crazyflie控制台上的控制台信息 |
2 | Parameters | 获取或设置Crazyflie参数.Crazyflie源码中宏定义参数 |
3 | Commander | 发送控制 滚转/俯仰/偏航/油门调节的设置点 |
4 | Memory access | 访问类似于单线或I2C总线的非易失性存储器 (只支持Crazyflie 2.0) |
5 | Data logging | 设置包含需要在特殊周期发回Crazyflie的变量的日记块. |
6 | Localization | 与定位相关的数据包 |
7 | Generic Setpoint | 允许发送设置点和控制模式 |
13 | Platform | 用于其它平台控制,例如调试和关机 |
14 | Client-side debugging | 调试界面并只存在于Crazyflie Python API,Crazyflie飞控本身不具备 |
15 | Link layer | 用于控制和询问通信连接 |
Console端口说明
该端口作为一种文本控制台方式,可以使用consoleprintf 函数从Crazyflie飞控端到主机端打印文本信息。
通信协议
1 | Answer (Crazyflie to host): |
如果任何如下条件满足,飞行器端的缓存区的内容将被发送:
- 输出缓存区满(31字节)
- 一个"新行"字符已经被发送(或
- 已发出刷新命令
代码分析
参考源文件 console.c,函数调用关系如下:
consoleInit函数说明
该函数用于初始化相关变量,并创建二值型信号量synch用于任务间,任务和中断间同步。
流程图
consoleTest函数说明
该函数返回初始化结果,初始化成功即测试通过。
consolePuts函数说明
该函数用于发送字符串。
流程图
该函数主要通过调用consolePutchar函数,实现字符串的发送。
consolePutchar函数说明
该函数用于发送单字节字符。
参考module/interface/console.h文件,通过utils/src/eprintf.c文件中的eprintf函数,将consolePutchar函数映射到通用打印函数,使用宏定义consolePrintf表示。其中VA_ARGS是可变参数宏。
1 |
在utils/interface/debug.h文件中
1 |
使用DEBUG_PRINT宏定义映射consolePrintf函数,通过无线模块或者USB接口发送,并在控制台显示。
流程图
consolePutcharFromISR函数说明
该函数用于在中断中运行,进行字符的发送工作。
流程图
consoleSendMessage函数说明
该函数用于将消息缓存区的的数据messageToPrint,通过CRTP函数发送出去。
addBufferFullMarker
该函数用于当发送队列快满时,在队列缓存区最后加上缓存区满的标志(
findMarkerStart函数说明
该函数用于查找标志的起始位置。
consoleFlush函数说明
该函数用于发送清空缓存区的内容。
Parameters端口说明
参数系统使得飞行器的所有可获得和可设置参数可访问。飞行器拥有一个可修改得参数表,在这个表中,每个参数都和一个ID和一个组名相关联。三个ID用于访问TOC,参数如下:
Port | Channel | Function |
---|---|---|
2 | 0 | TOC 访问 |
2 | 1 | 参数读取 |
2 | 2 | 参数写入 |
2 | 3 | 其它命令 |
TOC访问
这些信息允许访问参数表的内容。信息的第一个字节是信息ID,信息ID定义如下:
命令 | 数值 | 注解 |
---|---|---|
CMD_GET_ITEM | 0 | 原始版本,获取TOC元素 |
CMD_GET_INFO | 1 | 原始版本,获取CRC信息 |
CMD_GET_ITEM_V2 | 2 | V2版本,获取TOC元素 |
CMD_GET_INFO_V2 | 3 | V2版本,获取CRC信息 |
上游数据ID和命令单独发送,下游数据包拥有如下形式:
1 | Bytes 1 1 1 空终止字符串 |
参数被PC端有序请求直到最后。当达到最后参数时,ID为0'最后的TOC元素',复位命令允许复位TOC指针,因此下一个发送TOC元素将会是第一个。“获取 TOC CRC”命令也会返回参数数量。
CRC32是飞行器TOC的哈希值。旨在PC应用程序中实现TOC的缓存以避免每次飞行器连接后获取完整的TOC。
参数类型用一个字节描述如下:
类型码 | c语言类型 | Python解包 |
---|---|---|
0x08 | uint8_t | '<B ' |
0x09 | uint16_t | '<H' |
0x0A | uint32_t | '<L' |
0x0B | uint64_t | '<Q' |
0x00 | int8_t | '<b' |
0x01 | int16_t | '<h' |
0x02 | int32_t | '<i' |
0x03 | int64_t | '<q' |
0x05 | FP16 | '' |
0x06 | float | '<f' |
0x07 | double | '<d' |
参数读取
PC客户端请求内容如下:
字节 | 请求字段 | 内容 |
---|---|---|
0 | ID | 需要读取参数的ID |
Crazyflie飞控端应答内容如下:
字节 | 应答字段 | 内容 |
---|---|---|
0 | ID | 参数ID值 |
1- ... | 数值 | 参数值。TOC中描述了大小和形式 |
参数读取请求是在通道1上的一个简单包,Crazyflie飞控应答相应的参数值。
参数写入
PC客户端请求写入内容如下:
字节 | 请求字段 | 内容 |
---|---|---|
0 | ID | 需要写入的参数ID值 |
1- ... | value | 写入值,大小和形式在TOC中有描述 |
Crazyflie飞控端应答内容如下:
字节 | 应答字段 | 内容 |
---|---|---|
0 | ID | 参数ID |
1- ... | 数值 | 参数值,大小和形式在TOC中有描述 |
写入请求是一个通道2上的简单包。Crazyflie飞控发回参数值作为应答。
其它命令
如下其它命令被使用:
命令内容 | |
---|---|
0x00 | 按名称设置 |
按名称设置
请求内容
字节 | 请求字段 | 内容 |
---|---|---|
0 | 按名称设置 | 0x00 |
1~ n | 组 | 组名 |
n ~ (n+1) | NULL | 0 |
(n+1) ~ (n+m+1) | 名称 | 参数名称 |
(n+m+1)~(n+m+2) | NULL | 0 |
(n+m+2)~(n+m+3) | 类型 | 参数类型 |
(n+m+3) ~ ... | 数值 | 参数数值,大小和形式由类型描述 |
应答内容
字节 | 应答字段 | 内容 |
---|---|---|
0 | 按名称设置 | 0x00 |
1~ n | 组 | 组名 |
n ~ (n+1) | NULL | 0 |
(n+1) ~ (n+m+1) | 名称 | 参数名称 |
(n+m+2) | NULL | 0 |
(n+m+3) | 错误 | 如果参数被成功写入返回0.其它编码 |
组名和参数名称是ASCII字符串的形式,对应的大小分别为n和m。
Commander端口说明
命令端口被用来发送从PC客户端到Crazyflie飞控的控制指令,用来调节滚转、俯仰、偏航和油门等控制信号。随着通信链的建立这些数据包能被发送出去,并且直到下一包数据接收到之前该数值都是有效的。
通信协议
1 | +-------+-------+-------+-------+ |
名称 | 字节 | 大小 | 类型 | 注释 |
---|---|---|---|---|
滚转角 | 0-3 | 4 | float | 滚转设置点 |
俯仰角 | 4-7 | 4 | float | 俯仰设置点 |
偏航角 | 8-11 | 4 | float | 偏航设置点 |
油门 | 12-13 | 2 | uint16_t | 油门设置点 |
Memory access端口说明
存储器访问对Crazyflie Nano Quadcopter无用,当前只在Crazyflie 2.0中应用。使用存储器访问给出如下可能性:
获得哪些存储单元可用的信息;
读取/写入/擦除 存储器;
当前如下存储器被支持:
Crazyflie 2.0的板载EEPROM;
Crazyflie 2.0扩展板上的单线存储器;
有更多的信息关于EEPROM如何构建和单总线存储器如何工作和构建可用。
逻辑流程图
对于客户端获取信息和读写存储器是可选择的,但是Crazyflie Python 客户端总是在连接状态下载关于存储器的信息。
通信协议
存储器端口使用3个不同的通道:
端口 | 通道 | 功能 |
---|---|---|
4 | 0 | 获取关于存储器数量和类型的信息并同时擦除 |
4 | 1 | 读取存储器 |
4 | 2 | 写入存储器 |
通道0:信息/设置
这个通道被用来获取存在的存储器数量、关于存储器的信息和大规模擦除内存的可能性。每个包的第一个字节是命令类型:
命令内容 | 命令 | 操作 |
---|---|---|
1 | GET_NBR_OF_MEMS | 获取存储器的数量 |
2 | GET_MEM_INFO | 获取关于存储器的信息 |
3 | SET_MEM_ERASE | 块擦除存储器 |
GET_NBR_OF_MEMS
这个被用来获取存在的存储器数量。
- 请求从PC主机到Crazyflie飞控:
字节 | 字段 | 数值 | 长度 | 注解 |
---|---|---|---|---|
0 | 获取存储器数量 | 0x01 | 1 | 命令字节 |
- 响应从Crazyflie飞控到PC主机:
字节 | 字段 | 数值 | 长度 | 注解 |
---|---|---|---|---|
0 | 获取存储器数量 | 0x01 | 1 | 命令字节 |
1 | 存储器数量 | 1 | (所有类型)存在存储器数量 |
例如当Crazyflie飞控上存在三个存储器时:
1 | Host-to-Crazyflie: <port/chan> 0x01 |
GET_MEM_INFO
该命令被用来获取存储器的ID信息。存储器的ID是顺序的,并且从0到1,其数值小于从GET_NUMBER_OF_MEMS返回的存储器数量。
- 请求从PC主机到Crazyflie飞控:
字节 | 字段 | 数值 | 长度 | 注解 |
---|---|---|---|---|
0 | 获取存储器信息 | 0x02 | 1 | 命令字节 |
1 | 存储器ID | 1 | 存储器ID(0 <= id < 存储器数量) |
- 如果id有效,应答从Crazyflie飞控到PC主机如下:
字节 | 字段 | 数值 | 长度 | 注解 |
---|---|---|---|---|
0 | GET_MEM_INFO | 0x02 | 1 | 命令字节 |
1 | MEM_ID | 1 | 存储器ID | |
2 | MEM_TYPE | 1 | 存储器类型(详见如下) | |
3 | MEM_SIZE | 4 | 存储器的字节数 | |
7 | MEM_ADDR | 8 | 存储器地址(只对单总线存储器有效) |
关于MEM_ID字段如下:
ID | 数值 | 注解 |
---|---|---|
EEPROM_ID | 0x00 | 关于 |
LEDMEM_ID | 0x01 | LED环存储器ID |
LOCO_ID | 0x02 | 本地位置节点ID |
TRAJ_ID | 0x03 | 轨迹ID |
LOCO2_ID | 0x04 | 本地位置节点2的ID |
LH_ID | 0x05 | 灯塔基站的ID |
TESTER_ID | 0x06 | 存储器测试ID |
USD_ID | 0x07 | 待确认 |
OW_FIRST_ID | 0x08 | 第一个单总线存储器ID |
关于MEM_TYPE字段如下:
类型 | 数值 | 注解 |
---|---|---|
MEM_TYPE_EEPROM | 0x00 | 电可擦除存储器 |
MEM_TYPE_OW | 0x01 | 单总线存储器 |
MEM_TYPE_LED12 | 0x10 | LED环 |
MEM_TYPE_LOCO | 0x11 | 本地位置节点 |
MEM_TYPE_TRAJ | 0x12 | 轨迹 |
MEM_TYPE_LOCO2 | 0x13 | 本地位置节点2 |
MEM_TYPE_LH | 0x14 | 灯塔基站 |
MEM_TYPE_TESTER | 0x15 | 存储器测试 |
MEM_TYPE_USD | 0x16 | 待确认 |
- 如果id无效,应答从Crazyflie飞控到PC主机如下:
字节 | 字段 | 数值 | 长度 | 注解 |
---|---|---|---|---|
0 | GET_MEM_INFO | 0x02 | 1 | 字节命令 |
1 | MEM_ID | 1 | 存储器id |
例如对于单总线存储器的请求内容如下:
MEM_ID=1, MEM_SIZE=112bytes, MEM_ADDR=0x1234567890ABCDEF
1 | Host-to-Crazyflie: <port/chan> 0x02 0x01 |
例如请求的存储器索引信息无效时:
1 | Host-to-Crazyflie: <port/chan> 0x01 0x10 |
SET_MEM_ERASE(代码中无描述)
该命令被用来块擦除给定的id存储器。存储器的id是顺序的,并且从0到1,其数值小于从GET_NUMBER_OF_MEMS返回的存储器数量。
- 请求从PC主机到Crazyflie飞控:
字节 | 字段 | 数值 | 长度 | 注解 |
---|---|---|---|---|
0 | SET_MEM_ERASE | 0x03 | 1 | 命令字节 |
1 | MEM_ID | 1 | 存储器ID(0 <= id < 存储器数量) |
- 应答从Crazyflie飞控到PC主机:
字节 | 字段 | 数值 | 长度 | 注解 |
---|---|---|---|---|
0 | SET_MEM_ERASE | 0x03 | 1 | 命令字节 |
1 | MEM_ID | 1 | 存储器id | |
2 | STATUS | 1 | 命令状态(详见如下) |
例如请求块擦除MEM_ID=2的存储器
1 | Host-to-Crazyflie: <port/chan> 0x03 0x02 |
通道1:存储器读取
这个通道只被用来读取存储器,因此信息不包含任何命令字节。
- 请求从PC主机到Crazyflie飞控:
字节 | 字段 | 数值 | 长度 | 注解 |
---|---|---|---|---|
0 | MEM_ID | 1 | 存储器id(0 <= id < 存储器数量) | |
1 | MEM_ADDR | 4 | 要读取的首字节地址 | |
5 | LEN | 1 | 要被读取的字节数量 |
- 如果存储器的ID有效且地址和长度读取有效,则应答从Crazyflie飞控到PC主机如下:
字节 | 字段 | 数值 | 长度 | 注解 |
---|---|---|---|---|
0 | MEM_ID | 1 | 存储器id(0 <= id < 存储器数量) | |
1 | MEM_ADDR | 4 | 要读取的首字节地址 | |
5 | STATUS | 1 | 请求状态(详见如下) | |
6 | DATA | 1 .. 24? | 要读取的数据(只有MEM_ID/MEM_ADDR/LEN有效时) |
例如从MEM_ID=0x01 MEM_ADDR=0x0A读取LEN=0x0F字节数据:
1 | Host-to-Crazyflie: <port/chan> 0x01 0x0A 0x00 0x00 0x00 0x0F |
通道2:存储器写入
该通道只被用来写入存储器,因此消息中不好含任何命令字节。
- 请求从PC主机到Crazyflie飞控:
字节 | 字段 | 数值 | 长度 | 注解 |
---|---|---|---|---|
0 | MEM_ID | 1 | 存储器id(0 <= id < 存储器数量) | |
1 | MEM_ADDR | 4 | 要写入的首字节地址 | |
5 | DATA | 1 .. 24? | 要写入的数据 |
- 如果存储器的ID有效并且地址和长度被写入有效,应答从Crazyflie飞控到PC主机:
字节 | 字段 | 数值 | 长度 | 注解 |
---|---|---|---|---|
0 | MEM_ID | 1 | 存储器id(0 <= id < 存储器数量) | |
1 | MEM_ADDR | 4 | 要写入的首字节地址 | |
5 | STATUS | 1 | 请求状态 |
DataLog端口说明
log端口分为三个通道:
端口 | 通道 | 功能 |
---|---|---|
5 | 0 | 访问内容表:用于读取出TOC |
5 | 1 | 日志控制操作:用于添加/删除/开始/暂停log块 |
5 | 2 | 日志数据操作:用于从Crazyflie飞控端到PC客户端发送log数据 |
访问内容表(Table of content access)
这个通道用来下载包含所有可记录变量和变量类型的内容表。每组信息的第一个字节对应于命令,所有这个通道的通信都被客户端初始化,并且所有来自飞行器的应答都包含同样的命令字节。
TOC命令字 | 命令 | 操作 |
---|---|---|
0 | CMD_GET_ITEM | 原始版本:从TOC中获取元素 |
1 | CMD_GET_INFO | 原始版本:获取TOC和LOG子系统的信息 |
2 | CMD_GET_ITEM_V2 | V2版本:从TOC中获取元素 |
3 | CMD_GET_INFO_V2 | V2版本:获取TOC和LOG子系统的信息 |
Get TOC item
CMD_GET_ITEM命令允许从飞行器上检索日志变量名、组名和变量类型。该命令旨在从0到LOG_LEN 的所有ID中被请求。
1 | Request (PC to Copter): |
下表说明PC端请求内容如下:
字节 | 请求字段 | 内容 |
---|---|---|
0 | GET_ITEM | 数值0作为GET_ITEM操作 |
1 | ID | 被检索元素的ID,变量数量从0到LOG_LEN |
下表说明Crazyflie飞控端的应答响应内容:
字节 | 应答字段 | 内容 |
---|---|---|
0 | GET_ITEM | 数值0用于GET_ITEM操作 |
1 | ID | 返回元素的ID |
2 | Type | 元素的变量类型,详见变量类型列表 |
3-... | Group | 包含元素组名可变的空终止字符串 |
... | Name | 包含元素变量名可变的空终止字符串 |
如果请求的ID高于(TOC_LEN-1),则元素类型、元素组名和元素变量名不被发送。
Get Info
当连接到飞行器时,首先要请求Get Info命令。该操作能够知道变量数量、日志实施的限制和日志变量的指纹。
原始版本的请求和应答流程如下:
1 | Request (PC to Copter): |
下表详述PC端的请求内容:
字节 | 请求字段 | 内容 |
---|---|---|
0 | GET_INFO | 数值1用于GET_INFO操作 |
下表详述crazyflie飞控应答内容:
字节 | 应答字段 | 内容 |
---|---|---|
0 | GET_INFO | 数值1用于GET_INFO操作 |
1 | LOG_LEN | 包含在日志表中的元素的数量 |
2 | LOG_CRC | 在日志TOC存储区内容数值的CRC值,这是飞行器版本的指纹 |
6 | LOG_MAX_PACKET | 飞行器的最大日志包数量,可以在飞行器中编程 |
7 | LOG_MAX_OPS | 飞行器中的可编程操作的最大数量,该操作是一种日志变量检索程序 |
Log control
日志控制通道允许安装、激活、失效和移除日志包。就像访问TOC通道第一个字节代表的命令,日志控制同样有如下命令:
控制命令字节 | 命令 | 操作 |
---|---|---|
0 | CREATE_BLOCK | 创建一个新的日志块 |
1 | APPEND_BLOCK | 在存在的日志块上追加变量 |
2 | DELETE_BLOCK | 删除一个日志块 |
3 | START_BLOCK | 启用日志块传输 |
4 | STOP_BLOCK | 停止日志块传输 |
5 | RESET | 删除所有的日志块 |
6 | CREATE_BLOCK_V2 | V2版本:创建一个新的日志块 |
7 | APPEND_BLOCK_V2 | V2版本:在存在的日志块上追加变量 |
Create block
1 | Request (PC to Copter): |
返回状态参考<errno.h>文件内容。
Append variable to block
1 | Request (PC to Copter): |
返回状态参考<errno.h>文件内容。
Delelte block
1 | Request (PC to Copter): |
通过请求的LOG_BLOCK_ID,查找相关节点,并删除链表中的该节点。
Start block
通过启动相应的定时器实现日志的发送,并设置相应的周期时间。
1 | Request (PC to Copter): |
Stop block
通过停止相应的定时器来停止日志数据的发送。
1 | Request (PC to Copter): |
Reset
停止所有日志块的发送、删除所有日志块的内容,释放所有日志块的空间。
1 | Request (PC to Copter): |
CREATE BLOCK V2
V2版本的日志块创建。
1 | Request (PC to Copter): |
APPEND BLOCK V2
V2版本的追加日志内容。
1 | Request (PC to Copter): |
Log data
日志数据通道用于飞行器在可编程速率下发送日志块数据。
详细的请求内容如下:
1 | Answer (Copter to PC): |
字节 | 应答字段 | 内容 |
---|---|---|
0 | BLOCK_ID | 日志块的ID |
1 | TIME_STAMP | 时标以ms形式,从飞行器启动起算起,并以3字节的小端整形表示 |
4-... | Log variable values | 日志包的数据值以小端形式表述 |
Localization端口说明
该端口组有一系列定位相关的数据包,主要如下几个通道:
端口 | 通道 | 命名 | |
---|---|---|---|
6 | 0 | External Position | 外部位置 |
6 | 1 | Generic localization | 通用定位 |
6 | 2 | External Position Packet | 外部位置数据包 |
External Position
该数据包被用来发送由外部系统获取的Crazyflie位置信息。主要用该数据包发送由运动捕获系统获取的位置信息,并通过扩展卡尔曼滤波,允许Crazyflie计算位置估计并控制其状态。
数据包形式如下:
1 | struct CrtpExtPosition |
Generic Localization
该通道用于定位子系统有用的主机数据包,该数据包被创建用来服务于自身位置系统数据包,但可以被用作对更多通用系统像GPS NMEA编码或二进制数据流。数据包格式如下:
字节 | 数值 | 注解 |
---|---|---|
0 | PACKET_TYPE | |
1-... | Payload | 数据包的有效载荷,数据形式由包类型确定 |
关于PACKET_TYPE定义:
包类型 | 数值 | 含义 |
---|---|---|
RANGE_STREAM_FLOAT | 0 | 待确认 |
RANGE_STREAM_FP16 | 1 | 待确认 |
LPS_SHORT_LPP_PACKET | 2 | LPS 发送 LPP数据包 |
EMERGENCY_STOP | 3 | 紧急停止 |
EMERGENCY_STOP_WATCHDOG | 4 | 接收超时触发紧急停止 |
COMM_GNSS_NMEA | 6 | 待确认 |
COMM_GNSS_PROPRIETARY | 7 | 待确认 |
EXT_POSE | 8 | 外部位置信息包 |
EXT_POSE_PACKED | 9 | 外部位置信息压缩包 |
LPS:Loco Positioning System
LPP:Loco Positioning Protocol
LPP Short packet tunnel
该数据用于发送LPP短包到本地位置系统,有效数据以LPP Short Packet的形式发送给系统。
Emergency stop
当收到时,稳定循环系统被设置到紧急停止模式,该模式下停止所有电机。直到飞控状态复位,否则稳定循环模式一直保持在紧急停止状态。
EMERGENCY_STOP_WATCHDOG
飞控启动时超时紧急停止处于失效状态,当第一个数据包接收开始,超时1s就会使能超时紧急停止。该数据包至少每秒被Crazyflie发送和接收一次,否则稳定循环系统就会被设置进入紧急停止状态且所有电机停转。
EXT_POSE
外部系统的位置信息,详细结构如下:
字节 | 字段 | 类型 | 含义 |
---|---|---|---|
0 | EXT_POSE | byte | 外部位置 信息包 |
1 - 4 | x | float | x轴坐标信息 |
5 - 8 | y | float | y轴坐标信息 |
9 - 12 | z | float | z轴坐标信息 |
13 - 16 | qx | float | 四元素姿态信息:方位信息的x轴分量 |
17 - 20 | qy | float | 四元素姿态信息:方位信息的y轴分量 |
21 - 24 | qz | float | 四元素姿态信息:方位信息的z轴分量 |
25 - 28 | qw | float | 四元素姿态信息:矢量大小系数 |
EXT_POSE_PACKED
外部位置系统的数据通过该数据包形式进行压缩发送,节省通道带宽,详细包形式如下:
字节 | 字段 | 类型 | 系数 | 含义 |
---|---|---|---|---|
0 | EXT_POSE_PACKED | byte | 外部位置信息压缩包 | |
1 | id | uint8 | Crazyflie飞控地址的最后8bit | |
2 - 3 | x | int16 | 0.001 | x轴坐标信息 |
4 - 5 | y | int16 | 0.001 | y轴坐标信息 |
6 - 7 | z | int16 | 0.001 | z轴坐标信息 |
8 - 11 | quaternion | uint32_t | 压缩格式的四元素(压缩算法详见quatcompress.h) | |
... | 另一同样包形式的元素 |
每个CRTP数据包可以达到两个外部位置信息元素。
Generic Setpoint端口说明
该端口允许发送设定点到飞行器平台。其理念在于能够为每个不同的用例定义设定点数据的包格式。因此这是一个拥有一个通道和一个主要包形式的通用端口。
端口 | 通道 | 命名 |
---|---|---|
7 | 0 | 通用设定点 |
通用设定点包的形式如下:
字节 | 数值 | 注解 |
---|---|---|
0 | ID | 设定点数据包类型的ID值 |
1 - ... | Payload | 数据形式由数据包类型确定 |
详细的包类型如下:
ID | Type |
---|---|
0 | stop |
1 | Velocity World |
2 | Z Distance |
3 | CPPM Emulation |
4 | Altitude Hold |
5 | Hover |
6 | Full State |
7 | Position |
Stop
这个设定点无有效负载,用于停止电机和失效控制循环。需要在Crazyflie飞控着陆的情况下发送。
Velocity World
世界坐标系中的速度设定点伴随着偏航角速度。适用于在本地位置系统的遥控模式。
有效载荷数据的形式如下:
1 | struct velocityPacket_s { |
Z Distance
设置Crazyflie飞控绝对高度和俯仰/滚转角度,数据有效载荷形似如下:
1 | struct zDistancePacket_s { |
CPPM Emulation
CRTP数据包拥有一个CPPM(Crazyflie Pulse Position Modulation
)仿真通道,该通道数据范围1000-2000,其中间值为1500,支持原始的RPYT(Roll Pitch Yaw Thrust
)通道,再加上高达MAX_AUX_RC_CHANNELS 数量的辅组通道。辅组通道是可选的,并且除非给定通道被实际使用,发射器没必要传输所有的数据(numAuxChannels是设定依据)。
有效数据载荷形式:
1 |
|
Altitude Hold
设置Crazyflie飞控的垂直速度和滚转/俯仰角度。
数据有效载荷形式如下:
1 | struct altHoldPacket_s { |
Hover
设置Crazyflie飞控绝对高度和在刚体坐标系下的速度。
数据有效载荷形似如下:
1 | struct hoverPacket_s { |
Full State
设置所有的控制状态。其数据有效载荷形式如下:
1 | struct fullStatePacket_s { |
Position
设置绝对位置和方向,其数据有效载荷形式如下:
1 | struct positionPacket_s { |
连接步骤
CRTP被设计为无状态模式,所以不需要握手过程。任何命令可以在任何时候被发送,但是对于一些日记/参数/存储 命令,为了主机客户端能够发送正确的信息,内容表(TOC)需要被下载。为了能够使用所有的功能,在连接的情况下,执行Python API 将会下载 参数/日记/存储 TOC 。