Building a Jetson Telemetry Service for Flutter Dashboards
Edge AI platforms like NVIDIA Jetson are powerful, but understanding their real-time operational status is crucial for reliable robotics. This article outlines how to construct a system that monitors key Jetson hardware metrics—CPU load, GPU utilization, temperature, and power consumption—and streams this data to a custom dashboard built with Flutter. This approach treats the telemetry data as a form of observability, providing insights into the robot's health without attempting to control its actions.
The goal is to create a flexible, lightweight telemetry service. This service will collect vital signs from the Jetson, such as CPU and GPU activity, memory usage, temperature readings, and power modes. These metrics are then exposed in a way that a Flutter application can easily consume, enabling developers to visualize the Jetson's performance and health in real-time. This is particularly valuable for debugging, performance tuning, and ensuring the longevity of the hardware in demanding robotic applications.
By the end of this process, you will have a functional Jetson/ROS 2 architecture, a development workspace ready for deployment, and a basic robotics pipeline. Crucially, you'll establish a clear path for integrating this telemetry system with a Flutter interface, along with foundational practices for logging, testing, and troubleshooting.
System Architecture and ROS 2 Integration
The foundation of this system relies on a Jetson/ROS 2 architecture. ROS 2 (Robot Operating System 2) provides a robust framework for inter-process communication, essential for collecting and distributing hardware metrics across different nodes. A dedicated ROS 2 node will be responsible for querying the Jetson's hardware statistics. This node will periodically collect data points for CPU usage (across all cores), GPU utilization, current temperature (often from thermal sensors), and power draw or power mode status.
These collected metrics will be published as ROS 2 messages on specific topics. For instance, CPU load might be published on a topic like /jetson_telemetry/cpu_load, GPU utilization on /jetson_telemetry/gpu_util, temperature on /jetson_telemetry/temperature, and power on /jetson_telemetry/power. The frequency of these publications can be tuned based on the need for real-time updates versus reducing network overhead. A common interval might be every 1 to 5 seconds.
The choice of ROS 2 is deliberate. Its DDS (Data Distribution Service) middleware offers efficient and reliable data transport, suitable for embedded systems. Furthermore, ROS 2's tooling and community support make it a practical choice for robotics development. This architecture ensures that the telemetry data is decoupled from any specific application, allowing for flexible consumption by various clients, including our Flutter dashboard.
Collecting Jetson Hardware Metrics with Python
To gather the necessary hardware metrics on the Jetson, a Python script will be employed. This script will act as the core data acquisition component within the ROS 2 node. Python's extensive libraries make it straightforward to interact with the underlying Linux system and access hardware information.
For CPU load, the psutil library is an excellent choice. It can provide detailed CPU utilization percentages for each core and overall system load. GPU utilization can be accessed using NVIDIA's proprietary tools, such as querying nvidia-smi, or through libraries that interface with the NVIDIA management library (NVML). Memory usage (RAM and Swap) can also be retrieved using psutil.
Temperature monitoring typically involves reading values from specific system files in the /sys/class/thermal/ directory on Linux-based systems like Jetson. The exact path may vary slightly between Jetson models, but it generally involves iterating through thermal zones and reading their temperature readings, often in millidegrees Celsius, which then need to be converted to degrees Celsius.
Power metrics can be more complex. Some Jetson platforms offer power monitoring through tegrastats, a command-line utility that provides real-time information about CPU, GPU, and other component power consumption. Alternatively, specific sysfs entries might expose power-related data. The Python script will parse the output of these tools or read from these files, process the raw data into meaningful units (e.g., Watts for power, degrees Celsius for temperature), and prepare them for publication.
Exposing Metrics via ROS 2 Topics
Once the Python script successfully collects the hardware metrics, these values need to be published onto ROS 2 topics. This is where the ROS 2 framework shines, providing a standardized way to broadcast data.
We will define custom ROS 2 message types or use standard ones where appropriate to represent the telemetry data. For example, a custom message type for CPU load might include fields for overall CPU percentage and individual core percentages. A temperature message could contain a single float for the current temperature in degrees Celsius. For power, a message might include total power draw in Watts.
The Python ROS 2 node will instantiate a publisher for each topic. As the script collects new data points, it will create instances of these messages, populate them with the latest readings, and then publish them to their respective topics. For instance:
# Inside the Python ROS 2 node script
import rclpy
from rclpy.node import Node
# Assume custom message types are defined or standard ones are used
# from your_msgs.msg import JetsonMetrics
class TelemetryPublisher(Node):
def __init__(self):
super().__init__('jetson_telemetry_publisher')
self.publisher_cpu = self.create_publisher(Float32, '/jetson_telemetry/cpu_load', 10)
self.publisher_gpu = self.create_publisher(Float32, '/jetson_telemetry/gpu_util', 10)
# ... other publishers ...
self.timer = self.create_timer(1.0, self.collect_and_publish_metrics) # Publish every 1 second
def collect_and_publish_metrics(self):
cpu_load = self.get_cpu_load() # Function to get CPU load
gpu_util = self.get_gpu_util() # Function to get GPU util
msg_cpu = Float32()
msg_cpu.data = cpu_load
self.publisher_cpu.publish(msg_cpu)
msg_gpu = Float32()
msg_gpu.data = gpu_util
self.publisher_gpu.publish(msg_gpu)
# ... publish other metrics ...
self.get_logger().info('Published telemetry data')
def main(args=None):
rclpy.init(args=args)
telemetry_publisher = TelemetryPublisher()
rclpy.spin(telemetry_publisher)
telemetry_publisher.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
This setup ensures that any ROS 2 subscriber can easily subscribe to these topics and receive the real-time telemetry data. The use of standard ROS 2 communication patterns simplifies integration and debugging.
Connecting to Flutter for Dashboard Visualization
The final piece of the puzzle is connecting the ROS 2 telemetry data to a Flutter application for visualization. Since Flutter applications typically run as standalone clients and not directly within the ROS 2 network by default, an intermediary is often needed. One common approach is to use a ROS 2 bridge or an MQTT broker.
Using a ROS 2 Bridge: A ROS 2 bridge, such as rosbridge_server, can be run on the Jetson. This bridge listens to ROS 2 topics and exposes them over WebSockets. The Flutter application can then connect to this WebSocket server, subscribe to the telemetry topics, and receive the data. This requires running rosbridge_server on the Jetson and ensuring network connectivity between the Flutter app (which could be running on a connected tablet or PC) and the Jetson.
Using MQTT: Alternatively, a more decoupled approach involves an MQTT broker. The ROS 2 telemetry node can be configured to publish its ROS 2 messages to an MQTT broker. Then, the Flutter application, acting as an MQTT client, can subscribe to the same MQTT topics to receive the data. This method is often preferred for its simplicity and scalability, especially in environments where direct ROS 2 communication might be complex or undesirable. Libraries like paho-mqtt in Python can be used for publishing, and various Flutter MQTT client packages are available.
Once the Flutter app receives the data (e.g., via WebSockets from rosbridge or MQTT messages), it can use charting libraries like fl_chart or custom UI elements to display CPU load, GPU utilization, temperature, and power consumption in an intuitive, real-time dashboard format. This provides operators with immediate insight into the robot's operational status, enabling proactive maintenance and performance optimization.
