LCOV - code coverage report
Current view: top level - SITL - SIM_Calibration.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 63 84 75.0 %
Date: 2026-09-09 11:02:08 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2015-2016  Intel Corporation. All rights reserved.
       3             :  *
       4             :  * This file is free software: you can redistribute it and/or modify it
       5             :  * under the terms of the GNU General Public License as published by the
       6             :  * Free Software Foundation, either version 3 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * This file is distributed in the hope that it will be useful, but
      10             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      12             :  * See the GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License along
      15             :  * with this program.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : #include <assert.h>
      18             : 
      19             : #include <AP_Math/AP_Math.h>
      20             : 
      21             : #include "SIM_Calibration.h"
      22             : 
      23             : #define MAX_ANGULAR_SPEED (2 * M_PI)
      24             : 
      25             : #include <stdio.h>
      26             : 
      27          11 : SITL::Calibration::Calibration(const char *frame_str)
      28          11 :     : Aircraft(frame_str)
      29             : {
      30          11 :     mass = 1.5f;
      31          11 : }
      32             : 
      33     3481756 : void SITL::Calibration::update(const struct sitl_input &input)
      34             : {
      35     3481756 :     Vector3f rot_accel{0, 0, 0};
      36             : 
      37     3481756 :     float switcher_pwm = input.servos[4];
      38     3481756 :     if (switcher_pwm < 1100) {
      39      561094 :         _stop_control(input, rot_accel);
      40     2920662 :     } else if (switcher_pwm < 1200) {
      41      956439 :         _attitude_control(input, rot_accel);
      42     1964223 :     } else if (switcher_pwm < 1300) {
      43           0 :         _calibration_poses(rot_accel);
      44             :     } else {
      45     1964223 :         _angular_velocity_control(input, rot_accel);
      46             :     }
      47             : 
      48     3481756 :     accel_body.zero();
      49     3481756 :     update_dynamics(rot_accel);
      50     3481756 :     update_position();
      51     3481756 :     time_advance();
      52             : 
      53             :     // update magnetic field
      54     3481756 :     update_mag_field_bf();
      55             : 
      56     3481756 :     update_battery();
      57     3481756 : }
      58             : 
      59      561094 : void SITL::Calibration::_stop_control(const struct sitl_input &input,
      60             :                                       Vector3f& rot_accel)
      61             : {
      62      561094 :     Vector3f desired_angvel{0, 0, 0};
      63      561094 :     Vector3f error =  desired_angvel - gyro;
      64      561094 :     float dt = frame_time_us * 1.0e-6f;
      65      561094 :     rot_accel = error * (1.0f / dt);
      66             :     /* Provide a somewhat "smooth" transition */
      67      561094 :     rot_accel *= 0.002f;
      68      561094 : }
      69             : 
      70      956439 : void SITL::Calibration::_attitude_control(const struct sitl_input &input,
      71             :                                           Vector3f& rot_accel)
      72             : {
      73      956439 :     float desired_roll = -M_PI + 2 * M_PI * (input.servos[5] - 1000) / 1000.f;
      74      956439 :     float desired_pitch = -M_PI + 2 * M_PI * (input.servos[6] - 1000) / 1000.f;
      75      956439 :     float desired_yaw = -M_PI + 2 * M_PI * (input.servos[7] - 1000) / 1000.f;
      76             : 
      77      956439 :     _attitude_set(desired_roll, desired_pitch, desired_yaw, rot_accel);
      78      956439 : }
      79             : 
      80             : 
      81      956439 : void SITL::Calibration::_attitude_set(float desired_roll, float desired_pitch, float desired_yaw,
      82             :                                       Vector3f& rot_accel)
      83             : {
      84      956439 :     float dt = frame_time_us * 1.0e-6f;
      85             : 
      86      956439 :     Quaternion desired_q;
      87      956439 :     desired_q.from_euler(desired_roll, desired_pitch, desired_yaw);
      88      956439 :     desired_q.normalize();
      89             : 
      90      956439 :     Quaternion current_q;
      91      956439 :     current_q.from_rotation_matrix(dcm);
      92      956439 :     current_q.normalize();
      93             : 
      94      956439 :     Quaternion error_q = desired_q / current_q;
      95             : 
      96      956439 :     Vector3f angle_differential;
      97      956439 :     error_q.normalize();
      98      956439 :     error_q.to_axis_angle(angle_differential);
      99             : 
     100      956439 :     Vector3f desired_angvel = angle_differential * (1 / dt);
     101             :     /* Provide a somewhat "smooth" transition */
     102      956439 :     desired_angvel *= 0.005f;
     103             : 
     104      956439 :     Vector3f error = desired_angvel - gyro;
     105      956439 :     rot_accel = error * (1.0f / dt);
     106      956439 : }
     107             : 
     108     1964223 : void SITL::Calibration::_angular_velocity_control(const struct sitl_input &in,
     109             :                                                   Vector3f& rot_accel)
     110             : {
     111     1964223 :     Vector3f axis{(float)(in.servos[5] - 1500),
     112     1964223 :                   (float)(in.servos[6] - 1500),
     113     1964223 :                   (float)(in.servos[7] - 1500)};
     114     1964223 :     float theta = MAX_ANGULAR_SPEED * (in.servos[4] - 1300) / 700.f;
     115     1964223 :     float dt = frame_time_us * 1.0e-6f;
     116             : 
     117     1964223 :     if (axis.length() > 0) {
     118     1963539 :         axis.normalize();
     119             :     }
     120             : 
     121     1964223 :     Vector3f desired_angvel = axis * theta;
     122     1964223 :     Vector3f error = desired_angvel - gyro;
     123             : 
     124     1964223 :     rot_accel = error * (1.0f / dt);
     125             :     /* Provide a somewhat "smooth" transition */
     126     1964223 :     rot_accel *= 0.05f;
     127     1964223 : }
     128             : 
     129             : /*
     130             :   move continuously through 6 calibration poses, doing a rotation
     131             :   about each pose over 3 seconds
     132             :  */
     133           0 : void SITL::Calibration::_calibration_poses(Vector3f& rot_accel)
     134             : {
     135             :     const struct pose {
     136             :         int16_t roll, pitch, yaw;
     137             :         uint8_t axis;
     138           0 :     } poses[] = {
     139             :         {  0,   0,  0, 0 },
     140             :         {  0,   0,  0, 1 },
     141             :         {  0,   0,  0, 2 },
     142             :         { 90,   0,  0, 1 },
     143             :         {  0,  90,  0, 1 },
     144             :         {  0, 180,  0, 2 },
     145             :         { 45,   0,  0, 1 },
     146             :         {  0,  45,  0, 2 },
     147             :         {  0,   0, 45, 0 },
     148             :         { 30,   0,  0, 1 },
     149             :         {  0,  30,  0, 0 },
     150             :         { 30,   0,  0, 1 },
     151             :         {  0,   0, 30, 0 },
     152             :         {  0,   0, 30, 1 },
     153             :         { 60,  20,  0, 1 },
     154             :         {  0,  50, 10, 0 },
     155             :         {  0,  30, 50, 1 },
     156             :         {  0,  30, 50, 2 },
     157             :     };
     158           0 :     const float secs_per_pose = 6;
     159           0 :     const float rate = radians(360 / secs_per_pose);
     160           0 :     float tnow = AP_HAL::millis() * 1.0e-3;
     161           0 :     float t_in_pose = fmod(tnow, secs_per_pose);
     162           0 :     uint8_t pose_num = ((unsigned)(tnow / secs_per_pose)) % ARRAY_SIZE(poses);
     163           0 :     const struct pose &pose = poses[pose_num];
     164             : 
     165             :     // let the sensor smoothing create sensible gyro values
     166           0 :     use_smoothing = true;
     167           0 :     dcm.identity();
     168           0 :     dcm.from_euler(radians(pose.roll), radians(pose.pitch), radians(pose.yaw));
     169             : 
     170           0 :     Vector3f axis;
     171           0 :     axis[pose.axis] = 1;
     172           0 :     float rot_angle = rate * t_in_pose;
     173           0 :     Matrix3f r2;
     174           0 :     r2.from_axis_angle(axis, rot_angle);
     175           0 :     dcm = r2 * dcm;
     176             : 
     177           0 :     accel_body = {0, 0, -GRAVITY_MSS};
     178           0 :     accel_body = dcm.transposed() * accel_body;
     179           0 : }

Generated by: LCOV version 1.14