PyBullet (四) 将圆柱体看作机器人,推动目标,让目标按照输入的路径在可移动障碍物中移动

申明:本人今年博一(地点英国),项目是与机器人有关的内容。第三次导师见面,导师布置的另一个mini-experiment,用到“PyBullet”。

系列文章目录:
上一篇:
PyBullet (三) 将圆柱体看作机器人的加速和减速运动
下一篇:
PyBullet (五)(循环+优化)将圆柱体看作机器人,推动目标,让目标按照输入的路径在可移动障碍物中移动

虚拟机:VMware Workstation 16.x Pro
系统:Ubuntu20.04.1(官方下载链接
PyBullet:(官方链接)(官方指南

1. 整体思路

将圆柱体看作是机器人来进行移动,给定机器人一个速度,通过不断调整机器人的速度推动目标,让目标按照指定路径移动。下面介绍的方法算是一种比较“蠢”的方法,只当作是为熟练使用PyBullet的一个铺垫。思路略显臃肿,并且有局限性,但是容易理解,在这里只提供一个思路,不建议使用。

1.1 分情况讨论

本方法将机器人,目标以及路径的位置关系分成4种情况讨论:

  1. 锐角/直角 + 锐角
  2. 钝角 + 锐角
  3. 锐角 + 直角
  4. 锐角 + 钝角

当然前提是我们已知机器人,目标和路径的在环境中的坐标位置。并且机器人和目标都是圆柱体。

1.1.1 锐角/直角 + 锐角

先上图片:
1.1
锐角/直角+锐角:向量RT * 向量RP >= 0
锐角:向量PT * 向量PR > 0

1.1.1.1 计算垂足

过T点向直线RP做垂线,设垂足为O:
1.2

1.1.1.2 计算距离

接下来要计算线段RO的距离(DistanceRO),机器人R的半径(RadiusR)以及目标的半径(RadiusT)。然后我会比较他们之间的大小。
if DistanceRO <= RadiusR + RadiusT, 机器人会沿向量PR的方向移动,如图所示:
1.3
当然我会有函数用来实时检测距离,防止机器人太过于远离目标T和路径P。

if DistanceRO >> RadiusR + RadiusT(我的意思是远远大于),那么机器人会沿向量RP的方向移动,如图所示:
1.4
当然我会有函数用来实时检测距离,防止机器人太过于接近目标T和路径P。
所以最后机器人会停在一个区间内。

1.1.1.3 向“上”移动

过点R做直线RP的垂线,然后该垂线与线段TP的延长线交与一点C:
1.5
然后机器人R会朝向点C移动,当然在移动的过程中,每时每刻都在重复运行1.1.1.1、1.1.1.2以及1.1.1.3的步骤,到最后会出现下面这种情况:
1.6

1.1.1.4 “推”

然后机器人会朝向点P运动,也就是推动目标T。在推动的过程中,必定会推歪,所以我让机器人先朝向点P运动几秒钟,然后重新执行1.1.1.1、1.1.1.2以及1.1.1.3这三个步骤,然后再执行1.1.1.4。这样就实现了实时矫正目标T的位置。

1.1.2 钝角 + 锐角

先上图片:
1.7
钝角:向量RT * 向量RP < 0
锐角:向量PT * 向量PR > 0

1.1.2.1 计算垂足

同样的操作,过T点向直线RP做垂线,设垂足为O:
1.8

1.1.2.2 计算方向

有了垂足O就能知道向量TO的方向,然后让机器人R按照向量TO的方向从O点移动,直到向量RT * 向量RP > 0:
1.9
机器人移动之后我们会发现位置的关系变成了第一种,然后剩下的步骤就可以按照第一种(1.1.1.1、1.1.1.2、1.1.1.3和1.1.1.4)情况来执行。

1.1.3 锐角 + 直角

先上图片:
1.10
锐角:向量RT * 向量RP > 0
直角:向量PT * 向量PR = 0

1.1.3.1 “1.1.1.1”

先按照1.1.1.1的步骤执行:
1.11

1.1.3.2 向“上”移动

我们直到向量PT的方向,我们让机器人R从R点出发,向向量PT的方向移动:
1.12
机器人移动之后我们会发现位置的关系变成了第一种,然后剩下的步骤就可以按照第一种(1.1.1.1、1.1.1.2、1.1.1.3和1.1.1.4)情况来执行。

1.1.4 锐角 + 钝角

先上图片:
1.13
锐角:向量RT * 向量RP > 0
钝角:向量PT * 向量PR < 0

1.1.4.1 移动

我们让机器人R从R点出发按照向量RP的方向移动,直到向量PT * 向量PR > 0:
1.14
然后我会重新计算向量RT * 向量RP和向量 PT* 向量PR 的值然后根据他们的值来进行1,2,3情况的分类。

1.2 方法总结

方法的最后会让目标按照路径Path移动。略显臃肿的方法,但是对于初学者来说更容易上手,更容易理解。方法有局限性,机器人和目标都是在圆柱体的情况下,所以只适用与部分环境。当然后续会更新稍微好一点的算法。当然算法没有最好,只有更好。

2. 代码解析

2.1 代码分布

2.1.1 库

import pybullet as p
import time
import pybullet_data
import numpy as np
import datetime
import math

最基础的导入包啊,库啊

2.1.2 连接物理模拟

physicsClient = p.connect(p.GUI)#or p.DIRECT for non-graphical version
p.setAdditionalSearchPath(pybullet_data.getDataPath()) #optionally

导入PyBullet模块后,首先要做的是 "连接 "物理模拟。PyBullet是围绕客户端-服务器驱动的API设计的,客户端发送命令,物理服务器返回状态。PyBullet有一些内置的物理服务器。DIRECT和GUI。GUI和DIRECT连接都会在与PyBullet相同的过程中执行物理模拟和渲染。

2.1.3 重力设置

p.setGravity(0,0,-9.81)

设置重力系数分别是:x方向(+:x轴正半轴;-:x轴负半轴);y方向(+:y轴正半轴;-:y轴负半轴);z方向(+:z轴正半轴;-:z轴负半轴)。

2.1.4 设置基础参数

cylinder_Obstacle_1_StartPos = [-0.4, 0.3, 0.2 ]#圆柱体障碍物的初始位置
cylinder_Obstacle_2_StartPos = [ 0.0,-0.6, 0.15]
cylinder_Obstacle_3_StartPos = [ 0.6,-0.6, 0.1 ]
cylinder_Obstacle_4_StartPos = [ 0.8, 0.2, 0.1]
cylinder_target_StartPos = [ 0, 0.0, 0.3]
cylinder_robot_StartPos = [ -0.8, 0.0, 0.3]

cylinder_Obstacle_1_StartOrientation = p.getQuaternionFromEuler([0,0,0])#(圆柱体障碍物)这里的参数会转换成一个四元数,可以理解成能够控制模型在空间中绕x,y,z轴旋转的参数。(参数是角度。e.g. [3.14,0,0] == [pai,0,0];[1.57,0,0] == [pai/2,0,0]。参数的正负表示旋转的不同方向。)
cylinder_Obstacle_2_StartOrientation = p.getQuaternionFromEuler([0,0,0])
cylinder_Obstacle_3_StartOrientation = p.getQuaternionFromEuler([0,0,0])
cylinder_Obstacle_4_StartOrientation = p.getQuaternionFromEuler([0,0,0])
cylinder_target_StartOrientation = p.getQuaternionFromEuler([0,0,0])
cylinder_robot_StartOrientation = p.getQuaternionFromEuler([0,0,0])

2.1.5 模型加载

cylinder_Obstacle_1_Id = p.loadURDF("D:/Study/PhD/2020.10.15-2020.10.21/object/cylinder_obstacle1.urdf",cylinder_Obstacle_1_StartPos,cylinder_Obstacle_1_StartOrientation)
cylinder_Obstacle_2_Id = p.loadURDF("D:/Study/PhD/2020.10.15-2020.10.21/object/cylinder_obstacle2.urdf",cylinder_Obstacle_2_StartPos,cylinder_Obstacle_2_StartOrientation)
cylinder_Obstacle_3_Id = p.loadURDF("D:/Study/PhD/2020.10.15-2020.10.21/object/cylinder_obstacle3.urdf",cylinder_Obstacle_3_StartPos,cylinder_Obstacle_3_StartOrientation)
cylinder_Obstacle_4_Id = p.loadURDF("D:/Study/PhD/2020.10.15-2020.10.21/object/cylinder_obstacle4.urdf",cylinder_Obstacle_4_StartPos,cylinder_Obstacle_4_StartOrientation)
cylinder_target_Id = p.loadURDF("D:/Study/PhD/2020.10.15-2020.10.21/object/cylinder_target.urdf",cylinder_target_StartPos,cylinder_target_StartOrientation)
cylinder_robot_Id = p.loadURDF("D:/Study/PhD/2020.10.15-2020.10.21/object/cylinder_robot.urdf",cylinder_robot_StartPos,cylinder_robot_StartOrientation)

cylinder_obstacle1.urdf:

<?xml version="1.0"?>
 <robot name="myfirst">
 
   <material name="red">
     <color rgba="0.5 0 0 1"/>
   </material>
   
   <link name="base_link">
     <visual>
       <geometry>
         <cylinder length="0.4" radius="0.2"/>
       </geometry>
       <material name="red"/>
     </visual>
     <collision>
       <geometry>
         <cylinder length="0.4" radius="0.2"/>
       </geometry>
     </collision>
     <inertial>
       <mass value="1"/>
       <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
     </inertial>
   </link>

 </robot>

cylinder_obstacle2.urdf:

<?xml version="1.0"?>
 <robot name="myfirst">
 
   <material name="red">
     <color rgba="0.5 0 0 1"/>
   </material>
   
   <link name="base_link">
     <visual>
       <geometry>
         <cylinder length="0.3" radius="0.3"/>
       </geometry>
       <material name="red"/>
     </visual>
     <collision>
       <geometry>
         <cylinder length="0.3" radius="0.3"/>
       </geometry>
     </collision>
     <inertial>
       <mass value="1"/>
       <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
     </inertial>
   </link>
 </robot>

cylinder_obstacle3.urdf:

<?xml version="1.0"?>
 <robot name="myfirst">
 
   <material name="red">
     <color rgba="0.5 0 0 1"/>
   </material>
   
   <link name="base_link">
     <visual>
       <geometry>
         <cylinder length="0.2" radius="0.1"/>
       </geometry>
       <material name="red"/>
     </visual>
     <collision>
       <geometry>
         <cylinder length="0.2" radius="0.1"/>
       </geometry>
     </collision>
     <inertial>
       <mass value="1"/>
       <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
     </inertial>
   </link>

 </robot>

cylinder_obstacle4.urdf:

<?xml version="1.0"?>
 <robot name="myfirst">
 
   <material name="red">
     <color rgba="0.5 0 0 1"/>
   </material>
   
   <link name="base_link">
     <visual>
       <geometry>
         <cylinder length="0.2" radius="0.3"/>
       </geometry>
       <material name="red"/>
     </visual>
     <collision>
       <geometry>
         <cylinder length="0.2" radius="0.3"/>
       </geometry>
     </collision>
     <inertial>
       <mass value="1"/>
       <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
     </inertial>
   </link>

 </robot>

cylinder_target.urdf:

<?xml version="1.0"?>
 <robot name="myfirst">
 
   <material name="green">
     <color rgba="0 1 0 1"/>
   </material>
   
   <link name="base_link">
     <visual>
       <geometry>
         <cylinder length="0.6" radius="0.2"/>
       </geometry>
       <material name="green"/>
     </visual>
     <collision>
       <geometry>
         <cylinder length="0.6" radius="0.2"/>
       </geometry>
     </collision>
     <inertial>
       <mass value="1"/>
       <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
     </inertial>
   </link>

 </robot>

cylinder_robot.urdf:

<?xml version="1.0"?>
 <robot name="myfirst">
 
   <material name="blue">
     <color rgba="0 1 1 1"/>
   </material>
   
   <link name="base_link">
     <visual>
       <geometry>
         <cylinder length="0.6" radius="0.2"/>
       </geometry>
       <material name="blue"/>
     </visual>
     <collision>
       <geometry>
         <cylinder length="0.6" radius="0.2"/>
       </geometry>
     </collision>
     <inertial>
       <mass value="1"/>
       <inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
     </inertial>
   </link>

 </robot>

具体参数细节请访问PyBullet (二) 机器人手臂的简单移动中的“2.14模型加载(一)”

2.1.6 参数检测

robot_shape = p.getVisualShapeData(cylinder_robot_Id)#得到有关模型形状的一些列信息
target_shape = p.getVisualShapeData(cylinder_target_Id)
robot_R = robot_shape[0][3][1]#半径
robot_H = robot_shape[0][3][0]#高度
target_R = target_shape[0][3][1]
target_H = target_shape[0][3][0]

getVisualShapeData
您可以使用getVisualShapeData访问视觉形状信息。 您可以使用它将您自己的呈现方法与PyBullet模拟连接起来,并在每个模拟步骤之后手动同步世界转换。 您还可以使用GET网格数据,特别是对于可变形对象,来接收有关顶点位置的数据。
输入参数:

必需/可选参数参数名字参数类型介绍
必需objectUniqueIdint对象的唯一id,由加载方法返回。
可选flagsintVISUAL_SHAPE_DATA_TEXTURE_UNIQUE_IDS还将提供纹理独特的ID。
可选physicsClientIdint物理客户端id由“连接”返回。

输出参数:

参数名字参数类型介绍
objectUniqueIdint对象的唯一id,由加载方法返回。
linkIndexint基础的链接索引或-1。
visualGeometryTypeint视觉几何类型(TBD)。
dimensionsvec3, list of 3 floats几何尺寸(尺寸,局部尺度)。
meshAssetFileNamestring, list of chars到三角形网格的路径,如果有的话。 通常相对于URDF、SDF或MJCF文件位置,但可能是绝对的。
localVisualFrame positionvec3, list of 3 floats局部视觉框架的位置,相对于链接/关节框架。
localVisualFrame orientationvec4, list of 4 floats局部视觉框架相对于链路/关节框架的方向。
rgbaColorvec4, list of 4 floats红色/绿色/蓝色/阿尔法的URDF颜色(如果指定的话)。
textureUniqueIdint(字段只存在于使用VISUAL_SHAPE_DATA_TEXTURE_UNIQUE_IDS标志时)纹理形状的唯一id,或-1如果没有。

2.1.7 路径输入

path_string = input("Please input the path:")
path_string = path_string.replace('[','')
path_string = path_string.replace(']','')
path_string = path_string.split(',')
length = len(path_string)
little_length = length/3
path = []
little_length = int(little_length)
for i in range(little_length):
    path.append([])
    for j in range(3):
        path[i].append(0.4)
path_flag = 0
for i in range(little_length):
    for j in range(3):
        path[i][j] = float(path_string[path_flag])
        path_flag = path_flag + 1
#path = [[0.4,0.0,0.3],[0.6,0.0,0.3],[0.8,0.0,0.3],[1.0,0.0,0.3],[1.2,0.0,0.3]]

涉及到数据处理,这里就不再赘述了(一定会有处理的比较好的同学,欢迎评论区讨论)。

2.1.8 各类函数

2.1.8.1 求两直线交点

这里借鉴了博主“AD稳稳”的方法,自己稍作了修改,博客链接私戳:python 计算两直线交点

def cross_point(line1,line2):#计算交点函数
    x1=line1[0]#取四点坐标
    y1=line1[1]
    x2=line1[2]
    y2=line1[3]
    x3=line2[0]
    y3=line2[1]
    x4=line2[2]
    y4=line2[3]
    if (x4-x3)==0:#L2直线斜率不存在操作
        k2=None
        b2=0
        x=x3
        k1=(y2-y1)*1.0/(x2-x1)#计算k1,由于点均为整数,需要进行浮点数转化
        b1=y1*1.0-x1*k1*1.0#整型转浮点型是关键
        y=k1*x*1.0+b1*1.0
    elif (x2-x1)==0:#L1直线斜率不存在操作
        k1=None
        b1=0
        x=x1
        k2=(y4-y3)*1.0/(x4-x3)
        b2=y3*1.0-x3*k2*1.0
        y=k2*x*1.0+b2*1.0
    else:
        k1=(y2-y1)*1.0/(x2-x1)#计算k1,由于点均为整数,需要进行浮点数转化
        k2=(y4-y3)*1.0/(x4-x3)#斜率存在操作
        b1=y1*1.0-x1*k1*1.0#整型转浮点型是关键
        b2=y3*1.0-x3*k2*1.0
        x=(b2-b1)*1.0/(k1-k2)
        y=k1*x*1.0+b1*1.0    
    return [x,y]
2.1.8.2 计算垂心(1.1.1.1)
def orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y):
    if (path_y - robot_y) == 0 and (path_x - robot_x) != 0: #水平
        flag = 1
        orthocenter_x = target_x
        orthocenter_y = robot_y
    elif (path_y - robot_y) != 0 and (path_x - robot_x) == 0: #竖直
        flag = 2
        orthocenter_x = robot_x
        orthocenter_y = target_y
    else:
        flag = 3
        k1 = (path_y - robot_y)/(path_x - robot_x)
        k4 = -(1/k1)
        b4 = target_y - k4 * target_x
        point_fake_x = target_x + 1
        point_fake_y = k4 * point_fake_x + b4
        line1 = [path_x,path_y,robot_x,robot_y]
        line4 = [target_x,target_y,point_fake_x,point_fake_y]
        orthocenter = cross_point(line1,line4)
        orthocenter_x = orthocenter[0]
        orthocenter_y = orthocenter[1]
    return [orthocenter_x,orthocenter_y,flag]
2.1.8.3 计算移动的方向(1.1.1.2)
def move_direction(flag,robot_x,robot_y,path_x,path_y):
    if flag == 1:#水平
        direction_x = (robot_x - path_x)/abs((robot_x - path_x))
        direction_y = 0
        cosx = 1
        sinx = 0
    elif flag == 2:#竖直
        direction_x = 0
        direction_y = (robot_y - path_y)/abs((robot_y - path_y))
        cosx = 0
        sinx = 1
    else:
        dir_y = path_y - robot_y 
        dir_x = path_x - robot_x
        cosx = abs(dir_x)/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
        sinx = abs(dir_y)/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
        direction_x = (robot_x - path_x)/abs((robot_x - path_x))
        direction_y = (robot_y - path_y)/abs((robot_y - path_y))
    return [direction_x,direction_y,cosx,sinx]
2.1.8.3 计算向“上”移动的方向(1.1.1.3)
def move_vertically_direction(flag,robot_x,robot_y,target_x,target_y,path_x,path_y):
    if flag == 1:#水平
        fake_point_x = robot_x
        fake_point_y = target_y#只要不是robot_y,其他任意数字都可以
        line2 = [robot_x,robot_y,fake_point_x,fake_point_y]
        line3 = [path_x,path_y,target_x,target_y]
        cross_point_2 = cross_point(line2,line3)
        cross_point_2_x = cross_point_2[0]
        cross_point_2_y = cross_point_2[1]
        dir_x2 = (cross_point_2_x - robot_x)/abs(cross_point_2_x - robot_x)
        dir_y2 = (cross_point_2_y - robot_y)/abs(cross_point_2_y - robot_y)
        cosx2 = 0
        sinx2 = 1*dir_y2    
    elif flag == 2:#竖直
        fake_point_x = target_x#只要不是robot_x,其他任意数字都可以
        fake_point_y = robot_y
        line2 = [robot_x,robot_y,fake_point_x,fake_point_y]
        line3 = [path_x,path_y,target_x,target_y]
        cross_point_2 = cross_point(line2,line3)
        cross_point_2_x = cross_point_2[0]
        cross_point_2_y = cross_point_2[1]
        dir_x2 = (cross_point_2_x - robot_x)/abs(cross_point_2_x - robot_x)
        dir_y2 = (cross_point_2_y - robot_y)/abs(cross_point_2_y - robot_y)
        cosx2 = 1*dir_x2
        sinx2 = 0
    else:
        k1 = (path_y - robot_y)/(path_x - robot_x)
        k2 = -(1/k1) 
        b2 = robot_y - k2 * robot_x
        fake_point_x = robot_x + 1
        fake_point_y = k2 * fake_point_x + b2
        line2 = [robot_x,robot_y,fake_point_x,fake_point_y]
        line3 = [path_x,path_y,target_x,target_y]
        cross_point_2 = cross_point(line2,line3)
        cross_point_2_x = cross_point_2[0]
        cross_point_2_y = cross_point_2[1]
        dir_x2 = cross_point_2_x - robot_x
        dir_y2 = cross_point_2_y - robot_y
        cosx2 = dir_x2/(math.sqrt(np.square(dir_x2)+np.square(dir_y2)))
        sinx2 = dir_y2/(math.sqrt(np.square(dir_x2)+np.square(dir_y2)))
        
    return [cosx2,sinx2,cross_point_2_x,cross_point_2_y]

2.1.8.4 first move(1.1.1.2)
def first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y):
    #print("the first move")
    #垂点距离机器人的距离
    #target and robot are too close together, robot moves separate distance from target
    while 1:
        cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
        cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
        robot_x = cylinder_robot_data[0][0]
        robot_y = cylinder_robot_data[0][1]
        target_x = cylinder_target_data[0][0]
        target_y = cylinder_target_data[0][1]
        orthocenter = orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y)
        orthocenter_x = orthocenter[0]
        orthocenter_y = orthocenter[1]
        flag = orthocenter[2]
        orthocenter_2_robot = math.sqrt(np.square(orthocenter_x - robot_x)+np.square(orthocenter_y - robot_y))
        if orthocenter_2_robot - (robot_R + target_R) > 0.2 and orthocenter_2_robot - (robot_R + target_R) <= 0.3:
            break
        if (orthocenter_2_robot - (robot_R + target_R)) <= 0.2:
            direction_move = move_direction(flag,robot_x,robot_y,path_x,path_y)
            direction_x = direction_move[0]
            direction_y = direction_move[1]
            cosx = direction_move[2]
            sinx = direction_move[3]
        #距离太远
        elif orthocenter_2_robot - (robot_R + target_R) > 0.3:
            direction_move = move_direction(flag,robot_x,robot_y,path_x,path_y)
            direction_x = -direction_move[0]
            direction_y = -direction_move[1]
            cosx = direction_move[2]
            sinx = direction_move[3]
        else:
            direction_x = 0.0
            direction_y = 0.0
            cosx = 0.0
            sinx = 0.0      
        p.resetBaseVelocity(cylinder_robot_Id,[direction_x*cosx/5,direction_y*sinx/5,0])#give the robot a velocity
        p.stepSimulation()
        time.sleep(1./240.)
    orthocenter = orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y)
    flag = orthocenter[2]
    return flag

