Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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
205
211
212/* This is a different way to obtain yaw. It will not switch when going beyond 90 degrees pitch.
213 However, when rolling more then 90 degrees in combination with pitch it switches. For a
214 transition vehicle this is better as 90 degrees pitch will occur, but more than 90 degrees roll probably not. */
216{
219 if (abs(att->phi) < INT32_ANGLE_PI_2) {
223 } else if (ANGLE_FLOAT_OF_BFP(att->theta) > 0) {
224 heading = att->psi - att->phi;
225 } else {
226 heading = att->psi + att->phi;
227 }
228 return heading;
229}
230
232{
234 float heading;
235 if (fabsf(att->phi) < M_PI / 2) {
236 heading = att->psi - sinf(att->theta) * att->phi;
237 } else if (att->theta > 0) {
238 heading = att->psi - att->phi;
239 } else {
240 heading = att->psi + att->phi;
241 }
242 return heading;
243}
244
245
256 bool in_carefree, bool coordinated_turn, struct RadioControl *rc)
257{
258 struct Int32Eulers sp_i;
259 EULERS_BFP_OF_REAL(sp_i, rc_sp->rc_eulers);
260
261 sp_i.phi = get_rc_roll(rc);
262 sp_i.theta = get_rc_pitch(rc);
263
264 if (in_flight) {
265 /* calculate dt for yaw integration */
266 float dt = get_sys_time_float() - rc_sp->last_ts;
267 /* make sure nothing drastically weird happens, bound dt to 0.5sec */
268 Bound(dt, 0, 0.5);
269
270 /* do not advance yaw setpoint if within a small deadband around stick center or if throttle is zero */
272 sp_i.psi += get_rc_yaw(rc) * dt;
274 }
275 if (coordinated_turn) {
276 //Coordinated turn
277 //feedforward estimate angular rotation omega = g*tan(phi)/v
278 int32_t omega;
280 if (abs(sp_i.phi) < max_phi) {
282 } else { //max 60 degrees roll
283 omega = ANGLE_BFP_OF_REAL(9.81 / COORDINATED_TURN_AIRSPEED * 1.72305 * ((sp_i.phi > 0) - (sp_i.phi < 0)));
284 }
285
286 sp_i.psi += omega * dt;
287 }
288#ifdef STABILIZATION_ATTITUDE_SP_PSI_DELTA_LIMIT
289 // Make sure the yaw setpoint does not differ too much from the real yaw
290 // to prevent a sudden switch at 180 deg
292
294
297 if (delta_psi > delta_limit) {
298 sp_i.psi = heading + delta_limit;
299 } else if (delta_psi < -delta_limit) {
300 sp_i.psi = heading - delta_limit;
301 }
303#endif
304 //Care Free mode
305 if (in_carefree) {
306 //care_free_heading has been set to current psi when entering care free mode.
311
312 care_free_delta_psi_i = sp_i.psi - ANGLE_BFP_OF_REAL(rc_sp->care_free_heading);
313
315
318
322
323 sp_i.theta = temp_theta;
324 }
325 } else { /* if not flying, use current yaw as setpoint */
327 }
328
329 /* update timestamp for dt calculation */
330 rc_sp->last_ts = get_sys_time_float();
331 EULERS_FLOAT_OF_BFP(rc_sp->rc_eulers, sp_i);
332 return sp_i;
333}
334
335
346 bool in_carefree, bool coordinated_turn, struct RadioControl *rc)
347{
348 rc_sp->rc_eulers.phi = get_rc_roll_f(rc);
349 rc_sp->rc_eulers.theta = get_rc_pitch_f(rc);
350
351 if (in_flight) {
352 /* calculate dt for yaw integration */
353 float dt = get_sys_time_float() - rc_sp->last_ts;
354 /* make sure nothing drastically weird happens, bound dt to 0.5sec */
355 Bound(dt, 0, 0.5);
356
357 /* do not advance yaw setpoint if within a small deadband around stick center or if throttle is zero */
359 rc_sp->rc_eulers.psi += get_rc_yaw_f(rc) * dt;
360 FLOAT_ANGLE_NORMALIZE(rc_sp->rc_eulers.psi);
361 }
362 if (coordinated_turn) {
363 //Coordinated turn
364 //feedforward estimate angular rotation omega = g*tan(phi)/v
365 float omega;
366 const float max_phi = RadOfDeg(60.0);
367 if (fabsf(rc_sp->rc_eulers.phi) < max_phi) {
368 omega = 9.81 / COORDINATED_TURN_AIRSPEED * tanf(rc_sp->rc_eulers.phi);
369 } else { //max 60 degrees roll
370 omega = 9.81 / COORDINATED_TURN_AIRSPEED * 1.72305 * ((rc_sp->rc_eulers.phi > 0) - (rc_sp->rc_eulers.phi < 0));
371 }
372
373 rc_sp->rc_eulers.psi += omega * dt;
374 }
375#ifdef STABILIZATION_ATTITUDE_SP_PSI_DELTA_LIMIT
376 // Make sure the yaw setpoint does not differ too much from the real yaw
377 // to prevent a sudden switch at 180 deg
379
380 float delta_psi = rc_sp->rc_eulers.psi - heading;
386 }
387 FLOAT_ANGLE_NORMALIZE(rc_sp->rc_eulers.psi);
388#endif
389 //Care Free mode
390 if (in_carefree) {
391 //care_free_heading has been set to current psi when entering care free mode.
392 float cos_psi;
393 float sin_psi;
394 float temp_theta;
395
396 float care_free_delta_psi_f = rc_sp->rc_eulers.psi - rc_sp->care_free_heading;
397
399
402
403 temp_theta = cos_psi * rc_sp->rc_eulers.theta - sin_psi * rc_sp->rc_eulers.phi;
404 rc_sp->rc_eulers.phi = cos_psi * rc_sp->rc_eulers.phi - sin_psi * rc_sp->rc_eulers.theta;
405
406 rc_sp->rc_eulers.theta = temp_theta;
407 }
408 } else { /* if not flying, use current yaw as setpoint */
409 rc_sp->rc_eulers.psi = stateGetNedToBodyEulers_f()->psi;
410 }
411
412 /* update timestamp for dt calculation */
413 rc_sp->last_ts = get_sys_time_float();
414 return rc_sp->rc_eulers;
415}
416
417
424{
425 /* orientation vector describing simultaneous rotation of roll/pitch */
426 struct FloatVect3 ov;
427 ov.x = get_rc_roll_f(rc);
428 ov.y = get_rc_pitch_f(rc);
429 ov.z = 0.0;
430
431 /* quaternion from that orientation vector */
433}
434
442{
443 /* only non-zero entries for roll quaternion */
444 float roll2 = get_rc_roll_f(rc) / 2.0f;
445 float qx_roll = sinf(roll2);
446 float qi_roll = cosf(roll2);
447
448 //An offset is added if in forward mode
449 /* only non-zero entries for pitch quaternion */
450 float pitch2 = (theta_offset + get_rc_pitch_f(rc)) / 2.0f;
451 float qy_pitch = sinf(pitch2);
452 float qi_pitch = cosf(pitch2);
453
454 /* only multiply non-zero entries of float_quat_comp(q, &q_roll, &q_pitch) */
455 q->qi = qi_roll * qi_pitch;
456 q->qx = qx_roll * qi_pitch;
457 q->qy = qi_roll * qy_pitch;
458 q->qz = qx_roll * qy_pitch;
459}
460
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)
void float_quat_of_axis_angle(struct FloatQuat *q, const struct FloatVect3 *uv, float angle)
Quaternion from unit vector and angle.
static void float_quat_identity(struct FloatQuat *q)
initialises a quaternion to identity
void float_quat_comp_norm_shortest(struct FloatQuat *a2c, struct FloatQuat *a2b, struct FloatQuat *b2c)
Composition (multiplication) of two quaternions with normalization.
void float_quat_comp_inv(struct FloatQuat *a2b, struct FloatQuat *a2c, struct FloatQuat *b2c)
Composition (multiplication) of two quaternions.
#define FLOAT_EULERS_ZERO(_e)
void float_quat_of_orientation_vect(struct FloatQuat *q, const struct FloatVect3 *ov)
Quaternion from orientation vector.
void float_quat_comp(struct FloatQuat *a2c, struct FloatQuat *a2b, 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:1288
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition state.h:1306
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition state.h:1294
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:138
int int32_t
Typedef defining 32 bit int type.
float heading
Definition wedgebug.c:258