99
1010import launch_testing
1111from launch import LaunchDescription
12- from launch .actions import IncludeLaunchDescription
13- from launch .launch_description_sources import PythonLaunchDescriptionSource
14- import psutil
12+ from launch .actions import (
13+ IncludeLaunchDescription ,
14+ )
15+ from launch .launch_description_sources import (
16+ PythonLaunchDescriptionSource ,
17+ )
1518
1619import rclpy
17- from geometry_msgs .msg import Twist
20+ from std_msgs .msg import Bool
21+ from geometry_msgs .msg import Twist , PoseStamped
1822from sensor_msgs .msg import Imu
1923
24+ from rclpy .qos import (
25+ QoSProfile ,
26+ QoSReliabilityPolicy ,
27+ QoSHistoryPolicy ,
28+ )
29+
30+ from test .utils import stop_gazebo
31+
2032
2133@pytest .mark .launch_test
2234def generate_test_description ():
@@ -62,7 +74,7 @@ def setUpClass(cls):
6274 cls .node = rclpy .create_node ("test_node" )
6375
6476 # wait for topics to be setup
65- time .sleep (10 )
77+ time .sleep (15 )
6678
6779 @classmethod
6880 def tearDownClass (cls ):
@@ -71,10 +83,7 @@ def tearDownClass(cls):
7183 cls .node .destroy_node ()
7284 rclpy .shutdown ()
7385 # Stop any running Gazebo processes
74- for proc in psutil .process_iter (["name" ]):
75- if proc .info ["name" ] in ["gzserver" , "gazebo" , "ign gazebo" , "gz" ]:
76- print (f"Stopping gzserver (PID={ proc .pid } )" )
77- proc .terminate ()
86+ stop_gazebo ()
7887
7988 def test_imu_works (self , proc_output ):
8089 """Test that the imu topic works."""
@@ -89,12 +98,19 @@ def test_imu_works(self, proc_output):
8998
9099 # Wait for messages (up to 1 second)
91100 for _ in range (10 ):
92- rclpy .spin_once (self .__class__ .node , timeout_sec = 0.1 )
101+ rclpy .spin_once (
102+ self .__class__ .node ,
103+ timeout_sec = 0.1 ,
104+ )
93105 if msgs :
94106 break
95107
96108 # Check that we received msgs
97- self .assertGreater (len (msgs ), 0 , msg = "No IMU messages received." )
109+ self .assertGreater (
110+ len (msgs ),
111+ 0 ,
112+ msg = "No IMU messages received." ,
113+ )
98114
99115 # Clean up subscriptions
100116 self .__class__ .node .destroy_subscription (sub )
@@ -103,33 +119,67 @@ def test_movement_works(self, proc_output):
103119 """Test that the velocity topic works correctly."""
104120 msgs = []
105121
122+ sub_qos_profile = QoSProfile (
123+ reliability = QoSReliabilityPolicy .BEST_EFFORT ,
124+ history = QoSHistoryPolicy .KEEP_LAST ,
125+ depth = 10 ,
126+ )
127+
128+ pub_qos_profile = QoSProfile (
129+ reliability = QoSReliabilityPolicy .RELIABLE ,
130+ history = QoSHistoryPolicy .KEEP_LAST ,
131+ depth = 10 ,
132+ )
133+
106134 # Create a subscription to the velocity topic
107135 sub = self .__class__ .node .create_subscription (
108- Twist ,
109- "/gz/ drone0/cmd_vel " ,
136+ PoseStamped ,
137+ "/drone0/ground_truth/pose " ,
110138 lambda msg : msgs .append (msg ),
111- qos_profile = 10 ,
139+ qos_profile = sub_qos_profile ,
140+ )
141+
142+ arm_pub = self .__class__ .node .create_publisher (
143+ Bool ,
144+ "/gz/drone0/arm" ,
145+ qos_profile = pub_qos_profile ,
112146 )
113147
114148 # Create a publisher to the velocity topic
115149 pub = self .__class__ .node .create_publisher (
116150 Twist ,
117151 "/gz/drone0/cmd_vel" ,
118- qos_profile = 10 ,
152+ qos_profile = pub_qos_profile ,
119153 )
120154
121155 # Publish a high velocity message to move the vehicle
122156 twist_msg = Twist ()
123- twist_msg .linear .x = 45 .0 # Move forward at 45 m/s
124- twist_msg .angular .z = 120.0 # Turn at 120 rad/s
157+ twist_msg .linear .x = 1 .0 # Move forward at 1 m/s
158+ twist_msg .angular .z = 0.1 # Turn at 10 rad/s
125159
160+ arm_pub .publish (Bool (data = True ))
161+ rclpy .spin_once (
162+ self .__class__ .node ,
163+ timeout_sec = 0.1 ,
164+ )
126165 # Wait for a short time to allow odometry updates
127- for _ in range (15 ):
166+ for _ in range (100 ):
128167 pub .publish (twist_msg )
129- rclpy .spin_once (self .__class__ .node , timeout_sec = 0.1 )
130-
168+ rclpy .spin_once (
169+ self .__class__ .node ,
170+ timeout_sec = 0.1 ,
171+ )
131172 # Check that we received some messages
132- self .assertNotEqual (len (msgs ), 0 , msg = "No cmd_vel messages received." )
173+ self .assertNotAlmostEqual (
174+ msgs [- 1 ].pose .position .x ,
175+ msgs [0 ].pose .position .x ,
176+ msg = "Drone did not move." ,
177+ )
178+ self .assertNotEqual (
179+ len (msgs ),
180+ 0 ,
181+ msg = "No cmd_vel messages received." ,
182+ )
133183
134184 # Clean up subscriptions
135185 self .__class__ .node .destroy_subscription (sub )
0 commit comments