resetBaseVelocity
您可以使用重置基本速度重置身体底部的线性和/或角速度
输入参数:

必需/可选参数参数名字参数类型介绍
必需objectUniqueIdint对象的唯一id,由加载方法返回。
可选linearVelocityvec3, list of 3 floats直角世界坐标中的线速度[x,y,z]。
可选angularVelocityvec3, list of 3 floats直角速度[wx,wy,wz]在笛卡尔世界坐标中。
可选physicsClientIdint如果您连接到多个服务器,您可以选择一个。
2.1.8.5 second move(1.1.1.3)
def second_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag):
    #print("the second move")
    while 1:
        cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
        cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
        robot_x = cylinder_robot_data[0][0]
        robot_y = cylinder_robot_data[0][1]
        target_x = cylinder_target_data[0][0]
        target_y = cylinder_target_data[0][1]
        vertically_move_direction = move_vertically_direction(flag,robot_x,robot_y,target_x,target_y,path_x,path_y)
        cosx2 = vertically_move_direction[0]
        sinx2 = vertically_move_direction[1]
        cross_point_2_x = vertically_move_direction[2]
        cross_point_2_y = vertically_move_direction[3]
    
        if (math.sqrt(np.square(robot_x - cross_point_2_x)+np.square(robot_y - cross_point_2_y))) <= 0.1:
            break
        
        p.resetBaseVelocity(cylinder_robot_Id,[cosx2/5,sinx2/5,0])
        #p.applyExternalForce(cylinder_robot_Id,-1,[cosx2 * 2,sinx2 * 2,0],[0,0,robot_H/2],p.WORLD_FRAME) #施加力
        p.stepSimulation()
        time.sleep(1./240.)
        flag = first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y)

    return 1
    
