yahboom
HomeTutorialsProduct
Solution
Blog
Online Store
About Us
EN/中文
Store
ROSMASTER M1 PRO📖
0.Robot Configuration and Operation Guidelines
  • 0.Unboxing and Review
  • 1.Assembly Videos
  • 2.User Manual
  • 3.Enter Docker (For Raspberry Pi)
  • 4.FAQ
  • 5.RobotManager User Guide
1.Chassis Control Course
  • 1.Robot Information Publishing
  • 2.Robot Handle Control
  • 3.Robot Keyboard Control
  • 4.Linear Velocity Calibration
  • 5.Angular Velocity Calibration
  • 6.Robot URDF Model
  • 7.Robot EKF State Estimation
2.Lidar Course
  • 1.Lidar Introduction And Use
  • 2.Lidar Obstacle Avoidance
  • 3.Lidar Following
  • 4.Lidar Guard
  • 5.Lidar Patrol
  • 6.GMapping-SLAM Mapping
  • 7.Cartographer-SLAM Mapping
  • 8.Slam-Toolbox Mapping
  • 9.Lifelong Mode Mapping
  • 10.Navigation2 Single Point Navigation
  • 11.Navigation2 Multi Point Navigation
  • 12.Cartographer Relocalization Navigation
  • 13.Slam-Toolbox Localization Navigation
  • 14.Synchronous Mapping And Navigation
  • 15.Aruco Visual Relocalization Navigation
  • 16.Mobile App Mapping And Navigation
3.USB Camera-Depth Camera Course
  • 1.USB Camera Introduction
  • 2.USB Camera Intrinsic Calibration
  • 3.Nuwa-HP60C Camera Introduction (Depth Camera Only)
  • 4.Depth Pseudo Color Image (Depth Camera Only)
  • 5.Depth Camera Distance Measurement (Depth Camera Only)
  • 6.Block Volume Calculation (Depth Camera Only)
  • 7.Edge Detection (Depth Camera Only)
  • 8.RTAB-Map SLAM Mapping (Depth Camera Only)
  • 9.RTAB-Map Navigation (Depth Camera Only)
4.Robotic Arm and 3D Space Gripping Course
  • 1.Robotic Arm Basic Usage
  • 2.Robotic Arm Kinematics
  • 3.Robotic Arm Chassis Coordination Control
  • 4.AprilTag ID Sorting
  • 5.AprilTag Height Anomaly Sorting
  • 6.AprilTag Tracking and Grasping
  • 7.Color Block Sorting
  • 8.Color Block Height Anomaly Sorting
  • 9.Color Block Tracking and Grasping
  • 10.Wood Block Shape Sorting
  • 11.KCF Tracking and Grasping Objects
  • 12.Mediapipe Gesture ID Sorting AprilTag
  • 13.Mediapipe Gesture Height Sorting AprilTag
  • 14.Desktop Tracking and Grasping AprilTag
  • 15.3D Spatial Tracking AprilTag
  • 16.Transformer Model Tracking Algorithm
  • 17.Line Following Obstacle Clearing
5.Road network planning and navigation
  • 1.Introduction To Road Network Planning
  • 2.Road Network Annotation
  • 3.Planning And Navigation Between Waypoints
  • 4.Road Network Navigation In Any Pose
  • 5.Path Re-planning
6.OpenClaw Basic Course
  • 1.Introduction to OpenClaw
  • 2.OpenClaw Core Concepts
  • 3.OpenClaw API-KEY Configuration
  • 4.OpenClaw Switch Models
  • 5.OpenClaw System Prompt Words
  • 6.OpenClaw Common CLI Commands
7.OpenClaw Interaction Method
  • 1.OpenClaw Webchat Interaction
  • 2.OpenClaw Tui Interaction
  • 3.OpenClaw Voice Dialogue Interaction
  • 4.OpenClaw WhatsApp Interaction
