lms1xx_node.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 // standard includes
19 #include <csignal>
20 #include <cstdio>
21 
22 // ROS includes
23 #include "ros/ros.h"
24 
25 // ROS message includes
26 #include <sensor_msgs/LaserScan.h>
27 #include <diagnostic_msgs/DiagnosticArray.h>
28 
29 // external includes
30 #include <lms1xx.h>
31 
32 #define DEG2RAD M_PI/180.0
33 
34 
36 {
37 public:
38 
40 
41  bool initalize();
42 
43  void startScanner();
44  void publish();
45  void stopScanner();
46 
48 
49 private:
50 
51  bool initalizeLaser();
52  bool initalizeMessage();
53  void setScanDataConfig();
54  void publishError(std::string error_str);
55 
58 
59  // laser data
64  // published data
65  sensor_msgs::LaserScan scan_msg;
66  // parameters
67  std::string host;
68  std::string frame_id;
69  bool inverted;
70  double resolution;
71  double frequency;
72  bool set_config;
73  double min_range;
74  double max_range;
75 };
76 
78 {
80 
81  scan_pub = nh.advertise<sensor_msgs::LaserScan>("scan", 1);
82  diagnostic_pub = nh.advertise<diagnostic_msgs::DiagnosticArray>("/diagnostics", 1);
83 
84  if(!nh.hasParam("host")) ROS_WARN("Used default parameter for host");
85  nh.param<std::string>("host", host, "192.168.1.2");
86  if(!nh.hasParam("frame_id")) ROS_WARN("Used default parameter for frame_id");
87  nh.param<std::string>("frame_id", frame_id, "base_laser_link");
88  if(!nh.hasParam("inverted")) ROS_WARN("Used default parameter for inverted");
89  nh.param<bool>("inverted", inverted, false);
90  if(!nh.hasParam("angle_resolution")) ROS_WARN("Used default parameter for resolution");
91  nh.param<double>("angle_resolution", resolution, 0.5);
92  if(!nh.hasParam("scan_frequency")) ROS_WARN("Used default parameter for frequency");
93  nh.param<double>("scan_frequency", frequency, 25);
94  if(!nh.hasParam("set_config")) ROS_WARN("Used default parameter for set_config");
95  nh.param<bool>("set_config", set_config, false);
96  if(!nh.hasParam("min_range")) ROS_WARN("Used default parameter for min_range");
97  nh.param<double>("min_range", min_range, 0.01);
98  if(!nh.hasParam("max_range")) ROS_WARN("Used default parameter for max_range");
99  nh.param<double>("max_range", max_range, 20.0);
100 
101  ROS_INFO("connecting to laser at : %s", host.c_str());
102  ROS_INFO("using frame_id : %s", frame_id.c_str());
103  ROS_INFO("inverted : %s", (inverted)?"true":"false");
104  ROS_INFO("using res : %f", resolution);
105  ROS_INFO("using freq : %f", frequency);
106 }
107 
109 {
110  bool ret = false;
111 
112  if (initalizeLaser() && initalizeMessage()) {
113 
115  ret = true;
116  }
117 
118  return ret;
119 }
120 
122 {
123  bool ret = false;
124 
125  laser.connect(host);
126 
127  if (laser.isConnected()) {
128 
129  ROS_INFO("Connected to laser.");
130  ret = true;
131 
132  //setup laserscanner config
133  laser.login();
134  cfg = laser.getScanCfg();
135 
136  if(set_config)
137  {
138  ROS_DEBUG("Set angle resolution to %f deg",resolution);
139  cfg.angleResolution = (int)(resolution * 10000);
140  ROS_DEBUG("Set scan frequency to %f hz",frequency);
141  cfg.scaningFrequency = (int)(frequency * 100);
142 
144  laser.saveConfig();
145  }
146 
147  cfg = laser.getScanCfg();
148 
149  if(cfg.angleResolution != (int)(resolution * 10000))
150  ROS_ERROR("Setting angle resolution failed: Current angle resolution is %f.", cfg.angleResolution/10000.0);
151  if(cfg.scaningFrequency != (int)(frequency * 100))
152  ROS_ERROR("Setting scan frequency failed: Current scan frequency is %f.", cfg.scaningFrequency/100.0);
153 
154  } else {
155  ROS_ERROR("Connection to device failed");
156  publishError("Connection to device failed");
157  }
158  return ret;
159 }
160 
162 {
163  bool ret = true;
164 
165  //init scan msg
166  scan_msg.header.frame_id = frame_id;
167 
168  scan_msg.range_min = min_range;
169  scan_msg.range_max = max_range;
170 
171  scan_msg.scan_time = 100.0/cfg.scaningFrequency;
172 
173  scan_msg.angle_increment = (double)cfg.angleResolution/10000.0 * DEG2RAD;
174  scan_msg.angle_min = (double)cfg.startAngle/10000.0 * DEG2RAD - M_PI/2;
175  scan_msg.angle_max = (double)cfg.stopAngle/10000.0 * DEG2RAD - M_PI/2;
176 
177  int num_values;
178  if (cfg.angleResolution == 2500)
179  {
180  num_values = 1081;
181  }
182  else if (cfg.angleResolution == 5000)
183  {
184  num_values = 541;
185  }
186  else
187  {
188  ROS_ERROR("Unsupported resolution");
189  publishError("Unsupported resolution");
190  ret = false;
191  }
192 
193  scan_msg.time_increment = scan_msg.scan_time/num_values;
194 
195  scan_msg.ranges.resize(num_values);
196  scan_msg.intensities.resize(num_values);
197 
198  if(not inverted)
199  scan_msg.time_increment *= -1.;
200 
201  return ret;
202 }
203 
205 {
206  //set scandata config
207  dataCfg.outputChannel = 1;
208  dataCfg.remission = true;
209  dataCfg.resolution = 1;
210  dataCfg.encoder = 0;
211  dataCfg.position = false;
212  dataCfg.deviceName = false;
213  dataCfg.outputInterval = 1;
214 
216  ROS_DEBUG("setScanDataCfg");
217 
218  laser.startMeas();
219  ROS_DEBUG("startMeas");
220 }
221 
223 {
224  status_t stat;
225  do // wait for ready status
226  {
227  stat = laser.queryStatus();
228  ros::Duration(1.0).sleep();
229  }
230  while (stat != ready_for_measurement);
231 
232  laser.startDevice(); // Log out to properly re-enable system after config
233  ROS_DEBUG("startDevice");
234 
235  laser.scanContinous(1);
236  ROS_DEBUG("scanContinous true");
237 }
238 
240 {
241  scan_msg.header.stamp = ros::Time::now();
242  ++scan_msg.header.seq;
243 
244  if(laser.getData(data))
245  {
246  for (int i = 0; i < data.dist_len1; i++)
247  {
248  if(not inverted) {
249  scan_msg.ranges[i] = data.dist1[data.dist_len1-1-i] * 0.001;
250  scan_msg.intensities[i] = data.rssi1[data.rssi_len1-1-i];
251  } else {
252  scan_msg.ranges[i] = data.dist1[i] * 0.001;
253  scan_msg.intensities[i] = data.rssi1[i];
254  }
255  }
257 
258  //Diagnostics
259  diagnostic_msgs::DiagnosticArray diagnostics;
260  diagnostics.status.resize(1);
261  diagnostics.status[0].level = 0;
262  diagnostics.status[0].name = nh.getNamespace();
263  diagnostics.status[0].message = "sick scanner running";
264  diagnostic_pub.publish(diagnostics);
265  }
266 }
267 
269 {
270  laser.scanContinous(0);
271  ROS_DEBUG("scanContinous false");
272  laser.stopMeas();
273  ROS_DEBUG("stopMeas");
274  laser.disconnect();
275  ROS_DEBUG("disconnect");
276 }
277 
278 void SickLMS1xxNode::publishError(std::string error_str)
279 {
280  diagnostic_msgs::DiagnosticArray diagnostics;
281  diagnostics.status.resize(1);
282  diagnostics.status[0].level = 2;
283  diagnostics.status[0].name = nh.getNamespace();
284  diagnostics.status[0].message = error_str;
285  diagnostic_pub.publish(diagnostics);
286 }
287 
288 
289 //#######################
290 //#### main programm ####
291 int main(int argc, char** argv)
292 {
293  ros::init(argc, argv, "sick_lms1xx_node");
294 
295  SickLMS1xxNode node;
296 
297  if (!node.initalize()) {
298  return 1;
299  }
300 
301  node.startScanner();
302 
303  while(ros::ok())
304  {
305  node.publish();
306 
307  ros::spinOnce();
308  }
309 
310  node.stopScanner();
311 
312  return 0;
313 }
status_t
Definition: lms1xx.h:171
void setScanDataConfig()
bool initalizeMessage()
void setScanDataCfg(const scanDataCfg &cfg)
Set scan data configuration. Set format of scan message returned by device.
Definition: lms1xx.cpp:167
void publish(const boost::shared_ptr< M > &message) const
scanCfg getScanCfg() const
Get current scan configuration. Get scan configuration :
Definition: lms1xx.cpp:134
status_t queryStatus()
Get current status of LMS1xx device.
Definition: lms1xx.cpp:100
bool sleep() const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
int main(int argc, char **argv)
void login()
Log into LMS1xx unit. Increase privilege level, giving ability to change device configuration.
Definition: lms1xx.cpp:119
#define ROS_WARN(...)
bool initalizeLaser()
void stopMeas()
Stop measurements. After receiving this command LMS1xx unit stop spinning laser and measuring...
Definition: lms1xx.cpp:85
ros::Publisher scan_pub
Definition: lms1xx_node.cpp:56
Structure containing single scan message.
Structure containing scan configuration.
void setScanCfg(const scanCfg &cfg)
Set scan configuration. Get scan configuration :
Definition: lms1xx.cpp:154
void startDevice()
The device is returned to the measurement mode after configuration.
Definition: lms1xx.cpp:456
#define ROS_INFO(...)
void scanContinous(int start)
Start or stop continuous data acquisition. After reception of this command device start or stop conti...
Definition: lms1xx.cpp:181
bool param(const std::string &param_name, T &param_val, const T &default_val) const
std::string frame_id
Definition: lms1xx_node.cpp:68
scanDataCfg dataCfg
Definition: lms1xx_node.cpp:62
ROSCPP_DECL bool ok()
const std::string & getNamespace() const
void startMeas()
Start measurements. After receiving this command LMS1xx unit starts spinning laser and measuring...
Definition: lms1xx.cpp:70
bool isConnected()
Get status of connection.
Definition: lms1xx.cpp:66
void disconnect()
Disconnect from LMS1xx device.
Definition: lms1xx.cpp:59
void connect(std::string host, int port=2111)
Connect to LMS1xx.
Definition: lms1xx.cpp:40
void publishError(std::string error_str)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define DEG2RAD
Definition: lms1xx_node.cpp:32
ros::NodeHandle nh
Definition: lms1xx_node.cpp:47
sensor_msgs::LaserScan scan_msg
Definition: lms1xx_node.cpp:65
void saveConfig()
Save data permanently. Parameters are saved in the EEPROM of the LMS and will also be available after...
Definition: lms1xx.cpp:441
bool getData(scanData &data)
Receive single scan message.
Definition: lms1xx.cpp:203
Structure containing scan data configuration.
Class responsible for communicating with LMS1xx device.
Definition: lms1xx.h:189
static Time now()
std::string host
Definition: lms1xx_node.cpp:67
bool hasParam(const std::string &key) const
ROSCPP_DECL void spinOnce()
ros::Publisher diagnostic_pub
Definition: lms1xx_node.cpp:57
#define ROS_ERROR(...)
#define ROS_DEBUG(...)


cob_sick_lms1xx
Author(s): Konrad Banachowicz
autogenerated on Wed Apr 7 2021 02:11:49