Stats analysis

From the same run as the last two posts, I’ve been analysing the stats.

First the integrated gyro showing the yaw it detected:



This shows the unintentional clockwise (negative) yaw of about -10° shortly after take-off followed by the intentional anticlockwise yaw of +90° as Hermione headed off left.  I still need to have a play with the yaw rate PID to try to kill that initial -10° yaw.

More interesting, to me at least, is the motion processing:

FIFO stats

FIFO stats

The graph shows how often the FIFO was emptied.  In an unhindered world, the FIFO is emptied every 10ms (0.01s) and the PWM to the ESCs update.  Peaks above that means something else was taking up the spare time.  The FIFO overflows at just above 84ms (512 bytes total FIFO size / 12 bytes per IMU sample / 500Hz IMU sampling rate =  85.333ms), and the highest shown here is 38ms, well within safety limits.  I’m particularly delighted that the majority of the spikes are within the 10 to 20ms range – that strongly suggests the split phases of macro-block processing is working like a dream.

The 20ms norm means the PWM is updated at 50Hz.  Were the PWM consistently updated at less than 50Hz, it would really start to show in the stability of the flight.  But luckily it isn’t, meaning there’s probably just enough room to finally squeeze in compass and GPS processing.

In passing, it’s worth saying that such levels of stats would be impossible if I was using a microcontroller (Arduino etc) – this 11s flight logged 1.46MB of data to shared memory, and ultimately to SD card.  It logs both initial hard coded constants, and every dynamic variable for every cycle of motion processing – that means nothing is missing and it’s possible to diagnose any problem as long as the reader knows the code intimately.  Without these logs, it would have made it nigh on impossible for the ignorant me 4+ years ago to achieve what I have now.

* I rate myself as experienced having spent over 4 years on this.

Code update and horizontal flight plan

I’ve just uploaded the latest code up to GitHub.  It only adds some tested tuning and diagnostics to ensure the tightest zero drift yet, perhaps the best it can possibly be.

I have a cunning plan to add a degree of remote control without breaking my ruling of no human in the feedback loop.  But I need to check first Phoebe can walk before I teach her to run.

To that end I’ll add horizontal velocity targets into the configured flight plan along the lines of

  • 2.0 seconds climb at 30cm per second
  • 1.0 seconds hover
  • 2.0 seconds horizontal movements at 30cm per second
  • 1.0 seconds hover
  • 2.0 seconds descent at 30cm per second.

No changes to the code are required, but clearly the test flights will need to happen outside until my confidence builds.

I couldn’t resist taking her out for a flight with intentional lateral movement included in the flight plan. And it just worked – I just inserted 3s of leftwards movement between a second of hover either side. It was cool to watch her climb, hover, then lean left, flattening out once at 0.3m/s, and then leaning right to put the horizontal breaks on as the flight plan swapped back to hover again.

There was a lost of height throughout, but nowhere near as much as I’d expected.  I’ll see if I can get a video to show it.

Critical stats

Just thought I’d share with you the critical stats logged to console during a flight.

The majority of the stats data (about 0.5MB for a 10s flight) are logged at warning level to file (actually to shared memory and then dumped to file at the end of flight for performance reasons) allowing for post flight analysis.

The following critical stats are logged to file and console so I can check critical config and calibration prior to flight, flight progress and post-flight performance.

Pre-flight checks passes, enjoy your flight, sir!
calibrate_sensors = False, fly = True, hover_speed = 680, shoot_video = False, vvp_gain = 300.000000, vvi_gain = 150.000000, vvd_gain= 1.500000, hvp_gain = 0.500000, hvi_gain = 0.250000, hvd_gain = 0.050000, aap_gain = 2.500000, aai_gain = 0.000000, aad_gain = 0.010000, arp_gain = 140.000000, ari_gain = 0.000000, ard_gain = 2.500000, test_case = 0, tau = 0.500000, dlpf = 4, loop_frequency = 100, matrix = 2
Platform tilt: pitch -0.610291, roll -0.094064
Platform motion: qax -0.010648, qay -0.001641, qaz 0.999648, g 0.999706
Platform motion: eax 0.000000, eay 0.000000, eaz -0.000294, g 0.999706
loop speed 95.777507 loops per second
% fsm: 1.810349
% sensors: 40.043741
% eangles: 1.625082
% iangles: 0.495392
% angles_filter: 0.837208
% axes_shift: 1.772628
% speed_pids: 5.008621
% angle_pids: 8.999825
% pid_outputs: 8.510055
% pid_diagnosticss: 21.673254
% sleep: 9.416033

The interesting bits in the current testing context are the pre-flight “Platform” logs; they show the pitch / roll angles prior to take-off, the accelerometer readings along Phoebe’s axes, and the conversion to the earth axes.

You can see the take-off platform (the ground) wasn’t completely horizontal, and this shows up in the difference between the qa* and ea* values.  However what’s reassuring is that the total measure of g in both sets of axes comes out to 0.999706g; also reassuring is that the earth axis eax and eay figures are zero to 6 decimal places.  My only concern is that eaz is -0.000294 (I’ve subtracted 1g at this point), suggesting a roughly -3mms-2 vertical acceleration when stationary; for the moment I’m just using this as an offset ‘tweak’.

