Highlight
Object tracking in visionOS 27 supports high-frame-rate tracking for dynamic handheld objects, metric-space coordinates, and cross-platform iOS deployment. Apple also opens a third-party spatial accessory standard based on LEDs, IMUs, and Bluetooth, so developers can build physical input devices with buttons and haptic feedback.
Core Content
From Static Props to Handheld Tools
Object Tracking in visionOS 2.0 had a serious limitation: it could only track static objects placed on a table. As soon as someone picked the object up, or moved it quickly, tracking was lost.
(02:22) visionOS 27 adds High Frame Rate Tracking. Together with Create ML’s Extended Training Mode, the system can track handheld object motion much more reliably.
The talk uses a medical probe as an example: a doctor moves a handheld probe across a spine model, and the system calculates distances between vertebrae in real time. That kind of workflow was previously impossible because the hand partially occludes the object and static tracking quickly loses the target.
Metric-Space Coordinates: From “Looks Aligned” to “Measured Accurately”
(05:04) Object tracking in visionOS 2.0 had a hidden issue: returned coordinates included display correction. Apple slightly adjusted coordinates so virtual content looked visually aligned with the physical object in the headset. That correction is fine for rendering UI, but fatal for physical measurement.
visionOS 27 adds a Coordinate Space Correction API. Developers can choose between two coordinate spaces:
.rendered: Includes display correction and is suitable for rendering virtual content.none: Pure metric-space coordinates, suitable for physical measurement
That distinction turns object tracking from a “visual alignment tool” into a “precision measurement tool.”
Object Tracking Comes to iOS
(05:53) This year, the object tracking API officially comes to iOS. Trained .referenceobject files work across iOS and visionOS, so the same model can be reused on both platforms.
The iOS API is largely the same as visionOS: load reference objects, configure ARWorldTrackingConfiguration, and handle the lifecycle callbacks for ARObjectAnchor.
Third-Party Spatial Accessories: From Consuming to Creating
(07:25) visionOS 26 only supported officially certified spatial accessories such as Logitech Muse and PSVR2 Sense controllers. visionOS 27 opens the standard completely.
Any electronic device that meets these three conditions can become a spatial accessory:
- LED constellation array for Vision Pro’s cameras to track
- IMU for orientation and acceleration
- Bluetooth chip for communicating with Vision Pro
Spatial accessories can track at the display refresh rate with very low latency, and tracking continues through brief hand occlusions. Accessories can also include physical buttons and haptic motors, making interaction feel more real.
The talk demonstrates a steering wheel accessory: place the spatial accessory inside a physical steering wheel, and the digital vehicle aligns precisely with the wheel. When users grip the wheel, they feel as if they are really sitting in the car.
Details
Enable High-Frame-Rate Tracking
(03:50) High-frame-rate tracking is configured per reference object rather than through a global switch.
// Create the reference object configuration
var configuration = ReferenceObject.Configuration()
configuration.highFrameRateTrackingEnabled = true
// Pass the configuration when loading the reference object
let refObjURL = Bundle.main.url(forResource: "flashlight", withExtension: ".referenceobject")!
let refObject = try? await ReferenceObject(from: refObjURL, configuration: configuration)
Key points:
ReferenceObject.Configuration()is a new ARKit API on visionOShighFrameRateTrackingEnabledis configured per object, so different objects can use different tracking strategies- This setting is decided at runtime and does not require retraining the model
Extended Training Mode
(04:50) Create ML adds Extended Training Mode to improve tracking accuracy and robustness for handheld objects.
Command-line training:
% xrun createml objecttracker \
--source flashlight.usdz \
--output flashlight.referenceobject \
--training-mode extended \
--all-angles
Key points:
--training-mode extendedenables extended training, which takes much longer than standard mode- Extended Training Mode is recommended together with high-frame-rate tracking
- The command-line workflow supports training on a remote machine
--all-anglesmeans training from every angle
Metric-Space Coordinates
(05:25) The coordinateSpace(correction:) API lets developers choose a coordinate precision strategy.
// Get display-corrected coordinates for rendering virtual content
let renderingPose = myObjectAnchor.coordinateSpace(correction: .rendered)
// Get pure metric-space coordinates for physical measurement
let metricPose = myObjectAnchor.coordinateSpace(correction: .none)
Key points:
.renderedreturns coordinates after display correction, so virtual content visually aligns with the physical object.nonereturns absolute physical-world coordinates, unaffected by any display correction- Medical probe measurement, industrial inspection, and similar workflows must use
.none - Do not use
.nonecoordinates directly for rendering, or visual misalignment will appear
Object Tracking on iOS
(06:22) ARKit in iOS 27 fully supports object tracking.
import ARKit
import RealityKit
class ObjectTrackingARSessionDelegate: NSObject, ARSessionDelegate {
let arView = ARView(frame: .zero)
var entities: [UUID: AnchorEntity] = [:]
func start() throws {
let stationaryObject = try ARReferenceObject(archiveURL:
Bundle.main.url(forResource: "stationary", withExtension: "referenceobject")!)
let movingObject = try ARReferenceObject(archiveURL:
Bundle.main.url(forResource: "moving", withExtension: "referenceobject")!)
let configuration = ARWorldTrackingConfiguration()
configuration.detectionObjects = [stationaryObject] // Lower frame rate, stationary objects
configuration.trackingObjects = [movingObject] // High frame rate, moving objects
arView.session.delegate = self
arView.session.run(configuration)
}
func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
for case let anchor as ARObjectAnchor in anchors {
let entity = AnchorEntity(anchor: anchor)
entities[anchor.identifier] = entity
arView.scene.addAnchor(entity)
}
}
func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
for case let anchor as ARObjectAnchor in anchors {
entities[anchor.identifier]?.isEnabled = anchor.isTracked
}
}
func session(_ session: ARSession, didRemove anchors: [ARAnchor]) {
for case let anchor as ARObjectAnchor in anchors {
if let entity = entities.removeValue(forKey: anchor.identifier) {
arView.scene.removeAnchor(entity)
}
}
}
}
Key points:
ARReferenceObjectand visionOSReferenceObjectuse the same.referenceobjectfiledetectionObjectsis for mostly stationary objects and tracks at a lower frequencytrackingObjectsis for moving objects and enables high-frame-rate tracking- The three callbacks
didAdd,didUpdate, anddidRemovemanage the full lifecycle of anchors anchor.isTrackedcontrols whether the entity is visible, automatically hiding it when tracking is lost
Discover and Connect Spatial Accessories
(12:26) Spatial accessories are discovered and connected through the GameController framework.
import ARKit
import GameController
// Discover paired spatial accessories
if let device = GCSpatialAccessory.spatialAccessories.first {
// ARKit automatically parses the .referenceaccessory bundle
let accessory = try await Accessory(device: device)
let provider = AccessoryTrackingProvider(accessories: [accessory])
try await arkitSession.run([provider])
}
// Hot-swap at runtime; no session restart required
try await provider.updateAccessories([newAccessory])
Key points:
GCSpatialAccessory.spatialAccessoriesreturns all paired spatial accessoriesAccessory(device:)automatically parses the.referenceaccessoryfile in the deviceAccessoryTrackingProviderworks similarly to the object tracking providerupdateAccessoriessupports switching accessories at runtime without interrupting the tracking session- Accessory manufacturers need to declare
.referenceaccessoryas an exported UTType inInfo.plist - Third-party developers can declare accessory files as imported UTTypes so their apps can run independently
Key Ideas
1. Handheld Medical Measurement Tool
What to build: Build an orthopedic surgery training app where doctors practice drilling positions on a bone model with a tracked handheld probe.
Why it is worth building: High-frame-rate tracking plus metric-space coordinates makes millimeter-level localization for handheld tools possible. Previously, only fixed-table surgical navigation systems could reach this level of precision.
How to start: Train the probe’s reference object with Create ML’s extended mode, enable highFrameRateTrackingEnabled, and use coordinateSpace(correction: .none) to get real physical coordinates for distance calculations.
2. Immersive Racing Simulator
What to build: Embed a spatial accessory in a real steering wheel so the digital race car and the physical wheel rotate in perfect sync.
Why it is worth building: Spatial accessories track at the display refresh rate, have very low latency, and support physical buttons and haptic feedback. That creates a much better steering wheel experience than pure visual tracking.
How to start: Build a first prototype with off-the-shelf hardware kits from DFRobot or MIKROE, discover and connect it through GCSpatialAccessory, and track its pose with AccessoryTrackingProvider.
3. Industrial Assembly Guidance System
What to build: On a factory line, use object tracking to identify parts and overlay assembly step guidance.
Why it is worth building: Now that object tracking has come to iOS, the same reference object can be reused between iPad for on-site guidance and Vision Pro for immersive training.
How to start: Train a part’s reference object from a USDZ model. On iOS, configure detectionObjects for static recognition; on visionOS, enable high-frame-rate tracking for dynamic guidance.
4. Track Any Object with a 3D-Printed Marker
What to build: Attach a 3D-printed tracking marker to everyday objects without existing 3D models, such as surgical instruments or tools, to enable low-cost tracking.
Why it is worth building: You do not need a photorealistic USDZ model. A printed marker attached to the object is enough to track it, dramatically lowering the barrier to object tracking.
How to start: Design a 3D-printed marker with a distinctive texture, train the marker’s reference object with Create ML, and mount it on the object you want to track.
5. Mixed Reality Game with Multiple Cooperative Accessories
What to build: Build an MR game that tracks multiple spatial accessories at once, such as a gun in one hand and a shield in the other.
Why it is worth building: updateAccessories supports adding and removing accessories dynamically at runtime, so players can switch hands or add new devices without restarting the game.
How to start: Connect the primary accessory during initialization and start the session. When the player picks up a second accessory, call updateAccessories to append it to the tracking list, then trigger game actions from accessory button events.
Related Sessions
- Explore object tracking in visionOS — A foundational introduction to object tracking, useful to watch before digging into these enhancements.
- Explore spatial accessory input on visionOS — A deeper look at buttons, haptics, and input event handling for spatial accessories.
- What’s new in RealityKit — Lighting features such as Physical Surroundings Light can be combined with object tracking.
- Create ML and object tracking — The object tracking training workflow in Reality Composer Pro 3.
- SwiftUI and spatial computing — How to combine tracked objects with SwiftUI interfaces.
Comments
GitHub Issues · utterances