Carma-platform v4.2.0
CARMA Platform is built on robot operating system (ROS) and utilizes open source software (OSS) that enables Cooperative Driving Automation (CDA) features to allow Automated Driving Systems to interact and cooperate with infrastructure and other vehicles through communication.
monitor-ros-cpu.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2import psutil
3import time
4import csv
5import os
6import argparse
7from datetime import datetime
8
9# Define ROS-related keywords to filter processes
10ROS_KEYWORDS = {
11 "ros",
12 "node",
13 "rviz",
14 "rqt",
15 "/opt/ros/", # ROS installation path
16 "/opt/carma/", # CARMA ROS installation path
17 "roscore",
18 "rosmaster",
19 "roslaunch",
20 "rostopic",
21 "rosnode",
22 "rosbag",
23 "ros2",
24 "ros1_bridge",
25 "rmw", # ROS middleware
26 "fastrtps",
27 "cyclonedds",
28 "rclcpp",
29 "rclpy",
30 "noetic",
31 "foxy",
32 "humble",
33}
34
35# Define processes to exclude (to avoid false positives)
36# NOTE: Detection of these keywords overwrites the ROS_KEYWORDS
37EXCLUDE_KEYWORDS = {"code", "chrome", "firefox", "vscode", "gnome"}
38
39
41 parser = argparse.ArgumentParser(description="Monitor CPU usage of ROS2 nodes")
42 parser.add_argument(
43 "--output-dir",
44 "-o",
45 default="carma-cpu-usage-logs",
46 help="Directory to store output files (default: carma-cpu-usage-logs)",
47 )
48 parser.add_argument(
49 "--include-pattern",
50 "-i",
51 help="Additional comma-separated patterns to include in process filtering",
52 )
53 return parser.parse_args()
54
55
57 if not os.path.exists(output_dir):
58 os.makedirs(output_dir)
59 timestamp = datetime.now().strftime("%Y_%m_%d-%H_%M_%S")
60 filename = f"cpu_usage_ros2_nodes_{timestamp}.csv"
61 return os.path.join(output_dir, filename)
62
63
64def is_ros_related_process(proc_info, cmdline):
65 """
66 Check if a process is ROS-related based on name and command line
67 """
68 # Convert process information to lowercase for case-insensitive matching
69 name_lower = proc_info["name"].lower()
70 cmdline_lower = cmdline.lower()
71
72 # Check exclusions first
73 if any(excl in name_lower or excl in cmdline_lower for excl in EXCLUDE_KEYWORDS):
74 return False
75
76 # Check for ROS-related keywords in process name and command line
77 return any(
78 keyword in name_lower or keyword in cmdline_lower for keyword in ROS_KEYWORDS
79 )
80
81
83 """
84 Try to get ROS-related environment variables for a process
85 """
86 try:
87 proc = psutil.Process(pid)
88 env = proc.environ()
89 ros_env = {k: v for k, v in env.items() if "ROS" in k}
90 return bool(ros_env)
91 except (psutil.NoSuchProcess, psutil.AccessDenied):
92 return False
93
94
95def main():
96 args = parse_args()
97
98 # Add any additional include patterns from command line
99 if args.include_pattern:
100 additional_patterns = set(args.include_pattern.split(","))
101 ROS_KEYWORDS.update(additional_patterns)
102
103 output_file = setup_logging_directory(args.output_dir)
104
105 with open(output_file, mode="a") as file:
106 writer = csv.writer(file)
107 writer.writerow(
108 [
109 "Timestamp",
110 "PID",
111 "Process Name",
112 "CPU (%)",
113 "Memory (%)",
114 "Command Line",
115 "Total CPU (%)",
116 "Total CPU Num",
117 "Total Memory (%)",
118 "Total Memory (GB)",
119 ]
120 )
121
122 print(f"Starting to monitor the CPU usage data and saving to: {output_file}")
123
124 # Total CPU and memory size in GB doesn't change
125 total_memory_gb = psutil.virtual_memory().total / (1024**3)
126 total_cpus = os.cpu_count()
127
128 while True:
129 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
130 total_cpu_percent = psutil.cpu_percent(interval=None)
131 total_memory_percent = (
132 psutil.virtual_memory().percent
133 ) # Get total memory usage
134
135 for proc in psutil.process_iter(
136 ["pid", "name", "cpu_percent", "memory_percent", "cmdline"]
137 ):
138 try:
139 cmdline = (
140 " ".join(proc.info["cmdline"]) if proc.info["cmdline"] else ""
141 )
142
143 if is_ros_related_process(proc.info, cmdline):
144 pid = proc.info["pid"]
145 name = proc.info["name"]
146 cpu_percent = proc.info["cpu_percent"]
147 memory_percent = proc.info["memory_percent"]
148
149 writer.writerow(
150 [
151 timestamp,
152 pid,
153 name,
154 cpu_percent,
155 memory_percent,
156 cmdline,
157 total_cpu_percent,
158 total_cpus,
159 total_memory_percent,
160 total_memory_gb,
161 ]
162 )
163
164 except (
165 psutil.NoSuchProcess,
166 psutil.AccessDenied,
167 psutil.ZombieProcess,
168 ):
169 continue
170
171 time.sleep(1)
172
173
174if __name__ == "__main__":
175 main()
def is_ros_related_process(proc_info, cmdline)
def get_process_environment(pid)
def setup_logging_directory(output_dir)