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

EKF2 fix skipping magnetometer axes upon other axis failure #13921

Merged
merged 1 commit into from
May 20, 2020

Conversation

priseborough
Copy link
Contributor

Addresses #13912

Ensures that if fusion checks for an axis fails, fusion will not be performed for all axes. The only exceptions are if the failure is at the covariance update step due to a badly conditioned covariance matrix, in which case fusion for that and not completed axes will be aborted, however this is an extremely rare occurrence.

Ensure that if fusion checks for an axis fails, fusion will not be perfomred for all axes.
@rmackay9
Copy link
Contributor

rmackay9 commented Apr 7, 2020

@peterbarker is going to review this PR

@rmackay9
Copy link
Contributor

ping again for @peterbarker to review

Copy link
Contributor

@khancyr khancyr left a comment

Choose a reason for hiding this comment

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

Code review only, I haven't test yet on a failure

We don't have copy-paste error. It is now done similary to EKF3, and make me wonder why we trying to do the fusion each axis twice on EKF3 since

for (mag_state.obsIndex = 0; mag_state.obsIndex <= 2; mag_state.obsIndex++) 

is not remove on SelectMagFusion() like this patch does ?

Anyway,
The variable initialisation on start of FuseMagnetometer could be simplified. But this put forward a difference with the previous code.
Previously, we were doing axis X fusion with stateStruct data and other axis with mag_state data. Now we are using only stateStruct data. Is that the correct behavior ? If that is correct, we should create and initialize the date directly with stateStruct and not mag_state. The same behavior exist in EKF3.

All the perf checker were removed.

before : we used a loop for H_MAG setting to 0, we are now using a memset. The use is correct.
Then we are doing a loop for the Jabcobian calculation for each axis and at the end of each axis setting magFusePerformed=true. This is still necessary to correctly calculate the fusion health and record which axis is going wrong.

we zero the attitude error state and apply it to rotate the stateStruct.quat (L693) that seems unnecessary and not done in EKF3

@khancyr
Copy link
Contributor

khancyr commented May 4, 2020

my conserns about EKF3 issues are fixed in #13906

@priseborough priseborough requested a review from tridge May 13, 2020 06:17
@priseborough
Copy link
Contributor Author

@peterbarker bump

@peterbarker
Copy link
Contributor

The variable initialisation on start of FuseMagnetometer could be simplified. But this put forward a difference with the previous code.
Previously, we were doing axis X fusion with stateStruct data and other axis with mag_state data. Now we are using only stateStruct data. Is that the correct behavior ? If that is correct, we should create and initialize the date directly with stateStruct and not mag_state. The same behavior exist in EKF3.

I don't think that's correct. The declaration sets up a reference; from q0 to the mag_state. Further assignments to q0 change mag_state Previously these were initialised on the first call to FuseMagnetometer by looking at obsIndex. Now we're doing the looping within FuseMagnetometer this can be moved up outside that nasty check.

The critical thing here is that we are initialising mag_state here - q0 and friends are simply aliases for mag_state. i.e. all calculations are done with magstate data, it just happens on the first axis the magstate data is the same as the statestruct data.

Looking further, we could eliminate mag_state in its entirety as a structure and as state. It is only ever used within that one function. That would save us 100 bytes of RAM per core.

}
}

// fuse the three magnetometer componenents using sequential fusion of each axis
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// fuse the three magnetometer componenents using sequential fusion of each axis
// fuse the three magnetometer components using sequential fusion of each axis

... or just remove the comment entirely as it now assumes it knows what that function does, meaning it can get out-of-date.

if (obsIndex == 0)
{
// calculate observation jacobians
memset(&H_MAG, 0, sizeof(H_MAG));
Copy link
Contributor

Choose a reason for hiding this comment

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

Future cleanup could make H_MAG declared within the for loop, which would remove the need for getting these memsets correct.

Copy link
Contributor

Choose a reason for hiding this comment

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

the curly bracket should be on line 447..

hal.util->perf_begin(_perf_test[5]);
// set flags to indicate to other processes that fusion has been performed
// this can be used by other fusion processes to avoid fusing on the same frame as this expensive step
magFusePerformed = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Future cleanup can move this assignment elsewhere; there's no reason to do it on each axis.

@tridge
Copy link
Contributor

tridge commented May 19, 2020

needs testing with replay

@rmackay9
Copy link
Contributor

We generally agreed on the call that this can go in but Tridge is keen that we run it through replay before merging.

@peterbarker
Copy link
Contributor

To be clear, I volunteered to run this through Replay and merge it if nothing unexpected happens.

@tridge
Copy link
Contributor

tridge commented May 19, 2020

To be clear, I volunteered to run this through Replay and merge it if nothing unexpected happens.

thanks Peter!
can you also point me at the replay branch?

@peterbarker
Copy link
Contributor

@tridge #13885

@peterbarker
Copy link
Contributor

I've now run this through Replay on a lots of logs - where .

I haven't seen it produce anything but byte-for-byte identical output logfiles.

@peterbarker peterbarker merged commit af19fea into ArduPilot:master May 20, 2020
@peterbarker
Copy link
Contributor

Merged, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Copter 4.0 backports
Awaiting triage
Development

Successfully merging this pull request may close these issues.

None yet

6 participants