【UR5机械臂Moveit避障】【3】使用ros驱动真实UR5机械臂(直接驱动或使用moveit)

目录

有错误或没说清楚的地方欢迎评论指正,我会修改的,谢谢大家

apt安装必要组件

下载ur的ros包

ur5通讯连接(external control已有)

虚拟机修改网络连接方式

ur设置External Control网络

确认连接状况

启动ros连接节点和示教器程序

Rviz设置

实际测试(注意安全,必要时按急停键)

直接控制机械臂不经过moveit的方法(注意安全)

编写简单的moveit程序控制轨迹

修改ompl默认规划算法(非必要)


有错误或没说清楚的地方欢迎评论指正,我会修改的,谢谢大家

参考1:http://t.csdnimg.cn/OpXlh

参考2:http://t.csdnimg.cn/Tnlta

参考3:http://t.csdnimg.cn/Aicmy

参考4:http://t.csdnimg.cn/6BHgq

apt安装必要组件

先二进制安装一堆必要的包,不安装的话后面编译会缺东西报错。

不用参考:http://t.csdnimg.cn/WvSJS

那样找文件复制进来,这样本质就是编译安装了,但其实也是可以二进制安装的,这里我准备了apt安装大礼包一步到位:

sudo apt-get install ros-noetic-ur-client-library ros-noetic-ur-msgs ros-noetic-scaled-joint-trajectory-controller ros-noetic-joint-trajectory-controller ros-noetic-speed-scaling-interface ros-noetic-speed-scaling-state-controller ros-noetic-pass-through-controllers ros-noetic-industrial-robot-status-interface ros-noetic-moveit ros-noetic-effort-controllers ros-noetic-rqt-controller-manager ros-noetic-moveit-visual-tools ros-noetic-rviz-visual-tools ros-noetic-trac-ik-kinematics-plugin ros-noetic-ompl ros-noetic-moveit-planners-ompl

下面是大礼包的组成:

ur的ros包编译通过的必要组件:

sudo apt-get install ros-noetic-ur-client-library
sudo apt-get install ros-noetic-ur-msgs
sudo apt-get install ros-noetic-scaled-joint-trajectory-controller
sudo apt-get install ros-noetic-joint-trajectory-controller
sudo apt-get install ros-noetic-speed-scaling-interface
sudo apt-get install ros-noetic-speed-scaling-state-controller
sudo apt-get install ros-noetic-pass-through-controllers
sudo apt-get install ros-noetic-industrial-robot-status-interface
sudo apt-get install ros-noetic-moveit

下面是后续rviz和moveit的必要组件:

sudo apt-get install ros-noetic-effort-controllers
sudo apt-get install ros-noetic-rqt-controller-manager
sudo apt-get install ros-noetic-moveit-visual-tools
sudo apt-get install ros-noetic-rviz-visual-tools
sudo apt-get install ros-noetic-trac-ik-kinematics-plugin
sudo apt-get install ros-noetic-ompl
sudo apt-get install ros-noetic-moveit-planners-ompl

这里注意,如果后续要在moveit的ompl中添加自己的算法,可以编译安装moveit,我这里不涉及修改,所以moveit就使用二进制安装了(后续修改可以随时sudo apt-get remove moveit卸载并重新使用下载编译进行安装)。

下载ur的ros包

到工作空间目录下,下载ur的ros包1和ros包2,全部下载好之后编译:

cd ~/catkin_RealSense_ws/src 
git clone https://github.com/UniversalRobots/Universal_Robots_ROS_Driver.git
git clone -b noetic https://github.com/ros-industrial/universal_robot.git
cd ..
catkin_make

缺东西报错的情况(只是示例,moveit我们之前已经安装了):

一般这种显示ros缺什么就安装什么,

sudo apt install ros-noetic-xxx

比如这里显示缺moveit_core,那就使用如下命令进行安装(注意下划线_变为-)

sudo apt install ros-noetic-moveit-core

或者直接安装整个组件(core只是其中一部分)

sudo apt install ros-noetic-moveit

ur5通讯连接(external control已有)

