在这里插入图片描述
在基于Arduino与BLDC(无刷直流电机)的机器人系统中,实现“双机器人避障+目标跟踪”的VFF(Virtual Force Field,虚拟力场)控制,是一种将环境感知、协同决策与底层动力执行高度融合的先进方案。以下是对其主要特点、应用场景及注意事项的专业解析:
一、 主要特点
基于向量合成的动态避障与跟踪机制
VFF算法的核心在于将目标点(如领航机器人)建模为“引力场”,将环境障碍物建模为“斥力场”。系统通过传感器实时获取距离与方位,计算出引力与斥力向量,并进行向量合成得出最优的二维平移速度(Vx, Vy)与角速度(Wz)。这种数学建模方式能自然处理多障碍场景,生成平滑的避障轨迹,而非生硬的急转弯。
BLDC高动态响应与精准执行
传统的直流电机难以精确响应VFF输出的连续速度指令,而BLDC电机配合FOC(磁场定向控制)算法,能够实现扭矩和转速的精确调节。其毫秒级的动态响应和低转速转矩平滑性,完美契合VFF算法输出的连续速度指令,确保机器人能流畅地执行避让动作,避免“抖动”或“抽搐”。
去中心化协同与分层架构
在双机器人协同中,系统通常采用“领航-跟随”或“头机-从机”的分层逻辑。头机负责全局路径规划、缺口探测或目标跟踪;从机通过无线通信(如ESP-NOW)接收头机的实时坐标与航向,结合自身的VFF避障逻辑,自动解算出相对位置偏差并执行跟随。这种分布式决策避免了集中式控制的单点故障风险。
局部极小值逃逸与自适应调整
纯VFF算法容易在对称障碍物或狭窄通道中陷入“死锁”或“振荡”(即受力平衡导致机器人停滞)。优秀的系统会引入局部极小值逃逸机制,例如当检测到长期停滞时注入随机速度扰动,或在VFF失效时触发A*等全局重规划辅助脱困。同时,系统可根据环境复杂度动态调整引力/斥力系数,优化运动效率。
二、 典型应用场景
智能仓储与物流分拣
在模拟或实际仓库中,多台AGV执行货物搬运。VFF控制可让跟随机器人实时避开临时堆放的物料或其他AGV,同时通过全局路径规划优化整体运输效率,减少拥堵。
人机协作与动态跟随
在商场导览、医院配送或农业巡检中,跟随机器人需要尾随工作人员或顾客。融合VFF的自适应避障跟随,能让机器人在边跟随边避障的过程中,应对突然出现的行人或障碍物,提供平稳、不跟丢的交互体验。
无人机/车编队表演与军事协同
在机器人集群表演或特种作业中,VFF控制可避免因个体误差或外部干扰导致的碰撞。通过虚拟领航者保持编队一致性,结合热成像或气体传感器快速覆盖未知区域,单个机器人失效时其余设备可自动补位。
科研验证与教育平台
作为高校《机器人学》或机器人竞赛(如RoboMaster)的核心项目,该平台被广泛用于验证多传感器融合、局部路径规划、BLDC闭环控制以及多智能体协同等前沿算法。
三、 需要注意的关键事项
算力瓶颈与实时性保障
VFF算法、传感器数据处理及多轴BLDC的FOC控制对算力要求极高。标准的Arduino Uno极易成为瓶颈,强烈建议升级至ESP32、Teensy 4.1或STM32等高性能MCU。控制回路必须使用硬件定时器中断或millis()非阻塞定时(建议控制频率≥20Hz),严禁使用delay()函数,以确保通信与电机控制的严格同步。
通信延迟与状态预测
无线通信(如WiFi、ZigBee、ESP-NOW)的延迟可能导致VFF计算基于过时的邻居位置信息,引发误判。对策是在通信协议中附带时间戳,接收方根据延迟时间预测对方当前状态;或引入状态预测模型(如卡尔曼滤波)来补偿通信延迟。
严格的电源隔离与电磁兼容(EMC)
BLDC电机在启停和差速转向时会产生极大的电流冲击和高频PWM噪声,极易干扰传感器(如超声波、IMU)和通信模块,导致“通信中断”或“定位丢失”。必须采用隔离DC-DC模块为控制电路独立供电,加装共模电感与大容量去耦电容;传感器与通信天线需使用屏蔽线并远离动力线布线。
运动学约束与底盘参数标定
麦克纳姆轮或差速底盘不能直接控制X/Y坐标,必须通过精确的逆运动学公式将全局速度指令转化为各BLDC电机的转速。如果底盘尺寸参数(如轮距、轮径)测量不准,编队运动会发生严重的轨迹变形。此外,标准的VO/VFF假设机器人是全向的,但实际差速机器人有非完整约束,需在算法中引入运动学模型以避免死锁。
安全冗余与容错机制
系统必须具备完善的安全逻辑。硬件层需配备物理急停按钮和电池欠压监控;软件层需设置最小安全距离阈值(低于阈值强制减速或停机),并在目标彻底丢失或检测到前方严重障碍物时,自动触发安全停车机制,防止盲目跟随导致碰撞。

在这里插入图片描述
1、双机器人VFF基础避障与目标跟踪(I2C通信协同)
适用场景:两辆差速机器人协同执行目标趋近任务,需实时避开静态障碍物和彼此,同时保持对全局目标点的跟踪。
核心逻辑:每台机器人独立运行VFF算法——目标点产生引力,静态障碍物和其他机器人产生斥力,合力决定运动方向。机器人间通过I2C总线交换位置信息,实现“互斥”避碰,无需中心调度。

#include <SimpleFOC.h>
#include <Wire.h>

// ==================== BLDC差速电机 ====================
BLDCMotor motorL(7), motorR(7);
BLDCDriver3PWM driverL(9, 10, 11, 8);
BLDCDriver3PWM driverR(3, 5, 6, 7);
Encoder encoderL(18, 19, 2048), encoderR(20, 21, 2048);

// ==================== 机器人状态 ====================
#define MY_ID 1
#define I2C_ADDR 0x20 + MY_ID  // 0x21 或 0x22

struct RobotState {
    float x, y;
    uint8_t priority;  // 优先级:越高越有"路权"
};
RobotState self = {0, 0, 2};    // 自身位置与优先级
RobotState other = {0, 0, 1};   // 邻居状态

// ==================== VFF参数 ====================
const float GOAL_X = 4.0, GOAL_Y = 2.0;
const float ATTRACT_GAIN = 0.02;
const float REPULSE_GAIN = 6.0;
const float REPULSE_RANGE = 1.2;   // 斥力作用范围(m)

// ==================== I2C通信 ====================
void receiveEvent(int howMany) {
    if (Wire.available() >= 12) {
        uint8_t buf[12];
        for(int i=0; i<12; i++) buf[i] = Wire.read();
        other.x = *(float*)(buf);
        other.y = *(float*)(buf + 4);
        other.priority = buf[8];
    }
}
void requestEvent() {
    uint8_t buf[12];
    *(float*)(buf) = self.x;
    *(float*)(buf + 4) = self.y;
    buf[8] = self.priority;
    Wire.write(buf, 12);
}

void setup() {
    Serial.begin(115200);
    // 初始化电机与FOC (略)
    motorL.controller = MotionControlType::velocity;
    motorR.controller = MotionControlType::velocity;
    motorL.init(); motorL.initFOC();
    motorR.init(); motorR.initFOC();

    // I2C从机模式
    Wire.begin(I2C_ADDR);
    Wire.onReceive(receiveEvent);
    Wire.onRequest(requestEvent);
}

