yahboom
HomeLearn
Solution
Blog
Online Store
About Us
EN/中文
DOFBOT-JetsonNANO📖
00.Must Read Before Use!!
  • 00.Must Read Before Use!!
01.First Trial
  • 1.First Trial
  • 2.Analysis of common problems
  • 3.Calibration offset
  • 4.Precautions for DIY Robotic Arm
  • 5.Jetson Nano Version – Must Read
  • 6.Robotic arm gripping anomaly solutions
02.Assemble Course
  • 1.Installation video
  • 2.Calibrate the Robotic Arm
  • 3.Install the map
03.Remote control course
  • 1.Mobile APP control
  • 2.USB handle control
  • 3.PC web page programming
04.Preparation
  • 1.Manage APP control service
  • 2.Manage JupyterLab service
  • 3.Manage OLED service
  • 4.Modifying ROS_DOMAIN_ID for Multi-Machine
  • 5.Jetpack old system upgraded to SUPER system
05.Basic control course
  • 1.Control RGB light
  • 2.Control buzzer
  • 3.Control single servo
  • 4.Read servo angle
  • 5.Control all servo
  • 6.DOFBOT up down left right
  • 7.DOFBOT dancing
  • 8.DOFBOT memory action
  • 9.DOFBOT grab block
  • 10.Porter
  • 11.Stacked Arhat
  • 12.Synchronous action
  • 13.USB camera display
06.AI vision basic course
  • 1.Gesture Recognition
  • 2.Color threshold adjustment&Color calibration
  • 3.Color recognition
  • 4.Face recognition
  • 5.YOLOv11 garbage recognition
  • 6.YOLOv11 object recognition
07.2D Visual Tracking Course
  • 1.PID algorithm basics
  • 2.Color block positioning
  • 3.Color block tracking
  • 4.Face positioning
  • 5.Face tracking
  • 6.Gesture recognition fixed action
08.2D Visual Grasping Course
  • 1.Gesture recognition stack blocks
  • 2.Color recognition grab blocks
  • 3.Catch game
  • 4.Color sorting and stacking
  • 5.Garbage sorting
  • 6.Color interaction
09.Mediapipe course
  • 1.Hand detection
  • 02.Posture detection
  • 3.Overall detection
  • 4.Facial Detection
  • 5.Face Detection
  • 6.Face effects
  • 7.3D object recognition
  • 8.Paintbrush
  • 9.Finger control
  • 10.Gesture Recognition
  • 11.Gesture control robotic arm action group
  • 12.Arm posture control robotic arm
  • 13.Palm Targeting
  • 14.Robotic arm tracks the palm
  • 15.Fingertip trajectory recognition
  • 16.Fingertip trajectory control robotic arm
  • 17.Gesture Grasp and Release Objects
  • 18.Finger Control Robot Arm
10.AI Large Model Voice Module (Must Read)new
  • 1. Introduction to AI Large Model Voice Module
  • 2. Flash the firmware (Must read)
  • 3. Modify the wake-up word and command word
11.2D Voice Control Coursenew
  • 01.Simple Voice Control
  • 02.Smart Voice Control
  • 03.Voice Action Control
  • 04.Memory Learning Mode
  • 05.Color Recognition with Voice Broadcast
  • 06.Color Recognition and Grasping with Voice Broadcast
  • 07.Color Recognition and Sorting with Voice Broadcast
  • 08.Voice Recognition Target Tracking
  • 09.Voice Control Stacking
  • 10.Voice Control Color Sorting and Stacking
  • 11.Garbage Recognition with Voice Broadcast
  • 12.Garbage Sorting with Voice Broadcast
12.Robotic Arm Control and Inverse Kinematics
  • 1. Robotic arm ROS control
  • 2. Inverse solution
13.3D Sorting and Grasping Coursenew
  • 1.AprilTag ID sorting
  • 2.MediaPipe Gesture-AprilTag ID sorting
  • 3.MediaPipe Gesture-AprilTag distance sorting
  • 4.Block color sorting
  • 5.Block different shape sorting
  • 6.Yolov11 garbage sorting
14.3D Tracking Coursenew
  • 1.AprilTag Tracking
  • 2.Color Block Tracking
  • 3.KCF Object Tracking
15.3D Voice Control for Sorting & Tracking Coursenew
  • 1.Voice Control AprilTag ID Sorting
  • 2.Voice Control Color Block Sorting
  • 3.Voice Control Yolov11 Garbage Recognition Sorting
  • 4.Voice Control AprilTag Tracking
  • 5.Voice Control Color Block Tracking
  • 6.Voice Control Object Tracking
16.AI Model Basicsnew
  • 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
17.AI Model Developmentnew
  • 1.Register a model service provider account
  • 2. Configure API-KEY
  • 3. Introduction to Dify
  • 4. Basic Dify Features
  • 5. Deploy the RAG knowledge base
  • 6. AI Large Model Development - chatbot
  • 7. RAG knowledge base + chatbot
  • 8. AI agent workflow
18.AI Model – Text Versionnew
  • 1. Semantic understand instruction following
  • 2. Multimodal visual understand
  • 3. Text Large Model + robotic arm control
  • 4. Multimodal Large Model+video understanding
  • 5. Multimodal Large Model+robotic arm gripping
  • 6. Multimodal Large Model+robotic arm tracking
  • 7. Multimodal Large Model+robotic arm sorting
  • 8. Multimodal Large Model+robotic arm handling
  • 9. Multimodal Large Model+Color Blocks Back In Place
  • 10. Multimodal Large Model + Intent Prediction + Robotic Arm Gripping
  • 11. Text Large Model + YOLOv11 + Intelligent Garbage Classification
19.AI Model – Voice Versionnew
  • 1. Semantic understand instruction following
  • 2. Multimodal visual understand
  • 3. Text Large Model + robotic arm control
  • 4. Multimodal Large Model+video understanding
  • 5. Multimodal Large Model+robotic arm gripping
  • 6. Multimodal Large Model+robotic arm tracking
  • 7. Multimodal Large Model+robotic arm sorting
  • 8. Multimodal Large Model+robotic arm handling
  • 9. Multimodal Large Model+Color Blocks Back In Place
  • 10. Multimodal Large Model + Intent Prediction + Robotic Arm Gripping
  • 11. Text Large Model + YOLOv11 + Intelligent Garbage Classification
20.AI Model – Fun Applicationsnew
  • 1.AI Butler-Intent Inference
  • 2.AI Encyclopedia-Arithmetic Master
  • 3.AI Encyclopedia-You asked I Pointed
  • 4.AI Encyclopedia-Nutritional Analysis
  • 5.AI Encyclopedia-Problem Solving Expert
  • 6.AI Encyclopedia-English Spelling
  • 7.AI Butler-Garbage Sorting
  • 8.AI Top Chef
21.MoveIt2 Course
  • 1.MoveIt configuration
  • 2. MoveIt Usage
  • 3. MoveIt Drive Real Robot
  • 4. MoveIt Random Movement
  • 5. MoveIt Forward Kinematics Design
  • 6. MoveIt Inverse Kinematics Design
  • 7. MoveIt Cartesian Path
  • 8. MoveIt Scene Design
  • 9. MoveIt Trajectory Planning
  • 10. MoveIt Collision Detection
22.YOLOv11 Development Course
  • 1. YOLO Environment Setup
  • 2. CLI Usage
  • 3. Object Detection
  • 4. Instance Segmentation
  • 5. Pose Estimation
  • 6. Image Classification
  • 7. Oriented Bounding Boxes Object Detection
  • 8. Model Conversion
  • 9. Model Prediction
23.Linux Operating System
  • 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.Capacity expansion and resource allocation
  • 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
24.GPIO Hardware Control Course
  • 1.GPIO description
  • 2.GPIO library installation
  • 3.GPIO reading
  • 4.GPIO output
  • 5.Serial communication
  • 6.I2C communication
25.OpenCV course
  • 0. Must Read!
  • 1. Introduction to Open Source CV
  • 2. Image reading and display
  • 3. Image writing
  • 4. Image quality
  • 5. Pixel Operation
  • 6.Image zoom
  • 7.Picture cut
  • 8.Picture pan
  • 9.Picture mirroring
  • 10.Affine transformation
  • 11.Picture rotation
  • 12.perspective transformation
  • 13.Grayscale processing
  • 14.Binary image
  • 15.Edge green detection
  • 16.Line segment drawing
  • 17.Rectangular circle drawing
  • 18.Text and picture drawing
26.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
27. Advanced Visuals Course
  • 0. Must Read! Porting and Compilation
  • 1. QR Code
  • 2. Human Pose Estimation
  • 3. Object Detection
  • 4. AR Vision
  • 5. ROS + OpenCV Basics
28.Jupyter Lab Usage Course
  • 0.Read the document before operation
  • 1.Jupyter Lab environment construction
  • 2.Basic use of Jupyter Lab
  • 3.Jupyter Lab plug-in installation
  • 4.Basic use of Jupyter Widgets
29.Docker Course
  • 1.Docker overview and docker installation
  • 2.Common commands for docker image containers
  • 3.Docker images deeply understand and publish images
  • 4.Docker hardware interaction and data processing
  • 5.Start the Dofbot container
30.Python Programming Basics
  • 1.Python usage
  • 2.Use APT to install Python packages
  • 3.Python virtual environment
  • 4.GPIO Zero
  • 5.Pin output high and low levels
  • 6.Pin reads high and low levels
  • 7.Pin output PWM
Download
  • APP(iOS/Android)
  • Code
  • SystemFile
  • VM File
  • PC software
  • Instruction manual
  • Jetson_Boot_USB.tar.gz
  • More Annex
  • Tools
Download ZIP
FAQ
  • 1、Precautions for DIY Robotic Arm
  • 2、Why i can't robotic arm start normally
  • 3、When you control the No.1 servo, all servos will turn.
  • 4、How open VNC service on DOFBOT system
  • 5、Where can I get the URDF file?
  • 6、Gesture recognition cannot work normally.
  • 7、Write system image into U disk
  • 8、Write EMMC boot file

Welcome to DOFBOT-JetsonNANO repository

4.Embodied intelligent functions core source code

Embodied intelligent functions core source code

1.Course content

  1. AI large model embodied intelligence is a composite function involving the coordination of multiple node programs. This section explains the core programs.

2.Source Code Package Structure

2.1 Package File Structure

The ROS package for AI large model embodied intelligence is largemodel, with the package path:

First enter docker

root/LargeModel_ws/src/largemodel

The package file structure is as follows:

image-20250709183354363

Folder and file descriptions:

2.1.1 config

Configuration folder, containing configuration files

  • large_model_interface.yaml

    Large model interface configuration file, used to configure API-KEYs and large model parameters for various platforms

  • yahboom.yaml

    Node configuration file: used to configure core node parameters

2.1.2 largemodel

Source code folder, core programs for AI large model embodied intelligence

  • asr.py

    Speech recognition program file, used to run speech recognition models and interact with users

  • model_service.py

    Model server program file, used to call various model interfaces to implement model inference architecture

  • action_service.py

    Action server program file, used to receive action lists requested by the model server, control robot movement and play sounds

     

2.1.3 launch

Launch file folder, containing ROS2 node launch files

  • largemodel_control.launch.py

    Launch file for AI large model embodied intelligence: starts multiple nodes, with two startup modes: voice interaction mode and text interaction mode

2.1.4 resources_file

Audio files for storing system sounds

2.1.5 utils

Component folder, containing non-core function program files

  • large_model_interface.py

    Large model interface program file, containing underlying interfaces for calling large models from various platforms. Different platforms and models have different calling programs, which are uniformly managed in the interface file

  • mic_serial.py

    Voice module driver program file, used to drive the wake word function of the voice module

  • promot.py

    Large model prompt file: used to generate prompts for the execution layer large model

  • dify_client2.py

    dify API function, used for international version dify to request local dify applications

2.2 Inter-program Call Relationship Diagram

源码解析

 

3.Speech Recognition Function

Speech recognition function includes VAD speech activity detection and speech-to-text conversion, source code path:

First enter docker

xxxxxxxxxx
root/LargeModel_ws/src/largemodel/largemodel/asr.py

3.1 Program Flowchart

ASR program flowchart

3.2 VAD Speech Activity Detection

Implementation: listen_for_speech method in ASRNode class

Program Analysis: Real-time recording through specified microphone, using VAD (Voice Activity Detection) to determine if speaking is occurring. When speech ends (continuous silence exceeds set frame count), stop recording and save valid speech content to file.

Detailed logic:

  1. Initialize audio stream and configure parameters (such as sample rate, number of channels, etc.).
  2. Continuously read audio frames and perform speech activity detection.
  3. If speech start is detected, add audio frames to buffer; if continuous silence exceeds threshold (90 frames, about 1s), end recording.
  4. After recording ends, remove trailing silence part and save valid speech as WAV file.
  5. If no valid speech is detected, do not save file.
​x
  def listen_for_speech(self, mic_index=0):
        p = pyaudio.PyAudio()
        audio_buffer = []
        silence_counter = 0
        MAX_SILENCE_FRAMES = 90  # 30帧*30ms=900ms静音后停止 / Stop after 900ms of silence (30 frames * 30ms)
        speaking = False  # 语音活动标志 / Flag indicating speech activity
        frame_counter = 0  # 计数器 / Frame counter
        stream_kwargs = {
            "format": pyaudio.paInt16,
            "channels": 1,
            "rate": self.sample_rate,
            "input": True,
            "frames_per_buffer": self.frame_bytes,
        }
        if mic_index != 0:
            stream_kwargs["input_device_index"] = mic_index
​
        # 通过蜂鸣器提示用户讲话 / Prompt the user to speak via the buzzer
        self.pub_beep.publish(UInt16(data=1))
        time.sleep(0.5)
        self.pub_beep.publish(UInt16(data=0))
​
        try:
            # 打开音频流 / Open audio stream
            stream = p.open(**stream_kwargs)
            while True:
                if self.stop_event.is_set():
                    return False
​
                frame = stream.read(
                    self.frame_bytes, exception_on_overflow=False
                )  # 读取音频数据 / Read audio data
                is_speech = self.vad.is_speech(
                    frame, self.sample_rate
                )  # VAD检测 / VAD detection
​
                if is_speech:
                    # 检测到语音活动 / Detected speech activity
                    speaking = True
                    audio_buffer.append(frame)
                    silence_counter = 0
                else:
                    if speaking:
                        # 在语音活动后检测静音 / Detect silence after speech activity
                        silence_counter += 1
                        audio_buffer.append(
                            frame
                        )  # 持续记录缓冲 / Continue recording buffer
​
                        # 静音持续时间达标时结束录音 / End recording when silence duration meets the threshold
                        if silence_counter >= MAX_SILENCE_FRAMES:
                            break
                frame_counter += 1
                if frame_counter % 2 == 0:
                    self.get_logger().info("1" if is_speech else "-")
                    # print('1-' if is_speech else '0-', end='', flush=True)  # 实时状态显示方式 / Real-time status display
        finally:
            stream.stop_stream()
            stream.close()
            p.terminate()
​
        # 保存有效录音(去除尾部静音) / Save valid recording (remove trailing silence)
        if speaking and len(audio_buffer) > 0:
            # 裁剪最后静音部分 / Trim the last silent part
            clean_buffer = (
                audio_buffer[:-MAX_SILENCE_FRAMES]
                if len(audio_buffer) > MAX_SILENCE_FRAMES
                else audio_buffer
            )
​
            with wave.open(self.user_speechdir, "wb") as wf:
                wf.setnchannels(1)
                wf.setsampwidth(p.get_sample_size(pyaudio.paInt16))
                wf.setframerate(self.sample_rate)
                wf.writeframes(b"".join(clean_buffer))
                return True

3.3 ASR Speech Recognition

Implementation: ASR_conversion method in ASRNode class converts recording files to text

Calls speech recognition model interface functions in large_model_interface.py large model interface file

Note: Text recognized by speech recognition with less than 4 characters will be considered invalid, to prevent content after false wake-up from being treated as valid content

Program Analysis:

  1. If using online_asr, call corresponding method and check if result is valid text (length greater than 4), return recognized content if successful, otherwise log error and return 'error'.

  2. Otherwise use SenseVoiceSmall_ASR for recognition, with same result judgment and processing.

    Where SenseVoiceSmall_ASR is a local model speech recognition method, only available on jetson orin nano, jetson orin NX hosts.

xxxxxxxxxx
def ASR_conversion(self, input_file):
    if self.use_oline_asr:
        result=self.modelinterface.oline_asr(input_file)
        if result[0] == 'ok' and len(result[1]) > 4:
            return result[1]
        else:
            self.get_logger().error(f'ASR Error:{result[1]}')
            return 'error'
    else:
        result=self.modelinterface.SenseVoiceSmall_ASR(input_file)
        if result[0] == 'ok' and len(result[1]) > 4:
            return result[1]
        else:
            self.get_logger().error(f'ASR Error:{result[1]}')
            return 'error' 

 

4.Model Server Function

Implementation program is model_service.py, used to receive speech recognition results in voice interaction mode or terminal input in text interaction mode, implementing large model inference logic, source code path:

First enter docker

xxxxxxxxxx
root/LargeModel_ws/src/largemodel/largemodel/model_service.py

4.1 Program Flowchart

model_service program flowchart

 

4.2 Dual Model Inference (Domestic Version)

Default uses dual model inference mode, implemented by dual_large_model_mode and instruction_process methods in LargeModelService class

Program Analysis:

  1. If it's a new instruction cycle (self.new_order_cycle is True):

    • Initialize multimodal historical context;
    • Use task decision model to plan user input prompt;
    • Pass planning results to instruction execution layer model for processing;
    • Set new_order_cycle to False, indicating current instruction cycle starts execution.
  2. Otherwise (non-new cycle):

    • Directly pass input prompt and type to instruction execution layer model for processing.
xxxxxxxxxx
def dual_large_model_mode(self, type, prompt=""):
    """
    此函数实现了双模型推理模式,即先由文本生成模型进行任务规划,然后由多模态大模型生成动作列表
    This function implements the dual model inference mode, where the text generation model first plans the task, and then the multimodal large model generates the action list.
    """
    if (
        self.new_order_cycle
    ):  # 判断是否是新任务周期 / Determine if it is a new task cycle
        # 判断上一轮对话指令是否完成如果完成就清空历史上下文,开启新的上下文 / Determine if the previous round of dialogue instructions are completed. If completed, clear the historical context and start a new context
        self.model_client.init_Multimodal_history(
            get_prompt()
        )  # 初始化执行层上下文历史 / Initialize execution layer context history
        execute_instructions = self.model_client.TaskDecision(
            prompt
        )  # 调用决策层大模型进行任务规划 / Call the decision layer large model for task planning
​
        if not execute_instructions == "error":
            if self.text_chat_mode:
                msg = String(
                    data=f"The upcoming task to be carried out:{execute_instructions}"
                )
                self.text_pub.publish(msg)
            else:
                self.get_logger().info(
                    f"The upcoming task to be carried out:{execute_instructions}"
                )  # 即将执行的任务:... / Upcoming task to be executed...
            self.instruction_process(
                type="text",
                prompt=f"用户:{prompt},决策层AI规划:{execute_instructions}",
            )  # 传递决策层模型规划好的执行步骤给执行层模型 / Pass the planned execution steps from the decision layer model to the execution layer model
            self.new_order_cycle = (
                False  # 重置指令周期标志位 / Reset the instruction cycle flag
            )
        else:
            self.get_logger().info(
                "The model service is abnormal. Check the large model account or configuration options"
            )  # 模型推理失败,请检查模型配额和账户是否正常!!! / Model inference failed, please check the model quota and account whether normal!!!
    else:
        self.instruction_process(
            prompt, type
        )  # 调用执行层大模型生成成动作列表并执行 / Call the execution layer large model to generate an action list and execute
​
def instruction_process(self, prompt, type, conversation_id=None):
    """
    根据输入信息的类型(文字/图片),构建不同的请求体进行推理,并返回结果)
    Based on the type of input information (text/image), construct different request bodies for inference and return the result.
    """
    if self.regional_setting == "China":  # Domestic version
        if type == "text":
            raw_content = self.model_client.multimodalinfer(prompt)
        elif type == "image":
            self.save_single_image()
            raw_content = self.model_client.multimodalinfer(
                "机器人反馈:执行seewhat()完成", image_path=self.image_save_path
            )
        json_str = self.extract_json_content(raw_content)
​
    elif self.regional_setting == "international":  # International version
        if type == "text":
            result = self.model_client.TaskExecution(
                input=prompt,
                map_mapping=self.map_mapping,
                language=self.language_dict[self.language],
                conversation_id=conversation_id,
            )
            if result[0]:
                json_str = self.extract_json_content(result[1])
                self.conversation_id = result[2]
            else:
                self.get_logger().info(f"ERROR:{result[1]}")
        elif type == "image":
            self.save_single_image()
            result = self.model_client.TaskExecution(
                input="机器人反馈:执行seewhat()完成",
                map_mapping=self.map_mapping,
                language=self.language_dict[self.language],
                image_path=self.image_save_path,
                conversation_id=conversation_id,
            )
            if result[0]:
                json_str = self.extract_json_content(result[1])
                self.conversation_id = result[2]
            else:
                self.get_logger().info(f"ERROR:{result[1]}")
​
    if json_str is not None:
        # 解析JSON字符串,分离"action"、"response"字段 / Parse JSON string, separate "action" and "response" fields
        action_plan_json = json.loads(json_str)
        action_list = action_plan_json.get("action", [])
        llm_response = action_plan_json.get("response", "")
    else:
        self.get_logger().info(
            f"LargeScaleModel return: {json_str},The format was unexpected. The output format of the AI model at the execution layer did not meet the requirements"
        )
        return
​
    if self.text_chat_mode:
        msg = String(data=f'"action": {action_list}, "response": {llm_response}')
        self.text_pub.publish(msg)
    else:
        self.get_logger().info(
            f'"action": {action_list}, "response": {llm_response}'
        )
​
    self.send_action_service(
        action_list, llm_response
    )  # 异步发送动作列表、回复内容给ActionServer / Asynchronously send action list and response content to ActionServer

 

4.3 Dual Model Inference (International Version)

  1. Program implementation logic is the same as domestic version, difference is that international version requests local dify application, then dify requests cloud large model
xxxxxxxxxx
def dual_large_model_international_model(self, type, prompt=""):
    """
    This function is applicable to international version dual model inference mode, using dify as middleware
    """
    if (
        self.new_order_cycle
    ):  # 判断是否是新任务周期 / Determine if it is a new task cycle
        self.conversation_id = None
        result = self.model_client.TaskDecision(prompt)
        if result[0]:
            if self.text_chat_mode:  # 文字交互模式 / Text interaction mode
                msg = String(
                    data=f"The upcoming task to be carried out:{result[1]}"
                )
                self.text_pub.publish(msg)
            else:  # 语音交互模式 / Voice interaction mode
                self.get_logger().info(
                    f"The upcoming task to be carried out:{result[1]}"
                )
​
            self.instruction_process(
                type="text", prompt=f"用户:{prompt},决策层AI规划:{result[1]}"
            )
            self.new_order_cycle = (
                False  # 重置指令周期标志位 / Reset the instruction cycle flag
            )
        else:
            self.get_logger().info(f"ERROR: {result[1]}")
​
    else:
        self.instruction_process(
            prompt, type, conversation_id=self.conversation_id
        )  # 调用执行层大模型生成成动作列表并执行 / Call the execution layer large model to generate an action list and execute

 

5.Action Server Function

Implementation program is action_service.py, used to receive action lists requested by model server, parse action lists and execute them, source code path:

First enter docker

xxxxxxxxxx
root/LargeModel_ws/src/largemodel/largemodel/action_service.py

5.1 Program Flowchart

Saction_service program flowchart

Saction_service

 

5.2 Action Function Library

Robot action functions come from methods in CustomActionServer class, containing various sub-action functions. Here we use the robot arm upward control action function as an example. Other action functions will be explained when they first appear in subsequent chapters

Program Analysis:

  1. Convert input string parameters to floating point numbers
  2. Directly call function, pass parameters, communicate with underlying driver board, control six servos
  3. Decide whether to publish completion information based on mode
xxxxxxxxxx
def arm_up(self):  # Robot arm upward
    #Call function, directly communicate with underlying driver board, control six servos to extend upward
    Arm.Arm_serial_servo_write6(90,90,90,90,90,90,1000)
    #If not in combination mode and not interrupted, publish completion information for controlling robot arm upward
    if not self.combination_mode and not self.interrupt_flag:
        self.action_status_pub("arm_up_done")

5.3 Parse Action List to Control Robot Function

Parse action lists generated by large model into functions that control robot entities, and execute them. Implemented by execute_callback method in CustomActionServer class

Program Analysis:

  1. Receive action list sent by client (string format);
  2. If action list is empty, directly return success result;
  3. If only one action, parse and execute corresponding method, abort if failed;
  4. If multiple actions, enter combination mode and execute sequentially, recording logs and feedback during process;
  5. After all actions are executed, call stop() to stop robot;
  6. Finally return execution success result to client.
xxxxxxxxxx
def execute_callback(self, goal_handle):
    feedback_msg = Rot.Feedback()   
    stop = getattr(self, "stop")  # Get stop method, stop robot motion by publishing topic    
    actions=goal_handle.request.actions       
    if not actions: # If action list is empty, directly return success
        if not self.text_chat_mode:
           self.send_Audiorequest(goal_handle.request.llm_response)
​
        if self.use_double_llm:
            self.action_status_pub('机器人反馈:回复用户完成')
​
        goal_handle.succeed()
        result = Rot.Result()
        result.success = True
        return result
    elif len(actions) == 1:# If action list has only one action, normal execution flow
        # Case 2: List has only one element
        action = actions[0]
        if not self.text_chat_mode:
           self.send_Audiorequest(goal_handle.request.llm_response)
​
        match = re.match(r"(\w+)\((.*)\)", action)
        if not match:
            self.get_logger().warning(f'action_service: {action} is invalid action,skip execution')
            goal_handle.abort()
            result = Rot.Result()
            result.success = False
            return result
        else:
            action_name, args_str = match.groups()
            args = [arg.strip() for arg in args_str.split(",")] if args_str else []
            try:
                if hasattr(self, action_name):
                    method = getattr(self, action_name)
                    method(*args)
                    feedback_msg.status = f'action service execute  {action}  successed'
                    # self.get_logger().info(feedback_msg.status)  # 添加日志
                    goal_handle.publish_feedback(feedback_msg)
                else:
                    self.get_logger().warning(f'action_service:inviald: {action_name},skip execution')
                    self.action_status_pub('机器人反馈:动作函数不存在,无法执行')
                    goal_handle.abort()
                    result = Rot.Result()
                    result.success = False
                    return result
            except Exception as e:
                self.get_logger().error(f'action_service:execute action: {action} failed,error-log: {str(e)}')
                goal_handle.abort()
                result = Rot.Result()
                result.success = False
                return result                
    else:#If action list has multiple actions, enable combination mode
        if not self.text_chat_mode:
           self.send_Audiorequest(goal_handle.request.llm_response)
​
        self.combination_mode=True
        for action in actions:
            # Use regular expression to parse action name and parameters
            match = re.match(r"(\w+)\((.*)\)", action)
            if not match:
                self.get_logger().warning(f'action_service: {action} is invalid action,skip execution')
                continue
​
            action_name, args_str = match.groups()
            args = [arg.strip() for arg in args_str.split(",")] if args_str else []
​
            try:
​
                # Check if action is a method in CustomActionServer class
                if hasattr(self, action_name):
                    method = getattr(self, action_name)
                    # Dynamically call method and pass parameters
                    method(*args)
                    # method(*converted_args)
                    feedback_msg.status = f'action service execute  {action}  successed'
                    self.get_logger().info(feedback_msg.status)  # Add log
                    goal_handle.publish_feedback(feedback_msg)
                else:
                    self.get_logger().warning(f'action_service:inviald: {action_name},skip execution')
            except Exception as e:
                self.get_logger().error(f'action_service:execute action: {action} failed,error-log: {str(e)}')
                goal_handle.abort()
                result = Rot.Result()
                result.success = False
                return result
​
        self.action_status_pub(f'机器人反馈:执行{actions}完成') 
        self.combination_mode=False#Reset combination mode flag
    stop()  # Execute all actions to stop robot
    # Return success information to client
    goal_handle.succeed()
    result = Rot.Result()
    result.success = True
    return result

6.Interrupt Function

Robot supports interruption at any stage, specifically can be divided into recording stage interruption, dialogue stage interruption, action stage interruption. Here we introduce the principle of interruption at each stage

6.1 Recording Stage Interruption

If during recording process you find you said something wrong, or are not satisfied with the speaking content and need to re-record, during the recording process you can directly wake up again to interrupt the previous recording and directly restart speech recording

  • Logic implementation is main_loop method of ASRNode class in asr.py file:
  • Each time when waking up, if there is already a running wake-up recording thread, interrupt it through thread event stop_event and wait for it to end;
  • After clearing the stop event flag, start a new recording thread
xxxxxxxxxx
def main_loop(self):
    while rclpy.ok():
        while (
            self.audio_request_queue.qsize() > 1
        ):  # 只处理最近的一次唤醒请求,防止重复唤醒 / Process only the most recent wake-up request to prevent duplicates
            self.audio_request_queue.get()
​
        if not self.audio_request_queue.empty():
            self.audio_request_queue.get()
            self.wakeup_pub.publish(
                Bool(data=True)
            )  # 发布唤醒信号 / Publish wake-up signal
            self.get_logger().info("I'm here")
            playsound(
                self.audio_dict[self.first_response]
            )  # 应答用户 / Respond to the user
​
            if (
                self.current_thread and self.current_thread.is_alive()
            ):  # 打断上次的唤醒处理线程 / Interrupt the previous wake-up handling thread
                self.stop_event.set()
                self.current_thread.join()  # 等待当前线程结束 / Wait for the current thread to finish
                self.stop_event.clear()  # 清除事件 / Clear the event
            self.current_thread = threading.Thread(target=self.kws_handler)
            self.current_thread.daemon = True
            self.current_thread.start()
        rclpy.spin_once(self, timeout_sec=0.1)
        time.sleep(0.1)

 

6.2 Dialogue Stage Interruption

If during robot speaking process, you feel the robot's response is unsatisfactory or don't want the robot to continue responding, you can use the wake word to directly interrupt the robot's speech, directly start speech recording. At this time you can give new instructions to the robot (still in current task cycle), or say "end current task" to directly end the current task and start a new task cycle.

  • Logic implementation is wakeup_callback and play_audio methods of CustomActionServer class in action_service.py file:
  • wakeup_callback is the callback function for wake-up handling. Each time when waking up in asr.py program, wake-up signal will be published through topic communication, wakeup_callback subscribes to and processes the signal.
  • Each time when waking up, detect whether pygame.mixer is playing audio, if so, notify the playing thread to stop playing through thread event self.stop_event
  • If after wake-up it's detected that previous action is running, set self.interrupt_flag flag bit, used for subsequent action interruption
xxxxxxxxxx
def wakeup_callback(self, msg):
    if msg.data:
        if pygame.mixer.music.get_busy():
            self.stop_event.set()
        if self.action_runing:
            self.interrupt_flag = True
            self.stop()
            self.pubSix_Arm(self.init_joints)

play_audio播放音频时会检测self.stop_event是否被置位,一旦检测到置位,立刻停止当前播放的音频。

xxxxxxxxxx
def play_audio(self, file_path: str, feedback: Bool = False) -> None:
    """
    同步方式播放音频函数The function for playing audio in synchronous mode
    """
    pygame.mixer.music.load(file_path)
    pygame.mixer.music.play()
    while pygame.mixer.music.get_busy():
        if self.stop_event.is_set():
            pygame.mixer.music.stop()
            self.stop_event.clear()  # Clear event
            return
        pygame.time.Clock().tick(10)
    if feedback:
        self.action_status_pub("机器人反馈:回复用户完成")

 

6.3 Action Stage Interruption

Robot will stop current action and restore initial posture when woken up during action execution.

For example, actions like robot arm grabbing, sorting machine codes, etc. need to start external programs in subprocesses. Here we use the color block moving function change_pose as an example:

When color block moving is not completed, it will keep waiting in the while not self.change_pose_future.done(): loop: during this process, if it detects that the self.interrupt_flag interruption flag is set, it will first call check_close_change_pose function to recursively end the subprocess tree, then control the robot arm to return to grabbing posture and end the task.

xxxxxxxxxx
def change_pose(self, x1, y1, x2, y2,src,tar,side,tar_size):
    src_color = src.strip("'\"")  # Remove single quotes and double quotes
    self.cur_down_name = src_color
    self.cur_down_pose[self.cur_down_name] = []
    cmd1 = "ros2 run largemodel_arm Change_Pose"
    subprocess.Popen(
        [
            "gnome-terminal",
            "--title=Change_Pose",
            "--",
            "bash",
            "-c",
            f"{cmd1}; exec bash",
        ]
    )
    time.sleep(8.0)
    x1 = int(x1)
    y1 = int(y1)
    x2 = int(x2)
    y2 = int(y2)
    side = int(side)
    tar_size = int(tar_size)
    #time.sleep(5.0)       
    #self.object_position_pub.publish(Int16MultiArray(data=[x1, y1, x2, y2]))
    
    while not self.object_position_pub.get_subscription_count():
        self.get_logger().info("--------------------continue publish------------------")
        self.object_position_pub.publish(Int16MultiArray(data=[x1, y1, x2, y2,side,tar_size]))
        time.sleep(0.1)    
    self.get_logger().info("--------------------Publish Int16Array done------------------")       
    self.object_position_pub.publish(Int16MultiArray(data=[x1, y1, x2, y2,side,tar_size]))
​
    while not self.change_pose_future.done():
        if self.interrupt_flag:
            self.check_close_change_pose()
            #self.pubSix_Arm(self.init_joints)  # Robot arm retract
            Arm.Arm_serial_servo_write6(90,120,0,0,90,30,1000)
            return
        time.sleep(0.1)
​
    result = self.change_pose_future.result()
    self.check_close_change_pose()
    if not self.interrupt_flag:
        if result.data == "change_pose_done":
            self.action_status_pub("change_pose_done", x1=x1, y1=y1, x2=x2, y2=y2)
        else:
            self.action_status_pub("change_pose_failed", x1=x1, y1=y1, x2=x2, y2=y2)
    
    self.change_pose_future = Future()  # Reset Future object
    if self.interrupt_flag:
        time.sleep(0.5)
        Arm.Arm_serial_servo_write6(90,120,0,0,90,30,1000)

 

Embodied intelligent robot system architecture
Register a model service provider account

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