Go to the documentation of this file.
23 #define RET_ERROR(msg) \
25 cout << "[" << __CURRENT_FUNCTION_NAME__ << "] " << msg << endl; \
38 int CSickLaserSerial::CRC16_GEN_POL = 0x8005;
43 CSickLaserSerial::CSickLaserSerial()
48 m_mySerialPort(nullptr),
49 m_com_baudRate(38400),
52 m_skip_laser_config(false)
88 bool & outThereIsObservation,
91 outThereIsObservation =
false ;
92 hardwareError =
false ;
100 vector<float> ranges;
101 unsigned char LMS_stat;
123 outObservation.
maxRange = is_mm_mode ? 32.7 : 81.0;
129 for (
size_t i = 0; i < ranges.size(); i++)
133 i, (outObservation.
scan [i] <= outObservation.
maxRange ));
142 outThereIsObservation =
true ;
153 configSource.
read_float (iniSection,
"pose_x" , 0),
154 configSource.
read_float (iniSection,
"pose_y" , 0),
155 configSource.
read_float (iniSection,
"pose_z" , 0),
199 if (err_msg) *err_msg =
"" ;
214 throw std::logic_error(
215 "ERROR: No serial port attached with bindIO, neither it "
216 "set with 'setSerialPort'" );
221 bool just_open =
false ;
240 if (!just_open)
return true ;
252 for (
int nTry = 0; nTry < 4; nTry++)
255 if (!
res )
return false ;
257 for (
int nTry = 0; nTry < 4; nTry++)
268 catch (std::exception& e)
270 std::string s =
"[CSickLaserSerial] Error trying to open SICK at port " ;
272 if (err_msg) *err_msg =
s ;
282 vector<float>& out_ranges_meters,
unsigned char & LMS_status,
286 ASSERTMSG_ (COM !=
nullptr ,
"No I/O channel bound to this object" );
288 size_t nRead, nBytesToRead;
289 size_t nFrameBytes = 0;
291 unsigned char buf[2000];
292 buf[2] = buf[3] = buf[4] = 0;
294 while (nFrameBytes < (lengthField = (6 + (buf[2] | (buf[3] << 8)))))
296 if (lengthField > 800)
306 nBytesToRead = (lengthField)-nFrameBytes;
310 nRead = COM->
Read (buf + nFrameBytes, nBytesToRead);
312 catch (std::exception& e)
316 "[CSickLaserSerial::waitContinuousSampleFrame] Disconnecting "
317 "due to comms error: %s\n" ,
323 if (!nRead && !nFrameBytes)
return false ;
325 if (nRead < nBytesToRead) std::this_thread::sleep_for(1ms);
329 if (nFrameBytes > 1 || (!nFrameBytes && buf[0] == 0x02) ||
330 (nFrameBytes == 1 && buf[1] == 0x80))
332 nFrameBytes += nRead;
351 if (buf[4] != 0xB0)
return false ;
354 int info = buf[5] | (buf[6] << 8);
355 int n_points = info & 0x01FF;
356 is_mm_mode = 0 != ((info & 0xC000) >> 14);
358 out_ranges_meters.resize(n_points);
361 short mask = is_mm_mode ? 0x7FFF : 0x1FFF;
362 float meters_scale = is_mm_mode ? 0.001f : 0.01f;
364 for (
int i = 0; i < n_points; i++)
365 out_ranges_meters[i] =
366 ((buf[7 + i * 2] | (buf[8 + i * 2] << 8)) &
mask ) * meters_scale;
369 LMS_status = buf[lengthField - 3];
374 uint16_t CRC_packet = buf[lengthField - 2] | (buf[lengthField - 1] << 8);
375 if (CRC_packet != CRC)
378 "[CSickLaserSerial::waitContinuousSampleFrame] bad CRC "
379 "len=%u nptns=%u: %i != %i" ,
380 unsigned (lengthField),
unsigned (n_points), CRC_packet, CRC)
398 cerr << err_str << endl;
399 throw std::logic_error(err_str);
414 if (COM ==
nullptr )
return true ;
416 int detected_rate = 0;
421 int rates[] = {0, 9600, 38400, 500000};
430 !detected_rate && i <
sizeof (rates) /
sizeof (rates[0]); i++)
437 "[CSickLaserSerial] Testing if the scanner is "
438 "set to %i bauds...\n" ,
442 std::this_thread::sleep_for(100ms);
445 for (
int nTry = 0; nTry < 4 && !detected_rate; nTry++)
451 detected_rate = rates[i];
454 std::this_thread::sleep_for(20ms);
461 std::this_thread::sleep_for(5000ms);
480 std::this_thread::sleep_for(500ms);
494 printf(
"[CSickLaserSerial::LMS_setupBaudrate] rate=%i\n" , baud);
550 if (COM->
Read (&
b , 1))
552 if (
b == 0x06)
return true ;
554 }
while (tictac.
Tac () < timeout_ms * 1e-3);
571 unsigned int nBytes = 0;
575 const double maxTime = timeout * 1e-3;
581 if (COM->
Read (&
b , 1))
584 if (nBytes > 1 || (!nBytes &&
b == 0x02) ||
585 (nBytes == 1 &&
b == 0x80))
592 printf(
"[CSickLaserSerial::Receive] RX: %02X\n" ,
b );
596 if (tictac.
Tac () >= maxTime)
return false ;
602 if (4U + lengthField + 2U != nBytes)
605 "[CSickLaserSerial::LMS_waitIncomingFrame] Error: expected %u "
606 "bytes, received %u\n" ,
607 4U + lengthField + 2U, nBytes);
616 if (CRC_packet != CRC)
619 "[CSickLaserSerial::LMS_waitIncomingFrame] Error in CRC: rx: "
620 "0x%04X, computed: 0x%04X\n" ,
627 for (
unsigned int i=0;i<nBytes;i++)
659 RET_ERROR (
"Error waiting ACK to installation mode" );
661 RET_ERROR (
"Error in response to installation mode" );
666 RET_ERROR (
"Wrong response to installation mode" );
675 RET_ERROR (
"No ACK to 0x74 (req. config)" );
677 RET_ERROR (
"No answer to 0x74 (req. config)" );
681 RET_ERROR (
"No expected 0xF4 in response to 0x74 (req. config)" );
705 RET_ERROR (
"No ACK for config command (0x77)" );
707 RET_ERROR (
"No answer for config command (0x77)" );
711 RET_ERROR (
"Wrong answer for config command (0x77)" );
720 RET_ERROR (
"No ACK for set monitoring mode" );
722 RET_ERROR (
"No answer for set monitoring mode" );
726 RET_ERROR (
"Wrong answer for set monitoring mode" );
754 RET_ERROR (
"Error waiting ack for change angle/resolution" );
756 RET_ERROR (
"Error waiting answer for change angle/resolution" );
763 RET_ERROR (
"Error waiting ack for start scanning" );
765 RET_ERROR (
"Error waiting answer for start scanning" );
789 ASSERT_ (
sizeof (cmd_full) > cmd_len + 4U + 2U);
797 cmd_full[2] = cmd_len & 0xFF;
798 cmd_full[3] = cmd_len >> 8;
800 memcpy (cmd_full + 4, cmd, cmd_len);
804 cmd_full[4 + cmd_len + 0] =
crc & 0xFF;
805 cmd_full[4 + cmd_len + 1] =
crc >> 8;
807 const size_t toWrite = 4 + cmd_len + 2;
811 printf(
"[CSickLaserSerial::SendCommandToSICK] TX: " );
812 for (
unsigned int i = 0; i < toWrite; i++) printf(
"%02X " , cmd_full[i]);
816 const int NTRIES = 3;
818 for (
int k = 0; k < NTRIES; k++)
820 if (toWrite != COM->
Write (cmd_full, toWrite))
822 cout <<
"[CSickLaserSerial::SendCommandToSICK] Error writing data "
827 std::this_thread::sleep_for(15ms);
829 std::this_thread::sleep_for(10ms);
bool isOpen() const
Returns if port has been correctly open.
std::string sensorLabel
An arbitrary label that can be used to identify the sensor.
void setScanRange(const size_t i, const float val)
float maxRange
The maximum range allowed by the device, in meters (e.g.
bool rightToLeft
The scanning direction: true=counterclockwise; false=clockwise.
unsigned __int16 uint16_t
bool LMS_statusQuery()
Send a status query and wait for the answer.
A high-performance stopwatch, with typical resolution of nanoseconds.
uint16_t compute_CRC16(const std::vector< uint8_t > &data, const uint16_t gen_pol=0x8005)
Computes the CRC16 checksum of a block of data.
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
void initialize()
Set-up communication with the laser.
int m_com_baudRate
Baudrate: 9600, 38400, 500000.
size_t Read(void *Buffer, size_t Count)
Implements the virtual method responsible for reading from the stream - Unlike CStream::ReadBuffer,...
std::string m_com_port
If set to non-empty, the serial port will be attempted to be opened automatically when this class is ...
void filterByExclusionAngles(mrpt::obs::CObservation2DRangeScan &obs) const
Mark as invalid those ranges in a set of forbiden angle ranges.
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
A communications serial port built as an implementation of a utils::CStream.
bool read_bool(const std::string §ion, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
Contains classes for various device interfaces.
bool m_skip_laser_config
If true, doesn't send the initialization commands to the laser and go straight to capturing.
Serial and networking devices and utilities.
size_t Write(const void *Buffer, size_t Count) override
Introduces a pure virtual method responsible for writing to the stream.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
bool LMS_setupBaudrate(int baud)
Send a command to change the LMS comms baudrate, return true if ACK is OK.
void resizeScan(const size_t len)
Resizes all data vectors to allocate a given number of scan rays.
#define THROW_EXCEPTION(msg)
void purgeBuffers()
Purge tx and rx buffers.
#define ASSERT_(f)
Defines an assertion mechanism.
void setScanRangeValidity(const size_t i, const bool val)
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
bool tryToOpenComms(std::string *err_msg=nullptr)
Tries to open the com port and setup all the LMS protocol.
This namespace contains representation of robot actions and observations.
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
std::string read_string(const std::string §ion, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
mrpt::math::TPose3D m_sensorPose
The sensor 6D pose:
double Tac() noexcept
Stops the stopwatch.
int read_int(const std::string §ion, const std::string &name, int defaultValue, bool failIfNotFound=false) const
void setConfig(int baudRate, int parity=0, int bits=8, int nStopBits=1, bool enableFlowControl=false)
Changes the configuration of the port.
bool LMS_setupSerialComms()
Assures laser is connected and operating at 38400, in its case returns true.
uint8_t m_received_frame_buffer[2000]
virtual ~CSickLaserSerial()
Destructor
float aperture
The "aperture" or field-of-view of the range finder, in radians (typically M_PI = 180 degrees).
bool SendCommandToSICK(const uint8_t *cmd, const uint16_t cmd_len)
Send header+command-data+crc and waits for ACK.
This class allows loading and storing values and vectors of different types from a configuration text...
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
mrpt::io::CStream * m_stream
The I/O channel (will be nullptr if not bound).
void loadCommonParams(const mrpt::config::CConfigFileBase &configSource, const std::string &iniSection)
Should be call by derived classes at "loadConfig" (loads exclusion areas AND exclusion angles).
#define MRPT_LOG_ERROR_FMT(_FMT_STRING,...)
#define MRPT_LOG_ERROR(_STRING)
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
bool LMS_waitIncomingFrame(uint16_t timeout)
Returns false if timeout.
int m_scans_res
1/100th of deg: 100, 50 or 25
unsigned int m_nTries_current
bool waitContinuousSampleFrame(std::vector< float > &ranges, unsigned char &LMS_status, bool &is_mm_mode)
Lightweight 3D pose (three spatial coordinates, plus three angular coordinates).
void Tic() noexcept
Starts the stopwatch.
void loadConfig_sensorSpecific(const mrpt::config::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
std::string m_sensorLabel
See CGenericSensor.
float stdError
The "sigma" error of the device in meters, used while inserting the scan in an occupancy grid.
float read_float(const std::string §ion, const std::string &name, float defaultValue, bool failIfNotFound=false) const
This "software driver" implements the communication protocol for interfacing a SICK LMS 2XX laser sca...
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
#define IMPLEMENTS_GENERIC_SENSOR(class_name, NameSpace)
This must be inserted in all CGenericSensor classes implementation files:
void processPreview(const mrpt::obs::CObservation2DRangeScan &obs)
Must be called inside the capture method to allow optional GUI preview of scans.
mrpt::containers::ContainerReadOnlyProxyAccessor< mrpt::aligned_std_vector< float > > scan
The range values of the scan, in meters.
unsigned int m_nTries_connect
Default = 1.
void open()
Open the port.
mrpt::comms::CSerialPort * m_mySerialPort
Will be !=nullptr only if I created it, so I must destroy it at the end.
void setTimeouts(int ReadIntervalTimeout, int ReadTotalTimeoutMultiplier, int ReadTotalTimeoutConstant, int WriteTotalTimeoutMultiplier, int WriteTotalTimeoutConstant)
Changes the timeouts of the port, in milliseconds.
This base provides a set of functions for maths stuff.
GLsizei const GLchar ** string
void setSerialPortName(const std::string &COM_name)
Sets the serial port to open (it is an error to try to change this while open yet).
bool turnOn()
Enables the scanning mode (in this class this has no effect).
bool LMS_endContinuousMode()
bool LMS_sendMeasuringMode_cm_mm()
Returns false on error.
int m_scans_FOV
100 or 180 deg
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot at the moment of starting the scan.
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,...
void filterByExclusionAreas(mrpt::obs::CObservation2DRangeScan &obs) const
Mark as invalid those points which (x,y) coordinates fall within the exclusion polygons.
bool turnOff()
Disables the scanning mode (in this class this has no effect).
This namespace provides a OS-independent interface to many useful functions: filenames manipulation,...
bool LMS_startContinuousMode()
bool LMS_waitACK(uint16_t timeout_ms)
Returns false if timeout.
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
double DEG2RAD(const double x)
Degrees to radians.
Page generated by Doxygen 1.8.17 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at mié 12 jul 2023 10:03:34 CEST