Here are some answers about that:
Yes, every end of the network (both controller & device) can send & receive any type of data. The
low latency (3) type was created for video streaming on the Bebop (& Jumping), and is not used at all by the Mambo (and the others BLE minidrones).
Ack (1) data type is mostly an internal type, as it is not designed to transmit data from an app, but only to acknowledge data from the remote end. So usually, your choice when sending data is whether you want a network acknowledge (
data with ack (4)) or not (
The Acks messages, on the
libARNetwork level, are purely network acks. It means that the drone did get the message, but has no implication on whether the command was applied (or even understood). To get such “command-level” acks, you should wait on the app-end for the related events (i.e. when sending a TakeOff command, wait for a FlyingState event). In either case, there is no
Nack messages, so there is a need for timeouts.
To answer your questions, in order:
- Sending a sequence of commands without waiting for network acks should work fine on BLE, because it already handles retransmission & acknowledges at the radio level. The network acks are mostly useful on WiFi/UDP (the use case for the Bebop line, or on the Mambo FPV), where they ensure that your commands are actually received in order. Anyway, the drone will execute any command it gets when it gets it. In your case, it means that (with no time between the commands) the drone will start to take-off, cancel it (a landing command cancels a takeoff command), then take off again. While it seems that it only executed the last one, it actually executed all
- To achieve this, you will need to listen on the Flying State events from the drone. The drone has no queue for commands (this would add latency), so it you want to create a sequence, the trigger for the next command has to be on the controller side.
- Exactly: the payload of an Ack packet is the sequence number of the packet it acknowledges. But again, this is only a network ack. In
libARNetwork, we use this to sequence the commands on the network (i.e. send command N+1 only after command N was acknowledged)
- If you don’t send an ack for these data, the drone will consider them as “lost” and will send them again (up to 5 times, with 200ms between each sends, if I remember correctly). Retries are sent with the same sequence number, so you can “discard” excess data, but it creates unnecessary load on the network. So in short: not mandatory, highly advised.
To give some context here, the protocol was designed for use on UDP sockets on top of an unreliable wifi network. We expect some packet losses and sometimes a few out-of-order packets. Those two things should never happen on BLE.
Each command is associated with a sequence number, when received out of order, we need to make sure that only the “real” last one is executed (imagine sending a PCMD with full speed, another requesting a stop, and getting them out of order). That’s why we do check the sequence number in
libARNetwork. Any duplicate (i.e. retry) or “older” (i.e. sequence number lower than our last one) command is discarded and the upper software layers are not notified about it. But since the sequence number only uses one byte, we do encounter loobacks (255 -> 0) into the sequence number stream, and we need to consider that “0 > 255” is true. So we included an arbitrary limit of 10, meaning that if we’re getting the sequence “100 then 95” we consider 95 to be out of order, but if we get “100 then 85” we consider 85 to be “255 + 85” (i.e. we looped over).
A summary of the section 3 would be the following:
On top of the
ARNetworkAL data type, you can have multiple data streams (each stream has its own sequence numbers). On BLE, each data stream is mapped on a characteristic (the data stream id is based on the last 8 bits of the characteristic number), on UDP, it is marked as an additional header on the network.
By convention, we use a data stream for “periodic” (non acknowledged) data, and another for “event-driven” (acknowledged) data, in both direction. In reallity, the protocol does NOT require this, and you can send all the commands (and mix ack/non-ack commands) onto a single data stream.
Acks always use a different data stream than commands (as noted in 3.3, their ID is the data stream id + and offset [128 or 16, depends on network type])
The huge tables in 3.4 are only a “dump” of our configuration from the library. The thing of interest for you here is only that the Mambo (Mambo is a derivative of Rolling Spider), on BLE, will listen on data streams 10, 11 and 12, and will send data in data streams 15 and 14.
This table lists all the possible types of arguments you can encounter in a command, and how to pack them as a buffer to send on (or read from) a characteristic.
Lets take the ProductMotorsVersionChanged command as an example (its deprecated, but complex enough to serve as an example).
The XML file shows that the command has four arguments (motor, type, software & hardware), whose types are respectively one u8 then 3 strings. From the table, we can see that an u8 is encoded as a one-byte unsigned integer value (
unsigned char in C), then all the strings will be encoded as
NULL-terminated strings (As done in C, you can start to see a trend here ). We can also see that the command ID (project / class / command) is 2/11/0. Based on this, if we wanted to encode this commands with
(42, "a", "b", "c") as its arguments, we would end up with the following buffer (11 bytes long):
// project, class, --command-, motor, ---type--, -software-, -hardware-
[ 0x02, 0x0b, 0x00, 0x00, 0x2a, 'a', 0x00, 'b', 0x00, 'c', 0x00 ]
Totally a userland feature The “SDK” (in term of protocol) is purely peer to peer, you can’t have more than two nodes per connection. If you want to connect to N drone, you need N individual connections, then your software will do the link.