Adam Rivera's Posts (10)

Sort by

NEW FEATURE: Automatic Compass Declination



Hello DiyDroners,


I recently completed the implementation of a new feature for ArduPlane & ArduCopter. I have to thank Jan Scherrer for the idea and especially thank Andrew Tridgell for pushing me to improve the original implementation. The new feature is automatic compass declination.

Currently you are supposed to look up the magnetic declination value for your flight location and input that value into the Mission Planner so the compass heading can be corrected. If you are like me and constantly flying at new locations, it is a bit annoying to have to look this up every single time. In this post, Jan asked why it couldn't just be automatic... I did not have an answer so I decided to see if I could make that happen.




The automatic declination code is enabled by default. There is a new configuration parameter you can set in the Mission Planner if you wish to disable/re-enable it. See below:


To enable, set COMPASS_AUTODEC to 1. To disable, set COMPASS_AUTODEC to 0.

After any parameter changes you need to click the "Write Params" button.

With automatic declination enabled, the declination will be approximated to the declination at your GPS Lat/Lng coordinates as soon as a 3D fix is acquired. So far from our tests we show a +/- error of .5 degrees depending on your location. Andrew Tridgell reported accuracy of within .3 and I am seeing accuracy within .05.

The latest code that includes the automatic declination is available in the git repository. I should warn you that while most of the code in there is already tested, some of it may not be because that git repository is constantly in flux. If you feel confident, give it a try! The more testers the better. Otherwise, if you prefer to wait, this feature will be included in the next official release.



What is magnetic declination? Good question...Read this


I ended up finding another person that had put together a look up data table that used bi-linear interpolation to pull an approximate declination based on lat/lng GPS coordinates. This was definitely a good start. So I took that code and adapted it for our code base (of course giving proper credit to the original author). The problem with the original implementation was that the look up table took up a massive amount of space ( > 5kb ) and the way I had originally written it, that look up table was being stored in RAM instead of flash memory. Without going into too much detail on the difference between those two types of memory, the first is memory that is volatile memory that is used to store variables during code execution. It is fast, but resources are limited. Because the look up table is a static set of data that gets used infrequently, it is a much better option to store it in the flash memory (using PROGMEM). You can read about it all here.


Ok... so how to go from a 5kb to a lot less. We are dealing with integer values which vary in size. The first thing we need to do is make sure that we are using the smallest possible integer size for the values that we have in the look up table. The range of values in the original table -99 to 179. So out of the standard int sizes (int8_t, int16_t and int32_t) int16_t is the smallest we could use with a supported range of -32768 to 32767. The next smallest size, int8_t, supports a range of -128 to 127. You can see that the the lower end of the look up values will fit (-99 is greater than -128), but the upper range will not (179 is greater than the allowed 127).


Turns out there are a lot of clever ways to compress data. Here are a few that I considered, some of which I used.

1. Shift all the values -52 bringing the highest value in the look up table to 127 which is within int8_t. Oops that doesn't work. Now the lower end exceeds the lower limit of int8_t.

2. Store the first value in each row and then the differences between each consecutive value instead of the values themselves. This is a very promising approach because the difference between each value is quite small, meaning we can use a smaller integer size to store the value.

3. Pack the sign bits in a different array.


Lets take the highest value in the array (179) and see what that means in terms of a 16bit integer. 179 is represented by the following:


You can see that the upper 8 bits are not used (all zeros), but unfortunately we need at least one more bit to represent the sign of the lower end values. All of our values can fit into 9 bits, but when you create a 9 bit integer it is automatically padded up to 16 bits. What we could do is take all the extra sign bits out of the original array and put them in their own array. That means all of the absolutevalues fit in 8bits (a good improvement over the 16bits before, half the space). So how do we pack those sign bits? Remember that I said that the number of bits is automatically rounded up to the nearest byte. That means that if we tried to declare a 1 bit int for the sign and store it, it would actually take up 8 bits. Take the following:

00000001 - this would represent negative

00000000 - this would represent positive

All we need is that one value (1 or 0) to say that it is either negative or positive. So what we can do to avoid wasting those other 7 bits is to store 7 more signs in that one byte.

Take these values -99, 75, 43, -23, 175, 132, -45, -32

So that would be: 10010011 (1s for negative signs, zeros for the positive signs)

Now we are taking advantage of the full byte (8 bits) and not losing any space because of the padded bits.

