Add the MKV recorder so a node can Record, not only preview

The recorder was the gap: it is FTF's own customised SDK example (a 1139-line
K4A MKV writer), not a stock sample, and it lived only in one machine's build
tree. Bring its source into the repo and build it as part of install.

It writes K4A-format MKV — the format the rest of Ithaca reads — so it stays,
and gets its libk4a from the Orbbec K4A wrapper rather than Microsoft's Azure
Kinect SDK, which is set aside. build_k4a_wrapper.sh builds that wrapper;
build_sdk.sh injects the recorder into the SDK examples tree and builds it there
against the wrapper (it depends on the SDK's own cmake targets). Found by rpath
at runtime, so no LD_LIBRARY_PATH.

install.sh now builds wrapper -> SDK+recorder -> preview server, each reusing an
existing build so the Nano is untouched. If the wrapper is unavailable the
install still completes preview-only and says so.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
AngePierreandClaude Opus 5 committed 2026-09-10 16:21:44 +02:00
1 parent c167c836e6
commit 23b30ac1e8
7 files changed
+1460 -49

No files matched your search

+52 -21
View File
@@ -1,9 +1,11 @@
# Ithaca capture node # Ithaca capture node
The software a Jetson runs to join an Ithaca RGBD capture rig: a Python bridge that 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, and a C++ preview 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 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. 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: One checkout, one command, on any Jetson:
@@ -44,6 +46,9 @@ bridge/
server/ server/
ithaca_rgbd_server.cpp the preview server ithaca_rgbd_server.cpp the preview server
CMakeLists.txt links a prebuilt libOrbbecSDK, no GStreamer 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/ systemd/
ithaca-bridge.service.in templated with the user and repo path ithaca-bridge.service.in templated with the user and repo path
usbfs-memory.service raises usbfs_memory_mb for the camera bandwidth usbfs-memory.service raises usbfs_memory_mb for the camera bandwidth
@@ -52,41 +57,67 @@ udev/
scripts/ scripts/
detect_platform.sh L4T / JetPack / SoC, as KEY=value detect_platform.sh L4T / JetPack / SoC, as KEY=value
install_deps.sh apt + websockets install_deps.sh apt + websockets
build_sdk.sh reuse or build OrbbecSDK v2 for this platform 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 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 ## What install.sh does
1. Detects L4T / JetPack / SoC (`scripts/detect_platform.sh`). 1. Detects L4T / JetPack / SoC (`scripts/detect_platform.sh`).
2. Installs build and run dependencies (no GStreamer — the direct route encodes no 2. Installs build and run dependencies (OpenCV for the recorder; no GStreamer — the
video). direct route encodes no video).
3. Locates a working OrbbecSDK build, or clones and builds one. A node that already 3. Builds (or reuses) the Orbbec K4A wrapper — `libk4a` for the recorder.
has a good build (the Nano) is left untouched. 4. Builds (or reuses) the OrbbecSDK, injecting and building the recorder example
4. Builds `ithaca_rgbd_server` against it. against the wrapper. A node that already has a good build (the Nano) is left
5. Generates `bridge/config.json` for the current user — this is where all the 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. machine-specific paths live, so `bridge.py` itself stays unmodified.
6. Installs the udev rules and the `usbfs-memory` service, and adds the user to the 7. Installs the udev rules and the `usbfs-memory` service, and adds the user to the
`video` group. `video` group.
7. Generates and starts the `ithaca-bridge` systemd service. 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 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) restarts the service. It keeps an existing `config.json` (delete it to regenerate)
and an existing SDK build. and an existing SDK build.
## The SDK is the one thing to watch on a new JetPack ## The two source builds to watch on a new JetPack
`build_sdk.sh` reuses an existing build when it finds one. On a machine with none it Both scripts reuse an existing build when they find one. On a machine with none they
clones the official OrbbecSDK v2 and builds it — this is the step most likely to clone and build from source — the steps most likely to need attention on a JetPack
need attention on a JetPack it has not been tried on. If it fails, build the SDK by they have not been tried on:
hand once and re-run with its location:
```sh - **Orbbec K4A wrapper** — `OB_K4A_REPO` / `OB_K4A_REF` pin the source (default
OB_SDK_ROOT=/path/to/OrbbecSDK_v2 ./install.sh `v1.10.4`). If it fails, build it by hand once and re-run with its location:
``` ```sh
K4A_WRAPPER_DIR=/path/to/OrbbecSDK-K4A-Wrapper ./install.sh
```
- **OrbbecSDK v2** — `OB_SDK_REPO` / `OB_SDK_REF` pin the source (default `main`).
Likewise:
```sh
OB_SDK_ROOT=/path/to/OrbbecSDK_v2 ./install.sh
```
Override the source with `OB_SDK_REPO` / `OB_SDK_REF` to pin a tag known to build on Both can be passed together. Neither is Microsoft's Azure Kinect SDK — the recorder
your JetPack. gets its `libk4a` from the Orbbec wrapper, which is buildable from source across
platforms.
## Operating the node ## Operating the node
+21 -4
View File
@@ -34,13 +34,30 @@ fi
# ---- 1. dependencies ------------------------------------------------------ # ---- 1. dependencies ------------------------------------------------------
"$REPO/scripts/install_deps.sh" "$REPO/scripts/install_deps.sh"
# ---- 2. the SDK, then the server ------------------------------------------ # ---- 2. the K4A wrapper, the SDK (with the recorder), then the server ------
# build_sdk.sh reuses an existing build (leaving a working node untouched) or # Three compiled pieces, in dependency order:
# builds one; build_server.sh compiles ithaca_rgbd_server against it. # - the Orbbec K4A wrapper provides libk4a, which the recorder needs;
echo ">> Localisation / compilation de l'OrbbecSDK…" # - the SDK builds the library AND the recorder example against that wrapper;
# - the preview server links the built SDK.
# Each script reuses an existing build, so a working node (the Nano) is untouched.
echo ">> Localisation / compilation du wrapper K4A (libk4a, Orbbec)…"
eval "$("$REPO/scripts/build_k4a_wrapper.sh")" || true
if [[ -n "${K4A_WRAPPER_DIR:-}" ]]; then
echo " K4A_WRAPPER_DIR = $K4A_WRAPPER_DIR"
export K4A_WRAPPER_DIR
else
echo " !! wrapper K4A indisponible — le nœud fera la PREVIEW mais pas le RECORD."
fi
echo ">> Localisation / compilation de l'OrbbecSDK (+ recorder)…"
eval "$("$REPO/scripts/build_sdk.sh")" eval "$("$REPO/scripts/build_sdk.sh")"
echo " OB_SDK_ROOT = $OB_SDK_ROOT" echo " OB_SDK_ROOT = $OB_SDK_ROOT"
echo " OB_SDK_BUILD = $OB_SDK_BUILD" echo " OB_SDK_BUILD = $OB_SDK_BUILD"
if [[ -n "${RECORDER_BIN:-}" ]]; then
echo " RECORDER_BIN = $RECORDER_BIN"
else
echo " !! recorder non produit — RECORD indisponible sur ce nœud."
fi
echo ">> Compilation du serveur de preview…" echo ">> Compilation du serveur de preview…"
SERVER_BIN=$("$REPO/scripts/build_server.sh") SERVER_BIN=$("$REPO/scripts/build_server.sh")
+115
View File
@@ -0,0 +1,115 @@
# Copyright (c) Orbbec Inc. / French Touch Factory. All Rights Reserved.
# Licensed under the MIT License.
cmake_minimum_required(VERSION 3.10)
project(ob_stream_depth_color_k4arec_pipeline)
if(WIN32)
set(K4A_WRAPPER_DIR
"C:/Ithaca_Projects/RGBD/Clone K4A Depot V2/OrbbecSDK-K4A-Wrapper"
CACHE PATH "Path to OrbbecSDK-K4A-Wrapper root directory")
# Windows: the wrapper's own out-of-source build dir is conventionally "Build",
# producing MSVC import libs (k4a.lib/k4arecord.lib) alongside the DLLs in bin/.
set(K4A_WRAPPER_BUILD_SUBDIR "Build")
else()
set(K4A_WRAPPER_DIR
"$ENV{HOME}/Downloads/OrbbecSDK-K4A-Wrapper"
CACHE PATH "Path to OrbbecSDK-K4A-Wrapper root directory")
# Linux: built with a lowercase "build" dir; shared libs land in lib/, not bin/.
set(K4A_WRAPPER_BUILD_SUBDIR "build")
endif()
if(NOT EXISTS "${K4A_WRAPPER_DIR}/include/k4a/k4a.h")
message(WARNING
"${PROJECT_NAME}: K4A wrapper not found at '${K4A_WRAPPER_DIR}'. "
"Set K4A_WRAPPER_DIR to the OrbbecSDK-K4A-Wrapper root. Skipping.")
return()
endif()
add_executable(${PROJECT_NAME} depth_color_k4arec_pipeline.cpp)
# C++14: the source uses digit-separator literals (2'000'000ULL); C++11 rejects them.
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14)
# rightW/rightH (Spout) and pinCpu/pinCore (SetProcessAffinityMask) are only read
# inside #ifdef _WIN32 blocks, so non-Windows builds see them as set-but-unused —
# harmless, but this SDK's own linux_config.cmake enables -Werror globally.
if(NOT WIN32)
target_compile_options(${PROJECT_NAME} PRIVATE -Wno-unused-but-set-variable)
endif()
# SYSTEM: the K4A wrapper's public headers have GCC-pedantic issues (stray ';'
# after struct/enum decls) that -Wpedantic -Werror (set globally by this SDK's
# own linux_config.cmake) would otherwise turn into hard errors. -isystem makes
# GCC/Clang suppress warnings from headers found there.
target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE
"${K4A_WRAPPER_DIR}/include"
"${K4A_WRAPPER_DIR}/${K4A_WRAPPER_BUILD_SUBDIR}/src/orbbec/include"
"${K4A_WRAPPER_DIR}/${K4A_WRAPPER_BUILD_SUBDIR}/src/orbbec/record/sdk/include"
)
if(WIN32)
set(K4A_LIB "${K4A_WRAPPER_DIR}/${K4A_WRAPPER_BUILD_SUBDIR}/bin/k4a.lib")
set(K4ARECORD_LIB "${K4A_WRAPPER_DIR}/${K4A_WRAPPER_BUILD_SUBDIR}/bin/k4arecord.lib")
endif()
target_link_libraries(${PROJECT_NAME}
ob::${OB_SDK_LIB_NAME}
ob::examples::utils
${OpenCV_LIBS}
$<$<BOOL:${WIN32}>:${K4A_LIB}>
$<$<BOOL:${WIN32}>:${K4ARECORD_LIB}>
$<$<BOOL:${WIN32}>:SpoutDX>
# Linux: libk4a.so/libk4arecord.so are dlopen'd (RTLD_DEEPBIND) at runtime
# instead of link-time linked — see the dlopen comment block near the top
# of depth_color_k4arec_pipeline.cpp for why. Needs libdl for dlopen/dlsym.
$<$<NOT:$<BOOL:${WIN32}>>:dl>
)
set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER "examples")
if(MSVC)
set_target_properties(${PROJECT_NAME} PROPERTIES
VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
endif()
if(NOT WIN32)
# Linux: libk4a.so/libk4arecord.so aren't on the system search path — rpath
# the wrapper's build/lib so the binary finds them without LD_LIBRARY_PATH.
# BUILD_RPATH (not INSTALL_RPATH+BUILD_WITH_INSTALL_RPATH) so this ADDS to
# CMake's automatic build-tree rpath instead of replacing it — the automatic
# one is what makes libOrbbecSDK.so (built earlier in this same tree) found.
set_target_properties(${PROJECT_NAME} PROPERTIES
BUILD_RPATH "${K4A_WRAPPER_DIR}/${K4A_WRAPPER_BUILD_SUBDIR}/lib")
endif()
if(WIN32)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${K4A_WRAPPER_DIR}/${K4A_WRAPPER_BUILD_SUBDIR}/bin/k4a.dll"
"${K4A_WRAPPER_DIR}/${K4A_WRAPPER_BUILD_SUBDIR}/bin/k4arecord.dll"
"${K4A_WRAPPER_DIR}/${K4A_WRAPPER_BUILD_SUBDIR}/bin/depthengine_2_0.dll"
$<TARGET_FILE_DIR:${PROJECT_NAME}>
COMMENT "Copying K4A wrapper DLLs"
)
endif()
if(WIN32 AND TARGET opencv_world)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:opencv_world>"
$<TARGET_FILE_DIR:${PROJECT_NAME}>
COMMENT "Copying OpenCV DLL"
)
endif()
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
if(WIN32)
install(FILES
"${K4A_WRAPPER_DIR}/${K4A_WRAPPER_BUILD_SUBDIR}/bin/k4a.dll"
"${K4A_WRAPPER_DIR}/${K4A_WRAPPER_BUILD_SUBDIR}/bin/k4arecord.dll"
"${K4A_WRAPPER_DIR}/${K4A_WRAPPER_BUILD_SUBDIR}/bin/depthengine_2_0.dll"
DESTINATION bin
)
endif()
if(WIN32 AND TARGET opencv_world)
install(FILES "$<TARGET_FILE:opencv_world>" DESTINATION bin)
endif()
File diff suppressed because it is too large. Load diff
+67
View File
@@ -0,0 +1,67 @@
#!/usr/bin/env bash
# Makes sure the Orbbec K4A wrapper is built for THIS platform, and prints where
# it is as K4A_WRAPPER_DIR=... for build_sdk.sh (the recorder example needs its
# headers) and for the recorder's runtime rpath (its libk4a.so/libk4arecord.so).
#
# This is the libk4a provider — Orbbec's own, NOT Microsoft's Azure Kinect SDK.
# It bundles its own OrbbecSDK internally, so it builds standalone. The recorder
# dlopens the libk4a it produces (RTLD_DEEPBIND) rather than link-time linking it,
# which is why only its build/lib path matters at runtime, not link time.
#
# Reuses an existing build (leaving a working node untouched) or clones + builds.
set -euo pipefail
here=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
eval "$("$here/detect_platform.sh")"
REPO_URL="${OB_K4A_REPO:-https://github.com/orbbec/OrbbecSDK-K4A-Wrapper}"
# The tag the Nano runs. A caller can override to one known to build on a newer
# JetPack.
REF="${OB_K4A_REF:-v1.10.4}"
find_wrapper() {
local d="$1"
[[ -f "$d/include/k4a/k4a.h" ]] || return 1
[[ -f "$d/build/lib/libk4a.so" ]] || return 1
echo "$d"
}
for candidate in "${K4A_WRAPPER_DIR:-}" \
"$HOME/OrbbecSDK-K4A-Wrapper" \
"$HOME/Downloads/OrbbecSDK-K4A-Wrapper"; do
[[ -z "$candidate" ]] && continue
if find_wrapper "$candidate" >/dev/null 2>&1; then
echo ">> Wrapper K4A deja bati, reutilise: $candidate" >&2
echo "K4A_WRAPPER_DIR=$candidate"
exit 0
fi
done
dir="${K4A_WRAPPER_DIR:-$HOME/OrbbecSDK-K4A-Wrapper}"
echo ">> Wrapper K4A absent — clone et compilation (JetPack ${JETPACK}, ${SOC})" >&2
echo ">> ${REPO_URL} @ ${REF} -> ${dir}" >&2
if [[ ! -d "$dir/.git" ]]; then
# --recursive: the wrapper carries its OrbbecSDK and depth engine as submodules.
git clone --recursive --depth 1 --branch "$REF" "$REPO_URL" "$dir" >&2
fi
mkdir -p "$dir/build"
(
cd "$dir/build"
cmake .. -DCMAKE_BUILD_TYPE=Release >&2
make -j"$(nproc)" k4a k4arecord >&2
)
if ! find_wrapper "$dir" >/dev/null 2>&1; then
cat >&2 <<EOF
!! La compilation du wrapper K4A ne s'est pas terminee comme attendu
!! (libk4a.so absent de $dir/build/lib).
!! Bâtis-le une fois a la main, puis relance install.sh avec :
!! K4A_WRAPPER_DIR=$dir ./install.sh
EOF
exit 1
fi
echo ">> Wrapper K4A bati: $dir" >&2
echo "K4A_WRAPPER_DIR=$dir"
+62 -23
View File
@@ -1,71 +1,108 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Makes sure an OrbbecSDK v2 build exists for THIS platform, and prints where it # Makes sure an OrbbecSDK v2 build exists for THIS platform — INCLUDING the custom
# is as OB_SDK_ROOT=... / OB_SDK_BUILD=... / OB_SDK_GENERATED=... for build_server.sh. # MKV recorder example — and prints where it all is:
#
# OB_SDK_ROOT / OB_SDK_BUILD / OB_SDK_GENERATED the SDK
# RECORDER_BIN the recorder binary, or empty
# #
# Never ships a prebuilt binary between Jetsons: CUDA and glibc differ by # Never ships a prebuilt binary between Jetsons: CUDA and glibc differ by
# generation, so the SDK is built from source on the machine that will run it. # generation, so everything is built from source on the machine that runs it. The
# The heavy artifact stays out of git. # heavy artifacts stay out of git.
# #
# Order of preference: # The recorder is FTF's own source (recorder/ in this repo), not a stock SDK
# 1. An existing build pointed to by $OB_SDK_ROOT — reused as-is. This is what # example, so it is injected into the SDK's examples tree before the build and
# keeps a working node (the Nano already has one) untouched. # compiled there — it depends on the SDK's own cmake targets (ob::examples::utils).
# 2. A build at one of the known locations, likewise reused. # It needs the Orbbec K4A wrapper's headers; build_k4a_wrapper.sh provides them.
# 3. A fresh clone + build. On a new JetPack this is the step to watch; if it #
# fails, build the SDK by hand once and re-run install.sh with OB_SDK_ROOT set. # Order of preference for the SDK itself:
# 1. $OB_SDK_ROOT if it already holds a build — reused, which keeps a working
# node (the Nano) untouched.
# 2. A build at a known location, likewise reused.
# 3. A fresh clone + build.
set -euo pipefail set -euo pipefail
here=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) here=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
repo=$(cd "$here/.." && pwd)
eval "$("$here/detect_platform.sh")" eval "$("$here/detect_platform.sh")"
# The official v2 source. Pinned loosely: a caller can override both to match a
# tag known to build on their JetPack.
SDK_REPO="${OB_SDK_REPO:-https://github.com/orbbec/OrbbecSDK_v2.git}" SDK_REPO="${OB_SDK_REPO:-https://github.com/orbbec/OrbbecSDK_v2.git}"
SDK_REF="${OB_SDK_REF:-main}" SDK_REF="${OB_SDK_REF:-main}"
find_build() { find_build() {
local root="$1" local root="$1" b
[[ -f "$root/include/libobsensor/ObSensor.hpp" ]] || return 1 [[ -f "$root/include/libobsensor/ObSensor.hpp" ]] || return 1
local b
b=$(ls -d "$root"/build/linux_* 2>/dev/null | head -1) b=$(ls -d "$root"/build/linux_* 2>/dev/null | head -1)
[[ -z "$b" ]] && b="$root/build" [[ -z "$b" ]] && b="$root/build"
[[ -f "$b/lib/libOrbbecSDK.so" ]] || return 1 [[ -f "$b/lib/libOrbbecSDK.so" ]] || return 1
echo "$b" echo "$b"
} }
recorder_bin_in() { # echoes the recorder path under a build dir if present
local b="$1"
[[ -x "$b/bin/ob_stream_depth_color_k4arec_pipeline" ]] \
&& echo "$b/bin/ob_stream_depth_color_k4arec_pipeline"
}
emit() { emit() {
local root="$1" build="$2" local root="$1" build="$2"
echo "OB_SDK_ROOT=$root" echo "OB_SDK_ROOT=$root"
echo "OB_SDK_BUILD=$build" echo "OB_SDK_BUILD=$build"
echo "OB_SDK_GENERATED=$root/build/src/generated" echo "OB_SDK_GENERATED=$root/build/src/generated"
echo "RECORDER_BIN=$(recorder_bin_in "$build")"
} }
# 1 & 2: reuse whatever is already built. # Drops the FTF recorder into the SDK examples tree and registers it, so a plain
# example build picks it up. Idempotent.
inject_recorder() {
local root="$1"
local dst="$root/examples/1.stream.depth_color.k4arec.pipeline"
mkdir -p "$dst"
cp "$repo/recorder/depth_color_k4arec_pipeline.cpp" "$dst/"
cp "$repo/recorder/CMakeLists.txt" "$dst/"
local ex_cmake="$root/examples/CMakeLists.txt"
if [[ -f "$ex_cmake" ]] \
&& ! grep -q "1.stream.depth_color.k4arec.pipeline" "$ex_cmake"; then
echo "add_subdirectory(1.stream.depth_color.k4arec.pipeline)" >> "$ex_cmake"
fi
}
# 1 & 2: reuse an existing SDK build. Only inject/rebuild the recorder if it is
# missing there — never disturb the library build.
for candidate in "${OB_SDK_ROOT:-}" \ for candidate in "${OB_SDK_ROOT:-}" \
"$HOME/OrbbecSDK_v2" \ "$HOME/OrbbecSDK_v2" \
"$HOME/OrbbecSDK_v2_jetson"; do "$HOME/OrbbecSDK_v2_jetson"; do
[[ -z "$candidate" ]] && continue [[ -z "$candidate" ]] && continue
if b=$(find_build "$candidate" 2>/dev/null); then if b=$(find_build "$candidate" 2>/dev/null); then
echo ">> SDK deja bati, reutilise: $candidate" >&2 echo ">> SDK deja bati, reutilise: $candidate" >&2
if [[ -z "$(recorder_bin_in "$b")" && -n "${K4A_WRAPPER_DIR:-}" ]]; then
echo ">> Recorder absent de ce build — injection et compilation…" >&2
inject_recorder "$candidate"
( cd "$b" && cmake .. -DOB_BUILD_EXAMPLES=ON \
-DK4A_WRAPPER_DIR="$K4A_WRAPPER_DIR" >&2 \
&& make -j"$(nproc)" ob_stream_depth_color_k4arec_pipeline >&2 ) || true
fi
emit "$candidate" "$b" emit "$candidate" "$b"
exit 0 exit 0
fi fi
done done
# 3: clone + build from source. # 3: clone + build from source, with examples and the recorder.
root="${OB_SDK_ROOT:-$HOME/OrbbecSDK_v2}" root="${OB_SDK_ROOT:-$HOME/OrbbecSDK_v2}"
echo ">> Aucun SDK bati — clone et compilation (JetPack ${JETPACK}, ${SOC})" >&2 echo ">> Aucun SDK bati — clone et compilation (JetPack ${JETPACK}, ${SOC})" >&2
echo ">> ${SDK_REPO} @ ${SDK_REF} -> ${root}" >&2 [[ -d "$root/.git" ]] || git clone --depth 1 --branch "$SDK_REF" "$SDK_REPO" "$root" >&2
if [[ ! -d "$root/.git" ]]; then inject_recorder "$root"
git clone --depth 1 --branch "$SDK_REF" "$SDK_REPO" "$root" >&2
fi # The recorder needs the wrapper; without it the SDK still builds (its CMakeLists
# skips the recorder with a warning), giving preview-only.
cmake_k4a=()
[[ -n "${K4A_WRAPPER_DIR:-}" ]] && cmake_k4a=(-DK4A_WRAPPER_DIR="$K4A_WRAPPER_DIR")
build="$root/build/linux_$(uname -m)" build="$root/build/linux_$(uname -m)"
mkdir -p "$build" mkdir -p "$build"
( (
cd "$build" cd "$build"
# -DOB_BUILD_EXAMPLES=ON gives the k4a recorder sample used as recorder_bin. cmake ../.. -DCMAKE_BUILD_TYPE=Release -DOB_BUILD_EXAMPLES=ON "${cmake_k4a[@]}" >&2
cmake ../.. -DCMAKE_BUILD_TYPE=Release -DOB_BUILD_EXAMPLES=ON >&2
make -j"$(nproc)" >&2 make -j"$(nproc)" >&2
) )
@@ -74,9 +111,11 @@ if ! b=$(find_build "$root" 2>/dev/null); then
!! La compilation du SDK ne s'est pas terminee comme attendu. !! La compilation du SDK ne s'est pas terminee comme attendu.
!! Bâtis-le une fois a la main, puis relance install.sh en pointant dessus : !! Bâtis-le une fois a la main, puis relance install.sh en pointant dessus :
!! OB_SDK_ROOT=<chemin> ./install.sh !! OB_SDK_ROOT=$root ./install.sh
EOF EOF
exit 1 exit 1
fi fi
echo ">> SDK bati: $b" >&2 echo ">> SDK bati: $b" >&2
[[ -z "$(recorder_bin_in "$b")" ]] && \
echo ">> NOTE: recorder non produit (wrapper K4A absent) — preview seule." >&2
emit "$root" "$b" emit "$root" "$b"
+4 -1
View File
@@ -17,9 +17,12 @@ echo ">> Dependances pour JetPack ${JETPACK} (L4T ${L4T}, ${SOC})"
# back to pip when the distro is too old to carry it. # back to pip when the distro is too old to carry it.
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends \ sudo apt-get install -y --no-install-recommends \
build-essential cmake pkg-config \ build-essential cmake pkg-config git \
libusb-1.0-0-dev libudev-dev liblz4-dev libjpeg-turbo8-dev \ libusb-1.0-0-dev libudev-dev liblz4-dev libjpeg-turbo8-dev \
libopencv-dev \
python3 python3-pip python3 python3-pip
# libopencv-dev: the MKV recorder links OpenCV (image handling). liblz4/libjpeg:
# the preview server. libusb/libudev: the SDK and the K4A wrapper.
if ! python3 -c 'import websockets' 2>/dev/null; then if ! python3 -c 'import websockets' 2>/dev/null; then
echo ">> websockets absent — installation via pip" echo ">> websockets absent — installation via pip"