(译自PyBullet官方英文文档 )
控制一个机器人
在第一章的内容里面我们已经介绍了如何初始化PyBullet环境并载入一些对象。我们以ROS教程里面的"r2d2.urdf"为例介绍如何控制R2D2机器人移动,查看环境和控制末端操作器。当然首先我们需要知道驱动关节电机。
基座,关节和节点(实际上就是零件(个体/对象),感觉节点会好听一点)
一般来说,使用URDF文件描述的机器人至少会有一个基座,还可以有一些使用关节连接的节点。每个关节连接一个父节点和一个子节点。整个装配体的根节点(最开始的那个父节点)一般称作基座。基座可以是完全固定的,也可以有任意个自由度。由于这里每个节点都是通过一个关节连接到父节点的,因此实际上关节数量等同于节点的数量(不计基座在内)。每个节点都有一个节点索引(从0到getNumJoints())。基座我们一般用-1表示零件索引。跟其他很多程序差不多,这里的关节的表示是相对于父节点的质心表示的,参考系是惯性系。
在PyBullet中由getJointInfo()
函数用于获取关节信息,实际上y已经包含了节点的信息,因此其实没有getLinkInfo()
这样的函数,节点的索引与关节的索引完全一致,可以通过getJointInfo()
函数得到节点的名称和对应的索引
getNumJoints
加载了机器人之后可以通过getNumJoints
API接口获取关节的数量信息。r2d2.urdf文件会返回15。
getNumJoints
包含以下输入参数:
required
bodyUniqueId
int
机器人的唯一ID,就是使用loadURDF...
时返回的数值
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就需要仿真平台的ID了
getJointInfo
对于每一个关节都可以查询其详细信息,包括关节的名字和类型
getJointInfo
输入的参数如下:
required
bodyUniqueId
int
机器人的唯一ID,就是使用loadURDF...
时返回的数值
required
jointIndex
int
范围在[0,getNumJoints(bodyUniqueId)]
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就需要仿真平台的ID了
getJointInfo
返回如下信息
jointIndex
int
和上面的输入参数一致
jointName
string
关节名称,在URDF或者SDF等文件里面指定
jointType
int
关节的类型,也表示了位置和速度变量的数目。包括JOINT_REVOLUTE, JOINT_PRISMATIC, JOINT_SPHERICAL, JOINT_PLANAR, JOINT_FIXED,更多可以参考Base, Joint, and Links 的部分
qIndex
int
机器人第一个位置变量索引
uIndex
int
机器人第一个速度变量索引
flags
int
保留参数
jointDamping
float
关节的阻尼大小,在URDF等文件里指定
jointFriction
float
关节的摩擦参数,在URDF等文件里指定
jointLowerLimit
float
针对slider和revolute(hinge)类型的限位:位移的最小值(负数表示了反方向)
jointUpperLimit
float
针对slider和revolute(hinge)类型的限位:位移的最大值(负数表示了反方向)。如果upperlimit小于lowerlimit的话则该值将被忽略
jointMaxForce
float
关节驱动力的最大值,在URDF等文件中指定。需要指出的是该值不会自动使用?。开发人员可以在setJointMotorControl2
中添加最大的驱动力
jointMaxVelocity
float
关节的最大速度,在URDF等文件中指定。目前该值不会再实际的电机控制命令中使用
linkName
string
节点的名称,在URDF等文件中指定
jointAxis
vec3
local frame中的关节轴系(JOINT_FIXED类型的将会忽略此值)
parentFramePos
vec3
父节点frame的关节位置
parentFrameOn
vec3
父节点frame的关节方向
parentIndex
int
父节点的索引,如果是基座的话会返回-1
setJointMotorControl2/Array
老版本中的setJointMotorControl已经不再使用了,全部被setJointMotorControl2或者setJointMotorControlArray代替
通过设定控制模式我们可以控制一个机器人的多个关节。在stepSimulation
过程中PyBullet物理引擎会自动计算关节可以到达的目标位置(考虑最大驱动力和其它约束的条件下)
需要注意的是:默认情况下,revolute和prismatic类型的关节式速度控制方式。如果想改成力控制方式,可以通过设定最大力为0的方式关闭这种速度控制方式。另外还可以设定为一个小的非零力来模拟关节摩擦。举个例子:
maxForce = 0
mode = p. VELOCITY_CONTROL
p. setJointMotorControl2( objUid, JointIndex, controlMode= mode, force= maxForce)
以下给出一个轮子保持恒定转速的示例:
maxForce = 500
p. setJointMotorControl2( bodyUniqueId= objUid, jointIndex= 0 , controlMode= p. VELOCITY_CONTROL, targetVelocity= targetVel, force= maxForce)
setJointMotorControl2
的输入参数包括:
required
bodyUniqueId
int
机器人的唯一ID,就是使用loadURDF...
时返回的数值
required
jointIndex
int
节点索引范围是[0,getNumJoints(bodyUniqueId)(节点的索引实际上与关节的索引相等)]
required
controlMode
int
POSITION_CONTROL(实际上是CONTROL_MODE_POSITION_VELOCITY_PD(笔者觉得这应该是旧版本中的输入参数)), VELOCITY_CONTROL, TORQUE_CONTROL 和PD_CONTROL
optional
targetPostion
float
在POSITION_CONTROL中targetPostion是关节的期望位置
optional
targetVelocity
float
在VELOCITY_CONTROL和POSITION_CONTROL中targetVelocity是关节的期望速度,其它信息请见后面中的文档说明(implementation note)。注意:targetVelocity并不是关节的最大速度,在PD_CONTROL和POSITION_CONTROL/CONTROL_MODE_POSITION_VELOCITY_PD中,最终的目标速度通过下述公式计算:kp*(erp*(desiredPostion-currentPosition)/dt)+currentVelocity+kd*(m_desiredVelocity-currentVelocity).详见examples/pybullet/examples/pdControl.py 文件
optional
force
float
在POSITION_CONTROL和VELOCITY_CONTROL中指定了最大的关机驱动力。在TORQUE_CONTROL中制定了关节实际驱动力
optional
positionGain
float
详见文档说明
optional
velocityGain
float
详见文档说明
optional
maxVelocity
float
在POSITION_CONTROL中限制了速度的最大值
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
注意:关节电机控制器实际上就是施加位置或者速度约束(对于POSITION_CONTROL和VELOCITY_CONTROL)或者施加外力约束(对于TORQUE_CONTROL)
控制模式
实现方式
实现内容
进行最小化的约束的误差
POSITION_CONTROL
约束
速度和位置约束
error=position_gain*(desired_position-actual_position)+velocity_gain*(deired_velocity-actual_velocity)
VELOCITY_CONTROL
约束
纯速度约束
error=desired_velocity-actual_velocity
TORQUE_CONTROL
外力
一般来讲,速度或者位置控制会比力控制方便的多。对于力控制而言,在仿真中,真实的力还依赖于精确的URDF/SDF中指定的机器人参数(包括质量关节摩擦等等)和文件参数
setJointMotorControlArray
这个实际上是setJointMotorControl2
的加强版,可以用来同时控制多个关节,输入参数也与后者几乎一样,只是把单个的数值变成了列表(list)。这里就不介绍了。
getJointState(s), resetJointState
我们可以通过getJointState
获取多个关节的状态信息,比如关节的位置、速度、关节反力和关节驱动力 该API的输入参数如下:
required
bodyUniqueId
int
机器人的唯一ID,就是使用loadURDF...
时返回的数值
required
jointIndex
int
节点的索引,范围在[0,getNumJoints(bodyUniqueId)]
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
该API的输出参数如下:
jointPosition
float
关节的位置参数
jointVelocity
float
关节的速度参数
jointReactionForces
list of 6 floats
如果打开了关节力传感器,则会返回关节反力[Fx, Fy, Fz, Mx,My, Mz]。如果关节力传感器处于关闭状态,则是[0, 0, 0, 0, 0, 0]
appliedJointMotorTorque
float
最后一步stepSimulation
中关节的驱动力。在VELOCITY_CONTROL和POSITION_CONTROL中这个才有用,在TORQUE_CONTROL中其实没啥用,因为就是开发者施加的关节驱动力
getJointStates
就是getJointState
的阵列版本,可以获取多个关节的状态信息。
对于球绞关节比较特殊,使用getJointStateMultiDof
获取状态信息
resetJointState
这个API是用来重置关节状态的。一般在最开始的时候用这个函数来复位关节。目前官方没有像获取关节信息一样可以一次设置多个关节,这里一次只能设置一个关节,sliding关节或者revolute关节。输入参数如下:
required
bodyUniqueId
int
机器人的唯一ID,就是使用loadURDF...
时返回的数值
required
jointIndex
int
关节索引,范围在[0,getNumJoints(bodyUniqueId)]
required
targetValue
float
关节位置,如果是关节角度,单位是弧度
optional
targetVelocity
float
关节的(角)速度
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
对于spherical关节来说请使用 resetJointStateMultiDof
API。详见humaniodMotionCapture。
enableJointForceTorqueSensor
我们可以使用这个函数来打开或者关闭关节力/力矩传感器。打开之后,在每一步的stepSimulation
中,getJointState
会返回关节固定自由度所受到的反力(比如对于一个完全固定的关节,就会返回6个自由度方向的关节力/力矩)。关节实际的自由度方向上施加的力会存在getJointState
里面的appliedJointMotorTorque 该API的输入参数如下:
required
bodyUniqueId
int
机器人的唯一ID,就是使用loadURDF...
时返回的数值
required
jointIndex
int
关节索引,范围在[0,getNumJoints(bodyUniqueId)]
optional
enable
int
1/True:打开; 0/False:关闭;
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
getLinkState
我们可以通过getLinkState
获取每个节点的质心的笛卡尔坐标和方位。该函数还会返回质心的局部惯性系给URDF 的link frame, 以便计算graphics/visualization frame
该函数的输入参数:
required
bodyUniqueId
int
机器人的唯一ID,就是使用loadURDF...
时返回的数值
required
linkIndex
int
节点索引(不支持基座即-1的信息获取,使用第一章里面的getBasePositionAndOrientation
获取基座的信息)
optional
computeLinkVelocity
int
设置为1:计算并返回笛卡尔坐标系下的速度值
optional
computeForwardKinematics
int
设置为1/True:使用正运动学重新计算笛卡尔坐标系下的坐标和方位?
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
该函数返回以下参数:
linkWorldPosition
vec3, list of 3 floats
节点质心的笛卡尔坐标
linkWorldOrientation
vec3, list of 4 floats
质心的方向,以[x,y,z,w]四元数的形式返回
localInertialFramePosition
vec3, list of 3 floats
URDF link frame中传递的质心惯性系的局部坐标偏移量
localInertialFrameOrientation
vec3, list of 4 floats
URDF link frame中传递的质心惯性系的局部方向偏移量
worldLinkFramePosition
vec3, list of 3 floats
URDF link frame中的世界坐标系中的位置
worldLinkFrameOrientation
vec3, list of 4 floats
URDF link frame中的世界坐标系中的方向
worldLinkLinearVelocity
vec3, list of 3 floats
笛卡尔坐标系下的速度。只有在输入参数computeLinkVelocity
非0时会生效
worldLinkAngularVelocity
vec3, list of 3 floats
笛卡尔坐标系下的角速度。只有在输入参数computeLinkVelocity
非0时会生效
URDF link frame和质心框架的关系如下图所示。urdfLinkFrame=comLinkFrame*localInertialFrame.inverse().详见ROS的URDF教程
官方源程序的Bullet/examples/pybullet/examples文件夹下提供了多种API的应用示例
getBaseVelocity, resetBaseVelocity
该API函数提供了获取基座的线速度和角速度的功能。 输入参数如下:
required
bodyUniqueId
int
机器人的唯一ID,就是使用loadURDF...
时返回的数值
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
返回值是两个三维向量的列表,包括笛卡尔空间坐标系下的线速度[x,y,z]和角速度[wx,wy,wz]
resetBaseVelocity
提供了复位基座线速度/角速度的功能 输入参数如下:
required
bodyUniqueId
int
机器人的唯一ID,就是使用loadURDF...
时返回的数值
optional
linearVelocity
vec3, list of 3 floats
笛卡尔空间坐标系下的线速度[x,y,z]
optional
angularVelocity
vec3, list of 3 floats
笛卡尔空间坐标系下的角速度[wx,wy,wz]
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
applyExternalForce/Torque
该函数提供了给机器人施加外力的功能。需要注意的是,这个只在单步仿真中才会起作用(也就是使用stepSimulation
函数进行单步仿真,另外设置setRealTimeSimulation(0))。在单步的仿真后,外力都会清零。当设置setRealTimeSimulation(1)的时候,这个函数会起一些奇怪的作用(比如施加0,1或者多次力)
输入参数为:
required
bodyUniqueId
int
机器人的唯一ID,就是使用loadURDF...
时返回的数值
required
linkIndex
int
基座的节点索引为-1
required
forceObj
vec3, list of 3 floats
要施加的外力[x,y,z]。详见坐标系统(coordinate system)中的标志(flags)
required
posObj
vec3, list of 3 floats
要施加的外力的位置。只用于applyExternalForce
函数。详见坐标系统(coordinate system)中的标志(flags)
required
flags
int
确定上述力和位置的坐标系统(也就是参考坐标系):笛卡尔坐标系下的WORLD_FRAME或者局部坐标系下的LINK_FRAME
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
getNumBodies, getBodyInfo, getBodyUniqueId, removeBody
getNumBodies
会返回当前服务器个体的数目,然后还可以使用getBodyUniqueId
查询个体的唯一ID。提醒:这些API都会返回个体的唯一ID,所以在这种情况下,其实并不需要使用getBodyUniqueId
getBodyInfo
: 返回基座的名称(在URDF等文件中指定)
removeBody
: 根据个体的唯一ID移除某个个体
createConstraint, removeConstraint
实际上,URDF等文件中以树状结构确立了一种铰接式的个体(不能形成环路的那种)。createConstraint
可以帮助我们连接一些特定的节点,形成环路,跟实际的物理物体更加相符。Bullet/examples/pybullet/examples/quadruped.py文件中提供了一种连接四足动物五连杆的腿的示例。另外,还可以在物体之间、物体与某一坐标系之间添加任意约束。Bullet/examples/pybullet/examples/constraint.py提供了一些更多的应用。它还可以用来控制物体的运动,通过动画框架来驱动,比如VR控制器。实际上因为这里的约束可以放在其它动力学约束里面一起求解,所以使用这种办法比单纯的添加位置和速度限制更好一点。
输入参数如下:
required
parentBodyUniqueId
int
参考个体(父个体?)的唯一ID
required
parentLinkIndex
int
父节点的索引,基座为-1
required
childBodyUniqueId
int
目标个体(子个体?)的唯一ID,如果没有的话用输入为-1(specify a non-dynamic child frame in world coordinates)
required
childLinkIndex
int
子节点的索引,-1表示基座
required
jointType
int
关节类型:JOINT_PRISMATIC, JOINT_FIXED, JOINT_POINT2POINT, JOINT_GEAR(这里面应该指定两个个体之间的约束类型)
required
jointAxis
vec3, list of 3 floats
子节点的关节轴系
required
parentFramePosition
vec3, list of 3 floats
关节框架相对于参考个体质心框架的位置
required
childFramePosition
vec3, list of 3 floats
关节框架相对于给定的目标个体质心框架的位置(如果没有指定目标个体则为世界原点)
optional
parentFrameOrientation
vec4, list of 4 floats
关节框架相对于参考个体质心坐标系的方向
optional
childFrameOrientation
vec4, list of 4 floats
关节框架相对于目标个体质心坐标系的方向(如果没有指定目标个体,则为世界原点)
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
该函数会返回一个integer类型的ID,可以用于移除添加的约束。examples/pybullet/examples/mimicJointConstraint.py给出了一个JOINT_GEAR的示例, examples/pybullet/examples/minitaur.py——JOINT_POINT2POINT, examples/pybullet/examples/constraint.py——JOINT_FIXED.
changeConstraint
该函数允许修改已经添加的约束 输入的参数如下:
required
userConstraintUniqueId
int
也就是createContraint
函数的返回值
optional
jointChildPivot
vec3, list of 3 floats
用于更新目标个体的轴系(应该是createConstraint
里面的*jointAxis)
optional
jointChildFrameOrientation
vec4, list of 4 floats
更新目标个体的框架方向,四元数的形式
optional
maxForce
float
约束可以施加的最大力
optional
gearRadio
float
一对旋转齿轮的传动比
optional
gearAuxLink
int
有些情况下,比如差分传动,会用到一个辅助节点作为参考姿势。详见racecar differential.py
optional
relativePositionTarget
float
一对齿轮的相对位置目标偏移量
optional
erp
float
约束误差减小参数?
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
关于该API的更多信息详见Bullet/examples/pybullet/examples/constraint.py
removeConstraint
函数提供了根据ID移除约束的功能,输入参数为:
required
userConstraintUniqueId
int
函数createConstraint
返回的约束的ID
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
getNumConstraint, getConstraintUniqueId
用于查询添加的约束的数量和ID,注意可能返回来的ID并不连续,因为可能开发人员中间会移除某些约束
getConstraintInfo/State
我们可以通过约束的ID查询约束的相关信息。 输入参数为:
required
constraintUniqueId
int
函数createConstraint
返回的约束的ID
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
返回参数为:
parentBodyUniqueId
int
parentJointIndex
int
childBodyUniqueId
int
childLinkIndex
int
constraintType
int
jointAxis
int
jointPivotInParent
int
jointPivotInChild
int
jointFrameOrientationParent
int
jointFrameOrientationChild
int
maxAppliedForce
int
关于这些参数的详细说明参见createConstraint
部分内容
getConstraintState
通过约束的唯一ID可以查询最近仿真步中的施加的约束力。输入参数只有约束的ID,输出是约束力组成的向量,维数与约束所限制的的自由度数目相等(比如一个完全固定的约束对应的数量为6)
getDynamicsInfo/changeDynamics
我们可以通过这个API获取基座和节点的一些动力学相关的参数:比如质量,质心位置,摩擦参数等等 输入参数为:
required
bodyUniqueId
int
机器人的唯一ID,就是使用loadURDF...
时返回的数值
required
linkIndex
int
节点或者关节的索引,基座的索引为-1
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
返回的参数为:
mass
double
质量为kg
lateral_friction
double
摩擦系数
local inertial diagnoal
vec3, list of 3 floats
局部惯性对角线?注意:节点和基座以质心为中心,并于惯性主轴对齐
local inertial pos
vec3
关节框架的局部坐标系下的惯性框架位置
local inertial orn
vec4
关节框架的局部坐标系下的惯性框架的方向
restitution
double
恢复系数
rolling friction
double
滚动摩擦系数
spining friction
double
滑动摩擦系数
contact damping
double
阻尼系数,-1表示没有此项
contact stiffness
double
刚度系数,-1表示没有此项
changeDynamics
这个API用于改变个体的物理性质包括质量、摩擦等等
输入参数包括:
required
bodyUniqueId
int
机器人的唯一ID,就是使用loadURDF...
时返回的数值
required
linkIndex
int
-1表示基座
optional
mass
double
改变节点的质量
optional
lateralFriction
double
横向接触摩擦
optional
spiningFriction
double
滑动摩擦
optional
rollingFriction
double
滚动摩擦
optional
restitution
double
恢复系数,小于1
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
optional
linearDamping
double
节点的滑动阻尼(默认是0.04)
optional
angularDamping
double
节点的转动阻尼(默认是0.04)
optional
contactStiffness
double
接触约束的刚度系数,一般和contactDamping一起使用
optional
contactDamping
double
接触约束的接触阻尼。若设定此值会覆写URDF文件contact 部分中设定的值
optional
frictionAnchor
int
打开或关闭friction anchor:位置摩擦矫正?(默认关闭,除非在URDFcontact 部分中设定打开)
optional
localInertialDiagnoal
vec3
惯性张量的对角线元素。注意:由于基座和节点以质心为中心并与惯性主轴对齐,因此其惯性张量中没有非对角线元素
optional
jointDamping
double
每个关节的阻尼系数,在URDF文件中已经设定好了这个参数。一般这个参数非常接近于0。joint damping force = -damping_coefficient*joint_velocity
setTimeStep
注意:默认值为240Hz,大部分情况下不要动这个参数,因为实际上仿真器中有一些参数是根据这个参数调整的(牵一发而动全身)。一旦改了这个,其它参数也需要进行相应修改,比如求解器迭代的次数、接触误差减小参数(erp),摩擦和非接触关节等等
我们可以使用这个API设定物理仿真的单步时间(单步的物理仿真通过stepSimulation
函数实现)。一般由于上述原因尽可能不要使用这个函数,但如果要用的话也要在仿真最开始的时候用,在仿真进行的时候不要轻易使用这个函数。另外setPhysicsEngineParameter
函数也可以设定单步仿真的时间。
该函数的输入参数为:
required
timeStep
float
每一次调用stepSimulation
的时候都会调用这个参数
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
setPhysicsEngineParameter
这个函数可以用来设定物理引擎的一些参数,包括如下输入参数:
optional
fixedTimeStep
float
与setTimeStep
的功能一样,不要轻易修改这个参数
optional
numSolverIterations
int
选择约束求解器迭代的最大次数。不过如果先达到solverResidualThreshold,求解器会在达到numSolverIterations之前就终止计算
optional
useSplitImpulse
int
仅当使用最大的坐标系时:将位置约束求解和速度约束求解分成两个独立的求解过程,以防止巨大的恢复力矩
optional
splitImpulsePenetrationThreshold
float
与上个参数useSplitImpulse相关:如果特定的接触约束穿透值没有达到这个设定阈值,则此接触不会进行分割计算
optional
numSubSteps
int
奖物理引擎仿真的单步进一步划分成numSubSteps个子步,这个参数允许开发者在精确度和性能之间权衡
optional
collisionFilterMode
int
默认的碰撞过滤值为0,表示:(groupA&maskB)AND(groupB&maskA).该值为1时则切换到OR碰撞过滤器:(groupA&maskB) OR (groupB&maskA)
optional
contactBreakingThreshold
float
超过此距离阈值的接触点将不会被LCP求解器触力。另外,这个值还扩展了AABBs(?)。在Bullet2.x版本中这个值是0.02
optional
maxNumCmdPer1ms
int
目前还在测试的参数:如果执行的命令的数目超过了这个阈值,则添加1ms的睡眠(笔者认为应该是考虑到实际机器人的嵌入式设备的实时计算时间)
optional
enableFileCaching
int
该值为0时禁用文件缓存,比如.obj波前文件加载(?)
optional
restitutionVelocityThreshold
float
如果相对速度低于这个阈值,则恢复将被设置为0
optional
rep
float
约束误差减小参数(无摩擦、无接触)
optional
contactERP
float
接触误差减小参数
optional
frictionERP
float
摩擦误差减小参数(仅当位置摩擦角功能被打开时有效)
optional
enableConeFriction
int
该值为0时:禁用隐式锥体摩擦,使用金字塔式进行近似(默认椎体摩擦有效)
optional
deterministicOverlappingPairs
int
该值为1为启用。为0时为禁用:禁用重叠对的排序(向后兼容性设置)(?)
optional
solveResidualThreshold
double
速度阈值,如果哪个约束的最大速度误差低于该阈值,则求解器会终止求解(除非求解器碰到numSolverIteration)。默认值是1e-7
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
setDefaultContactERP
函数用来设置默认的接触参数设置,该函数会加入到setPhysicsEngineParameter
函数中
getPhysicsEngineParameters
我们可以使用这个函数查询当前物理引擎的一些参数,输入是physicsClientID
参数。该函数返回一些带有名称的参数
resetSimulation
该函数会移除当前环境中的所有对象并复位当前环境。该函数有一个optional 的输入:the physics client Id。在有多个仿真平台时,可以通过这个参数指定需要复位的平台
startStateLogging/stopStateLogging
我们可以通过状态记录的功能来记录仿真的一些状态,包括不同对象在每一步仿真后的状态。我们可以通过这种方式记录对象的运动轨迹。我们还可以选择是否记录每个对象中的基座、关节的信息比如位置、力等等
所有产生的日志文件都可以被C++或者Python脚本。关于python的使用方法详见quadruped_playback.py和kuka_with_cube_playback.py文件,关于C++的使用方法可以使用bullet3/examples/Utils/RobotLoggingUtil.cpp/h来读入日志文件
我们还能通过STATE_LOGGING_VIDEO_MP4选项来录制MP4格式的视频。以后还将支持其它状态的记录,包括VR控制器的状态
我们做了一个minitaur机器人记录的示例,Pybullet仿真的日志文件和真正的Minitaur四足机器人的日志文件相同。详见Bullet/examples/pybullet/examples/logMinitaur.py for an example. ==注意:==不同的日志记录器有着自己的记录时间(开始的时候设置为0)。所以我们最好同时开启所有记录器以保持同步,并且最好在开启实时仿真之前启用记录器 该函数有以下输入参数:
required
loggingType
int
该参数有多个值可供选择:1.STATE_LOGGING_MINITAUR: (官方做的特例),该值主要在载入使用quadruped/quadruped.urdf模型的时候使用(对象ID是该四足机器人的ID)。该值能记录下时间戳、IMU的三个角度、8个腿电机的位置、8个腿电机的转矩和躯干的前进速度以及模式(仿真中未使用) 2.STATE_LOGGING_GENERIC_ROBOT:此值会记录所有的或者指定的(如果给定了objectUniqueID的话)机器人的状态数据 3.STATE_LOGGING_VIDEO_MP4: 此值会创建一个MP4文件,并记录OPenGL_3D视觉像素流。该值使用ffmpeg管道方法,因此需要安装好ffmpeg。我们也可以使用Ubuntu中默认的avconv来创建一个符号连接以便ffmpeg指向avconv。windows平台在某些情况下会出现一些导致撕裂/颜色瑕疵的问题。 4.STATE_LOGGING_CONTACT_POINTS 5.STATE_LOGGING_VR_CONTROLLERS 6.STATE_LOGGING_PROFILE_TIMINGS: 该值可以转储JSON格式的计时文件,该文件可以使用google Chrome打开://tracing LOAD
required
fileName
string
用于存储数据的文件名称(含路径,绝对或者相对路径)
optional
objectUniqueIds
list of int
指定了需要记录状态的对象,如果为空,则记录所有的对象
optional
maxLogDof
int
可以记录的机器人的关节自由度的最大数目(除了基座的自由度)。仅对第一个参数的STATE_LOGGING_GENERIC_ROBOT_DATA参数有效。默认值是12。如果机器人超过了这个阈值,则该机器人的状态将不会被记录
optional
bodyUniqueIdA
int
仅对STATE_LOGGING_CONTACT_POINTS有效。如果提供了A的ID,则只会记录涉及到对象A的接触点
optional
bodyUniqueIdB
int
仅对STATE_LOGGING_CONTACT_POINTS有效。如果提供了B的ID,则只会记录涉及到对象B的接触点
optional
linkIndexA
int
仅对STATE_LOGGING_CONTACT_POINTS有效。如果提供了该ID,则对于只会记录涉及到对象A中索引为A的节点的接触点
optional
linkIndexA
int
仅对STATE_LOGGING_CONTACT_POINTS有效。如果提供了该ID,则对于只会记录涉及到对象A中索引为B的节点的接触点
optional
deviceTypeFilter
int
我们可以使用该值记录所需要记录的VR设备的状态。可以使用VR_DEVICE_CONTROLLER, VR_DEVICE_HMD ,VR_DEVICE_GENERIC_TRACKER的任意参数或者参数组合,仅对STATE_LOGGING_VR_CONTROLLERS有效。默认值是VR_DEVICE_CONTROLLER
optional
logFlags
int
(Pybullet1.3.1中新增选项)。该值可以为STATE_LOG_JOINT_TORQUES用于记录关节电机产生的关节转矩
optional
physicsClientId
int
有些模式下可以建立多个仿真平台,就可以选择某一个仿真平台的ID了
该命令正常情况下会返回一个非负值,可以用于停止状态记录。
Todo: 记下为每种日志记录类型记录的数据(有点绕口)。目前只能使用日志查看工具来查找,详见 C++ source code of the logging 或者 Python dumpLog.py 脚本
stopStateLogging
该函数可以用来停止日志记录程序。输入是startStateLogging
的返回值(即loggingUniqueId)。
submitProfileTiming
PyBullet和Bullet测试过很多种功能,目前我们可以看到时间都花在哪些地方。我们可以转储这些时间到一个文件里面然后用Google Chrome来看://tracing window using the LOAD feature。在GUI界面中,我们可以使用’p’命令来开始或者停止文件转储,以便于有些时候我们希望计量某些时间。我们还能使用Pybulet提交一些定时存下来的文件