Skip to content

Commit 723ed13

Browse files
committed
attempt to check distance to waypoint
1 parent 8c42411 commit 723ed13

File tree

2 files changed

+37
-118
lines changed

2 files changed

+37
-118
lines changed

artefacts.yaml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,8 @@ jobs:
3434
scenarios:
3535
defaults: # Global to all scenarios, and overriden in specific scenarios.
3636
output_dirs: ["output"]
37-
metrics:
38-
- /odometry_error
39-
- /distance_from_start_gt
40-
- /distance_from_start_est
4137
params:
4238
launch/world: ["empty.sdf"]
43-
controller_server/controller_frequency: [10.0]
4439
settings:
4540
- name: reach_goal
4641
run: "python3 -m pytest src/sam_bot_nav2_gz/test/test_reach_goal_pytest.py -s --junit-xml output/tests_junit.xml"

src/sam_bot_nav2_gz/test/test_reach_goal_pytest.py

Lines changed: 37 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import os
3131
sys.path.append(os.path.dirname(__file__))
3232
from sim_state import IgnitionSimStateUtil, EntityNotFoundError
33+
from sim_state.metric_value import Pose
3334

3435

3536

@@ -60,7 +61,7 @@ def merge_ros_params_files(source, override, destination):
6061
with open(destination, "w") as f:
6162
yaml.dump(merged_params, f)
6263

63-
@pytest.fixture()
64+
@pytest.fixture(scope="module")
6465
def reach_goal_proc():
6566
reach_goal = Node(
6667
package="sam_bot_nav2_gz",
@@ -71,8 +72,8 @@ def reach_goal_proc():
7172
return reach_goal
7273

7374

74-
@launch_pytest.fixture
75-
def launch_description(reach_goal_proc):
75+
@launch_pytest.fixture(scope="module")
76+
def launch_description(reach_goal_proc, sim):
7677
"""Launch description fixture for pytest-based testing"""
7778
try:
7879
world = get_artefacts_param("launch", "world", default="empty.sdf")
@@ -100,11 +101,10 @@ def launch_description(reach_goal_proc):
100101
launch_arguments=[
101102
("run_headless", run_headless),
102103
("world_file", world),
103-
("params_file", new_params_file),
104+
#("params_file", new_params_file),
104105
],
105106
)
106107

107-
108108

109109
# Gazebo ros bridge
110110
gz_bridge = Node(
@@ -120,115 +120,30 @@ def launch_description(reach_goal_proc):
120120
output="screen",
121121
)
122122

123-
gz_env = {'GZ_SIM_SYSTEM_PLUGIN_PATH':
124-
':'.join([os.environ.get('GZ_SIM_SYSTEM_PLUGIN_PATH', default=''),
125-
os.environ.get('LD_LIBRARY_PATH', default='')]),
126-
'IGN_GAZEBO_SYSTEM_PLUGIN_PATH': # TODO(CH3): To support pre-garden. Deprecated.
127-
':'.join([os.environ.get('IGN_GAZEBO_SYSTEM_PLUGIN_PATH', default=''),
128-
os.environ.get('LD_LIBRARY_PATH', default='')])}
129-
log_level = LaunchConfiguration("log_level")
130-
use_sim_time = LaunchConfiguration("use_sim_time")
131-
gz_verbosity = LaunchConfiguration("gz_verbosity")
132123
pkg_share = launch_ros.substitutions.FindPackageShare(
133124
package="sam_bot_nav2_gz"
134125
).find("sam_bot_nav2_gz")
135-
default_model_path = os.path.join(
136-
pkg_share, "src/description/sam_bot_description.urdf"
137-
)
138126
run_headless = LaunchConfiguration("run_headless")
139-
world_file_name = LaunchConfiguration("world_file")
140127
gz_models_path = ":".join([pkg_share, os.path.join(pkg_share, "models")])
141-
#gz_models_path = os.path.join(pkg_share, "models")
142-
world_path = PathJoinSubstitution([pkg_share, "world", world_file_name])
143-
gazebo = [
144-
ExecuteProcess(
145-
condition=launch.conditions.IfCondition(run_headless),
146-
cmd=['ruby', FindExecutable(name="ign"), 'gazebo', '-r', '-v', gz_verbosity, '-s', '--headless-rendering', world_path],
147-
output='screen',
148-
additional_env=gz_env, # type: ignore
149-
shell=False,
150-
),
151-
ExecuteProcess(
152-
condition=launch.conditions.UnlessCondition(run_headless),
153-
cmd=['ruby', FindExecutable(name="ign"), 'gazebo', '-r', '-v', gz_verbosity, world_path],
154-
output='screen',
155-
additional_env=gz_env, # type: ignore
156-
shell=False,
157-
)
158-
]
159128

160-
spawn_entity = Node(
161-
package="ros_gz_sim",
162-
executable="create",
163-
output="screen",
164-
arguments=[
165-
"-name",
166-
"sam_bot",
167-
"-topic",
168-
"robot_description",
169-
"-z",
170-
"1.0",
171-
"-x",
172-
"-2.0",
173-
"--ros-args",
174-
"--log-level",
175-
log_level,
176-
],
177-
parameters=[{"use_sim_time": use_sim_time}],
178-
)
179129

