ImuConfigUtility.cc
Go to the documentation of this file.
1 
37 #ifdef WIN32
38 #ifndef WIN32_LEAN_AND_MEAN
39 #define WIN32_LEAN_AND_MEAN 1
40 #endif
41 
42 #include <windows.h>
43 #include <winsock2.h>
44 #else
45 #include <unistd.h>
46 #endif
47 
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <errno.h>
52 #include <iostream>
53 #include <iomanip>
54 
56 
58 
59 #ifdef WIN32
60 #define strcasecmp _stricmp
61 #endif
62 
63 using namespace crl::multisense;
64 
65 namespace { // anonymous
66 
67 std::vector<imu::Info> sensor_infos;
68 std::vector<imu::Config> sensor_configs;
69 uint32_t sensor_samplesPerMessage = 0;
70 uint32_t sensor_maxSamplesPerMessage = 0;
71 
72 void usage(const char *programNameP)
73 {
74  std::cerr << "USAGE: " << programNameP << " [<options>]" << std::endl;
75  std::cerr << "Where <options> are:" << std::endl;
76  std::cerr << "\t-a <ip_address> : IPV4 address (default=10.66.171.21)" << std::endl;
77  std::cerr << "\t-q : query and report IMU configuration" << std::endl;
78  std::cerr << "\t-f : store IMU configuration in non-volatile flash" << std::endl;
79  std::cerr << "\t-s <samples> : set IMU samples-per-message" << std::endl;
80  std::cerr << "\t-c \"<sensor_config>\" : IMU sensor configuration string\n" << std::endl;
81  std::cerr << "And \"<sensor_config>\" is of the following form:" << std::endl;
82  std::cerr << "\t\"<sensor_name> <enabled> <rate_table_index> <range_table_index>\"\n" << std::endl;
83  std::cerr << "For example, to enable the accelerometer, and have it use rate index 1 and range index 2:\n" << std::endl;
84  std::cerr << "\t-c \"accelerometer true 1 2\"\n" << std::endl;
85  std::cerr << "Multiple \"-c\" options may be specified to configure more than 1 sensor\n" << std::endl;
86  std::cerr << "Please note that small values for samples-per-message combined with high IMU sensor rates" << std::endl;
87  std::cerr << "may interfere with the acquisition and transmission of image and lidar data, if applicable" << std::endl;
88 
89  exit(-1);
90 }
91 
92 bool imuInfoByName(const std::string& name, imu::Info& info)
93 {
94  std::vector<imu::Info>::const_iterator it = sensor_infos.begin();
95 
96  for(; it != sensor_infos.end(); ++it)
97  if (name == (*it).name) {
98  info = (*it);
99  return true;
100  }
101 
102  return false;
103 }
104 
105 }; // anonymous
106 
107 int main(int argc,
108  char **argvPP)
109 {
110  std::string currentAddress = "10.66.171.21";
111  int32_t user_samplesPerMessage = 0;
112  bool query = false;
113  bool storeInFlash = false;
114  std::vector<std::string> cli_configs;
115  Status status;
116 
117  //
118  // Parse args
119 
120  int c;
121 
122  while(-1 != (c = getopt(argc, argvPP, "a:s:c:qf")))
123  switch(c) {
124  case 'a': currentAddress = std::string(optarg); break;
125  case 's': user_samplesPerMessage = atoi(optarg); break;
126  case 'q': query = true; break;
127  case 'f': storeInFlash = true; break;
128  case 'c': cli_configs.push_back(optarg); break;
129  default: usage(*argvPP); break;
130  }
131 
132  //
133  // A setting of zero here tells the firmware to leave it alone, useful
134  // if you do not want to change the default.
135 
136  if (user_samplesPerMessage < 0) {
137  std::cerr << "Invalid samples-per-message: " << user_samplesPerMessage << std::endl;
138  exit(-2);
139  }
140 
141  //
142  // If no setting changes are requested, perform a query
143 
144  if (0 == cli_configs.size() && 0 == user_samplesPerMessage)
145  query = true;
146 
147  //
148  // Initialize communications.
149 
150  Channel *channelP = Channel::Create(currentAddress);
151  if (NULL == channelP) {
152  std::cerr << "Failed to establish communications with \"" << currentAddress << "\"" << std::endl;
153  return -1;
154  }
155 
156  //
157  // Query firmware version
158 
160 
161  status = channelP->getVersionInfo(v);
162  if (Status_Ok != status) {
163  std::cerr << "Failed to query sensor version: " << Channel::statusString(status) << std::endl;
164  goto clean_out;
165  }
166 
167  if (query) {
168  std::cout << "Version information:\n";
169  std::cout << "\tAPI build date : " << v.apiBuildDate << "\n";
170  std::cout << "\tAPI version : 0x" << std::hex << std::setw(4) << std::setfill('0') << v.apiVersion << "\n";
171  std::cout << "\tFirmware build date : " << v.sensorFirmwareBuildDate << "\n";
172  std::cout << "\tFirmware version : 0x" << std::hex << std::setw(4) << std::setfill('0') << v.sensorFirmwareVersion << "\n";
173  std::cout << "\tHardware version : 0x" << std::hex << v.sensorHardwareVersion << "\n";
174  std::cout << "\tHardware magic : 0x" << std::hex << v.sensorHardwareMagic << "\n";
175  std::cout << "\tFPGA DNA : 0x" << std::hex << v.sensorFpgaDna << "\n";
176  std::cout << std::dec;
177  }
178 
179  //
180  // Make sure firmware supports IMU
181 
182  if (v.sensorFirmwareVersion <= 0x0202) {
183  std::cerr << "IMU support requires sensor firmware version v2.3 or greater, sensor is " <<
184  "running v" << (v.sensorFirmwareVersion >> 8) << "." << (v.sensorFirmwareVersion & 0xff) << std::endl;
185  goto clean_out;
186  }
187 
188  //
189  // Query IMU info / configuration
190 
191  status = channelP->getImuInfo(sensor_maxSamplesPerMessage,
192  sensor_infos);
193  if (Status_Ok != status) {
194  std::cerr << "Failed to query imu info: " << Channel::statusString(status) << std::endl;
195  goto clean_out;
196  }
197  status = channelP->getImuConfig(sensor_samplesPerMessage, sensor_configs);
198  if (Status_Ok != status) {
199  std::cerr << "Failed to query imu config: " << Channel::statusString(status) << std::endl;
200  goto clean_out;
201  }
202 
203  if (query) {
204  std::cout << "\nMax IMU samples-per-message: " << sensor_maxSamplesPerMessage << "\n";
205  std::cout << sensor_infos.size () << " IMU sensors:\n";
206  for(uint32_t i=0; i<sensor_infos.size(); i++) {
207 
208  const imu::Info& m = sensor_infos[i];
209 
210  std::cout << "\t" << m.name << ":\n";
211  std::cout << "\t\tdevice: " << m.device << "\n";
212  std::cout << "\t\tunits : " << m.units << "\n";
213  std::cout << "\t\trates : " << m.rates.size() << ": rate (Hz), bandwidthCutoff (Hz)\n";
214  for (uint32_t j = 0; j < m.rates.size(); j++)
215  std::cout << "\t\t\t\t" << j << ": " << std::fixed << std::setprecision(1) << m.rates[j].sampleRate << "," <<
216  std::fixed << std::setprecision(3) << m.rates[j].bandwidthCutoff << "\n";
217  std::cout << "\t\tranges: " << m.ranges.size() << ": range (+/- " << m.units << "), resolution (" << m.units << ")\n";
218  for (uint32_t j = 0; j < m.ranges.size(); j++)
219  std::cout << "\t\t\t\t" << j << ": " << std::fixed << std::setprecision(1) << m.ranges[j].range << ", " <<
220  std::fixed << std::setprecision(6) << m.ranges[j].resolution << "\n";
221  }
222 
223  std::cout << "\nCurrent IMU configuration:\n";
224  std::cout << "\t-s " << sensor_samplesPerMessage << " ";
225  for(uint32_t i=0; i<sensor_configs.size(); i++) {
226 
227  const imu::Config& c = sensor_configs[i];
228 
229  std::cout << "-c \"" << c.name << " " << (c.enabled ? "true" : "false") << " " <<
230  c.rateTableIndex << " " << c.rangeTableIndex << "\" ";
231  }
232  std::cout << "\n";
233  }
234 
235  //
236  // Send current configuration
237 
238  if (user_samplesPerMessage > 0 || cli_configs.size() > 0) {
239 
240  std::vector<imu::Config> user_configs;
241  bool configValid = true;
242 
243  if (user_samplesPerMessage > static_cast<int32_t>(sensor_maxSamplesPerMessage)) {
244  std::cerr << "Invalid samples-per-message " << user_samplesPerMessage << ", valid values are in [1," << sensor_maxSamplesPerMessage << "]" << std::endl;
245  configValid = false;
246  }
247 
248  //
249  // Validate each command line config option against IMU information from the head
250 
251  for(uint32_t i=0; i<cli_configs.size(); i++) {
252 
253  char nameP[32] = {0};
254  char enabledP[32] = {0};
255  int rate = -1;
256  int range = -1;
257 
258  if (4 != sscanf(cli_configs[i].c_str(), "%31s %31s %d %d",
259  nameP, enabledP, &rate, &range)) {
260  std::cerr << "Malformed IMU config: \"" << cli_configs[i] << "\"" << std::endl;
261  configValid = false;
262  continue; // keep parsing for maximum feedback
263  }
264 
265  if (0 != strcasecmp(enabledP, "true") &&
266  0 != strcasecmp(enabledP, "false")) {
267  std::cerr << "Malformed <enabled> string \"" << enabledP << "\", must be one of \"true\" or \"false\"" << std::endl;
268  configValid = false;
269  continue;
270  }
271 
272  //
273  // Find the IMU information for this name
274 
275  imu::Info info;
276  if (false == imuInfoByName(nameP, info)) {
277  std::cerr << "Unknown <sensor_name> \"" << nameP << "\", query config for a list of valid names" << std::endl;
278  configValid = false;
279  continue;
280  }
281 
282  //
283  // Validate the rate/range indices
284 
285  if (rate < 0 || rate >= static_cast<int32_t>(info.rates.size())) {
286  std::cerr << "Invalid rate table index " << rate << " for \"" << nameP << "\", valid indices are in [0," << (info.rates.size() - 1) << "]" << std::endl;
287  configValid = false;
288  }
289  if (range < 0 || range >= static_cast<int32_t>(info.ranges.size())) {
290  std::cerr << "Invalid range table index " << range << " for \"" << nameP << "\", " <<
291  "valid indices are in [0," << (info.ranges.size() - 1) << "]" << std::endl;
292  configValid = false;
293  }
294 
295  if (false == configValid)
296  continue;
297 
298  //
299  // We have a valid config, store it
300 
301  imu::Config c;
302  c.name = std::string(nameP);
303  c.enabled = (0 == strcasecmp(enabledP, "true"));
304  c.rateTableIndex = rate;
305  c.rangeTableIndex = range;
306 
307  user_configs.push_back(c);
308  }
309 
310  if (false == configValid)
311  std::cerr << "Errors exist in configuration, aborting" << std::endl;
312  else {
313  status = channelP->setImuConfig(storeInFlash,
314  user_samplesPerMessage,
315  user_configs); // can be empty
316  if (Status_Ok != status)
317  std::cerr << "Failed to set IMU configuration: " << Channel::statusString(status) << std::endl;
318  else
319  std::cout << "IMU configuration updated successfully\n";
320  }
321  }
322 
323 clean_out:
324 
325  Channel::Destroy(channelP);
326  return 0;
327 }
std::vector< RangeEntry > ranges
static const char * statusString(Status status)
Definition: channel.cc:609
static Channel * Create(const std::string &sensorAddress)
Definition: channel.cc:583
virtual Status getVersionInfo(system::VersionInfo &v)=0
virtual Status getImuConfig(uint32_t &samplesPerMessage, std::vector< imu::Config > &c)=0
int getopt(int argc, char **argv, char *opts)
Definition: getopt.c:34
virtual Status setImuConfig(bool storeSettingsInFlash, uint32_t samplesPerMessage, const std::vector< imu::Config > &c)=0
std::vector< RateEntry > rates
static CRL_CONSTEXPR Status Status_Ok
def usage(progname)
static void Destroy(Channel *instanceP)
Definition: channel.cc:596
char * optarg
Definition: getopt.c:32
int main(int argc, char **argvPP)
virtual Status getImuInfo(uint32_t &maxSamplesPerMesage, std::vector< imu::Info > &info)=0


multisense_lib
Author(s):
autogenerated on Sat Apr 6 2019 02:16:46