crazyflie-CRTP解析

概述

本文主要分析CRTP协议的结构,对该协议结构的理解,有助于后续的数据扩展和对软件架构的理解。为了和Crazyflie通信,Crazyflie飞控中提出一种高层次的协议叫做CRTP(Crazy RealTime Protocol)。这种简单的协议使用一些可以收发数据的双向目标端口,但是大都时候通信由主机发起。

物理载体

当前CRTP同时支持 Crazyradio 和 USB(只针对Crazyflie 2.0)模式。

物理载体支持的飞控
Crazyradio (PA)Crazyflie 1.0/2.0
USBCrazyflie 2.0

协议头

每个数据包拥有1字节的数据头和31字节有效数据载荷,数据头布局如下:

       7    6    5    4    3    2    1    0
    +----+----+----+----+----+----+----+----+
    |       Port        |  Link   |  Chan.  |
    +----+----+----+----+----+----+----+----+

其中:

  • Port: 用来区别与消息相关的功能和任务
  • Link: 为以后使用预留
  • Channel: 用来识别子任务和子功能

端口分配

当前端口分配如下:

端口目标用途
0Console读取使用consoleprintf打印到Crazyflie控制台上的控制台信息
2Parameters获取或设置Crazyflie参数.Crazyflie源码中宏定义参数
3Commander发送控制 滚转/俯仰/偏航/油门调节的设置点
4Memory access访问类似于单线或I2C总线的非易失性存储器 (只支持Crazyflie 2.0)
5Data logging设置包含需要在特殊周期发回Crazyflie的变量的日记块.
6Localization与定位相关的数据包
7Generic Setpoint允许发送设置点和控制模式
13Platform用于其它平台控制,例如调试和关机
14Client-side debugging调试界面并只存在于Crazyflie Python API,Crazyflie飞控本身不具备
15Link layer用于控制和询问通信连接

Console端口说明

该端口作为一种文本控制台方式,可以使用consoleprintf 函数从Crazyflie飞控端到主机端打印文本信息。

通信协议
Answer (Crazyflie to host):
        +---------//-----------+
        | PRINTED CONSOLE TEXT |
        +---------//-----------+
Length          0-31

如果任何如下条件满足,飞行器端的缓存区的内容将被发送:

  • 输出缓存区满(31字节)
  • 一个"新行"字符已经被发送(\n 或 \r)
  • 已发出刷新命令
代码分析

参考源文件 console.c,函数调用关系如下:

consoleInit函数说明

该函数用于初始化相关变量,并创建二值型信号量synch用于任务间,任务和中断间同步。

流程图

consoleTest函数说明

该函数返回初始化结果,初始化成功即测试通过。

consolePuts函数说明

该函数用于发送字符串。

流程图


该函数主要通过调用consolePutchar函数,实现字符串的发送。

consolePutchar函数说明

该函数用于发送单字节字符。

参考module/interface/console.h文件,通过utils/src/eprintf.c文件中的eprintf函数,将consolePutchar函数映射到通用打印函数,使用宏定义consolePrintf表示。其中VA_ARGS是可变参数宏。

#define consolePrintf(FMT, ...) eprintf(consolePutchar, FMT, ## __VA_ARGS__)

在utils/interface/debug.h文件中

#define DEBUG_PRINT(fmt, ...) consolePrintf(DEBUG_FMT(fmt), ##__VA_ARGS__)

使用DEBUG_PRINT宏定义映射consolePrintf函数,通过无线模块或者USB接口发送,并在控制台显示。

流程图

consolePutcharFromISR函数说明

该函数用于在中断中运行,进行字符的发送工作。

流程图

consoleSendMessage函数说明

该函数用于将消息缓存区的的数据messageToPrint,通过CRTP函数发送出去。

addBufferFullMarker

该函数用于当发送队列快满时,在队列缓存区最后加上缓存区满的标志()。

findMarkerStart函数说明

该函数用于查找标志的起始位置。

