Skip to content

Conversation

@jdanieck
Copy link
Contributor

@jdanieck jdanieck commented Dec 29, 2025

📝 Description

This PR modernizes RobotVision’s CMake configuration around per‑target C++ standards and shared helpers, and introduces a new minimal Tracker service that consumes the RobotVision library via the updated targets.

Changes

  • CMAKE_SOURCE_DIR replaced with CMAKE_CURRENT_SOURCE_DIR so RobotVision can be configured and built cleanly from other directories and as a subproject.
  • Added BUILD_PYTHON_BINDINGS option so Python bindings can be disabled for consumers like the new Tracker service build.
  • Replaced deprecated (since C++11) std::bind1st in the Apollo matcher with an equivalent lambda to keep RobotVision warning‑free on modern compilers.
  • Switched RobotVision to C++17 by default via a per‑target knob (RV_CXX_STANDARD), while allowing consumers (e.g. Tracker) to override and use newer standards such as C++20.
  • Encapsulated security compiler/linker flags in a dedicated rv::security_options INTERFACE target so hardening is applied consistently and can be reused by dependents.
  • Introduced a new Tracker service that builds against RobotVision using the updated CMake targets and standard configuration

Tests

$ make cpp-tests 
cmake -S . -B build-rv-tests -DBUILD_TESTING=ON -DBUILD_PYTHON_BINDINGS=OFF
-- Using installed gtest
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests
cmake --build build-rv-tests
gmake[1]: Entering directory '/home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests'
gmake[2]: Entering directory '/home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests'
gmake[3]: Entering directory '/home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests'
gmake[3]: Leaving directory '/home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests'
[ 84%] Built target RobotVision
gmake[3]: Entering directory '/home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests'
gmake[3]: Leaving directory '/home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests'
[100%] Built target RobotVisionTests
gmake[2]: Leaving directory '/home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests'
gmake[1]: Leaving directory '/home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests'
cd build-rv-tests && ctest -V
UpdateCTestConfiguration  from :/home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests/DartConfiguration.tcl
UpdateCTestConfiguration  from :/home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests/DartConfiguration.tcl
Test project /home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests
Constructing a list of tests
Done constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end
test 1
    Start 1: RobotVisionTests

1: Test command: /home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests/test/RobotVisionTests
1: Working Directory: /home/jdanieck/repos/scenescape/controller/src/robot_vision/build-rv-tests/test
1: Test timeout computed to be: 10000000
1: [==========] Running 8 tests from 1 test suite.
1: [----------] Global test environment set-up.
1: [----------] 8 tests from MultipleObjectTrackerTest
1: [ RUN      ] MultipleObjectTrackerTest.SingleDetectionTracking
1: [       OK ] MultipleObjectTrackerTest.SingleDetectionTracking (40 ms)
1: [ RUN      ] MultipleObjectTrackerTest.SingleDetectionSingleModelTracking
1: [       OK ] MultipleObjectTrackerTest.SingleDetectionSingleModelTracking (39 ms)
1: [ RUN      ] MultipleObjectTrackerTest.MultipleDetectionTrackingEuclideanDistance
1: [       OK ] MultipleObjectTrackerTest.MultipleDetectionTrackingEuclideanDistance (430 ms)
1: [ RUN      ] MultipleObjectTrackerTest.MultipleDetectionTrackingMultiClassEuclideanDistance
1: [       OK ] MultipleObjectTrackerTest.MultipleDetectionTrackingMultiClassEuclideanDistance (430 ms)
1: [ RUN      ] MultipleObjectTrackerTest.MultipleDetectionTrackingMahalanobisDistance
1: [       OK ] MultipleObjectTrackerTest.MultipleDetectionTrackingMahalanobisDistance (431 ms)
1: [ RUN      ] MultipleObjectTrackerTest.MultipleDetectionTrackingMCEMahalanobisDistance
1: [       OK ] MultipleObjectTrackerTest.MultipleDetectionTrackingMCEMahalanobisDistance (431 ms)
1: [ RUN      ] MultipleObjectTrackerTest.MultipleDetectionTrackingStressTest
1: [       OK ] MultipleObjectTrackerTest.MultipleDetectionTrackingStressTest (1203 ms)
1: [ RUN      ] MultipleObjectTrackerTest.SingleJumpingDetectionTracking
1: [       OK ] MultipleObjectTrackerTest.SingleJumpingDetectionTracking (817 ms)
1: [----------] 8 tests from MultipleObjectTrackerTest (3824 ms total)
1: 
1: [----------] Global test environment tear-down
1: [==========] 8 tests from 1 test suite ran. (3824 ms total)
1: [  PASSED  ] 8 tests.
1/1 Test #1: RobotVisionTests .................   Passed    3.83 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   3.83 sec

✨ Type of Change

