Paparazzi UAS  v5.8.2_stable-0-g6260b7c
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
formation.c
Go to the documentation of this file.
1 
5 #define FORMATION_C
6 
7 #include <math.h>
8 
10 
11 #include "multi/formation.h"
12 #include "state.h"
15 #include "autopilot.h"
16 #include "subsystems/gps.h"
17 #include "generated/flight_plan.h"
18 #include "generated/airframe.h"
19 #include "dl_protocol.h"
20 
21 #include <stdio.h>
22 
25 
27 float form_prox;
35 
37 
38 #ifndef FORM_CARROT
39 #define FORM_CARROT 2.
40 #endif
41 
42 #ifndef FORM_POS_PGAIN
43 #define FORM_POS_PGAIN 0.
44 #endif
45 
46 #ifndef FORM_SPEED_PGAIN
47 #define FORM_SPEED_PGAIN 0.
48 #endif
49 
50 #ifndef FORM_COURSE_PGAIN
51 #define FORM_COURSE_PGAIN 0.
52 #endif
53 
54 #ifndef FORM_ALTITUDE_PGAIN
55 #define FORM_ALTITUDE_PGAIN 0.
56 #endif
57 
58 #ifndef FORM_PROX
59 #define FORM_PROX 20.
60 #endif
61 
62 #ifndef FORM_MODE
63 #define FORM_MODE 0
64 #endif
65 
66 int formation_init(void)
67 {
68  int i;
69  for (i = 0; i < NB_ACS; ++i) { formation[i].status = UNSET; }
70 
71  leader_id = 0;
79  old_cruise = V_CTL_AUTO_THROTTLE_NOMINAL_CRUISE_THROTTLE;
80  old_alt = GROUND_ALT + SECURITY_HEIGHT;
81  return FALSE;
82 }
83 
84 int add_slot(uint8_t _id, float slot_e, float slot_n, float slot_a)
85 {
86  if (_id != AC_ID && the_acs_id[_id] == 0) { return FALSE; } // no info for this AC
87  DOWNLINK_SEND_FORMATION_SLOT_TM(DefaultChannel, DefaultDevice, &_id, &form_mode, &slot_e, &slot_n, &slot_a);
89  formation[the_acs_id[_id]].east = slot_e;
90  formation[the_acs_id[_id]].north = slot_n;
91  formation[the_acs_id[_id]].alt = slot_a;
92  return FALSE;
93 }
94 
95 int start_formation(void)
96 {
97  uint8_t i;
98  uint8_t ac_id = AC_ID;
99  for (i = 0; i < NB_ACS; ++i) {
100  if (formation[i].status == IDLE) { formation[i].status = ACTIVE; }
101  }
102  uint8_t active = ACTIVE;
103  DOWNLINK_SEND_FORMATION_STATUS_TM(DefaultChannel, DefaultDevice, &ac_id, &leader_id, &active);
104  // store current cruise and alt
107  return FALSE;
108 }
109 
110 int stop_formation(void)
111 {
112  uint8_t i;
113  uint8_t ac_id = AC_ID;
114  for (i = 0; i < NB_ACS; ++i) {
115  if (formation[i].status == ACTIVE) { formation[i].status = IDLE; }
116  }
117  uint8_t idle = IDLE;
118  DOWNLINK_SEND_FORMATION_STATUS_TM(DefaultChannel, DefaultDevice, &ac_id, &leader_id, &idle);
119  // restore cruise and alt
121  old_cruise = V_CTL_AUTO_THROTTLE_NOMINAL_CRUISE_THROTTLE;
123  old_alt = GROUND_ALT + SECURITY_HEIGHT;
124  return FALSE;
125 }
126 
127 
129 {
130 
131  static uint8_t _1Hz = 0;
132  uint8_t nb = 0, i;
133  float hspeed_dir = stateGetHorizontalSpeedDir_f();
134  float ch = cosf(hspeed_dir);
135  float sh = sinf(hspeed_dir);
136  form_n = 0.;
137  form_e = 0.;
138  form_a = 0.;
140  form_speed_n = form_speed * ch;
141  form_speed_e = form_speed * sh;
142 
143  if (AC_ID == leader_id) {
146  }
147  // set info for this AC
148  SetAcInfo(AC_ID, stateGetPositionEnu_f()->x, stateGetPositionEnu_f()->y, hspeed_dir,
150 
151  // broadcast info
152  uint8_t ac_id = AC_ID;
154  DOWNLINK_SEND_FORMATION_STATUS_TM(DefaultChannel, DefaultDevice, &ac_id, &leader_id, &status);
155  if (++_1Hz >= 4) {
156  _1Hz = 0;
157  DOWNLINK_SEND_FORMATION_SLOT_TM(DefaultChannel, DefaultDevice, &ac_id, &form_mode,
158  &formation[the_acs_id[AC_ID]].east,
159  &formation[the_acs_id[AC_ID]].north,
160  &formation[the_acs_id[AC_ID]].alt);
161  }
162  if (formation[the_acs_id[AC_ID]].status != ACTIVE) { return FALSE; } // AC not ready
163 
164  // get leader info
165  struct ac_info_ * leader = get_ac_info(leader_id);
166  if (formation[the_acs_id[leader_id]].status == UNSET ||
167  formation[the_acs_id[leader_id]].status == IDLE) {
168  // leader not ready or not in formation
169  return FALSE;
170  }
171 
172  // compute slots in the right reference frame
173  struct slot_ form[NB_ACS];
174  float cr = 0., sr = 1.;
175  if (form_mode == FORM_MODE_COURSE) {
176  cr = cosf(leader->course);
177  sr = sinf(leader->course);
178  }
179  for (i = 0; i < NB_ACS; ++i) {
180  if (formation[i].status == UNSET) { continue; }
181  form[i].east = formation[i].east * sr - formation[i].north * cr;
182  form[i].north = formation[i].east * cr + formation[i].north * sr;
183  form[i].alt = formation[i].alt;
184  }
185 
186  // compute control forces
187  for (i = 0; i < NB_ACS; ++i) {
188  if (the_acs[i].ac_id == AC_ID) { continue; }
189  struct ac_info_ * ac = get_ac_info(the_acs[i].ac_id);
190  float delta_t = Max((int)(gps.tow - ac->itow) / 1000., 0.);
191  if (delta_t > FORM_CARROT) {
192  // if AC not responding for too long
193  formation[i].status = LOST;
194  continue;
195  } else {
196  // compute control if AC is ACTIVE and around the same altitude (maybe not so usefull)
197  formation[i].status = ACTIVE;
198  if (ac->alt > 0 && fabs(stateGetPositionUtm_f()->alt - ac->alt) < form_prox) {
199  form_e += (ac->east + ac->gspeed * sinf(ac->course) * delta_t - stateGetPositionEnu_f()->x)
200  - (form[i].east - form[the_acs_id[AC_ID]].east);
201  form_n += (ac->north + ac->gspeed * cosf(ac->course) * delta_t - stateGetPositionEnu_f()->y)
202  - (form[i].north - form[the_acs_id[AC_ID]].north);
203  form_a += (ac->alt - stateGetPositionUtm_f()->alt) - (formation[i].alt - formation[the_acs_id[AC_ID]].alt);
204  form_speed += ac->gspeed;
205  //form_speed_e += ac->gspeed * sinf(ac->course);
206  //form_speed_n += ac->gspeed * cosf(ac->course);
207  ++nb;
208  }
209  }
210  }
211  uint8_t _nb = Max(1, nb);
212  form_n /= _nb;
213  form_e /= _nb;
214  form_a /= _nb;
216  //form_speed_e = form_speed_e / (nb+1) - stateGetHorizontalSpeedNorm_f() * sh;
217  //form_speed_n = form_speed_n / (nb+1) - stateGetHorizontalSpeedNorm_f() * ch;
218 
219  // set commands
221 
222  // altitude loop
223  float alt = 0.;
224  if (AC_ID == leader_id) {
225  alt = nav_altitude;
226  } else {
227  alt = leader->alt - form[the_acs_id[leader_id]].alt;
228  }
229  alt += formation[the_acs_id[AC_ID]].alt + coef_form_alt * form_a;
230  flight_altitude = Max(alt, ground_alt + SECURITY_HEIGHT);
231 
232  // carrot
233  if (AC_ID != leader_id) {
234  float dx = form[the_acs_id[AC_ID]].east - form[the_acs_id[leader_id]].east;
235  float dy = form[the_acs_id[AC_ID]].north - form[the_acs_id[leader_id]].north;
236  desired_x = leader->east + NOMINAL_AIRSPEED * form_carrot * sinf(leader->course) + dx;
237  desired_y = leader->north + NOMINAL_AIRSPEED * form_carrot * cosf(leader->course) + dy;
238  // fly to desired
240  desired_x = leader->east + dx;
241  desired_y = leader->north + dy;
242  // lateral correction
243  //float diff_heading = asin((dx*ch - dy*sh) / sqrt(dx*dx + dy*dy));
244  //float diff_course = leader->course - hspeed_dir;
245  //NormRadAngle(diff_course);
246  //h_ctl_roll_setpoint += coef_form_course * diff_course;
247  //h_ctl_roll_setpoint += coef_form_course * diff_heading;
248  }
249  //BoundAbs(h_ctl_roll_setpoint, h_ctl_roll_max_setpoint);
250 
251  // speed loop
252  if (nb > 0) {
253  float cruise = V_CTL_AUTO_THROTTLE_NOMINAL_CRUISE_THROTTLE;
254  cruise += coef_form_pos * (form_n * ch + form_e * sh) + coef_form_speed * form_speed;
255  Bound(cruise, V_CTL_AUTO_THROTTLE_MIN_CRUISE_THROTTLE, V_CTL_AUTO_THROTTLE_MAX_CRUISE_THROTTLE);
257  }
258  return TRUE;
259 }
260 
262 {
263  if (leader_id == AC_ID) {
266  }
267 }
268 
uint8_t ac_id
Definition: sim_ap.c:47
status
Definition: anemotaxis.c:10
float old_alt
Definition: formation.c:34
uint8_t leader_id
Definition: formation.c:33
static float stateGetHorizontalSpeedNorm_f(void)
Get norm of horizontal ground speed (float).
Definition: state.h:912
uint8_t the_acs_id[NB_ACS_ID]
Definition: traffic_info.c:34
struct ac_info_ the_acs[NB_ACS]
Definition: traffic_info.c:35
float alt
in meters above WGS84 reference ellipsoid
int start_formation(void)
Definition: formation.c:95
float form_n
Definition: formation.c:23
float form_prox
Definition: formation.c:27
float gspeed
Definition: traffic_info.h:41
float ground_alt
size == nb_waypoint, waypoint 0 is a dummy waypoint
Definition: common_nav.c:40
float coef_form_pos
Definition: formation.c:28
#define FORM_POS_PGAIN
Definition: formation.c:43
int formation_flight(void)
Definition: formation.c:128
#define FORM_MODE
Definition: formation.c:63
#define FORM_COURSE_PGAIN
Definition: formation.c:51
float course
Definition: traffic_info.h:39
int stop_formation(void)
Definition: formation.c:110
uint8_t form_mode
Definition: formation.c:32
float east
Definition: formation.h:25
struct slot_ formation[NB_ACS]
Definition: formation.c:36
float form_speed_n
Definition: formation.c:24
float north
Definition: traffic_info.h:38
static struct EnuCoor_f * stateGetPositionEnu_f(void)
Get position in local ENU coordinates (float).
Definition: state.h:702
struct ac_info_ * get_ac_info(uint8_t id)
Definition: traffic_info.c:45
#define FALSE
Definition: std.h:5
Fixed wing horizontal control.
float alt
Definition: traffic_info.h:40
float form_speed_e
Definition: formation.c:24
#define TRUE
Definition: std.h:4
float form_carrot
Definition: formation.c:26
#define Max(x, y)
float east
Definition: traffic_info.h:37
float x
in meters
Vertical control for fixed wing vehicles.
#define FORM_ALTITUDE_PGAIN
Definition: formation.c:55
uint32_t tow
GPS time of week in ms.
Definition: gps.h:84
Definition: formation.h:21
uint32_t itow
Definition: traffic_info.h:43
Device independent GPS code (interface)
float old_cruise
Definition: formation.c:34
float coef_form_alt
Definition: formation.c:31
Definition: formation.h:21
#define FORM_PROX
Definition: formation.c:59
float alt
Definition: formation.h:27
#define SetAcInfo(_id, _utm_x, _utm_y, _course, _alt, _gspeed, _climb, _itow)
Definition: traffic_info.h:52
float form_speed
Definition: formation.c:24
static float stateGetHorizontalSpeedDir_f(void)
Get dir of horizontal ground speed (float).
Definition: state.h:921
#define FORM_SPEED_PGAIN
Definition: formation.c:47
float v_ctl_auto_throttle_cruise_throttle
Definition: energy_ctrl.c:103
static struct UtmCoor_f * stateGetPositionUtm_f(void)
Get position in UTM coordinates (float).
Definition: state.h:675
#define NB_ACS
Definition: traffic_info.h:33
unsigned char uint8_t
Definition: types.h:14
Formation flight library.
API to get/set the generic vehicle states.
void formation_pre_call(void)
Definition: formation.c:261
float north
Definition: formation.h:26
static struct EnuCoor_f * stateGetSpeedEnu_f(void)
Get ground speed in local ENU coordinates (float).
Definition: state.h:894
#define FORM_MODE_COURSE
Definition: formation.h:14
float coef_form_speed
Definition: formation.c:29
float coef_form_course
Definition: formation.c:30
#define FORM_CARROT
Definition: formation.c:39
float form_a
Definition: formation.c:23
enum slot_status status
Definition: formation.h:24
int add_slot(uint8_t _id, float slot_e, float slot_n, float slot_a)
Definition: formation.c:84
float form_e
Definition: formation.c:23
float y
in meters
struct GpsState gps
global GPS state
Definition: gps.c:41
int formation_init(void)
Definition: formation.c:66