YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
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;
16using namespace yarp::sig;
17
18#ifndef DEG2RAD
19#define DEG2RAD M_PI/180.0
20#endif
21
22YARP_LOG_COMPONENT(LASER_BASE, "yarp.devices.Lidar2DDeviceBase")
23
24bool Lidar2DDeviceBase::getScanLimits(double& min, double& max)
25{
26 std::lock_guard<std::mutex> guard(m_mutex);
27 min = m_min_angle;
28 max = m_max_angle;
29 return true;
30}
31
32bool Lidar2DDeviceBase::getDistanceRange(double& min, double& max)
33{
34 std::lock_guard<std::mutex> guard(m_mutex);
35 min = m_min_distance;
36 max = m_max_distance;
37 return true;
38}
39
41{
42 std::lock_guard<std::mutex> guard(m_mutex);
43 step = m_resolution;
44 return true;
45}
46
48{
49 std::lock_guard<std::mutex> guard(m_mutex);
50 status = m_device_status;
51 return true;
52}
53
55{
56 std::lock_guard<std::mutex> guard(m_mutex);
57 out = m_laser_data;
58 if (timestamp != nullptr)
59 {
60 *timestamp = m_timestamp.getTime();
61 }
62 return true;
63}
64
66{
67 std::lock_guard<std::mutex> guard(m_mutex);
68 rate = m_scan_rate;
69 return true;
70}
71
72bool Lidar2DDeviceBase::getDeviceInfo(std::string& device_info)
73{
74 std::lock_guard<std::mutex> guard(m_mutex);
75 device_info = m_info;
76 return true;
77}
78
79bool Lidar2DDeviceBase::getLaserMeasurement(std::vector<LaserMeasurementData>& data, double* timestamp)
80{
81 std::lock_guard<std::mutex> guard(m_mutex);
82#ifdef LASER_DEBUG
83 //yDebug("data: %s\n", laser_data.toString().c_str());
84#endif
85 size_t size = m_laser_data.size();
86 data.resize(size);
87 if (m_max_angle < m_min_angle) { yCError(LASER_BASE) << "getLaserMeasurement failed"; return false; }
89 for (size_t i = 0; i < size; i++)
90 {
91 double angle = (i / double(size) * laser_angle_of_view + m_min_angle) * DEG2RAD;
92 data[i].set_polar(m_laser_data[i], angle);
93 }
94 if (timestamp!=nullptr)
95 {
96 *timestamp = m_timestamp.getTime();
97 }
98 return true;
99}
100
102 m_device_status(yarp::dev::IRangefinder2D::Device_status::DEVICE_GENERAL_ERROR),
103 m_scan_rate(0.0),
104 m_sensorsNum(0),
105 m_min_angle(0.0),
106 m_max_angle(0.0),
107 m_min_distance(0.1),
108 m_max_distance(30.0),
109 m_resolution(0.0),
110 m_clip_max_enable(false),
111 m_clip_min_enable(false),
112 m_do_not_clip_and_allow_infinity_enable(true)
113{}
114
116{
117 std::string config_str = config.toString();
118
119 //sensor options (should be mandatory? TBD)
120 {
121 bool br = config.check("SENSOR");
122 if (br != false)
123 {
125 if (general_config.check("max_angle")) { m_max_angle = general_config.find("max_angle").asFloat64(); }
126 if (general_config.check("min_angle")) { m_min_angle = general_config.find("min_angle").asFloat64(); }
127 if (general_config.check("resolution")) { m_resolution = general_config.find("resolution").asFloat64(); }
128 m_clip_max_enable = general_config.check("max_distance");
129 m_clip_min_enable = general_config.check("min_distance");
130 if (m_clip_max_enable) { m_max_distance = general_config.find("max_distance").asFloat64(); }
131 if (m_clip_min_enable) { m_min_distance = general_config.find("min_distance").asFloat64(); }
132 m_do_not_clip_and_allow_infinity_enable = (general_config.find("allow_infinity").asInt32() == 1);
133 }
134 else
135 {
136 //yCError(LASER_BASE) << "Missing SENSOR section";
137 //return false;
138 }
139 }
140
141 //skip options (optional)
142 {
143 bool bs = config.check("SKIP");
144 if (bs == true)
145 {
147 Bottle mins = skip_config.findGroup("min");
148 Bottle maxs = skip_config.findGroup("max");
149 size_t s_mins = mins.size();
150 size_t s_maxs = mins.size();
151 if (s_mins == s_maxs && s_maxs > 1)
152 {
153 for (size_t s = 1; s < s_maxs; s++)
154 {
156 range.max = maxs.get(s).asFloat64();
157 range.min = mins.get(s).asFloat64();
158 if (range.max >= 0 && range.max <= 360 &&
159 range.min >= 0 && range.min <= 360 &&
160 range.max > range.min)
161 {
162 m_range_skip_vector.push_back(range);
163 }
164 else
165 {
166 yCError(LASER_BASE) << "Invalid range in SKIP section:"<< range.min << range.max;
167 return false;
168 }
169 }
170 }
171 //yCDebug(LASER_BASE) << "Skip section set successfully";
172 }
173 else
174 {
175 //yCDebug(LASER_BASE) << "No Skip section required";
176 }
177 }
178
179 //checks and allocation
181 {
182 yCError(LASER_BASE) << "invalid parameters: max_distance/min_distance";
183 return false;
184 }
185 double fov = (m_max_angle - m_min_angle);
186 if (fov <= 0)
187 {
188 yCError(LASER_BASE) << "invalid parameters: max_angle should be > min_angle";
189 return false;
190 }
191 if (fov > 360)
192 {
193 yCError(LASER_BASE) << "invalid parameters: max_angle - min_angle <= 360";
194 return false;
195 }
196 if (m_resolution <= 0)
197 {
198 yCError(LASER_BASE) << "invalid parameters resolution";
199 return false;
200 }
201 m_sensorsNum = (int)(fov / m_resolution);
203
204 yCInfo(LASER_BASE) << "Using the following parameters:";
205 yCInfo(LASER_BASE) << "max_dist:" << m_max_distance << " min_dist:" << m_min_distance;
206 yCInfo(LASER_BASE) << "max_angle:" << m_max_angle << " min_angle:" << m_min_angle;
207 yCInfo(LASER_BASE) << "resolution:" << m_resolution;
208 yCInfo(LASER_BASE) << "sensors:" << m_sensorsNum;
209 yCInfo(LASER_BASE) << "allow_infinity:" << (m_do_not_clip_and_allow_infinity_enable ==true);
210 if (m_range_skip_vector.size() >0)
211 {
212 for (size_t i = 0; i < m_range_skip_vector.size(); i++) {
213 yCInfo(LASER_BASE) << "skip area:" << m_range_skip_vector[i].min << "->" << m_range_skip_vector[i].max;
214 }
215 }
216 return true;
217}
218
219//this function checks if the angle is inside the allowed limits
220//if not, distance value is set to NaN
221bool Lidar2DDeviceBase::checkSkipAngle(const double& angle, double& distance)
222{
223 for (auto& it_skip : m_range_skip_vector)
224 {
225 if (angle > it_skip.min&& angle < it_skip.max)
226 {
227 distance = std::nan("");
228 return true;
229 }
230 }
231 return false;
232}
233
235{
236 for (size_t i = 0; i < m_sensorsNum; i++)
237 {
238 double& distance = m_laser_data[i];
239 double angle = i * m_resolution;
240
241 if (std::isnan(distance)) {
242 continue;
243 }
244 if (checkSkipAngle(angle, distance)) {
245 continue;
246 }
247
249 {
251 {
252 distance = std::numeric_limits<double>::infinity();
253 //the following means: if we want to clip infinity...
255 {
257 }
258 }
259 }
261 {
263 {
264 distance = std::numeric_limits<double>::infinity();
265 //the following means: if we want to clip infinity...
267 {
269 }
270 }
271 }
272 }
273 return true;
274}
275
277{
278 bool b = true;
279 b &= acquireDataFromHW();
280 if (!b) {
281 return false;
282 }
284 if (!b) {
285 return false;
286 }
287 b &= updateTimestamp();
288 return b;
289}
290
292{
294 return true;
295}
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 getLaserMeasurement(std::vector< yarp::sig::LaserMeasurementData > &data, double *timestamp=nullptr) override
Get the device 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 getDistanceRange(double &min, double &max) override
get the device detection range
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:64
A mini-server for performing network communication in the background.
A base class for nested structures that can be searched.
Definition Searchable.h:31
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
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
void resize(size_t size) override
Resize the vector.
Definition Vector.h:221
size_t size() const
Definition Vector.h:341
#define yCInfo(component,...)
#define yCError(component,...)
#define YARP_LOG_COMPONENT(name,...)
For streams capable of holding different kinds of content, check what they actually have.
Definition jointData.cpp:13
An interface to the operating system, including Port based communication.
The main, catch-all namespace for YARP.
Definition dirs.h:16