cltool_main.cpp
Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright (c) 2014-2020 Inertial Sense, Inc. - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 /*
14 * main.cpp
15 *
16 * (c) 2014 Inertial Sense, LLC
17 *
18 * The Inertial Sense Command Line Tool (cltool) shows how easy it is to communicate with the uINS, log data, update firmware and more.
19 *
20 * The following keywords are found within this file to identify instructions
21 * for SDK implementation.
22 *
23 * KEYWORD: SDK Implementation
24 * [C++ COMM INSTRUCTION] - C++ binding API - InertialSense class with binary communication
25 * protocol and serial port support for Linux and Windows.
26 * [C COMM INSTRUCTION] - C binding API - Com Manager with binary communication protocol.
27 * [LOGGER INSTRUCTION] - Data logger.
28 * [BOOTLOADER INSTRUCTION] - Firmware update feature.
29 *
30 * This app is designed to be compiled in Linux and Windows. When using MS
31 * Visual Studio IDE, command line arguments can be supplied by right clicking
32 * the project in solution explorer and then selecting properties -> debugging -> command line arguments
33 */
34 
35 // Contains command line parsing and utility functions. Include this in your project to use these utility functions.
36 #include "cltool.h"
37 
38 static bool output_server_bytes(InertialSense* i, const char* prefix = "", const char* suffix = "")
39 {
40  static float serverKBps = 0;
41  static uint64_t serverByteCount = 0;
42  static uint64_t updateCount = 0;
43  static uint64_t serverByteRateTimeMsLast = 0;
44  static uint64_t serverByteCountLast = 0;
45 
47  {
48  uint64_t newServerByteCount = i->GetClientServerByteCount();
49  if (serverByteCount != newServerByteCount)
50  {
51  serverByteCount = newServerByteCount;
52 
53  // Data rate of server bytes
54  uint64_t timeMs = getTickCount();
55  uint64_t dtMs = timeMs - serverByteRateTimeMsLast;
56  if (dtMs >= 1000)
57  {
58  uint64_t serverBytesDelta = serverByteCount - serverByteCountLast;
59  serverKBps = ((float)serverBytesDelta / (float)dtMs);
60 
61  // Update history
62  serverByteCountLast = serverByteCount;
63  serverByteRateTimeMsLast = timeMs;
64  }
65  printf("%sServer: %02" PRIu64 " (%3.1f KB/s : %lld) %s", prefix, (++updateCount) % 100, serverKBps, (long long)i->GetClientServerByteCount(), suffix);
66  return true;
67  }
68  }
69  return false;
70 }
71 
73 {
75  {
76  return;
77  }
78 
80  {
81  char suffix[256];
83  suffix[0] = '\0';
85  {
86  snprintf(suffix, sizeof(suffix), "Com errors: %d ", status->communicationErrorCount);
87  }
89  if (i->GetClientServerByteCount() == 0)
90  {
91  cout << endl << suffix;
92  }
93  else
94  {
95  output_server_bytes(i, "\n", suffix);
96  }
97  }
98 }
99 
100 // [C++ COMM INSTRUCTION] STEP 5: Handle received data
101 static void cltool_dataCallback(InertialSense* i, p_data_t* data, int pHandle)
102 {
103  (void)i;
104  (void)pHandle;
105  // Print data to terminal
108 
109 #if 0
110 
111  // uDatasets is a union of all datasets that we can receive. See data_sets.h for a full list of all available datasets.
112  uDatasets d = {};
113  copyDataPToStructP(&d, data, sizeof(uDatasets));
114 
115  // Example of how to access dataset fields.
116  switch (data->hdr.id)
117  {
118  case DID_INS_2:
119  d.ins2.qn2b; // quaternion attitude
120  d.ins2.uvw; // body velocities
121  d.ins2.lla; // latitude, longitude, altitude
122  break;
123  case DID_INS_1:
124  d.ins1.theta; // euler attitude
125  d.ins1.lla; // latitude, longitude, altitude
126  break;
127  case DID_DUAL_IMU:
128  d.dualImu;
129  break;
130  case DID_PREINTEGRATED_IMU:
131  d.pImu;
132  break;
133  case DID_GPS_NAV:
134  d.gpsNav;
135  break;
136  case DID_MAGNETOMETER_1:
137  d.mag;
138  break;
139  case DID_MAGNETOMETER_2:
140  d.mag;
141  break;
142  case DID_BAROMETER:
143  d.baro;
144  break;
145  case DID_SYS_SENSORS:
146  d.sysSensors;
147  break;
148  }
149 
150 #endif
151 
152 }
153 
154 // Where we tell the uINS what data to send and at what rate.
155 // "cltool_dataCallback()" is registered as the callback functions for all received data.
156 // All DID messages are found in data_sets.h
157 static bool cltool_setupCommunications(InertialSense& inertialSenseInterface)
158 {
159  inertialSenseInterface.StopBroadcasts(); // Stop streaming any prior messages
160 
161  if (g_commandLineOptions.asciiMessages.size() != 0)
162  {
164  return true;
165  }
166 
167  // ask for device info every 2 seconds
168  inertialSenseInterface.BroadcastBinaryData(DID_DEV_INFO, 2000);
169 
170  // depending on command line options. stream various data sets
172  {
174  }
176  {
178  }
180  {
182  }
184  {
186  }
188  {
190  }
192  {
194  }
196  {
198  }
200  {
202  }
204  {
206  }
208  {
210  }
212  {
214  }
216  {
218  }
220  {
222  }
224  {
226  }
228  {
230  system_command_t cfg;
232  cfg.invCommand = ~cfg.command;
233  inertialSenseInterface.SendRawData(DID_SYS_CMD, (uint8_t*)&cfg, sizeof(system_command_t), 0);
234  }
236  {
238  }
240  {
242  }
244  {
245  // Enable broadcase of DID_MAG_CAL so we can observe progress and tell when the calibration is done (i.e. DID_MAG_CAL.recalCmd == 100).
246  inertialSenseInterface.BroadcastBinaryData(DID_MAG_CAL, 100);
247  // Enable mag recal
248  inertialSenseInterface.SendRawData(DID_MAG_CAL, (uint8_t*)&g_commandLineOptions.magRecalMode, sizeof(g_commandLineOptions.magRecalMode), offsetof(mag_cal_t, recalCmd));
249  }
251  { // Enable mult-axis
252  inertialSenseInterface.SendRawData(DID_SURVEY_IN, (uint8_t*)&g_commandLineOptions.surveyIn, sizeof(survey_in_t), 0);
253  }
255  {
257  }
259  { // Save persistent messages to flash
260  system_command_t cfg;
262  cfg.invCommand = ~cfg.command;
263  inertialSenseInterface.SendRawData(DID_SYS_CMD, (uint8_t*)&cfg, sizeof(system_command_t), 0);
264  }
266  { // Issue software reset
267  system_command_t cfg;
269  cfg.invCommand = ~cfg.command;
270  inertialSenseInterface.SendRawData(DID_SYS_CMD, (uint8_t*)&cfg, sizeof(system_command_t), 0);
271  }
272 
273  if (g_commandLineOptions.serverConnection.length() != 0)
274  {
275  if (g_commandLineOptions.serverConnection.find("RTCM3:") == 0 ||
276  g_commandLineOptions.serverConnection.find("IS:") == 0 ||
277  g_commandLineOptions.serverConnection.find("UBLOX:") == 0)
278  {
279  if (!inertialSenseInterface.OpenServerConnection(g_commandLineOptions.serverConnection))
280  {
281  cout << "Failed to connect to server." << endl;
282  }
283  }
284  else
285  {
286  cout << "Invalid server connection, must prefix with RTCM3:, IS: or UBLOX:, " << g_commandLineOptions.serverConnection << endl;
287  return false;
288  }
289  }
290  if (g_commandLineOptions.flashConfig.length() != 0)
291  {
292  return cltool_updateFlashConfig(inertialSenseInterface, g_commandLineOptions.flashConfig);
293  }
294  return true;
295 }
296 
298 {
299  // [BOOTLOADER INSTRUCTION] Update firmware
300  cout << "Updating application firmware using file at " << g_commandLineOptions.updateAppFirmwareFilename << endl;
301  vector<InertialSense::bootloader_result_t> results = InertialSense::BootloadFile(g_commandLineOptions.comPort,
308  cout << endl << "Results:" << endl;
309  int errorCount = 0;
310  for (size_t i = 0; i < results.size(); i++)
311  {
312  cout << results[i].port << ": " << (results[i].error.size() == 0 ? "Success\n" : results[i].error);
313  errorCount += (int)(results[i].error.size() != 0);
314  }
315  if (errorCount != 0)
316  {
317  cout << endl << errorCount << " ports failed." << endl;
318  }
319  return (errorCount == 0 ? 0 : -1);
320 }
321 
323 {
324  cout << "Updating bootloader using file at " << g_commandLineOptions.updateBootloaderFilename << endl;
325  vector<InertialSense::bootloader_result_t> results = InertialSense::BootloadFile(g_commandLineOptions.comPort,
327  "",
332  true);
333  cout << endl << "Results:" << endl;
334  int errorCount = 0;
335  for (size_t i = 0; i < results.size(); i++)
336  {
337  cout << results[i].port << ": " << (results[i].error.size() == 0 ? "Success\n" : results[i].error);
338  errorCount += (int)(results[i].error.size() != 0);
339  }
340  if (errorCount != 0)
341  {
342  cout << endl << errorCount << " ports failed." << endl;
343  }
344  return (errorCount == 0 ? 0 : -1);
345 }
346 
347 static int cltool_createHost()
348 {
349  InertialSense inertialSenseInterface;
350  if (!inertialSenseInterface.Open(g_commandLineOptions.comPort.c_str(), g_commandLineOptions.baudRate))
351  {
352  cout << "Failed to open serial port at " << g_commandLineOptions.comPort.c_str() << endl;
353  return -1;
354  }
355  else if (g_commandLineOptions.flashConfig.length() != 0 && !cltool_updateFlashConfig(inertialSenseInterface, g_commandLineOptions.flashConfig))
356  {
357  cout << "Failed to update flash config" << endl;
358  return -1;
359  }
360  else if (!inertialSenseInterface.CreateHost(g_commandLineOptions.host))
361  {
362  cout << "Failed to create host at " << g_commandLineOptions.host << endl;
363  return -1;
364  }
365 
366  inertialSenseInterface.StopBroadcasts();
367 
369  {
370  inertialSenseInterface.Update();
372  output_server_bytes(&inertialSenseInterface);
373  }
374  cout << "Shutting down..." << endl;
375 
376  // close the interface cleanly, this ensures serial port and any logging are shutdown properly
377  inertialSenseInterface.Close();
378 
379  return 0;
380 }
381 
382 static int inertialSenseMain()
383 {
384  // clear display
387 
388  // if replay data log specified on command line, do that now and return
390  {
391  // [REPLAY INSTRUCTION] 1.) Replay data log
392  return !cltool_replayDataLog();
393  }
394  // if app firmware was specified on the command line, do that now and return
395  else if (g_commandLineOptions.updateAppFirmwareFilename.length() != 0)
396  {
398  {
399  cout << "Incorrect file extension." << endl;
400  return -1;
401  }
402 
403  // [BOOTLOADER INSTRUCTION] 1.) Run bootloader
404  return cltool_updateAppFirmware();
405  }
406  // if bootloader filename was specified on the command line, do that now and return
407  else if (g_commandLineOptions.updateBootloaderFilename.length() != 0)
408  {
410  {
411  cout << "Incorrect file extension." << endl;
412  return -1;
413  }
414 
415  return cltool_updateBootloader();
416  }
417  // if host was specified on the command line, create a tcp server
418  else if (g_commandLineOptions.host.length() != 0)
419  {
420  return cltool_createHost();
421  }
422  else if (g_commandLineOptions.asciiMessages.size() != 0)
423  {
424  serial_port_t serialForAscii;
425  serialPortPlatformInit(&serialForAscii);
427  serialPortWriteAscii(&serialForAscii, "STPB", 4);
428  serialPortWriteAscii(&serialForAscii, ("ASCB," + g_commandLineOptions.asciiMessages).c_str(), (int)(5 + g_commandLineOptions.asciiMessages.size()));
429  unsigned char line[512];
430  unsigned char* asciiData;
432  {
433  int count = serialPortReadAsciiTimeout(&serialForAscii, line, sizeof(line), 100, &asciiData);
434  if (count > 0)
435  {
436  printf("%s", (char*)asciiData);
437  printf("\r\n");
438  }
439  }
440  }
441  // open the device, start streaming data and logging if needed
442  else
443  {
444  // [C++ COMM INSTRUCTION] STEP 1: Instantiate InertialSense Class
445  // Create InertialSense object, passing in data callback function pointer.
446  InertialSense inertialSenseInterface(cltool_dataCallback);
447 
448  // [C++ COMM INSTRUCTION] STEP 2: Open serial port
450  {
451  cout << "Failed to open serial port at " << g_commandLineOptions.comPort.c_str() << endl;
452  return -1; // Failed to open serial port
453  }
454 
455  // [C++ COMM INSTRUCTION] STEP 3: Enable data broadcasting
456  if (cltool_setupCommunications(inertialSenseInterface))
457  {
458  // [LOGGER INSTRUCTION] Setup and start data logger
459  if (g_commandLineOptions.asciiMessages.size() == 0 && !cltool_setupLogger(inertialSenseInterface))
460  {
461  cout << "Failed to setup logger!" << endl;
462  inertialSenseInterface.Close();
463  return -1;
464  }
465  try
466  {
467  // Main loop. Could be in separate thread if desired.
469  {
470  // [C++ COMM INSTRUCTION] STEP 4: Read data
471  if (!inertialSenseInterface.Update())
472  {
473  // device disconnected, exit
474  break;
475  }
476  }
477  }
478  catch (...)
479  {
480  cout << "Unknown exception...";
481  }
482  }
483 
484  cout << "Shutting down..." << endl;
485 
486  // [C++ COMM INSTRUCTION] STEP 6: Close interface
487  // Close cleanly to ensure serial port and logging are shutdown properly. (optional)
488  inertialSenseInterface.Close();
489  }
490 
491  return 0;
492 }
493 
494 
495 int cltool_main(int argc, char* argv[])
496 {
497  // Parse command line options
498  if (!cltool_parseCommandLine(argc, argv))
499  {
501 
502  // parsing failed
503  return -1;
504  }
505 
506  // InertialSense class example using command line options
507  int result = inertialSenseMain();
508  if (result == -1)
509  {
511 
512  // Pause so user can read error
513  SLEEP_MS(2000);
514  }
515 
517 
518  return result;
519 }
d
#define DID_SURVEY_IN
Definition: data_sets.h:107
string asciiMessages
Definition: cltool.h:60
#define DID_DUAL_IMU
Definition: data_sets.h:92
int streamRtkCmpRel
Definition: cltool.h:76
void StopBroadcasts(bool allPorts=true)
static vector< bootloader_result_t > BootloadFile(const string &comPort, const string &fileName, const string &bootloaderFileName, int baudRate=IS_BAUD_RATE_BOOTLOADER, pfnBootloadProgress uploadProgress=NULLPTR, pfnBootloadProgress verifyProgress=NULLPTR, pfnBootloadStatus infoProgress=NULLPTR, bool updateBootloader=false)
ins_2_t ins2
Definition: data_sets.h:3407
static int cltool_updateBootloader()
com_manager_status_t * comManagerGetStatus(int pHandle)
Definition: com_manager.c:482
bool bootloaderVerify
Definition: cltool.h:54
float qn2b[4]
Definition: data_sets.h:534
ins_1_t ins1
Definition: data_sets.h:3406
string updateBootloaderFilename
Definition: cltool.h:53
void ProcessData(p_data_t *data, bool enableReplay=false, double replaySpeedX=1.0)
Definition: ISDisplay.cpp:283
static int cltool_updateAppFirmware()
uint32_t id
Definition: ISComm.h:375
is_can_uvw uvw
Definition: CAN_comm.h:257
#define DID_INS_1
Definition: data_sets.h:38
int streamRtkPosRel
Definition: cltool.h:75
static void output_client_bytes(InertialSense *i)
Definition: cltool_main.cpp:72
int serialPortOpen(serial_port_t *serialPort, const char *port, int baudRate, int blocking)
uint32_t state
Definition: data_sets.h:2846
#define DID_GPS2_RTK_CMP_REL
Definition: data_sets.h:125
uint32_t communicationErrorCount
Definition: com_manager.h:89
#define printf(...)
cInertialSenseDisplay g_inertialSenseDisplay
Definition: cltool.cpp:18
bool OpenServerConnection(const string &connectionString)
uint64_t GetClientServerByteCount()
bool cltool_replayDataLog()
Definition: cltool.cpp:412
float mag[3]
Definition: data_sets.h:642
int serialPortWriteAscii(serial_port_t *serialPort, const char *buffer, int bufferLength)
size_t count(InputIterator first, InputIterator last, T const &item)
Definition: catch.hpp:3206
#define DID_DEV_INFO
Definition: data_sets.h:35
bool softwareReset
Definition: cltool.h:56
#define DID_INS_2
Definition: data_sets.h:39
int bootloadUploadProgress(const void *port, float percent)
cmd_options_t g_commandLineOptions
Definition: cltool.cpp:16
int bootloadVerifyProgress(const void *port, float percent)
int streamRTOS
Definition: cltool.h:82
char copyDataPToStructP(void *sptr, const p_data_t *data, const unsigned int maxsize)
Definition: ISComm.c:975
void SetTimeoutFlushLoggerSeconds(time_t timeoutFlushLoggerSeconds)
uint64_t getTickCount(void)
#define DID_PREINTEGRATED_IMU
Definition: data_sets.h:37
#define SLEEP_MS(timeMs)
Definition: ISUtilities.h:134
int baudRate
Definition: cltool.h:91
int serialPortReadAsciiTimeout(serial_port_t *serialPort, unsigned char *buffer, int bufferLength, int timeoutMilliseconds, unsigned char **asciiData)
void SetDisplayMode(eDisplayMode mode)
Definition: ISDisplay.h:43
int streamSensorsADC
Definition: cltool.h:83
bool cltool_parseCommandLine(int argc, char *argv[])
Definition: cltool.cpp:63
#define DID_MAG_CAL
Definition: data_sets.h:53
#define NULLPTR
Definition: ISConstants.h:426
#define RMC_OPTIONS_PRESERVE_CTRL
Definition: data_sets.h:1217
bool persistentMessages
Definition: cltool.h:65
bool CreateHost(const string &ipAndPort)
void bootloadStatusInfo(const void *port, const char *str)
bool cltool_setupLogger(InertialSense &inertialSenseInterface)
Definition: cltool.cpp:27
#define DID_MAGNETOMETER_2
Definition: data_sets.h:89
int streamINS2
Definition: cltool.h:67
std::ostream & cout()
uint32_t invCommand
Definition: data_sets.h:1112
void SendRawData(eDataIDs dataId, uint8_t *data, uint32_t length=0, uint32_t offset=0)
bool magRecal
Definition: cltool.h:57
bool cltool_updateFlashConfig(InertialSense &inertialSenseInterface, string flashConfigString)
Definition: cltool.cpp:534
preintegrated_imu_t pImu
Definition: data_sets.h:3417
#define DID_SYS_CMD
Definition: data_sets.h:41
bool disableBroadcastsOnClose
Definition: cltool.h:92
uint32_t command
Definition: data_sets.h:1109
string updateAppFirmwareFilename
Definition: cltool.h:52
int streamGPS
Definition: cltool.h:73
int cltool_main(int argc, char *argv[])
int streamDThetaVel
Definition: cltool.h:81
int streamSysSensors
Definition: cltool.h:80
survey_in_t surveyIn
Definition: cltool.h:59
int streamRtkPos
Definition: cltool.h:74
uint64_t rmcPreset
Definition: cltool.h:64
double lla[3]
Definition: data_sets.h:511
int streamMag1
Definition: cltool.h:77
static bool cltool_setupCommunications(InertialSense &inertialSenseInterface)
string comPort
Definition: cltool.h:51
int displayMode
Definition: cltool.h:62
p_data_hdr_t hdr
Definition: ISComm.h:388
int streamDualIMU
Definition: cltool.h:70
sys_sensors_t sysSensors
Definition: data_sets.h:3428
#define DID_MAGNETOMETER_1
Definition: data_sets.h:86
int streamBaro
Definition: cltool.h:79
USBInterfaceDescriptor data
bool BroadcastBinaryData(uint32_t dataId, int periodMultiple, pfnHandleBinaryData callback=NULL)
string flashConfig
Definition: cltool.h:97
#define DID_GPS1_POS
Definition: data_sets.h:47
int serialPortPlatformInit(serial_port_t *serialPort)
float theta[3]
Definition: data_sets.h:505
#define DID_SYS_SENSORS
Definition: data_sets.h:45
#define DID_INS_3
Definition: data_sets.h:99
uint32_t magRecalMode
Definition: cltool.h:58
eDisplayMode GetDisplayMode()
Definition: ISDisplay.h:44
bool Open(const char *port, int baudRate=IS_COM_BAUDRATE_DEFAULT, bool disableBroadcastsOnClose=false)
#define snprintf
Definition: test_suite.cpp:86
barometer_t baro
Definition: data_sets.h:3414
int streamINS4
Definition: cltool.h:69
serial_port_t * GetSerialPort(int pHandle=0)
static void cltool_dataCallback(InertialSense *i, p_data_t *data, int pHandle)
#define DID_GPS1_RTK_POS
Definition: data_sets.h:88
#define DID_GPS1_RTK_POS_REL
Definition: data_sets.h:55
int streamINS3
Definition: cltool.h:68
uint32_t timeoutFlushLoggerSeconds
Definition: cltool.h:99
bool replayDataLog
Definition: cltool.h:55
static bool output_server_bytes(InertialSense *i, const char *prefix="", const char *suffix="")
Definition: cltool_main.cpp:38
string host
Definition: cltool.h:95
static int inertialSenseMain()
void cltool_outputHelp()
Definition: cltool.cpp:529
#define DID_INS_4
Definition: data_sets.h:100
static int cltool_createHost()
#define DID_BAROMETER
Definition: data_sets.h:87
string serverConnection
Definition: cltool.h:94
#define DID_RTOS_INFO
Definition: data_sets.h:72
int streamMag2
Definition: cltool.h:78
void BroadcastBinaryDataRmcPreset(uint64_t rmcPreset=RMC_PRESET_INS_BITS, uint32_t rmcOptions=0)
dual_imu_t dualImu
Definition: data_sets.h:3411
int streamINS1
Definition: cltool.h:66
#define DID_SENSORS_ADC
Definition: data_sets.h:62


inertial_sense_ros
Author(s):
autogenerated on Sat Sep 19 2020 03:19:04