mrpt_sensorlib.cpp
Go to the documentation of this file.
1 /* mrpt_sensors ROS package
2  *
3  * Copyright 2021-2022, Jose Luis Blanco Claraco
4  * License: BSD 3-Clause License
5  */
6 
8 #include <mrpt/system/filesystem.h>
9 #include <mrpt/serialization/CArchive.h>
10 #include <mrpt/config/CConfigFile.h>
11 #include <mrpt/config/CConfigFileMemory.h>
12 #include <mrpt/io/vector_loadsave.h> // file_get_contents()
13 
14 #include <mrpt/ros1bridge/point_cloud2.h>
15 #include <mrpt/ros1bridge/time.h>
16 #include <mrpt/obs/CObservationVelodyneScan.h>
17 #include <mrpt/maps/CSimplePointsMap.h>
18 
19 using namespace mrpt::hwdrivers;
20 using namespace mrpt_sensorlib;
21 using mrpt::config::CConfigFile;
22 
23 GenericSensorNode::GenericSensorNode() {}
24 
25 GenericSensorNode::~GenericSensorNode() {}
26 
27 void GenericSensorNode::internal_init()
28 {
29  try
30  {
31  ASSERT_(cfgfile_);
32 
33  // Call sensor factory:
34  std::string driver_name =
35  cfgfile_->read_string(cfg_section_, "driver", "", true);
36  sensor_ = mrpt::hwdrivers::CGenericSensor::createSensorPtr(driver_name);
37  if (!sensor_)
38  {
40  "Sensor class name not recognized: " << driver_name);
41  return;
42  }
43 
44  // Load common & sensor specific parameters:
45  sensor_->loadConfig(*cfgfile_, cfg_section_);
46 
47  // Initialize sensor:
48  sensor_->initialize();
49 
50  // Custom init:
51  this->init_sensor_specific();
52 
53  // Open rawlog file, if enabled:
54  if (!out_rawlog_prefix_.empty())
55  {
56  // Build full rawlog file name:
57 
58  std::string rawlog_postfix = "_";
59 
60  // rawlog_postfix += dateTimeToString( now() );
61  mrpt::system::TTimeParts parts;
62  mrpt::system::timestampToParts(mrpt::system::now(), parts, true);
63  rawlog_postfix += mrpt::format(
64  "%04u-%02u-%02u_%02uh%02um%02us", (unsigned int)parts.year,
65  (unsigned int)parts.month, (unsigned int)parts.day,
66  (unsigned int)parts.hour, (unsigned int)parts.minute,
67  (unsigned int)parts.second);
68 
69  rawlog_postfix =
70  mrpt::system::fileNameStripInvalidChars(rawlog_postfix);
71 
72  const std::string fil = out_rawlog_prefix_ + rawlog_postfix;
73  // auto out_arch = archiveFrom(out_rawlog_);
74  ROS_INFO("Writing rawlog to file: `%s`", fil.c_str());
75 
76  out_rawlog_.open(fil, rawlog_GZ_compress_level_);
77 
78  if (!out_rawlog_.is_open())
79  ROS_ERROR("Error opening output rawlog for writing");
80  }
81  }
82  catch (const std::exception& e)
83  {
85  "Exception in GenericSensorNode::init(): " << e.what());
86  return;
87  }
88 }
89 
90 void GenericSensorNode::init_from_config_file( //
91  [[maybe_unused]] int argc, [[maybe_unused]] char** argv)
92 {
93  try
94  {
95  // Load parameters:
96  std::string cfgFileName;
97  nhlocal_.getParam("config_file", cfgFileName);
98  cfgfilename_ = cfgFileName;
99 
100  cfgfile_ = std::make_shared<mrpt::config::CConfigFile>(*cfgfilename_);
101 
102  nhlocal_.getParam("config_section", cfg_section_);
103 
104  internal_init();
105  }
106  catch (const std::exception& e)
107  {
109  "Exception in GenericSensorNode::init(): " << e.what());
110  return;
111  }
112 }
113 
114 void GenericSensorNode::init_from_template_and_parameters( //
115  [[maybe_unused]] int argc, [[maybe_unused]] char** argv)
116 {
117  using namespace std::string_literals;
118 
119  try
120  {
121  // Load parameters:
122  std::string templateFileName;
123  nhlocal_.getParam("template_file", templateFileName);
124  cfgfilename_ = templateFileName;
125 
126  ASSERT_FILE_EXISTS_(templateFileName);
127 
128  // Read template INI file and prepend all ROS node parameters:
129  std::string cfgContents = mrpt::io::file_get_contents(templateFileName);
130 
131  // prepend ros node params:
132  ros::V_string allParams;
133  nhlocal_.getParamNames(allParams);
134  for (const auto& paramName : allParams)
135  {
136  std::string value;
137  if (!nhlocal_.getParam(paramName, value)) continue;
138 
139  cfgContents =
140  "@define "s + paramName + " "s + value + "\n" + cfgContents;
141  }
142 
143  ROS_INFO_STREAM("cfgContents:\n" << cfgContents);
144 
145  // Parse and run:
146  cfgfile_ =
147  std::make_shared<mrpt::config::CConfigFileMemory>(cfgContents);
148  nhlocal_.getParam("template_file_section", cfg_section_);
149 
150  internal_init();
151  }
152  catch (const std::exception& e)
153  {
155  "Exception in GenericSensorNode::init(): " << e.what());
156  return;
157  }
158 }
159 
161 void GenericSensorNode::run()
162 {
163  ROS_INFO("Starting run() at %.02f Hz", sensor_->getProcessRate());
164  if (!sensor_)
165  {
166  ROS_ERROR("Aborting: sensor object was not properly initialized.");
167  return;
168  }
169  ros::Rate loop_rate(sensor_->getProcessRate());
170  while (ros::ok())
171  {
172  sensor_->doProcess();
173 
174  // Get new observations
175  CGenericSensor::TListObservations lstObjs = sensor_->getObservations();
176 
177  for (const auto& o : lstObjs)
178  {
179  if (const auto& obs =
180  std::dynamic_pointer_cast<mrpt::obs::CObservation>(
181  o.second);
182  obs)
183  on_observation(obs);
184  }
185 
186  if (out_rawlog_.is_open())
187  {
188  auto out_arch = mrpt::serialization::archiveFrom(out_rawlog_);
189  for (const auto& o : lstObjs)
190  {
191  out_arch << *o.second;
192  }
193  }
194 
195  ros::spinOnce();
196  }
197 }
198 
199 void GenericSensorNode::on_observation(const mrpt::obs::CObservation::Ptr& o)
200 {
201  ASSERT_(o);
202 
203  if (const auto& obsVel =
204  std::dynamic_pointer_cast<mrpt::obs::CObservationVelodyneScan>(o);
205  obsVel)
206  {
207  on_observation_velodyne(*obsVel);
208  }
209  else
210  {
211  ROS_WARN(
212  "Do not know how to publish observation '%s' of type '%s'",
213  o->sensorLabel.c_str(), o->GetRuntimeClass()->className);
214  }
215 }
216 
217 void GenericSensorNode::on_observation_velodyne(
218  const mrpt::obs::CObservationVelodyneScan& o)
219 {
220  thread_local std::map<std::string, ros::Publisher> publishers;
221 
222  ROS_DEBUG("Received velodyne obs: %s", o.sensorLabel.c_str());
223 
224  // Create publisher on first use:
225  if (publishers.count(o.sensorLabel) == 0)
226  {
227  publishers[o.sensorLabel] =
228  nh_.advertise<sensor_msgs::PointCloud2>(o.sensorLabel, 20);
229  }
230 
231  auto& pub = publishers[o.sensorLabel];
232 
233  if (o.point_cloud.size() == 0)
234  {
235  mrpt::obs::CObservationVelodyneScan::TGeneratePointCloudParameters p;
236  p.minDistance = 0.2;
237 
238  const_cast<mrpt::obs::CObservationVelodyneScan&>(o)
239  .generatePointCloud();
240  }
241 
242  mrpt::maps::CSimplePointsMap pts;
243  pts.loadFromVelodyneScan(o);
244 
245  std_msgs::Header hdr;
246  hdr.frame_id = "base_link";
247  hdr.stamp = mrpt::ros1bridge::toROS(o.timestamp);
248 
249  sensor_msgs::PointCloud2 velodyneCloud;
250  bool ok = mrpt::ros1bridge::toROS(pts, hdr, velodyneCloud);
251  ASSERT_(ok);
252 
253  pub.publish(velodyneCloud);
254 }
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
s
XmlRpcServer s
ros::spinOnce
ROSCPP_DECL void spinOnce()
ros::ok
ROSCPP_DECL bool ok()
ROS_DEBUG
#define ROS_DEBUG(...)
ROS_WARN
#define ROS_WARN(...)
ROS_INFO_STREAM
#define ROS_INFO_STREAM(args)
mrpt_sensorlib.h
ROS_ERROR
#define ROS_ERROR(...)
ros::Rate
ros::V_string
std::vector< std::string > V_string
ROS_INFO
#define ROS_INFO(...)
mrpt_sensorlib
Definition: mrpt_sensorlib.h:15


mrpt_sensorlib
Author(s): Jose-Luis Blanco-Claraco
autogenerated on Wed Jun 14 2023 02:56:31