Select the type of change your PR introduces:

  • 🐞 Bug fix – Non-breaking change which fixes an issue
  • 🚀 New feature – Non-breaking change which adds functionality
  • 🔨 Refactor – Non-breaking change which refactors the code base
  • 💥 Breaking change – Changes that break existing functionality
  • 📚 Documentation update
  • 🔒 Security update
  • 🧪 Tests
  • 🚂 CI

🧪 Testing Scenarios

Describe how the changes were tested and how reviewers can test them too:

  • ✅ Tested manually
  • 🤖 Ran automated end-to-end tests

✅ Checklist

Before submitting the PR, ensure the following:

  • 🔍 PR title is clear and descriptive
  • 📝 For internal contributors: If applicable, include the JIRA ticket number (e.g., ITEP-123456) in the PR title. Do not include full URLs
  • 💬 I have commented my code, especially in hard-to-understand areas
  • 📄 I have made corresponding changes to the documentation
  • ✅ I have added tests that prove my fix is effective or my feature works

@jdanieck jdanieck self-assigned this Dec 29, 2025
@jdanieck jdanieck changed the title RobotVision CMake refactor RobotVision CMake refactor + Tracker service introduction Dec 29, 2025
@jdanieck jdanieck marked this pull request as ready for review December 29, 2025 15:14
@jdanieck jdanieck requested a review from Copilot December 30, 2025 11:09
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR modernizes RobotVision's CMake configuration by replacing deprecated C++ constructs, introducing per-target C++ standard settings, and creating a new Tracker service that consumes RobotVision as a library dependency.

Key changes:

  • Refactored CMake to use CMAKE_CURRENT_SOURCE_DIR for subproject compatibility and introduced BUILD_PYTHON_BINDINGS option
  • Replaced deprecated std::bind1st with lambda expression for modern C++ compliance
  • Introduced per-target C++ standard configuration (RV_CXX_STANDARD) with C++17 default for RobotVision
  • Created reusable scenescape::security_options INTERFACE target for consistent security hardening
  • Added new Tracker service with its own C++20 standard that integrates RobotVision as a library

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tracker/src/main.cpp New minimal tracker application demonstrating RobotVision integration
tracker/Makefile Build automation for tracker service including Docker targets
tracker/Dockerfile Multi-stage Docker build for tracker with distroless runtime
tracker/CMakeLists.txt Tracker CMake configuration consuming RobotVision with C++20
controller/src/robot_vision/test/CMakeLists.txt Updated test configuration to use per-target C++ standard and new security target
controller/src/robot_vision/include/rv/apollo/gated_hungarian_bigraph_matcher.hpp Replaced deprecated std::bind1st with lambda
controller/src/robot_vision/cmake/security_options.cmake New module encapsulating security compiler/linker flags
controller/src/robot_vision/cmake/opencv.cmake New module normalizing OpenCV target interface
controller/src/robot_vision/benchmarks/CMakeLists.txt Updated benchmark configuration for per-target standards
controller/src/robot_vision/Makefile Added cpp-tests target for C++ test execution
controller/src/robot_vision/CMakeLists.txt Major refactor replacing global settings with per-target configuration

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

# Collect all runtime library dependencies for the tracker binary
RUN mkdir -p /scenescape/runtime-libs
WORKDIR /scenescape/runtime-libs
RUN ldd /scenescape/tracker/build/tracker \
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you make sure that the intermediate build binaries are not copied and only the runtime lib files are copied? alternative is to create a deb package and dpkg install in the runtime stage.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The current implementation already ensures only runtime shared libraries are copied, not intermediate build artifacts. Here's the step-by-step breakdown with actual output from the build:

How the pipeline works

ldd /scenescape/tracker/build/tracker \
    | awk '{print $3}' \
    | grep '^/' \
    | xargs -I '{}' cp -v '{}' .

Step 1: ldd — list all runtime dependencies

