source: pacpussensors/trunk/Sick/SickLDMRSSensor.h@ 72

Last change on this file since 72 was 72, checked in by DHERBOMEZ Gérald, 10 years ago
  • Correction of a little bug in gps component (property recording bad)
  • Improvement of sick lms151 component
  • Correction of bug in sick LDRMS : buffer overflow in a memcpy
File size: 9.6 KB
Line 
1/*********************************************************************
2// created: 2014/02/02 - 10:48
3// filename: SickLDMRSSensor.h
4//
5// author: Cyril Fougeray
6// Copyright Heudiasyc UMR UTC/CNRS 6599
7//
8// version: $Id: $
9//
10// purpose: Definition of the SickLDMRSSensor class
11*********************************************************************/
12
13
14
15
16#ifndef SICKLDMRSSENSOR_H
17#define SICKLDMRSSENSOR_H
18
19#include "Pacpus/kernel/ComponentBase.h"
20#include "Pacpus/kernel/DbiteFile.h"
21
22#include "AbstractSickSensor.h"
23#include "SickLDMRSData.h"
24#include "AlascaViewer3D.h"
25#include <fstream>
26#include <string>
27
28// Constants for Sick LDMRS
29static const uint32_t DATA_HEADER_SIZE = 24; // in bytes
30static const uint32_t SCAN_HEADER_SIZE = 44; // in bytes
31static const uint32_t MEASURED_POINT_DATA_SIZE = 10; // in bytes
32// @12.5Hz, the sensor has a multiresolution:
33// - lateral range (50 to 30 degrees and -30 to -60 degrees): 0.5 degrees
34// - medium range (30 to 10 degrees and -10 to -30 degrees): 0.25 degrees
35// - central range (10 to -10 degrees): 0.125 degrees
36// So theorically, the max number of points per layer is (20+30)/0.5 + (20+20)/0.25 + 20/0.125 + 1 = 321
37static const uint32_t MAX_SCAN_POINT_PER_LAYER = 321;
38static const uint32_t MAX_SCAN_POINT = 4 * MAX_SCAN_POINT_PER_LAYER; // 4 layers sensor
39static const uint32_t BODY_MAX_SIZE = DATA_HEADER_SIZE + SCAN_HEADER_SIZE + MEASURED_POINT_DATA_SIZE * MAX_SCAN_POINT; // 12 908
40
41// Export macro for SickLDMRS DLL for Windows only
42#ifdef WIN32
43# ifdef SICKLDMRS_EXPORTS
44 // make DLL
45# define SICKLDMRS_API __declspec(dllexport)
46# else
47 // use DLL
48# define SICKLDMRS_API __declspec(dllimport)
49# endif
50#else
51 // On other platforms, simply ignore this
52# define SICKLDMRS_API
53#endif
54
55class QEvent;
56
57namespace pacpus {
58
59class ShMem;
60class SickComponent;
61
62
63
64/// The class carrying Sick LDMRS message.
65/** This class is used so that we can store every information sent by a Sick LDMRS sensor.
66 * First, the raw data is stored in \c body.
67 * These data are then decoded and general information about the message is stored in DataHeader and ScanHeader
68 * (Object data decoding is not implemented yet).
69 * Then, the body field is replaced by a ScanPoint or ScanObject array in order to be stored in DBT/UTC files.
70 */
71class SICKLDMRS_API MessageLDMRS
72{
73public:
74 /// Constructor.
75 MessageLDMRS()
76 {
77 time = 0;
78 timerange = 0;
79 memset(&hData,0,sizeof(hData));
80 memset(&hScan,0,sizeof(hScan));
81 }
82
83 /// Destructor.
84 ~MessageLDMRS(){}
85
86 //! An instance of DataHeader.
87 DataHeader hData;
88
89 //! An instance of ScanHeader (if data type is scan points).
90 ScanHeader hScan;
91
92 //! An array of characters : raw data then array of points or objects, depending on data type.
93 /** This array pointer points to allocated in memory (basically, in heap (malloc)) and then must be freed (free) when the whole message is decoded and stored. */
94 char body[BODY_MAX_SIZE];
95
96 //! Time when the message is received.
97 road_time_t time;
98
99 //! Timerange : roughly, time between measurement of a point and the processing step (not implemented).
100 road_timerange_t timerange;
101};
102
103
104
105//! The class implenting receiving, decoding and storing process of Sick LD-MRS data.
106/**
107 * This class can be used as a particular thread to acquire data from Sick LDMRS sensors.
108 * The Ethernet interface is used to get data from the sensor. Thus, the goal of this class is to
109 * get packets and decode them. Also, it offers the possibility to store all relevant information in
110 * two files (.dbt and .utc).
111 * It can be managed by SickComponent objects.
112 */
113class SickLDMRSSensor : public AbstractSickSensor
114{
115 Q_OBJECT
116public:
117 /// Constructor
118 SickLDMRSSensor(QObject *parent);
119
120 /**
121 * @brief SickLDMRSSensor constructor.
122 * @param parent Basically, a SickComponent object.
123 * @param name Name of the sensor in order to write on .dbt and .utc files and to recognize every sensors used.
124 * @param ip The IP address of the remote Sick LDMRS sensor.
125 * @param port The port of the remote Sick LDMRS sensor.
126 * @param recording If \c true, data is recorded into dbt + utc files. Data is not recorded otherwise.
127 */
128 SickLDMRSSensor(QObject *parent, QString name, QString ip, int port, int recording);
129
130 /// Destructor
131 ~SickLDMRSSensor();
132
133
134 void stopActivity(); /*!< To stop the processing thread */
135 void startActivity(); /*!< To start the processing thread */
136
137 /**
138 * @brief splitPacket reconstitute incoming data and find messages.
139 * @param packet Raw data coming from the sensor.
140 * @param length Length of the data.
141 * @param time Time of the last received data.
142 *
143 * Analyse the ethernet packet received from the Sick sensor and try to find a
144 * complete message (scan data message or object message)
145 * If a message has been found it is added at the end of the message list
146 * else the pending bytes are stored to be analyzed by further incoming data.
147 */
148 void splitPacket(const char * packet, const int length, road_time_t time);
149
150
151 /**
152 * @brief Process/decode a message.
153 * @param msg The message is encapsulated into a MessageLDMRS
154 * @return Type of the message
155 *
156 * Process the raw data of the message and update the MessageLDMRS object passed : it fills the 2 headers (message and scan)
157 * and replace the body field of the MessageLDRMS object by an array of ScanPoint.
158 * - @b Warning : the process of object data type is not implemented yet !
159 */
160 unsigned long processMessage(MessageLDMRS & msg);
161
162 //! Find the position of the magic word into the array and returns this index.
163 /*!
164 * \param message Array of characters, raw data received from sensor.
165 * \param length Length of the array.
166 * \return
167 * - @b -1 if no magic word is found
168 * - @b position of the magic word otherwise
169 */
170 uint32_t findMagicWord(const char * message, const unsigned length);
171
172 /**
173 * @brief getMessageSize get the message size of the entire message.
174 * @param message Raw data of the message.
175 * @param length Length of the raw data received.
176 * @param magicWordIndex First element of the message, used to get the size of the message.
177 * @return The @b size of the whole message.
178 *
179 * The size of the message is found inside the message thanks to an offset after the index of the Magic Word.
180 * - The first header of the message that contains the size of the message is in \b Big \b Endian format !
181 *
182 */
183 uint32_t getMessageSize(const char * message, const unsigned length, const long magicWordIndex);
184
185 /**
186 * @brief isMessageComplete compare the size of the message read into the message and the length of the received data.
187 * @param length Length of the received data.
188 * @param size Size of the message read. See getMessageSize.
189 * @return @b true if the message is complete, @b false otherwise
190 */
191 bool isMessageComplete(const unsigned length, const long size);
192
193public Q_SLOTS:
194 /**
195 * @brief customEvent allows to receive the incoming data and store them into known structures.
196 * @param e Event that carries the Ethernet packets and receiving time.
197 */
198 void customEvent(QEvent * e);
199
200 /**
201 * @brief Configure the object, not used for the moment.
202 */
203 void configure();
204
205public:
206 /**
207 * @brief S_socket, used to receive and send data to the remote sensor.
208 */
209 SickSocket * S_socket;
210
211signals:
212 void refreshDisplay();
213
214private:
215 /// Name is used to recognize between several sensors and store data into .dbt and utc files.
216 QString name_;
217
218 /// The IP address of the remote Sick LDMRS sensor we are connected to.
219 QString ipaddr_;
220
221 /// The SickLDMRS port
222 int port_;
223
224 /// Enable storing in DBT + UTC files
225 bool recording_;
226
227 /// List of messages to process.
228 std::list<MessageLDMRS> msgList;
229
230 /// Received raw data is appended into this MessagePacket.
231 MessagePacket pendingBytes;
232
233 /// Append new data into the private MessagePacket @b pendingBytes.
234 void storePendingBytes(road_time_t time);
235
236 /**
237 * @brief fillDataHeader fills the message header of the message
238 * @param msg
239 * - @b Warning:
240 * - the body field of the message have to be completed before
241 * - Data header format is @b Big @b Endian
242 */
243 void fillDataHeader(MessageLDMRS& msg);
244
245
246 /**
247 * @brief fillScanHeader fill the scan header of the message
248 * @param msg Raw data must be stored into the body field of the message
249 * - @b Warning
250 * - the body field of the message have to be completed before
251 * - Scan header format is @b Little @b Endian
252 */
253 void fillScanHeader(MessageLDMRS& msg);
254
255 /**
256 * @brief Write data into .dbt + .utc files.
257 * @param msg
258 *
259 * SickLDMRS_dbt structure is filled and stored into the DBT file.
260 * The array of ScanPoint is then stored into the UTC file.
261 */
262 void writeData(MessageLDMRS &msg);
263
264 std::string kSickDbtFileName; //!< Name of the DBT file.
265 std::string kSickUtcFileName; //!< Name of the UTC file.
266
267 pacpus::DbiteFile dbtFile_; //!< DBT file.
268 std::ofstream dataFile_; //!< UTC file.
269
270#ifdef SICKLDMRS_SH_MEM
271 ShMem * shmem_;
272 SickLDMRS_shMem sickData;
273#endif
274
275};
276
277} // namespace pacpus
278
279#endif // SICKLDMRSSENSOR_H
Note: See TracBrowser for help on using the repository browser.