|
36 | 36 | #include <tf2/impl/utils.h>
|
37 | 37 | #include <tf2_ros/buffer.h>
|
38 | 38 | #include <tf2_ros/message_filter.h>
|
| 39 | +#include <fuse_core/graph.hpp> |
| 40 | +#include <fuse_variables/position_3d_stamped.hpp> |
| 41 | +#include <geometry_msgs/msg/detail/point__struct.hpp> |
39 | 42 | #include <memory>
|
40 | 43 |
|
41 | 44 | #include <fuse_core/transaction.hpp>
|
|
46 | 49 | #include <geometry_msgs/msg/twist_with_covariance_stamped.hpp>
|
47 | 50 | #include <nav_msgs/msg/odometry.hpp>
|
48 | 51 | #include <pluginlib/class_list_macros.hpp>
|
| 52 | +#include <rclcpp/logging.hpp> |
49 | 53 | #include <rclcpp/rclcpp.hpp>
|
50 | 54 | #include <stdexcept>
|
51 | 55 | #include <string>
|
@@ -73,6 +77,21 @@ void TransformSensor::initialize(fuse_core::node_interfaces::NodeInterfaces<ALL_
|
73 | 77 | fuse_core::AsyncSensorModel::initialize(interfaces, name, transaction_callback);
|
74 | 78 | }
|
75 | 79 |
|
| 80 | +void TransformSensor::onGraphUpdate(fuse_core::Graph::ConstSharedPtr graph) |
| 81 | +{ |
| 82 | + if (last_uuid_.has_value()) |
| 83 | + { |
| 84 | + if (graph->variableExists(last_uuid_.value())) |
| 85 | + { |
| 86 | + auto const& last_position = graph->getVariable(last_uuid_.value()); |
| 87 | + last_position_ = geometry_msgs::msg::Point(); |
| 88 | + last_position_->x = last_position.data()[fuse_variables::Position3DStamped::X]; |
| 89 | + last_position_->y = last_position.data()[fuse_variables::Position3DStamped::Y]; |
| 90 | + last_position_->z = last_position.data()[fuse_variables::Position3DStamped::Z]; |
| 91 | + } |
| 92 | + } |
| 93 | +} |
| 94 | + |
76 | 95 | void TransformSensor::onInit()
|
77 | 96 | {
|
78 | 97 | logger_ = interfaces_.get_node_logging_interface()->get_logger();
|
@@ -254,6 +273,30 @@ void TransformSensor::process(MessageType const& msg)
|
254 | 273 | pose.pose.covariance[i * 7] = pose_covariances_[estimation_index][i];
|
255 | 274 | }
|
256 | 275 |
|
| 276 | + // outlier filtering |
| 277 | + if (params_.filter_outliers && last_position_.has_value() && last_stamp_.has_value()) |
| 278 | + { |
| 279 | + Eigen::Vector3d position_difference = Eigen::Vector3d::Zero(); |
| 280 | + position_difference.x() = last_position_->x - pose.pose.pose.position.x; |
| 281 | + position_difference.y() = last_position_->y - pose.pose.pose.position.y; |
| 282 | + position_difference.z() = last_position_->z - pose.pose.pose.position.z; |
| 283 | + auto const distance = position_difference.norm(); |
| 284 | + auto const time_difference = (rclcpp::Time(transform.header.stamp) - last_stamp_.value()).seconds(); |
| 285 | + |
| 286 | + if (distance >= params_.outlier_distance && time_difference <= params_.outlier_time_threshold) |
| 287 | + { |
| 288 | + // this is an outlier |
| 289 | + RCLCPP_WARN(logger_, |
| 290 | + "Filtered outlier with distance %.3f from (%.3f, %.3f, %.3f) %.3f seconds after most recent update", |
| 291 | + distance, last_position_->x, last_position_->y, last_position_->z, time_difference); |
| 292 | + return; |
| 293 | + } |
| 294 | + } |
| 295 | + |
| 296 | + // update outlier finding variables (must occur after outlier filtering) |
| 297 | + last_stamp_ = transform.header.stamp; |
| 298 | + last_uuid_ = fuse_variables::Position3DStamped(transform.header.stamp, device_id_).uuid(); |
| 299 | + |
257 | 300 | bool const validate = !params_.disable_checks;
|
258 | 301 | common::processAbsolutePose3DWithCovariance(name(), device_id_, pose, params_.pose_loss, "",
|
259 | 302 | params_.position_indices, params_.orientation_indices, *tf_buffer_,
|
|
0 commit comments