$ ldd /scenescape/tracker/build/tracker
      linux-vdso.so.1 (0x00007ffff7fc5000)
      libRobotVision.so => /scenescape/tracker/build/robot_vision/libRobotVision.so (0x00007ffff7f6e000)
      libopencv_core.so.410 => /lib/x86_64-linux-gnu/libopencv_core.so.410 (0x00007ffff7b90000)
      libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ffff792a000)
      libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ffff78fd000)
      libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff7708000)
      libopencv_tracking.so.410 => /lib/x86_64-linux-gnu/libopencv_tracking.so.410 (0x00007ffff7516000)
      libopencv_calib3d.so.410 => /lib/x86_64-linux-gnu/libopencv_calib3d.so.410 (0x00007ffff72b4000)
      libgomp.so.1 => /lib/x86_64-linux-gnu/libgomp.so.1 (0x00007ffff725f000)
      libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ffff716f000)
      libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007ffff714f000)
      libGLX.so.0 => /lib/x86_64-linux-gnu/libGLX.so.0 (0x00007ffff7119000)
      liblapack.so.3 => /lib/x86_64-linux-gnu/liblapack.so.3 (0x00007ffff69e0000)
      libblas.so.3 => /lib/x86_64-linux-gnu/libblas.so.3 (0x00007ffff695f000)
      libtbb.so.12 => /lib/x86_64-linux-gnu/libtbb.so.12 (0x00007ffff6907000)
      /lib64/ld-linux-x86-64.so.2 (0x00007ffff7fc7000)
      libopencv_video.so.410 => /lib/x86_64-linux-gnu/libopencv_video.so.410 (0x00007ffff6880000)
      libopencv_imgproc.so.410 => /lib/x86_64-linux-gnu/libopencv_imgproc.so.410 (0x00007ffff62ad000)
      libopencv_features2d.so.410 => /lib/x86_64-linux-gnu/libopencv_features2d.so.410 (0x00007ffff61db000)
      libopencv_flann.so.410 => /lib/x86_64-linux-gnu/libopencv_flann.so.410 (0x00007ffff6169000)
      libGLdispatch.so.0 => /lib/x86_64-linux-gnu/libGLdispatch.so.0 (0x00007ffff60b0000)
      libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007ffff5f68000)
      libopenblas.so.0 => /lib/x86_64-linux-gnu/libopenblas.so.0 (0x00007ffff3988000)
      libgfortran.so.5 => /lib/x86_64-linux-gnu/libgfortran.so.5 (0x00007ffff3684000)
      libopencv_dnn.so.410 => /lib/x86_64-linux-gnu/libopencv_dnn.so.410 (0x00007ffff314e000)
      libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007ffff3123000)
      libprotobuf.so.32 => /lib/x86_64-linux-gnu/libprotobuf.so.32 (0x00007ffff2dc6000)
      libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007ffff5f61000)
      libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007ffff2dbc000)

Step 2: awk '{print $3}' — extract library paths (3rd column)

/scenescape/tracker/build/robot_vision/libRobotVision.so
/lib/x86_64-linux-gnu/libopencv_core.so.410
/lib/x86_64-linux-gnu/libstdc++.so.6
/lib/x86_64-linux-gnu/libgcc_s.so.1
/lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libopencv_tracking.so.410
/lib/x86_64-linux-gnu/libopencv_calib3d.so.410
/lib/x86_64-linux-gnu/libgomp.so.1
/lib/x86_64-linux-gnu/libm.so.6
/lib/x86_64-linux-gnu/libz.so.1
/lib/x86_64-linux-gnu/libGLX.so.0
/lib/x86_64-linux-gnu/liblapack.so.3
/lib/x86_64-linux-gnu/libblas.so.3
/lib/x86_64-linux-gnu/libtbb.so.12
/lib/x86_64-linux-gnu/libopencv_video.so.410
/lib/x86_64-linux-gnu/libopencv_imgproc.so.410
/lib/x86_64-linux-gnu/libopencv_features2d.so.410
/lib/x86_64-linux-gnu/libopencv_flann.so.410
/lib/x86_64-linux-gnu/libGLdispatch.so.0
/lib/x86_64-linux-gnu/libX11.so.6
/lib/x86_64-linux-gnu/libopenblas.so.0
/lib/x86_64-linux-gnu/libgfortran.so.5
/lib/x86_64-linux-gnu/libopencv_dnn.so.410
/lib/x86_64-linux-gnu/libxcb.so.1
/lib/x86_64-linux-gnu/libprotobuf.so.32
/lib/x86_64-linux-gnu/libXau.so.6
/lib/x86_64-linux-gnu/libXdmcp.so.6

Step 3: grep '^/' — filter to absolute paths only

This removes virtual entries like linux-vdso.so.1 which have no filesystem path.

Step 4: xargs ... cp -v — copy only these .so files

