Main MRPT website > C++ reference for MRPT 1.9.9
CRoboPeakLidar.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "hwdrivers-precomp.h" // Precompiled headers
11 
13 #include <mrpt/comms/CSerialPort.h>
15 #include <mrpt/system/os.h>
16 
18 
19 #if MRPT_HAS_ROBOPEAK_LIDAR
20 #include "rplidar.h" // RPLidar API
21 using namespace rp::standalone::rplidar;
22 #define RPLIDAR_DRV static_cast<RPlidarDriver*>(m_rplidar_drv)
23 #endif
24 
25 using namespace mrpt::utils;
26 using namespace mrpt::obs;
27 using namespace mrpt::hwdrivers;
28 using namespace mrpt::system;
29 using namespace mrpt::opengl;
30 using namespace std;
31 
32 /*-------------------------------------------------------------
33  Constructor
34 -------------------------------------------------------------*/
35 CRoboPeakLidar::CRoboPeakLidar()
36  : m_com_port(""), m_com_port_baudrate(115200), m_rplidar_drv(nullptr)
37 {
38  m_sensorLabel = "RPLidar";
39 }
40 
41 /*-------------------------------------------------------------
42  ~CRoboPeakLidar
43 -------------------------------------------------------------*/
45 {
46  turnOff();
47  disconnect();
48 }
49 
51 {
52 #if MRPT_HAS_ROBOPEAK_LIDAR
53  RPlidarDriver::DisposeDriver(RPLIDAR_DRV);
54  m_rplidar_drv = nullptr;
55 #endif
56 }
57 
58 /*-------------------------------------------------------------
59  doProcessSimple
60 -------------------------------------------------------------*/
62  bool& outThereIsObservation,
63  mrpt::obs::CObservation2DRangeScan& outObservation, bool& hardwareError)
64 {
65 #if MRPT_HAS_ROBOPEAK_LIDAR
66  outThereIsObservation = false;
67  hardwareError = false;
68 
69  // Bound?
70  if (!checkCOMMs())
71  {
72  hardwareError = true;
73  return;
74  }
75 
76  rplidar_response_measurement_node_t nodes[360 * 2];
77  size_t count = sizeof(nodes) / sizeof(nodes[0]);
78 
79  // Scan:
80  const mrpt::system::TTimeStamp tim_scan_start = mrpt::system::now();
81  u_result op_result = RPLIDAR_DRV->grabScanData(nodes, count);
82  // const mrpt::system::TTimeStamp tim_scan_end = mrpt::system::now();
83  // const double scan_duration =
84  // mrpt::system::timeDifference(tim_scan_start,tim_scan_end);
85 
86  // Fill in scan data:
87  if (op_result == RESULT_OK)
88  {
89  op_result = RPLIDAR_DRV->ascendScanData(nodes, count);
90  if (op_result == RESULT_OK)
91  {
92  const size_t angle_compensate_nodes_count = 360;
93  const size_t angle_compensate_multiple = 1;
94  int angle_compensate_offset = 0;
95  rplidar_response_measurement_node_t
96  angle_compensate_nodes[angle_compensate_nodes_count];
97  memset(
98  angle_compensate_nodes, 0,
99  angle_compensate_nodes_count *
100  sizeof(rplidar_response_measurement_node_t));
101 
102  outObservation.resizeScanAndAssign(
103  angle_compensate_nodes_count, 0, false);
104 
105  for (size_t i = 0; i < count; i++)
106  {
107  if (nodes[i].distance_q2 != 0)
108  {
109  float angle =
110  (float)((nodes[i].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT) / 64.0f);
111  int angle_value = (int)(angle * angle_compensate_multiple);
112  if ((angle_value - angle_compensate_offset) < 0)
113  angle_compensate_offset = angle_value;
114  for (size_t j = 0; j < angle_compensate_multiple; j++)
115  {
116  angle_compensate_nodes[angle_value -
117  angle_compensate_offset + j] =
118  nodes[i];
119  }
120  }
121  }
122 
123  for (size_t i = 0; i < angle_compensate_nodes_count; i++)
124  {
125  const float read_value =
126  (float)angle_compensate_nodes[i].distance_q2 / 4.0f / 1000;
127  outObservation.setScanRange(i, read_value);
128  outObservation.setScanRangeValidity(i, (read_value > 0));
129  }
130  }
131  else if (op_result == RESULT_OPERATION_FAIL)
132  {
133  // All the data is invalid, just publish them
134  outObservation.resizeScanAndAssign(count, 0, false);
135  }
136 
137  // Fill common parts of the obs:
138  outObservation.timestamp = tim_scan_start;
139  outObservation.rightToLeft = false;
140  outObservation.aperture = 2 * M_PIf;
141  outObservation.maxRange = 6.0;
142  outObservation.stdError = 0.010f;
143  outObservation.sensorPose = m_sensorPose;
144  outObservation.sensorLabel = m_sensorLabel;
145 
146  // Do filter:
149  // Do show preview:
151 
152  outThereIsObservation = true;
153  }
154  else
155  {
156  if (op_result == RESULT_OPERATION_TIMEOUT ||
157  op_result == RESULT_OPERATION_FAIL)
158  {
159  // Error? Retry connection
160  this->disconnect();
161  }
162  }
163 
164 #endif
165 }
166 
167 /*-------------------------------------------------------------
168  loadConfig_sensorSpecific
169 -------------------------------------------------------------*/
171  const mrpt::utils::CConfigFileBase& configSource,
172  const std::string& iniSection)
173 {
175  configSource.read_float(iniSection, "pose_x", 0),
176  configSource.read_float(iniSection, "pose_y", 0),
177  configSource.read_float(iniSection, "pose_z", 0),
178  DEG2RAD(configSource.read_float(iniSection, "pose_yaw", 0)),
179  DEG2RAD(configSource.read_float(iniSection, "pose_pitch", 0)),
180  DEG2RAD(configSource.read_float(iniSection, "pose_roll", 0)));
181 
182 #ifdef MRPT_OS_WINDOWS
183  m_com_port =
184  configSource.read_string(iniSection, "COM_port_WIN", m_com_port, true);
185 #else
186  m_com_port =
187  configSource.read_string(iniSection, "COM_port_LIN", m_com_port, true);
188 #endif
189 
190  // Parent options:
191  this->loadCommonParams(configSource, iniSection);
192 }
193 
194 /*-------------------------------------------------------------
195  turnOn
196 -------------------------------------------------------------*/
198 {
199 #if MRPT_HAS_ROBOPEAK_LIDAR
200  bool ret = checkCOMMs();
201  if (ret && RPLIDAR_DRV) RPLIDAR_DRV->startMotor();
202  return ret;
203 #else
204  THROW_EXCEPTION("MRPT has been compiled without RPLidar support!")
205 #endif
206 }
207 
208 /*-------------------------------------------------------------
209  turnOff
210 -------------------------------------------------------------*/
212 {
213 #if MRPT_HAS_ROBOPEAK_LIDAR
214  if (RPLIDAR_DRV)
215  {
216  RPLIDAR_DRV->stop();
217  RPLIDAR_DRV->stopMotor();
218  }
219  return true;
220 #else
221  THROW_EXCEPTION("MRPT has been compiled without RPLidar support!")
222 #endif
223 }
224 
225 /** Returns true if the device is connected & operative */
227 {
228 #if MRPT_HAS_ROBOPEAK_LIDAR
229  if (!RPLIDAR_DRV) return false;
230 
231  rplidar_response_device_health_t healthinfo;
232 
233  u_result op_result = RPLIDAR_DRV->getHealth(healthinfo);
234  if (IS_OK(op_result))
235  {
236  printf(
237  "[CRoboPeakLidar] RPLidar health status : %d\n", healthinfo.status);
238  if (healthinfo.status != RPLIDAR_STATUS_OK)
239  {
240  fprintf(
241  stderr,
242  "[CRoboPeakLidar] Error, rplidar internal error detected. "
243  "Please reboot the device to retry.\n");
244  return false;
245  }
246  }
247  else
248  {
249  fprintf(
250  stderr,
251  "[CRoboPeakLidar] Error, cannot retrieve rplidar health code: %x\n",
252  op_result);
253  return false;
254  }
255 
256  return true;
257 #else
258  THROW_EXCEPTION("MRPT has been compiled without RPLidar support!")
259 #endif
260 }
261 
262 /*-------------------------------------------------------------
263  checkCOMMs
264 -------------------------------------------------------------*/
266 {
267  MRPT_START
268 #if MRPT_HAS_ROBOPEAK_LIDAR
269  if (RPLIDAR_DRV) return true;
270 
271  // create the driver instance
272  m_rplidar_drv =
273  RPlidarDriver::CreateDriver(RPlidarDriver::DRIVER_TYPE_SERIALPORT);
274  ASSERTMSG_(m_rplidar_drv, "Create Driver failed.")
275 
276  // Is it COMX, X>4? -> "\\.\COMX"
277  if (m_com_port.size() >= 3)
278  {
279  if (tolower(m_com_port[0]) == 'c' && tolower(m_com_port[1]) == 'o' &&
280  tolower(m_com_port[2]) == 'm')
281  {
282  // Need to add "\\.\"?
283  if (m_com_port.size() > 4 || m_com_port[3] > '4')
284  m_com_port = std::string("\\\\.\\") + m_com_port;
285  }
286  }
287 
288  // make connection...
289  if (IS_FAIL(
290  RPLIDAR_DRV->connect(
291  m_com_port.c_str(), (_u32)m_com_port_baudrate)))
292  {
293  fprintf(
294  stderr,
295  "[CRoboPeakLidar] Error, cannot bind to the specified serial port "
296  "%s\n",
297  m_com_port.c_str());
298  return false;
299  }
300 
301  rplidar_response_device_info_t devinfo;
302  if (IS_FAIL(RPLIDAR_DRV->getDeviceInfo(devinfo)))
303  {
304  return false;
305  }
306 
307  if (m_verbose)
308  {
309  printf(
310  "[CRoboPeakLidar] Connection established:\n"
311  "Firmware version: %u\n"
312  "Hardware version: %u\n"
313  "Model: %u\n"
314  "Serial: ",
315  (unsigned int)devinfo.firmware_version,
316  (unsigned int)devinfo.hardware_version,
317  (unsigned int)devinfo.model);
318 
319  for (int i = 0; i < 16; i++) printf("%02X", devinfo.serialnum[i]);
320  printf("\n");
321  }
322 
323  // check health:
324  if (!getDeviceHealth()) return false;
325 
326  // start scan...
327  u_result res = RPLIDAR_DRV->startScan();
328  if (IS_FAIL(res))
329  {
330  fprintf(
331  stderr, "[CRoboPeakLidar] Error starting scanning mode: %x\n", res);
332  return false;
333  }
334 
335  return true;
336 #else
337  THROW_EXCEPTION("MRPT has been compiled without RPLidar support!")
338 #endif
339  MRPT_END
340 }
341 
342 /*-------------------------------------------------------------
343  initialize
344 -------------------------------------------------------------*/
346 {
347  if (!checkCOMMs())
348  throw std::runtime_error(
349  "[CRoboPeakLidar::initialize] Error initializing RPLIDAR scanner.");
350  if (!turnOn())
351  throw std::runtime_error(
352  "[CRoboPeakLidar::initialize] Error initializing RPLIDAR scanner.");
353 }
354 
356 {
357  if (m_rplidar_drv)
358  THROW_EXCEPTION("Can't change serial port while connected!")
359 
360  m_com_port = port_name;
361 }
uint64_t TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1...
Definition: datetime.h:32
GLuint GLuint GLsizei count
Definition: glext.h:3528
virtual void initialize()
Attempts to connect and turns the laser on.
#define IS_OK(x)
Definition: rptypes.h:108
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
void setSerialPort(const std::string &port_name)
If set to non-empty, the serial port will be attempted to be opened automatically when this class is ...
#define RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT
Definition: rplidar_cmd.h:113
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
Definition: math_frwds.h:30
float read_float(const std::string &section, const std::string &name, float defaultValue, bool failIfNotFound=false) const
_u16 angle_q6_checkbit
Definition: rplidar_cmd.h:21
void setScanRange(const size_t i, const float val)
std::string m_sensorLabel
See CGenericSensor.
void disconnect()
Closes the comms with the laser.
#define THROW_EXCEPTION(msg)
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Definition: datetime.h:76
Contains classes for various device interfaces.
virtual void doProcessSimple(bool &outThereIsObservation, mrpt::obs::CObservation2DRangeScan &outObservation, bool &hardwareError)
Specific laser scanner "software drivers" must process here new data from the I/O stream...
bool getDeviceHealth() const
Returns true if the device is connected & operative.
std::string read_string(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
STL namespace.
void filterByExclusionAreas(mrpt::obs::CObservation2DRangeScan &obs) const
Mark as invalid those points which (x,y) coordinates fall within the exclusion polygons.
#define RESULT_OK
Definition: rptypes.h:97
float stdError
The "sigma" error of the device in meters, used while inserting the scan in an occupancy grid...
void filterByExclusionAngles(mrpt::obs::CObservation2DRangeScan &obs) const
Mark as invalid those ranges in a set of forbiden angle ranges.
This class allows loading and storing values and vectors of different types from a configuration text...
float maxRange
The maximum range allowed by the device, in meters (e.g.
#define IS_FAIL(x)
Definition: rptypes.h:109
#define M_PIf
void loadConfig_sensorSpecific(const mrpt::utils::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
#define MRPT_END
This namespace contains representation of robot actions and observations.
Interfaces a Robo Peak LIDAR laser scanner.
#define DEG2RAD
void resizeScanAndAssign(const size_t len, const float rangeVal, const bool rangeValidity, const int32_t rangeIntensity=0)
Resizes all data vectors to allocate a given number of scan rays and assign default values...
void loadCommonParams(const mrpt::utils::CConfigFileBase &configSource, const std::string &iniSection)
Should be call by derived classes at "loadConfig" (loads exclusion areas AND exclusion angles)...
GLsizei const GLchar ** string
Definition: glext.h:4101
#define IMPLEMENTS_GENERIC_SENSOR(class_name, NameSpace)
This must be inserted in all CGenericSensor classes implementation files:
#define RESULT_OPERATION_TIMEOUT
Definition: rptypes.h:102
bool checkCOMMs()
Returns true if communication has been established with the device.
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
Definition: os.cpp:405
virtual bool turnOff()
See base class docs.
virtual bool turnOn()
See base class docs.
#define MRPT_START
std::string sensorLabel
An arbitrary label that can be used to identify the sensor.
Definition: CObservation.h:60
_u16 distance_q2
Definition: rplidar_cmd.h:22
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
Definition: CObservation.h:58
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
poses::CPose3D m_sensorPose
The sensor 6D pose:
void setFromValues(const double x0, const double y0, const double z0, const double yaw=0, const double pitch=0, const double roll=0)
Set the pose from a 3D position (meters) and yaw/pitch/roll angles (radians) - This method recomputes...
Definition: CPose3D.cpp:248
uint32_t _u32
Definition: rptypes.h:66
void processPreview(const mrpt::obs::CObservation2DRangeScan &obs)
Must be called inside the capture method to allow optional GUI preview of scans.
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:15
float aperture
The "aperture" or field-of-view of the range finder, in radians (typically M_PI = 180 degrees)...
#define RESULT_OPERATION_FAIL
Definition: rptypes.h:101
GLuint res
Definition: glext.h:7268
#define ASSERTMSG_(f, __ERROR_MSG)
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot at the moment of starting the scan.
virtual ~CRoboPeakLidar()
Destructor: turns the laser off.
bool rightToLeft
The scanning direction: true=counterclockwise; false=clockwise.
uint32_t u_result
Definition: rptypes.h:95
void setScanRangeValidity(const size_t i, const bool val)
#define RPLIDAR_STATUS_OK
Definition: rplidar_cmd.h:106



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019