| EM datagrams on *.kmall format Reg.no. 410224 rev F

KMALL_reader.cpp
Go to the documentation of this file.
1 /*
2 * KONGSBERG retain full title to and ownership to the Licensed Software,
3 * including all copies, derivatives or future versions thereof, and all
4 * rights therein. Notwithstanding the foregoing, Customer may modify the
5 * Licensed Software to the extent necessary in connection with Customer’s
6 * creation of applications for the Licensed Software, however, provided
7 * that such permitted modifications shall be for Customer’s internal use
8 * only. Customer shall not sell, distribute or otherwise provide access to
9 * such modifications to any third party, without the consent from KONGSBERG.
10 *
11 * Copyright (c) 2018 KONGSBERG - All rights reserved.
12 */
13
14 //h+/////////////////////////////////////////////////////////////////////////////////////
31 //
33 // Revision History:
34 //
35 // 00 27 APR 2018 THP Original Version
36 // 01 19 OCT 2018 jornh Updated with helper functions
37 //
39
40 //#include "stdafx.h"
41 #define _MDP_STANDALONE
42 #define _DATUM_DEFINED
43 #include <iostream>
44 #include <fstream>
45 #include <string>
46 #include <iomanip>
47 #include <sys/stat.h>
48 using namespace std;
49
50 #include "EMdgmFormat.h"
51
52
53 //f+/////////////////////////////////////////////////////////////////////////
54 //
55 // getMRZPingInfo
67 //f-/////////////////////////////////////////////////////////////////////////
68
69 char * getMRZPingInfo(void * tgm)
70 {
71 char *pData = NULL;
72
73 // if this record is not empty
74 if (tgm != NULL)
75 {
76 pEMdgmMRZ dgm = (pEMdgmMRZ)tgm;
77 int sizeCommon = dgm->cmnPart.numBytesCmnPart;
78
79 // Find rxInfo. Must take account of number of TX sectors.
80 int numTxSectors = dgm->pingInfo.numTxSectors;
81
82 //Get PingInfo
83 char* pPI = (char*)(&(dgm->partition.dgmNum));
84 pPI += 2;
85 pPI += sizeCommon;
86
87 pEMdgmMRZ_pingInfo pPingInfo = (pEMdgmMRZ_pingInfo)pPI;
88
89 pData = pPI;
90
91 // end of datagram for safety testing
92 char *pSOD = (char*)dgm;
93 char *pEOD = pSOD + dgm->header.numBytesDgm; // first byte past end of data
94
95 // safety check - verify pointer is valid
96 if (pData >= pEOD)
97 {
98 pData = NULL;
99 }
100 }
101
102 return pData;
103 }
104
105 //f+/////////////////////////////////////////////////////////////////////////
106 //
107 // getMRZSectorInfo
119 //f-/////////////////////////////////////////////////////////////////////////
120
121 char * getMRZSectorInfo(void * tgm)
122 {
123 char *pData = NULL;
124
125 // if this record is not empty
126 if (tgm != NULL)
127 {
128 pEMdgmMRZ dgm = (pEMdgmMRZ)tgm;
129 int sizeCommon = dgm->cmnPart.numBytesCmnPart;
130
131 // Find rxInfo. Must take account of number of TX sectors.
132 int numTxSectors = dgm->pingInfo.numTxSectors;
133
134 //Get PingInfo
135 char* pPI = (char*)(&(dgm->partition.dgmNum));
136 pPI += 2;
137 pPI += sizeCommon;
138
139 pEMdgmMRZ_pingInfo pPingInfo = (pEMdgmMRZ_pingInfo)pPI;
140
141 //Move to end of pingInfo
142 char* pch = pPI + pPingInfo->numBytesInfoData; //At start of txsectors
143 int nSkip = 0;
144 pch += nSkip;
145
146 //Get sector
147 int nBytesTx = pPingInfo->numBytesPerTxSector;
148 pEMdgmMRZ_txSectorInfo pSect = (pEMdgmMRZ_txSectorInfo)pch;
149
150 pData = pch;
151
152 // end of datagram for safety testing
153 char *pSOD = (char*)dgm;
154 char *pEOD = pSOD + dgm->header.numBytesDgm; // first byte past end of data
155
156 // safety check - verify pointer is valid
157 if (pData >= pEOD)
158 {
159 pData = NULL;
160 }
161 }
162
163 return pData;
164 }
165
166 //f+/////////////////////////////////////////////////////////////////////////
167 //
168 // getMRZRxInfo
180 //f-/////////////////////////////////////////////////////////////////////////
181
182 char *getMRZRxInfo(void* tgm)
183 {
184 char *pData = NULL;
185
186 // if this record is not empty
187 if (tgm != NULL)
188 {
189 pEMdgmMRZ dgm = (pEMdgmMRZ)tgm;
190 int sizeCommon = dgm->cmnPart.numBytesCmnPart;
191
192 // Find rxInfo. Must take account of number of TX sectors.
193 int numTxSectors = dgm->pingInfo.numTxSectors;
194
195 //Get PingInfo
196 char* pPI = (char*)(&(dgm->partition.dgmNum));
197 pPI += 2;
198 pPI += sizeCommon;
199
200 pEMdgmMRZ_pingInfo pPingInfo = (pEMdgmMRZ_pingInfo)pPI;
201
202 //Move to end of pingInfo
203 char* pch = pPI + pPingInfo->numBytesInfoData; //At start of txsectors
204 int nSkip = 0;
205 pch += nSkip;
206
207 //Get sector
208 int nBytesTx = pPingInfo->numBytesPerTxSector;
209 pEMdgmMRZ_txSectorInfo pSect = (pEMdgmMRZ_txSectorInfo)pch;
210
211 //Move to start of rxInfo
212 pch = (char*)pSect;
213 pch += (nBytesTx * numTxSectors);
214 EMdgmMRZ_rxInfo* pRxInfo = (EMdgmMRZ_rxInfo*)pch;
215
216 pData = pch;
217
218 // end of datagram for safety testing
219 char *pSOD = (char*)dgm;
220 char *pEOD = pSOD + dgm->header.numBytesDgm; // first byte past end of data
221
222 // safety check - verify pointer is valid
223 if (pData >= pEOD)
224 {
225 pData = NULL;
226 }
227 }
228
229 return pData;
230 }
231
232 //f+/////////////////////////////////////////////////////////////////////////
233 //
234 // getMRZSoundings
246 //f-/////////////////////////////////////////////////////////////////////////
247
248 char *getMRZSoundings(void* tgm)
249 {
250 char *pData = NULL;
251
252 // if this record is not empty
253 if (tgm != NULL)
254 {
255 pEMdgmMRZ dgm = (pEMdgmMRZ)tgm;
256 int sizeCommon = dgm->cmnPart.numBytesCmnPart;
257
258 // Find rxInfo. Must take account of number of TX sectors.
259 int numTxSectors = dgm->pingInfo.numTxSectors;
260
261 //Get PingInfo
262 char* pPI = (char*)(&(dgm->partition.dgmNum));
263 pPI += 2;
264 pPI += sizeCommon;
265
266 pEMdgmMRZ_pingInfo pPingInfo = (pEMdgmMRZ_pingInfo)pPI;
267
268 //Move to end of pingInfo
269 char* pch = pPI + pPingInfo->numBytesInfoData; //At start of txsectors
270 int nSkip = 0;
271 pch += nSkip;
272
273 //Get sector
274 int nBytesTx = pPingInfo->numBytesPerTxSector;
275 pEMdgmMRZ_txSectorInfo pSect = (pEMdgmMRZ_txSectorInfo)pch;
276
277 //Move to start of rxInfo
278 pch = (char*)pSect;
279 pch += (nBytesTx * numTxSectors);
280 EMdgmMRZ_rxInfo* pRxInfo = (EMdgmMRZ_rxInfo*)pch;
281 int nSizeRXInfo = pRxInfo->numBytesRxInfo;
282
283 // Now, find soundings.
284 int numExtraDet = pRxInfo->numExtraDetectionClasses;
285 pch += nSizeRXInfo;
286 pch += numExtraDet * sizeof(EMdgmMRZ_extraDetClassInfo);
287 EMdgmMRZ_sounding* pSoundings = (EMdgmMRZ_sounding*)pch;
288
289 pData = pch;
290
291 // end of datagram for safety testing
292 char *pSOD = (char*)dgm;
293 char *pEOD = pSOD + dgm->header.numBytesDgm; // first byte past end of data
294
295 // safety check - verify pointer is valid
296 if (pData >= pEOD)
297 {
298 pData = NULL;
299 }
300 }
301
302 return pData;
303 }
304
306 static void help(char* progname)
307 {
308 cout << "\n\nUsage: " << progname << "\n";
309 cout << " -h (gives this help)\n";
310 cout << " -f <filename>\n";
311 }
312
313 int main(int argc, char *argv[])
314 {
315 string filename("");
316 bool helpNeeded = false;
317 EMdgmMRZ mrz;
318 EMdgmHeader header;
319 char *p;
320
321 if (argc == 1) helpNeeded = true;
322 string h = string("-h");
323 string f = string("-f");
324 for (int i = 1; i < argc; i++)
325 {
326 if (h.compare(string(argv[i])) == 0)
327 {
328 helpNeeded = true;
329 break;
330 }
331 if (f.compare(argv[i]) == 0)
332 {
333 i++;
334 if (i >= argc)
335 {
336 helpNeeded = true;
337 break;
338 }
339 filename.assign(argv[i]);
340 ifstream fexists(filename);
341 if (fexists.good() == false)
342 {
343 cout << "Filename " << filename << " does not exist.\n";
344 helpNeeded = true;
345 break;
346 }
347 }
348 }
349
350 if (helpNeeded)
351 {
352 help(argv[0]);
353 exit(0);
354 }
355 else {
356 cout << "Filename: " << filename << "\n";
357 }
358
359
360 // Now do the thing.
361 ifstream kmall(filename, ios::in | ios::binary);
362 // Then read datagrams
363 long long tmptime;
364 while (1 == 1) {
365 memset(&mrz, 0, sizeof(mrz));
366 memset(&header, 0, sizeof(header));
367 // First read header
368 kmall.read((char*)&header, sizeof(header));
369 if (kmall.gcount() != sizeof(header))
370 {
371 break;
372 }
373 // Check datagram type
374 if (header.dgmType[0] == '#' && header.dgmType[1] == 'M' && header.dgmType[2] == 'R' && header.dgmType[3] == 'Z')
375 {
376 p = (char*)&mrz;
377 // Put the header into the datagram
378 memcpy(p, (char*)&header, sizeof(header));
379 p += sizeof(header);
380 // Read the rest of the datagram
381 kmall.read(p, header.numBytesDgm - sizeof(header));
382 if (kmall.gcount() != header.numBytesDgm - sizeof(header))
383 {
384 break;
385 }
386 // Make time into millisec
387 tmptime = header.time_sec;
388 tmptime *= 1000;
389 tmptime += (header.time_nanosec / 1000000);
390
391 pEMdgmMRZ depths = &mrz;
392 //Structs above rxinfo can grow in newer datagram version. Use getMRZRxInfo to move to the correct location
393 pEMdgmMRZ_rxInfo rxInfo = (pEMdgmMRZ_rxInfo)getMRZRxInfo((char*)depths);
394 char* pData = (char*)(&(depths->sectorInfo[depths->pingInfo.numTxSectors]));
395 unsigned short numExtraDet = ((pEMdgmMRZ_rxInfo)(pData))->numExtraDetectionClasses;
396
397 //Structs above sounding can grow in newer datagram version. Use getMRZSoundings to move to the correct location
398 pEMdgmMRZ_sounding depthList = (pEMdgmMRZ_sounding)getMRZSoundings((char*)depths);
399
400 //Structs above pinginfo can grow in newer datagram version. Use getMRZPingInfo to move to the correct location
401 pEMdgmMRZ_pingInfo pPingInfo = (pEMdgmMRZ_pingInfo)getMRZPingInfo((char*)depths);
402 double blat = pPingInfo->latitude_deg;
403 double blon = pPingInfo->longitude_deg;
404
405 for (int i = 0; i < rxInfo->numSoundingsMaxMain; i++) {
406 double dlat = (depthList + i)->deltaLatitude_deg;
407 double dlon = (depthList + i)->deltaLongitude_deg;
408 double depthRefPoint = (depthList + i)->z_reRefPoint_m;
409 double lat = blat + dlat;
410 double lon = blon + dlon;
411 double depthReWaterline = depthRefPoint - mrz.pingInfo.z_waterLevelReRefPoint_m;
412 cout << std::fixed << std::setprecision(8) << lat << " ";
413 cout << std::fixed << std::setprecision(8) << lon << " ";
414 cout << std::fixed << std::setprecision(2) << depthReWaterline << " ";
415 cout << tmptime << "\n";
416 }
417 }//if #MRZ
418 else {
419 // Move file pointer to next datagram
420 kmall.seekg(header.numBytesDgm - sizeof(header), ios::cur);
421 }
422 }//while forever
423 int i = 0;
424 }
425
EMdgmMRZ_txSectorInfo_def
#MRZ - sector information.
Definition: EMdgmFormat.h:879
EMdgmFormat.h
Definitions of structs used for building EM output datagrams of *.kmall format.
EMdgmMRZ_rxInfo_def::numBytesRxInfo
uint16_t numBytesRxInfo
Definition: EMdgmFormat.h:908
std
EMdgmMpartition_def::dgmNum
uint16_t dgmNum
Definition: EMdgmFormat.h:666
EMdgmMRZ_extraDetClassInfo_def
#MRZ - Extra detection class information.
Definition: EMdgmFormat.h:929
EMdgmHeader_def::numBytesDgm
uint32_t numBytesDgm
Definition: EMdgmFormat.h:105
getMRZRxInfo
char * getMRZRxInfo(void *tgm)
Definition: KMALL_reader.cpp:182
EMdgmMRZ_pingInfo_def::numBytesInfoData
uint16_t numBytesInfoData
Definition: EMdgmFormat.h:737
EMdgmMRZ_pingInfo_def::latitude_deg
double latitude_deg
Definition: EMdgmFormat.h:865
EMdgmMRZ_pingInfo_def::z_waterLevelReRefPoint_m
float z_waterLevelReRefPoint_m
Definition: EMdgmFormat.h:857
EMdgmMRZ_pingInfo_def::numTxSectors
uint16_t numTxSectors
Definition: EMdgmFormat.h:848
EMdgmMRZ_def
#MRZ - Multibeam Raw Range and Depth datagram. The datagram also contains seabed image data...
Definition: EMdgmFormat.h:1062
getMRZSectorInfo
char * getMRZSectorInfo(void *tgm)
Definition: KMALL_reader.cpp:121
EMdgmMRZ_sounding_def
#MRZ - Data for each sounding, e.g. XYZ, reflectivity, two way travel time etc.
Definition: EMdgmFormat.h:946
EMdgmMRZ_rxInfo_def::numSoundingsMaxMain
uint16_t numSoundingsMaxMain
Definition: EMdgmFormat.h:909
EMdgmMbody_def::numBytesCmnPart
uint16_t numBytesCmnPart
Definition: EMdgmFormat.h:710
EMdgmMRZ_rxInfo_def::numExtraDetectionClasses
uint16_t numExtraDetectionClasses
Definition: EMdgmFormat.h:918
EMdgmMRZ_pingInfo_def::numBytesPerTxSector
uint16_t numBytesPerTxSector
Definition: EMdgmFormat.h:849
EMdgmMRZ_pingInfo_def
#MRZ - ping info. Information on vessel/system level, i.e. information common to all beams in the cur...
Definition: EMdgmFormat.h:735
getMRZSoundings
char * getMRZSoundings(void *tgm)
Definition: KMALL_reader.cpp:248
EMdgmMRZ_rxInfo_def
#MRZ - receiver specific information.
Definition: EMdgmFormat.h:906
getMRZPingInfo
char * getMRZPingInfo(void *tgm)
Definition: KMALL_reader.cpp:69
EMdgmHeader_def
Definition of general datagram header.
Definition: EMdgmFormat.h:103
EMdgmMRZ_pingInfo_def::longitude_deg
double longitude_deg
Definition: EMdgmFormat.h:866