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

Migrate to IVRInput's haptic Actions and/or consider OpenXR? #15

Open
digitalf0x opened this issue Aug 10, 2024 · 0 comments
Open

Migrate to IVRInput's haptic Actions and/or consider OpenXR? #15

digitalf0x opened this issue Aug 10, 2024 · 0 comments

Comments

@digitalf0x
Copy link
Contributor

digitalf0x commented Aug 10, 2024

About that IVRInput

This is the supported, modern way forward.

  • Allows for frequency modulation
    • Even with ERMs instead of LRAs, offers a slightly adjustable haptics feel on Tundra Trackers
  • Allows Steam to automatically map Vive/Tundra/etc Trackers with given SteamVR roles (e.g. Chest, Left Foot)
    • Haptic Pancake would just be mapping from e.g. "Chest tracker" to /avatar/parameters/something_here
  • Solves the Tundra Tracker issue with the legacy haptics pulses being cut off, requiring 4 ms loops
  • As part of this, we'll want a .vrmanifest file which will make the Bridge App auto-start with SteamVR, too

But.. it is an involved change.

I still don't get why lighthouse_console's haptic2 command can use the new haptics API without the need for the entire SteamVR Actions system - if we could simply copy that, then Haptic Pancake itself would need almost no changes.

Further research on triggerHapticVibrationAction and how the Lighthouse console uses it is needed.

This is a large enough project we may want to make this a v2 of Tundra Tracker support, or even a v2 of the entire Bridge App.

Considering Valve is pushing SteamVR towards OpenXR (an actually independent standard) as the replacement for OpenVR (Valve's own standard), perhaps OpenXR will provide another path forward? It looks like OpenXR uses the same rebindable Action system, though.

Using lighthouse_console

With SteamVR open and your headset connected to your PC

Launching console

Linux

Run as your normal user:

$HOME/.local/share/Steam/steamapps/common/SteamVR/tools/lighthouse/bin/linux64/lighthouse_console

Windows

May need to run as administrator:

C:\Program Files (x86)\Steam\steamapps\common\SteamVR\tools\lighthouse\bin\win32\lighthouse_console.exe

(See this HTC thread)

Examples

Haptics help

lh> help
[…]
haptic [<duration_us>] [<interval_us>] [<repeat_count>] Trigger haptic pulse
haptic2 [<frequency_hz>] [<duration_ms>] [<amplitude_percent>]  Trigger haptics
[…]

Legacy API

triggerHapticPulse()

Some long duration (4000µs duration, 4000µs interval, 100× repeat):

lh> haptic 4000 4000 100

Modern API

triggerHapticVibrationAction()

400 Hz for 4 seconds:

lh> haptic2 400 4000

SteamVR OpenVR API

Legacy API (in use now)

    def triggerHapticPulse(self, controllerDeviceIndex, axisId, durationMicroSec: int) -> None:
        """
        Trigger a single haptic pulse on a controller. After this call the application may not trigger another haptic pulse on this controller
        and axis combination for 5ms. This function is deprecated in favor of the new IVRInput system.
        """
        […]

OpenVR says the duration is in microseconds, NOT milliseconds!

Vive Trackers are doing something wrong. (Perhaps they were built to an older spec, and HTC didn't want to break backwards compatibility for their enterprise customers?) Tundra Trackers, Index Wands, etc are doing things correctly.

Tundra Trackers do have a problem with cutting off haptic pulses longer than about 4000 microseconds, though.

Modern API (IVRInput)

    def triggerHapticVibrationAction(self, action, startSecondsFromNow: float, durationSeconds: float, frequency: float, amplitude: float, restrictToDevice) -> None:
        """Triggers a haptic event as described by the specified action"""
        […]

SteamVR now makes everything - including haptics! - rebindable with SteamVR Input 2.0, as per the Action manifest.

Haptic Pancake will no longer handle mapping to specific trackers. This is handled by SteamVR's own UI with assigning roles to trackers.

This should allow changing tracker bindings inside SteamVR and when Haptic Pancake isn't running.

This involves a lot of haptics vibrations:

vibration - The action is a output haptic vibration. Include one of these per type of haptic output in your application so they can be bound to different output devices if the user has them available. Examples include haptics due to firing a gun (that would usually be bound directly to a controller) or haptics from getting shot (which could be bound to a feedback vest worn on the chest).

And I think this is looking at…

  1. def setActionManifestPath(self, actionManifestPath: str) -> None: which will need generated according to the Valve wiki page
  2. def getActionHandle(self, actionName: str): on tracker load
  3. def triggerHapticVibrationAction(self, action, [...]) -> None: inside the Bridge App haptics loop

And to allow binding when Bridge App isn't running, and to have SteamVR auto-start the Bridge App, then we need a .vrmanifest file, like how WlxOverlay-S creates it - see below.

Other context

The whole action manifest is the route VRCOSC went, though they're only handling controllers.

VRC-OSC-Manager looked interesting initially as it supports both Linux and Windows and allows multiple plugins to use one OSC input, but that entirely skips VR manifests.

Example config files

Adapted from Valve's documentation.
BridgeApp/hp_actions.json:

{
  "default_bindings": [
   {
      "controller_type": "some_controller",
      "binding_url": "hp_bindings_fbt_trackers.json"
   }
  ], 
  "actions": [
    {
      "name": "/actions/hp_haptics/out/chest",
      "requirement" : "optional",
      "type": "vibration"
    },
    {
      "name": "/actions/hp_haptics/out/foot_left",
      "requirement" : "optional",
      "type": "vibration"
    }
  ],
  "action_sets": [
    {
      "name": "/actions/hp_haptics",
      "usage": "leftright"
    }
  ],
  "localization" : [
   {
       "language_tag": "en_us",

        "/actions/hp_haptics" : "Haptics",

        "/actions/hp_haptics/out/chest" : "Touch near Chest",
        "/actions/hp_haptics/out/foot_left" : "Touch near Left Foot",

    }
  ]
}

Adapted from WlxOverlay-S actions_binding_vive.json.
BridgeApp/hp_bindings_fbt_trackers.json:

{
   "action_manifest_version" : 0,
   "app_key" : "galister.wlxoverlay-s",
   "bindings" : {
      "/actions/default": {
         "haptics": [
            {
               "output": "/actions/hp_haptics/out/chest",
               "path": "/user/[path for SteamVR's chest tracker role, e.g. 'hand/left']/output/haptic"
            },
            {
               "output": "/actions/hp_haptics/out/foot_left",
               "path": "/user/[path for SteamVR's left foot tracker role, e.g. 'hand/left']/output/haptic"
            }
         ]
      }
   },
   "category" : "steamvr_input",
   "controller_type" : "TODO_vive_controller",
   "description" : "Ver1",
   "interaction_profile" : "",
   "name" : "Haptic Pancake configuration for Full Body Trackers",
   "options" : {
      "mirror_actions" : false,
      "simulated_controller_type" : "none"
   },
   "simulated_actions" : []
}

Adapted from WlxOverlay-S openvr/manifest.rs.
BridgeApp/haptic_pancake.vrmanifest:

{
    "source" : "builtin",
    "applications" : [
            {
                "app_key" : "z4urce.vrc-haptic-pancake",
                "launch_type" : "binary",
                "binary_path_linux" : "PATH/TO/hapticpancake",
                "binary_path_windows" : "PATH\\TO\\hapticpancake.exe",
                "is_dashboard_overlay" : false,
                "strings" : {
                    "en_us": {
                        "name" : "Haptic Pancake",
                        "description" : "A cheap solution to enable haptic feedback on full body trackers in OSC compatible games.",
                    }
                }
            }
        ]
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant