ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

ROS 2 Bouncy : Node, Log and Classes best practice

asked 2018-10-03 02:54:58 -0500

Marc Testier gravatar image

updated 2018-10-03 02:59:01 -0500

Hello I am working with ROS 2 Bouncy and was wondering what is the best practice to log stuff in classes that are instantiated in a Node ?

I know it's now recommended to inherit the rclcpp::Node class and you can simply log by doing RCLCPP_INFO(this->get_logger(), "My message").

My question is about the best practice to log in customs classes inside the Node. For example, let's say we have this class :

class MyNodeClass : public rclcpp::Node
{
public:
  MyNodeClass()
  : Node("my_node_class") {
    CustomClass custom_class();
  }

  MyNodeClass::do_stuff(){
    custom_class.do_stuff();
  }
}

Which of this 4 options is the recommended way to give CustomClass access to the logger ?

Option 1 : We give the Node to the CustomClass constructor which save it in some var to be able to log in any function.

MyNodeClass : public rclcpp::Node
{
public:
  MyNodeClass()
  : Node("my_node_class") {
    CustomClass custom_class(this);
  }

  MyNodeClass::do_stuff(){
    custom_class.do_stuff();
  }
}

Option 2 : We give the logger to the CustomClass constructor which save it in some var to be able to use it in any function.

MyNodeClass : public rclcpp::Node
{
public:
  MyNodeClass()
  : Node("my_node_class") {
    CustomClass custom_class(this->get_logger());
  }

  MyNodeClass::do_stuff(){
    custom_class.do_stuff();
  }
}

Option 3 : We give the node to each CustomClass function if they need to log stuff.

class MyNodeClass : public rclcpp::Node
{
public:
  MyNodeClass()
  : Node("my_node_class") {
    CustomClass custom_class();
  }

  MyNodeClass::do_stuff(){
    custom_class.do_stuff(this);
  }
}

Option 4 : We only give the Node's logger to each CustomClass function.

class MyNodeClass : public rclcpp::Node
{
public:
  MyNodeClass()
  : Node("my_node_class") {
    CustomClass custom_class();
  }

  MyNodeClass::do_stuff(){
    custom_class.do_stuff(this->get_logger());
  }
}

Any other option ? Does any of this really matter or can we choose any option ?

Thank you.

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
2

answered 2018-10-05 09:30:35 -0500

William gravatar image

I'd actually recommend option 2 (passing the logger instance given by the node to your custom class), unless your class also needs the node, in which case option 1 is fine (no need to pass both the node and the logger).

If only a few methods of the custom class need to do logging you might consider option 3 or 4, but again I'd prefer option 4 to option 3, preferring to limit what information you pass into the class to only what you need.

In all cases, I'll point out that you can "extend" the logger given to the class to add extra namespace if you desire it, see: http://docs.ros2.org/bouncy/api/rclcp...

Also, you might consider taking a function for logging to completely decouple your custom class from ROS primitives altogether. For example:

MyNodeClass : public rclcpp::Node
{
public:
  MyNodeClass()
  : Node("my_node_class") {
    custom_class(
      [logger = this->get_logger()] (const std::string & msg) -> void {RCLCPP_INFO(logger, msg);}
    );
  }

  MyNodeClass::do_stuff(){
    custom_class.do_stuff();
  }

  CustomClass custom_class;
}
edit flag offensive delete link more

Comments

For option 2, how do I declare and define the logger var on the CustomClass side? I tried smth like this but it didn't work:

Class CustomClass{
  CustomClass(rclcpp::Logger &logger){
    this->logger = logger;
  }
  private:
    rclcpp::Logger *logger;
};
vadbut gravatar image vadbut  ( 2019-02-26 17:27:06 -0500 )edit
1

This:

struct CustomClass {
  CustomeClass(rclcpp::Logger logger) : logger_(logger) {}
private:
  rclcpp::Logger logger_;
};

Maybe?

William gravatar image William  ( 2019-02-27 00:09:30 -0500 )edit
0

answered 2018-10-03 05:03:23 -0500

tfoote gravatar image

It does matter, however there's no generic right option for all cases. Each one could be better in different situations.

If you are only planning to use the logger in that one function one time or only in places where the logger is easily accessible in the current context it would be fine to use Option 3

If you're going to use the logger in many different methods, call methods from contexts without the logger conveniently accessible, or potentially callbacks etc you'll probably want to escalate to option 2 where the logger does not need to be passed to all elements of the API.

And if you're going to be using other features of the Node inside the class you could consider option 1. But if you just want the logger functionality I'd recommend only passing what you need.

edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2018-10-03 02:54:58 -0500

Seen: 760 times

Last updated: Oct 05 '18