我正在建造一个附有传感器的机器人。机器人上的控制单元是ARM Cortex-M3,所有传感器都连接到它上面,它通过以太网连接到“地面站”。
现在我想通过地面站在机器人上读写设置。因此,我考虑在机器人上实施一个可由地面站操纵的“虚拟寄存器”。
它可以由结构组成,看起来像这样:
// accelerometer register
struct accel_reg {
// accelerations
int32_t accelX;
int32_t accelY;
int32_t accelZ;
};
// infrared distance sensor register
struct ir_reg {
uint16_t dist; // distance
};
// robot's register table
struct {
uint8_t status; // current state
uint32_t faultFlags; // some fault flags
accel_reg accelerometer; // accelerometer register
ir_reg ir_sensors[4]; // 4 IR sensors connected
} robot;
// usage example:
robot.accelerometer.accelX = -981;
robot.ir_sensors[1].dist = 1024;
在机器人上,寄存器将不断填充新值,配置设置由地面站设置并由机器人应用。
地面站和机器人将用C ++编写,因此它们都可以使用相同的struct数据类型。
问题我现在的问题是如何在不写大量元数据的情况下将读/写操作封装在协议中?
假设我想阅读注册robot.ir_sensors[2].dist
。我如何在我的协议中解决这个寄存器?
我已经考虑过以字节为单位传输相对偏移量(即结构内存中的相对位置),但我认为内存对齐和填充可能会导致问题,特别是因为地面站在x86_64架构上运行而机器人运行在一个32位ARM处理器。
感谢任何提示! :)
答案 0 :(得分:1)
我认为Google protocol buffers是一个很好的会话/表示层工具。实际上,Google协议缓冲区不支持我想到的语法。因此,我将更改我的答案的这一部分,以通过Code Synthesis推荐XSD。虽然它主要与XML一起使用,但它支持不同的表示层,例如XDR,并且可能比具有大量可选数据的协议缓冲区更有效。生成代码也非常适合使用。 XSD 可以免费使用OpenSource软件,甚至可以使用有限的消息结构进行商业用途。
我不相信你想随机读/写寄存器组。您可以使用enum
为消息添加前缀,该消息表示消息,例如IR update
,distance
,accel
等。这些是注册组。然后机器人用寄存器组响应。到目前为止,您提供的所有寄存器都是传感器。 write
必须是电机控制?
您想要考虑您想要执行的控制以及您希望接收的遥测类型。然后提出一个消息结构并将信息捆绑在一起。您可以使用sequence diagrams
和远程过程API,例如SOA/SOAP,RPC,REST等。我不直接表示这些RPC框架,但是诸如request/response
之类的概念以及可能只是在没有特定请求的情况下定期发送的消息(遥测)。因此,来自地面站的遥测请求会有某种间隔,然后机器人会定期响应未经请求的数据。你总是需要一个消息ID(enum
以上),除非你的协议是有状态的,我会因为健壮的原因而不鼓励。
您还没有描述控制系统如何工作或者您是否希望远程执行此操作。描述可能会导致更多关于协议的想法。我相信我们正在讨论OSI的第5,6,7层。玩得开心。
答案 1 :(得分:1)
我也会建议使用Google Protocol Buffers。
在最简单的情况下,您可以像这样实现一条消息RobotState
:
message RobotState { optional int32_t status = 1; optional int32_t distance = 2; optional int32_t accelX = 3; ... }
然后,当机器人收到消息时,它将从存在的任何可选字段中获取新值。然后它将回复一条包含所有字段当前值的消息。
这样,使用大多数protobuf实现的“合并消息”功能实现字段更新非常容易。此外,您可以在开始时保持简单,因为您只有一种消息类型,但如果您稍后需要扩展,则可以添加子消息。
protobuf确实不支持int8_t
或int16_t
。只需使用int32_t
代替。