From da2165d240e8867fc3fe2e018c520f742f7a5289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Mon, 31 Aug 2026 11:13:47 +0200 Subject: [PATCH 1/2] Restructure the X500 documentation into the per vehicle section layout used by bluerobotics_models MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: Claude Fable 5 Signed-off-by: Carlos Agüero --- docs/reference/index.md | 3 +- docs/vehicles/index.md | 4 +- docs/vehicles/x500.md | 73 ----------------------------- docs/vehicles/x500/actuators.md | 39 +++++++++++++++ docs/vehicles/x500/configuration.md | 28 +++++++++++ docs/vehicles/x500/index.md | 21 +++++++++ docs/vehicles/x500/running.md | 35 ++++++++++++++ docs/vehicles/x500/sensors.md | 36 ++++++++++++++ 8 files changed, 163 insertions(+), 76 deletions(-) delete mode 100644 docs/vehicles/x500.md create mode 100644 docs/vehicles/x500/actuators.md create mode 100644 docs/vehicles/x500/configuration.md create mode 100644 docs/vehicles/x500/index.md create mode 100644 docs/vehicles/x500/running.md create mode 100644 docs/vehicles/x500/sensors.md diff --git a/docs/reference/index.md b/docs/reference/index.md index ff41cb7..c822acd 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -33,7 +33,8 @@ the problem and fail the build or the launch. ## Topics -See [X500: Sensors and Driving](../vehicles/x500.md). `/clock` and +See the X500 [Sensors](../vehicles/x500/sensors.md) and +[Actuators](../vehicles/x500/actuators.md) pages. `/clock` and `/joint_states` are always bridged; every part topic follows `///` on both sides. diff --git a/docs/vehicles/index.md b/docs/vehicles/index.md index 51bccef..9fb1b5c 100644 --- a/docs/vehicles/index.md +++ b/docs/vehicles/index.md @@ -3,9 +3,9 @@ ```{toctree} :hidden: -x500 +x500/index ``` | Vehicle | Packages | Manual | |---|---|---| -| Holybro X500 V2 quadcopter | `x500_description`, `x500_gazebo` | [X500](x500.md) | +| Holybro X500 V2 quadcopter | `x500_description`, `x500_gazebo` | [X500](x500/index.md) | diff --git a/docs/vehicles/x500.md b/docs/vehicles/x500.md deleted file mode 100644 index 25a1754..0000000 --- a/docs/vehicles/x500.md +++ /dev/null @@ -1,73 +0,0 @@ -# X500 - -The [Holybro X500 V2](https://holybro.com/products/x500-v2-kits) development -kit quadcopter, assembled from the `holybro_parts` library. - -## The default loadout - -The default vehicle needs no configuration: the airframe fits its four 1345 -propellers (PX4 quad X spin: rotors 0 and 1 counter clockwise, 2 and 3 -clockwise), the 4S battery and the GPS mast. A companion computer and a -gimbal camera are available but not fitted by default. - -## Running - -```bash -ros2 launch x500_gazebo sim.launch.xml -ros2 launch x500_gazebo sim.launch.xml config_file:=/path/my_loadout.yaml -``` - -The launch generates every artifact of the loadout at start (URDF, composed -model, bridge config, into a per loadout directory under `$ROS_HOME`), spawns -the model as `x500` into the vehicle free ground world and starts the bridge. -`gz sim $(ros2 pkg prefix x500_gazebo)/share/x500_gazebo/worlds/x500_playground.sdf` -runs the default vehicle without ROS. - -## Driving - -There is no control layer in the model. The rotors are driven by -`gz.msgs.Actuators` messages on `/x500/command/motor_speed` (angular -velocity per rotor, indexed by the rotor number), which is the interface -PX4 SITL and ArduPilot SITL expect; the bus is deliberately not bridged to -ROS, since the autopilot owns it. Rotor joint states are bridged to -`/joint_states` so RViz animates the props. - -The marine vehicles (BlueBoat, BlueROV2) expose a normalized -1..1 -`throttle` topic per thruster, the ArduPilot output convention, next to -their low level thrust topics. The X500 intentionally has no such manual -layer: on a multicopter the normalized outputs only make sense downstream -of an attitude controller, so the autopilot (SITL or real) is the -normalized layer, and it talks to the motor bus directly. - -## Sensors - -| Topic | Type | From | -|---|---|---| -| `/x500/imu` | `sensor_msgs/msg/Imu` | airframe (always) | -| `/x500/air_pressure` | `sensor_msgs/msg/FluidPressure` | airframe (always) | -| `/x500/mag` | `sensor_msgs/msg/MagneticField` | airframe (always) | -| `/x500/gps/fix` | `sensor_msgs/msg/NavSatFix` | the GPS mast part (default) | - -The IMU, barometer and magnetometer belong to the airframe (the autopilot -carries them). The GPS is a part: empty its slot and the topic disappears; -rename the instance and the topic follows. - -## Configuration - -The loadout config (`x500_description/config/x500.yaml`) picks what goes in -each slot the parts declare: - -| Slot | Accepts | Default | -|---|---|---| -| `rotor_0` .. `rotor_3` | the matching 1345 propeller | fitted | -| `battery` | `battery_4s` | fitted | -| `gps` | `gps_mast` | fitted | -| `companion` | `companion_computer` | empty | -| `gimbal` | `gimbal_camera` | empty | - -Keep the rotor instances named `rotor_0` .. `rotor_3`: the motor command bus -indexes actuators by that number, and the expansion fails loudly on a rotor -whose name does not end in its actuator number. Entries, free placements, -ad hoc slots and topic overrides follow the schema in -[Reference](../reference/index.md); mistakes fail the build or the launch -with a message naming the problem. diff --git a/docs/vehicles/x500/actuators.md b/docs/vehicles/x500/actuators.md new file mode 100644 index 0000000..964ed7c --- /dev/null +++ b/docs/vehicles/x500/actuators.md @@ -0,0 +1,39 @@ +# Actuators + +Actuators are parts fitted into slots, exactly like the sensors. The +vehicle's slots and their accepted types are in the +[configuration page](configuration.md), and new parts can be added +following the [Add a part](../../how-to/index.md) guide. + +## Available actuators + +| Actuator | Part | Slot | Fitted by default | +|---|---|---|---| +| 1345 propellers, counter clockwise | `prop_1345_ccw` | `rotor_0`, `rotor_1` | yes | +| 1345 propellers, clockwise | `prop_1345_cw` | `rotor_2`, `rotor_3` | yes | + +## Actuators ROS API + +There is none, deliberately. On a multicopter the per rotor outputs only +make sense downstream of an attitude controller, so the autopilot (PX4 +SITL, ArduPilot SITL or a custom controller) is the control layer and it +talks to the Gazebo motor bus directly. The marine vehicles (BlueBoat, +BlueROV2) expose a normalized -1..1 `throttle` topic per thruster, the +ArduPilot output convention; the X500's equivalent normalized layer is +the autopilot itself. Rotor joint states are bridged to `/joint_states` +so RViz animates the props. + +## Gazebo transport API + +| gz Topic | Description | Message type | +|---|---|---| +| `/x500/command/motor_speed` | Angular velocity per rotor (rad/s), indexed by the rotor number | `gz.msgs.Actuators` | + +To spin the rotors by hand, with no autopilot: + +```bash +gz topic -t /x500/command/motor_speed -m gz.msgs.Actuators -p 'velocity: [700, 700, 700, 700]' +``` + +Keep the rotor instances named `rotor_0` .. `rotor_3`: the bus indexes +actuators by that trailing number. diff --git a/docs/vehicles/x500/configuration.md b/docs/vehicles/x500/configuration.md new file mode 100644 index 0000000..3960c61 --- /dev/null +++ b/docs/vehicles/x500/configuration.md @@ -0,0 +1,28 @@ +# Configuration + +The X500 needs no configuration: every slot the parts declare fills +itself with its default. The loadout config +(`x500_description/config/x500.yaml`, or any file passed as +`config_file:=`) states differences only. + +## Payload + +Sensors and actuators are fitted into slots, one config entry each. The +fitted options and their topics live in [Sensors](sensors.md) and +[Actuators](actuators.md); the slots are: + +| Slot | Accepts | Default | +|---|---|---| +| `rotor_0` .. `rotor_3` | the matching 1345 propeller | fitted | +| `battery` | `battery_4s` | fitted | +| `gps` | `gps_mast` | fitted | +| `companion` | `companion_computer` | empty | +| `gimbal` | `gimbal_camera` | empty | + +Keep the rotor instances named `rotor_0` .. `rotor_3`: the motor command +bus indexes actuators by that number, and the expansion fails loudly on a +rotor whose name does not end in its actuator number. Slot entries, free +placements, ad hoc slots and topic overrides follow the schema in +[Reference](../../reference/index.md); the instance key is `of:`, not +`on:`. Mistakes fail the build or the launch with a message naming the +problem. diff --git a/docs/vehicles/x500/index.md b/docs/vehicles/x500/index.md new file mode 100644 index 0000000..d9ffdc0 --- /dev/null +++ b/docs/vehicles/x500/index.md @@ -0,0 +1,21 @@ +# X500 + +The [Holybro X500 V2](https://holybro.com/products/x500-v2-kits) development +kit quadcopter, assembled from the `holybro_parts` library. + +```{toctree} +:maxdepth: 1 + +running +actuators +sensors +configuration +``` + +## The default vehicle + +The default loadout is the airframe with its four 1345 propellers (PX4 +quad X spin: rotors 0 and 1 counter clockwise, 2 and 3 clockwise), the 4S +battery and the GPS mast. Everything else in the catalog (companion +computer, gimbal camera) can be fitted, and the defaults swapped or left +off ([Configuration](configuration.md)). diff --git a/docs/vehicles/x500/running.md b/docs/vehicles/x500/running.md new file mode 100644 index 0000000..11aa991 --- /dev/null +++ b/docs/vehicles/x500/running.md @@ -0,0 +1,35 @@ +# Running the simulation + +```bash +ros2 launch x500_gazebo sim.launch.xml +``` + +Launches the vehicle in its default configuration: every artifact of the +loadout is generated at start (URDF, composed model, bridge config, into +a directory under `$ROS_HOME`), the model is spawned as `x500` into the +ground world and the ROS bridge comes up with it. The vehicle rests on +its landing gear; the rotors idle until an autopilot publishes on the +motor bus ([Actuators](actuators.md)). + +To run a custom vehicle instead, pass a loadout file with `config_file:=`; +the [configuration page](configuration.md) lists the slots and +[Change the loadout](../../how-to/index.md) walks through writing one. + +## Choosing the world + +By default the vehicle is spawned into the vehicle free ground world +(`x500_ground.sdf`). The `world:=` argument swaps the environment without +changing anything else about the simulation: pass any vehicle free world +SDF: + +```bash +ros2 launch x500_gazebo sim.launch.xml world:=/path/my_world.sdf +``` + +## In RViz + +To see the model in RViz: + +```bash +ros2 launch x500_description display.launch.xml +``` diff --git a/docs/vehicles/x500/sensors.md b/docs/vehicles/x500/sensors.md new file mode 100644 index 0000000..0ac16f2 --- /dev/null +++ b/docs/vehicles/x500/sensors.md @@ -0,0 +1,36 @@ +# Sensors + +Sensors are parts fitted into slots, with one exception: the IMU, +barometer and magnetometer belong to the airframe itself, as the +autopilot carries them on the real vehicle. The slots and their accepted +types are in the [configuration page](configuration.md), and new sensor +parts can be added following the [Add a part](../../how-to/index.md) +guide. + +## Available sensors + +| Sensor | Part | Slot | Fitted by default | +|---|---|---|---| +| IMU, barometer, magnetometer | the airframe | | yes | +| GPS | `gps_mast` | `gps` | yes | + +## Sensors ROS API + +### Flight sensors + +| ROS Topic | Description | Message type | +|---|---|---| +| `/x500/imu` | Body IMU | [sensor_msgs/msg/Imu](https://docs.ros.org/en/rolling/p/sensor_msgs/interfaces/msg/Imu.html) | +| `/x500/air_pressure` | Barometer | [sensor_msgs/msg/FluidPressure](https://docs.ros.org/en/rolling/p/sensor_msgs/interfaces/msg/FluidPressure.html) | +| `/x500/mag` | Magnetometer | [sensor_msgs/msg/MagneticField](https://docs.ros.org/en/rolling/p/sensor_msgs/interfaces/msg/MagneticField.html) | + +### GPS + +| ROS Topic | Description | Message type | +|---|---|---| +| `/x500/gps/fix` | Position fix | [sensor_msgs/msg/NavSatFix](https://docs.ros.org/en/rolling/p/sensor_msgs/interfaces/msg/NavSatFix.html) | + +Topic bases follow `///...`: empty the GPS slot and +its topic disappears, rename the instance and it follows, and per part +`topic` / `gz_topic` / `ros_topic` overrides in the config rename the +base. From 80336bf4745f158bb3bd732fb927752b0fd3adf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ag=C3=BCero?= Date: Mon, 31 Aug 2026 15:24:59 +0200 Subject: [PATCH 2/2] Split getting started into requirements, installation and first simulation pages matching bluerobotics_models MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: Claude Fable 5 Signed-off-by: Carlos Agüero --- docs/getting-started/first-simulation.md | 25 ++++++++++++ docs/getting-started/index.md | 51 +++--------------------- docs/getting-started/installation.md | 45 +++++++++++++++++++++ docs/getting-started/requirements.md | 7 ++++ 4 files changed, 83 insertions(+), 45 deletions(-) create mode 100644 docs/getting-started/first-simulation.md create mode 100644 docs/getting-started/installation.md create mode 100644 docs/getting-started/requirements.md diff --git a/docs/getting-started/first-simulation.md b/docs/getting-started/first-simulation.md new file mode 100644 index 0000000..531bf32 --- /dev/null +++ b/docs/getting-started/first-simulation.md @@ -0,0 +1,25 @@ +# First simulation + +Bring up the X500 with the full ROS stack (Gazebo server, ros_gz bridge, +robot_state_publisher and the Gazebo GUI): + +```bash +ros2 launch x500_gazebo sim.launch.xml +``` + +Gazebo opens with the X500 resting on its landing gear: the airframe, its +four 1345 propellers, the 4S battery and the GPS mast. That is the default +configuration; no configuration was involved. The model carries no control +layer, so the rotors idle until an autopilot publishes on the motor bus +([Actuators](../vehicles/x500/actuators.md)). + +In a second terminal (also sourced), the flight sensors publish right away: + +```bash +ros2 topic echo /x500/imu --once +ros2 topic echo /x500/gps/fix --once +``` + +Next: [change what is fitted](../vehicles/x500/configuration.md). The +[Running page](../vehicles/x500/running.md) covers worlds, custom configs +and RViz. diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index ac2f4d9..db63bc6 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -1,50 +1,11 @@ # Getting started -## Requirements +Install the models and run your first simulation. -- ROS 2 Lyrical on Ubuntu 26.04 -- Gazebo Jetty, installed as ROS 2 Lyrical's `ros_gz` dependency (the - packages talk to Gazebo only through `ros_gz`) +```{toctree} +:maxdepth: 1 -## Installation - -Into a colcon workspace: - -```bash -mkdir -p ~/ws/src -cd ~/ws/src -git clone https://github.com/HonuRobotics/holybro_models.git -cd ~/ws -rosdep update -rosdep install --from-paths src --ignore-packages-from-source --default-yes -colcon build --merge-install -source install/setup.bash -``` - -The project standard is `colcon build --merge-install`; the default isolated -layout also works. Binary debs are planned once the packages are released -into the ROS ecosystem; a released vehicle can then be reconfigured without -rebuilding (see [Change the loadout](../how-to/index.md)). - -## First simulation - -```bash -ros2 launch x500_gazebo sim.launch.xml -``` - -Gazebo opens with the X500 resting on its landing gear. The model carries -no control layer: the rotors idle until something publishes -`gz.msgs.Actuators` on `/x500/command/motor_speed` (that is the autopilot's -job; PX4 SITL, ArduPilot SITL or a custom controller). The flight sensors -publish right away: - -```bash -ros2 topic echo /x500/imu --once -ros2 topic echo /x500/gps/fix --once -``` - -To see the model in RViz instead: - -```bash -ros2 launch x500_description display.launch.xml +requirements +installation +first-simulation ``` diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md new file mode 100644 index 0000000..e22218c --- /dev/null +++ b/docs/getting-started/installation.md @@ -0,0 +1,45 @@ +# Installation + +## From source + +Into a colcon workspace: + +```bash +mkdir -p ~/ws/src +cd ~/ws/src +git clone https://github.com/HonuRobotics/holybro_models.git +cd ~/ws +rosdep update +rosdep install --from-paths src --ignore-packages-from-source --default-yes +colcon build --merge-install +source install/setup.bash +``` + +```{tip} +`rosdep update` refreshes the dependency database; skipping it in fresh +containers is the usual cause of "Cannot locate rosdep definition" errors. +``` + +The project standard is `colcon build --merge-install` (one deb style prefix, +the layout users get from binary installs). The default isolated layout also +works if you prefer it. + +The build generates the default vehicle artifacts from the vehicle's config +(the URDF, the composed Gazebo model, the ros_gz bridge config). + +## From ROS packages (debs) + +Binary packages (`ros--x500-gazebo`, `ros--x500-description`, +`ros--holybro-parts`) are planned for the ROS build farm and are not +published yet. When they are, installation is: + +```bash +sudo apt install ros-lyrical-x500-gazebo +source /opt/ros/lyrical/setup.bash +ros2 launch x500_gazebo sim.launch.xml +``` + +Nothing under `/opt/ros` is meant to be edited. The default vehicle is baked +into the packages; a custom config is a YAML file anywhere on disk passed +to the launch (`config_file:=`), which regenerates every artifact at launch +time ([Configuration](../vehicles/x500/configuration.md)). diff --git a/docs/getting-started/requirements.md b/docs/getting-started/requirements.md new file mode 100644 index 0000000..36b3b5c --- /dev/null +++ b/docs/getting-started/requirements.md @@ -0,0 +1,7 @@ +# Requirements + +| | Supported | +|---|---| +| OS | Ubuntu 26.04 | +| ROS 2 | [Lyrical](https://docs.ros.org/en/lyrical/) | +| Gazebo | [Jetty](https://gazebosim.org/docs/jetty), installed as ROS 2 Lyrical's `ros_gz` dependency (the default pairing); no separate Gazebo install needed |