多仿真世界与多场景下ROS2自动化测试技术问询
在多仿真世界与不同场景下开展ROS2测试的实操方案
一、加载仿真世界、场景及测试数据
1. 加载仿真世界
- 用Gazebo的话,直接在launch文件里指定世界文件:
示例launch代码:from launch import LaunchDescription from launch.actions import ExecuteProcess def generate_launch_description(): return LaunchDescription([ ExecuteProcess( cmd=['gazebo', '--verbose', 'path/to/your/world.world', '-s', 'libgazebo_ros_init.so'], output='screen' ) ]) - 如果用Webots这类其他仿真工具,通过对应的ROS2接口加载场景配置,比如在launch中启动Webots节点并指定world路径:
from launch_ros.actions import Node import os from ament_index_python.packages import get_package_share_directory def generate_launch_description(): return LaunchDescription([ Node( package='webots_ros2_driver', executable='driver', parameters=[{'world': os.path.join(get_package_share_directory('your_package'), 'worlds', 'test_world.wbt')}] ) ])
2. 加载场景参数
- 通过ROS2参数服务器传递场景变量,比如障碍物位置、目标点:
在launch里给测试节点传参:Node( package='your_test_package', executable='scene_loader', parameters=[ {'obstacle_coords': [1.5, 3.0]}, {'target_pos': [6.0, 0.0]} ] ) - 也可以用YAML配置文件批量加载,在launch里指定参数文件路径:
Node( package='your_test_package', executable='scene_loader', parameters=[os.path.join(get_package_share_directory('your_test_package'), 'config', 'scene_config.yaml')] )
3. 加载测试数据
- 预录制的传感器数据(激光、相机等)直接用rosbag2播放:
终端命令:ros2 bag play path/to/your/test_sensor_data_bag - 动态生成测试数据的话,在测试节点里构造话题消息发布就行,比如模拟GPS数据:
import rclpy from rclpy.node import Node from sensor_msgs.msg import NavSatFix class TestDataPublisher(Node): def __init__(self): super().__init__('test_data_pub') self.pub = self.create_publisher(NavSatFix, '/gps/fix', 10) self.timer = self.create_timer(0.1, self.publish_gps) def publish_gps(self): msg = NavSatFix() msg.latitude = 39.9042 msg.longitude = 116.4074 self.pub.publish(msg) def main(args=None): rclpy.init(args=args) node = TestDataPublisher() rclpy.spin(node) node.destroy_node() rclpy.shutdown() if __name__ == '__main__': main()
二、保存测试结果并与预期结果对比、分析偏差
1. 保存测试结果
- 用rosbag2录制关键话题(机器人位姿、控制指令等):
终端命令:ros2 bag record /robot/odom /cmd_vel -o test_results_bag - 在测试节点里直接把结果写入文件,比如CSV格式:
import csv from datetime import datetime def save_pose_result(pose): timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') with open('pose_results.csv', 'a', newline='') as f: writer = csv.writer(f) writer.writerow([timestamp, pose.position.x, pose.position.y, pose.orientation.z])
2. 与预期结果对比
- 先准备好预期结果文件(比如CSV格式的目标位姿序列),在测试脚本里读取后逐帧对比:
def read_expected_results(file_path): expected = [] with open(file_path, 'r') as f: reader = csv.reader(f) next(reader) # 跳过表头 for row in reader: expected.append((float(row[1]), float(row[2]))) return expected def compare_with_expected(actual_data, expected_data): for idx, (actual, expected) in enumerate(zip(actual_data, expected_data)): pos_error = ((actual[0]-expected[0])**2 + (actual[1]-expected[1])**2)**0.5 print(f"Step {idx}: Position error = {pos_error:.2f}m") - 用launch_testing写自动化测试用例,断言偏差在允许范围内:
import launch_testing from geometry_msgs.msg import PoseStamped def test_pose_accuracy(pose_sub): msg = pose_sub.wait_for_msg(timeout=5.0) assert abs(msg.pose.position.x - 6.0) < 0.1, "X轴位姿偏差超出阈值" assert abs(msg.pose.position.y - 0.0) < 0.1, "Y轴位姿偏差超出阈值"
3. 偏差分析
- 统计偏差的均值、最大值,用Matplotlib生成可视化图表:
import matplotlib.pyplot as plt def analyze_error(error_list): plt.figure(figsize=(10, 5)) plt.plot(error_list, label='Position Error') plt.title('测试过程中位姿偏差变化') plt.xlabel('时间步') plt.ylabel('偏差(m)') plt.legend() plt.savefig('error_trend.png') avg_error = sum(error_list)/len(error_list) max_error = max(error_list) print(f"平均偏差: {avg_error:.2f}m") print(f"最大偏差: {max_error:.2f}m") - 结合ROS2日志排查原因:用
ros2 topic echo /rosout查看节点输出,判断是传感器噪声、控制算法问题,还是仿真环境参数设置不合理导致的偏差。
内容的提问来源于stack exchange,提问作者shrw
相关产品推荐
相关产品推荐