consoleFlush函数说明

该函数用于发送清空缓存区的内容。

Parameters端口说明

参数系统使得飞行器的所有可获得和可设置参数可访问。飞行器拥有一个可修改得参数表,在这个表中,每个参数都和一个ID和一个组名相关联。三个ID用于访问TOC,参数如下:

PortChannelFunction
20TOC 访问
21参数读取
22参数写入
23其它命令
TOC访问

这些信息允许访问参数表的内容。信息的第一个字节是信息ID,信息ID定义如下:

命令数值注解
CMD_GET_ITEM0原始版本,获取TOC元素
CMD_GET_INFO1原始版本,获取CRC信息
CMD_GET_ITEM_V22V2版本,获取TOC元素
CMD_GET_INFO_V23V2版本,获取CRC信息

上游数据ID和命令单独发送,下游数据包拥有如下形式:

Bytes     1       1          1        空终止字符串
        +---+------------+------+----------+--------------+
        | 0 |  Param ID  | Type |  Group   |     Name     |
        +---+------------+------+---+------+--------------+
        | 1 | Num. Param |  CRC32   |
        +---+------------+----------+
Bytes     1       1           4

参数被PC端有序请求直到最后。当达到最后参数时,ID为0’最后的TOC元素’,复位命令允许复位TOC指针,因此下一个发送TOC元素将会是第一个。“获取 TOC CRC”命令也会返回参数数量。

CRC32是飞行器TOC的哈希值。旨在PC应用程序中实现TOC的缓存以避免每次飞行器连接后获取完整的TOC。

参数类型用一个字节描述如下:

类型码c语言类型Python解包
0x08uint8_t'<B ’
0x09uint16_t‘<H’
0x0Auint32_t‘<L’
0x0Buint64_t‘<Q’
0x00int8_t‘<b’
0x01int16_t‘<h’
0x02int32_t‘<i’
0x03int64_t‘<q’
0x05FP16‘’
0x06float‘<f’
0x07double‘<d’
参数读取

PC客户端请求内容如下:

字节请求字段内容
0ID需要读取参数的ID

Crazyflie飞控端应答内容如下:

字节应答字段内容
0ID参数ID值
1- …数值参数值。TOC中描述了大小和形式

参数读取请求是在通道1上的一个简单包,Crazyflie飞控应答相应的参数值。

参数写入

PC客户端请求写入内容如下:

字节请求字段内容
0ID需要写入的参数ID值
1- …value写入值,大小和形式在TOC中有描述

Crazyflie飞控端应答内容如下:

字节应答字段内容
0ID参数ID
1- …数值参数值,大小和形式在TOC中有描述

写入请求是一个通道2上的简单包。Crazyflie飞控发回参数值作为应答。

其它命令

如下其它命令被使用:

命令内容
0x00按名称设置
按名称设置

请求内容

字节请求字段内容
0按名称设置0x00
1~ n组名
n ~ (n+1)NULL0
(n+1) ~ (n+m+1)名称参数名称
(n+m+1)~(n+m+2)NULL0
(n+m+2)~(n+m+3)类型参数类型
(n+m+3) ~ …数值参数数值,大小和形式由类型描述

应答内容

字节应答字段内容
0按名称设置0x00
1~ n组名
n ~ (n+1)NULL0
(n+1) ~ (n+m+1)名称参数名称
(n+m+2)NULL0
(n+m+3)错误如果参数被成功写入返回0.其它编码

组名和参数名称是ASCII字符串的形式,对应的大小分别为n和m。

Commander端口说明

命令端口被用来发送从PC客户端到Crazyflie飞控的控制指令,用来调节滚转、俯仰、偏航和油门等控制信号。随着通信链的建立这些数据包能被发送出去,并且直到下一包数据接收到之前该数值都是有效的。

通信协议
        +-------+-------+-------+-------+
        | ROLL  | PITCH |  YAW  |THRUST |
        +-------+-------+-------+-------+
Length      4       4       4       2      bytes
名称字节大小类型注释
滚转角0-34float滚转设置点
俯仰角4-74float俯仰设置点
偏航角8-114float偏航设置点
油门12-132uint16_t油门设置点

Memory access端口说明

存储器访问对Crazyflie Nano Quadcopter无用,当前只在Crazyflie 2.0中应用。使用存储器访问给出如下可能性:

  • 获得哪些存储单元可用的信息;

  • 读取/写入/擦除 存储器;

当前如下存储器被支持:

  • Crazyflie 2.0的板载EEPROM;

  • Crazyflie 2.0扩展板上的单线存储器;

    有更多的信息关于EEPROM如何构建和单总线存储器如何工作和构建可用。

逻辑流程图

对于客户端获取信息和读写存储器是可选择的,但是Crazyflie Python 客户端总是在连接状态下载关于存储器的信息。

通信协议

存储器端口使用3个不同的通道:

端口通道功能
40获取关于存储器数量和类型的信息并同时擦除
41读取存储器
42写入存储器
通道0:信息/设置

这个通道被用来获取存在的存储器数量、关于存储器的信息和大规模擦除内存的可能性。每个包的第一个字节是命令类型:

命令内容命令操作
1GET_NBR_OF_MEMS获取存储器的数量
2GET_MEM_INFO获取关于存储器的信息
3SET_MEM_ERASE块擦除存储器
GET_NBR_OF_MEMS

这个被用来获取存在的存储器数量。

  • 请求从PC主机到Crazyflie飞控:
字节字段数值长度注解
0获取存储器数量0x011命令字节
  • 响应从Crazyflie飞控到PC主机:
字节字段数值长度注解
0获取存储器数量0x011命令字节
1存储器数量1(所有类型)存在存储器数量

例如当Crazyflie飞控上存在三个存储器时:

Host-to-Crazyflie: <port/chan> 0x01
Crazyflie-to-Host: <port/chan> 0x01 0x03
GET_MEM_INFO

该命令被用来获取存储器的ID信息。存储器的ID是顺序的,并且从0到1,其数值小于从GET_NUMBER_OF_MEMS返回的存储器数量。

  • 请求从PC主机到Crazyflie飞控:
字节字段数值长度注解
0获取存储器信息0x021命令字节
1存储器ID1存储器ID(0 <= id < 存储器数量)
  • 如果id有效,应答从Crazyflie飞控到PC主机如下:
字节字段数值长度注解
0GET_MEM_INFO0x021命令字节
1MEM_ID1存储器ID
2MEM_TYPE1存储器类型(详见如下)
3MEM_SIZE4存储器的字节数
7MEM_ADDR8存储器地址(只对单总线存储器有效)

关于MEM_ID字段如下:

ID数值注解
EEPROM_ID0x00关于
LEDMEM_ID0x01LED环存储器ID
LOCO_ID0x02本地位置节点ID
TRAJ_ID0x03轨迹ID
LOCO2_ID0x04本地位置节点2的ID
LH_ID0x05灯塔基站的ID
TESTER_ID0x06存储器测试ID
USD_ID0x07待确认
OW_FIRST_ID0x08第一个单总线存储器ID

关于MEM_TYPE字段如下:

类型数值注解
MEM_TYPE_EEPROM0x00电可擦除存储器
MEM_TYPE_OW0x01单总线存储器
MEM_TYPE_LED120x10LED环
MEM_TYPE_LOCO0x11本地位置节点
MEM_TYPE_TRAJ0x12轨迹
MEM_TYPE_LOCO20x13本地位置节点2
MEM_TYPE_LH0x14灯塔基站
MEM_TYPE_TESTER0x15存储器测试
MEM_TYPE_USD0x16待确认
  • 如果id无效,应答从Crazyflie飞控到PC主机如下:
字节字段数值长度注解
0GET_MEM_INFO0x021字节命令
1MEM_ID1存储器id

例如对于单总线存储器的请求内容如下:

MEM_ID=1, MEM_SIZE=112bytes, MEM_ADDR=0x1234567890ABCDEF

Host-to-Crazyflie: <port/chan> 0x02 0x01
Crazyflie-to-Host: <port/chan> 0x02 0x01 0x01 0x70 0x00 0x00 0x00 0xEF 0xCD 0xAB 0x90 0x78 0x56 0x34 0x12

例如请求的存储器索引信息无效时:

Host-to-Crazyflie: <port/chan> 0x01 0x10
Crazyflie-to-Host: <port/chan> 0x01 0x10
SET_MEM_ERASE(代码中无描述)

该命令被用来块擦除给定的id存储器。存储器的id是顺序的,并且从0到1,其数值小于从GET_NUMBER_OF_MEMS返回的存储器数量。

  • 请求从PC主机到Crazyflie飞控:
字节字段数值长度注解
0SET_MEM_ERASE0x031命令字节
1MEM_ID1存储器ID(0 <= id < 存储器数量)
  • 应答从Crazyflie飞控到PC主机:
字节字段数值长度注解
0SET_MEM_ERASE0x031命令字节
1MEM_ID1存储器id
2STATUS1命令状态(详见如下)

例如请求块擦除MEM_ID=2的存储器

Host-to-Crazyflie: <port/chan> 0x03 0x02
Crazyflie-to-Host: <port/chan> 0x03 0x02 0x00
通道1:存储器读取

这个通道只被用来读取存储器,因此信息不包含任何命令字节。

  • 请求从PC主机到Crazyflie飞控:
字节字段数值长度注解
0MEM_ID1存储器id(0 <= id < 存储器数量)
1MEM_ADDR4要读取的首字节地址
5LEN1要被读取的字节数量
  • 如果存储器的ID有效且地址和长度读取有效,则应答从Crazyflie飞控到PC主机如下:
字节字段数值长度注解
0MEM_ID1存储器id(0 <= id < 存储器数量)
1MEM_ADDR4要读取的首字节地址
5STATUS1请求状态(详见如下)
6DATA1 … 24?要读取的数据(只有MEM_ID/MEM_ADDR/LEN有效时)

例如从MEM_ID=0x01 MEM_ADDR=0x0A读取LEN=0x0F字节数据:

Host-to-Crazyflie: <port/chan> 0x01 0x0A 0x00 0x00 0x00 0x0F
Crazyflie-to-Host: <port/chan> 0x01 0x0A 0x00 0x00 0x00 0x00 0x01 0x09 0x62 0x63 0x4C 0x65 0x64 0x52 0x69 0x6E 0x67 0x02 0x01 0x62 0x55 
通道2:存储器写入

该通道只被用来写入存储器,因此消息中不好含任何命令字节。

  • 请求从PC主机到Crazyflie飞控:
字节字段数值长度注解
0MEM_ID1存储器id(0 <= id < 存储器数量)
1MEM_ADDR4要写入的首字节地址
5DATA1 … 24?要写入的数据
  • 如果存储器的ID有效并且地址和长度被写入有效,应答从Crazyflie飞控到PC主机:
字节字段数值长度注解
0MEM_ID1存储器id(0 <= id < 存储器数量)
1MEM_ADDR4要写入的首字节地址
5STATUS1请求状态

DataLog端口说明

log端口分为三个通道:

端口通道功能
50访问内容表:用于读取出TOC
51日志控制操作:用于添加/删除/开始/暂停log块
52日志数据操作:用于从Crazyflie飞控端到PC客户端发送log数据
访问内容表(Table of content access)

这个通道用来下载包含所有可记录变量和变量类型的内容表。每组信息的第一个字节对应于命令,所有这个通道的通信都被客户端初始化,并且所有来自飞行器的应答都包含同样的命令字节。

TOC命令字命令操作
0CMD_GET_ITEM原始版本:从TOC中获取元素
1CMD_GET_INFO原始版本:获取TOC和LOG子系统的信息
2CMD_GET_ITEM_V2V2版本:从TOC中获取元素
3CMD_GET_INFO_V2V2版本:获取TOC和LOG子系统的信息
Get TOC item

CMD_GET_ITEM命令允许从飞行器上检索日志变量名、组名和变量类型。该命令旨在从0到LOG_LEN 的所有ID中被请求。

Request (PC to Copter):
        +--------------+----+
        | GET_ITEM (0) | ID |
        +--------------+----+
Length         1         1

Answer (Copter to PC):
        +--------------+----+
        | GET_ITEM (0) | ID |                                        If index out of range
        +--------------+----+------+------------+--------------+
        | GET_ITEM (0) | ID | Type |   Group    |     Name     |     If returning Item
        +--------------+----+------+------------+--------------+
Length        1          1     1    < Null terminated strings >

下表说明PC端请求内容如下:

字节请求字段内容
0GET_ITEM数值0作为GET_ITEM操作
1ID被检索元素的ID,变量数量从0到LOG_LEN

下表说明Crazyflie飞控端的应答响应内容:

字节应答字段内容
0GET_ITEM数值0用于GET_ITEM操作
1ID返回元素的ID
2Type元素的变量类型,详见变量类型列表
3-…Group包含元素组名可变的空终止字符串
Name包含元素变量名可变的空终止字符串

如果请求的ID高于(TOC_LEN-1),则元素类型、元素组名和元素变量名不被发送。

Get Info

当连接到飞行器时,首先要请求Get Info命令。该操作能够知道变量数量、日志实施的限制和日志变量的指纹。

原始版本的请求和应答流程如下:

Request (PC to Copter):
        +--------------+
        | GET_INFO (1) |
        +--------------+
Length         1

Answer (Copter to PC):
        +--------------+---------+---------+-----------------+-------------+
        | GET_INFO (1) | LOG_LEN | LOG_CRC |  LOG_MAX_PACKET | LOG_MAX_OPS |
        +--------------+---------+---------+-----------------+-------------+
Length        1             1         4             1               1

下表详述PC端的请求内容:

字节请求字段内容
0GET_INFO数值1用于GET_INFO操作

下表详述crazyflie飞控应答内容:

字节应答字段内容
0GET_INFO数值1用于GET_INFO操作
1LOG_LEN包含在日志表中的元素的数量
2LOG_CRC在日志TOC存储区内容数值的CRC值,这是飞行器版本的指纹
6LOG_MAX_PACKET飞行器的最大日志包数量,可以在飞行器中编程
7LOG_MAX_OPS飞行器中的可编程操作的最大数量,该操作是一种日志变量检索程序
Log control

日志控制通道允许安装、激活、失效和移除日志包。就像访问TOC通道第一个字节代表的命令,日志控制同样有如下命令:

控制命令字节命令操作
0CREATE_BLOCK创建一个新的日志块
1APPEND_BLOCK在存在的日志块上追加变量
2DELETE_BLOCK删除一个日志块
3START_BLOCK启用日志块传输
4STOP_BLOCK停止日志块传输
5RESET删除所有的日志块
6CREATE_BLOCK_V2V2版本:创建一个新的日志块
7APPEND_BLOCK_V2V2版本:在存在的日志块上追加变量
Create block
Request (PC to Copter):
										  < 更多设置参数按如下结构扩展      >
        +------------------+--------------+--------------+-------------+
        | CREATE_BLOCK (0) | LOG_BLOCK_ID | SET_LOG_TYPE |  SET_LOG_ID |
        +------------------+--------------+--------------+-------------+
Length         1				   1			  1				1

Answer (Copter to PC):
        +------------------+--------------+------------+
        | CREATE_BLOCK (0) | LOG_BLOCK_ID | CREATE_STS |
        +------------------+--------------+------------+
Length            1               1               1

返回状态参考**<errno.h>**文件内容。

Append variable to block
Request (PC to Copter):
										  < 更多设置参数按如下结构扩展      >
        +------------------+--------------+--------------+-------------+
        | APPEND_BLOCK (1) | LOG_BLOCK_ID | SET_LOG_TYPE |  SET_LOG_ID |
        +------------------+--------------+--------------+-------------+
Length         1				   1			  1				1

Answer (Copter to PC):
        +------------------+--------------+------------+
        | APPEND_BLOCK (1) | LOG_BLOCK_ID | CREATE_STS |
        +------------------+--------------+------------+
Length            1               1               1

返回状态参考errno.h文件内容。

Delelte block
Request (PC to Copter):
        +------------------+--------------+
        | DELETE_BLOCK (2) | LOG_BLOCK_ID |
        +------------------+--------------+
Length         1				   1		

Answer (Copter to PC):
        +------------------+--------------+------------+
        | DELETE_BLOCK (2) | LOG_BLOCK_ID | CREATE_STS |
        +------------------+--------------+------------+
Length            1               1               1

通过请求的LOG_BLOCK_ID,查找相关节点,并删除链表中的该节点。

Start block

通过启动相应的定时器实现日志的发送,并设置相应的周期时间。

Request (PC to Copter):
        +-----------------+--------------+------------+
        | START_BLOCK (3) | LOG_BLOCK_ID | LOG_PERIOD |
        +-----------------+--------------+------------+
Length         1				   1		     1

Answer (Copter to PC):
        +-----------------+--------------+------------+
        | START_BLOCK (3) | LOG_BLOCK_ID | CREATE_STS |
        +-----------------+--------------+------------+
Length            1               1               1
Stop block

通过停止相应的定时器来停止日志数据的发送。

Request (PC to Copter):
        +----------------+--------------+
        | STOP_BLOCK (4) | LOG_BLOCK_ID |
        +----------------+--------------+
Length         1				   1		

Answer (Copter to PC):
        +----------------+--------------+------------+
        | STOP_BLOCK (4) | LOG_BLOCK_ID | CREATE_STS |
        +----------------+--------------+------------+
Length          1               1               1
Reset

停止所有日志块的发送、删除所有日志块的内容,释放所有日志块的空间。

Request (PC to Copter):
        +-----------+
        | RESET (5) |
        +-----------+
Length       1					

Answer (Copter to PC):
        +-----------+--------------+------------+
        | RESET (5) | LOG_BLOCK_ID | CREATE_STS |
        +-----------+--------------+------------+
Length        1             1             1
CREATE BLOCK V2

V2版本的日志块创建。

Request (PC to Copter):
										  < 更多设置参数按如下结构扩展      >
        +---------------------+--------------+--------------+-------------+
        | CREATE_BLOCK_V2 (6) | LOG_BLOCK_ID | SET_LOG_TYPE |  SET_LOG_ID |
        +---------------------+--------------+--------------+-------------+
Length         1				   1			  1				2

Answer (Copter to PC):
        +---------------------+--------------+------------+
        | CREATE_BLOCK_V2 (6) | LOG_BLOCK_ID | CREATE_STS |
        +---------------------+--------------+------------+
Length            1               1               1
APPEND BLOCK V2

V2版本的追加日志内容。

Request (PC to Copter):
										  < 更多设置参数按如下结构扩展      >
        +---------------------+--------------+--------------+-------------+
        | APPEND_BLOCK_V2 (7) | LOG_BLOCK_ID | SET_LOG_TYPE |  SET_LOG_ID |
        +---------------------+--------------+--------------+-------------+
Length         1				   1			  1				2

Answer (Copter to PC):
        +---------------------+--------------+------------+
        | APPEND_BLOCK_V2 (7) | LOG_BLOCK_ID | CREATE_STS |
        +---------------------+--------------+------------+
Length            1               1               1
Log data

日志数据通道用于飞行器在可编程速率下发送日志块数据。

详细的请求内容如下:

