Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
navdata.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016 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, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
21/* Thanks to TU Delft by assigning students Dino Hensen, Vincent van Hoek for
22 * their inital work and later improvements made in 2015 by Freek van Tienen
23*/
24
33#include <stdio.h>
34#include <stdlib.h>
35#include <fcntl.h>
36#include <termios.h> /* for baud rates and options */
37#include <unistd.h>
38#include <string.h>
39#include <math.h>
40#include <errno.h>
41#include <assert.h>
42#include <pthread.h>
43
44#include "std.h"
45#include "navdata.h"
46#include "modules/ins/ins.h"
47#include "modules/ahrs/ahrs.h"
48#include "modules/core/abi.h"
49#include "mcu_periph/gpio.h"
50
51/* Internal used functions */
52static void *navdata_read(void *data __attribute__((unused)));
53static void navdata_cmd_send(uint8_t cmd);
54static bool navdata_baro_calib(void);
55static void mag_freeze_check(void);
56static void baro_update_logic(void);
57
58/* Main navdata structure */
60
64static bool navdata_available = false;
65
66/* syncronization variables */
69
70#ifndef NAVDATA_FILTER_ID
71#define NAVDATA_FILTER_ID 2
72#endif
73
78#ifndef SONAR_OFFSET
79#define SONAR_OFFSET 880
80#endif
81
85#ifndef SONAR_SCALE
86#define SONAR_SCALE 0.00047
87#endif
88
92static const struct Int32Rates gyro_scale[2] = {
93 {4359, 4359, 4359},
94 {1000, 1000, 1000}
95};
96
100static const struct Int32Vect3 accel_scale[2] = {
101 {195, 195, 195},
102 {10, 10, 10}
103};
104static const struct Int32Vect3 accel_neutral = {
105 2048, 2048, 2048
106};
107
111static const struct Int32Vect3 mag_scale[2] = {
112 {16, 16, 16},
113 {1, 1, 1}
114};
115
119ssize_t full_write(int fd, const uint8_t *buf, size_t count)
120{
121 size_t written = 0;
122
123 while (written < count) {
124 ssize_t n = write(fd, buf + written, count - written);
125 if (n < 0) {
126 if (errno == EAGAIN || errno == EWOULDBLOCK) {
127 continue;
128 }
129 return n;
130 }
131 written += n;
132 }
133 return written;
134}
135
139ssize_t full_read(int fd, uint8_t *buf, size_t count)
140{
141 /* Apologies for illiteracy, but we can't overload |read|.*/
142 size_t readed = 0;
143
144 while (readed < count) {
145 ssize_t n = read(fd, buf + readed, count - readed);
146 if (n < 0) {
147 if (errno == EAGAIN || errno == EWOULDBLOCK) {
148 continue;
149 }
150 return n;
151 }
152 readed += n;
153 }
154 return readed;
155}
156
157#if PERIODIC_TELEMETRY
159
160static void send_navdata(struct transport_tx *trans, struct link_device *dev)
161{
162#pragma GCC diagnostic push
163#pragma GCC diagnostic ignored "-Wpragmas"
164#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
195#pragma GCC diagnostic pop
196}
197#endif
198
203{
205
206 /* Check if the FD isn't already initialized */
207 if (navdata.fd <= 0) {
208 navdata.fd = open("/dev/ttyO1", O_RDWR | O_NOCTTY); /* O_NONBLOCK doesn't work */
209
210 if (navdata.fd < 0) {
211 printf("[navdata] Unable to open navdata board connection(/dev/ttyO1)\n");
212 return false;
213 }
214
215 /* Update the settings of the UART connection */
216 fcntl(navdata.fd, F_SETFL, 0); /* read calls are non blocking */
217 /* set port options */
218 struct termios options;
219 /* Get the current options for the port */
221 /* Set the baud rates to 460800 */
224
225 options.c_cflag |= (CLOCAL | CREAD); /* Enable the receiver and set local mode */
226 options.c_iflag = 0; /* clear input options */
227 options.c_lflag = 0; /* clear local options */
228 options.c_oflag &= ~OPOST; //clear output options (raw output)
229
230 //Set the new options for the port
232 }
233
234 // Reset available flags
235 navdata_available = false;
236 navdata.baro_calibrated = false;
237 navdata.baro_available = false;
238 navdata.imu_lost = false;
239
240 // Set all statistics to 0
246
247 /* Stop acquisition */
249
250 /* Read the baro calibration(blocking) */
251 if (!navdata_baro_calib()) {
252 printf("[navdata] Could not acquire baro calibration!\n");
253 return false;
254 }
256
257 /* Set the default scalings/neutrals */
261
262 /* Start acquisition */
264
265 /* Set navboard gpio control */
268
269 /* Start navdata reading thread */
272 printf("[navdata] Could not create navdata reading thread!\n");
273 return false;
274 }
275 pthread_setname_np(navdata_thread, "pprz_navdata_thread");
276
277#if PERIODIC_TELEMETRY
279#endif
280
281 /* Set to initialized */
282 navdata.is_initialized = true;
283 return true;
284}
285
286
291static void *navdata_read(void *data __attribute__((unused)))
292{
293 /* Buffer insert index for reading/writing */
294 static uint8_t buffer_idx = 0;
295
296 while (TRUE) {
297
298 /* Wait until we are notified to read next data,
299 i.e. buffer has been copied in navdata_update */
301 while (navdata_available) {
303 }
305
306 /* Read new bytes */
307 int newbytes = read(navdata.fd, navdata_buffer + buffer_idx, NAVDATA_PACKET_SIZE - buffer_idx);
308
309 /* When there was no signal interrupt */
310 if (newbytes > 0) {
311 buffer_idx += newbytes;
313 }
314
315 /* If we got a full packet */
316 if (buffer_idx >= NAVDATA_PACKET_SIZE) {
317 /* check if the start byte is correct */
320
321 /* Check if we found the start byte in the read data */
322 if (pint != NULL) {
324 buffer_idx = pint - navdata_buffer;
325 fprintf(stderr, "[navdata] sync error, startbyte not found, resetting...\n");
326 } else {
327 buffer_idx = 0;
328 }
329 continue;
330 }
331
332 /* full packet read with startbyte at the beginning, reset insert index */
333 buffer_idx = 0;
334
335 /* Calculate the checksum */
336 uint16_t checksum = 0;
337 for (int i = 2; i < NAVDATA_PACKET_SIZE - 2; i += 2) {
338 checksum += navdata_buffer[i] + (navdata_buffer[i + 1] << 8);
339 }
340
342
343 /* Check if the checksum is OK */
344 if (new_measurement->chksum != checksum) {
345 fprintf(stderr, "[navdata] Checksum error [calculated: %d] [packet: %d] [diff: %d]\n",
348 continue;
349 }
350
351 /* Set flag that we have new valid navdata */
353 navdata_available = true;
355 }
356 }
357
358 return NULL;
359}
360
361#include "modules/imu/imu.h"
362static void navdata_publish_imu(void)
363{
365 struct Int32Rates gyro = {
369 };
371
372 struct Int32Vect3 accel = {
374 4096 - navdata.measure.ay,
375 4096 - navdata.measure.az
376 };
378
379 struct Int32Vect3 mag = {
383 };
385}
386
391{
392 /* Check if initialized */
393 if (!navdata.is_initialized) {
394 navdata_init();
396 return;
397 }
398
400 /* If we got a new navdata packet */
401 if (navdata_available) {
402
403 /* Copy the navdata packet */
405
406 /* reset the flag */
407 navdata_available = false;
408 /* signal that we copied the buffer and new packet can be read */
411
412 /* Check if we missed a packet (our counter and the one from the navdata) */
415 fprintf(stderr, "[navdata] Lost frame: %d should have been %d\n",
418 }
420
421 /* Invert byte order so that TELEMETRY works better */
422 uint8_t tmp;
424 tmp = p[0];
425 p[0] = p[1];
426 p[1] = tmp;
428 tmp = p[0];
429 p[0] = p[1];
430 p[1] = tmp;
431
434
435#ifdef USE_SONAR
436 /* Check if there is a new sonar measurement and update the sonar */
437 if (navdata.measure.ultrasound >> 15) {
441 }
442#endif
443
445
447 } else {
448 /* no new packet available, still unlock mutex again */
450 }
451}
452
456static void navdata_cmd_send(uint8_t cmd)
457{
458 full_write(navdata.fd, &cmd, 1);
459}
460
461
465static bool navdata_baro_calib(void)
466{
467 /* Start baro calibration acquisition */
469
470 /* Receive the calibration (blocking) */
472 if (full_read(navdata.fd, calibBuffer, sizeof calibBuffer) < 0) {
473 printf("[navdata] Could not read calibration data.");
474 return false;
475 }
476
477 /* Convert the read bytes */
489
490 return true;
491}
492
497static void mag_freeze_check(void)
498{
499 /* Thanks to Daren.G.Lee for initial fix on 20140530 */
500 static int16_t LastMagValue = 0;
501 static int MagFreezeCounter = 0;
502
505
506 /* Has to have at least 30 times the exact same value to consider it a frozen magnetometer value */
507 if (MagFreezeCounter > 30) {
508 fprintf(stderr, "mag freeze detected, resetting!\n");
509
510 /* set imu_lost flag */
511 navdata.imu_lost = true;
513
514 /* Stop acquisition */
516
517 /* Reset the hardware of the navboard */
519 usleep(20000);
521
522 /* Wait for 40ms for it to boot */
523 usleep(40000);
524
525 /* Start the navdata again and reset the counter */
527 MagFreezeCounter = 0; /* reset counter back to zero */
528 }
529 } else {
530 navdata.imu_lost = false;
531 /* Reset counter if value _does_ change */
533 }
534 /* set last value */
536}
537
543static void baro_update_logic(void)
544{
545 static int32_t lastpressval = 0;
546 static uint16_t lasttempval = 0;
547 static int32_t lastpressval_nospike = 0;
548 static uint16_t lasttempval_nospike = 0;
550 0; /* 0 = press, so we now wait for temp, 1 = temp so we now wait for press */
551
552 static int sync_errors = 0;
553 static int spike_detected = 0;
554
555 if (temp_or_press_was_updated_last == 0) { /* Last update was press so we are now waiting for temp */
556 /* temp was updated */
558
559 /* This means that press must remain constant */
560 if (lastpressval != 0) {
561 /* If pressure was updated: this is a sync error */
563 /* wait for temp again */
565 sync_errors++;
566 //printf("Baro-Logic-Error (expected updated temp, got press)\n");
567 }
568 }
569 } else {
570 /* press was updated */
572
573 /* This means that temp must remain constant */
574 if (lasttempval != 0) {
575 /* If temp was updated: this is a sync error */
577 /* wait for press again */
579 sync_errors++;
580 //printf("Baro-Logic-Error (expected updated press, got temp)\n");
581
582 } else {
583 /* We now got valid pressure and temperature */
584 navdata.baro_available = true;
585 }
586 }
587 }
588
589 /* Detected a pressure swap */
590 if (lastpressval != 0 && lasttempval != 0
592 navdata.baro_available = false;
593 }
594
595 /* Detected a temprature swap */
596 if (lastpressval != 0 && lasttempval != 0
598 navdata.baro_available = false;
599 }
600
603
604 /*
605 * It turns out that a lot of navdata boards have a problem (probably interrupt related)
606 * in which reading I2C data and writing uart output data is interrupted very long (50% of 200Hz).
607 * Afterwards, the 200Hz loop tries to catch up lost time but reads the baro too fast swapping the
608 * pressure and temperature values by exceeding the minimal conversion time of the bosh baro. The
609 * normal Parrot firmware seems to be perfectly capable to fly with this, either with excessive use of
610 * the sonar or with software filtering or spike detection. Paparazzi with its tightly coupled baro-altitude
611 * had problems. Since this problems looks not uncommon a detector was made. A lot of evidence is grabbed
612 * with a logic analyzer on the navboard I2C and serial output. The UART CRC is still perfect, the baro
613 * temp-press-temp-press logic is still perfect, so not easy to detect. Temp and pressure are swapped,
614 * and since both can have almost the same value, the size of the spike is not predictable. However at
615 * every spike of at least 3 broken boards the press and temp are byte-wise exactly the same due to
616 * reading them too quickly (trying to catch up for delay that happened earlier due to still non understood
617 * reasons. As pressure is more likely to quickly change, a small (yet unlikely) spike on temperature together with
618 * press==temp yields very good results as a detector, although theoretically not perfect.
619
620 #samp press temp.
621 50925 39284 34501
622 50926 39287 34501
623 50927 39287 34501
624 50928 39283 34501 // *press good -> baro
625 50929 39283 34501
626 50930 39285 34501 // *press good -> baro
627 50931 39285 34500
628 50932 34500 34500 // press read too soon from chip (<4.5ms) -> ADC register still previous temp value
629 50933 34500 36618 // press not updated, still wrong. Temp is weird: looks like the average of both
630 50934 39284 36618 // new press read, but temp still outdated
631 50935 39284 34501
632 50936 39284 34501 // *press good -> baro
633 50937 39284 34500
634 50938 39281 34500
635 50939 39281 34500
636 50940 39280 34500
637 50941 39280 34502
638 50942 39280 34502
639 50943 39280 34501
640
641 */
642
643 /* If press and temp are same and temp has jump: neglect the next frame */
645 navdata.measure.pressure) { // && (abs((int32_t)navdata.temperature_pressure - (int32_t)lasttempval) > 40))
646 /* dont use the next 3 packets */
647 spike_detected = 3;
648 }
649
650 if (spike_detected > 0) {
651 /* disable kalman filter use */
652 navdata.baro_available = false;
653
654 // override both to last good
657
658 /* Countdown */
660 } else { // both are good
663 }
664}
Main include for ABI (AirBorneInterface).
#define AGL_SONAR_ARDRONE2_ID
#define IMU_BOARD_ID
static uint8_t checksum
#define ARDRONE_GPIO_PORT
Definition actuators.c:58
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
static void gpio_set(ioportid_t port, uint16_t pin)
Set a gpio output to high level.
Definition gpio_arch.h:104
static void gpio_clear(ioportid_t port, uint16_t pin)
Clear a gpio output to low level.
Definition gpio_arch.h:114
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
#define B460800
Definition uart_arch.h:50
Some architecture independent helper functions for GPIOs.
angular rates
void imu_set_defaults_mag(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Vect3 *neutral, const struct Int32Vect3 *scale)
Set the defaults for a mag sensor WARNING: Should be called before sensor is publishing messages to e...
Definition imu.c:640
void imu_set_defaults_accel(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Vect3 *neutral, const struct Int32Vect3 *scale)
Set the defaults for a accel sensor WARNING: Should be called before sensor is publishing messages to...
Definition imu.c:610
void imu_set_defaults_gyro(uint8_t abi_id, const struct Int32RMat *imu_to_sensor, const struct Int32Rates *neutral, const struct Int32Rates *scale)
Set the defaults for a gyro sensor WARNING: Should be called before sensor is publishing messages to ...
Definition imu.c:580
Inertial Measurement Unit interface.
Integrated Navigation System interface.
static float p[2][2]
uint16_t foo
Definition main_demo5.c:58
static void mag_freeze_check(void)
Check if the magneto is frozen Unknown why this bug happens.
Definition navdata.c:497
static bool navdata_baro_calib(void)
Try to receive the baro calibration from the navdata board.
Definition navdata.c:465
static void send_navdata(struct transport_tx *trans, struct link_device *dev)
Definition navdata.c:160
ssize_t full_write(int fd, const uint8_t *buf, size_t count)
Write to fd even while being interrupted.
Definition navdata.c:119
static void * navdata_read(void *data)
Main reading thread This is done asynchronous because the navdata board doesn't support NON_BLOCKING.
Definition navdata.c:291
static void baro_update_logic(void)
Handle the baro(pressure/temperature) logic Sometimes the temperature and pressure are switched becau...
Definition navdata.c:543
void navdata_update()
Update the navdata (event loop)
Definition navdata.c:390
static const struct Int32Vect3 accel_neutral
Definition navdata.c:104
static void navdata_cmd_send(uint8_t cmd)
Sends a one byte command.
Definition navdata.c:456
static uint8_t navdata_buffer[NAVDATA_PACKET_SIZE]
Buffer filled in the thread (maximum one navdata packet)
Definition navdata.c:62
#define SONAR_SCALE
Sonar scale.
Definition navdata.c:86
struct navdata_t navdata
Definition navdata.c:59
static pthread_mutex_t navdata_mutex
Definition navdata.c:67
static const struct Int32Vect3 mag_scale[2]
Default mag scale.
Definition navdata.c:111
bool navdata_init()
Initialize the navdata board.
Definition navdata.c:202
static const struct Int32Rates gyro_scale[2]
Default gyro scale.
Definition navdata.c:92
static bool navdata_available
flag to indicate new packet is available in buffer
Definition navdata.c:64
#define SONAR_OFFSET
Sonar offset.
Definition navdata.c:79
static void navdata_publish_imu(void)
Definition navdata.c:362
static const struct Int32Vect3 accel_scale[2]
Default accel scale/neutral.
Definition navdata.c:100
ssize_t full_read(int fd, uint8_t *buf, size_t count)
Read from fd even while being interrupted.
Definition navdata.c:139
static pthread_cond_t navdata_cond
Definition navdata.c:68
ardrone2 navdata aquisition driver.
int32_t pressure
Definition navdata.h:75
uint16_t nb_echo
Definition navdata.h:68
struct bmp180_calib_t bmp180_calib
BMP180 calibration receieved from navboard.
Definition navdata.h:126
int16_t ac2
Definition navdata.h:89
uint16_t ac4
Definition navdata.h:91
uint32_t totalBytesRead
Definition navdata.h:119
int16_t gradient
Definition navdata.h:71
uint16_t temperature_gyro
Definition navdata.h:55
int16_t ac3
Definition navdata.h:90
uint16_t ay
Definition navdata.h:48
int16_t mc
Definition navdata.h:97
uint16_t us_debut_echo
Definition navdata.h:59
struct navdata_measure_t measure
Main navdata packet receieved from navboard.
Definition navdata.h:125
bool imu_lost
Whenever the imu is lost.
Definition navdata.h:130
#define NAVDATA_CMD_STOP
Definition navdata.h:108
int16_t ac1
Definition navdata.h:88
uint16_t flag_echo_ini
Definition navdata.h:73
uint16_t ac6
Definition navdata.h:93
uint32_t lost_imu_frames
Definition navdata.h:122
bool baro_calibrated
Whenever the baro is calibrated.
Definition navdata.h:128
#define NAVDATA_START_BYTE
Definition navdata.h:106
uint32_t packetsRead
Definition navdata.h:120
uint16_t chksum
Definition navdata.h:82
uint16_t ultrasound
Definition navdata.h:57
uint16_t us_curve_ref
Definition navdata.h:66
uint16_t nu_trame
Definition navdata.h:45
#define ARDRONE_GPIO_PIN_NAVDATA
Definition navdata.h:112
uint16_t taille
Definition navdata.h:44
int16_t b1
Definition navdata.h:94
int fd
The navdata file pointer.
Definition navdata.h:117
uint16_t temperature_acc
Definition navdata.h:54
bool baro_available
Whenever the baro is available.
Definition navdata.h:129
int16_t md
Definition navdata.h:98
uint16_t us_distance_echo
Definition navdata.h:62
uint16_t us_curve_value
Definition navdata.h:65
#define NAVDATA_CMD_START
Definition navdata.h:107
uint32_t checksum_errors
Definition navdata.h:121
#define NAVDATA_CMD_BARO_CALIB
Definition navdata.h:109
int16_t b2
Definition navdata.h:95
uint16_t us_fin_echo
Definition navdata.h:60
uint16_t last_packet_number
Definition navdata.h:123
uint16_t ac5
Definition navdata.h:92
uint32_t sum_echo
Definition navdata.h:70
#define NAVDATA_PACKET_SIZE
Definition navdata.h:105
bool is_initialized
Check if the navdata board is initialized.
Definition navdata.h:116
uint16_t us_association_echo
Definition navdata.h:61
uint16_t az
Definition navdata.h:49
uint16_t us_curve_time
Definition navdata.h:64
int16_t mb
Definition navdata.h:96
uint16_t temperature_pressure
Definition navdata.h:76
uint16_t ax
Definition navdata.h:47
Main navdata structure from the navdata board This is received from the navdata board at ~200Hz.
Definition navdata.h:43
int fd
Definition serial.c:26
#define TRUE
Definition std.h:4
static const struct usb_device_descriptor dev
Definition usb_ser_hw.c:74
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition telemetry.c:51
Periodic telemetry system header (includes downlink utility and generated code).
#define DefaultPeriodic
Set default periodic telemetry.
Definition telemetry.h:66
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.