Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags. |
How to register and publish variables
Description: How to register and publish variablesKeywords: pal_statistics, logging
Tutorial Level: INTERMEDIATE
Next Tutorial: pal_statistics/Tutorials/Aggregate, store and visualise statistics
Contents
Registration C++
The Code
The following example shows how to register and publish a temperature reading.
1 #include <pal_statistics/pal_statistics_macros.h>
2 void do_monitor_temperature()
3 {
4 double temperature;
5 pal_statistics::RegistrationsRAII registrations;
6 REGISTER_VARIABLE("/statistics_topic", "motor temperature", &temperature, ®istrations);
7 while (ros::ok())
8 {
9 temperature = read_temperature();
10 ros::Duration(0.1).sleep();
11 PUBLISH_STATISTICS("/statistics_topic");
12 }
13 //Unregister variable
14 UNREGISTER_VARIABLE("/statistics_topic", "motor temperature");
15 }
The Code Explained
Now, let's break down the code piece by piece.
5 pal_statistics::RegistrationsRAII registrations;
To log a variable, it must be registered with a name to a topic, the address of the variable must be provided.
When asked to publish all registered variables, their address will be accessed and and their values updated.
This part of the code modifies the variable we have registered, and publishes them periodically. If the topic name is changed, it will attempt to publish variables registered to the new topic name, which will not include "motor temperature"
12 }
Unregister the variable, this is critical. If a variable is destroyed, but it has not been unregistered, it may be attempted to read, which in the worst case scenario will cause a segmentation fault.
Automatic Unregister C++
The Code
Following on the previous example, we'll see how to have automatic unregistration when going out of scope.
This is the recommended way of using pal_statistics, in the same way smart pointers are preferred over old C-style pointers.
1 #include <pal_statistics/pal_statistics_macros.h>
2 void do_monitor_temperature()
3 {
4 double temperature;
5 RegistrationsRAII registrations;
6 REGISTER_VARIABLE("/statistics_topic", "motor temperature", &temperature, ®istrations);
7 while (ros::ok())
8 {
9 temperature = read_temperature();
10 ros::Duration(0.1).sleep();
11 PUBLISH_STATISTICS("/statistics_topic");
12 }
13 //Unregister is automatic when registrations goes out of scope
14 }
The Code Explained
Now, let's break down the code piece by piece.
We declare an object of type RegistrationsRAII after the declaration of our variables.
This object when provided to the REGISTER_VARIABLE macro, will keep track of the registration done. When it is destroyed, it will unregister all variables associated to it.
By declaring it after our variables, we ensure that it will be destroyed before the variables.
Advanced Registration C++
Non double variables
Any variable that can be cast to a double is suitable for registration.
Registering functions
You can also register a function to be called:
As well as a lambda expression:
Real Time Usage
This framework has been designed for realtime operation.
The following actions are RT safe (no memory allocs, waits, or other blocking or undeterministic behavior).
Publishing (using PUBLISH_ASYNC_STATISTICS)
- Enable a variable
- Disable a variable
Everything else is not RT safe, but for completeness:
- Register a variable
- Unregister a variable
- Start publish thread
Publish without using PUBLISH_ASYNC_STATISTICS
Real Time usage example
1 #include <pal_statistics/pal_statistics_macros.h>
2 void do_monitor_temperature()
3 {
4 // Initialization. Non RT Safe code
5 double temperature;
6 RegistrationsRAII registrations;
7 REGISTER_VARIABLE("/statistics_topic", "motor temperature", &temperature, ®istrations);
8 START_PUBLISH_THREAD("/statistics_topic");
9
10 // Main loop. RT Safe code only
11 while (ros::ok())
12 {
13 temperature = read_temperature();
14 PUBLISH_ASYNC_STATISTICS("/statistics_topic");
15 }
16 }
Each call to PUBLISH_ASYNC_STATISTICS reads the value of the registered variables and passes it to the publish thread without blocking, the publish thread which will then wake up and publish all the data that hasn't been published yet.
Enable/Disable variable
This is an advanced feature, allowing a soft unregistration in a RT-safe way. Look at the code documentation for more information.
Python API
The Python API is more limited due to language constraints, and since it doesn't have to deal with Real Time issues.
Registering variables
Notice that in Python, there's no registerVariable method, because python will copy the value of variables of simple types such as numbers. Therefore we have to use a lambda to read the value of the address at a later time.
It can still be used to register full functions that return some value:
1 registerFunction("my_function", self.my_function)
Publishing registered variables
1 registry.publish()
Unregistering registered variables
registry.unregister("var1")
Also, when a registry is destroyed, the variables are automatically unregistered.