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


hls-lfcd-lds-driver
Author(s): Pyo , Darby Lim , Gilbert , Will Son , JH Yang, SP Kong
autogenerated on Fri Apr 16 2021 02:20:09