Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
gps.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2011 The 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 
40 #include "subsystems/abi.h"
41 #include "subsystems/gps.h"
42 #include "led.h"
43 #include "subsystems/settings.h"
44 #include "generated/settings.h"
46 #include "math/pprz_geodetic.h"
47 
48 #ifndef PRIMARY_GPS
49 #error "PRIMARY_GPS not set!"
50 #else
51 PRINT_CONFIG_VAR(PRIMARY_GPS)
52 #endif
53 
54 #ifdef SECONDARY_GPS
55 PRINT_CONFIG_VAR(SECONDARY_GPS)
56 #endif
57 
58 /* expand GpsId(PRIMARY_GPS) to e.g. GPS_UBX_ID */
59 #define __GpsId(_x) _x ## _ID
60 #define _GpsId(_x) __GpsId(_x)
61 #define GpsId(_x) _GpsId(_x)
62 
63 
64 #ifdef GPS_POWER_GPIO
65 #include "mcu_periph/gpio.h"
66 
67 #ifndef GPS_POWER_GPIO_ON
68 #define GPS_POWER_GPIO_ON gpio_set
69 #endif
70 #endif
71 
72 #define MSEC_PER_WEEK (1000*60*60*24*7)
73 #define TIME_TO_SWITCH 5000 //ten s in ms
74 
75 struct GpsState gps;
76 
78 
79 #ifdef SECONDARY_GPS
80 static uint8_t current_gps_id = 0;
81 #endif
82 
84 
85 
86 #if PERIODIC_TELEMETRY
88 
89 static void send_svinfo_id(struct transport_tx *trans, struct link_device *dev,
90  uint8_t svid)
91 {
92  if (svid < GPS_NB_CHANNELS) {
93  pprz_msg_send_SVINFO(trans, dev, AC_ID, &svid,
94  &gps.svinfos[svid].svid, &gps.svinfos[svid].flags,
95  &gps.svinfos[svid].qi, &gps.svinfos[svid].cno,
96  &gps.svinfos[svid].elev, &gps.svinfos[svid].azim);
97  }
98 }
99 
101 static void send_svinfo(struct transport_tx *trans, struct link_device *dev)
102 {
103  static uint8_t i = 0;
104  if (i == gps.nb_channels) { i = 0; }
105  send_svinfo_id(trans, dev, i);
106  i++;
107 }
108 
113 static inline void send_svinfo_available(struct transport_tx *trans, struct link_device *dev)
114 {
115  static uint8_t i = 0;
116  static uint8_t last_cnos[GPS_NB_CHANNELS];
117  if (i >= gps.nb_channels) { i = 0; }
118  // send SVINFO for all satellites while no GPS fix,
119  // after 3D fix, send avialable sats if they were updated
120  if (gps.fix < GPS_FIX_3D) {
121  send_svinfo_id(trans, dev, i);
122  } else if (gps.svinfos[i].cno != last_cnos[i]) {
123  send_svinfo_id(trans, dev, i);
124  last_cnos[i] = gps.svinfos[i].cno;
125  }
126  i++;
127 }
128 
129 static void send_gps(struct transport_tx *trans, struct link_device *dev)
130 {
131  uint8_t zero = 0;
132  int16_t climb = -gps.ned_vel.z;
133  int16_t course = (DegOfRad(gps.course) / ((int32_t)1e6));
134  struct UtmCoor_i utm = utm_int_from_gps(&gps, 0);
135  pprz_msg_send_GPS(trans, dev, AC_ID, &gps.fix,
136  &utm.east, &utm.north,
137  &course, &gps.hmsl, &gps.gspeed, &climb,
138  &gps.week, &gps.tow, &utm.zone, &zero);
139  // send SVINFO for available satellites that have new data
140  send_svinfo_available(trans, dev);
141 }
142 
143 static void send_gps_int(struct transport_tx *trans, struct link_device *dev)
144 {
145  pprz_msg_send_GPS_INT(trans, dev, AC_ID,
148  &gps.hmsl,
150  &gps.pacc, &gps.sacc,
151  &gps.tow,
152  &gps.pdop,
153  &gps.num_sv,
154  &gps.fix,
155  &gps.comp_id);
156  // send SVINFO for available satellites that have new data
157  send_svinfo_available(trans, dev);
158 }
159 
160 static void send_gps_lla(struct transport_tx *trans, struct link_device *dev)
161 {
162  uint8_t err = 0;
163  int16_t climb = -gps.ned_vel.z;
164  int16_t course = (DegOfRad(gps.course) / ((int32_t)1e6));
165  pprz_msg_send_GPS_LLA(trans, dev, AC_ID,
167  &gps.hmsl, &course, &gps.gspeed, &climb,
168  &gps.week, &gps.tow,
169  &gps.fix, &err);
170 }
171 
172 static void send_gps_sol(struct transport_tx *trans, struct link_device *dev)
173 {
174  pprz_msg_send_GPS_SOL(trans, dev, AC_ID, &gps.pacc, &gps.sacc, &gps.pdop, &gps.num_sv);
175 }
176 #endif
177 
178 
179 #ifdef SECONDARY_GPS
180 static uint8_t gps_multi_switch(struct GpsState *gps_s) {
181  static uint32_t time_since_last_gps_switch = 0;
182 
183  if (multi_gps_mode == GPS_MODE_PRIMARY){
184  return GpsId(PRIMARY_GPS);
185  } else if (multi_gps_mode == GPS_MODE_SECONDARY){
186  return GpsId(SECONDARY_GPS);
187  } else{
188  if (gps_s->fix > gps.fix){
189  return gps_s->comp_id;
190  } else if (gps.fix > gps_s->fix){
191  return gps.comp_id;
192  } else{
193  if (get_sys_time_msec() - time_since_last_gps_switch > TIME_TO_SWITCH) {
194  if (gps_s->num_sv > gps.num_sv) {
195  current_gps_id = gps_s->comp_id;
196  time_since_last_gps_switch = get_sys_time_msec();
197  } else if (gps.num_sv > gps_s->num_sv) {
198  current_gps_id = gps.comp_id;
199  time_since_last_gps_switch = get_sys_time_msec();
200  }
201  }
202  }
203  }
204  return current_gps_id;
205 }
206 #endif /*SECONDARY_GPS*/
207 
208 
209 void gps_periodic_check(struct GpsState *gps_s)
210 {
211  if (sys_time.nb_sec - gps_s->last_msg_time > GPS_TIMEOUT) {
212  gps_s->fix = GPS_FIX_NONE;
213  }
214 
215 #ifdef SECONDARY_GPS
216  current_gps_id = gps_multi_switch(gps_s);
217  if (gps_s->comp_id == current_gps_id) {
218  gps = *gps_s;
219  }
220 #else
221  gps = *gps_s;
222 #endif
223 }
224 
225 
227 static void gps_cb(uint8_t sender_id,
228  uint32_t stamp __attribute__((unused)),
229  struct GpsState *gps_s)
230 {
231  /* ignore callback from own AbiSendMsgGPS */
232  if (sender_id == GPS_MULTI_ID) {
233  return;
234  }
235  uint32_t now_ts = get_sys_time_usec();
236 #ifdef SECONDARY_GPS
237  current_gps_id = gps_multi_switch(gps_s);
238  if (gps_s->comp_id == current_gps_id) {
239  gps = *gps_s;
240  AbiSendMsgGPS(GPS_MULTI_ID, now_ts, gps_s);
241  }
242 #else
243  gps = *gps_s;
244  AbiSendMsgGPS(GPS_MULTI_ID, now_ts, gps_s);
245 #endif
246  if (gps.tow != gps_time_sync.t0_tow)
247  {
250  }
251 }
252 
253 
254 void gps_init(void)
255 {
256  multi_gps_mode = MULTI_GPS_MODE;
257 
258  gps.valid_fields = 0;
259  gps.fix = GPS_FIX_NONE;
260  gps.week = 0;
261  gps.tow = 0;
262  gps.cacc = 0;
263 
264  gps.last_3dfix_ticks = 0;
265  gps.last_3dfix_time = 0;
266  gps.last_msg_ticks = 0;
267  gps.last_msg_time = 0;
268 
269 #ifdef GPS_POWER_GPIO
271  GPS_POWER_GPIO_ON(GPS_POWER_GPIO);
272 #endif
273 #ifdef GPS_LED
274  LED_OFF(GPS_LED);
275 #endif
276 
277  AbiBindMsgGPS(ABI_BROADCAST, &gps_ev, gps_cb);
278 
279 #if PERIODIC_TELEMETRY
285 #endif
286 }
287 
289 {
290  uint32_t clock_delta;
291  uint32_t time_delta;
292  uint32_t itow_now;
293 
294  if (sys_ticks < gps_time_sync.t0_ticks) {
295  clock_delta = (0xFFFFFFFF - sys_ticks) + gps_time_sync.t0_ticks + 1;
296  } else {
297  clock_delta = sys_ticks - gps_time_sync.t0_ticks;
298  }
299 
300  time_delta = msec_of_sys_time_ticks(clock_delta);
301 
302  itow_now = gps_time_sync.t0_tow + time_delta;
303  if (itow_now > MSEC_PER_WEEK) {
304  itow_now %= MSEC_PER_WEEK;
305  }
306 
307  return itow_now;
308 }
309 
313 void WEAK gps_inject_data(uint8_t packet_id __attribute__((unused)), uint8_t length __attribute__((unused)), uint8_t *data __attribute__((unused))){
314 
315 }
316 
320 #include "state.h"
322 {
323  struct UtmCoor_f utm = {.east = 0., .north=0., .alt=0., .zone=zone};
324 
325  if (bit_is_set(gps_s->valid_fields, GPS_VALID_POS_UTM_BIT)) {
326  /* A real UTM position is available, use the correct zone */
327  UTM_FLOAT_OF_BFP(utm, gps_s->utm_pos);
328  } else if (bit_is_set(gps_s->valid_fields, GPS_VALID_POS_LLA_BIT))
329  {
330  /* Recompute UTM coordinates in this zone */
331  struct UtmCoor_i utm_i;
332  utm_i.zone = zone;
333  utm_of_lla_i(&utm_i, &gps_s->lla_pos);
334  UTM_FLOAT_OF_BFP(utm, utm_i);
335 
336  /* set utm.alt in hsml */
337  if (bit_is_set(gps_s->valid_fields, GPS_VALID_HMSL_BIT)) {
338  utm.alt = gps_s->hmsl/1000.;
339  } else {
340  utm.alt = wgs84_ellipsoid_to_geoid_i(gps_s->lla_pos.lat, gps_s->lla_pos.lon)/1000.;
341  }
342  }
343 
344  return utm;
345 }
346 
348 {
349  struct UtmCoor_i utm = {.east = 0, .north=0, .alt=0, .zone=zone};
350 
351  if (bit_is_set(gps_s->valid_fields, GPS_VALID_POS_UTM_BIT)) {
352  // A real UTM position is available, use the correct zone
353  UTM_COPY(utm, gps_s->utm_pos);
354  }
355  else if (bit_is_set(gps_s->valid_fields, GPS_VALID_POS_LLA_BIT)){
356  /* Recompute UTM coordinates in zone */
357  utm_of_lla_i(&utm, &gps_s->lla_pos);
358 
359  /* set utm.alt in hsml */
360  if (bit_is_set(gps_s->valid_fields, GPS_VALID_HMSL_BIT)) {
361  utm.alt = gps_s->hmsl;
362  } else {
363  utm.alt = wgs84_ellipsoid_to_geoid_i(gps_s->lla_pos.lat, gps_s->lla_pos.lon);
364  }
365  }
366 
367  return utm;
368 }
uint8_t qi
quality bitfield (GPS receiver specific)
Definition: gps.h:74
static void send_gps_int(struct transport_tx *trans, struct link_device *dev)
Definition: gps.c:143
Event structure to store callbacks in a linked list.
Definition: abi_common.h:65
int32_t z
in centimeters
uint32_t t0_tow
GPS time of week in ms from last message.
Definition: gps.h:115
int32_t north
in centimeters
struct SVinfo svinfos[GPS_NB_CHANNELS]
holds information from the Space Vehicles (Satellites)
Definition: gps.h:104
int16_t azim
azimuth in deg
Definition: gps.h:77
float east
in meters
uint32_t pacc
position accuracy in cm
Definition: gps.h:94
float alt
in meters (above WGS84 reference ellipsoid or above MSL)
static void send_svinfo_id(struct transport_tx *trans, struct link_device *dev, uint8_t svid)
Definition: gps.c:89
uint8_t nb_channels
Number of scanned satellites.
Definition: gps.h:103
uint32_t t0_ticks
hw clock ticks when GPS message is received
Definition: gps.h:117
Periodic telemetry system header (includes downlink utility and generated code).
uint32_t get_sys_time_msec(void)
Definition: sys_time_arch.c:78
uint8_t valid_fields
bitfield indicating valid fields (GPS_VALID_x_BIT)
Definition: gps.h:82
int32_t y
in centimeters
#define LED_OFF(i)
Definition: led_hw.h:50
uint16_t week
GPS week.
Definition: gps.h:100
Some architecture independent helper functions for GPIOs.
#define GPS_NB_CHANNELS
Definition: gps.h:57
#define TIME_TO_SWITCH
Definition: gps.c:73
static uint32_t msec_of_sys_time_ticks(uint32_t ticks)
Definition: sys_time.h:158
Main include for ABI (AirBorneInterface).
static void send_gps_sol(struct transport_tx *trans, struct link_device *dev)
Definition: gps.c:172
static void send_gps(struct transport_tx *trans, struct link_device *dev)
Definition: gps.c:129
#define UTM_FLOAT_OF_BFP(_o, _i)
position in UTM coordinates Units: meters
int32_t east
in centimeters
#define MSEC_PER_WEEK
Definition: gps.c:72
uint8_t svid
Satellite ID.
Definition: gps.h:72
volatile uint32_t nb_tick
SYS_TIME_TICKS since startup.
Definition: sys_time.h:74
#define GPS_FIX_3D
3D GPS fix
Definition: gps.h:39
int32_t z
Down.
void gpio_setup_output(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as outputs.
Definition: gpio_arch.c:33
uint32_t last_3dfix_ticks
cpu time ticks at last valid 3D fix
Definition: gps.h:106
int8_t elev
elevation in deg
Definition: gps.h:76
int32_t alt
in millimeters above WGS84 reference ellipsoid
WGS-84 Geoid Heights.
uint32_t sacc
speed accuracy in cm/s
Definition: gps.h:95
uint32_t last_msg_time
cpu time in sec at last received GPS message
Definition: gps.h:109
uint32_t cacc
course accuracy in rad*1e7
Definition: gps.h:96
uint8_t zone
UTM zone number.
struct UtmCoor_i utm_int_from_gps(struct GpsState *gps_s, uint8_t zone)
Convenience function to get utm position in int from GPS structure.
Definition: gps.c:347
static void send_svinfo_available(struct transport_tx *trans, struct link_device *dev)
send SVINFO message if updated.
Definition: gps.c:113
static abi_event gps_ev
Definition: gps.c:226
int32_t hmsl
height above mean sea level (MSL) in mm
Definition: gps.h:88
void WEAK gps_inject_data(uint8_t packet_id, uint8_t length, uint8_t *data)
Default parser for GPS injected data.
Definition: gps.c:313
uint8_t cno
Carrier to Noise Ratio (Signal Strength) in dbHz.
Definition: gps.h:75
data structure for GPS information
Definition: gps.h:81
static void send_gps_lla(struct transport_tx *trans, struct link_device *dev)
Definition: gps.c:160
uint32_t tow
GPS time of week in ms.
Definition: gps.h:101
#define GPS_FIX_NONE
No GPS fix.
Definition: gps.h:37
Device independent GPS code (interface)
uint16_t pdop
position dilution of precision scaled by 100
Definition: gps.h:97
uint8_t multi_gps_mode
Definition: gps.c:83
unsigned long uint32_t
Definition: types.h:18
struct EcefCoor_i ecef_pos
position in ECEF in cm
Definition: gps.h:85
signed short int16_t
Definition: types.h:17
#define GPS_MODE_PRIMARY
Definition: gps.h:61
#define GPS_VALID_HMSL_BIT
Definition: gps.h:53
#define DefaultPeriodic
Set default periodic telemetry.
Definition: telemetry.h:66
int32_t lon
in degrees*1e7
void utm_of_lla_i(struct UtmCoor_i *utm, struct LlaCoor_i *lla)
Convert a LLA to UTM.
uint8_t zone
UTM zone number.
signed long int32_t
Definition: types.h:19
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:73
static void gps_cb(uint8_t sender_id, uint32_t stamp, struct GpsState *gps_s)
Definition: gps.c:227
uint32_t last_3dfix_time
cpu time in sec at last valid 3D fix
Definition: gps.h:107
int32_t alt
in millimeters (above WGS84 reference ellipsoid or above MSL)
Paparazzi generic macros for geodetic calculations.
unsigned char uint8_t
Definition: types.h:14
static void send_svinfo(struct transport_tx *trans, struct link_device *dev)
send SVINFO message (regardless of state)
Definition: gps.c:101
struct UtmCoor_f utm_float_from_gps(struct GpsState *gps_s, uint8_t zone)
Convenience functions to get utm position from GPS state.
Definition: gps.c:321
API to get/set the generic vehicle states.
int32_t course
GPS course over ground in rad*1e7, [0, 2*Pi]*1e7 (CW/north)
Definition: gps.h:93
Persistent settings interface.
uint8_t comp_id
id of current gps
Definition: gps.h:83
volatile uint32_t nb_sec
full seconds since startup
Definition: sys_time.h:72
#define GPS_MULTI_ID
#define GPS_MODE_SECONDARY
Definition: gps.h:62
static int16_t course[3]
Definition: airspeed_uADC.c:57
uint8_t flags
bitfield with GPS receiver specific flags
Definition: gps.h:73
struct GpsTimeSync gps_time_sync
Definition: gps.c:77
#define MULTI_GPS_MODE
Definition: gps.h:65
uint32_t last_msg_ticks
cpu time ticks at last received GPS message
Definition: gps.h:108
#define GPS_VALID_POS_LLA_BIT
Definition: gps.h:49
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:288
uint8_t num_sv
number of sat in fix
Definition: gps.h:98
arch independent LED (Light Emitting Diodes) API
int32_t x
in centimeters
#define ABI_BROADCAST
Broadcast address.
Definition: abi_common.h:56
uint16_t gspeed
norm of 2d ground speed in cm/s
Definition: gps.h:91
struct EcefCoor_i ecef_vel
speed ECEF in cm/s
Definition: gps.h:89
data structure for GPS time sync
Definition: gps.h:114
#define GPS_TIMEOUT
GPS timeout in seconds.
Definition: gps.h:138
struct LlaCoor_i lla_pos
position in LLA (lat,lon: deg*1e7; alt: mm over ellipsoid)
Definition: gps.h:86
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
Definition: sys_time_arch.c:68
int32_t lat
in degrees*1e7
uint8_t fix
status of fix
Definition: gps.h:99
#define GPS_VALID_POS_UTM_BIT
Definition: gps.h:50
struct NedCoor_i ned_vel
speed NED in cm/s
Definition: gps.h:90
struct GpsState gps
global GPS state
Definition: gps.c:75
void gps_init(void)
initialize the global GPS state
Definition: gps.c:254
static int32_t wgs84_ellipsoid_to_geoid_i(int32_t lat, int32_t lon)
Get WGS84 ellipsoid/geoid separation.
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition: telemetry.c:46
#define GpsId(_x)
Definition: gps.c:61
void gps_periodic_check(struct GpsState *gps_s)
Periodic GPS check.
Definition: gps.c:209
position in UTM coordinates
#define UTM_COPY(_u1, _u2)
Definition: pprz_geodetic.h:66