-
Notifications
You must be signed in to change notification settings - Fork 151
Deepanshu/maximum arming angle #198
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
base: master
Are you sure you want to change the base?
Changes from 2 commits
00e9e59
e435227
e031996
ec794df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,7 @@ | ||
| #include "Control/Actuator.h" | ||
| #include "Utils/Math.hpp" | ||
| #include <algorithm> | ||
| #include <cmath> | ||
|
|
||
| namespace Espfc::Control { | ||
|
|
||
|
|
@@ -96,6 +98,19 @@ void Actuator::updateArmingDisabled() | |
| _model.setArmingDisabled(ARMING_DISABLED_CALIBRATING, _model.calibrationActive()); | ||
| _model.setArmingDisabled(ARMING_DISABLED_MOTOR_PROTOCOL, _model.config.output.protocol == ESC_PROTOCOL_DISABLED); | ||
| _model.setArmingDisabled(ARMING_DISABLED_REBOOT_REQUIRED, _model.state.mode.rescueConfigMode == RESCUE_CONFIG_ACTIVE); | ||
|
|
||
| // Check small angle - prevent arming if tilted beyond configured angle | ||
| if(_model.config.arming.smallAngle < 180 && _model.accelActive()) | ||
| { | ||
| const float maxTiltRad = Utils::toRad(_model.config.arming.smallAngle); | ||
| const float currentTilt = std::max(std::abs(_model.state.attitude.euler[AXIS_PITCH]), | ||
| std::abs(_model.state.attitude.euler[AXIS_ROLL])); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. technically correct formula should be
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have used the approach that you suggested but the tilt calculation using trigonometric functions (acosf, cosf) is computationally more expensive than the previous max(abs(pitch), abs(roll)) approach. This code runs in the arming check path which may execute frequently. Is the increased accuracy justifies the performance cost ?
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right, I'm still wondering if your initial solution will be sufficient. Although the actual solution is more computationally complex, this fragment is only executed 50 times per second. The total impact can be seen in the CLI by entering the "stats" command. The result will then be in the "rx_a:" line. Of course, we can still ask the AI to propose an intermediate solution. Give me some more time to think about it.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure |
||
| _model.setArmingDisabled(ARMING_DISABLED_ANGLE, currentTilt > maxTiltRad); | ||
| } | ||
| else | ||
| { | ||
| _model.setArmingDisabled(ARMING_DISABLED_ANGLE, false); | ||
| } | ||
| if(_model.isFeatureActive(FEATURE_GPS)) | ||
| { | ||
| _model.setArmingDisabled(ARMING_DISABLED_GPS, !_model.state.gps.present || _model.state.gps.numSats < _model.config.gps.minSats); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -104,7 +104,7 @@ void Fusion::experimentalFusion() | |
|
|
||
| void Fusion::simpleFusion() | ||
| { | ||
| _model.state.pose = _model.state.accel.adc.accelToEuler(); | ||
| _model.state.pose = getAccelEulerWithTrim(); | ||
| _model.state.attitude.euler.x = _model.state.pose.x; | ||
| _model.state.attitude.euler.y = _model.state.pose.y; | ||
| _model.state.attitude.euler.z += _model.state.gyro.timer.intervalf * _model.state.gyro.adc.z; | ||
|
|
@@ -114,7 +114,7 @@ void Fusion::simpleFusion() | |
|
|
||
| void Fusion::kalmanFusion() | ||
| { | ||
| _model.state.pose = _model.state.accel.adc.accelToEuler(); | ||
| _model.state.pose = getAccelEulerWithTrim(); | ||
| _model.state.pose.z = _model.state.attitude.euler.z; | ||
| const float dt = _model.state.gyro.timer.intervalf; | ||
| for(size_t i = 0; i < 3; i++) | ||
|
|
@@ -128,7 +128,7 @@ void Fusion::kalmanFusion() | |
|
|
||
| void Fusion::complementaryFusion() | ||
| { | ||
| _model.state.pose = _model.state.accel.adc.accelToEuler(); | ||
| _model.state.pose = getAccelEulerWithTrim(); | ||
| _model.state.pose.z = _model.state.attitude.euler.z; | ||
| const float dt = _model.state.gyro.timer.intervalf; | ||
| const float alpha = 0.002f; | ||
|
|
@@ -147,7 +147,7 @@ void Fusion::complementaryFusionOld() | |
| { | ||
| const float alpha = 0.01f; | ||
| const float dt = _model.state.gyro.timer.intervalf; | ||
| _model.state.pose = _model.state.accel.adc.accelToEuler(); | ||
| _model.state.pose = getAccelEulerWithTrim(); | ||
| _model.state.pose.z = _model.state.attitude.euler.z; | ||
| _model.state.attitude.euler = (_model.state.attitude.euler + _model.state.gyro.adc * dt) * (1.f - alpha) + _model.state.pose * alpha; | ||
| _model.state.attitude.quaternion = _model.state.attitude.euler.eulerToQuaternion(); | ||
|
|
@@ -213,9 +213,27 @@ void Fusion::rtqfFusion() | |
| _model.state.attitude.euler.eulerFromQuaternion(fusionQPose); | ||
| } | ||
|
|
||
| VectorFloat Fusion::getAccelEulerWithTrim() const | ||
| { | ||
| VectorFloat euler = _model.state.accel.adc.accelToEuler(); | ||
| // Euler ordering and aircraft axes mapping: | ||
| // euler.x -> roll (rotation about body X) | ||
| // euler.y -> pitch (rotation about body Y) | ||
| // euler.z -> yaw (rotation about body Z) | ||
| // | ||
| // Accelerometer trim values are stored in 0.1 degree units: | ||
| // trim[0] = pitch trim, applied to euler.y | ||
| // trim[1] = roll trim, applied to euler.x | ||
| // | ||
| // Convert trim from 0.1 degrees to radians and apply. | ||
| euler.y += _model.config.accel.trim[0] * 0.1f * (PI / 180.0f); // pitch trim | ||
| euler.x += _model.config.accel.trim[1] * 0.1f * (PI / 180.0f); // roll trim | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This solution is not correct. It'll cause that euler angles are out of allowed range for AHRS algorithms. It may result in very bad behaviour in some specific attitude. My recommendation is to build rotation matrix and apply rotation to accel readings somehere in AccelSensor class.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, sure I'll try to build rotation matrix then. thanks |
||
| return euler; | ||
| } | ||
|
|
||
| void Fusion::updatePoseFromAccelMag() | ||
| { | ||
| _model.state.pose = _model.state.accel.adc.accelToEuler(); | ||
| _model.state.pose = getAccelEulerWithTrim(); | ||
| //_model.state.accelPose = _model.state.pose; | ||
|
|
||
| if(_model.magActive()) | ||
|
|
@@ -274,7 +292,7 @@ void Fusion::lerpFusion() | |
| { | ||
| float correctionAlpha = 0.001f; // 0 - 1 => gyro - accel | ||
|
|
||
| _model.state.accelPose = _model.state.accel.adc.accelToEuler(); | ||
| _model.state.accelPose = getAccelEulerWithTrim(); | ||
| _model.state.accelPoseQ = _model.state.accelPose.eulerToQuaternion(); | ||
|
|
||
| if(_model.magActive()) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not add fields that are not handled in any way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah sorry, my bad. Reverted