PyBullet开荒笔记


基于gazebo_ros的机器人开发不是很适合RL的研究,所以我看了看网上大致主流的几款机器人模拟的平台。一般来说,大家会在gym上来做RL的第一个实例,后来我查到opencv在gym的基础上,基于bullet物理引擎开发了一款机器人仿真平台:roboschool,但是我在他们的github主页上发现roboschool已经被丢弃了,失望之余,一个新的链接给了我希望,这也就是下面目前开始学习的PyBullet。


安装

首先最大的坑就是安装啦,这也是PyBullet的优点之一,不同于装到自闭,demo还跑不通的openai_ros或者其余的平台,PyBullet的安装很简单:

python3 -m pip install pybullet

我使用的平台是Ubuntu18,请根据自己平台安装pybullet。

然后PyBullet内部的一些demo需要额外下载,也就是pybullet的baselines模块,通过以下命令来下载:

git clone https://github.com/openai/baselines.git
cd baselines
pip3 install -e .

由于pybullet内部的一些开箱即用的RL算法是由tensorflow实现的,所以在运行pybullet内部现成的算法前,需要确保安装了tensorflow。


第一个demo

我们来构建第一个pybullet程序,召唤一个星球大战中的r2d2机器人:

#!/usr/bin/python3
import pybullet as p
import pybullet_data
from time import sleep

# 链接物理引擎
p.connect(p.GUI)

# 设置模型加载路径
datapath = pybullet_data.getDataPath()
p.setAdditionalSearchPath(datapath)

# 加载模型
robot_id = p.loadURDF("r2d2.urdf", [0, 0, 0.5])

# 在这停顿
sleep(1000)

out:

鼠标滚轮可以调整观察的远近,Ctrl+拖动鼠标可以调整观察位置


查看机器人信息

查看机器人的信息主要有getNumJoints()getJointInfo()两个函数。

getNumJoints()接受两个参数,其中第一个参数为机器人ID,第二个参数可选,一般不需要选,因为只有多平台开发时才用得到。该函数返回该ID机器人的关节数量。

getJointInfo()接受三个参数,其中第三个参数和上面那个函数的第二个参数一样,有关平台,可以不填,前两个参数为需要查看的机器人的ID和需要查看的该机器人的关节序号。该函数返回一个tuple,该tuple的长度为17。具体含义可看下面的代码:

可以试着打印关于机器人的信息:

#!/usr/bin/python3
import pybullet as p
import pybullet_data
from time import sleep

# 链接物理引擎
p.connect(p.GUI)

# 设置模型加载路径
datapath = pybullet_data.getDataPath()
p.setAdditionalSearchPath(datapath)

# 加载模型
robot_id = p.loadURDF("r2d2.urdf", [0, 0, 0.5])

# 输出基本信息
joint_num = p.getNumJoints(robot_id)
print("r2d2的节点数量为:", joint_num)

print("r2d2的信息:")
for joint_index in range(joint_num):
    info_tuple = p.getJointInfo(robot_id, joint_index)
    print(f"关节序号:{info_tuple[0]}\n\
            关节名称:{info_tuple[1]}\n\
            关节类型:{info_tuple[2]}\n\
            机器人第一个位置的变量索引:{info_tuple[3]}\n\
            机器人第一个速度的变量索引:{info_tuple[4]}\n\
            保留参数:{info_tuple[5]}\n\
            关节的阻尼大小:{info_tuple[6]}\n\
            关节的摩擦系数:{info_tuple[7]}\n\
            slider和revolute(hinge)类型的位移最小值:{info_tuple[8]}\n\
            slider和revolute(hinge)类型的位移最大值:{info_tuple[9]}\n\
            关节驱动的最大值:{info_tuple[10]}\n\
            关节的最大速度:{info_tuple[11]}\n\
            节点名称:{info_tuple[12]}\n\
            局部框架中的关节轴系:{info_tuple[13]}\n\
            父节点frame的关节位置:{info_tuple[14]}\n\
            父节点frame的关节方向:{info_tuple[15]}\n\
            父节点的索引,若是基座返回-1{info_tuple[16]}\n\n")

# 在这停顿
sleep(1000)

除去基本的环境连接与结束的信息外,打印信息如下:

r2d2的节点数量为: 15
r2d2的信息:
关节序号:0
            关节名称:b'base_to_right_leg'
            关节类型:4
            机器人第一个位置的变量索引:-1
            机器人第一个速度的变量索引:-1
            保留参数:0
            关节的阻尼大小:0.0
            关节的摩擦系数:0.0
            slider和revolute(hinge)类型的位移最小值:0.0
            slider和revolute(hinge)类型的位移最大值:-1.0
            关节驱动的最大值:0.0
            关节的最大速度:0.0
            节点名称:b'right_leg'
            局部框架中的关节轴系:(0.0, 0.0, 0.0)
            父节点frame的关节位置:(0.22, 0.0, 0.25)
            父节点frame的关节方向:(0.0, -0.7070904020014416, 0.0, 0.7071231599922604)
            父节点的索引,若是基座返回-1:-1


关节序号:1
            关节名称:b'right_base_joint'
            关节类型:4
            机器人第一个位置的变量索引:-1
            机器人第一个速度的变量索引:-1
            保留参数:0
            关节的阻尼大小:0.0
            关节的摩擦系数:0.0
            slider和revolute(hinge)类型的位移最小值:0.0
            slider和revolute(hinge)类型的位移最大值:-1.0
            关节驱动的最大值:0.0
            关节的最大速度:0.0
            节点名称:b'right_base'
            局部框架中的关节轴系:(0.0, 0.0, 0.0)
            父节点frame的关节位置:(0.2999999996780742, 0.0, -1.3898038463944216e-05)
            父节点frame的关节方向:(0.0, 0.7070904020014416, 0.0, 0.7071231599922604)
            父节点的索引,若是基座返回-1:0


