Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add gamepad to Joy mapping options #9

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM mcr.microsoft.com/devcontainers/typescript-node:0-18

# Copy package.json and package-lock.json (if available)
COPY package*.json ./

# Install dependencies
RUN npm ci

# Set the user
USER node

# Command to keep the container running
CMD ["bash"]
46 changes: 46 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-outside-of-docker-compose
{
"name": "Foxglove Joystick Extension Dev Container",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",

// Use this environment variable if you need to bind mount your local source code into a new container.
"remoteEnv": {
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}"
},
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-typescript-eslint.vscode-typescript-eslint",
"foxglove.studio-extension-helpers",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-vscode-remote.remote-containers",
"ms-azuretools.vscode-docker",
"streetsidesoftware.code-spell-checker",
"orta.vscode-jest",
"foxglove.vscode-foxglove-studio",
"SonarSource.sonarlint-vscode"
],
"settings": {
"git.useEditorAsCommitInput": false
}
}
},
"forwardPorts": [8080],
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {},
"ghcr.io/devcontainers/features/node:1": {},
"ghcr.io/devcontainers-contrib/features/jest:2": {},
"ghcr.io/devcontainers/features/git:1": {
"version": "latest"
}
},
"postCreateCommand": [
"echo 'Dev container is ready!'"
]
}
28 changes: 28 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
version: '3'

services:
app:
network_mode: host
build:
context: ..
dockerfile: .devcontainer/Dockerfile

volumes:
# Forwards the local Docker socket to the container.
- /var/run/docker.sock:/var/run/docker-host.sock
# Update this to wherever you want VS Code to mount the folder of your project
- ../..:/workspaces:cached
- ~/.gitconfig:/root/.gitconfig # Mount the .gitconfig file
- ~/.ssh:/root/.ssh # Mount the .ssh directory
# Overrides default command so things don't shut down after the process ends.
entrypoint: /usr/local/share/docker-init.sh
command: sleep infinity

# Uncomment the next four lines if you will use a ptrace-based debuggers like C++, Go, and Rust.
# cap_add:
# - SYS_PTRACE
# security_opt:
# - seccomp:unconfined

# Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
# (Adding the "ports" property to this file will not forward from a Codespace.)
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for more information:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
# https://containers.dev/guide/dependabot

version: 2
updates:
- package-ecosystem: "devcontainers"
directory: "/"
schedule:
interval: weekly
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,10 @@ dist
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
.pnp.*


# Extension artifact files
*.foxe
local-install
run
16 changes: 16 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-typescript-eslint.vscode-typescript-eslint",
"foxglove.studio-extension-helpers",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-vscode-remote.remote-containers",
"ms-azuretools.vscode-docker",
"streetsidesoftware.code-spell-checker",
"orta.vscode-jest",
"foxglove.vscode-foxglove-studio",
"sonarsource.sonarlint-vscode"
]
}
15 changes: 15 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"cSpell.words": [
"disp",
"fracwidth",
"gamepadconnected",
"gamepaddisconnected",
"immer",
"ipega",
"kbmapping",
"nsec",
"rostime",
"steamdeck",
"unadvertise"
]
}
1 change: 0 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
- Add keyboard mode
- Add interactive mode


## 0.0.1

- Initial release
32 changes: 14 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ There are four main operating modes/input sources/use cases:
| Subscribe Mode | Subscribes to an existing ROS `Joy` topic | Monitoring a robot that is being teleoperated, or replaying a log and reviewing operator actions |
| Gamepad Mode | Receives input from a locally-connected gamepad (and publishes it to a ROS `Joy` topic) | Live control of a robot using a gamepad connected to any Foxglove-supported device |
| Keyboard Mode | Converts local keystrokes into `Joy` messages (for publishing) | Bench-testing a configuration that is primarily designed to use a gamepad but does not currently have one connected |
| Interactive Display Mode | Makes the displayed indicators clickable/touchable (for publishing) | Controlling a robot from a touchscreen device |``
| Interactive Display Mode | Makes the displayed indicators clickable/touchable (for publishing) | Controlling a robot from a touchscreen device |

