27 #define RET_ERROR(msg) \
29 cout << "[" << __CURRENT_FUNCTION_NAME__ << "] " << msg << endl; \
41 if (
n >=
'0' &&
n <=
'9')
45 if (
n >=
'A' &&
n <=
'F')
46 return (
n -
'A' + 10);
54 CCANBusReader::CCANBusReader()
57 m_mySerialPort(nullptr),
58 m_com_baudRate(57600),
61 m_canbus_speed(250000),
62 m_canreader_timestamp(false),
63 m_CANBusChannel_isOpen(false)
95 mrpt::make_aligned_shared<mrpt::obs::CObservationCANBusJ1939>();
96 bool thereIsObservation;
100 if (thereIsObservation)
103 cout <<
"No frame received" << endl;
110 bool& outThereIsObservation,
113 outThereIsObservation =
false;
114 hardwareError =
false;
118 hardwareError =
true;
125 uint8_t out_prio, out_pdu_format, out_pdu_spec, out_src_address,
128 vector<uint8_t> out_data;
129 vector<char> out_raw_frame;
131 out_prio, out_pdu_format, out_pdu_spec, out_src_address,
132 out_data_length, out_pgn, out_data, out_raw_frame))
148 outObservation.
m_pgn = out_pgn;
150 outObservation.
m_data.resize(out_data.size());
151 for (
uint8_t k = 0; k < out_data.size(); ++k)
152 outObservation.
m_data[k] = out_data[k];
153 outObservation.
m_raw_frame.resize(out_raw_frame.size());
154 for (
uint8_t k = 0; k < out_raw_frame.size(); ++k)
158 outThereIsObservation =
true;
202 if (err_msg) *err_msg =
"";
215 throw std::logic_error(
216 "ERROR: No serial port attached with bindIO, neither it "
217 "set with 'setSerialPort'");
222 bool just_open =
false;
240 if (!just_open)
return true;
247 cout <<
"Setting up serial comms in port " <<
m_com_port;
249 cout <<
" ... done" << endl;
255 cout <<
"Setting up CAN BUS Speed at: " <<
m_canbus_speed << endl;
256 for (
int nTry = 0; nTry < 250000 ; nTry++)
258 if (!
res)
return false;
259 cout <<
" ... done" << endl;
263 cout <<
"Opening CAN BUS and starting to receive." << endl;
264 for (
int nTry = 0; nTry < 250000 ; nTry++)
266 if (!
res)
return false;
267 cout <<
" ... done" << endl;
279 catch (std::exception& e)
282 "[CCANBusReader] Error trying to open CANBusReader at port ";
284 if (err_msg) *err_msg =
s;
297 unsigned char cmd[2];
339 unsigned char cmd[1];
348 unsigned char cmd[1];
359 unsigned char cmd[1];
367 unsigned char cmd[2];
376 unsigned char cmd[1];
388 vector<uint8_t>& out_data, vector<char>& out_raw_frame)
390 size_t nRead, nBytesToRead;
391 size_t nFrameBytes = 0;
393 unsigned char buf[40];
396 for (
uint8_t k = 0; k < 40; ++k) buf[k] = 0;
399 while (nFrameBytes < (lengthField = (10U + dlc + 1U)))
402 if (lengthField > 30)
404 cout <<
"#" << int(dlc) <<
" ";
406 for (
uint8_t k = 0; k < 40; ++k) buf[k] = 0;
410 if (nFrameBytes < 10)
416 nBytesToRead = (lengthField)-nFrameBytes;
428 catch (std::exception& e)
432 "[waitContinuousSampleFrame] Disconnecting due to comms error: "
437 if (!nRead)
return false;
439 if (nRead < nBytesToRead) std::this_thread::sleep_for(30ms);
443 if (nFrameBytes > 0 || (nFrameBytes == 0 && buf[0] == 0x54 ))
444 nFrameBytes += nRead;
448 for (
uint8_t k = 0; k < 40; ++k) buf[k] = 0;
455 out_raw_frame.resize(nFrameBytes);
456 for (
uint8_t k = 0; k < nFrameBytes; ++k)
459 out_raw_frame[k] = buf[k];
462 out_prio = (aux[1] << 2) | (aux[2] >> 2);
463 out_pdu_format = (aux[3] << 4) | aux[4];
464 out_pdu_spec = (aux[5] << 4) | aux[6];
465 out_src_address = (aux[7] << 4) | aux[8];
466 out_data_length = aux[9];
468 out_data.resize(out_data_length);
469 for (
uint8_t k = 0, k2 = 0; k < 2 * out_data_length; k += 2, k2++)
470 out_data[k2] = (aux[10 + k] << 4) | aux[11 + k];
472 if (buf[nFrameBytes - 1] != 0x0D)
475 "[CCANBusReader::waitContinuousSampleFrame] expected 0x0D "
476 "ending flag, 0x%X found instead",
495 cerr << err_str << endl;
496 throw std::logic_error(err_str);
512 int detected_rate = 0;
517 int rates[] = {0, 9600, 38400, 57600, 500000};
526 !detected_rate && i <
sizeof(rates) /
sizeof(rates[0]); i++)
531 std::this_thread::sleep_for(100ms);
536 cout << endl <<
"Closing CAN Channel " << endl;
537 for (
int nTry = 0; nTry < 250000 ; nTry++)
539 cout <<
" ... done" << endl;
542 std::this_thread::sleep_for(100ms);
545 for (
int nTry = 0; nTry < 250000 && !detected_rate; nTry++)
552 detected_rate = rates[i];
555 std::this_thread::sleep_for(20ms);
562 std::this_thread::sleep_for(5000ms);
572 std::this_thread::sleep_for(500ms);
608 cout << int(
b) << endl;
612 }
while (tictac.
Tac() < timeout_ms * 1e-3);
625 unsigned int nBytes = 0;
629 const double maxTime = timeout * 1e-3;
639 if (nBytes > 0 || (nBytes == 0 &&
b ==
'V'))
646 if (tictac.
Tac() >= maxTime)
648 cout <<
"Version timeout" << endl;
657 "[CCANBusReader::waitForVersion] Error: expected 0x0D final byte, "
666 for (
uint8_t k = 0; k < nBytes; ++k)
676 unsigned int nBytes = 0;
680 const double maxTime = timeout * 1e-3;
682 while (nBytes < 10 || (nBytes < (10U + dlc + 1U )))
687 if (nBytes > 1 || (!nBytes &&
b == 0x54 ))
703 if (tictac.
Tac() >= maxTime)
return false;
709 "[CCANBusReader::waitIncomingFrame] Error: expected 0x0D as final "
710 "flag, received %x\n",
717 for (
unsigned int i=0;i<nBytes;i++)
731 ASSERT_(
sizeof(cmd_full) > cmd_len);
734 memcpy(cmd_full, cmd, cmd_len);
735 cmd_full[cmd_len] = 0x0D;
737 const size_t toWrite = cmd_len + 1;
741 for (
unsigned int i = 0; i < toWrite; i++) printf(
"%02X ", cmd_full[i]);
751 cout <<
"[CCANBusReader::SendCommandToCANReader] Error writing data to "
char hexCharToInt(char n)
#define IMPLEMENTS_GENERIC_SENSOR(class_name, NameSpace)
This must be inserted in all CGenericSensor classes implementation files:
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.
size_t Write(const void *Buffer, size_t Count) override
Introduces a pure virtual method responsible for writing to the stream.
size_t Read(void *Buffer, size_t Count)
Implements the virtual method responsible for reading from the stream - Unlike CStream::ReadBuffer,...
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.
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).
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
This "software driver" implements the communication protocol for interfacing a SICK LMS 2XX laser sca...
bool waitIncomingFrame(uint16_t timeout)
bool CANBusCloseChannel()
Closes the CAN Channel.
mrpt::comms::CSerialPort * m_mySerialPort
Will be !=nullptr only if I created it, so I must destroy it at the end.
bool waitForVersion(uint16_t timeout, bool printOutVersion=false)
void doProcessSimple(bool &outThereIsObservation, mrpt::obs::CObservationCANBusJ1939 &outObservation, bool &hardwareError)
Specific laser scanner "software drivers" must process here new data from the I/O stream,...
bool sendCANBusReaderSpeed()
Sends the specified speed to the CAN Converter.
uint8_t m_received_frame_buffer[2000]
int m_com_baudRate
Baudrate: 9600, 38400, 500000.
bool waitContinuousSampleFrame(uint8_t &out_prio, uint8_t &out_pdu_format, uint8_t &out_pdu_spec, uint8_t &out_src_address, uint8_t &out_data_length, uint16_t &out_pgn, std::vector< uint8_t > &out_data, std::vector< char > &out_raw_frame)
virtual ~CCANBusReader()
Destructor
bool CANBusOpenChannel()
Opens the CAN Channel.
void initialize()
Set-up communication with the laser.
bool waitACK(uint16_t timeout_ms)
void doProcess()
This method will be invoked at a minimum rate of "process_rate" (Hz)
void setBaudRate(int baud)
Changes the serial port baud rate (call prior to 'doProcess'); valid values are 9600,...
bool queryVersion(bool printOutVersion=false)
bool m_canreader_timestamp
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 tryToOpenComms(std::string *err_msg=nullptr)
Tries to open the com port and setup all the LMS protocol.
unsigned int m_nTries_connect
Default = 1.
void loadConfig_sensorSpecific(const mrpt::config::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
unsigned int m_nTries_current
bool sendCommandToCANReader(const uint8_t *cmd, const uint16_t cmd_len, bool wait=true)
bool m_CANBusChannel_isOpen
void appendObservation(const mrpt::serialization::CSerializable::Ptr &obj)
Like appendObservations() but for just one observation.
std::string m_sensorLabel
See CGenericSensor.
This class stores a message from a CAN BUS with the protocol J1939.
uint8_t m_src_address
The address of the source node within this frame.
uint16_t m_pgn
The Parameter Group Number within this frame.
std::vector< uint8_t > m_data
The data within this frame (0-8 bytes)
uint8_t m_pdu_format
PDU Format.
uint8_t m_pdu_spec
PDU Specific.
uint8_t m_priority
The priority.
std::vector< char > m_raw_frame
The ASCII frame.
std::shared_ptr< CObservationCANBusJ1939 > Ptr
uint8_t m_data_length
Data length
std::string sensorLabel
An arbitrary label that can be used to identify the sensor.
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
Versatile class for consistent logging and management of output messages.
A high-performance stopwatch, with typical resolution of nanoseconds.
void Tic() noexcept
Starts the stopwatch.
double Tac() noexcept
Stops the stopwatch.
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
#define ASSERT_(f)
Defines an assertion mechanism.
GLsizei const GLchar ** string
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
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.
Contains classes for various device interfaces.
This namespace contains representation of robot actions and observations.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
unsigned __int16 uint16_t
#define MRPT_LOG_ERROR_STREAM(__CONTENTS)