PX4 Firmware
PX4 Autopilot Software http://px4.io
tailsitter.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2015 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35 * @file tailsitter.cpp
36 *
37 * @author Roman Bapst <bapstroman@gmail.com>
38 * @author David Vorsin <davidvorsin@gmail.com>
39 *
40 */
41 
42 #include "tailsitter.h"
43 #include "vtol_att_control_main.h"
44 
45 #define ARSP_YAW_CTRL_DISABLE 4.0f // airspeed at which we stop controlling yaw during a front transition
46 #define THROTTLE_TRANSITION_MAX 0.25f // maximum added thrust above last value in transition
47 #define PITCH_TRANSITION_FRONT_P1 -1.1f // pitch angle to switch to TRANSITION_P2
48 #define PITCH_TRANSITION_BACK -0.25f // pitch angle to switch to MC
49 
50 using namespace matrix;
51 
53  VtolType(attc)
54 {
55  _vtol_schedule.flight_mode = vtol_mode::MC_MODE;
56  _vtol_schedule.transition_start = 0;
57 
58  _mc_roll_weight = 1.0f;
59  _mc_pitch_weight = 1.0f;
60  _mc_yaw_weight = 1.0f;
61 
63 
64  _params_handles_tailsitter.front_trans_dur_p2 = param_find("VT_TRANS_P2_DUR");
65  _params_handles_tailsitter.fw_pitch_sp_offset = param_find("FW_PSP_OFF");
66 }
67 
68 void
70 {
71  float v;
72 
73  /* vtol front transition phase 2 duration */
74  param_get(_params_handles_tailsitter.front_trans_dur_p2, &v);
75  _params_tailsitter.front_trans_dur_p2 = v;
76 
77  param_get(_params_handles_tailsitter.fw_pitch_sp_offset, &v);
78  _params_tailsitter.fw_pitch_sp_offset = math::radians(v);
79 }
80 
82 {
83  /* simple logic using a two way switch to perform transitions.
84  * after flipping the switch the vehicle will start tilting in MC control mode, picking up
85  * forward speed. After the vehicle has picked up enough and sufficient pitch angle the uav will go into FW mode.
86  * For the backtransition the pitch is controlled in MC mode again and switches to full MC control reaching the sufficient pitch angle.
87  */
88 
89  float pitch = Eulerf(Quatf(_v_att->q)).theta();
90 
92 
93  switch (_vtol_schedule.flight_mode) { // user switchig to MC mode
94  case vtol_mode::MC_MODE:
95  break;
96 
97  case vtol_mode::FW_MODE:
99  _vtol_schedule.transition_start = hrt_absolute_time();
100  break;
101 
103  // failsafe into multicopter mode
104  _vtol_schedule.flight_mode = vtol_mode::MC_MODE;
105  break;
106 
108  float time_since_trans_start = (float)(hrt_absolute_time() - _vtol_schedule.transition_start) * 1e-6f;
109 
110  // check if we have reached pitch angle to switch to MC mode
111  if (pitch >= PITCH_TRANSITION_BACK || time_since_trans_start > _params->back_trans_duration) {
112  _vtol_schedule.flight_mode = vtol_mode::MC_MODE;
113  }
114 
115  break;
116  }
117 
118  } else { // user switchig to FW mode
119 
120  switch (_vtol_schedule.flight_mode) {
121  case vtol_mode::MC_MODE:
122  // initialise a front transition
124  _vtol_schedule.transition_start = hrt_absolute_time();
125  break;
126 
127  case vtol_mode::FW_MODE:
128  break;
129 
131 
132 
133  const bool airspeed_triggers_transition = PX4_ISFINITE(_airspeed_validated->equivalent_airspeed_m_s)
135 
136  bool transition_to_fw = false;
137 
138  if (pitch <= PITCH_TRANSITION_FRONT_P1) {
139  if (airspeed_triggers_transition) {
141 
142  } else {
143  transition_to_fw = true;
144  }
145  }
146 
147  transition_to_fw |= can_transition_on_ground();
148 
149  if (transition_to_fw) {
150  _vtol_schedule.flight_mode = vtol_mode::FW_MODE;
151  }
152 
153  break;
154  }
155 
157  // failsafe into fixed wing mode
158  _vtol_schedule.flight_mode = vtol_mode::FW_MODE;
159  break;
160  }
161  }
162 
163  // map tailsitter specific control phases to simple control modes
164  switch (_vtol_schedule.flight_mode) {
165  case vtol_mode::MC_MODE:
168  _flag_was_in_trans_mode = false;
169  break;
170 
171  case vtol_mode::FW_MODE:
174  _flag_was_in_trans_mode = false;
175  break;
176 
180  break;
181 
185  break;
186  }
187 }
188 
190 {
191  float time_since_trans_start = (float)(hrt_absolute_time() - _vtol_schedule.transition_start) * 1e-6f;
192 
195 
196  if (_vtol_schedule.flight_mode == vtol_mode::TRANSITION_BACK) {
197  // calculate rotation axis for transition.
200  _trans_rot_axis = z.cross(Vector3f(0, 0, -1));
201 
202  // as heading setpoint we choose the heading given by the direction the vehicle points
203  float yaw_sp = atan2f(z(1), z(0));
204 
205  // the intial attitude setpoint for a backtransition is a combination of the current fw pitch setpoint,
206  // the yaw setpoint and zero roll since we want wings level transition
208 
209  // attitude during transitions are controlled by mc attitude control so rotate the desired attitude to the
210  // multirotor frame
211  _q_trans_start = _q_trans_start * Quatf(Eulerf(0, -M_PI_2_F, 0));
212 
213  } else if (_vtol_schedule.flight_mode == vtol_mode::TRANSITION_FRONT_P1) {
214  // initial attitude setpoint for the transition should be with wings level
216  Vector3f x = Dcmf(Quatf(_v_att->q)) * Vector3f(1, 0, 0);
217  _trans_rot_axis = -x.cross(Vector3f(0, 0, -1));
218  }
219 
221  }
222 
223  // tilt angle (zero if vehicle nose points up (hover))
224  float tilt = acosf(_q_trans_sp(0) * _q_trans_sp(0) - _q_trans_sp(1) * _q_trans_sp(1) - _q_trans_sp(2) * _q_trans_sp(
225  2) + _q_trans_sp(3) * _q_trans_sp(3));
226 
227  if (_vtol_schedule.flight_mode == vtol_mode::TRANSITION_FRONT_P1) {
228 
229  const float trans_pitch_rate = M_PI_2_F / _params->front_trans_duration;
230 
231  if (tilt < M_PI_2_F - _params_tailsitter.fw_pitch_sp_offset) {
233  time_since_trans_start * trans_pitch_rate)) * _q_trans_start;
234  }
235 
236  } else if (_vtol_schedule.flight_mode == vtol_mode::TRANSITION_BACK) {
237 
238  const float trans_pitch_rate = M_PI_2_F / _params->back_trans_duration;
239 
240  if (!flag_idle_mc) {
242  }
243 
244  if (tilt > 0.01f) {
246  time_since_trans_start * trans_pitch_rate)) * _q_trans_start;
247  }
248  }
249 
251 
252  _mc_roll_weight = 1.0f;
253  _mc_pitch_weight = 1.0f;
254  _mc_yaw_weight = 1.0f;
255 
257 
258  const Eulerf euler_sp(_q_trans_sp);
259  _v_att_sp->roll_body = euler_sp.phi();
260  _v_att_sp->pitch_body = euler_sp.theta();
261  _v_att_sp->yaw_body = euler_sp.psi();
262 
264  _v_att_sp->q_d_valid = true;
265 }
266 
268 {
269  // copy the last trust value from the front transition
271 }
272 
274 {
276 
277  // allow fw yawrate control via multirotor roll actuation. this is useful for vehicles
278  // which don't have a rudder to coordinate turns
279  if (_params->diff_thrust == 1) {
280  _mc_roll_weight = 1.0f;
281  }
282 }
283 
284 /**
285 * Write data to actuator output topic.
286 */
288 {
291 
294 
295  _actuators_out_0->control[actuator_controls_s::INDEX_ROLL] = _actuators_mc_in->control[actuator_controls_s::INDEX_ROLL]
296  * _mc_roll_weight;
297  _actuators_out_0->control[actuator_controls_s::INDEX_PITCH] =
298  _actuators_mc_in->control[actuator_controls_s::INDEX_PITCH] * _mc_pitch_weight;
299  _actuators_out_0->control[actuator_controls_s::INDEX_YAW] = _actuators_mc_in->control[actuator_controls_s::INDEX_YAW] *
301 
302  if (_vtol_schedule.flight_mode == vtol_mode::FW_MODE) {
303  _actuators_out_0->control[actuator_controls_s::INDEX_THROTTLE] =
304  _actuators_fw_in->control[actuator_controls_s::INDEX_THROTTLE];
305 
306  } else {
307  _actuators_out_0->control[actuator_controls_s::INDEX_THROTTLE] =
308  _actuators_mc_in->control[actuator_controls_s::INDEX_THROTTLE];
309  }
310 
311  if (_params->elevons_mc_lock && _vtol_schedule.flight_mode == vtol_mode::MC_MODE) {
312  _actuators_out_1->control[actuator_controls_s::INDEX_ROLL] = 0;
313  _actuators_out_1->control[actuator_controls_s::INDEX_PITCH] = 0;
314 
315  } else {
316  _actuators_out_1->control[actuator_controls_s::INDEX_ROLL] =
317  _actuators_fw_in->control[actuator_controls_s::INDEX_ROLL];
318  _actuators_out_1->control[actuator_controls_s::INDEX_PITCH] =
319  _actuators_fw_in->control[actuator_controls_s::INDEX_PITCH];
320  }
321 }
vtol is in fixed wing mode
Vector3 cross(const Matrix31 &b) const
Definition: Vector3.hpp:59
void update_transition_state() override
Update transition state.
Definition: tailsitter.cpp:189
void parameters_update() override
Definition: tailsitter.cpp:69
Type theta() const
Definition: Euler.hpp:132
int32_t diff_thrust
Definition: vtol_type.h:71
void waiting_on_tecs() override
Special handling opportunity for the time right after transition to FW before TECS is running...
Definition: tailsitter.cpp:267
float _mc_pitch_weight
Definition: vtol_type.h:200
__EXPORT int param_get(param_t param, void *val)
Copy the value of a parameter.
Definition: parameters.cpp:589
float _mc_yaw_weight
Definition: vtol_type.h:201
Dcm< float > Dcmf
Definition: Dcm.hpp:185
Vector3< Type > dcm_z() const
Corresponding body z-axis to an attitude quaternion / last orthogonal unit basis vector.
Definition: Quaternion.hpp:514
struct actuator_controls_s * _actuators_mc_in
Definition: vtol_type.h:186
struct vehicle_attitude_s * _v_att
Definition: vtol_type.h:178
matrix::Quatf _q_trans_sp
Definition: tailsitter.h:89
mode _vtol_mode
Definition: vtol_type.h:174
struct Tailsitter::@139 _params_tailsitter
void copyTo(Type dst[M *N]) const
Definition: Matrix.hpp:115
Type phi() const
Definition: Euler.hpp:128
Type psi() const
Definition: Euler.hpp:136
VtolAttitudeControl * _attc
Definition: vtol_type.h:173
struct Params * _params
Definition: vtol_type.h:194
struct actuator_controls_s * _actuators_out_0
Definition: vtol_type.h:184
vtol is in front transition part 1 mode
struct Tailsitter::@141 _vtol_schedule
virtual void update_fw_state()
Update fixed wing state.
Definition: vtol_type.cpp:140
struct actuator_controls_s * _actuators_fw_in
Definition: vtol_type.h:187
struct vehicle_attitude_setpoint_s * _v_att_sp
Definition: vtol_type.h:179
constexpr T radians(T degrees)
Definition: Limits.hpp:85
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
Euler< float > Eulerf
Definition: Euler.hpp:156
struct vehicle_attitude_setpoint_s * _mc_virtual_att_sp
Definition: vtol_type.h:180
bool set_idle_mc()
Sets mc motor minimum pwm to VT_IDLE_PWM_MC which ensures that they are spinning in mc mode...
Definition: vtol_type.cpp:245
Euler angles class.
Definition: AxisAngle.hpp:18
struct vehicle_attitude_setpoint_s * _fw_virtual_att_sp
Definition: vtol_type.h:181
bool flag_idle_mc
Definition: vtol_type.h:196
vtol is in back transition mode
#define PITCH_TRANSITION_BACK
Definition: tailsitter.cpp:48
__EXPORT param_t param_find(const char *name)
Look up a parameter by name.
Definition: parameters.cpp:370
float back_trans_duration
Definition: vtol_type.h:62
Tailsitter(VtolAttitudeControl *_att_controller)
Definition: tailsitter.cpp:52
Vector3< float > Vector3f
Definition: Vector3.hpp:136
float _thrust_transition
Definition: vtol_type.h:205
matrix::Vector3f _trans_rot_axis
Definition: tailsitter.h:90
float _mc_roll_weight
Definition: vtol_type.h:199
float transition_airspeed
Definition: vtol_type.h:63
vtol is in multicopter mode
Quaternion< float > Quatf
Definition: Quaternion.hpp:544
#define PITCH_TRANSITION_FRONT_P1
Definition: tailsitter.cpp:47
void update_vtol_state() override
Update vtol state.
Definition: tailsitter.cpp:81
struct airspeed_validated_s * _airspeed_validated
Definition: vtol_type.h:190
bool elevons_mc_lock
Definition: vtol_type.h:54
struct Tailsitter::@140 _params_handles_tailsitter
AxisAngle< float > AxisAnglef
Definition: AxisAngle.hpp:160
bool _flag_was_in_trans_mode
Definition: vtol_type.h:210
struct actuator_controls_s * _actuators_out_1
Definition: vtol_type.h:185
bool airspeed_disabled
Definition: vtol_type.h:67
void update_fw_state() override
Update fixed wing state.
Definition: tailsitter.cpp:273
float front_trans_duration
Definition: vtol_type.h:61
struct vtol_vehicle_status_s * _vtol_vehicle_status
Definition: vtol_type.h:183
void fill_actuator_outputs() override
Write data to actuator output topic.
Definition: tailsitter.cpp:287
bool can_transition_on_ground()
Returns true if we&#39;re allowed to do a mode transition on the ground.
Definition: vtol_type.cpp:181
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
matrix::Quatf _q_trans_start
Definition: tailsitter.h:88