我们打算在robopal项目(提供仿真建模与渲染)中使用DP模型进行push-T任务

一.仿真环境搭建

1.分析仿真功能

物体:一个机械臂,桌子,小物件

物体间:机械臂和物件放在桌子上;机械臂能够夹取物件并带动物件移动;更进一步机械臂能实现物件指定位置的搬运

2.实现仿真—初步

2.1分析已有

通过对robopal下前五个任务的分析:

demo_controllers.py能召唤孤零零一个机械臂实现机械臂运动到指定位置

demo_enviroments能召唤机械臂,物件和桌子,实现机械臂采样运动

      其中第7个环境召唤出了锤子,锤子能被碰撞

demo_grasping能召唤机械臂,物件和桌子,实现物件的自主抓取

demo__motion_planning召唤能力不足,实现机械臂路径规划

....这几个足够了

2.2个性化修改

选择一个作为基础,demo_enviroments的第七个环境就很好,让我们修改一些代码,让它变成生成一个机械臂,锤子和桌子的代码

但是demo_enviroments不仅要选择环境,第七个还是两个机械臂

相较于demo_grasping要改的太多,还是以demo_grasping为基础

2.2.1锁定机械臂种类

demo_grasping要遍历三种机械臂,先让我们把机械臂种类锁定为panda

原文件改为:

import numpy as np
from robopal.envs import RobotEnv
from robopal.robots.panda import PandaGrasp

if __name__ == "__main__":
    # 直接使用 PandaGrasp 机器人
    env = RobotEnv(
        PandaGrasp,  # 指定 PandaGrasp 机器人
        render_mode='human',
        control_freq=100,
        controller='CARTIK',
    )
    env.reset()
    env.controller.reference = 'world'

    # 打开机械臂末端执行器
    env.robot.end['agent0'].open()

    # 获取目标物体的位置
    action = env.get_body_pos('green_block')

    # 移动到目标位置
    for t in range(int(200)):
        env.step(action)

    # 关闭机械臂末端执行器以抓取物体
    for t in range(int(250)):
        env.robot.end['agent0'].close()
        env.step(action)

    # 将物体提升到一定高度
    action += np.array([0.0, 0.0, 0.29])
    for t in range(int(200)):
        env.step(action)

    # 关闭渲染窗口
    env.renderer.close_render_window()

    # 关闭环境
    env.close()

2.2.2取消自动关闭

取消窗口会自动关闭的功能并且添加交互界面

代码:

import numpy as np
from robopal.envs import RobotEnv
from robopal.robots.panda import PandaGrasp

if __name__ == "__main__":
    # 直接使用 PandaGrasp 机器人
    env = RobotEnv(
        PandaGrasp,  # 指定 PandaGrasp 机器人
        render_mode='human',
        control_freq=100,
        controller='CARTIK',
    )
    env.reset()
    env.controller.reference = 'world'

    # 打开机械臂末端执行器
    env.robot.end['agent0'].open()

    # 获取目标物体的位置
    action = env.get_body_pos('green_block')

    # 移动到目标位置
    for t in range(int(200)):
        env.step(action)

    # 关闭机械臂末端执行器以抓取物体
    for t in range(int(250)):
        env.robot.end['agent0'].close()
        env.step(action)

    # 将物体提升到一定高度
    action += np.array([0.0, 0.0, 0.29])
    for t in range(int(200)):
        env.step(action)

    # 交互循环
    print("任务完成!输入 'q' 并按 Enter 键退出...")
    while True:
        user_input = input("输入动作(例如 'up', 'down', 'left', 'right')或 'q' 退出:")
        if user_input == 'q':
            break
        elif user_input == 'up':
            action += np.array([0.0, 0.0, 0.05])
        elif user_input == 'down':
            action += np.array([0.0, 0.0, -0.05])
        elif user_input == 'left':
            action += np.array([0.0, -0.05, 0.0])
        elif user_input == 'right':
            action += np.array([0.0, 0.05, 0.0])
        for t in range(int(50)):
            env.step(action)

    # 关闭环境
    env.close()

2.2.3修改物件

原本想让机械臂去抓锤子的,但是我不会改,只好退而求其次之修改目前抓取东西的尺寸(正方体)了,打开目录如图:

修改内容如下:

