lms1xx_node.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *   http://www.apache.org/licenses/LICENSE-2.0
00009 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016  
00017 
00018 // standard includes
00019 #include <csignal>
00020 #include <cstdio>
00021 
00022 // ROS includes
00023 #include "ros/ros.h"
00024 
00025 // ROS message includes
00026 #include <sensor_msgs/LaserScan.h>
00027 #include <diagnostic_msgs/DiagnosticArray.h>
00028 
00029 // external includes
00030 #include <lms1xx.h>
00031 
00032 #define DEG2RAD M_PI/180.0
00033 
00034 
00035 class SickLMS1xxNode
00036 {
00037 public:
00038 
00039     SickLMS1xxNode();
00040 
00041     bool initalize();
00042 
00043     void startScanner();
00044     void publish();
00045     void stopScanner();
00046 
00047     ros::NodeHandle nh;
00048 
00049 private:
00050 
00051     bool initalizeLaser();
00052     bool initalizeMessage();
00053     void setScanDataConfig();
00054     void publishError(std::string error_str);
00055 
00056     ros::Publisher scan_pub;
00057     ros::Publisher diagnostic_pub;
00058 
00059     // laser data
00060     LMS1xx laser;
00061     scanCfg cfg;
00062     scanDataCfg dataCfg;
00063     scanData data;
00064     // published data
00065     sensor_msgs::LaserScan scan_msg;
00066     // parameters
00067     std::string host;
00068     std::string frame_id;
00069     bool inverted;
00070     double resolution;
00071     double frequency;
00072     bool set_config;
00073     double min_range;
00074     double max_range;
00075 };
00076 
00077 SickLMS1xxNode::SickLMS1xxNode()
00078 {
00079     ros::NodeHandle nh;
00080 
00081     scan_pub = nh.advertise<sensor_msgs::LaserScan>("scan", 1);
00082     diagnostic_pub = nh.advertise<diagnostic_msgs::DiagnosticArray>("/diagnostics", 1);
00083 
00084     if(!nh.hasParam("host")) ROS_WARN("Used default parameter for host");
00085     nh.param<std::string>("host", host, "192.168.1.2");
00086     if(!nh.hasParam("frame_id")) ROS_WARN("Used default parameter for frame_id");
00087     nh.param<std::string>("frame_id", frame_id, "base_laser_link");
00088     if(!nh.hasParam("inverted")) ROS_WARN("Used default parameter for inverted");
00089     nh.param<bool>("inverted", inverted, false);
00090     if(!nh.hasParam("angle_resolution")) ROS_WARN("Used default parameter for resolution");
00091     nh.param<double>("angle_resolution", resolution, 0.5);
00092     if(!nh.hasParam("scan_frequency")) ROS_WARN("Used default parameter for frequency");
00093     nh.param<double>("scan_frequency", frequency, 25);
00094     if(!nh.hasParam("set_config")) ROS_WARN("Used default parameter for set_config");
00095     nh.param<bool>("set_config", set_config, false);
00096     if(!nh.hasParam("min_range")) ROS_WARN("Used default parameter for min_range");
00097     nh.param<double>("min_range", min_range, 0.01);
00098     if(!nh.hasParam("max_range")) ROS_WARN("Used default parameter for max_range");
00099     nh.param<double>("max_range", max_range, 20.0);
00100 
00101     ROS_INFO("connecting to laser at : %s", host.c_str());
00102     ROS_INFO("using frame_id : %s", frame_id.c_str());
00103     ROS_INFO("inverted : %s", (inverted)?"true":"false");
00104     ROS_INFO("using res : %f", resolution);
00105     ROS_INFO("using freq : %f", frequency);
00106 }
00107 
00108 bool SickLMS1xxNode::initalize()
00109 {
00110     bool ret = false;
00111 
00112     if (initalizeLaser() && initalizeMessage()) {
00113 
00114     setScanDataConfig();
00115     ret = true;
00116     }
00117 
00118     return ret;
00119 }
00120 
00121 bool SickLMS1xxNode::initalizeLaser()
00122 {
00123     bool ret = false;
00124 
00125     laser.connect(host);
00126 
00127     if (laser.isConnected()) {
00128 
00129     ROS_INFO("Connected to laser.");
00130     ret = true;
00131 
00132     //setup laserscanner config
00133     laser.login();
00134     cfg = laser.getScanCfg();
00135 
00136     if(set_config)
00137     {
00138       ROS_DEBUG("Set angle resolution to %f deg",resolution);
00139       cfg.angleResolution = (int)(resolution * 10000);
00140       ROS_DEBUG("Set scan frequency to %f hz",frequency);
00141       cfg.scaningFrequency = (int)(frequency * 100);
00142 
00143       laser.setScanCfg(cfg);
00144       laser.saveConfig();
00145     }
00146 
00147     cfg = laser.getScanCfg();
00148 
00149     if(cfg.angleResolution != (int)(resolution * 10000))
00150       ROS_ERROR("Setting angle resolution failed: Current angle resolution is %f.", cfg.angleResolution/10000.0);
00151     if(cfg.scaningFrequency != (int)(frequency * 100))
00152       ROS_ERROR("Setting scan frequency failed: Current scan frequency is %f.", cfg.scaningFrequency/100.0);
00153 
00154     } else {
00155       ROS_ERROR("Connection to device failed");
00156       publishError("Connection to device failed");
00157     }
00158     return ret;
00159 }
00160 
00161 bool SickLMS1xxNode::initalizeMessage()
00162 {
00163     bool ret = true;
00164 
00165     //init scan msg
00166     scan_msg.header.frame_id = frame_id;
00167 
00168     scan_msg.range_min = min_range;
00169     scan_msg.range_max = max_range;
00170 
00171     scan_msg.scan_time = 100.0/cfg.scaningFrequency;
00172 
00173     scan_msg.angle_increment = (double)cfg.angleResolution/10000.0 * DEG2RAD;
00174     scan_msg.angle_min = (double)cfg.startAngle/10000.0 * DEG2RAD - M_PI/2;
00175     scan_msg.angle_max = (double)cfg.stopAngle/10000.0 * DEG2RAD - M_PI/2;
00176 
00177     int num_values;
00178     if (cfg.angleResolution == 2500)
00179     {
00180       num_values = 1081;
00181     }
00182     else if (cfg.angleResolution == 5000)
00183     {
00184       num_values = 541;
00185     }
00186     else
00187     {
00188       ROS_ERROR("Unsupported resolution");
00189       publishError("Unsupported resolution");
00190       ret = false;
00191     }
00192 
00193     scan_msg.time_increment = scan_msg.scan_time/num_values;
00194 
00195     scan_msg.ranges.resize(num_values);
00196     scan_msg.intensities.resize(num_values);
00197 
00198     if(not inverted)
00199       scan_msg.time_increment *= -1.;
00200 
00201     return ret;
00202 }
00203 
00204 void SickLMS1xxNode::setScanDataConfig()
00205 {
00206     //set scandata config
00207     dataCfg.outputChannel = 1;
00208     dataCfg.remission = true;
00209     dataCfg.resolution = 1;
00210     dataCfg.encoder = 0;
00211     dataCfg.position = false;
00212     dataCfg.deviceName = false;
00213     dataCfg.outputInterval = 1;
00214 
00215     laser.setScanDataCfg(dataCfg);
00216     ROS_DEBUG("setScanDataCfg");
00217 
00218     laser.startMeas();
00219     ROS_DEBUG("startMeas");
00220 }
00221 
00222 void SickLMS1xxNode::startScanner()
00223 {
00224     status_t stat;
00225     do // wait for ready status
00226     {
00227       stat = laser.queryStatus();
00228       ros::Duration(1.0).sleep();
00229     }
00230     while (stat != ready_for_measurement);
00231 
00232     laser.startDevice(); // Log out to properly re-enable system after config
00233     ROS_DEBUG("startDevice");
00234 
00235     laser.scanContinous(1);
00236     ROS_DEBUG("scanContinous true");
00237 }
00238 
00239 void SickLMS1xxNode::publish()
00240 {
00241     scan_msg.header.stamp = ros::Time::now();
00242     ++scan_msg.header.seq;
00243 
00244     if(laser.getData(data))
00245     {
00246     for (int i = 0; i < data.dist_len1; i++)
00247     {
00248       if(not inverted) {
00249       scan_msg.ranges[i] = data.dist1[data.dist_len1-1-i] * 0.001;
00250       scan_msg.intensities[i] = data.rssi1[data.rssi_len1-1-i];
00251       } else {
00252       scan_msg.ranges[i] = data.dist1[i] * 0.001;
00253       scan_msg.intensities[i] = data.rssi1[i];
00254       }
00255     }
00256     scan_pub.publish(scan_msg);
00257 
00258     //Diagnostics
00259     diagnostic_msgs::DiagnosticArray diagnostics;
00260     diagnostics.status.resize(1);
00261     diagnostics.status[0].level = 0;
00262     diagnostics.status[0].name = nh.getNamespace();
00263     diagnostics.status[0].message = "sick scanner running";
00264     diagnostic_pub.publish(diagnostics);
00265     }
00266 }
00267 
00268 void SickLMS1xxNode::stopScanner()
00269 {
00270     laser.scanContinous(0);
00271     ROS_DEBUG("scanContinous false");
00272     laser.stopMeas();
00273     ROS_DEBUG("stopMeas");
00274     laser.disconnect();
00275     ROS_DEBUG("disconnect");
00276 }
00277 
00278 void SickLMS1xxNode::publishError(std::string error_str)
00279 {
00280     diagnostic_msgs::DiagnosticArray diagnostics;
00281     diagnostics.status.resize(1);
00282     diagnostics.status[0].level = 2;
00283     diagnostics.status[0].name = nh.getNamespace();
00284     diagnostics.status[0].message = error_str;
00285     diagnostic_pub.publish(diagnostics);
00286 }
00287 
00288 
00289 //#######################
00290 //#### main programm ####
00291 int main(int argc, char** argv)
00292 {
00293     ros::init(argc, argv, "sick_lms1xx_node");
00294 
00295     SickLMS1xxNode node;
00296 
00297     if (!node.initalize()) {
00298       return 1;
00299     }
00300 
00301     node.startScanner();
00302 
00303     while(ros::ok())
00304     {
00305       node.publish();
00306 
00307       ros::spinOnce();
00308     }
00309 
00310     node.stopScanner();
00311 
00312     return 0;
00313 }


cob_sick_lms1xx
Author(s): Konrad Banachowicz
autogenerated on Sat Jun 8 2019 21:02:21