ros / geometry2

A set of ROS packages for keeping track of coordinate transforms.
190 stars 275 forks source link

TransformListener x10 higher CPU load in rclpy than rclpp #513

Closed charlielito closed 3 years ago

charlielito commented 3 years ago

System info

Steps to reproduce issue

Make sure the system is publishing transforms to /tf at 30Hz. Run a simple node with a TransformListener in python and in C++.

Python code

```python import rclpy from rclpy.node import Node from tf2_ros.buffer import Buffer from tf2_ros.transform_listener import TransformListener class MyNode(Node): def __init__( self, ) -> None: super().__init__("navigation_god_node") self.buffer = Buffer() self.listener = TransformListener( buffer=self.buffer, node=self, spin_thread=False ) self.listener.buffer = self.buffer self.tm_main = self.create_timer( timer_period_sec=0.5, callback=self.timer_callback, ) def timer_callback(self): if self.buffer.can_transform( "camera_color_optical_frame", "map", rclpy.time.Time(seconds=0, nanoseconds=0).to_msg(), ): self.get_logger().info("Can transform") def main(args=None) -> None: rclpy.init(args=args) node = MyNode() rclpy.spin(node) node.destroy_node() rclpy.shutdown() if __name__ == "__main__": main() ```

C++ code

```c++ #include #include "rclcpp/rclcpp.hpp" #include "rclcpp/time.hpp" #include #include #include "tf2_geometry_msgs/tf2_geometry_msgs.h" using namespace std::chrono_literals; using namespace std; class MyNode : public rclcpp::Node { public: MyNode(const string& node_name, const string& nm) : Node(node_name, nm) { _buffer_tf2 = std::make_unique(this->get_clock()); _listener_tf2 = std::make_shared(*_buffer_tf2); timer_ = this->create_wall_timer( 500ms, std::bind(&TFListenerNode::timer_callback, this)); } private: void timer_callback() { if (_buffer_tf2->canTransform("camera_color_optical_frame", "map", tf2::TimePointZero)) RCLCPP_INFO(this->get_logger(), "Can transform"); } rclcpp::TimerBase::SharedPtr timer_; std::unique_ptr _buffer_tf2; std::shared_ptr _listener_tf2; }; int main(int argc, char* argv[]) { rclcpp::init(argc, argv); auto tf_transforms_node = make_shared("listener_transforms_node", "tf_transforms"); rclcpp::spin(tf_transforms_node); rclcpp::shutdown(); return 0; } ```

Expected behavior

Roughly the CPU load should be the same, at least not that big difference.

Actual behavior

The python implementation loads the CPU almost 10x. Tested in my beefy laptop and in a Jetson.

My laptop

Python node: ~8% CPU one core C++ node: ~1% CPU one core

Jetson

Python node: ~20% CPU one core C++ node: ~2% CPU one core

In this case, it makes the python API unusable in a constraint environment like a Jetson.

charlielito commented 3 years ago

Sorry, posted this in the incorrect repository. Either way for an answer go to https://answers.ros.org/question/381395/transformlistener-x10-higher-cpu-load-in-rclpy-than-rclpp/