180130

181131
return LaunchDescription(
182132
[
183-
SetEnvironmentVariable(
184-
name="IGN_GAZEBO_RESOURCE_PATH",
185-
value=gz_models_path,
186-
),
187-
DeclareLaunchArgument(
188-
"gz_verbosity",
189-
default_value="3",
190-
description="Verbosity level for Ignition Gazebo (0~4).",
191-
),
192-
DeclareLaunchArgument(
193-
"gz_args",
194-
default_value="",
195-
description="Extra args for Gazebo (ie. '-s' for running headless)",
196-
),
197-
DeclareLaunchArgument(
198-
name="world_file",
199-
default_value="empty.sdf",
200-
),
201133
DeclareLaunchArgument(
202134
name="run_headless",
203135
default_value="False",
204136
description="Start GZ in hedless mode and don't start RViz (overrides use_rviz)",
205137
),
206-
DeclareLaunchArgument(
207-
name="use_sim_time",
208-
default_value="True",
209-
description="Flag to enable use_sim_time",
210-
),
211-
DeclareLaunchArgument(
212-
name="log_level",
213-
default_value="warn",
214-
description="The level of logging that is applied to all ROS 2 nodes launched by this script.",
215-
),
216-
#DeclareLaunchArgument(
217-
# name="run_headless",
218-
# default_value="False",
219-
# description="Start GZ in headless mode and don't start RViz (overrides use_rviz)",
220-
#),
221-
#launch_navigation_stack",
222-
*gazebo,
223-
spawn_entity,
224-
#reach_goal_proc,
138+
launch_navigation_stack,
139+
reach_goal_proc,
225140
gz_bridge,
226141
launch_pytest.actions.ReadyToTest()
227142
]
228143
)
229144

230145

231-
@pytest.fixture(scope="function")
146+
@pytest.fixture(scope="module")
232147
def sim():
233148
"""Fixture that provides access to simulation state during tests"""
234149
if not rclpy.ok():
@@ -241,32 +156,41 @@ def sim():
241156
util.stop_recording()
242157

243158

244-
#@pytest.mark.launch(fixture=launch_description)
245-
#def test_nav2_started(reach_goal_proc, launch_context):
246-
# """Test that Nav2 starts successfully"""
247-
# def validate_nav2_output(output):
248-
# return output and 'Nav2 active!' in output
249-
#
250-
# # Get the reach_goal process from the launch context
251-
# process_tools.wait_for_output_sync(
252-
# launch_context, reach_goal_proc, validate_nav2_output, timeout=30)
253-
#
159+
@pytest.mark.launch(fixture=launch_description)
160+
def test_nav2_started(reach_goal_proc, launch_context):
161+
"""Test that Nav2 starts successfully"""
162+
def validate_nav2_output(output):
163+
print(output)
164+
assert 'Nav2 active' in output, "process never printed Nav2 is ready"
165+
166+
# Get the reach_goal process from the launch context
167+
process_tools.assert_output_sync(
168+
launch_context, reach_goal_proc, validate_nav2_output, timeout=40)
169+
254170

255171
@pytest.mark.launch(fixture=launch_description)
256-
def test_reached_goal(reach_goal_proc,launch_context, sim):
172+
def test_reached_goal(reach_goal_proc, launch_context, sim):
257173
"""Check that the navigation goal is reached"""
258174
def validate_goal_output(output):
259-
return output and 'Goal succeeded!' in output
175+
print(output)
176+
assert 'Goal succeeded!' in output, "process never printed Goal succeeded!"
260177

261178
# Get the reach_goal process from the launch context
262-
process_tools.wait_for_output_sync(launch_context, reach_goal_proc, validate_goal_output, timeout=5)
179+
#process_tools.wait_for_output_sync(launch_context, reach_goal_proc, validate_goal_output, timeout=15)
180+
process_tools.assert_output_sync(launch_context, reach_goal_proc, validate_goal_output, timeout=45)
263181

264182
# Additional assertion using simulation state
265-
goal_coordinates = (2.0, 3.0) # Example goal coordinates - adjust as needed
266-
entity = sim.get_entity('ros_symbol')
267-
cam = sim.get_entity('sky_cam/camera_link')
268-
dist = entity.distance_to(cam).now()
269-
assert dist > 1.0, f"Robot is not close enough to camera at {cam.pose().now().x}. Distance: {dist}"
270-
assert cam.pose().now().z > 1.0
271-
entity.distance_to(cam).to_csv("output/test.csv")
183+
robot = sim.get_entity('sam_bot')
184+
185+
# Create odom frame using add_transform (uses robot's pose at time 0)
186+
initial_robot_pose = robot.pose().at(0) #shall we use .first()
187+
sim.add_transform("world", "odom", initial_robot_pose)
188+
189+
# Create goal waypoint in odom frame
190+
goal = Pose(x=0.8, y=-0.5, z=0.0, frame="odom")
191+
192+
dist = robot.distance_to(goal).now()
193+
assert dist < 1.0, f"Robot is not close enough to goal. Distance: {dist}"
194+
robot.distance_to(goal).to_csv("output/test.csv")
195+
robot.pose().to_csv("output/pose.csv")
272196

0 commit comments

Comments
 (0)