这里需要先在机器人面板中添加一个控制程序external control,但是我这里已经有前人导入过了,具体的操作我也不明白所以也不好写。(我也比较懒,不想再搞一次)看教程好像也是要用个u盘导入进去即可。上面几个链接各位看一下吧。

虚拟机修改网络连接方式

如果是虚拟机的话,把网络连接修改为桥接模式。

开启ur5并用网线连接电脑,确认插入的是哪个网口

在那个网口手动设置ip地址

首先可以查看机器人的ip地址,一般为192.168.x.1,不同路由器有不同的x值,这个即为网关地址,子网掩码填255.255.255.0,最后是设置的地址192.168.x.yyy,这里的yyy可以随便填,但是最好填大一些,较小的值可能会和局域网内其他上网的设备ip冲突,我这里填192.168.0.114,记为地址1。

ur设置自身网络

设置机器人-网络-ip地址 填为 192.168.x.zzz,这里的zzz也可以随便填,我这里填192.168.0.101,记为地址2

ur设置External Control网络

为机器人编程-加载程序-打开externalcontrol.urp-安装设置-External control-设置ip地址为192.168.0.114,端口设置为50002

先不要运行,等ros节点开启后再点运行。

确保安装设置中的Ethernet/IP为禁用状态。

确认连接状况

ping 地址2

ping 192.168.0.101

如果有反应那就是连接成功

启动ros连接节点和示教器程序

roslaunch ur_robot_driver ur5_bringup.launch robot_ip:=地址2 limited:=true

roslaunch ur_robot_driver ur5_bringup.launch robot_ip:=192.168.0.101 limited:=true

在示教器上,安装设置左边-程序-点击下面的播放(启动),这时应该不会有报错

继续启动ros节点

启动moveit+启动rviz:

roslaunch ur5_moveit_config moveit_planning_execution.launch limited:=true
roslaunch ur5_moveit_config moveit_rviz.launch config:=true

总共需要开三个终端。

Rviz设置

在rviz中,Fixed Frame改为base_link或base。点击add-Motion_Planning确认。

把Planning Group改为manipulator。

如果发现设置为manipulator没有出现小球的话,那就是少安装下面这个东西了

sudo apt-get install ros-noetic-trac-ik-kinematics-plugin

参考:http://t.csdnimg.cn/Sbm4x

至此,所有设置完毕

实际测试(注意安全,必要时按急停键)

拖动球(不建议,关节会乱)或拉动joints中的关节值之后,点击plan查看预期轨迹,点击execute执行轨迹

直接控制机械臂不经过moveit的方法(注意安全)

在之前自己创建的ros包中添加demo01.py(这边建议用vscode)

#! /usr/bin/env python
from trajectory_msgs.msg import *
from control_msgs.msg import *
import rospy
import actionlib
from sensor_msgs.msg import JointState
 
JOINT_NAMES = ['shoulder_pan_joint', 'shoulder_lift_joint', 'elbow_joint',
               'wrist_1_joint', 'wrist_2_joint', 'wrist_3_joint']
Positions = [
    [1.57079632679490, -1.57079632679490, 0, 0, 0, 0],
    [1.57079632679490, -1.57079632679490, 1.57, 0, 0, 0],
    [0.535223679329313, -1.38916449768429, 0.0707966926333014, 0.00992183797719428, 0.207852467763008, -0.524655836120612],
    [0.446489423955664, -1.42714661245728, 0.294078481730749, 0.0980603444067962, -0.0256790257130683, -0.607041204841708],
    [-0.0216574244814170, -1.40521223969719, 0.402378963072291, -0.0189799772752150, -0.112174110863272, -0.803850090823849],
    [-0.531253055104619, -1.50586863685589, 0.398415734706829, 0.262154054243566, -0.0905583415373497, -0.714059925812534],
    [-1.05374250471503, -1.53850223076636, 0.198166237055209, 0.130391643533963, -0.0450424122672318, -0.355163102768306],
    [-1.00600034209831, -1.51992796220248, 0.184870711478269, 0.322985701688979, 0.242597136147687, -0.336522962390776],
    [-1.38004123386078, -1.43510968807964, 0.216763030854692, 0.267613089847475, 0.121854942204861, 0.0131483190630100],
    [-1.57079632679490, -1.57079632679490, 1.57, 0, 0, 0],
    [-1.57079632679490, -1.57079632679490, 0, 0, 0, 0]
    ]

 
