| EM datagrams on *.kmall format Reg.no. 410224 Revision H

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 #define _MDP_STANDALONE
32 #define _DATUM_DEFINED
33 #include <iostream>
34 #include <fstream>
35 #include <string>
36 #include <iomanip>
37 #include <sys/stat.h>
38 using namespace std;
39
40 #include "EMdgmFormat.h"
41
42 char * getMRZPingInfo(void * tgm)
43 {
44 char *pData = NULL;
45
46 // If this record is not empty
47 if (tgm != NULL)
48 {
49 pEMdgmMRZ dgm = (pEMdgmMRZ)tgm;
50 int sizeCommon = dgm->cmnPart.numBytesCmnPart;
51
52 // Find rxInfo. Must take account of number of TX sectors.
53 int numTxSectors = dgm->pingInfo.numTxSectors;
54
55 //Get PingInfo
56 char* pPI = (char*)(&(dgm->partition.dgmNum));
57 pPI += 2;
58 pPI += sizeCommon;
59
60 pEMdgmMRZ_pingInfo pPingInfo = (pEMdgmMRZ_pingInfo)pPI;
61
62 pData = pPI;
63
64 // end of datagram for safety testing
65 char *pSOD = (char*)dgm;
66 char *pEOD = pSOD + dgm->header.numBytesDgm; // first byte past end of data
67
68 // safety check - verify pointer is valid
69 if (pData >= pEOD)
70 {
71 pData = NULL;
72 }
73 }
74
75 return pData;
76 }
77
78 char * getMRZSectorInfo(void * tgm)
79 {
80 char *pData = NULL;
81
82 // if this record is not empty
83 if (tgm != NULL)
84 {
85 pEMdgmMRZ dgm = (pEMdgmMRZ)tgm;
86 int sizeCommon = dgm->cmnPart.numBytesCmnPart;
87
88 // Find rxInfo. Must take account of number of TX sectors.
89 int numTxSectors = dgm->pingInfo.numTxSectors;
90
91 //Get PingInfo
92 char* pPI = (char*)(&(dgm->partition.dgmNum));
93 pPI += 2;
94 pPI += sizeCommon;
95
96 pEMdgmMRZ_pingInfo pPingInfo = (pEMdgmMRZ_pingInfo)pPI;
97
98 //Move to end of pingInfo
99 char* pch = pPI + pPingInfo->numBytesInfoData; //At start of txsectors
100 int nSkip = 0;
101 pch += nSkip;
102
103 //Get sector
104 int nBytesTx = pPingInfo->numBytesPerTxSector;
105 pEMdgmMRZ_txSectorInfo pSect = (pEMdgmMRZ_txSectorInfo)pch;
106
107 pData = pch;
108
109 // end of datagram for safety testing
110 char *pSOD = (char*)dgm;
111 char *pEOD = pSOD + dgm->header.numBytesDgm; // first byte past end of data
112
113 // safety check - verify pointer is valid
114 if (pData >= pEOD)
115 {
116 pData = NULL;
117 }
118 }
119
120 return pData;
121 }
122
123 char *getMRZRxInfo(void* tgm)
124 {
125 char *pData = NULL;
126
127 // if this record is not empty
128 if (tgm != NULL)
129 {
130 pEMdgmMRZ dgm = (pEMdgmMRZ)tgm;
131 int sizeCommon = dgm->cmnPart.numBytesCmnPart;
132
133 // Find rxInfo. Must take account of number of TX sectors.
134 int numTxSectors = dgm->pingInfo.numTxSectors;
135
136 //Get PingInfo
137 char* pPI = (char*)(&(dgm->partition.dgmNum));
138 pPI += 2;
139 pPI += sizeCommon;
140
141 pEMdgmMRZ_pingInfo pPingInfo = (pEMdgmMRZ_pingInfo)pPI;
142
143 //Move to end of pingInfo
144 char* pch = pPI + pPingInfo->numBytesInfoData; //At start of txsectors
145 int nSkip = 0;
146 pch += nSkip;
147
148 //Get sector
149 int nBytesTx = pPingInfo->numBytesPerTxSector;
150 pEMdgmMRZ_txSectorInfo pSect = (pEMdgmMRZ_txSectorInfo)pch;
151
152 //Move to start of rxInfo
153 pch = (char*)pSect;
154 pch += (nBytesTx * numTxSectors);
155 EMdgmMRZ_rxInfo* pRxInfo = (EMdgmMRZ_rxInfo*)pch;
156
157 pData = pch;
158
159 // end of datagram for safety testing
160 char *pSOD = (char*)dgm;
161 char *pEOD = pSOD + dgm->header.numBytesDgm; // first byte past end of data
162
163 // safety check - verify pointer is valid
164 if (pData >= pEOD)
165 {
166 pData = NULL;
167 }
168 }
169
170 return pData;
171 }
172
173 char *getMRZSoundings(void* tgm)
174 {
175 char *pData = NULL;
176
177 // if this record is not empty
178 if (tgm != NULL)
179 {
180 pEMdgmMRZ dgm = (pEMdgmMRZ)tgm;
181 int sizeCommon = dgm->cmnPart.numBytesCmnPart;
182
183 // Find rxInfo. Must take account of number of TX sectors.
184 int numTxSectors = dgm->pingInfo.numTxSectors;
185
186 //Get PingInfo
187 char* pPI = (char*)(&(dgm->partition.dgmNum));
188 pPI += 2;
189 pPI += sizeCommon;
190
191 pEMdgmMRZ_pingInfo pPingInfo = (pEMdgmMRZ_pingInfo)pPI;
192
193 //Move to end of pingInfo
194 char* pch = pPI + pPingInfo->numBytesInfoData; //At start of txsectors
195 int nSkip = 0;
196 pch += nSkip;
197
198 //Get sector
199 int nBytesTx = pPingInfo->numBytesPerTxSector;
200 pEMdgmMRZ_txSectorInfo pSect = (pEMdgmMRZ_txSectorInfo)pch;
201
202 //Move to start of rxInfo
203 pch = (char*)pSect;
204 pch += (nBytesTx * numTxSectors);
205 EMdgmMRZ_rxInfo* pRxInfo = (EMdgmMRZ_rxInfo*)pch;
206 int nSizeRXInfo = pRxInfo->numBytesRxInfo;
207
208 // Now, find soundings.
209 int numExtraDet = pRxInfo->numExtraDetectionClasses;
210 pch += nSizeRXInfo;
211 pch += numExtraDet * sizeof(EMdgmMRZ_extraDetClassInfo);
212 EMdgmMRZ_sounding* pSoundings = (EMdgmMRZ_sounding*)pch;
213
214 pData = pch;
215
216 // end of datagram for safety testing
217 char *pSOD = (char*)dgm;
218 char *pEOD = pSOD + dgm->header.numBytesDgm; // first byte past end of data
219
220 // safety check - verify pointer is valid
221 if (pData >= pEOD)
222 {
223 pData = NULL;
224 }
225 }
226
227 return pData;
228 }
229
230 static void help(char* progname)
231 {
232 cout << "\n\nUsage: " << progname << "\n";
233 cout << " -h (gives this help)\n";
234 cout << " -f <filename>\n";
235 }
236
237 int main(int argc, char *argv[])
238 {
239 string filename("");
240 bool helpNeeded = false;
241 EMdgmMRZ mrz;
242 EMdgmHeader header;
243 char *p;
244
245 if (argc == 1) helpNeeded = true;
246 string h = string("-h");
247 string f = string("-f");
248 for (int i = 1; i < argc; i++)
249 {
250 if (h.compare(string(argv[i])) == 0)
251 {
252 helpNeeded = true;
253 break;
254 }
255 if (f.compare(argv[i]) == 0)
256 {
257 i++;
258 if (i >= argc)
259 {
260 helpNeeded = true;
261 break;
262 }
263 filename.assign(argv[i]);
264 ifstream fexists(filename);
265 if (fexists.good() == false)
266 {
267 cout << "Filename " << filename << " does not exist.\n";
268 helpNeeded = true;
269 break;
270 }
271 }
272 }
273
274 if (helpNeeded)
275 {
276 help(argv[0]);
277 exit(0);
278 }
279 else {
280 cout << "Filename: " << filename << "\n";
281 }
282
283 // Now do the thing.
284 ifstream kmall(filename, ios::in | ios::binary);
285
286 // Then read datagrams
287 long long tmptime;
288 while (1 == 1)
289 {
290 memset(&mrz, 0, sizeof(mrz));
291 memset(&header, 0, sizeof(header));
292 // First read header
293 kmall.read((char*)&header, sizeof(header));
294 if (kmall.gcount() != sizeof(header))
295 {
296 break;
297 }
298 // Check datagram type
299 if (header.dgmType[0] == '#' && header.dgmType[1] == 'M' && header.dgmType[2] == 'R' && header.dgmType[3] == 'Z')
300 {
301 p = (char*)&mrz;
302
303 // Put the header into the datagram
304 memcpy(p, (char*)&header, sizeof(header));
305 p += sizeof(header);
306
307 // Read the rest of the datagram
308 kmall.read(p, header.numBytesDgm - sizeof(header));
309 if (kmall.gcount() != header.numBytesDgm - sizeof(header))
310 {
311 break;
312 }
313 // Make time into millisec
314 tmptime = header.time_sec;
315 tmptime *= 1000;
316 tmptime += (header.time_nanosec / 1000000);
317
318 pEMdgmMRZ depths = &mrz;
319
320 //Structs above rxinfo can grow in newer datagram version. Use getMRZRxInfo to move to the correct location
321 pEMdgmMRZ_rxInfo rxInfo = (pEMdgmMRZ_rxInfo)getMRZRxInfo((char*)depths);
322 char* pData = (char*)(&(depths->sectorInfo[depths->pingInfo.numTxSectors]));
323 unsigned short numExtraDet = ((pEMdgmMRZ_rxInfo)(pData))->numExtraDetectionClasses;
324
325 //Structs above sounding can grow in newer datagram version. Use getMRZSoundings to move to the correct location
326 pEMdgmMRZ_sounding depthList = (pEMdgmMRZ_sounding)getMRZSoundings((char*)depths);
327
328 //Structs above pinginfo can grow in newer datagram version. Use getMRZPingInfo to move to the correct location
329 pEMdgmMRZ_pingInfo pPingInfo = (pEMdgmMRZ_pingInfo)getMRZPingInfo((char*)depths);
330 double blat = pPingInfo->latitude_deg;
331 double blon = pPingInfo->longitude_deg;
332
333 for (int i = 0; i < rxInfo->numSoundingsMaxMain; i++)
334 {
335 double dlat = (depthList + i)->deltaLatitude_deg;
336 double dlon = (depthList + i)->deltaLongitude_deg;
337 double depthRefPoint = (depthList + i)->z_reRefPoint_m;
338 double lat = blat + dlat;
339 double lon = blon + dlon;
340 double depthReWaterline = depthRefPoint - mrz.pingInfo.z_waterLevelReRefPoint_m;
341 cout << std::fixed << std::setprecision(8) << lat << " ";
342 cout << std::fixed << std::setprecision(8) << lon << " ";
343 cout << std::fixed << std::setprecision(2) << depthReWaterline << " ";
344 cout << tmptime << "\n";
345 }
346 }
347 else
348 {
349 // Move file pointer to next datagram
350 kmall.seekg(header.numBytesDgm - sizeof(header), ios::cur);
351 }
352 }//while forever
353 int i = 0;
354 }
355
EMdgmFormat.h
Definitions of structs used for building EM output datagrams of *.kmall format.
EMdgmMRZ_txSectorInfo_def
#MRZ - sector information.
Definition: EMdgmFormat.h:905
EMdgmHeader_def::numBytesDgm
uint32_t numBytesDgm
Definition: EMdgmFormat.h:116
EMdgmMRZ_pingInfo_def::latitude_deg
double latitude_deg
Definition: EMdgmFormat.h:879
EMdgmMRZ_def
#MRZ - Multibeam Raw Range and Depth datagram. The datagram also contains seabed image data.
Definition: EMdgmFormat.h:1094
EMdgmHeader_def
Definition of general datagram header.
Definition: EMdgmFormat.h:110
EMdgmMRZ_pingInfo_def::numBytesInfoData
uint16_t numBytesInfoData
Definition: EMdgmFormat.h:749
EMdgmMRZ_extraDetClassInfo_def
#MRZ - Extra detection class information.
Definition: EMdgmFormat.h:961
EMdgmMRZ_rxInfo_def::numSoundingsMaxMain
uint16_t numSoundingsMaxMain
Definition: EMdgmFormat.h:941
EMdgmMRZ_pingInfo_def::numTxSectors
uint16_t numTxSectors
Definition: EMdgmFormat.h:862
EMdgmMRZ_rxInfo_def::numExtraDetectionClasses
uint16_t numExtraDetectionClasses
Definition: EMdgmFormat.h:950
EMdgmMRZ_rxInfo_def::numBytesRxInfo
uint16_t numBytesRxInfo
Definition: EMdgmFormat.h:940
EMdgmMRZ_sounding_def
#MRZ - Data for each sounding, e.g. XYZ, reflectivity, two way travel time etc.
Definition: EMdgmFormat.h:978
EMdgmMRZ_pingInfo_def::numBytesPerTxSector
uint16_t numBytesPerTxSector
Definition: EMdgmFormat.h:863
EMdgmMRZ_pingInfo_def::z_waterLevelReRefPoint_m
float z_waterLevelReRefPoint_m
Definition: EMdgmFormat.h:871
EMdgmMpartition_def::dgmNum
uint16_t dgmNum
Definition: EMdgmFormat.h:679
EMdgmMRZ_rxInfo_def
#MRZ - receiver specific information.
Definition: EMdgmFormat.h:938
EMdgmMRZ_pingInfo_def::longitude_deg
double longitude_deg
Definition: EMdgmFormat.h:880
EMdgmMbody_def::numBytesCmnPart
uint16_t numBytesCmnPart
Definition: EMdgmFormat.h:719
EMdgmMRZ_pingInfo_def
#MRZ - ping info. Information on vessel/system level, i.e. information common to all beams in the cur...
Definition: EMdgmFormat.h:744