void loop() {
    motorL.loopFOC(); motorR.loopFOC();

    // ==================== 1. VFF力场计算 ====================
    // 目标引力
    float fx = (GOAL_X - self.x) * ATTRACT_GAIN;
    float fy = (GOAL_Y - self.y) * ATTRACT_GAIN;

    // 邻居斥力(互斥避碰核心)
    float dx = self.x - other.x;
    float dy = self.y - other.y;
    float dist = sqrt(dx*dx + dy*dy);
    if (dist < REPULSE_RANGE && dist > 0.01) {
        float f = REPULSE_GAIN * (1.0 - dist/REPULSE_RANGE) / (dist + 0.01);
        fx += f * dx / dist;
        fy += f * dy / dist;
    }

    // 静态障碍物斥力(超声波/红外模拟)
    // ... (从传感器读取障碍物距离并加入斥力)

    // ==================== 2. 优先级柔化处理 ====================
    // 当距离极近时,低优先级主动让行
    if (dist < 0.6) {
        if (self.priority < other.priority) {
            // 低优先级:施加垂直于运动方向的逃逸力
            float perpX = -dy / (dist + 0.01);
            float perpY = dx / (dist + 0.01);
            fx += perpX * 0.5;
            fy += perpY * 0.5;
        } else {
            // 高优先级:小幅减速,让低优先级先过
            fx *= 0.85;
            fy *= 0.85;
        }
    }

    // ==================== 3. 差速驱动 ====================
    float vLin = constrain(sqrt(fx*fx + fy*fy) * 5, 0, 0.8);
    float vAng = constrain(atan2(fy, fx) * 1.5, -0.6, 0.6);
    float wheelBase = 0.25;
    motorL.move(vLin - vAng * wheelBase / 2);
    motorR.move(vLin + vAng * wheelBase / 2);

    // 更新自身位置(里程计积分简化)
    self.x += fx * 0.05;
    self.y += fy * 0.05;

    delay(50);
}

2、多传感器融合VFF——超声波矩阵感知与互斥逃逸决策
适用场景:仓库/展会中双AGV避障跟随,机器人通过多方向超声波感知360°环境,实现全向避障与柔性互斥逃逸。
核心逻辑:全向超声波阵列感知前后左右障碍,VFF算法将每个方向的障碍物转换为对应方向的斥力。同时,通过I2C/ESP-NOW获取邻居状态,当检测到碰撞风险时,根据预设优先级执行柔性避让——低优先级机器人主动偏航让行,高优先级小幅减速。

#include <SimpleFOC.h>
#include <NewPing.h>
#include <Wire.h>

// ==================== BLDC差速电机 ====================
BLDCMotor motorL(7), motorR(7);
// ... (驱动器和编码器初始化略)

// ==================== 机器人状态 ====================
#define MY_ID 1
#define NUM_SENSORS 4  // 前、后、左、右
const int trigPins[NUM_SENSORS] = {2, 4, 6, 8};
const int echoPins[NUM_SENSORS] = {3, 5, 7, 9};
NewPing sonar[NUM_SENSORS] = {
    NewPing(2, 3, 200), NewPing(4, 5, 200),
    NewPing(6, 7, 200), NewPing(8, 9, 200)
};

struct RobotState {
    float x, y;
    bool collisionRisk;
    uint8_t priority;
};
RobotState self = {0, 0, false, 2};
RobotState other = {0, 0, false, 1};

// ==================== VFF参数 ====================
const float GOAL_X = 3.0, GOAL_Y = 1.0;
const float ATTRACT_GAIN = 0.015;
const float REPULSE_GAIN = 8.0;
const float REPULSE_RANGE = 1.2;

// 逃逸状态
float escapeAngularVel = 0;
float slowDownRatio = 1.0;

// ==================== I2C通信 ====================
void receiveEvent(int howMany) {
    if (Wire.available() >= 10) {
        uint8_t buf[10];
        for(int i=0; i<10; i++) buf[i] = Wire.read();
        other.x = *(float*)(buf);
        other.y = *(float*)(buf + 4);
        other.priority = buf[8];
        other.collisionRisk = buf[9] > 0;
    }
}
void requestEvent() {
    uint8_t buf[10];
    *(float*)(buf) = self.x;
    *(float*)(buf + 4) = self.y;
    buf[8] = self.priority;
    buf[9] = self.collisionRisk ? 1 : 0;
    Wire.write(buf, 10);
}

void setup() {
    Serial.begin(115200);
    // 初始化电机与FOC (略)
    motorL.controller = MotionControlType::velocity;
    motorR.controller = MotionControlType::velocity;
    motorL.init(); motorL.initFOC();
    motorR.init(); motorR.initFOC();

    Wire.begin(0x21 + MY_ID);
    Wire.onReceive(receiveEvent);
    Wire.onRequest(requestEvent);
}

void loop() {
    motorL.loopFOC(); motorR.loopFOC();

    // ==================== 1. 多方向超声波测距 ====================
    float distances[NUM_SENSORS];
    float angles[NUM_SENSORS] = {0, PI, PI/2, -PI/2}; // 前、后、左、右
    for (int i = 0; i < NUM_SENSORS; i++) {
        distances[i] = sonar[i].ping_cm() / 100.0;  // 转米
        if (distances[i] <= 0) distances[i] = REPULSE_RANGE + 0.5;
    }

    // ==================== 2. VFF力场计算 ====================
    float fx = (GOAL_X - self.x) * ATTRACT_GAIN;
    float fy = (GOAL_Y - self.y) * ATTRACT_GAIN;

    // 2.1 全向超声波斥力(按方向分解)
    for (int i = 0; i < NUM_SENSORS; i++) {
        if (distances[i] < REPULSE_RANGE) {
            float f = REPULSE_GAIN * (1.0 - distances[i]/REPULSE_RANGE) / (distances[i] + 0.01);
            fx += f * cos(angles[i]);
            fy += f * sin(angles[i]);
        }
    }

    // 2.2 邻居机器人斥力
    float dx = self.x - other.x;
    float dy = self.y - other.y;
    float dist = sqrt(dx*dx + dy*dy);
    if (dist < REPULSE_RANGE && dist > 0.01) {
        float f = REPULSE_GAIN * 0.5 * (1.0/dist - 1.0/REPULSE_RANGE);
        fx += f * dx / dist;
        fy += f * dy / dist;
    }

    // ==================== 3. 【核心】柔性互斥逃逸决策 ====================
    if (dist < 0.6) {
        // 近距离碰撞风险:基于优先级执行逃逸
        if (self.priority < other.priority) {
            // 低优先级:施加垂直于碰撞方向的偏航
            float perpAngle = atan2(dy, dx) + PI/2;
            fx += cos(perpAngle) * 0.6;
            fy += sin(perpAngle) * 0.6;
            escapeAngularVel = 0.3;
        } else if (self.priority > other.priority) {
            // 高优先级:小幅减速
            slowDownRatio = 0.85;
        }
    } else {
        escapeAngularVel = 0;
        slowDownRatio = 1.0;
    }

    // 应用减速
    fx *= slowDownRatio;
    fy *= slowDownRatio;

    // ==================== 4. 差速驱动 ====================
    float vLin = constrain(sqrt(fx*fx + fy*fy) * 4, 0, 0.7) * slowDownRatio;
    float vAng = constrain(atan2(fy, fx) * 1.5 + escapeAngularVel, -0.8, 0.8);
    float wheelBase = 0.25;
    motorL.move(vLin - vAng * wheelBase / 2);
    motorR.move(vLin + vAng * wheelBase / 2);

    // 更新位置(简化)
    self.x += fx * 0.05;
    self.y += fy * 0.05;

    delay(50);
}

3、UWB差分定位双机器人协同跟随与VFF避障
适用场景:两机器人在开阔场地(商场/园区)执行协同任务,从机通过UWB差分定位获取主机位置并跟随,同时利用VFF避开静态障碍物。
核心逻辑:从机通过双UWB标签差分定位获取主机相对位置,设定期望跟随距离(如1.2m)。跟随误差作为引力源,VFF算法同步处理静态障碍物斥力,实现目标跟踪与避障融合控制。

#include <SimpleFOC.h>
#include <DW1000Ranging.h>  // UWB定位库

// ==================== BLDC差速电机 ====================
BLDCMotor motorL(7), motorR(7);
// ... (驱动器和编码器初始化略)

// ==================== UWB定位变量 ====================
const uint8_t ROBOT1_TAG_ID = 0x01;  // 主机标签ID
const uint8_t ROBOT2_TAG_ID = 0x02;  // 从机标签ID

float targetPos[2] = {0, 0};    // 主机位置
float currentPos[2] = {0, 0};   // 从机自身位置

