【Issac gym】关于如何在play.py里写控制命令command控制机器人运动的一点心得和教程
1.前言
比如你在Issac里训练了一个机器人行走,但是command确实已经定下来的,

我想用键盘操作要怎样??或者手柄呢?给个指令让机器人去追??
下面我来教大家
2.正文
2.1 pygame
开多线程即可,把命令赋给play.py里面的command
我看智元机器人X1的配置文件play.py就是这么写的,可能手柄好用,键盘就不行了。。。我分析原因觉得是窗口的调用,因为可视化的时候一部分监督窗口被issac gym占用着。

2.2 render()
2.2.1
修改base_task.py的__init__,在初始化里加上这些gym初始化按键订阅,相当于函数的预先声明一样,写下你想使用的键盘按键,比如上KEY_UP等,其他见官方文档:
https://junxnone.github.io/isaacgymdocs/api/python/enum_py.html?highlight=key_up


2.2.2
修改render函数:该函数是通过event的action检测查询到用户按键,在每个下面if else修改即可,修改每一个按键对应的功能:

2.2.3
找到render调用的位置:

也就是说是在这个位置调用的该函数,实现的键盘按键的读取。
将鼠标双击gym的可视化窗口:(也就是让鼠标默认工作空间在issac窗口下即可,很简单理解的)

这时按下键盘的按键就可以响应:机械臂也作出了响应的动作

2.3 代码
方便一些懒鬼的直接复制,这里给出所有代码:
2.3.1 pygame
import pygame
from threading import Thread
x_vel_cmd, y_vel_cmd, yaw_vel_cmd = 0.0, 0.0, 0.0
joystick_use = True
joystick_opened = False
if joystick_use:
pygame.init()
try:
# get joystick
joystick = pygame.joystick.Joystick(0)
joystick.init()
joystick_opened = True
except Exception as e:
print(f"无法打开手柄:{e}")
# joystick thread exit flag
exit_flag = False
def handle_joystick_input():
global exit_flag, x_vel_cmd, y_vel_cmd, yaw_vel_cmd, head_vel_cmd
while not exit_flag:
# get joystick input
pygame.event.get()
# update robot command
x_vel_cmd = -joystick.get_axis(1) * 1
y_vel_cmd = -joystick.get_axis(0) * 1
yaw_vel_cmd = -joystick.get_axis(3) * 1
pygame.time.delay(100)
if joystick_opened and joystick_use:
joystick_thread = Thread(target=handle_joystick_input)
joystick_thread.start()
2.3.2 render()
base_task.py --> init():
# zsy add 订阅机械臂控制的键盘响应
self.gym.subscribe_viewer_keyboard_event(self.viewer, gymapi.KEY_A, "A")
self.gym.subscribe_viewer_keyboard_event(self.viewer, gymapi.KEY_D, "D")
self.gym.subscribe_viewer_keyboard_event(self.viewer, gymapi.KEY_W, "W")
self.gym.subscribe_viewer_keyboard_event(self.viewer, gymapi.KEY_S, "S")
self.gym.subscribe_viewer_keyboard_event(self.viewer, gymapi.KEY_R, "R")
base_task.py --> self.render()函数
当然,这个函数定义在legged_robot.py里面也未尝不可,而且便于操作键盘改编后的值,直接在legged_gym里self多香啊~
下面的按键是和之前base_task.py初始化的按键一样
# zsy 根据键盘输入操作机械臂关节:
def render_keyboard_ui(self, sync_frame_time=True):
if self.viewer:
# check for window closed
if self.gym.query_viewer_has_closed(self.viewer):
sys.exit()
# check for keyboard events
for evt in self.gym.query_viewer_action_events(self.viewer):
if evt.action == "QUIT" and evt.value > 0:
sys.exit()
# ==== 上一个关节 ====
elif evt.action == "A" and evt.value > 0:
self.dof_pos_count -= 1
if self.dof_pos_count <0: self.dof_pos_count = 0 #限制关节索引范围
elif self.dof_pos_count >5: self.dof_pos_count = 5
print(f"当前关节:{self.dof_pos_count}, 当前关节角度:{self.ref_buff[0,self.dof_pos_count]}")
# ==== 下一个关节 ====
elif evt.action == "D" and evt.value > 0:
self.dof_pos_count += 1
if self.dof_pos_count <0: self.dof_pos_count = 0
elif self.dof_pos_count >5: self.dof_pos_count = 5
print(f"当前关节:{self.dof_pos_count}, 当前关节角度:{self.ref_buff[0,self.dof_pos_count]}")
# ==== 增加关节角度 ====
elif evt.action == "W" and evt.value > 0:
self.ref_buff[:,self.dof_pos_count] += self.dof_pos_delta
print(f"当前关节:{self.dof_pos_count}, 当前关节角度:{self.ref_buff[0,self.dof_pos_count]}")
# ==== 减少关节角度 ====
elif evt.action == "S" and evt.value > 0:
self.ref_buff[:,self.dof_pos_count] -= self.dof_pos_delta
print(f"当前关节:{self.dof_pos_count}, 当前关节角度:{self.ref_buff[0,self.dof_pos_count]}")
# 回到初始default状态
elif evt.action == "R" and evt.value > 0:
self.ref_buff = self.default_dof_pos[:,:6]
# fetch results
if self.device != 'cpu':
self.gym.fetch_results(self.sim, True)
# step graphics
if self.enable_viewer_sync:
self.gym.step_graphics(self.sim)
self.gym.draw_viewer(self.viewer, self.sim, True)
if sync_frame_time:
self.gym.sync_frame_time(self.sim)
else:
self.gym.poll_viewer_events(self.viewer)
FAQ
Q:有一些bug,就是不响应按键了,我的issac在reset之后就这样了,怎么按都没反应????
A:有可能是按键按的太快了,导致无响应了。。。。我也没找到合理的解决方案。。。(汗
3.尾声
记到这里,有问题评论去指出!!我都会一一回答!!

浙公网安备 33010602011771号