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>
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>
19 using namespace mrpt::hwdrivers;
21 using mrpt::config::CConfigFile;
23 GenericSensorNode::GenericSensorNode() {}
25 GenericSensorNode::~GenericSensorNode() {}
27 void GenericSensorNode::internal_init()
34 std::string driver_name =
35 cfgfile_->read_string(cfg_section_,
"driver",
"",
true);
36 sensor_ = mrpt::hwdrivers::CGenericSensor::createSensorPtr(driver_name);
40 "Sensor class name not recognized: " << driver_name);
45 sensor_->loadConfig(*cfgfile_, cfg_section_);
48 sensor_->initialize();
51 this->init_sensor_specific();
54 if (!out_rawlog_prefix_.empty())
58 std::string rawlog_postfix =
"_";
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);
70 mrpt::system::fileNameStripInvalidChars(rawlog_postfix);
72 const std::string fil = out_rawlog_prefix_ + rawlog_postfix;
74 ROS_INFO(
"Writing rawlog to file: `%s`", fil.c_str());
76 out_rawlog_.open(fil, rawlog_GZ_compress_level_);
78 if (!out_rawlog_.is_open())
79 ROS_ERROR(
"Error opening output rawlog for writing");
82 catch (
const std::exception& e)
85 "Exception in GenericSensorNode::init(): " << e.what());
90 void GenericSensorNode::init_from_config_file(
91 [[maybe_unused]]
int argc, [[maybe_unused]]
char** argv)
96 std::string cfgFileName;
97 nhlocal_.getParam(
"config_file", cfgFileName);
98 cfgfilename_ = cfgFileName;
100 cfgfile_ = std::make_shared<mrpt::config::CConfigFile>(*cfgfilename_);
102 nhlocal_.getParam(
"config_section", cfg_section_);
106 catch (
const std::exception& e)
109 "Exception in GenericSensorNode::init(): " << e.what());
114 void GenericSensorNode::init_from_template_and_parameters(
115 [[maybe_unused]]
int argc, [[maybe_unused]]
char** argv)
117 using namespace std::string_literals;
122 std::string templateFileName;
123 nhlocal_.getParam(
"template_file", templateFileName);
124 cfgfilename_ = templateFileName;
126 ASSERT_FILE_EXISTS_(templateFileName);
129 std::string cfgContents = mrpt::io::file_get_contents(templateFileName);
133 nhlocal_.getParamNames(allParams);
134 for (
const auto& paramName : allParams)
137 if (!nhlocal_.getParam(paramName, value))
continue;
140 "@define "s + paramName +
" "s + value +
"\n" + cfgContents;
147 std::make_shared<mrpt::config::CConfigFileMemory>(cfgContents);
148 nhlocal_.getParam(
"template_file_section", cfg_section_);
152 catch (
const std::exception& e)
155 "Exception in GenericSensorNode::init(): " << e.what());
161 void GenericSensorNode::run()
163 ROS_INFO(
"Starting run() at %.02f Hz", sensor_->getProcessRate());
166 ROS_ERROR(
"Aborting: sensor object was not properly initialized.");
169 ros::Rate loop_rate(sensor_->getProcessRate());
172 sensor_->doProcess();
175 CGenericSensor::TListObservations lstObjs = sensor_->getObservations();
177 for (
const auto& o : lstObjs)
179 if (
const auto& obs =
180 std::dynamic_pointer_cast<mrpt::obs::CObservation>(
186 if (out_rawlog_.is_open())
188 auto out_arch = mrpt::serialization::archiveFrom(out_rawlog_);
189 for (
const auto& o : lstObjs)
191 out_arch << *o.second;
199 void GenericSensorNode::on_observation(
const mrpt::obs::CObservation::Ptr& o)
203 if (
const auto& obsVel =
204 std::dynamic_pointer_cast<mrpt::obs::CObservationVelodyneScan>(o);
207 on_observation_velodyne(*obsVel);
212 "Do not know how to publish observation '%s' of type '%s'",
213 o->sensorLabel.c_str(), o->GetRuntimeClass()->className);
217 void GenericSensorNode::on_observation_velodyne(
218 const mrpt::obs::CObservationVelodyneScan& o)
220 thread_local std::map<std::string, ros::Publisher> publishers;
222 ROS_DEBUG(
"Received velodyne obs: %s", o.sensorLabel.c_str());
225 if (publishers.count(o.sensorLabel) == 0)
227 publishers[o.sensorLabel] =
228 nh_.advertise<sensor_msgs::PointCloud2>(o.sensorLabel, 20);
231 auto& pub = publishers[o.sensorLabel];
233 if (o.point_cloud.size() == 0)
235 mrpt::obs::CObservationVelodyneScan::TGeneratePointCloudParameters p;
238 const_cast<mrpt::obs::CObservationVelodyneScan&
>(o)
239 .generatePointCloud();
242 mrpt::maps::CSimplePointsMap pts;
243 pts.loadFromVelodyneScan(o);
245 std_msgs::Header hdr;
246 hdr.frame_id =
"base_link";
247 hdr.stamp = mrpt::ros1bridge::toROS(o.timestamp);
249 sensor_msgs::PointCloud2 velodyneCloud;
250 bool ok = mrpt::ros1bridge::toROS(pts, hdr, velodyneCloud);
253 pub.publish(velodyneCloud);