cameron5906 / OverkillFramework

A .NET Core framework for building telepresent robots with modular functionality through plugins and custom drivers. Overkill is meant to allow for the easy development of robots controllable from anywhere.
0 stars 0 forks source link

Abstraction of manual controls #11

Closed cameron5906 closed 4 years ago

cameron5906 commented 4 years ago

Currently there is a concept of a "locomotion message" that instructs the connected vehicle to perform a movement by a certain angle and speed. It may be interesting to explore the option of having controls laid out within the vehicle driver itself, perhaps give them a name, so that the UI (or whatever is managing the inputs to the vehicle) can simply call it and not have to do any logic itself.

This system may also open up more opportunities for customization, especially in the form of the manual drive mode, as front-ends will not need to be modified to get new control functionality working on the vehicle.

For example,

//keyboard controls
controls.Keyboard("Turn Left", KeyboardKey.A, KeyEvent.Pressed, () => {

});

//joystick
controls.Joystick("Steering", (x, y) => {

});

//simple triggers
controls.Button("Honk", () => {

});

This would involve a new service that would keep track of a vehicle's control scheme and have a mechanism for delivering it to the consuming client application. The concept of a Locomotion topic should still remain for other plugins to easily control the vehicle through a common interface.

cameron5906 commented 4 years ago

Settled on the following: IInputService:

void Keyboard(string name, KeyboardKey key, Action<InputState> action);
void GamepadJoystick(string name, GamepadInput input, Action<(bool isPressed, float x, float y)> action);
void GamepadTrigger(string name, GamepadInput input, Action<float> action);
void GamepadButton(string name, GamepadInput input, Action<InputState> action);

It will define a "name" for the Input (a UI could show this so the user knows what it does) as well as a default mapped button so the consuming interface can have something mapped initially.

The vehicle driver should call these methods in it's Initialize function, and the framework will take the resulting dictionaries before booting up and send them to the web service backend which will then deliver them to any clients that connect to control the vehicle.

With the named references to an input in place, a UI could theoretically re-map inputs from their defaults and the vehicle will still understand what it is being told to do.

Inputs are defined in the configuration file for the vehicle like:

"Input": {
    "Keyboard": {
      "TurnLeft": "A",
      "TurnRight": "D",
      "MoveForward": "W",
      "MoveBackward": "D",
      "Horn": "Space"
    },
    "Gamepad": {
      "Steering": "JoystickL",
      "Throttle": "JoystickR",
      "Horn": "X"
    }
  }

If the vehicle driver attempts to register something that is not defined in this file, an InvalidInputConfiguration exception is thrown. If the driver attempts to assign more than one handler, an InputAlreadyBound exception is thrown.

cameron5906 commented 4 years ago

Tested yesterday and its working