diff --git a/src/rai_core/rai/tools/ros2/manipulation/custom.py b/src/rai_core/rai/tools/ros2/manipulation/custom.py index 08c45b955..f3d801152 100644 --- a/src/rai_core/rai/tools/ros2/manipulation/custom.py +++ b/src/rai_core/rai/tools/ros2/manipulation/custom.py @@ -454,3 +454,16 @@ def _run(self): return "Arm successfully reset." else: return "Failed to reset the arm." + + +# GetGrabbingPointTool is only imported for type checking above (to avoid a +# circular import), so Pydantic cannot resolve the "GetGrabbingPointTool" +# annotation on GetObjectPositionsTool by itself. Resolve it here once the real +# class can be imported. If rai_perception is not installed, the tool stays +# unresolved, as before. +try: + from rai_perception.tools import GetGrabbingPointTool # noqa: F811 + + GetObjectPositionsTool.model_rebuild() +except ImportError: + pass diff --git a/tests/tools/ros2/test_manipulation_custom.py b/tests/tools/ros2/test_manipulation_custom.py index 15613e253..bd2709e62 100644 --- a/tests/tools/ros2/test_manipulation_custom.py +++ b/tests/tools/ros2/test_manipulation_custom.py @@ -420,3 +420,13 @@ def test_objects_detected( camera_info_topic="/camera/rgb/camera_info", object_name="cup", ) + + +def test_get_object_positions_tool_model_is_fully_defined(): + """Regression test: the forward reference to GetGrabbingPointTool must resolve. + + Building the tool with model_construct() skips this check, so look at the + Pydantic completeness flag directly. + """ + pytest.importorskip("rai_perception.tools") + assert GetObjectPositionsTool.__pydantic_complete__