30 CHokuyoURG::CHokuyoURG()
34 m_sensorPose(0, 0, 0),
36 m_highSensMode(false),
41 m_I_am_owner_serial_port(false),
43 m_timeStartSynchDelay(0),
44 m_disable_firmware_timestamp(false),
68 const size_t N = strlen(str);
79 bool& outThereIsObservation,
82 outThereIsObservation =
false;
83 hardwareError =
false;
95 char rcv_status0, rcv_status1;
97 int expectedSize = nRanges * 3 + 4;
111 if (rcv_status0 !=
'0' && rcv_status0 !=
'9')
113 hardwareError =
true;
122 if ((
size_t)expectedSize !=
m_rcv_data.size())
125 "[CHokuyoURG::doProcess] ERROR: Expected "
126 << expectedSize <<
" data bytes, received " <<
m_rcv_data.size()
128 hardwareError =
true;
134 if (do_timestamp_sync &&
137 do_timestamp_sync =
false;
141 if (do_timestamp_sync)
157 auto AtDO = std::chrono::milliseconds(AtUI);
177 for (
int i = 0; i < nRanges; i++)
179 int b1 = (*ptr++) - 0x30;
180 int b2 = (*ptr++) - 0x30;
181 int b3 = (*ptr++) - 0x30;
183 int range_mm = ((
b1 << 12) | (
b2 << 6) |
b3);
192 int b4 = (*ptr++) - 0x30;
193 int b5 = (*ptr++) - 0x30;
194 int b6 = (*ptr++) - 0x30;
205 outThereIsObservation =
true;
219 configSource.
read_int(iniSection,
"HOKUYO_motorSpeed_rpm", 0);
221 configSource.
read_float(iniSection,
"pose_x", 0),
222 configSource.
read_float(iniSection,
"pose_y", 0),
223 configSource.
read_float(iniSection,
"pose_z", 0),
244 "Either COM_port or IP_DIR must be defined in the configuration file!");
247 "Both COM_port and IP_DIR set! Please, define only one of them.");
252 "A TCP/IP port number `PORT_DIR` must be specified for Ethernet "
290 std::this_thread::sleep_for(10ms);
293 std::this_thread::sleep_for(10ms);
297 std::this_thread::sleep_for(10ms);
299 std::this_thread::sleep_for(10ms);
319 std::this_thread::sleep_for(10ms);
322 std::this_thread::sleep_for(10ms);
325 std::this_thread::sleep_for(10ms);
353 const int half_range =
static_cast<int>(
360 "[HOKUYO::turnOn] Using reduced FOV: ranges ["
391 char rcv_status0, rcv_status1;
395 "[CHokuyoURG::setHighBaudrate] Changing baudrate to 115200...");
404 "[CHokuyoURG::setHighBaudrate] Error waiting for response");
437 nRead = client->
readAsync(buf, to_read, 100, 10);
446 catch (std::exception&)
481 }
while (i < verifLen);
491 if (rcv_status1 != 0x0A)
507 if (nextChar != 0x0A)
return false;
517 bool lastWasLF =
false;
553 "[Hokuyo] receiveResponse(): RX `" <<
m_rcv_data
556 if (rcv_status0 !=
'0' &&
557 (rcv_status0 !=
'9' && rcv_status1 !=
'9'))
560 "[Hokuyo] Error LIDAR status: "
561 << (
int)rcv_status0 <<
" after command: `"
574 catch (std::exception& e)
577 "[Hokuyo] receiveResponse() Exception: %s", e.what());
588 char rcv_status0, rcv_status1;
592 "[CHokuyoURG::enableSCIP20] Changing protocol to SCIP2.0...");
611 char rcv_status0, rcv_status1;
615 MRPT_LOG_DEBUG(
"[CHokuyoURG::switchLaserOn] Switching laser ON...");
634 char rcv_status0, rcv_status1;
638 MRPT_LOG_DEBUG(
"[CHokuyoURG::switchLaserOff] Switching laser OFF...");
662 char rcv_status0, rcv_status1;
666 "[CHokuyoURG::setMotorSpeed] Setting to %i rpm...", motoSpeed_rpm);
669 int motorSpeedCode = (600 - motoSpeed_rpm) / 6;
670 if (motorSpeedCode < 0 || motorSpeedCode > 10)
674 <<
" Motorspeed must be in the range 540-600 rpm");
679 os::sprintf(cmd, 20,
"CR%02i\x0A", motorSpeedCode);
699 char rcv_status0, rcv_status1;
703 "[CHokuyoURG::setHighSensitivityMode] Setting HS mode to: %s...",
704 enabled ?
"true" :
"false");
734 char rcv_status0, rcv_status1;
737 MRPT_LOG_DEBUG(
"[CHokuyoURG::displayVersionInfo] Asking info...");
754 if (
c ==
';')
c =
'\n';
760 "\n------------- HOKUYO Scanner: Version Information ------\n"
763 "-------------------------------------------------------\n\n");
773 char rcv_status0, rcv_status1;
776 MRPT_LOG_DEBUG(
"[CHokuyoURG::displaySensorInfo] Asking for info...");
792 if (
c ==
';')
c =
'\n';
798 "\n------------- HOKUYO Scanner: Product Information ------\n"
801 "-------------------------------------------------------\n\n");
809 if (
nullptr != (ptr = strstr(&
m_rcv_data[0],
"DMAX:")))
810 out_data->
d_max = 0.001 * atoi(ptr + 5);
814 if (
nullptr != (ptr = strstr(&
m_rcv_data[0],
"DMIN:")))
815 out_data->
d_min = 0.001 * atoi(ptr + 5);
819 if (
nullptr != (ptr = strstr(&
m_rcv_data[0],
"ARES:")))
824 if (
nullptr != (ptr = strstr(&
m_rcv_data[0],
"SCAN:")))
829 if (
nullptr != (ptr = strstr(&
m_rcv_data[0],
"AMIN:")))
834 if (
nullptr != (ptr = strstr(&
m_rcv_data[0],
"AMAX:")))
839 if (
nullptr != (ptr = strstr(&
m_rcv_data[0],
"AFRT:")))
844 if (
nullptr != (ptr = strstr(&
m_rcv_data[0],
"MODL:")))
849 out_data->
model = aux;
860 char rcv_status0, rcv_status1;
863 MRPT_LOG_DEBUG(
"[CHokuyoURG::startScanningMode] Starting scanning mode...");
874 if (scan_interval > 9) scan_interval = 9;
911 "[CHokuyoURG] Socket connection lost! trying to "
938 if (COM->
isOpen())
return true;
943 <<
": Serial port connection lost! Trying to reconnect...");
969 "No stream bound to the laser nor COM serial port or ip and "
970 "port provided in 'm_com_port','m_ip_dir' and 'm_port_dir'");
987 <<
" Cannot connect with the server '" <<
m_com_port
1056 void* buf = malloc(
sizeof(
uint8_t) * to_read);
1060 if (nRead != to_read)
1062 "Error in purge buffers: read and expected number of bytes "
#define IMPLEMENTS_GENERIC_SENSOR(class_name, NameSpace)
This must be inserted in all CGenericSensor classes implementation files:
const int MINIMUM_PACKETS_TO_SET_TIMESTAMP_REFERENCE
A TCP socket that can be connected to a TCP server, implementing MRPT's CStream interface for passing...
size_t getReadPendingBytes()
Return the number of bytes already in the receive queue (they can be read without waiting)
bool isConnected()
Returns true if this objects represents a successfully connected socket.
void connect(const std::string &remotePartAddress, unsigned short remotePartTCPPort, unsigned int timeout_ms=0)
Establishes a connection with a remote part.
size_t readAsync(void *Buffer, const size_t Count, const int timeoutStart_ms=-1, const int timeoutBetween_ms=-1)
A method for reading from the socket with an optional timeout.
A communications serial port built as an implementation of a utils::CStream.
bool isOpen() const
Returns if port has been correctly open.
void open()
Open the port.
void setConfig(int baudRate, int parity=0, int bits=8, int nStopBits=1, bool enableFlowControl=false)
Changes the configuration of the port.
void purgeBuffers()
Purge tx and rx buffers.
void setTimeouts(int ReadIntervalTimeout, int ReadTotalTimeoutMultiplier, int ReadTotalTimeoutConstant, int WriteTotalTimeoutMultiplier, int WriteTotalTimeoutConstant)
Changes the timeouts of the port, in milliseconds.
This class allows loading and storing values and vectors of different types from a configuration text...
bool read_bool(const std::string §ion, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
std::string read_string(const std::string §ion, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
int read_int(const std::string §ion, const std::string &name, int defaultValue, bool failIfNotFound=false) const
float read_float(const std::string §ion, const std::string &name, float defaultValue, bool failIfNotFound=false) const
T pop()
Retrieve an element from the buffer.
size_t available() const
The maximum number of elements that can be written ("push") without rising an overflow error.
size_t capacity() const
Return the maximum capacity of the buffer.
size_t size() const
Return the number of elements available for read ("pop") in the buffer (this is NOT the maximum size ...
void push_many(T *array_elements, size_t count)
Insert an array of elements in the buffer.
void processPreview(const mrpt::obs::CObservation2DRangeScan &obs)
Must be called inside the capture method to allow optional GUI preview of scans.
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).
void bindIO(mrpt::io::CStream *streamIO)
Binds the object to a given I/O channel.
void filterByExclusionAngles(mrpt::obs::CObservation2DRangeScan &obs) const
Mark as invalid those ranges in a set of forbiden angle ranges.
void filterByExclusionAreas(mrpt::obs::CObservation2DRangeScan &obs) const
Mark as invalid those points which (x,y) coordinates fall within the exclusion polygons.
std::string m_sensorLabel
See CGenericSensor.
This software driver implements the protocol SCIP-2.0 for interfacing HOKUYO URG/UTM/UXM/UST laser sc...
TSensorInfo m_sensor_info
The information gathered when the laser is first open.
mrpt::system::TTimeStamp m_timeStartTT
bool ensureStreamIsOpen()
Returns true if there is a valid stream bound to the laser scanner, otherwise it first try to open th...
bool displayVersionInfo()
Ask to the device, and print to the debug stream, details about the firmware version,...
bool setHighBaudrate()
Passes to 115200bps bitrate.
std::string m_rcv_data
temp buffer for incoming data packets
mrpt::gui::CDisplayWindow3D::Ptr m_win
uint32_t m_timeStartUI
Time of the first data packet, for synchronization purposes.
bool m_highSensMode
High sensitivity [HS] mode (default: false)
unsigned int m_port_dir
If set to non-empty and m_ip_dir too, the program will try to connect to a Hokuyo using Ethernet comm...
bool enableSCIP20()
Enables the SCIP2.0 protocol (this must be called at the very begining!).
bool displaySensorInfo(CHokuyoURG::TSensorInfo *out_data=nullptr)
Ask to the device, and print to the debug stream, details about the sensor model.
void loadConfig_sensorSpecific(const mrpt::config::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
bool startScanningMode()
Start the continuous scanning mode, using parameters stored in the object (loaded from the ....
bool switchLaserOn()
Switchs the laser on.
bool setHighSensitivityMode(bool enabled)
Changes the high sensitivity mode (HS) (default: false)
std::string m_com_port
If set to non-empty, the serial port will be attempted to be opened automatically when this class is ...
bool turnOff()
Disables the scanning mode (this can be used to turn the device in low energy mode,...
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,...
double m_reduced_fov
Used to reduce artificially the interval of scan ranges.
bool turnOn()
Enables the scanning mode (which may depend on the specific laser device); this must be called before...
poses::CPose3D m_sensorPose
The sensor 6D pose:
bool assureBufferHasBytes(const size_t nDesiredBytes)
Assures a minimum number of bytes in the input buffer, reading from the serial port only if required.
bool receiveResponse(char &rcv_status0, char &rcv_status1)
Waits for a response from the device.
mrpt::containers::circular_buffer< uint8_t > m_rx_buffer
Auxiliary buffer for readings.
int m_firstRange
The first and last ranges to consider from the scan.
bool setIntensityMode(bool enabled)
If true scans will capture intensity.
unsigned int m_scan_interval
void sendCmd(const char *str)
void setScanInterval(unsigned int skipScanCount)
Set the skip scan count (0 means send all scans).
void purgeBuffers()
Empties the RX buffers of the serial port.
void initialize()
Turns the laser on.
unsigned int getScanInterval() const
bool setMotorSpeed(int motoSpeed_rpm)
Changes the motor speed in rpm's (default 600rpm)
std::string m_ip_dir
If set to non-empty and m_port_dir too, the program will try to connect to a Hokuyo using Ethernet co...
int m_timeStartSynchDelay
Counter to discard to first few packets before setting the correspondence between device and computer...
bool m_intensity
Get intensity from lidar scan (default: false)
bool m_I_am_owner_serial_port
std::string m_lastSentMeasCmd
The last sent measurement command (MDXXX), including the last 0x0A.
bool switchLaserOff()
Switchs the laser off.
bool m_disable_firmware_timestamp
int m_motorSpeed_rpm
The motor speed (default=600rpm)
virtual ~CHokuyoURG()
Destructor: turns the laser off.
virtual size_t Write(const void *Buffer, size_t Count)=0
Introduces a pure virtual method responsible for writing to the stream.
virtual size_t Read(void *Buffer, size_t Count)=0
Introduces a pure virtual method responsible for reading from the stream.
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
float maxRange
The maximum range allowed by the device, in meters (e.g.
void setScanIntensity(const size_t i, const int val)
float aperture
The "aperture" or field-of-view of the range finder, in radians (typically M_PI = 180 degrees).
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot at the moment of starting the scan.
bool rightToLeft
The scanning direction: true=counterclockwise; false=clockwise.
void resizeScan(const size_t len)
Resizes all data vectors to allocate a given number of scan rays.
void setScanRangeValidity(const size_t i, const bool val)
float stdError
The "sigma" error of the device in meters, used while inserting the scan in an occupancy grid.
void setScanHasIntensity(bool setHasIntensityFlag)
Marks this scan as having or not intensity data.
mrpt::containers::ContainerReadOnlyProxyAccessor< mrpt::aligned_std_vector< float > > scan
The range values of the scan, in meters.
void setScanRange(const size_t i, const float val)
std::string sensorLabel
An arbitrary label that can be used to identify the sensor.
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
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...
void setMinLoggingLevel(const VerbosityLevel level)
Set the minimum logging level for which the incoming logs are going to be taken into account.
#define __CURRENT_FUNCTION_NAME__
A macro for obtaining the name of the current function:
#define MRPT_LOAD_HERE_CONFIG_VAR( variableName, variableType, targetVariable, configFileObject, sectionNameStr)
#define ASSERT_EQUAL_(__A, __B)
Assert comparing two values, reporting their actual values upon failure.
#define ASSERT_(f)
Defines an assertion mechanism.
#define THROW_EXCEPTION(msg)
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
GLsizei const GLchar ** string
int sprintf(char *buf, size_t bufSize, const char *format,...) noexcept MRPT_printf_format_check(3
An OS-independent version of sprintf (Notice the bufSize param, which may be ignored in some compiler...
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Serial and networking devices and utilities.
Contains classes for various device interfaces.
This namespace contains representation of robot actions and observations.
The namespace for 3D scene representation and rendering.
double RAD2DEG(const double x)
Radians to degrees.
double DEG2RAD(const double x)
Degrees to radians.
unsigned __int32 uint32_t
Used in CHokuyoURG::displayVersionInfo.
std::string model
The sensor model.
int scans_per_360deg
Number of measuremens per 360 degrees.
double d_min
Min/Max ranges, in meters.
int scan_first
First, last, and front step of the scanner angular span.
int motor_speed_rpm
Standard motor speed, rpm.
#define MRPT_LOG_ERROR_STREAM(__CONTENTS)
#define MRPT_LOG_DEBUG_FMT(_FMT_STRING,...)
Use: MRPT_LOG_DEBUG_FMT("i=%u", i);
#define MRPT_LOG_ERROR(_STRING)
#define MRPT_LOG_DEBUG_STREAM(__CONTENTS)
Use: MRPT_LOG_DEBUG_STREAM("Var=" << value << " foo=" << foo_var);
#define MRPT_LOG_INFO_STREAM(__CONTENTS)
#define MRPT_LOG_DEBUG(_STRING)
Use: MRPT_LOG_DEBUG("message");
#define MRPT_LOG_ERROR_FMT(_FMT_STRING,...)