dm_control
dm_control copied to clipboard
Viewer Continuous Key Callback
Hello,
I am trying to control the actuators with the keyboard using the viewer.launch function. In order to do this, I have created the following class:
class Application(viewer.application.Application):
def __init__(self, title, width, height):
super().__init__(title, width, height)
self._keyboard.on_key_hold += self._handle_key
self._input_map.bind(self._move_forward, viewer.user_input.KEY_UP)
self._input_map.bind(self._move_back, viewer.user_input.KEY_DOWN)
def _move_forward(self):
action = self._environment.action_spec()
action = np.zeros_like(action.shape)
action[0] = 1
self._runtime._time_step = self._runtime._env.step(action)
self._runtime._last_action = action
finished = self._runtime._time_step.last()
print("moving forward")
return finished or self._runtime._error_logger.errors_found
def _move_back(self):
action = self._environment.action_spec()
action = np.zeros_like(action.shape)
action[0] = -1
self._runtime._time_step = self._runtime._env.step(action)
self._runtime._last_action = action
finished = self._runtime._time_step.last()
print("moving backward")
return finished or self._runtime._error_logger.errors_found
This basically allows me to set the action values at each timestep given the UP or DOWN key presses. The only issue is when I am trying to continuously control the simulator such as it goes forward as I keep the UP key pressed rather than on the release.
I was looking at a way to edit the file from dm_control/viewer/user_input.py such that it can accept it but I cannot see a clear way to do it. Is there any suggestion on how to approach this?
Thank you!
I modified the InputMap class from here so that it can handle repeated actions as follows:
def _handle_key(self, key, action, modifiers):
"""Handles a single key press (mouse and keyboard)."""
alias_key = (key, modifiers)
exclusive_key, exclusive_callback = self._active_exclusive
if exclusive_key is not None:
if action == RELEASE and key == exclusive_key:
exclusive_callback(False)
self._active_exclusive = _NO_EXCLUSIVE_KEY
else:
is_exclusive, callback = self._action_callbacks.get(
alias_key, _NO_CALLBACK)
if callback:
if action == PRESS:
if is_exclusive:
callback(True)
self._active_exclusive = (key, callback)
else:
callback()
if action == REPEAT:
callback()
This seems to work but I am not sure if this can cause other issues :)