xv11_laser.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011, Eric Perko, Chad Rockey
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Case Western Reserve University nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
36 
37 namespace xv_11_laser_driver {
38  XV11Laser::XV11Laser(const std::string& port, uint32_t baud_rate, uint32_t firmware, boost::asio::io_service& io): port_(port),
39  baud_rate_(baud_rate), firmware_(firmware), shutting_down_(false), serial_(io, port_) {
40  serial_.set_option(boost::asio::serial_port_base::baud_rate(baud_rate_));
41  }
42 
43  void XV11Laser::poll(sensor_msgs::LaserScan::Ptr scan) {
44  uint8_t temp_char;
45  uint8_t start_count = 0;
46  bool got_scan = false;
47 
48  if(firmware_ == 1){ // This is for the old driver, the one that only outputs speed once per revolution
49  boost::array<uint8_t, 1440> raw_bytes;
50  while (!shutting_down_ && !got_scan) {
51  // Wait until the start sequence 0x5A, 0xA5, 0x00, 0xC0 comes around
52  boost::asio::read(serial_, boost::asio::buffer(&temp_char,1));
53  if(start_count == 0) {
54  if(temp_char == 0x5A) {
55  start_count = 1;
56  }
57  } else if(start_count == 1) {
58  if(temp_char == 0xA5) {
59  start_count = 2;
60  }
61  } else if(start_count == 2) {
62  if(temp_char == 0x00) {
63  start_count = 3;
64  }
65  } else if(start_count == 3) {
66  if(temp_char == 0xC0) {
67  start_count = 0;
68  // Now that entire start sequence has been found, read in the rest of the message
69  got_scan = true;
70  // Now read speed
71  boost::asio::read(serial_,boost::asio::buffer(&motor_speed_,2));
72 
73  // Read in 360*4 = 1440 chars for each point
74  boost::asio::read(serial_,boost::asio::buffer(&raw_bytes,1440));
75 
76  scan->angle_min = 0.0;
77  scan->angle_max = 2.0*M_PI;
78  scan->angle_increment = (2.0*M_PI/360.0);
79  scan->time_increment = motor_speed_/1e8;
80  scan->range_min = 0.06;
81  scan->range_max = 5.0;
82  scan->ranges.reserve(360);
83  scan->intensities.reserve(360);
84 
85  for(uint16_t i = 0; i < raw_bytes.size(); i=i+4) {
86  // Four bytes per reading
87  uint8_t byte0 = raw_bytes[i];
88  uint8_t byte1 = raw_bytes[i+1];
89  uint8_t byte2 = raw_bytes[i+2];
90  uint8_t byte3 = raw_bytes[i+3];
91  // First two bits of byte1 are status flags
92  uint8_t flag1 = (byte1 & 0x80) >> 7; // No return/max range/too low of reflectivity
93  uint8_t flag2 = (byte1 & 0x40) >> 6; // Object too close, possible poor reading due to proximity kicks in at < 0.6m
94  // Remaining bits are the range in mm
95  uint16_t range = ((byte1 & 0x3F)<< 8) + byte0;
96  // Last two bytes represent the uncertanty or intensity, might also be pixel area of target...
97  uint16_t intensity = (byte3 << 8) + byte2;
98 
99  scan->ranges.push_back(range / 1000.0);
100  scan->intensities.push_back(intensity);
101  }
102  }
103  }
104  }
105  } else if(firmware_ == 2) { // This is for the newer driver that outputs packets 4 pings at a time
106  boost::array<uint8_t, 1980> raw_bytes;
107  uint8_t good_sets = 0;
108  uint32_t motor_speed = 0;
109  rpms=0;
110  int index;
111  while (!shutting_down_ && !got_scan) {
112  // Wait until first data sync of frame: 0xFA, 0xA0
113  boost::asio::read(serial_, boost::asio::buffer(&raw_bytes[start_count],1));
114  if(start_count == 0) {
115  if(raw_bytes[start_count] == 0xFA) {
116  start_count = 1;
117  }
118  } else if(start_count == 1) {
119  if(raw_bytes[start_count] == 0xA0) {
120  start_count = 0;
121 
122  // Now that entire start sequence has been found, read in the rest of the message
123  got_scan = true;
124 
125  boost::asio::read(serial_,boost::asio::buffer(&raw_bytes[2], 1978));
126 
127  scan->angle_min = 0.0;
128  scan->angle_max = 2.0*M_PI;
129  scan->angle_increment = (2.0*M_PI/360.0);
130  scan->range_min = 0.06;
131  scan->range_max = 5.0;
132  scan->ranges.resize(360);
133  scan->intensities.resize(360);
134 
135  //read data in sets of 4
136  for(uint16_t i = 0; i < raw_bytes.size(); i=i+22) {
137  if(raw_bytes[i] == 0xFA && raw_bytes[i+1] == (0xA0+i/22)) {//&& CRC check
138  good_sets++;
139  motor_speed += (raw_bytes[i+3] << 8) + raw_bytes[i+2]; //accumulate count for avg. time increment
140  rpms=(raw_bytes[i+3]<<8|raw_bytes[i+2])/64;
141 
142  for(uint16_t j = i+4; j < i+20; j=j+4) {
143  index = (4*i)/22 + (j-4-i)/4;
144  // Four bytes per reading
145  uint8_t byte0 = raw_bytes[j];
146  uint8_t byte1 = raw_bytes[j+1];
147  uint8_t byte2 = raw_bytes[j+2];
148  uint8_t byte3 = raw_bytes[j+3];
149  // First two bits of byte1 are status flags
150  // uint8_t flag1 = (byte1 & 0x80) >> 7; // No return/max range/too low of reflectivity
151  // uint8_t flag2 = (byte1 & 0x40) >> 6; // Object too close, possible poor reading due to proximity kicks in at < 0.6m
152  // Remaining bits are the range in mm
153  uint16_t range = ((byte1 & 0x3F)<< 8) + byte0;
154  // Last two bytes represent the uncertanty or intensity, might also be pixel area of target...
155  uint16_t intensity = (byte3 << 8) + byte2;
156 
157  scan->ranges[index] = range / 1000.0;
158  scan->intensities[index] = intensity;
159  }
160  }
161  }
162 
163  scan->time_increment = motor_speed/good_sets/1e8;
164  }
165  }
166  }
167  }
168  }
169 };
bool shutting_down_
Flag for whether the driver is supposed to be shutting down or not.
Definition: xv11_laser.h:73
uint32_t firmware_
The firmware version to check. Currently supports two different versions: 1 and 2.
Definition: xv11_laser.h:71
uint32_t baud_rate_
The baud rate for the serial connection.
Definition: xv11_laser.h:70
uint16_t rpms
RPMS derived from the rpm bytes in an XV11 packet.
Definition: xv11_laser.h:43
boost::asio::serial_port serial_
Actual serial port object for reading/writing to the XV11 Laser Scanner.
Definition: xv11_laser.h:74
uint16_t motor_speed_
current motor speed as reported by the XV11.
Definition: xv11_laser.h:75
XV11Laser(const std::string &port, uint32_t baud_rate, uint32_t firmware, boost::asio::io_service &io)
Constructs a new XV11Laser attached to the given serial port.
Definition: xv11_laser.cpp:38
void poll(sensor_msgs::LaserScan::Ptr scan)
Poll the laser to get a new scan. Blocks until a complete new scan is received or close is called...
Definition: xv11_laser.cpp:43


xv_11_laser_driver
Author(s): Eric Perko, Chad Rockey, Rohan Agrawal, Steve 'dillo Okay
autogenerated on Mon Jun 10 2019 15:48:10