Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compensate long-term baro drift #3749

Closed
wants to merge 2 commits into from

Conversation

hsteinhaus
Copy link
Contributor

This PR slowly corrects the barometric base altitude (ALT_OFFSET parameter) during flight using a low pass filtered signal derived from GPS altitude.

Correcting the base altitude is important during long AUTO missings, otherwise the actual flight altitude above home slowly drifts away from the altitude target. I have regularly seen drifts of more then 20m per hour of flight. This could easily lead to a violation of protected air spaces or to controlled flight into terrain.

The compensation starts after a certain period of flight with constant alt target (configurable by parameter ADJ_DELAY). The rate of compensation (paramter ADJ_RATE) and the time constant for filtering the GPS altitude (parameter ADJ_TC) are configurable as well. The compensation is disabled by default and has to be enabled by the user by setting a non-zero ADJ_RATE.

Fixes #2022 .

@hsteinhaus hsteinhaus force-pushed the gps_qnh4 branch 2 times, most recently from fe38284 to 8deacbb Compare March 14, 2016 18:42
@@ -111,6 +111,7 @@ const AP_Scheduler::Task Copter::scheduler_tasks[] = {
SCHED_TASK(three_hz_loop, 3, 75),
SCHED_TASK(compass_accumulate, 100, 100),
SCHED_TASK(barometer_accumulate, 50, 90),
SCHED_TASK(barometer_adjust, 400, 50),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

400Hz update loop rate is massive overkill.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment in L80-L93 says "400 = 1Hz". But the macro definition says rate_hz.

So what is correct? May we should fix either the comment or the macro?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the comment is wrong.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can add it to one_hz_loop()

@magicrub
Copy link
Contributor

Thanks for this patch. It is one of many solutions to this problem so having this "in our bag" as an option will be a plus. There are a few changes I posted which I'd like to see before something like this goes in since it will be a critical change.

@hsteinhaus
Copy link
Contributor Author

@magicrub Thanks for the review, very much appreciated! Obviously some nasty "things" happened when porting forward the patch from AC 3.2.1 to master in a hurry. Fixes will be pushed after a test flight.

@magicrub
Copy link
Contributor

while you're at it, can you remove all those .set() and .get()'s from _alt_offset. Just makes it harder to read.

@hsteinhaus
Copy link
Contributor Author

Will do a test flight tomorrow. If everything goes well, I will rebase the reworks into the original commits.

I did not touch the comment and the get/set problem, will better create a separate branch for that kind of work.

@magicrub
Copy link
Contributor

I also see that all your commits start with 'AP_Baro'. Per our guidleines (http://dev.ardupilot.com/wiki/submitting-patches-back-to-master/) we like to have the directory name as the first thing in the comment. Next time!

@@ -367,7 +402,8 @@ void AP_Baro::update(void)
if (is_zero(ground_pressure) || isnan(ground_pressure) || isinf(ground_pressure)) {
sensors[i].ground_pressure = sensors[i].pressure;
}
float altitude = get_altitude_difference(sensors[i].ground_pressure, sensors[i].pressure);
float altitude = get_altitude_difference(sensors[i].ground_pressure, sensors[i].pressure) +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Up at line 380 I added a LPF to _alt_offset a few months ago for when step-inputs are done by companion computer or GCS. The result of that is _alt_offset_active. Then at line 405 you add your "raw" offset then at 410 the existing code adds my LPF'd offset again. The offset is applied twice. The offset at line 405 should be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very interesting information. Today, I tried a flight, but something was strange. The correction seems to oscillate, what I have never seen with my branch of AC before. I think, this could be a very good explanation for the strange behavior.

Unfortunately it's too late now for another flight, getting dark already here...

@hsteinhaus
Copy link
Contributor Author

Just did a successful test flight: The takeoff, all touch-and-gos and the final landing were targeted to exactly the same place on the ground. The reported altitude in was within +-30cm of true value before entering ground effect/pressure bubble.

alt_adjust

The periodic signal in the graph is probably from my copter flying without canopy in strong winds. My AUTO pattern was a rectangle of about 2 minutes per round, flying the upwind leg nearly at maximum possible airspeed. The correction signal has been scaled by a factor of 10 for better visualization.

@R-Lefebvre
Copy link
Contributor

Very interesting work Holger.

How do you measure ground-truth when you claim +/-30cm? Would be interesting to get a longer-duration copter and a Lidar.

@hsteinhaus
Copy link
Contributor Author

By loitering in front of me, exactly in the height of my eyes, then reading the altitude shown on the display of my transmitter (which is equivalent to BARO.Alt) ;-)

else {
_gps_alt_over_home.apply(gps_alt - _home_alt, GPS_DT);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@magicrub During one test flight I had a home point, that was not on the ground (discussed here: https://groups.google.com/forum/#!topic/drones-discuss/FzWhvnpW0cI ). In that case, (gps_alt-home_alt) is obviously not the altitude over takeoff. Is there any need to handle that case here?

Or better fix the problem that HOME is not on the ground elsewhere?

@magicrub magicrub added the GPS label Mar 16, 2016
@magicrub magicrub added this to the Plane v3.6.1 milestone Jun 6, 2016
@ghost
Copy link

ghost commented Jun 23, 2016

@rmackay9 @hsteinhaus
Any chance this will go in AC 3.4?
Best regards,
Thorsten

@rmackay9 rmackay9 assigned WickedShell and rmackay9 and unassigned tridge and magicrub Apr 11, 2017
Copy link
Contributor

@WickedShell WickedShell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This came up on the dev call today. I think I missed reviewing the changes before now (sorry about that).

Given that Paul's happy with a LPF outside of the EKF for this slowly slewing the baro altitude to match the GPS altitude I think we can rework this to do that. However what is presented here is not the correct approach.

It's updating the offset based on the copter's altitude target, rather then it's current GPS altitude, which means that it's always slowly slewing towards the demand altitude, which would show up during an extended climb for example where the desired altitude was always 7 meters above the current position.

This needs to be reworked to only be filtering the baro altitude against the reported GPS altitude (and only when the GPS unit has a vertical accuracy and it is below a threshold value) should the filter be updated.

This would need to be based around the altitude relative to the EKF origin on copter, and relative to the to home on plane.

A couple of other collected comments: I'm not sure alt_offset is the right place to be accumulating the result, it has a couple of problems: The user can modify it, the modified values aren't being reported to the user, which means that if the user wants to adjust this inflight they messed up the baro compensation.

If you want to rework this to instead be based around just the GPS altitude that would be great, otherwise this is on @rmackay9 and my schedules to try and take a look at getting reworked and in in the near future.

@hsteinhaus
Copy link
Contributor Author

hsteinhaus commented Apr 11, 2017

@WickedShell

It's updating the offset based on the copter's altitude target, rather then it's current GPS altitude, which > means that it's always slowly slewing towards the demand altitude

I am not sure if I understand this statement correctly - the altitude already slews towards gps_location().alt .The alt target is only used to ignore segments of the flight where the alt target is not constant, i.e. after the pilot or the mission has requested alt changes (by resetting the LPF on every alt target change). This restriction could probably be relaxed, but I do not see any benefit for the given purpose of the PR.

*/
void Copter::barometer_adjust(void)
{
barometer.update_alt_target(pos_control->get_alt_target()*0.01f);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

watch the alt target to prevent spoiling the LPF with a moving alt target

@@ -557,6 +568,7 @@ void Copter::update_GPS(void)
#endif
}
}
barometer.update_gps_alt(float(gps.location().alt)*0.01f);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update the LPF with GPS altitude (not alt target!)

@WickedShell
Copy link
Contributor

Why do you need to take into account the altitude target changing? You are trying to slew the baro to the GPS which will always be changing? The need for the altitude target to be ingested at all feels very incorrect.

@hsteinhaus
Copy link
Contributor Author

hsteinhaus commented Apr 12, 2017

The (infinite response) LPF is lagging behind for a minute or more, so I guess it is the best choice to do a clean restart if the target altitude has changed.

May be there are other possible impementations, e.g. based on filtering altitude deltas instead of absolute altitudes, but the one submitted in this PR was the most obvious one that fulfills my requirements: to cancel out the baro drift for long (1 hour) constant-alt auto missions or long static loiters.

But even when looking on deltas, I guess the (huge!) phase offset caused by the LPF needs extra care in case of alt changes. Maybe @priseborough can give advice here on the theoretical aspects?

@hsteinhaus
Copy link
Contributor Author

fixed whitespace

@tridge
Copy link
Contributor

tridge commented Apr 18, 2017

I don't understand why the barometer sensor library ever should need to know or care about the altitude target. It's mixing up inputs and outputs. We can't have loops in the sensors -> control path in the code

@priseborough
Copy link
Contributor

I have a few comments:

  1. We should be using the term 'reference', not 'target' to avoid confusion with the altitude target used by control loops.

  2. The calculation of the baro drift correction should perform the following processing order:
    a) Calculate the error between the reference and baro alt
    b) Clamped the magnitude of the error to prevent large spikes driving downstream IIR filters
    c) Apply an IIR LPF to the error using ADJ_TC_DEFAULT
    d) Rate limit the filtered error using ADJ_RATE_DEFAULT to calculate the correction

  3. The datum used to define the reference altitude needs to be clearly stated - is it home or sea level?

  4. The drift correction should not start start updating offset until the GPS vertical accuracy meets a prescribed minimum

  5. The algorithm should be able to handle the case here GPS lock is gained in-flight and should not result in a step in baro alt used by the AHRS and EKF libraries. This requires the LPF to be applied to the error, not the reference altitude

