ViSP  2.6.2
vpSickLDMRS.cpp
1 /****************************************************************************
2  *
3  * $Id: vpSickLDMRS.cpp 3842 2012-07-13 22:21:42Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2012 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 #ifdef UNIX
43 #include "visp/vpSickLDMRS.h"
44 #include "visp/vpMath.h"
45 #include "visp/vpDebug.h"
46 #include "visp/vpTime.h"
47 #include <sys/socket.h>
48 #include <netinet/in.h>
49 #include <fcntl.h>
50 #include <errno.h>
51 #include <netdb.h>
52 #include <string.h>
53 #include <strings.h>
54 #include <math.h>
55 #include <assert.h>
56 #include <stdlib.h>
57 
58 
59 
74 {
75  ip = "131.254.12.119";
76  port = 12002;
77  body = new unsigned char [104000];
78  isFirstMeasure = true;
79  time_offset = 0;
80 
81  vAngle.resize(4); // Vertical angle of the 4 layers
82  vAngle[0] = vpMath::rad(-1.2);
83  vAngle[1] = vpMath::rad(-0.4);
84  vAngle[2] = vpMath::rad( 0.4);
85  vAngle[3] = vpMath::rad( 1.2);
86 
87 }
88 
93 {
94  if (body)
95  delete [] body;
96 }
97 
107 bool vpSickLDMRS::setup(std::string ip, int port)
108 {
109  setIpAddress( ip );
110  setPort( port );
111  return ( this->setup() );
112 }
113 
120 {
121  struct sockaddr_in serv_addr;
122  int res;
123  struct timeval tv;
124  fd_set myset;
125 
126  // Create the TCP socket
127  socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
128  if (socket_fd < 0) {
129  fprintf(stderr, "Failed to create socket\n");
130  return false;
131  }
132  bzero(&serv_addr, sizeof(serv_addr));
133  serv_addr.sin_family = AF_INET; // Internet/IP
134  serv_addr.sin_addr.s_addr = inet_addr(ip.c_str()); // IP address
135  serv_addr.sin_port = htons(port); // server port
136 
137  // Establish connection
138  res = connect(socket_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) ;
139  if (errno == EINPROGRESS) {
140  tv.tv_sec = 3;
141  tv.tv_usec = 0;
142  FD_ZERO(&myset);
143  FD_SET(static_cast<unsigned int>(socket_fd), &myset);
144  res = select(socket_fd+1, NULL, &myset, NULL, &tv);
145  if (res < 0 && errno != EINTR) {
146  fprintf(stderr, "Error connecting to server %d - %s\n", errno, strerror(errno));
147  return false;
148  }
149  else if (res > 0) {
150  fprintf(stderr,"ok");
151  }
152  else {
153  fprintf(stderr, "Timeout in select() - Cancelling!\n");
154  return false;
155  }
156  }
157 
158  return true;
159 }
160 
168 {
169  unsigned int *uintptr;
170  unsigned short *ushortptr;
171  static unsigned char header[24];
172  ushortptr=(unsigned short *)header;
173  uintptr=(unsigned int *)header;
174 
175  assert (sizeof(header) == 24);
176  //std::cout << "size " << sizeof(header) << std::endl;
177 
178  double time_second = 0;
179 
180  if (isFirstMeasure) {
181  time_second = vpTime::measureTimeSecond();
182  }
183 
184  // read the 24 bytes header
185  if (recv(socket_fd, header, sizeof(header), MSG_WAITALL) == -1) {
186  printf("recv\n");
187  perror("recv");
188  return false;
189  }
190 
191  if (ntohl(uintptr[0]) != vpSickLDMRS::MagicWordC2) {
192  printf("Error, wrong magic number !!!\n");
193  return false;
194  }
195 
196  // get the message body
197  uint16_t msgtype = ntohs(ushortptr[7]);
198  uint32_t msgLength = ntohl(uintptr[2]);
199 
200  ssize_t len = recv(socket_fd, body, msgLength, MSG_WAITALL);
201  if (len != (ssize_t)msgLength){
202  printf("Error, wrong msg length: %d of %d bytes.\n", (int)len, msgLength);
203  return false;
204  }
205 
206  if (msgtype!=vpSickLDMRS::MeasuredData){
207  //printf("The message in not relative to measured data !!!\n");
208  return true;
209  }
210 
211  // decode measured data
212 
213  // get the measurement number
214  unsigned short measurementId;
215  ushortptr = (unsigned short *) body;
216  measurementId = ushortptr[0];
217 
218  // get the start timestamp
219  uintptr=(unsigned int *) (body+6);
220  unsigned int seconds = uintptr[1];
221  unsigned int fractional=uintptr[0];
222  double startTimestamp = seconds + fractional / 4294967296.; // 4294967296. = 2^32
223 
224  // get the end timestamp
225  uintptr=(unsigned int *) (body+14);
226  seconds = uintptr[1];
227  fractional=uintptr[0];
228  double endTimestamp = seconds + fractional / 4294967296.; // 4294967296. = 2^32
229 
230  // compute the time offset to bring the measures in the Unix time reference
231  if (isFirstMeasure) {
232  time_offset = time_second - startTimestamp;
233  isFirstMeasure = false;
234  }
235 
236  startTimestamp += time_offset;
237  endTimestamp += time_offset;
238 
239  // get the number of steps per scanner rotation
240  unsigned short numSteps = ushortptr[11];
241 
242  // get the start/stop angle
243  short startAngle = (short)ushortptr[12];
244  short stopAngle = (short)ushortptr[13];
245 // std::cout << "angle in [" << startAngle << "; " << stopAngle
246 // << "]" << std::endl;
247 
248  // get the number of points of this measurement
249  unsigned short numPoints = ushortptr[14];
250 
251  int nlayers = 4;
252  for (int i=0; i < nlayers; i++) {
253  laserscan[i].clear();
254  laserscan[i].setMeasurementId(measurementId);
255  laserscan[i].setStartTimestamp(startTimestamp);
256  laserscan[i].setEndTimestamp(endTimestamp);
257  laserscan[i].setNumSteps(numSteps);
258  laserscan[i].setStartAngle(startAngle);
259  laserscan[i].setStopAngle(stopAngle);
260  laserscan[i].setNumPoints(numPoints);
261  }
262 
263  // decode the measured points
264  double hAngle; // horizontal angle in rad
265  double rDist; // radial distance in meters
266  vpScanPoint scanPoint;
267 
268  for (int i=0; i < numPoints; i++) {
269  ushortptr = (unsigned short *) (body+44+i*10);
270  unsigned char layer = ((unsigned char) body[44+i*10])&0x0F;
271  unsigned char echo = ((unsigned char) body[44+i*10])>>4;
272  //unsigned char flags = (unsigned char) body[44+i*10+1];
273 
274  if (echo==0) {
275  hAngle = (2.f * M_PI / numSteps)*(short) ushortptr[1];
276  rDist = 0.01 * ushortptr[2]; // cm to meters conversion
277 
278  //vpTRACE("layer: %d d: %f hangle: %f", layer, rDist, hAngle);
279  scanPoint.setPolar(rDist, hAngle, vAngle[layer]);
280  laserscan[layer].addPoint(scanPoint);
281  }
282  }
283  return true;
284 }
285 
286 #endif
void setMeasurementId(const unsigned short &measurementId)
Definition: vpLaserScan.h:106
std::string ip
void setPort(int port)
The magic word that allows to identify the messages that are sent by the Sick LD-MRS.
Definition: vpSickLDMRS.h:113
void setNumPoints(const unsigned short &numPoints)
Definition: vpLaserScan.h:130
void setStartAngle(const short &startAngle)
Definition: vpLaserScan.h:122
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:97
virtual ~vpSickLDMRS()
Definition: vpSickLDMRS.cpp:92
void setEndTimestamp(const double &endTimestamp)
Definition: vpLaserScan.h:114
void setIpAddress(std::string ip)
Class that defines a single laser scanner point.
Definition: vpScanPoint.h:74
Flag to indicate that the body of a message contains measured data.
Definition: vpSickLDMRS.h:116
static double rad(double deg)
Definition: vpMath.h:100
void setStopAngle(const short &stopAngle)
Definition: vpLaserScan.h:126
bool measure(vpLaserScan laserscan[4])
void setNumSteps(const unsigned short &numSteps)
Definition: vpLaserScan.h:118
void setPolar(double rDist, double hAngle, double vAngle)
Definition: vpScanPoint.h:108
void addPoint(const vpScanPoint &p)
Definition: vpLaserScan.h:93
void setStartTimestamp(const double &startTimestamp)
Definition: vpLaserScan.h:110
static double measureTimeSecond()
Definition: vpTime.cpp:225
SOCKET socket_fd
Definition: vpSickLDMRS.h:131
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:94