小鱼 ROS 2 新书上线!点击链接查看, 新书配套视频点击链接查看。
提问前必看的发帖注意事项—— 提问前必看!不符合要求的问题拒绝回答!!
社区使用指南—如何添加标签修改密码
运行自己编写的代码时出现Could not find parameter robot_description_semantic and did……问题
-
我在尝试用自己编写的代码替代RViz进行机械臂模型控制时,运行节点遇到了如下问题:
pan@pan-System-Product-Name:~/moveit_test$ ros2 launch abb_move abb_movetest.launch.py description_package:=abb_irb1200_support description_file:=irb1200_5_90.xacro [INFO] [launch]: All log files can be found below /home/pan/.ros/log/2022-12-09-04-44-13-053005-pan-System-Product-Name-18773 [INFO] [launch]: Default logging verbosity is set to INFO [INFO] [abb_move_node-1]: process started with pid [18774] [abb_move_node-1] [ERROR] [1670532263.177034233] [move_group_interface_tutorial]: Could not find parameter robot_description_semantic and did not receive robot_description_semantic via std_msgs::msg::String subscription within 10.000000 seconds. [abb_move_node-1] Error: Could not parse the SRDF XML File. Error=XML_ERROR_EMPTY_DOCUMENT ErrorID=13 (0xd) Line number=0 [abb_move_node-1] at line 715 in /home/pan/moveit2_ws/src/srdfdom/src/model.cpp [abb_move_node-1] [ERROR] [1670532263.202130862] [moveit_rdf_loader.rdf_loader]: Unable to parse SRDF [abb_move_node-1] [FATAL] [1670532263.202532924] [move_group_interface]: Unable to construct robot model. Please make sure all needed information is on the parameter server. [abb_move_node-1] terminate called after throwing an instance of 'std::runtime_error' [abb_move_node-1] what(): Unable to construct robot model. Please make sure all needed information is on the parameter server. [ERROR] [abb_move_node-1]: process has died [pid 18774, exit code -6, cmd '/home/pan/moveit_test/install/abb_move/lib/abb_move/abb_move_node --ros-args'].
代码是参考move_group_interface_tutorial所写,部分代码如下所示:
// launch设置里面需要设置srdf等模型信息吗? /* 需求: 步骤: 1.包含头文件; 2.初始化 ROS2 客户端; 3.定义节点类; 4.调用spin函数,并传入节点对象指针; 5.释放资源。 */ // 1.包含头文件; #include <rclcpp/rclcpp.hpp> #include <moveit/move_group_interface/move_group_interface.h> #include <moveit/planning_scene_interface/planning_scene_interface.h> #include <moveit_msgs/msg/display_robot_state.hpp> #include <moveit_msgs/msg/display_trajectory.hpp> #include <moveit_msgs/msg/attached_collision_object.hpp> #include <moveit_msgs/msg/collision_object.hpp> #include <moveit_visual_tools/moveit_visual_tools.h> static const rclcpp::Logger LOGGER = rclcpp::get_logger("move_group_demo"); int main(int argc, char** argv) { rclcpp::init(argc, argv); rclcpp::NodeOptions node_options; //这允许加载未声明的参数最佳实践是在相应的类中声明参数并提供有关预期用途的描述 node_options.automatically_declare_parameters_from_overrides(true); auto move_group_node = rclcpp::Node::make_shared("move_group_interface_tutorial", node_options); /* auto const node = std::make_shared<rclcpp::Node>( "hello_moveit", rclcpp::NodeOptions().automatically_declare_parameters_from_overrides(true) ); 第一个参数是ROS将用于创建唯一节点的字符串。MoveIt需要第二个,因为我们使用ROS参数的方式。 */ rclcpp::executors::SingleThreadedExecutor executor; executor.add_node(move_group_node); std::thread([&executor]() { executor.spin(); }).detach(); // step1:**********设置****************** static const std::string PLANNING_GROUP = "manipulator"; //规划组名称 private里面不能调用static 在rviz_planning request里面可以找到 moveit::planning_interface::MoveGroupInterface move_group(move_group_node, PLANNING_GROUP); const moveit::core::JointModelGroup* joint_model_group = move_group.getCurrentState()->getJointModelGroup(PLANNING_GROUP); // step2:*********可视化***************** namespace rvt = rviz_visual_tools; //命名空间 在remote_control里面有 namespace rviz_visual_tools moveit_visual_tools::MoveItVisualTools visual_tools(move_group_node, "base_link", "move_group_tutorial", move_group.getRobotModel()); visual_tools.deleteAllMarkers(); //删除所有标记 visual_tools.loadRemoteControl(); //加载远程控件 Eigen::Isometry3d text_pose = Eigen::Isometry3d::Identity(); text_pose.translation().z() = 1.0; visual_tools.publishText(text_pose, "MoveGroupInterface_Demo", rvt::WHITE, rvt::XLARGE); visual_tools.trigger(); RCLCPP_INFO(LOGGER, "Planning frame: %s", move_group.getPlanningFrame().c_str()); //打印 参考坐标系名称 一般参考坐标系就是选的 base_frame visual_tools.prompt("Press 'next' in the RvizVisualToolsGui window to start the demo"); //默认是绑定在next上面吗? // step3:*********规划一个目标位姿********** geometry_msgs::msg::Pose target_pose1; target_pose1.orientation.w = 1.0; target_pose1.position.x = 0.28; target_pose1.position.y = -0.2; target_pose1.position.z = 0.5; move_group.setPoseTarget(target_pose1); // 规划一个运动,使动作组末端达到期望的位资 moveit::planning_interface::MoveGroupInterface::Plan my_plan; bool success = (move_group.plan(my_plan) == moveit::core::MoveItErrorCode::SUCCESS); RCLCPP_INFO(LOGGER, "Visualizing plan 1 (pose goal) %s", success ? "" : "FAILED"); // 将轨迹可视化为带有RViz标记的线 RCLCPP_INFO(LOGGER, "Visualizing plan 1 as trajectory line"); visual_tools.publishAxisLabeled(target_pose1, "pose1"); visual_tools.publishText(text_pose, "Pose_Goal", rvt::WHITE, rvt::XLARGE); visual_tools.publishTrajectoryLine(my_plan.trajectory_, joint_model_group); visual_tools.trigger(); // 每次trigger后面都要按next吗? visual_tools.prompt("Press 'next' in the RvizVisualToolsGui window to continue the demo"); // step4:*********移动目标位姿********* (采用的是规划关节空间目标的方法,而不是move_group.move();阻塞函数,在实际机器人中使用move() ) rclcpp::shutdown(); return 0; }
这是launch配置的代码:(总共有两个配置文件)
abb_control.launch.pyfrom launch import LaunchDescription from launch.actions import DeclareLaunchArgument from launch.conditions import IfCondition from launch.substitutions import ( Command, FindExecutable, LaunchConfiguration, PathJoinSubstitution, ) from launch_ros.actions import Node from launch_ros.substitutions import FindPackageShare def generate_launch_description(): declared_arguments = [] declared_arguments.append( DeclareLaunchArgument( "runtime_config_package", default_value="abb_bringup", description='Package with the controller\'s configuration in "config" folder. \ Usually the argument is not set, it enables use of a custom setup.', ) ) declared_arguments.append( DeclareLaunchArgument( "controllers_file", default_value="abb_controllers.yaml", description="YAML file with the controllers configuration.", ) ) declared_arguments.append( DeclareLaunchArgument( "description_package", default_value="", description="Description package with robot URDF/XACRO files. Usually the argument \ is not set, it enables use of a custom description.", ) ) declared_arguments.append( DeclareLaunchArgument( "moveit_config_package", default_value="", description="MoveIt configuration package for the robot, e.g. abb_irb1200_5_90_moveit_config", ) ) declared_arguments.append( DeclareLaunchArgument( "description_file", default_value="", description="URDF/XACRO description file with the robot, e.g. irb1200_5_90.xacro", ) ) declared_arguments.append( DeclareLaunchArgument( "prefix", default_value='""', description="Prefix of the joint names, useful for \ multi-robot setup. If changed then also joint names in the controllers' configuration \ have to be updated.", ) ) declared_arguments.append( DeclareLaunchArgument( "use_fake_hardware", default_value="false", description="Start robot with fake hardware mirroring command to its states.", ) ) declared_arguments.append( DeclareLaunchArgument( "rws_ip", default_value="None", description="IP of RWS computer. \ Used only if 'use_fake_hardware' parameter is false.", ) ) declared_arguments.append( DeclareLaunchArgument( "rws_port", default_value="80", description="Port at which RWS can be found. \ Used only if 'use_fake_hardware' parameter is false.", ) ) declared_arguments.append( DeclareLaunchArgument( "fake_sensor_commands", default_value="false", description="Enable fake command interfaces for sensors used for simple simulations. \ Used only if 'use_fake_hardware' parameter is true.", ) ) declared_arguments.append( DeclareLaunchArgument( "initial_joint_controller", default_value="joint_trajectory_controller", description="Robot controller to start.", ) ) declared_arguments.append( DeclareLaunchArgument( "launch_rviz", default_value="true", description="Launch RViz?" ) ) # Initialize Arguments runtime_config_package = LaunchConfiguration("runtime_config_package") controllers_file = LaunchConfiguration("controllers_file") description_package = LaunchConfiguration("description_package") moveit_config_package = LaunchConfiguration("moveit_config_package") description_file = LaunchConfiguration("description_file") prefix = LaunchConfiguration("prefix") use_fake_hardware = LaunchConfiguration("use_fake_hardware") fake_sensor_commands = LaunchConfiguration("fake_sensor_commands") rws_ip = LaunchConfiguration("rws_ip") rws_port = LaunchConfiguration("rws_port") initial_joint_controller = LaunchConfiguration("initial_joint_controller") launch_rviz = LaunchConfiguration("launch_rviz") robot_description_content = Command( [ PathJoinSubstitution([FindExecutable(name="xacro")]), " ", PathJoinSubstitution( [FindPackageShare(description_package), "urdf", description_file] ), " ", "prefix:=", prefix, " ", "use_fake_hardware:=", use_fake_hardware, " ", "fake_sensor_commands:=", fake_sensor_commands, " ", "rws_ip:=", rws_ip, " ", "rws_port:=", rws_port, " ", ] ) robot_description = {"robot_description": robot_description_content} robot_controllers = PathJoinSubstitution( [FindPackageShare(runtime_config_package), "config", controllers_file] ) rviz_config_file = PathJoinSubstitution( [FindPackageShare(moveit_config_package), "rviz", "moveit.rviz"] ) control_node = Node( package="controller_manager", executable="ros2_control_node", parameters=[robot_description, robot_controllers], output="both", ) robot_state_publisher_node = Node( package="robot_state_publisher", executable="robot_state_publisher", output="both", parameters=[robot_description], ) rviz_node = Node( package="rviz2", condition=IfCondition(launch_rviz), executable="rviz2", name="rviz2", output="log", arguments=["-d", rviz_config_file], ) joint_state_broadcaster_spawner = Node( package="controller_manager", executable="spawner", arguments=[ "joint_state_broadcaster", "--controller-manager", "/controller_manager", ], ) initial_joint_controller_spawner = Node( package="controller_manager", executable="spawner", arguments=[initial_joint_controller, "-c", "/controller_manager"], ) nodes_to_start = [ control_node, robot_state_publisher_node, rviz_node, joint_state_broadcaster_spawner, initial_joint_controller_spawner, ] return LaunchDescription(declared_arguments + nodes_to_start)
abb_moveit.launch.py
from ament_index_python.packages import get_package_share_directory from launch import LaunchDescription from launch.actions import DeclareLaunchArgument from launch.actions import OpaqueFunction from launch.substitutions import ( Command, FindExecutable, LaunchConfiguration, PathJoinSubstitution, ) from launch_ros.actions import Node from launch_ros.substitutions import FindPackageShare import os import yaml def load_yaml(package_name, file_path): package_path = get_package_share_directory(package_name) absolute_file_path = os.path.join(package_path, file_path) try: with open(absolute_file_path, "r") as file: return yaml.safe_load(file) except EnvironmentError: # parent of IOError, OSError *and* WindowsError where available return None def launch_setup(context, *args, **kwargs): # Command-line arguments robot_xacro_file = LaunchConfiguration("robot_xacro_file") support_package = LaunchConfiguration("support_package") moveit_config_package = LaunchConfiguration("moveit_config_package") moveit_config_file = LaunchConfiguration("moveit_config_file") # Planning context robot_description_content = Command( [ PathJoinSubstitution([FindExecutable(name="xacro")]), " ", PathJoinSubstitution( [FindPackageShare(support_package), "urdf", robot_xacro_file] ), ] ) robot_description = {"robot_description": robot_description_content} robot_description_semantic_content = Command( [ PathJoinSubstitution([FindExecutable(name="xacro")]), " ", PathJoinSubstitution( [FindPackageShare(moveit_config_package), "config", moveit_config_file] ), ] ) robot_description_semantic = { "robot_description_semantic": robot_description_semantic_content.perform( context ) } kinematics_yaml = load_yaml( "abb_irb1200_5_90_moveit_config", "config/kinematics.yaml" ) # Planning Functionality ompl_planning_pipeline_config = { "move_group": { "planning_plugin": "ompl_interface/OMPLPlanner", "request_adapters": """default_planner_request_adapters/AddTimeOptimalParameterization default_planner_request_adapters/ResolveConstraintFrames default_planner_request_adapters/FixWorkspaceBounds default_planner_request_adapters/FixStartStateBounds default_planner_request_adapters/FixStartStateCollision default_planner_request_adapters/FixStartStatePathConstraints""", "start_state_max_bounds_error": 0.1, } } ompl_planning_yaml = load_yaml( "abb_irb1200_5_90_moveit_config", "config/ompl_planning.yaml" ) ompl_planning_pipeline_config["move_group"].update(ompl_planning_yaml) # Trajectory Execution Functionality moveit_simple_controllers_yaml = load_yaml( "abb_irb1200_5_90_moveit_config", "config/moveit_controllers.yaml" ) moveit_controllers = { "moveit_simple_controller_manager": moveit_simple_controllers_yaml, "moveit_controller_manager": "moveit_simple_controller_manager/MoveItSimpleControllerManager", } trajectory_execution = { # MoveIt does not handle controller switching automatically "moveit_manage_controllers": False, "trajectory_execution.allowed_execution_duration_scaling": 1.2, "trajectory_execution.allowed_goal_duration_margin": 0.5, "trajectory_execution.allowed_start_tolerance": 0.01, } planning_scene_monitor_parameters = { "publish_planning_scene": True, "publish_geometry_updates": True, "publish_state_updates": True, "publish_transforms_updates": True, } # Start the actual move_group node/action server move_group_node = Node( package="moveit_ros_move_group", executable="move_group", output="screen", parameters=[ robot_description, robot_description_semantic, kinematics_yaml, ompl_planning_pipeline_config, trajectory_execution, moveit_controllers, planning_scene_monitor_parameters, ], ) # RViz rviz_base = os.path.join( get_package_share_directory("abb_irb1200_5_90_moveit_config"), "rviz" ) rviz_config = os.path.join(rviz_base, "moveit.rviz") rviz_node = Node( package="rviz2", executable="rviz2", name="rviz2", output="log", arguments=["-d", rviz_config], parameters=[ robot_description, robot_description_semantic, ompl_planning_pipeline_config, kinematics_yaml, ], ) # Static TF static_tf_node = Node( package="tf2_ros", executable="static_transform_publisher", name="static_transform_publisher", output="log", arguments=["0.0", "0.0", "0.0", "0.0", "0.0", "0.0", "world", "base_link"], ) # Publish TF robot_state_pub_node = Node( package="robot_state_publisher", executable="robot_state_publisher", name="robot_state_publisher", output="both", parameters=[robot_description], ) nodes_to_start = [move_group_node, rviz_node, static_tf_node, robot_state_pub_node] return nodes_to_start def generate_launch_description(): declared_arguments = [] # TODO(andyz): add other options declared_arguments.append( DeclareLaunchArgument( "robot_xacro_file", description="Xacro describing the robot.", choices=["irb1200_5_90.xacro"], ) ) declared_arguments.append( DeclareLaunchArgument( "support_package", description="Name of the support package", choices=["abb_irb1200_support"], ) ) declared_arguments.append( DeclareLaunchArgument( "moveit_config_package", description="Name of the support package", choices=["abb_irb1200_5_90_moveit_config"], ) ) declared_arguments.append( DeclareLaunchArgument( "moveit_config_file", description="Name of the SRDF file", choices=["abb_irb1200_5_90.srdf.xacro"], ) ) return LaunchDescription( declared_arguments + [OpaqueFunction(function=launch_setup)] )
版本 ros2 humble moveit2
以上是全部问题描述,下面是尝试部分:
使用官方ros2 launch moveit2_tutorials demo.launch.py rviz_tutorial:=true 仿真,然后用如下实例代码无问题#include <memory> #include <rclcpp/rclcpp.hpp> #include <moveit/move_group_interface/move_group_interface.h> int main(int argc, char* argv[]) { // Initialize ROS and create the Node rclcpp::init(argc, argv); auto const node = std::make_shared<rclcpp::Node>( "hello_moveit", rclcpp::NodeOptions().automatically_declare_parameters_from_overrides(true)); // Create a ROS logger auto const logger = rclcpp::get_logger("hello_moveit"); // Create the MoveIt MoveGroup Interface using moveit::planning_interface::MoveGroupInterface; auto move_group_interface = MoveGroupInterface(node, "panda_arm"); // Set a target Pose auto const target_pose = [] { geometry_msgs::msg::Pose msg; msg.orientation.w = 1.0; msg.position.x = 0.28; msg.position.y = -0.2; msg.position.z = 0.5; return msg; }(); move_group_interface.setPoseTarget(target_pose); // Create a plan to that target pose auto const [success, plan] = [&move_group_interface] { moveit::planning_interface::MoveGroupInterface::Plan msg; auto const ok = static_cast<bool>(move_group_interface.plan(msg)); return std::make_pair(ok, msg); }(); // Execute the plan if (success) { move_group_interface.execute(plan); } else { RCLCPP_ERROR(logger, "Planning failed!"); } // Shutdown ROS rclcpp::shutdown(); return 0; }
两者环境配置均在一个功能包里面。
然后在网上搜索了相关问题(用的chatgpt搜的,也不确定可不可行,找到了部分思路,但是貌似是moveit1 的思路)帮助1:如果在运行 MoveIt! 的代码时出现 "Could not find parameter robot_description_semantic" 的错误提示,通常是因为您在启动节点之前没有将机械臂的 URDF 模型文件加载到 ROS 的参数服务器中。
要解决这个问题,您需要在启动 MoveIt! 节点之前,使用以下命令将机械臂的 URDF 模型文件加载到参数服务器中:
rosparam load /path/to/robot_description.urdf robot_description
其中,"/path/to/robot_description.urdf" 是机械臂的 URDF 模型文件的完整路径,"robot_description" 是参数服务器中的参数名称。
帮助2:
如果您在运行代码时报告了 "Could not find parameter robot_description_semantic" 错误,这可能是因为您的代码中没有指定机械臂的描述信息。在 MoveIt! 中,机械臂的描述信息通常存储在一个名为 robot_description 的参数中,该参数用于描述机械臂的几何形状、关节信息、传感器位置等。
您可以在代码中通过如下方式指定机械臂的描述信息:
// First, create a node handle ros::NodeHandle node_handle; // Next, load the robot model const std::string robot_description = "robot_description"; const robot_model_loader::RobotModelLoader robot_model_loader(robot_description); const robot_model::RobotModelPtr robot_model = robot_model_loader.getModel();
在上面的代码中,我们使用了 robot_model_loader 类来加载 robot_description 参数中存储的机械臂描述信息,并将其存储在 robot_model 中。
帮助3:
这个问题可能是由于你没有在你的代码中正确地加载机器人描述文件(即URDF文件)造成的。URDF文件包含了机器人的几何形状和连杆参数信息,Rviz需要它来渲染机器人模型。要解决这个问题,你需要确保你的代码中有一行来加载URDF文件,例如:
const std::string robot_description = "robot_description"; const std::string robot_description_semantic = "robot_description_semantic"; ros::NodeHandle node_handle; urdf::Model model; if (!model.initParam(robot_description)) { ROS_ERROR("Failed to parse URDF file"); return -1; }
这段代码会使用ROS参数服务器加载机器人描述文件。如果你使用了不同的方法来加载URDF文件,可能需要修改这段代码以适应你的情况。
另外,如果你在代码中使用了机器人的参数(例如连杆长度、关节角度等),你需要确保这些参数在URDF文件中定义了。否则,在读取这些参数时会出现错误。
感觉大概的思路应该是为运行的节点找不到相关的描述文件,希望大家教教我怎么做,因为我在测试panda机器人的时候节点也没有进行对应的操作,两个操作的不同应该就在于launch文件不一样
-
@空白 我在ros2 param list |grep robot_description 中可以找到robot_description和robot_description_semantic相关参数,感觉重点好像在下面一句无法解析上面?
-
@空白 正确运行的时候会有以下日志输出:
[panda_move_node-1] [INFO] [1670539142.267081075] [moveit_rdf_loader.rdf_loader]: Loaded robot model in 0.0560178 seconds [panda_move_node-1] [INFO] [1670539142.267119504] [moveit_robot_model.robot_model]: Loading robot model 'panda'...
-
@空白
robot_description
包你运行了吗?我研究的不深,一般机械臂的模型参数都是那个包发布的 -
@Lorry 包都是可以正常运行的,效果就是启动了RViz,然后可以使用界面进行控制,查看参数的时候也可以找到robot_description和robot_description_semantic的对应描述,参数文件在launch里面有描述,如abb_moveit.launch.py
robot_description_content = Command( [ PathJoinSubstitution([FindExecutable(name="xacro")]), " ", PathJoinSubstitution( [FindPackageShare(support_package), "urdf", robot_xacro_file] ), ] ) robot_description = {"robot_description": robot_description_content} robot_description_semantic_content = Command( [ PathJoinSubstitution([FindExecutable(name="xacro")]), " ", PathJoinSubstitution( [FindPackageShare(moveit_config_package), "config", moveit_config_file] ), ] )
具体的细节我也不是特别了解,所以也不确定哪里出问题了
-
@空白 感觉有两个解决思路,一个就是在代码部分加上参数声明,一个就是改launch文件配置,但是两个都不是特别会
-
@Lorry 我刚刚在chatgpt上面找到了一个可能的思路,就是我moveit提供的机器人描述信息是通过运行节点时输入参数获得的,然后我在启动自己的节点包时可能这种方法会找不到描述信息
-
@空白 我之前看一个moveit2的包,他其中的机械臂描述文件通过robot_description包发布出去
-
@空白 用rviz2中的moveit插件手动拖拉规划是正常的吗,如果有robot_description可以尝试做一个重映射
将move_group_interface_tutorial节点robot_description_semantic重映射为robot_description
-
@小鱼 小鱼你好,手动拖拉是可以的,也能正常规划,我在param get 里面发现move_group的publish_robot_description的值是无not set,会不会是因为move_group没有发布robot_description的相关内容?
-
@空白 因为我发现其他能用move_group控制的这个参数是bool值true
-
@空白 有这个可能,没理解错这个值设成true的意思才是发布robot__description,你可以到配置文件找找这个参数,改改看
-
@小鱼 将semantic重映射的原理是什么呢,我在设置里面semantic对应的是srdf模型,对应的是动作组机械臂,而robot_description是用的urdf,对应的是机械臂模型
-
@小鱼 因为我重新改了launch文件,urdf文件都还是报一样的错误,只有觉得是参数的问题了
-
@空白 从你的参数这块入手,重映射方法要先确保robot_description是正常的才行,你可以通过ros2 topic echo /robot_description看看
-
@小鱼 我用ros2 param get robot_description得到的内容是正确的,同理robot_description_semantic内容也是正确的
-
@小鱼 这个重映射是为什么呢?因为在我的理解范围内两者并不是同一个内容
-
@空白 这应该都是机械臂的描述文件吧,看具体的错误是没有订阅到数据,不是通过参数传递的,而是话题,所以你应该检查话题
@空白 在 运行自己编写的代码时出现Could not find parameter robot_description_semantic and did……问题 中说:
did not receive robot_description_semantic via std_msgs::msg::String subscription within 10.000000 seconds.
-
@小鱼 我好像没有发布和订阅相关的话题 在后面用panda机械臂对比的时候也是,我理解中应该是调用move_group给节点的时候自动发布和订阅了这个话题吧?
-
@空白 有可能,这两天比较忙,抽空看看moveit源码这个话题到底用来干啥的