vl53l1x.cpp
Go to the documentation of this file.
1 /*
2  * STM VL53L1X ToF rangefinder driver for ROS
3  *
4  * Author: Oleg Kalachev <okalachev@gmail.com>
5  *
6  * Distributed under BSD 3-Clause License (available at https://opensource.org/licenses/BSD-3-Clause).
7  *
8  * Documentation used:
9  * VL53L1X datasheet - https://www.st.com/resource/en/datasheet/vl53l1x.pdf
10  * VL53L1X API user manual - https://www.st.com/content/ccc/resource/technical/document/user_manual/group0/98/0d/38/38/5d/84/49/1f/DM00474730/files/DM00474730.pdf/jcr:content/translations/en.DM00474730.pdf
11  *
12  */
13 
14 #include <string>
15 #include <vector>
16 #include <ros/ros.h>
17 #include <sensor_msgs/Range.h>
18 #include <vl53l1x/MeasurementData.h>
19 
20 #include "vl53l1_api.h"
21 #include "i2c.h"
22 
23 #define xSTR(x) #x
24 #define STR(x) xSTR(x)
25 
26 #define CHECK_STATUS(func) { \
27  VL53L1_Error status = func; \
28  if (status != VL53L1_ERROR_NONE) { \
29  ROS_WARN("VL53L1X: Error %d on %s", status, STR(func)); \
30  } \
31 }
32 
33 int main(int argc, char **argv)
34 {
35  ros::init(argc, argv, "vl53l1x");
36  ros::NodeHandle nh, nh_priv("~");
37 
38  sensor_msgs::Range range;
39  vl53l1x::MeasurementData data;
40  range.radiation_type = sensor_msgs::Range::INFRARED;
41  ros::Publisher range_pub = nh_priv.advertise<sensor_msgs::Range>("range", 20);
42  ros::Publisher data_pub = nh_priv.advertise<vl53l1x::MeasurementData>("data", 20);
43 
44  // Read parameters
45  int mode, i2c_bus, i2c_address;
46  double poll_rate, timing_budget, offset;
47  bool ignore_range_status;
48  std::vector<int> pass_statuses { VL53L1_RANGESTATUS_RANGE_VALID,
51 
52  nh_priv.param("mode", mode, 3);
53  nh_priv.param("i2c_bus", i2c_bus, 1);
54  nh_priv.param("i2c_address", i2c_address, 0x29);
55  nh_priv.param("poll_rate", poll_rate, 100.0);
56  nh_priv.param("ignore_range_status", ignore_range_status, false);
57  nh_priv.param("timing_budget", timing_budget, 0.1);
58  nh_priv.param("offset", offset, 0.0);
59  nh_priv.param<std::string>("frame_id", range.header.frame_id, "");
60  nh_priv.param("field_of_view", range.field_of_view, 0.471239f); // 27 deg, source: datasheet
61  nh_priv.param("min_range", range.min_range, 0.0f);
62  nh_priv.param("max_range", range.max_range, 4.0f);
63  nh_priv.getParam("pass_statuses", pass_statuses);
64 
65  if (timing_budget < 0.02 || timing_budget > 1) {
66  ROS_FATAL("Error: timing_budget should be within 0.02 and 1 s (%g is set)", timing_budget);
67  ros::shutdown();
68  }
69 
70  // The minimum inter-measurement period must be longer than the timing budget + 4 ms (*)
71  double inter_measurement_period = timing_budget + 0.004;
72 
73  // Setup I2C bus
74  i2c_setup(i2c_bus, i2c_address);
75 
76  // Init sensor
77  VL53L1_Dev_t dev;
78  VL53L1_Error dev_error;
81  VL53L1_DataInit(&dev);
82  VL53L1_StaticInit(&dev);
84 
85  // Print device info
86  VL53L1_DeviceInfo_t device_info;
87  CHECK_STATUS(VL53L1_GetDeviceInfo(&dev, &device_info));
88  ROS_INFO("VL53L1X: Device name: %." STR(VL53L1_DEVINFO_STRLEN) "s", device_info.Name);
89  ROS_INFO("VL53L1X: Device type: %." STR(VL53L1_DEVINFO_STRLEN) "s", device_info.Type);
90  ROS_INFO("VL53L1X: Product ID: %." STR(VL53L1_DEVINFO_STRLEN) "s", device_info.ProductId);
91  ROS_INFO("VL53L1X: Type: %u Version: %u.%u", device_info.ProductType,
92  device_info.ProductRevisionMajor, device_info.ProductRevisionMinor);
93 
94  // Setup sensor
96  CHECK_STATUS(VL53L1_SetMeasurementTimingBudgetMicroSeconds(&dev, round(timing_budget * 1e6)));
97 
98  double min_signal;
99  if (nh_priv.getParam("min_signal", min_signal)) {
101  }
102 
103  double max_sigma;
104  if (nh_priv.getParam("max_sigma", max_sigma)) {
106  }
107 
108  // Start sensor
109  for (int i = 0; i < 100; i++) {
110  CHECK_STATUS(VL53L1_SetInterMeasurementPeriodMilliSeconds(&dev, round(inter_measurement_period * 1e3)));
111  dev_error = VL53L1_StartMeasurement(&dev);
112  if (dev_error == VL53L1_ERROR_INVALID_PARAMS) {
113  inter_measurement_period += 0.001; // Increase inter_measurement_period to satisfy condition (*)
114  } else break;
115  }
116 
117  // Check for errors after start
118  if (dev_error != VL53L1_ERROR_NONE) {
119  ROS_FATAL("VL53L1X: Can't start measurement: error %d", dev_error);
120  ros::shutdown();
121  }
122 
123  ROS_INFO("VL53L1X: ranging");
124 
125  VL53L1_RangingMeasurementData_t measurement_data;
126 
127  // Main loop
128  ros::Rate r(poll_rate);
129  while (ros::ok()) {
130  r.sleep();
131  range.header.stamp = ros::Time::now();
132 
133  // Check the data is ready
134  uint8_t data_ready = 0;
135  VL53L1_GetMeasurementDataReady(&dev, &data_ready);
136  if (!data_ready) {
137  continue;
138  }
139 
140  // Read measurement
141  VL53L1_GetRangingMeasurementData(&dev, &measurement_data);
143 
144  // Publish measurement data
145  data.header.stamp = range.header.stamp;
146  data.signal = measurement_data.SignalRateRtnMegaCps / 65536.0;
147  data.ambient = measurement_data.AmbientRateRtnMegaCps / 65536.0;
148  data.effective_spad = measurement_data.EffectiveSpadRtnCount / 256;
149  data.sigma = measurement_data.SigmaMilliMeter / 65536.0 / 1000.0;
150  data.status = measurement_data.RangeStatus;
151  data_pub.publish(data);
152 
153  // Check measurement for validness
154  if (!ignore_range_status &&
155  std::find(pass_statuses.begin(), pass_statuses.end(), measurement_data.RangeStatus) == pass_statuses.end()) {
156  char range_status[VL53L1_MAX_STRING_LENGTH];
157  VL53L1_get_range_status_string(measurement_data.RangeStatus, range_status);
158  ROS_DEBUG("Range measurement status is not valid: %s", range_status);
159  ros::spinOnce();
160  continue;
161  }
162 
163  // Publish measurement
164  range.range = measurement_data.RangeMilliMeter / 1000.0 + offset;
165  range_pub.publish(range);
166 
167  ros::spinOnce();
168  }
169 
170  // Release
171  ROS_INFO("VL53L1X: stop ranging");
173  i2c_release();
174 }
VL53L1_Error VL53L1_StopMeasurement(VL53L1_DEV Dev)
Stop device measurement.
Definition: vl53l1_api.c:1794
char Name[VL53L1_DEVINFO_STRLEN]
Definition: vl53l1_def.h:114
#define ROS_FATAL(...)
Defines the parameters of the Get Device Info Functions.
Definition: vl53l1_def.h:113
char Type[VL53L1_DEVINFO_STRLEN]
Definition: vl53l1_def.h:116
#define VL53L1_RANGESTATUS_RANGE_VALID
Definition: vl53l1_def.h:505
#define STR(x)
Definition: vl53l1x.cpp:24
VL53L1_Error VL53L1_GetMeasurementDataReady(VL53L1_DEV Dev, uint8_t *pMeasurementDataReady)
Return Measurement Data Ready.
Definition: vl53l1_api.c:1910
#define CHECK_STATUS(func)
Definition: vl53l1x.cpp:26
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
int8_t VL53L1_Error
#define VL53L1_CHECKENABLE_SIGMA_FINAL_RANGE
Definition: vl53l1_def.h:201
uint8_t ProductRevisionMinor
Definition: vl53l1_def.h:126
FixPoint1616_t SignalRateRtnMegaCps
Definition: vl53l1_def.h:362
#define VL53L1_MAX_STRING_LENGTH
int main(int argc, char **argv)
Definition: vl53l1x.cpp:33
#define VL53L1_ERROR_NONE
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void publish(const boost::shared_ptr< M > &message) const
VL53L1_Error VL53L1_DataInit(VL53L1_DEV Dev)
One time device initialization.
Definition: vl53l1_api.c:758
VL53L1_Error VL53L1_get_range_status_string(uint8_t RangeStatus, char *pRangeStatusString)
Generates a string for the input device range status code.
VL53L1_Error VL53L1_WaitDeviceBooted(VL53L1_DEV Dev)
Wait for device booted after chip enable (hardware standby) This function can be run only when VL53L1...
Definition: vl53l1_api.c:840
#define VL53L1_RANGESTATUS_RANGE_VALID_NO_WRAP_CHECK_FAIL
Definition: vl53l1_def.h:517
VL53L1_Error VL53L1_SetMeasurementTimingBudgetMicroSeconds(VL53L1_DEV Dev, uint32_t MeasurementTimingBudgetMicroSeconds)
Set Ranging Timing Budget in microseconds.
Definition: vl53l1_api.c:1116
#define ROS_INFO(...)
VL53L1_Error VL53L1_SetPresetMode(VL53L1_DEV Dev, VL53L1_PresetModes PresetMode)
Set a new Preset Mode.
Definition: vl53l1_api.c:968
bool getParam(const std::string &key, std::string &s) const
ROSCPP_DECL bool ok()
VL53L1_Error VL53L1_SetLimitCheckValue(VL53L1_DEV Dev, uint16_t LimitCheckId, FixPoint1616_t LimitCheckValue)
Set a specific limit check value.
Definition: vl53l1_api.c:1486
#define VL53L1_ERROR_INVALID_PARAMS
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void i2c_setup(uint8_t bus, uint8_t addr)
Definition: i2c.cpp:12
VL53L1_Error VL53L1_SetInterMeasurementPeriodMilliSeconds(VL53L1_DEV Dev, uint32_t InterMeasurementPeriodMilliSeconds)
Definition: vl53l1_api.c:1315
bool sleep()
VL53L1_Error VL53L1_software_reset(VL53L1_DEV Dev)
Performs device software reset and then waits for the firmware to finish booting. ...
#define VL53L1_DEVINFO_STRLEN
Definition: vl53l1_def.h:109
#define VL53L1_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE
Definition: vl53l1_def.h:202
VL53L1_Error VL53L1_ClearInterruptAndStartMeasurement(VL53L1_DEV Dev)
Clear the Interrupt flag and start new measurement *.
Definition: vl53l1_api.c:1883
VL53L1_Error VL53L1_StaticInit(VL53L1_DEV Dev)
Do basic device init (and eventually patch loading) This function will change the VL53L1_State from V...
Definition: vl53l1_api.c:811
#define VL53L1_RANGESTATUS_RANGE_VALID_MERGED_PULSE
Definition: vl53l1_def.h:527
VL53L1_Error VL53L1_StartMeasurement(VL53L1_DEV Dev)
Start device measurement.
Definition: vl53l1_api.c:1732
Single Range measurement data.
Definition: vl53l1_def.h:348
static Time now()
#define VL53L1_PRESETMODE_AUTONOMOUS
Definition: vl53l1_def.h:138
VL53L1_Error VL53L1_GetDeviceInfo(VL53L1_DEV Dev, VL53L1_DeviceInfo_t *pVL53L1_DeviceInfo)
Reads the Device information for given Device.
Definition: vl53l1_api.c:648
ROSCPP_DECL void shutdown()
void i2c_release()
Definition: i2c.cpp:31
uint8_t ProductRevisionMajor
Definition: vl53l1_def.h:124
VL53L1_Error VL53L1_SetDistanceMode(VL53L1_DEV Dev, VL53L1_DistanceModes DistanceMode)
Set the distance mode.
Definition: vl53l1_api.c:1022
ROSCPP_DECL void spinOnce()
VL53L1_Error VL53L1_GetRangingMeasurementData(VL53L1_DEV Dev, VL53L1_RangingMeasurementData_t *pRangingMeasurementData)
Retrieve the measurements from device for a given setup.
Definition: vl53l1_api.c:2159
FixPoint1616_t AmbientRateRtnMegaCps
Definition: vl53l1_def.h:368
unsigned char uint8_t
Typedef defining 8 bit unsigned char type. The developer should modify this to suit the platform bein...
Definition: vl53l1_types.h:133
#define ROS_DEBUG(...)
char ProductId[VL53L1_DEVINFO_STRLEN]
Definition: vl53l1_def.h:118


vl53l1x
Author(s):
autogenerated on Sat Dec 10 2022 03:15:50