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 " 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).
size_t Write(const void *Buffer, size_t Count)
Implements the virtual method responsible for writing to the stream.
bool sendCANBusReaderSpeed()
Sends the specified speed to the CAN Converter.
bool read_bool(const std::string §ion, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
bool m_canreader_timestamp
unsigned __int16 uint16_t
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...
void open()
Open the port.
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Contains classes for various device interfaces.
std::string read_string(const std::string §ion, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
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.
void Tic()
Starts the stopwatch.
std::shared_ptr< CObservationCANBusJ1939 > Ptr
uint8_t m_priority
The priority.
This class allows loading and storing values and vectors of different types from a configuration text...
int read_int(const std::string §ion, const std::string &name, int defaultValue, bool failIfNotFound=false) const
void doProcess()
This method will be invoked at a minimum rate of "process_rate" (Hz)
bool CANBusCloseChannel()
Closes the CAN Channel.
bool waitForVersion(uint16_t timeout, bool printOutVersion=false)
uint8_t m_pdu_spec
PDU Specific.
void loadConfig_sensorSpecific(const mrpt::utils::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
virtual ~CCANBusReader()
Destructor.
This class implements a high-performance stopwatch.
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.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
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 appendObservation(const mrpt::utils::CSerializable::Ptr &obj)
Like appendObservations() but for just one observation.
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.
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.
double Tac()
Stops the stopwatch.
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.
#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".
bool queryVersion(bool printOutVersion=false)
unsigned int m_nTries_connect
Default = 1.