Rust机器人动作库r2r_actions的使用:高效实现机器人控制与自动化任务

Rust机器人动作库r2r_actions的使用:高效实现机器人控制与自动化任务

r2r_actions是r2r的内部依赖库,主要用于机器人控制和自动化任务。

安装

在项目目录中运行以下Cargo命令:

cargo add r2r_actions

或者在你的Cargo.toml中添加以下行:

r2r_actions = "0.9.5"

元数据

  • 版本:0.9.5
  • 发布时间:4个月前
  • 2021 edition
  • 许可证:MIT
  • 大小:8.28 KiB

所有者

  • Martin Dahl (m-dahl)

示例代码

以下是一个使用r2r_actions库的基本示例:

use r2r_actions::ActionServer;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建一个动作服务器
    let mut action_server = ActionServer::new()?;
    
    // 定义机器人动作
    action_server.register_action("move_arm", |params| {
        println!("Moving arm with parameters: {:?}", params);
        // 这里实现实际的机器人手臂移动逻辑
        Ok(())
    });
    
    // 定义另一个动作
    action_server.register_action("gripper_control", |params| {
        println!("Controlling gripper with parameters: {:?}", params);
        // 这里实现实际的夹爪控制逻辑
        Ok(())
    });
    
    // 启动动作服务器
    action_server.run()?;
    
    Ok(())
}

这个示例展示了如何:

  1. 创建一个动作服务器
  2. 注册自定义机器人动作
  3. 启动服务器处理动作请求

完整示例代码

下面是一个更完整的示例,展示了如何使用r2r_actions实现机器人控制:

use r2r_actions::ActionServer;
use std::collections::HashMap;
use std::time::Duration;

// 定义机器人状态结构体
struct RobotState {
    arm_position: f32,
    gripper_open: bool,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 初始化机器人状态
    let mut robot_state = RobotState {
        arm_position: 0.0,
        gripper_open: false,
    };

    // 创建动作服务器
    let mut action_server = ActionServer::new()?;

    // 注册移动手臂动作
    action_server.register_action("move_arm", move |params: HashMap<String, String>| {
        // 解析参数
        let target_pos = params.get("position")
            .and_then(|v| v.parse::<f32>().ok())
            .unwrap_or(0.0);
        
        println!("Moving arm to position: {}", target_pos);
        
        // 模拟移动过程
        std::thread::sleep(Duration::from_secs(1));
        
        // 更新机器人状态
        robot_state.arm_position = target_pos;
        
        Ok(())
    });

    // 注册夹爪控制动作
    action_server.register_action("gripper_control", |params: HashMap<String, String>| {
        // 解析参数
        let action = params.get("action").map(|s| s.as_str()).unwrap_or("");
        
        match action {
            "open" => {
                println!("Opening gripper");
                robot_state.gripper_open = true;
            }
            "close" => {
                println!("Closing gripper");
                robot_state.gripper_open = false;
            }
            _ => println!("Unknown gripper action"),
        }
        
        Ok(())
    });

    // 注册状态查询动作
    action_server.register_action("get_status", |_params| {
        println!("Current status - Arm position: {}, Gripper: {}", 
            robot_state.arm_position,
            if robot_state.gripper_open { "open" } else { "closed" }
        );
        Ok(())
    });

    println!("Robot action server started. Ready to receive commands...");
    
    // 启动动作服务器
    action_server.run()?;
    
    Ok(())
}

这个完整示例展示了:

  1. 定义机器人状态结构体
  2. 实现更复杂的动作处理逻辑
  3. 处理不同类型的动作参数
  4. 模拟实际的机器人动作执行
  5. 状态查询功能

你可以根据实际需求进一步扩展这个示例,添加更多动作类型和更复杂的控制逻辑。


1 回复

Rust机器人动作库r2r_actions的使用:高效实现机器人控制与自动化任务

以下是基于r2r_actions库的完整机器人控制示例demo,展示了如何实现一个完整的机器人导航系统:

use r2r_actions::prelude::*;
use async_trait::async_trait;
use r2r_actions::{ActionSequence, ActionParallel};
use r2r::{Context, Node};
use r2r_actions::ros2::RosAction;

// 定义基本机器人动作
#[derive(Debug)]
struct MoveAction {
    distance: f32,
}

#[derive(Debug)]
struct TurnAction {
    angle: f32,  // 角度,单位度
}

#[derive(Debug)]
struct ScanAction {
    duration: f32,  // 扫描持续时间,单位秒
}

// 实现移动动作
#[async_trait]
impl Action for MoveAction {
    type Result = f32;
    
    async fn execute(&mut self) -> Result<Self::Result, ActionError> {
        println!("开始移动 {} 米...", self.distance);
        
        // 模拟移动过程
        for i in 1..=10 {
            let progress = i as f32 / 10.0 * self.distance;
            println!("移动进度: {:.1} 米", progress);
            tokio::time::sleep(std::time::Duration::from_millis(300)).await;
            
            // 模拟障碍检测
            if progress > self.distance * 0.8 {
                return Err(ActionError::new("检测到障碍物!"));
            }
        }
        
        println!("移动完成!");
        Ok(self.distance)
    }
}