2.1.8.6 third move(1.1.1.4)
def third_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag):
    #print("the third move")
    while 1:
        cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
        cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
        robot_x = cylinder_robot_data[0][0]
        robot_y = cylinder_robot_data[0][1]
        target_x = cylinder_target_data[0][0]
        target_y = cylinder_target_data[0][1]
        if flag == 1:
            cosx3 = (path_x - robot_x)/abs((path_x - robot_x))
            sinx3 = 0
        elif flag == 2:
            cosx3 = 0
            sinx3 = (path_y - robot_y)/abs((path_y - robot_y))
        else:
            dir_x = path_x - robot_x
            dir_y = path_y - robot_y
            cosx3 = dir_x/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
            sinx3 = dir_y/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
        if (math.sqrt(np.square(target_x - path_x)+np.square(target_y - path_y))) <= 0.1:
            break
        start_time = datetime.datetime.now()
        while 1:
            end_time = datetime.datetime.now()
            interval = (end_time-start_time).seconds
            if interval == 3:
                break
            p.resetBaseVelocity(cylinder_robot_Id,[cosx3/5,sinx3/5,0])
            p.stepSimulation()
            time.sleep(1./240.)
        flag = first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y)
        second_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag)
2.1.8.7 向“下”移动(1.1.2.2)
def second_time_first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag):
    #print("the second time first move")
    while 1:
        cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
        cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
        robot_x = cylinder_robot_data[0][0]
        robot_y = cylinder_robot_data[0][1]
        target_x = cylinder_target_data[0][0]
        target_y = cylinder_target_data[0][1]
        Scalar_Product_1 = (path_x - robot_x)*(target_x - robot_x) + (path_y - robot_y)*(target_y - robot_y)#向量的点乘
        if Scalar_Product_1 > 0:
            break
        if flag == 1:
            if target_y >= path_y:
                cosx21 = 0
                sinx21 = -1
                p.resetBaseVelocity(cylinder_robot_Id,[cosx21/5,sinx21/5,0])
            else:
                cosx21 = 0
                sinx21 = 1
                p.resetBaseVelocity(cylinder_robot_Id,[cosx21/5,sinx21/5,0])
        elif flag ==3:
            if target_x >= path_x:
                cosx21 = -1
                sinx21 = 0
                p.resetBaseVelocity(cylinder_robot_Id,[cosx21/5,sinx21/5,0])
            else:
                cosx21 = 1
                sinx21 = 0
                p.resetBaseVelocity(cylinder_robot_Id,[cosx21/5,sinx21/5,0])
        else:
            orthocenter = orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y)
            orthocenter_x = orthocenter[0]
            orthocenter_y = orthocenter[1]
            flag = orthocenter[2]
            dir_x = orthocenter_x - target_x
            dir_y = orthocenter_y - target_y
            cosx21 = dir_x/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
            sinx21 = dir_y/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
        p.resetBaseVelocity(cylinder_robot_Id,[cosx21/5,sinx21/5,0])
        p.stepSimulation()
        time.sleep(1./240.)    
