Skip to content

vr: add VrBaseComponent base-velocity teleop leader#262

Open
abhichothani42 wants to merge 3 commits into
vr-05-vr-arm-componentfrom
vr-06-vr-base-component
Open

vr: add VrBaseComponent base-velocity teleop leader#262
abhichothani42 wants to merge 3 commits into
vr-05-vr-arm-componentfrom
vr-06-vr-base-component

Conversation

@abhichothani42

@abhichothani42 abhichothani42 commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds VrBaseComponent, a base-velocity teleop leader driven by VR thumbstick(s) (hardware type vr_base_component). Pairs with the SLATE base follower.

Changes

  • read() samples the configured thumbstick(s) and returns [linear_mps, angular_rps]: forward stick → forward velocity, left stick → positive yaw. write() is a no-op (leader-only). Returns zeros while the headset is disconnected so the base does not coast on a stale frame.
  • A centered deadzone zeroes small stick noise, then rescales the remaining travel to full range before applying max_linear_mps / max_angular_rps caps.
  • Split-axis mode: linear and angular axes may come from the same or different controllers; either axis may be specified independently, with a documented fallback.
  • configure() validates max_linear_mps / max_angular_rps (non-negative, finite).

Test Plan

  • Builds cleanly (make build)
  • Tests pass (make test)
  • Lint passes (pre-commit run --all-files)
  • Tested on hardware

Breaking Changes

None.

Related Issues

N/A — part of the VR teleoperation feature stack.

abhichothani42 commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new VR hardware component that exposes VR controller thumbstick input as a mobile-base velocity teleop leader, integrating with the existing VrSession singleton and hardware registry.

Changes:

  • Introduces VrBaseComponent (header + implementation) that outputs [linear_mps, angular_rps] from thumbstick axes with deadzone + scaling.
  • Adds JSON configuration parsing for controller selection (single-hand and split-axis modes), plus connection waiting in prepare_for_teleop().
  • Registers the component and links it into the trossen_sdk shared library build.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
src/hw/vr/vr_base_component.cpp Implements VR thumbstick → base velocity readout, session lifecycle, and config parsing.
include/trossen_sdk/hw/vr/vr_base_component.hpp Declares the new teleop-capable hardware component and documents its JSON config/IO contract.
CMakeLists.txt Adds the new source file to the trossen_sdk library target.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/hw/vr/vr_base_component.cpp
Comment thread src/hw/vr/vr_base_component.cpp Outdated
Comment thread src/hw/vr/vr_base_component.cpp
Comment thread include/trossen_sdk/hw/vr/vr_base_component.hpp

@shantanuparab-tr shantanuparab-tr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The deadzone, the scaling, the caps, and especially the steering direction (push forward to go forward, push left to turn left) can all be tested without hardware. A wrong direction here is a crash into a wall, so a tiny test to lock the direction is worth it.

// user-configured limit.
const double linear = y * max_linear_mps_;
const double angular = -x * max_angular_rps_;
return {static_cast<float>(linear), static_cast<float>(angular)};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A "not a number" value coming in over the network would pass through the math and reach the base. Your own math cannot create one given the config checks, but the network can. Same small real-number check as the arm.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the same finite check, a bad frame stops the base instead of forwarding NaN.

std::vector<float> VrBaseComponent::read() {
// Hold zero velocity while the headset is disconnected so the base does not
// coast on a stale frame.
if (!VrSession::instance().is_vr_connected()) return {0.0f, 0.0f};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Sends zeros when disconnected" is true once it notices, but it only counts as disconnected after about 2 seconds of silence. So on a sudden drop, the base keeps moving at the last speed for up to 2 seconds. On a moving base that is a real distance. Can we document that, or shorten the timeout?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read() already zeros velocity while disconnected. added a note that is_vr_connected() tracks the heartbeat, so it can lag a real drop by up to that timeout

Comment thread src/hw/vr/vr_base_component.cpp Outdated
const bool has_angular = config.contains("angular_controller_type");
const bool has_legacy = config.contains("controller_type");

if (!has_linear && !has_angular && !has_legacy) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"legacy" is confusing on a brand new component. Legacy compared to what?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed has_legacy → has_shared

@abhichothani42

Copy link
Copy Markdown
Collaborator Author

Added test_vr_base_component.cpp for deadzone, scaling, caps, and the steering direction

Add VrBaseComponent, a base-velocity teleop leader driven by VR thumbstick(s). Registered as hardware type "vr_base_component".

- read() samples the configured thumbstick(s) and returns [linear_mps, angular_rps]: forward stick -> forward velocity, left stick -> positive yaw. write() is a no-op (leader-only).
- A centered deadzone zeroes small stick noise, then rescales the remaining travel to full range before applying max_linear_mps / max_angular_rps caps.
- Split-axis mode: linear and angular axes may come from the same or different controllers (e.g. right stick to drive, left stick to turn). Claims the thumbstick on each controller_type it reads via VrSession.

Builds on VrSession and the Base teleop space (BaseSpaceTeleop). Pairs with the SLATE base follower. Adds src/hw/vr/vr_base_component.cpp to the library.
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.

3 participants