This gives me yet more confidence the angles / axes code is good, and I should stop spending too much time considering it as the cause for drift.

Suntan or just a bit grubby?

I coded the trend-line offsets for the accelerometer last night and have just take Phoebe out into the back garden for a quick sanity check test flight.  There was no wind, and very little drift, so the results are a bit inconclusive for the moment (other than no harm was done), but it’s probably worth my while rerunning yesterday’s trend-line tests to get the best values I can.

At the same time, Dave pointed me in the direction of gyro temperature sensitivity too.  I’m less concerned about this since the flights are currently short, the gyro is calibrated per flight, and the gyro is only used short term for rapid detection of changes in tilt – longer term, the accelerometer Euler angles take over via the complementary filter.  Still, probably worth investigating just in case, if only for longer flight drift.

Finally, Jeremy requested some flight sensor data – I’ve attached the .csv file (Excel can turn this into a spreadsheet) corresponding to one of this morning’s flights.  Just leave a comment if you want me to churn out some graphs!

10s flight stats

Prologue: Accelerometer sensor testing rig

Acclerometer testing rig

Acclerometer testing rig

Phoebe sits on a perspex sheet, which normally I used to check horizontal before a flight. I pop it on top of the motors with a spirit level on top, as it’s the blades that need to be perfectly horizontal to get a horizontal hover with no drift (assuming no wind).

However, in this rig, it provides a flat platform to roll over the balls.  Once Phoebe is running – she’s powered by the normal micro-USB cable in this case, so no motors (an advantage of opt-isolated ESCs) – she gets rolled to her left (downward in the picture) and then in reverse (to the right in the picture) generating stats all the while:

Accelerometer test stats

Accelerometer test stats

Scale for the left axis as usual is meters (distance), meters per second (speed) and meters per second per second (acceleration).

Blue is the y-axis data representing left / right movement; green is the x-axis data representing forward / backward movement.

The values for the move left seem plausible: 34cm peak distance is good though the drift down from there is annoying – I have to hope this is a slight angle in the flooring causing non-zero y-accelerometer integrating up – it’s plausible looking at the y-axis accelerometer readings at the end.

The values for move backwards are better – a 43cm move in reverse.

The key point of this is I now know that backwards movement from standstill produced a falling edge negative accelerometer output, a negative speed, and a negative distance. Or swapping it round, a forward acceleration produces a positive rising edge accelerometer output, a positive speed, and a positive distance travelled.

Similarly, a leftwards movement from standstill produced a rising edge positive accelerometer reading, a positive speed, and a positive distance.

And in both cases, the sensor outputs match real-world acceleration, speed and distance values.

These findings are important to allow me to add the wind-drift PIDs – more on those in another post as they are subtle and there’s a variety of options to choose from.

P.S. I already have figures from Pitch and Roll testing, but I reran the test to make sure: a nose down and return from Phoebe leads to a positive pitch peak; a left side down and then up leads to a negative roll peak, and the angles in both seems plausible as 30 degrees.

Pitch roll stats

Pitch roll stats


Where next?

Phoebe has pretty much answered the question: she took off from as good an approximation of a horizontal surface as I could come up with, and yet, once airborne, she drifted backwards. This is the polar-opposite of being able to control her flight in a desired direction; if I can stop this drift for a vertical take-off, then I can apply the opposite logic to apply drift for horizontal movement.

First step as always is to have a nosey through Phoebe’s stats from the flight, in particular the x-axis accelerometer output (plus integral for speed), and engage the outer horizontal-speed PIDs to produce the targets for the inner angular PID (which actually drives lateral speed); the unwarranted horizontal movement is stopped by a managed tilt upwards the same direction (i.e. a backwards drift will be stopped by raising Phoebe’s rear blades, and tilting down her forward ones).

But before I get too engrossed, I think Phoebe and I are due some free-play time together!

One last thing – some stats from a separate flight that day showing two things:

First how much effort is required to maintain stable yaw – about 17% more power is applied to the CW blades than to the ACW blades – that surprised me given that in theory at least, the motors and blades are nigh on identical, and the body is well balanced.  I’ll have to have a think:

YAW stats

YAW stats

Secondly, a plot of acceleration, speed, and height, all derived from the accelerometer; I’m particularly impressed with the speed and height results, particularly as they are just integrated from the acceleration, and the fact that as the applied power drops, you can see the controlled drop in height as expected.  Bodes well for a more automated takeoff.  Units on the left at meters per second per second, meters per second or meters for acceleration, speed and height respectively.  Units on the right are the motor power between 0 and 1000 (PWM pulse width in microseconds)

Vertical Height, Speed and Acceleration

Vertical Height, Speed and Acceleration


Trampoline testing and virtual reality

With a little thought, I have a better idea of what’s required from the trampoline. Consider the following:

Height, Speed and Accleration

Height, Speed, and Acceleration

