diff --git a/include/wolf_ros_scan_visualizer.h b/include/wolf_ros_scan_visualizer.h index 504b1047ee66cfc8ec433b9a49455d837fc217af..59e502748076538ef6d29aaad81e8d81a6dcdfa4 100644 --- a/include/wolf_ros_scan_visualizer.h +++ b/include/wolf_ros_scan_visualizer.h @@ -25,12 +25,13 @@ using namespace wolf; class WolfRosScanVisualizer: public WolfRosVisualizer { + int max_frames_; public: WolfRosScanVisualizer(); virtual ~WolfRosScanVisualizer(){}; void initialize(ros::NodeHandle &nh) override; - pcl::PointCloud<pcl::PointXYZ> buildPointCloud(const ProblemPtr); - pcl::PointCloud<pcl::PointXYZ> buildPointCloudWithMeasurements(const ProblemPtr); + pcl::PointCloud<pcl::PointXYZRGB> buildPointCloud(const ProblemPtr); + pcl::PointCloud<pcl::PointXYZRGB> buildPointCloudWithMeasurements(const ProblemPtr); void publishPointCloud(const ProblemPtr); ros::Publisher pub_pcl_from_states; ros::Publisher pub_pcl_from_measurements; diff --git a/src/wolf_ros_scan_visualizer.cpp b/src/wolf_ros_scan_visualizer.cpp index 44638c66c537b21a8e5910f2225c5836ed3d92ff..e60a35f5a2ceaee0f2caeba976ae62325fb3e735 100644 --- a/src/wolf_ros_scan_visualizer.cpp +++ b/src/wolf_ros_scan_visualizer.cpp @@ -3,6 +3,7 @@ #include "Eigen/src/Geometry/Transform.h" #include "core/common/wolf.h" #include "core/feature/feature_base.h" +#include "pcl/impl/point_types.hpp" #include <iterator> #include <laser/capture/capture_laser_2D.h> #include <laser/sensor/sensor_laser_2D.h> @@ -28,6 +29,8 @@ WolfRosScanVisualizer::WolfRosScanVisualizer() : WolfRosVisualizer() void WolfRosScanVisualizer::initialize(ros::NodeHandle& nh) { WolfRosVisualizer::initialize(nh); + + nh.param<int>("num_frames_visualize", max_frames_, 2); WOLF_INFO("scan visualizer initialize"); pub_pcl_from_states = nh.advertise<sensor_msgs::PointCloud2>("point_cloud", 1); pub_pcl_from_measurements = nh.advertise<sensor_msgs::PointCloud2>("point_cloud_measurements", 1); @@ -42,7 +45,7 @@ void WolfRosScanVisualizer::fillFactorMarker(FactorBaseConstPtr fac, visualization_msgs::Marker& fac_text_marker) { WolfRosVisualizer::fillFactorMarker(fac, fac_marker, fac_text_marker); - if (fac->getFeature()->getType() == "ICP ALIGN" and fac->getType() == "ODOM 2D") + if (fac->getFeature()->getType() == "FeatureIcpAlign" and fac->getType() == "FactorOdom2D") { FactorOdom2DConstPtr fac_odom = std::static_pointer_cast<const FactorOdom2D>(fac); @@ -50,7 +53,7 @@ void WolfRosScanVisualizer::fillFactorMarker(FactorBaseConstPtr fac, unsigned int cap_id_other = -1; for (const auto& cap_other : fac->getFrameOther()->getCaptureList()) { - if (cap_other->getType() == "LASER 2D") + if (cap_other->getType() == "CaptureLaser2D") cap_id_other = cap_other->id(); } @@ -61,9 +64,9 @@ void WolfRosScanVisualizer::fillFactorMarker(FactorBaseConstPtr fac, fac_text_marker.pose.position.z = fac_text_marker.pose.position.z + 0.25; } } -void transformPointCloudFromLaserScan(pcl::PointCloud<pcl::PointXYZ>& cloud, - CaptureLaser2DPtr cptr_laser, - Eigen::Affine3f transform) +void transformPointCloudFromLaserScan(pcl::PointCloud<pcl::PointXYZRGB>& cloud, + CaptureLaser2DPtr cptr_laser, + Eigen::Affine3f transform) { SensorLaser2DPtr sensor_laser = std::static_pointer_cast<SensorLaser2D>(cptr_laser->getSensor()); sensor_msgs::LaserScan laser_msg; @@ -88,17 +91,26 @@ void transformPointCloudFromLaserScan(pcl::PointCloud<pcl::PointXYZ>& cloud, pcl::transformPointCloud(cloud, cloud, transform); } -pcl::PointCloud<pcl::PointXYZ> WolfRosScanVisualizer::buildPointCloud(const ProblemPtr problem) +pcl::PointCloud<pcl::PointXYZRGB> WolfRosScanVisualizer::buildPointCloud(const ProblemPtr problem) { std::ofstream file; - pcl::PointCloud<pcl::PointXYZ> agg_cloud; - for (auto key_frame : problem->getTrajectory()->getFrameList()) + pcl::PointCloud<pcl::PointXYZRGB> agg_cloud; + auto trajectory_aux = problem->getTrajectory()->getFrameList(); + trajectory_aux.reverse(); + auto end = std::next(trajectory_aux.begin(), min(trajectory_aux.size(), max_frames_ + 1)); + if(max_frames_ == 0) + end = trajectory_aux.end(); + std::list<FrameBasePtr> trajectory(trajectory_aux.begin(), end); + unsigned int counter = 0; + bool first = true; + WOLF_INFO("Start scan Visualize ======================================================================"); + for (auto key_frame : trajectory) { - if (key_frame->isKey()) + if (key_frame->isKey() or first) { for (auto cptr : key_frame->getCaptureList()) { - if (cptr->getType() == "LASER 2D") + if (cptr->getType() == "CaptureLaser2D") { // Preparation CaptureLaser2DPtr cptr_laser = std::static_pointer_cast<CaptureLaser2D>(cptr); @@ -119,27 +131,67 @@ pcl::PointCloud<pcl::PointXYZ> WolfRosScanVisualizer::buildPointCloud(const Prob Eigen::Affine3f T_world_sensor = T_world_robot * T_robot_sensor; // Transform laser scan point cloud - pcl::PointCloud<pcl::PointXYZ> aux_cloud; + pcl::PointCloud<pcl::PointXYZRGB> aux_cloud; transformPointCloudFromLaserScan(aux_cloud, cptr_laser, T_world_sensor); + for(auto& p : aux_cloud) + { + // pack r/g/b into rgb + uint8_t r, g, b; // Example: Red color + double z = 0; + switch (counter) { + case 0: + r = 255; + g = 165; + b = 0; + z = 0.4; + break; + case 1: + r = 255; + g = b = 0; + z = 0.3; + break; + case 2: + r = 0; + g = 255; + b = 0; + z = 0.2; + break; + case 3: + r = 0; + g = 0; + b = 255; + z = 0.1; + break; + default: + r = 128; + g = 128; + b = 192; + } + uint32_t rgb = ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b); + p.rgb = *reinterpret_cast<float*>(&rgb); + p.z = z; + } agg_cloud = agg_cloud + aux_cloud; } + ++counter; + first = false; } } } + WOLF_INFO("End scan Visualize ======================================================================"); return agg_cloud; } -pcl::PointCloud<pcl::PointXYZ> WolfRosScanVisualizer::buildPointCloudWithMeasurements(const ProblemPtr problem) +pcl::PointCloud<pcl::PointXYZRGB> WolfRosScanVisualizer::buildPointCloudWithMeasurements(const ProblemPtr problem) { FrameBasePtr last, current = nullptr; FrameBasePtrList key_frames; - pcl::PointCloud<pcl::PointXYZ> agg_cloud; + pcl::PointCloud<pcl::PointXYZRGB> agg_cloud; Eigen::Affine3f T_world_n = Eigen::Affine3f::Identity(); auto trajectory_frames = problem->getTrajectory()->getFrameList(); std::copy_if(trajectory_frames.rbegin(), trajectory_frames.rend(), std::back_inserter(key_frames), [](FrameBasePtr _frame) { return _frame->isKey(); }); - WOLF_TRACE("KEY FRAMES EMPTY? ", key_frames.empty()); for (const auto& key_frame : key_frames) { if (last == nullptr) @@ -151,7 +203,7 @@ pcl::PointCloud<pcl::PointXYZ> WolfRosScanVisualizer::buildPointCloudWithMeasure // Get all laser captures from the key frame auto cptr_list = key_frame->getCaptureList(); std::copy_if(cptr_list.begin(), cptr_list.end(), std::back_inserter(laser_cptrs), [](CaptureBasePtr _cptr) { - return (_cptr->getType() == "LASER 2D"); + return (_cptr->getType() == "CaptureLaser2D"); }); FeatureBasePtrList icp_aligns; // From the first LASER 2D capture we get the ICP ALIGN features. We are assuming that the list of LASER 2D @@ -162,7 +214,7 @@ pcl::PointCloud<pcl::PointXYZ> WolfRosScanVisualizer::buildPointCloudWithMeasure // std::for_each(ftr_list.begin(), ftr_list.end(), [](FeatureBasePtr _ftr){WOLF_TRACE("TYPE ", // _ftr->getType());}); std::copy_if(ftr_list.begin(), ftr_list.end(), std::back_inserter(icp_aligns), [](FeatureBasePtr _ftr) { - return (_ftr->getType() == "ICP ALIGN"); + return (_ftr->getType() == "FeatureIcpAlign"); }); FeatureICPAlignPtr last_icp_align; if (not icp_aligns.empty()) @@ -178,7 +230,7 @@ pcl::PointCloud<pcl::PointXYZ> WolfRosScanVisualizer::buildPointCloudWithMeasure CaptureLaser2DPtr cptr_laser = std::static_pointer_cast<CaptureLaser2D>( icp_aligns.front()->getCapture()); - pcl::PointCloud<pcl::PointXYZ> aux_cloud; + pcl::PointCloud<pcl::PointXYZRGB> aux_cloud; transformPointCloudFromLaserScan(aux_cloud, cptr_laser, T_world_n); agg_cloud = agg_cloud + aux_cloud; } diff --git a/src/wolf_ros_subscriber_laser2D.cpp b/src/wolf_ros_subscriber_laser2D.cpp index cbb0d6cf5485d5f036fc7f532b3087a9fc93a51f..4ee3f2974c201c2bf3db3ab3e7f3f5c8890dc4fb 100644 --- a/src/wolf_ros_subscriber_laser2D.cpp +++ b/src/wolf_ros_subscriber_laser2D.cpp @@ -1,4 +1,5 @@ #include "wolf_ros_subscriber_laser2D.h" +#include <limits> namespace wolf { @@ -18,7 +19,29 @@ void SubscriberWrapperLaser2D::callback(const sensor_msgs::LaserScan::ConstPtr& { CaptureLaser2DPtr new_capture = std::make_shared<CaptureLaser2D>(TimeStamp(msg->header.stamp.sec, msg->header.stamp.nsec), sensor_ptr_, msg->ranges); - std::cout << "Cap Seq " << new_capture->id() << " " << msg->header.seq << "\n"; + // auto n = std::min(msg->ranges.size(), new_capture->getScan().ranges_raw_.size()); + // auto total = 0; + // for(int i = 0; i < n; ++i) + // { + // if (msg->ranges[i] != std::numeric_limits<double>::infinity() and new_capture->getScan().ranges_raw_[i] != std::numeric_limits<double>::infinity()) + // total += std::abs(msg->ranges[i] - new_capture->getScan().ranges_raw_[i]); + // else if (msg->ranges[i] != std::numeric_limits<double>::infinity() or new_capture->getScan().ranges_raw_[i] != std::numeric_limits<double>::infinity()) + // { + // total += 10e3; + // } + // } + // std::cout << "Total error " << total << "\n"; + + // auto sensor_laser_ptr = std::dynamic_pointer_cast<SensorLaser2D>(sensor_ptr_); + // auto params = sensor_laser_ptr->getScanParams(); + + // WOLF_INFO("MSG ", msg->angle_increment, " PARAMS ", params.angle_step_); + // WOLF_INFO("MSG ", msg->angle_max, " PARAMS " , params.angle_max_); + // WOLF_INFO("MSG ", msg->angle_min, " PARAMS " , params.angle_min_); + // WOLF_INFO("MSG ", msg->range_max, " PARAMS " , params.range_max_); + // WOLF_INFO("MSG ", msg->range_min, " PARAMS " , params.range_min_); + + // std::cout << "Cap Seq " << new_capture->id() << " " << msg->header.seq << "\n"; //Currently this line is just to bypass the ROS "auto config". from the ROS msg. Maybe we want to explore //getting the params from the msg instead of the yaml file in the future. laser_intrinsics_set_ = true; @@ -48,19 +71,19 @@ void SubscriberWrapperLaser2D::callback(const sensor_msgs::LaserScan::ConstPtr& } new_capture->process(); - if (msg->header.seq == 14031) - { - auto problem = sensor_ptr_->getProblem(); - for(const auto& frame : problem->getTrajectory()->getFrameList()) - { - if(frame->isKey()){ - for(const auto& cap : frame->getCaptureList()) - { - if(cap->getType() == "LASER 2D") std::cout << "Frm Cap " << frame->id() << " " << cap->id() << "\n"; - } - } - } - } + // if (msg->header.seq == 14031) + // { + // auto problem = sensor_ptr_->getProblem(); + // for(const auto& frame : problem->getTrajectory()->getFrameList()) + // { + // if(frame->isKey()){ + // for(const auto& cap : frame->getCaptureList()) + // { + // if(cap->getType() == "LASER 2D") std::cout << "Frm Cap " << frame->id() << " " << cap->id() << "\n"; + // } + // } + // } + // } } std::shared_ptr<SubscriberWrapper> SubscriberWrapperLaser2D::create(const std::string& _unique_name, const ParamsServer& _params, const SensorBasePtr _sensor_ptr)