Paparazzi UAS  v5.12_stable-4-g9b43e9b
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
mission_common.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Paparazzi Team
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  */
22 
28 
29 #include <string.h>
30 #include "generated/flight_plan.h"
31 #include "generated/airframe.h"
34 
36 
37 void mission_init(void)
38 {
39  mission.insert_idx = 0;
40  mission.current_idx = 0;
41  mission.element_time = 0.;
42 }
43 
44 
45 // Insert element
46 bool mission_insert(enum MissionInsertMode insert, struct _mission_element *element)
47 {
48  uint8_t tmp;
49  // convert element if needed, return FALSE if failed
50  if (!mission_element_convert(element)) { return false; }
51 
52  switch (insert) {
53  case Append:
55  if (tmp == mission.current_idx) { return false; } // no room to insert element
56  mission.elements[mission.insert_idx] = *element; // add element
57  mission.insert_idx = tmp; // move insert index
58  break;
59  case Prepend:
60  if (mission.current_idx == 0) { tmp = MISSION_ELEMENT_NB - 1; }
61  else { tmp = mission.current_idx - 1; }
62  if (tmp == mission.insert_idx) { return false; } // no room to inser element
63  mission.elements[tmp] = *element; // add element
64  mission.current_idx = tmp; // move current index
65  break;
66  case ReplaceCurrent:
67  // current element can always be modified, index are not changed
68  mission.elements[mission.current_idx] = *element;
69  break;
70  case ReplaceAll:
71  // reset queue and index
72  mission.elements[0] = *element;
73  mission.current_idx = 0;
74  mission.insert_idx = 1;
75  break;
76  case ReplaceNexts:
78  mission.elements[tmp] = *element;
80  default:
81  // unknown insertion mode
82  return false;
83  }
84  return true;
85 
86 }
87 
88 
89 // Weak implementation of mission_element_convert (leave element unchanged)
90 bool __attribute__((weak)) mission_element_convert(struct _mission_element *el __attribute__((unused))) { return true; }
91 
92 
93 // Get element
95 {
97  return NULL;
98  }
100 }
101 
102 
103 // Report function
105 {
106  // build index list
107  uint8_t index_list[MISSION_ELEMENT_NB];
108  uint8_t i = mission.current_idx, j = 0;
109  while (i != mission.insert_idx) {
110  index_list[j++] = mission.elements[i].index;
111  i = (i + 1) % MISSION_ELEMENT_NB;
112  }
113  if (j == 0) { index_list[j++] = 0; } // Dummy value if index list is empty
114  //compute remaining time (or -1. if no time limit)
115  float remaining_time = -1.;
118  }
119 
120  // send status
121  DOWNLINK_SEND_MISSION_STATUS(DefaultChannel, DefaultDevice, &remaining_time, j, index_list);
122 }
123 
124 
126 // Parsing functions //
128 
130 {
131  if (DL_MISSION_GOTO_WP_ac_id(dl_buffer) != AC_ID) { return false; } // not for this aircraft
132 
133  struct _mission_element me;
134  me.type = MissionWP;
135  me.element.mission_wp.wp.wp_f.x = DL_MISSION_GOTO_WP_wp_east(dl_buffer);
136  me.element.mission_wp.wp.wp_f.y = DL_MISSION_GOTO_WP_wp_north(dl_buffer);
137  me.element.mission_wp.wp.wp_f.z = DL_MISSION_GOTO_WP_wp_alt(dl_buffer);
138  me.duration = DL_MISSION_GOTO_WP_duration(dl_buffer);
139  me.index = DL_MISSION_GOTO_WP_index(dl_buffer);
140 
141  enum MissionInsertMode insert = (enum MissionInsertMode)(DL_MISSION_GOTO_WP_insert(dl_buffer));
142 
143  return mission_insert(insert, &me);
144 }
145 
147 {
148  if (DL_MISSION_GOTO_WP_LLA_ac_id(dl_buffer) != AC_ID) { return false; } // not for this aircraft
149 
150  struct LlaCoor_i lla;
151  lla.lat = DL_MISSION_GOTO_WP_LLA_wp_lat(dl_buffer);
152  lla.lon = DL_MISSION_GOTO_WP_LLA_wp_lon(dl_buffer);
153  lla.alt = DL_MISSION_GOTO_WP_LLA_wp_alt(dl_buffer);
154 
155  struct _mission_element me;
156  me.type = MissionWP;
157  // if there is no valid local coordinate, do not insert mission element
158  if (!mission_point_of_lla(&me.element.mission_wp.wp.wp_f, &lla)) { return false; }
159  me.duration = DL_MISSION_GOTO_WP_LLA_duration(dl_buffer);
160  me.index = DL_MISSION_GOTO_WP_LLA_index(dl_buffer);
161 
162  enum MissionInsertMode insert = (enum MissionInsertMode)(DL_MISSION_GOTO_WP_LLA_insert(dl_buffer));
163 
164  return mission_insert(insert, &me);
165 }
166 
168 {
169  if (DL_MISSION_CIRCLE_ac_id(dl_buffer) != AC_ID) { return false; } // not for this aircraft
170 
171  struct _mission_element me;
172  me.type = MissionCircle;
173  me.element.mission_circle.center.center_f.x = DL_MISSION_CIRCLE_center_east(dl_buffer);
174  me.element.mission_circle.center.center_f.y = DL_MISSION_CIRCLE_center_north(dl_buffer);
175  me.element.mission_circle.center.center_f.z = DL_MISSION_CIRCLE_center_alt(dl_buffer);
176  me.element.mission_circle.radius = DL_MISSION_CIRCLE_radius(dl_buffer);
177  me.duration = DL_MISSION_CIRCLE_duration(dl_buffer);
178  me.index = DL_MISSION_CIRCLE_index(dl_buffer);
179 
180  enum MissionInsertMode insert = (enum MissionInsertMode)(DL_MISSION_CIRCLE_insert(dl_buffer));
181 
182  return mission_insert(insert, &me);
183 }
184 
186 {
187  if (DL_MISSION_CIRCLE_LLA_ac_id(dl_buffer) != AC_ID) { return false; } // not for this aircraft
188 
189  struct LlaCoor_i lla;
190  lla.lat = DL_MISSION_CIRCLE_LLA_center_lat(dl_buffer);
191  lla.lon = DL_MISSION_CIRCLE_LLA_center_lon(dl_buffer);
192  lla.alt = DL_MISSION_CIRCLE_LLA_center_alt(dl_buffer);
193 
194  struct _mission_element me;
195  me.type = MissionCircle;
196  // if there is no valid local coordinate, do not insert mission element
197  if (!mission_point_of_lla(&me.element.mission_circle.center.center_f, &lla)) { return false; }
198  me.element.mission_circle.radius = DL_MISSION_CIRCLE_LLA_radius(dl_buffer);
199  me.duration = DL_MISSION_CIRCLE_LLA_duration(dl_buffer);
200  me.index = DL_MISSION_CIRCLE_LLA_index(dl_buffer);
201 
202  enum MissionInsertMode insert = (enum MissionInsertMode)(DL_MISSION_CIRCLE_LLA_insert(dl_buffer));
203 
204  return mission_insert(insert, &me);
205 }
206 
208 {
209  if (DL_MISSION_SEGMENT_ac_id(dl_buffer) != AC_ID) { return false; } // not for this aircraft
210 
211  struct _mission_element me;
212  me.type = MissionSegment;
213  me.element.mission_segment.from.from_f.x = DL_MISSION_SEGMENT_segment_east_1(dl_buffer);
214  me.element.mission_segment.from.from_f.y = DL_MISSION_SEGMENT_segment_north_1(dl_buffer);
215  me.element.mission_segment.from.from_f.z = DL_MISSION_SEGMENT_segment_alt(dl_buffer);
216  me.element.mission_segment.to.to_f.x = DL_MISSION_SEGMENT_segment_east_2(dl_buffer);
217  me.element.mission_segment.to.to_f.y = DL_MISSION_SEGMENT_segment_north_2(dl_buffer);
218  me.element.mission_segment.to.to_f.z = DL_MISSION_SEGMENT_segment_alt(dl_buffer);
219  me.duration = DL_MISSION_SEGMENT_duration(dl_buffer);
220  me.index = DL_MISSION_SEGMENT_index(dl_buffer);
221 
222  enum MissionInsertMode insert = (enum MissionInsertMode)(DL_MISSION_SEGMENT_insert(dl_buffer));
223 
224  return mission_insert(insert, &me);
225 }
226 
228 {
229  if (DL_MISSION_SEGMENT_LLA_ac_id(dl_buffer) != AC_ID) { return false; } // not for this aircraft
230 
231  struct LlaCoor_i from_lla, to_lla;
232  from_lla.lat = DL_MISSION_SEGMENT_LLA_segment_lat_1(dl_buffer);
233  from_lla.lon = DL_MISSION_SEGMENT_LLA_segment_lon_1(dl_buffer);
234  from_lla.alt = DL_MISSION_SEGMENT_LLA_segment_alt(dl_buffer);
235  to_lla.lat = DL_MISSION_SEGMENT_LLA_segment_lat_2(dl_buffer);
236  to_lla.lon = DL_MISSION_SEGMENT_LLA_segment_lon_2(dl_buffer);
237  to_lla.alt = DL_MISSION_SEGMENT_LLA_segment_alt(dl_buffer);
238 
239  struct _mission_element me;
240  me.type = MissionSegment;
241  // if there is no valid local coordinate, do not insert mission element
242  if (!mission_point_of_lla(&me.element.mission_segment.from.from_f, &from_lla)) { return false; }
243  if (!mission_point_of_lla(&me.element.mission_segment.to.to_f, &to_lla)) { return false; }
244  me.duration = DL_MISSION_SEGMENT_LLA_duration(dl_buffer);
245  me.index = DL_MISSION_SEGMENT_LLA_index(dl_buffer);
246 
247  enum MissionInsertMode insert = (enum MissionInsertMode)(DL_MISSION_SEGMENT_LLA_insert(dl_buffer));
248 
249  return mission_insert(insert, &me);
250 }
251 
253 {
254  if (DL_MISSION_PATH_ac_id(dl_buffer) != AC_ID) { return false; } // not for this aircraft
255 
256  struct _mission_element me;
257  me.type = MissionPath;
258  me.element.mission_path.path.path_f[0].x = DL_MISSION_PATH_point_east_1(dl_buffer);
259  me.element.mission_path.path.path_f[0].y = DL_MISSION_PATH_point_north_1(dl_buffer);
260  me.element.mission_path.path.path_f[0].z = DL_MISSION_PATH_path_alt(dl_buffer);
261  me.element.mission_path.path.path_f[1].x = DL_MISSION_PATH_point_east_2(dl_buffer);
262  me.element.mission_path.path.path_f[1].y = DL_MISSION_PATH_point_north_2(dl_buffer);
263  me.element.mission_path.path.path_f[1].z = DL_MISSION_PATH_path_alt(dl_buffer);
264  me.element.mission_path.path.path_f[2].x = DL_MISSION_PATH_point_east_3(dl_buffer);
265  me.element.mission_path.path.path_f[2].y = DL_MISSION_PATH_point_north_3(dl_buffer);
266  me.element.mission_path.path.path_f[2].z = DL_MISSION_PATH_path_alt(dl_buffer);
267  me.element.mission_path.path.path_f[3].x = DL_MISSION_PATH_point_east_4(dl_buffer);
268  me.element.mission_path.path.path_f[3].y = DL_MISSION_PATH_point_north_4(dl_buffer);
269  me.element.mission_path.path.path_f[3].z = DL_MISSION_PATH_path_alt(dl_buffer);
270  me.element.mission_path.path.path_f[4].x = DL_MISSION_PATH_point_east_5(dl_buffer);
271  me.element.mission_path.path.path_f[4].y = DL_MISSION_PATH_point_north_5(dl_buffer);
272  me.element.mission_path.path.path_f[4].z = DL_MISSION_PATH_path_alt(dl_buffer);
273  me.element.mission_path.nb = DL_MISSION_PATH_nb(dl_buffer);
274  if (me.element.mission_path.nb > MISSION_PATH_NB) { me.element.mission_path.nb = MISSION_PATH_NB; }
275  me.element.mission_path.path_idx = 0;
276  me.duration = DL_MISSION_PATH_duration(dl_buffer);
277  me.index = DL_MISSION_PATH_index(dl_buffer);
278 
279  enum MissionInsertMode insert = (enum MissionInsertMode)(DL_MISSION_PATH_insert(dl_buffer));
280 
281  return mission_insert(insert, &me);
282 }
283 
285 {
286  if (DL_MISSION_PATH_LLA_ac_id(dl_buffer) != AC_ID) { return false; } // not for this aircraft
287 
288  struct LlaCoor_i lla[MISSION_PATH_NB];
289  lla[0].lat = DL_MISSION_PATH_LLA_point_lat_1(dl_buffer);
290  lla[0].lon = DL_MISSION_PATH_LLA_point_lon_1(dl_buffer);
291  lla[0].alt = DL_MISSION_PATH_LLA_path_alt(dl_buffer);
292  lla[1].lat = DL_MISSION_PATH_LLA_point_lat_2(dl_buffer);
293  lla[1].lon = DL_MISSION_PATH_LLA_point_lon_2(dl_buffer);
294  lla[1].alt = DL_MISSION_PATH_LLA_path_alt(dl_buffer);
295  lla[2].lat = DL_MISSION_PATH_LLA_point_lat_3(dl_buffer);
296  lla[2].lon = DL_MISSION_PATH_LLA_point_lon_3(dl_buffer);
297  lla[2].alt = DL_MISSION_PATH_LLA_path_alt(dl_buffer);
298  lla[3].lat = DL_MISSION_PATH_LLA_point_lat_4(dl_buffer);
299  lla[3].lon = DL_MISSION_PATH_LLA_point_lon_4(dl_buffer);
300  lla[3].alt = DL_MISSION_PATH_LLA_path_alt(dl_buffer);
301  lla[4].lat = DL_MISSION_PATH_LLA_point_lat_5(dl_buffer);
302  lla[4].lon = DL_MISSION_PATH_LLA_point_lon_5(dl_buffer);
303  lla[4].alt = DL_MISSION_PATH_LLA_path_alt(dl_buffer);
304 
305  struct _mission_element me;
306  me.type = MissionPath;
307  uint8_t i;
308  me.element.mission_path.nb = DL_MISSION_PATH_LLA_nb(dl_buffer);
309  if (me.element.mission_path.nb > MISSION_PATH_NB) { me.element.mission_path.nb = MISSION_PATH_NB; }
310  for (i = 0; i < me.element.mission_path.nb; i++) {
311  // if there is no valid local coordinate, do not insert mission element
312  if (!mission_point_of_lla(&me.element.mission_path.path.path_f[i], &lla[i])) { return false; }
313  }
314  me.element.mission_path.path_idx = 0;
315  me.duration = DL_MISSION_PATH_LLA_duration(dl_buffer);
316  me.index = DL_MISSION_PATH_LLA_index(dl_buffer);
317 
318  enum MissionInsertMode insert = (enum MissionInsertMode)(DL_MISSION_PATH_LLA_insert(dl_buffer));
319 
320  return mission_insert(insert, &me);
321 }
322 
324 {
325  if (DL_GOTO_MISSION_ac_id(dl_buffer) != AC_ID) { return false; } // not for this aircraft
326 
327  uint8_t mission_id = DL_GOTO_MISSION_mission_id(dl_buffer);
328  if (mission_id < MISSION_ELEMENT_NB) {
329  mission.current_idx = mission_id;
330  } else { return false; }
331 
332  return true;
333 }
334 
336 {
337  if (DL_NEXT_MISSION_ac_id(dl_buffer) != AC_ID) { return false; } // not for this aircraft
338 
339  if (mission.current_idx == mission.insert_idx) { return false; } // already at the last position
340 
341  // increment current index
343  return true;
344 }
345 
347 {
348  if (DL_END_MISSION_ac_id(dl_buffer) != AC_ID) { return false; } // not for this aircraft
349 
350  // set current index to insert index (last position)
352  return true;
353 }
int mission_parse_NEXT_MISSION(void)
replace the next element and remove all the others
int mission_parse_SEGMENT(void)
struct _mission_element * mission_get(void)
Get current mission element.
void mission_init(void)
Init mission structure.
bool mission_insert(enum MissionInsertMode insert, struct _mission_element *element)
Insert a mission element according to the insertion mode.
bool mission_element_convert(struct _mission_element *el)
Convert mission element's points format if needed.
void mission_status_report(void)
Report mission status.
MissionInsertMode
remove all elements and add the new one
union _mission_element::@289 element
float duration
time to spend in the element (<= 0 to disable)
add before the current element
vector in Latitude, Longitude and Altitude
replace current element
int mission_parse_GOTO_WP(void)
Parsing functions called when a mission message is received.
int mission_parse_CIRCLE(void)
int32_t alt
in millimeters above WGS84 reference ellipsoid
float element_time
time in second spend in the current element
int mission_parse_GOTO_WP_LLA(void)
#define MISSION_ELEMENT_NB
Max number of elements in the tasks' list can be redefined.
mission planner library
add at the last position
int mission_parse_PATH(void)
int32_t lon
in degrees*1e7
uint8_t insert_idx
inserstion index
int mission_parse_SEGMENT_LLA(void)
unsigned char uint8_t
Definition: types.h:14
int mission_parse_GOTO_MISSION(void)
uint8_t index
index of mission element
#define MISSION_PATH_NB
uint8_t current_idx
current mission element index
struct _mission mission
uint8_t dl_buffer[MSG_SIZE]
Definition: main_demo5.c:64
struct _mission_element elements[MISSION_ELEMENT_NB]
bool mission_point_of_lla(struct EnuCoor_f *point, struct LlaCoor_i *lla)
Get the ENU component of LLA mission point This function is firmware specific.
int32_t lat
in degrees*1e7
int mission_parse_PATH_LLA(void)
int mission_parse_CIRCLE_LLA(void)
int mission_parse_END_MISSION(void)
enum MissionType type