25 #define RET_ERROR(msg) \
27 cout << "[" << __CURRENT_FUNCTION_NAME__ << "] " << msg << endl; \
39 if (
n >=
'0' &&
n <=
'9')
43 if (
n >=
'A' &&
n <=
'F')
44 return (
n -
'A' + 10);
52 CCANBusReader::CCANBusReader()
53 :
mrpt::utils::COutputLogger(
"CCANBusReader"),
55 m_mySerialPort(nullptr),
56 m_com_baudRate(57600),
59 m_canbus_speed(250000),
60 m_canreader_timestamp(false),
61 m_CANBusChannel_isOpen(false)
93 mrpt::make_aligned_shared<mrpt::obs::CObservationCANBusJ1939>();
94 bool thereIsObservation;
98 if (thereIsObservation)
101 cout <<
"No frame received" << endl;
108 bool& outThereIsObservation,
111 outThereIsObservation =
false;
112 hardwareError =
false;
116 hardwareError =
true;
123 uint8_t out_prio, out_pdu_format, out_pdu_spec, out_src_address,
126 vector<uint8_t> out_data;
127 vector<char> out_raw_frame;
129 out_prio, out_pdu_format, out_pdu_spec, out_src_address,
130 out_data_length, out_pgn, out_data, out_raw_frame))
146 outObservation.
m_pgn = out_pgn;
148 outObservation.
m_data.resize(out_data.size());
149 for (
uint8_t k = 0; k < out_data.size(); ++k)
150 outObservation.
m_data[k] = out_data[k];
151 outObservation.
m_raw_frame.resize(out_raw_frame.size());
152 for (
uint8_t k = 0; k < out_raw_frame.size(); ++k)
156 outThereIsObservation =
true;
180 #ifdef MRPT_OS_WINDOWS
200 if (err_msg) *err_msg =
"";
213 throw std::logic_error(
214 "ERROR: No serial port attached with bindIO, neither it "
215 "set with 'setSerialPort'");
220 bool just_open =
false;
238 if (!just_open)
return true;
245 cout <<
"Setting up serial comms in port " <<
m_com_port;
247 cout <<
" ... done" << endl;
253 cout <<
"Setting up CAN BUS Speed at: " <<
m_canbus_speed << endl;
254 for (
int nTry = 0; nTry < 250000 ; nTry++)
256 if (!
res)
return false;
257 cout <<
" ... done" << endl;
261 cout <<
"Opening CAN BUS and starting to receive." << endl;
262 for (
int nTry = 0; nTry < 250000 ; nTry++)
264 if (!
res)
return false;
265 cout <<
" ... done" << endl;
277 catch (std::exception& e)
280 "[CCANBusReader] Error trying to open CANBusReader at port ";
282 if (err_msg) *err_msg =
s;
295 unsigned char cmd[2];
337 unsigned char cmd[1];
346 unsigned char cmd[1];
357 unsigned char cmd[1];
365 unsigned char cmd[2];
374 unsigned char cmd[1];
386 vector<uint8_t>& out_data, vector<char>& out_raw_frame)
388 size_t nRead, nBytesToRead;
389 size_t nFrameBytes = 0;
391 unsigned char buf[40];
394 for (
uint8_t k = 0; k < 40; ++k) buf[k] = 0;
397 while (nFrameBytes < (lengthField = (10U + dlc + 1U)))
400 if (lengthField > 30)
402 cout <<
"#" << int(dlc) <<
" ";
404 for (
uint8_t k = 0; k < 40; ++k) buf[k] = 0;
408 if (nFrameBytes < 10)
414 nBytesToRead = (lengthField)-nFrameBytes;
426 catch (std::exception& e)
430 "[waitContinuousSampleFrame] Disconnecting due to comms error: "
435 if (!nRead)
return false;
437 if (nRead < nBytesToRead) std::this_thread::sleep_for(30ms);
441 if (nFrameBytes > 0 || (nFrameBytes == 0 && buf[0] == 0x54 ))
442 nFrameBytes += nRead;
446 for (
uint8_t k = 0; k < 40; ++k) buf[k] = 0;
453 out_raw_frame.resize(nFrameBytes);
454 for (
uint8_t k = 0; k < nFrameBytes; ++k)
457 out_raw_frame[k] = buf[k];
460 out_prio = (aux[1] << 2) | (aux[2] >> 2);
461 out_pdu_format = (aux[3] << 4) | aux[4];
462 out_pdu_spec = (aux[5] << 4) | aux[6];
463 out_src_address = (aux[7] << 4) | aux[8];
464 out_data_length = aux[9];
466 out_data.resize(out_data_length);
467 for (
uint8_t k = 0, k2 = 0; k < 2 * out_data_length; k += 2, k2++)
468 out_data[k2] = (aux[10 + k] << 4) | aux[11 + k];
470 if (buf[nFrameBytes - 1] != 0x0D)
473 "[CCANBusReader::waitContinuousSampleFrame] expected 0x0D "
474 "ending flag, 0x%X found instead",
493 cerr << err_str << endl;
494 throw std::logic_error(err_str);
510 int detected_rate = 0;
515 int rates[] = {0, 9600, 38400, 57600, 500000};
524 !detected_rate && i <
sizeof(rates) /
sizeof(rates[0]); i++)
529 std::this_thread::sleep_for(100ms);
534 cout << endl <<
"Closing CAN Channel " << endl;
535 for (
int nTry = 0; nTry < 250000 ; nTry++)
537 cout <<
" ... done" << endl;
540 std::this_thread::sleep_for(100ms);
543 for (
int nTry = 0; nTry < 250000 && !detected_rate; nTry++)
550 detected_rate = rates[i];
553 std::this_thread::sleep_for(20ms);
560 std::this_thread::sleep_for(5000ms);
570 std::this_thread::sleep_for(500ms);
606 cout << int(
b) << endl;
610 }
while (tictac.
Tac() < timeout_ms * 1e-3);
623 unsigned int nBytes = 0;
627 const double maxTime = timeout * 1e-3;
637 if (nBytes > 0 || (nBytes == 0 &&
b ==
'V'))
644 if (tictac.
Tac() >= maxTime)
646 cout <<
"Version timeout" << endl;
655 "[CCANBusReader::waitForVersion] Error: expected 0x0D final byte, "
664 for (
uint8_t k = 0; k < nBytes; ++k)
674 unsigned int nBytes = 0;
678 const double maxTime = timeout * 1e-3;
680 while (nBytes < 10 || (nBytes < (10U + dlc + 1U )))
685 if (nBytes > 1 || (!nBytes &&
b == 0x54 ))
701 if (tictac.
Tac() >= maxTime)
return false;
707 "[CCANBusReader::waitIncomingFrame] Error: expected 0x0D as final "
708 "flag, received %x\n",
715 for (
unsigned int i=0;i<nBytes;i++)
729 ASSERT_(
sizeof(cmd_full) > cmd_len);
732 memcpy(cmd_full, cmd, cmd_len);
733 cmd_full[cmd_len] = 0x0D;
735 const size_t toWrite = cmd_len + 1;
739 for (
unsigned int i = 0; i < toWrite; i++) printf(
"%02X ", cmd_full[i]);
749 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:
#define MRPT_LOG_ERROR_STREAM(__CONTENTS)
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)
Implements the 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 "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,...
void loadConfig_sensorSpecific(const mrpt::utils::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
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.
unsigned int m_nTries_current
bool sendCommandToCANReader(const uint8_t *cmd, const uint16_t cmd_len, bool wait=true)
bool m_CANBusChannel_isOpen
std::string m_sensorLabel
See CGenericSensor.
void appendObservation(const mrpt::utils::CSerializable::Ptr &obj)
Like appendObservations() but for just one observation.
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.
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 class implements a high-performance stopwatch.
double Tac()
Stops the stopwatch.
void Tic()
Starts the stopwatch.
GLsizei const GLchar ** string
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.
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
Contains classes for various device interfaces.
This namespace contains representation of robot actions and observations.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
unsigned __int16 uint16_t