Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
traffic_info.c
Go to the documentation of this file.
1/*
2 * Copyright (C) Pascal Brisset, Antoine Drouin (2008), Kirk Scheper (2016)
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 */
28
29#include "generated/airframe.h" // AC_ID
30#include "generated/flight_plan.h" // NAV_MSL0
31
33#include "pprzlink/dl_protocol.h" // datalink messages
34#include "pprzlink/messages.h" // telemetry messages
35
36#include "state.h"
39
40/* number of ac being tracked */
42/* index of ac in the list of traffic info aircraft (ti_acs) */
44/* container for available traffic info */
46
47/* Geoid height (msl) over ellipsoid [mm] */
49
51{
53
54 ti_acs_id[0] = 0; // ground station
55 ti_acs_id[AC_ID] = 1;
57 ti_acs_idx = 2;
58
60}
61
75
77{
79 uint8_t msg_id = IdOfPprzMsg(buf);
80
81 /* handle telemetry message */
82#if PPRZLINK_DEFAULT_VER == 2
84#else
85 if (sender_id > 0) {
86#endif
87 switch (msg_id) {
88 case DL_GPS_SMALL: {
90
91 // decode compressed values
92 int16_t course = (int16_t)((multiplex_speed >> 21) & 0x7FF); // bits 31-21 course in decideg
93 if (course & 0x400) {
94 course |= 0xF800; // fix for twos complements
95 }
96 course *= 2; // scale course by resolution
97 int16_t gspeed = (int16_t)((multiplex_speed >> 10) & 0x7FF); // bits 20-10 ground speed cm/s
98 if (gspeed & 0x400) {
99 gspeed |= 0xF800; // fix for twos complements
100 }
101 int16_t climb = (int16_t)(multiplex_speed & 0x3FF); // bits 9-0 z climb speed in cm/s
102 if (climb & 0x200) {
103 climb |= 0xFC00; // fix for twos complements
104 }
105
107 DL_GPS_SMALL_lat(buf),
108 DL_GPS_SMALL_lon(buf),
109 (int32_t)DL_GPS_SMALL_alt(buf) * 10,
110 course,
111 gspeed,
112 climb,
114 }
115 break;
116 case DL_GPS: {
118 DL_GPS_utm_east(buf),
119 DL_GPS_utm_north(buf),
120 DL_GPS_alt(buf),
121 DL_GPS_utm_zone(buf),
122 DL_GPS_course(buf),
123 DL_GPS_speed(buf),
124 DL_GPS_climb(buf),
125 DL_GPS_itow(buf));
126 }
127 break;
128 case DL_GPS_LLA: {
130 DL_GPS_LLA_lat(buf),
131 DL_GPS_LLA_lon(buf),
132 DL_GPS_LLA_alt(buf),
134 DL_GPS_LLA_speed(buf),
135 DL_GPS_LLA_climb(buf),
136 DL_GPS_LLA_itow(buf));
137 }
138 break;
139 case DL_GPS_INT: {
140 struct LtpDef_i def = {0};
141 struct EcefCoor_i ecef_pos = {
142 .x = DL_GPS_INT_ecef_x(buf),
143 .y = DL_GPS_INT_ecef_y(buf),
144 .z = DL_GPS_INT_ecef_z(buf),
145 };
146 struct EcefCoor_i ecef_vel = {
147 .x = DL_GPS_INT_ecef_xd(buf),
148 .y = DL_GPS_INT_ecef_yd(buf),
149 .z = DL_GPS_INT_ecef_zd(buf),
150 };
151 struct NedCoor_i ned_vel;
152 ltp_def_from_ecef_i(&def, &ecef_pos);
153 ned_of_ecef_vect_i(&ned_vel, &def, &ecef_vel);
154 struct NedCoor_f ned_vel_f;
156 int16_t course = (int16_t)(10.f * DegOfRad(atan2f(ned_vel_f.y, ned_vel_f.x))); // decideg
158 int16_t climb = (int16_t)(CM_OF_M(-ned_vel_f.z));
160 DL_GPS_INT_lat(buf),
161 DL_GPS_INT_lon(buf),
162 DL_GPS_INT_alt(buf),
163 course,
164 gspeed,
165 climb,
166 DL_GPS_INT_tow(buf));
167 }
168 break;
169 default:
170 return FALSE;
171 }
172 /* handle datalink message */
173 } else {
174 switch (msg_id) {
175 case DL_ACINFO: {
179 DL_ACINFO_alt(buf) * 10,
181 DL_ACINFO_course(buf),
182 DL_ACINFO_speed(buf),
183 DL_ACINFO_climb(buf),
184 DL_ACINFO_itow(buf));
185 }
186 break;
187 case DL_ACINFO_LLA: {
191 DL_ACINFO_LLA_alt(buf) * 10,
195 DL_ACINFO_LLA_itow(buf));
196 }
197 break;
198 default:
199 return FALSE;
200 }
201 }
202 return TRUE;
203}
204
205
207 uint16_t gspeed, uint16_t climb, uint32_t itow)
208{
209 if (ti_acs_idx < NB_ACS) {
210 if (id > 0 && ti_acs_id[id] == 0) { // new aircraft id
211 ti_acs_id[id] = ti_acs_idx++;
212 ti_acs[ti_acs_id[id]].ac_id = id;
213 }
214
215 if (itow < ti_acs[ti_acs_id[id]].itow) {
216 return; // don't update on old data
217 }
218
219 ti_acs[ti_acs_id[id]].status = 0;
220
222 if (utm_zone == my_zone) {
225 ti_acs[ti_acs_id[id]].utm_pos_i.alt = alt;
228
229 } else { // store other uav in utm extended zone
230 struct UtmCoor_i utm = {.east = utm_east, .north = utm_north, .alt = alt, .zone = utm_zone};
231 struct LlaCoor_i lla;
232 lla_of_utm_i(&lla, &utm);
233 LLA_COPY(ti_acs[ti_acs_id[id]].lla_pos_i, lla);
235
236 utm.zone = my_zone;
237 utm_of_lla_i(&utm, &lla);
238
239 UTM_COPY(ti_acs[ti_acs_id[id]].utm_pos_i, utm);
241 }
242
244 ti_acs[ti_acs_id[id]].gspeed = MOfCm(gspeed);
245 ti_acs[ti_acs_id[id]].climb = MOfCm(climb);
247
248 ti_acs[ti_acs_id[id]].itow = itow;
249 }
250}
251
253 int16_t course, uint16_t gspeed, int16_t climb, uint32_t itow)
254{
255 if (ti_acs_idx < NB_ACS) {
256 if (id > 0 && ti_acs_id[id] == 0) {
257 ti_acs_id[id] = ti_acs_idx++;
258 ti_acs[ti_acs_id[id]].ac_id = id;
259 }
260
261 if (itow < ti_acs[ti_acs_id[id]].itow) {
262 return; // don't update on old data
263 }
264
265 ti_acs[ti_acs_id[id]].status = 0;
266
267 struct LlaCoor_i lla = {.lat = lat, .lon = lon, .alt = alt};
268 LLA_COPY(ti_acs[ti_acs_id[id]].lla_pos_i, lla);
270
272 ti_acs[ti_acs_id[id]].gspeed = MOfCm(gspeed);
273 ti_acs[ti_acs_id[id]].climb = MOfCm(climb);
275
276 ti_acs[ti_acs_id[id]].itow = itow;
277 }
278}
279
280/* Conversion funcitons for computing ac position in requested reference frame from
281 * any other available reference frame
282 */
283
284/* compute UTM position of aircraft with ac_id (int) */
286{
287 uint8_t ac_nr = ti_acs_id[ac_id];
289 {
290 return;
291 }
292
293 /* LLA_i -> UTM_i is more accurate than from UTM_f */
295 {
296 // use my zone as reference, i.e zone extend
298 utm_of_lla_i(&ti_acs[ac_nr].utm_pos_i, &ti_acs[ac_nr].lla_pos_i);
302 {
303 UTM_BFP_OF_REAL(ti_acs[ac_nr].utm_pos_i, ti_acs[ac_nr].utm_pos_f);
305 {
306 // use my zone as reference, i.e zone extend
308 utm_of_lla_f(&ti_acs[ac_nr].utm_pos_f, &ti_acs[ac_nr].lla_pos_f);
312 UTM_BFP_OF_REAL(ti_acs[ac_nr].utm_pos_i, ti_acs[ac_nr].utm_pos_f);
313 }
315}
316
317/* compute LLA position of aircraft with ac_id (int) */
319{
320 uint8_t ac_nr = ti_acs_id[ac_id];
322 {
323 return;
324 }
325
327 {
328 LLA_BFP_OF_REAL(ti_acs[ac_nr].lla_pos_i, ti_acs[ac_nr].lla_pos_f);
330 {
331 lla_of_utm_i(&ti_acs[ac_nr].lla_pos_i, &ti_acs[ac_nr].utm_pos_i);
335 {
336 lla_of_utm_f(&ti_acs[ac_nr].lla_pos_f, &ti_acs[ac_nr].utm_pos_f);
340 LLA_BFP_OF_REAL(ti_acs[ac_nr].lla_pos_i, ti_acs[ac_nr].lla_pos_f);
341 }
343}
344
345/* compute ENU position of aircraft with ac_id (int) */
347{
348 uint8_t ac_nr = ti_acs_id[ac_id];
350 {
351 return;
352 }
353
355 {
356 ENU_BFP_OF_REAL(ti_acs[ac_nr].enu_pos_i, ti_acs[ac_nr].enu_pos_f);
357 }
358 else if (state.ned_initialized_i)
359 {
361 {
362 struct EnuCoor_i enu;
364 // convert ENU pos from cm to BFP with INT32_POS_FRAC
365 enu.x = POS_BFP_OF_REAL(enu.x) / 100;
366 enu.y = POS_BFP_OF_REAL(enu.y) / 100;
367 enu.z = POS_BFP_OF_REAL(enu.z) / 100;
370 {
373 ENU_BFP_OF_REAL(ti_acs[ac_nr].enu_pos_i, ti_acs[ac_nr].enu_pos_f)
374 }
375 } else if (state.utm_initialized_f)
376 {
377 /* if utm origin is initialized we use the ENU = UTM - UTM_ORIGIN as in state to facilitate comparison */
380 ENU_BFP_OF_REAL(ti_acs[ac_nr].enu_pos_i, ti_acs[ac_nr].enu_pos_f);
381 }
383}
384
385/* compute UTM position of aircraft with ac_id (float) */
387{
388 uint8_t ac_nr = ti_acs_id[ac_id];
390 {
391 return;
392 }
393
395 {
396 UTM_FLOAT_OF_BFP(ti_acs[ac_nr].utm_pos_f, ti_acs[ac_nr].utm_pos_i);
398 {
399 // use my zone as reference, i.e zone extend
401 utm_of_lla_i(&ti_acs[ac_nr].utm_pos_i, &ti_acs[ac_nr].lla_pos_i);
405 UTM_FLOAT_OF_BFP(ti_acs[ac_nr].utm_pos_f, ti_acs[ac_nr].utm_pos_i);
407 {
408 /* not very accurate with float ~5cm */
410 utm_of_lla_f(&ti_acs[ac_nr].utm_pos_f, &ti_acs[ac_nr].lla_pos_f);
413 }
415}
416
417/* compute LLA position of aircraft with ac_id (float) */
419{
420 uint8_t ac_nr = ti_acs_id[ac_id];
422 {
423 return;
424 }
425
427 {
428 LLA_FLOAT_OF_BFP(ti_acs[ac_nr].lla_pos_f, ti_acs[ac_nr].lla_pos_i);
430 {
431 lla_of_utm_i(&ti_acs[ac_nr].lla_pos_i, &ti_acs[ac_nr].utm_pos_i);
435 LLA_FLOAT_OF_BFP(ti_acs[ac_nr].lla_pos_f, ti_acs[ac_nr].lla_pos_i);
437 {
438 lla_of_utm_f(&ti_acs[ac_nr].lla_pos_f, &ti_acs[ac_nr].utm_pos_f);
441 }
443}
444
445/* compute ENU position of aircraft with ac_id (float) */
447{
448 uint8_t ac_nr = ti_acs_id[ac_id];
450 {
451 return;
452 }
453
455 {
456 ENU_FLOAT_OF_BFP(ti_acs[ac_nr].enu_pos_f, ti_acs[ac_nr].enu_pos_i);
457 }
458 else if (state.ned_initialized_i)
459 {
461 {
464 {
465 struct EnuCoor_i enu;
467 // convert ENU pos from cm to BFP with INT32_POS_FRAC
468 enu.x = POS_BFP_OF_REAL(enu.x) / 100;
469 enu.y = POS_BFP_OF_REAL(enu.y) / 100;
470 enu.z = POS_BFP_OF_REAL(enu.z) / 100;
473 ENU_FLOAT_OF_BFP(ti_acs[ac_nr].enu_pos_f, ti_acs[ac_nr].enu_pos_i);
474 }
475 } else if (state.utm_initialized_f)
476 {
477 /* if utm origin is initialized we use the ENU = UTM - UTM_ORIGIN as in state to facilitate comparison */
479 }
481}
482
483/* compute ENU velocity of aircraft with ac_id (int) */
504
505/* compute ENU position of aircraft with ac_id (float) */
static int16_t course[3]
static uint8_t status
struct GpsState gps
global GPS state
Definition gps.c:74
uint32_t gps_tow_from_sys_ticks(uint32_t sys_ticks)
Convert time in sys_time ticks to GPS time of week.
Definition gps.c:419
int32_t hmsl
height above mean sea level (MSL) in mm
Definition gps.h:97
struct LlaCoor_i lla_pos
position in LLA (lat,lon: deg*1e7; alt: mm over ellipsoid)
Definition gps.h:95
#define GPS_VALID_POS_LLA_BIT
Definition gps.h:49
#define GPS_VALID_HMSL_BIT
Definition gps.h:53
uint8_t valid_fields
bitfield indicating valid fields (GPS_VALID_x_BIT)
Definition gps.h:91
struct LlaCoor_f lla_pos_f
Position in Latitude, Longitude and Altitude.
struct EnuCoor_f enu_vel_f
speed in North East Down coordinates
uint8_t ac_id
uint32_t itow
ms
float climb
m/s
struct LlaCoor_i lla_pos_i
Position in Latitude, Longitude and Altitude.
float gspeed
m/s
struct UtmCoor_i utm_pos_i
Position in UTM coordinates.
uint16_t status
Holds the status bits for all acinfo position and velocity representations.
struct UtmCoor_f utm_pos_f
Position in UTM coordinates.
float course
rad
struct EnuCoor_i enu_pos_i
Position in North East Down coordinates.
#define AC_INFO_VEL_ENU_I
bool parse_acinfo_dl(uint8_t *buf)
Parse all datalink or telemetry messages that contain global position of other acs Messages currently...
#define AC_INFO_POS_LLA_I
uint8_t ti_acs_idx
#define AC_INFO_VEL_ENU_F
void set_ac_info_utm(uint8_t id, uint32_t utm_east, uint32_t utm_north, uint32_t alt, uint8_t utm_zone, uint16_t course, uint16_t gspeed, uint16_t climb, uint32_t itow)
Set Aircraft info.
void acInfoCalcPositionUtm_f(uint8_t ac_id)
#define AC_INFO_POS_LLA_F
void acInfoCalcPositionEnu_f(uint8_t ac_id)
void acInfoCalcVelocityEnu_f(uint8_t ac_id)
void acInfoCalcPositionUtm_i(uint8_t ac_id)
void acInfoCalcPositionLla_i(uint8_t ac_id)
void acInfoCalcPositionLla_f(uint8_t ac_id)
void set_ac_info_lla(uint8_t id, int32_t lat, int32_t lon, int32_t alt, int16_t course, uint16_t gspeed, int16_t climb, uint32_t itow)
Set Aircraft info.
static struct LlaCoor_i * acInfoGetPositionLla_i(uint8_t ac_id)
Get position from LLA coordinates (int).
#define AC_INFO_POS_ENU_F
#define AC_INFO_POS_UTM_F
#define AC_INFO_POS_UTM_I
#define AC_INFO_POS_ENU_I
void traffic_info_init(void)
#define AC_INFO_VEL_LOCAL_F
struct acInfo ti_acs[NB_ACS]
uint8_t ti_acs_id[NB_ACS_ID]
static struct LlaCoor_f * acInfoGetPositionLla_f(uint8_t ac_id)
Get position from LLA coordinates (float).
void acInfoCalcPositionEnu_i(uint8_t ac_id)
void acInfoCalcVelocityEnu_i(uint8_t ac_id)
static struct UtmCoor_f * acInfoGetPositionUtm_f(uint8_t ac_id)
Get position from UTM coordinates (float).
#define FLOAT_VECT2_NORM(_v)
#define SPEEDS_BFP_OF_REAL(_ef, _ei)
#define SPEEDS_FLOAT_OF_BFP(_ef, _ei)
#define POS_BFP_OF_REAL(_af)
#define LLA_COPY(_pos1, _pos2)
#define ENU_OF_UTM_DIFF(_pos, _utm1, _utm2)
#define UTM_COPY(_u1, _u2)
int32_t lat
in degrees*1e7
int32_t alt
in millimeters (above WGS84 reference ellipsoid or above MSL)
int32_t alt
in millimeters above WGS84 reference ellipsoid
uint8_t zone
UTM zone number.
int32_t x
in centimeters
int32_t east
in centimeters
int32_t lon
in degrees*1e7
int32_t north
in centimeters
#define ENU_FLOAT_OF_BFP(_o, _i)
void lla_of_utm_i(struct LlaCoor_i *lla, struct UtmCoor_i *utm)
Convert a UTM to LLA.
#define ENU_BFP_OF_REAL(_o, _i)
#define LLA_BFP_OF_REAL(_o, _i)
void ltp_def_from_ecef_i(struct LtpDef_i *def, struct EcefCoor_i *ecef)
#define UTM_BFP_OF_REAL(_o, _i)
void enu_of_lla_point_i(struct EnuCoor_i *enu, struct LtpDef_i *def, struct LlaCoor_i *lla)
Convert a point from LLA to local ENU.
void ned_of_ecef_vect_i(struct NedCoor_i *ned, struct LtpDef_i *def, struct EcefCoor_i *ecef)
Rotate a vector from ECEF to NED.
#define CM_OF_M(_m)
#define VECT3_FLOAT_OF_CM(_o, _i)
#define LLA_FLOAT_OF_BFP(_o, _i)
void utm_of_lla_i(struct UtmCoor_i *utm, struct LlaCoor_i *lla)
Convert a LLA to UTM.
#define UTM_FLOAT_OF_BFP(_o, _i)
vector in EarthCenteredEarthFixed coordinates
vector in East North Up coordinates
vector in Latitude, Longitude and Altitude
definition of the local (flat earth) coordinate system
vector in North East Down coordinates
position in UTM coordinates
static int32_t wgs84_ellipsoid_to_geoid_i(int32_t lat, int32_t lon)
Get WGS84 ellipsoid/geoid separation.
struct State state
Definition state.c:36
static struct LtpDef_f * stateGetNedOrigin_f(void)
Get the coordinate NED frame origin (float)
Definition state.h:566
bool utm_initialized_f
True if utm origin (float) coordinate frame is initialsed.
Definition state.h:264
static struct UtmCoor_f * stateGetUtmOrigin_f(void)
Get the coordinate UTM frame origin (int)
Definition state.h:576
bool ned_initialized_i
true if local int coordinate frame is initialsed
Definition state.h:199
static struct LtpDef_i * stateGetNedOrigin_i(void)
Get the coordinate NED frame origin (int)
Definition state.h:556
uint16_t foo
Definition main_demo5.c:58
void lla_of_utm_f(struct LlaCoor_f *lla, struct UtmCoor_f *utm)
void enu_of_lla_point_f(struct EnuCoor_f *enu, struct LtpDef_f *def, struct LlaCoor_f *lla)
void utm_of_lla_f(struct UtmCoor_f *utm, struct LlaCoor_f *lla)
float alt
in meters (normally above WGS84 reference ellipsoid)
float y
in meters
float x
in meters
float alt
in meters (above WGS84 reference ellipsoid or above MSL)
uint8_t zone
UTM zone number.
float z
in meters
vector in North East Down coordinates Units: meters
Constants UTM (Mercator) projections.
WGS-84 Geoid Heights.
#define NB_ACS_ID
Definition rssi.c:35
#define NB_ACS
Definition rssi.c:38
API to get/set the generic vehicle states.
#define TRUE
Definition std.h:4
#define FALSE
Definition std.h:5
volatile uint32_t nb_tick
SYS_TIME_TICKS since startup.
Definition sys_time.h:74
static void update_geoid_height(void)
Update estimate of the geoid height Requires an available hsml and/or lla measurement,...
int32_t geoid_height
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
int int32_t
Typedef defining 32 bit int type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
short int16_t
Typedef defining 16 bit short type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.