8.OpenClaw Development
  • 1.OpenClaw Connecting to Robot MCP Service
  • 2.Robot CLI Command Tool
  • 3.robot-control Plugin Tool
  • 4.reply-bridge Plugin Tool
  • 5.OpenClaw Multimodal Vision
  • 6.OpenClaw Chassis Control
  • 7.OpenClaw Robotic Arm Control
  • 8.OpenClaw Skills Development
  • 9.OpenClaw Scheduled Tasks
  • 10.OpenClaw Multi-Agent Intelligent Agent
  • 11.OpenClaw Active Interaction
  • 12.OpenClaw Vector Memory
9.OpenClaw Embodied intelligent application
  • 1.OpenClaw Target Tracking
  • 2.OpenClaw Arm Tracking And Grasping
  • 3.OpenClaw Arm Fixed-point Placement
  • 4.OpenClaw Waste Sorting
  • 5.OpenClaw SLAM Mapping And Navigation
  • 6.OpenClaw Navigation Transport
  • 7.OpenClaw AprilTag Grasping
  • 8.OpenClaw Color Line Patrol
  • 9.OpenClaw Visual Distance Measurement
10.OpenClaw scenario sandbox
  • 1.Map Description and Props Placement
  • 2.Building the Sandbox Map
  • 3.Visual Relocalization Marker
  • 4.Map Mapping Marker
  • 5.Sandbox Scenario Comprehensive Case
11.AI Large Model Basics
  • 1.AI Large Model Types and Principles
  • 2.RAG Retrieval Enhancement and Model Training Samples
  • 3.Embodied Intelligent Robot System Architecture
  • 4.Embodied Intelligent Functions Core Source Code
12.AI large Model Development
  • 1.Register a Model Service Provider Account
  • 2.Configuring API-KEY
  • 3.Introduction to Dify
  • 4.Basic Dify Features
  • 5.AI Large Model Development - Chatbot
  • 6.Deploy the RAG Knowledge Base
  • 7.RAG Knowledge Base + Chatbot
  • 8.AI Agent Workflow
  • 9.Custom Wake-up Response
13.AI Model - Voice Version
  • 1.Semantic Understanding and Command Following
  • 2.Multimodal Visual Understanding
  • 3.Multimodal Visual Understanding and Robotic Arm Gripping
  • 4.Multimodal Visual Understanding and SLAM Navigation
  • 5.Robotic arm gripping+Multimodal visual understand+SLAM navigation
  • 6.Intention Understanding
14.AI Model - Text Version
  • 1.Semantic Understanding and Command Following
  • 2.Multimodal Visual Understanding
  • 3.Multimodal Visual Understanding and Robotic Arm Gripping
  • 4.Multimodal Visual Understanding and SLAM Navigation
  • 5.Robotic arm gripping+Multimodal visual understand+SLAM navigation
  • 6.Intention estimation
15.Mediapipe Visual Course
  • 1.Hand detection
  • 2.Posture detection
  • 3.Overall detection
  • 4.Facial Landmark Detection
  • 5.Face detection
  • 6.Face special effects
  • 7.3D object recognition
  • 8.Brush
  • 9.Finger control
  • 10.Palm target positioning
  • 11.Fingertip trajectory recognition
  • 12.Fingertip gesture control robotic arm
  • 13.Gesture grabbing and releasing objects
  • 14.Finger control robotic arm
  • 15.Medipipe gesture control robotic arm action group
16.MoveIt2 Simulation Course
  • 1.MovelT2 configuration
  • 2.MovelT2 simulation-reality linkage
  • 3.Random movement
  • 4.Forward kinematics design
  • 5.Inverse kinematics design
  • 6.Cartesian path
  • 7.Trajectory Planning
  • 8.Collision Detection
  • 9.Scene Design
  • 10.3D perception obstacle‑avoidance
17.Multi-vehicle Course
  • 1.Multi-vehicle Control
  • 2.Multi-vehicle Navigation
  • 3.Multi-vehicle Formation
18.YOLO26 Development
  • 1.CLI Use
  • 2.Object Detection
  • 3.Instance Segmentation
  • 4.Pose Estimation
  • 5.Image Classification
  • 6.Oriented Object Detection
  • 7.YOLOv26 + DeepSORT Tracking
  • 8.Monocular Depth Estimation
19.Control Board STM32 Driver Course
  • 0.Notes (Must Read)
  • 1.About Expansion Board
  • 2.STM32 Development Environment
  • 3.Button Control
  • 4.FreeRTOS Application
  • 5.Serial Communication
  • 6.SBUS Model Aircraft Remote Control
  • 7.CAN Bus Communication
  • 8.RGB Colorful Light Bar
  • 9.Timer Interrupt to Control PWM Servo
  • 10.Control Serial Port Servos
  • 11.Nine-axis Attitude Sensor to Obtain Data
  • 12.Control Motor
  • 13.Timer Captures the Encoder Data
  • 14.1 Kinematic Analysis of Mecanum Wheel
  • 14.2 Kinematic Analysis of Ackerman
  • 14.3 Kinematic Analysis of 4WD
  • 15.PID Control Robot Movement
20.Docker Course
  • 1.Docker Introduction and Installation
  • 2.Docker Basic Commands
  • 3.Docker Submission and Multi-Terminal Access
  • 4. Docker Startup Script
  • 5.Docker-Vscode Environment Construction
21.Image Processing Basics Course
  • 1. Introduction to Open Source CV
  • 2. Image reading and display
  • 3. Image writing
  • 4. Image quality
  • 5. Pixel Operation
  • 6. Image zoom
  • 7. Image cutting
  • 8. Image translation
  • 9. Image Mirroring
  • 10. Affine Transformation
  • 11. Image Rotation
  • 12. Perspective Transformation
  • 13. Grayscale processing
  • 14. Image Binarization
  • 15. Edge Detection
  • 16. Line drawing
  • 17. Rectangle and circle drawing
  • 18. Drawing text and pictures
22.Linux System Course
  • 1.Introduction to Linux system
  • 2.Ubuntu file system
  • 3.Ubuntu common commands
  • 4.Ubuntu common editors
  • 5.Ubuntu software operation commands
  • 6.Virtual machine installation
  • 7.SSH remote control
  • 8.VNC remote control
  • 9.Transfer files remotely
  • 10.Driver library and communication
  • 11.Static IP and hotspot mode
  • 12.Bind device ID
  • 13.Capacity expansion and resource allocation
  • 14.Update system software sources
  • 15.Set root user password
  • 16.sudo free password
  • 17.Connect to WiFi network
  • 18.View system version
  • 19.Customized service management
  • 20.Back up system image
23.ROS2 Basic Course
  • 1.Introduction to ROS2
  • 2.ROS2 install Humble
  • 3.ROS2 development environment
  • 4.ROS2 workspace
  • 5.ROS2 function package
  • 6.ROS2 node
  • 7.ROS2 topic communication
  • 8.ROS2 service communication
  • 9.ROS2 action communication
  • 10.ROS2 custom interface message
  • 11.ROS2 parameter service case
  • 12.ROS2 meta-function package
  • 13.ROS2 distributed communication
  • 14.ROS2 DDS
  • 15.ROS2 time related API
  • 16.ROS2 common command tools
  • 17.ROS2 rviz2 use
  • 18.ROS2 rqt toolbox
  • 19.ROS2 Launch startup file configuration
  • 20.ROS2 recording and playback tool
  • 21.ROS2 URDF model
  • 22.ROS2 Gazebo simulation platform
  • 23.ROS2 TF2 coordinate transformation
24.Main Control Course
Jetson Orin Nano_NX
  • 1.Jetson Orin board introduction
  • 2.Restore the factory image system
  • 3.Backup SSD system
  • 4.SSD expansion
  • 5.Network configuration
  • 6.SSH remote login
  • 7.VNC remote control
  • 8.Remote file transfer
  • 9.Jtop tool
  • 10.Exchange space expansion
Raspberry Pi
  • 1. Introduction to Raspberry PI 5
  • 2. Raspberry PI system installation and backup
  • 3. Powering the Raspberry PI 5
  • 4. Startup of Raspberry PI 5
  • 5. Update and upgrade operating system
  • 6. Introduction to raspi-config tool
  • 7. config.txt file description
  • 8. Network Configuration
  • 9. remote access
  • 10. Transfer files remotely
  • 11. Set display resolution and rotation
  • 12. Set screen to sleep
  • 13. Play audio and video
  • 14. Using USB camera
  • 15. Using MIPI camera
  • 16. Get real-time temperature of Raspberry Pi