2.1.8.8 第一种情况
def the_first_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y):
    print("The first situation")
    flag = first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y)
    time.sleep(3)
    print("*********************************************")
    #robot 移动到 target和path的延长线上,robot moves to the extension of target and path.
    second_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag)
    time.sleep(3)
    orthocenter = orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y)
    flag = orthocenter[2]
    #robot begin to move to target and pull the target to the goal
    third_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag)
2.1.8.9 第二种情况
def the_second_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y):
    print("The second situation")
    orthocenter = orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y)
    flag = orthocenter[2]
    second_time_first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag)
    flag = first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y)
    time.sleep(3)
    print("*********************************************")
    #robot 移动到 target和path的延长线上,robot moves to the extension of target and path.
    second_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag)
    time.sleep(3)
    orthocenter = orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y)
    flag = orthocenter[2]
    third_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag) 
2.1.8.10 第三种情况
def the_third_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y):
    print("The third situation")
    first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y)
    time.sleep(3)
    while 1:
        dir_x31 = target_x - path_x
        dir_y31 = target_y - path_y
        cosx31 = dir_x31/(math.sqrt(np.square(dir_x31)+np.square(dir_y31)))
        sinx31 = dir_y31/(math.sqrt(np.square(dir_x31)+np.square(dir_y31)))
        cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
        cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
        robot_x = cylinder_robot_data[0][0]
        robot_y = cylinder_robot_data[0][1]
        target_x = cylinder_target_data[0][0]
        target_y = cylinder_target_data[0][1]
        Scalar_Product_2 = (target_x - path_x)*(robot_x - path_x) + (target_y - path_y)*(robot_y - path_y)
        if Scalar_Product_2 > 0:
            break
        p.resetBaseVelocity(cylinder_robot_Id,[cosx31/5,sinx31/5,0])
        p.stepSimulation()
        time.sleep(1./240.)
    the_first_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
