10 #if CONFIG_HAL_BOARD == HAL_BOARD_SITL 28 #include <sys/types.h> 31 #pragma GCC diagnostic ignored "-Wunused-result" 54 while (ioctl(fd, FIONREAD, &num_ready) == 0 && num_ready > 3000) {
57 if (
read(fd, tmp,
sizeof(tmp)) !=
sizeof(tmp)) {
62 return read(fd, buf, count);
108 float r = ((((unsigned)random()) % 1000000)) / 1.0e4;
109 if (r < _sitl->gps_byteloss) {
119 if (gps2_state.
gps_fd != 0) {
133 static uint64_t first_usec;
134 static struct timeval first_tv;
135 if (first_usec == 0) {
137 gettimeofday(&first_tv,
nullptr);
140 tv->tv_sec += now / 1000000ULL;
141 uint64_t new_usec = tv->tv_usec + (now % 1000000ULL);
142 tv->tv_sec += new_usec / 1000000ULL;
143 tv->tv_usec = new_usec % 1000000ULL;
151 const uint8_t PREAMBLE1 = 0xb5;
152 const uint8_t PREAMBLE2 = 0x62;
153 const uint8_t CLASS_NAV = 0x1;
154 uint8_t hdr[6], chk[2];
159 hdr[4] = size & 0xFF;
161 chk[0] = chk[1] = hdr[2];
162 chk[1] += (chk[0] += hdr[3]);
163 chk[1] += (chk[0] += hdr[4]);
164 chk[1] += (chk[0] += hdr[5]);
165 for (uint8_t i=0; i<size; i++) {
166 chk[1] += (chk[0] += buf[i]);
168 _gps_write(hdr,
sizeof(hdr), instance);
169 _gps_write(buf, size, instance);
170 _gps_write(chk,
sizeof(chk), instance);
176 static void gps_time(uint16_t *time_week, uint32_t *time_week_ms)
181 uint32_t epoch_seconds = tv.tv_sec - epoch;
183 uint32_t t_ms = tv.tv_usec / 1000;
193 struct PACKED ubx_nav_posllh {
197 int32_t altitude_ellipsoid;
198 int32_t altitude_msl;
199 uint32_t horizontal_accuracy;
200 uint32_t vertical_accuracy;
202 struct PACKED ubx_nav_status {
206 uint8_t differential_status;
208 uint32_t time_to_first_fix;
211 struct PACKED ubx_nav_velned {
219 uint32_t speed_accuracy;
220 uint32_t heading_accuracy;
222 struct PACKED ubx_nav_solution {
231 uint32_t position_accuracy_3d;
232 int32_t ecef_x_velocity;
233 int32_t ecef_y_velocity;
234 int32_t ecef_z_velocity;
235 uint32_t speed_accuracy;
236 uint16_t position_DOP;
241 struct PACKED ubx_nav_dop {
251 struct PACKED ubx_nav_pvt {
254 uint8_t month, day, hour, min, sec;
263 int32_t height, h_msl;
264 uint32_t h_acc, v_acc;
265 int32_t velN, velE, velD, gspeed;
270 uint8_t reserved1[6];
272 uint8_t reserved2[4];
274 const uint8_t SV_COUNT = 10;
275 struct PACKED ubx_nav_svinfo {
279 uint8_t reserved1[2];
292 const uint8_t MSG_POSLLH = 0x2;
293 const uint8_t MSG_STATUS = 0x3;
294 const uint8_t MSG_DOP = 0x4;
295 const uint8_t MSG_VELNED = 0x12;
296 const uint8_t MSG_SOL = 0x6;
297 const uint8_t MSG_PVT = 0x7;
298 const uint8_t MSG_SVINFO = 0x30;
300 static uint32_t _next_nav_sv_info_time = 0;
303 uint32_t time_week_ms;
305 gps_time(&time_week, &time_week_ms);
307 pos.time = time_week_ms;
310 pos.altitude_ellipsoid = d->
altitude * 1000.0f;
311 pos.altitude_msl = d->
altitude * 1000.0f;
312 pos.horizontal_accuracy = 1500;
313 pos.vertical_accuracy = 2000;
315 status.time = time_week_ms;
318 status.differential_status = 0;
320 status.time_to_first_fix = 0;
323 velned.time = time_week_ms;
324 velned.ned_north = 100.0f * d->
speedN;
325 velned.ned_east = 100.0f * d->
speedE;
326 velned.ned_down = 100.0f * d->
speedD;
330 if (velned.heading_2d < 0.0f) {
331 velned.heading_2d += 360.0f * 100000.0f;
333 velned.speed_accuracy = 40;
334 velned.heading_accuracy = 4;
336 memset(&sol, 0,
sizeof(sol));
338 sol.fix_status = 221;
340 sol.time = time_week_ms;
341 sol.week = time_week;
343 dop.time = time_week_ms;
352 pvt.itow = time_week_ms;
363 pvt.flags = 0b10000011;
372 pvt.velN = 1000.0f * d->
speedN;
373 pvt.velE = 1000.0f * d->
speedE;
374 pvt.velD = 1000.0f * d->
speedD;
378 pvt.head_acc = 38 * 1.0e5;
380 memset(pvt.reserved1,
'\0',
ARRAY_SIZE(pvt.reserved1));
382 memset(pvt.reserved2,
'\0',
ARRAY_SIZE(pvt.reserved2));
384 _gps_send_ubx(MSG_POSLLH, (uint8_t*)&pos,
sizeof(pos), instance);
385 _gps_send_ubx(MSG_STATUS, (uint8_t*)&status,
sizeof(status), instance);
386 _gps_send_ubx(MSG_VELNED, (uint8_t*)&velned,
sizeof(velned), instance);
387 _gps_send_ubx(MSG_SOL, (uint8_t*)&sol,
sizeof(sol), instance);
388 _gps_send_ubx(MSG_DOP, (uint8_t*)&dop,
sizeof(dop), instance);
389 _gps_send_ubx(MSG_PVT, (uint8_t*)&pvt,
sizeof(pvt), instance);
391 if (time_week_ms > _next_nav_sv_info_time) {
392 svinfo.itow = time_week_ms;
394 svinfo.globalFlags = 4;
397 for (uint8_t i = 0; i < SV_COUNT; i++) {
398 svinfo.sv[i].chn = i;
399 svinfo.sv[i].svid = i;
401 svinfo.sv[i].quality = 7;
402 svinfo.sv[i].cno =
MAX(20, 30 - i);
403 svinfo.sv[i].elev =
MAX(30, 90 - i);
404 svinfo.sv[i].azim = i;
407 _gps_send_ubx(MSG_SVINFO, (uint8_t*)&svinfo,
sizeof(svinfo), instance);
408 _next_nav_sv_info_time = time_week_ms + 10000;
423 static void mtk_checksum(
const uint8_t *data, uint8_t n, uint8_t *ck_a, uint8_t *ck_b)
446 int32_t ground_speed;
447 int32_t ground_course;
464 if (p.ground_course < 0.0f) {
465 p.ground_course += 360.0f * 1000000.0f;
478 tm = *gmtime(&tv.tv_sec);
479 uint32_t hsec = (tv.tv_usec / (10000*20)) * 20;
481 p.utc_time = hsec + tm.tm_sec*100 + tm.tm_min*100*100 + tm.tm_hour*100*100*100;
485 mtk_checksum(&p.msg_class,
sizeof(p)-4, &p.ck_a, &p.ck_b);
487 _gps_write((uint8_t*)&p,
sizeof(p), instance);
502 int32_t ground_speed;
503 int32_t ground_course;
515 p.size =
sizeof(p) - 5;
521 if (p.ground_course < 0.0f) {
522 p.ground_course += 360.0f * 100.0f;
535 tm = *gmtime(&tv.tv_sec);
536 uint32_t millisec = (tv.tv_usec / (1000*200)) * 200;
538 p.utc_date = (tm.tm_year-100) + ((tm.tm_mon+1)*100) + (tm.tm_mday*100*100);
539 p.utc_time = millisec + tm.tm_sec*1000 + tm.tm_min*1000*100 + tm.tm_hour*1000*100*100;
545 _gps_write((uint8_t*)&p,
sizeof(p), instance);
560 int32_t ground_speed;
561 int32_t ground_course;
573 p.size =
sizeof(p) - 5;
579 if (p.ground_course < 0.0f) {
580 p.ground_course += 360.0f * 100.0f;
593 tm = *gmtime(&tv.tv_sec);
594 uint32_t millisec = (tv.tv_usec / (1000*200)) * 200;
596 p.utc_date = (tm.tm_year-100) + ((tm.tm_mon+1)*100) + (tm.tm_mday*100*100);
597 p.utc_time = millisec + tm.tm_sec*1000 + tm.tm_min*1000*100 + tm.tm_hour*1000*100*100;
603 _gps_write((uint8_t*)&p,
sizeof(p), instance);
612 const uint8_t *b = (
const uint8_t *)s;
613 for (uint16_t i=1; s[i]; i++) {
633 csum = _gps_nmea_checksum(s);
634 snprintf(trailer,
sizeof(trailer),
"*%02X\r\n", (
unsigned)csum);
635 _gps_write((
const uint8_t*)s, strlen(s), instance);
636 _gps_write((
const uint8_t*)trailer, 5, instance);
655 tm = gmtime(&tv.tv_sec);
658 snprintf(tstring,
sizeof(tstring),
"%02u%02u%06.3f", tm->tm_hour, tm->tm_min, tm->tm_sec + tv.tv_usec*1.0e-6);
661 snprintf(dstring,
sizeof(dstring),
"%02u%02u%02u", tm->tm_mday, tm->tm_mon+1, tm->tm_year % 100);
665 snprintf(lat_string,
sizeof(lat_string),
"%02u%08.5f,%c",
672 snprintf(lng_string,
sizeof(lng_string),
"%03u%08.5f,%c",
677 _gps_nmea_printf(instance,
"$GPGGA,%s,%s,%s,%01d,%02d,%04.1f,%07.2f,M,0.0,M,,",
690 _gps_nmea_printf(instance,
"$GPRMC,%s,%c,%s,%s,%.2f,%.2f,%s,,",
702 if (len != 0 && payload == 0) {
706 uint8_t preamble = 0x55;
707 _gps_write(&preamble, 1, instance);
708 _gps_write((uint8_t*)&msg_type, 2, instance);
709 _gps_write((uint8_t*)&sender_id, 2, instance);
710 _gps_write(&len, 1, instance);
712 _gps_write((uint8_t*)payload, len, instance);
720 _gps_write((uint8_t*)&crc, 2, instance);
725 struct sbp_heartbeat_t {
730 uint8_t protocol_minor : 8;
731 uint8_t protocol_major : 8;
733 bool ext_antenna : 1;
736 struct PACKED sbp_gps_time_t {
742 struct PACKED sbp_pos_llh_t {
752 struct PACKED sbp_vel_ned_t {
762 struct PACKED sbp_dops_t {
772 static const uint16_t SBP_HEARTBEAT_MSGTYPE = 0xFFFF;
773 static const uint16_t SBP_GPS_TIME_MSGTYPE = 0x0100;
774 static const uint16_t SBP_DOPS_MSGTYPE = 0x0206;
775 static const uint16_t SBP_POS_LLH_MSGTYPE = 0x0201;
776 static const uint16_t SBP_VEL_NED_MSGTYPE = 0x0205;
778 uint32_t time_week_ms;
780 gps_time(&time_week, &time_week_ms);
783 t.tow = time_week_ms;
786 _sbp_send_message(SBP_GPS_TIME_MSGTYPE, 0x2222,
sizeof(t), (uint8_t*)&t, instance);
792 pos.tow = time_week_ms;
796 pos.h_accuracy = 5e3;
797 pos.v_accuracy = 10e3;
802 _sbp_send_message(SBP_POS_LLH_MSGTYPE, 0x2222,
sizeof(pos), (uint8_t*)&pos, instance);
805 _sbp_send_message(SBP_POS_LLH_MSGTYPE, 0x2222,
sizeof(pos), (uint8_t*)&pos, instance);
807 velned.tow = time_week_ms;
808 velned.n = 1e3 * d->
speedN;
809 velned.e = 1e3 * d->
speedE;
810 velned.d = 1e3 * d->
speedD;
811 velned.h_accuracy = 5e3;
812 velned.v_accuracy = 5e3;
815 _sbp_send_message(SBP_VEL_NED_MSGTYPE, 0x2222,
sizeof(velned), (uint8_t*)&velned, instance);
817 static uint32_t do_every_count = 0;
818 if (do_every_count % 5 == 0) {
820 dops.tow = time_week_ms;
827 _sbp_send_message(SBP_DOPS_MSGTYPE, 0x2222,
sizeof(dops),
828 (uint8_t*)&dops, instance);
830 hb.protocol_major = 0;
831 _sbp_send_message(SBP_HEARTBEAT_MSGTYPE, 0x2222,
sizeof(hb),
832 (uint8_t*)&hb, instance);
841 struct sbp_heartbeat_t {
846 uint8_t protocol_minor : 8;
847 uint8_t protocol_major : 8;
849 bool ext_antenna : 1;
852 struct PACKED sbp_gps_time_t {
858 struct PACKED sbp_pos_llh_t {
868 struct PACKED sbp_vel_ned_t {
878 struct PACKED sbp_dops_t {
888 static const uint16_t SBP_HEARTBEAT_MSGTYPE = 0xFFFF;
889 static const uint16_t SBP_GPS_TIME_MSGTYPE = 0x0102;
890 static const uint16_t SBP_DOPS_MSGTYPE = 0x0208;
891 static const uint16_t SBP_POS_LLH_MSGTYPE = 0x020A;
892 static const uint16_t SBP_VEL_NED_MSGTYPE = 0x020E;
895 uint32_t time_week_ms;
897 gps_time(&time_week, &time_week_ms);
900 t.tow = time_week_ms;
903 _sbp_send_message(SBP_GPS_TIME_MSGTYPE, 0x2222,
sizeof(t), (uint8_t*)&t, instance);
909 pos.tow = time_week_ms;
913 pos.h_accuracy = 5e3;
914 pos.v_accuracy = 10e3;
919 _sbp_send_message(SBP_POS_LLH_MSGTYPE, 0x2222,
sizeof(pos), (uint8_t*)&pos, instance);
922 _sbp_send_message(SBP_POS_LLH_MSGTYPE, 0x2222,
sizeof(pos), (uint8_t*)&pos, instance);
924 velned.tow = time_week_ms;
925 velned.n = 1e3 * d->
speedN;
926 velned.e = 1e3 * d->
speedE;
927 velned.d = 1e3 * d->
speedD;
928 velned.h_accuracy = 5e3;
929 velned.v_accuracy = 5e3;
932 _sbp_send_message(SBP_VEL_NED_MSGTYPE, 0x2222,
sizeof(velned), (uint8_t*)&velned, instance);
934 static uint32_t do_every_count = 0;
935 if (do_every_count % 5 == 0) {
937 dops.tow = time_week_ms;
944 _sbp_send_message(SBP_DOPS_MSGTYPE, 0x2222,
sizeof(dops),
945 (uint8_t*)&dops, instance);
947 hb.protocol_major = 2;
948 _sbp_send_message(SBP_HEARTBEAT_MSGTYPE, 0x2222,
sizeof(hb),
949 (uint8_t*)&hb, instance);
956 static struct PACKED nova_header
961 uint8_t headerlength;
969 uint16_t messagelength;
1019 uint8_t svsmultfreq;
1022 uint8_t galbeisigmask;
1023 uint8_t gpsglosigmask;
1040 uint32_t time_week_ms;
1042 gps_time(&time_week, &time_week_ms);
1044 header.preamble[0] = 0xaa;
1045 header.preamble[1] = 0x44;
1046 header.preamble[2] = 0x12;
1047 header.headerlength =
sizeof(header);
1048 header.week = time_week;
1049 header.tow = time_week_ms;
1051 header.messageid = 174;
1052 header.messagelength =
sizeof(psrdop);
1053 header.sequence += 1;
1056 psrdop.htdop = 1.20;
1057 _nova_send_message((uint8_t*)&header,
sizeof(header),(uint8_t*)&psrdop,
sizeof(psrdop), instance);
1060 header.messageid = 99;
1061 header.messagelength =
sizeof(bestvel);
1062 header.sequence += 1;
1066 bestvel.vertspd = -d->
speedD;
1068 _nova_send_message((uint8_t*)&header,
sizeof(header),(uint8_t*)&bestvel,
sizeof(bestvel), instance);
1071 header.messageid = 42;
1072 header.messagelength =
sizeof(bestpos);
1073 header.sequence += 1;
1079 bestpos.latsdev=0.2;
1080 bestpos.lngsdev=0.2;
1081 bestpos.hgtsdev=0.2;
1085 _nova_send_message((uint8_t*)&header,
sizeof(header),(uint8_t*)&bestpos,
sizeof(bestpos), instance);
1090 _gps_write(header, headerlength, instance);
1091 _gps_write(payload, payloadlen, instance);
1093 uint32_t crc = CalculateBlockCRC32(headerlength, header, (uint32_t)0);
1094 crc = CalculateBlockCRC32(payloadlen, payload, crc);
1096 _gps_write((uint8_t*)&crc, 4, instance);
1099 #define CRC32_POLYNOMIAL 0xEDB88320L 1103 uint32_t crc = icrc;
1104 for ( i = 8 ; i > 0; i-- )
1116 while ( length-- != 0 )
1118 crc = ((crc >> 8) & 0x00FFFFFFL) ^ (CRC32Value(((uint32_t) crc ^ *buffer++) & 0xff));
1129 static int fd2 = -1;
1131 if (instance == 0) {
1133 fd =
open(
"/tmp/gps.dat", O_RDONLY|O_CLOEXEC);
1138 fd2 =
open(
"/tmp/gps2.dat", O_RDONLY|O_CLOEXEC);
1143 if (temp_fd == -1) {
1147 ssize_t ret =
::read(temp_fd, buf,
sizeof(buf));
1149 ::printf(
"wrote gps %u bytes\n", (
unsigned)ret);
1150 _gps_write((
const uint8_t *)buf, ret, instance);
1154 lseek(temp_fd, 0, SEEK_SET);
1162 double speedN,
double speedE,
double speedD,
bool have_lock)
1175 if (!_gps_has_basestation_position) {
1177 _gps_basestation_data.latitude = latitude;
1178 _gps_basestation_data.longitude = longitude;
1179 _gps_basestation_data.altitude = altitude;
1180 _gps_basestation_data.speedN = speedN;
1181 _gps_basestation_data.speedE = speedE;
1182 _gps_basestation_data.speedD = speedD;
1183 _gps_basestation_data.have_lock = have_lock;
1184 _gps_has_basestation_position =
true;
1197 if (gps2_state.
gps_fd != 0) {
1218 if (!posRelOffsetBF.
is_zero()) {
1224 Vector3f posRelOffsetEF = rotmat * posRelOffsetBF;
1227 double const earth_rad_inv = 1.569612305760477e-7;
1238 Vector3f velRelOffsetBF = gyro % posRelOffsetBF;
1241 Vector3f velRelOffsetEF = rotmat * velRelOffsetBF;
1289 if (gps2_state.
gps_fd != 0) {
1301 _update_gps_ubx(data, instance);
1305 _update_gps_mtk(data, instance);
1309 _update_gps_mtk16(data, instance);
1313 _update_gps_mtk19(data, instance);
1317 _update_gps_nmea(data, instance);
1321 _update_gps_sbp(data, instance);
1325 _update_gps_sbp2(data, instance);
1329 _update_gps_nova(data, instance);
1333 _update_gps_file(instance);
float norm(const T first, const U second, const Params... parameters)
int printf(const char *fmt,...)
#define GPS_LEAPSECONDS_MILLIS
static void swap_uint32(uint32_t *v, uint8_t n)
int vasprintf(char **strp, const char *fmt, va_list ap)
ssize_t gps_read(int fd, void *buf, size_t count)
uint16_t _gps_nmea_checksum(const char *s)
uint32_t CalculateBlockCRC32(uint32_t length, uint8_t *buffer, uint32_t crc)
static void mtk_checksum(const uint8_t *data, uint8_t n, uint8_t *ck_a, uint8_t *ck_b)
int open(const char *pathname, int flags)
POSIX Open a file with integer mode flags.
void _update_gps_file(uint8_t instance)
static uint8_t buffer[SRXL_FRAMELEN_MAX]
ssize_t write(int fd, const void *buf, size_t count)
POSIX Write count bytes from *buf to fileno fd.
void _update_gps_nmea(const struct gps_data *d, uint8_t instance)
void _update_gps_nova(const struct gps_data *d, uint8_t instance)
void _gps_send_ubx(uint8_t msgid, uint8_t *buf, uint16_t size, uint8_t instance)
static void gps_time(uint16_t *time_week, uint32_t *time_week_ms)
void _update_gps_mtk16(const struct gps_data *d, uint8_t instance)
void _update_gps_sbp(const struct gps_data *d, uint8_t instance)
static void simulation_timeval(struct timeval *tv)
static void _set_nonblocking(int)
static uint8_t next_gps_index
static auto MAX(const A &one, const B &two) -> decltype(one > two ? one :two)
void _gps_nmea_printf(uint8_t instance, const char *fmt,...)
static struct gps_state gps2_state
ssize_t read(int fd, void *buf, size_t count)
POSIX read count bytes from *buf to fileno fd.
void _update_gps_ubx(const struct gps_data *d, uint8_t instance)
void _update_gps(double latitude, double longitude, float altitude, double speedN, double speedE, double speedD, bool have_lock)
AP_Vector3f gps_pos_offset
void _sbp_send_message(uint16_t msg_type, uint16_t sender_id, uint8_t len, uint8_t *payload, uint8_t instance)
void rotation_matrix(Matrix3f &m) const
off_t lseek(int fileno, off_t position, int whence)
POSIX seek to file position.
void _update_gps_mtk(const struct gps_data *d, uint8_t instance)
void _gps_write(const uint8_t *p, uint16_t size, uint8_t instance)
void _update_gps_mtk19(const struct gps_data *d, uint8_t instance)
uint32_t CRC32Value(uint32_t icrc)
void _nova_send_message(uint8_t *header, uint8_t headerlength, uint8_t *payload, uint8_t payloadlen, uint8_t instance)
static constexpr float radians(float deg)
int snprintf(char *str, size_t size, const char *fmt,...)
static struct gps_state gps_state
void _update_gps_sbp2(const struct gps_data *d, uint8_t instance)
const AP_HAL::HAL & hal
-*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
void _update_gps_instance(SITL::SITL::GPSType gps_type, const struct gps_data *d, uint8_t instance)
uint16_t crc16_ccitt(const uint8_t *buf, uint32_t len, uint16_t crc)