RDKX5
  • 1.Introduction to RDK X5 board
  • 2.Write system file
  • 3.Hardware interface description
  • 4.Install case and other accessories
  • 5.Network configuration
  • 6.Remote login
  • 7.Update system
  • 8.srpi-config user guide
  • 9.config. txt configuration file
  • 10.Self-startup setting
  • 11.RDK exclusive command usage
  • 12.Linux command usage
  • 13.GPIO readwrite operation
  • 14.Image classification algorithm
  • 15.Use USB camera
  • 16.Use MIPI camera
  • 17.Binocular camera depth algorithm
  • 18. Controlling RGB Cooling Fans
Download
  • System File
  • Code
  • 3D Model File
  • Software Tools
  • Hardware_Info
  • Deb function package
  • Dify AI Agent
Download ZIP

Welcome to ROSMASTER M1 PRO repository

3.Multimodal Visual Understanding and Robotic Arm Gripping

Multimodal Visual Understanding + Robotic Arm Gripping

Multimodal Visual Understanding + Robotic Arm Gripping1. Course Content2. Preparation3. Running the Cases3.1 Case 1: "Find the red block in front of you and grasp it"3.2 Case 2: "Please help me remove the AprilTag in front of you whose height is higher than 5 centimeters"4. Source Code Analysis4.1 Case 14.2 Case 2

1. Course Content

  • Basic: Run the example program to perform a comprehensive task using the robot's visual understanding combined with the robotic arm gripping function.

  • Advanced: Master the key source code newly introduced in this lesson.

Note

Note

  • For the same test command, the reply content of the AI large model is not exactly the same each time, and it will differ slightly from the screenshots in the tutorial.

  • The depth camera and the USB monocular camera have different gripping functions. Depth camera: track and grasp the target; USB monocular camera: grasp a block of the specified color.

 

2. Preparation

xxxxxxxxxx
ros2 launch yahboomcar_bringup dify_llm_agents.launch.py use_tts:=true use_camera:=true

image-20260912182502896

  • Voice recognition node

xxxxxxxxxx
ros2 run multi_brains asr_detect

image-20260912182534334

 

 

 

3. Running the Cases

The cases here are for reference only. You can write your own test commands as you like. The wooden block used is 30x30x30mm.

3.1 Case 1: "Find the red block in front of you and grasp it"

Important

  • When grasping a color block here, the USB monocular camera can only grasp a color block in front of it, and it will first adjust the camera's viewing angle.

  • First wake it up with "Hi Yahboom". The robot will give a response reply, and at this time you can give commands to the robot.

  • The robot will first have a conversation reply with the user, then act according to the command. Meanwhile, the terminal prints the following information:

image-20251222165242923

 

  • After the pick() function is called, a window titled rgb_img will open in the VNC screen to display the image of the current robot view. The robot will adjust the distance to the target object by itself. After the distance adjustment is complete, the robot will use the robotic arm to grasp the target item.

image-20251222165233107

 

Important

Note: After the robot grasps an item, the robotic arm will be in a gripping state. If you need the robotic arm to return to its initial state, you can use the following methods.

  • Method 1: Wake up the robot again and ask the robot to put down the red block it just grasped.

  • Method 2: Wake up the robot again and issue the command "End the current task" to let the robot end the current task. After the task cycle ends, the robotic arm will reset to its initial pose.

 

3.2 Case 2: "Please help me remove the AprilTag in front of you whose height is higher than 5 centimeters"

The wooden blocks used are 30x30x30mm and 30x30x60mm AprilTag wooden blocks.

  • After waking up the robot, speak the command "Please remove the AprilTag in front of you whose height is higher than 5 centimeters". The terminal prints the following information:

