60 #include "rnr/rnrconfig.h" 95 static const char *ToFName[] =
97 "front",
"left_front",
"left",
"left_rear",
98 "rear",
"right_rear",
"right",
"right_front" 101 static const double ToFDir[] =
120 static const char *Sep = \
121 "----------------------------------------------------------------------------";
126 static int OptsCvtArgMeas(
const char *argv0,
const char *sOptName,
127 char *optarg,
void *pOptVal);
138 "Test and calibrate Laelaps Time-of-Flight sensors.",
141 "The %P command tests and calibrates the Laelaps Time-of-Flight sensors. " 142 "The standard Laelaps comes with 3 forward facing ToFs, with an additional " 143 "5 sensors available as an upgrade option. Sensors are identified by " 144 "the number Id number of symbolic Name.\n" 145 " Id Name Direction Package\n" 146 " -- ----------- --------- -------\n" 147 " 0 front 0 degrees std\n" 148 " 1 left_front 15 degrees std\n" 149 " 2 left 90 degrees opt\n" 150 " 3 left_rear 165 degrees opt\n" 151 " 4 rear 180 degrees opt\n" 152 " 5 right_rear 195 degrees opt\n" 153 " 6 right 270 degrees opt\n" 154 " 7 right_front 345 degrees std\n\n" 155 "The ROS node laelaps_control cannot be running while using this tool.",
177 "Perform range sensor cross-talk compensation calibration " 178 "procedures. After calibration, %P measurements automatically begin." 192 "Perform range sensor part-to-part offset calibration " 193 "procedures. After calibration, %P measurements automatically begin." 207 "Sensor measurement(s). One of:\n range ambient both." 221 "Don't auto-sense at the given millisecond time period. In this mode the " 222 "user must provide keyboard input to control when to sense." 236 "Auto-sense at the given millisecond time period rate." 242 static int OptsCvtArgMeas(
const char *argv0,
const char *sOptName,
243 char *optarg,
void *pOptVal)
246 OptsCvtArgStr(argv0, sOptName, optarg, pOptVal);
250 Measure = MeasTypeDistance;
254 Measure = MeasTypeAmbient;
258 Measure = MeasTypeBoth;
262 OptsInvalid(
Argv0,
"'%s': Invalid '%s' measurement value.",
269 static int tofNameToInt(
const string &str,
int &val)
273 for(i = 0; i < arraysize(ToFName); ++i)
275 if( !strcmp(ToFName[i], str.c_str()) )
285 static int strToInt(
const string &str,
int &val)
289 if( sscanf(str.c_str(),
"%lli", &val1) != 1 )
301 struct termios old = {0};
304 if( tcgetattr(0, &old) < 0 )
309 old.c_lflag &= ~ICANON;
310 old.c_lflag &= ~ECHO;
314 if( tcsetattr(0, TCSANOW, &old) < 0 )
319 if( read(0, &c, 1) < 0 )
324 old.c_lflag |= ICANON;
327 if( tcsetattr(0, TCSADRAIN, &old) < 0 )
338 while( (c = getch()) == 0 );
343 static int connectSensor(
int n)
348 if( I2CBus.
open(LaeDevI2C) < 0 )
350 LOGSYSERROR(
"%s.", LaeDevI2C);
351 return -LAE_ECODE_NO_DEV;
357 ToFSensor =
new LaeVL6180Mux(I2CMux, SensorId, ToFDir[SensorId], 0.0,
362 LOGERROR(
"Sensor %d %s: Failed to initialize.",
363 SensorId, ToFName[SensorId]);
364 return -LAE_ECODE_NO_EXEC;
370 static int readSensorInfo()
374 if( ToFSensor->
readId(
id) < 0 )
376 LOGERROR(
"Failed to read sensor identification.");
377 return -LAE_ECODE_IO;
381 printf(
"VL6180 Sensor Info:\n");
382 printf(
" Name: %s\n", ToFSensor->
getNameId().c_str());
383 printf(
" Desc: %s\n", ToFSensor->
getDesc().c_str());
384 printf(
" Model: 0x%02x v%u.%u\n",
385 id.idModel,
id.idModelRevMajor,
id.idModelRevMinor);
386 printf(
" Module: v%u.%u\n",
id.idModuleRevMajor,
id.idModuleRevMinor);
387 printf(
" Date/Time: %u/%u\n",
id.idDate,
id.idTime);
392 static int calibrateSensorCrossTalk()
404 "Range sensor cross-talk compensation calibration.\n" 405 " Note: Perform range part-to-part offset calibration, " 406 "if required, first.\n\n");
412 printf(
"Calibrate Cross-Talk Compensation\n\n");
414 printf(
"Setup: Place a black target (<= 3%% reflectance) at a distance\n");
415 printf(
" of 100mm from sensor (or front of glass cover if present).\n");
417 printf(
"\nPress any key to when ready ('q' to quit): ");
420 if( (c ==
'q') || (c == EOF) )
422 return -LAE_ECODE_NO_EXEC;
425 printf(
"\n Calibrating...\r");
432 printf(
"Error: Failed to calibrate cross-talk compensation.\n");
433 return -LAE_ECODE_NO_EXEC;
436 printf(
"Cross-Talk Calibration Summary:\n");
437 printf(
" Cross-Talk\n");
438 printf(
" Post-Calib: %3d\n", nCrossTalk);
439 printf(
" Note: Cross-talk compensation is stored in volatile register\n" 440 " SYSRANGE_CROSSTALK_COMPENSATION_RATE (0x%04x)\n" 441 " Tune parameter <tof_crosstalk>\n",
442 VL6180X_SYSRANGE_CROSSTALK_COMPENSATION_RATE);
449 static int calibrateSensorOffset()
461 "Range sensor part-to-part offset calibration.\n\n" );
467 printf(
"Calibrate Part-To-Part Offset\n\n");
469 printf(
"Setup: Place a white target (>= 88%% reflectance) at a distance\n");
470 printf(
" of 50mm from sensor (or front of glass cover if present).\n");
472 printf(
"\nPress any key to when ready ('q' to quit): ");
475 if( (c ==
'q') || (c == EOF) )
477 return -LAE_ECODE_NO_EXEC;
480 printf(
"\n Calibrating...\r");
483 rc = ToFSensor->
calibOffset(nOffsetPre, fAvgPre, nOffsetPost, fAvgPost);
487 printf(
"Error: Failed to calibrate offset.\n");
488 return -LAE_ECODE_NO_EXEC;
491 printf(
"Offset Calibration Summary:\n");
492 printf(
" Offset Average\n");
493 printf(
" Pre-Calib: %3d %.3lf\n", nOffsetPre, fAvgPre);
494 printf(
" Post-Calib: %3d %.3lf\n", nOffsetPost, fAvgPost);
495 printf(
" Note: Offset is stored in volatile register\n" 496 " SYSRANGE_PART_TO_PART_RANGE_OFFSET (0x%04x)\n" 497 " Tune parameter <tof_offset>\n",
498 VL6180X_SYSRANGE_PART_TO_PART_RANGE_OFFSET);
504 static void readSensorCalibTuneRegs()
506 byte_t regRangeOffset;
507 u16_t regRangeCrossTalk;
509 u16_t regAlsIntPeriod;
512 regAlsGain, regAlsIntPeriod);
514 printf(
"VL6180 Sensor Calibration/Tuning Register Values:\n");
515 printf(
" Range Offset: %u\n", regRangeOffset);
516 printf(
" Range Cross Talk: %u\n", regRangeCrossTalk);
517 printf(
" ALS Analog Gain: %u\n", regAlsGain);
518 printf(
" ALS Integration Period: %u\n", regAlsIntPeriod);
521 static void printHdr(
int what)
525 case MeasTypeAmbient:
529 printf(
" meters lux\n");
531 case MeasTypeDistance:
538 static void printMeasurement(
int seqnum,
int what,
double fMeters,
double fFlux)
540 printf(
"%7d ", seqnum);
543 if( (what == MeasTypeDistance) || (what == MeasTypeBoth) )
555 printf(
" %6.3lf ", fMeters);
559 if( (what == MeasTypeAmbient) || (what == MeasTypeBoth) )
567 printf(
" %6.1lf ", fMeters);
578 double fMeters = 0.0, fLux = 0.0;
585 printf(
"Press any key to start measurements ('q' to quit): ");
600 for(seqnum=0; ; ++seqnum)
604 case MeasTypeAmbient:
606 printMeasurement(seqnum, Measure, 0.0, fLux);
611 printMeasurement(seqnum, Measure, fMeters, fLux);
613 case MeasTypeDistance:
616 printMeasurement(seqnum, Measure, fMeters, 0.0);
623 if( (c ==
'q') || (c == EOF) )
653 Argv0 = basename(argv[0]);
660 fprintf(stderr,
"%s: No sensor number <N> specified.\n",
Argv0);
661 fprintf(stderr,
"Try '%s --help' for more information.\n",
Argv0);
664 else if( strToInt(argv[0], SensorId) < 0 )
666 if( tofNameToInt(argv[0], SensorId) < 0 )
668 fprintf(stderr,
"%s: '%s': Bad sensor Id/Name.\n",
Argv0, argv[0]);
669 fprintf(stderr,
"Try '%s --help' for more information.\n",
Argv0);
673 else if( (SensorId < ToFSensor0Chan) || (SensorId > ToFSensor7Chan) )
675 fprintf(stderr,
"%s: %d: Sensor number out of range.\n",
Argv0, SensorId);
676 fprintf(stderr,
"Try '%s --help' for more information.\n",
Argv0);
689 int main(
int argc,
char* argv[])
695 if( connectSensor(SensorId) < 0 )
704 calibrateSensorOffset();
709 calibrateSensorCrossTalk();
712 readSensorCalibTuneRegs();
int main(int argc, char *argv[])
Main.
#define VL6180X_RANGE_MAX
maximum range (m)
static char * Argv0
the command
double degToRad(double d)
Convert degrees to radians.
static void mainInit(int argc, char *argv[])
Main initialization.
static char * OptsMeasure
measure range
Laelaps PCA9548A I2C multiplexer switch interface.
#define APP_EC_OK
success exit code
VL6180 Time of Flight Class.
int calibCrossTalk(int &nCrossTalk)
Calibrate cross-talk compensation.
Laelaps I2C class interface.
int calibOffset(int &nOffsetPre, double &fAvgPre, int &nOffsetPost, double &fAvgPost)
Calibrate part-to-part offset.
Laelaps Time-of-Flight sensors. The ToFs are used as a virtual bumper for close-in obstacle detection...
int initSensor(bool bForce=false)
Initialize sensor with recommended settings and defaults.
virtual int open(const std::string &strDevName)
Open I2C bus device.
#define APP_EC_EXEC
execution exit code
static int OptsTimePeriod
sense time period (msec)
The <b><i>Laelaps</i></b> namespace encapsulates all <b><i>Laelaps</i></b> related constructs...
int readId(struct VL6180xIdentification &id)
Read sensor identification.
static const PkgInfo_T PkgInfo
void readShadowRegs()
Read shadows register values and update derived data.
std::string getDesc()
Get sensor short description.
Laelaps common utilities.
std::string getNameId()
Get sensor assigned name id.
static bool_t OptsNoAuto
don't auto-run
#define APP_EC_ARGS
command-line options/arguments error exit code
Package version information.
static OptsPgmInfo_T PgmInfo
Program information.
static bool_t OptsCalibXTalk
do [not] calibrate range crosstalk
#define VL6180X_ERR_MEAS
error meassurement
static OptsInfo_T OptsInfo[]
Command line options information.
virtual int close()
Close I2C bus device.
double measureRange(u32_t msecWait=0xffff)
Measure the sensed target range.
static bool_t OptsCalibOffset
do [not] calibrate range offset
double measureAmbientLight(u32_t msecWait=0xffff)
Measure the sensed ambient light illuminance.
Top-level package include file.