Blackbox device type 'file' (SITL) considered working when file handler is available
[inav.git] / src / main / sensors / boardalignment.c
blob1f149faeff6a1ab754f12b5b90849cc8990e14c6
1 /*
2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <math.h>
21 #include <string.h>
23 #include "platform.h"
25 #include "common/maths.h"
26 #include "common/vector.h"
27 #include "common/axis.h"
29 #include "config/parameter_group.h"
30 #include "config/parameter_group_ids.h"
31 #include "fc/runtime_config.h"
33 #include "drivers/sensor.h"
35 #if defined(UNIT_TEST)
36 // Unit tests can't include settings. Provide some dummy limits.
37 #define SETTING_ALIGN_BOARD_ROLL_MIN -1800
38 #define SETTING_ALIGN_BOARD_ROLL_MAX 3600
39 #define SETTING_ALIGN_BOARD_PITCH_MIN -1800
40 #define SETTING_ALIGN_BOARD_PITCH_MAX 3600
41 #else
42 #include "fc/settings.h"
43 #endif
45 #include "boardalignment.h"
47 static bool standardBoardAlignment = true; // board orientation correction
48 static fpMat3_t boardRotMatrix;
49 static fpMat3_t tailRotMatrix;
51 // no template required since defaults are zero
52 PG_REGISTER(boardAlignment_t, boardAlignment, PG_BOARD_ALIGNMENT, 0);
54 static bool isBoardAlignmentStandard(const boardAlignment_t *boardAlignment)
56 return !boardAlignment->rollDeciDegrees && !boardAlignment->pitchDeciDegrees && !boardAlignment->yawDeciDegrees;
59 void initBoardAlignment(void)
61 standardBoardAlignment=isBoardAlignmentStandard(boardAlignment());
62 fp_angles_t rotationAngles;
64 rotationAngles.angles.roll = DECIDEGREES_TO_RADIANS(boardAlignment()->rollDeciDegrees );
65 rotationAngles.angles.pitch = DECIDEGREES_TO_RADIANS(boardAlignment()->pitchDeciDegrees);
66 rotationAngles.angles.yaw = DECIDEGREES_TO_RADIANS(boardAlignment()->yawDeciDegrees );
68 rotationMatrixFromAngles(&boardRotMatrix, &rotationAngles);
69 fp_angles_t tailSitter_rotationAngles;
70 tailSitter_rotationAngles.angles.roll = DECIDEGREES_TO_RADIANS(0);
71 tailSitter_rotationAngles.angles.pitch = DECIDEGREES_TO_RADIANS(900);
72 tailSitter_rotationAngles.angles.yaw = DECIDEGREES_TO_RADIANS(0);
73 rotationMatrixFromAngles(&tailRotMatrix, &tailSitter_rotationAngles);
76 void updateBoardAlignment(int16_t roll, int16_t pitch)
78 const float sinAlignYaw = sin_approx(DECIDEGREES_TO_RADIANS(boardAlignment()->yawDeciDegrees));
79 const float cosAlignYaw = cos_approx(DECIDEGREES_TO_RADIANS(boardAlignment()->yawDeciDegrees));
81 int16_t rollDeciDegrees = boardAlignment()->rollDeciDegrees + -sinAlignYaw * pitch + cosAlignYaw * roll;
82 int16_t pitchDeciDegrees = boardAlignment()->pitchDeciDegrees + cosAlignYaw * pitch + sinAlignYaw * roll;
84 boardAlignmentMutable()->rollDeciDegrees = constrain(rollDeciDegrees, SETTING_ALIGN_BOARD_ROLL_MIN, SETTING_ALIGN_BOARD_ROLL_MAX);
85 boardAlignmentMutable()->pitchDeciDegrees = constrain(pitchDeciDegrees, SETTING_ALIGN_BOARD_PITCH_MIN, SETTING_ALIGN_BOARD_PITCH_MAX);
87 initBoardAlignment();
90 void applyTailSitterAlignment(fpVector3_t *fpVec)
92 if (!STATE(TAILSITTER)) {
93 return;
95 rotationMatrixRotateVector(fpVec, fpVec, &tailRotMatrix);
98 void applyBoardAlignment(float *vec)
100 if (standardBoardAlignment && (!STATE(TAILSITTER))) {
101 return;
104 fpVector3_t fpVec = { .v = { vec[X], vec[Y], vec[Z] } };
105 rotationMatrixRotateVector(&fpVec, &fpVec, &boardRotMatrix);
106 applyTailSitterAlignment(&fpVec);
107 vec[X] = lrintf(fpVec.x);
108 vec[Y] = lrintf(fpVec.y);
109 vec[Z] = lrintf(fpVec.z);
112 void FAST_CODE applySensorAlignment(float * dest, float * src, uint8_t rotation)
114 // Create a copy so we could use the same buffer for src & dest
115 const float x = src[X];
116 const float y = src[Y];
117 const float z = src[Z];
119 switch (rotation) {
120 default:
121 case CW0_DEG:
122 dest[X] = x;
123 dest[Y] = y;
124 dest[Z] = z;
125 break;
126 case CW90_DEG:
127 dest[X] = y;
128 dest[Y] = -x;
129 dest[Z] = z;
130 break;
131 case CW180_DEG:
132 dest[X] = -x;
133 dest[Y] = -y;
134 dest[Z] = z;
135 break;
136 case CW270_DEG:
137 dest[X] = -y;
138 dest[Y] = x;
139 dest[Z] = z;
140 break;
141 case CW0_DEG_FLIP:
142 dest[X] = -x;
143 dest[Y] = y;
144 dest[Z] = -z;
145 break;
146 case CW90_DEG_FLIP:
147 dest[X] = y;
148 dest[Y] = x;
149 dest[Z] = -z;
150 break;
151 case CW180_DEG_FLIP:
152 dest[X] = x;
153 dest[Y] = -y;
154 dest[Z] = -z;
155 break;
156 case CW270_DEG_FLIP:
157 dest[X] = -y;
158 dest[Y] = -x;
159 dest[Z] = -z;
160 break;