Home
avatar

230

控制无人机无果,在油管评论区找到的思路

这篇文章主要讲的是emmm,如何在argos利用buzz脚本对无人机进行控制。流程清晰,按照我得方法指定能跑。第四部分为标题所对应的内容。

讲一下最近在干什么

这俩月老师给的需求是设计一种语言,对多个机器进行分布式控制、协调、调度。调研相关资料,问了一下gpt先生最相关的DSL(领域特定语言)有什么。BUZZ语言感觉是最贴切这个任务的,要把这个语言跑起来需要利用仿真器ARGoS3。OK那么进入正题 论文地址

确认一下环境

  • A UNIX system (Linux or MacOSX; Microsoft Windows is not supported)
  • g++ >= 4.3 (on Linux) or clang >= 3.1 (on MacOSX)
  • cmake >= 2.8.12

安装仿真器ARGoS3

下载二进制文件argos3_simulator-3.0.0-x86_64-beta59.deb免去了cmke构建的过程

sudo apt install ./argos3_simulator-3.0.0-x86_64-beta59.deb
argos3 -v

屏幕截图 2025-09-30 224009.png

验证完版本信息以后,需要看看这个argos3能不能用?github有一个仓库叫argos3-example有大量的例子,我们git clone一下

git clone https://github.com/ilpincy/argos3-examples.git argos3-examples
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make

注意需要自己构建一下

遇到的问题:图形化界面弹不出来?缺少libglut.so.3 依赖屏幕截图 2025-09-30 224350.png

解决方法:

sudo apt update
sudo apt install -y libglut3.12 libglu1-mesa
ls -l /usr/lib/x86_64-linux-gnu/libglut.so*
ldconfig -p | grep libglut.so.3
sudo ln -sf /usr/lib/x86_64-linux-gnu/libglut.so.3.12.0 /usr/lib/x86_64-linux-gnu/libglut.so.3
sudo ln -sf /usr/lib/x86_64-linux-gnu/libglut.so.3.12.0 /lib/x86_64-linux-gnu/libglut.so.3
sudo ldconfig

运行:

cd ~/argos3-examples
argos3 -c experiments/diffusion_1.argos

屏幕截图 2025-09-30 224501.png

BUZZ获取

很好现在已经有仿真器了,如何得到buzz并且跑起来呢?

git clone https://github.com/buzz-lang/Buzz.git buzz
cd buzz
mkdir build && cd build
cmake ../src
make
sudo make install
sudo ldconfig

构建完以后查看一下 屏幕截图 2025-09-30 224652.png

目录结构核对一下,解释一下里面的内容:

  • bzzrun → Buzz 的解释器(运行 .bzz 程序的主入口,等价于你预期的 buzz 命令)。
  • bzzasm → Buzz 的汇编器,把 Buzz 汇编代码转成字节码。
  • bzzdeasm → Buzz 的反汇编器。
  • bzzparse → Buzz 解析器,用来调试语法。
  • libbuzz.so / libbuzzdbg.so → Buzz 的动态库。

如何在ARGoS中把Buzz脚本跑起来?

原理图:屏幕截图 2025-09-27 214951.png 来看一下buzz官方仓库的md文档,给的很笼统写不出demo例子。拷打了大模型先生两天无果,因为xml里面的一些组件根本就没有实现,当时怀疑是不是.so链接库和buzz版本不匹配实现不了?毕竟是十年前的产物,嫉妒怀疑自己。偶然间发现啊,Youtube视频下面讲buzz的有个人的评论

屏幕截图 2025-09-30 181258.png

testing目录下面有buzz对应的例子,ok去找了一下屏幕截图 2025-09-30 225248.png

发现,

卧槽真能跑。OK了把argos文件和bzz喂给大模型,让他学习。 给了一个例子红蓝两队无人机,按照id进行分组利用buzz的swarm特性。

<?xml version="1.0" ?>
<argos-configuration>
<!-- ************************* -->
<!-- * General configuration * -->
<!-- ************************* -->
<framework>
 <!--
    system threads: 0 表示“使用所有可用 CPU 线程”,手动限核就填具体数字。
     experiment:
    length=0 表示“无限时长”,直到控制脚本主动停止或窗口关闭。
    ticks_per_second: 仿真步频(Hz)。10 意味着每个 tick = 0.1s。
    random_seed: 随机种子;固定种子可复现实验。
  -->
  <system threads="0" />
  <experiment length="0"
              ticks_per_second="10"
              random_seed="123" />
