Paparazzi UAS v7.1_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
rotwing_state.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2023 Dennis van Wijngaarden <D.C.vanWijngaarden@tudelft.nl>
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, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
30#include "modules/core/abi.h"
31
32
33/* Minimum measured RPM to consider the hover motors running (RPM) */
34#ifndef ROTWING_QUAD_MIN_RPM
35#define ROTWING_QUAD_MIN_RPM 400
36#endif
37
38/* Minimum measured RPM to consider the pusher motor running (RPM) */
39#ifndef ROTWING_PUSH_MIN_RPM
40#define ROTWING_PUSH_MIN_RPM 300
41#endif
42
43/* Timeout for the RPM feedback (seconds) */
44#ifndef ROTWING_RPM_TIMEOUT
45#define ROTWING_RPM_TIMEOUT 1.0
46#endif
47
48/* Minimum thrust to consider the hover motors idling (PPRZ) */
49#ifndef ROTWING_QUAD_IDLE_MIN_THRUST
50#define ROTWING_QUAD_IDLE_MIN_THRUST 100
51#endif
52
53/* Minimum time for the hover motors to be considered idling (seconds) */
54#ifndef ROTWING_QUAD_IDLE_TIMEOUT
55#define ROTWING_QUAD_IDLE_TIMEOUT 0.4
56#endif
57
58/* Minimum measured skew angle to consider the rotating wing in fixedwing (deg) */
59#ifndef ROTWING_FW_SKEW_ANGLE
60#define ROTWING_FW_SKEW_ANGLE 85.0
61#endif
62
63/* Maximum measured skew angle to consider the rotating wing drone in quad (deg) */
64#ifndef ROTWING_QUAD_SKEW_ANGLE
65#define ROTWING_QUAD_SKEW_ANGLE 25.0
66#endif
67
68/* Maximum bank angle while the rotwing is skewing */
69#ifndef ROTWING_TRANSITION_MAX_BANK
70#define ROTWING_TRANSITION_MAX_BANK RadOfDeg(20)
71#endif
72
73/* Maximum climb speed while the rotwing is transitioning */
74#ifndef ROTWING_TRANSITION_MAX_CLIMB_SPEED
75#define ROTWING_TRANSITION_MAX_CLIMB_SPEED 0.5
76#endif
77
78/* Maximum descend speed while the rotwing is transitioning */
79#ifndef ROTWING_TRANSITION_MAX_DESCEND_SPEED
80#define ROTWING_TRANSITION_MAX_DESCEND_SPEED -0.5
81#endif
82
83/* TODO: Give a name.... */
84#ifndef ROTWING_SKEW_BACK_MARGIN
85#define ROTWING_SKEW_BACK_MARGIN 5.0
86#endif
87
88/* Maximum angle difference between the measured skew and modelled skew for skew failure detection */
89#ifndef ROTWING_SKEW_REF_MODEL_MAX_DIFF
90#define ROTWING_SKEW_REF_MODEL_MAX_DIFF 5.f
91#endif
92
93/* Skew angle at which the mininum airspeed starts its linear portion */
94#ifndef ROTWING_MIN_AIRSPEED_SLOPE_START_ANGLE
95#define ROTWING_MIN_AIRSPEED_SLOPE_START_ANGLE 30.0
96#endif
97
98/* Amount of time the airspeed needs to be below the FW_MIN_AIRSPEED */
99#ifndef ROTWING_FW_STALL_TIMEOUT
100#define ROTWING_FW_STALL_TIMEOUT 0.5
101#endif
102
103#ifndef ROTWING_STATE_MIN_FW_DIST
104#define ROTWING_STATE_MIN_FW_DIST 200.0
105#endif
106
107/* Sweep of the forced skew angle: lowest and highest skew angle (deg) and frequency (Hz) */
108#ifndef ROTWING_SKEW_SWEEP_MIN
109#define ROTWING_SKEW_SWEEP_MIN 0.f
110#endif
111
112#ifndef ROTWING_SKEW_SWEEP_MAX
113#define ROTWING_SKEW_SWEEP_MAX 60.f
114#endif
115
116#ifndef ROTWING_SKEW_SWEEP_FREQ
117#define ROTWING_SKEW_SWEEP_FREQ 0.1f
118#endif
119
120/* Fix for not having double can busses */
121#ifndef SERVO_BMOTOR_PUSH_IDX
122#define SERVO_BMOTOR_PUSH_IDX SERVO_MOTOR_PUSH_IDX
123#endif
124
125/* Fix for not having double can busses */
126#ifndef SERVO_BROTATION_MECH_IDX
127#define SERVO_BROTATION_MECH_IDX SERVO_ROTATION_MECH_IDX
128#endif
129
131#ifndef ROTWING_STATE_ACT_FEEDBACK_ID
132#define ROTWING_STATE_ACT_FEEDBACK_ID ABI_BROADCAST
133#endif
134
138#ifndef GUIDANCE_INDI_FWD_CLIMB_SPEED
139#define GUIDANCE_INDI_FWD_CLIMB_SPEED 4.0
140#endif
141
145#ifndef GUIDANCE_INDI_FWD_DESCEND_SPEED
146#define GUIDANCE_INDI_FWD_DESCEND_SPEED -4.0
147#endif
148
152#ifndef GUIDANCE_INDI_QUAD_CLIMB_SPEED
153#define GUIDANCE_INDI_QUAD_CLIMB_SPEED 2.0
154#endif
155
159#ifndef GUIDANCE_INDI_QUAD_DESCEND_SPEED
160#define GUIDANCE_INDI_QUAD_DESCEND_SPEED -2.0
161#endif
162
165static void rotwing_state_skew_sweep(bool run, float time);
167#if PERIODIC_TELEMETRY
169static void send_rotating_wing_state(struct transport_tx *trans, struct link_device *dev)
170{
171 // Set the status
173 status.value = 0;
174 status.skew_angle_valid = rotwing_state_skew_angle_valid();
175 status.hover_motors_enabled = rotwing_state.hover_motors_enabled;
176 status.hover_motors_idle = rotwing_state_hover_motors_idling();
177 status.hover_motors_running = rotwing_state_hover_motors_running();
178 status.pusher_motor_running = rotwing_state_pusher_motor_running();
179 status.skew_forced = rotwing_state.force_skew;
180
181 // Send the message
183 uint8_t nav_state = rotwing_state.nav_state;
185 &state,
186 &nav_state,
187 &status.value,
193}
194#endif // PERIODIC_TELEMETRY
195
196#if PREFLIGHT_CHECKS
197/* Preflight checks */
200
201static void rotwing_state_skew_preflight(struct preflight_result_t *result) {
203 preflight_success(result, "Rotwing skew success");
204 } else {
205 preflight_error(result, "Rotwing skew error [meas: %.1f, sp: %.1f]", rotwing_state.meas_skew_angle_deg, rotwing_state.sp_skew_angle_deg);
206 }
207}
208#endif // PREFLIGHT_CHECKS
209
211{
212 // Initialize rotwing state
223 rotwing_state.skew_sweep.active = false;
227 for (int i = 0; i < 5; i++) {
228 rotwing_state.meas_rpm[i] = 0;
230 }
235 // Bind ABI messages
237
238#if PERIODIC_TELEMETRY
240#endif
241
242 /* Register preflight checks */
243#if PREFLIGHT_CHECKS
245#endif
246}
247
253 static float last_idle_time = 0;
254 // Check if hover motors are idling and reset timer
257 }
258
259 // Check if we exceeded the idle timeout
261 return true;
262 }
263 return false;
264}
265
271static void rotwing_state_skew_sweep(bool run, float time)
272{
273 static float start_time = -1.f;
274 if (!run) {
275 start_time = -1.f;
276 return;
277 }
278 if (start_time < 0.f) {
279 start_time = time;
280 }
281 float mid = (rotwing_state.skew_sweep.max_deg + rotwing_state.skew_sweep.min_deg) / 2.f;
282 float amplitude = (rotwing_state.skew_sweep.max_deg - rotwing_state.skew_sweep.min_deg) / 2.f;
284}
285
287{
288 /* Get some genericly used variables */
289 static float last_stall_time = 0;
293 Bound(meas_skew_angle, 0, 90); // Bound to prevent errors
294
297 }
298
299 /* Override modes if flying with RC */
303 }
305 // Kill mode
308 }
309 // ATT and ATT_FWD
313 } else {
315 }
316 }
317 }
318
319 /* Handle the quad motors on/off state */
322 }
326 }
327 else {
329 }
330
331
332 /* Calculate min/max airspeed bounds based on skew angle */
337
341 }
342
343
344 /* Handle the skew angle setpoint */
347 // Set by the GCS (or by the skew sweep)
348 }
351 }
354 }
357 }
360 }
361 else {
362 // SKEWING function based on Vair
366 // Hysteresis do nothing
369 } else {
371 }
372 }
374
375
376 /* Handle the airspeed bounding */
381 }
385 }
389 }
393 }
394 else{
397 }
398
399 /* Bound max bank angle, climb speed and descend speed if the rotwing drone is transitioning and not in FREE mode */
405 } else {
409 }
410
411 // Override failing skewing while fwd
412 /*if(meas_skew_angle > 70 && rotwing_state_.skewing_failing) {
413 rotwing_state.min_airspeed = 0; // Vstall + margin
414 rotwing_state.max_airspeed = 0; // Max airspeed FW
415 }*/
416
418
419 /* Set navigation/guidance settings */
420 nav_max_deceleration_sp = ROTWING_FW_MAX_DECELERATION * meas_skew_angle / 90.f + ROTWING_QUAD_MAX_DECELERATION * (90.f - meas_skew_angle) / 90.f; //TODO: Do we really want to based this on the skew?
421
422
423 /* Calculate the skew command */
424 float servo_pprz_cmd = MAX_PPRZ * (rotwing_state.sp_skew_angle_deg - 45.f) / 45.f;
426
427 // Rotate with second order filter
428 static float rotwing_state_skew_p_cmd = -MAX_PPRZ;
429 static float rotwing_state_skew_d_cmd = 0;
430
437
438#if (ROTWING_SKEW_REF_MODEL || USE_NPS)
440#else
442#endif
443#ifdef COMMAND_ROT_MECH
445#endif
446
447 /* Add simulation feedback for the skewing and RPM */
448#if USE_NPS
449 // Export to the index of the SKEW in the NPS_ACTUATOR_NAMES array
450#ifdef COMMAND_ROT_MECH
451 commands[COMMAND_ROT_MECH] = (rotwing_state.skew_cmd + MAX_PPRZ) / 2.f; // Scale to simulation command
452#else
453 actuators_pprz[INDI_NUM_ACT] = (rotwing_state.skew_cmd + MAX_PPRZ) / 2.f; // Scale to simulation command
454#endif
455 // SEND ABI Message to ctr_eff_sched, ourself and other modules that want Actuator position feedback
458 feedback.position = 0.5f * M_PI - RadOfDeg((float) rotwing_state.skew_cmd / MAX_PPRZ * 45.f + 45.f);
459 feedback.set.position = true;
460
461 // Send ABI message (or simulate failure)
464 }
465
466 // Simulate to always have RPM if on and active feedback
472 for(uint8_t i = 0; i < 5; i++) {
474 }
475
476#ifdef SITL
478 rotwing_state.meas_rpm[0] = 0;
479 rotwing_state.meas_rpm[1] = 0;
480 rotwing_state.meas_rpm[2] = 0;
481 rotwing_state.meas_rpm[3] = 0;
482 }
483
485 rotwing_state.meas_rpm[4] = 0;
486 }
487#endif
488
489#endif
490}
491
494{
496 for (int i = 0; i < num_act_message; i++) {
497 int idx = feedback_msg[i].idx;
498
499 // Check for wing rotation feedback
501 // Get wing rotation angle from sensor
502 float skew_angle_rad = 0.5 * M_PI - feedback_msg[i].position;
505 }
506
507 // Get the RPM feedbacks of the motors
508 if (feedback_msg[i].set.rpm) {
512 } else if ((idx == SERVO_MOTOR_RIGHT_IDX) || (idx == SERVO_BMOTOR_RIGHT_IDX)) {
515 } else if ((idx == SERVO_MOTOR_BACK_IDX) || (idx == SERVO_BMOTOR_BACK_IDX)) {
518 } else if ((idx == SERVO_MOTOR_LEFT_IDX) || (idx == SERVO_BMOTOR_LEFT_IDX)) {
521 } else if ((idx == SERVO_MOTOR_PUSH_IDX) || (idx == SERVO_BMOTOR_PUSH_IDX)) {
524 }
525 }
526 }
527}
528
545
547 // Check if pusher motor is running
549 return true;
550 } else {
551 return false;
552 }
553}
554
556 // Check if the measured skew angle is timed out and the reference model is matching
559
560 return (!skew_timeout && skew_angle_match);
561}
562
566
567
568/* TODO move these rotwing navigation helper functions to an appropriate module/file */
570 // Get circle waypoint coordinates in NED
571 struct FloatVect3 circ_ned = {.x = waypoints[wp_id].enu_f.y,
572 .y = waypoints[wp_id].enu_f.x,
573 .z = -waypoints[wp_id].enu_f.z};
574
575 // Get drone position coordinates in NED
577 .y = stateGetPositionNed_f()->y,
578 .z = stateGetPositionNed_f()->z};
579
580 // Get vector pointing from drone to waypoint
583
584 static struct FloatVect3 x_axis = {.x = 1, .y = 0, .z = 0};
585 static struct FloatVect3 z_axis = {.x = 0, .y = 0, .z = 1};
586 struct FloatVect3 att_NED;
588
590
594
595 float body_to_wp_angle_rad = atan2f(y, x);
596
597 if (body_to_wp_angle_rad >= 0.f) {
598 return true; // CCW circle
599 } else {
600 return false; // CW circle
601 }
602}
603
605 struct EnuCoor_f wp = waypoints[wp_id].enu_f;
606 float dist2_to_wp = get_dist2_to_point(&wp);
608
609 if (autopilot.mode == AP_MODE_NAV) {
612 return true; // Necessary for flight plan
613 } else {
615 return false; // Necessary for flight plan
616 }
617 }
618
619 return false; // Necessary for flight plan
620}
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition abi_common.h:68
#define ACT_FEEDBACK_BOARD_ID
struct pprz_autopilot autopilot
Global autopilot structure.
Definition autopilot.c:49
uint8_t mode
current autopilot mode
Definition autopilot.h:63
static uint8_t status
#define UNUSED(x)
Hardware independent code for commands handling.
float dist2_to_wp
Definition common_nav.c:39
struct point waypoints[NB_WAYPOINT]
size == nb_waypoint, waypoint 0 is a dummy waypoint
Definition common_nav.c:44
float y
Definition common_nav.h:41
float x
Definition common_nav.h:40
static struct uart_periph * dev
int start_time
Definition gps_sirf.c:192
void float_rmat_transp_vmult(struct FloatVect3 *vb, const struct FloatRMat *m_b2a, const struct FloatVect3 *va)
rotate 3D vector by transposed rotation matrix.
#define VECT3_CROSS_PRODUCT(_vo, _v1, _v2)
#define VECT3_DIFF(_c, _a, _b)
#define VECT3_DOT_PRODUCT(_v1, _v2)
static struct FloatRMat * stateGetNedToBodyRMat_f(void)
Get vehicle body attitude rotation matrix (float).
Definition state.h:1308
struct State state
Definition state.c:36
static struct NedCoor_f * stateGetPositionNed_f(void)
Get position in local NED coordinates (float).
Definition state.h:839
static float stateGetAirspeed_f(void)
Get airspeed (float).
Definition state.h:1604
struct FloatVect3 speed_sp
void guidance_set_max_bank_angle(float max_bank)
void guidance_set_max_climb_speed(float max_climb_speed_quad, float max_climb_speed_fwd)
void guidance_set_min_max_airspeed(float min_airspeed, float max_airspeed)
void guidance_set_max_descend_speed(float max_descend_speed_quad, float max_descend_speed_fwd)
float gi_unbounded_airspeed_sp
uint16_t foo
Definition main_demo5.c:58
Hardware independent API for actuators (servos, motor controllers).
bool position
Position is set.
Definition actuators.h:48
struct act_feedback_t::act_feedback_set_t set
Bitset registering what is set as feedback.
uint8_t idx
General index of the actuators (generated in airframe.h)
Definition actuators.h:45
float nav_max_deceleration_sp
static uint32_t idx
#define MAX_PPRZ
Definition paparazzi.h:8
float z
in meters
float x
in meters
float y
in meters
vector in East North Up coordinates Units: meters
void preflight_error(struct preflight_result_t *result, const char *fmt,...)
Register a preflight error used inside the preflight checking functions.
void preflight_success(struct preflight_result_t *result, const char *fmt,...)
Register a preflight success used inside the preflight checking functions.
void preflight_check_register(struct preflight_check_t *check, preflight_check_f func)
Register a preflight check and add it to the linked list.
Rotorcraft specific autopilot interface and initialization.
#define AP_MODE_NAV
#define AP_MODE_FAILSAFE
struct HorizontalGuidance guidance_h
Definition guidance_h.c:45
#define GUIDANCE_H_MODE_NONE
Definition guidance_h.h:56
#define GUIDANCE_H_MAX_BANK
Max bank controlled by guidance.
Definition guidance_h.h:64
float get_dist2_to_point(struct EnuCoor_f *p)
Returns squared horizontal distance to given point.
Definition navigation.c:308
bool rotwing_state_pusher_motor_running(void)
static void rotwing_state_feedback_cb(uint8_t sender_id, struct act_feedback_t *feedback_msg, uint8_t num_act)
#define ROTWING_RPM_TIMEOUT
#define ROTWING_SKEW_REF_MODEL_MAX_DIFF
bool rotwing_state_hover_motors_running(void)
#define ROTWING_FW_STALL_TIMEOUT
#define GUIDANCE_INDI_QUAD_DESCEND_SPEED
Descend speed when navigation is doing direct lines.
#define ROTWING_SKEW_SWEEP_MAX
#define ROTWING_FW_SKEW_ANGLE
#define ROTWING_TRANSITION_MAX_BANK
#define ROTWING_MIN_AIRSPEED_SLOPE_START_ANGLE
static void rotwing_state_skew_sweep(bool run, float time)
Sweep the skew angle setpoint between skew_sweep.min_deg and skew_sweep.max_deg at skew_sweep....
#define ROTWING_STATE_MIN_FW_DIST
#define GUIDANCE_INDI_FWD_DESCEND_SPEED
Descend speed when navigation is making turns instead of direct lines.
void rotwing_state_init(void)
#define ROTWING_PUSH_MIN_RPM
#define ROTWING_TRANSITION_MAX_DESCEND_SPEED
#define GUIDANCE_INDI_QUAD_CLIMB_SPEED
Climb speed when navigation is doing direct lines.
#define ROTWING_TRANSITION_MAX_CLIMB_SPEED
bool rotwing_state_hover_motors_idling(void)
Check if hover motors are idling (COMMAND_THRUST < ROTWING_QUAD_IDLE_MIN_THRUST) for ROTWING_QUAD_IDL...
#define GUIDANCE_INDI_FWD_CLIMB_SPEED
Climb speed when navigation is making turns instead of direct lines.
#define ROTWING_SKEW_BACK_MARGIN
#define SERVO_BMOTOR_PUSH_IDX
#define ROTWING_SKEW_SWEEP_FREQ
bool rotwing_state_skew_angle_valid(void)
#define ROTWING_SKEW_SWEEP_MIN
#define ROTWING_QUAD_IDLE_MIN_THRUST
#define SERVO_BROTATION_MECH_IDX
#define ROTWING_QUAD_SKEW_ANGLE
#define ROTWING_QUAD_MIN_RPM
static void send_rotating_wing_state(struct transport_tx *trans, struct link_device *dev)
bool rotwing_state_choose_state_by_dist(uint8_t wp_id)
#define ROTWING_STATE_ACT_FEEDBACK_ID
ABI binding feedback data.
abi_event rotwing_state_feedback_ev
#define ROTWING_QUAD_IDLE_TIMEOUT
bool rotwing_state_choose_circle_direction(uint8_t wp_id)
struct rotwing_state_t rotwing_state
void rotwing_state_periodic(void)
void rotwing_state_set(enum rotwing_states_t state)
enum rotwing_states_t state
int32_t meas_rpm[5]
float meas_skew_angle_time
float meas_rpm_time[5]
float ref_model_skew_angle_deg
struct rotwing_state_t::@315 skew_sweep
float meas_skew_angle_deg
#define ROTWING_SKEW_ANGLE_STEP
rotwing_states_t
@ ROTWING_STATE_FREE
@ ROTWING_STATE_REQUEST_HOVER
@ ROTWING_STATE_FORCE_FW
@ ROTWING_STATE_FORCE_HOVER
@ ROTWING_STATE_REQUEST_FW
enum rotwing_states_t nav_state
static const ShellCommand commands[]
Definition shell_arch.c:77
struct Stabilization stabilization
uint8_t mode
current mode
#define STABILIZATION_MODE_ATTITUDE
uint8_t att_submode
current attitude sub-mode
#define STABILIZATION_ATT_SUBMODE_FORWARD
int32_t cmd[COMMANDS_NB]
output command vector, range from [-MAX_PPRZ:MAX_PPRZ] (store for messages)
#define STABILIZATION_MODE_NONE
Stabilization modes.
int16_t actuators_pprz[INDI_NUM_ACT+1]
PPRZ command to each actuator Can be used to directly control actuators from the control algorithm if...
static float get_sys_time_float(void)
Get the time in seconds since startup.
Definition sys_time.h:174
int16_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint16_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition telemetry.c:51
Periodic telemetry system header (includes downlink utility and generated code).
#define DefaultPeriodic
Set default periodic telemetry.
Definition telemetry.h:66
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.