def move():
          #goal就是我们向发送的关节运动数据,实例化为FollowJointTrajectoryGoal()类
          goal = FollowJointTrajectoryGoal()
 
          #goal当中的trajectory就是我们要操作的,其余的Header之类的不用管
          goal.trajectory = JointTrajectory()
          #goal.trajectory底下一共还有两个成员,分别是joint_names和points,先给joint_names赋值
          goal.trajectory.joint_names = JOINT_NAMES
 
          #从joint_state话题上获取当前的关节角度值,因为后续要移动关节时第一个值要为当前的角度值
          joint_states = rospy.wait_for_message("joint_states",JointState)
          joints_pos = joint_states.position
          print("here")
 
          #给trajectory中的第二个成员points赋值
          #points中有四个变量,positions,velocities,accelerations,effort,我们给前三个中的全部或者其中一两个赋值就行了
          #goal.trajectory.points=[0]*3
          goal.trajectory.points=[0]*(len(Positions)+1)
          goal.trajectory.points[0]=JointTrajectoryPoint(positions=joints_pos, velocities=[0]*6,time_from_start=rospy.Duration(0.0))
          for i in range(len(Positions)):
          	goal.trajectory.points[i+1]=JointTrajectoryPoint(positions=Positions[i], velocities=[0]*6,time_from_start=rospy.Duration(float((i+1)*3)))
          	#print(i)
          #goal.trajectory.points[1]=JointTrajectoryPoint(positions=[0,-1.58,0,-1.58,0,0], velocities=[0]*6,time_from_start=rospy.Duration(3.0))
          #goal.trajectory.points[2]=JointTrajectoryPoint(positions=[0,-0.785,-0.785,-1.58,0,0], velocities=[0]*6,time_from_start=rospy.Duration(6.0))
          #goal.trajectory.points[3]=JointTrajectoryPoint(positions=[1.5,-1.58,-1.57,0,0,0], velocities=[0]*6,time_from_start=rospy.Duration(3.0))
          
          #发布goal,注意这里的client还没有实例化,ros节点也没有初始化,我们在后面的程序中进行如上操作
          client.send_goal(goal)
          client.wait_for_result()
 
def pub_test():
          global client
 
          #初始化ros节点
          rospy.init_node("pub_action_test")
 
          #实例化一个action的类,命名为client,与上述client对应,话题为/pos_joint_traj_controller/follow_joint_trajectory,消息类型为FollowJointTrajectoryAction
          #gazebo仿真 pos_joint_traj_controller
          #client = actionlib.SimpleActionClient('/pos_joint_traj_controller/follow_joint_trajectory', FollowJointTrajectoryAction)
          #真实机械臂 scaled_pos_joint_traj_controller
          client = actionlib.SimpleActionClient('/scaled_pos_joint_traj_controller/follow_joint_trajectory', FollowJointTrajectoryAction)
          print("Waiting for server...")
          #等待server
          client.wait_for_server()
          print("Connect to server......")
          #执行move函数,发布action
          move()
 
if __name__ == "__main__":
    count = 0
    while not rospy.is_shutdown():
        count += 1
        pub_test()
        rospy.loginfo("发布次数:%d",count)

在cmakelists.txt中添加py文件

之后重新编译一下。

cd ~/catkin_RealSense_ws
catkin_make

记得给py文件权限

如果显示

 的话,参考:http://t.csdnimg.cn/PICNeicon-default.png?t=N7T8http://t.csdnimg.cn/PICNe

运行ur5启动launch:

roslaunch ur_robot_driver ur5_bringup.launch robot_ip:=192.168.0.101 limited:=true

示教器上启动external control

运行自己的节点:

rosrun my_bag demo01.py

之后可以看到它按照代码中的预设参数执行轨迹。

编写简单的moveit程序控制轨迹

参考:http://t.csdnimg.cn/S3h13