const float DESIRED_DISTANCE = 1.2;   // 期望跟随距离(m)
const float MAX_SPEED = 1.0;
const float REPULSE_RANGE = 1.0;
const float REPULSE_GAIN = 5.0;

// ==================== 超声波避障 ====================
#define TRIG_F 2
#define ECHO_F 3
NewPing sonarF(TRIG_F, ECHO_F, 200);

void setup() {
    Serial.begin(115200);
    // 初始化电机与FOC (略)
    motorL.controller = MotionControlType::velocity;
    motorR.controller = MotionControlType::velocity;
    motorL.init(); motorL.initFOC();
    motorR.init(); motorR.initFOC();

    // 初始化UWB (DW1000)
    // uwb_robot1.begin(ROBOT1_TAG_ID, 9600);
    // uwb_robot2.begin(ROBOT2_TAG_ID, 9600);
}

void loop() {
    motorL.loopFOC(); motorR.loopFOC();

    // ==================== 1. UWB获取位置 ====================
    // 实际从UWB模块读取
    // uwb_robot1.getPosition(targetPos);
    // uwb_robot2.getPosition(currentPos);

    // ==================== 2. 计算跟随误差 ====================
    float errorX = targetPos[0] - currentPos[0];
    float errorY = targetPos[1] - currentPos[1];
    float errorDist = sqrt(errorX*errorX + errorY*errorY);

    // ==================== 3. 跟随引力 + 避障斥力 ====================
    float fx = 0, fy = 0;

    // 3.1 引力:目标位置(带期望距离调整)
    if (errorDist > DESIRED_DISTANCE) {
        float scale = (errorDist - DESIRED_DISTANCE) * 0.02;
        fx += errorX / errorDist * scale;
        fy += errorY / errorDist * scale;
    } else if (errorDist < DESIRED_DISTANCE * 0.8) {
        // 距离过近:产生反向力(后退)
        float scale = (DESIRED_DISTANCE - errorDist) * 0.01;
        fx -= errorX / errorDist * scale;
        fy -= errorY / errorDist * scale;
    }

    // 3.2 前方超声波避障斥力
    float frontDist = sonarF.ping_cm() / 100.0;
    if (frontDist > 0 && frontDist < REPULSE_RANGE) {
        float f = REPULSE_GAIN * (1.0 - frontDist/REPULSE_RANGE) / (frontDist + 0.01);
        fx -= f;  // 向后斥力(前方有障碍)
    }

    // ==================== 4. 差速驱动 ====================
    float vLin = constrain(sqrt(fx*fx + fy*fy) * 3, 0, MAX_SPEED);
    float vAng = constrain(atan2(fy, fx) * 1.5, -0.8, 0.8);
    float wheelBase = 0.25;
    motorL.move(vLin - vAng * wheelBase / 2);
    motorR.move(vLin + vAng * wheelBase / 2);

    delay(50);
}

要点解读
基于上述案例与搜索结果,以下是面向双机器人VFF避障+目标跟踪的五个核心工程要点:
1、VFF的核心架构:引力+斥力双场融合:目标点产生引力(ATTRACT_GAIN),障碍物(含其他机器人)产生斥力(REPULSE_GAIN),合力决定机器人运动方向。关键调参:引力增益过大导致路径生硬易撞障碍,斥力增益过大则机器人可能被“弹开”偏离目标过远。工程上从较小增益开始逐步调整。

2、互斥避碰的“优先级+柔性逃逸”策略:当两机接近碰撞时,传统VFF对称斥力易导致双方同时偏转造成“死锁”。改进方案引入优先级机制——低优先级机器人主动偏航让行(施加垂直于碰撞方向的逃逸力),高优先级小幅减速配合,实现“互惠”避让。工程实现中,低优先级偏航角度约45°90°,偏航力系数0.30.6为宜。

3、通信是协同的“神经系统”:双机需实时交换位置和状态。在短距离(<5m)场景,I2C总线是简单可靠的方案(案例一、二);在开阔场地,ESP-NOW提供更低延迟(<10ms)的无线通信。必须设计通信超时保护——当邻居数据超时(如>200ms未更新),应降级为纯静态避障模式。

4、局部极小值逃逸是VFF的“必修课”:U型障碍或对称布局下,机器人的引力与斥力可能恰好抵消导致停滞。缓解策略包括:停滞检测(速度低于阈值持续数秒)→附加旋转力场(在合力方向叠加垂直旋转分量,引导机器人沿障碍边缘滑出);或注入随机扰动打破平衡。搜索结果显示,旋转力场逃逸是当前VFF改进的主流方向。

5、BLDC FOC是VFF指令的“物理执行保障”:VFF算法会输出方向角度的连续微小变化,传统有刷电机响应慢、低速抖动,难以精准执行。SimpleFOC库的磁场定向控制能毫秒级响应速度/扭矩指令,使差速转向“丝滑”无顿挫。控制频率建议≥50Hz(周期≤20ms),以匹配VFF力场更新的实时性要求。

在这里插入图片描述
4、仓储场景双机器人协同避障+动态目标跟踪(货架搬运与目标定位)
适用场景:电商仓储、物流分拣场景中,双机器人(主机器人R1负责货架搬运,从机器人R2负责目标货物定位)需在货架林立、人员流动的动态环境中,协同规避货架、叉车、人员等障碍物,同时动态跟踪移动目标(如贴有定位标签的货物小车、移动拣货员),保障搬运与定位的同步高效,避免碰撞并确保跟踪不丢失。
核心逻辑:R1与R2通过串口建立轻量通信,共享目标位置与障碍物信息;各自通过VFF算法融合“目标吸引力”与“障碍物排斥力”,驱动BLDC电机调整行进速度与方向,R1以目标位置为引导进行货架搬运,R2动态跟踪目标并同步向R1传递位置,双机器人在避障的同时形成闭环跟踪,提升仓储协同效率。

// 核心库引入:BLDC控制+传感器+VFF算法+串口通信
#include <SimpleFOC.h>       // BLDC电机驱动
#include <Wire.h>             // I2C通信(适配部分传感器)
#include <VFFControl.h>       // VFF避障跟踪控制算法库
#include <NewPing.h>          // 超声波传感器
#include <RPLidar.h>          // 激光雷达(可选,若无则用超声波替代)

// 硬件引脚定义:双机器人硬件配置(此处仅定义主机器人R1,从机器人R2配置类似,引脚可按需求区分)
// BLDC驱动引脚(主机器人)
#define BLDC_PWM_R1 9
#define BLDC_IN1_R1 10
#define BLDC_IN2_R1 11
#define ENC_A_R1 2
#define ENC_B_R1 3
// 传感器引脚(主机器人)
#define SONAR_TRIG_R1 4
#define SONAR_ECHO_R1 5
#define IR_SENSOR_R1 A0      // 红外目标检测
#define LIDAR_RX_R1 6        // 激光雷达串口接收

// 通信与VFF核心参数
#define ROBOT_BAUD_RATE 115200   // 双机器人通信波特率
#define SAFE_DISTANCE 20.0        // 避障安全距离(cm)
#define TARGET_ATTRACTION 15.0    // 目标吸引力系数
#define OBSTACLE_REPULSION 30.0   // 障碍物排斥力系数
#define VFF_UPDATE_RATE 50        // VFF算法更新频率(Hz)
#define TARGET_TRACKING_THRESH 5  // 目标跟踪有效距离阈值(cm)

// 双机器人全局状态结构体(主机器人R1)
struct RobotStateR1 {
  float positionX, positionY;      // 机器人当前位置(cm)
  float targetX, targetY;          // 目标当前位置(cm)
  float obstacleDist;              // 最近障碍物距离(cm)
  float vffSpeed;                  // VFF算法输出的速度
  float vffDirection;              // VFF算法输出的方向(弧度)
  bool targetDetected;             // 目标是否被检测到
  float encSpeed;                  // 编码器反馈的电机速度
} stateR1;

// 从机器人R2状态(通过串口接收,此处为主机器人接收后的存储结构)
struct RobotStateR2 {
  float positionX, positionY;
  float targetX, targetY;
  bool hasTarget;
} stateR2;

