做机械臂导航时遇到的问题7:正向运动学求解:在关节空间进行规划
2017-12-22 15:36
465 查看
有时已经知道机械臂目标位姿的各关节信息,对于这种情况,我们用moveit可以很简单的将机械臂移动到目标位姿。本篇主要是参考《ROS by example (volume 2)》里的实例,在pi_robot代码的基础上修改。还有一些资料:http://www.360doc.com/content/16/0825/16/7821691_585865831.shtml一、配置moveit关节控制器ArbotiX的包提供了一个JTAC(Joint Trajectory Action Controller),它一方面直接控制伺服电机,另一方面使用Ros中的FollowJointTrajectoryAction去接收程序发过来的joint轨迹目标。所以:需要做的有2点:(1)配置一个底层硬件实际用到的JTAC。 这个JTAC会负责接收FollowJointTrajectoryAction内容。(2)配置一个moveit!插件,这个插件负责将JTAC与moveit!之间的通信抽象化。 这个插件叫moveit_simple_controller_manager,它可以配合FollowJointTrajectoryAction工作。需要我们自己做的事情就是配置参数将它们联系起来(topic和actions的名字)1、创建controllers.yaml文件
controller_list: - name: right_arm_controller action_ns: follow_joint_trajectory type: FollowJointTrajectory default: true joints: - joint_1 - joint_2 - joint_3这个文件放置在moveit配置文件的config目录下,我们用来测试的机械臂没有抓取的手爪,只用到了right_arm_controller这个控制器。注意:这个right_arm_controller控制器命名可以修改,但是与当初我们测试arbotix时的配置文件有关。我们当初学习arbotix节点控制伺服电机时,为arbotix配置了文件,名为:my_robot_arbotix.yaml,在里面我们命名了一些控制器controller,这里的controller命名、action_name必须要与moveit配置里的controllers.yaml文件中设置的action_ns相匹配。2、创建控制器管理器启动文件robot_arm_moveit_controller_manager.launch.xml这个文件放置在moveit配置文件的launch目录下,他会读取我们的controllers.yaml中设置好的控制器参数。
<launch> <!-- Set the param that trajectory_execution_manager needs to find the controller plugin --> <arg name="moveit_controller_manager" default="moveit_simple_controller_manager/MoveItSimpleControllerManager" /> <param name="moveit_controller_manager" value="$(arg moveit_controller_manager)"/> <!-- load controller_list --> <arg name="use_controller_manager" default="true" /> <!-- Load joint controller configurations from YAML file to parameter server --> <rosparam file="$(find arm_moveit_config)/config/controllers.yaml"/> </launch>二、关节空间的正运动学规划1、用arbotix关节控制器启动虚拟机械臂模型
xs@xs-PC:~/catkin_ws2/src/mybot_description/launch$ roslaunch my_robot_arbotix_ok.launch文件代码内容如下:(我是在教材例子中进行修改的,与机械臂控制无关的部分,比如right_gripper_controller,已经被注释掉了)大致内容是;(1)加载urdf模型(2)启动arbotix,包括上面我们提到的配置的一些控制器(3)启动tf节点,这里是我参考其他的文件时加上的。我在调试时,没有这个tf节点,规划过程中可以plan()出规划结果,但是excute()失败,加上之后就可以了,具体原因还不清楚,找到后,我会再补充。目前猜测可能是odom坐标系与机械臂的base_link之间缺少tf关系。(4)启动robot_state_publisher
<launch> <!-- Make sure we are not using simulated time --> <param name="/use_sim_time" value="false" /> <!-- Launch the arbotix driver in fake mode by default --> <arg name="sim" default="true" /> <!-- If using a real controller, look on /dev/ttyUSB0 by default --> <arg name="port" default="/dev/ttyUSB0" /> <!-- Load the URDF/Xacro model of our robot --> <param name="robot_description" textfile="/home/xs/catkin_ws2/src/mybot_description/urdf/robot_arm.urdf" /> <!-- Bring up the arbotix driver with a configuration file appropriate to the robot --> <node name="arbotix" pkg="arbotix_python" type="arbotix_driver" clear_params="true" output="screen"> <rosparam file="/home/xs/catkin_ws2/src/mybot_description/my_robot_arbotix.yaml" command="load" /> <param name="sim" value="$(arg sim)" /> <param name="port" value="$(arg port)" /> </node> <!-- Run a separate controller for the one sided gripper <node name="right_gripper_controller" pkg="arbotix_controllers" type="gripper_controller" output="screen"> <rosparam> model: singlesided invert: true center: 0.0 pad_width: 0.004 finger_length: 0.065 min_opening: -0.8 max_opening: 0.5 joint: right_gripper_finger_joint </rosparam> </node> --> <!-- Load the URDF, SRDF and other .yaml configuration files on the param server --> <include file="$(find arm_moveit_config)/launch/planning_context.launch"> <arg name="load_robot_description" value="true"/> </include> <!-- If needed, broadcast static tf for robot root --> <node pkg="tf" type="static_transform_publisher" name="virtual_joint_broadcaster_0" args="0 0 0 0 0 0 odom base_link 100" /> <!-- We do not have a robot connected, so publish fake joint states > <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher"> <param name="/use_gui" value="false"/> <rosparam param="/source_list">[/move_group/fake_controller_joint_states]</rosparam> </node--> <!-- Publish the robot state --> <node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher"> <param name="publish_frequency" type="double" value="20.0" /> </node> <!-- <node name="rviz" pkg="rviz" type="rviz" args="-d /home/xs/catkin_ws2/src/robot_arm/my_moveit.rviz" /> --> <!-- args="-d /home/xs/catkin_ws2/src/robot_arm/urdf.rviz" args="-d /home/xs/catkin_ws2/src/robot_arm/arm_nav_my.rviz" --> <!-- Start all servos in a relaxed state --> <node pkg="rbx2_dynamixels" type="arbotix_relax_all_servos.py" name="relax_all_servos" unless="$(arg sim)" /> <!-- Load diagnostics --> <node pkg="diagnostic_aggregator" type="aggregator_node" name="diagnostic_aggregator" clear_params="true" unless="$(arg sim)"> <rosparam command="load" file="$(find rbx2_dynamixels)/config/dynamixel_diagnostics.yaml" /> </node> <node pkg="rqt_robot_monitor" type="rqt_robot_monitor" name="rqt_robot_monitor" unless="$(arg sim)" /> </launch>启动这个launch文件后,终端显示状态如下,可以看到高亮显示arbotix 、virtual_joint_broadcaster_0、 robot_state_publisher、 right_arm_controller已被启动。2、启动move_group
xs@xs-PC:~/catkin_ws2/src/arm_moveit_config/launch$ roslaunch move_group.launch这个move_group.launch在moveit配置文件的launch目录下,文件启动的节点和服务都是moveit用来和机械臂交互的
<launch> <include file="$(find arm_moveit_config)/launch/planning_context.launch" /> <!-- GDB Debug Option --> <arg name="debug" default="false" /> <arg unless="$(arg debug)" name="launch_prefix" value="" /> <arg if="$(arg debug)" name="launch_prefix" value="gdb -x $(find arm_moveit_config)/launch/gdb_settings.gdb --ex run --args" /> <!-- Verbose Mode Option --> <arg name="info" default="$(arg debug)" /> <arg unless="$(arg info)" name="command_args" value="" /> <arg if="$(arg info)" name="command_args" value="--debug" /> <!-- move_group settings --> <arg name="allow_trajectory_execution" default="true"/> <arg name="fake_execution" default="false"/> <arg name="max_safe_path_cost" default="1"/> <arg name="jiggle_fraction" default="0.05" /> <arg name="publish_monitored_planning_scene" default="true"/> <!-- Planning Functionality --> <include ns="move_group" file="$(find arm_moveit_config)/launch/planning_pipeline.launch.xml"> <arg name="pipeline" value="ompl" /> </include> <!-- Trajectory Execution Functionality --> <include ns="move_group" file="$(find arm_moveit_config)/launch/trajectory_execution.launch.xml" if="$(arg allow_trajectory_execution)"> <arg name="moveit_manage_controllers" value="true" /> <arg name="moveit_controller_manager" value="robot_arm" unless="$(arg fake_execution)"/> <arg name="moveit_controller_manager" value="fake" if="$(arg fake_execution)"/> </include> <!-- Sensors Functionality --> <include ns="move_group" file="$(find arm_moveit_config)/launch/sensor_manager.launch.xml" if="$(arg allow_trajectory_execution)"> <arg name="moveit_sensor_manager" value="robot_arm" /> </include> <!-- Start the actual move_group node/action server --> <node name="move_group" launch-prefix="$(arg launch_prefix)" pkg="moveit_ros_move_group" type="move_group" respawn="false" output="screen" args="$(arg command_args)"> <!-- Set the display variable, in case OpenGL code is used internally --> <env name="DISPLAY" value="$(optenv DISPLAY :0)" /> <param name="allow_trajectory_execution" value="$(arg allow_trajectory_execution)"/> <param name="max_safe_path_cost" value="$(arg max_safe_path_cost)"/> <param name="jiggle_fraction" value="$(arg jiggle_fraction)" /> <!-- load these non-default MoveGroup capabilities --> <!-- <param name="capabilities" value=" a_package/AwsomeMotionPlanningCapability another_package/GraspPlanningPipeline " /> --> <!-- MoveGroup capabilities to load --> <param name="capabilities" value="move_group/MoveGroupCartesianPathService move_group/MoveGroupExecuteService move_group/MoveGroupKinematicsService move_group/MoveGroupMoveAction move_group/MoveGroupPickPlaceAction move_group/MoveGroupPlanService move_group/MoveGroupQueryPlannersService move_group/MoveGroupStateValidationService move_group/MoveGroupGetPlanningSceneService move_group/ClearOctomapService " /> <!-- inhibit these default MoveGroup capabilities --> <!-- <param name="disable_capabilities" value=" move_group/MoveGroupKinematicsService move_group/ClearOctomapService " /> --> <!-- Publish the planning scene of the physical robot so that rviz plugin can know actual robot --> <param name="planning_scene_monitor/publish_planning_scene" value="$(arg publish_monitored_planning_scene)" /> <param name="planning_scene_monitor/publish_geometry_updates" value="$(arg publish_monitored_planning_scene)" /> <param name="planning_scene_monitor/publish_state_updates" value="$(arg publish_monitored_planning_scene)" /> <param name="planning_scene_monitor/publish_transforms_updates" value="$(arg publish_monitored_planning_scene)" /> </node> </launch>3、启动rviz
xs@xs-PC:~$ rosrun rviz rviz -d'rospack find robot_arm'/my_moveit.rivzmy_moveit.rivz文件我保存在百度网盘链接:https://pan.baidu.com/s/1qY0vwZE 密码:astj执行结果4、运行运动学求解的脚本
xs@xs-PC:~$ rosrun rbx2_arm_nav moveit_fk_demo_my.pymoveit_fk_demo_my.py脚本内容如下,同样,我是在教材实例的脚本文件修改的,其中注释掉了与机械臂控制无关的内容,加了一些输出调试状态的信息代码(如rospy.loginfo("1111 execute traj_1 completed 1111 ") )
#!/usr/bin/env python """ moveit_fk_demo.py - Version 0.1 2014-01-14 Use forward kinemtatics to move the arm to a specified set of joint angles Created for the Pi Robot Project: http://www.pirobot.org Copyright (c) 2014 Patrick Goebel. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.5 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at: http://www.gnu.org/licenses/gpl.html """ import rospy, sys import moveit_commander from control_msgs.msg import GripperCommand class MoveItDemo: def __init__(self): # Initialize the move_group API moveit_commander.roscpp_initialize(sys.argv) # Initialize the ROS node rospy.init_node('moveit_demo', anonymous=True) #GRIPPER_OPEN = [0.05] #GRIPPER_CLOSED = [-0.03] #GRIPPER_NEUTRAL = [0.01] # Connect to the right_arm move group robot_arm = moveit_commander.MoveGroupCommander('arm') # Connect to the right_gripper move group # right_gripper = moveit_commander.MoveGroupCommander('right_gripper') # Get the name of the end-effector link end_effector_link = robot_arm.get_end_effector_link() # Display the name of the end_effector link rospy.loginfo("The end effector link is: " + str(end_effector_link)) # Set a small tolerance on joint angles robot_arm.set_goal_joint_tolerance(0.001) # right_gripper.set_goal_joint_tolerance(0.001) # Start the arm target in "resting" pose stored in the SRDF file robot_arm.set_named_target('resting') # Plan a trajectory to the goal configuration traj = robot_arm.plan() # Execute the planned trajectory robot_arm.execute(traj) # Pause for a moment rospy.sleep(1) # Set the gripper target to neutal position using a joint value target # right_gripper.set_joint_value_target(GRIPPER_NEUTRAL) # Plan and execute the gripper motion # right_gripper.go() # rospy.sleep(1) # Set target joint values for the arm: joints are in the order they appear in # the kinematic tree. robot_arm_active_joints = robot_arm.get_active_joints() rospy.loginfo("The robot_arm_active_joints is: " + str(robot_arm_active_joints)) joint_positions = [-1.0, -1.0, -1.0] # Set the arm's goal configuration to the be the joint positions robot_arm.set_joint_value_target(joint_positions) rospy.loginfo("0000 set_joint_target_completed 0000 ") # Plan and execute the motion ######robot_arm.go() traj1 = robot_arm.plan() #rospy.loginfo("11111111111111111111111111 "+ str(traj1)) # Execute the planned trajectory robot_arm.execute(traj1) rospy.loginfo("1111 execute traj_1 completed 1111 ") rospy.sleep(1) # Save this configuration for later robot_arm.remember_joint_values('saved_config', joint_positions) # Close the gripper as if picking something up # right_gripper.set_joint_value_target(GRIPPER_CLOSED) # right_gripper.go() # rospy.sleep(1) # Set the arm target to the named "straight_out" pose stored in the SRDF file robot_arm.set_named_target('forward') # Plan and execute the motion ########robot_arm.go() traj2 = robot_arm.plan() # Execute the planned trajectory robot_arm.execute(traj2) #rospy.loginfo("22222222222222222222222222223 "+ str(traj2)) rospy.loginfo("2222 execute traj_2 completed 2222 ") rospy.sleep(1) # Set the goal configuration to the named configuration saved earlier robot_arm.set_named_target('saved_config') # Plan and execute the motion #######robot_arm.go() traj3 = robot_arm.plan() # Execute the planned trajectory robot_arm.execute(traj3) #rospy.loginfo("333333333333333333333333333333333333 "+ str(traj3)) rospy.loginfo("3333 execute traj_3 completed 3333") rospy.sleep(1) # Open the gripper as if letting something go # right_gripper.set_joint_value_target(GRIPPER_OPEN) # right_gripper.go() # rospy.sleep(1) # Return the arm to the named "resting" pose stored in the SRDF file robot_arm.set_named_target('resting') #######robot_arm.go() traj4 = robot_arm.plan() 99b1 # Execute the planned trajectory robot_arm.execute(traj4) #rospy.loginfo("44444444444444444444444444444444 "+ str(traj4)) rospy.loginfo("4444 execute traj_4 completed 4444") rospy.sleep(1) # Return the gripper target to neutral position # right_gripper.set_joint_value_target(GRIPPER_NEUTRAL) # right_gripper.go() # rospy.sleep(1) # Cleanly shut down MoveIt moveit_commander.roscpp_shutdown() # Exit the script moveit_commander.os._exit(0) if __name__ == "__main__": try: MoveItDemo() except rospy.ROSInterruptException: pass运行结果是机械臂执到达了脚本中所设定的几个位姿 三、用图形化工具观察执行状态1、观察topic之间的联系信息
xs@xs-PC:~$ rosrun rqt_graph rqt_graph效果如下2、观察joint_states话题中包含的position和velocity信息xs@xs-PC:~$ rosrun rqt_plot rqt_plot 将postion【0】、postion【1】、postion【2】,velocity【0】、velocity【1】、velocity【2】加载上去,效果如下四、将joint_states话题中包含的position和velocity信息通过串口通信发送出去我们启动(做机械臂导航时遇到的问题5:如何使用ROS内嵌serial功能包实现串口通信)中的my_serial_node节点,来像串口助手发送状态信息
xs@xs-PC:~$ rosrun my_serial_node my_serial_node串口助手接收到信息如下:完成数据接收。
相关文章推荐
- 做机械臂导航时遇到的问题8:逆运动学求解:在笛卡尔空间规划
- 做机械臂导航时遇到的问题4:如何订阅joint_states话题(输出关节状态)
- 做机械臂导航时遇到的问题2:solidworks用sw_urdf插件生成urdf文件包后,需要修改的部分
- 做机械臂导航遇到的问题3:如何用arbotix接口控制机械臂
- 使用MATLAB进行一次和二次规划问题求解
- 做机械臂导航时遇到的问题5:如何使用ROS内嵌serial功能包实现串口通信
- 做机械臂导航时遇到的问题6:实现ROS串口通信的其他方式
- 做机械臂导航遇到的问题1:solidworks在生成urdf文件时崩溃的一种解决方法
- Matlab和LINGO求解线性规划问题
- Retrofit进行WebService请求遇到的问题总结
- LoadRunner进行性能测试时遇到的问题汇总
- 需求获取常见的方法是进行客户访谈,结合你的实践谈谈会遇到什么问题,你是怎么解决的?
- 使用mybatis在mysql中进行like查询遇到的问题
- socket iOS 与java 后台进行socket通讯遇到的问题以及解决方法
- 进行混合高斯聚类时遇到的ill-Condition问题
- 今天进行最后编译了,遇到了不少问题,现已解决,将问题和解决方法都记录下来;
- .net中使用TripleDESCryptoServiceProvider进行3DES加密遇到弱密钥的问题
- 常见的动态规划问题分析与求解
- 常见的动态规划问题分析与求解
- 利用IHttpModule及Session_End事件进行在线会员统计遇到的问题