Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AeroSurvey direction-finding ring — PX4 SITL + Gazebo Harmonic + ROS 2

Spawns 9 quadrotors in a helical ring (3 altitude layers × 3 azimuths, every drone at a distinct azimuth so no rotor sits above another), holds them on station in an ABL wind field, and estimates the inflow direction — plus a per-layer veer profile — from their wind readings.

This matches the "config 1" quick direction pass: a fast, coarse estimate of where the wind is coming from, used to orient the full inflow campaign later.

Files

File What it does
ring_geometry.py Single source of truth: ring layout + the ABL wind field. Also a CLI that prints spawn poses.
worlds/aerosurvey_ring.sdf Gazebo Harmonic world (PX4-compatible systems + ground/sun + wind).
swarm_offboard.py ROS 2 node — holds all 9 drones at their ring altitudes via PX4 Offboard.
wind_estimator.py ROS 2 node — software anemometer per drone, circular-mean direction + per-layer veer.
run_sim.sh tmux launcher — agent + gz + 9 PX4 + both nodes.

Prerequisites (once)

You already have Gazebo Harmonic (gz-sim 8). You still need PX4, the DDS agent, ROS 2, and the PX4 ROS 2 messages.

1. PX4-Autopilot (builds the SITL binary + pulls the gz models)

cd ~
git clone https://github.com/PX4/PX4-Autopilot.git --recursive
bash ./PX4-Autopilot/Tools/setup/ubuntu.sh      # installs the toolchain
cd PX4-Autopilot
make px4_sitl                                   # first build is slow
# smoke test a single drone, then close it:
make px4_sitl gz_x500

2. ROS 2 — Humble on Ubuntu 22.04, or Jazzy on Ubuntu 24.04. Set ROS_DISTRO in run_sim.sh to match.

3. Micro XRCE-DDS Agent (the PX4↔ROS 2 bridge)

cd ~ && git clone -b v2.4.2 https://github.com/eProsima/Micro-XRCE-DDS-Agent.git
cd Micro-XRCE-DDS-Agent && mkdir build && cd build
cmake .. && make && sudo make install && sudo ldconfig /usr/local/lib/
# test:  MicroXRCEAgent udp4 -p 8888

4. px4_msgs in a ROS 2 workspace

mkdir -p ~/px4_ros2_ws/src && cd ~/px4_ros2_ws/src
git clone https://github.com/PX4/px4_msgs.git
cd ~/px4_ros2_ws && source /opt/ros/$ROS_DISTRO/setup.bash && colcon build

Use the px4_msgs branch that matches your PX4 version (the main/release branches track recent PX4). A message-definition mismatch shows up as topics that never deliver — rebuild px4_msgs from the matching branch if so.

Run

chmod +x run_sim.sh
PX4_DIR=~/PX4-Autopilot ROS2_WS=~/px4_ros2_ws ROS_DISTRO=humble ./run_sim.sh

The launcher copies the world into PX4's gz folder, starts the agent, brings up the gz server with drone 1, attaches drones 2–9, then starts both ROS 2 nodes. Ctrl-b n / Ctrl-b p switch tmux windows; the estimator window prints, e.g.:

[9/9 drones]  est  209.4deg  (true 210.0, err  -0.6deg)
    layer   20 m -> dir  207.8deg, speed  7.0 m/s  (3 drones)
    layer   35 m -> dir  210.1deg, speed  8.0 m/s  (3 drones)
    layer   50 m -> dir  212.3deg, speed  8.7 m/s  (3 drones)

The per-layer rows are the veer profile — proof the azimuthal stagger keeps it.

Tuning knobs

  • Ring size / layers / azimuths: top of ring_geometry.py.
  • Wind field (speed, shear, direction, veer rate, set VEER_DEG_PER_M=0 to switch veer off): the ABL wind field block in ring_geometry.py.
  • Sensor noise: NOISE_STD in wind_estimator.py.
  • Headless (no GUI, faster): prefix the first PX4 command with HEADLESS=1.

Known gotchas (read before debugging)

  1. Arming/offboard never engages → the VehicleCommand.target_system off-by-one. swarm_offboard.py uses instance + 1; if your PX4 build maps it differently, check ros2 topic echo /px4_1/fmu/out/vehicle_status and the MAV_SYS_ID param, then adjust self.target_system.
  2. Topics don't appear → px4_msgs built from a branch that doesn't match your PX4 version. Rebuild from the matching branch.
  3. Models spawn but won't fly / actuator index errors → the world is missing a system PX4 expects. Diff worlds/aerosurvey_ring.sdf against PX4-Autopilot/Tools/simulation/gz/worlds/default.sdf and add what's missing.
  4. Wind doesn't push the drones → expected. WindEffects only acts on links with <enable_wind>true</enable_wind>; the stock x500 has none, so the wind is scene context and the measurement is taken in software. To get real station-keeping error, copy the x500 model into a PX4 models folder and add <enable_wind>true</enable_wind> to its base link.

Next steps

  • Swap the analytic wind_true() for a Mann/Kaimal turbulence field (IEC 61400-1) or a CFD snapshot to stress-test the estimate under real gusts.
  • ros2 bag record -a while it runs, then plot estimate-vs-time and the error band — that's your validation figure.
  • For the render: the gz GUI already shows the ring; add a gz-sim camera or drive a follow-camera path, or feed the rosbag positions to PyVista/Plotly.
  • Make the wind physical (gotcha 4) and measure how station-keeping drift maps into direction error — that's the realism PX4 buys you over a kinematic sim.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages