原文
:http://uavcan.org/Specification/3._Data_structure_description_language/
DSDL
:Data structure description language
实际上,就是自动生成的C++格式的数据结构。用来定义UAVCAN中的各种类型的消息。个人认为就是看着更清晰,理解起来更容易,也是UAVCAN的设计思想。使用C代码也很容易实现
C代码例子
:https://github.com/zwx230741/libcanard
结构定义
[default data type ID.]<data type name>.uavcan
+ uavcan <-- Root namespace
+ equipment <-- Nested namespace
+ ...
+ protocol <-- Nested namespace
+ 341.NodeStatus.uavcan <-- Definition of data type "uavcan.protocol.NodeStatus" with
default data type ID 341
+ ...
+ Timestamp.uavcan <-- Definition of data type "uavcan.Timestamp", default data
type ID is not assigned
DSDL中定义的都是标准的数据类型,也是默认的数据类型,不需要更改
可用的数据类型ID是有限的
DSDL发布消息
具体源码可以参考UAVCAN源码
DSDL通过Publisher来发布消息,当你需要发送数据到can设备时使用
uavcan::equipment::esc::RawCommand msg;
uavcan::Publisher<uavcan::equipment::esc::RawCommand> _uavcan_pub_raw_cmd;
(void)_uavcan_pub_raw_cmd.broadcast(msg); //广播消息
DSDL订阅消息
DSDL通过Subscriber来订阅消息,当你需要接收can设备数据到时使用
typedef uavcan::MethodBinder<UavcanEscController*,
void (UavcanEscController::*)(const uavcan::ReceivedDataStructure<uavcan::equipment::esc::Status>&)>
StatusCbBinder;
uavcan::Subscriber<uavcan::equipment::esc::Status, StatusCbBinder> _uavcan_sub_status;
int res = _uavcan_sub_status.start(StatusCbBinder(this, &UavcanEscController::esc_status_sub_cb));
if (res < 0)
{
warnx("ESC status sub failed %i", res);
return res;
}
void UavcanEscController::esc_status_sub_cb(const uavcan::ReceivedDataStructure<uavcan::equipment::esc::Status> &msg)
{
;
}
数据结构举例
#
# Abstract node status information.
#
# Any UAVCAN node is required to publish this message periodically.
#
#
# Publication period may vary within these limits.
# It is NOT recommended to change it at run time.
#
uint16 MAX_BROADCASTING_PERIOD_MS = 1000
uint16 MIN_BROADCASTING_PERIOD_MS = 2
#
# If a node fails to publish this message in this amount of time, it should be considered offline.
#
uint16 OFFLINE_TIMEOUT_MS = 3000
#
# Uptime counter should never overflow.
# Other nodes may detect that a remote node has restarted when this value goes backwards.
#
uint32 uptime_sec
#
# Abstract node health.
#
uint2 HEALTH_OK = 0 # The node is functioning properly.
uint2 HEALTH_WARNING = 1 # A critical parameter went out of range or the node
encountered a minor failure.
uint2 HEALTH_ERROR = 2 # The node encountered a major failure.
uint2 HEALTH_CRITICAL = 3 # The node suffered a fatal malfunction.
uint2 health
#
# Current mode.
#
# Mode OFFLINE can be actually reported by the node to explicitly inform other network
# participants that the sending node is about to shutdown. In this case other nodes will not
# have to wait OFFLINE_TIMEOUT_MS before they detect that the node is no longer available.
#
# Reserved values can be used in future revisions of the specification.
#
uint3 MODE_OPERATIONAL = 0 # Node is performing its main functions.
uint3 MODE_INITIALIZATION = 1 # Node is initializing; this mode is entered
immediately after startup.
uint3 MODE_MAINTENANCE = 2 # Node is under maintenance.
uint3 MODE_SOFTWARE_UPDATE = 3 # Node is in the process of updating its software.
uint3 MODE_OFFLINE = 7 # Node is no longer available.
uint3 mode
#
# Not used currently, keep zero when publishing, ignore when receiving.
#
uint3 sub_mode
#
# Optional, vendor-specific node status code, e.g. a fault code or a status bitmask.
#
uint16 vendor_specific_status_code
结构体中的属性值:
默认值:不可以修改,也不参与网络交互
变量:可以通过应用程序修改,参与网络收发
uint8[<=64] payload
UAVCAN支持不定长数组,使用起来很方便。但是要注意,DSDL订阅消息的时候,默认第一个字节表示数组的长度
服务响应标记:
该标记由三个减号组成
---
C方式发送消息
等价于DSDL发布消息
/*
封包数据,根据数据类型
void canardEncodeScalar(void *destination,
uint32_t bit_offset,
uint8_t bit_length, //bit长度
const void *value)
*/
canardEncodeScalar(buffer, 0, 28, &uptime_sec);
/*
发送消息,加入到发送队列
int canardBroadcast(CanardInstance *ins,
uint64_t data_type_signature,
uint16_t data_type_id,
uint8_t *inout_transfer_id,
uint8_t priority,
const void *payload,
uint16_t payload_len)
*/
canardBroadcast(&canard, UAVCAN_NODE_STATUS_DATA_TYPE_SIGNATURE,
UAVCAN_NODE_STATUS_DATA_TYPE_ID, &transfer_id, CANARD_TRANSFER_PRIORITY_LOW,
buffer, UAVCAN_NODE_STATUS_MESSAGE_SIZE);
C方式接收消息
等价于DSDL订阅消息
/*
从接收到的数据包中,解析出数据
int canardDecodeScalar(const CanardRxTransfer *transfer,
uint32_t bit_offset,
uint8_t bit_length,
bool value_is_signed,
void *out_value)
*/
canardDecodeScalar(transfer, 0, 28, false, &uptime_sec[i]);