Skip to content

WebXR (Android/Quest) support for XR mode#515

Open
j5155 wants to merge 84 commits into
Mechanical-Advantage:mainfrom
j5155:webxr
Open

WebXR (Android/Quest) support for XR mode#515
j5155 wants to merge 84 commits into
Mechanical-Advantage:mainfrom
j5155:webxr

Conversation

@j5155
Copy link
Copy Markdown
Contributor

@j5155 j5155 commented May 3, 2026

Since the XR view currently uses three.js, it's relatively easy to enable WebXR and allow for both Android phones and VR headsets to use it.
Current status: Complete except for Android app. Demo video here, though I'd love it if someone with a Quest 3 or newer could record a better one that includes the passthrough!

Current setup: download and run a copy of AdvantageScope from the Actions build, then open 3D Field and XR mode. Scan the QR code with an Android phone, and/or press the Send to Meta Quest button to open on a Quest headset. To open on another device, manually type the displayed URL into the browser. (Docs updated.)

Development/Debugging: I configured tsconfig to allow you to build with ENABLE_SOURCEMAP=true as an environment variable, which makes debugging much easier. A local copy of something Chromium-based with this extension installed can be used for testing/debugging without a headset with the controls added in the WebXR section of Developer Tools [edit: seemingly updating three.js broke this??]. If you want to debug from within WebStorm, which I personally highly recommend, create a manual JavaScript Debug configuration with URL http://localhost:56328 and your Chromium-based browser. You'll need to install the extension a second time within the profile opened by the debugger. For debugging on headset, with it connected in ADB, you can open chrome://inspect/#devices to remotely access DevTools on the headset. I haven't yet found a solution to attach the WebStorm debugger to the headset!

TODO:

  • Fix existing iOS XR support and properly refactor for toggling between them.
  • Proper in-headset message display UI with loading indication
  • A secure context workaround. [Self-signed certificate on :56329]
  • Updates to XR configuration UI within AdvantageScope [Edit: added IP selection, Send to Meta Quest button, made QR code go to HTTP page, and legacy iOS support.]
  • Proper controls [now raycasting to floor on Android. Also easy to do in headset, but unnecessary]
  • Android Phone AR support [edit: this worked immediately! apparently webxr abstracts everything]
  • flim -> film
  • Make the Web UI look good and properly open links in the right places. [Edit: Added buttons to open Android app, iOS app clip, Send to Meta Quest, and open self-signed. They could look better though and the process could be streamligned.]
  • Style the Send to Meta Quest button in the UI
  • Docs updates.
  • Make preferred IP apply for iOS app (put only it in the URL parameters). Closes XR clients never find server when server device has Tailscale enabled #453
  • Controller/hand models (downloaded from CDN and autocached by browser to avoid adding hundreds of megabytes to the advantagescope app size, tested and safely falls back to no models when offline)
  • FTC calibration text too wide for Android/VR [Manually added newlines]
  • Mysterious issues with connections taking a long time to recieve command [Added auto reconnection with 2 second timeout.]
  • Inside out hand models [Seemingly fixed by updating three.js, which also massively improved performance throughout the app. Unsure of cause]
  • Basic anchor support to keep the field in the same place after a recenter
  • Optional: Save certificate to file so you don't have to retrust it every time
  • Optional: Persistent anchor support to have the field in the same place across sessions [Keys stored in localstorage. Weirdly even though persistent anchors always work perfectly regular anchors drift on sleep and resume (because Meta Browser is evil), but I couldn't figure out how to reliably detect resume, so I just regenerate the regular anchors from the persistent anchors every second and it works fine.
  • Blaze-Developer reported persistent anchors are broken on Quest 3s, waiting for more debug info from her to fix, Meta Browser is evil

Known issues I don't know how to fix/need input on:

  • Extremely high detail robot models slow down the headset so badly you can't even close the app, I had to reboot. Possibly related to Significantly optimized 3D Renderer performance, shadow update suppression, instancing optimizations #482 ? Edit: this is documented though, and easy for users to work around. I have a branch with 482 merged with this PR here though I haven't yet tested it with XR devices. I've also noticed poor performance in general but particularly in VR that still needs debugging; I'm working on going through this guide and have so far discovered that the issues are GPU bound. I also tried switching to the WebGPU renderer and enabling multiview, but that only made things worse and is incompatible with lighting. Possibly better optimization is needed for AdvantageScope in general, like more simplified models, LOD options, testing removing translucent objects, etc.
  • iOS app updates. I included a very simple patch to the iOS code that allows it to scan the new QR codes, but I have no way of building or testing it locally. I have a jailbroken iOS device so I can easily install an IPA if you're able to build it or anything (though my iOS version is too old to test the App Clip). Note that this is exclusively for scanning the QR code directly within the app; App Clips still work perfectly fine, and scanning the QR code to open the HTTP UI and clicking the open app clip button also works perfectly fine. I also added a legacy iOS option that shows the old URL.
  • Android app. While arguably unnecessary because of the self-signed secure context workaround, it would certainly be nice to have and improve user experience. I have a working one at https://github.com/j5155/AdvantageScopeXR-Android, let me know how that should be integrated into the repo (or if it should happen at all). Note that the app can only work if the phone's default browser is Chromium-based (and I only tested with Chrome and Meta Browser; it definitely does not work in IronFox).
  • The XR controls UI doesn't fit all the controls anymore, but I can't figure out how to make it scale properly. Any tips?
  • The docs screenshot should be retaken on a light mode Mac.

Potential future work:

  • AdvantageScope controls within headset? Canvases are seemingly the best option for this and they're very limited unfortunately. Maybe a simple buttons UI, potentially on your wrist, to control play/pause/position in log/loop would be possible?
  • Use the upcoming webxr direct camera access API and the Umich library compiled to WASM to auto detect and calibrate to field apriltags (https://discord.com/channels/176186766946992128/1365422855378178048/1501857130834296902, some setup work started at https://github.com/j5155/AdvantageScope/tree/web-xr-apriltag but this certainly isn't happening any time soon)
  • I personally would love to somehow be able to log or broadcast the positions of the VR controllers so that I could mount them on a bot and test odometry, but that's probably something for a personal fork.

Tested by me on a Pixel 3a, a Quest 2, an iPhone 12 and a iPad Air, and by others on an Apple Vision Pro and Quest 3S. No AI was used for any part of this PR beyond JetBrains IDE single line completion.

@jwbonner
Copy link
Copy Markdown
Member

jwbonner commented May 4, 2026

Thanks, this looks very cool. I can take a look in more detail soon, but I think my primary concern is about the secure context requirement. The first version of AdvantageScope XR that I used for development was based on WebXR, but I couldn’t come up with a good solution to the secure context problem that “just works” for users. The best solution I came up with was using VSCode’s built-in tunneling, but that 1) requires an internet connection and 2) is still too confusing to set up. In order to be viable, I think any solution for Android/VR probably needs to be just as easy to set up as the existing system on iOS.