image-20251222165503057

 

  • A window titled result_image will open in the VNC screen, where you can see the height of each AprilTag. After the distance measurement stabilizes, the robot will adjust the distance between itself and the target by itself, then use the robotic arm to grasp the AprilTag at the target height and move it to the right side of the robot.

image-20251222165512533

 

 

4. Source Code Analysis

  • The path of the robot's action source code:

xxxxxxxxxx
~/yahboomcar_ros2_ws/yahboomcar_ws/src/multi_brains/multi_brains/action_service.py

4.1 Case 1

action_service.py program:

Case 1 uses the seewhat and pick methods of the ActionController class. The seewhat function mainly acquires the color image of the depth camera, which has already been explained in the Multimodal Visual Understanding lesson. Here, the pick function is explained.

The coordinate rules of the object in the robotic arm gripping view are shown in the figure below:

image-20251222170437018

 

The pick(x1, y1, x2, y2) function is used to call the robotic arm to grasp the target object. The parameters are the coordinates of the top-left vertex and the bottom-right vertex of the outer bounding box of the object to be grasped (the top-left corner of the image is the pixel coordinate origin). For example, in Case 1, the outer bounding box coordinates of the red block to be grasped can be learned from the large model's reply: the top-left coordinate is (365,200), and the bottom-right coordinate is (408,261).

 

pick function code description:

  • @llm_action: A decorator that registers this method as an action that can be called by the large model. Before execution, it automatically checks prerequisite states such as wake-up interrupts.

  • pick(self, x1, y1, x2, y2): Receives the pixel coordinates of the top-left corner (x1, y1) and the bottom-right corner (x2, y2) of the target's outer bounding box, and returns [bool, str] indicating whether it succeeded and the information.

  • _check_camera_action("pick", "nuwa"): Checks whether the depth camera is available and whether the current action has been interrupted; if abnormal, it directly returns a guard value to avoid subsequent invalid execution.

  • start_track_client.wait_for_service(timeout_sec=5.0): Waits for the StartTrack service to come online; if it times out after 5 seconds, the service is judged to be unavailable.

  • StartTrack.Request(x1=x1, y1=y1, x2=x2, y2=y2): Calls the visual tracking service, passing in the target bounding box coordinates so that the tracking node locks onto that region.

  • response.success: Determines whether the tracking initialization succeeded; if it failed, cancels tracking and returns an error.

  • time.sleep(1.0): Waits for tracking to run stably before proceeding to the next step.

  • self.interrupt_event.is_set(): Checks before each step whether it has been interrupted by the wake-up word; if interrupted, calls cancel_track_client to cancel tracking and exits.

  • _adjust_grasp_pose(align_x, align_y): Calls the VisualTracker Action to move the robot chassis to a position aligned with the target. align_x is the desired front-back distance, and align_y is the desired left-right offset.

  • _get_grasp_point(): Obtains the 3D grasp coordinates [success, x, y, z] of the target object in the robot's base coordinate frame.

  • self._grasp(...): Executes the final grasping action, passing in the grasp coordinates, the pitch angle grasp_pitch, and the gripper offset offset.