Answer (Copter to PC):
        +----------+------------+---------//----------+
        | BLOCK_ID | TIME_STAMP | LOG VARIABLE VALUES |
        +----------+------------+---------//----------+
Length        1          3           0 to 28
字节应答字段内容
0BLOCK_ID日志块的ID
1TIME_STAMP时标以ms形式,从飞行器启动起算起,并以3字节的小端整形表示
4-…Log variable values日志包的数据值以小端形式表述

Localization端口说明

该端口组有一系列定位相关的数据包,主要如下几个通道:

端口通道命名
60External Position外部位置
61Generic localization通用定位
62External Position Packet外部位置数据包
External Position

该数据包被用来发送由外部系统获取的Crazyflie位置信息。主要用该数据包发送由运动捕获系统获取的位置信息,并通过扩展卡尔曼滤波,允许Crazyflie计算位置估计并控制其状态。

数据包形式如下:

struct CrtpExtPosition
{
  float x; // in m
  float y; // in m
  float z; // in m
} __attribute__((packed));
Generic Localization

该通道用于定位子系统有用的主机数据包,该数据包被创建用来服务于自身位置系统数据包,但可以被用作对更多通用系统像GPS NMEA编码或二进制数据流。数据包格式如下:

字节数值注解
0PACKET_TYPE
1-…Payload数据包的有效载荷,数据形式由包类型确定

关于PACKET_TYPE定义:

包类型数值含义
RANGE_STREAM_FLOAT0待确认
RANGE_STREAM_FP161待确认
LPS_SHORT_LPP_PACKET2LPS 发送 LPP数据包
EMERGENCY_STOP3紧急停止
EMERGENCY_STOP_WATCHDOG4接收超时触发紧急停止
COMM_GNSS_NMEA6待确认
COMM_GNSS_PROPRIETARY7待确认
EXT_POSE8外部位置信息包
EXT_POSE_PACKED9外部位置信息压缩包

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

外部系统的位置信息,详细结构如下:

字节字段类型含义
0EXT_POSEbyte外部位置 信息包
1 - 4xfloatx轴坐标信息
5 - 8yfloaty轴坐标信息
9 - 12zfloatz轴坐标信息
13 - 16qxfloat四元素姿态信息:方位信息的x轴分量
17 - 20qyfloat四元素姿态信息:方位信息的y轴分量
21 - 24qzfloat四元素姿态信息:方位信息的z轴分量
25 - 28qwfloat四元素姿态信息:矢量大小系数
EXT_POSE_PACKED

外部位置系统的数据通过该数据包形式进行压缩发送,节省通道带宽,详细包形式如下:

字节字段类型系数含义
0EXT_POSE_PACKEDbyte外部位置信息压缩包
1iduint8Crazyflie飞控地址的最后8bit
2 - 3xint160.001x轴坐标信息
4 - 5yint160.001y轴坐标信息
6 - 7zint160.001z轴坐标信息
8 - 11quaternionuint32_t压缩格式的四元素(压缩算法详见quatcompress.h)
另一同样包形式的元素

每个CRTP数据包可以达到两个外部位置信息元素。

Generic Setpoint端口说明

该端口允许发送设定点到飞行器平台。其理念在于能够为每个不同的用例定义设定点数据的包格式。因此这是一个拥有一个通道和一个主要包形式的通用端口。

端口通道命名
70通用设定点

通用设定点包的形式如下:

字节数值注解
0ID设定点数据包类型的ID值
1 - …Payload数据形式由数据包类型确定

详细的包类型如下:

IDType
0Stop
1Velocity World
2Z Distance
3CPPM Emulation
4Altitude Hold
5Hover
6Full State
7Position
Stop

这个设定点无有效负载,用于停止电机和失效控制循环。需要在Crazyflie飞控着陆的情况下发送。

Velocity World

世界坐标系中的速度设定点伴随着偏航角速度。适用于在本地位置系统的遥控模式。

有效载荷数据的形式如下:

struct velocityPacket_s {
  float vx;        // m in the world frame of reference
  float vy;        // ...
  float vz;        // ...
  float yawrate;  // deg/s
} __attribute__((packed));
Z Distance

设置Crazyflie飞控绝对高度和俯仰/滚转角度,数据有效载荷形似如下:

struct zDistancePacket_s {
  float roll;            // deg
  float pitch;           // ...
  float yawrate;         // deg/s
  float zDistance;        // m in the world frame of reference
} __attribute__((packed));
CPPM Emulation

CRTP数据包拥有一个CPPM(Crazyflie Pulse Position Modulation)仿真通道,该通道数据范围1000-2000,其中间值为1500,支持原始的RPYT(Roll Pitch Yaw Thrust)通道,再加上高达MAX_AUX_RC_CHANNELS 数量的辅组通道。辅组通道是可选的,并且除非给定通道被实际使用,发射器没必要传输所有的数据(numAuxChannels是设定依据)。

有效数据载荷形式:

#define MAX_AUX_RC_CHANNELS 10

static float s_CppmEmuRollMaxRateDps = 720.0f; // For rate mode
static float s_CppmEmuPitchMaxRateDps = 720.0f; // For rate mode
static float s_CppmEmuRollMaxAngleDeg = 50.0f; // For level mode
static float s_CppmEmuPitchMaxAngleDeg = 50.0f; // For level mode
static float s_CppmEmuYawMaxRateDps = 400.0f; // Used regardless of flight mode

struct cppmEmuPacket_s {
  struct {
      uint8_t numAuxChannels : 4;   // Set to 0 through MAX_AUX_RC_CHANNELS
      uint8_t reserved : 4;
  } hdr;
  uint16_t channelRoll;
  uint16_t channelPitch;
  uint16_t channelYaw;
  uint16_t channelThrust;
  uint16_t channelAux[MAX_AUX_RC_CHANNELS];
} __attribute__((packed));
Altitude Hold

设置Crazyflie飞控的垂直速度和滚转/俯仰角度。

数据有效载荷形式如下:

struct altHoldPacket_s {
  float roll;            // rad
  float pitch;           // ...
  float yawrate;         // deg/s
  float zVelocity;       // m/s in the world frame of reference
} __attribute__((packed));
Hover

设置Crazyflie飞控绝对高度和在刚体坐标系下的速度。

数据有效载荷形似如下:

struct hoverPacket_s {
  float vx;           // m/s in the body frame of reference
  float vy;           // ...
  float yawrate;      // deg/s
  float zDistance;    // m in the world frame of reference
} __attribute__((packed));
Full State

设置所有的控制状态。其数据有效载荷形式如下:

struct fullStatePacket_s {
  int16_t x;         // position - mm
  int16_t y;
  int16_t z;
  int16_t vx;        // velocity - mm / sec
  int16_t vy;
  int16_t vz;
  int16_t ax;        // acceleration - mm / sec^2
  int16_t ay;
  int16_t az;
  int32_t quat;      // compressed quaternion, see quatcompress.h
  int16_t rateRoll;  // angular velocity - milliradians / sec
  int16_t ratePitch; //  (NOTE: limits to about 5 full circles per sec.
  int16_t rateYaw;   //   may not be enough for extremely aggressive flight.)
} __attribute__((packed));
Position

设置绝对位置和方向,其数据有效载荷形式如下:

 struct positionPacket_s {
   float x;     // Position in m
   float y;
   float z;
   float yaw;   // Orientation in degree
 } __attribute__((packed));

连接步骤

CRTP被设计为无状态模式,所以不需要握手过程。任何命令可以在任何时候被发送,但是对于一些日记/参数/存储 命令,为了主机客户端能够发送正确的信息,内容表(TOC)需要被下载。为了能够使用所有的功能,在连接的情况下,执行Python API 将会下载 参数/日记/存储 TOC 。

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

henry.zhu51

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值