<mujoco>
    <worldbody>
        <body name="green_block" pos="0.5 0.0 0.46">
            <joint name="green_block:joint" type="free" damping="0.1" frictionloss="0"/>
            <geom name="green_block" size="0.04 0.02 0.02" rgba="0 1 0 1" type="box" conaffinity="0" contype="0" group="1"/>
            <geom size="0.04 0.02 0.02" type="box" conaffinity="1" contype="1" condim="4" group="4" mass="0.01" friction="5 5 5" solimp="1 1 1" solref="0.00001 1"/>
            <site name="green_block" pos="0 0 0" size="0.02 0.02 0.02" rgba="0 1 0 0.5" type="sphere" />
        </body>
    </worldbody>
</mujoco>

3.实现仿真--进阶

机械臂能实现物件指定位置的搬运

import numpy as np
from robopal.envs import RobotEnv
from robopal.robots.panda import PandaGrasp

if __name__ == "__main__":
    # 初始化仿真环境
    env = RobotEnv(
        PandaGrasp,  # 指定 PandaGrasp 机器人
        render_mode='human',
        control_freq=100,
        controller='CARTIK',
    )
    env.reset()
    env.controller.reference = 'world'

    # 用户输入目标位置
    print("请输入目标位置的坐标(例如:0.5 0.2 0.46):")
    while True:
        try:
            user_input = input("x y z: ").split()  # 获取用户输入
            target_pos = np.array([float(user_input[0]), float(user_input[1]), float(user_input[2])])  # 转换为 numpy 数组
            break
        except (ValueError, IndexError):
            print("输入无效,请重新输入!")

    # 打开夹爪
    env.robot.end['agent0'].open()


    action = env.get_body_pos('green_block')  # 获取物体位置
    for t in range(int(200)):       # 移动到目标位置
        env.step(action)

    #关闭机械臂末端执行器以抓取物体
    for t in range(int(250)):
        env.robot.end['agent0'].close()
        env.step(action)

    # 抬起物体
    action[2] += 0.2  # 抬起物体 20 cm
    for t in range(int(200)):
        env.step(action)

    # 移动到目标位置上方
    action[:2] = target_pos[:2]  # 移动到目标位置上方
    for t in range(int(200)):
        env.step(action)

    # 放置物体
    action[2] = target_pos[2]  # 放置物体
    for t in range(int(200)):
        env.robot.end['agent0'].open()
        env.step(action)

    # 返回初始位置
    action = np.array([0.0, 0.0, 0.56])  # 初始位置
    for t in range(int(200)):
        env.step(action)

    # 交互循环
    print("任务完成!输入 'q' 并按 Enter 键退出...")
    while True:
        user_input = input("输入动作(例如 'up', 'down', 'left', 'right')或 'q' 退出:")
        if user_input == 'q':
            break
        elif user_input == 'up':
            action += np.array([0.0, 0.0, 0.05])
        elif user_input == 'down':
            action += np.array([0.0, 0.0, -0.05])
        elif user_input == 'left':
            action += np.array([0.0, -0.05, 0.0])
        elif user_input == 'right':
            action += np.array([0.0, 0.05, 0.0])
        for t in range(int(50)):
            env.step(action)

    # 关闭环境
    env.close()

进行后有两次输入:

第一次是输入目标坐标:

超出范围会让重新输入

格式是数字空格数字空格数字;举例:0.5 0.25 0.46

  • 对于 PandaGrasp 机器人,默认的工作空间范围大致为:
    • x-0.5 到 0.5 米
    • y-0.5 到 0.5 米
    • z0.0 到 1.0 米

第二次是输入

完成任务后的后续操作

4.仿真补充(ing)

这节可选,因为后续为了DP模型的实现还会对仿真robopal作出许多修改,其中有很多重复或者冲突的内容;但是为了好玩和更详细得了解可以弄弄。

4.1

为了后续的训练方便,还可以让机械臂在进行第一次放置后重新开始放置或者直接重新加载环境自动重开(参考原demo_grasp),起码不是回到一个奇怪的位置(已实现)并且修改为用键盘操控机械臂移动

改后为:

 

import numpy as np
from robopal.envs import RobotEnv
from robopal.robots.panda import PandaGrasp