// 硬件对象实例化
BLDCMotor motorR1 = BLDCMotor(11);
BLDCDriver2PWM driverR1 = BLDCDriver2PWM(BLDC_PWM_R1, BLDC_IN1_R1, BLDC_IN2_R1);
Encoder encR1(ENC_A_R1, ENC_B_R1);
NewPing sonarR1(SONAR_TRIG_R1, SONAR_ECHO_R1, 200); // 超声波最大测距200cm
VFFControl vffR1; // VFF控制算法实例

// 初始化函数
void setup() {
  Serial.begin(ROBOT_BAUD_RATE);
  
  // 初始化BLDC电机与编码器(主机器人R1)
  driverR1.init();
  motorR1.linkDriver(&driverR1);
  motorR1.init();
  motorR1.initFOC();
  motorR1.controller = MotionControlType::velocity; // 速度控制模式,便于VFF调整
  encR1.init();
  motorR1.linkSensor(&encR1);
  
  // 初始化VFF算法
  vffR1.setObstacleRepulsion(OBSTACLE_REPULSION);
  vffR1.setTargetAttraction(TARGET_ATTRACTION);
  vffR1.setSafeDistance(SAFE_DISTANCE);
  
  // 初始化传感器
  pinMode(IR_SENSOR_R1, INPUT);
  
  // 初始化全局状态
  stateR1.positionX = 0.0;
  stateR1.positionY = 0.0;
  stateR1.obstacleDist = 1000.0; // 初始无障碍
  stateR1.targetDetected = false;
  stateR1.vffSpeed = 0.0;
  stateR1.vffDirection = 0.0;
  stateR1.encSpeed = 0.0;
  
  Serial.println("仓储主机器人R1初始化完成,等待与R2通信同步");
}

// 目标检测函数:红外传感器检测目标,返回目标位置(简化为相对机器人的坐标)
void detectTarget() {
  int irValue = analogRead(IR_SENSOR_R1);
  if (irValue < 500) { // 目标在检测范围内(阈值可根据实际情况调整)
    stateR1.targetDetected = true;
    // 简化目标位置:假设目标在机器人正前方30cm,水平偏移0cm(实际可结合多传感器融合计算)
    stateR1.targetX = stateR1.positionX + 30.0;
    stateR1.targetY = stateR1.positionY;
  } else {
    stateR1.targetDetected = false;
  }
}

// 障碍物检测函数:超声波检测最近障碍物距离
void detectObstacle() {
  stateR1.obstacleDist = sonarR1.ping_cm();
  // 超声波无数据时设为最大值
  if (stateR1.obstacleDist <= 0 || stateR1.obstacleDist > 200) {
    stateR1.obstacleDist = 1000.0;
  }
}

// VFF算法计算:融合目标跟踪与避障需求,输出速度与方向
void calculateVFF() {
  // 构建VFF输入:目标位置、障碍物距离、机器人当前位置
  vffR1.setCurrentPosition(stateR1.positionX, stateR1.positionY);
  vffR1.setTargetPosition(stateR1.targetX, stateR1.targetY);
  vffR1.setObstacleDistance(stateR1.obstacleDist);
  
  // 执行VFF计算(计算虚拟吸引力与排斥力的合力,转化为速度与方向)
  vffR1.compute();
  stateR1.vffSpeed = vffR1.getOutputSpeed();
  stateR1.vffDirection = vffR1.getOutputDirection();
  
  // 速度限幅,避免电机过载
  stateR1.vffSpeed = constrain(stateR1.vffSpeed, -100.0, 100.0);
}

// 通信函数:接收从机器人R2的状态信息(主机器人R1接收,从机器人发送)
void receiveR2State() {
  if (Serial.available() >= sizeof(RobotStateR2)) {
    RobotStateR2 receivedData;
    Serial.readBytes((uint8_t*)&receivedData, sizeof(RobotStateR2));
    // 同步R2状态(实际可根据协同逻辑调整,此处为简化示例)
    stateR2 = receivedData;
    // 若R2检测到目标,且R1未检测到,则同步目标位置(协同跟踪)
    if (stateR2.hasTarget && !stateR1.targetDetected) {
      stateR1.targetX = stateR2.targetX;
      stateR1.targetY = stateR2.targetY;
      stateR1.targetDetected = true;
    }
  }
}

// BLDC电机控制函数:根据VFF输出的速度控制电机
void controlBLDCWithVFF() {
  // 将VFF输出的速度映射到电机目标速度(假设编码器脉冲与速度对应关系为1:1,实际需校准)
  motorR1.target = stateR1.vffSpeed * 50; // 映射系数,根据电机参数调整
  motorR1.move(VFF_UPDATE_RATE); // 按VFF更新频率执行电机控制
  
  // 获取编码器反馈速度
  stateR1.encSpeed = motorR1.shaft_velocity();
}

void loop() {
  // 1. 通信同步:接收从机器人R2的状态
  receiveR2State();
  
  // 2. 传感器检测:目标与障碍物
  detectTarget();
  detectObstacle();
  
  // 3. VFF控制计算:融合避障与跟踪需求
  if (stateR1.targetDetected) {
    calculateVFF();
    // 执行电机控制,实现避障+跟踪
    controlBLDCWithVFF();
  } else {
    // 无目标时,仅执行避障(VFF仅输出排斥力对应的速度)
    vffR1.setTargetPosition(stateR1.positionX, stateR1.positionY); // 目标为自身,仅避障
    vffR1.compute();
    stateR1.vffSpeed = constrain(vffR1.getOutputSpeed(), -50.0, 50.0);
    motorR1.target = stateR1.vffSpeed * 50;
    motorR1.move(VFF_UPDATE_RATE);
  }
  
  // 4. 更新机器人位置(简化模型:根据速度与方向更新位置,实际可结合编码器或定位模块)
  stateR1.positionX += stateR1.vffSpeed * cos(stateR1.vffDirection) * 0.02; // 0.02为时间步长(50Hz对应0.02s)
  stateR1.positionY += stateR1.vffSpeed * sin(stateR1.vffDirection) * 0.02;
  
  // 5. 输出状态信息
  Serial.print("R1状态 | 位置(X,Y):(" + String(stateR1.positionX,1) + "," + String(stateR1.positionY,1) + ") ");
  Serial.print("目标检测:" + String(stateR1.targetDetected?"是":"否") + " ");
  Serial.print("障碍物距离:" + String(stateR1.obstacleDist,1) + "cm ");
  Serial.print("VFF速度:" + String(stateR1.vffSpeed,1) + " 方向:" + String(stateR1.vffDirection * 180 / M_PI,1) + "°");
  Serial.println();
  
  delay(20); // 50Hz运行频率,与VFF更新频率匹配
}
// 从机器人R2代码框架(硬件配置与R1类似,核心差异为通信发送与目标共享)
/*
// 从机器人R2核心逻辑简化版
struct RobotStateR2 {
  float positionX, positionY;
  float targetX, targetY;
  bool hasTarget;
  float vffSpeed, vffDirection;
} stateR2;

void setupR2() {
  // 初始化BLDC、传感器、VFF(同R1,引脚对应R2硬件)
  // 初始化串口通信
  Serial.begin(ROBOT_BAUD_RATE);
}

void loopR2() {
  // 1. 目标检测(R2检测自身目标)
  // 2. VFF计算(R2的避障+跟踪,目标为自身检测的目标)
  // 3. 控制BLDC电机
  // 4. 发送R2状态(目标位置、自身位置、是否有目标)到R1
  Serial.write((uint8_t*)&stateR2, sizeof(RobotStateR2));
  delay(20);
}
*/

代码逻辑说明:
双机器人协同逻辑:通过串口实现主从机器人的状态共享,主机器人R1接收从机器人R2的目标信息,弥补自身目标检测盲区,从机器人R2主动上报自身检测到的目标,确保双机器人目标信息同步,实现协同跟踪;
VFF融合控制:将目标跟踪的“吸引力”与避障的“排斥力”纳入同一力场计算,机器人根据合力调整BLDC电机速度与方向,既跟随目标,又自动规避障碍,无需分开处理避障与跟踪逻辑;
状态实时更新:通过编码器反馈电机实际速度,结合VFF输出的速度实时更新机器人位置,确保位置信息的动态准确性,为VFF算法提供可靠的当前位置数据,形成闭环控制。