关节序号:2
            关节名称:b'right_front_wheel_joint'
            关节类型:0
            机器人第一个位置的变量索引:7
            机器人第一个速度的变量索引:6
            保留参数:1
            关节的阻尼大小:0.0
            关节的摩擦系数:0.0
            slider和revolute(hinge)类型的位移最小值:0.0
            slider和revolute(hinge)类型的位移最大值:-1.0
            关节驱动的最大值:100.0
            关节的最大速度:100.0
            节点名称:b'right_front_wheel'
            局部框架中的关节轴系:(0.0, 0.0, 1.0)
            父节点frame的关节位置:(0.0, 0.133333333333, -0.085)
            父节点frame的关节方向:(0.0, -0.7070904020014416, 0.0, 0.7071231599922604)
            父节点的索引,若是基座返回-1:1


关节序号:3
            关节名称:b'right_back_wheel_joint'
            关节类型:0
            机器人第一个位置的变量索引:8
            机器人第一个速度的变量索引:7
            保留参数:1
            关节的阻尼大小:0.0
            关节的摩擦系数:0.0
            slider和revolute(hinge)类型的位移最小值:0.0
            slider和revolute(hinge)类型的位移最大值:-1.0
            关节驱动的最大值:100.0
            关节的最大速度:100.0
            节点名称:b'right_back_wheel'
            局部框架中的关节轴系:(0.0, 0.0, 1.0)
            父节点frame的关节位置:(0.0, -0.133333333333, -0.085)
            父节点frame的关节方向:(0.0, -0.7070904020014416, 0.0, 0.7071231599922604)
            父节点的索引,若是基座返回-1:1

......


我的知乎系列笔记

呼~,我在知乎上写了不少了,贴在这儿吧:

PyBullet笔记(一)pybullet及其依赖项的安装、pybullet初探

PyBullet笔记(二)从hello world开始的杂谈(引擎连接,URDF模型加载,查看信息)

PyBullet笔记(三)createMultiBody创建带有碰撞箱性质的模型对象

PyBullet笔记(四)机器人控制,相机追踪与状态记录

PyBullet笔记(五)碰撞检测与模拟激光探测

PyBullet笔记(六)Debug模块与GUI的正确食用姿势

PyBullet笔记(七)获取键盘事件和鼠标事件

PyBullet笔记(八)强化学习环境的引入与训练

  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 你可以使用 SQL 的 CASE-WHEN 语句来替换地块类别。下面是一个例子: ``` UPDATE table_name SET dklb = CASE WHEN dklb = 10 THEN '承包地块' WHEN dklb = 21 THEN '自留地' WHEN dklb = 22 THEN '机动地' WHEN dklb = 23 THEN '开荒地' WHEN dklb = 99 THEN '其他集体土地' ELSE dklb END ``` 这句话就是说更新表中所有dklb字段中等于10 的为承包地块,等于21的为自留地,等于22的为机动地,等于23的为开荒地,等于99的为其他集体土地,其他的保持不变。 当然,还可以在查询中使用CASE-WHEN,来达到替换字段值相同的目的,如下 ``` SELECT dklb, CASE WHEN dklb = 10 THEN '承包地块' WHEN dklb = 21 THEN '自留地' WHEN dklb = 22 THEN '机动地' WHEN dklb = 23 THEN '开荒地' WHEN dklb = 99 THEN '其他集体土地' ELSE '其他' END AS dklb_name FROM table_name; ``` 如上,就是选取表中的dklb字段和替换后的dklb_name,其中dklb_name是用原来的dklb字段来替换达到相同的目的,在这里是只是展示目的,并没有对原始数据进行修改 ### 回答2: 可以使用SQL的CASE WHEN语句来替换地块类别字段dklb的值。根据题目描述,我们需要将字段dklb的值替换为相应的地块类别。 假设表名为land,可以使用以下SQL语句来实现替换操作: ``` UPDATE land SET dklb = CASE WHEN dklb = 10 THEN '承包地块' WHEN dklb = 21 THEN '自留地' WHEN dklb = 22 THEN '机动地' WHEN dklb = 23 THEN '开荒地' WHEN dklb = 99 THEN '其他集体土地' ELSE '未知类别' END; ``` 上述语句中,CASE WHEN语句会根据字段dklb的值进行判断,当满足条件时,将对应的地块类别字符串赋值给dklb字段。如果字段值不在给定的条件范围内,则会被替换为'未知类别'。 执行以上SQL语句后,字段dklb的值将被替换成相应的地块类别,实现了对地块类别的替换操作。 ### 回答3: 可以使用SQL的CASE WHEN语句来替换地块类别字段。 CASE WHEN语句的语法如下: CASE WHEN condition1 THEN result1 WHEN condition2 THEN result2 ... ELSE result END 根据题目要求,我们可以使用如下的CASE WHEN语句来替换地块类别字段‘dklb’: SELECT CASE WHEN dklb = 10 THEN '承包地块' WHEN dklb = 21 THEN '自留地' WHEN dklb = 22 THEN '机动地' WHEN dklb = 23 THEN '开荒地' WHEN dklb = 99 THEN '其他集体土地' ELSE '未知' END AS 地块类别 FROM my_table; 以上语句将根据‘dklb’字段的值,返回对应的地块类别。如果‘dklb’的值为10,则返回‘承包地块’,如果‘dklb’的值为21,则返回‘自留地’,以此类推。如果‘dklb’的值不在这些条件中,则返回‘未知’。 注意:将my_table替换为实际的表名。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值