diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index b6826a3a0..35b959355 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -14,6 +14,7 @@ on:
- cron: "0 */6 * * 1-5"
jobs:
+ # Lint and non-integration tests for all packages
integration-test-in-studio-container:
uses: PickNikRobotics/moveit_pro_ci/.github/workflows/workspace_integration_test.yaml@v0.0.7
with:
@@ -22,6 +23,32 @@ jobs:
secrets:
moveit_license_key: ${{ secrets.STUDIO_CI_LICENSE_KEY }}
+ # Per-config objective integration tests (run in parallel via matrix)
+ objective-integration-test:
+ strategy:
+ fail-fast: false
+ matrix:
+ config_package:
+ - lab_sim
+ - kitchen_sim
+ - april_tag_sim
+ - grinding_sim
+ - dual_arm_sim
+ - factory_sim
+ - hangar_sim
+ - kinova_sim
+ - space_satellite_sim
+ - space_satellite_sim_camera_cal
+ - mock_sim
+ - multi_arm_sim
+ uses: PickNikRobotics/moveit_pro_ci/.github/workflows/workspace_integration_test.yaml@v0.0.6
+ with:
+ image_tag: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.ref || github.ref_name }}
+ config_package: ${{ matrix.config_package }}
+ colcon_test_args: "--executor sequential"
+ secrets:
+ moveit_license_key: ${{ secrets.STUDIO_CI_LICENSE_KEY }}
+
ensure-no-ssh-in-gitmodules:
name: Ensure no SSH URLs in .gitmodules
runs-on: ubuntu-22.04
diff --git a/src/april_tag_sim/CMakeLists.txt b/src/april_tag_sim/CMakeLists.txt
index 3715fb432..8180bc7b1 100644
--- a/src/april_tag_sim/CMakeLists.txt
+++ b/src/april_tag_sim/CMakeLists.txt
@@ -28,8 +28,13 @@ install(
)
if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ ament_add_pytest_test(
+ objectives_integration_test test/objectives_integration_test.py
+ TIMEOUT 600
+ ENV MOVEIT_CONFIG_PACKAGE=april_tag_sim MOVEIT_HOST_USER_WORKSPACE=${CMAKE_SOURCE_DIR})
endif()
ament_package()
diff --git a/src/april_tag_sim/package.xml b/src/april_tag_sim/package.xml
index 24bbf1161..5b3acee7c 100644
--- a/src/april_tag_sim/package.xml
+++ b/src/april_tag_sim/package.xml
@@ -28,7 +28,9 @@
ur_description
velocity_force_controller
+ ament_cmake_pytest
ament_lint_auto
+ moveit_pro_test_utils
ament_clang_format
ament_clang_tidy
diff --git a/src/april_tag_sim/test/objectives_integration_test.py b/src/april_tag_sim/test/objectives_integration_test.py
new file mode 100644
index 000000000..93ba5566e
--- /dev/null
+++ b/src/april_tag_sim/test/objectives_integration_test.py
@@ -0,0 +1,57 @@
+# Copyright 2026 PickNik Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the PickNik Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import pytest
+from moveit_pro_test_utils.objective_test_fixture import (
+ ExecuteObjectiveResource,
+ execute_objective_resource as execute_objective_resource,
+ get_objective_pytest_params,
+ run_objective,
+)
+
+cancel_objectives = set()
+
+# Objectives requiring AprilTag camera perception (no simulated camera feed in CI)
+skip_objectives = {
+ "Pick April Tag Labeled Object", # Requires AprilTag detection + camera
+ "Collect Angled AprilTag Detection Data", # Requires camera feed
+ "Collect AprilTag Detection Data", # Requires camera feed
+ "Collect Parallel AprilTag Detection Data", # Requires camera feed
+}
+
+
+@pytest.mark.parametrize(
+ "objective_id, should_cancel",
+ get_objective_pytest_params("april_tag_sim", cancel_objectives, skip_objectives),
+)
+def test_all_objectives(
+ objective_id: str,
+ should_cancel: bool,
+ execute_objective_resource: ExecuteObjectiveResource,
+):
+ run_objective(objective_id, should_cancel, execute_objective_resource)
diff --git a/src/dual_arm_sim/CMakeLists.txt b/src/dual_arm_sim/CMakeLists.txt
index eb41ba94f..4d5618f0d 100644
--- a/src/dual_arm_sim/CMakeLists.txt
+++ b/src/dual_arm_sim/CMakeLists.txt
@@ -15,8 +15,13 @@ install(
)
if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ ament_add_pytest_test(
+ objectives_integration_test test/objectives_integration_test.py
+ TIMEOUT 600
+ ENV MOVEIT_CONFIG_PACKAGE=dual_arm_sim MOVEIT_HOST_USER_WORKSPACE=${CMAKE_SOURCE_DIR})
endif()
ament_package()
diff --git a/src/dual_arm_sim/package.xml b/src/dual_arm_sim/package.xml
index 9f925622d..498977339 100644
--- a/src/dual_arm_sim/package.xml
+++ b/src/dual_arm_sim/package.xml
@@ -20,8 +20,10 @@
ament_clang_tidy
ament_cmake_copyright
ament_cmake_lint_cmake
+ ament_cmake_pytest
ament_flake8
ament_lint_auto
+ moveit_pro_test_utils
picknik_ament_copyright
diff --git a/src/dual_arm_sim/test/objectives_integration_test.py b/src/dual_arm_sim/test/objectives_integration_test.py
new file mode 100644
index 000000000..64befc17d
--- /dev/null
+++ b/src/dual_arm_sim/test/objectives_integration_test.py
@@ -0,0 +1,54 @@
+# Copyright 2026 PickNik Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the PickNik Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import pytest
+from moveit_pro_test_utils.objective_test_fixture import (
+ ExecuteObjectiveResource,
+ execute_objective_resource as execute_objective_resource,
+ get_objective_pytest_params,
+ run_objective,
+)
+
+cancel_objectives = set()
+
+# Objectives requiring user input or ML/GPU inference
+skip_objectives = {
+ "Teleoperate", # Requires user teleoperation input
+}
+
+
+@pytest.mark.parametrize(
+ "objective_id, should_cancel",
+ get_objective_pytest_params("dual_arm_sim", cancel_objectives, skip_objectives),
+)
+def test_all_objectives(
+ objective_id: str,
+ should_cancel: bool,
+ execute_objective_resource: ExecuteObjectiveResource,
+):
+ run_objective(objective_id, should_cancel, execute_objective_resource)
diff --git a/src/factory_sim/CMakeLists.txt b/src/factory_sim/CMakeLists.txt
index d0928b05c..22131ac8e 100644
--- a/src/factory_sim/CMakeLists.txt
+++ b/src/factory_sim/CMakeLists.txt
@@ -31,8 +31,13 @@ install(DIRECTORY "${PICKNIK_ACCESSORIES_PATH}"
FILES_MATCHING PATTERN "*")
if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ ament_add_pytest_test(
+ objectives_integration_test test/objectives_integration_test.py
+ TIMEOUT 600
+ ENV MOVEIT_CONFIG_PACKAGE=factory_sim MOVEIT_HOST_USER_WORKSPACE=${CMAKE_SOURCE_DIR})
endif()
ament_package()
diff --git a/src/factory_sim/package.xml b/src/factory_sim/package.xml
index f83042099..53fcd195b 100644
--- a/src/factory_sim/package.xml
+++ b/src/factory_sim/package.xml
@@ -20,7 +20,9 @@
moveit_studio_agent
moveit_pro_behavior
+ ament_cmake_pytest
ament_lint_auto
+ moveit_pro_test_utils
ament_clang_format
ament_clang_tidy
diff --git a/src/factory_sim/test/objectives_integration_test.py b/src/factory_sim/test/objectives_integration_test.py
new file mode 100644
index 000000000..121c39c7f
--- /dev/null
+++ b/src/factory_sim/test/objectives_integration_test.py
@@ -0,0 +1,57 @@
+# Copyright 2026 PickNik Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the PickNik Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import pytest
+from moveit_pro_test_utils.objective_test_fixture import (
+ ExecuteObjectiveResource,
+ execute_objective_resource as execute_objective_resource,
+ get_objective_pytest_params,
+ run_objective,
+)
+
+cancel_objectives = set()
+
+# Objectives requiring user input or ML/GPU inference
+skip_objectives = {
+ "Automask from File", # Requires ML segmentation model
+ "Automask from Camera", # Requires ML segmentation model + camera
+ "Automask Camera Iterate Masks", # Requires ML segmentation model + camera
+ "Pick and Place Brackets from Left Bin", # Requires ML perception pipeline
+}
+
+
+@pytest.mark.parametrize(
+ "objective_id, should_cancel",
+ get_objective_pytest_params("factory_sim", cancel_objectives, skip_objectives),
+)
+def test_all_objectives(
+ objective_id: str,
+ should_cancel: bool,
+ execute_objective_resource: ExecuteObjectiveResource,
+):
+ run_objective(objective_id, should_cancel, execute_objective_resource)
diff --git a/src/grinding_sim/CMakeLists.txt b/src/grinding_sim/CMakeLists.txt
index b87bb4e0b..cb1e86159 100644
--- a/src/grinding_sim/CMakeLists.txt
+++ b/src/grinding_sim/CMakeLists.txt
@@ -25,8 +25,13 @@ install(
)
if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ ament_add_pytest_test(
+ objectives_integration_test test/objectives_integration_test.py
+ TIMEOUT 600
+ ENV MOVEIT_CONFIG_PACKAGE=grinding_sim MOVEIT_HOST_USER_WORKSPACE=${CMAKE_SOURCE_DIR})
endif()
ament_package()
diff --git a/src/grinding_sim/package.xml b/src/grinding_sim/package.xml
index f80313b0f..59be76415 100644
--- a/src/grinding_sim/package.xml
+++ b/src/grinding_sim/package.xml
@@ -20,7 +20,9 @@
moveit_studio_agent
moveit_pro_behavior
+ ament_cmake_pytest
ament_lint_auto
+ moveit_pro_test_utils
ament_clang_format
ament_clang_tidy
diff --git a/src/grinding_sim/test/objectives_integration_test.py b/src/grinding_sim/test/objectives_integration_test.py
new file mode 100644
index 000000000..8369c00dc
--- /dev/null
+++ b/src/grinding_sim/test/objectives_integration_test.py
@@ -0,0 +1,54 @@
+# Copyright 2026 PickNik Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the PickNik Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import pytest
+from moveit_pro_test_utils.objective_test_fixture import (
+ ExecuteObjectiveResource,
+ execute_objective_resource as execute_objective_resource,
+ get_objective_pytest_params,
+ run_objective,
+)
+
+cancel_objectives = set()
+
+# Objectives requiring user input or perception hardware
+skip_objectives = {
+ "Grind Machined Part", # Requires admittance control user interaction
+}
+
+
+@pytest.mark.parametrize(
+ "objective_id, should_cancel",
+ get_objective_pytest_params("grinding_sim", cancel_objectives, skip_objectives),
+)
+def test_all_objectives(
+ objective_id: str,
+ should_cancel: bool,
+ execute_objective_resource: ExecuteObjectiveResource,
+):
+ run_objective(objective_id, should_cancel, execute_objective_resource)
diff --git a/src/hangar_sim/CMakeLists.txt b/src/hangar_sim/CMakeLists.txt
index 14a7e1635..44bd43362 100644
--- a/src/hangar_sim/CMakeLists.txt
+++ b/src/hangar_sim/CMakeLists.txt
@@ -32,8 +32,13 @@ install(IMPORTED_RUNTIME_ARTIFACTS moveit_studio_plugins::dummy_controller_handl
lib)
if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ ament_add_pytest_test(
+ objectives_integration_test test/objectives_integration_test.py
+ TIMEOUT 600
+ ENV MOVEIT_CONFIG_PACKAGE=hangar_sim MOVEIT_HOST_USER_WORKSPACE=${CMAKE_SOURCE_DIR})
endif()
ament_package()
diff --git a/src/hangar_sim/package.xml b/src/hangar_sim/package.xml
index 9eb2a1e65..67abc6658 100644
--- a/src/hangar_sim/package.xml
+++ b/src/hangar_sim/package.xml
@@ -29,7 +29,9 @@
ur_description
velocity_force_controller
+ ament_cmake_pytest
ament_lint_auto
+ moveit_pro_test_utils
ament_clang_format
ament_clang_tidy
diff --git a/src/hangar_sim/test/objectives_integration_test.py b/src/hangar_sim/test/objectives_integration_test.py
new file mode 100644
index 000000000..d7c22fe48
--- /dev/null
+++ b/src/hangar_sim/test/objectives_integration_test.py
@@ -0,0 +1,59 @@
+# Copyright 2026 PickNik Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the PickNik Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import pytest
+from moveit_pro_test_utils.objective_test_fixture import (
+ ExecuteObjectiveResource,
+ execute_objective_resource as execute_objective_resource,
+ get_objective_pytest_params,
+ run_objective,
+)
+
+cancel_objectives = set()
+
+# Objectives requiring user input or ML/GPU inference
+skip_objectives = {
+ "Count Boxes", # Requires ML segmentation
+ "ML Move Boxes to Loading Zone", # Requires ML segmentation
+ "Segment Image from Point", # Requires clicked point + ML segmentation
+ "Segment Image from Text Prompt", # Requires ML segmentation
+ "Segment Point Cloud from Clicked Point", # Requires clicked point + ML segmentation
+ "Verify Box Count", # Requires ML segmentation (calls Count Boxes)
+}
+
+
+@pytest.mark.parametrize(
+ "objective_id, should_cancel",
+ get_objective_pytest_params("hangar_sim", cancel_objectives, skip_objectives),
+)
+def test_all_objectives(
+ objective_id: str,
+ should_cancel: bool,
+ execute_objective_resource: ExecuteObjectiveResource,
+):
+ run_objective(objective_id, should_cancel, execute_objective_resource)
diff --git a/src/kitchen_sim/CMakeLists.txt b/src/kitchen_sim/CMakeLists.txt
index c7784596b..e1f61681b 100644
--- a/src/kitchen_sim/CMakeLists.txt
+++ b/src/kitchen_sim/CMakeLists.txt
@@ -15,8 +15,13 @@ install(
)
if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ ament_add_pytest_test(
+ objectives_integration_test test/objectives_integration_test.py
+ TIMEOUT 600
+ ENV MOVEIT_CONFIG_PACKAGE=kitchen_sim MOVEIT_HOST_USER_WORKSPACE=${CMAKE_SOURCE_DIR})
endif()
ament_package()
diff --git a/src/kitchen_sim/package.xml b/src/kitchen_sim/package.xml
index 015c1022b..c581d8312 100644
--- a/src/kitchen_sim/package.xml
+++ b/src/kitchen_sim/package.xml
@@ -20,8 +20,10 @@
ament_clang_tidy
ament_cmake_copyright
ament_cmake_lint_cmake
+ ament_cmake_pytest
ament_flake8
ament_lint_auto
+ moveit_pro_test_utils
picknik_ament_copyright
diff --git a/src/kitchen_sim/test/objectives_integration_test.py b/src/kitchen_sim/test/objectives_integration_test.py
new file mode 100644
index 000000000..fafa191b0
--- /dev/null
+++ b/src/kitchen_sim/test/objectives_integration_test.py
@@ -0,0 +1,58 @@
+# Copyright 2026 PickNik Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the PickNik Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import pytest
+from moveit_pro_test_utils.objective_test_fixture import (
+ ExecuteObjectiveResource,
+ execute_objective_resource as execute_objective_resource,
+ get_objective_pytest_params,
+ run_objective,
+)
+
+cancel_objectives = set()
+
+# Objectives requiring user input (clicked point) or ML/GPU inference
+skip_objectives = {
+ "Segment Point Cloud from Point", # Requires clicked point + ML segmentation
+ "Grasp Object from Point", # Requires clicked point + ML segmentation
+ "Generate Graspable Object", # Requires ML segmentation
+ "Segment Image from Point", # Requires clicked point + ML segmentation
+ "Segment Image from Prompt", # Requires ML segmentation
+}
+
+
+@pytest.mark.parametrize(
+ "objective_id, should_cancel",
+ get_objective_pytest_params("kitchen_sim", cancel_objectives, skip_objectives),
+)
+def test_all_objectives(
+ objective_id: str,
+ should_cancel: bool,
+ execute_objective_resource: ExecuteObjectiveResource,
+):
+ run_objective(objective_id, should_cancel, execute_objective_resource)
diff --git a/src/lab_sim/package.xml b/src/lab_sim/package.xml
index 6bddc8072..1e2691f3e 100644
--- a/src/lab_sim/package.xml
+++ b/src/lab_sim/package.xml
@@ -30,7 +30,9 @@
velocity_force_controller
lab_sim_behaviors
+ ament_cmake_pytest
ament_lint_auto
+ moveit_pro_test_utils
ament_clang_format
ament_clang_tidy
diff --git a/src/moveit_pro_kinova_configs/kinova_sim/CMakeLists.txt b/src/moveit_pro_kinova_configs/kinova_sim/CMakeLists.txt
index 1a86011df..7dabb5a4c 100644
--- a/src/moveit_pro_kinova_configs/kinova_sim/CMakeLists.txt
+++ b/src/moveit_pro_kinova_configs/kinova_sim/CMakeLists.txt
@@ -16,8 +16,13 @@ install(
)
if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ ament_add_pytest_test(
+ objectives_integration_test test/objectives_integration_test.py
+ TIMEOUT 600
+ ENV MOVEIT_CONFIG_PACKAGE=kinova_sim MOVEIT_HOST_USER_WORKSPACE=${CMAKE_SOURCE_DIR})
endif()
ament_package()
diff --git a/src/moveit_pro_kinova_configs/kinova_sim/package.xml b/src/moveit_pro_kinova_configs/kinova_sim/package.xml
index cca74f3be..355e43735 100644
--- a/src/moveit_pro_kinova_configs/kinova_sim/package.xml
+++ b/src/moveit_pro_kinova_configs/kinova_sim/package.xml
@@ -22,6 +22,9 @@
realsense2_description
velocity_force_controller
+ ament_cmake_pytest
+ moveit_pro_test_utils
+
ament_cmake
diff --git a/src/moveit_pro_kinova_configs/kinova_sim/test/objectives_integration_test.py b/src/moveit_pro_kinova_configs/kinova_sim/test/objectives_integration_test.py
new file mode 100644
index 000000000..befd2b16e
--- /dev/null
+++ b/src/moveit_pro_kinova_configs/kinova_sim/test/objectives_integration_test.py
@@ -0,0 +1,55 @@
+# Copyright 2026 PickNik Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the PickNik Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import pytest
+from moveit_pro_test_utils.objective_test_fixture import (
+ ExecuteObjectiveResource,
+ execute_objective_resource as execute_objective_resource,
+ get_objective_pytest_params,
+ run_objective,
+)
+
+cancel_objectives = set()
+
+# Objectives requiring user input or ML/GPU inference
+skip_objectives = {
+ "April Tag Object Registration", # Requires AprilTag detection + camera
+ "Demo Trajectory Stitching", # Requires user interaction for trajectory recording
+}
+
+
+@pytest.mark.parametrize(
+ "objective_id, should_cancel",
+ get_objective_pytest_params("kinova_sim", cancel_objectives, skip_objectives),
+)
+def test_all_objectives(
+ objective_id: str,
+ should_cancel: bool,
+ execute_objective_resource: ExecuteObjectiveResource,
+):
+ run_objective(objective_id, should_cancel, execute_objective_resource)
diff --git a/src/moveit_pro_kinova_configs/space_satellite_sim/CMakeLists.txt b/src/moveit_pro_kinova_configs/space_satellite_sim/CMakeLists.txt
index dc8273f82..47645d3f9 100644
--- a/src/moveit_pro_kinova_configs/space_satellite_sim/CMakeLists.txt
+++ b/src/moveit_pro_kinova_configs/space_satellite_sim/CMakeLists.txt
@@ -26,8 +26,13 @@ install(DIRECTORY "${PICKNIK_ACCESSORIES_SHARE_DIR}"
FILES_MATCHING PATTERN "*")
if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ ament_add_pytest_test(
+ objectives_integration_test test/objectives_integration_test.py
+ TIMEOUT 600
+ ENV MOVEIT_CONFIG_PACKAGE=space_satellite_sim MOVEIT_HOST_USER_WORKSPACE=${CMAKE_SOURCE_DIR})
endif()
ament_package()
diff --git a/src/moveit_pro_kinova_configs/space_satellite_sim/package.xml b/src/moveit_pro_kinova_configs/space_satellite_sim/package.xml
index 5d43ec288..e8e6baa0c 100644
--- a/src/moveit_pro_kinova_configs/space_satellite_sim/package.xml
+++ b/src/moveit_pro_kinova_configs/space_satellite_sim/package.xml
@@ -27,6 +27,9 @@
robotiq_description
velocity_force_controller
+ ament_cmake_pytest
+ moveit_pro_test_utils
+
ament_cmake
diff --git a/src/moveit_pro_kinova_configs/space_satellite_sim/test/objectives_integration_test.py b/src/moveit_pro_kinova_configs/space_satellite_sim/test/objectives_integration_test.py
new file mode 100644
index 000000000..3af5bd5d8
--- /dev/null
+++ b/src/moveit_pro_kinova_configs/space_satellite_sim/test/objectives_integration_test.py
@@ -0,0 +1,56 @@
+# Copyright 2026 PickNik Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the PickNik Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import pytest
+from moveit_pro_test_utils.objective_test_fixture import (
+ ExecuteObjectiveResource,
+ execute_objective_resource as execute_objective_resource,
+ get_objective_pytest_params,
+ run_objective,
+)
+
+cancel_objectives = set()
+
+# Objectives requiring user input or ML/GPU inference
+skip_objectives = {
+ "Grapple Moving Satellite via Fiducial Tracking", # Requires AprilTag detection + camera
+}
+
+
+@pytest.mark.parametrize(
+ "objective_id, should_cancel",
+ get_objective_pytest_params(
+ "space_satellite_sim", cancel_objectives, skip_objectives
+ ),
+)
+def test_all_objectives(
+ objective_id: str,
+ should_cancel: bool,
+ execute_objective_resource: ExecuteObjectiveResource,
+):
+ run_objective(objective_id, should_cancel, execute_objective_resource)
diff --git a/src/moveit_pro_kinova_configs/space_satellite_sim_camera_cal/CMakeLists.txt b/src/moveit_pro_kinova_configs/space_satellite_sim_camera_cal/CMakeLists.txt
index 9cb3ced4b..aeb6f4379 100644
--- a/src/moveit_pro_kinova_configs/space_satellite_sim_camera_cal/CMakeLists.txt
+++ b/src/moveit_pro_kinova_configs/space_satellite_sim_camera_cal/CMakeLists.txt
@@ -42,8 +42,13 @@ install(DIRECTORY "${PICKNIK_ACCESSORIES_SHARE_DIR}"
FILES_MATCHING PATTERN "*")
if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ ament_add_pytest_test(
+ objectives_integration_test test/objectives_integration_test.py
+ TIMEOUT 600
+ ENV MOVEIT_CONFIG_PACKAGE=space_satellite_sim_camera_cal MOVEIT_HOST_USER_WORKSPACE=${CMAKE_SOURCE_DIR})
endif()
ament_package()
diff --git a/src/moveit_pro_kinova_configs/space_satellite_sim_camera_cal/package.xml b/src/moveit_pro_kinova_configs/space_satellite_sim_camera_cal/package.xml
index ec035c1da..17fafdc62 100644
--- a/src/moveit_pro_kinova_configs/space_satellite_sim_camera_cal/package.xml
+++ b/src/moveit_pro_kinova_configs/space_satellite_sim_camera_cal/package.xml
@@ -17,6 +17,9 @@
space_satellite_sim
apriltag_ros
+ ament_cmake_pytest
+ moveit_pro_test_utils
+
ament_cmake
diff --git a/src/moveit_pro_kinova_configs/space_satellite_sim_camera_cal/test/objectives_integration_test.py b/src/moveit_pro_kinova_configs/space_satellite_sim_camera_cal/test/objectives_integration_test.py
new file mode 100644
index 000000000..c758631fd
--- /dev/null
+++ b/src/moveit_pro_kinova_configs/space_satellite_sim_camera_cal/test/objectives_integration_test.py
@@ -0,0 +1,55 @@
+# Copyright 2026 PickNik Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the PickNik Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import pytest
+from moveit_pro_test_utils.objective_test_fixture import (
+ ExecuteObjectiveResource,
+ execute_objective_resource as execute_objective_resource,
+ get_objective_pytest_params,
+ run_objective,
+)
+
+cancel_objectives = set()
+
+# No objectives require user input or ML/GPU — all non-runnable ones are already
+# tagged runnable="false" in their XML and will be auto-skipped by the fixture.
+skip_objectives = set()
+
+
+@pytest.mark.parametrize(
+ "objective_id, should_cancel",
+ get_objective_pytest_params(
+ "space_satellite_sim_camera_cal", cancel_objectives, skip_objectives
+ ),
+)
+def test_all_objectives(
+ objective_id: str,
+ should_cancel: bool,
+ execute_objective_resource: ExecuteObjectiveResource,
+):
+ run_objective(objective_id, should_cancel, execute_objective_resource)
diff --git a/src/moveit_pro_ur_configs/mock_sim/CMakeLists.txt b/src/moveit_pro_ur_configs/mock_sim/CMakeLists.txt
index 85c7cfaaa..55c3d9edd 100644
--- a/src/moveit_pro_ur_configs/mock_sim/CMakeLists.txt
+++ b/src/moveit_pro_ur_configs/mock_sim/CMakeLists.txt
@@ -16,8 +16,13 @@ install(
)
if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ ament_add_pytest_test(
+ objectives_integration_test test/objectives_integration_test.py
+ TIMEOUT 600
+ ENV MOVEIT_CONFIG_PACKAGE=mock_sim MOVEIT_HOST_USER_WORKSPACE=${CMAKE_SOURCE_DIR})
endif()
ament_package()
diff --git a/src/moveit_pro_ur_configs/mock_sim/package.xml b/src/moveit_pro_ur_configs/mock_sim/package.xml
index f1b321318..7f6b51060 100644
--- a/src/moveit_pro_ur_configs/mock_sim/package.xml
+++ b/src/moveit_pro_ur_configs/mock_sim/package.xml
@@ -15,6 +15,9 @@
picknik_ur_base_config
+ ament_cmake_pytest
+ moveit_pro_test_utils
+
ament_cmake
diff --git a/src/moveit_pro_ur_configs/mock_sim/test/objectives_integration_test.py b/src/moveit_pro_ur_configs/mock_sim/test/objectives_integration_test.py
new file mode 100644
index 000000000..b1a141c3c
--- /dev/null
+++ b/src/moveit_pro_ur_configs/mock_sim/test/objectives_integration_test.py
@@ -0,0 +1,52 @@
+# Copyright 2026 PickNik Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the PickNik Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import pytest
+from moveit_pro_test_utils.objective_test_fixture import (
+ ExecuteObjectiveResource,
+ execute_objective_resource as execute_objective_resource,
+ get_objective_pytest_params,
+ run_objective,
+)
+
+cancel_objectives = set()
+
+# No objectives require user input or ML/GPU in mock_sim.
+skip_objectives = set()
+
+
+@pytest.mark.parametrize(
+ "objective_id, should_cancel",
+ get_objective_pytest_params("mock_sim", cancel_objectives, skip_objectives),
+)
+def test_all_objectives(
+ objective_id: str,
+ should_cancel: bool,
+ execute_objective_resource: ExecuteObjectiveResource,
+):
+ run_objective(objective_id, should_cancel, execute_objective_resource)
diff --git a/src/moveit_pro_ur_configs/multi_arm_sim/CMakeLists.txt b/src/moveit_pro_ur_configs/multi_arm_sim/CMakeLists.txt
index 7720d49c9..1c01f7639 100644
--- a/src/moveit_pro_ur_configs/multi_arm_sim/CMakeLists.txt
+++ b/src/moveit_pro_ur_configs/multi_arm_sim/CMakeLists.txt
@@ -15,8 +15,13 @@ install(
)
if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ ament_add_pytest_test(
+ objectives_integration_test test/objectives_integration_test.py
+ TIMEOUT 600
+ ENV MOVEIT_CONFIG_PACKAGE=multi_arm_sim MOVEIT_HOST_USER_WORKSPACE=${CMAKE_SOURCE_DIR})
endif()
ament_package()
diff --git a/src/moveit_pro_ur_configs/multi_arm_sim/package.xml b/src/moveit_pro_ur_configs/multi_arm_sim/package.xml
index 237686e82..d5f11b69a 100644
--- a/src/moveit_pro_ur_configs/multi_arm_sim/package.xml
+++ b/src/moveit_pro_ur_configs/multi_arm_sim/package.xml
@@ -23,7 +23,9 @@
robotiq_controllers
ur_description
+ ament_cmake_pytest
ament_lint_auto
+ moveit_pro_test_utils
ament_clang_format
ament_clang_tidy
diff --git a/src/moveit_pro_ur_configs/multi_arm_sim/test/objectives_integration_test.py b/src/moveit_pro_ur_configs/multi_arm_sim/test/objectives_integration_test.py
new file mode 100644
index 000000000..770b6d55a
--- /dev/null
+++ b/src/moveit_pro_ur_configs/multi_arm_sim/test/objectives_integration_test.py
@@ -0,0 +1,54 @@
+# Copyright 2026 PickNik Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the PickNik Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import pytest
+from moveit_pro_test_utils.objective_test_fixture import (
+ ExecuteObjectiveResource,
+ execute_objective_resource as execute_objective_resource,
+ get_objective_pytest_params,
+ run_objective,
+)
+
+cancel_objectives = set()
+
+# Objectives requiring user input
+skip_objectives = {
+ "Teleoperate", # Requires user teleoperation input
+}
+
+
+@pytest.mark.parametrize(
+ "objective_id, should_cancel",
+ get_objective_pytest_params("multi_arm_sim", cancel_objectives, skip_objectives),
+)
+def test_all_objectives(
+ objective_id: str,
+ should_cancel: bool,
+ execute_objective_resource: ExecuteObjectiveResource,
+):
+ run_objective(objective_id, should_cancel, execute_objective_resource)