在my_bag/scripts中新建一个demo02.py和demo03.py,具体过程略,这种demo用的节点要用的时候直接run就行,不一定要通过ros启动。

demo02.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
import rospy, sys
import moveit_commander
import math

def degrees_to_radians(degrees):
    return degrees * math.pi / 180.0

def degrees_list_to_radians_list(degrees_list):
    return [degrees_to_radians(degrees) for degrees in degrees_list]

def plan_and_execute(arm_group, target_pose=None, joint_state=None, max_velocity_scaling_factor=0.2):
    """规划并执行目标位姿或关节状态的辅助函数。"""
    arm_group.set_max_velocity_scaling_factor(max_velocity_scaling_factor)
    
    if target_pose:
        arm_group.set_pose_target(target_pose)
        plan = arm_group.plan()
    elif joint_state:
        plan = arm_group.plan(joint_state)
    else:
        raise ValueError("Either target_pose or joint_state must be provided")

    success = arm_group.execute(plan[1], wait=True)
    arm_group.stop()
    arm_group.clear_pose_targets()
    while not success:
        if target_pose:
            arm_group.set_pose_target(target_pose)
            plan = arm_group.plan()
        elif joint_state:
            plan = arm_group.plan(joint_state)

        success = arm_group.execute(plan[1], wait=True)
        arm_group.stop()
        arm_group.clear_pose_targets()
    
    return success
 
class MoveItFkDemo:
    def __init__(self):
 
        # 初始化move_group的API,出现roscpp是因为底层是通过C++进行实现的
        moveit_commander.roscpp_initialize(sys.argv)
 
        # 初始化ROS节点,节点名为'moveit_fk_demo'
        rospy.init_node('moveit_fk_demo', anonymous=True)       
 
        # 初始化需要使用move group控制的机械臂中的arm group
        arm = moveit_commander.MoveGroupCommander('manipulator')
        
        # 设置机械臂运动的允许误差值,单位弧度
        arm.set_goal_joint_tolerance(0.01)
 
        # 设置允许的最大速度和加速度,范围0~1
        arm.set_max_acceleration_scaling_factor(0.1)
        arm.set_max_velocity_scaling_factor(0.1)
        
        # # 控制机械臂先回到初始化位置,home是setup assistant中设置的
        # arm.set_named_target('home')
        # arm.go()  #让机械臂先规划,再运动,阻塞指令,直到机械臂到达home后再向下执行
        # rospy.sleep(1)
         
        while True:
        
            # 设置机械臂的目标位置,使用六轴的位置数据进行描述(单位:弧度)
            # joint_positions = [0, 0, -0.376217, 0, 0, 0]
            joint_positions = degrees_list_to_radians_list([-21.5, -104.4, 113.84, -90, 0, 0])
            # arm.set_joint_value_target(joint_positions)  #设置关节值作为目标值
                    
            # 控制机械臂完成运动
            plan_and_execute(arm, joint_state=joint_positions)
            rospy.sleep(1)  # 等待1秒
 
             # 设置机械臂的目标位置,使用六轴的位置数据进行描述(单位:弧度)
            # joint_positions = [0, 0, -0.376217, 0, 0, 0]
            joint_positions = degrees_list_to_radians_list([165.0, -104.4, 113.84, -90, 0, 0])
            arm.set_joint_value_target(joint_positions)  #设置关节值作为目标值
                    
            # 控制机械臂完成运动
            plan_and_execute(arm, joint_state=joint_positions)
            rospy.sleep(1)  # 等待1秒

        # # 控制机械臂先回到初始化位置
        # arm.set_named_target('home')
        # arm.go()
        # rospy.sleep(1)
        
        # 关闭并退出moveit
        # moveit_commander.roscpp_shutdown()
        # moveit_commander.os._exit(0)
 
if __name__ == "__main__":
    try:
        MoveItFkDemo()
    except rospy.ROSInterruptException:
        pass

demo03.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
import rospy, sys
import moveit_commander
import math


def degrees_to_radians(degrees):
    return degrees * math.pi / 180.0