5、户外安防双机器人协同避障+移动目标跟踪(园区巡检与人员跟踪)
适用场景:园区、厂区等户外开放场景中,双安防机器人需在树木、路灯、车辆等静态障碍,以及行人、车辆等动态障碍的复杂环境下,协同规避所有障碍,同时动态跟踪移动目标(如闯入人员、可疑车辆),保障园区安全,要求机器人能应对户外环境变化,实时调整跟踪与避障策略,避免漏跟踪或碰撞。
核心逻辑:双机器人采用“主从互补”策略——主机器人R1负责大范围目标搜索与全局避障,从机器人R2负责近距离精准跟踪;二者通过通信共享障碍物信息,VFF算法在户外复杂环境下自适应调整排斥力(遇动态障碍时增大排斥力,避免突发碰撞),主机器人R1锁定目标后,R2跟进跟踪,同时二者协同规避树木、车辆等静态障碍,确保跟踪的连续性与避障的安全性。

// 核心库引入:适配户外环境的传感器与控制
#include <SimpleFOC.h>
#include <Wire.h>
#include <VFFControl.h>
#include <NewPing.h>
#include <RPLidar.h> // 激光雷达用于户外大范围障碍检测(可选,无则用多超声波替代)

// 硬件引脚定义:户外机器人主机器人R1
#define BLDC_PWM_R1 9
#define BLDC_IN1_R1 10
#define BLDC_IN2_R1 11
#define ENC_A_R1 2
#define ENC_B_R1 3
#define SONAR_TRIG_1_R1 4
#define SONAR_ECHO_1_R1 5
#define SONAR_TRIG_2_R1 6 // 双超声波,扩大检测范围
#define SONAR_ECHO_2_R1 7
#define IR_SENSOR_R1 A0
#define LIDAR_TX_R1 8
#define LIDAR_RX_R1 9

// 户外场景VFF核心参数(动态调整)
#define OUTDOOR_SAFE_DIST 30.0       // 户外安全距离增大,适应开阔场景
#define OUTDOOR_TARGET_ATTR 12.0     // 户外目标吸引力适当降低,避免过冲
#define DYNAMIC_OBSTACLE_REPULSION 50.0 // 动态障碍排斥力增强,应对突发干扰
#define OUTDOOR_VFF_RATE 40         // 户外更新频率降低,适应大范围运动

// 户外双机器人状态结构体(主机器人R1)
struct OutdoorRobotStateR1 {
  float positionX, positionY;
  float targetX, targetY;
  float obsDistFront, obsDistLeft, obsDistRight; // 多方向障碍物距离
  bool targetTracking;
  float vffSpeed, vffDirection;
  bool dynamicObstacle; // 是否存在动态障碍
  float targetSpeed;    // 目标移动速度(用于调整吸引力)
} outdoorStateR1;

// 硬件对象实例化
BLDCMotor motorR1 = BLDCMotor(11);
BLDCDriver2PWM driverR1 = BLDCDriver2PWM(BLDC_PWM_R1, BLDC_IN1_R1, BLDC_IN2_R1);
Encoder encR1(ENC_A_R1, ENC_B_R1);
NewPing sonarFrontR1(SONAR_TRIG_1_R1, SONAR_ECHO_1_R1, 200);
NewPing sonarLeftR1(SONAR_TRIG_2_R1, SONAR_ECHO_2_R1, 200);
VFFControl vffR1;

// 初始化函数
void setup() {
  Serial.begin(115200);
  Serial2.begin(115200); // 激光雷达串口(若使用)
  
  // 初始化BLDC电机
  driverR1.init();
  motorR1.linkDriver(&driverR1);
  motorR1.init();
  motorR1.initFOC();
  motorR1.controller = MotionControlType::velocity;
  encR1.init();
  motorR1.linkSensor(&encR1);
  
  // 初始化VFF算法,适配户外参数
  vffR1.setObstacleRepulsion(OUTDOOR_TARGET_ATTR);
  vffR1.setSafeDistance(OUTDOOR_SAFE_DIST);
  vffR1.setDynamicObstacleMode(true); // 开启动态障碍模式
  
  // 初始化状态
  outdoorStateR1.positionX = 0.0;
  outdoorStateR1.positionY = 0.0;
  outdoorStateR1.targetTracking = false;
  outdoorStateR1.dynamicObstacle = false;
  outdoorStateR1.vffSpeed = 0.0;
  outdoorStateR1.obsDistFront = 1000.0;
  outdoorStateR1.obsDistLeft = 1000.0;
  outdoorStateR1.obsDistRight = 1000.0;
  outdoorStateR1.targetSpeed = 0.0;
  
  Serial.println("户外安防主机器人R1初始化完成");
}

// 多方向障碍物检测:前、左、右三个超声波检测,扩大感知范围
void detectMultiDirectionObstacle() {
  outdoorStateR1.obsDistFront = sonarFrontR1.ping_cm();
  outdoorStateR1.obsDistLeft = sonarLeftR1.ping_cm();
  outdoorStateR1.obsDistRight = 1000.0; // 若需右方检测,可增加第三个超声波
  
  // 无数据或超量程设为最大值
  if (outdoorStateR1.obsDistFront <= 0) outdoorStateR1.obsDistFront = 1000.0;
  if (outdoorStateR1.obsDistLeft <= 0) outdoorStateR1.obsDistLeft = 1000.0;
  
  // 检测动态障碍:若障碍物距离快速变化,判定为动态障碍
  static float lastFrontDist = 1000.0;
  float distChange = fabs(outdoorStateR1.obsDistFront - lastFrontDist);
  if (distChange > 10.0) { // 距离变化超过10cm,判定为动态障碍
    outdoorStateR1.dynamicObstacle = true;
    vffR1.setDynamicRepulsion(DYNAMIC_OBSTACLE_REPULSION); // 增大动态障碍排斥力
  } else {
    outdoorStateR1.dynamicObstacle = false;
    vffR1.setDynamicRepulsion(OBSTACLE_REPULSION); // 恢复正常排斥力
  }
  lastFrontDist = outdoorStateR1.obsDistFront;
}

// 户外目标检测:红外+激光雷达(简化为红外检测,雷达用于障碍物补充)
void detectOutdoorTarget() {
  int irValue = analogRead(IR_SENSOR_R1);
  if (irValue < 400) { // 户外红外检测阈值调整
    outdoorStateR1.targetTracking = true;
    // 简化目标位置:结合红外与超声波估算目标距离,计算目标坐标
    float targetDist = sonarFrontR1.ping_cm() - 5.0; // 目标与机器人的直线距离
    if (targetDist > 0) {
      outdoorStateR1.targetX = outdoorStateR1.positionX + targetDist;
      outdoorStateR1.targetY = outdoorStateR1.positionY;
      // 估算目标移动速度:基于距离变化率(简化计算)
      static float lastTargetDist = targetDist;
      outdoorStateR1.targetSpeed = (targetDist - lastTargetDist) / 0.025; // 0.025s为时间间隔
      lastTargetDist = targetDist;
    }
  } else {
    outdoorStateR1.targetTracking = false;
  }
}

// 户外VFF自适应计算:根据动态障碍与目标速度调整参数
void calculateOutdoorVFF() {
  // 根据目标速度调整吸引力:目标移动越快,吸引力适当增大,避免跟踪丢失
  float adjustedAttraction = OUTDOOR_TARGET_ATTR;
  if (fabs(outdoorStateR1.targetSpeed) > 10.0) { // 目标速度超过10cm/s
    adjustedAttraction = OUTDOOR_TARGET_ATTR * 1.2;
  }
  vffR1.setTargetAttraction(adjustedAttraction);
  
  // 设置机器人位置与目标位置
  vffR1.setCurrentPosition(outdoorStateR1.positionX, outdoorStateR1.positionY);
  vffR1.setTargetPosition(outdoorStateR1.targetX, outdoorStateR1.targetY);
  
  // 传递多方向障碍物距离(VFF算法内部可处理多方向障碍的合力计算)
  vffR1.setMultiObstacleDistance(outdoorStateR1.obsDistFront, outdoorStateR1.obsDistLeft, outdoorStateR1.obsDistRight);
  
  // 执行VFF计算
  vffR1.compute();
  outdoorStateR1.vffSpeed = vffR1.getOutputSpeed();
  outdoorStateR1.vffDirection = vffR1.getOutputDirection();
  
  // 速度限幅,适应户外大范围运动
  outdoorStateR1.vffSpeed = constrain(outdoorStateR1.vffSpeed, -80.0, 80.0);
}