Using a combination of the above methods allowed me to pack the values into around 1.6kb. When you compress the values, the retrieval strategy must change. Normally you would access values in an array using this simple syntax. MyArray[12][2] which means give me the value in the 13th row, 3rd column. If we are splitting the array into their starting values, consecutive delta values, and signs, we will need to pull those values out in a different way. If you are interested in learning how it works, feel free to check out the code from the git repository. The logic is located in the AP_Declination.cpp file in the libraries folder.

As always, questions are welcome!



Read more…

RESOLVED: ArduCopter 2.5.3 Yaw Issues


I just finished a long debugging session with Andrew Tridgell and he has discovered the cause of my yaw (and attitude) issues. In case you don't know Andrew Tridgell, he is the genius developer who made the the latest release fly so well with his DCM improvements.

I think the majority of people out there are experiencing this issue can fix the problem very easily.

"So, what is it?!?!"

It turns out that the automatic compass calibration code on the APM does not work so well. I suspect it is working even more poorly under 2.5 because of the improvements to the DCM, but that correlation has not been confirmed. Like most of the users out there, I have never given more than a moments thought to compass offsets because they have been set automatically for as long as I have been a user, but it turns out they have an enormous impact on the performance of one's copter.

First, what are compass offsets? The offsets are three values that account for the difference in the magnetic field of the earth and the magnetic field that your copter experiences due to interference created by the ESCs, motors, etc. So, the magnetic interference can't possible effect heading that much, right? Wrong. If you don't believe me take a look at this graph:


You can see that towards the beginning of the flight when I am not doing much, the red and green lines are not that far off. As the flight continues and I start using more throttle, they are way off. At about 5:20:20 my heading is off by about 250 degrees. That is massive!!!! So why does it change throughout the flight? The more throttle that is applied the more current is flowing through one's electronics which increases the magnetic interference. Normally this field offset is accounted for, but recently I suspect that some users have bad offsets like I did. My offsets were essentially 1,1,1 when they should have been -180,3,52. Check out the next graph which shows the effect throttle has on the magnetic field:

3689450007?profile=originalThis is a log from another user, Marco Robustini. The green line shows the throttle and the red line shows the magnetic field. You can see that as the throttle increases, the magnetic field more than doubles.

So how do you fix it? There is a new feature in the latest Mission Planner that allows you to use a telemetry log to determine the offsets OR you can calibrate your compass in real time by holding and spinning your copter 360 degrees. It is highly recommended that you use the telemetry log method. The reason is that when you are holding your copter and spinning it, you are not accounting for the amount of mag interference from the motors (because they are hopefully not running :-D ). Follow these steps:

With Telemetry Log (recommended)

1. Connect to your copter via telemetry.

2. Take off and fly around for a few minutes like you would normally fly. At this point we are collecting data about the magnetic fields during flight.

3. Land and disarm.

