AngePierreandClaude Opus 5 948bf0cc8a build_sdk: also reuse an SDK pre-placed under ~/Downloads
The Orin came with the SDK source at ~/Downloads/OrbbecSDK_v2; add it to the
reuse candidates so a clean install finds the build there instead of cloning a
second copy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 17:03:42 +02:00

Ithaca capture node

The software a Jetson runs to join an Ithaca RGBD capture rig: a Python bridge that puts the node on the WebSocket mesh and answers Preview / Record, a C++ preview server that streams each camera's colour (the sensor's own JPEG) and depth (its own 16-bit millimetres, LZ4-compressed) straight to the Unity viewer, and a C++ recorder that writes K4A-format MKV takes on Record — the same format the rest of Ithaca reads.

One checkout, one command, on any Jetson:

git clone <this repo> ~/ithaca-node
cd ~/ithaca-node
./install.sh

Why an install script and not a disk image

The rig currently spans two Jetsons with no JetPack in common:

Node SoC JetPack Ubuntu / CUDA
Jetson Nano (2019) tegra210 4.x only (EOL) 18.04 / 10.2
Jetson Orin Nano tegra234 5 or 6 22.04 / 12.x

tegra210 never got a newer L4T and the Orin refuses the old one, so no single OS image covers both, and no compiled binary is portable between them — CUDA, glibc and the C++ ABI all differ by generation.

What is portable is the source and the procedure. install.sh detects the platform and builds the C++ locally against a locally-built OrbbecSDK, so the same command produces a correct binary on each machine. Adding a future Orin NX or a Thor needs nothing new here — the script compiles against whatever toolchain it finds.

The bridge is pure Python and already runs identically everywhere; keep it that way by never giving it a dependency that has to be compiled.

Layout

install.sh                     one entry point, idempotent
bridge/
  bridge.py                    the node client — shipped verbatim, tested in place
  config.template.json         @PLACEHOLDERS@ filled per user by install.sh
server/
  ithaca_rgbd_server.cpp       the preview server
  CMakeLists.txt               links a prebuilt libOrbbecSDK, no GStreamer
recorder/
  depth_color_k4arec_pipeline.cpp   the MKV recorder — FTF source, not a stock example
  CMakeLists.txt               built inside the SDK examples tree, links the K4A wrapper
systemd/
  ithaca-bridge.service.in     templated with the user and repo path
  usbfs-memory.service         raises usbfs_memory_mb for the camera bandwidth
udev/
  99-obsensor-libusb.rules     reference copy (the SDK's own installer wins if present)
scripts/
  detect_platform.sh           L4T / JetPack / SoC, as KEY=value
  install_deps.sh              apt + websockets
  build_k4a_wrapper.sh         reuse or build the Orbbec K4A wrapper (libk4a)
  build_sdk.sh                 reuse or build OrbbecSDK v2 + inject/build the recorder
  build_server.sh              cmake + make the preview server

The three C++ pieces, and how each is built

  • Preview server (server/) — our source, built standalone against the prebuilt libOrbbecSDK.so. Simple.
  • Recorder (recorder/) — FTF's own source, a customised SDK example, so it is injected into the SDK's examples/ tree and built there (it uses the SDK's own cmake targets). It writes K4A-format MKV, and at runtime dlopens libk4a.so / libk4arecord.so — provided by the Orbbec K4A wrapper, not Microsoft's Azure Kinect SDK. Found by rpath, so no LD_LIBRARY_PATH.
  • Orbbec K4A wrapper — Orbbec's libk4a, backed by their own SDK, cloned and built by build_k4a_wrapper.sh. This is what makes Record work while setting the Microsoft SDK aside.

What install.sh does

  1. Detects L4T / JetPack / SoC (scripts/detect_platform.sh).
  2. Installs build and run dependencies (OpenCV for the recorder; no GStreamer — the direct route encodes no video).
  3. Builds (or reuses) the Orbbec K4A wrapper — libk4a for the recorder.
  4. Builds (or reuses) the OrbbecSDK, injecting and building the recorder example against the wrapper. A node that already has a good build (the Nano) is left untouched; the recorder is added to it only if missing.
  5. Builds ithaca_rgbd_server against the SDK.
  6. Generates bridge/config.json for the current user — this is where all the machine-specific paths live, so bridge.py itself stays unmodified.
  7. Installs the udev rules and the usbfs-memory service, and adds the user to the video group.
  8. Generates and starts the ithaca-bridge systemd service.

If the K4A wrapper is unavailable, install.sh still completes: the node then does preview only, and says so. Record needs the wrapper.

Re-run it after a git pull: it rebuilds, regenerates the unit and config, and restarts the service. It keeps an existing config.json (delete it to regenerate) and an existing SDK build.

The two source builds to watch on a new JetPack

Both scripts reuse an existing build when they find one. On a machine with none they clone and build from source — the steps most likely to need attention on a JetPack they have not been tried on:

  • Orbbec K4A wrapper — OB_K4A_REPO / OB_K4A_REF pin the source (default v1.10.4). If it fails, build it by hand once and re-run with its location:
    K4A_WRAPPER_DIR=/path/to/OrbbecSDK-K4A-Wrapper ./install.sh
    
  • OrbbecSDK v2 — OB_SDK_REPO / OB_SDK_REF pin the source (default main). Likewise:
    OB_SDK_ROOT=/path/to/OrbbecSDK_v2 ./install.sh
    

Both can be passed together. Neither is Microsoft's Azure Kinect SDK — the recorder gets its libk4a from the Orbbec wrapper, which is buildable from source across platforms.

Operating the node

systemctl status ithaca-bridge      # is it up
journalctl -u ithaca-bridge -f      # live log

Runtime state the bridge writes beside itself (git-ignored):

  • config.json — this machine's config (generated).
  • cam_settings.json — per-camera settings, kept across restarts.
  • stream_map.txt — the live composition: line 1 the cameras to stream, line 2 the alignment (raw or compare). The preview server re-reads it once a second, so a camera can be turned on or off, and Compare switched, without restarting.
S
Description
No description provided
Readme
134 KiB
0 Stars 1 Watchers 0 Forks
Languages
C++ 54.7%
Python 30.7%
Shell 9.3%
CMake 5.3%