5 #include <simgear/constants.h>
6 #include <simgear/math/sg_geodesy.hxx>
7 #include <simgear/misc/sgstream.hxx>
8 #include <simgear/misc/strutils.hxx>
10 #include "MIDG-II.hxx"
16 MIDGTrack::MIDGTrack() {};
17 MIDGTrack::~MIDGTrack() {};
22 static uint32_t read_swab( char *buf, size_t offset, size_t size ) {
25 char *ptr = buf + offset;
27 // MIDG data is big endian so swap if needed.
28 if ( ulIsLittleEndian ) {
30 ulEndianSwap( (uint32_t *)ptr );
31 } else if ( size == 2 ) {
32 ulEndianSwap( (uint16_t *)ptr );
37 result = *(uint32_t *)ptr;
38 } else if ( size == 2 ) {
39 result = *(uint16_t *)ptr;
40 } else if ( size == 1 ) {
41 result = *(uint8_t *)ptr;
43 cout << "unknown size in read_swab()" << endl;
50 static bool validate_cksum( uint8_t id, uint8_t size, char *buf,
51 uint8_t cksum0, uint8_t cksum1 )
62 for ( uint8_t i = 0; i < size; i++ ) {
63 c0 += (uint8_t)buf[i];
67 // cout << "c0 = " << (unsigned int)c0 << " (" << (unsigned int)cksum0
68 // << ") c1 = " << (unsigned int)c1 << " (" << (unsigned int)cksum1
71 if ( c0 == cksum0 && c1 == cksum1 ) {
79 void MIDGTrack::parse_msg( const int id, char *buf, MIDGpos *pos, MIDGatt *att )
86 // cout << "message 1 =" << endl;
89 ts = (uint32_t)read_swab( buf, 0, 4 );
90 // cout << " time stamp = " << ts << endl;
93 status = (uint16_t)read_swab( buf, 4, 2 );
94 // cout << " status = " << status << endl;
97 temp = (int16_t)read_swab( buf, 6, 2 );
98 // cout << " temp = " << temp << endl;
100 } else if ( id == 2 ) {
107 // cout << "message 2 =" << endl;
110 ts = (uint32_t)read_swab( buf, 0, 4 );
111 // cout << " time stamp = " << ts << endl;
114 p = (int16_t)read_swab( buf, 4, 2 );
115 q = (int16_t)read_swab( buf, 6, 2 );
116 r = (int16_t)read_swab( buf, 8, 2 );
117 // cout << " pqr = " << p << "," << q << "," << r << endl;
120 ax = (int16_t)read_swab( buf, 10, 2 );
121 ay = (int16_t)read_swab( buf, 12, 2 );
122 az = (int16_t)read_swab( buf, 14, 2 );
123 // cout << " ax ay az = " << ax << "," << ay << "," << az << endl;
126 mx = (int16_t)read_swab( buf, 16, 2 );
127 my = (int16_t)read_swab( buf, 18, 2 );
128 mz = (int16_t)read_swab( buf, 20, 2 );
129 // cout << " mx my mz = " << mx << "," << my << "," << mz << endl;
132 flags = (uint8_t)read_swab( buf, 22, 1 );
133 // cout << " GPS 1PPS flag = " << (int)(flags & (1 << 6))
134 // << " Timestamp is gps = " << (int)(flags & (1 << 7)) << endl;
136 } else if ( id == 3 ) {
141 // cout << "message 3 =" << endl;
144 ts = (uint32_t)read_swab( buf, 0, 4 );
145 // cout << " time stamp = " << ts << endl;
148 mx = (int16_t)read_swab( buf, 4, 2 );
149 my = (int16_t)read_swab( buf, 6, 2 );
150 mz = (int16_t)read_swab( buf, 8, 2 );
151 // cout << " mx my mz = " << mx << "," << my << "," << mz << endl;
154 flags = (uint8_t)read_swab( buf, 10, 1 );
155 // cout << " GPS 1PPS flag = " << (int)(flags & (1 << 6)) << endl;
157 } else if ( id == 10 ) {
161 int16_t yaw, pitch, roll;
162 int32_t Qw, Qx, Qy, Qz;
165 // cout << "message 10 =" << endl;
168 ts = (uint32_t)read_swab( buf, 0, 4 );
169 // cout << " time stamp = " << ts << endl;
170 if ( ts > att->get_msec() && att->get_msec() > 1.0 ) {
171 attdata.push_back( *att );
173 if ( ts < att->get_msec() ) {
174 cout << "OOOPS moving back in time!!! " << ts << " < " << att->get_msec() << endl;
176 att->midg_time = MIDGTime( ts );
180 p = (int16_t)read_swab( buf, 4, 2 );
181 q = (int16_t)read_swab( buf, 6, 2 );
182 r = (int16_t)read_swab( buf, 8, 2 );
183 // cout << " pqr = " << p << "," << q << "," << r << endl;
186 ax = (int16_t)read_swab( buf, 10, 2 );
187 ay = (int16_t)read_swab( buf, 12, 2 );
188 az = (int16_t)read_swab( buf, 14, 2 );
189 // cout << " ax ay az = " << ax << "," << ay << "," << az << endl;
192 yaw = (int16_t)read_swab( buf, 16, 2 );
193 pitch = (int16_t)read_swab( buf, 18, 2 );
194 roll = (int16_t)read_swab( buf, 20, 2 );
195 // cout << " yaw, pitch, roll = " << yaw << "," << pitch << ","
197 att->yaw_rad = ( (double)yaw / 100.0 ) * SG_PI / 180.0;
198 att->pitch_rad = ( (double)pitch / 100.0 ) * SG_PI / 180.0;
199 att->roll_rad = ( (double)roll / 100.0 ) * SG_PI / 180.0;
202 Qw = (int32_t)read_swab( buf, 22, 4 );
203 Qx = (int32_t)read_swab( buf, 26, 4 );
204 Qy = (int32_t)read_swab( buf, 30, 4 );
205 Qz = (int32_t)read_swab( buf, 34, 4 );
206 // cout << " Qw,Qx,Qy,Qz = " << Qw << "," << Qx << "," << Qy << ","
210 flags = (uint8_t)read_swab( buf, 38, 1 );
211 // cout << " External hdg measurement applied = "
212 // << (int)(flags & (1 << 3)) << endl
213 // << " Magnatometer measurement applied = "
214 // << (int)(flags & (1 << 4)) << endl
215 // << " DGPS = " << (int)(flags & (1 << 5)) << endl
216 // << " Timestamp is gps = " << (int)(flags & (1 << 6)) << endl
217 // << " INS mode = " << (int)(flags & (1 << 7))
220 } else if ( id == 12 ) {
222 int32_t posx, posy, posz;
223 int32_t velx, vely, velz;
226 // cout << "message 12 =" << endl;
229 ts = (uint32_t)read_swab( buf, 0, 4 );
230 // cout << " time stamp = " << ts << endl;
231 if ( ts > pos->get_msec() && pos->get_msec() > 1.0 ) {
232 posdata.push_back( *pos );
234 if ( ts < pos->get_msec() ) {
235 cout << "OOOPS moving back in time!!! " << ts << " < " << pos->get_msec() << endl;
237 pos->midg_time = MIDGTime( ts );
241 posx = (int32_t)read_swab( buf, 4, 4 );
242 posy = (int32_t)read_swab( buf, 8, 4 );
243 posz = (int32_t)read_swab( buf, 12, 4 );
244 // cout << " pos = " << posx << "," << posy << "," << posz << endl;
247 xyz[0] = posx/100; xyz[1] = posy/100; xyz[2] = posz/100;
248 double lat, lon, alt;
249 sgCartToGeod(xyz, &lat, &lon, &alt);
250 pos->lat_deg = lat * 180.0 / SG_PI;
251 pos->lon_deg = lon * 180.0 / SG_PI;
252 pos->altitude_msl = alt;
253 // cout << " lon = " << pos->lon_deg << " lat = " << pos->lat_deg
254 // << " alt = " << pos->altitude_msl << endl;
257 velx = (int32_t)read_swab( buf, 16, 4 );
258 vely = (int32_t)read_swab( buf, 20, 4 );
259 velz = (int32_t)read_swab( buf, 24, 4 );
260 // cout << " vel = " << velx << "," << vely << "," << velz << endl;
261 double vel_cms = sqrt( velx*velx + vely*vely + velz*velz );
262 double vel_ms = vel_cms / 100.0;
263 pos->speed_kts = vel_ms * SG_METER_TO_NM * 3600;
266 flags = (uint8_t)read_swab( buf, 28, 1 );
267 // cout << " ENU pos rel to 1st fix = " << (int)(flags & (1 << 0)) << endl
268 // << " Velocity format = " << (int)(flags & (1 << 1)) << endl
269 // << " bit 2 = " << (int)(flags & (1 << 2)) << endl
270 // << " bit 3 = " << (int)(flags & (1 << 3)) << endl
271 // << " GPS pos/vel valid = " << (int)(flags & (1 << 4)) << endl
272 // << " DGPS = " << (int)(flags & (1 << 5)) << endl
273 // << " Timestamp is gps = " << (int)(flags & (1 << 6)) << endl
274 // << " Solution src (0=gps, 1=ins) = " << (int)(flags & (1 << 7))
277 } else if ( id == 20 ) {
278 uint32_t gps_ts, gps_week;
280 int32_t gps_posx, gps_posy, gps_posz;
281 int32_t gps_velx, gps_vely, gps_velz;
282 int16_t pdop, pacc, sacc;
284 // cout << "message 20 =" << endl;
286 // timestamp -- often slightly off from midg time stamp so
287 // let's not use gps ts to determine if we need to push the
288 // previous data or not, just roll it into the current data
289 // independent of time stamp.
290 gps_ts = (uint32_t)read_swab( buf, 0, 4 );
291 // if ( ts > pt->get_msec() && pt->get_msec() > 1.0 ) {
292 // data.push_back( *pt );
294 // if ( ts < pt->get_msec() ) {
295 // cout << "OOOPS moving back in time!!! " << ts << " < " << pt->get_msec() << endl;
297 // pt->midg_time = MIDGTime( ts );
300 gps_week = (uint16_t)read_swab( buf, 4, 2 );
301 // cout << " gps time stamp = " << gps_ts << " week = " << gps_week
305 details = (uint16_t)read_swab( buf, 6, 2 );
306 // cout << " details = " << details << endl;
308 // gps_posx, gps_posy, gps_posz
309 gps_posx = (int32_t)read_swab( buf, 8, 4 );
310 gps_posy = (int32_t)read_swab( buf, 12, 4 );
311 gps_posz = (int32_t)read_swab( buf, 16, 4 );
312 // cout << " gps_pos = " << gps_posx << "," << gps_posy << ","
313 // << gps_posz << endl;
315 // gps_velx, gps_vely, gps_velz
316 gps_velx = (int32_t)read_swab( buf, 20, 4 );
317 gps_vely = (int32_t)read_swab( buf, 24, 4 );
318 gps_velz = (int32_t)read_swab( buf, 28, 4 );
319 // cout << " gps_vel = " << gps_velx << "," << gps_vely << ","
320 // << gps_velz << endl;
323 pdop = (uint16_t)read_swab( buf, 32, 2 );
324 // cout << " pdop = " << pdop << endl;
327 pacc = (uint16_t)read_swab( buf, 34, 2 );
328 // cout << " pacc = " << pacc << endl;
331 sacc = (uint16_t)read_swab( buf, 36, 2 );
332 // cout << " sacc = " << sacc << endl;
335 cout << "unknown id = " << id << endl;
340 // load the specified file, return the number of records loaded
341 int MIDGTrack::load( const string &file ) {
348 fd = fopen( file.c_str(), "r" );
351 cout << "Cannot open file: " << file << endl;
355 vector <string> tokens;
359 while ( ! feof( fd ) ) {
360 // scan for sync characters
364 while ( (sync0 != 129 || sync1 != 161) && !feof(fd) ) {
369 // cout << "start of message ..." << endl;
371 // read message id and size
372 int id = fgetc( fd );
373 int size = fgetc( fd );
374 // cout << "message = " << id << " size = " << size << endl;
378 fread( buf, size, 1, fd );
381 int cksum0 = fgetc( fd );
382 int cksum1 = fgetc( fd );
384 if ( validate_cksum( id, size, buf, cksum0, cksum1 ) ) {
385 parse_msg( id, buf, &pos, &att );
387 cout << "Check sum failure!" << endl;
395 static double interp( double a, double b, double p, bool rotational = false ) {
398 // special handling of rotational data
399 if ( diff > SGD_PI ) {
401 } else if ( diff < -SGD_PI ) {
409 MIDGpos MIDGInterpPos( const MIDGpos A, const MIDGpos B, const double percent )
412 p.midg_time = MIDGTime((uint32_t)interp(A.midg_time.get_msec(),
413 B.midg_time.get_msec(),
415 p.lat_deg = interp(A.lat_deg, B.lat_deg, percent);
416 p.lon_deg = interp(A.lon_deg, B.lon_deg, percent);
417 p.altitude_msl = interp(A.altitude_msl, B.altitude_msl, percent);
418 p.fix_quality = (int)interp(A.fix_quality, B.fix_quality, percent);
419 p.num_satellites = (int)interp(A.num_satellites, B.num_satellites, percent);
420 p.hdop = interp(A.hdop, B.hdop, percent);
421 p.speed_kts = interp(A.speed_kts, B.speed_kts, percent);
422 p.course_true = interp(A.course_true, B.course_true, percent, true);
427 MIDGatt MIDGInterpAtt( const MIDGatt A, const MIDGatt B, const double percent )
430 p.midg_time = MIDGTime((uint32_t)interp(A.midg_time.get_msec(),
431 B.midg_time.get_msec(),
433 p.yaw_rad = interp(A.yaw_rad, B.yaw_rad, percent, true);
434 p.pitch_rad = interp(A.pitch_rad, B.pitch_rad, percent, true);
435 p.roll_rad = interp(A.roll_rad, B.roll_rad, percent, true);