189 lines
7.3 KiB
C++
189 lines
7.3 KiB
C++
#include "rideheight_sensing/rideheight_sensing.h"
|
|
|
|
#include <optional>
|
|
|
|
#include "vl53l0x_api.h"
|
|
#include "vl53l0x_i2c_comms.h"
|
|
#include "vl6180x_api.h"
|
|
#include "vl6180x_glue.h"
|
|
|
|
#include <ros/assert.h>
|
|
#include <sensor_msgs/Range.h>
|
|
|
|
namespace rh_sensing {
|
|
RideheightSensing::RideheightSensing(ros::NodeHandle nh,
|
|
ros::NodeHandle nh_private)
|
|
: nh{nh}, nh_private{nh_private},
|
|
vl6180x_pub{nh.advertise<sensor_msgs::Range>("vl6180x", 10)},
|
|
vl53l0x_pub{nh.advertise<sensor_msgs::Range>("vl53l0x", 10)} {
|
|
// init_6180("/dev/i2c-8");
|
|
init_53l0("/dev/i2c-8");
|
|
}
|
|
|
|
void RideheightSensing::spin() {
|
|
sensor_msgs::Range vl6180x_msg, vl53l0x_msg;
|
|
vl6180x_msg.radiation_type = vl53l0x_msg.radiation_type =
|
|
sensor_msgs::Range::INFRARED;
|
|
vl6180x_msg.field_of_view = vl53l0x_msg.field_of_view = 25.0f / 180 * M_PI;
|
|
vl6180x_msg.min_range = 0.005f;
|
|
vl6180x_msg.max_range = 0.1f;
|
|
vl53l0x_msg.min_range = 0.05f;
|
|
vl53l0x_msg.max_range = 1.0f;
|
|
|
|
ros::Rate loop_rate(20);
|
|
std::optional<ros::Time> first_signal_fail = std::nullopt;
|
|
while (ros::ok()) {
|
|
// VL6180x_RangePollMeasurement(vl6180x_dev, &vl6180x_range);
|
|
// if (vl6180x_range.errorStatus == 0) {
|
|
// vl6180x_msg.header.stamp = ros::Time::now();
|
|
// vl6180x_msg.range = vl6180x_range.range_mm / 1000.0f;
|
|
// vl6180x_pub.publish(vl6180x_msg);
|
|
// } else {
|
|
// ROS_WARN("VL6180X Ranging error: %s",
|
|
// VL6180x_RangeGetStatusErrString(vl6180x_range.errorStatus));
|
|
// }
|
|
VL53L0X_Error status =
|
|
VL53L0X_PerformSingleRangingMeasurement(&vl53l0x_dev, &vl53l0x_range);
|
|
if (status != VL53L0X_ERROR_NONE) {
|
|
char str[512];
|
|
ROS_ASSERT(VL53L0X_GetDeviceErrorString(status, str) ==
|
|
VL53L0X_ERROR_NONE);
|
|
ROS_WARN("VL53L0X Ranging error: %s", str);
|
|
} else if (vl53l0x_range.RangeStatus != 0) {
|
|
if (!vl53l0x_long_range && vl53l0x_range.RangeStatus == 2) {
|
|
// Signal fail
|
|
if (first_signal_fail.has_value()) {
|
|
if (ros::Time::now() - *first_signal_fail > ros::Duration(1)) {
|
|
ROS_WARN("VL53L0X signal has failed for more than 1s, switching to "
|
|
"long range mode");
|
|
config_53l0(true);
|
|
}
|
|
} else {
|
|
first_signal_fail = ros::Time::now();
|
|
}
|
|
} else {
|
|
char str[512];
|
|
ROS_ASSERT(
|
|
VL53L0X_GetRangeStatusString(vl53l0x_range.RangeStatus, str) == 0);
|
|
ROS_WARN("VL53L0X Ranging status: %s", str);
|
|
}
|
|
} else {
|
|
first_signal_fail = std::nullopt;
|
|
|
|
vl53l0x_msg.header.stamp = ros::Time::now();
|
|
vl53l0x_msg.range = vl53l0x_range.RangeMilliMeter / 1000.0f;
|
|
vl53l0x_pub.publish(vl53l0x_msg);
|
|
}
|
|
ros::spinOnce();
|
|
loop_rate.sleep();
|
|
}
|
|
}
|
|
|
|
void RideheightSensing::init_6180(const char *i2c_dev_path) {
|
|
VL6180x_glue_init(i2c_dev_path);
|
|
VL6180x_InitData(vl6180x_dev);
|
|
VL6180x_Prepare(vl6180x_dev);
|
|
}
|
|
|
|
void RideheightSensing::init_53l0(const char *i2c_dev_path) {
|
|
VL53L0X_i2c_init(i2c_dev_path, &vl53l0x_dev);
|
|
|
|
// Adapted from Adafruit's VL53L0X library
|
|
VL53L0X_Error status = VL53L0X_DataInit(&vl53l0x_dev);
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE, "Error in DataInit: %d", status);
|
|
|
|
VL53L0X_DeviceInfo_t device_info;
|
|
status = VL53L0X_GetDeviceInfo(&vl53l0x_dev, &device_info);
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE, "Error in GetDeviceInfo: %d",
|
|
status);
|
|
ROS_INFO("[VL53L0X] Device Name: %s, Type: %s, ID: %s", device_info.Name,
|
|
device_info.Type, device_info.ProductId);
|
|
ROS_INFO("[VL53L0X] Rev: %u.%u", device_info.ProductRevisionMajor,
|
|
device_info.ProductRevisionMinor);
|
|
|
|
status = VL53L0X_StaticInit(&vl53l0x_dev);
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE, "Error in StaticInit: %d",
|
|
status);
|
|
|
|
uint32_t ref_spad_count;
|
|
uint8_t is_aperture_spads;
|
|
status = VL53L0X_PerformRefSpadManagement(&vl53l0x_dev, &ref_spad_count,
|
|
&is_aperture_spads);
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE,
|
|
"Error in PerformRefSpadManagement: %d", status);
|
|
ROS_INFO("Ref spad count: %u, is aperture spads: %u", ref_spad_count,
|
|
is_aperture_spads);
|
|
|
|
uint8_t vhv_settings, phase_cal;
|
|
status =
|
|
VL53L0X_PerformRefCalibration(&vl53l0x_dev, &vhv_settings, &phase_cal);
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE,
|
|
"Error in PerformRefCalibration: %d", status);
|
|
|
|
status =
|
|
VL53L0X_SetDeviceMode(&vl53l0x_dev, VL53L0X_DEVICEMODE_SINGLE_RANGING);
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE, "Error in SetDeviceMode: %d",
|
|
status);
|
|
|
|
// Enable/Disable Sigma and Signal check
|
|
status = VL53L0X_SetLimitCheckEnable(
|
|
&vl53l0x_dev, VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 1);
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE,
|
|
"Error in SetLimitCheckEnable: %d", status);
|
|
|
|
status = VL53L0X_SetLimitCheckEnable(
|
|
&vl53l0x_dev, VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 1);
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE,
|
|
"Error in SetLimitCheckEnable: %d", status);
|
|
|
|
config_53l0(false);
|
|
}
|
|
|
|
void RideheightSensing::config_53l0(bool long_range) {
|
|
this->vl53l0x_long_range = long_range;
|
|
if (long_range) {
|
|
VL53L0X_Error status = VL53L0X_SetLimitCheckEnable(
|
|
&vl53l0x_dev, VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 0);
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE,
|
|
"Error in SetLimitCheckEnable: %d", status);
|
|
|
|
status = VL53L0X_SetLimitCheckValue(
|
|
&vl53l0x_dev, VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
|
|
(FixPoint1616_t)(0.1 * 65536));
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE,
|
|
"Error in SetLimitCheckValue: %d", status);
|
|
status = VL53L0X_SetLimitCheckValue(&vl53l0x_dev,
|
|
VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE,
|
|
(FixPoint1616_t)(60 * 65536));
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE,
|
|
"Error in SetLimitCheckValue: %d", status);
|
|
status =
|
|
VL53L0X_SetMeasurementTimingBudgetMicroSeconds(&vl53l0x_dev, 33000);
|
|
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE,
|
|
"Error in SetMeasurementTimingBudgetMicroSeconds: %d",
|
|
status);
|
|
status = VL53L0X_SetVcselPulsePeriod(&vl53l0x_dev,
|
|
VL53L0X_VCSEL_PERIOD_PRE_RANGE, 18);
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE,
|
|
"Error in SetVcselPulsePeriod: %d", status);
|
|
status = VL53L0X_SetVcselPulsePeriod(&vl53l0x_dev,
|
|
VL53L0X_VCSEL_PERIOD_FINAL_RANGE, 14);
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE,
|
|
"Error in SetVcselPulsePeriod: %d", status);
|
|
} else {
|
|
VL53L0X_Error status = VL53L0X_SetLimitCheckEnable(
|
|
&vl53l0x_dev, VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 1);
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE,
|
|
"Error in SetLimitCheckEnable: %d", status);
|
|
|
|
status = VL53L0X_SetLimitCheckValue(
|
|
&vl53l0x_dev, VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
|
|
(FixPoint1616_t)(1.5 * 0.023 * 65536));
|
|
ROS_ASSERT_MSG(status == VL53L0X_ERROR_NONE,
|
|
"Error in SetLimitCheckEnable: %d", status);
|
|
}
|
|
}
|
|
|
|
} // namespace rh_sensing
|