Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b61029f
Modify Pixhawk6C-bdshot default parameter list
akshar-airbound Dec 30, 2025
1206984
Handle gimbal lock singularity specifically for pitch in ahrs view
botmayank Jan 7, 2026
d6d469a
Update version to rc5
botmayank Jan 7, 2026
9bae2ea
Add simple ahrs pitch based check to correct att pitch beyond 90
botmayank Jan 7, 2026
b9be9bc
Add rot matrix based check for nose down belly up/down
botmayank Jan 8, 2026
be8846e
Swap pitch corrections in ahrs view
botmayank Jan 8, 2026
46b98b4
Add logging for ahrs view compensation
botmayank Jan 9, 2026
439dcd3
Fix logging of pitch before and after compensation
botmayank Jan 9, 2026
b42218b
Add logging for att target axis angle
botmayank Jan 9, 2026
de2de56
Add logging of att body and error quat as axis angle
botmayank Jan 9, 2026
6a0e179
Add flags for belly up/down and nose down in logs
botmayank Jan 9, 2026
5185062
Update version to rc6
botmayank Jan 9, 2026
cd141fd
Change version to 4.5.7.3 rc1
botmayank Jan 10, 2026
717e0c5
Change mode check for landing phase for doors script
botmayank Jan 15, 2026
8f5952c
Check valid landing mission commands
botmayank Jan 16, 2026
57a78d7
Add check for vtol land descent from quadplane
botmayank Jan 21, 2026
93bb8d2
Force doors open under takeoff alt_trig_m and don't check for transit…
botmayank Jan 21, 2026
8d25f52
Add a landing latch flag to only trigger doors basis modes
botmayank Jan 21, 2026
3642cad
Initialize servo pwm open close based on specific defaults
botmayank Jan 21, 2026
07200d7
Update version to 4.5.7.2 hf1
botmayank Jan 21, 2026
a81a5c6
Update version to v4.5.7.2 - hf1
botmayank Jan 21, 2026
990981f
Merge branch 'pr-fix_doors_script' into pr-add_att_logging
botmayank Jan 21, 2026
305ebb6
Fix vtol flight check logic basis latch
botmayank Jan 21, 2026
7615a90
Add global override param for doors auto logic
botmayank Jan 21, 2026
102f425
Fix num params for door script
botmayank Jan 21, 2026
e30dab2
Fix docstring for ATPC logging
botmayank Jan 22, 2026
befdd50
Improve tailsitter transition by adding heading alignment, timeout sa…
Tarun24-airbound Jan 28, 2026
aedaa74
Resolve belly flop and rough transition issues with improved tailsitt…
Tarun24-airbound Jan 28, 2026
ca70950
Disable weathervane and lock climb rate during transition alignment
Tarun24-airbound Jan 30, 2026
644d922
Implement internal yaw angle controller, replacing manual P-gain control
Tarun24-airbound Feb 4, 2026
bdc4ae9
Fix weathervane issue and update version to Auto Yaw Align
Tarun24-airbound Feb 4, 2026
96dd024
Add version name (Auto Yaw Align)
Tarun24-airbound Feb 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions ArduPlane/Log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ void Plane::Log_Write_Attitude(void)
quadplane.attitude_control->get_attitude_target_quat().to_euler(targets.x, targets.y, targets.z);
targets *= degrees(100.0f);
quadplane.ahrs_view->Write_AttitudeView(targets);

// Logging for att target quat to axis angle, error quat to axis angle
Vector3f att_body_axis_ang, att_tar_axis_ang, att_err_axis_ang;
quadplane.attitude_control->get_attitude_target_quat().to_axis_angle(att_tar_axis_ang);
quadplane.attitude_control->get_attitude_body_quat().to_axis_angle(att_body_axis_ang);
quadplane.attitude_control->get_attitude_error_quat().to_axis_angle(att_err_axis_ang);

quadplane.ahrs_view->Write_Att_Tar_Axis_Ang(att_tar_axis_ang);
quadplane.ahrs_view->Write_Att_Body_Axis_Ang(att_body_axis_ang);
quadplane.ahrs_view->Write_Att_Err_Axis_Ang(att_err_axis_ang);

