Source code for isaaclab.devices.keyboard.se2_keyboard
# Copyright (c) 2022-2025, The Isaac Lab Project Developers.# All rights reserved.## SPDX-License-Identifier: BSD-3-Clause"""Keyboard controller for SE(2) control."""importnumpyasnpimportweakreffromcollections.abcimportCallableimportcarbimportomnifrom..device_baseimportDeviceBase
[docs]classSe2Keyboard(DeviceBase):r"""A keyboard controller for sending SE(2) commands as velocity commands. This class is designed to provide a keyboard controller for mobile base (such as quadrupeds). It uses the Omniverse keyboard interface to listen to keyboard events and map them to robot's task-space commands. The command comprises of the base linear and angular velocity: :math:`(v_x, v_y, \omega_z)`. Key bindings: ====================== ========================= ======================== Command Key (+ve axis) Key (-ve axis) ====================== ========================= ======================== Move along x-axis Numpad 8 / Arrow Up Numpad 2 / Arrow Down Move along y-axis Numpad 4 / Arrow Right Numpad 6 / Arrow Left Rotate along z-axis Numpad 7 / Z Numpad 9 / X ====================== ========================= ======================== .. seealso:: The official documentation for the keyboard interface: `Carb Keyboard Interface <https://docs.omniverse.nvidia.com/dev-guide/latest/programmer_ref/input-devices/keyboard.html>`__. """
[docs]def__init__(self,v_x_sensitivity:float=0.8,v_y_sensitivity:float=0.4,omega_z_sensitivity:float=1.0):"""Initialize the keyboard layer. Args: v_x_sensitivity: Magnitude of linear velocity along x-direction scaling. Defaults to 0.8. v_y_sensitivity: Magnitude of linear velocity along y-direction scaling. Defaults to 0.4. omega_z_sensitivity: Magnitude of angular velocity along z-direction scaling. Defaults to 1.0. """# store inputsself.v_x_sensitivity=v_x_sensitivityself.v_y_sensitivity=v_y_sensitivityself.omega_z_sensitivity=omega_z_sensitivity# acquire omniverse interfacesself._appwindow=omni.appwindow.get_default_app_window()self._input=carb.input.acquire_input_interface()self._keyboard=self._appwindow.get_keyboard()# note: Use weakref on callbacks to ensure that this object can be deleted when its destructor is calledself._keyboard_sub=self._input.subscribe_to_keyboard_events(self._keyboard,lambdaevent,*args,obj=weakref.proxy(self):obj._on_keyboard_event(event,*args),)# bindings for keyboard to commandself._create_key_bindings()# command buffersself._base_command=np.zeros(3)# dictionary for additional callbacksself._additional_callbacks=dict()
def__del__(self):"""Release the keyboard interface."""self._input.unsubscribe_from_keyboard_events(self._keyboard,self._keyboard_sub)self._keyboard_sub=Nonedef__str__(self)->str:"""Returns: A string containing the information of joystick."""msg=f"Keyboard Controller for SE(2): {self.__class__.__name__}\n"msg+=f"\tKeyboard name: {self._input.get_keyboard_name(self._keyboard)}\n"msg+="\t----------------------------------------------\n"msg+="\tReset all commands: L\n"msg+="\tMove forward (along x-axis): Numpad 8 / Arrow Up\n"msg+="\tMove backward (along x-axis): Numpad 2 / Arrow Down\n"msg+="\tMove right (along y-axis): Numpad 4 / Arrow Right\n"msg+="\tMove left (along y-axis): Numpad 6 / Arrow Left\n"msg+="\tYaw positively (along z-axis): Numpad 7 / Z\n"msg+="\tYaw negatively (along z-axis): Numpad 9 / X"returnmsg""" Operations """
[docs]defadd_callback(self,key:str,func:Callable):"""Add additional functions to bind keyboard. A list of available keys are present in the `carb documentation <https://docs.omniverse.nvidia.com/dev-guide/latest/programmer_ref/input-devices/keyboard.html>`__. Args: key: The keyboard button to check against. func: The function to call when key is pressed. The callback function should not take any arguments. """self._additional_callbacks[key]=func
[docs]defadvance(self)->np.ndarray:"""Provides the result from keyboard event state. Returns: 3D array containing the linear (x,y) and angular velocity (z). """returnself._base_command
""" Internal helpers. """def_on_keyboard_event(self,event,*args,**kwargs):"""Subscriber callback to when kit is updated. Reference: https://docs.omniverse.nvidia.com/dev-guide/latest/programmer_ref/input-devices/keyboard.html """# apply the command when pressedifevent.type==carb.input.KeyboardEventType.KEY_PRESS:ifevent.input.name=="L":self.reset()elifevent.input.nameinself._INPUT_KEY_MAPPING:self._base_command+=self._INPUT_KEY_MAPPING[event.input.name]# remove the command when un-pressedifevent.type==carb.input.KeyboardEventType.KEY_RELEASE:ifevent.input.nameinself._INPUT_KEY_MAPPING:self._base_command-=self._INPUT_KEY_MAPPING[event.input.name]# additional callbacksifevent.type==carb.input.KeyboardEventType.KEY_PRESS:ifevent.input.nameinself._additional_callbacks:self._additional_callbacks[event.input.name]()# since no error, we are fine :)returnTruedef_create_key_bindings(self):"""Creates default key binding."""self._INPUT_KEY_MAPPING={# forward command"NUMPAD_8":np.asarray([1.0,0.0,0.0])*self.v_x_sensitivity,"UP":np.asarray([1.0,0.0,0.0])*self.v_x_sensitivity,# back command"NUMPAD_2":np.asarray([-1.0,0.0,0.0])*self.v_x_sensitivity,"DOWN":np.asarray([-1.0,0.0,0.0])*self.v_x_sensitivity,# right command"NUMPAD_4":np.asarray([0.0,1.0,0.0])*self.v_y_sensitivity,"LEFT":np.asarray([0.0,1.0,0.0])*self.v_y_sensitivity,# left command"NUMPAD_6":np.asarray([0.0,-1.0,0.0])*self.v_y_sensitivity,"RIGHT":np.asarray([0.0,-1.0,0.0])*self.v_y_sensitivity,# yaw command (positive)"NUMPAD_7":np.asarray([0.0,0.0,1.0])*self.omega_z_sensitivity,"Z":np.asarray([0.0,0.0,1.0])*self.omega_z_sensitivity,# yaw command (negative)"NUMPAD_9":np.asarray([0.0,0.0,-1.0])*self.omega_z_sensitivity,"X":np.asarray([0.0,0.0,-1.0])*self.omega_z_sensitivity,}