2.1.8.11 第四种情况
def the_fourth_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y):
    print("The fourth situation")
    while 1:
        dir_x = path_x - robot_x
        dir_y = path_y - robot_y
        cosx41 = dir_x/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
        sinx41 = dir_y/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
        cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
        cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
        robot_x = cylinder_robot_data[0][0]
        robot_y = cylinder_robot_data[0][1]
        path_x = path[i][0]
        path_y = path[i][1]
        target_x = cylinder_target_data[0][0]
        target_y = cylinder_target_data[0][1]            
        Scalar_Product_2 = (target_x - path_x)*(robot_x - path_x) + (target_y - path_y)*(robot_y - path_y)
        if Scalar_Product_2 > 0:
            start_time = datetime.datetime.now()
            while 1:
                end_time = datetime.datetime.now()
                interval = (end_time-start_time).seconds
                if interval == 1:
                    break
                p.resetBaseVelocity(cylinder_robot_Id,[cosx41/5,sinx41/5,0])
                p.stepSimulation()
                time.sleep(1./240.)
            break
        p.resetBaseVelocity(cylinder_robot_Id,[cosx41/5,sinx41/5,0])
        p.stepSimulation()
        time.sleep(1./240.)
    cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
    cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
    robot_x = cylinder_robot_data[0][0]
    robot_y = cylinder_robot_data[0][1]
    path_x = path[i][0]
    path_y = path[i][1]
    target_x = cylinder_target_data[0][0]
    target_y = cylinder_target_data[0][1]  
    Scalar_Product_1 = (path_x - robot_x)*(target_x - robot_x) + (path_y - robot_y)*(target_y - robot_y)
    Scalar_Product_2 = (target_x - path_x)*(robot_x - path_x) + (target_y - path_y)*(robot_y - path_y)
    if Scalar_Product_1 >= 0 and Scalar_Product_2 > 0:
        print("Before that I am the fourth situation")
        the_first_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
    #点乘是钝角
    elif Scalar_Product_1 < 0 and Scalar_Product_2 > 0:
        print("Before that I am the fourth situation")
        the_second_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
        
    elif Scalar_Product_2 == 0:
        print("Before that I am the fourth situation")
        the_third_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
    else:
        print("Before that I am the fourth situation")
        the_fourth_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
2.1.8.12 主函数
for i in range(len(path)):
    print("robot go to the",i+1,"point")
    cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
    cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
    robot_x = cylinder_robot_data[0][0]
    robot_y = cylinder_robot_data[0][1]
    path_x = path[i][0]
    path_y = path[i][1]
    target_x = cylinder_target_data[0][0]
    target_y = cylinder_target_data[0][1]
    Scalar_Product_1 = (path_x - robot_x)*(target_x - robot_x) + (path_y - robot_y)*(target_y - robot_y)#向量的点乘
    Scalar_Product_2 = (target_x - path_x)*(robot_x - path_x) + (target_y - path_y)*(robot_y - path_y)
    print("*********************************************")
    #点乘是锐角或者直角
    if Scalar_Product_1 >= 0 and Scalar_Product_2 > 0:
        the_first_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
    #点乘是钝角
    elif Scalar_Product_1 < 0 and Scalar_Product_2 > 0:
        the_second_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
        
    elif Scalar_Product_2 == 0:
        the_third_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
    else:
        the_fourth_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)

2.1.9 程序结束

p.disconnect()#有连接就有断开

2.2 代码总体

# -*- coding: utf-8 -*-
"""
Created on Mon Oct 19 11:12:43 2020

@author: 12106
"""


# -*- coding: utf-8 -*-
"""
Created on Sat Oct 17 16:03:00 2020

@author: 12106
"""

import pybullet as p
import time
import pybullet_data
import numpy as np
import datetime
import math

physicsClient = p.connect(p.GUI)#or p.DIRECT for non-graphical version
p.setAdditionalSearchPath(pybullet_data.getDataPath()) #optionally
p.setGravity(0,0,-9.81)
planeId = p.loadURDF("plane.urdf")

cylinder_Obstacle_1_StartPos = [-0.4, 0.3, 0.2 ]
cylinder_Obstacle_2_StartPos = [ 0.0,-0.6, 0.15]
cylinder_Obstacle_3_StartPos = [ 0.6,-0.6, 0.1 ]
cylinder_Obstacle_4_StartPos = [ 0.8, 0.2, 0.1]
cylinder_target_StartPos = [ 0, 0.0, 0.3]
cylinder_robot_StartPos = [ -0.8, 0.0, 0.3]

cylinder_Obstacle_1_StartOrientation = p.getQuaternionFromEuler([0,0,0])
cylinder_Obstacle_2_StartOrientation = p.getQuaternionFromEuler([0,0,0])
cylinder_Obstacle_3_StartOrientation = p.getQuaternionFromEuler([0,0,0])
cylinder_Obstacle_4_StartOrientation = p.getQuaternionFromEuler([0,0,0])
cylinder_target_StartOrientation = p.getQuaternionFromEuler([0,0,0])
cylinder_robot_StartOrientation = p.getQuaternionFromEuler([0,0,0])