quadplane.ahrs_view->Write_AttitudePitchCompensation();
} else
#endif
{
Expand Down
133 changes: 133 additions & 0 deletions ArduPlane/tailsitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,139 @@ void Tailsitter_Transition::update()
switch (transition_state) {

case TRANSITION_ANGLE_WAIT_FW: {

const uint32_t now_ = AP_HAL::millis();
// -----------------------------------------------------------
// 1. INITIALIZATION
// -----------------------------------------------------------
quadplane.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);

// -----------------------------------------------------------
// 2. TAILSITTER HEADING ALIGNMENT & WAIT
// -----------------------------------------------------------
if (quadplane.tailsitter.enabled()) {

// Constants
const int32_t ALIGN_TOLERANCE_CD = 1000; // 10.0 degrees
const float MAX_SPIN_RATE_DEG = 3.0f; // Max yaw rate allowed
const uint32_t ALIGN_PHASE_LIMIT_MS = 10000; // 10s Total Timeout
const uint32_t WAIT_DELAY_MS = 2000; // 2s Wait

// Static Variables (State Tracking)
static uint32_t align_phase_start_ms = 0;
static uint32_t alignment_done_ms = 0;
static uint32_t last_run_ms = 0;
static uint32_t last_log_ms = 0;
// NEW: One-Shot Flag to prevent infinite loops
static bool alignment_completed_for_this_flight = false;

// --- DETECT NEW FLIGHT/TRANSITION ENTRY ---
// If this function hasn't run for >200ms, assume it's a new attempt.
if (now_ - last_run_ms > 200) {
align_phase_start_ms = now_;
alignment_done_ms = 0;
last_log_ms = 0;
alignment_completed_for_this_flight = false; // Reset flag for new transition
}
last_run_ms = now_;

// Check Validity & Only run if we haven't finished aligning yet
bool should_run_alignment = !alignment_completed_for_this_flight &&
(plane.control_mode == &plane.mode_auto || plane.control_mode == &plane.mode_guided) &&
(plane.nav_controller != nullptr);

if (should_run_alignment) {
// Disable weathervane during alignment
if (quadplane.weathervane != nullptr) {
quadplane.weathervane->allow_weathervaning(false);
}

int32_t target_bearing_cd = plane.nav_controller->target_bearing_cd();
int32_t current_yaw_cd = quadplane.ahrs.yaw_sensor;
int32_t error_cd = wrap_180_cd(target_bearing_cd - current_yaw_cd);
Vector3f gyro = quadplane.ahrs.get_gyro();
float yaw_rate_deg = degrees(gyro.z);

// LOGIC: Are we aligned right now?
bool is_aligned = (abs(error_cd) <= ALIGN_TOLERANCE_CD) && (abs(yaw_rate_deg) <= MAX_SPIN_RATE_DEG);

// TIMER LOGIC
if (is_aligned) {
if (alignment_done_ms == 0) alignment_done_ms = now_;
} else {
alignment_done_ms = 0; // Reset if we drift out
}

// EXIT CRITERIA
bool wait_complete = (alignment_done_ms != 0) && (now_ - alignment_done_ms >= WAIT_DELAY_MS);
bool timeout_expired = (now_ - align_phase_start_ms >= ALIGN_PHASE_LIMIT_MS);

Comment on lines +924 to +972
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Start the alignment timeout only when alignment is actually active.
align_phase_start_ms is set on entry regardless of should_run_alignment. If the vehicle enters TRANSITION_ANGLE_WAIT_FW in a non-AUTO/GUIDED mode and later switches into AUTO/GUIDED, the timeout can already be expired, causing alignment to be skipped immediately. Consider arming the timer when alignment becomes active (or clearing it while inactive).

💡 One way to gate the timer
-            // --- DETECT NEW FLIGHT/TRANSITION ENTRY ---
-            // If this function hasn't run for >200ms, assume it's a new attempt.
+            // --- DETECT NEW FLIGHT/TRANSITION ENTRY ---
             if (now_ - last_run_ms > 200) {
                 align_phase_start_ms = now_;
                 alignment_done_ms = 0;
                 last_log_ms = 0;
                 alignment_completed_for_this_flight = false; // Reset flag for new transition
             }
             last_run_ms = now_;

             // Check Validity & Only run if we haven't finished aligning yet
             bool should_run_alignment = !alignment_completed_for_this_flight &&
                                         (plane.control_mode == &plane.mode_auto || plane.control_mode == &plane.mode_guided) &&
                                         (plane.nav_controller != nullptr);
+
+            if (!should_run_alignment) {
+                align_phase_start_ms = 0;
+                alignment_done_ms = 0;
+            } else if (align_phase_start_ms == 0) {
+                align_phase_start_ms = now_;
+            }
🤖 Prompt for AI Agents
In `@ArduPlane/tailsitter.cpp` around lines 924 - 972, The timeout start
(align_phase_start_ms) is set unconditionally on detecting a "new attempt" which
can expire before alignment actually becomes active; change the logic so
align_phase_start_ms is only initialized when alignment is actually active
(should_run_alignment == true) — e.g., on the new-attempt branch do not set
align_phase_start_ms unconditionally but only set it when should_run_alignment
is true (or set it to 0/clear it when should_run_alignment is false), and ensure
you detect the transition from inactive->active to start the timer (use
last_run_ms and alignment_completed_for_this_flight to gate this), updating the
places that use align_phase_start_ms, timeout_expired, and WAIT_DELAY_MS
accordingly.

// --- BLOCKING CONTROL LOOP ---
// Run this ONLY if we are NOT done waiting AND haven't timed out
if (!wait_complete && !timeout_expired) {

// Log (1Hz)
if (now_ - last_log_ms > 1000) {
if (is_aligned) {
float remaining = (WAIT_DELAY_MS - (now_ - alignment_done_ms)) * 0.001f;
gcs().send_text(MAV_SEVERITY_INFO, "Aligned. Waiting: %.1fs", (double)remaining);
} else {
gcs().send_text(MAV_SEVERITY_INFO, "Aligning: Err %.1f", error_cd * 0.01f);
}
last_log_ms = now_;
}
//Force zero climb rate (Altitude Hold)
quadplane.pos_control->set_pos_target_z_from_climb_rate_cm(0.0f);

// Control
quadplane.pos_control->update_z_controller();
Copy link

@atharva-airbound atharva-airbound Feb 9, 2026

Choose a reason for hiding this comment

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

We are manually calling update_z_controller() here but there is a comment in quadplane.cpp mentioning this shouldn't be done during transition

// never run Z controller in tailsitter transtion

Here is a relevant PR from when the comment was added: ArduPilot#19286
Needs investigation.

Choose a reason for hiding this comment

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

Can try calling hold_hover(0) instead of running the position controllers to get the roll and pitch setpoints.

Will try this when I have time.

quadplane.pos_control->update_xy_controller();
quadplane.attitude_control->input_euler_angle_roll_pitch_yaw(
quadplane.pos_control->get_roll_cd(),
quadplane.pos_control->get_pitch_cd(),
(float)target_bearing_cd,
true
);

quadplane.motors_output();
set_last_fw_pitch(); // Keep tracking pitch so we don't snap later
return; // BLOCK TRANSITION
}

// --- HANDOVER LOGIC (Runs ONCE when done) ---

if (timeout_expired) {
gcs().send_text(MAV_SEVERITY_WARNING, "Align Timeout: Proceeding");
} else {
gcs().send_text(MAV_SEVERITY_INFO, "Alignment Complete: Transitioning");
}

// 1. Mark as complete so we NEVER enter this 'if' block again for this flight
alignment_completed_for_this_flight = true;

// 2. Reset Standard Transition Timer to now
fw_transition_start_ms = now_;

// 3. Reset Integrators and Pitch Target
quadplane.attitude_control->reset_rate_controller_I_terms();
plane.nav_pitch_cd = constrain_float(quadplane.ahrs.pitch_sensor, -8500, 8500);
plane.nav_roll_cd = 0;
set_last_fw_pitch();
// --- RE-ENABLE WEATHERVANE AFTER ALIGNMENT ---
if (quadplane.weathervane != nullptr) {
quadplane.weathervane->allow_weathervaning(true);
}
}
else {
// --- ENSURE WEATHERVANE IS ENABLED WHEN NOT ALIGNING ---
if (quadplane.weathervane != nullptr) {
quadplane.weathervane->allow_weathervaning(true);
}
}
}

// Normal transition code continues here for non-tailsitters
// or after tailsitter alignment completes...
if (tailsitter.transition_fw_complete()) {
transition_state = TRANSITION_DONE;
if (plane.arming.is_armed_and_safety_off()) {
Expand Down
2 changes: 1 addition & 1 deletion ArduPlane/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#include "ap_version.h"

#define THISFIRMWARE "Airbound ArduPlane V4.5.7.2"
#define THISFIRMWARE "Airbound ArduPlane V4.5.7.2 - hf1 (Auto Yaw Align)"

// the following line is parsed by the autotest scripts
#define FIRMWARE_VERSION 4,5,7,FIRMWARE_VERSION_TYPE_DEV
Expand Down
1 change: 1 addition & 0 deletions libraries/AC_AttitudeControl/AC_AttitudeControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ void AC_AttitudeControl::attitude_controller_run_quat()

// Record error to handle EKF resets
_attitude_ang_error = attitude_body.inverse() * _attitude_target;
_attitude_body = attitude_body;
}

// thrust_heading_rotation_angles - calculates two ordered rotations to move the attitude_body quaternion to the attitude_target quaternion.
Expand Down
9 changes: 9 additions & 0 deletions libraries/AC_AttitudeControl/AC_AttitudeControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ class AC_AttitudeControl {
// Return the angle between the target thrust vector and the current thrust vector.
float get_att_error_angle_deg() const { return degrees(_thrust_error_angle); }

// Return the body-to-NED error attitude used by the quadplane-specific attitude control input methods
Quaternion get_attitude_error_quat() const { return _attitude_ang_error; }

// Return the body-to-NED attitude used by the quadplane-specific attitude control input methods
Quaternion get_attitude_body_quat() const { return _attitude_body; }

Comment on lines +229 to +234
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

fd -t f "AC_AttitudeControl" | head -20

Repository: AirboundInc/ardupilot

Length of output: 734


🏁 Script executed:

find . -name "*.h" -o -name "*.cpp" | xargs grep -l "AC_AttitudeControl" | grep -E "AC_AttitudeControl\.(h|cpp)$"

Repository: AirboundInc/ardupilot

Length of output: 170


🏁 Script executed:

git ls-files | grep -i "attitude" | grep -E "\.(h|cpp)$"

Repository: AirboundInc/ardupilot

Length of output: 1220


🏁 Script executed:

wc -l libraries/AC_AttitudeControl/AC_AttitudeControl.h

Repository: AirboundInc/ardupilot

Length of output: 118


🏁 Script executed:

sed -n '220,240p' libraries/AC_AttitudeControl/AC_AttitudeControl.h

Repository: AirboundInc/ardupilot

Length of output: 1262


🏁 Script executed:

sed -n '500,520p' libraries/AC_AttitudeControl/AC_AttitudeControl.h

Repository: AirboundInc/ardupilot

Length of output: 1017


🏁 Script executed:

grep -n "AC_AttitudeControl::AC_AttitudeControl" libraries/AC_AttitudeControl/AC_AttitudeControl.cpp | head -5

Repository: AirboundInc/ardupilot

Length of output: 47


🏁 Script executed:

grep -n "relax_attitude_controllers" libraries/AC_AttitudeControl/AC_AttitudeControl.cpp

Repository: AirboundInc/ardupilot

Length of output: 122


🏁 Script executed:

grep -n "attitude_controller_run_quat" libraries/AC_AttitudeControl/AC_AttitudeControl.cpp

Repository: AirboundInc/ardupilot

Length of output: 561


🏁 Script executed:

sed -n '168,190p' libraries/AC_AttitudeControl/AC_AttitudeControl.cpp

Repository: AirboundInc/ardupilot

Length of output: 840


🏁 Script executed:

sed -n '708,750p' libraries/AC_AttitudeControl/AC_AttitudeControl.cpp

Repository: AirboundInc/ardupilot

Length of output: 2304


🏁 Script executed:

grep -n "_attitude_body" libraries/AC_AttitudeControl/AC_AttitudeControl.cpp | head -20

Repository: AirboundInc/ardupilot

Length of output: 104


🏁 Script executed:

sed -n '750,760p' libraries/AC_AttitudeControl/AC_AttitudeControl.cpp

Repository: AirboundInc/ardupilot

Length of output: 515


🏁 Script executed:

grep -n "get_attitude_body_quat\|get_attitude_target_quat\|get_attitude_error_quat" libraries/AC_AttitudeControl/AC_AttitudeControl.cpp

Repository: AirboundInc/ardupilot

Length of output: 47


🏁 Script executed:

grep -rn "get_attitude_body_quat" --include="*.cpp" --include="*.h" | head -20

Repository: AirboundInc/ardupilot

Length of output: 307


🏁 Script executed:

grep -n "AC_AttitudeControl::" libraries/AC_AttitudeControl/AC_AttitudeControl.cpp | grep -E "(constructor|AC_AttitudeControl\()" | head -5

Repository: AirboundInc/ardupilot

Length of output: 47


🏁 Script executed:

sed -n '1,100p' libraries/AC_AttitudeControl/AC_AttitudeControl.cpp | grep -A 20 "AC_AttitudeControl::"

Repository: AirboundInc/ardupilot

Length of output: 907


🏁 Script executed:

cat libraries/AC_AttitudeControl/AC_AttitudeControl.h | grep -A 5 "class AC_AttitudeControl"

Repository: AirboundInc/ardupilot

Length of output: 570


🏁 Script executed:

grep -n "Quaternion.*initialise\|Quaternion()" libraries/AC_AttitudeControl/AC_AttitudeControl.cpp | head -10

Repository: AirboundInc/ardupilot

Length of output: 47


🏁 Script executed:

sed -n '1,50p' libraries/AC_AttitudeControl/AC_AttitudeControl.cpp | grep -A 30 "AC_AttitudeControl::" | head -40

Repository: AirboundInc/ardupilot

Length of output: 1296


🏁 Script executed:

grep -n "AC_AttitudeControl.*{" libraries/AC_AttitudeControl/AC_AttitudeControl.h | head -5

Repository: AirboundInc/ardupilot

Length of output: 190


🏁 Script executed:

sed -n '1,100p' libraries/AC_AttitudeControl/AC_AttitudeControl.h | grep -A 50 "AC_AttitudeControl("

Repository: AirboundInc/ardupilot

Length of output: 2361


Initialize _attitude_body in relax_attitude_controllers() to ensure valid state before first use.

The getter get_attitude_body_quat() may be called before attitude_controller_run_quat() has executed (e.g., during early logging in startup), but _attitude_body is only assigned within attitude_controller_run_quat() at line 756. Unlike _attitude_target and _attitude_ang_error, which are explicitly initialized in relax_attitude_controllers(), _attitude_body is left uninitialized. The getter is already in use (ArduPlane/Log.cpp:27) and could return an uninitialized quaternion.

Add _attitude_body = _attitude_target; in relax_attitude_controllers() after line 172 to match the initialization pattern of other attitude members:

Suggested initialization
 void AC_AttitudeControl::relax_attitude_controllers()
 {
     // Initialize the attitude variables to the current attitude
     _ahrs.get_quat_body_to_ned(_attitude_target);
     _attitude_target.to_euler(_euler_angle_target);
     _attitude_ang_error.initialise();
+    _attitude_body = _attitude_target;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Return the body-to-NED error attitude used by the quadplane-specific attitude control input methods
Quaternion get_attitude_error_quat() const { return _attitude_ang_error; }
// Return the body-to-NED attitude used by the quadplane-specific attitude control input methods
Quaternion get_attitude_body_quat() const { return _attitude_body; }
void AC_AttitudeControl::relax_attitude_controllers()
{
// Initialize the attitude variables to the current attitude
_ahrs.get_quat_body_to_ned(_attitude_target);
_attitude_target.to_euler(_euler_angle_target);
_attitude_ang_error.initialise();
_attitude_body = _attitude_target;
}
🤖 Prompt for AI Agents
In `@libraries/AC_AttitudeControl/AC_AttitudeControl.h` around lines 229 - 234,
relax_attitude_controllers() currently initializes _attitude_target and
_attitude_ang_error but leaves _attitude_body uninitialized, which can cause
get_attitude_body_quat() to return garbage during early startup; update
relax_attitude_controllers() to set _attitude_body = _attitude_target (matching
the pattern used for _attitude_target and _attitude_ang_error) so _attitude_body
has a valid value before attitude_controller_run_quat() runs and before
get_attitude_body_quat() or logging uses it.

// Set x-axis angular velocity in centidegrees/s
void rate_bf_roll_target(float rate_cds) { _ang_vel_body.x = radians(rate_cds * 0.01f); }

Expand Down Expand Up @@ -498,6 +504,9 @@ class AC_AttitudeControl {
// This represents a quaternion attitude error in the body frame, used for inertial frame reset handling.
Quaternion _attitude_ang_error;

// This represents a quaternion attitude in the body frame
Quaternion _attitude_body;

// The angle between the target thrust vector and the current thrust vector.
float _thrust_angle;

Expand Down
54 changes: 54 additions & 0 deletions libraries/AP_AHRS/AP_AHRS_Logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,60 @@ void AP_AHRS_View::Write_AttitudeView(const Vector3f &targets) const
AP::logger().WriteBlock(&pkt, sizeof(pkt));
}

// Write an Attitude pitch compensation packet
void AP_AHRS_View::Write_AttitudePitchCompensation() const
{
const struct log_AttitudeViewCompensation pkt{
LOG_PACKET_HEADER_INIT(LOG_ATT_PIT_COMP_MSG),
time_us : AP_HAL::micros64(),
pitch : (int16_t)(degrees(pitch) * 100),
pitch_raw : (int16_t)(degrees(pitch_raw) * 100),
z_ned_z : z_ned.z,
x_ned_z : x_ned.z,
is_nose_down : (float)is_nose_down,
is_belly_up : (float)is_belly_up,
};
AP::logger().WriteBlock(&pkt, sizeof(pkt));
}

// Write attitude target axis angle
void AP_AHRS_View::Write_Att_Tar_Axis_Ang(Vector3f att_tar_axis_ang) const
{
const struct log_AttitudeTarAxisAng pkt{
LOG_PACKET_HEADER_INIT(LOG_ATT_TAR_AA_MSG),
time_us : AP_HAL::micros64(),
target_x : att_tar_axis_ang.x,
target_y : att_tar_axis_ang.y,
target_z : att_tar_axis_ang.z,
};
AP::logger().WriteBlock(&pkt, sizeof(pkt));
}

// Write attitude body axis angle
void AP_AHRS_View::Write_Att_Body_Axis_Ang(Vector3f att_body_axis_ang) const
{
const struct log_AttitudeBodyAxisAng pkt{
LOG_PACKET_HEADER_INIT(LOG_ATT_BOD_AA_MSG),
time_us : AP_HAL::micros64(),
body_x : att_body_axis_ang.x,
body_y : att_body_axis_ang.y,
body_z : att_body_axis_ang.z,
};
AP::logger().WriteBlock(&pkt, sizeof(pkt));
}

// Write attitude error axis angle
void AP_AHRS_View::Write_Att_Err_Axis_Ang(Vector3f att_err_axis_ang) const
{
const struct log_AttitudeErrAxisAng pkt{
LOG_PACKET_HEADER_INIT(LOG_ATT_ERR_AA_MSG),
time_us : AP_HAL::micros64(),
err_x : att_err_axis_ang.x,
err_y : att_err_axis_ang.y,
err_z : att_err_axis_ang.z,
};
AP::logger().WriteBlock(&pkt, sizeof(pkt));
}
// Write a rate packet
void AP_AHRS_View::Write_Rate(const AP_Motors &motors, const AC_AttitudeControl &attitude_control,
const AC_PosControl &pos_control) const
Expand Down
12 changes: 10 additions & 2 deletions libraries/AP_AHRS/AP_AHRS_View.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,31 @@ void AP_AHRS_View::update()

rot_body_to_ned.to_euler(&roll, &pitch, &yaw);

pitch_raw = pitch;

Vector3f z_body{0, 0, 1};
Vector3f x_body{1, 0, 0};
Vector3f z_ned = rot_body_to_ned * z_body;
Vector3f x_ned = rot_body_to_ned * x_body;

z_ned = rot_body_to_ned * z_body;
x_ned = rot_body_to_ned * x_body;

// compensate for going beyond +/- 90 degree in pitch
if(z_ned.z <= 0 ){
// Nose down below horizon
is_nose_down = true;
if(x_ned.z > 0.0f) {
// Belly down
pitch = -M_PI - pitch;
is_belly_up = false;
}
else {
// Belly up
pitch = M_PI - pitch;
is_belly_up = true;
}
} else {
is_nose_down = false;
is_belly_up = false;
}

roll_sensor = degrees(roll) * 100;
Expand Down
12 changes: 10 additions & 2 deletions libraries/AP_AHRS/AP_AHRS_View.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,17 +174,25 @@ class AP_AHRS_View
}

// Logging Functions
void Write_AttitudeView(const Vector3f &targets) const;
void Write_AttitudeView(const Vector3f &targets) const;
void Write_AttitudePitchCompensation(void) const;

void Write_Att_Tar_Axis_Ang(Vector3f att_tar_axis_ang) const;
void Write_Att_Body_Axis_Ang(Vector3f att_body_axis_ang) const;
void Write_Att_Err_Axis_Ang(Vector3f att_err_axis_ang) const;

void Write_Rate( const AP_Motors &motors, const AC_AttitudeControl &attitude_control,
const AC_PosControl &pos_control) const;

float roll;
float pitch;
float pitch, pitch_raw;
float yaw;
int32_t roll_sensor;
int32_t pitch_sensor;
int32_t yaw_sensor;

Vector3f z_ned, x_ned;
bool is_nose_down = false, is_belly_up = false;

// get current rotation
// note that this may not be the rotation were actually using, see _pitch_trim_deg
Expand Down
Loading
Loading