hlds_laser_segment_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 
52 LFCDLaser::~LFCDLaser()
53 {
54  boost::asio::write(serial_, boost::asio::buffer("e", 1)); // stop motor
55 }
56 
57 // This sensor is currently transmitting data every 6 degrees.
58 // It doesn't transmit whole 360 degrees of data.
59 // The improved code below transfers data at a faster rate than the previous one,
60 // but it is updated with only 6 degrees data. The bandwidth also increases 60 times. (15KB/s > 900KB/s)
61 void LFCDLaser::poll(sensor_msgs::LaserScan::Ptr scan)
62 {
63  uint8_t temp_char;
64  bool got_scan = false;
65  boost::array<uint8_t, 42> raw_bytes;
66  uint8_t good_sets = 0;
67  uint32_t motor_speed = 0;
68  rpms=0;
69  int index;
70 
71  while (!shutting_down_ && !got_scan)
72  {
73  // Wait until first data sync of frame: 0xFA, 0xA0
74  boost::asio::read(serial_, boost::asio::buffer(&raw_bytes[0], 1));
75 
76  if(raw_bytes[0] == 0xFA)
77  {
78  // Now that entire start sequence has been found, read in the rest of the message
79  got_scan = true;
80  boost::asio::read(serial_,boost::asio::buffer(&raw_bytes[1], 41));
81 
82  if(raw_bytes[1] >= 0xA0 && raw_bytes[1] <= 0xDB)
83  {
84  int degree_count_num = 0;
85  index = (raw_bytes[1] - 0xA0) * 6;
86  good_sets++;
87 
88  motor_speed += (raw_bytes[3] << 8) + raw_bytes[2]; //accumulate count for avg. time increment
89  rpms=(raw_bytes[3]<<8|raw_bytes[2])/10;
90 
91  //read data in sets of 6
92  for(uint16_t j = 4; j < 40; j = j + 6)
93  {
94  uint8_t byte0 = raw_bytes[j];
95  uint8_t byte1 = raw_bytes[j+1];
96  uint8_t byte2 = raw_bytes[j+2];
97  uint8_t byte3 = raw_bytes[j+3];
98 
99  uint16_t intensity = (byte1 << 8) + byte0;
100  uint16_t range = (byte3 << 8) + byte2;
101 
102  scan->ranges[359 - index - degree_count_num] = range / 1000.0;
103  scan->intensities[359 - index - degree_count_num] = intensity;
104 
105  degree_count_num++;
106  }
107 
108  scan->time_increment = motor_speed/good_sets/1e8;
109  }
110  }
111  }
112 }
113 }
114 
115 int main(int argc, char **argv)
116 {
117  ros::init(argc, argv, "hlds_laser_segment_publisher");
118  ros::NodeHandle n;
119  ros::NodeHandle priv_nh("~");
120 
121  std::string port;
122  int baud_rate;
123  std::string frame_id;
124 
125  std_msgs::UInt16 rpms;
126 
127  priv_nh.param("port", port, std::string("/dev/ttyUSB0"));
128  priv_nh.param("baud_rate", baud_rate, 230400);
129  priv_nh.param("frame_id", frame_id, std::string("laser"));
130 
131  boost::asio::io_service io;
132 
133  try
134  {
135  hls_lfcd_lds::LFCDLaser laser(port, baud_rate, io);
136  ros::Publisher laser_pub = n.advertise<sensor_msgs::LaserScan>("scan", 1000);
137  ros::Publisher motor_pub = n.advertise<std_msgs::UInt16>("rpms",1000);
138  sensor_msgs::LaserScan::Ptr scan(new sensor_msgs::LaserScan);
139 
140  scan->header.frame_id = frame_id;
141  scan->angle_increment = (2.0*M_PI/360.0);
142  scan->angle_min = 0.0;
143  scan->angle_max = 2.0*M_PI-scan->angle_increment;
144  scan->range_min = 0.12;
145  scan->range_max = 3.5;
146  scan->ranges.resize(360);
147  scan->intensities.resize(360);
148 
149  while (ros::ok())
150  {
151  laser.poll(scan);
152  scan->header.stamp = ros::Time::now();
153  rpms.data=laser.rpms;
154  laser_pub.publish(scan);
155  motor_pub.publish(rpms);
156  }
157  laser.close();
158 
159  return 0;
160  }
161  catch (boost::system::system_error ex)
162  {
163  ROS_ERROR("An exception was thrown: %s", ex.what());
164  return -1;
165  }
166 }
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.
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)
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...
int main(int argc, char **argv)
static Time now()
#define ROS_ERROR(...)


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