@tridge
Copy link
Contributor

tridge commented Apr 18, 2017

@priseborough that sounds like a good plan, thanks Paul!

@EShamaev
Copy link
Member

@hsteinhaus Holger, please advice if you can make requested changes. I was planning to implement the same algorithm, so if by any chance you are not willing to finish this, I can take over this PR if you do not mind.

@priseborough
Copy link
Contributor

I had forgotten there was exisiting functionality in the EKF's which adjusted origin height using a Bayes filter, however it effectively stopped updating after about a minute due to 1cm precision in the origin height. I am working on a branch that improves the calculation and provides parameter control.

https://github.com/priseborough/ardupilot/tree/pr-ekfOriginHeightEst

@rmackay9
Copy link
Contributor

I think that @priseborough's work is complementary to what @EShamaev is offering to work on. So Paul will allow the current compensation in the EKF (which adjusts the EKF-origin down so that the Baro and GPS altitudes match) to be turned off and then we can add a Baro-compensation feature outside the EKF to instead adjust the baro towards the GPS.

That's my guess on how we can proceed but we could create a small chat to clear that up if necessary.

@hsteinhaus
Copy link
Contributor Author

Hi guys,

I am perfectly fine with anybody stepping in here, as I am rather busy with other things currently. The approach in this PR was to share back some kind of least effort solution keeping the vehicle roughly on track, as the stock ArduCopter firmware would probably crash into ground due to the baro drift when doing longer low altitude surveys (1 hour @ 30m).

@priseborough If I understand your changes correctly, I only have to set OGN_HGT_MASK to 5 and there should be no more long time drift after applying these two changes (04716d2 and 56d31f9) ?

@EShamaev
Copy link
Member

Version 2 is here: #6228

@magicrub
Copy link
Contributor

If there's a new PR, should we close this one?

@EShamaev
Copy link
Member

Maybe it should be open for some time for reference?

@magicrub
Copy link
Contributor

closing it doesn't make it disappear. It's referenced in your new PR (thank you!) so it sounds like this one should not be considered "open"

@priseborough
Copy link
Contributor

@hsteinhaus The local position reported by the EKF is not corrected, regardless of the parameter setting, however if you set the parameter to 7 (the default) then the origin height reported by the EKF will be adjusted. However unless the copter height controller is using the origin height in it's calculations, that will not help.

@EShamaev
Copy link
Member

My PR based on this seems to be working. More tests are needed, but I agree that this one can be closed.

@EShamaev EShamaev closed this May 11, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants