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

9.Scene Design

Scene Design

Scene Design1. Course Content2. Preparation3. Case Demonstration4. Core Source Code Analysis

1. Course Content

  • This course implements a virtual scene: a three-layer shelf is built, and after the robot arm grasps a cylindrical object, it plans to the middle upper and lower layers to simulate the action of placing the object, while avoiding the shelf obstacles.

2. Preparation

ros2 launch yahboomcar_bringup moveit_simulation.launch.py sim2real:=true rviz_config:=demo

Once the program starts, when You can start planning now! appears in the terminal, it means the startup was successful, as shown in the figure below:

image-20260914145339789

 

3. Case Demonstration

xxxxxxxxxx
ros2 run moveit_demo set_scene

After the program runs, the robot arm will plan to the set init pose, then a purple cylindrical object will be added to the gripper. Next, it starts planning and executing the simulated action of placing the object between the middle two layers: first grasp the cylinder from the upper shelf, then the robot arm returns to the initial position -> plans a trajectory to move to the lower shelf to place the object -> finally the robot arm returns to the initial pose.

image-20260914170234516

image-20260914170304108

image-20260914170321806

 

 

4. Core Source Code Analysis

  • Source code path

xxxxxxxxxx
~/yahboomcar_ros2_ws/yahboomcar_ws/src/moveit_demo/src/set_scene.cpp

Loading the scene file and adding the cylinder:

  • ament_index_cpp::get_package_share_directory("moveit_demo"): Gets the installation path of the moveit_demo package.

  • loadSceneFile(scene_path): Loads the shape.scene scene file and parses out the collision object list.

  • Position adaptation: Maps the x coordinate in the scene model to pose.position.x = 0.26, pose.position.y = -old_x, adjusting the scene model to the front of the robot.

  • Orientation adaptation: Rotates the orientation of the scene model by 90° (about the Z axis) through quaternion multiplication, aligning it with the robot coordinate frame.

  • addCollisionObjects(scene_objects): Adds all collision objects in the scene to the planning scene.

  • Cylinder pre-placement: Adds a cylinder with a height of 0.03 m and a radius of 0.02 m at the middle shelf position (0.24, 0.0, 0.22).

  • applyCollisionObject(cylinder_pre): Applies the cylinder collision object to the scene.

Allowed Collision Matrix (ACM) configuration:

  • create_publisher<PlanningScene>("/planning_scene", 10): Creates a planning scene publisher, used to send ACM updates.

  • getLinkModelNames(): Gets the names of all links of the robot.

  • gripper_links = {"llink2", "rlink2", "arm5_Link"}: The gripper link list, used to re-enable collision detection with base_link.

  • shelf_exempt = {"llink2", "rlink2"}: The links exempted from collision detection with the shelf, allowing the gripper to touch the shelf edges.

  • shelf_ids = {"Box_0"..."Box_4"}: The list of shelf collision object IDs.

  • entry_names: Builds the ACM entry name list, including robot links + cylinder + shelf collision objects.

  • allowed_collision_matrix.entry_values[i].enabled[j] = false: Sets that collision between the two objects is allowed (collision detection is ignored).

  • Between robot links: disables self-collision, but re-enables collision detection between the gripper and base_link.

  • Between the shelf and the gripper: collision between llink2/rlink2 and the shelf is allowed (exempted), and collision detection between other links and the shelf is disabled.

Execution flow:

  • Step 1: Move to the init initial pose.

  • Step 2: Move to the middle shelf position through a joint-space target, specifying each joint angle (radians).

  • Step 4: attachObject("cylinder", "gripper_tcp", touch_links): Attaches the cylinder to the gripper; touch_links specifies the links allowed to make contact.

  • Step 4.5: Retreat to the init pose to prepare for the lower shelf motion.

  • Step 5: Move to the lower shelf position through a joint-space target.

  • Step 6: Place the cylinder — first remove it from the scene, then re-add it at the lower shelf position (0.24, 0.0, 0.09).

  • removeCollisionObjects(to_remove): Removes the cylinder from the scene.

  • detachObject("cylinder"): Releases the attachment relationship between the cylinder and the gripper.

  • applyCollisionObject(cyl_placed): Re-adds the cylinder at the lower shelf position.

  • Step 7: Move to the init pose; the task is complete.