def degrees_list_to_radians_list(degrees_list):
    return [degrees_to_radians(degrees) for degrees in degrees_list]
 
class MoveItFkDemo:
    def __init__(self):
 
        # 初始化move_group的API,出现roscpp是因为底层是通过C++进行实现的
        moveit_commander.roscpp_initialize(sys.argv)
 
        # 初始化ROS节点,节点名为'moveit_fk_demo'
        rospy.init_node('moveit_fk_demo', anonymous=True)       
 
        # 初始化需要使用move group控制的机械臂中的arm group
        arm = moveit_commander.MoveGroupCommander('manipulator')
        
        # 设置机械臂运动的允许误差值,单位弧度
        arm.set_goal_joint_tolerance(0.01)
 
        # 设置允许的最大速度和加速度,范围0~1
        arm.set_max_acceleration_scaling_factor(0.1)
        arm.set_max_velocity_scaling_factor(0.1)
        
        # # 控制机械臂先回到初始化位置,home是setup assistant中设置的
        # arm.set_named_target('home')
        # arm.go()  #让机械臂先规划,再运动,阻塞指令,直到机械臂到达home后再向下执行
        # rospy.sleep(1)
         
        while True:
        
            # 设置机械臂的目标位置,使用六轴的位置数据进行描述(单位:弧度)
            # joint_positions = [0, 0, -0.376217, 0, 0, 0]
            joint_positions = degrees_list_to_radians_list([-21.5, -104.4, 113.84, -90, 0, 0])
            arm.set_joint_value_target(joint_positions)  #设置关节值作为目标值
                    
            # 控制机械臂完成运动
            success = arm.go()   # 规划+执行
            print(success)
            arm.stop()
            arm.clear_pose_targets()
            rospy.sleep(1)
 
             # 设置机械臂的目标位置,使用六轴的位置数据进行描述(单位:弧度)
            # joint_positions = [0, 0, -0.376217, 0, 0, 0]
            joint_positions = degrees_list_to_radians_list([165.0, -104.4, 113.84, -90, 0, 0])
            arm.set_joint_value_target(joint_positions)  #设置关节值作为目标值
                    
            # 控制机械臂完成运动
            arm.go()   # 规划+执行
            print(success)
            arm.stop()
            arm.clear_pose_targets()
            rospy.sleep(1)
            
        # # 控制机械臂先回到初始化位置
        # arm.set_named_target('home')
        # arm.go()
        # rospy.sleep(1)
        
        # 关闭并退出moveit
        # moveit_commander.roscpp_shutdown()
        # moveit_commander.os._exit(0)
 
if __name__ == "__main__":
    try:
        MoveItFkDemo()
    except rospy.ROSInterruptException:
        pass

Plan()+execuate()和go()的功能差不多,只是后面我们要添加传感器部分,execuate()我试下来遇到障碍物好像不会中间停下来,所以我之后还是用go()。

修改ompl默认规划算法(非必要)

在下面路径中修改默认规划算法,文件路径如图所示。

/home/lu/catkin_RealSense_ws/src/universal_robot/ur5_moveit_config/config/ompl_planning.yaml

