2014-03-28 16:52:27 -03:00
|
|
|
/*
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
2010-09-08 02:06:56 -03:00
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2010-09-08 02:06:56 -03:00
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2016-02-17 21:25:23 -04:00
|
|
|
#pragma once
|
2012-12-18 20:40:18 -04:00
|
|
|
|
2015-08-11 03:28:43 -03:00
|
|
|
#include <AP_HAL/AP_HAL.h>
|
2014-03-28 16:52:27 -03:00
|
|
|
#include <inttypes.h>
|
2015-08-11 03:28:43 -03:00
|
|
|
#include <AP_Common/AP_Common.h>
|
|
|
|
#include <AP_Param/AP_Param.h>
|
|
|
|
#include <AP_Math/AP_Math.h>
|
|
|
|
#include <GCS_MAVLink/GCS_MAVLink.h>
|
|
|
|
#include <AP_Vehicle/AP_Vehicle.h>
|
2014-03-28 16:52:27 -03:00
|
|
|
#include "GPS_detect_state.h"
|
2015-08-15 19:50:18 -03:00
|
|
|
#include <AP_SerialManager/AP_SerialManager.h>
|
2014-03-28 16:52:27 -03:00
|
|
|
|
|
|
|
/**
|
|
|
|
maximum number of GPS instances available on this platform. If more
|
|
|
|
than 1 then redundent sensors may be available
|
|
|
|
*/
|
|
|
|
#define GPS_MAX_INSTANCES 2
|
2015-06-27 04:26:25 -03:00
|
|
|
#define GPS_RTK_INJECT_TO_ALL 127
|
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
class DataFlash_Class;
|
|
|
|
class AP_GPS_Backend;
|
|
|
|
|
|
|
|
/// @class AP_GPS
|
|
|
|
/// GPS driver main class
|
|
|
|
class AP_GPS
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// constructor
|
|
|
|
AP_GPS() {
|
|
|
|
AP_Param::setup_object_defaults(this, var_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Startup initialisation.
|
2015-01-19 09:36:35 -04:00
|
|
|
void init(DataFlash_Class *dataflash, const AP_SerialManager& serial_manager);
|
2014-03-28 16:52:27 -03:00
|
|
|
|
|
|
|
/// Update GPS state based on possible bytes received from the module.
|
|
|
|
/// This routine must be called periodically (typically at 10Hz or
|
|
|
|
/// more) to process incoming data.
|
|
|
|
void update(void);
|
|
|
|
|
|
|
|
// GPS driver types
|
|
|
|
enum GPS_Type {
|
|
|
|
GPS_TYPE_NONE = 0,
|
|
|
|
GPS_TYPE_AUTO = 1,
|
|
|
|
GPS_TYPE_UBLOX = 2,
|
|
|
|
GPS_TYPE_MTK = 3,
|
|
|
|
GPS_TYPE_MTK19 = 4,
|
|
|
|
GPS_TYPE_NMEA = 5,
|
2014-04-01 03:25:15 -03:00
|
|
|
GPS_TYPE_SIRF = 6,
|
2014-04-04 20:05:54 -03:00
|
|
|
GPS_TYPE_HIL = 7,
|
2014-11-03 08:37:06 -04:00
|
|
|
GPS_TYPE_SBP = 8,
|
2015-09-02 06:13:38 -03:00
|
|
|
GPS_TYPE_PX4 = 9,
|
|
|
|
GPS_TYPE_SBF = 10,
|
2015-09-11 10:42:58 -03:00
|
|
|
GPS_TYPE_GSOF = 11,
|
2015-12-19 22:56:10 -04:00
|
|
|
GPS_TYPE_QURT = 12,
|
2016-01-18 17:54:40 -04:00
|
|
|
GPS_TYPE_ERB = 13,
|
2016-05-19 20:24:08 -03:00
|
|
|
GPS_TYPE_MAV = 14,
|
2016-05-16 10:09:06 -03:00
|
|
|
GPS_TYPE_NOVA = 15,
|
2014-03-28 16:52:27 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
/// GPS status codes
|
|
|
|
enum GPS_Status {
|
|
|
|
NO_GPS = 0, ///< No GPS connected/detected
|
|
|
|
NO_FIX = 1, ///< Receiving valid GPS messages but no lock
|
|
|
|
GPS_OK_FIX_2D = 2, ///< Receiving valid messages and 2D lock
|
2014-03-31 20:39:53 -03:00
|
|
|
GPS_OK_FIX_3D = 3, ///< Receiving valid messages and 3D lock
|
|
|
|
GPS_OK_FIX_3D_DGPS = 4, ///< Receiving valid messages and 3D lock with differential improvements
|
|
|
|
GPS_OK_FIX_3D_RTK = 5, ///< Receiving valid messages and 3D lock, with relative-positioning improvements
|
2014-03-28 16:52:27 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
// GPS navigation engine settings. Not all GPS receivers support
|
|
|
|
// this
|
|
|
|
enum GPS_Engine_Setting {
|
|
|
|
GPS_ENGINE_NONE = -1,
|
|
|
|
GPS_ENGINE_PORTABLE = 0,
|
|
|
|
GPS_ENGINE_STATIONARY = 2,
|
|
|
|
GPS_ENGINE_PEDESTRIAN = 3,
|
|
|
|
GPS_ENGINE_AUTOMOTIVE = 4,
|
|
|
|
GPS_ENGINE_SEA = 5,
|
|
|
|
GPS_ENGINE_AIRBORNE_1G = 6,
|
|
|
|
GPS_ENGINE_AIRBORNE_2G = 7,
|
|
|
|
GPS_ENGINE_AIRBORNE_4G = 8
|
|
|
|
};
|
|
|
|
|
2016-02-02 03:58:33 -04:00
|
|
|
enum GPS_Config {
|
|
|
|
GPS_ALL_CONFIGURED = 255
|
|
|
|
};
|
|
|
|
|
2014-03-31 06:48:22 -03:00
|
|
|
/*
|
|
|
|
The GPS_State structure is filled in by the backend driver as it
|
|
|
|
parses each message from the GPS.
|
|
|
|
*/
|
2014-03-28 16:52:27 -03:00
|
|
|
struct GPS_State {
|
|
|
|
uint8_t instance; // the instance number of this GPS
|
|
|
|
|
|
|
|
// all the following fields must all be filled by the backend driver
|
|
|
|
GPS_Status status; ///< driver fix status
|
|
|
|
uint32_t time_week_ms; ///< GPS time (milliseconds from start of GPS week)
|
|
|
|
uint16_t time_week; ///< GPS week number
|
|
|
|
Location location; ///< last fix location
|
|
|
|
float ground_speed; ///< ground speed in m/sec
|
2016-05-04 22:28:35 -03:00
|
|
|
float ground_course; ///< ground course in degrees
|
2014-04-01 17:49:29 -03:00
|
|
|
uint16_t hdop; ///< horizontal dilution of precision in cm
|
2015-09-07 19:22:12 -03:00
|
|
|
uint16_t vdop; ///< vertical dilution of precision in cm
|
2016-05-12 14:02:29 -03:00
|
|
|
uint8_t num_sats; ///< Number of visible satellites
|
2014-03-28 16:52:27 -03:00
|
|
|
Vector3f velocity; ///< 3D velocitiy in m/s, in NED format
|
2014-10-28 16:44:07 -03:00
|
|
|
float speed_accuracy;
|
|
|
|
float horizontal_accuracy;
|
|
|
|
float vertical_accuracy;
|
2014-03-28 16:52:27 -03:00
|
|
|
bool have_vertical_velocity:1; ///< does this GPS give vertical velocity?
|
2014-10-28 16:44:07 -03:00
|
|
|
bool have_speed_accuracy:1;
|
|
|
|
bool have_horizontal_accuracy:1;
|
|
|
|
bool have_vertical_accuracy:1;
|
2014-03-28 16:52:27 -03:00
|
|
|
uint32_t last_gps_time_ms; ///< the system time we got the last GPS timestamp, milliseconds
|
|
|
|
};
|
|
|
|
|
2016-05-19 20:24:08 -03:00
|
|
|
// Pass mavlink data to message handlers (for MAV type)
|
2016-10-04 04:37:01 -03:00
|
|
|
void handle_msg(const mavlink_message_t *msg);
|
2016-05-19 20:24:08 -03:00
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
// Accessor functions
|
|
|
|
|
2014-04-03 18:32:34 -03:00
|
|
|
// return number of active GPS sensors. Note that if the first GPS
|
|
|
|
// is not present but the 2nd is then we return 2
|
2014-03-28 16:52:27 -03:00
|
|
|
uint8_t num_sensors(void) const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return num_instances;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
2014-06-06 18:58:11 -03:00
|
|
|
uint8_t primary_sensor(void) const {
|
|
|
|
return primary_instance;
|
|
|
|
}
|
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
/// Query GPS status
|
|
|
|
GPS_Status status(uint8_t instance) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
return state[instance].status;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
GPS_Status status(void) const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return status(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
2014-06-06 18:58:11 -03:00
|
|
|
// Query the highest status this GPS supports
|
|
|
|
GPS_Status highest_supported_status(uint8_t instance) const;
|
|
|
|
GPS_Status highest_supported_status(void) const;
|
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
// location of last fix
|
|
|
|
const Location &location(uint8_t instance) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
return state[instance].location;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
const Location &location() const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return location(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
2014-10-28 16:44:07 -03:00
|
|
|
bool speed_accuracy(uint8_t instance, float &sacc) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
if(state[instance].have_speed_accuracy) {
|
|
|
|
sacc = state[instance].speed_accuracy;
|
2014-10-28 16:44:07 -03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool speed_accuracy(float &sacc) const {
|
|
|
|
return speed_accuracy(primary_instance, sacc);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool horizontal_accuracy(uint8_t instance, float &hacc) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
if(state[instance].have_horizontal_accuracy) {
|
|
|
|
hacc = state[instance].horizontal_accuracy;
|
2014-10-28 16:44:07 -03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool horizontal_accuracy(float &hacc) const {
|
|
|
|
return horizontal_accuracy(primary_instance, hacc);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool vertical_accuracy(uint8_t instance, float &vacc) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
if(state[instance].have_vertical_accuracy) {
|
|
|
|
vacc = state[instance].vertical_accuracy;
|
2014-10-28 16:44:07 -03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool vertical_accuracy(float &vacc) const {
|
|
|
|
return vertical_accuracy(primary_instance, vacc);
|
|
|
|
}
|
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
// 3D velocity in NED format
|
|
|
|
const Vector3f &velocity(uint8_t instance) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
return state[instance].velocity;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
const Vector3f &velocity() const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return velocity(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
// ground speed in m/s
|
|
|
|
float ground_speed(uint8_t instance) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
return state[instance].ground_speed;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
float ground_speed() const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return ground_speed(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
// ground speed in cm/s
|
|
|
|
uint32_t ground_speed_cm(void) {
|
|
|
|
return ground_speed() * 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ground course in centidegrees
|
2016-05-04 22:28:35 -03:00
|
|
|
float ground_course(uint8_t instance) const {
|
|
|
|
return state[instance].ground_course;
|
|
|
|
}
|
|
|
|
float ground_course() const {
|
|
|
|
return ground_course(primary_instance);
|
|
|
|
}
|
2014-03-28 16:52:27 -03:00
|
|
|
int32_t ground_course_cd(uint8_t instance) const {
|
2016-05-04 22:28:35 -03:00
|
|
|
return ground_course(instance) * 100;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
int32_t ground_course_cd() const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return ground_course_cd(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
// number of locked satellites
|
|
|
|
uint8_t num_sats(uint8_t instance) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
return state[instance].num_sats;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
uint8_t num_sats() const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return num_sats(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
// GPS time of week in milliseconds
|
|
|
|
uint32_t time_week_ms(uint8_t instance) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
return state[instance].time_week_ms;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
uint32_t time_week_ms() const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return time_week_ms(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
// GPS week
|
|
|
|
uint16_t time_week(uint8_t instance) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
return state[instance].time_week;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
uint16_t time_week() const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return time_week(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
// horizontal dilution of precision
|
2014-04-01 17:49:29 -03:00
|
|
|
uint16_t get_hdop(uint8_t instance) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
return state[instance].hdop;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
2014-04-01 17:49:29 -03:00
|
|
|
uint16_t get_hdop() const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return get_hdop(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
2015-09-07 19:37:13 -03:00
|
|
|
// vertical dilution of precision
|
|
|
|
uint16_t get_vdop(uint8_t instance) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
return state[instance].vdop;
|
2015-09-07 19:37:13 -03:00
|
|
|
}
|
|
|
|
uint16_t get_vdop() const {
|
|
|
|
return get_vdop(primary_instance);
|
|
|
|
}
|
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
// the time we got our last fix in system milliseconds. This is
|
|
|
|
// used when calculating how far we might have moved since that fix
|
|
|
|
uint32_t last_fix_time_ms(uint8_t instance) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
return timing[instance].last_fix_time_ms;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
uint32_t last_fix_time_ms(void) const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return last_fix_time_ms(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
2015-11-03 09:17:25 -04:00
|
|
|
// the time we last processed a message in milliseconds. This is
|
|
|
|
// used to indicate that we have new GPS data to process
|
|
|
|
uint32_t last_message_time_ms(uint8_t instance) const {
|
|
|
|
return timing[instance].last_message_time_ms;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
uint32_t last_message_time_ms(void) const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return last_message_time_ms(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
2016-05-03 19:21:18 -03:00
|
|
|
// convert GPS week and millis to unix epoch in ms
|
|
|
|
static uint64_t time_epoch_convert(uint16_t gps_week, uint32_t gps_ms);
|
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
// return last fix time since the 1/1/1970 in microseconds
|
|
|
|
uint64_t time_epoch_usec(uint8_t instance);
|
|
|
|
uint64_t time_epoch_usec(void) {
|
2014-04-03 18:32:34 -03:00
|
|
|
return time_epoch_usec(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
// return true if the GPS supports vertical velocity values
|
|
|
|
bool have_vertical_velocity(uint8_t instance) const {
|
2015-11-03 09:17:25 -04:00
|
|
|
return state[instance].have_vertical_velocity;
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
bool have_vertical_velocity(void) const {
|
2014-04-03 18:32:34 -03:00
|
|
|
return have_vertical_velocity(primary_instance);
|
2014-03-28 16:52:27 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
// the expected lag (in seconds) in the position and velocity readings from the gps
|
|
|
|
float get_lag() const { return 0.2f; }
|
|
|
|
|
2016-10-07 19:04:14 -03:00
|
|
|
// return a 3D vector defining the offset of the GPS antenna in metres relative to the body frame origin
|
2016-10-27 01:05:58 -03:00
|
|
|
const Vector3f &get_antenna_offset(uint8_t instance) const {
|
2016-10-07 19:04:14 -03:00
|
|
|
return _antenna_offset[instance];
|
|
|
|
}
|
2016-10-27 01:05:58 -03:00
|
|
|
const Vector3f &get_antenna_offset(void) const {
|
2016-10-07 19:04:14 -03:00
|
|
|
return _antenna_offset[primary_instance];
|
|
|
|
}
|
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
// set position for HIL
|
2014-04-01 17:49:29 -03:00
|
|
|
void setHIL(uint8_t instance, GPS_Status status, uint64_t time_epoch_ms,
|
2014-08-09 09:47:54 -03:00
|
|
|
const Location &location, const Vector3f &velocity, uint8_t num_sats,
|
2016-05-04 22:28:35 -03:00
|
|
|
uint16_t hdop);
|
2014-03-28 16:52:27 -03:00
|
|
|
|
2016-05-04 05:16:05 -03:00
|
|
|
// set accuracy for HIL
|
2016-05-05 03:04:18 -03:00
|
|
|
void setHIL_Accuracy(uint8_t instance, float vdop, float hacc, float vacc, float sacc, bool _have_vertical_velocity, uint32_t sample_ms);
|
2016-05-04 05:16:05 -03:00
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
static const struct AP_Param::GroupInfo var_info[];
|
|
|
|
|
|
|
|
// dataflash for logging, if available
|
|
|
|
DataFlash_Class *_DataFlash;
|
|
|
|
|
|
|
|
// configuration parameters
|
|
|
|
AP_Int8 _type[GPS_MAX_INSTANCES];
|
|
|
|
AP_Int8 _navfilter;
|
2014-06-06 18:58:11 -03:00
|
|
|
AP_Int8 _auto_switch;
|
|
|
|
AP_Int8 _min_dgps;
|
2015-04-22 20:10:46 -03:00
|
|
|
AP_Int16 _sbp_logmask;
|
|
|
|
AP_Int8 _inject_to;
|
2015-05-21 18:07:59 -03:00
|
|
|
uint32_t _last_instance_swap_ms;
|
2014-09-04 01:27:05 -03:00
|
|
|
AP_Int8 _sbas_mode;
|
2014-09-04 01:43:29 -03:00
|
|
|
AP_Int8 _min_elevation;
|
2015-05-04 05:18:34 -03:00
|
|
|
AP_Int8 _raw_data;
|
2016-02-02 03:58:33 -04:00
|
|
|
AP_Int8 _gnss_mode[2];
|
2016-10-01 04:42:47 -03:00
|
|
|
AP_Int16 _rate_ms[2];
|
2015-10-28 21:40:50 -03:00
|
|
|
AP_Int8 _save_config;
|
2016-02-02 03:58:33 -04:00
|
|
|
AP_Int8 _auto_config;
|
2016-10-07 19:04:14 -03:00
|
|
|
AP_Vector3f _antenna_offset[2];
|
|
|
|
|
2014-03-31 06:48:22 -03:00
|
|
|
// handle sending of initialisation strings to the GPS
|
2015-10-26 08:25:44 -03:00
|
|
|
void send_blob_start(uint8_t instance, const char *_blob, uint16_t size);
|
2014-03-31 06:48:22 -03:00
|
|
|
void send_blob_update(uint8_t instance);
|
|
|
|
|
2014-04-04 17:33:34 -03:00
|
|
|
// lock out a GPS port, allowing another application to use the port
|
|
|
|
void lock_port(uint8_t instance, bool locked);
|
|
|
|
|
2015-04-22 20:10:46 -03:00
|
|
|
//Inject a packet of raw binary to a GPS
|
|
|
|
void inject_data(uint8_t *data, uint8_t len);
|
|
|
|
void inject_data(uint8_t instance, uint8_t *data, uint8_t len);
|
|
|
|
|
2014-06-06 18:58:11 -03:00
|
|
|
//MAVLink Status Sending
|
|
|
|
void send_mavlink_gps_raw(mavlink_channel_t chan);
|
|
|
|
void send_mavlink_gps2_raw(mavlink_channel_t chan);
|
|
|
|
|
|
|
|
void send_mavlink_gps_rtk(mavlink_channel_t chan);
|
|
|
|
void send_mavlink_gps2_rtk(mavlink_channel_t chan);
|
|
|
|
|
2016-02-02 03:58:33 -04:00
|
|
|
// Returns the index of the first unconfigured GPS (returns GPS_ALL_CONFIGURED if all instances report as being configured)
|
|
|
|
uint8_t first_unconfigured_gps(void) const;
|
2016-04-12 00:16:20 -03:00
|
|
|
void broadcast_first_configuration_failure_reason(void) const;
|
2016-02-02 03:58:33 -04:00
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
private:
|
|
|
|
struct GPS_timing {
|
|
|
|
// the time we got our last fix in system milliseconds
|
|
|
|
uint32_t last_fix_time_ms;
|
|
|
|
|
|
|
|
// the time we got our last fix in system milliseconds
|
|
|
|
uint32_t last_message_time_ms;
|
|
|
|
};
|
|
|
|
GPS_timing timing[GPS_MAX_INSTANCES];
|
|
|
|
GPS_State state[GPS_MAX_INSTANCES];
|
|
|
|
AP_GPS_Backend *drivers[GPS_MAX_INSTANCES];
|
2015-01-19 09:36:35 -04:00
|
|
|
AP_HAL::UARTDriver *_port[GPS_MAX_INSTANCES];
|
2014-03-28 16:52:27 -03:00
|
|
|
|
2014-04-03 18:32:34 -03:00
|
|
|
/// primary GPS instance
|
|
|
|
uint8_t primary_instance:2;
|
|
|
|
|
|
|
|
/// number of GPS instances present
|
|
|
|
uint8_t num_instances:2;
|
2014-03-28 16:52:27 -03:00
|
|
|
|
2014-04-04 17:33:34 -03:00
|
|
|
// which ports are locked
|
|
|
|
uint8_t locked_ports:2;
|
|
|
|
|
2014-03-28 16:52:27 -03:00
|
|
|
// state of auto-detection process, per instance
|
|
|
|
struct detect_state {
|
|
|
|
uint32_t detect_started_ms;
|
|
|
|
uint32_t last_baud_change_ms;
|
2016-09-24 03:16:40 -03:00
|
|
|
uint8_t current_baud;
|
2014-03-28 16:52:27 -03:00
|
|
|
struct UBLOX_detect_state ublox_detect_state;
|
|
|
|
struct MTK_detect_state mtk_detect_state;
|
|
|
|
struct MTK19_detect_state mtk19_detect_state;
|
|
|
|
struct SIRF_detect_state sirf_detect_state;
|
|
|
|
struct NMEA_detect_state nmea_detect_state;
|
2014-04-04 20:05:54 -03:00
|
|
|
struct SBP_detect_state sbp_detect_state;
|
2016-01-18 17:54:40 -04:00
|
|
|
struct ERB_detect_state erb_detect_state;
|
2014-03-28 16:52:27 -03:00
|
|
|
} detect_state[GPS_MAX_INSTANCES];
|
|
|
|
|
2014-03-31 06:48:22 -03:00
|
|
|
struct {
|
2015-10-26 08:25:44 -03:00
|
|
|
const char *blob;
|
2014-03-31 06:48:22 -03:00
|
|
|
uint16_t remaining;
|
|
|
|
} initblob_state[GPS_MAX_INSTANCES];
|
|
|
|
|
2014-04-04 20:05:54 -03:00
|
|
|
static const uint32_t _baudrates[];
|
2015-10-26 08:25:44 -03:00
|
|
|
static const char _initialisation_blob[];
|
|
|
|
static const char _initialisation_raw_blob[];
|
2014-03-28 16:52:27 -03:00
|
|
|
|
|
|
|
void detect_instance(uint8_t instance);
|
|
|
|
void update_instance(uint8_t instance);
|
2016-02-09 16:59:12 -04:00
|
|
|
void _broadcast_gps_type(const char *type, uint8_t instance, int8_t baud_index);
|
2016-10-04 04:37:01 -03:00
|
|
|
|
|
|
|
/*
|
|
|
|
buffer for re-assembling RTCM data for GPS injection.
|
|
|
|
The 8 bit flags field in GPS_RTCM_DATA is interpreted as:
|
|
|
|
1 bit for "is fragmented"
|
|
|
|
2 bits for fragment number
|
|
|
|
5 bits for sequence number
|
|
|
|
|
|
|
|
The rtcm_buffer is allocated on first use. Once a block of data
|
|
|
|
is successfully reassembled it is injected into all active GPS
|
|
|
|
backends. This assumes we don't want more than 4*180=720 bytes
|
|
|
|
in a RTCM data block
|
|
|
|
*/
|
|
|
|
struct rtcm_buffer {
|
|
|
|
uint8_t fragments_received:4;
|
|
|
|
uint8_t sequence:5;
|
|
|
|
uint8_t fragment_count;
|
|
|
|
uint16_t total_length;
|
|
|
|
uint8_t buffer[MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN*4];
|
|
|
|
} *rtcm_buffer;
|
|
|
|
|
|
|
|
// re-assemble GPS_RTCM_DATA message
|
|
|
|
void handle_gps_rtcm_data(const mavlink_message_t *msg);
|
|
|
|
|
|
|
|
// ibject data into all backends
|
|
|
|
void inject_data_all(const uint8_t *data, uint16_t len);
|
2014-03-28 16:52:27 -03:00
|
|
|
};
|
|
|
|
|
2015-07-14 04:07:29 -03:00
|
|
|
#define GPS_BAUD_TIME_MS 1200
|