// 双机器人协同通信:主机器人R1发送自身状态,从机器人R2接收并同步(示例为R1发送逻辑,R2接收适配)
void sendR1StateToR2() {
  // 打包状态数据(简化发送,实际需按协议打包)
  String stateStr = String(outdoorStateR1.positionX) + "," + String(outdoorStateR1.positionY) + "," +
                    String(outdoorStateR1.targetX) + "," + String(outdoorStateR1.targetY) + "," +
                    String(outdoorStateR1.dynamicObstacle ? "1" : "0") + ";";
  Serial.println(stateStr); // 通过串口发送给R2
}

// 电机控制:根据户外VFF输出调整BLDC速度
void controlOutdoorBLDC() {
  motorR1.target = outdoorStateR1.vffSpeed * 40; // 映射系数适配户外电机
  motorR1.move(1000 / OUTDOOR_VFF_RATE); // 按户外更新频率执行
}

void loop() {
  // 1. 障碍物与目标检测
  detectMultiDirectionObstacle();
  detectOutdoorTarget();
  
  // 2. 若跟踪目标,执行户外VFF自适应计算
  if (outdoorStateR1.targetTracking) {
    calculateOutdoorVFF();
    controlOutdoorBLDC();
  } else {
    // 无目标时,仅执行避障(VFF排斥力主导)
    vffR1.setTargetPosition(outdoorStateR1.positionX, outdoorStateR1.positionY);
    vffR1.compute();
    outdoorStateR1.vffSpeed = constrain(vffR1.getOutputSpeed(), -40.0, 40.0);
    motorR1.target = outdoorStateR1.vffSpeed * 40;
    motorR1.move(1000 / OUTDOOR_VFF_RATE);
  }
  
  // 3. 更新机器人位置(户外运动范围大,时间步长调整)
  outdoorStateR1.positionX += outdoorStateR1.vffSpeed * cos(outdoorStateR1.vffDirection) * 0.025;
  outdoorStateR1.positionY += outdoorStateR1.vffSpeed * sin(outdoorStateR1.vffDirection) * 0.025;
  
  // 4. 协同通信:发送状态给从机器人R2
  sendR1StateToR2();
  
  // 5. 输出状态
  Serial.print("户外R1 | 位置(X,Y):(" + String(outdoorStateR1.positionX,1) + "," + String(outdoorStateR1.positionY,1) + ") ");
  Serial.print("目标跟踪:" + String(outdoorStateR1.targetTracking?"是":"否") + " ");
  Serial.print("动态障碍:" + String(outdoorStateR1.dynamicObstacle?"是":"否") + " ");
  Serial.print("VFF速度:" + String(outdoorStateR1.vffSpeed,1) + " 方向:" + String(outdoorStateR1.vffDirection * 180 / M_PI,1) + "°");
  Serial.println();
  
  delay(1000 / OUTDOOR_VFF_RATE); // 按VFF更新频率延时
}

代码逻辑说明:
多方向障碍检测:通过多超声波传感器覆盖前、左、右等方向,扩大户外环境感知范围,解决户外开阔场景下障碍物方向不固定的问题,为VFF算法提供全面的障碍信息,避免单方向检测的盲区;
VFF自适应调整:针对户外动态障碍(如行人、车辆),通过距离变化率判定动态障碍,自动增大排斥力系数,同时根据目标移动速度调整吸引力系数——目标移动快时增大吸引力,避免跟踪丢失,实现VFF参数随环境动态适配;
双机器人协同通信:主机器人实时向从机器人发送自身状态与目标信息,从机器人同步调整跟踪策略,形成主从互补的跟踪模式,主机器人负责大范围搜索,从机器人负责近距离精准跟踪,提升户外目标跟踪的连续性与覆盖范围。

6、应急救援双机器人协同避障+生命体征目标跟踪(废墟搜救)
适用场景:地震、建筑坍塌等废墟救援场景中,双救援机器人需在瓦砾、钢筋、障碍物密集的复杂环境中,协同规避坍塌障碍物,同时动态跟踪具有生命体征的目标(通过生命体征传感器检测的目标位置),为救援人员提供目标定位与路径开辟,要求机器人能在狭小空间内精准避障,同时稳定跟踪生命目标,避免因避障导致跟踪丢失,保障救援效率。
核心逻辑:双机器人采用“前后协同”策略——前机器人R1负责近距离避障与目标搜索,后机器人R2负责生命体征目标锁定与跟踪;R1通过VFF算法规避密集障碍,同时将感知到的障碍物信息传递给R2,R2同步调整避障路径,锁定目标后通过VFF算法融合“生命目标吸引力”与“R1传递的障碍信息”,在规避障碍的同时稳定跟踪目标,双机器人形成前后呼应的协同模式,适应废墟狭小空间的复杂环境。

// 核心库引入:适配废墟救援的紧凑控制与传感器
#include <SimpleFOC.h>
#include <Wire.h>
#include <VFFControl.h>
#include <NewPing.h>
#include <Servo.h> // 伺服舵机辅助转向,适应狭小空间

// 硬件引脚定义:废墟救援前机器人R1(结构紧凑,多超声波检测)
#define BLDC_PWM_R1 9
#define BLDC_IN1_R1 10
#define BLDC_IN2_R1 11
#define ENC_A_R1 2
#define ENC_B_R1 3
#define SONAR_FRONT_R1 4
#define SONAR_ECHO_FRONT_R1 5
#define SONAR_LEFT_R1 6
#define SONAR_ECHO_LEFT_R1 7
#define SONAR_RIGHT_R1 8
#define SONAR_ECHO_RIGHT_R1 9
#define SERVO_STEER_R1 12 // 伺服舵机用于转向,适应狭小空间
#define LIFE_SENSOR_R1 A0  // 生命体征检测传感器(简化为模拟输入,实际为专用传感器)

// 废墟场景VFF核心参数(狭小空间优化)
#define RUBBLE_SAFE_DIST 15.0        // 狭小空间安全距离减小,适配密集障碍
#define RUBBLE_TARGET_ATTR 18.0      // 吸引力增大,确保废墟中跟踪稳定性
#define RUBBLE_REPULSION 40.0        // 排斥力增大,应对密集障碍
#define RUBBLE_VFF_RATE 60          // 高更新频率,应对狭小空间快速避障
#define MIN_TRACKING_DIST 10.0       // 最小跟踪距离,避免碰撞目标

// 废墟救援双机器人状态结构体(前机器人R1)
struct RescueRobotStateR1 {
  float positionX, positionY;
  float targetX, targetY;
  float obsFront, obsLeft, obsRight;
  bool lifeTargetDetected;
  float vffSpeed, vffDirection;
  float steerAngle; // 伺服舵机转向角度
} rescueStateR1;

// 硬件对象实例化
BLDCMotor motorR1 = BLDCMotor(11);
BLDCDriver2PWM driverR1 = BLDCDriver2PWM(BLDC_PWM_R1, BLDC_IN1_R1, BLDC_IN2_R1);
Encoder encR1(ENC_A_R1, ENC_B_R1);
NewPing sonarFrontR1(SONAR_FRONT_R1, SONAR_ECHO_FRONT_R1, 150);
NewPing sonarLeftR1(SONAR_LEFT_R1, SONAR_ECHO_LEFT_R1, 150);
NewPing sonarRightR1(SONAR_RIGHT_R1, SONAR_ECHO_RIGHT_R1, 150);
Servo steerServoR1;
VFFControl vffR1;