xxxxxxxxxx
  @llm_action
    def pick(self, x1, y1, x2, y2) -> list[bool, str]:
        if (guard := self._check_camera_action("pick", "nuwa")) is not None:
            return guard
        #step 1: tracking object
        self.get_logger().info("Start tracking object")
        if not self.start_track_client.wait_for_service(timeout_sec=5.0):
            self.get_logger().error("StartTrack service not available")
            return [False, "Tracking service not available"]
        x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
        response: StartTrack.Response = self.start_track_client.call(
            StartTrack.Request(x1=x1, y1=y1, x2=x2, y2=y2))
        if not response.success:
            self.get_logger().error("Failed to initialize tracking target")
            return [False, "Failed to initialize tracking target"]
        time.sleep(1.0)
        
        #step 2: align to target
        if self.interrupt_event.is_set():
            self.cancel_track_client.call(CancelTrack.Request())
            return [False, "pick interrupted by wakeup"]
        self.get_logger().info("Start aligning to target")
        ok, message = self._adjust_grasp_pose(align_x=self.track_align_distance[0], align_y=self.track_align_distance[1])
        if not ok:
            self.cancel_track_client.call(CancelTrack.Request())
            self.get_logger().error(f"Failed to align to target: {message}")
            return [False, f"pick failed: {message}"]
        time.sleep(2.0)

        #step 3: get grasp point coordinates
        if self.interrupt_event.is_set():
            self.cancel_track_client.call(CancelTrack.Request())
            return [False, "pick interrupted by wakeup"]
        result=self._get_grasp_point()
        if not result[0]:
            self.cancel_track_client.call(CancelTrack.Request())
            self.get_logger().error("Failed to get grasp target position")
            return [False, "Failed to get grasp target position"]
        
        #step 4: grasp object
        self.get_logger().info("Start grasping object")
        self.cancel_track_client.call(CancelTrack.Request())
        if not self._grasp(grasp_x=result[1],
                           grasp_y=result[2],
                           grasp_z=result[3],
                           grasp_pitch=self.grasp_offset[3],
                           offset=self.grasp_offset):
            self.get_logger().error("Failed to grasp object")
            return [False, "Failed to grasp object"]
        return [True, "Object grasped successfully"]

    def _adjust_grasp_pose(self,align_x, align_y) -> list[bool, str]:
        if not self.visual_tracker_client.wait_for_server(timeout_sec=5.0):
            return [False, "VisualTracker action server not available"]
        goal = VisualTracker.Goal()
        goal.align_x = float(align_x)
        goal.align_y = float(align_y)
        goal.tolerance_x = float(self.track_align_tolerance[0])
        goal.tolerance_y = float(self.track_align_tolerance[1])
        send_goal_future = self.visual_tracker_client.send_goal_async(goal)
        while rclpy.ok() and not send_goal_future.done():
            if self.interrupt_event.is_set():
                return [False, "VisualTracker interrupted by wakeup"]
            time.sleep(0.2)
        if not send_goal_future.done() or not send_goal_future.result().accepted:
            return [False, "VisualTracker goal was rejected"]

        goal_handle = send_goal_future.result()
        result_future = goal_handle.get_result_async()
        while rclpy.ok() and not result_future.done():
            if self.interrupt_event.is_set():
                try:
                    goal_handle.cancel_goal_async()
                except Exception:
                    pass
                return [False, "VisualTracker interrupted by wakeup"]
            time.sleep(0.2)
        if not result_future.done():
            return [False, "VisualTracker failed to get result"]

        status = result_future.result().status
        result = result_future.result().result
        if status == GoalStatus.STATUS_SUCCEEDED and result.success:
            self.get_logger().info("Grasp pose adjustment complete")
            return [True, result.message]
        return [False, f"Grasp pose adjustment failed: status={status}, message={result.message}"]

 

4.2 Case 2

