In the last blog post, we looked into how Viam can be integrated with ROS 2 and how to connect a Flutter app for remote control. In this blog, I wanted to take a look at monitoring and debugging ROS 2 logging with the Viam cloud platform web UI.
The use case I had in my mind was when a fleet is spread across many different places and networks and you are looking for a cloud-based single pane of glass to see what’s going on with your robots. The Viam cloud platform has a built-in view for log data, so the goal was to figure out how easy it would be to bring ROS logging messages into it.
After a bit of research on how ROS 2 handles logging, I learned that there are basically two options to access log messages: there are the usual log files, but there are also ROS topics providing holistic access to log data across your robots' components.
While it would be easy and straightforward to upload any type of file via the Viam Data Manager to the Viam cloud platform, it wouldn’t directly help me achieve my goal of viewing a real-time continuous stream of log messages. Also, I intended to use Viam’s log viewer UI, including its filter and search features, as log information can be overwhelming and those features definitely make the process of analyzing and debugging much easier.
Therefore, I decided to go down the road of using the preexisting ROS 2 integration module to get the logging data from the “/rosout” topic and develop a little service. This service will simply take the ROS messages, map them to Viam messages, and log them through the Viam logger, just like any other logging that happens within Viam. This allows me to use all of Viam's cloud platform features without any additional effort.
As has been mentioned in earlier blog posts, Viam uses the concept of modular resources. Resources in this context are either components or services. While components represent hardware devices, services are used for software functionality. You can combine or bundle multiple resources into a so-called module, which makes it easy to deploy, especially through our recently released Viam Registry.
Since we had already created a ROS 2 Integration module in the previous Integrate Your ROS 2 Robot with Viam blog, all I had to do now was add a service resource.
Creating a new service type is not complicated, and consists of three steps:
- Defining the service APIs through protobuf
- Implementing the abstract service class and APIs
- Implementing and registering the actual logger service model
Creating the ROS 2 logger service
For most of the other modular resources, especially components, Viam already provides a variety of standard API types and you don’t have to go through tedious processes such as writing protobuf files. However, for my logging service, there was no suitable type available, which gave me the opportunity to explore what needed to be done to add completely new resource types to Viam, including building a new API.
I didn’t want to overcomplicate things, so I decided to just add a single API, which allowed me to retrieve the current service configuration, the ROS topic in current use, and the log level.
Since I chose Python, this service definition then needed to be compiled into gRPC Python classes, which are used to build out the API. While you could use protoc, I chose Buf, which I find much simpler. Buf generates three Python files, containing client and server class definitions and types to be used for implementing the APIs.
It is recommended to use a separate “api.py” file to implement the APIs. In my specific logger service case, and probably most other cases, it contains three classes:
- Abstract ROS2LoggerService - Specifies the service API subtype and the signature of the status api.
- ROS2LoggerRPCService - The gRPC service server definition.
- ROS2LoggerClient - The gRPC service client definition.
Now that the service APIs are defined, it’s time for the actual ROS 2 Logger service model implementation. This is basically exactly the same as if you had created a new model of an existing type using one of the Viam standard resource APIs.
You can find the code for the implementation in the ros2_logger.py file. It’s simply a single class with a couple of functions defining the ROS 2 Logger service.
I was almost done, but there was still one more thing left to do. Since the Viam concept is to configure the back-end plumbing to free up developer time for actual robot functionality, I had to register my new service type with Viam's built-in registry. If you are curious how to do this, go and have a look at the __init__.py file in the ros2_logger folder and the main.py file.
Testing the ROS 2 logger service
The code was now complete! Now I had to see if it worked. My Turtlebot 4 was already set up, with Viam installed. All I had to do then was to copy my module folder onto the robot, and add the module and service configuration. Since it's a custom service, I simply added it directly to the RAW JSON configuration and let the Viam RDK do the rest.
If everything had been set up correctly, it would automatically instantiate a ROS 2 Logger service. Sure enough, voila!, the first messages started to arrive:
While it's great to get a lot of information about the robots, at a certain point the data volume can become problematic, especially in bigger fleets. So I have added a configuration attribute called “log_level” which accepts “debug", "info", "warn", "error" and "critical" as values. This means that for normal operations, I can set the log_level to error, which means only error-level and messages and above are sent to the cloud backend, reducing cost. Once I have identified that there is an actual issue which needs further investigation, I can then go ahead and change the level to info or lower and get many more details. Just another little thing to make life with robots a bit easier!
Stay tuned for future blog posts where we will keep extending the ROS 2 integration. If you have any questions or feedback, or want to discuss our approach in more detail, feel free to reach out!