'/scenescape/tracker/build/robot_vision/libRobotVision.so' -> './libRobotVision.so'
'/lib/x86_64-linux-gnu/libopencv_core.so.410' -> './libopencv_core.so.410'
'/lib/x86_64-linux-gnu/libstdc++.so.6' -> './libstdc++.so.6'
'/lib/x86_64-linux-gnu/libgcc_s.so.1' -> './libgcc_s.so.1'
'/lib/x86_64-linux-gnu/libc.so.6' -> './libc.so.6'
'/lib/x86_64-linux-gnu/libopencv_tracking.so.410' -> './libopencv_tracking.so.410'
'/lib/x86_64-linux-gnu/libopencv_calib3d.so.410' -> './libopencv_calib3d.so.410'
'/lib/x86_64-linux-gnu/libgomp.so.1' -> './libgomp.so.1'
'/lib/x86_64-linux-gnu/libm.so.6' -> './libm.so.6'
'/lib/x86_64-linux-gnu/libz.so.1' -> './libz.so.1'
'/lib/x86_64-linux-gnu/libGLX.so.0' -> './libGLX.so.0'
'/lib/x86_64-linux-gnu/liblapack.so.3' -> './liblapack.so.3'
'/lib/x86_64-linux-gnu/libblas.so.3' -> './libblas.so.3'
'/lib/x86_64-linux-gnu/libtbb.so.12' -> './libtbb.so.12'
'/lib/x86_64-linux-gnu/libopencv_video.so.410' -> './libopencv_video.so.410'
'/lib/x86_64-linux-gnu/libopencv_imgproc.so.410' -> './libopencv_imgproc.so.410'
'/lib/x86_64-linux-gnu/libopencv_features2d.so.410' -> './libopencv_features2d.so.410'
'/lib/x86_64-linux-gnu/libopencv_flann.so.410' -> './libopencv_flann.so.410'
'/lib/x86_64-linux-gnu/libGLdispatch.so.0' -> './libGLdispatch.so.0'
'/lib/x86_64-linux-gnu/libX11.so.6' -> './libX11.so.6'
'/lib/x86_64-linux-gnu/libopenblas.so.0' -> './libopenblas.so.0'
'/lib/x86_64-linux-gnu/libgfortran.so.5' -> './libgfortran.so.5'
'/lib/x86_64-linux-gnu/libopencv_dnn.so.410' -> './libopencv_dnn.so.410'
'/lib/x86_64-linux-gnu/libxcb.so.1' -> './libxcb.so.1'
'/lib/x86_64-linux-gnu/libprotobuf.so.32' -> './libprotobuf.so.32'
'/lib/x86_64-linux-gnu/libXau.so.6' -> './libXau.so.6'
'/lib/x86_64-linux-gnu/libXdmcp.so.6' -> './libXdmcp.so.6'

Final result: files in /scenescape/runtime-libs

total 82888
-rw-r--r-- 1 root root   141744 libGLX.so.0
-rw-r--r-- 1 root root   723248 libGLdispatch.so.0
-rwxr-xr-x 1 root root   357072 libRobotVision.so
-rw-r--r-- 1 root root  1342984 libX11.so.6
-rw-r--r-- 1 root root    14472 libXau.so.6
-rw-r--r-- 1 root root    26728 libXdmcp.so.6
-rw-r--r-- 1 root root   522656 libblas.so.3
-rwxr-xr-x 1 root root  1999312 libc.so.6
-rw-r--r-- 1 root root   182856 libgcc_s.so.1
-rw-r--r-- 1 root root  3157224 libgfortran.so.5
-rw-r--r-- 1 root root   348056 libgomp.so.1
-rw-r--r-- 1 root root  7572240 liblapack.so.3
-rw-r--r-- 1 root root   977112 libm.so.6
-rw-r--r-- 1 root root 39608152 libopenblas.so.0
-rw-r--r-- 1 root root  2496832 libopencv_calib3d.so.410
-rw-r--r-- 1 root root  3971840 libopencv_core.so.410
-rw-r--r-- 1 root root  5457000 libopencv_dnn.so.410
-rw-r--r-- 1 root root   846080 libopencv_features2d.so.410
-rw-r--r-- 1 root root   461392 libopencv_flann.so.410
-rw-r--r-- 1 root root  5450368 libopencv_imgproc.so.410
-rw-r--r-- 1 root root  2030752 libopencv_tracking.so.410
-rw-r--r-- 1 root root   547136 libopencv_video.so.410
-rw-r--r-- 1 root root  3524496 libprotobuf.so.32
-rw-r--r-- 1 root root  2497768 libstdc++.so.6
-rw-r--r-- 1 root root   268800 libtbb.so.12
-rw-r--r-- 1 root root   170936 libxcb.so.1
-rw-r--r-- 1 root root   125376 libz.so.1

What is NOT copied

Artifact Reason
.o object files Not linked into final binary, ldd doesn't see them
.a static archives Already linked, not runtime deps
CMake cache/build files Not libraries, ldd ignores them
Headers (.h, .hpp) Not executables or libraries
Source files Not in ldd output

Why not a .deb package?

The runtime stage uses distroless/cc-debian13 which doesn't include dpkg or any package manager. The ldd + copy approach is the standard pattern for distroless images — it's essentially a manual "shrink-wrap" of runtime dependencies without adding packaging complexity.

Summary

Only 27 shared library files (all .so files) totaling ~83MB are copied to the runtime image. No intermediate build artifacts (object files, CMake files, headers, etc.) are included.

@jdanieck jdanieck merged commit 5452cef into main Jan 14, 2026
29 of 30 checks passed
@jdanieck jdanieck deleted the rv-cmake-refactor branch January 14, 2026 11:58
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