YARP
Yet Another Robot Platform
Lidar2DDeviceBase.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#define _USE_MATH_DEFINES
7
9#include <yarp/os/LogStream.h>
10#include <mutex>
11#include <limits>
12#include <cmath>
13
14using namespace yarp::os;
15using namespace yarp::dev;
16
17#ifndef DEG2RAD
18#define DEG2RAD M_PI/180.0
19#endif
20
21YARP_LOG_COMPONENT(LASER_BASE, "yarp.devices.Lidar2DDeviceBase")
22
23bool Lidar2DDeviceBase::getScanLimits(double& min, double& max)
24{
25 std::lock_guard<std::mutex> guard(m_mutex);
26 min = m_min_angle;
27 max = m_max_angle;
28 return true;
29}
30
31bool Lidar2DDeviceBase::getDistanceRange(double& min, double& max)
32{
33 std::lock_guard<std::mutex> guard(m_mutex);
34 min = m_min_distance;
35 max = m_max_distance;
36 return true;
37}
38
40{
41 std::lock_guard<std::mutex> guard(m_mutex);
42 step = m_resolution;
43 return true;
44}
45
47{
48 std::lock_guard<std::mutex> guard(m_mutex);
49 status = m_device_status;
50 return true;
51}
52
54{
55 std::lock_guard<std::mutex> guard(m_mutex);
56 out = m_laser_data;
57 if (timestamp != nullptr)
58 {
59 *timestamp = m_timestamp.getTime();
60 }
61 return true;
62}
63
65{
66 std::lock_guard<std::mutex> guard(m_mutex);
67 rate = m_scan_rate;
68 return true;
69}
70
71bool Lidar2DDeviceBase::getDeviceInfo(std::string& device_info)
72{
73 std::lock_guard<std::mutex> guard(m_mutex);
74 device_info = m_info;
75 return true;
76}
77
78bool Lidar2DDeviceBase::getLaserMeasurement(std::vector<LaserMeasurementData>& data, double* timestamp)
79{
80 std::lock_guard<std::mutex> guard(m_mutex);
81#ifdef LASER_DEBUG
82 //yDebug("data: %s\n", laser_data.toString().c_str());
83#endif
84 size_t size = m_laser_data.size();
85 data.resize(size);
86 if (m_max_angle < m_min_angle) { yCError(LASER_BASE) << "getLaserMeasurement failed"; return false; }
87 double laser_angle_of_view = m_max_angle - m_min_angle;
88 for (size_t i = 0; i < size; i++)
89 {
90 double angle = (i / double(size) * laser_angle_of_view + m_min_angle) * DEG2RAD;
91 data[i].set_polar(m_laser_data[i], angle);
92 }
93 if (timestamp!=nullptr)
94 {
95 *timestamp = m_timestamp.getTime();
96 }
97 return true;
98}
99
101 m_device_status(yarp::dev::IRangefinder2D::Device_status::DEVICE_GENERAL_ERROR),
102 m_scan_rate(0.0),
103 m_sensorsNum(0),
104 m_min_angle(0.0),
105 m_max_angle(0.0),
106 m_min_distance(0.1),
107 m_max_distance(30.0),
108 m_resolution(0.0),
109 m_clip_max_enable(false),
110 m_clip_min_enable(false),
111 m_do_not_clip_and_allow_infinity_enable(true)
112{}
113
115{
116 //sensor options (should be mandatory? TBD)
117 {
118 bool br = config.check("SENSOR");
119 if (br != false)
120 {
121 yarp::os::Searchable& general_config = config.findGroup("SENSOR");
122 if (general_config.check("max_angle")) { m_max_angle = general_config.find("max_angle").asFloat64(); }
123 if (general_config.check("min_angle")) { m_min_angle = general_config.find("min_angle").asFloat64(); }
124 if (general_config.check("resolution")) { m_resolution = general_config.find("resolution").asFloat64(); }
125 m_clip_max_enable = general_config.check("max_distance");
126 m_clip_min_enable = general_config.check("min_distance");
127 if (m_clip_max_enable) { m_max_distance = general_config.find("max_distance").asFloat64(); }
128 if (m_clip_min_enable) { m_min_distance = general_config.find("min_distance").asFloat64(); }
129 m_do_not_clip_and_allow_infinity_enable = (general_config.find("allow_infinity").asInt32() == 1);
130 }
131 else
132 {
133 //yCError(LASER_BASE) << "Missing SENSOR section";
134 //return false;
135 }
136 }
137
138 //skip options (optional)
139 {
140 bool bs = config.check("SKIP");
141 if (bs == true)
142 {
143 yarp::os::Searchable& skip_config = config.findGroup("SKIP");
144 Bottle mins = skip_config.findGroup("min");
145 Bottle maxs = skip_config.findGroup("max");
146 size_t s_mins = mins.size();
147 size_t s_maxs = mins.size();
148 if (s_mins == s_maxs && s_maxs > 1)
149 {
150 for (size_t s = 1; s < s_maxs; s++)
151 {
152 Range_t range;
153 range.max = maxs.get(s).asFloat64();
154 range.min = mins.get(s).asFloat64();
155 if (range.max >= 0 && range.max <= 360 &&
156 range.min >= 0 && range.min <= 360 &&
157 range.max > range.min)
158 {
159 m_range_skip_vector.push_back(range);
160 }
161 else
162 {
163 yCError(LASER_BASE) << "Invalid range in SKIP section:"<< range.min << range.max;
164 return false;
165 }
166 }
167 }
168 //yCDebug(LASER_BASE) << "Skip section set successfully";
169 }
170 else
171 {
172 //yCDebug(LASER_BASE) << "No Skip section required";
173 }
174 }
175
176 //checks and allocation
178 {
179 yCError(LASER_BASE) << "invalid parameters: max_distance/min_distance";
180 return false;
181 }
182 double fov = (m_max_angle - m_min_angle);
183 if (fov <= 0)
184 {
185 yCError(LASER_BASE) << "invalid parameters: max_angle should be > min_angle";
186 return false;
187 }
188 if (fov > 360)
189 {
190 yCError(LASER_BASE) << "invalid parameters: max_angle - min_angle <= 360";
191 return false;
192 }
193 if (m_resolution <= 0)
194 {
195 yCError(LASER_BASE) << "invalid parameters resolution";
196 return false;
197 }
198 m_sensorsNum = (int)(fov / m_resolution);
200
201 yCInfo(LASER_BASE) << "Using the following parameters:";
202 yCInfo(LASER_BASE) << "max_dist:" << m_max_distance << " min_dist:" << m_min_distance;
203 yCInfo(LASER_BASE) << "max_angle:" << m_max_angle << " min_angle:" << m_min_angle;
204 yCInfo(LASER_BASE) << "resolution:" << m_resolution;
205 yCInfo(LASER_BASE) << "sensors:" << m_sensorsNum;
206 yCInfo(LASER_BASE) << "allow_infinity:" << (m_do_not_clip_and_allow_infinity_enable ==true);
207 if (m_range_skip_vector.size() >0)
208 {
209 for (size_t i = 0; i < m_range_skip_vector.size(); i++) {
210 yCInfo(LASER_BASE) << "skip area:" << m_range_skip_vector[i].min << "->" << m_range_skip_vector[i].max;
211 }
212 }
213 return true;
214}
215
216//this function checks if the angle is inside the allowed limits
217//if not, distance value is set to NaN
218bool Lidar2DDeviceBase::checkSkipAngle(const double& angle, double& distance)
219{
220 for (auto& it_skip : m_range_skip_vector)
221 {
222 if (angle > it_skip.min&& angle < it_skip.max)
223 {
224 distance = std::nan("");
225 return true;
226 }
227 }
228 return false;
229}
230
232{
233 for (size_t i = 0; i < m_sensorsNum; i++)
234 {
235 double& distance = m_laser_data[i];
236 double angle = i * m_resolution;
237
238 if (std::isnan(distance)) {
239 continue;
240 }
241 if (checkSkipAngle(angle, distance)) {
242 continue;
243 }
244
246 {
247 if (distance < m_min_distance)
248 {
249 distance = std::numeric_limits<double>::infinity();
250 //the following means: if we want to clip infinity...
252 {
253 distance = m_min_distance;
254 }
255 }
256 }
258 {
259 if (distance > m_max_distance)
260 {
261 distance = std::numeric_limits<double>::infinity();
262 //the following means: if we want to clip infinity...
264 {
265 distance = m_max_distance;
266 }
267 }
268 }
269 }
270 return true;
271}
272
274{
275 bool b = true;
276 b &= acquireDataFromHW();
277 if (!b) {
278 return false;
279 }
281 if (!b) {
282 return false;
283 }
284 b &= updateTimestamp();
285 return b;
286}
287
289{
291 return true;
292}
const yarp::os::LogComponent & LASER_BASE()
#define DEG2RAD
A generic interface for planar laser range finders.
The Lidar2DDeviceBase class.
bool getDeviceStatus(Device_status &status) override
get the device status
bool getScanRate(double &rate) override
get the scan rate (scans per seconds)
bool getRawData(yarp::sig::Vector &data, double *timestamp=nullptr) override
Get the device measurements.
virtual bool updateLidarData()
This utility method calls in sequence: grabDataFromHW(), updateTimestamp and applyLimitsOnLaserData()...
virtual bool acquireDataFromHW()=0
This method should be implemented by the user, and contain the logic to grab data from the hardware.
virtual bool applyLimitsOnLaserData()
Apply the limits on the internally stored lidar measurements.
bool getDeviceInfo(std::string &device_info) override
get the device hardware characteristics
std::vector< Range_t > m_range_skip_vector
yarp::dev::IRangefinder2D::Device_status m_device_status
virtual bool updateTimestamp()
By default, it automatically updates the internal timestamp with the yarp time.
bool getHorizontalResolution(double &step) override
get the angular step between two measurements.
bool parseConfiguration(yarp::os::Searchable &config)
bool getLaserMeasurement(std::vector< LaserMeasurementData > &data, double *timestamp=nullptr) override
Get the device measurements.
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:64
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:251
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
A base class for nested structures that can be searched.
Definition: Searchable.h:63
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
virtual Bottle & findGroup(const std::string &key) const =0
Gets a list corresponding to a given keyword.
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition: Stamp.cpp:124
double getTime() const
Get the time stamp.
Definition: Stamp.cpp:34
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:222
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:204
void resize(size_t size) override
Resize the vector.
Definition: Vector.h:220
size_t size() const
Definition: Vector.h:321
#define yCInfo(component,...)
Definition: LogComponent.h:171
#define yCError(component,...)
Definition: LogComponent.h:213
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:76
For streams capable of holding different kinds of content, check what they actually have.
An interface to the operating system, including Port based communication.
The main, catch-all namespace for YARP.
Definition: dirs.h:16