# ArUco -- the square fiducial marker library from the AVA group at the # University of Cordoba (Rafael Munoz-Salinas). Not the same thing as OpenCV's # cv::aruco module: this is the standalone library, and it is the one the Plus # Toolkit's optical marker tracker is written against (it includes # markerdetector.h, posetracker.h, cameraparameters.h and uses # aruco::MarkerDetector / aruco::MarkerPoseTracker). # # Why we want it: with aruco, Plus turns ANY camera -- a webcam, a V4L2 device, # an Intel RealSense -- into a pose tracker by watching printed markers. That is # the only optical tracking path in the whole neuronavigation stack that needs # no proprietary SDK and no five-figure camera. See # docs/neuronavigation-hardware.md. # # LICENCE, READ THIS BEFORE REUSING THE TAG: LICENSE says "ArUco is released # under a GPLv3 license", while every source file carries a BSD 2-clause notice, # and SourceForge's project metadata still says "BSD License" (which was true of # aruco 1.x/2.x). We package under the most restrictive of the three, GPL-3.0, # because that is what the project-level statement says and it is the only # reading that is safe if the header notices are the stale ones. Consequence: # anything linking this becomes GPL-3 as a combined work. That is fine for # PlusLib (BSD-style is GPL-compatible) and for NaviNIBS (LGPL-3), and it does # not touch 3D Slicer, which reaches Plus over OpenIGTLink rather than by # linking. Clarification requested upstream: # docs/upstream/aruco-licence-and-cmake.md Name: aruco Version: 3.1.12 Release: 2%{?dist} Summary: Square fiducial marker detection and pose estimation library # See the long note above. GPL-3.0-only per LICENSE; source headers say BSD-2. License: GPL-3.0-only URL: https://www.uco.es/investiga/grupos/ava/portfolio/aruco/ Source0: https://downloads.sourceforge.net/project/%{name}/%{version}/%{name}-%{version}.zip # Three things that stop this being packageable, all in the install step: # - cmake_minimum_required(VERSION 3.0), which CMake 4 (Fedora 44 ships # 4.3.0) refuses outright; # - hardcoded lib/ and include/ destinations, so nothing lands in lib64; # - arucoConfig.cmake defines only variables and hardcodes an absolute # LINK_DIRECTORIES, so find_package(aruco) yields no imported target -- # and PlusLib's FIND_PACKAGE(aruco NO_MODULE) then calls # GET_TARGET_PROPERTY(aruco IMPORTED_CONFIGURATIONS) and fails. # The patch fixes all three: GNUInstallDirs, install(EXPORT) with a real # imported target, and a config that resolves relative to itself while keeping # the legacy aruco_LIBS / aruco_INCLUDE_DIRS variables for existing consumers. Patch0: aruco-install-layout-and-cmake-target.patch # aruco 3.1.12 is from 2019 and does not build against OpenCV 5, which this # repository ships. Verified green against BOTH OpenCV 4.13 (stock Fedora) and # OpenCV 5.0 (this COPR). Five incompatibilities, all mechanical: # - the nested compatibility headers (opencv2/calib3d/calib3d.hpp and the # rest) are gone; the flat forms have existed since OpenCV 2.4, so # rewriting the 88 of them keeps OpenCV 4 working too; # - cv::Exception's first parameter is cv::Error::Code, now a strongly typed # enum, so the 45 call sites passing a bare int need a cast; # - the module libraries were renamed (calib3d -> calib/3d, features2d -> # features), so the hardcoded opencv_calib3d / opencv_features2d link # names fail; ${OpenCV_LIBS} is right for both versions; # - cv::FastFeatureDetector now needs opencv2/features.hpp included # explicitly, version-guarded so OpenCV 4 keeps its own spelling; # - compilerOptions.cmake overwrote CMAKE_CXX_FLAGS_ wholesale and # options.cmake defaulted an unconfigured build to Debug, which together # produced an -O0 library with debug logging on. Now they append. # No algorithm is touched. Offered upstream in # docs/upstream/aruco-licence-and-cmake.md. Patch1: aruco-opencv5-compat.patch BuildRequires: cmake >= 3.10 BuildRequires: gcc-c++ BuildRequires: ninja-build BuildRequires: unzip BuildRequires: opencv-devel BuildRequires: eigen3-devel BuildRequires: pkgconfig %description ArUco detects square fiducial markers in images and recovers their full 6-DoF pose from a calibrated camera. It provides marker dictionaries, a detector tuned for speed and robustness, marker maps for multi-marker rigid bodies, fractal markers for wide range coverage, and a correlation-filter tracker. Given a calibrated camera and markers of known size, this turns an ordinary camera into an optical pose tracker -- which is how the Plus Toolkit's optical marker tracker works, and therefore how a neuronavigation setup can track a stimulation coil without a dedicated tracking system. %package devel Summary: Development files for %{name} Requires: %{name}%{?_isa} = %{version}-%{release} Requires: opencv-devel%{?_isa} %description devel Headers, pkg-config file and CMake package configuration for building against %{name}. %package utils Summary: Command line tools for %{name} Requires: %{name}%{?_isa} = %{version}-%{release} %description utils Command line tools shipped with %{name}: marker and marker-map creation, camera calibration, detection from images and video, and the tracker demos. These are what you use to print a marker board and calibrate the camera before tracking anything. %prep %autosetup -p1 -n %{name}-%{version} # The tarball bundles a copy of Eigen under 3rdparty/eigen3 and defaults to # using it. Fedora has eigen3; remove the bundled copy so the build cannot # silently fall back to it. rm -rf 3rdparty/eigen3 %build # Fedora's default build type (RelWithDebInfo) is kept. An earlier revision of # this spec cleared CMAKE_BUILD_TYPE to make install(EXPORT) emit NOCONFIG, # because PlusLib's aruco block only handles RELEASE, NOCONFIG and DEBUG -- but # aruco sets CMAKE_CXX_FLAGS_DEBUG to "-O0 -g3 -DDEBUG", so that quietly # produced an unoptimised library. The NOCONFIG name is provided by the # installed CMake config instead (it aliases whatever configuration exists), # which gets PlusLib what it needs without giving everyone else a debug build. # # CMAKE_BUILD_TYPE must be set explicitly. cmake/options.cmake does # `if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Debug")`, and Fedora's # %%cmake does not set one -- so the default here is a Debug build whose # CMAKE_CXX_FLAGS_DEBUG ("-O0 -g3 -DDEBUG -D_DEBUG -DPRINT_DEBUG_MESSAGES") # is appended after %%{build_cxxflags} and wins. That would ship an # unoptimised, debug-logging build of a real-time vision library. %cmake -G Ninja \ -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo \ -DBUILD_SHARED_LIBS:BOOL=ON \ -DUSE_OWN_EIGEN3:BOOL=OFF \ -DBUILD_UTILS:BOOL=ON \ -DBUILD_GLSAMPLES:BOOL=OFF \ -DBUILD_TESTS:BOOL=OFF \ -DINSTALL_DOC:BOOL=OFF \ -DARUCO_DEVINSTALL:BOOL=ON \ -DCMAKE_SKIP_INSTALL_RPATH:BOOL=ON %cmake_build %install %cmake_install # The uninstalled pkg-config file describes a build tree, so it is meaningless # once installed and would point consumers at paths that do not exist. rm -f %{buildroot}%{_libdir}/pkgconfig/aruco-uninstalled.pc %check # Assert an optimised build FIRST, while the working directory is still the # source tree. aruco's compilerOptions.cmake used to overwrite # CMAKE_CXX_FLAGS_ wholesale, turning RelWithDebInfo into # "-O1 ... -DPRINT_DEBUG_MESSAGES" and defaulting an unconfigured build to # Debug at -O0; Patch1 makes it append instead. Ninja records the flags in # build.ninja. A missing file fails here rather than passing silently. flags="$PWD/%{_vpath_builddir}/build.ninja" test -f "$flags" || { echo "cannot find $flags to verify build flags"; exit 1; } libflags=$(grep -m1 '^ *FLAGS = .*aruco' "$flags" || grep -m1 '^ *FLAGS = ' "$flags") test -n "$libflags" || { echo "no compile flags found in $flags"; exit 1; } case "$libflags" in *-O0*|*-O1*) echo "not an optimised build: $libflags"; exit 1 ;; esac case "$libflags" in *PRINT_DEBUG_MESSAGES*) echo "aruco debug logging is enabled"; exit 1 ;; esac # No camera in a build root, so check what does not need one: the library # resolves, the CMake package gives consumers a real imported target (which is # the thing PlusLib needs and upstream did not provide), pkg-config is sane, # and the marker generator actually produces a marker. ldd -r %{buildroot}%{_libdir}/libaruco.so.3.1 | grep '^undefined symbol' \ && { echo "libaruco has undefined symbols"; exit 1; } || : # It must NOT have picked up a bundled Eigen; Eigen is header-only, so the # check is that the build did not resurrect 3rdparty. test ! -d 3rdparty/eigen3 PKG_CONFIG_PATH=%{buildroot}%{_libdir}/pkgconfig \ pkg-config --exists --print-errors aruco test "$(PKG_CONFIG_PATH=%{buildroot}%{_libdir}/pkgconfig pkg-config --modversion aruco)" = "%{version}" # The imported target is the whole point of Patch0: PlusLib does # GET_TARGET_PROPERTY(aruco IMPORTED_CONFIGURATIONS) and aborts without it. mkdir -p %{_builddir}/consumer && cd %{_builddir}/consumer cat > CMakeLists.txt <<'EOF' cmake_minimum_required(VERSION 3.16) project(consumer CXX) find_package(aruco REQUIRED NO_MODULE) if(NOT TARGET aruco) message(FATAL_ERROR "find_package(aruco) defined no imported target") endif() get_target_property(_configs aruco IMPORTED_CONFIGURATIONS) if(NOT _configs) message(FATAL_ERROR "imported target aruco has no IMPORTED_CONFIGURATIONS") endif() foreach(_c IN LISTS _configs) get_target_property(_loc aruco IMPORTED_LOCATION_${_c}) if(NOT EXISTS ${_loc}) message(FATAL_ERROR "IMPORTED_LOCATION_${_c} does not exist: ${_loc}") endif() message(STATUS "aruco config ${_c}: ${_loc}") endforeach() # PlusLib only accepts RELEASE, NOCONFIG or DEBUG and aborts on anything else # (src/PlusDataCollection/CMakeLists.txt, "dependent files don't exist"). A # Fedora build is RelWithDebInfo, so the installed config aliases it to # NOCONFIG; assert that alias is present rather than discovering it is gone # when PlusLib fails to configure. set(_plus_ok FALSE) foreach(_c IN LISTS _configs) if(_c MATCHES "^(RELEASE|NOCONFIG|DEBUG)$") set(_plus_ok TRUE) endif() endforeach() if(NOT _plus_ok) message(FATAL_ERROR "no RELEASE/NOCONFIG/DEBUG configuration exported; PlusLib would abort") endif() message(STATUS "aruco version ${aruco_VERSION}") EOF cmake -DCMAKE_PREFIX_PATH=%{buildroot}%{_prefix} \ -Daruco_DIR=%{buildroot}%{_libdir}/cmake/aruco . \ | grep -E 'aruco (config|version)' # And the tools run: generate a marker and confirm it is a real image. The # library is only in the buildroot at this point, hence LD_LIBRARY_PATH. cd %{_builddir} export LD_LIBRARY_PATH=%{buildroot}%{_libdir} %{buildroot}%{_bindir}/aruco_print_marker 42 %{_builddir}/marker42.png 200 \ 2>/dev/null || %{buildroot}%{_bindir}/aruco_print_marker 42 %{_builddir}/marker42.png test -s %{_builddir}/marker42.png file %{_builddir}/marker42.png | grep -q 'PNG image data' # And it must not be the accidental Debug build: aruco's Debug flavour # defines PRINT_DEBUG_MESSAGES, which makes the detector chatter on stdout. echo "aruco: library, CMake target, pkg-config and marker generation all OK" %files %license LICENSE License-gpl.txt %doc README ChangeLog %{_libdir}/libaruco.so.3.1* %files devel %{_includedir}/aruco/ %{_libdir}/libaruco.so %{_libdir}/pkgconfig/aruco.pc %{_libdir}/cmake/aruco/ %files utils %{_bindir}/aruco_* %{_bindir}/fractal_tracker # The printable A4 chessboard for aruco_calibration -- you need this before # any pose estimate means anything. %{_datadir}/aruco/ %changelog * Thu Oct 08 2026 Morgan Hough - 3.1.12-2 - Rebuild: the f43 build (11039714) predates OpenCV 5 in the COPR and links libopencv_core.so.411, which conflicts with opencv-devel 5 (blocked PlusLib). * Sat Sep 26 2026 Morgan Hough - 3.1.12-1 - Initial package. Required by PlusLib's optical marker tracker, which is the only tracking path in the neuronavigation stack that needs no proprietary SDK. Patched to install under GNUInstallDirs, to build under CMake 4, and to export a real CMake imported target -- without which PlusLib's find_package(aruco) cannot work at all.