Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpSickLDMRS.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Sick LD-MRS laser driver on UNIX platform.
32 */
33
40
41#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
42
43#include <errno.h>
44#include <fcntl.h>
45#include <netdb.h>
46#include <netinet/in.h>
47#include <string.h>
48#include <sys/select.h>
49#include <sys/socket.h>
50#include <visp3/core/vpDebug.h>
51#include <visp3/core/vpMath.h>
52#include <visp3/core/vpTime.h>
53#include <visp3/sensor/vpSickLDMRS.h>
54//#include <strings.h>
55#include <assert.h>
56#include <limits.h>
57#include <math.h>
58#include <stdlib.h>
59
68 : socket_fd(-1), body(nullptr), vAngle(), time_offset(0), isFirstMeasure(true), maxlen_body(104000)
69{
70 ip = "131.254.12.119";
71 port = 12002;
72 body = new unsigned char[maxlen_body];
73
74 vAngle.resize(4); // Vertical angle of the 4 layers
75 vAngle[0] = vpMath::rad(-1.2);
76 vAngle[1] = vpMath::rad(-0.4);
77 vAngle[2] = vpMath::rad(0.4);
78 vAngle[3] = vpMath::rad(1.2);
79}
80
85{
86 if (body)
87 delete[] body;
88}
89
99bool vpSickLDMRS::setup(const std::string &ip_address, int com_port)
100{
101 setIpAddress(ip_address);
102 setPort(com_port);
103 return (this->setup());
104}
105
112{
113 struct sockaddr_in serv_addr;
114 int res;
115 struct timeval tv;
116 fd_set myset;
117
118 // Create the TCP socket
119 socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
120 if (socket_fd < 0) {
121 fprintf(stderr, "Failed to create socket\n");
122 return false;
123 }
124 // bzero(&serv_addr, sizeof(serv_addr));
125 memset(&serv_addr, 0, sizeof(serv_addr));
126 serv_addr.sin_family = AF_INET; // Internet/IP
127 serv_addr.sin_addr.s_addr = inet_addr(ip.c_str()); // IP address
128 serv_addr.sin_port = htons(port); // server port
129
130 // Establish connection
131 res = connect(socket_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
132 if (errno == EINPROGRESS) {
133 tv.tv_sec = 3;
134 tv.tv_usec = 0;
135 FD_ZERO(&myset);
136 FD_SET(static_cast<unsigned int>(socket_fd), &myset);
137 res = select(socket_fd + 1, nullptr, &myset, nullptr, &tv);
138 if (res < 0 && errno != EINTR) {
139 fprintf(stderr, "Error connecting to server %d - %s\n", errno, strerror(errno));
140 return false;
141 }
142 else if (res > 0) {
143 fprintf(stderr, "ok");
144 }
145 else {
146 fprintf(stderr, "Timeout in select() - Cancelling!\n");
147 return false;
148 }
149 }
150
151 return true;
152}
153
161{
162 unsigned int *uintptr;
163 unsigned short *ushortptr;
164 static unsigned char header[24];
165 ushortptr = (unsigned short *)header;
166 uintptr = (unsigned int *)header;
167
168 assert(sizeof(header) == 24);
169 // std::cout << "size " << sizeof(header) << std::endl;
170
171 double time_second = 0;
172
173 if (isFirstMeasure) {
174 time_second = vpTime::measureTimeSecond();
175 }
176
177 // read the 24 bytes header
178 if (recv(socket_fd, header, sizeof(header), MSG_WAITALL) == -1) {
179 printf("recv\n");
180 perror("recv");
181 return false;
182 }
183
184 if (ntohl(uintptr[0]) != vpSickLDMRS::MagicWordC2) {
185 printf("Error, wrong magic number !!!\n");
186 return false;
187 }
188
189 // get the message body
190 uint16_t msgtype = ntohs(ushortptr[7]);
191 uint32_t msgLength = ntohl(uintptr[2]);
192
193 ssize_t len = recv(socket_fd, body, msgLength, MSG_WAITALL);
194 if (len != (ssize_t)msgLength) {
195 printf("Error, wrong msg length: %d of %d bytes.\n", static_cast<int>(len), msgLength);
196 return false;
197 }
198
199 if (msgtype != vpSickLDMRS::MeasuredData) {
200 // printf("The message in not relative to measured data !!!\n");
201 return true;
202 }
203
204 // decode measured data
205
206 // get the measurement number
207 unsigned short measurementId;
208 ushortptr = (unsigned short *)body;
209 measurementId = ushortptr[0];
210
211 // get the start timestamp
212 uintptr = (unsigned int *)(body + 6);
213 unsigned int seconds = uintptr[1];
214 unsigned int fractional = uintptr[0];
215 double startTimestamp = seconds + fractional / 4294967296.; // 4294967296. = 2^32
216
217 // get the end timestamp
218 uintptr = (unsigned int *)(body + 14);
219 seconds = uintptr[1];
220 fractional = uintptr[0];
221 double endTimestamp = seconds + fractional / 4294967296.; // 4294967296. = 2^32
222
223 // compute the time offset to bring the measures in the Unix time reference
224 if (isFirstMeasure) {
225 time_offset = time_second - startTimestamp;
226 isFirstMeasure = false;
227 }
228
229 startTimestamp += time_offset;
230 endTimestamp += time_offset;
231
232 // get the number of steps per scanner rotation
233 unsigned short numSteps = ushortptr[11];
234
235 // get the start/stop angle
236 short startAngle = (short)ushortptr[12];
237 short stopAngle = (short)ushortptr[13];
238
239 // get the number of points of this measurement
240 unsigned short numPoints = ushortptr[14];
241
242 int nlayers = 4;
243 for (int i = 0; i < nlayers; i++) {
244 laserscan[i].clear();
245 laserscan[i].setMeasurementId(measurementId);
246 laserscan[i].setStartTimestamp(startTimestamp);
247 laserscan[i].setEndTimestamp(endTimestamp);
248 laserscan[i].setNumSteps(numSteps);
249 laserscan[i].setStartAngle(startAngle);
250 laserscan[i].setStopAngle(stopAngle);
251 laserscan[i].setNumPoints(numPoints);
252 }
253
254 // decode the measured points
255 double hAngle; // horizontal angle in rad
256 double rDist; // radial distance in meters
257 vpScanPoint scanPoint;
258
259 if (numPoints > USHRT_MAX - 2)
260 throw(vpException(vpException::ioError, "Out of range number of point"));
261
262 for (int i = 0; i < numPoints; i++) {
263 ushortptr = (unsigned short *)(body + 44 + i * 10);
264 unsigned char layer = ((unsigned char)body[44 + i * 10]) & 0x0F;
265 unsigned char echo = ((unsigned char)body[44 + i * 10]) >> 4;
266 // unsigned char flags = (unsigned char) body[44+i*10+1];
267
268 if (echo == 0) {
269 hAngle = (2.f * M_PI / numSteps) * (short)ushortptr[1];
270 rDist = 0.01 * ushortptr[2]; // cm to meters conversion
271
272 // vpTRACE("layer: %d d: %f hangle: %f", layer, rDist, hAngle);
273 scanPoint.setPolar(rDist, hAngle, vAngle[layer]);
274 laserscan[layer].addPoint(scanPoint);
275 }
276 }
277 return true;
278}
279END_VISP_NAMESPACE
280#endif
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ ioError
I/O error.
Definition vpException.h:67
Implements a laser scan data structure that contains especially the list of scanned points that have ...
Definition vpLaserScan.h:63
void setNumPoints(const unsigned short &num_points)
void setStopAngle(const short &stop_angle)
void setMeasurementId(const unsigned short &id)
Definition vpLaserScan.h:98
void setNumSteps(const unsigned short &num_steps)
void setStartTimestamp(const double &start_timestamp)
void addPoint(const vpScanPoint &p)
Definition vpLaserScan.h:87
void clear()
Definition vpLaserScan.h:89
void setEndTimestamp(const double &end_timestamp)
void setStartAngle(const short &start_angle)
void setPort(int com_port)
std::string ip
void setIpAddress(std::string ip_address)
static double rad(double deg)
Definition vpMath.h:129
Class that defines a single laser scanner point.
Definition vpScanPoint.h:74
void setPolar(double r_dist, double h_angle, double v_angle)
bool isFirstMeasure
virtual ~vpSickLDMRS() VP_OVERRIDE
unsigned char * body
size_t maxlen_body
vpColVector vAngle
double time_offset
bool measure(vpLaserScan laserscan[4])
VISP_EXPORT double measureTimeSecond()