The top ‘picture’ shows flight – plotting height over time. The quad sits on the ground, then rises at fixed speed for a bit, hovers for a bit, descends for a bit. and sits back on the ground again – this is the external set of targets for the quad – what the human wants it to do.

The middle ‘picture’ shows the same, but plotting vertical speed over time. The sitting quad starts with 0 speed; a pulse of linear speed integrates over time to produce the sloped rise in height in the first picture. Descent is clearly the opposite. This is what the outer PID does – it takes the target set by the first picture to produce and output to achieve the desired vertical speed

The final ‘picture’ shows the same but from the acceleration point of view. Violent spikes of power are applied to the drone to change it speed as per picture two; momentum maintains that power to change it’s height as per picture one. This is what the inner PID does – it takes the output of the output PID as it’s target acceleration, and combined that with the gyro inputs to control the acceleration.

OK, in the real world, all the sharp corners will be rounded or wobbly depending on how well the PIDs are tuned. But the sharp diagrams provide excellent PID ‘targets’ for simulation – and that’s the next direction I’m going: using these targets, and some basic math(s) and a spreadsheet, it should be possible to tune the PID in simulation alone except for one missing link, and that’s where the trampoline steps in: I need a mapping between the blade PWM inputs, and the net acceleration that produces. That simply means that I do several runs at various PWM inputs, and use the accelerometer to measure the resultant acceleration.

Don’t think I’ll need it, but the drone currently weighs 1509g (1.5kg) currently:

Drone weight

Drone weight

That’s with the new case and corresponding diet Model A RPi, micro-USB adapter, carbon legs and the golf ball feet!


Stats never lie!

Here’s some of the stats that match the PID tuning video from my previous post.

Live PID tuning stats

Live PID tuning Stats

Pink and blue are the sensor outputs, integrated to show the angles.  This clearly shows the lurch downwards at the start, the recovery back to near horizonal, and the oscillations setting in.

Yellow and cyan show the blades reaction to this in an attempt to compensate.  They’re actually doing the right thing, but in some cases they are not trying hard enough, in other cases, too hard, and in others, they don’t know when to stop trying!

Here’s what I’m speculating this means, and therefore what I’ll do next.

  • The inner gyro force PID P gain is too high, causing the oscillations – essentially the extra power it’s adding causes the blades to overshoot their mark, and then the same PID over-compensates for this – I think my approach will be two-fold here – first reduce the PID P gain, but at the same time balance that with some PID D gain – however by using the D gain, when the error since last time has reduced, the D gain lowers, and hence should prevent the overshoot.
  • The initial lurch may well be ignorable – I think it comes from the fact that the legs have a flat bottom, which means that the drone doesn’t need much power to keep it balanced when horizonal as the feet are doing the work – but once the gyro force PID overshoot, and the feet are no longer keeping the balance, the drone starts to fall over, and the outer gyro angle doesn’t provide enough oomph to straighten things out – it’s ultimately the inner PID I gain which achieves this slowly.  So the outer gyro angle P PID gain needs upping.

Fingers crossed!


Reality bites…

and has nasty, big, pointy teeth!

Live testing stats

Live testing!

This live action test shows the drone take-off well under manual control, and then throw itself manically at every piece of furniture it could reach. Luckily due to the restraints fitted onto the test slab (rubber bands), that furniture was a metal table frame. The drone lost the fight. One motor and blade to be replaced, but I knew this would happen so already have spares standing by.

What did I learn? That my various PID settings were out by a factor of 10, and that there was a bug in my code for transitioning between manual take-off and auto-hover which meant the z-axis PID differenial was huge, which was what instigated the giant spikes! From that point on the rest was history! Ouch!

Dealing with the Drone DT’s

So the noise / jitters on the various spreadsheets bothered me, and having sorted so many other bit’s I’ve finally have the time to fix these. The problem arises due to noise / jitter on the accelerometer, even if it’s standing still on a stable platform. The problem was that the PID output jitter was disproportionate spiky compared to the accelerometer jitter. Having cleared the other problems, it’s apparent why. The frequency of reading the accelerometer was also unstable (due to a bug in the code). Combine this (and especially an occasional very short time increment between read) led to the PIDs for all 3 axes spiking in the D value of the PID. The Differential value is error / time_since_last_read (delta t or dt as t shrinks to 0). Too small a time leads to too large an influence of the D value on the PID output.

Where’s what I got once fixed:

More stable with better timing

More stable with better timing

A few clarifying points:

  • The chart shows the spinning rate of each blade – not it’s altitude.
  • The first 100 points (10s) is the blades under manual control to attain take-off
  • The next 200 points (20s) are the blades in automatic hover to attain 1g hover
  • The final 100 points (10s) are the blades slowing to gently land automatically – so the spin rate drops ever so slightly under hover level. Note that it continues to descend more because it can’t get to 0.95g (my chosen descent rate) because this is a sumulation and the drone hasn’t moved off the floor – so the z-axis PID integrator is slowly reducing the power to the blades in an attempt to land quicker.

Overall, I think I’m at the point of live testing again!