Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
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 
32 #include "modules/core/abi.h"
33 
34 /* Minimum measured RPM to consider the hover motors running (RPM) */
35 #ifndef ROTWING_QUAD_MIN_RPM
36 #define ROTWING_QUAD_MIN_RPM 400
37 #endif
38 
39 /* Minimum measured RPM to consider the pusher motor running (RPM) */
40 #ifndef ROTWING_PUSH_MIN_RPM
41 #define ROTWING_PUSH_MIN_RPM 300
42 #endif
43 
44 /* Timeout for the RPM feedback (seconds) */
45 #ifndef ROTWING_RPM_TIMEOUT
46 #define ROTWING_RPM_TIMEOUT 1.0
47 #endif
48 
49 /* Minimum thrust to consider the hover motors idling (PPRZ) */
50 #ifndef ROTWING_QUAD_IDLE_MIN_THRUST
51 #define ROTWING_QUAD_IDLE_MIN_THRUST 100
52 #endif
53 
54 /* Minimum time for the hover motors to be considered idling (seconds) */
55 #ifndef ROTWING_QUAD_IDLE_TIMEOUT
56 #define ROTWING_QUAD_IDLE_TIMEOUT 0.4
57 #endif
58 
59 /* Minimum measured skew angle to consider the rotating wing in fixedwing (deg) */
60 #ifndef ROTWING_FW_SKEW_ANGLE
61 #define ROTWING_FW_SKEW_ANGLE 85.0
62 #endif
63 
64 /* Magnitude skew angle jump away from quad */
65 #ifndef ROTWING_SKEW_ANGLE_STEP
66 #define ROTWING_SKEW_ANGLE_STEP 55.0
67 #endif
68 
69 /* TODO: Give a name.... */
70 #ifndef ROTWING_SKEW_BACK_MARGIN
71 #define ROTWING_SKEW_BACK_MARGIN 5.0
72 #endif
73 
74 /* Maximum angle difference between the measured skew and modelled skew for skew failure detection */
75 #ifndef ROTWING_SKEW_REF_MODEL_MAX_DIFF
76 #define ROTWING_SKEW_REF_MODEL_MAX_DIFF 5.f
77 #endif
78 
79 /* Skew angle at which the mininum airspeed starts its linear portion */
80 #ifndef ROTWING_MIN_AIRSPEED_SLOPE_START_ANGLE
81 #define ROTWING_MIN_AIRSPEED_SLOPE_START_ANGLE 30.0
82 #endif
83 
84 /* Preferred pitch angle for the quad mode (deg) */
85 #ifndef ROTWING_QUAD_PREF_PITCH
86 #define ROTWING_QUAD_PREF_PITCH -5.0
87 #endif
88 
89 /* Amount of time the airspeed needs to be below the FW_MIN_AIRSPEED */
90 #ifndef ROTWING_FW_STALL_TIMEOUT
91 #define ROTWING_FW_STALL_TIMEOUT 0.5
92 #endif
93 
94 /* Fix for not having double can busses */
95 #ifndef SERVO_BMOTOR_PUSH_IDX
96 #define SERVO_BMOTOR_PUSH_IDX SERVO_MOTOR_PUSH_IDX
97 #endif
98 
99 /* Fix for not having double can busses */
100 #ifndef SERVO_BROTATION_MECH_IDX
101 #define SERVO_BROTATION_MECH_IDX SERVO_ROTATION_MECH_IDX
102 #endif
103 
105 #ifndef ROTWING_STATE_ACT_FEEDBACK_ID
106 #define ROTWING_STATE_ACT_FEEDBACK_ID ABI_BROADCAST
107 #endif
109 static void rotwing_state_feedback_cb(uint8_t sender_id, struct act_feedback_t *feedback_msg, uint8_t num_act);
110 
111 static bool rotwing_state_hover_motors_idling(void);
112 static const float Wu_gih_original[GUIDANCE_INDI_HYBRID_U] = GUIDANCE_INDI_WLS_WU;
114 
115 inline void guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle);
116 
117 #if PERIODIC_TELEMETRY
119 static void send_rotating_wing_state(struct transport_tx *trans, struct link_device *dev)
120 {
121  // Set the status
123  status.value = 0;
124  status.skew_angle_valid = rotwing_state_skew_angle_valid();
125  status.hover_motors_enabled = rotwing_state.hover_motors_enabled;
126  status.hover_motors_idle = rotwing_state_hover_motors_idling();
127  status.hover_motors_running = rotwing_state_hover_motors_running();
128  status.pusher_motor_running = rotwing_state_pusher_motor_running();
129  status.skew_forced = rotwing_state.force_skew;
130 
131  // Send the message
133  uint8_t nav_state = rotwing_state.nav_state;
134  pprz_msg_send_ROTATING_WING_STATE(trans, dev, AC_ID,
135  &state,
136  &nav_state,
137  &status.value,
143 }
144 #endif // PERIODIC_TELEMETRY
145 
147 {
148  // Initialize rotwing state
152  rotwing_state.fw_min_airspeed = ROTWING_FW_MIN_AIRSPEED;
153  rotwing_state.cruise_airspeed = ROTWING_FW_CRUISE_AIRSPEED;
158  rotwing_state.force_skew = false;
159  for (int i = 0; i < 5; i++) {
160  rotwing_state.meas_rpm[i] = 0;
162  }
167 
168  // Bind ABI messages
170 
171 #if PERIODIC_TELEMETRY
172  register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_ROTATING_WING_STATE, send_rotating_wing_state);
173 #endif
174 }
175 
181  static float last_idle_time = 0;
182  // Check if hover motors are idling and reset timer
183  if(stabilization.cmd[COMMAND_THRUST] > ROTWING_QUAD_IDLE_MIN_THRUST) {
184  last_idle_time = get_sys_time_float();
185  }
186 
187  // Check if we exceeded the idle timeout
188  if(get_sys_time_float() - last_idle_time > ROTWING_QUAD_IDLE_TIMEOUT) {
189  return true;
190  }
191  return false;
192 }
193 
195 {
196  /* Get some genericly used variables */
197  static float last_stall_time = 0;
198  float current_time = get_sys_time_float();
199  float meas_airspeed = stateGetAirspeed_f();
200  float meas_skew_angle = rotwing_state.meas_skew_angle_deg;
201  Bound(meas_skew_angle, 0, 90); // Bound to prevent errors
202 
203  if(meas_airspeed > rotwing_state.fw_min_airspeed) {
204  last_stall_time = current_time;
205  }
206 
207  /* Override modes if flying with RC */
210  // Kill mode
213  }
214  // ATT and ATT_FWD
218  } else {
220  }
221  }
222  }
223 
224  /* Handle the quad motors on/off state */
227  }
228  else if((current_time - last_stall_time) < ROTWING_FW_STALL_TIMEOUT && rotwing_state_hover_motors_idling() && rotwing_state_pusher_motor_running() && meas_skew_angle >= ROTWING_FW_SKEW_ANGLE
231  }
232  else {
234  }
235 
236 
237  /* Calculate min/max airspeed bounds based on skew angle */
238  float skew_min_airspeed = ROTWING_FW_QUAD_MIN_AIRSPEED * (meas_skew_angle - ROTWING_MIN_AIRSPEED_SLOPE_START_ANGLE) / (90.f - ROTWING_MIN_AIRSPEED_SLOPE_START_ANGLE);
239  float skew_max_airspeed = ROTWING_QUAD_MAX_AIRSPEED + (ROTWING_FW_MAX_AIRSPEED - ROTWING_QUAD_MAX_AIRSPEED) * meas_skew_angle / ROTWING_FW_SKEW_ANGLE;
240  Bound(skew_min_airspeed, 0, rotwing_state.fw_min_airspeed);
241  Bound(skew_max_airspeed, ROTWING_QUAD_MAX_AIRSPEED, ROTWING_FW_MAX_AIRSPEED);
242 
244  skew_min_airspeed = rotwing_state.fw_min_airspeed;
245  skew_max_airspeed = ROTWING_FW_MAX_AIRSPEED;
246  }
247 
248 
249  /* Handle the skew angle setpoint */
251  // Do nothing
252  }
255  }
258  }
261  }
264  }
265  else {
266  // SKEWING function based on Vair
267  if (meas_airspeed < ROTWING_SKEW_DOWN_AIRSPEED) {
269  } else if (meas_airspeed < ROTWING_SKEW_UP_AIRSPEED) {
270  // Hysteresis do nothing
271  } else if (meas_airspeed < ROTWING_QUAD_MAX_AIRSPEED) {
273  } else {
274  rotwing_state.sp_skew_angle_deg = ((meas_airspeed - ROTWING_QUAD_MAX_AIRSPEED)) / (rotwing_state.fw_min_airspeed - ROTWING_QUAD_MAX_AIRSPEED) * (90.f - ROTWING_SKEW_ANGLE_STEP) + ROTWING_SKEW_ANGLE_STEP;
275  }
276  }
277  Bound(rotwing_state.sp_skew_angle_deg, 0.f, 90.f);
278 
279 
280  /* Handle the airspeed bounding */
281  Bound(rotwing_state.cruise_airspeed, rotwing_state.fw_min_airspeed, ROTWING_FW_MAX_AIRSPEED);
285  }
288  rotwing_state.max_airspeed = ROTWING_QUAD_NOPUSH_AIRSPEED;
289  }
291  rotwing_state.min_airspeed = skew_min_airspeed;
292  rotwing_state.max_airspeed = fmax(ROTWING_QUAD_MAX_AIRSPEED, skew_min_airspeed);
293  }
295  rotwing_state.min_airspeed = fmin(rotwing_state.cruise_airspeed, skew_max_airspeed);
296  rotwing_state.max_airspeed = fmin(rotwing_state.cruise_airspeed, skew_max_airspeed);
297  }
298  else{
299  rotwing_state.min_airspeed = skew_min_airspeed;
300  rotwing_state.max_airspeed = skew_max_airspeed;
301  }
302 
303  // Override failing skewing while fwd
304  /*if(meas_skew_angle > 70 && rotwing_state_.skewing_failing) {
305  rotwing_state.min_airspeed = 0; // Vstall + margin
306  rotwing_state.max_airspeed = 0; // Max airspeed FW
307  }*/
308 
310 
311 
312  /* Set navigation/guidance settings */
313  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?
314 
315 
316  /* Calculate the skew command */
317  float servo_pprz_cmd = MAX_PPRZ * (rotwing_state.sp_skew_angle_deg - 45.f) / 45.f;
318  BoundAbs(servo_pprz_cmd, MAX_PPRZ);
319 
320  // Rotate with second order filter
321  static float rotwing_state_skew_p_cmd = -MAX_PPRZ;
322  static float rotwing_state_skew_d_cmd = 0;
323 
324  float speed_sp = ROTWING_SKEW_REF_MODEL_P_GAIN * (servo_pprz_cmd - rotwing_state_skew_p_cmd);
325  BoundAbs(speed_sp, ROTWING_SKEW_REF_MODEL_MAX_SPEED);
326  rotwing_state_skew_d_cmd += ROTWING_SKEW_REF_MODEL_D_GAIN * (speed_sp - rotwing_state_skew_d_cmd);
327  rotwing_state_skew_p_cmd += rotwing_state_skew_d_cmd;
328  BoundAbs(rotwing_state_skew_p_cmd, MAX_PPRZ);
329  rotwing_state.ref_model_skew_angle_deg = 45.0 / MAX_PPRZ * rotwing_state_skew_p_cmd + 45.0;
330 
331 #if (ROTWING_SKEW_REF_MODEL || USE_NPS)
332  rotwing_state.skew_cmd = rotwing_state_skew_p_cmd;
333 #else
334  rotwing_state.skew_cmd = servo_pprz_cmd;
335 #endif
336 
337 
338  /* Add simulation feedback for the skewing and RPM */
339 #if USE_NPS
340  // Export to the index of the SKEW in the NPS_ACTUATOR_NAMES array
341  actuators_pprz[INDI_NUM_ACT] = (rotwing_state.skew_cmd + MAX_PPRZ) / 2.f; // Scale to simulation command
342 
343  // SEND ABI Message to ctr_eff_sched, ourself and other modules that want Actuator position feedback
344  struct act_feedback_t feedback;
345  feedback.idx = SERVO_ROTATION_MECH_IDX;
346  feedback.position = 0.5f * M_PI - RadOfDeg((float) rotwing_state.skew_cmd / MAX_PPRZ * 45.f + 45.f);
347  feedback.set.position = true;
348 
349  // Send ABI message (or simulate failure)
351  AbiSendMsgACT_FEEDBACK(ACT_FEEDBACK_BOARD_ID, &feedback, 1);
352  }
353 
354  // Simulate to always have RPM if on and active feedback
355  rotwing_state.meas_rpm[0] = (actuators[SERVO_MOTOR_FRONT_IDX].pprz_val >= 0)? (ROTWING_QUAD_MIN_RPM + 100) : 0;
356  rotwing_state.meas_rpm[1] = (actuators[SERVO_MOTOR_RIGHT_IDX].pprz_val >= 0)? (ROTWING_QUAD_MIN_RPM + 100) : 0;
357  rotwing_state.meas_rpm[2] = (actuators[SERVO_MOTOR_BACK_IDX].pprz_val >= 0)? (ROTWING_QUAD_MIN_RPM + 100) : 0;
358  rotwing_state.meas_rpm[3] = (actuators[SERVO_MOTOR_LEFT_IDX].pprz_val >= 0)? (ROTWING_QUAD_MIN_RPM + 100) : 0;
359  rotwing_state.meas_rpm[4] = (actuators[SERVO_MOTOR_PUSH_IDX].pprz_val >= 0)? (ROTWING_PUSH_MIN_RPM + 100) : 0;
360  for(uint8_t i = 0; i < 5; i++) {
361  rotwing_state.meas_rpm_time[i] = current_time;
362  }
363 
364 #ifdef SITL
366  rotwing_state.meas_rpm[0] = 0;
367  rotwing_state.meas_rpm[1] = 0;
368  rotwing_state.meas_rpm[2] = 0;
369  rotwing_state.meas_rpm[3] = 0;
370  }
371 
373  rotwing_state.meas_rpm[4] = 0;
374  }
375 #endif
376 
377 #endif
378 }
379 
380 static void rotwing_state_feedback_cb(uint8_t __attribute__((unused)) sender_id,
381  struct act_feedback_t UNUSED *feedback_msg, uint8_t UNUSED num_act_message)
382 {
383  float current_time = get_sys_time_float();
384  for (int i = 0; i < num_act_message; i++) {
385  int idx = feedback_msg[i].idx;
386 
387  // Check for wing rotation feedback
388  if ((feedback_msg[i].set.position) && (idx == SERVO_ROTATION_MECH_IDX || idx == SERVO_BROTATION_MECH_IDX)) {
389  // Get wing rotation angle from sensor
390  float skew_angle_rad = 0.5 * M_PI - feedback_msg[i].position;
391  rotwing_state.meas_skew_angle_deg = DegOfRad(skew_angle_rad);
392  rotwing_state.meas_skew_angle_time = current_time;
393  }
394 
395  // Get the RPM feedbacks of the motors
396  if (feedback_msg[i].set.rpm) {
397  if ((idx == SERVO_MOTOR_FRONT_IDX) || (idx == SERVO_BMOTOR_FRONT_IDX)) {
398  rotwing_state.meas_rpm[0] = feedback_msg->rpm;
399  rotwing_state.meas_rpm_time[0] = current_time;
400  } else if ((idx == SERVO_MOTOR_RIGHT_IDX) || (idx == SERVO_BMOTOR_RIGHT_IDX)) {
401  rotwing_state.meas_rpm[1] = feedback_msg->rpm;
402  rotwing_state.meas_rpm_time[1] = current_time;
403  } else if ((idx == SERVO_MOTOR_BACK_IDX) || (idx == SERVO_BMOTOR_BACK_IDX)) {
404  rotwing_state.meas_rpm[2] = feedback_msg->rpm;
405  rotwing_state.meas_rpm_time[2] = current_time;
406  } else if ((idx == SERVO_MOTOR_LEFT_IDX) || (idx == SERVO_BMOTOR_LEFT_IDX)) {
407  rotwing_state.meas_rpm[3] = feedback_msg->rpm;
408  rotwing_state.meas_rpm_time[3] = current_time;
409  } else if ((idx == SERVO_MOTOR_PUSH_IDX) || (idx == SERVO_BMOTOR_PUSH_IDX)) {
410  rotwing_state.meas_rpm[4] = feedback_msg->rpm;
411  rotwing_state.meas_rpm_time[4] = current_time;
412  }
413  }
414  }
415 }
416 
418  float current_time = get_sys_time_float();
419  // Check if hover motors are running
424  && (current_time - rotwing_state.meas_rpm_time[0]) < ROTWING_RPM_TIMEOUT
425  && (current_time - rotwing_state.meas_rpm_time[1]) < ROTWING_RPM_TIMEOUT
426  && (current_time - rotwing_state.meas_rpm_time[2]) < ROTWING_RPM_TIMEOUT
427  && (current_time - rotwing_state.meas_rpm_time[3]) < ROTWING_RPM_TIMEOUT) {
428  return true;
429  } else {
430  return false;
431  }
432 }
433 
435  // Check if pusher motor is running
437  return true;
438  } else {
439  return false;
440  }
441 }
442 
444  // Check if the measured skew angle is timed out and the reference model is matching
447 
448  return (!skew_timeout && skew_angle_match);
449 }
450 
451 void guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle)
452 {
453  // adjust weights
454  float fixed_wing_percentile = (rotwing_state_hover_motors_idling())? 1:0; // TODO: when hover props go below 40%, ...
455  Bound(fixed_wing_percentile, 0, 1);
456 #define AIRSPEED_IMPORTANCE_IN_FORWARD_WEIGHT 16
457 
458  float Wv_original[GUIDANCE_INDI_HYBRID_V] = GUIDANCE_INDI_WLS_PRIORITIES;
459 
460  // Increase importance of forward acceleration in forward flight
461  wls_guid_p.Wv[0] = Wv_original[0] * (1.0f + fixed_wing_percentile *
462  AIRSPEED_IMPORTANCE_IN_FORWARD_WEIGHT); // stall n low hover motor_off (weight 16x more important than vertical weight)
463 
464  struct FloatEulers eulers_zxy;
466 
467  float du_min_thrust_z = ((MAX_PPRZ - actuator_state_filt_vect[0]) * g1g2[3][0] + (MAX_PPRZ -
470  Bound(du_min_thrust_z, -50., 0.);
471  float du_max_thrust_z = -(actuator_state_filt_vect[0] * g1g2[3][0] + actuator_state_filt_vect[1] * g1g2[3][1] +
473  Bound(du_max_thrust_z, 0., 50.);
474 
475  float roll_limit_rad = guidance_indi_max_bank;
476  float max_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MAX_PITCH);
477  float min_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MIN_PITCH);
478 
479  float fwd_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MAX_PITCH);
480  float quad_pitch_limit_rad = RadOfDeg(5.0);
481 
482  float airspeed = stateGetAirspeed_f();
483 
484  float scheduled_pitch_angle = 0.f;
485  float pitch_angle_range = 3.;
486  float meas_skew_angle = rotwing_state.meas_skew_angle_deg;
487  Bound(meas_skew_angle, 0, 90); // Bound to prevent errors
488  if (meas_skew_angle < ROTWING_SKEW_ANGLE_STEP) {
489  scheduled_pitch_angle = ROTWING_QUAD_PREF_PITCH;
490  wls_guid_p.Wu[1] = Wu_gih_original[1];
491  max_pitch_limit_rad = quad_pitch_limit_rad;
492  } else {
493  float pitch_progression = (airspeed - rotwing_state.fw_min_airspeed) / 2.f;
494  Bound(pitch_progression, 0.f, 1.f);
495  scheduled_pitch_angle = pitch_angle_range * pitch_progression + ROTWING_QUAD_PREF_PITCH*(1.f-pitch_progression);
496  wls_guid_p.Wu[1] = Wu_gih_original[1] * (1.f - pitch_progression*0.99);
497  max_pitch_limit_rad = quad_pitch_limit_rad + (fwd_pitch_limit_rad - quad_pitch_limit_rad) * pitch_progression;
498  }
500  scheduled_pitch_angle = 8.;
501  max_pitch_limit_rad = fwd_pitch_limit_rad;
502  }
503  Bound(scheduled_pitch_angle, -5., 8.);
504  guidance_indi_pitch_pref_deg = scheduled_pitch_angle;
505 
506  float pitch_pref_rad = RadOfDeg(guidance_indi_pitch_pref_deg);
507 
508  // Set lower limits
509  wls_guid_p.u_min[0] = -roll_limit_rad - roll_angle; //roll
510  wls_guid_p.u_min[1] = min_pitch_limit_rad - pitch_angle; // pitch
511 
512  // Set upper limits limits
513  wls_guid_p.u_max[0] = roll_limit_rad - roll_angle; //roll
514  wls_guid_p.u_max[1] = max_pitch_limit_rad - pitch_angle; // pitch
515 
517  wls_guid_p.u_min[2] = du_min_thrust_z;
518  wls_guid_p.u_max[2] = du_max_thrust_z;
519  } else {
520  wls_guid_p.u_min[2] = 0.;
521  wls_guid_p.u_max[2] = 0.;
522  }
523 
525  wls_guid_p.u_min[3] = (-actuator_state_filt_vect[8] * g1g2[4][8]);
526  wls_guid_p.u_max[3] = 9.0; // Hacky value to prevent drone from pitching down in transition
527  } else {
528  wls_guid_p.u_min[3] = 0.;
529  wls_guid_p.u_max[3] = 0.;
530  }
531 
532  // Set prefered states
533  wls_guid_p.u_pref[0] = 0; // prefered delta roll angle
534  wls_guid_p.u_pref[1] = -pitch_angle + pitch_pref_rad;// prefered delta pitch angle
535  wls_guid_p.u_pref[2] = wls_guid_p.u_max[2]; // Low thrust better for efficiency
536  wls_guid_p.u_pref[3] = body_v[0]; // solve the body acceleration
537 }
538 
541 }
542 
543 
544 /* TODO move these rotwing navigation helper functions to an appropriate module/file */
546  // Get circle waypoint coordinates in NED
547  struct FloatVect3 circ_ned = {.x = waypoints[wp_id].enu_f.y,
548  .y = waypoints[wp_id].enu_f.x,
549  .z = -waypoints[wp_id].enu_f.z};
550 
551  // Get drone position coordinates in NED
552  struct FloatVect3 pos_ned = {.x = stateGetPositionNed_f()->x,
553  .y = stateGetPositionNed_f()->y,
554  .z = stateGetPositionNed_f()->z};
555 
556  // Get vector pointing from drone to waypoint
557  struct FloatVect3 vect_pos_circ;
558  VECT3_DIFF(vect_pos_circ, circ_ned, pos_ned);
559 
560  static struct FloatVect3 x_axis = {.x = 1, .y = 0, .z = 0};
561  static struct FloatVect3 z_axis = {.x = 0, .y = 0, .z = 1};
562  struct FloatVect3 att_NED;
563  struct FloatVect3 cross_att_circ;
564 
565  float_rmat_transp_vmult(&att_NED, stateGetNedToBodyRMat_f(), &x_axis);
566 
567  VECT3_CROSS_PRODUCT(cross_att_circ, vect_pos_circ, att_NED);
568  float y = VECT3_DOT_PRODUCT(cross_att_circ, z_axis);
569  float x = VECT3_DOT_PRODUCT(vect_pos_circ, att_NED);
570 
571  float body_to_wp_angle_rad = atan2f(y, x);
572 
573  if (body_to_wp_angle_rad >= 0.f) {
574  return true; // CCW circle
575  } else {
576  return false; // CW circle
577  }
578 }
579 
581 
582  // Get drone position coordinates in NED
583  struct EnuCoor_f target_enu = {.x = stateGetPositionNed_f()->y,
584  .y = stateGetPositionNed_f()->x,
585  .z = -stateGetPositionNed_f()->z};
586 
587  static struct FloatVect3 x_axis = {.x = 1, .y = 0, .z = 0};
588  struct FloatVect3 x_att_NED;
589 
590  float_rmat_transp_vmult(&x_att_NED, stateGetNedToBodyRMat_f(), &x_axis);
591 
592  // set the new transition WP coordinates 100m ahead of the drone
593  target_enu.x = 100.f * x_att_NED.y + target_enu.x;
594  target_enu.y = 100.f * x_att_NED.x + target_enu.y;
595 
596  waypoint_set_enu(wp_id, &target_enu);
597 
598  // Send waypoint update every half second
599  RunOnceEvery(100 / 2, {
600  // Send to the GCS that the waypoint has been moved
601  DOWNLINK_SEND_WP_MOVED_ENU(DefaultChannel, DefaultDevice, &wp_id,
602  &waypoints[wp_id].enu_i.x,
603  &waypoints[wp_id].enu_i.y,
604  &waypoints[wp_id].enu_i.z);
605  });
606 
607 }
608 
609 void rotwing_state_update_WP_height(uint8_t wp_id, float height) {
610  struct EnuCoor_f target_enu = {.x = waypoints[wp_id].enu_f.x,
611  .y = waypoints[wp_id].enu_f.y,
612  .z = height};
613 
614  waypoint_set_enu(wp_id, &target_enu);
615 
616  DOWNLINK_SEND_WP_MOVED_ENU(DefaultChannel, DefaultDevice, &wp_id,
617  &waypoints[wp_id].enu_i.x,
618  &waypoints[wp_id].enu_i.y,
619  &waypoints[wp_id].enu_i.z);
620 }
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition: abi_common.h:67
#define ACT_FEEDBACK_BOARD_ID
uint8_t last_wp UNUSED
struct point waypoints[NB_WAYPOINT]
size == nb_waypoint, waypoint 0 is a dummy waypoint
Definition: common_nav.c:39
float y
Definition: common_nav.h:41
float x
Definition: common_nav.h:40
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
void float_rmat_transp_vmult(struct FloatVect3 *vb, struct FloatRMat *m_b2a, struct FloatVect3 *va)
rotate 3D vector by transposed rotation matrix.
euler angles
#define VECT3_CROSS_PRODUCT(_vo, _v1, _v2)
Definition: pprz_algebra.h:244
#define VECT3_DIFF(_c, _a, _b)
Definition: pprz_algebra.h:182
#define VECT3_DOT_PRODUCT(_v1, _v2)
Definition: pprz_algebra.h:250
static struct FloatRMat * stateGetNedToBodyRMat_f(void)
Get vehicle body attitude rotation matrix (float).
Definition: state.h:1137
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition: state.h:1131
struct State state
Definition: state.c:36
static struct NedCoor_f * stateGetPositionNed_f(void)
Get position in local NED coordinates (float).
Definition: state.h:710
static float stateGetAirspeed_f(void)
Get airspeed (float).
Definition: state.h:1407
float guidance_indi_max_bank
struct FloatVect3 speed_sp
Definition: guidance_indi.c:73
float guidance_indi_pitch_pref_deg
struct FloatEulers eulers_zxy
state eulers in zxy order
float gi_unbounded_airspeed_sp
void guidance_indi_set_min_max_airspeed(float min_airspeed, float max_airspeed)
A guidance mode based on Incremental Nonlinear Dynamic Inversion Come to ICRA2016 to learn more!
#define GUIDANCE_INDI_MAX_PITCH
#define GUIDANCE_INDI_MIN_PITCH
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 position
In radians.
Definition: actuators.h:52
void waypoint_set_enu(uint8_t wp_id, struct EnuCoor_f *enu)
Set local ENU waypoint coordinates.
Definition: waypoints.c:177
float nav_max_deceleration_sp
static uint32_t idx
uint8_t status
#define MAX_PPRZ
Definition: paparazzi.h:8
float y
in meters
float x
in meters
float z
in meters
float x
in meters
float y
in meters
vector in East North Up coordinates Units: meters
Rotorcraft specific autopilot interface and initialization.
struct HorizontalGuidance guidance_h
Definition: guidance_h.c:45
#define GUIDANCE_H_MODE_NONE
Definition: guidance_h.h:56
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
Definition: rotwing_state.c:46
#define ROTWING_SKEW_REF_MODEL_MAX_DIFF
Definition: rotwing_state.c:76
#define ROTWING_QUAD_PREF_PITCH
Definition: rotwing_state.c:86
bool rotwing_state_hover_motors_running(void)
#define ROTWING_FW_STALL_TIMEOUT
Definition: rotwing_state.c:91
#define ROTWING_FW_SKEW_ANGLE
Definition: rotwing_state.c:61
#define ROTWING_MIN_AIRSPEED_SLOPE_START_ANGLE
Definition: rotwing_state.c:81
void rotwing_state_init(void)
#define ROTWING_PUSH_MIN_RPM
Definition: rotwing_state.c:41
static const float Wu_gih_original[GUIDANCE_INDI_HYBRID_U]
#define ROTWING_SKEW_BACK_MARGIN
Definition: rotwing_state.c:71
#define SERVO_BMOTOR_PUSH_IDX
Definition: rotwing_state.c:96
#define AIRSPEED_IMPORTANCE_IN_FORWARD_WEIGHT
bool rotwing_state_skew_angle_valid(void)
#define ROTWING_QUAD_IDLE_MIN_THRUST
Definition: rotwing_state.c:51
#define SERVO_BROTATION_MECH_IDX
#define ROTWING_QUAD_MIN_RPM
Definition: rotwing_state.c:36
static void send_rotating_wing_state(struct transport_tx *trans, struct link_device *dev)
static bool rotwing_state_hover_motors_idling(void)
Check if hover motors are idling (COMMAND_THRUST < ROTWING_QUAD_IDLE_MIN_THRUST) for ROTWING_QUAD_IDL...
void rotwing_state_set_transition_wp(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
Definition: rotwing_state.c:56
bool rotwing_state_choose_circle_direction(uint8_t wp_id)
#define ROTWING_SKEW_ANGLE_STEP
Definition: rotwing_state.c:66
struct rotwing_state_t rotwing_state
void guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle)
void rotwing_state_periodic(void)
void rotwing_state_update_WP_height(uint8_t wp_id, float height)
void rotwing_state_set(enum rotwing_states_t state)
enum rotwing_states_t state
Definition: rotwing_state.h:53
int32_t meas_rpm[5]
Definition: rotwing_state.h:72
float meas_skew_angle_time
Definition: rotwing_state.h:61
float meas_rpm_time[5]
Definition: rotwing_state.h:73
bool hover_motors_enabled
Definition: rotwing_state.h:55
float ref_model_skew_angle_deg
Definition: rotwing_state.h:59
float sp_skew_angle_deg
Definition: rotwing_state.h:58
float meas_skew_angle_deg
Definition: rotwing_state.h:60
rotwing_states_t
Definition: rotwing_state.h:31
@ ROTWING_STATE_FREE
Definition: rotwing_state.h:36
@ ROTWING_STATE_REQUEST_HOVER
Definition: rotwing_state.h:33
@ ROTWING_STATE_FORCE_FW
Definition: rotwing_state.h:34
@ ROTWING_STATE_FORCE_HOVER
Definition: rotwing_state.h:32
@ ROTWING_STATE_REQUEST_FW
Definition: rotwing_state.h:35
enum rotwing_states_t nav_state
Definition: rotwing_state.h:54
struct Stabilization stabilization
Definition: stabilization.c:41
uint8_t mode
current mode
#define STABILIZATION_MODE_ATTITUDE
Definition: stabilization.h:41
uint8_t att_submode
current attitude sub-mode
#define STABILIZATION_ATT_SUBMODE_FORWARD
Definition: stabilization.h:47
int32_t cmd[COMMANDS_NB]
output command vector, range from [-MAX_PPRZ:MAX_PPRZ] (store for messages)
#define STABILIZATION_MODE_NONE
Stabilization modes.
Definition: stabilization.h:38
float g1g2[INDI_OUTPUTS][INDI_NUM_ACT]
float actuator_state_filt_vect[INDI_NUM_ACT]
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:74
static float get_sys_time_float(void)
Get the time in seconds since startup.
Definition: sys_time.h:138
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_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.
Definition: vl53l1_types.h:98