// 实现旋转动作
#[async_trait]
impl Action for TurnAction {
    type Result = f32;
    
    async fn execute(&mut self) -> Result<Self::Result, ActionError> {
        println!("开始旋转 {} 度...", self.angle);
        tokio::time::sleep(std::time::Duration::from_secs_f32(self.angle.abs() / 90.0)).await;
        println!("旋转完成!");
        Ok(self.angle)
    }
}

// 实现扫描动作
#[async_trait]
impl Action for ScanAction {
    type Result = Vec<f32>;  // 返回扫描到的障碍物距离
    
    async fn execute(&mut self) -> Result<Self::Result, ActionError> {
        println!("开始环境扫描,持续 {} 秒...", self.duration);
        tokio::time::sleep(std::time::Duration::from_secs_f32(self.duration)).await;
        
        // 模拟返回扫描结果
        let obstacles = vec![1.5, 2.8, 0.7];
        println!("扫描完成,发现 {} 个障碍物", obstacles.len());
        Ok(obstacles)
    }
}

// 定义高级导航动作
struct NavigateToPoint {
    x: f32,
    y: f32,
}

#[async_trait]
impl Action for NavigateToPoint {
    type Result = (f32, f32);  // 返回实际到达的坐标
    
    async fn execute(&mut self) -> Result<Self::Result, ActionError> {
        println!("开始导航到坐标 ({}, {})", self.x, self.y);
        
        // 计算需要旋转的角度和移动的距离
        let angle = self.y.atan2(self.x).to_degrees();
        let distance = (self.x.powi(2) + self.y.powi(2)).sqrt();
        
        // 创建动作序列:先旋转,再移动
        let mut sequence = ActionSequence::new();
        sequence.add(TurnAction { angle });
        sequence.add(MoveAction { distance });
        
        // 执行动作序列
        sequence.execute().await?;
        
        // 返回最终位置
        Ok((self.x, self.y))
    }
}

// 主函数
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== 机器人控制系统启动 ===");
    
    // 示例1: 执行单个动作
    println!("\n1. 测试移动动作:");
    let move_act = MoveAction { distance: 2.0 };
    match move_act.execute().await {
        Ok(d) => println!("成功移动了 {} 米", d),
        Err(e) => println!("移动失败: {}", e),
    }
    
    // 示例2: 执行动作序列
    println!("\n2. 测试动作序列:");
    let mut seq = ActionSequence::new();
    seq.add(TurnAction { angle: 90.0 });
    seq.add(MoveAction { distance: 1.5 });
    seq.add(TurnAction { angle: -45.0 });
    seq.add(MoveAction { distance: 1.0 });
    
    match seq.execute().await {
        Ok(_) => println!("所有动作执行完成!"),
        Err(e) => println!("动作序列执行失败: {}", e),
    }
    
    // 示例3: 并行执行动作
    println!("\n3. 测试并行动作:");
    let mut parallel = ActionParallel::new();
    parallel.add(MoveAction { distance: 1.0 });
    parallel.add(ScanAction { duration: 2.0 });
    
    match parallel.execute().await {
        Ok(results) => println!("并行动作结果: {:?}", results),
        Err(e) => println!("并行执行失败: {}", e),
    }
    
    // 示例4: 高级导航
    println!("\n4. 测试导航功能:");
    let nav_action = NavigateToPoint { x: 3.0, y: 4.0 };
    match nav_action.execute().await {
        Ok((x, y)) => println!("成功导航到坐标 ({}, {})", x, y),
        Err(e) => println!("导航失败: {}", e),
    }
    
    // 示例5: 与ROS 2集成
    println!("\n5. 测试ROS 2集成:");
    let ctx = Context::create()?;
    let node = Node::create(ctx, "robot_controller", "")?;
    
    // 创建ROS 2动作客户端 (这里需要实际的ROS 2环境)
    let move_client = RosAction::new(
        node.clone(),
        "move_robot",
        "robot_control_msgs/action/Move"
    )?;
    
    // 执行ROS动作 (这里需要实际的ROS 2服务)
    let goal = MoveGoal { distance: 1.5 };
    match move_client.execute(goal).await {
        Ok(result) => println!("ROS动作执行结果: {:?}", result),
        Err(e) => println!("ROS动作执行失败: {}", e),
    }
    
    println!("\n=== 机器人控制系统关闭 ===");
    Ok(())
}

这个完整示例展示了:

  1. 定义了三种基本机器人动作:移动、旋转和扫描
  2. 实现了高级导航动作,组合基本动作形成复杂行为
  3. 演示了单个动作、动作序列和并行动作的执行
  4. 展示了与ROS 2集成的代码
  5. 包含了完整的错误处理机制

要运行此代码,需要:

  1. 安装Rust和Cargo
  2. 在Cargo.toml中添加r2r_actions和tokio依赖
  3. 对于ROS 2集成部分,需要安装ROS 2和r2r库

这个示例可以作为机器人控制应用的起点,您可以根据实际需求扩展更多动作类型和复杂行为。

回到顶部