// 初始化函数
void setup() {
  Serial.begin(115200);
  
  // 初始化BLDC电机
  driverR1.init();
  motorR1.linkDriver(&driverR1);
  motorR1.init();
  motorR1.initFOC();
  motorR1.controller = MotionControlType::velocity;
  encR1.init();
  motorR1.linkSensor(&encR1);
  
  // 初始化伺服舵机(转向用)
  steerServoR1.attach(SERVO_STEER_R1);
  steerServoR1.write(90); // 初始居中
  
  // 初始化VFF算法,适配废墟参数
  vffR1.setObstacleRepulsion(RUBBLE_REPULSION);
  vffR1.setTargetAttraction(RUBBLE_TARGET_ATTR);
  vffR1.setSafeDistance(RUBBLE_SAFE_DIST);
  
  // 初始化状态
  rescueStateR1.positionX = 0.0;
  rescueStateR1.positionY = 0.0;
  rescueStateR1.lifeTargetDetected = false;
  rescueStateR1.vffSpeed = 0.0;
  rescueStateR1.vffDirection = 0.0;
  rescueStateR1.steerAngle = 90.0;
  rescueStateR1.obsFront = 1000.0;
  rescueStateR1.obsLeft = 1000.0;
  rescueStateR1.obsRight = 1000.0;
  
  Serial.println("废墟救援前机器人R1初始化完成");
}

// 废墟狭小空间障碍检测:三方向超声波,适配密集障碍
void detectRubbleObstacle() {
  rescueStateR1.obsFront = sonarFrontR1.ping_cm();
  rescueStateR1.obsLeft = sonarLeftR1.ping_cm();
  rescueStateR1.obsRight = sonarRightR1.ping_cm();
  
  // 无数据或超量程设为最大值
  if (rescueStateR1.obsFront <= 0 || rescueStateR1.obsFront > 150) rescueStateR1.obsFront = 1000.0;
  if (rescueStateR1.obsLeft <= 0 || rescueStateR1.obsLeft > 150) rescueStateR1.obsLeft = 1000.0;
  if (rescueStateR1.obsRight <= 0 || rescueStateR1.obsRight > 150) rescueStateR1.obsRight = 1000.0;
}

// 生命体征目标检测:模拟传感器检测,返回目标位置(简化为正前方近距离)
void detectLifeTarget() {
  int lifeValue = analogRead(LIFE_SENSOR_R1);
  if (lifeValue > 800) { // 生命体征检测阈值(实际需根据传感器校准)
    rescueStateR1.lifeTargetDetected = true;
    // 简化目标位置:假设目标在机器人正前方12cm处(废墟狭小空间近距离)
    rescueStateR1.targetX = rescueStateR1.positionX + 12.0;
    rescueStateR1.targetY = rescueStateR1.positionY;
  } else {
    rescueStateR1.lifeTargetDetected = false;
  }
}

// 废墟VFF密集障碍计算:三方向障碍合力,精准避障
void calculateRubbleVFF() {
  // 设置当前位置与目标位置
  vffR1.setCurrentPosition(rescueStateR1.positionX, rescueStateR1.positionY);
  vffR1.setTargetPosition(rescueStateR1.targetX, rescueStateR1.targetY);
  
  // 设置三方向障碍物距离(VFF算法内部计算各方向排斥力的合力)
  vffR1.setMultiObstacleDistance(rescueStateR1.obsFront, rescueStateR1.obsLeft, rescueStateR1.obsRight);
  
  // 执行VFF计算,输出速度与方向
  vffR1.compute();
  rescueStateR1.vffSpeed = vffR1.getOutputSpeed();
  rescueStateR1.vffDirection = vffR1.getOutputDirection();
  
  // 速度限幅,适配狭小空间的低速高精度要求
  rescueStateR1.vffSpeed = constrain(rescueStateR1.vffSpeed, -30.0, 30.0);
  
  // 计算伺服舵机转向角度:根据方向与前进方向的偏差,控制转向
  float targetDirDeg = rescueStateR1.vffDirection * 180 / M_PI; // 转换为角度
  // 简化转向逻辑:方向偏差对应舵机角度(90°为正前方,左偏减小角度,右偏增大角度)
  rescueStateR1.steerAngle = map(targetDirDeg, -90, 90, 30, 150);
  rescueStateR1.steerAngle = constrain(rescueStateR1.steerAngle, 30, 150);
}

// BLDC与舵机协同控制:速度+转向,适配狭小空间
void controlRescueBLDCWithSteer() {
  // 控制BLDC电机速度
  motorR1.target = rescueStateR1.vffSpeed * 30; // 低速映射,确保狭小空间控制精度
  motorR1.move(1000 / RUBBLE_VFF_RATE);
  
  // 控制伺服舵机转向
  steerServoR1.write(rescueStateR1.steerAngle);
}

// 双机器人协同通信:前机器人R1发送障碍物与目标信息给后机器人R2
void sendRescueStateToR2() {
  // 打包障碍物、目标、位置信息(简化协议)
  String dataStr = String(rescueStateR1.positionX) + "," + String(rescueStateR1.positionY) + "," +
                   String(rescueStateR1.obsFront) + "," + String(rescueStateR1.obsLeft) + "," + String(rescueStateR1.obsRight) + "," +
                   String(rescueStateR1.targetX) + "," + String(rescueStateR1.targetY) + "," +
                   String(rescueStateR1.lifeTargetDetected ? "1" : "0") + ";";
  Serial.println(dataStr);
}

void loop() {
  // 1. 障碍与生命目标检测
  detectRubbleObstacle();
  detectLifeTarget();
  
  // 2. 若检测到生命目标,执行废墟VFF计算与协同控制
  if (rescueStateR1.lifeTargetDetected) {
    calculateRubbleVFF();
    controlRescueBLDCWithSteer();
  } else {
    // 无生命目标时,仅避障(保持低速,避免碰撞废墟)
    vffR1.setTargetPosition(rescueStateR1.positionX, rescueStateR1.positionY);
    vffR1.compute();
    rescueStateR1.vffSpeed = constrain(vffR1.getOutputSpeed(), -15.0, 15.0);
    motorR1.target = rescueStateR1.vffSpeed * 30;
    motorR1.move(1000 / RUBBLE_VFF_RATE);
    steerServoR1.write(90); // 无目标时舵机居中,直行避障
  }
  
  // 3. 更新机器人位置(低速,时间步长适配高更新频率)
  rescueStateR1.positionX += rescueStateR1.vffSpeed * cos(rescueStateR1.vffDirection) * 0.0167; // 60Hz对应0.0167s
  rescueStateR1.positionY += rescueStateR1.vffSpeed * sin(rescueStateR1.vffDirection) * 0.0167;
  
  // 4. 协同通信:发送状态给后机器人R2
  sendRescueStateToR2();
  
  // 5. 输出状态
  Serial.print("废墟R1 | 位置(X,Y):(" + String(rescueStateR1.positionX,1) + "," + String(rescueStateR1.positionY,1) + ") ");
  Serial.print("生命目标:" + String(rescueStateR1.lifeTargetDetected?"是":"否") + " ");
  Serial.print("前/左/右障碍:" + String(rescueStateR1.obsFront,1) + "/" + String(rescueStateR1.obsLeft,1) + "/" + String(rescueStateR1.obsRight,1) + "cm ");
  Serial.print("VFF速度:" + String(rescueStateR1.vffSpeed,1) + " 方向:" + String(rescueStateR1.vffDirection * 180 / M_PI,1) + "°");
  Serial.println();
  
  delay(1000 / RUBBLE_VFF_RATE); // 适配高更新频率
}

代码逻辑说明:
狭小空间适配控制:采用BLDC电机+伺服舵机的协同控制模式,VFF算法输出速度与方向后,伺服舵机负责精准转向,BLDC电机负责低速精准调速,适应废墟狭小空间的转向与移动需求,避免因空间限制导致的碰撞;
密集障碍VFF计算:通过三方向超声波检测密集障碍物,VFF算法计算三方向障碍的排斥力合力,精准生成避障路径,同时确保对生命目标的吸引力,在密集障碍中平衡避障与跟踪,避免因避障导致目标丢失;
前后协同通信:前机器人R1实时向后机器人R2发送障碍物位置、目标位置等信息,后机器人R2同步调整避障路径与跟踪策略,前机器人负责开路避障,后机器人负责锁定生命目标,形成前后呼应的协同救援模式,提升废墟救援效率与安全性。

要点解读

  1. VFF算法核心:构建“跟踪+避障”融合力场,实现决策统一
    VFF算法的核心是将双机器人的目标跟踪需求与避障需求转化为统一的虚拟力场,避免传统控制中“先避障、后跟踪”或“先跟踪、后避障”的逻辑割裂,从根本上解决动态场景下避障与跟踪的冲突,是双机器人协同控制的核心决策逻辑。
    力场构成与逻辑:力场包含两类核心虚拟力——
    目标吸引力:基于目标与机器人的距离、运动状态生成,距离越远吸引力越强,目标移动越快吸引力适当增大(如户外场景),确保机器人主动向目标靠近,实现跟踪;
    障碍物排斥力:基于障碍物与机器人的距离、方向生成,距离越近排斥力呈指数级增大,方向垂直于障碍物指向机器人外侧,确保机器人主动远离障碍,实现避障;
    力场融合决策:机器人根据虚拟吸引力与排斥力的合力,直接生成BLDC电机的速度与方向控制量,合力的方向决定运动方向,合力的大小决定运动速度,既避免了避障与跟踪的逻辑冲突,又实现了两种任务的同步执行,让机器人在跟随目标的同时,自然规避障碍。
    双机器人协同适配:双机器人通过共享目标与障碍物信息,各自构建独立的力场,但力场参数与目标/障碍信息同步,实现“各自决策、协同目标”的联动效果,避免双机器人因信息不一致导致的路径冲突或跟踪遗漏。

  2. 双机器人协同机制:信息共享与动作互补,提升整体效能
    双机器人的核心优势在于“协同”,通过信息共享突破单一机器人的感知局限,通过动作互补弥补单一机器人的能力短板,形成“1+1>2”的协同效果,适配不同场景下的避障与跟踪需求。
    信息共享:突破感知局限:双机器人通过串口通信实现目标位置、障碍物分布、自身状态等信息的实时共享,解决单一机器人感知范围有限、信息不完整的问题——仓储场景中主机器人获取从机器人的目标信息,弥补自身盲区;户外场景中双机器人共享动态障碍信息,提前调整避障策略;救援场景中前机器人向后机器人传递障碍物信息,让后机器人提前规避,避免碰撞。
    动作互补:弥补能力短板:根据场景需求设计协同动作逻辑,仓储场景采用“主从协同”,主机器人负责搬运,从机器人负责定位;户外场景采用“主从互补”,主机器人负责大范围搜索,从机器人负责近距离跟踪;救援场景采用“前后呼应”,前机器人负责开路避障,后机器人负责锁定目标,通过动作分工与互补,提升双机器人整体的避障跟踪能力,避免单一机器人因能力不足导致的跟踪丢失或避障失效。
    逻辑价值:信息共享与动作互补的结合,让双机器人形成“感知-决策-执行”的闭环协同,既扩大了感知范围,又提升了任务执行的鲁棒性,能有效应对单一机器人无法处理的复杂动态场景。

  3. 动态环境自适应:参数动态调整与多传感器融合,提升鲁棒性
    动态环境的核心挑战是环境信息的不确定性——目标移动速度、障碍物类型、环境干扰等因素随时变化,固定参数的算法无法应对,需通过参数动态调整与多传感器融合,让双机器人自适应环境变化,提升避障与跟踪的鲁棒性。
    参数动态调整:适配环境变化:根据环境反馈动态调整VFF算法的关键参数,户外场景中目标移动快时增大吸引力,避免跟踪丢失;遇到动态障碍时增大排斥力,应对突发碰撞;仓储场景中障碍物密集时适当降低速度,提升控制精度;救援场景中狭小空间内减小安全距离,适配密集障碍,通过参数与环境匹配,确保算法始终处于最优状态。
    多传感器融合:强化感知能力:采用多传感器融合提升感知的全面性与准确性——激光雷达用于户外大范围障碍检测,超声波用于近距离障碍避障,红外用于目标检测,编码器用于反馈电机速度与位置,通过传感器优势互补,解决单一传感器的盲区与噪声问题,为VFF算法提供准确、全面的感知数据,确保力场计算的精准性。
    自适应价值:参数动态调整让算法“适应环境”,多传感器融合让感知“全面可靠”,二者结合让双机器人在动态变化的环境中,既能稳定识别目标,又能精准规避障碍,有效应对环境突变,提升系统的鲁棒性与适应性。

  4. BLDC闭环控制:高精度驱动与实时反馈,保障执行精度
    BLDC电机是双机器人运动的执行核心,其控制精度直接决定避障与跟踪的执行效果,采用闭环控制实现BLDC电机的高精度驱动,确保VFF算法的决策能精准转化为机器人的运动动作,是避障与跟踪的执行保障。
    闭环控制架构:构建“速度/位置双闭环控制”架构——外环为VFF算法输出的目标速度或位置,内环为编码器反馈的实际速度或位置,通过PID控制算法实时调整电机驱动信号,消除负载变化、地面摩擦等干扰导致的速度偏差,确保电机实际速度与VFF输出的目标速度一致,实现精准执行。
    编码器反馈:实时状态修正:编码器实时反馈电机的实际转速与位置,为闭环控制提供精准的状态反馈,VFF算法根据编码器反馈的速度实时修正力场输出,若电机实际速度滞后于目标速度,VFF算法适当增大吸引力或减小排斥力,确保机器人按预期轨迹运动,形成“感知-决策-执行-反馈-修正”的闭环。
    执行精度保障:闭环控制让BLDC电机具备高精度的响应能力与抗干扰能力,既能快速响应VFF算法的速度与方向变化,又能在动态负载下维持稳定的速度,确保机器人在避障与跟踪过程中轨迹精准,避免因电机控制偏差导致的避障失败或跟踪丢失。

  5. 实时性与安全性:高更新频率与安全边界设计,保障系统可靠
    双机器人在动态环境中作业,既要满足避障与跟踪的实时性要求,又要保障人员与设备的安全,实时性与安全性是系统可靠运行的双重底线,需通过算法优化与安全设计同步保障。
    实时性保障:高更新频率与轻量化算法:采用高更新频率(50-60Hz)确保VFF算法能快速响应环境变化,同时优化算法逻辑,采用轻量化的力场计算与数据打包方式,减少运算量与通信延迟,确保双机器人能实时处理目标移动、障碍物变化等动态信息,避免因响应滞后导致的避障失效或跟踪丢失;同时匹配BLDC电机的闭环控制频率,确保执行与决策同步。
    安全性设计:多层安全边界防护:通过多层设计构建安全边界,保障系统安全——设置安全距离阈值,当障碍物距离低于阈值时,立即增大排斥力或停止电机,避免碰撞;设置速度限幅,限制BLDC电机的最大速度,避免高速运动导致失控;设置目标跟踪最小距离,防止机器人与目标碰撞;设置传感器故障检测,当传感器失效时,自动切换到应急模式(如停止运动或仅执行基础避障),避免因传感器故障导致的安全事故。
    双重保障价值:高更新频率保障系统对动态环境的响应速度,多层安全设计筑牢安全防线,二者结合让双机器人在动态环境中既能高效执行避障与跟踪任务,又能保障人员与设备的安全,确保系统在复杂场景下的可靠运行。

请注意:以上案例仅作为思路拓展的参考示例,不保证完全正确、适配所有场景或可直接编译运行。由于硬件平台、实际使用场景、Arduino 版本的差异,均可能影响代码的适配性与使用方法的选择。在实际编程开发时,请务必根据自身硬件配置、使用场景及具体功能需求进行针对性调整,并通过多次实测验证效果;同时需确保硬件接线正确,充分了解所用传感器、执行器等设备的技术规范与核心特性。对于涉及硬件操作的代码,使用前务必核对引脚定义、电平参数等关键信息的准确性与安全性,避免因参数错误导致硬件损坏或运行异常。
在这里插入图片描述

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