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
gps_ubx.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 Antoine Drouin <poinix@gmail.com>
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 
23 #include "subsystems/gps.h"
24 #include "subsystems/abi.h"
25 #include "led.h"
26 
27 #if GPS_USE_LATLONG
28 /* currently needed to get nav_utm_zone0 */
31 #endif
32 
34 #include "ubx_protocol.h"
35 
36 /* parser status */
37 #define UNINIT 0
38 #define GOT_SYNC1 1
39 #define GOT_SYNC2 2
40 #define GOT_CLASS 3
41 #define GOT_ID 4
42 #define GOT_LEN1 5
43 #define GOT_LEN2 6
44 #define GOT_PAYLOAD 7
45 #define GOT_CHECKSUM1 8
46 
47 /* last error type */
48 #define GPS_UBX_ERR_NONE 0
49 #define GPS_UBX_ERR_OVERRUN 1
50 #define GPS_UBX_ERR_MSG_TOO_LONG 2
51 #define GPS_UBX_ERR_CHECKSUM 3
52 #define GPS_UBX_ERR_UNEXPECTED 4
53 #define GPS_UBX_ERR_OUT_OF_SYNC 5
54 
55 #define UTM_HEM_NORTH 0
56 #define UTM_HEM_SOUTH 1
57 
58 struct GpsUbx gps_ubx;
59 
60 #if USE_GPS_UBX_RXM_RAW
61 struct GpsUbxRaw gps_ubx_raw;
62 #endif
63 
64 void gps_impl_init(void)
65 {
68  gps_ubx.error_cnt = 0;
70  gps_ubx.have_velned = 0;
71 }
72 
73 
75 {
76 
77  if (gps_ubx.msg_class == UBX_NAV_ID) {
78  if (gps_ubx.msg_id == UBX_NAV_SOL_ID) {
79  /* get hardware clock ticks */
81  gps_time_sync.t0_tow = UBX_NAV_SOL_ITOW(gps_ubx.msg_buf);
82  gps_time_sync.t0_tow_frac = UBX_NAV_SOL_Frac(gps_ubx.msg_buf);
83  gps.tow = UBX_NAV_SOL_ITOW(gps_ubx.msg_buf);
84  gps.week = UBX_NAV_SOL_week(gps_ubx.msg_buf);
85  gps.fix = UBX_NAV_SOL_GPSfix(gps_ubx.msg_buf);
86  gps.ecef_pos.x = UBX_NAV_SOL_ECEF_X(gps_ubx.msg_buf);
87  gps.ecef_pos.y = UBX_NAV_SOL_ECEF_Y(gps_ubx.msg_buf);
88  gps.ecef_pos.z = UBX_NAV_SOL_ECEF_Z(gps_ubx.msg_buf);
89  gps.pacc = UBX_NAV_SOL_Pacc(gps_ubx.msg_buf);
90  gps.ecef_vel.x = UBX_NAV_SOL_ECEFVX(gps_ubx.msg_buf);
91  gps.ecef_vel.y = UBX_NAV_SOL_ECEFVY(gps_ubx.msg_buf);
92  gps.ecef_vel.z = UBX_NAV_SOL_ECEFVZ(gps_ubx.msg_buf);
93  gps.sacc = UBX_NAV_SOL_Sacc(gps_ubx.msg_buf);
94  gps.pdop = UBX_NAV_SOL_PDOP(gps_ubx.msg_buf);
95  gps.num_sv = UBX_NAV_SOL_numSV(gps_ubx.msg_buf);
96 #ifdef GPS_LED
97  if (gps.fix == GPS_FIX_3D) {
98  LED_ON(GPS_LED);
99  } else {
100  LED_TOGGLE(GPS_LED);
101  }
102 #endif
103  } else if (gps_ubx.msg_id == UBX_NAV_POSLLH_ID) {
104  gps.lla_pos.lat = UBX_NAV_POSLLH_LAT(gps_ubx.msg_buf);
105  gps.lla_pos.lon = UBX_NAV_POSLLH_LON(gps_ubx.msg_buf);
106  gps.lla_pos.alt = UBX_NAV_POSLLH_HEIGHT(gps_ubx.msg_buf);
107  gps.hmsl = UBX_NAV_POSLLH_HMSL(gps_ubx.msg_buf);
108 #if GPS_USE_LATLONG
109  /* Computes from (lat, long) in the referenced UTM zone */
110  struct LlaCoor_f lla_f;
111  LLA_FLOAT_OF_BFP(lla_f, gps.lla_pos);
112  struct UtmCoor_f utm_f;
113  utm_f.zone = nav_utm_zone0;
114  /* convert to utm */
115  utm_of_lla_f(&utm_f, &lla_f);
116  /* copy results of utm conversion */
117  gps.utm_pos.east = utm_f.east * 100;
118  gps.utm_pos.north = utm_f.north * 100;
121 #else
122  } else if (gps_ubx.msg_id == UBX_NAV_POSUTM_ID) {
123  gps.utm_pos.east = UBX_NAV_POSUTM_EAST(gps_ubx.msg_buf);
124  gps.utm_pos.north = UBX_NAV_POSUTM_NORTH(gps_ubx.msg_buf);
125  uint8_t hem = UBX_NAV_POSUTM_HEM(gps_ubx.msg_buf);
126  if (hem == UTM_HEM_SOUTH) {
127  gps.utm_pos.north -= 1000000000; /* Subtract false northing: -10000km */
128  }
129  gps.utm_pos.alt = UBX_NAV_POSUTM_ALT(gps_ubx.msg_buf) * 10;
130  gps.hmsl = gps.utm_pos.alt;
131  gps.lla_pos.alt = gps.utm_pos.alt; // FIXME: with UTM only you do not receive ellipsoid altitude
132  gps.utm_pos.zone = UBX_NAV_POSUTM_ZONE(gps_ubx.msg_buf);
133 #endif
134  } else if (gps_ubx.msg_id == UBX_NAV_VELNED_ID) {
135  gps.speed_3d = UBX_NAV_VELNED_Speed(gps_ubx.msg_buf);
136  gps.gspeed = UBX_NAV_VELNED_GSpeed(gps_ubx.msg_buf);
137  gps.ned_vel.x = UBX_NAV_VELNED_VEL_N(gps_ubx.msg_buf);
138  gps.ned_vel.y = UBX_NAV_VELNED_VEL_E(gps_ubx.msg_buf);
139  gps.ned_vel.z = UBX_NAV_VELNED_VEL_D(gps_ubx.msg_buf);
140  // Ublox gives I4 heading in 1e-5 degrees, apparenty from 0 to 360 degrees (not -180 to 180)
141  // I4 max = 2^31 = 214 * 1e5 * 100 < 360 * 1e7: overflow on angles over 214 deg -> casted to -214 deg
142  // solution: First to radians, and then scale to 1e-7 radians
143  // First x 10 for loosing less resolution, then to radians, then multiply x 10 again
144  gps.course = (RadOfDeg(UBX_NAV_VELNED_Heading(gps_ubx.msg_buf) * 10)) * 10;
145  gps.cacc = (RadOfDeg(UBX_NAV_VELNED_CAcc(gps_ubx.msg_buf) * 10)) * 10;
146  gps.tow = UBX_NAV_VELNED_ITOW(gps_ubx.msg_buf);
147  gps_ubx.have_velned = 1;
148  } else if (gps_ubx.msg_id == UBX_NAV_SVINFO_ID) {
149  gps.nb_channels = Min(UBX_NAV_SVINFO_NCH(gps_ubx.msg_buf), GPS_NB_CHANNELS);
150  uint8_t i;
151  for (i = 0; i < gps.nb_channels; i++) {
152  gps.svinfos[i].svid = UBX_NAV_SVINFO_SVID(gps_ubx.msg_buf, i);
153  gps.svinfos[i].flags = UBX_NAV_SVINFO_Flags(gps_ubx.msg_buf, i);
154  gps.svinfos[i].qi = UBX_NAV_SVINFO_QI(gps_ubx.msg_buf, i);
155  gps.svinfos[i].cno = UBX_NAV_SVINFO_CNO(gps_ubx.msg_buf, i);
156  gps.svinfos[i].elev = UBX_NAV_SVINFO_Elev(gps_ubx.msg_buf, i);
157  gps.svinfos[i].azim = UBX_NAV_SVINFO_Azim(gps_ubx.msg_buf, i);
158  }
159  } else if (gps_ubx.msg_id == UBX_NAV_STATUS_ID) {
160  gps.fix = UBX_NAV_STATUS_GPSfix(gps_ubx.msg_buf);
161  gps_ubx.status_flags = UBX_NAV_STATUS_Flags(gps_ubx.msg_buf);
162  gps_ubx.sol_flags = UBX_NAV_SOL_Flags(gps_ubx.msg_buf);
163  }
164  }
165 #if USE_GPS_UBX_RXM_RAW
166  else if (gps_ubx.msg_class == UBX_RXM_ID) {
167  if (gps_ubx.msg_id == UBX_RXM_RAW_ID) {
168  gps_ubx_raw.iTOW = UBX_RXM_RAW_iTOW(gps_ubx.msg_buf);
169  gps_ubx_raw.week = UBX_RXM_RAW_week(gps_ubx.msg_buf);
170  gps_ubx_raw.numSV = UBX_RXM_RAW_numSV(gps_ubx.msg_buf);
171  uint8_t i;
172  for (i = 0; i < gps_ubx_raw.numSV; i++) {
173  gps_ubx_raw.measures[i].cpMes = UBX_RXM_RAW_cpMes(gps_ubx.msg_buf, i);
174  gps_ubx_raw.measures[i].prMes = UBX_RXM_RAW_prMes(gps_ubx.msg_buf, i);
175  gps_ubx_raw.measures[i].doMes = UBX_RXM_RAW_doMes(gps_ubx.msg_buf, i);
176  gps_ubx_raw.measures[i].sv = UBX_RXM_RAW_sv(gps_ubx.msg_buf, i);
177  gps_ubx_raw.measures[i].mesQI = UBX_RXM_RAW_mesQI(gps_ubx.msg_buf, i);
178  gps_ubx_raw.measures[i].cno = UBX_RXM_RAW_cno(gps_ubx.msg_buf, i);
179  gps_ubx_raw.measures[i].lli = UBX_RXM_RAW_lli(gps_ubx.msg_buf, i);
180  }
181  }
182  }
183 #endif
184 }
185 
186 #if LOG_RAW_GPS
187 #include "sdLog.h"
188 #include "subsystems/chibios-libopencm3/chibios_sdlog.h"
189 #endif
190 
191 /* UBX parsing */
193 {
194 #if LOG_RAW_GPS
195  sdLogWriteByte(pprzLogFile, c);
196 #endif
197  if (gps_ubx.status < GOT_PAYLOAD) {
198  gps_ubx.ck_a += c;
200  }
201  switch (gps_ubx.status) {
202  case UNINIT:
203  if (c == UBX_SYNC1) {
204  gps_ubx.status++;
205  }
206  break;
207  case GOT_SYNC1:
208  if (c != UBX_SYNC2) {
210  goto error;
211  }
212  gps_ubx.ck_a = 0;
213  gps_ubx.ck_b = 0;
214  gps_ubx.status++;
215  break;
216  case GOT_SYNC2:
217  if (gps_ubx.msg_available) {
218  /* Previous message has not yet been parsed: discard this one */
220  goto error;
221  }
222  gps_ubx.msg_class = c;
223  gps_ubx.status++;
224  break;
225  case GOT_CLASS:
226  gps_ubx.msg_id = c;
227  gps_ubx.status++;
228  break;
229  case GOT_ID:
230  gps_ubx.len = c;
231  gps_ubx.status++;
232  break;
233  case GOT_LEN1:
234  gps_ubx.len |= (c << 8);
237  goto error;
238  }
239  gps_ubx.msg_idx = 0;
240  gps_ubx.status++;
241  break;
242  case GOT_LEN2:
244  gps_ubx.msg_idx++;
245  if (gps_ubx.msg_idx >= gps_ubx.len) {
246  gps_ubx.status++;
247  }
248  break;
249  case GOT_PAYLOAD:
250  if (c != gps_ubx.ck_a) {
252  goto error;
253  }
254  gps_ubx.status++;
255  break;
256  case GOT_CHECKSUM1:
257  if (c != gps_ubx.ck_b) {
259  goto error;
260  }
262  goto restart;
263  break;
264  default:
266  goto error;
267  }
268  return;
269 error:
270  gps_ubx.error_cnt++;
271 restart:
273  return;
274 }
275 
276 static void ubx_send_1byte(struct link_device *dev, uint8_t byte)
277 {
278  dev->put_byte(dev->periph, byte);
279  gps_ubx.send_ck_a += byte;
281 }
282 
283 void ubx_header(struct link_device *dev, uint8_t nav_id, uint8_t msg_id, uint16_t len)
284 {
285  dev->put_byte(dev->periph, UBX_SYNC1);
286  dev->put_byte(dev->periph, UBX_SYNC2);
287  gps_ubx.send_ck_a = 0;
288  gps_ubx.send_ck_b = 0;
289  ubx_send_1byte(dev, nav_id);
290  ubx_send_1byte(dev, msg_id);
291  ubx_send_1byte(dev, (uint8_t)(len&0xFF));
292  ubx_send_1byte(dev, (uint8_t)(len>>8));
293 }
294 
296 {
297  dev->put_byte(dev->periph, gps_ubx.send_ck_a);
298  dev->put_byte(dev->periph, gps_ubx.send_ck_b);
299  dev->send_message(dev->periph);
300 }
301 
302 void ubx_send_bytes(struct link_device *dev, uint8_t len, uint8_t *bytes)
303 {
304  int i;
305  for (i = 0; i < len; i++) {
306  ubx_send_1byte(dev, bytes[i]);
307  }
308 }
309 
310 void ubx_send_cfg_rst(struct link_device *dev, uint16_t bbr , uint8_t reset_mode)
311 {
312 #ifdef GPS_LINK
313  UbxSend_CFG_RST(dev, bbr, reset_mode, 0x00);
314 #endif /* else less harmful for HITL */
315 }
316 
317 #ifndef GPS_UBX_UCENTER
318 #define gps_ubx_ucenter_event() {}
319 #else
321 #endif
322 
323 void gps_ubx_msg(void)
324 {
325  // current timestamp
326  uint32_t now_ts = get_sys_time_usec();
327 
332  if (gps_ubx.msg_class == UBX_NAV_ID &&
333  (gps_ubx.msg_id == UBX_NAV_VELNED_ID ||
334  (gps_ubx.msg_id == UBX_NAV_SOL_ID &&
335  gps_ubx.have_velned == 0))) {
336  if (gps.fix == GPS_FIX_3D) {
339  }
340  AbiSendMsgGPS(GPS_UBX_ID, now_ts, &gps);
341  }
343 }
344 
uint8_t qi
quality bitfield (GPS receiver specific)
Definition: gps.h:60
unsigned short uint16_t
Definition: types.h:16
#define GOT_CLASS
Definition: gps_ubx.c:40
int32_t z
in centimeters
#define UTM_HEM_SOUTH
Definition: gps_ubx.c:56
uint32_t t0_tow
GPS time of week in ms from last message.
Definition: gps.h:98
int32_t north
in centimeters
struct SVinfo svinfos[GPS_NB_CHANNELS]
holds information from the Space Vehicles (Satellites)
Definition: gps.h:87
int16_t azim
azimuth in deg
Definition: gps.h:63
float east
in meters
#define GOT_CHECKSUM1
Definition: gps_ubx.c:45
#define Min(x, y)
uint32_t pacc
position accuracy in cm
Definition: gps.h:77
#define GOT_ID
Definition: gps_ubx.c:41
void ubx_trailer(struct link_device *dev)
Definition: gps_ubx.c:295
float north
in meters
void ubx_send_bytes(struct link_device *dev, uint8_t len, uint8_t *bytes)
Definition: gps_ubx.c:302
#define gps_ubx_ucenter_event()
Definition: gps_ubx.c:318
uint8_t nb_channels
Number of scanned satellites.
Definition: gps.h:86
uint32_t t0_ticks
hw clock ticks when GPS message is received
Definition: gps.h:100
uint8_t sol_flags
Definition: gps_ubx.h:54
int32_t y
in centimeters
uint16_t week
GPS week.
Definition: gps.h:83
Definition: gps_ubx.h:39
void gps_ubx_parse(uint8_t c)
Definition: gps_ubx.c:192
#define GPS_UBX_ID
Main include for ABI (AirBorneInterface).
uint8_t nav_utm_zone0
Definition: common_nav.c:44
uint16_t len
Definition: gps_ubx.h:46
struct GpsUbx gps_ubx
Definition: gps_ubx.c:58
position in UTM coordinates Units: meters
uint8_t msg_buf[GPS_UBX_MAX_PAYLOAD]
Definition: gps_ubx.h:41
int32_t east
in centimeters
uint8_t svid
Satellite ID.
Definition: gps.h:58
volatile uint32_t nb_tick
SYS_TIME_TICKS since startup.
Definition: sys_time.h:71
uint16_t speed_3d
norm of 3d speed in cm/s
Definition: gps.h:75
#define GPS_FIX_3D
3D GPS fix
Definition: gps.h:43
int32_t z
Down.
struct UtmCoor_i utm_pos
position in UTM (north,east: cm; alt: mm over ellipsoid)
Definition: gps.h:70
static void ubx_send_1byte(struct link_device *dev, uint8_t byte)
Definition: gps_ubx.c:276
#define GPS_UBX_ERR_OUT_OF_SYNC
Definition: gps_ubx.c:53
uint8_t msg_id
Definition: gps_ubx.h:42
uint8_t error_cnt
Definition: gps_ubx.h:50
uint32_t last_3dfix_ticks
cpu time ticks at last valid 3D fix
Definition: gps.h:89
int8_t elev
elevation in deg
Definition: gps.h:62
#define FALSE
Definition: std.h:5
int32_t alt
in millimeters above WGS84 reference ellipsoid
static uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
Definition: sys_time_arch.h:39
#define GPS_UBX_MAX_PAYLOAD
Definition: gps_ubx.h:38
uint32_t sacc
speed accuracy in cm/s
Definition: gps.h:78
#define LED_TOGGLE(i)
Definition: led_hw.h:44
int32_t y
East.
#define GOT_SYNC2
Definition: gps_ubx.c:39
uint32_t last_msg_time
cpu time in sec at last received GPS message
Definition: gps.h:92
uint32_t cacc
course accuracy in rad*1e7
Definition: gps.h:79
uint8_t zone
UTM zone number.
Paparazzi floating point math for geodetic calculations.
Configure Ublox GPS.
vector in Latitude, Longitude and Altitude
#define TRUE
Definition: std.h:4
#define GPS_UBX_ERR_UNEXPECTED
Definition: gps_ubx.c:52
int32_t hmsl
height above mean sea level in mm
Definition: gps.h:71
uint8_t cno
Carrier to Noise Ratio (Signal Strength) in dbHz.
Definition: gps.h:61
uint32_t tow
GPS time of week in ms.
Definition: gps.h:84
uint8_t ck_b
Definition: gps_ubx.h:48
Device independent GPS code (interface)
uint16_t pdop
position dilution of precision scaled by 100
Definition: gps.h:80
uint8_t ck_a
Definition: gps_ubx.h:48
void ubx_header(struct link_device *dev, uint8_t nav_id, uint8_t msg_id, uint16_t len)
Definition: gps_ubx.c:283
int32_t x
North.
unsigned long uint32_t
Definition: types.h:18
struct EcefCoor_i ecef_pos
position in ECEF in cm
Definition: gps.h:68
bool_t msg_available
Definition: gps_ubx.h:40
void ubx_send_cfg_rst(struct link_device *dev, uint16_t bbr, uint8_t reset_mode)
Definition: gps_ubx.c:310
uint8_t msg_idx
Definition: gps_ubx.h:47
int32_t lon
in degrees*1e7
#define GPS_UBX_ERR_MSG_TOO_LONG
Definition: gps_ubx.c:50
uint8_t zone
UTM zone number.
volatile uint32_t nb_sec_rem
remainder of seconds since startup in CPU_TICKS
Definition: sys_time.h:70
uint8_t send_ck_b
Definition: gps_ubx.h:49
uint8_t status
Definition: gps_ubx.h:45
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:69
void gps_ubx_read_message(void)
Definition: gps_ubx.c:74
uint8_t status_flags
Definition: gps_ubx.h:53
#define LED_ON(i)
Definition: led_hw.h:42
uint32_t last_3dfix_time
cpu time in sec at last valid 3D fix
Definition: gps.h:90
int32_t alt
in millimeters above WGS84 reference ellipsoid
#define GOT_LEN1
Definition: gps_ubx.c:42
unsigned char uint8_t
Definition: types.h:14
#define GPS_UBX_ERR_OVERRUN
Definition: gps_ubx.c:49
int32_t course
GPS course over ground in rad*1e7, [0, 2*Pi]*1e7 (CW/north)
Definition: gps.h:76
#define GOT_PAYLOAD
Definition: gps_ubx.c:44
volatile uint32_t nb_sec
full seconds since startup
Definition: sys_time.h:69
int32_t t0_tow_frac
fractional ns remainder of tow [ms], range -500000 .. 500000
Definition: gps.h:99
uint8_t flags
bitfield with GPS receiver specific flags
Definition: gps.h:59
struct GpsTimeSync gps_time_sync
Definition: gps.c:43
uint32_t last_msg_ticks
cpu time ticks at last received GPS message
Definition: gps.h:91
#define GOT_LEN2
Definition: gps_ubx.c:43
uint8_t num_sv
number of sat in fix
Definition: gps.h:81
arch independent LED (Light Emitting Diodes) API
int32_t x
in centimeters
#define UNINIT
Includes macros generated from ubx.xml.
Definition: gps_ubx.c:37
uint16_t gspeed
norm of 2d ground speed in cm/s
Definition: gps.h:74
struct EcefCoor_i ecef_vel
speed ECEF in cm/s
Definition: gps.h:72
uint8_t send_ck_a
Definition: gps_ubx.h:49
struct LlaCoor_i lla_pos
position in LLA (lat,lon: deg*1e7; alt: mm over ellipsoid)
Definition: gps.h:69
uint8_t have_velned
Definition: gps_ubx.h:55
void gps_ubx_msg(void)
Definition: gps_ubx.c:323
void gps_impl_init(void)
GPS initialization.
Definition: gps_ubx.c:64
int32_t lat
in degrees*1e7
uint8_t fix
status of fix
Definition: gps.h:82
uint8_t error_last
Definition: gps_ubx.h:51
#define GOT_SYNC1
Definition: gps_ubx.c:38
struct NedCoor_i ned_vel
speed NED in cm/s
Definition: gps.h:73
#define GPS_UBX_ERR_NONE
Definition: gps_ubx.c:48
uint8_t msg_class
Definition: gps_ubx.h:43
struct GpsState gps
global GPS state
Definition: gps.c:41
#define LLA_FLOAT_OF_BFP(_o, _i)
#define GPS_UBX_ERR_CHECKSUM
Definition: gps_ubx.c:51
void utm_of_lla_f(struct UtmCoor_f *utm, struct LlaCoor_f *lla)