cylinder_Obstacle_1_Id = p.loadURDF("D:/Study/University of Leeds/PhD/2020.10.15-2020.10.21/object/cylinder_obstacle1.urdf",cylinder_Obstacle_1_StartPos,cylinder_Obstacle_1_StartOrientation)
cylinder_Obstacle_2_Id = p.loadURDF("D:/Study/University of Leeds/PhD/2020.10.15-2020.10.21/object/cylinder_obstacle2.urdf",cylinder_Obstacle_2_StartPos,cylinder_Obstacle_2_StartOrientation)
cylinder_Obstacle_3_Id = p.loadURDF("D:/Study/University of Leeds/PhD/2020.10.15-2020.10.21/object/cylinder_obstacle3.urdf",cylinder_Obstacle_3_StartPos,cylinder_Obstacle_3_StartOrientation)
cylinder_Obstacle_4_Id = p.loadURDF("D:/Study/University of Leeds/PhD/2020.10.15-2020.10.21/object/cylinder_obstacle4.urdf",cylinder_Obstacle_4_StartPos,cylinder_Obstacle_4_StartOrientation)
cylinder_target_Id = p.loadURDF("D:/Study/University of Leeds/PhD/2020.10.15-2020.10.21/object/cylinder_target.urdf",cylinder_target_StartPos,cylinder_target_StartOrientation)
cylinder_robot_Id = p.loadURDF("D:/Study/University of Leeds/PhD/2020.10.15-2020.10.21/object/cylinder_robot.urdf",cylinder_robot_StartPos,cylinder_robot_StartOrientation)
robot_shape = p.getVisualShapeData(cylinder_robot_Id)
target_shape = p.getVisualShapeData(cylinder_target_Id)
robot_R = robot_shape[0][3][1]
robot_H = robot_shape[0][3][0]
target_R = target_shape[0][3][1]
target_H = target_shape[0][3][0]

#path = [[0.4,0.4,0.3],[0.6,0.6,0.3],[0.8,0.8,0.3],[1.0,1.0,0.3],[1.2,1.2,0.3]]
path_string = input("Please input the path:")
path_string = path_string.replace('[','')
path_string = path_string.replace(']','')
path_string = path_string.split(',')
length = len(path_string)
little_length = length/3
path = []
little_length = int(little_length)
for i in range(little_length):
    path.append([])
    for j in range(3):
        path[i].append(0.4)
path_flag = 0
for i in range(little_length):
    for j in range(3):
        path[i][j] = float(path_string[path_flag])
        path_flag = path_flag + 1
#path = [[0.4,0.0,0.3],[0.6,0.0,0.3],[0.8,0.0,0.3],[1.0,0.0,0.3],[1.2,0.0,0.3]]

def cross_point(line1,line2):#计算交点函数
    x1=line1[0]#取四点坐标
    y1=line1[1]
    x2=line1[2]
    y2=line1[3]
    x3=line2[0]
    y3=line2[1]
    x4=line2[2]
    y4=line2[3]
    if (x4-x3)==0:#L2直线斜率不存在操作
        k2=None
        b2=0
        x=x3
        k1=(y2-y1)*1.0/(x2-x1)#计算k1,由于点均为整数,需要进行浮点数转化
        b1=y1*1.0-x1*k1*1.0#整型转浮点型是关键
        y=k1*x*1.0+b1*1.0
    elif (x2-x1)==0:
        k1=None
        b1=0
        x=x1
        k2=(y4-y3)*1.0/(x4-x3)
        b2=y3*1.0-x3*k2*1.0
        y=k2*x*1.0+b2*1.0
    else:
        k1=(y2-y1)*1.0/(x2-x1)#计算k1,由于点均为整数,需要进行浮点数转化
        k2=(y4-y3)*1.0/(x4-x3)#斜率存在操作
        b1=y1*1.0-x1*k1*1.0#整型转浮点型是关键
        b2=y3*1.0-x3*k2*1.0
        x=(b2-b1)*1.0/(k1-k2)
        y=k1*x*1.0+b1*1.0    
    return [x,y]

def orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y):
    if (path_y - robot_y) == 0 and (path_x - robot_x) != 0: #水平
        flag = 1
        orthocenter_x = target_x
        orthocenter_y = robot_y
    elif (path_y - robot_y) != 0 and (path_x - robot_x) == 0: #竖直
        flag = 2
        orthocenter_x = robot_x
        orthocenter_y = target_y
    else:
        flag = 3
        k1 = (path_y - robot_y)/(path_x - robot_x)
        k4 = -(1/k1)
        b4 = target_y - k4 * target_x
        point_fake_x = target_x + 1
        point_fake_y = k4 * point_fake_x + b4
        line1 = [path_x,path_y,robot_x,robot_y]
        line4 = [target_x,target_y,point_fake_x,point_fake_y]
        orthocenter = cross_point(line1,line4)
        orthocenter_x = orthocenter[0]
        orthocenter_y = orthocenter[1]
    return [orthocenter_x,orthocenter_y,flag]
    
def move_direction(flag,robot_x,robot_y,path_x,path_y):
    if flag == 1:#水平
        direction_x = (robot_x - path_x)/abs((robot_x - path_x))
        direction_y = 0
        cosx = 1
        sinx = 0
    elif flag == 2:#竖直
        direction_x = 0
        direction_y = (robot_y - path_y)/abs((robot_y - path_y))
        cosx = 0
        sinx = 1
    else:
        dir_y = path_y - robot_y 
        dir_x = path_x - robot_x
        cosx = abs(dir_x)/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
        sinx = abs(dir_y)/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
        direction_x = (robot_x - path_x)/abs((robot_x - path_x))
        direction_y = (robot_y - path_y)/abs((robot_y - path_y))
    return [direction_x,direction_y,cosx,sinx]
    
def move_vertically_direction(flag,robot_x,robot_y,target_x,target_y,path_x,path_y):
    if flag == 1:#水平
        fake_point_x = robot_x
        fake_point_y = target_y#只要不是robot_y,其他任意数字都可以
        line2 = [robot_x,robot_y,fake_point_x,fake_point_y]
        line3 = [path_x,path_y,target_x,target_y]
        cross_point_2 = cross_point(line2,line3)
        cross_point_2_x = cross_point_2[0]
        cross_point_2_y = cross_point_2[1]
        dir_x2 = (cross_point_2_x - robot_x)/abs(cross_point_2_x - robot_x)
        dir_y2 = (cross_point_2_y - robot_y)/abs(cross_point_2_y - robot_y)
        cosx2 = 0
        sinx2 = 1*dir_y2    
    elif flag == 2:#竖直
        fake_point_x = target_x#只要不是robot_x,其他任意数字都可以
        fake_point_y = robot_y
        line2 = [robot_x,robot_y,fake_point_x,fake_point_y]
        line3 = [path_x,path_y,target_x,target_y]
        cross_point_2 = cross_point(line2,line3)
        cross_point_2_x = cross_point_2[0]
        cross_point_2_y = cross_point_2[1]
        dir_x2 = (cross_point_2_x - robot_x)/abs(cross_point_2_x - robot_x)
        dir_y2 = (cross_point_2_y - robot_y)/abs(cross_point_2_y - robot_y)
        cosx2 = 1*dir_x2
        sinx2 = 0
    else:
        k1 = (path_y - robot_y)/(path_x - robot_x)
        k2 = -(1/k1) 
        b2 = robot_y - k2 * robot_x
        fake_point_x = robot_x + 1
        fake_point_y = k2 * fake_point_x + b2
        line2 = [robot_x,robot_y,fake_point_x,fake_point_y]
        line3 = [path_x,path_y,target_x,target_y]
        cross_point_2 = cross_point(line2,line3)
        cross_point_2_x = cross_point_2[0]
        cross_point_2_y = cross_point_2[1]
        dir_x2 = cross_point_2_x - robot_x
        dir_y2 = cross_point_2_y - robot_y
        cosx2 = dir_x2/(math.sqrt(np.square(dir_x2)+np.square(dir_y2)))
        sinx2 = dir_y2/(math.sqrt(np.square(dir_x2)+np.square(dir_y2)))
        
    return [cosx2,sinx2,cross_point_2_x,cross_point_2_y]