![Panel Overview Screenshot](https://github.com/joshnewans/foxglove-joystick/blob/main/docs/screenshot1.png?raw=true)

Expand All @@ -28,46 +28,44 @@ Download the latest `.foxe` release [here](https://github.com/joshnewans/foxglov
### Compile from source

With Node and Foxglove installed
- `npm install` to install dependencies
- `npm run local-install` to build and install for a local copy of the Foxglove Studio Desktop App
- `npm run package` to package it up into a `.foxe` file

- `npm install` to install dependencies
- `npm run local-install` to build and install for a local copy of the Foxglove Studio Desktop App
- `npm run package` to package it up into a `.foxe` file

### Snap Users

Right now it seems that this panel will **not** work with the `snap` version of Foxglove Studio. Snaps do not allow joystick input by default and I am looking into what is required to use it (possibly the Foxglove team enabling the `joystick` interface).
Right now it seems that this panel will **not** work with the `snap` version of Foxglove Studio. Snaps do not allow joystick input by default and I am looking into what is required to use it (possibly the Foxglove team enabling the `joystick` interface).

### Steam Deck Users

Please follow [this guide](docs/steamdeck.md).



## Mapping

Right now all "mapping" within the program is direct, but it is intended that there will be flexibility here. This is because different controllers (and in some cases the same controller on different platforms) will have the buttons/axes arranged in a different order.
Different controllers (and in some cases the same controller on different platforms) will have the buttons/axes arranged in a different order.

Some more complex examples of this are D-Pads (sometimes register as two axes, sometimes four buttons) and triggers (sometimes register as axes + buttons, sometimes buttons with a variable value, unsupported by `Joy`).

Thus it is expected to eventually need the following:
You can select the Gamepad to Joy transformation that works in the panel options. The Gamepad to Joy transformations are stored in the [mappings](src/mappings/gamepadJoyTransforms.ts) file.

| Mapping | Purpose | Current implementation |
| ------- | ------- | ---------------------- |
| Gamepad (numerical) -> Joy (or Keyboard -> Joy) | Defines how key pressed are mapped to `Joy` values (e.g. gamepad button 3 maps to joy button 4). | Direct mapping |
| Joy -> Gamepad/Layout (named) | Defines how `Joy` values map into the Layout (e.g. joy button 4 maps to layout button "L1"). | Built into layout JSON (separate in future) |
To create a new mapping, you can use the [Gamepad Tester](https://gamepad-tester.com/) to see the order of the buttons and axes on your controller. Then add a the new mapping logic to the [mappings](src/mappings/gamepadJoyTransforms.ts)

Also note that the HTML gamepad API seems to have the axes reversed compared to what typically comes out of the `joy` drivers, so the panel flips those values back automatically.

## Layouts

Currently consist of a `.json` to determine button locations and an entry in `GamepadBackground.tsx` for the background. Intention is for this to be more configurable in future.
Currently consist of a `.json` to determine button locations and an entry in `GamepadBackground.tsx` for the background.

To add a new mapping, create a new .json mapping file in the [mappings](src/mappings) and be sure to update the `GamepadLayoutMappingKey` with the id `gamepadLayoutMappings` object with the new mapping so the panel options are also updated.

## Planned functionality/improvements

- **Source modes**
- [x] Source Mode 1 (Subscriber)
- [x] Source Mode 2 (Gamepad)
- [ ] Option for a custom mapping from gamepad to `Joy` (e.g. GP 6-> Joy 8)
- [ ] Deadzones, inversion, scaling, etc.
- [ ] Dead-zones, inversion, scaling, etc.
- [x] Source Mode 3 (Keyboard)
- [x] Source Mode 4 (Interactive)
- **Display modes**
Expand All @@ -79,8 +77,6 @@ Currently consist of a `.json` to determine button locations and an entry in `Ga
- [x] Options for axes to be sticks, d-pads, triggers, or more
- [ ] General improved customisability



## Contributions

Thanks to [rgov](https://github.com/rgov) for creating [this repo](https://github.com/ARMADAMarineRobotics/studio-extension-gamepad) which I originally worked on this project from before rewriting it mostly from scratch (but have retained [useGamepads.ts](src/hooks/useGamepad.ts)).
Thanks to [rgov](https://github.com/rgov) for creating [this repo](https://github.com/ARMADAMarineRobotics/studio-extension-gamepad) which I originally worked on this project from before rewriting it mostly from scratch (but have retained [useGamepads.ts](src/hooks/useGamepad.ts)).
12 changes: 12 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
},
moduleNameMapper: {
'^lodash-es$': 'lodash',
},
setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
};
Loading