Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
guidance_indi_hybrid_quadplane.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Ewoud Smeur <ewoud.smeur@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 
29 #include "state.h"
30 #include "autopilot.h"
31 #include "generated/modules.h"
32 
33 #ifndef COMMAND_THRUST_X
34 #error "Quadplanes require a forward thrust actuator"
35 #endif
36 
37 #ifndef GUIDANCE_INDI_PUSHER_INDEX
38 #error "You need to define GUIDANCE_INDI_PUSHER_INDEX"
39 #endif
40 
41 #ifndef GUIDANCE_INDI_THRUST_Z_EFF
42 #error "You need to define GUIDANCE_INDI_THRUST_Z_EFF"
43 #else
44 float guidance_indi_thrust_z_eff = GUIDANCE_INDI_THRUST_Z_EFF;
45 #endif
46 
47 float bodyz_filter_cutoff = 0.2;
48 
50 
56  float tau_bodyz = 1.0/(2.0*M_PI*bodyz_filter_cutoff);
57  float sample_time = 1.0 / PERIODIC_FREQUENCY;
58  init_butterworth_2_low_pass(&accel_bodyz_filt, tau_bodyz, sample_time, -9.81);
59 }
60 
68  // Propagate filter for thrust/lift estimate
69  float accelz = ACCEL_FLOAT_OF_BFP(stateGetAccelBody_i()->z);
71 }
72 
80 void guidance_indi_calcg_wing(float Gmat[GUIDANCE_INDI_HYBRID_V][GUIDANCE_INDI_HYBRID_U], struct FloatVect3 a_diff, float body_v[GUIDANCE_INDI_HYBRID_V]) {
81  // Get attitude
82  struct FloatEulers eulers_zxy;
84 
85  /*Pre-calculate sines and cosines*/
86  float sphi = sinf(eulers_zxy.phi);
87  float cphi = cosf(eulers_zxy.phi);
88  float stheta = sinf(eulers_zxy.theta);
89  float ctheta = cosf(eulers_zxy.theta);
90  float spsi = sinf(eulers_zxy.psi);
91  float cpsi = cosf(eulers_zxy.psi);
92 
93 #ifndef GUIDANCE_INDI_PITCH_EFF_SCALING
94 #define GUIDANCE_INDI_PITCH_EFF_SCALING 1.0
95 #endif
96 
97  /*Amount of lift produced by the wing*/
98  float lift_thrust_bz = accel_bodyz_filt.o[0]; // Sum of lift and thrust in boxy z axis (level flight)
99 
100  // get the derivative of the lift wrt to theta
101  float liftd = guidance_indi_get_liftd(0.0f, 0.0f);
102 
103  Gmat[0][0] = -sphi*stheta*lift_thrust_bz;
104  Gmat[1][0] = -cphi*lift_thrust_bz;
105  Gmat[2][0] = -sphi*ctheta*lift_thrust_bz;
106 
107  Gmat[0][1] = cphi*ctheta*lift_thrust_bz*GUIDANCE_INDI_PITCH_EFF_SCALING;
108  Gmat[1][1] = sphi*stheta*lift_thrust_bz*GUIDANCE_INDI_PITCH_EFF_SCALING - sphi*liftd;
109  Gmat[2][1] = -cphi*stheta*lift_thrust_bz*GUIDANCE_INDI_PITCH_EFF_SCALING + cphi*liftd;
110 
111  Gmat[0][2] = cphi*stheta;
112  Gmat[1][2] = -sphi;
113  Gmat[2][2] = cphi*ctheta;
114 
115  Gmat[0][3] = ctheta;
116  Gmat[1][3] = 0;
117  Gmat[2][3] = -stheta;
118  // Make this term zero to prevent switching 'exploits'
119  // Gmat[2][3] = 0;
120 
121  // Convert acceleration error to body axis system
122  body_v[0] = cpsi * a_diff.x + spsi * a_diff.y;
123  body_v[1] = -spsi * a_diff.x + cpsi * a_diff.y;
124  body_v[2] = a_diff.z;
125 }
126 
127 
128 void WEAK guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle)
129 {
130  float max_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MAX_PITCH);
131  float min_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MIN_PITCH);
132 
133  float pitch_pref_rad = RadOfDeg(guidance_indi_pitch_pref_deg);
134 
135  // Set lower limits
136  wls_guid_p.u_min[0] = -guidance_indi_max_bank - roll_angle; //roll
137  wls_guid_p.u_min[1] = min_pitch_limit_rad - pitch_angle; // pitch
138  wls_guid_p.u_min[2] = (MAX_PPRZ - stabilization.cmd[COMMAND_THRUST]) * guidance_indi_thrust_z_eff;
139  wls_guid_p.u_min[3] = -stabilization.cmd[COMMAND_THRUST_X]*g1g2[4][GUIDANCE_INDI_PUSHER_INDEX];
140 
141  // Set upper limits limits
142  wls_guid_p.u_max[0] = guidance_indi_max_bank - roll_angle; //roll
143  wls_guid_p.u_max[1] = max_pitch_limit_rad - pitch_angle; // pitch
144  wls_guid_p.u_max[2] = -stabilization.cmd[COMMAND_THRUST] * guidance_indi_thrust_z_eff;
145  wls_guid_p.u_max[3] = (MAX_PPRZ - stabilization.cmd[COMMAND_THRUST_X])*g1g2[4][GUIDANCE_INDI_PUSHER_INDEX];
146 
147  // Set prefered states
148  wls_guid_p.u_pref[0] = -roll_angle; // prefered delta roll angle
149  wls_guid_p.u_pref[1] = -pitch_angle + pitch_pref_rad;// prefered delta pitch angle
150  wls_guid_p.u_pref[2] = wls_guid_p.u_max[2]; // Low thrust better for efficiency
151  wls_guid_p.u_pref[3] = body_v[0]; // solve the body acceleration
152 }
153 
154 
157  return ! motors_on;
158 }
159 
Core autopilot interface common to all firmwares.
uint8_t last_wp UNUSED
float phi
in radians
float theta
in radians
float psi
in radians
void float_eulers_of_quat_zxy(struct FloatEulers *e, struct FloatQuat *q)
euler rotation 'ZXY' This rotation order is useful if you need 90 deg pitch
euler angles
#define ACCEL_FLOAT_OF_BFP(_ai)
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition: state.h:1131
static struct Int32Vect3 * stateGetAccelBody_i(void)
Get acceleration in Body coordinates (int).
Definition: state.h:953
float guidance_indi_max_bank
float guidance_indi_pitch_pref_deg
float WEAK guidance_indi_get_liftd(float airspeed, float theta)
Get the derivative of lift w.r.t.
struct FloatEulers eulers_zxy
state eulers in zxy order
A guidance mode based on Incremental Nonlinear Dynamic Inversion Come to ICRA2016 to learn more!
float guidance_indi_thrust_z_eff
void guidance_indi_quadplane_propagate_filters(void)
Low pass the accelerometer measurements to remove noise from vibrations.
float bodyz_filter_cutoff
void guidance_indi_quadplane_init(void)
Call upon entering indi guidance.
bool autopilot_in_flight_end_detection(bool motors_on UNUSED)
Quadplanes can still be in-flight with COMMAND_THRUST==0 and can even soar not descending in updrafts...
#define GUIDANCE_INDI_PITCH_EFF_SCALING
void guidance_indi_calcg_wing(float Gmat[GUIDANCE_INDI_HYBRID_V][GUIDANCE_INDI_HYBRID_U], struct FloatVect3 a_diff, float body_v[GUIDANCE_INDI_HYBRID_V])
Perform WLS.
void WEAK guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle)
Butterworth2LowPass accel_bodyz_filt
#define GUIDANCE_INDI_MAX_PITCH
#define GUIDANCE_INDI_MIN_PITCH
Simple first order low pass filter with bilinear transform.
float o[2]
output history
static void init_butterworth_2_low_pass(Butterworth2LowPass *filter, float tau, float sample_time, float value)
Init a second order Butterworth filter.
static float update_butterworth_2_low_pass(Butterworth2LowPass *filter, float value)
Update second order Butterworth low pass filter state with a new value.
Second order low pass filter structure.
#define MAX_PPRZ
Definition: paparazzi.h:8
struct Stabilization stabilization
Definition: stabilization.c:41
int32_t cmd[COMMANDS_NB]
output command vector, range from [-MAX_PPRZ:MAX_PPRZ] (store for messages)
float g1g2[INDI_OUTPUTS][INDI_NUM_ACT]
API to get/set the generic vehicle states.