(4-3-01) 轨迹规划算法和优化:工业机器人的运动控制和轨迹规划系统(1)

工业机器人是专门设计和制造用于执行各种工业任务的机器人系统,这些机器人通常被用于自动化制造过程,以提高生产效率、降低成本,并执行危险或重复性高的任务。随着技术的不断进步,工业机器人的能力和应用范围还将继续扩大。在本节的内容中,将介绍基于ROS实现一个工业机器人运动控制和轨迹规划系统。

实例4-1:基于ROS的工业机器人的运动控制和轨迹规划系统(源码路径:codes\4\gui\ ROS_Motion_Control

4.9.1  系统介绍

本项目基于ROS实现了一个工业机器人运动控制和轨迹规划系统,通过使用ROS、Gazebo和RViz等开发工具,借助Python程序对ABB、Universal Robots和Fanuc等多个工业机器人进行运动规划。本项目分别实现了机械设计(使用SolidWorks和Autodesk Inventor)、ROS中的机器人轨迹路径规划(使用Python)、RViz中的机器人轨迹可视化功能。通过提供简单的演示,展示了对多个工业机器人的运动控制、关节和笛卡尔运动、ROS参数、话题、服务等基本概念的应用。

4.9.2  配置文件

文件config/robot.yaml用于初始化项目中的一些关键参数。首先,它包含了用于在RVIZ仿真工具中初始化对象位置的参数,包括对象的初始坐标和是否可见。其次,它定义了不同机器人臂的初始家庭参数,其中包括UR5、ABB IRB 1200和FANUC CR7IA机器人臂的关节初始角度。这些参数在项目启动时用于设置机器人和环境的初始状态。

# 初始化对象的参数(RVIZ中)
object_pos: [0.0, 0.0, 0.0]  # 对象的初始坐标
object_visible: False  # 对象是否可见

# 初始化机器人臂的参数
# UR5: [1.57, -1.57, 1.57, -1.57, -1.57, 0.0]
# ABB IRB 1200: [0.0, 0.0, 0.0, 0.0, 1.57, 0.0]
# FANUC CR7IA [0.0, 0.0, 0.0, 0.0, -1.57, 0.0]
robot_home_param: [0.0, 0.0, 0.0, 0.0, -1.57, 0.0]  # 机器人臂的关节初始角度

4.9.3  数据采集

在“data_collection”目录中包含了两个程序文件,分别是 read_joint_pose.py 和 read_tcp_pose.py。这两个文件共同构成了数据采集(data_collection)模块,负责实时获取机器人的关节姿态和工具坐标系姿态,并通过ROS话题发布,以便其他模块或用户实时监测机器人状态。

(1)文件src/data_collection/read_joint_pose.py是一个ROS节点,通过库MoveIt与机器人的关节进行交互,实时读取当前关节姿态,并使用ROS发布者发布到话题 'current_joint_pose'。脚本通过异常处理确保稳定运行,发布频率为1 Hz。这适用于需要实时监测机器人关节状态的场景。

# 系统(默认库)
import sys
# ROS的Python客户端库
import rospy
# MoveIt库提供的功能包装器
import moveit_commander
# 数据类型(消息、服务)
from rospy.numpy_msg import numpy_msg
from rospy_tutorials.msg import Floats

# Numpy(数组计算库)
import numpy as np

def main():
    # 节点初始化
    rospy.init_node('read_joint_init', anonymous=True)

    # 创建MoveGroupCommander对象
    group = moveit_commander.MoveGroupCommander('manipulator')
    # 创建ROS发布者
    publisher = rospy.Publisher('current_joint_pose', numpy_msg(Floats), queue_size=5)

    try:
        while not rospy.is_shutdown():
            # 获取当前关节值
            c_jP = group.get_current_joint_values()
            # 转换为NumPy数组
            fConv_c_jP = np.array([c_jP[0], c_jP[1], c_jP[2], c_jP[3], c_jP[4], c_jP[5]], dtype=np.float32)
            # 发布到ROS话题
            publisher.publish(fConv_c_jP)

            # rospy频率休眠 -> 1 Hz
            rospy.Rate(1).sleep()
    except:
        print('意外错误:', sys.exc_info()[0])
    finally:
        print('再见.')

if __name__ == '__main__':
    sys.exit(main())

对上述代码的具体说明如下所示:

  1. 首先进行了ROS节点的初始化,并创建了MoveIt库的MoveGroupCommander对象,用于与机器人的关节进行交互。接着,它创建了一个ROS发布者,负责发布当前机器人关节姿态到名为'current_joint_pose'的ROS话题。
  2. 在主循环中,通过group.get_current_joint_values()获取当前机器人的关节值,并将其转换为NumPy数组。然后,使用ROS发布者将这个数组发布到指定话题。最后,通过rospy.Rate(1).sleep()控制发布频率为1 Hz。
  3. 最后通过异常处理功能捕获任何异常并打印错误信息,在代码的最后,无论是否发生异常,都会打印“Bye.”。

总体而言,该脚本用于实时读取机器人关节姿态并通过ROS话题发布,适用于需要实时监测机器人关节状态的应用场景。

(2)文件src/data_collection/read_tcp_pose.py是一个ROS节点,用于读取机器人当前的工具坐标系(TCP - Tool Center Point)姿态,并将其发布到ROS话题 'current_tcp_pose'。

# 系统(默认库)
import sys
# ROS的Python客户端库
import rospy
# MoveIt库提供的功能包装器
import moveit_commander

# 数据类型(消息、服务)
import geometry_msgs.msg

def main():
    # 节点初始化
    rospy.init_node('read_tcp_init', anonymous=True)

    # 创建MoveGroupCommander对象
    group = moveit_commander.MoveGroupCommander('manipulator')
    # 创建ROS发布者
    publisher = rospy.Publisher('current_tcp_pose', geometry_msgs.msg.PoseStamped, queue_size=5)

    try:
        while not rospy.is_shutdown():
            # 获取当前工具坐标系(TCP)的姿态
            c_tcpP = group.get_current_pose(group.get_end_effector_link())
            # 发布到ROS话题
            publisher.publish(c_tcpP)

            # rospy频率休眠 -> 1 Hz
            rospy.Rate(1).sleep()
    except:
        print('意外错误:', sys.exc_info()[0])
    finally:
        print('再见.')

if __name__ == '__main__':
    sys.exit(main())

4.9.4  ROS 服务

在“service”目录中包含两个 Python程序,分别是 reset_robot.py 和 set_object.py。这两个文件提供了 ROS 服务,用于重置机器人的关节位置,并在 MoveIt 规划场景中动态设置或移除一个球体对象。

(1)文件src/service/reset_robot.py定义了一个 ROS 服务,用于重置机器人的位置(关节空间)。通过调用该服务可以将机器人的关节空间重置到预定义的初始位置,用于调试和初始化机器人状态。

# 系统(默认库)
import sys
# ROS的Python客户端库
import rospy
# MoveIt库提供的功能包装器
import moveit_commander
# 数据类型(消息、服务)
from std_srvs.srv import Trigger
# Numpy(数组计算库)
import numpy as np

class reset_robot_handler():
    """
    描述:
        该类定义了一个用于重置机器人位置(关节空间)的ROS服务。
    """

    def __init__(self):
        # 节点初始化
        rospy.init_node('reset_init')   

        self.robotics_arm_name = 'manipulator'
        self.robot = moveit_commander.RobotCommander() 
        self.group = None

        # 等待MoveGroupCommander对象初始化
        while self.group == None:
            try:
                self.group = moveit_commander.MoveGroupCommander(self.robotics_arm_name)
            except Exception:
                rospy.sleep(1)

        # 触发器 -> 重置机器人位置(关节)
        self.set_trigger = rospy.Service('reset_robot', Trigger, self.reset_robot_pose)    

    def reset_robot_pose(self, request):
        # 从robot.yaml文件中获取机器人的初始关节角度参数
        joint_target = rospy.get_param('/robot_home_param')

        # 设置规划参数
        self.group.set_max_velocity_scaling_factor(0.25)
        self.group.set_max_acceleration_scaling_factor(0.25)

        # 设置机器人参数(关节控制)
        self.group.set_joint_value_target(joint_target)

        # 获取机器人关节空间的轨迹规划
        plan = self.group.plan(joint_target)

        # 执行轨迹
        self.group.execute(plan, wait=True)
        rospy.sleep(0.5)

        # 重置
        self.group.stop()
        self.group.clear_path_constraints()
        self.group.clear_pose_targets()

        return [True, '机器人位置已成功重置。']

def main():
    rospy.wait_for_service('/move_group/get_loggers')
    reset_robot_handler()
    rospy.spin()

if __name__ == '__main__':
    sys.exit(main())

上述代码的实现流程如下所示:

  1. 首先初始化 ROS 节点,并在初始化时尝试创建 MoveGroupCommander 对象,与机器人的指定运动组进行交互。然后,定义了一个名为 reset_robot 的 ROS 服务,用于重置机器人的关节姿态。
  2. 在 reset_robot_pose 方法中,通过读取参数文件中的机器人初始关节角度,设置运动规划的速度和加速度参数,然后规划并执行关节空间中的目标姿态。最后,清除路径约束和姿态目标。
  3. 通过 main 函数等待 MoveIt 的相关服务初始化,然后创建 reset_robot_handler 对象,开始监听 ROS 服务请求。

(2)文件src/service/set_object.py是一个 ROS 节点,用于在 MoveIt 环境中设置或移除一个球体对象,通过检测 ROS 参数 /object_visible 来控制对象的显示和移除功能。

import sys
# ROS的Python客户端库
import rospy
# MoveIt库提供的功能包装器
import moveit_commander
# 数据类型(消息、服务)
import geometry_msgs

def main():
    # 节点初始化
    rospy.init_node('set_object_init', anonymous=True)

    # 创建MoveGroupCommander和PlanningSceneInterface对象
    group = moveit_commander.MoveGroupCommander('manipulator')
    scene = moveit_commander.PlanningSceneInterface()
    robot = moveit_commander.RobotCommander()

    try:
        while not rospy.is_shutdown():
            # 获取ROS参数 '/object_visible'
            visibility = rospy.get_param('/object_visible')

            if visibility == True:
                # 获取主脚本中的参数(见 test.py)
                position = rospy.get_param('/object_pos')

                # 设置对象的参数(RVIZ)
                obj = geometry_msgs.msg.PoseStamped()
                obj.header.frame_id = robot.get_planning_frame()
                obj.pose.position.x = position[0]
                obj.pose.position.y = position[1]
                obj.pose.position.z = position[2] - 0.3

                # 在环境中显示对象
                scene.add_sphere('obj_1', obj, 0.05)
            else:
                # 移除环境中的所有对象
                scene.remove_world_object()

            # rospy频率休眠 -> 10 Hz
            rospy.Rate(10).sleep()
    except:
        print('Unexpected error:', sys.exc_info()[0])
    finally:
        print('Bye.')

if __name__ == '__main__':
    sys.exit(main())

上述代码用于在 MoveIt 环境中动态设置或移除一个球体对象,通过 ROS 参数控制对象的可见性,适用于需要在机器人规划场景中添加或移除物体的应用场景。上述代码的实现流程如下所示。

  1. 首先初始化 ROS 节点,并创建 MoveGroupCommander 和 PlanningSceneInterface 对象,分别用于与机器人的运动组进行交互和管理场景规划。
  2. 在主循环中,通过读取 ROS 参数 /object_visible 判断是否显示对象。如果 visibility 为 True,则获取参数 /object_pos 来确定对象的位置,并创建一个球体对象。这个球体对象通过 PlanningSceneInterface 加入到 MoveIt 的规划场景中。如果 visibility 为 False,则移除场景中的所有物体。
  3. 最后,通过 rospy.Rate(10).sleep() 控制主循环的执行频率为 10 Hz。

未完待续

  • 32
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
基于瞬态优化机器人路径规划算法是一种基于最优控制理论的算法,用于解决机器人路径规划问题。该算法通过优化控制输入来寻找机器人的最优路径。 以下是该算法的基本思路: 1. 问题建模:将机器人路径规划问题转化为一个优化问题。定义目标函数和约束条件,目标函数可以是路径长度、时间消耗、能量消耗等。约束条件可以包括避免障碍物、满足运动学限制等。 2. 状态空间建模:将机器人的状态表示为一组状态变量,如位置、速度、加速度等。根据问题的具体要求,确定状态空间的维度和表示方式。 3. 动力学模型建立:根据机器人的运动特性和动力学方程,建立机器人的动力学模型。这个模型描述了机器人在给定控制输入下的运动轨迹。 4. 瞬态优化过程:通过优化控制输入来寻找最优路径。具体步骤如下: - 初始化控制输入:随机生成一组初始控制输入作为种群。 - 状态演化:根据动力学模型,模拟机器人在当前控制输入下的状态演化。 - 目标函数评估:根据目标函数,计算机器人在当前控制输入下的目标函数值。 - 优化控制输入:根据优化算法(如遗传算法、粒子群优化等),对控制输入进行优化,以改善目标函数值。 - 终止条件判断:根据预设的终止条件(如达到最大迭代次数、目标函数收敛等),判断是否终止优化过程。 5. 输出最优路径:在优化过程结束后,输出具有最优目标函数值的控制输入作为最优路径。 需要注意的是,基于瞬态优化机器人路径规划算法是一种启发式算法,通过优化控制输入来寻找最优路径。算法的性能和效果受到多个因素的影响,包括问题建模的准确性、动力学模型的精度、优化算法的选择和参数设置等。因此,在实际应用中需要根据具体问题进行调整和优化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农三叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值