System designTroubleshooting

Missing OpenCV aruco module: fix the CMake calibration build

CMake finds OpenCV 4.5.4 yet reports aruco missing: the contrib modules are absent. Build OpenCV 4.6.0 with opencv_contrib and prove the fix end to end.

LumaSpec Vision9 min read Share on LinkedIn

On this page 8 sections
  1. 01Why does catkin build fail with "Could NOT find OpenCV (missing: aruco)"?
  2. 02Which OpenCV version still exposes aruco as a CMake component?
  3. 03How do you build OpenCV 4.6.0 with the contrib modules?
  4. 04Why did copying the aruco headers compile but crash with an undefined symbol?
  5. 05How do you verify the aruco fix end to end?
  6. 06What breaks the same way next in the calibration workspace?
  7. 07What does the rig need once the build is green?
  8. 08Questions

A catkin build of a ROS hand-eye calibration stack stops in CMake with Could NOT find OpenCV (missing: aruco) (found version "4.5.4"), even though OpenCV is installed and other packages compile against it. The component is missing, not the library: through OpenCV 4.6.0 the aruco module lives in opencv_contrib, and the prebuilt OpenCV on the board was compiled without it. This walkthrough is for engineers building a ROS Noetic calibration workspace on an ARM64 board. It pins the right OpenCV version, builds it with the contrib modules, undoes the header-copy workaround that compiles but crashes rviz at start-up, and proves the fix before you mount a camera and start capturing poses.

Why does catkin build fail with "Could NOT find OpenCV (missing: aruco)"?

The package requests an OpenCV aruco component with find_package(OpenCV REQUIRED imgcodecs aruco), and the OpenCV 4.5.4 installed on the board was compiled without the contrib modules that carried aruco up to version 4.6.0.

The error is not a search failure. Read the call stack in the log: OpenCVConfig.cmake under /usr/lib/aarch64-linux-gnu/cmake/opencv4/ located a valid OpenCV 4.5.4, and FindPackageHandleStandardArgs.cmake rejected it for exactly one component, (missing: aruco). The failing package is moveit_calibration_plugins, and line 22 of its CMakeLists.txt is the requirement line quoted above.

Aruco is the fiducial-marker module that finds the printed calibration target during hand-eye calibration; OpenCV's ArUco marker detection tutorial shows the markers it detects. The board is not the cause: the same failure appears on an x86 machine with a contrib-less OpenCV. ARM64 only decides how you build the replacement, not whether you need one.

Which OpenCV version still exposes aruco as a CMake component?

Pin OpenCV 4.6.0 together with opencv_contrib 4.6.0: that is the last release line where aruco is its own contrib module and OpenCVConfig.cmake offers an aruco component for find_package to test.

OpenCV 4.7.0 moved the marker API from opencv_contrib into the objdetect module of the main library. The separate aruco component disappears, so the same find_package(OpenCV REQUIRED imgcodecs aruco) line fails again on a clean 4.7 install even though the functionality is present. The calibration package as released compiles against the contrib-era headers and calls, which is why 4.6.0 is the target.

Keep base and contrib on one tag. A 4.6.0 contrib tree against a 4.5.4 base configures happily and produces ABI mismatches later, the same class of failure as the rviz crash described below. If your package feed supplies an OpenCV with the contrib modules, it must be 4.6.0 or older to expose the aruco component; otherwise build from source.

How do you build OpenCV 4.6.0 with the contrib modules?

Clone opencv and opencv_contrib, check out the 4.6.0 tag in both, configure the base build with the extra-modules flag pointed at opencv_contrib/modules, then install to /usr/local and refresh the linker cache.

This is the from-source route OpenCV documents in its Linux installation tutorial. The compile is the long step; everything around it takes minutes.

  1. Install the toolchain: sudo apt install build-essential cmake git, plus the GUI and codec development packages your board image lists.

  2. Clone both repositories side by side:

