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 
14 using namespace yarp::os;
15 using namespace yarp::dev;
16 
17 #ifndef DEG2RAD
18 #define DEG2RAD M_PI/180.0
19 #endif
20 
21 YARP_LOG_COMPONENT(LASER_BASE, "yarp.devices.Lidar2DDeviceBase")
22 
23 bool 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 
31 bool 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 
39 bool Lidar2DDeviceBase::getHorizontalResolution(double& step)
40 {
41  std::lock_guard<std::mutex> guard(m_mutex);
42  step = m_resolution;
43  return true;
44 }
45 
46 bool Lidar2DDeviceBase::getDeviceStatus(Device_status& status)
47 {
48  std::lock_guard<std::mutex> guard(m_mutex);
49  status = m_device_status;
50  return true;
51 }
52 
53 bool Lidar2DDeviceBase::getRawData(yarp::sig::Vector& out)
54 {
55  std::lock_guard<std::mutex> guard(m_mutex);
56  out = m_laser_data;
57  return true;
58 }
59 
60 bool Lidar2DDeviceBase::getScanRate(double& rate)
61 {
62  std::lock_guard<std::mutex> guard(m_mutex);
63  rate = m_scan_rate;
64  return true;
65 }
66 
67 bool Lidar2DDeviceBase::getDeviceInfo(std::string& device_info)
68 {
69  std::lock_guard<std::mutex> guard(m_mutex);
70  device_info = m_info;
71  return true;
72 }
73 
74 bool Lidar2DDeviceBase::getLaserMeasurement(std::vector<LaserMeasurementData>& data)
75 {
76  std::lock_guard<std::mutex> guard(m_mutex);
77 #ifdef LASER_DEBUG
78  //yDebug("data: %s\n", laser_data.toString().c_str());
79 #endif
80  size_t size = m_laser_data.size();
81  data.resize(size);
82  if (m_max_angle < m_min_angle) { yCError(LASER_BASE) << "getLaserMeasurement failed"; return false; }
83  double laser_angle_of_view = m_max_angle - m_min_angle;
84  for (size_t i = 0; i < size; i++)
85  {
86  double angle = (i / double(size) * laser_angle_of_view + m_min_angle) * DEG2RAD;
87  data[i].set_polar(m_laser_data[i], angle);
88  }
89  return true;
90 }
91 
92 Lidar2DDeviceBase::Lidar2DDeviceBase() :
93  m_device_status(yarp::dev::IRangefinder2D::Device_status::DEVICE_GENERAL_ERROR),
94  m_scan_rate(0.0),
95  m_sensorsNum(0),
96  m_min_angle(0.0),
97  m_max_angle(0.0),
98  m_min_distance(0.1),
99  m_max_distance(30.0),
100  m_resolution(0.0),
101  m_clip_max_enable(false),
102  m_clip_min_enable(false),
103  m_do_not_clip_and_allow_infinity_enable(true)
104 {}
105 
107 {
108  //sensor options (should be mandatory? TBD)
109  {
110  bool br = config.check("SENSOR");
111  if (br != false)
112  {
113  yarp::os::Searchable& general_config = config.findGroup("SENSOR");
114  if (general_config.check("max_angle")) { m_max_angle = general_config.find("max_angle").asFloat64(); }
115  if (general_config.check("min_angle")) { m_min_angle = general_config.find("min_angle").asFloat64(); }
116  if (general_config.check("resolution")) { m_resolution = general_config.find("resolution").asFloat64(); }
117  m_clip_max_enable = general_config.check("max_distance");
118  m_clip_min_enable = general_config.check("min_distance");
119  if (m_clip_max_enable) { m_max_distance = general_config.find("max_distance").asFloat64(); }
120  if (m_clip_min_enable) { m_min_distance = general_config.find("min_distance").asFloat64(); }
121  m_do_not_clip_and_allow_infinity_enable = (general_config.find("allow_infinity").asInt32() == 1);
122  }
123  else
124  {
125  //yCError(LASER_BASE) << "Missing SENSOR section";
126  //return false;
127  }
128  }
129 
130  //skip options (optional)
131  {
132  bool bs = config.check("SKIP");
133  if (bs == true)
134  {
135  yarp::os::Searchable& skip_config = config.findGroup("SKIP");
136  Bottle mins = skip_config.findGroup("min");
137  Bottle maxs = skip_config.findGroup("max");
138  size_t s_mins = mins.size();
139  size_t s_maxs = mins.size();
140  if (s_mins == s_maxs && s_maxs > 1)
141  {
142  for (size_t s = 1; s < s_maxs; s++)
143  {
144  Range_t range;
145  range.max = maxs.get(s).asFloat64();
146  range.min = mins.get(s).asFloat64();
147  if (range.max >= 0 && range.max <= 360 &&
148  range.min >= 0 && range.min <= 360 &&
149  range.max > range.min)
150  {
151  m_range_skip_vector.push_back(range);
152  }
153  else
154  {
155  yCError(LASER_BASE) << "Invalid range in SKIP section:"<< range.min << range.max;
156  return false;
157  }
158  }
159  }
160  //yCDebug(LASER_BASE) << "Skip section set successfully";
161  }
162  else
163  {
164  //yCDebug(LASER_BASE) << "No Skip section required";
165  }
166  }
167 
168  //checks and allocation
169  if (m_max_distance - m_min_distance <= 0)
170  {
171  yCError(LASER_BASE) << "invalid parameters: max_distance/min_distance";
172  return false;
173  }
174  double fov = (m_max_angle - m_min_angle);
175  if (fov <= 0)
176  {
177  yCError(LASER_BASE) << "invalid parameters: max_angle should be > min_angle";
178  return false;
179  }
180  if (fov > 360)
181  {
182  yCError(LASER_BASE) << "invalid parameters: max_angle - min_angle <= 360";
183  return false;
184  }
185  if (m_resolution <= 0)
186  {
187  yCError(LASER_BASE) << "invalid parameters resolution";
188  return false;
189  }
190  m_sensorsNum = (int)(fov / m_resolution);
192 
193  yCInfo(LASER_BASE) << "Using the following parameters:";
194  yCInfo(LASER_BASE) << "max_dist:" << m_max_distance << " min_dist:" << m_min_distance;
195  yCInfo(LASER_BASE) << "max_angle:" << m_max_angle << " min_angle:" << m_min_angle;
196  yCInfo(LASER_BASE) << "resolution:" << m_resolution;
197  yCInfo(LASER_BASE) << "sensors:" << m_sensorsNum;
198  yCInfo(LASER_BASE) << "allow_infinity:" << (m_do_not_clip_and_allow_infinity_enable ==true);
199  if (m_range_skip_vector.size() >0)
200  {
201  for (size_t i = 0; i < m_range_skip_vector.size(); i++) {
202  yCInfo(LASER_BASE) << "skip area:" << m_range_skip_vector[i].min << "->" << m_range_skip_vector[i].max;
203  }
204  }
205  return true;
206 }
207 
208 //this function checks if the angle is inside the allowed limits
209 //if not, distance value is set to NaN
210 bool Lidar2DDeviceBase::checkSkipAngle(const double& angle, double& distance)
211 {
212  for (auto& it_skip : m_range_skip_vector)
213  {
214  if (angle > it_skip.min&& angle < it_skip.max)
215  {
216  distance = std::nan("");
217  return true;
218  }
219  }
220  return false;
221 }
222 
224 {
225  for (size_t i = 0; i < m_sensorsNum; i++)
226  {
227  double& distance = m_laser_data[i];
228  double angle = i * m_resolution;
229 
230  if (std::isnan(distance)) {
231  continue;
232  }
233  if (checkSkipAngle(angle, distance)) {
234  continue;
235  }
236 
237  if (m_clip_min_enable)
238  {
239  if (distance < m_min_distance)
240  {
241  distance = std::numeric_limits<double>::infinity();
242  //the following means: if we want to clip infinity...
244  {
245  distance = m_min_distance;
246  }
247  }
248  }
249  if (m_clip_max_enable)
250  {
251  if (distance > m_max_distance)
252  {
253  distance = std::numeric_limits<double>::infinity();
254  //the following means: if we want to clip infinity...
256  {
257  distance = m_max_distance;
258  }
259  }
260  }
261  }
262  return true;
263 }
264 
266 {
267  std::lock_guard<std::mutex> guard(m_mutex);
268  return m_timestamp;
269 }
270 
271 
273 {
274  bool b = true;
275  b &= acquireDataFromHW();
276  if (!b) {
277  return false;
278  }
279  b &= applyLimitsOnLaserData();
280  if (!b) {
281  return false;
282  }
283  b &= updateTimestamp();
284  return b;
285 }
286 
288 {
290  return true;
291 }
const yarp::os::LogComponent & LASER_BASE()
#define DEG2RAD
A generic interface for planar laser range finders.
The Lidar2DDeviceBase class.
virtual yarp::os::Stamp getLastInputStamp() override
Return the time stamp relative to the last acquisition.
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.
std::vector< Range_t > m_range_skip_vector
virtual bool updateTimestamp()
By default, it automatically updates the internal timestamp with the yarp time.
bool parseConfiguration(yarp::os::Searchable &config)
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
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:66
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual Bottle & findGroup(const std::string &key) const =0
Gets a list corresponding to a given keyword.
An abstraction for a time stamp and/or sequence number.
Definition: Stamp.h:22
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition: Stamp.cpp:124
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:222
#define yCInfo(component,...)
Definition: LogComponent.h:132
#define yCError(component,...)
Definition: LogComponent.h:154
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:77
An interface for the device drivers.
An interface to the operating system, including Port based communication.
The main, catch-all namespace for YARP.
Definition: dirs.h:16