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 
30 #include "state.h"
31 #include "autopilot.h"
32 #include "generated/modules.h"
33 
34 
35 #ifndef COMMAND_THRUST_X
36 #error "Quadplanes require a forward thrust actuator"
37 #endif
38 
39 #ifndef GUIDANCE_INDI_THRUST_Z_EFF
40 #error "You need to define GUIDANCE_INDI_THRUST_Z_EFF"
41 #else
42 float guidance_indi_thrust_z_eff = GUIDANCE_INDI_THRUST_Z_EFF;
43 #endif
44 
45 #ifndef GUIDANCE_INDI_THRUST_X_EFF
46 #error "You need to define GUIDANCE_INDI_THRUST_X_EFF"
47 #else
48 float guidance_indi_thrust_x_eff = GUIDANCE_INDI_THRUST_X_EFF;
49 #endif
50 
51 
52 float bodyz_filter_cutoff = 0.2;
53 
55 
56 
57 
63  float tau_bodyz = 1.0/(2.0*M_PI*bodyz_filter_cutoff);
64  float sample_time = 1.0 / PERIODIC_FREQUENCY;
65  init_butterworth_2_low_pass(&accel_bodyz_filt, tau_bodyz, sample_time, -9.81);
66 }
67 
68 
76  // Propagate filter for thrust/lift estimate
77  float accelz = ACCEL_FLOAT_OF_BFP(stateGetAccelBody_i()->z);
79 }
80 
81 
82 
83 
91 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]) {
92  // Get attitude
93  struct FloatEulers eulers_zxy;
95 
96  /*Pre-calculate sines and cosines*/
97  float sphi = sinf(eulers_zxy.phi);
98  float cphi = cosf(eulers_zxy.phi);
99  float stheta = sinf(eulers_zxy.theta);
100  float ctheta = cosf(eulers_zxy.theta);
101  float spsi = sinf(eulers_zxy.psi);
102  float cpsi = cosf(eulers_zxy.psi);
103 
104 #ifndef GUIDANCE_INDI_PITCH_EFF_SCALING
105 #define GUIDANCE_INDI_PITCH_EFF_SCALING 1.0
106 #endif
107 
108  /*Amount of lift produced by the wing*/
109  float lift_thrust_bz = accel_bodyz_filt.o[0]; // Sum of lift and thrust in boxy z axis (level flight)
110 
111  // get the derivative of the lift wrt to theta
112  float liftd = guidance_indi_get_liftd(0.0f, 0.0f);
113 
114  Gmat[0][0] = -sphi*stheta*lift_thrust_bz;
115  Gmat[1][0] = -cphi*lift_thrust_bz;
116  Gmat[2][0] = -sphi*ctheta*lift_thrust_bz;
117 
118  Gmat[0][1] = cphi*ctheta*lift_thrust_bz*GUIDANCE_INDI_PITCH_EFF_SCALING;
119  Gmat[1][1] = sphi*stheta*lift_thrust_bz*GUIDANCE_INDI_PITCH_EFF_SCALING - sphi*liftd;
120  Gmat[2][1] = -cphi*stheta*lift_thrust_bz*GUIDANCE_INDI_PITCH_EFF_SCALING + cphi*liftd;
121 
122  Gmat[0][2] = cphi*stheta;
123  Gmat[1][2] = -sphi;
124  Gmat[2][2] = cphi*ctheta;
125 
126  Gmat[0][3] = ctheta;
127  Gmat[1][3] = 0;
128  Gmat[2][3] = -stheta;
129 
130  // Convert acceleration error to body axis system
131  body_v[0] = cpsi * a_diff.x + spsi * a_diff.y;
132  body_v[1] = -spsi * a_diff.x + cpsi * a_diff.y;
133  body_v[2] = a_diff.z;
134 }
135 
136 
137 void WEAK guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle)
138 {
139  float roll_limit_rad = GUIDANCE_H_MAX_BANK;
140  float max_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MAX_PITCH);
141  float min_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MIN_PITCH);
142 
143  float pitch_pref_rad = RadOfDeg(guidance_indi_pitch_pref_deg);
144 
145  // Set lower limits
146  du_min_gih[0] = -roll_limit_rad - roll_angle; //roll
147  du_min_gih[1] = min_pitch_limit_rad - pitch_angle; // pitch
148  du_min_gih[2] = (MAX_PPRZ - stabilization_cmd[COMMAND_THRUST]) * guidance_indi_thrust_z_eff;
149  du_min_gih[3] = -stabilization_cmd[COMMAND_THRUST_X]*guidance_indi_thrust_x_eff;
150 
151  // Set upper limits limits
152  du_max_gih[0] = roll_limit_rad - roll_angle; //roll
153  du_max_gih[1] = max_pitch_limit_rad - pitch_angle; // pitch
154  du_max_gih[2] = -stabilization_cmd[COMMAND_THRUST] * guidance_indi_thrust_z_eff;
155  du_max_gih[3] = (MAX_PPRZ - stabilization_cmd[COMMAND_THRUST_X])*guidance_indi_thrust_x_eff;
156 
157  // Set prefered states
158  du_pref_gih[0] = -roll_angle; // prefered delta roll angle
159  du_pref_gih[1] = -pitch_angle + pitch_pref_rad;// prefered delta pitch angle
160  du_pref_gih[2] = du_max_gih[2]; // Low thrust better for efficiency
161  du_pref_gih[3] = body_v[0]; // solve the body acceleration
162 }
163 
164 
167  return ! motors_on;
168 }
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_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
float guidance_indi_thrust_x_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
#define GUIDANCE_H_MAX_BANK
Max bank controlled by guidance.
Definition: guidance_h.h:71
int32_t stabilization_cmd[COMMANDS_NB]
Stabilization commands.
Definition: stabilization.c:34
Rotorcraft attitude reference generation.
API to get/set the generic vehicle states.