4. Download the tlog from that flight. (Instructions here:

5. Connect to your board


6. Goto the Configuration tab


7. Click on the Setup tab

8. Click on the Hardware tab in the popup


9. Click the "Calibrate" button

10. Click "No" when asked if you want to use live data.


11. Browse to the fresh tlog

12. Your offsets are now saved

Without Telemetry Log

1. Follow the above steps 1 through 9

2. Click "Yes" when asked to use Live Data

3. Rotate the copter 360 degrees

The calibration utility is leagues ahead of the automatic calibration on the board that most of us are relying on. Many thanks to Andrew Tridgell, Michael Oborne, and all the devs who had a hand in the compass calibration utility in the planner. There is some serious brain power behind these features we take for granted.

Andrew Tridgell is working on improving the automatic calibration routines that reside on the board based on the updated (and original) algorithms by Bill Premerlani, but for now the Mission Planner calibration is everyone's best bet for improved flight performance.

If you have any questions just leave a comment.


Read more…

Object Tracking - Real Test (teaser)

Note: This video is available in 1080p. Use it!


I finally have an update on the object tracking software I started back in these two posts:


Here is whats new:

1. Added support for the Pololu Maestro USB Servo Controller (Thanks Chuck!)

2. Added tunable PID controller that takes the X/Y error and converts it into an output for the USB servo controller



1. Add zoom (this will be tricky)

2. Add option to select either 360 degree servo or regular fixed position servo

3. Test outdoors with real tripod mounted gimbal

4. Polish up the UI and provide a beta copy to you guys!


It is coming along nicely! I am really happy with the software so far. As soon as I have a field test I will post another video. Also, I am still planning on integrating it into the mission planner. Time has been scarce (it always is).


Anything you would like to see? Just leave a comment.



Adam Rivera

Read more…

Rate PI Autotuning - A third attempt

Hi again all, Two blog posts in two days... i'm on a roll. I just finished the next set of revisions to my autotuning code. I have shifted from tuning the stab gains to tuning the rate gains. This is more dangerous but also more rewarding.

Here are the major changes:

1. Stab gains no longer tuned, switched to rate gains.

2. Addressed the issue of inconsistent user induced disturbances. Previously if the user disturbance was not consistent, the calculated performance value would be inaccurate. Now it is a scaled based on the initial pitch/roll of the copter.

3. Lowered the initial amount of gain change to 25% to mitigate the risk of in flight gain changes.

4. Added a safeguard against a gain that is too low and never returns the copter to level.

5. Moved all autotuning related logic into its own .pde file so it is easy to find


1. Upload the modified code (see attached zip based on v2.3)

2. Set your stab p gain to 1, stab i and d to zero

3. Set your rate p gain to some ballpark number, rate i and d to zero

4. Start your simulator

5. Bring the copter to a hover

6. Flip the ch 7 switch to the high position

7. Introduce a pitch or roll disturbance. This should be a quick movement and then return the stick to center (see video) (repeat 10 times at least).

8. Flip the ch 7 switch to the low position

9. Go to the planner and refresh the param list.

10. Set stab p = 1 + the value from rate p (maybe a little lower), stab i = 0 and stab d = .002

11. Set rate d = rate i - .003

12. Write the new values and observe in the simulator.

That should get you very close to rock solid. I have found the need to play with the stab p gain a little bit, but other than that I have had good results. Steps 10 - 12 are a bit hazy at the moment and will require some additional manual tuning.  Those last steps are based on observations that I have made, not specific processes that I can guarantee will work for everyone. I am hoping some others can chime in here with some insight. Perhaps some devs can get eyes on this as well. I did try to push this into my git branch, but I am having some authentication issues at the moment.

Please watch the video for more information.... It is still uploading as of now, so if you can't see it yet just give it another 20 min or so. My videos are in 1080p so you can read my screen.



Read more…

Introducing Nemesis: APM powered octo platform

Good Morning DIYDrones,


I am pleased to introduce a drone platform that I have been working on for some time. I have not finalized my marketing materials, but I thought this community would like to see an early peek. Please see the included rough-edit promo video as well as my website. Questions/Comments are encouraged.






Adam (Sentient Drone, LLC)


Read more…

DISCLAIMER: This could be dangerous and might crash your copter.

OK! I made some new changes to the autotuning algorithm and I have tested it again in the simulator. I think this is ready for some real world testing from some VERY BRAVE users, or some simulation testing. Unfortunately I do not own a quad and my octo is out of commission until Tuesday, or I would be testing this right now outside.




First, here is what is new:

1. The amount of change applied to the P gain scales down with each iteration. This allows for quicker acquisition and better resolution of your Pretty Good Gain

2. If the tuning logic moved the P gain in the wrong direction it will revert to the best P gain that had been found and use that as the new launching point which should save some iterations

How to use it:

1. Replace the files in your ArduCopter 2.2b2 code base with the files that I have included in the .zip.

2. Upload the code to your board and test in the simulator so that you can get a feel for how it works (follow the same steps below for setup starting at step 5)

3. Update the config file to disable the HIL setting or change your frame type, etc...

4. Re-upload the code for live flight IF YOU DARE

5. Connect the APM to the Mission Planner.

6. Go to the configuration tab and manually set the CH7_OPTION to 8 as seen below and click "Write Params"


7. Set your Integral (I) gains for pitch and roll to zero and click "Write Params"

8. Bring the copter to a hover and flip CH7 to the high position to activate the auto tuning mode

9. Roll to the right or left and quickly return the stick to the center position. (Repeat this step at least 5 times)

10. Deactivate auto tuning mode by flipping CH7 to the low position

11. Reactivate auto tuning mode by flipping CH7 to the high position

12. Pitch the copter forward or back and quickly return the stick to the center position. (Repeat this step at least 5 times)

13. Deactivate auto tuning mode by flipping CH7 to the low position

14. Go to the configuration tab of the Mission planner and click "Refresh Params" to see your new tuned P gains

15. Write those values down.

The idea of steps 9 and 12 is to introduce a wobble and let the copter try to even itself out. Don't go too aggressive with your pitch or roll... again its just to introduce a disturbance.


My videos are in 1080p so that you will be able to read whats on the screen.


Questions, comments, discussion is welcome and encouraged!

Read more…

ArduCopter PID Autotuning - FOR SIMULATION ONLY

Hello all,

First, THIS IS EXPERIMENTAL FOR SIMULATION ONLY. Video coming shortly of me using it in the simulator.

I have a functional first attempt at automatic P gain tuning. I'm calling it Pretty Good Gains (pun intended). There is definitely room for improvement, but here is how it works:

PID controllers usually end up with an output graph that looks something like this (from wikipedia):


As you can see by the above graph the most well tuned P gain value in this controller is 2. Why? Because it arrives at its target value the fastest with the least amount of overshoot and oscillation. One can see this in practice when flying a multi-copter and the PIDs are too high producing an oscillation. I have read a lot of different PID tuning strategies looking for something that I could replicate in code. I came across something called the Good Gain Method. Essentially this method of tuning requires the user to set the Integral and Derivative gains to zero and first focus on the P gain. Adjust the P gain until the least amount of oscillation is seen with an acceptable arrival time at the target value. If the P value is too low, the curve will take too long to get to the target and if the P value is too high you will see the more violent oscillations.

How do we do this in code? Well, first I require the user to input a disturbance into the system (ie. pitch right) and then wait for the user's input to return to zero (center stick). Now we have our starting point (the disturbance) and our target (zero pitch, or stable hover). As the copter attempts to return to a stable hover the error values follow a path similar to the curve above. As this is happening I measure the distance between the first peak and the first valley of that curve and how long it took to produce that peak and valley. Now we have our starting point. When another disturbance is introduced we can compare its peak/valley to the previous oscillation and decide which direction to move the P gain. Once that is done enough times, the P value is tuned.

Right now I move the P gain value in increments of 10%, but I can see changing that to adapt to the degree of the oscillation with increasing granularity as the P gain improves. I have tested this in the HIL simulator and it seems to work well. It works best if you set the P values a bit too high and let the auto-tune lower it.

I am attaching a zip of the files I modified. Please give me feedback and discuss my method. Again, Pretty Good Gains means that this isn't perfect. It also doesn't address the Integral gain... but I have plans for that too.

Read more…

Object Tracking - Proof of Concept

A few days ago I posted some videos of my object tracking algorithm, and some folks were curious how well it would perform if the object left the frame. Since posting I have hit kind of a breakthrough in the algorithm and it is working much better than I had ever expected. I am still fine tuning some of the sensitivities, but I added some neat features.

  1. Now you get a white box when you click and drag to define the target.
  2. There is an adjustable accuracy threshold. If one finds that the target will not re-aquire, one can reduce the accuracy (demonstrated in the video above)
  3. New improved multi-threading (under the covers)

I am working on both Mission Planner integration and, for those who want to use this for auto antenna tracking or camera tracking from the ground, Pololu Micro Maestro integration. As you can see in the video above, the software is able to re-aquire the target when it leaves the frame or gets confused. This is thanks to the constant learning of that objects features as it changes shape or orientation over time.

Read more…

I am currently working on integrating an object tracking algorithm of my own making into the Mission Planner. The algorithm combines Lucas-Kanade and SURF and attempts to learn negative and positive reinforcement values as it runs. Right now it is in the early stages of development, but I hope to have something fully functional within a few months.


My hope is to use this to aid in automatic centering of the tracked object by sending commands to the APM to move the camera gimbal based on the distance of the tracked object from the center of the frame. In the videos below you will see two demonstrations of this tracking algorithm. In both cases it seems to perform well with background noise.


NOTE: I apologize for the terrible frame rate of the videos. I don't have very good screen capture software. The second video is a little higher quality.

Read more…

Lesson: always fly with telemetry or a spotter!

After some painstaking PID tuning and some near crashes, I decided to take out my octocopter and see what kind of thrust it was able to generate. After hovering for a moment, I gunned the throttle and the machine disappeared into the sky. It was beautiful. The only problem was that I had forgotten my Xbee receiver and thus had no telemetry data. My glee quickly turned into panic as I tried to judge which way the octo was facing and how to get it back. As it drifted further and further with the wind, I collected myself and started to lower the throttle. It grew larger for a moment but I knew it was still drifting. I tested pitching backwards, to see if it would get closer, then pitched forwards.... forwards was the trick and it moved back within a comfortable range.


Moral: Never fly without telemetry OR a spotter. I had neither and my very expensive prototype almost disappeared forever because of it.

Read more…