ArUcoRemoveHigh function code description:

  • @llm_action: A decorator that registers the method as an action that can be called by the large model.

  • self.pubSix_Arm(self.aruco_detect_pose): Moves the robotic arm to the preset detection pose, making it easier for the depth camera to observe the AprilTag on the tabletop.

  • _start_aruco_detect(height_cm=target_high * 100.0): Starts an independent AprilTag detection process and passes in the height threshold (in centimeters), detecting only AprilTags whose height exceeds the threshold.

  • _wait_for_any_aruco_target(timeout_sec=15.0): Waits for the detection process to return the first AprilTag that meets the condition; if it times out after 15 seconds, returns None.

  • target_msg.id: Obtains the ID of the detected target AprilTag.

  • _adjust_grasp_pose(align_x=self.aruco_grasp_distance[0], align_y=self.aruco_grasp_distance[1]): Uses the dedicated AprilTag alignment distance parameters to adjust the chassis position so that the target is centered.

  • _get_aruco_grasp_point(target_id): Obtains the 3D grasp coordinates and angle [success, x, y, z, angle] of the target AprilTag in the robot's base coordinate frame.

  • _normalize_angle_to_0_45(grasp_point[4]): Normalizes the detected AprilTag angle to the range 0°~45°, which is used to determine the rotation direction of the gripper.

  • self._grasp(...): Executes the grasping action. grasp_roll is the gripper rotation angle, and offset is the dedicated AprilTag gripper offset parameter.

  • self._remove_pose(): After a successful grasp, moves the robotic arm to the placement pose and places the object to the side of the robot.

    @llm_action
    def ArUcoRemoveHigh(self, target_high):
        try:
            target_high = float(str(target_high).strip().strip("'\"")) / 100.0
        except (TypeError, ValueError):
            return [False, f"apriltag_remove_higher failed: invalid target_high '{target_high}', must be a number in centimeters"]
        self.get_logger().info(f"apriltag_remove_higher: target_high {target_high * 100:.1f}cm parsed to {target_high:.3f}m")

        self.pubSix_Arm(self.aruco_detect_pose)
        time.sleep(2.0)
        try:
            #step 1: launch the standalone detect process; it selects the first tag
            self.get_logger().info(f"apriltag_remove_higher: start detecting AprilTags above {target_high:.3f}m")
            self._start_aruco_detect(height_cm=target_high * 100.0)
            target_msg = self._wait_for_any_aruco_target(timeout_sec=15.0)
            if target_msg is None:
                return [False, f"No AprilTag above height {target_high:.3f}m detected (see aruco_detect process log for visible tags)"]
            target_id = target_msg.id
            self.get_logger().info(f"apriltag_remove_higher: selected target ID {target_id}")
            time.sleep(1.0)

            #step 2: align to target
            if self.interrupt_event.is_set():
                return [False, "apriltag_remove_higher interrupted by wakeup"]
            self.get_logger().info(f"apriltag_remove_higher: start aligning to target ID {target_id}")
            ok, message = self._adjust_grasp_pose(align_x=self.aruco_grasp_distance[0], align_y=self.aruco_grasp_distance[1])
            if not ok:
                self.get_logger().error(f"apriltag_remove_higher failed to align to target: {message}")
                return [False, f"apriltag_remove_higher failed to align: {message}"]
            time.sleep(3.0)

            #step 3: get grasp point coordinates (fresh measure-frame pose of the target tag)
            grasp_point = self._get_aruco_grasp_point(target_id)
            if not grasp_point[0]:
                self.get_logger().error(f"apriltag_remove_higher failed to get grasp point: {grasp_point[1]}")
                return [False, f"apriltag_remove_higher failed to get grasp point: {grasp_point[1]}"]

            #step 4: grasp object
            self.get_logger().info(f"apriltag_remove_higher: grasp point x={grasp_point[1]:.3f}, y={grasp_point[2]:.3f}, "
                f"z={grasp_point[3]:.3f}, angle={grasp_point[4]:.1f}deg")
            grasp_roll = self._normalize_angle_to_0_45(grasp_point[4])
            if not self._grasp(grasp_x=grasp_point[1],
                               grasp_y=grasp_point[2],
                               grasp_z=grasp_point[3],
                               grasp_pitch=self.aruco_grasp_offset[3],
                               grasp_roll=grasp_roll,
                               offset=self.aruco_grasp_offset):
                self.get_logger().error("apriltag_remove_higher: failed to grasp object")
                return [False, "apriltag_remove_higher failed to grasp object"]
            
            self._remove_pose()
            return [True, f"AprilTag {target_id} above height {target_high:.3f}m grasped successfully"]
        finally:
            self._stop_aruco_detect()
Multimodal Visual Understanding
Multimodal Visual Understanding and SLAM Navigation

COMPANY

  • About us
  • Team Style
  • Blog

LEARNING & EXPLORATION

  • Tutorials
  • Edge AI hardware
  • Educational robots
  • Embedded intelligent hardware

WHERE TO BUY

  • Yahboom Online Store
  • Amazon
  • Alibaba
  • AliExpress
  • Mercado

TECHNOLOGY SUPPORT

  • Email: support@yahboom.com

BE A DISTRIBUTOR

  • Email: sales@yahboom.com
QR Code

Copyright © 2017-2026 Yahboom. All Rights Reserved.

EN/中文