​x
  void initialize()
  {
    move_group_interface_ =
      std::make_shared<moveit::planning_interface::MoveGroupInterface>(
        shared_from_this(), "arm_group");
    planning_scene_interface_ =
      std::make_shared<moveit::planning_interface::PlanningSceneInterface>();

    move_group_interface_->setNumPlanningAttempts(30);
    move_group_interface_->setPlanningTime(20.0);
    move_group_interface_->setGoalPositionTolerance(0.02);
    move_group_interface_->setGoalJointTolerance(0.05);  // wider goal region for joint-space plans
    move_group_interface_->setWorkspace(-0.1, -0.4, -0.05, 0.5, 0.4, 0.7);
    move_group_interface_->setMaxVelocityScalingFactor(1.0);
    move_group_interface_->setMaxAccelerationScalingFactor(1.0);
    move_group_interface_->setEndEffectorLink("gripper_tcp");
    move_group_interface_->setPoseReferenceFrame("measure");

    const moveit::core::JointModelGroup* joint_model_group =
      move_group_interface_->getRobotModel()->getJointModelGroup("arm_group");
    visual_tools_ = std::make_shared<moveit_visual_tools::MoveItVisualTools>(
      shared_from_this(), "measure", "set_scene",
      move_group_interface_->getRobotModel());
    visual_tools_->deleteAllMarkers();
    visual_tools_->loadRemoteControl();

    // Load shape.scene and cylinder
    try
    {
      std::string scene_path =
        ament_index_cpp::get_package_share_directory("moveit_demo")
        + "/scene/shape.scene";
      RCLCPP_INFO(this->get_logger(),
        "Loading scene file: %s", scene_path.c_str());
      std::vector<moveit_msgs::msg::CollisionObject> scene_objects =
        loadSceneFile(scene_path);
      for (auto& obj : scene_objects)
      {
        for (auto& pose : obj.primitive_poses)
        {
          //Special operations, adapted to scene models
          double old_x = pose.position.x;
          pose.position.x =  0.26;
          pose.position.y = -old_x;

          double qr_x = 0.0, qr_y = 0.0, qr_z = -0.70710678, qr_w = 0.70710678;
          double qo_x = pose.orientation.x;
          double qo_y = pose.orientation.y;
          double qo_z = pose.orientation.z;
          double qo_w = pose.orientation.w;
          pose.orientation.x = qr_w * qo_x + qr_x * qo_w + qr_y * qo_z - qr_z * qo_y;
          pose.orientation.y = qr_w * qo_y - qr_x * qo_z + qr_y * qo_w + qr_z * qo_x;
          pose.orientation.z = qr_w * qo_z + qr_x * qo_y - qr_y * qo_x + qr_z * qo_w;
          pose.orientation.w = qr_w * qo_w - qr_x * qo_x - qr_y * qo_y - qr_z * qo_z;
        }
      }

      planning_scene_interface_->addCollisionObjects(scene_objects);

      // Pre-place cylinder at middle shelf
      {
        moveit_msgs::msg::CollisionObject cylinder_pre;
        cylinder_pre.id = "cylinder";
        cylinder_pre.header.frame_id = "measure";
        cylinder_pre.operation = cylinder_pre.ADD;
        shape_msgs::msg::SolidPrimitive cyl_prim;
        cyl_prim.type = cyl_prim.CYLINDER;
        cyl_prim.dimensions.resize(2);
        cyl_prim.dimensions[cyl_prim.CYLINDER_HEIGHT] = 0.03;
        cyl_prim.dimensions[cyl_prim.CYLINDER_RADIUS] = 0.02;

        geometry_msgs::msg::Pose cyl_pose;
        cyl_pose.orientation.w = 1.0;
        cyl_pose.position.x = 0.24;
        cyl_pose.position.y = 0.0;
        cyl_pose.position.z = 0.22;
        cylinder_pre.primitives.push_back(cyl_prim);
        cylinder_pre.primitive_poses.push_back(cyl_pose);
        planning_scene_interface_->applyCollisionObject(cylinder_pre);
      }
    }
    catch (const std::exception& e)
    {
      RCLCPP_ERROR(this->get_logger(),
        "Failed to load scene file: %s", e.what());
    }
    //  Disable robot self-collision.  Only re-enable gripper ↔ base_link
    //  Also exempt llink2/rlink2 ↔ shelf so gripper fingers can touch shelf edges.
    {
      auto acm_pub = this->create_publisher<moveit_msgs::msg::PlanningScene>(
        "/planning_scene", 10);
      rclcpp::sleep_for(std::chrono::milliseconds(300));

      const auto& links =
        move_group_interface_->getRobotModel()->getLinkModelNames();
      const size_t robot_n = links.size();

      // Gripper links checked against base_link
      const std::vector<std::string> gripper_links = {
        "llink2", "rlink2", "arm5_Link"};

      // Gripper links exempted from shelf collision
      const std::vector<std::string> shelf_exempt = {"llink2", "rlink2"};

      const std::vector<std::string> shelf_ids = {
        "Box_0", "Box_1", "Box_2", "Box_3", "Box_4"};

      // Build entry list: robot links + cylinder + shelf boxes
      std::vector<std::string> entry_names = links;
      entry_names.push_back("cylinder");
      const size_t cyl_idx = entry_names.size() - 1;
      for (const auto& sid : shelf_ids)
        entry_names.push_back(sid);
      const size_t total = entry_names.size();

      // Build name → index map
      std::map<std::string, size_t> name_to_idx;
      for (size_t i = 0; i < total; i++)
        name_to_idx[entry_names[i]] = i;

      auto it_base = name_to_idx.find("base_link");
      const size_t base_idx = (it_base != name_to_idx.end()) ? it_base->second : 0;

      moveit_msgs::msg::PlanningScene ps_msg;
      ps_msg.is_diff = true;
      ps_msg.allowed_collision_matrix.entry_names = entry_names;
      ps_msg.allowed_collision_matrix.entry_values.resize(total);

      // --- Row 0..robot_n-1 (robot links) ---
      for (size_t i = 0; i < robot_n; i++)
      {
        auto& row = ps_msg.allowed_collision_matrix.entry_values[i];
        row.enabled.resize(total, true);
        // Check robot ↔ shelf (except exempt links)
        bool is_exempt = false;
        for (const auto& ename : shelf_exempt)
          if (entry_names[i] == ename) { is_exempt = true; break; }
        if (!is_exempt)
        {
          for (const auto& sid : shelf_ids)
          {
            auto it = name_to_idx.find(sid);
            if (it != name_to_idx.end())
              row.enabled[it->second] = false;
          }
        }
      }

      // --- Cylinder row ---
      {
        auto& row = ps_msg.allowed_collision_matrix.entry_values[cyl_idx];
        row.enabled.resize(total, true);
      }

      // --- Shelf rows ---
      for (const auto& sid : shelf_ids)
      {
        auto it_s = name_to_idx.find(sid);
        if (it_s == name_to_idx.end()) continue;
        auto& row = ps_msg.allowed_collision_matrix.entry_values[it_s->second];
        row.enabled.resize(total, false);
        for (const auto& ename : shelf_exempt)
        {
          auto it_e = name_to_idx.find(ename);
          if (it_e != name_to_idx.end())
            row.enabled[it_e->second] = true;
        }
      }

      // Re-enable gripper ↔ base_link (both directions)
      for (const auto& gname : gripper_links)
      {
        auto it = name_to_idx.find(gname);
        if (it == name_to_idx.end()) continue;
        size_t gi = it->second;
        ps_msg.allowed_collision_matrix.entry_values[gi].enabled[base_idx] = false;
        ps_msg.allowed_collision_matrix.entry_values[base_idx].enabled[gi] = false;
      }

      acm_pub->publish(ps_msg);
      rclcpp::sleep_for(std::chrono::milliseconds(500));
      RCLCPP_INFO(this->get_logger(),
        "ACM: self-collision OFF, gripper↔base ON, llink2/rlink2↔shelf OFF. "
        "(%zu links + %zu shelf)",
        robot_n, shelf_ids.size());
    }

    // shelf pick-and-place
    const int max_attempts = 5;
    const double SHELF_X = 0.24; 
    const double MIDDLE_Z = 0.23;
    const double LOWER_Z  = 0.09;
    auto exec_named = [&](const std::string& desc, const std::string& target,
                          bool show_trajectory = true,
                          rviz_visual_tools::Colors color = rviz_visual_tools::LIME_GREEN)
    {
      RCLCPP_INFO(this->get_logger(),
        "=== %s: named target '%s' ===", desc.c_str(), target.c_str());
      for (int a = 1; a <= max_attempts; a++)
      {
        move_group_interface_->setNamedTarget(target);
        moveit::planning_interface::MoveGroupInterface::Plan plan;
        if (move_group_interface_->plan(plan) ==
            moveit::core::MoveItErrorCode::SUCCESS)
        {
          if (show_trajectory)
          {
            visual_tools_->publishTrajectoryLine(plan.trajectory_,
              move_group_interface_->getRobotModel()->getLinkModel("gripper_tcp"),
              joint_model_group, color);
            visual_tools_->trigger();
          }
          move_group_interface_->execute(plan);
          return true;
        }
        RCLCPP_WARN(this->get_logger(),
          "%s attempt %d/%d failed", desc.c_str(), a, max_attempts);
      }
      RCLCPP_ERROR(this->get_logger(), "%s failed!", desc.c_str());
      return false;
    };

    auto exec_position = [&](const std::string& desc,
                             double x, double y, double z,
                             rviz_visual_tools::Colors color = rviz_visual_tools::BLUE)
    {
      RCLCPP_INFO(this->get_logger(),
        "=== %s: position (%.3f, %.3f, %.3f) ===", desc.c_str(), x, y, z);
      for (int a = 1; a <= max_attempts; a++)
      {
        move_group_interface_->setStartStateToCurrentState();
        move_group_interface_->setPositionTarget(x, y, z);
        moveit::planning_interface::MoveGroupInterface::Plan plan;
        if (move_group_interface_->plan(plan) ==
            moveit::core::MoveItErrorCode::SUCCESS)
        {
          visual_tools_->publishTrajectoryLine(plan.trajectory_,
            move_group_interface_->getRobotModel()->getLinkModel("gripper_tcp"),
            joint_model_group, color);
          visual_tools_->trigger();
          move_group_interface_->execute(plan);
          return true;
        }
        RCLCPP_WARN(this->get_logger(),
          "%s attempt %d/%d failed", desc.c_str(), a, max_attempts);
        rclcpp::sleep_for(std::chrono::milliseconds(200));
      }
      RCLCPP_ERROR(this->get_logger(), "%s failed!", desc.c_str());
      return false;
    };

    //  Move to init pose
    if (!exec_named("Step 1: init pose", "init", false))
    {
      RCLCPP_ERROR(this->get_logger(), "Aborting: init pose failed.");
      rclcpp::shutdown();
      return;
    }

    // --- 4b. Move to middle shelf via joint-space target (orange) ---
    {
      RCLCPP_INFO(this->get_logger(),
        "=== Step 2: approach middle shelf via joint target ===");

      std::map<std::string, double> middle_joints;
      middle_joints["arm1"] = 1.5825;
      middle_joints["arm2"] = 0.2489;
      middle_joints["arm3"] = 0.9974;
      middle_joints["arm4"] = 1.9240;
      middle_joints["arm5"] = 1.57;

      bool ok = false;
      for (int a = 1; a <= max_attempts; a++)
      {
        move_group_interface_->setStartStateToCurrentState();
        move_group_interface_->setJointValueTarget(middle_joints);
        moveit::planning_interface::MoveGroupInterface::Plan plan;
        if (move_group_interface_->plan(plan) ==
            moveit::core::MoveItErrorCode::SUCCESS)
        {
          visual_tools_->publishTrajectoryLine(plan.trajectory_,
            move_group_interface_->getRobotModel()->getLinkModel("gripper_tcp"),
            joint_model_group, rviz_visual_tools::ORANGE);
          visual_tools_->trigger();
          move_group_interface_->execute(plan);
          ok = true;
          break;
        }
        RCLCPP_WARN(this->get_logger(),
          "Step 2 attempt %d/%d failed", a, max_attempts);
        rclcpp::sleep_for(std::chrono::milliseconds(500));
      }

      if (!ok)
      {
        RCLCPP_ERROR(this->get_logger(), "Aborting: middle shelf approach failed.");
        rclcpp::shutdown();
        return;
      }
    }

    // Attach cylinder at middle shelf 
    {
      RCLCPP_INFO(this->get_logger(),
        "=== Step 4: attach cylinder from middle shelf ===");

      std::vector<std::string> touch_links;
      touch_links.push_back("llink2");
      touch_links.push_back("rlink2");
      move_group_interface_->attachObject("cylinder", "gripper_tcp", touch_links);

    }

    {
      RCLCPP_INFO(this->get_logger(),
        "=== Step 4.5: retreat to init before lower shelf ===");
      bool retreated = false;
      for (int a = 1; a <= max_attempts; a++)
      {
        move_group_interface_->setNamedTarget("init");
        moveit::planning_interface::MoveGroupInterface::Plan plan;
        if (move_group_interface_->plan(plan) ==
            moveit::core::MoveItErrorCode::SUCCESS)
        {
          visual_tools_->publishTrajectoryLine(plan.trajectory_,
            move_group_interface_->getRobotModel()->getLinkModel("gripper_tcp"),
            joint_model_group, rviz_visual_tools::ORANGE);
          visual_tools_->trigger();
          move_group_interface_->execute(plan);
          retreated = true;
          break;
        }
        RCLCPP_WARN(this->get_logger(),
          "Retreat to init attempt %d/%d failed", a, max_attempts);
        rclcpp::sleep_for(std::chrono::milliseconds(200));
      }
      if (!retreated)
      {
        RCLCPP_ERROR(this->get_logger(),
          "Cannot retreat to init, lower shelf plan will likely fail.");
      }
    }

    // --- 4e. Move to lower shelf via joint-space target ---
    {
      RCLCPP_INFO(this->get_logger(),
        "=== Step 5: approach lower shelf via joint target ===");

      std::map<std::string, double> lower_joints;
      lower_joints["arm1"] = 1.5837;
      lower_joints["arm2"] = -0.1831;
      lower_joints["arm3"] = 1.1294;
      lower_joints["arm4"] = 1.8359;
      lower_joints["arm5"] = 1.3307;

      bool ok = false;
      for (int a = 1; a <= max_attempts; a++)
      {
        move_group_interface_->setStartStateToCurrentState();
        move_group_interface_->setJointValueTarget(lower_joints);
        moveit::planning_interface::MoveGroupInterface::Plan plan;
        if (move_group_interface_->plan(plan) ==
            moveit::core::MoveItErrorCode::SUCCESS)
        {
          visual_tools_->publishTrajectoryLine(plan.trajectory_,
            move_group_interface_->getRobotModel()->getLinkModel("gripper_tcp"),
            joint_model_group, rviz_visual_tools::LIME_GREEN);
          visual_tools_->trigger();
          move_group_interface_->execute(plan);
          ok = true;
          break;
        }
        RCLCPP_WARN(this->get_logger(),
          "Step 5 attempt %d/%d failed", a, max_attempts);
        rclcpp::sleep_for(std::chrono::milliseconds(500));
      }

      if (!ok)
      {
        RCLCPP_WARN(this->get_logger(),
          "Lower shelf joint target failed, will still try to place cylinder.");
      }
    }

    // --- 4f. Place cylinder at lower shelf (detach, reset to upright) ---
    {
      RCLCPP_INFO(this->get_logger(),
        "=== Step 6: place cylinder at lower shelf ===");

      std::vector<std::string> to_remove = {"cylinder"};
      planning_scene_interface_->removeCollisionObjects(to_remove);
      rclcpp::sleep_for(std::chrono::milliseconds(200));

      move_group_interface_->detachObject("cylinder");

      // Now add a fresh vertical cylinder at lower shelf
      moveit_msgs::msg::CollisionObject cyl_placed;
      cyl_placed.id = "cylinder";
      cyl_placed.header.frame_id = "measure";
      cyl_placed.operation = cyl_placed.ADD;

      shape_msgs::msg::SolidPrimitive cyl_prim;
      cyl_prim.type = cyl_prim.CYLINDER;
      cyl_prim.dimensions.resize(2);
      cyl_prim.dimensions[cyl_prim.CYLINDER_HEIGHT] = 0.03;
      cyl_prim.dimensions[cyl_prim.CYLINDER_RADIUS] = 0.02;

      geometry_msgs::msg::Pose cyl_pose;
      cyl_pose.orientation.w = 1.0;
      cyl_pose.position.x = SHELF_X;
      cyl_pose.position.y = 0.0;
      cyl_pose.position.z = 0.09;  // bottom shelf (z=0.06) + half height

      cyl_placed.primitives.push_back(cyl_prim);
      cyl_placed.primitive_poses.push_back(cyl_pose);
      planning_scene_interface_->applyCollisionObject(cyl_placed);

    }

    // Return to init pose
    exec_named("Step 7: return to init", "init");

    rclcpp::shutdown();
  }

 

Collision Detection
3D perception obstacle‑avoidance

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/中文