diff --git a/include/pub_map.hpp b/include/pub_map.hpp index 84ee1ff..30a0cb4 100644 --- a/include/pub_map.hpp +++ b/include/pub_map.hpp @@ -62,29 +62,11 @@ #include #include +#include "util.hpp" -namespace util -{ - -template -inline ros_T& to_ros(primitive_T& v) -{ - static_assert( - std::is_same::value && - sizeof(ros_T) == sizeof(primitive_T) && - alignof(ros_T) == alignof(primitive_T)); - - return reinterpret_cast(v); -} -template -inline ros_T to_ros_val(primitive_T v) +namespace util { - static_assert(std::is_same::value); - - return ros_T{}.set__data(v); -} - template struct is_convertible_to_std_msg : std::false_type @@ -110,28 +92,72 @@ struct is_convertible_to_std_msg< std::is_same, std::is_same, std::is_same, - std::is_same >, - void> > : std::is_convertible + std::is_same>, + void>> : std::is_convertible { }; +class PubMapBase +{ +public: + using RclNode = rclcpp::Node; + using RclQoS = rclcpp::QoS; + + template + using Pub = rclcpp::Publisher; + template + using SharedPub = typename Pub::SharedPtr; + + template + using StringMap = std::unordered_map< + std::string, + T, + util::TransparentStringHash, + util::TransparentStringEq>; + +protected: + inline PubMapBase(RclNode& n, std::string_view prefix, const RclQoS& qos) : + node{n}, + default_qos{qos}, + prefix{ + // empty prefix should be left alone because in some cases it is nice to exploit namespace-local topics + prefix.empty() || prefix.back() == '/' ? prefix + : std::string(prefix) + "/"} + { + } + +protected: + inline std::string formatFullTopic(std::string_view topic) + { + // ASSERT TOPIC IS NOT EMPTY!? + return this->prefix + + std::string(topic.front() == '/' ? topic.substr(1) : topic); + } + +protected: + RclNode& node; + RclQoS default_qos; + std::string prefix; +}; + + template -class PubMap +class PubMap : public PubMapBase { public: using MsgT = Msg_T; - using SharedPubT = typename rclcpp::Publisher::SharedPtr; + using SharedPubT = SharedPub; public: + /* Construct a publisher map. + * Prefix may be relative or absolute and gets appended to topics in all method calls. */ inline PubMap( - rclcpp::Node* n, + RclNode& n, std::string_view prefix = "", - const rclcpp::QoS& qos = rclcpp::SensorDataQoS{}) : - node{n}, - default_qos{qos}, - prefix{prefix}, + const RclQoS& qos = rclcpp::SensorDataQoS{}) : + PubMapBase{n, prefix, qos}, publishers{} { } @@ -139,57 +165,44 @@ class PubMap ~PubMap() = default; public: - // wraps the other addPub using the default QoS + /* Add a publisher on the provided topic, using the default QoS */ inline SharedPubT addPub(std::string_view topic) { return this->addPub(topic, this->default_qos); } - // create a publisher and add it to the map - SharedPubT addPub(std::string_view topic, const rclcpp::QoS& qos) + /* Add a publisher on the provided topic, using the provided QoS. + * Does not recreate publisher if the topic is already used. */ + SharedPubT addPub(std::string_view topic, const RclQoS& qos) { - if (!this->node) - { - return nullptr; - } + std::lock_guard lock{this->mtx}; - std::string full; - if (this->prefix.empty()) + auto it = this->publishers.find(topic); + if (it != this->publishers.end()) { - full = topic; - } - else - { -#if __cpp_lib_string_view >= 202403 // from cppreference - full = this->prefix + topic; -#else - full = this->prefix + std::string{topic}; -#endif + return it->second; } - std::lock_guard _lock{this->mtx}; - auto ptr = this->publishers.insert( - {std::string{topic}, - this->node->template create_publisher(full, qos)}); + auto ptr = this->publishers.emplace( + topic, + this->node.template create_publisher( + this->formatFullTopic(topic), + qos)); if (ptr.second && ptr.first->second) { return ptr.first->second; } + return nullptr; } - // extract a publisher from its topic + /* Find and return a publisher if it exists for the provided topic, + * otherwise returns nullptr. */ SharedPubT findPub(std::string_view topic) { - if (!this->node) - { - return nullptr; - } - - std::shared_lock _lock{this->mtx}; - auto search = this->publishers.find(std::string{topic}); - _lock.unlock(); + std::shared_lock lock{this->mtx}; + auto search = this->publishers.find(topic); if (search == this->publishers.end()) { return nullptr; @@ -200,7 +213,8 @@ class PubMap } } - // extract or add if not already present + /* Get the publisher for the provided topic if it exists, + * otherwise creates a new one with the default QoS. */ SharedPubT getPub(std::string_view topic) { SharedPubT p = this->findPub(topic); @@ -211,13 +225,13 @@ class PubMap return p; } - // wraps getPub() + /* Operator wrapper for getPub() */ inline SharedPubT operator[](std::string_view topic) { return this->getPub(topic); } - // publish a value to a topic + /* Publish a value on the provided topic, which is created if not already present. */ template void publish(std::string_view topic, T val) { @@ -227,11 +241,11 @@ class PubMap return; } - if constexpr (std::is_same::value) + if constexpr (std::is_same_v) { p->publish(val); } - else if constexpr (std::is_convertible::value) + else if constexpr (std::is_convertible_v) { p->publish(static_cast(val)); } @@ -240,106 +254,95 @@ class PubMap p->publish( MsgT{}.set__data(static_cast(val))); } + else + { + static_assert( + std::is_same_v || + std::is_convertible_v || + is_convertible_to_std_msg::value, "Error: incompatible types!"); + } } protected: - rclcpp::Node* node = nullptr; - rclcpp::QoS default_qos = 1; - std::string prefix = ""; - - std::unordered_map publishers{}; + StringMap publishers{}; std::shared_mutex mtx; - // }; template<> -class PubMap +class PubMap : public PubMapBase { - template - using Pub = rclcpp::Publisher; - template - using SharedPub = typename Pub::SharedPtr; - - using SharedVoidPtr = std::shared_ptr; + using SharedBasePtr = std::shared_ptr; public: + /* Construct a publisher map. + * Prefix may be relative or absolute and gets appended to topics in all method calls. */ inline PubMap( - rclcpp::Node* n, + RclNode& n, std::string_view prefix = "", - const rclcpp::QoS& qos = 1) : - node{n}, - default_qos{qos}, - prefix{prefix}, - pubs{} + const RclQoS& qos = 1) : + PubMapBase{n, prefix, qos}, + publishers{} { } PubMap(const PubMap&) = delete; ~PubMap() = default; public: + /* Add a publisher on the provided topic, using the default QoS */ template inline SharedPub addPub(std::string_view topic) { return this->addPub(topic, this->default_qos); } + + /* Add a publisher on the provided topic, using the provided QoS. + * Does not recreate publisher if the topic is already used. */ template - inline SharedPub addPub( - std::string_view topic, - const rclcpp::QoS& qos) + inline SharedPub addPub(std::string_view topic, const RclQoS& qos) { - if (!this->node) - { - return nullptr; - } + std::lock_guard lock{this->mtx}; - std::string full; - if (this->prefix.empty()) + // Avoid additional calls to create_publisher + auto it = this->publishers.find(topic); + if (it != this->publishers.end()) { - full = topic; - } - else - { -#if __cpp_lib_string_view >= 202403 // from cppreference - full = this->prefix + topic; -#else - full = this->prefix + std::string{topic}; -#endif + return std::dynamic_pointer_cast>(it->second); } - std::lock_guard lock_{this->mtx}; - auto iter = this->pubs.insert( - {std::string(topic), - this->node->template create_publisher(full, qos)}); + auto iter = this->publishers.emplace( + topic, + this->node.template create_publisher( + this->formatFullTopic(topic), + qos)); if (iter.second && iter.first->second) { - return std::static_pointer_cast>(iter.first->second); + return std::dynamic_pointer_cast>(iter.first->second); } + return nullptr; } + /* Find and return a publisher if it exists for the provided topic, + * otherwise returns nullptr. */ template SharedPub findPub(std::string_view topic) { - if (!this->node) - { - return nullptr; - } + std::shared_lock lock{this->mtx}; - std::shared_lock lock_{this->mtx}; - auto iter = this->pubs.find(std::string(topic)); - lock_.unlock(); - - if (iter == this->pubs.end()) + auto iter = this->publishers.find(topic); + if (iter == this->publishers.end()) { return nullptr; } else { - return std::static_pointer_cast>(iter->second); + return std::dynamic_pointer_cast>(iter->second); } } + /* Get the publisher for the provided topic if it exists, + * otherwise creates a new one with the default QoS. */ template SharedPub getPub(std::string_view topic) { @@ -351,12 +354,14 @@ class PubMap return ptr; } + /* Publish a value on the provided topic, which is created if not already present. */ template inline void publish(std::string_view topic, const MsgT& val) { this->publish(topic, val); } + /* Publish a value on the provided topic, which is created if not already present. */ template void publish(std::string_view topic, const T& val) { @@ -366,32 +371,34 @@ class PubMap return; } - if constexpr (std::is_same::value) + if constexpr (std::is_same_v) { pub->publish(val); return; } - if constexpr (std::is_convertible::value) + else if constexpr (std::is_convertible_v) { pub->publish(static_cast(val)); return; } - if constexpr (is_convertible_to_std_msg::value) + else if constexpr (is_convertible_to_std_msg::value) { pub->publish( MsgT{}.set__data(static_cast(val))); return; } + else + { + static_assert( + std::is_same_v || + std::is_convertible_v || + is_convertible_to_std_msg::value, "Error: incompatible types!"); + } } protected: - rclcpp::Node* node = nullptr; - rclcpp::QoS default_qos = 1; - std::string prefix = ""; - - std::unordered_map pubs; + StringMap publishers; std::shared_mutex mtx; - // }; using GenericPubMap = PubMap; diff --git a/include/scan_preprocessor.hpp b/include/scan_preprocessor.hpp index 337a927..414fe43 100644 --- a/include/scan_preprocessor.hpp +++ b/include/scan_preprocessor.hpp @@ -62,11 +62,12 @@ #include #include +#include "tsq.hpp" +#include "util.hpp" #include "geometry.hpp" #include "cloud_ops.hpp" #include "point_def.hpp" #include "imu_integrator.hpp" -#include "tsq.hpp" #define DESKEW_ROT_THRESH_RAD 1e-3 @@ -175,29 +176,12 @@ class ScanPreprocessor } protected: - struct TransparentStringHash - { - using is_transparent = void; - size_t operator()(std::string_view s) const noexcept - { - return std::hash{}(s); - } - }; - struct TransparentStringEq - { - using is_transparent = void; - bool operator()(std::string_view a, std::string_view b) const noexcept - { - return a == b; - } - }; - template using UoStrMultiMap = std::unordered_multimap< std::string, T, - TransparentStringHash, - TransparentStringEq>; + util::TransparentStringHash, + util::TransparentStringEq>; using TfZoneList = std::pair>; diff --git a/include/util.hpp b/include/util.hpp index 1056dcc..c2b682c 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -138,6 +139,15 @@ inline builtin_interfaces::msg::Time toTimeStamp(double t_secs) } +template +inline ros_T to_ros_val(primitive_T v) +{ + static_assert(std::is_same::value); + + return ros_T{}.set__data(v); +} + + /* Create a shared pointer from a stack-allocated variable pointer. Make sure * the object will outlast the shared pointer scope! */ template @@ -153,6 +163,23 @@ inline std::shared_ptr wrap_unmanaged(T& x) return std::shared_ptr(&x, [](T*) {}); } +struct TransparentStringHash +{ + using is_transparent = void; + size_t operator()(std::string_view s) const noexcept + { + return std::hash{}(s); + } +}; +struct TransparentStringEq +{ + using is_transparent = void; + bool operator()(std::string_view a, std::string_view b) const noexcept + { + return a == b; + } +}; + }; // namespace util #define DECLARE_IMMOVABLE(Typename) \ diff --git a/src/core/perception.hpp b/src/core/perception.hpp index 5cfaa2f..be8076e 100644 --- a/src/core/perception.hpp +++ b/src/core/perception.hpp @@ -74,6 +74,8 @@ namespace csm namespace perception { +struct PerceptionConfig; + class PerceptionNode : public rclcpp::Node { protected: @@ -95,9 +97,9 @@ class PerceptionNode : public rclcpp::Node void shutdown(); protected: - void getParams(void* = nullptr); - void initPubSubs(void* = nullptr); - void printStartup(void* = nullptr); + void getParams(PerceptionConfig& cfg); + void initPubSubs(PerceptionConfig& cfg); + void printStartup(PerceptionConfig& cfg); private: // --- TRANSFORM UTILITEIS ------------------------------------------------- diff --git a/src/core/perception_core.cpp b/src/core/perception_core.cpp index 7b2b56f..ed94126 100644 --- a/src/core/perception_core.cpp +++ b/src/core/perception_core.cpp @@ -91,29 +91,6 @@ struct PerceptionConfig public: explicit PerceptionConfig(PerceptionNode& node) : node{node} {} - inline static PerceptionConfig& castOrAllocate( - void* buff, - PerceptionNode& node) - { - PerceptionConfig* config_ptr; - if (!buff) - { - config_ptr = new PerceptionConfig(node); - } - else - { - config_ptr = static_cast(buff); - } - return *config_ptr; - } - inline static void handleDeallocate(void* buff, PerceptionConfig& config) - { - if (!buff) - { - delete &config; - } - } - public: PerceptionNode& node; @@ -197,8 +174,174 @@ struct PerceptionConfig { return val ? "Enabled" : "Disabled"; } + + friend std::ostream& operator<<( + std::ostream& os, + const PerceptionConfig& config); }; +std::ostream& operator<<(std::ostream& os, const PerceptionConfig& config) { +// alignment, feat. ChatGPT lol + constexpr int CONFIG_ALIGN_WIDTH = 25; + auto align = [](const char* label) + { + std::ostringstream oss; + oss << " | " << std::left << std::setw(CONFIG_ALIGN_WIDTH) << label + << ": "; + return oss.str(); + }; + + + + os << std::setprecision(3); + os << "\n" + " +-- CONFIGURATION ---------------------------------+\n" + " |\n" + " +- PIPELINE STAGES\n" + << align("Fiducial mode") << PerceptionConfig::getFiducialModeStr() + << "\n" + << align("Mapping") + << PerceptionConfig::getEnableDisableStr(PERCEPTION_ENABLE_MAPPING) + << "\n" + << align("Traversibility") + << PerceptionConfig::getEnableDisableStr( + PERCEPTION_ENABLE_TRAVERSIBILITY) + << "\n" + << align("Path Planning") + << PerceptionConfig::getEnableDisableStr( + PERCEPTION_ENABLE_PATH_PLANNING) + << "\n" + " |\n" + " +- FEATURES\n" + << align("Scan Deskew") + << PerceptionConfig::getEnableDisableStr(PERCEPTION_USE_SCAN_DESKEW) + << "\n" + << align("Null Ray Mapping") + << PerceptionConfig::getEnableDisableStr( + PERCEPTION_USE_NULL_RAY_DELETION) + << "\n" + " |\n" + " +- CORE\n" + << align("Scan Topic") << config.scan_topic << "\n" + << align("IMU Topic") << config.imu_topic << "\n" + << align("Map Frame ID") << config.map_frame << "\n" + << align("Odom Frame ID") << config.odom_frame << "\n" + << align("Robot Frame ID") << config.base_frame << "\n" + << align("Statistics Frequency") << config.metrics_pub_freq + << " hz\n" + " |\n" + " +- EXCLUSION ZONES\n"; + if (config.num_excl_zones) + { + for (const auto& zone : config.excl_zones) + { + os << " | +- Frame \"" << std::get<0>(zone) << "\"\n" + << align("| Min") << "[" << std::get<1>(zone)[0] << ", " + << std::get<1>(zone)[1] << ", " << std::get<1>(zone)[2] + << "] (m)\n" + << align("| Max") << "[" << std::get<2>(zone)[0] << ", " + << std::get<2>(zone)[1] << ", " << std::get<2>(zone)[2] + << "] (m)\n"; + } + } + else + { + os << " | (none)\n"; + } + os << " |\n" + << " +- TRAJECTORY FILTER\n" + << align("Sample Window") << config.trjf_sample_window_s << " seconds\n" + << align("Filter Window") << config.trjf_filter_window_s << " seconds\n" + << align("Linear Error Thresh") << config.trjf_avg_linear_err_thresh + << " meters\n" + << align("Angular Error Thresh") << config.trjf_avg_angular_err_thresh + << " radians\n" + << align("Linear Dev Thresh") << config.trjf_max_linear_dev_thresh + << "\n" + << align("Angular Dev Thresh") << config.trjf_max_angular_dev_thresh + << "\n" + << " |\n" + " +- ODOMETRY\n" + " | (not implemented)\n"; + + #if LFD_ENABLED + os << " |\n" + " +- LIDAR FIDUCIAL DETECTOR\n" + << align("Detection Range") << config.lfd_detection_radius + << " meters\n" + << align("Plane Seg Thickness") << config.lfd_plane_seg_thickness + << " meters\n" + << align("Ground Seg Thickness") << config.lfd_ground_seg_thickness + << " meters\n" + << align("Up Vec Max Angular Dev") << config.lfd_up_vec_max_angular_dev + << " radians\n" + << align("Planes Max Angular Dev") << config.lfd_planes_max_angular_dev + << " radians\n" + << align("Voxel Resolution") << config.lfd_vox_res << " meters\n" + << align("Max Percentage Leftover") + << (config.lfd_max_proportion_leftover * 100) << "%\n" + << align("Min Num Input Points") << config.lfd_min_num_input_points + << "\n" + << align("Min Num Seg Points") << config.lfd_min_plane_seg_points + << "\n"; + #endif + + #if MAPPING_ENABLED + os << " |\n" + " +- MAPPING\n" + << align("Horizontal Crop Range") << config.map_crop_horizontal_range + << " meters\n" + << align("Vertical Crop Range") << config.map_crop_vertical_range + << " meters\n" + << align("Frustum Radius") << config.kfc_frustum_search_radius + << " radians\n" + << align("Radial Dist Thresh") << config.kfc_radial_dist_thresh + << " meters\n" + << align("Surface Width") << config.kfc_surface_width << " meters\n" + << align("Delete Max Range") << config.kfc_delete_max_range + << " meters\n" + << align("Add Max Range") << config.kfc_add_max_range << " meters\n" + << align("Voxel Size") << config.kfc_voxel_size << " meters\n"; + #endif + + #if TRAVERSIBILITY_ENABLED + os << " |\n" + " +- TRAVERSIBILITY\n" + << align("Horizontal Export Range") + << config.map_export_horizontal_range << " meters\n" + << align("Vertical Export Range") << config.map_export_vertical_range + << " meters\n" + << align("Normal Est Radius") << config.trav_norm_estimation_radius + << " meters\n" + << align("Output Grid Res") << config.trav_output_res << " meters\n" + << align("Grad Search Radius") << config.trav_grad_search_radius + << " meters\n" + << align("Min Grad Diff") << config.trav_min_grad_diff << " meters\n" + << align("Avoid Grad Angle") << config.trav_avoid_grad_angle + << " degrees\n" + << align("Avoid Radius") << config.trav_avoid_radius << " meters\n" + << align("Curvature Trav Weight") << config.trav_score_curvature_weight + << "\n" + << align("Gradient Trav Weight") << config.trav_score_grad_weight + << "\n" + << align("Point Samples") << config.trav_interp_point_samples << "\n"; + #endif + + #if PATH_PLANNING_ENABLED + os << " |\n" + " +- PATH PLANNING\n" + << align("Boundary Radius") << config.pplan_boundary_radius + << " meters\n" + << align("Goal Threshold") << config.pplan_goal_thresh << " meters\n" + << align("Search Radius") << config.pplan_search_radius << " meters\n" + << align("Lambda Distance") << config.pplan_lambda_dist << " meters\n" + << align("Lambda Penalty") << config.pplan_lambda_penalty << "\n" + << align("Max Num Neighbors") << config.pplan_max_neighbors << "\n"; + #endif + + os << " +\n"; + return os; +} PerceptionNode::PerceptionNode() : Node("cardinal_perception"), @@ -210,13 +353,13 @@ PerceptionNode::PerceptionNode() : traversibility_worker{*this, imu_worker.getSampler()}, path_planning_worker{*this, tf_buffer}, mining_eval_worker{*this, tf_buffer}, - generic_pub{this, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS} + generic_pub{*this, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS} { PerceptionConfig config{*this}; - this->getParams(&config); - this->initPubSubs(&config); - this->printStartup(&config); + this->getParams(config); + this->initPubSubs(config); + this->printStartup(config); this->localization_worker.connectOutput(this->mapping_worker.getInput()); this->mapping_worker.connectOutput(this->traversibility_worker.getInput()); @@ -246,10 +389,8 @@ void PerceptionNode::shutdown() -void PerceptionNode::getParams(void* buff) +void PerceptionNode::getParams(PerceptionConfig& config) { - PerceptionConfig& config = PerceptionConfig::castOrAllocate(buff, *this); - util::declare_param(this, "map_frame_id", config.map_frame, "map"); util::declare_param(this, "odom_frame_id", config.odom_frame, "odom"); util::declare_param(this, "base_frame_id", config.base_frame, "base_link"); @@ -596,16 +737,12 @@ void PerceptionNode::getParams(void* buff) this->traversibility_worker.configure(config.odom_frame); this->path_planning_worker.configure(config.odom_frame); this->mining_eval_worker.configure(config.odom_frame); - - PerceptionConfig::handleDeallocate(buff, config); } -void PerceptionNode::initPubSubs(void* buff) +void PerceptionNode::initPubSubs(PerceptionConfig& config) { - PerceptionConfig& config = PerceptionConfig::castOrAllocate(buff, *this); - util::declare_param(this, "scan_topic", config.scan_topic, "scan"); util::declare_param(this, "imu_topic", config.imu_topic, "imu"); @@ -660,197 +797,19 @@ void PerceptionNode::initPubSubs(void* buff) "process_stats", this->process_stats.toMsg()); }); - - PerceptionConfig::handleDeallocate(buff, config); } -void PerceptionNode::printStartup(void* buff) +void PerceptionNode::printStartup(PerceptionConfig& config) { std::ostringstream msg; msg << "\n" << STARTUP_SPLASH; #if PERCEPTION_PRINT_STARTUP_CONFIGS - // alignment, feat. ChatGPT lol - constexpr int CONFIG_ALIGN_WIDTH = 25; - auto align = [](const char* label) - { - std::ostringstream oss; - oss << " | " << std::left << std::setw(CONFIG_ALIGN_WIDTH) << label - << ": "; - return oss.str(); - }; - // auto align_numbered = [](int i, const char* label) - // { - // std::ostringstream n_label, oss; - // n_label << i << ". " << label; - // oss << " | " << std::left << std::setw(CONFIG_ALIGN_WIDTH) - // << n_label.str() << ": "; - // return oss.str(); - // }; - - if (buff) - { - PerceptionConfig& config = *static_cast(buff); - - msg << std::setprecision(3); - msg << "\n" - " +-- CONFIGURATION ---------------------------------+\n" - " |\n" - " +- PIPELINE STAGES\n" - << align("Fiducial mode") << PerceptionConfig::getFiducialModeStr() - << "\n" - << align("Mapping") - << PerceptionConfig::getEnableDisableStr(PERCEPTION_ENABLE_MAPPING) - << "\n" - << align("Traversibility") - << PerceptionConfig::getEnableDisableStr( - PERCEPTION_ENABLE_TRAVERSIBILITY) - << "\n" - << align("Path Planning") - << PerceptionConfig::getEnableDisableStr( - PERCEPTION_ENABLE_PATH_PLANNING) - << "\n" - " |\n" - " +- FEATURES\n" - << align("Scan Deskew") - << PerceptionConfig::getEnableDisableStr(PERCEPTION_USE_SCAN_DESKEW) - << "\n" - << align("Null Ray Mapping") - << PerceptionConfig::getEnableDisableStr( - PERCEPTION_USE_NULL_RAY_DELETION) - << "\n" - " |\n" - " +- CORE\n" - << align("Scan Topic") << config.scan_topic << "\n" - << align("IMU Topic") << config.imu_topic << "\n" - << align("Map Frame ID") << config.map_frame << "\n" - << align("Odom Frame ID") << config.odom_frame << "\n" - << align("Robot Frame ID") << config.base_frame << "\n" - << align("Statistics Frequency") << config.metrics_pub_freq - << " hz\n" - " |\n" - " +- EXCLUSION ZONES\n"; - if (config.num_excl_zones) - { - for (const auto& zone : config.excl_zones) - { - msg << " | +- Frame \"" << std::get<0>(zone) << "\"\n" - << align("| Min") << "[" << std::get<1>(zone)[0] << ", " - << std::get<1>(zone)[1] << ", " << std::get<1>(zone)[2] - << "] (m)\n" - << align("| Max") << "[" << std::get<2>(zone)[0] << ", " - << std::get<2>(zone)[1] << ", " << std::get<2>(zone)[2] - << "] (m)\n"; - } - } - else - { - msg << " | (none)\n"; - } - msg << " |\n" - << " +- TRAJECTORY FILTER\n" - << align("Sample Window") << config.trjf_sample_window_s - << " seconds\n" - << align("Filter Window") << config.trjf_filter_window_s - << " seconds\n" - << align("Linear Error Thresh") << config.trjf_avg_linear_err_thresh - << " meters\n" - << align("Angular Error Thresh") - << config.trjf_avg_angular_err_thresh << " radians\n" - << align("Linear Dev Thresh") << config.trjf_max_linear_dev_thresh - << "\n" - << align("Angular Dev Thresh") << config.trjf_max_angular_dev_thresh - << "\n" - << " |\n" - " +- ODOMETRY\n" - " | (not implemented)\n"; - - #if LFD_ENABLED - msg << " |\n" - " +- LIDAR FIDUCIAL DETECTOR\n" - << align("Detection Range") << config.lfd_detection_radius - << " meters\n" - << align("Plane Seg Thickness") << config.lfd_plane_seg_thickness - << " meters\n" - << align("Ground Seg Thickness") << config.lfd_ground_seg_thickness - << " meters\n" - << align("Up Vec Max Angular Dev") - << config.lfd_up_vec_max_angular_dev << " radians\n" - << align("Planes Max Angular Dev") - << config.lfd_planes_max_angular_dev << " radians\n" - << align("Voxel Resolution") << config.lfd_vox_res << " meters\n" - << align("Max Percentage Leftover") - << (config.lfd_max_proportion_leftover * 100) << "%\n" - << align("Min Num Input Points") << config.lfd_min_num_input_points - << "\n" - << align("Min Num Seg Points") << config.lfd_min_plane_seg_points - << "\n"; - #endif - - #if MAPPING_ENABLED - msg << " |\n" - " +- MAPPING\n" - << align("Horizontal Crop Range") - << config.map_crop_horizontal_range << " meters\n" - << align("Vertical Crop Range") << config.map_crop_vertical_range - << " meters\n" - << align("Frustum Radius") << config.kfc_frustum_search_radius - << " radians\n" - << align("Radial Dist Thresh") << config.kfc_radial_dist_thresh - << " meters\n" - << align("Surface Width") << config.kfc_surface_width << " meters\n" - << align("Delete Max Range") << config.kfc_delete_max_range - << " meters\n" - << align("Add Max Range") << config.kfc_add_max_range << " meters\n" - << align("Voxel Size") << config.kfc_voxel_size << " meters\n"; - #endif - - #if TRAVERSIBILITY_ENABLED - msg << " |\n" - " +- TRAVERSIBILITY\n" - << align("Horizontal Export Range") - << config.map_export_horizontal_range << " meters\n" - << align("Vertical Export Range") - << config.map_export_vertical_range << " meters\n" - << align("Normal Est Radius") << config.trav_norm_estimation_radius - << " meters\n" - << align("Output Grid Res") << config.trav_output_res << " meters\n" - << align("Grad Search Radius") << config.trav_grad_search_radius - << " meters\n" - << align("Min Grad Diff") << config.trav_min_grad_diff - << " meters\n" - << align("Avoid Grad Angle") << config.trav_avoid_grad_angle - << " degrees\n" - << align("Avoid Radius") << config.trav_avoid_radius << " meters\n" - << align("Curvature Trav Weight") - << config.trav_score_curvature_weight << "\n" - << align("Gradient Trav Weight") << config.trav_score_grad_weight - << "\n" - << align("Point Samples") << config.trav_interp_point_samples - << "\n"; - #endif - - #if PATH_PLANNING_ENABLED - msg << " |\n" - " +- PATH PLANNING\n" - << align("Boundary Radius") << config.pplan_boundary_radius - << " meters\n" - << align("Goal Threshold") << config.pplan_goal_thresh - << " meters\n" - << align("Search Radius") << config.pplan_search_radius - << " meters\n" - << align("Lambda Distance") << config.pplan_lambda_dist - << " meters\n" - << align("Lambda Penalty") << config.pplan_lambda_penalty << "\n" - << align("Max Num Neighbors") << config.pplan_max_neighbors << "\n"; - #endif - - msg << " +\n"; - } + msg << config; #else - (void)buff; + (void)config; #endif RCLCPP_INFO( diff --git a/src/core/tag_detection.cpp b/src/core/tag_detection.cpp index 5ecd614..120c264 100644 --- a/src/core/tag_detection.cpp +++ b/src/core/tag_detection.cpp @@ -134,7 +134,7 @@ TagDetector::TagDetector() : img_transport{std::shared_ptr(this, [](auto*) {})}, mt_callback_group{ this->create_callback_group(rclcpp::CallbackGroupType::Reentrant)}, - generic_pub{this, "", rclcpp::SensorDataQoS{}}, + generic_pub{*this, "", rclcpp::SensorDataQoS{}}, aruco_params{cv::aruco::DetectorParameters::create()} { this->getParams(); diff --git a/src/core/threads/imu_worker.cpp b/src/core/threads/imu_worker.cpp index 95b4d3e..bad21ea 100644 --- a/src/core/threads/imu_worker.cpp +++ b/src/core/threads/imu_worker.cpp @@ -65,7 +65,7 @@ namespace perception ImuWorker::ImuWorker(RclNode& node, const Tf2Buffer& tf_buffer) : node{node}, tf_buffer{tf_buffer}, - pub_map{&node, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS} + pub_map{node, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS} { } diff --git a/src/core/threads/localization_worker.cpp b/src/core/threads/localization_worker.cpp index 49079ec..0a7af0f 100644 --- a/src/core/threads/localization_worker.cpp +++ b/src/core/threads/localization_worker.cpp @@ -92,7 +92,7 @@ LocalizationWorker::LocalizationWorker( tf_buffer{tf_buffer}, imu_sampler{imu_sampler}, tf_broadcaster{node}, - pub_map{&node, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS}, + pub_map{node, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS}, lidar_odom{node}, transform_sync{tf_broadcaster} { diff --git a/src/core/threads/mapping_worker.cpp b/src/core/threads/mapping_worker.cpp index 463c457..4cdefc0 100644 --- a/src/core/threads/mapping_worker.cpp +++ b/src/core/threads/mapping_worker.cpp @@ -69,7 +69,7 @@ namespace perception MappingWorker::MappingWorker(RclNode& node) : node{node}, - pub_map{&node, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS} + pub_map{node, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS} { } diff --git a/src/core/threads/mining_eval_worker.cpp b/src/core/threads/mining_eval_worker.cpp index a5d3742..220af4f 100644 --- a/src/core/threads/mining_eval_worker.cpp +++ b/src/core/threads/mining_eval_worker.cpp @@ -57,7 +57,7 @@ MiningEvalWorker::MiningEvalWorker( const Tf2Buffer& tf_buffer) : node{node}, tf_buffer{tf_buffer}, - pub_map{&node, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS} + pub_map{node, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS} { } diff --git a/src/core/threads/path_planning_worker.cpp b/src/core/threads/path_planning_worker.cpp index 50fa4ab..49bdfdb 100644 --- a/src/core/threads/path_planning_worker.cpp +++ b/src/core/threads/path_planning_worker.cpp @@ -75,7 +75,7 @@ PathPlanningWorker::PathPlanningWorker( const Tf2Buffer& tf_buffer) : node{node}, tf_buffer{tf_buffer}, - pub_map{&node, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS} + pub_map{node, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS} { } diff --git a/src/core/threads/traversibility_worker.cpp b/src/core/threads/traversibility_worker.cpp index 2da0c04..ae17db4 100644 --- a/src/core/threads/traversibility_worker.cpp +++ b/src/core/threads/traversibility_worker.cpp @@ -72,7 +72,7 @@ TraversibilityWorker::TraversibilityWorker( const ImuIntegrator<>& imu_sampler) : node{node}, imu_sampler{imu_sampler}, - pub_map{&node, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS} + pub_map{node, PERCEPTION_TOPIC(""), PERCEPTION_PUBSUB_QOS} { }