def first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y):
    #print("the first move")
    #垂点距离机器人的距离
    #target and robot are too close together, robot moves separate distance from target
    while 1:
        cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
        cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
        robot_x = cylinder_robot_data[0][0]
        robot_y = cylinder_robot_data[0][1]
        target_x = cylinder_target_data[0][0]
        target_y = cylinder_target_data[0][1]
        orthocenter = orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y)
        orthocenter_x = orthocenter[0]
        orthocenter_y = orthocenter[1]
        flag = orthocenter[2]
        orthocenter_2_robot = math.sqrt(np.square(orthocenter_x - robot_x)+np.square(orthocenter_y - robot_y))
        if orthocenter_2_robot - (robot_R + target_R) > 0.2 and orthocenter_2_robot - (robot_R + target_R) <= 0.3:
            break
        if (orthocenter_2_robot - (robot_R + target_R)) <= 0.2:
            direction_move = move_direction(flag,robot_x,robot_y,path_x,path_y)
            direction_x = direction_move[0]
            direction_y = direction_move[1]
            cosx = direction_move[2]
            sinx = direction_move[3]
        #距离太远
        elif orthocenter_2_robot - (robot_R + target_R) > 0.3:
            direction_move = move_direction(flag,robot_x,robot_y,path_x,path_y)
            direction_x = -direction_move[0]
            direction_y = -direction_move[1]
            cosx = direction_move[2]
            sinx = direction_move[3]
        else:
            direction_x = 0.0
            direction_y = 0.0
            cosx = 0.0
            sinx = 0.0      
        p.resetBaseVelocity(cylinder_robot_Id,[direction_x*cosx/5,direction_y*sinx/5,0])#give the robot a velocity
        p.stepSimulation()
        time.sleep(1./240.)
    orthocenter = orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y)
    flag = orthocenter[2]
    return flag

def second_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag):
    #print("the second move")
    while 1:
        cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
        cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
        robot_x = cylinder_robot_data[0][0]
        robot_y = cylinder_robot_data[0][1]
        target_x = cylinder_target_data[0][0]
        target_y = cylinder_target_data[0][1]
        vertically_move_direction = move_vertically_direction(flag,robot_x,robot_y,target_x,target_y,path_x,path_y)
        cosx2 = vertically_move_direction[0]
        sinx2 = vertically_move_direction[1]
        cross_point_2_x = vertically_move_direction[2]
        cross_point_2_y = vertically_move_direction[3]
    
        if (math.sqrt(np.square(robot_x - cross_point_2_x)+np.square(robot_y - cross_point_2_y))) <= 0.1:
            break
        
        p.resetBaseVelocity(cylinder_robot_Id,[cosx2/5,sinx2/5,0])
        #p.applyExternalForce(cylinder_robot_Id,-1,[cosx2 * 2,sinx2 * 2,0],[0,0,robot_H/2],p.WORLD_FRAME) #施加力
        p.stepSimulation()
        time.sleep(1./240.)
        flag = first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y)

    return 1
    
def third_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag):
    #print("the third move")
    while 1:
        cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
        cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
        robot_x = cylinder_robot_data[0][0]
        robot_y = cylinder_robot_data[0][1]
        target_x = cylinder_target_data[0][0]
        target_y = cylinder_target_data[0][1]
        if flag == 1:
            cosx3 = (path_x - robot_x)/abs((path_x - robot_x))
            sinx3 = 0
        elif flag == 2:
            cosx3 = 0
            sinx3 = (path_y - robot_y)/abs((path_y - robot_y))
        else:
            dir_x = path_x - robot_x
            dir_y = path_y - robot_y
            cosx3 = dir_x/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
            sinx3 = dir_y/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
        if (math.sqrt(np.square(target_x - path_x)+np.square(target_y - path_y))) <= 0.1:
            break
        start_time = datetime.datetime.now()
        while 1:
            end_time = datetime.datetime.now()
            interval = (end_time-start_time).seconds
            if interval == 3:
                break
            p.resetBaseVelocity(cylinder_robot_Id,[cosx3/5,sinx3/5,0])
            p.stepSimulation()
            time.sleep(1./240.)
        flag = first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y)
        second_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag)
    
def second_time_first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag):
    #print("the second time first move")
    while 1:
        cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
        cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
        robot_x = cylinder_robot_data[0][0]
        robot_y = cylinder_robot_data[0][1]
        target_x = cylinder_target_data[0][0]
        target_y = cylinder_target_data[0][1]
        Scalar_Product_1 = (path_x - robot_x)*(target_x - robot_x) + (path_y - robot_y)*(target_y - robot_y)#向量的点乘
        if Scalar_Product_1 > 0:
            break
        if flag == 1:
            if target_y >= path_y:
                cosx21 = 0
                sinx21 = -1
                p.resetBaseVelocity(cylinder_robot_Id,[cosx21/5,sinx21/5,0])
            else:
                cosx21 = 0
                sinx21 = 1
                p.resetBaseVelocity(cylinder_robot_Id,[cosx21/5,sinx21/5,0])
        elif flag ==3:
            if target_x >= path_x:
                cosx21 = -1
                sinx21 = 0
                p.resetBaseVelocity(cylinder_robot_Id,[cosx21/5,sinx21/5,0])
            else:
                cosx21 = 1
                sinx21 = 0
                p.resetBaseVelocity(cylinder_robot_Id,[cosx21/5,sinx21/5,0])
        else:
            orthocenter = orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y)
            orthocenter_x = orthocenter[0]
            orthocenter_y = orthocenter[1]
            flag = orthocenter[2]
            dir_x = orthocenter_x - target_x
            dir_y = orthocenter_y - target_y
            cosx21 = dir_x/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
            sinx21 = dir_y/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
        p.resetBaseVelocity(cylinder_robot_Id,[cosx21/5,sinx21/5,0])
        p.stepSimulation()
        time.sleep(1./240.)    

def the_first_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y):
    print("The first situation")
    flag = first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y)
    time.sleep(3)
    print("*********************************************")
    #robot 移动到 target和path的延长线上,robot moves to the extension of target and path.
    second_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag)
    time.sleep(3)
    orthocenter = orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y)
    flag = orthocenter[2]
    #robot begin to move to target and pull the target to the goal
    third_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag)
            
def the_second_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y):
    print("The second situation")
    orthocenter = orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y)
    flag = orthocenter[2]
    second_time_first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag)
    flag = first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y)
    time.sleep(3)
    print("*********************************************")
    #robot 移动到 target和path的延长线上,robot moves to the extension of target and path.
    second_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag)
    time.sleep(3)
    orthocenter = orthocenter_point(robot_x,robot_y,path_x,path_y,target_x,target_y)
    flag = orthocenter[2]
    third_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y,flag) 

