【Issac gym】关于如何在play.py里写控制命令command控制机器人运动的一点心得和教程

1.前言

比如你在Issac里训练了一个机器人行走,但是command确实已经定下来的,
image
我想用键盘操作要怎样??或者手柄呢?给个指令让机器人去追??
下面我来教大家

2.正文

2.1 pygame

开多线程即可,把命令赋给play.py里面的command
我看智元机器人X1的配置文件play.py就是这么写的,可能手柄好用,键盘就不行了。。。我分析原因觉得是窗口的调用,因为可视化的时候一部分监督窗口被issac gym占用着。
image

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
image

image

2.2.2

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

2.2.3

找到render调用的位置:
image
也就是说是在这个位置调用的该函数,实现的键盘按键的读取。
将鼠标双击gym的可视化窗口:(也就是让鼠标默认工作空间在issac窗口下即可,很简单理解的)
image
这时按下键盘的按键就可以响应:机械臂也作出了响应的动作
image

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_gymself多香啊~
下面的按键是和之前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.尾声

记到这里,有问题评论去指出!!我都会一一回答!!

posted @ 2025-03-25 19:00  泪水下的笑靥  阅读(334)  评论(0)    收藏  举报