if __name__ == "__main__":
    while True:
        # 初始化仿真环境
        env = RobotEnv(
            PandaGrasp,  # 指定 PandaGrasp 机器人
            render_mode='human',
            control_freq=100,
            controller='CARTIK',
        )
        env.reset()
        env.controller.reference = 'world'

        # 用户输入目标位置
        print("请输入目标位置的坐标(例如:0.5 0.2 0.46):")
        while True:
            try:
                user_input = input("x y z: ").split()  # 获取用户输入
                target_pos = np.array([float(user_input[0]), float(user_input[1]), float(user_input[2])])  # 转换为 numpy 数组
                break
            except (ValueError, IndexError):
                print("输入无效,请重新输入!")

        # 打开夹爪
        env.robot.end['agent0'].open()

        # 移动到物体上方
        action = env.get_body_pos('green_block')  # 获取物体位置
        for t in range(int(200)):  # 移动到目标位置
            env.step(action)

        # 关闭机械臂末端执行器以抓取物体
        for t in range(int(250)):
            env.robot.end['agent0'].close()
            env.step(action)

        # 抬起物体
        action[2] += 0.2  # 抬起物体 20 cm
        for t in range(int(200)):
            env.step(action)

        # 移动到目标位置上方
        action[:2] = target_pos[:2]  # 移动到目标位置上方
        for t in range(int(200)):
            env.step(action)

        # 放置物体
        action[2] = target_pos[2]  # 放置物体
        for t in range(int(200)):
            env.robot.end['agent0'].open()
            env.step(action)

        # 抬起物体 20 cm
        action[2] += 0.2
        for t in range(int(200)):
            env.step(action)
        # 交互循环:键盘自由控制
        print("任务完成!输入 'q' 并按 Enter 键退出...")
        print("使用以下键控制机械臂:")
        print("  w: 向前移动")
        print("  s: 向后移动")
        print("  a: 向左移动")
        print("  d: 向右移动")
        print("  r: 向上移动")
        print("  f: 向下移动")
        print("  o: 打开夹爪")
        print("  c: 关闭夹爪")
        print("  q: 退出")

        # 获取机械臂的初始位置
        action = env.robot.get_end_xpos()
        while True:
            user_input = input("输入控制命令:").lower()
            if user_input == 'q':
                break
            elif user_input == 'w':
                action[0] += 0.02  # 向前移动
                for t in range(int(30)):
                    env.step(action)
            elif user_input == 's':
                action[0] -= 0.02  # 向后移动
                for t in range(int(30)):
                    env.step(action)
            elif user_input == 'a':
                action[1] += 0.02  # 向左移动
                for t in range(int(30)):
                    env.step(action)
            elif user_input == 'd':
                action[1] -= 0.02  # 向右移动
                for t in range(int(30)):
                    env.step(action)
            elif user_input == 'r':
                action[2] += 0.02  # 向上移动
                for t in range(int(30)):
                    env.step(action)
            elif user_input == 'f':
                action[2] -= 0.02  # 向下移动
                for t in range(int(30)):
                    env.step(action)
            elif user_input == 'o':
                env.robot.end['agent0'].open()  # 打开夹爪
            elif user_input == 'c':
                env.robot.end['agent0'].close()  # 关闭夹爪
            else:
                print("无效输入,请重新输入!")

            
           

        # 关闭渲染窗口
        env.renderer.close_render_window()

    # 关闭环境
    env.close()

4.2

我们训练的是中间的路径,你在进行放置任务的时候也观察到了,机械臂起始的加速度都很大,但是目前可控的只有起始位置;或许可以参考demo__motion_planning来获取灵感?

 

二.DP实现

1.分析DP功能

在夹爪提起物体后,我们知道物体此时此刻的坐标,我们也根据自己的输入知道物体目的坐标,我们要用DP模型在两点生成轨迹?

2.实现流程

我在b站一个视频的简介里发现了这样一段话:

初次尝试 diffusion policy,使用自己搭建的环境,并编写相应的遥操作和数据收集/回放脚本,这些脚本全部在 github 开源,搜索 robopal 即可。可以方便根据 robopal 搭建自己的环境并进行模仿学习,强化学习或多智能体强化学习的训练。

把这句话给AI作为引子来开始尝试DP实现

 

 

 

 

 

 

 

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