def the_third_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y):
    print("The third situation")
    first_move(cylinder_target_Id,cylinder_robot_Id,path_x,path_y)
    time.sleep(3)
    while 1:
        dir_x31 = target_x - path_x
        dir_y31 = target_y - path_y
        cosx31 = dir_x31/(math.sqrt(np.square(dir_x31)+np.square(dir_y31)))
        sinx31 = dir_y31/(math.sqrt(np.square(dir_x31)+np.square(dir_y31)))
        cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
        cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
        robot_x = cylinder_robot_data[0][0]
        robot_y = cylinder_robot_data[0][1]
        target_x = cylinder_target_data[0][0]
        target_y = cylinder_target_data[0][1]
        Scalar_Product_2 = (target_x - path_x)*(robot_x - path_x) + (target_y - path_y)*(robot_y - path_y)
        if Scalar_Product_2 > 0:
            break
        p.resetBaseVelocity(cylinder_robot_Id,[cosx31/5,sinx31/5,0])
        p.stepSimulation()
        time.sleep(1./240.)
    the_first_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)

def the_fourth_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y):
    print("The fourth situation")
    while 1:
        dir_x = path_x - robot_x
        dir_y = path_y - robot_y
        cosx41 = dir_x/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
        sinx41 = dir_y/(math.sqrt(np.square(dir_x)+np.square(dir_y)))
        cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
        cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
        robot_x = cylinder_robot_data[0][0]
        robot_y = cylinder_robot_data[0][1]
        path_x = path[i][0]
        path_y = path[i][1]
        target_x = cylinder_target_data[0][0]
        target_y = cylinder_target_data[0][1]            
        Scalar_Product_2 = (target_x - path_x)*(robot_x - path_x) + (target_y - path_y)*(robot_y - path_y)
        if Scalar_Product_2 > 0:
            start_time = datetime.datetime.now()
            while 1:
                end_time = datetime.datetime.now()
                interval = (end_time-start_time).seconds
                if interval == 1:
                    break
                p.resetBaseVelocity(cylinder_robot_Id,[cosx41/5,sinx41/5,0])
                p.stepSimulation()
                time.sleep(1./240.)
            break
        p.resetBaseVelocity(cylinder_robot_Id,[cosx41/5,sinx41/5,0])
        p.stepSimulation()
        time.sleep(1./240.)
    cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
    cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
    robot_x = cylinder_robot_data[0][0]
    robot_y = cylinder_robot_data[0][1]
    path_x = path[i][0]
    path_y = path[i][1]
    target_x = cylinder_target_data[0][0]
    target_y = cylinder_target_data[0][1]  
    Scalar_Product_1 = (path_x - robot_x)*(target_x - robot_x) + (path_y - robot_y)*(target_y - robot_y)
    Scalar_Product_2 = (target_x - path_x)*(robot_x - path_x) + (target_y - path_y)*(robot_y - path_y)
    if Scalar_Product_1 >= 0 and Scalar_Product_2 > 0:
        print("Before that I am the fourth situation")
        the_first_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
    #点乘是钝角
    elif Scalar_Product_1 < 0 and Scalar_Product_2 > 0:
        print("Before that I am the fourth situation")
        the_second_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
        
    elif Scalar_Product_2 == 0:
        print("Before that I am the fourth situation")
        the_third_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
    else:
        print("Before that I am the fourth situation")
        the_fourth_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)

    
    
for i in range(len(path)):
    print("robot go to the",i+1,"point")
    cylinder_target_data = p.getBasePositionAndOrientation(cylinder_target_Id)
    cylinder_robot_data = p.getBasePositionAndOrientation(cylinder_robot_Id)
    robot_x = cylinder_robot_data[0][0]
    robot_y = cylinder_robot_data[0][1]
    path_x = path[i][0]
    path_y = path[i][1]
    target_x = cylinder_target_data[0][0]
    target_y = cylinder_target_data[0][1]
    Scalar_Product_1 = (path_x - robot_x)*(target_x - robot_x) + (path_y - robot_y)*(target_y - robot_y)#向量的点乘
    Scalar_Product_2 = (target_x - path_x)*(robot_x - path_x) + (target_y - path_y)*(robot_y - path_y)
    print("*********************************************")
    #点乘是锐角或者直角
    if Scalar_Product_1 >= 0 and Scalar_Product_2 > 0:
        the_first_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
    #点乘是钝角
    elif Scalar_Product_1 < 0 and Scalar_Product_2 > 0:
        the_second_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
        
    elif Scalar_Product_2 == 0:
        the_third_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
    else:
        the_fourth_situation(cylinder_target_Id,cylinder_robot_Id,robot_x,robot_y,path_x,path_y,target_x,target_y)
        
p.disconnect()     
       

3. 效果展示

视频演示(Bilibili)
视频演示(YouTube)

移动效果图

4. 总结

像完成一个大项目先要从小项目开始慢慢学习,别看项目虽小,但是五脏俱全,这是为后续做铺垫。这个项目是为了更好的熟悉pybullet而存在。后续学习内容我一会慢慢逐一完成发布到博客里,希望大家共同进步,有问题想要讨论的尽管发在评论区。由于我是初学者,可能有好多问题我也不会,到时候大家一起讨论,共同进步!!!

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
好的,以下是建模圆柱体并让PUMA560机器人搬运的Matlab代码: ```matlab % 定义圆柱体的尺寸和位置 radius = 0.1; % 圆柱体半径 height = 0.4; % 圆柱体高度 position = [0.5, 0.5, 0.1]; % 圆柱体心位置 % 建立圆柱体模型 cylinder = collisionCylinder(radius, height); % 创建PUMA560机器人模型 robot = importrobot('examplePuma560.urdf'); robot.DataFormat = 'column'; % 初始化机器人姿态 q0 = homeConfiguration(robot); % 定义机器人末端执行器 ee = 'ee_link'; % 设置机器人碰撞检测模型 robot = setRobotCollisionModel(robot, cylinder); % 显示机器人圆柱体模型 figure show(robot, q0) hold on plotCollision(cylinder, 'FaceColor', 'red'); % 计算机器人的运动轨迹 qf = [0, pi/4, 0, pi/3, 0, pi/6]; traj = cscvn([q0, qf]); % 按照轨迹运动机器人的末端执行器 for i = 1:length(traj.breaks) q = traj.coefs(:, i); show(robot, q, 'PreservePlot', false); T = getTransform(robot, q, ee); T(1:3, 4) = position'; setTransform(cylinder, T); drawnow; end ``` 该代码首先定义圆柱体的尺寸和位置,然后使用`collisionCylinder`函数建立圆柱体模型。接着,使用`importrobot`函数导入PUMA560机器人模型,并初始化机器人姿态。然后,定义机器人末端执行器和圆柱体碰撞检测模型,并在图形窗口显示机器人圆柱体模型。 接下来,使用`cscvn`函数计算机器人的运动轨迹,并使用`getTransform`函数计算机器人末端执行器的姿态矩阵。然后,将圆柱体的位置和姿态与机器人末端执行器对应,并在每个时间步上按照轨迹运动机器人的末端执行器,同时更新圆柱体的位置和姿态,并在图形窗口显示机器人圆柱体的运动轨迹

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值