<think>嗯,用户想了解Elasticsearch中的scaled_float数据类型的使用场景和示例。首先,我需要回忆一下scaled_float的定义和特点。根据引用[2],scaled_float是一种带有缩放因子的浮点类型,主要用于需要高精度存储但需要整数压缩的场景。比如存储价格汇率这样的数据,通常会使用小数点后多位,但实际存储时可以将其乘以缩放因子转换为长整型,节省空间。 接下来,我需要确定用户可能需要的具体信息。他们可能想知道如何正确声明这个类型的字段,包括必要的参数,比如scaling_factor。根据引用[2],scaling_factor是scaled_float特有的属性,其他类型不能用。所以在映射定义时,必须包含这个参数,并且类型要明确写成scaled_float。 然后,使用场景方面,除了提到的价格和汇率,可能还有其他需要高精度但希望优化存储的情况。例如,科学测量数据者金融数据中的小数处理。需要举几个例子,说明为什么在这些场景下使用scaled_float更好,比如节省存储空间,提高索引效率。 另外,用户可能还关心如何在实际操作中创建这样的映射。引用[3]中给出了创建索引和mapping的示例,可以借鉴这个结构,构造一个包含scaled_float字段的请求示例。需要注意的是,scaling_factor的设置要根据实际需求,比如价格可能用100,汇率用10000等。 可能还需要提到与其他数值类型的对比,比如普通的floatdouble,解释scaled_float的优势和限制。例如,scaled_float在存储时是作为长整型处理的,因此在范围上有一定的限制,但压缩效果更好。同时,查询时需要注意缩放因子的存在,应用层面可能需要转换回实际值。 用户还可能遇到动态映射的问题,引用[1]提到动态字段映射和动态模板,可能需要指导用户如何正确配置动态模板来识别scaled_float类型,避免自动映射成其他类型。此外,引用[2]强调scaling_factor只适用于scaled_float,必须注意不要在其他类型上误用。 最后,应该总结使用时的注意事项,比如缩放因子的选择,数据转换的方法,以及查询时的处理。确保用户了解如何正确插入数据,例如在索引文档时是否需要预先乘以缩放因子,者在查询时如何转换回实际值。 可能还需要提供完整的示例,从创建映射到插入数据,再到查询,展示整个流程。比如,创建一个产品价格的索引,定义price字段为scaled_float,scaling_factor为100。然后插入文档时,将实际价格乘以100作为整数值存储。查询时,Elasticsearch返回的是缩放后的值,应用层需要再转换回来。 此外,需要提醒用户关于数据迁移更新映射时的注意事项,比如已有的字段类型不能直接修改,可能需要重建索引。引用[1]中的更新映射API可能在这里派上用场,但具体是否支持scaled_float的修改需要进一步确认。 总结来说,回答需要涵盖定义、使用场景、映射配置示例、数据操作示例以及注意事项,同时引用提供的参考资料来支持各个要点。</think>### Elasticsearch scaled_float 数据类型详解 #### 一、核心定义与特性 `scaled_float` 是 Elasticsearch 中一种特殊的浮点类型,通过**缩放因子**(`scaling_factor`)将浮点数转换为长整型存储,从而优化存储空间和查询性能[^2]。其公式为: $$实际值 = 存储值 / scaling\_factor$$ #### 二、适用场景 1. **高精度金融数据** 如价格($12.99 → 存储为 `1299`,缩放因子 100)、汇率($1.12345 → 缩放因子 100000$)。 2. **节省存储空间** 相比普通 `float` `double`,使用长整型压缩可减少磁盘占用。 3. **范围可控的浮点运算** 缩放因子需根据业务精度预设,避免浮点运算误差。 #### 三、映射定义示例 ```json PUT /financial_data { "mappings": { "properties": { "product_price": { "type": "scaled_float", // 必须明确指定类型 "scaling_factor": 100 // 缩放因子为100,不可省略 }, "exchange_rate": { "type": "scaled_float", "scaling_factor": 10000 } } } } ``` #### 四、数据操作示例 1. **插入文档**(需手动缩放值) ```json POST /financial_data/_doc/1 { "product_price": 1299, // 实际值12.99 = 1299/100 "exchange_rate": 112345 // 实际值1.12345 = 112345/10000 } ``` 2. **查询结果** Elasticsearch 返回存储的整数值,应用层需自行还原为实际值。 #### 五、注意事项 1. **缩放因子限制** 若 `scaling_factor=100`,最大安全存储值为 $9,223,372,036,854,775,807 / 100$,需避免溢出。 2. **字段更新限制** 已存在的字段类型无法直接修改,需通过重建索引别名切换实现[^1]。 3. **聚合与排序** 缩放后的值以长整型参与计算,聚合结果需在应用层转换回实际值。 #### 六、与其他类型的对比 | 类型 | 存储方式 | 精度控制 | 适用场景 | |--------------|-------------|----------|------------------------| | `float` | 32位浮点 | 低 | 通用小数存储 | | `scaled_float`| 长整型压缩 | 高 | 金融、科学测量等高精度 | | `integer` | 整型 | 固定 | 无小数场景 |
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值