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