Русская версия | English
Low-overhead body tracking from a single 1080p webcam (30-60 FPS) for SteamVR and VRChat. Tracks waist + knees + ankles (5 points) via MediaPipe and exposes them as SteamVR GenericTracker devices through a native OpenVR driver. Optimized to leave GPU/CPU headroom for PCVR.
Current version:
v0.3— 5 trackers, Z-inversion fix, mirror fix, HMD-anchored calibration. See Releases.
- Single webcam 1080p, 30 FPS (60 FPS supported) → 5 SteamVR trackers:
waist,left_knee,right_knee,left_ankle,right_ankle(configurable,config/config.yaml:21) - HMD-anchored calibration:
T-pose(c) computes scale +HMD offsetvia OpenVR (tracker/app.py:342) so trackers appear under the headset, not 2 m away at the camera - OneEuro filter (
tracker/utils/one_euro.py:1) — jitter-free without lag - Mirror & Z fixes:
flip_horizontal(config.yaml:11) andflip_z(config.yaml:35) with runtime togglem/z(tracker/app.py:374) - Lightweight:
640x360inference,~13 msoni5-13600KFXNNPACK CPU (tracker/bench.py:1),~4-6% CPU,0% GPU(CPU mode) or~5% GPUonRTX 5070 - Prebuilt driver:
driver/dist/bin/win64/driver_camvr.dll(MinGW,4.3 MB) +vrpathregauto-install, or build from source (openvr+nlohmann/json)
[1080p Webcam] --1280x720--> [OpenCV 640x360] --> [MediaPipe Pose Full] --> [Pose Mapping + HMD Offset]
--> [OneEuro] --> [UDP 127.0.0.1:6969] --> [OpenVR Driver C++ 5x GenericTracker] --> [SteamVR / VRChat FBT]
- Capture
1280x720→ resize640x360for inference (4× saving) MediaPipe Posemodel_complexity=1(full)~13 ms,Lite (0)~8 msif CPU-bound- UDP JSON bridge (
tracker/utils/ipc.py:1) — driver-agnostic,tools/fake_driver.pyfor testing without SteamVR
- Tested on:
i5-13600KF + RTX 5070, 1080p webcam,Oculus Quest 3via Link (SteamVRoculusdriver). Any1080p 30 FPScamera works. - Camera placement: tripod,
~2 mdistance,~1.2 mheight, full body in frame. Desk-mounted crops legs.
MediaPipe's C++ binarypb fails on C:\Users\<Cyrillic>\.... Use a venv on D:\ (already configured as .venv):
python -m venv .venv
.venv\Scripts\pip.exe install -r requirements.txt
:: behind firewall/proxy:
.venv\Scripts\pip.exe install -r requirements.txt --proxy socks5h://127.0.0.1:10808
:: optional Lite/Heavy models:
.venv\Scripts\python.exe tools/download_models.py --proxy socks5h://127.0.0.1:10808.venv\Scripts\python.exe tools/test_camera.py
.venv\Scripts\python.exe tracker/bench.py --frames 100 --complexity 1Expected: Avg ~13 ms → OK for 60 FPS (33 ms budget for 30 FPS). If >33 ms, lower inference_width to 512 in config/config.yaml:9.
run.bat
:: or
.venv\Scripts\python.exe -m tracker --no-udpWindow CamVR - Body Tracking POC:
- Green/orange dots:
waist/knees/ankles(tracker/utils/pose.py:44) - Overlay:
FPS / Infer / Scale / Mirror / Z - Keys:
qexit,cT-pose calibrate (scale + HMD offset),mmirror toggle,zflip Z,ffilter toggle,rreset,ddebug,hHMD pose
:: terminal 1
.venv\Scripts\python.exe tools/fake_driver.py
:: terminal 2
.venv\Scripts\python.exe -m tracker --headless --frames 100Should print waist=+0.01,+0.95,+0.10 every 0.5 s.
Driver is prebuilt at driver/dist/ and driver/camvr_driver_win64.zip (v0.3), already copied to C:\Program Files (x86)\Steam\steamapps\common\SteamVR\drivers\camvr and registered via vrpathreg.
After pulling:
:: if steamvr path differs, run:
powershell -ExecutionPolicy Bypass -File driver/install.ps1Restart SteamVR → Settings → Manage Trackers shows 5 CAMVR devices (green when tracking). If grey, see Troubleshooting.
Build from source (optional, needs CMake 3.30 + MinGW/VS2022 + OpenVR SDK):
git clone https://github.com/ValveSoftware/openvr.git D:/openvr
mkdir driver\third_party\nlohmann -Force
curl.exe -L https://github.com/nlohmann/json/releases/download/v3.11.3/json.hpp -o driver\third_party\nlohmann\json.hpp
:: with proxy: curl.exe -x socks5h://127.0.0.1:10808 -L ...
build_driver.bat
:: or manually:
tools\cmake\bin\cmake.exe -S driver -B driver/build -G "MinGW Makefiles" -DOPENVR_ROOT="D:/openvr" -DCMAKE_MAKE_PROGRAM="C:/Program Files/TDM-GCC-64/bin/mingw32-make.exe"
tools\cmake\bin\cmake.exe --build driver/build --config Release
powershell -ExecutionPolicy Bypass -File driver/install.ps1- Start
SteamVR(headset tracking), thenrun.bat. Log should show[HMD] SteamVR HMD pos [x y z](tracker/app.py:178), notnot found. - Stand
T-pose2 mfrom camera, face camera,cin tracker window. Console:[Calib] HMD [...] raw_waist [...] -> offset [...](tracker/app.py:350). Filters reset. - SteamVR → Manage Trackers assign roles:
CAMVR_waist→WAIST(ПОЯС)CAMVR_left_knee→LEFT KNEE(ЛЕВОЕ КОЛЕНО)CAMVR_right_knee→RIGHT KNEECAMVR_left_ankle→LEFT FOOT(ЛЕВАЯ НОГА= foot, not ankle) for best VRChat leg IK, orLEFT ANKLE(ЛЕВАЯ ЛОДЫЖКА)CAMVR_right_ankle→RIGHT FOOT(ПРАВАЯ НОГА)
НОГАin SteamVR = foot (on top of foot). ChooseНОГАfor VRChat,ЛОДЫЖКАis ankle ~10 cm above. - VRChat: use an FBT-compatible avatar (not default robot). Search worlds
Avatar SearchforFBT/Full Body.Settings → Tracking & IK → Allow Full Body. ThenQuick Menu → Calibrate FBTin T-pose. Check mirror — waist/knees/ankles should bend legs. Ifleftmovesright, pressmandcagain.
Keys: m mirror left/right, z flip Z (back↔forward), o show offset.
config/config.yaml:
camera:
fps: 30
inference_width: 640
flip_horizontal: true # mirror fix for front camera
mediapipe:
model_complexity: 1 # 0=lite, 1=full, 2=heavy
tracking:
points: ["waist","left_knee","right_knee","left_ankle","right_ankle"]
calibration:
use_hmd: true
hmd_offset: [0,0,0] # auto after c
flip_z: false| Metric | Value | Note |
|---|---|---|
| Infer 640x360 | ~13 ms CPU | 30 FPS budget 33 ms |
| CPU | 4-6% i5-13600KF | pin to E-cores if needed |
| GPU | 0% (CPU) or 5% RTX 5070 | use_gpu: false → 0% |
| RAM | ~300 MB | |
| Latency | 40-50 ms | camera 33 ms + infer 13 ms |
If VRChat stutters: model_complexity:0 + 512x288 + fps:30.
- Grey hexagons in SteamVR: not tracking → check
C:\tmp\camvr.log(driver/src/driver.cpp:26logs every 90 pkts), firewallUDP 6969, camera full body,ccalibrate with HMD.tools/check_udp.pyshould show packets. - Left ↔ Right inverted:
mtoggle orflip_horizontal: true/false. - Back ↔ Forward inverted:
ztoggle orflip_z: true. - Trackers in floor / 2 m away: press
cin T-pose with SteamVR running to compute HMD offset; ensureuse_hmd: true. - Avatar doesn't move but calibration dots move: use FBT avatar, enable
Allow Full Body, VR not Desktop, and ensure roles areWAIST/FOOT. - Cyrillic path
binarypbfail: use.venvonD:\(run.batdoes this). Ortools/download_models.pywith proxy for403. - Driver not loading:
vrserver.txtshould haveLoaded server driver camvr. Re-rundriver/install.ps1, restart SteamVR.
tracker/ # Python CV pipeline (app.py, bench.py, utils/pose.py, one_euro.py, ipc.py)
driver/ # OpenVR C++ driver (src/driver.cpp, tracked_device.cpp, CMakeLists.txt)
driver/dist/ # prebuilt driver (committed)
config/config.yaml
tools/ # fake_driver, check_udp, test_camera, download_models, test_vr_trackers
.venv/ # venv on D: (not committed)
run.bat / build_driver.bat
- Feet (heel) vs ankle offset tuning
- Tray UI