Monthly Archives: October 2014

Reliable UDP

Silkopter uses 2 sockets to communicate with the ground station. A TCP reliable socket for the remote control, diagnostics, telemetry etc and an unreliable UDP socket for the video stream.  Both go through a Alfa AWUS036H wifi card.

The UAV brain splits video frames in 1Kbyte packets in order to minimize their chances of corruption – and marks each of them with the frame index and timestamp. The ground station receives these packets and tries to put them in order. It waits for up to 100ms for all the packets of a frame to be received before either presenting the frame to the user or discarding it. So it allows some lag to improve video quality but above 100ms it favors real-time-ness over quality.

All the remote control, telemetry and sensor data is sent through TCP and in theory, given a good enough wifi link – this should be ideal. But it’s not, not even close. I consistently get 300-2000ms (yes, 2 full seconds) of lag over this channel.
All of this is due to how TCP treats network congestion. When lots of packets are lost, tcp assumes the network is under a lot of pressure and throttles down its data rate in an attempt to prevent even more packet loss. This is precisely what is causing my lags – the TCP traffic hits the heavy, raw UDP video traffic and thinks the network is congested, so it slows down a lot. It doesn’t realize that I care more about the tcp traffic than the udp one so I end up having smooth video but zero control.

My solution is to create a new reliable protocol over UDP and send control, telemetry and sensor data over this channel, in parallel to the video traffic. In low bandwidth situations I can favor the critical control data over the video one.

There are lots of reliable udp libraries but I always preferred writing my own for simple enough problems when there is the potential of getting something better suited to my needs (not to mention the learning experience).

So my design is this:

  1. I will have a transport layer that can send messages – binary blobs – and presents some channels where received messages can be accessed.
  2. Data is split in messages, and each message has the following properties:
    1. MTU. Big messages can be split in smaller packets. If a packet is lost, it will be resent if needed. This should limit the size of the data to resend.
    2. Priority. Messages with higher priority are send before those with lower priority.
    3. Delivery control. If enabled, these messages will send delivery confirmation. If confirmation is nor received within X seconds, message is resent. The deliveries also have priority – just like any other messages.
    4. Waiting time. If a low priority message waited for too long, it will have its priority bumped. For video, I’ll use a 500ms waiting time to make sure I get some video even in critical situations.
  3. Channels. Each message will have a channel number so that the receiving end can configure some options per channel. Video will have one channel index, telemetry another and so on. The GS will be able to configure a 100ms waiting period for out-of-order messages on the video channel for example.


My current implementation uses boost::asio and I intend to keep using it.

As soon as I finish the stability pids I’ll move to the new protocol.



Stability pids

While waiting for the new components to arrive I’ve worked a bit on the stability pids.

The stability pids are responsible of controlling the orientation of the quad. So if I tell the quad to lean forward 30 degrees, the stab pids have to figure out how to control the motors lean forward with exactly 30 degrees. Same for leaning left/right.

Silkopter uses quaternions to represent rotations so it’s not as simple as just subtracting the pitch and roll from my target pitch and roll and use the delta. First of all I want to avoid as much as possible using euler angles because of the dreaded gimbal lock. Second of all there’s the wrapping problem of euler angles – going from 0 to 360 or from -180 to 180 which I always get wrong.

So quaternion it is.

My approach is this:

  • First compute the target quaternion from the input. I treat the input as euler angles and build a quaternion fro them. This presents no issue as the input is limited by design to +- 90 degrees. Let’s call this target_q
  • Get the current quad quaternion. This represents the orientation of the quad relative to the world frame of reference (the Earth). Let’s call this uav_q
  • Now compute their difference – or how much apart is target_q from uav_q
    • diff_q = inverse(uav_q) * target_q 
      • where inverse(q) = quat(-q.x, -q.y, -q.z, q.w)
    • This step is the key – by doing the math with quaternions instead of euler angles I avoid the gimbal lock. Also, the quat difference give me the shortest path between the 2 rotations
  • I convert this q_diff to euler and this is how much I have to rotate in each axis to get to my desired orientation. These represent the stability pid inputs – how much the uav deviates from the desired pose – and the stab pids targets is 0.
  • I process the pids and the error is send as the target of the rate pids.
  • The rate pid outputs is sent to the motor mixer which in turn decides – based on the geometry of the uav – what motors need more or less thrust.
  • Repeat this 200 times per second.

Here’s a video of the quad simulation trying to match a pose. I control the pose (the 3 axis system to the right) with a ps3 controller and the quad is matching the pose using the algorithm above. It’s rock solid even if I move the joysticks randomly and it always follows the minimal path to the target rotation. Thank you, quaternions!

New brain – Odroid W

Just received my Odroid W board from here.

It’s incredibly small:

2014-10-09 16.12.27

In the end I decided I’ll use this instead of the standard raspberry pi.

I’m working on a new design right now that will include vibration damping at the motor mount and the Odroid W.

The new components are:

  • Blue Wonder 1300Kv motors, as they are half the size of the Suppo 2208 I use currently – 24g vs 45g. 80 grams saved just from these
  • 9×4.7 CF props
  • The tiny Odroid W. This will allow me to design a smaller case. It also contains 2 ADC inputs – perfect for the voltage/current sensors. It’s such a pity that it’s discontinued.
  • 4 new ESCs – They are 6g each without the shrink wrap and work perfectly when flashed with bl-heli. So 24 total compared to 50 total for the Quattro ESC I use now.
  • A new sonar – SRF02 – Should have better range, is smaller and doesn’t require 2 GPIOs and accurate timing as it’s i2c and does the range computation itself.
  • A 5A switching BEC.
  • The Drotek IMU

In total I think I can save 200 grams. The new quad will total at around 550-600g – perfect for the blue wonder motors that have a total max thrust of 1800-2000g.