@j5155
Copy link
Copy Markdown
Contributor Author

j5155 commented May 4, 2026

I have managed to get hosting a self-signed HTTPS server to work, and at least on desktop it can load WebXR perfectly. I didn't manage to test on device yet probably because of my weird network config, still troubleshooting that.

The only problem with a self-signed server is that it does have the big red scary "this connection is not secure" warning that users have to manually bypass from the more details -> proceed unsafe section. Is that acceptable, or should I look for a solution with a nicer UI?

Using a tunneling service would work, Cloudflare for example lets you run it from the CLI interface, but I think it would be really slow and use a lot of bandwidth. Also, requiring both devices to be online would make using this with live data on robot networks very difficult. But the UI would absolutely be a lot nicer.

I think the theoretical option with the best UI and best performance would be developing an Android app that proxies the AdvantageScope Desktop IP to localhost and then loads it in a browser, but that would also require by far the most development and maintenance, and users would still have to download an app.

@j5155
Copy link
Copy Markdown
Contributor Author

j5155 commented May 4, 2026

I confirmed that a self-signed server will work on mobile devices as well. Here's what the scare screen looks like:

https.mp4

@toddyocum
Copy link
Copy Markdown

Works for the Apple Vision Pro, at least in a minimal way of viewing. AVP doesn't scan QR codes, so I typed in the URL manually.
https://www.icloud.com/photos/#/icloudlinks/0b1Cf6SJMXyjmNAKtYApfzg7A/0/

@j5155
Copy link
Copy Markdown
Contributor Author

j5155 commented May 6, 2026

Several people in Discord were opposed to the self-signed scare screen for Android phone users, so I've gone ahead and moved forward with making an Android app proxy. I've gotten QR scanning, web embedding, and the proxy part working, I just need to integrate them properly and work on the UI. I'm currently working on development at https://github.com/j5155/AdvantageScopeXR-Android , let me know how best to integrate that back into the larger project.

Also, what's the reasoning behind the qr code exposing every IP of the server at the moment? I'm thinking about having the QR generation ui guess at the correct one and adding a dropdown menu for selecting it. That way the QR can go directly to http://server-ip:56328 and I can make a GUI for choosing whether to open in app or trigger the scare screen, and VR users can see what IP to type into their browsers manually like Todd.

@blaze-developer
Copy link
Copy Markdown
Contributor

Here's a video with a Quest 3s!

https://files.catbox.moe/qg1sx0.mp4

@j5155
Copy link
Copy Markdown
Contributor Author

j5155 commented Jun 1, 2026

Screenshot_20260531_173120 Screenshot_20260531_171548 Screenshot_20260531_171528 Screenshot_20260531_171514 @blaze-developer has been working on some huge improvements to the web UI as well

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

Successfully merging this pull request may close these issues.

XR clients never find server when server device has Tailscale enabled

5 participants