git clone https://github.com/opencv/opencv.git
git clone https://github.com/opencv/opencv_contrib.git
  1. Check out the matching tag in each:
cd opencv && git checkout 4.6.0
cd ../opencv_contrib && git checkout 4.6.0
  1. Configure from opencv/build with the contrib path:
cmake -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules \
      -DCMAKE_BUILD_TYPE=Release \
      -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF \
      -DBUILD_EXAMPLES=OFF ..
  1. Read the configure summary before compiling: the module table must list aruco. If the line is absent, the extra-modules path did not resolve, and no amount of compiling adds the component.

  2. Build and install, with the core count from nproc (the example assumes an eight-core board):

make -j8
sudo make install
sudo ldconfig
  1. Confirm the version: pkg-config --modversion opencv4 should print 4.6.0. If it still reports the old library, put /usr/local/lib/pkgconfig ahead of the default in PKG_CONFIG_PATH.

Why did copying the aruco headers compile but crash with an undefined symbol?

Headers satisfy only the compiler: once the aruco headers are pasted in and the component requirement edited out, the plugin builds and links against libopencv 4.5.4, which defines no cv::aruco functions, so loading fails.

Shared libraries may leave symbols unresolved at link time and resolve them when the loader opens them. The header-copy route therefore passes configure and compile, then dies at start-up: rviz exits with symbol lookup error: libmoveit_handeye_calibration_target_core.so.0.1.0: undefined symbol. The missing symbol is one of the cv::aruco functions the target-management code calls, and the 4.5.4 binary has no implementation for it. Deleting the aruco requirement from find_package reaches the same place by another route.

Undo the workaround completely before rebuilding:

  1. In src/moveit_calibration/moveit_calibration_plugins, run git status: the pasted aruco headers appear as untracked files. Delete them, in handeye_calibration_target and every subfolder they were copied into.

  2. Restore the edits: git checkout -- CMakeLists.txt puts the original find_package(OpenCV REQUIRED imgcodecs aruco) back.

  3. Rebuild with the 4.6.0 contrib install in place: catkin build moveit_calibration_plugins.

How do you verify the aruco fix end to end?

Three checks prove it: pkg-config reports 4.6.0, a fresh CMake configure of the package finds OpenCV 4.6.0 with no missing components, and the calibration launch passes rviz start-up without a symbol lookup error.

Work through them in order and read the output, not just the exit code.

  1. pkg-config --modversion opencv4 prints 4.6.0.

  2. Delete the package's stale cache: the failed run stored its findings in build/moveit_calibration_plugins, and CMake reuses that 4.5.4 result until the folder is gone. Then catkin build moveit_calibration_plugins and read the configure line: it must name the 4.6.0 install and list no missing components.

  3. Launch the hand-eye calibration tool set. rviz starts and the target plugin loads without the old symbol lookup error. If the error returns, a stale shared object from the header-copy attempt survives in the devel space: clean the package's build and devel output, run sudo ldconfig, and rebuild.

CMake searches /usr/local before /usr, so the new install takes over the workspace without extra flags. On a dev board that default is fine. When the same stack runs on an industrial controller with its own OpenCV, pin the search path explicitly, as the OpenCV CMake path walkthrough for industrial controllers shows.

What breaks the same way next in the calibration workspace?

Treat each remaining build failure as the same fault class — a dependency declared in a package's CMakeLists.txt that the installed library lacks — and the usual next ones are other contrib modules, ROS message packages and version conflicts between SDKs.

Map the symptom before you fix it blind:

Symptom Cause First test
Another missing: component in the OpenCV check The module lives outside base OpenCV Search the 4.6.0 configure summary for the module name
A message package is not found The package is absent from the workspace Add and build it before its dependents: fix a missing ROS message package in your calibration build
Builds here, crashes there Two OpenCV builds compete in the path OpenCV version conflicts that crash vision calibration tools
Symbol lookup error at plugin load Build-time and run-time libraries differ Diagnose a ROS OpenCV runtime library mismatch
Another SDK misses the OpenCV headers The build skips its include and library paths Camera SDK missing OpenCV headers: causes, tests and fixes

If the failure sits inside the calibration stack rather than the library, hand-eye calibration build errors: resolve dependency mismatches and hand-eye calibration plugin load failure: diagnostic steps continue from here. The systems topic page collects the rest of the build-side fixes.

What does the rig need once the build is green?

The stack you just fixed drives the physical calibration — a camera, a stand or flange mount and a printed target — and the build fix changes nothing about the optics, so size the camera for how it moves during capture.

Two arrangements cover the task. Eye-to-hand: the camera sits fixed on a camera stand or bracket and watches a target carried on the flange. Eye-in-hand: the camera rides the flange and the target sits on the bench. Pick a global shutter sensor whenever the camera moves during capture: a rolling shutter reads lines sequentially, so a fast arm move skews the frames you are calibrating with. For a moving mount, the MV-CU020-90GC pairs a global shutter with GigE. For a fixed stand, the LS-CMR-0166 runs 12 MP at 4000 × 3000 over USB3 at 30 fps, which buys margin for corner detection on the printed target.

Area scan camerasHikrobot MV-CU020-90GC 2.5 MP Area Scan Camera, GigE, GMAX4002, ColorMV-CU020-90GC
Sensor format
1/1.7"
Lens mount
C-mount
$309.00View part
Area scan cameras12 MP USB3 area scan camera, IMX226, 1/1.7" rolling shutter, 30 fps, 4000 × 3000 resolution (LS-CMR-0166)LS-CMR-0166
Sensor format
1/1.7"
Interface
USB3
$560.00View part
AccessoriesCamera stands

Stands, slide stages and brackets

265 models · from $69.00

Browse the wider sensor range on the area scan cameras category page or the camera finder. Once the rig exists, the next failures are practical rather than build-side: the eye-to-hand verification guide checks the finished calibration, and the target frame checklist covers the first run.

If the open question is the rig rather than the code, tell us the target size and mounting envelope through the contact page, or start the configurator below and match camera, mount and lens in one pass.

Build the whole station

The configurator matches a camera, lens, light, light controller and cables to each other, step by step, and lists only parts that fit what you already picked.

Start with the camera

Questions

Does a pip-installed OpenCV satisfy this catkin build?

No. The wheel installs Python bindings under site-packages and ships no OpenCVConfig.cmake, so C++ find_package never sees it and the error keeps pointing at the system OpenCV 4.5.4 in /usr/lib. The workspace needs a C++ install: a distro package or a from-source build with the contrib modules.

What changes with OpenCV 4.7 and newer?

Version 4.7.0 moved the ArUco marker API out of opencv_contrib into the objdetect module of the main library. The separate aruco component disappears, so find_package(OpenCV REQUIRED ... aruco) fails even on a clean 4.7 build. The calibration package as released targets the contrib-era API, so pin 4.6.0 until you update its source.

Can the package manager provide the contrib modules?

Sometimes. If your board's feed offers an OpenCV package built with contrib at 4.6.0 or earlier, install it and the same find_package check passes without a source build. Test it the same way: delete the package's CMake cache, rebuild, and confirm the configure line shows the installed version with no missing components.

Why does CMake still find the old OpenCV after I install 4.6.0?

CMake caches its findings in CMakeCache.txt inside the package's build folder, so a new OpenCV stays invisible until that cache clears. Delete build/moveit_calibration_plugins and rebuild, or pass -DOpenCV_DIR=/usr/local/lib/cmake/opencv4 to force the path. Read the configure line before the compile starts; it names the version actually used.

Which cameras suit the hand-eye rig this build feeds?

Pick a global shutter sensor when the camera rides the robot flange, because a rolling shutter skews frames during fast arm moves; a 2.5 MP GigE global shutter model is the usual eye-in-hand choice. For a camera fixed on a stand, a 12 MP USB3 model at 30 fps adds corner-detection margin on the printed target.