dm_control icon indicating copy to clipboard operation
dm_control copied to clipboard

Viewer Continuous Key Callback

Open tudorjnu opened this issue 2 years ago • 1 comments

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!

tudorjnu avatar Jan 12 '23 14:01 tudorjnu

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 :)

tudorjnu avatar Jan 16 '23 14:01 tudorjnu