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 " double Tac() noexcept
Stops the stopwatch.
bool sendCANBusReaderSpeed()
Sends the specified speed to the CAN Converter.
void loadConfig_sensorSpecific(const mrpt::config::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
bool m_canreader_timestamp
unsigned __int16 uint16_t
void appendObservation(const mrpt::serialization::CSerializable::Ptr &obj)
Like appendObservations() but for just one observation.
std::string read_string(const std::string §ion, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
A communications serial port built as an implementation of a utils::CStream.
bool waitACK(uint16_t timeout_ms)
char hexCharToInt(char n)
std::string m_sensorLabel
See CGenericSensor.
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)
This class stores a message from a CAN BUS with the protocol J1939.
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...
A high-performance stopwatch, with typical resolution of nanoseconds.
void open()
Open the port.
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Contains classes for various device interfaces.
bool waitIncomingFrame(uint16_t timeout)
void setBaudRate(int baud)
Changes the serial port baud rate (call prior to 'doProcess'); valid values are 9600,38400 and 500000.
void setConfig(int baudRate, int parity=0, int bits=8, int nStopBits=1, bool enableFlowControl=false)
Changes the configuration of the port.
int read_int(const std::string §ion, const std::string &name, int defaultValue, bool failIfNotFound=false) const
uint8_t m_priority
The priority.
#define ASSERT_(f)
Defines an assertion mechanism.
void doProcess()
This method will be invoked at a minimum rate of "process_rate" (Hz)
bool CANBusCloseChannel()
Closes the CAN Channel.
This class allows loading and storing values and vectors of different types from a configuration text...
bool waitForVersion(uint16_t timeout, bool printOutVersion=false)
uint8_t m_pdu_spec
PDU Specific.
virtual ~CCANBusReader()
Destructor.
Versatile class for consistent logging and management of output messages.
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 "software driver" implements the communication protocol for interfacing a SICK LMS 2XX laser sca...
bool isOpen() const
Returns if port has been correctly open.
This namespace contains representation of robot actions and observations.
size_t Write(const void *Buffer, size_t Count) override
Introduces a pure virtual method responsible for writing to the stream.
void purgeBuffers()
Purge tx and rx buffers.
uint8_t m_received_frame_buffer[2000]
bool tryToOpenComms(std::string *err_msg=nullptr)
Tries to open the com port and setup all the LMS protocol.
GLsizei const GLchar ** string
#define IMPLEMENTS_GENERIC_SENSOR(class_name, NameSpace)
This must be inserted in all CGenericSensor classes implementation files:
void setTimeouts(int ReadIntervalTimeout, int ReadTotalTimeoutMultiplier, int ReadTotalTimeoutConstant, int WriteTotalTimeoutMultiplier, int WriteTotalTimeoutConstant)
Changes the timeouts of the port, in milliseconds.
void initialize()
Set-up communication with the laser.
std::string sensorLabel
An arbitrary label that can be used to identify the sensor.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
bool sendCommandToCANReader(const uint8_t *cmd, const uint16_t cmd_len, bool wait=true)
unsigned int m_nTries_current
bool m_CANBusChannel_isOpen
uint8_t m_pdu_format
PDU Format.
bool read_bool(const std::string §ion, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
std::vector< char > m_raw_frame
The ASCII frame.
mrpt::comms::CSerialPort * m_mySerialPort
Will be !=nullptr only if I created it, so I must destroy it at the end.
uint16_t m_pgn
The Parameter Group Number within this frame.
std::string m_com_port
If set to non-empty, the serial port will be attempted to be opened automatically when this class is ...
int m_com_baudRate
Baudrate: 9600, 38400, 500000.
uint8_t m_src_address
The address of the source node within this frame.
void Tic() noexcept
Starts the stopwatch.
#define MRPT_LOG_ERROR_STREAM(__CONTENTS)
std::vector< uint8_t > m_data
The data within this frame (0-8 bytes)
size_t Read(void *Buffer, size_t Count)
Implements the virtual method responsible for reading from the stream - Unlike CStream::ReadBuffer, this method will not raise an exception on zero bytes read, as long as there is not any fatal error in the communications.
uint8_t m_data_length
Data length.
bool CANBusOpenChannel()
Opens the CAN Channel.
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
bool queryVersion(bool printOutVersion=false)
unsigned int m_nTries_connect
Default = 1.