</framework>
<!-- *************** -->
<!-- * Controllers * -->
<!-- *************** -->
<controllers>
  <!-- Buzz 控制器(Spiri 四旋翼) -->
  <buzz_controller_spiri id="bcs">
    <actuators>
     <!--
        quadrotor_position: 位置控制执行 。
        implementation="default" 常用即可。
      -->
      <quadrotor_position implementation="default" />
         <!--
        range_and_bearing: 近距通信与测距执行器(RAB 发射端)。
      -->
      <range_and_bearing  implementation="default" />
    </actuators>
    <sensors>
    <!--
        RAB 传感器(接收端):
        - implementation="medium" 代表该传感器连接到 id="rab" 的“通信媒介”。
        - medium="rab" 必须与 <media> 中 id 匹配,否则无法通信。
        - show_rays="false" 可视化时不画出射线。
      -->
      <range_and_bearing implementation="medium" medium="rab" show_rays="false" />
        <!--
        positioning: 位姿估计传感器;用于在Buzz中获取自身位姿。
      -->
      <positioning       implementation="default" />
    </sensors>
     <!--
      params:
      - bytecode_file: Buzz 字节码文件,由 red_blue.bzz 编译而来。
      - debug_file: 可选,记录 Buzz VM 调试信息,便于课后分析。
    -->
    <params bytecode_file="red_blue.bo"
            debug_file="red_blue.bdb" />
  </buzz_controller_spiri>
</controllers>
<!-- *********************** -->
<!-- * Arena configuration * -->
<!-- *********************** -->
 <!--
  arena: 尺寸与中心
  - size="10, 10, 4" 表示 x=10m, y=10m, z=4m 的盒形空间。
  - center="0,0,2" 将空间中心抬到 z=2,使地面位于 z=0。
  教学建议:无人机默认在 z≈0 起始时要确保不与地面/障碍重叠;也可直接用定位控制上升到目标高度。
-->
<arena size="10, 10, 4" center="0,0,2">
  <box id="wall_n" size="10, .1, 2" movable="false">
    <body position="0, 4.95, 0" orientation="0,0,0" />
  </box>
  <box id="wall_s" size="10, .1, 2" movable="false">
    <body position="0, -4.95, 0" orientation="0,0,0" />
  </box>
  <box id="wall_e" size=".1, 10, 2" movable="false">
    <body position="4.95, 0, 0" orientation="0,0,0" />
  </box>
  <box id="wall_w" size=".1, 10, 2" movable="false">
    <body position="-4.95, 0, 0" orientation="0,0,0" />
  </box>
  <!-- 随机投放 5 台机器人;数量要与 bzz 的 ROBOTS 一致
    distribute: 在给定范围内“随机”投放实体。
    position: 在 min/max 矩形内均匀采样 (z=0 表示从地面高度开始)。
    orientation: 这里均匀分布在 yaw=0(固定朝向);如需随机朝向,把 max 改成 "0,0,360deg"。
    entity quantity="5": 一次性生成 5 台 spiri;会自动生成 id: sp0..sp4。
  -->
  <distribute>
    <position    method="uniform"  min="-1.5,-1.5,0" max="1.5,1.5,0" />
    <orientation method="uniform" min="0,0,0" max="0,0,0" />
    <entity quantity="5" max_trials="100">
     <!--
        spiri: 四旋翼机体
        id="sp": 基名前缀,实际生成 sp0..sp4
        rab_range="10": RAB 通信/感知半径(米);要覆盖全场可调大至 > 14 (对角线更长)。
        rab_data_size="500": 单次发送的最大字节数;500 很大,演示富消息可用,但会增压性能。
        <controller config="bcs" />: 绑定上面定义的 Buzz 控制器。
      -->
      <spiri id="sp" rab_range="10" rab_data_size="500">
        <controller config="bcs" />
      </spiri>
    </entity>
  </distribute>
</arena>
<!-- ******************* -->
<!-- * Physics engines * -->
<!-- ******************* -->
<physics_engines>
  <pointmass3d id="pm3d" />
