hlds_lds2_publisher.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright (c) 2016, Hitachi-LG Data Storage
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * * Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *******************************************************************************/
30 
31  /* Authors: SP Kong, Jeehoon Yang */
32  /* maintainer: Jeehoon Yang */
33 
34 #include <ros/ros.h>
35 #include <sensor_msgs/LaserScan.h>
36 #include <boost/asio.hpp>
38 #include <std_msgs/UInt16.h>
39 
40 namespace hls_lfcd_lds2
41 {
42 LFCDLaser::LFCDLaser(const std::string& port, uint32_t baud_rate, boost::asio::io_service& io)
43  : port_(port), baud_rate_(baud_rate), shutting_down_(false), serial_(io, port_)
44 {
45  serial_.set_option(boost::asio::serial_port_base::baud_rate(baud_rate_));
46 
47  boost::asio::write(serial_, boost::asio::buffer("b", 1)); // start motor
48 }
49 
51 {
52  boost::asio::write(serial_, boost::asio::buffer("e", 1)); // stop motor
53  boost::asio::write(serial_, boost::asio::buffer("e", 1)); // stop motor
54 }
55 
56 void LFCDLaser::poll(sensor_msgs::LaserScan::Ptr scan)
57 {
58  uint8_t temp_char;
59  uint8_t start_count = 0;
60  bool got_scan = false;
61  boost::array<uint8_t, 1980> raw_bytes;
62  uint8_t good_sets = 0;
63  uint32_t motor_speed = 0;
64  rpms=0;
65  int index;
66 
67  while (!shutting_down_ && !got_scan)
68  {
69  // Wait until first data sync of frame: 0xFA, 0xA0
70  boost::asio::read(serial_, boost::asio::buffer(&raw_bytes[start_count],1));
71 
72  if(start_count == 0)
73  {
74  if(raw_bytes[start_count] == 0xFA)
75  {
76  start_count = 1;
77  }
78  }
79  else if(start_count == 1)
80  {
81  if(raw_bytes[start_count] == 0xA0)
82  {
83  start_count = 0;
84 
85  // Now that entire start sequence has been found, read in the rest of the message
86  got_scan = true;
87 
88  boost::asio::read(serial_,boost::asio::buffer(&raw_bytes[2], 1978));
89 
90  scan->angle_min = 0.0;
91  scan->angle_max = 2.0*M_PI-scan->angle_increment;
92  scan->angle_increment = (2.0*M_PI/360.0);
93  scan->range_min = 0.12;
94  scan->range_max = 5.0;
95  scan->ranges.resize(360);
96  scan->intensities.resize(360);
97 
98  //read data in sets of 4
99  for(uint16_t i = 0; i < raw_bytes.size(); i=i+22)
100  {
101  if(raw_bytes[i] == 0xFA && raw_bytes[i+1] == (0xA0 + i / 22))
102  {
103  good_sets++;
104  motor_speed += (raw_bytes[i+3] << 8) + raw_bytes[i+2];
105  rpms=(raw_bytes[i+3]<<8|raw_bytes[i+2])/10;
106 
107  for(uint16_t j = i+4; j < i+20; j=j+4)
108  {
109  index = 4*(i/22) + (j-4-i)/4;
110 
111  // Four bytes per reading
112  uint8_t byte0 = raw_bytes[j];
113  uint8_t byte1 = raw_bytes[j+1];
114  uint8_t byte2 = raw_bytes[j+2];
115  uint8_t byte3 = raw_bytes[j+3];
116 
117  // Remaining bits are the range in mm
118  uint16_t range = ((byte1 & 0x3F)<< 8) + byte0;
119 
120  // Last two bytes represent the uncertanty or intensity, might also be pixel area of target...
121  uint16_t intensity = (byte3 << 8) + byte2;
122 
123  scan->ranges[359-index] = range / 1000.0;
124  scan->intensities[359-index] = intensity;
125  }
126  }
127  }
128 
129  scan->time_increment = motor_speed/good_sets/1e8;
130  }
131  else
132  {
133  start_count = 0;
134  }
135  }
136  }
137 }
138 }
139 
140 int main(int argc, char **argv)
141 {
142  ros::init(argc, argv, "hlds_lds2_publisher");
143  ros::NodeHandle n;
144  ros::NodeHandle priv_nh("~");
145 
146  std::string port;
147  int baud_rate;
148  std::string frame_id;
149 
150  std_msgs::UInt16 rpms;
151 
152  priv_nh.param("port", port, std::string("/dev/ttyUSB0"));
153  priv_nh.param("baud_rate", baud_rate, 115200);
154  priv_nh.param("frame_id", frame_id, std::string("laser"));
155 
156  boost::asio::io_service io;
157 
158  try
159  {
160  hls_lfcd_lds2::LFCDLaser laser(port, baud_rate, io);
161  ros::Publisher laser_pub = n.advertise<sensor_msgs::LaserScan>("scan", 1000);
162  ros::Publisher motor_pub = n.advertise<std_msgs::UInt16>("rpms",1000);
163 
164  while (ros::ok())
165  {
166  sensor_msgs::LaserScan::Ptr scan(new sensor_msgs::LaserScan);
167  scan->header.frame_id = frame_id;
168  laser.poll(scan);
169  scan->header.stamp = ros::Time::now();
170  rpms.data=laser.rpms;
171  laser_pub.publish(scan);
172  motor_pub.publish(rpms);
173  }
174  laser.close();
175 
176  return 0;
177  }
178  catch (boost::system::system_error ex)
179  {
180  ROS_ERROR("An exception was thrown: %s", ex.what());
181  return -1;
182  }
183 }
boost::asio::serial_port serial_
Actual serial port object for reading/writing to the LFCD Laser Scanner.
Definition: lfcd_lds2.h:73
void publish(const boost::shared_ptr< M > &message) const
LFCDLaser(const std::string &port, uint32_t baud_rate, boost::asio::io_service &io)
Constructs a new LFCDLaser attached to the given serial port.
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void close()
Close the driver down and prevent the polling loop from advancing.
Definition: lfcd_lds2.h:67
~LFCDLaser()
Default destructor.
bool param(const std::string &param_name, T &param_val, const T &default_val) const
ROSCPP_DECL bool ok()
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool shutting_down_
Flag for whether the driver is supposed to be shutting down or not.
Definition: lfcd_lds2.h:72
uint16_t rpms
RPMS derived from the rpm bytes in an LFCD packet.
Definition: lfcd_lds2.h:44
int main(int argc, char **argv)
static Time now()
uint32_t baud_rate_
The baud rate for the serial connection.
Definition: lfcd_lds2.h:71
#define ROS_ERROR(...)
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...


hls-lfcd-lds2-driver
Author(s): SP Kong, Jeehoon Yang
autogenerated on Mon Jun 10 2019 13:24:10