Paparazzi UAS v7.1_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
stabilization_attitude_rc_setpoint.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012-2013 Felix Ruess <felix.ruess@gmail.com>
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
27#include "generated/airframe.h"
28
30#include "state.h"
33#include "mcu_periph/sys_time.h"
34
35#ifndef STABILIZATION_ATTITUDE_DEADBAND_A
36#define STABILIZATION_ATTITUDE_DEADBAND_A 0
37#endif
38
39#ifndef STABILIZATION_ATTITUDE_DEADBAND_E
40#define STABILIZATION_ATTITUDE_DEADBAND_E 0
41#endif
42
49#ifndef COORDINATED_TURN_AIRSPEED
50#define COORDINATED_TURN_AIRSPEED 12.0
51#endif
52
53#define YAW_DEADBAND_EXCEEDED(_rc) \
54 (rc->values[RADIO_YAW] > STABILIZATION_ATTITUDE_DEADBAND_R || \
55 rc->values[RADIO_YAW] < -STABILIZATION_ATTITUDE_DEADBAND_R)
56
64
72
80
87
94
101
103{
106 rc_sp->care_free_heading = 0.f;
107 rc_sp->transition_theta_offset = 0.f;
108 rc_sp->last_ts = 0.f;
109}
110
120 bool coordinated_turn, struct RadioControl *rc)
121{
122 // FIXME: remove me, do in quaternion directly
123 // is currently still needed, since the yaw setpoint integration is done in eulers
125
126 struct FloatQuat q_rp_cmd;
128
129 /* get current heading */
130 const struct FloatVect3 zaxis = {0., 0., 1.};
131 struct FloatQuat q_yaw;
132
133 //Care Free mode
134 if (in_carefree) {
135 //care_free_heading has been set to current psi when entering care free mode.
137 } else {
139 }
140
141 /* roll/pitch commands applied to to current heading */
142 struct FloatQuat q_rp_sp;
145
146 if (in_flight) {
147 /* get current heading setpoint */
148 struct FloatQuat q_yaw_sp;
150
151 /* rotation between current yaw and yaw setpoint */
152 struct FloatQuat q_yaw_diff;
154
155 /* compute final setpoint with yaw */
157 } else {
158 QUAT_COPY(rc_sp->rc_quat, q_rp_sp);
159 }
160}
161
170 bool in_carefree, bool coordinated_turn, struct RadioControl *rc)
171{
172 // FIXME: remove me, do in quaternion directly
173 // is currently still needed, since the yaw setpoint integration is done in eulers
175
176 const struct FloatVect3 zaxis = {0., 0., 1.};
177
178 struct FloatQuat q_rp_cmd;
180
181 if (in_flight) {
182 /* get current heading setpoint */
183 struct FloatQuat q_yaw_sp;
186 } else {
187 struct FloatQuat q_yaw;
189
190 /* roll/pitch commands applied to to current heading */
191 struct FloatQuat q_rp_sp;
194
195 QUAT_COPY(rc_sp->rc_quat, q_rp_sp);
196 }
197}
198
201{
202#if USE_EARTH_BOUND_RC_SETPOINT
204#else
206#endif
208}
209
215
216/* This is a different way to obtain yaw. It will not switch when going beyond 90 degrees pitch.
217 However, when rolling more then 90 degrees in combination with pitch it switches. For a
218 transition vehicle this is better as 90 degrees pitch will occur, but more than 90 degrees roll probably not. */
220{
223 if (abs(att->phi) < INT32_ANGLE_PI_2) {
227 } else if (ANGLE_FLOAT_OF_BFP(att->theta) > 0) {
228 heading = att->psi - att->phi;
229 } else {
230 heading = att->psi + att->phi;
231 }
232 return heading;
233}
234
236{
238 float heading;
239 if (fabsf(att->phi) < M_PI / 2) {
240 heading = att->psi - sinf(att->theta) * att->phi;
241 } else if (att->theta > 0) {
242 heading = att->psi - att->phi;
243 } else {
244 heading = att->psi + att->phi;
245 }
246 return heading;
247}
248
249
260 bool in_carefree, bool coordinated_turn, struct RadioControl *rc)
261{
262 struct Int32Eulers sp_i;
263 EULERS_BFP_OF_REAL(sp_i, rc_sp->rc_eulers);
264
265 sp_i.phi = get_rc_roll(rc);
266 sp_i.theta = get_rc_pitch(rc);
267
268 if (in_flight) {
269 /* calculate dt for yaw integration */
270 float dt = get_sys_time_float() - rc_sp->last_ts;
271 /* make sure nothing drastically weird happens, bound dt to 0.5sec */
272 Bound(dt, 0, 0.5);
273
274 /* do not advance yaw setpoint if within a small deadband around stick center or if throttle is zero */
276 sp_i.psi += get_rc_yaw(rc) * dt;
278 }
279 if (coordinated_turn) {
280 //Coordinated turn
281 //feedforward estimate angular rotation omega = g*tan(phi)/v
282 int32_t omega;
284 if (abs(sp_i.phi) < max_phi) {
286 } else { //max 60 degrees roll
287 omega = ANGLE_BFP_OF_REAL(9.81 / COORDINATED_TURN_AIRSPEED * 1.72305 * ((sp_i.phi > 0) - (sp_i.phi < 0)));
288 }
289
290 sp_i.psi += omega * dt;
291 }
292#ifdef STABILIZATION_ATTITUDE_SP_PSI_DELTA_LIMIT
293 // Make sure the yaw setpoint does not differ too much from the real yaw
294 // to prevent a sudden switch at 180 deg
296
298
301 if (delta_psi > delta_limit) {
302 sp_i.psi = heading + delta_limit;
303 } else if (delta_psi < -delta_limit) {
304 sp_i.psi = heading - delta_limit;
305 }
307#endif
308 //Care Free mode
309 if (in_carefree) {
310 //care_free_heading has been set to current psi when entering care free mode.
315
316 care_free_delta_psi_i = sp_i.psi - ANGLE_BFP_OF_REAL(rc_sp->care_free_heading);
317
319
322
326
327 sp_i.theta = temp_theta;
328 }
329 } else { /* if not flying, use current yaw as setpoint */
331 }
332
333 /* update timestamp for dt calculation */
334 rc_sp->last_ts = get_sys_time_float();
335 EULERS_FLOAT_OF_BFP(rc_sp->rc_eulers, sp_i);
336 return sp_i;
337}
338
339
350 bool in_carefree, bool coordinated_turn, struct RadioControl *rc)
351{
352 rc_sp->rc_eulers.phi = get_rc_roll_f(rc);
353 rc_sp->rc_eulers.theta = get_rc_pitch_f(rc);
354
355 if (in_flight) {
356 /* calculate dt for yaw integration */
357 float dt = get_sys_time_float() - rc_sp->last_ts;
358 /* make sure nothing drastically weird happens, bound dt to 0.5sec */
359 Bound(dt, 0, 0.5);
360
361 /* do not advance yaw setpoint if within a small deadband around stick center or if throttle is zero */
363 rc_sp->rc_eulers.psi += get_rc_yaw_f(rc) * dt;
364 FLOAT_ANGLE_NORMALIZE(rc_sp->rc_eulers.psi);
365 }
366 if (coordinated_turn) {
367 //Coordinated turn
368 //feedforward estimate angular rotation omega = g*tan(phi)/v
369 float omega;
370 const float max_phi = RadOfDeg(60.0);
371 if (fabsf(rc_sp->rc_eulers.phi) < max_phi) {
372 omega = 9.81 / COORDINATED_TURN_AIRSPEED * tanf(rc_sp->rc_eulers.phi);
373 } else { //max 60 degrees roll
374 omega = 9.81 / COORDINATED_TURN_AIRSPEED * 1.72305 * ((rc_sp->rc_eulers.phi > 0) - (rc_sp->rc_eulers.phi < 0));
375 }
376
377 rc_sp->rc_eulers.psi += omega * dt;
378 }
379#ifdef STABILIZATION_ATTITUDE_SP_PSI_DELTA_LIMIT
380 // Make sure the yaw setpoint does not differ too much from the real yaw
381 // to prevent a sudden switch at 180 deg
383
384 float delta_psi = rc_sp->rc_eulers.psi - heading;
390 }
391 FLOAT_ANGLE_NORMALIZE(rc_sp->rc_eulers.psi);
392#endif
393 //Care Free mode
394 if (in_carefree) {
395 //care_free_heading has been set to current psi when entering care free mode.
396 float cos_psi;
397 float sin_psi;
398 float temp_theta;
399
400 float care_free_delta_psi_f = rc_sp->rc_eulers.psi - rc_sp->care_free_heading;
401
403
406
407 temp_theta = cos_psi * rc_sp->rc_eulers.theta - sin_psi * rc_sp->rc_eulers.phi;
408 rc_sp->rc_eulers.phi = cos_psi * rc_sp->rc_eulers.phi - sin_psi * rc_sp->rc_eulers.theta;
409
410 rc_sp->rc_eulers.theta = temp_theta;
411 }
412 } else { /* if not flying, use current yaw as setpoint */
413 rc_sp->rc_eulers.psi = stateGetNedToBodyEulers_f()->psi;
414 }
415
416 /* update timestamp for dt calculation */
417 rc_sp->last_ts = get_sys_time_float();
418 return rc_sp->rc_eulers;
419}
420
421
428{
429 /* orientation vector describing simultaneous rotation of roll/pitch */
430 struct FloatVect3 ov;
431 ov.x = get_rc_roll_f(rc);
432 ov.y = get_rc_pitch_f(rc);
433 ov.z = 0.0;
434
435 /* quaternion from that orientation vector */
437}
438
446{
447 /* only non-zero entries for roll quaternion */
448 float roll2 = get_rc_roll_f(rc) / 2.0f;
449 float qx_roll = sinf(roll2);
450 float qi_roll = cosf(roll2);
451
452 //An offset is added if in forward mode
453 /* only non-zero entries for pitch quaternion */
454 float pitch2 = (theta_offset + get_rc_pitch_f(rc)) / 2.0f;
455 float qy_pitch = sinf(pitch2);
456 float qi_pitch = cosf(pitch2);
457
458 /* only multiply non-zero entries of float_quat_comp(q, &q_roll, &q_pitch) */
459 q->qi = qi_roll * qi_pitch;
460 q->qx = qx_roll * qi_pitch;
461 q->qy = qi_roll * qy_pitch;
462 q->qz = qx_roll * qy_pitch;
463}
464
float phi
in radians
float theta
in radians
float psi
in radians
static void float_quat_normalize(struct FloatQuat *q)
#define FLOAT_ANGLE_NORMALIZE(_a)
static void float_quat_identity(struct FloatQuat *q)
initialises a quaternion to identity
#define FLOAT_EULERS_ZERO(_e)
void float_quat_comp_norm_shortest(struct FloatQuat *a2c, const struct FloatQuat *a2b, const struct FloatQuat *b2c)
Composition (multiplication) of two quaternions with normalization.
void float_quat_comp(struct FloatQuat *a2c, const struct FloatQuat *a2b, const struct FloatQuat *b2c)
Composition (multiplication) of two quaternions.
void float_quat_of_orientation_vect(struct FloatQuat *q, const struct FloatVect3 *ov)
Quaternion from orientation vector.
void float_quat_of_axis_angle(struct FloatQuat *q, const struct FloatVect3 *uv, const float angle)
Quaternion from unit vector and angle.
void float_quat_comp_inv(struct FloatQuat *a2b, const struct FloatQuat *a2c, const struct FloatQuat *b2c)
Composition (multiplication) of two quaternions.
euler angles
Roation quaternion.
#define EULERS_BFP_OF_REAL(_ei, _ef)
#define QUAT_COPY(_qo, _qi)
#define EULERS_FLOAT_OF_BFP(_ef, _ei)
int32_t phi
in rad with INT32_ANGLE_FRAC
int32_t psi
in rad with INT32_ANGLE_FRAC
int32_t theta
in rad with INT32_ANGLE_FRAC
#define INT_MULT_RSHIFT(_a, _b, _r)
#define ANGLE_BFP_OF_REAL(_af)
#define INT32_TRIG_FRAC
#define INT32_ANGLE_PI_2
#define INT32_ANGLE_FRAC
#define ANGLE_FLOAT_OF_BFP(_ai)
#define INT32_ANGLE_NORMALIZE(_a)
euler angles
static struct Int32Eulers * stateGetNedToBodyEulers_i(void)
Get vehicle body attitude euler angles (int).
Definition state.h:1296
static struct FloatEulers * stateGetNedToBodyEulersZxy_f(void)
Get vehicle body attitude ZXY euler angles (float).
Definition state.h:1320
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition state.h:1314
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition state.h:1302
uint16_t foo
Definition main_demo5.c:58
#define MAX_PPRZ
Definition paparazzi.h:8
#define PPRZ_ITRIG_SIN(_s, _a)
#define PPRZ_ITRIG_COS(_c, _a)
Generic interface for radio control modules.
Some helper functions to check RC sticks.
#define THROTTLE_STICK_DOWN_FROM_RC(_rc)
General attitude stabilization interface for rotorcrafts.
void stabilization_attitude_reset_care_free_heading(struct AttitudeRCInput *rc_sp)
reset the heading for care-free mode to current heading
int32_t stabilization_attitude_get_heading_i(void)
Get attitude heading as int (avoiding jumps)
static int32_t get_rc_yaw(struct RadioControl *rc)
static float get_rc_pitch_f(struct RadioControl *rc)
#define COORDINATED_TURN_AIRSPEED
Airspeed that will be used in the turning speed calculation (m/s).
static int32_t get_rc_pitch(struct RadioControl *rc)
static int32_t get_rc_roll(struct RadioControl *rc)
void stabilization_attitude_reset_rc_setpoint(struct AttitudeRCInput *rc_sp)
reset to current state
void stabilization_attitude_rc_setpoint_init(struct AttitudeRCInput *rc_sp)
Init rc input.
void stabilization_attitude_read_rc_setpoint_earth_bound(struct AttitudeRCInput *rc_sp, bool in_flight, bool in_carefree, bool coordinated_turn, struct RadioControl *rc)
Read attitude setpoint from RC as quaternion in earth bound frame.
void stabilization_attitude_read_rc_roll_pitch_earth_quat_f(struct FloatQuat *q, float theta_offset, struct RadioControl *rc)
Read roll/pitch command from RC as quaternion.
void stabilization_attitude_read_rc_roll_pitch_quat_f(struct FloatQuat *q, struct RadioControl *rc)
Read roll/pitch command from RC as quaternion.
void stabilization_attitude_read_rc_setpoint(struct AttitudeRCInput *rc_sp, bool in_flight, bool in_carefree, bool coordinated_turn, struct RadioControl *rc)
Read attitude setpoint from RC as quaternion Interprets the stick positions as axes.
#define STABILIZATION_ATTITUDE_DEADBAND_A
#define STABILIZATION_ATTITUDE_DEADBAND_E
struct Int32Eulers stabilization_attitude_read_rc_setpoint_eulers(struct AttitudeRCInput *rc_sp, bool in_flight, bool in_carefree, bool coordinated_turn, struct RadioControl *rc)
Read attitude setpoint from RC as euler angles Only the euler format is updated and returned.
static float get_rc_roll_f(struct RadioControl *rc)
#define YAW_DEADBAND_EXCEEDED(_rc)
struct FloatEulers stabilization_attitude_read_rc_setpoint_eulers_f(struct AttitudeRCInput *rc_sp, bool in_flight, bool in_carefree, bool coordinated_turn, struct RadioControl *rc)
Read attitude setpoint from RC as float euler angles Only the euler format is updated and returned.
float stabilization_attitude_get_heading_f(void)
Get attitude heading as float (avoiding jumps)
static float get_rc_yaw_f(struct RadioControl *rc)
Read an attitude setpoint from the RC.
struct FloatEulers rc_eulers
RC input in eulers (needed even for quat for yaw integration)
struct FloatQuat rc_quat
RC input in quaternion.
float care_free_heading
care_free heading
float transition_theta_offset
pitch offset for hybrids, add when in forward mode
Attitude (and Rate) Remote Control input.
API to get/set the generic vehicle states.
Architecture independent timing functions.
static float get_sys_time_float(void)
Get the time in seconds since startup.
Definition sys_time.h:168
int int32_t
Typedef defining 32 bit int type.
float heading
Definition wedgebug.c:258