</physics_engines>
<!-- ********* -->
<!-- * Media * -->
<!-- ********* -->
<media>
  <range_and_bearing id="rab" />
</media>
<!-- ****************** -->
<!-- * Visualization * -->
<!-- ****************** -->
<visualization>
  <qt-opengl>
    <camera>
    <placement idx="0"
               position="0,-12,7"
               look_at="0,0,1"
               lens_focal_length="15" />
    <placement idx="1"
               position="0,0,14"
               look_at="0,0,0"
               lens_focal_length="18" />
    </camera>
    <user_functions label="buzz_qt" />
  </qt-opengl>
</visualization>
</argos-configuration>
SPEED = 0.5      # 期望水平速度(m/s 近似;取决于底层控制器/物理引擎的解释)
LIM   = 4.4      # “内缩边界”:场地墙在 ±4.95m,提前在 ±4.4m 处反弹,避免贴墙抖动
TARGET_RED  = 1  # 红队枚举值
TARGET_BLUE = 2  # 蓝队枚举值

# 起飞阶段:起飞完成后分队并设定巡航方向
# 约定:takeoff() 在爬升过程返回 true,到达目标高度后返回 false
# 因此 not takeoff() 代表“起飞完成,可以切换状态”
# 分队规则:id 偶数 -> 红队(+X 方向),奇数 -> 蓝队(-X 方向)
function state_takeoff() {
  if(not takeoff()) {        # 起飞完成的那个 tick 进入分队初始化
    if((id % 2) == 0) {      # id 为内置的机器人唯一编号
      mygroup = TARGET_RED
      vx = SPEED;  vy = 0.0  # 红队面向 +X 巡航
    }
    else {
      mygroup = TARGET_BLUE
      vx = -SPEED; vy = 0.0  # 蓝队面向 -X 巡航
    }
    statef   = state_cruise  # 状态机:函数指针切换到巡航
    statestr = "cruise"      # 记录文字状态,方便 debug 输出
  }
}

# keep_inside:简单“弹性边界”
# 思路:若位置超出内缩阈值且速度仍朝外,就把该轴速度取反(镜像反弹)
# 使用 LIM=4.4 而不是 4.95,可显著降低贴墙卡顿和穿模风险
# 同一 tick 可同时触发 X/Y 两轴反弹(斜向撞边)
function keep_inside() {
  var x = pose.position.x    # pose 为定位传感器提供的自位姿;单位米
  var y = pose.position.y
  if(x >  LIM and vx > 0.0) vx = -vx
  if(x < -LIM and vx < 0.0) vx = -vx
  if(y >  LIM and vy > 0.0) vy = -vy
  if(y < -LIM and vy < 0.0) vy = -vy
}

# 巡航状态:持续按 (vx, vy) 指定的平面速度飞行
# goto(vx, vy) 语义:水平速度指令(通常 m/s);高度由飞控/起飞逻辑维持
function state_cruise() {
  keep_inside()    # 每步先做边界约束,必要时反向
  goto(vx, vy)     # 下发速度指令;若 vx=vy=0 则悬停
}

# 初始化:设置状态机入口、清空分队与速度
function init() {
  statef   = state_takeoff   # 初始进入起飞状态
  statestr = "takeoff"
  mygroup  = 0               # 0 表示未分队
  vx = 0.0; vy = 0.0
}

# 主循环:每个仿真 tick 调一次
# 先运行当前状态函数(statef)
# 再根据分队在调试通道打印状态与位置
function step() {
  statef()  # 调用当前状态
  if(mygroup == TARGET_RED) {
    debug.print(statestr, " RED  pos=(", pose.position.x, ",", pose.position.y, ")")
  }
  else if(mygroup == TARGET_BLUE) {
    debug.print(statestr, " BLUE pos=(", pose.position.x, ",", pose.position.y, ")")
  }
  else {
    debug.print(statestr, " pos=(", pose.position.x, ",", pose.position.y, ")")
  }
}
function destroy() { }

执行一下:

bzzc red_blue.bzz
argos3 -c red_blue.argos 

效果:屏幕截图 2025-09-30 204656.png

发现红的往一边飞,蓝的往一边飞。OK,后续继续拷打大模型,基础功能已经实现了。

Buzz DSL

喜欢这篇文章嘛,觉得文章不错的话,奖励奖励我!

支付宝打赏支付宝微信打赏 微信