ARGoS¶
ARGoS3 owns the robots, physics and simulated
radios. phyelds-argos runs one aggregate round on each robot per simulation tick,
whatever the robot: foot-bot, e-puck, eye-bot, Spiri, Pi-Puck, BuilderBot, drone, block
or prototype. Each controller owns a Device:
neighbors exchange its serialized messages over the robot's simulated radio, with
delivery on the next tick. There is no global message table or centrally computed
neighborhood.
Install and build¶
Use Python 3.12 or 3.13, a C++17 compiler, CMake 3.18+ and an installed ARGoS3. The Python development headers and shared library must match the interpreter you use. UV-managed CPython distributions include both. During development, from the phyelds root:
pip install -e . -e packages/phyelds-argos
python -m phyelds.argos.build --build-dir build/argos
The package ships sources, so the command compiles against your installed ARGoS and
the Python running it. It creates libphyelds_argos.so and libphyelds_argos_qt.so.
Use --no-gui to omit the Qt/OpenGL renderer. With a released package, install
phyelds-argos from PyPI first; the same build command applies. Rebuild if you move
or replace the Python environment. ARGoS runs the embedded interpreter selected at
build time, regardless of the python3 on its launch-time PATH.
A line of five robots¶
The complete experiment is in docs/examples/argos/line.argos. From the phyelds root:
PYTHONPATH=docs/examples/argos argos3 -c docs/examples/argos/line.argos
# Without a window:
PYTHONPATH=docs/examples/argos argos3 -z -n -c docs/examples/argos/line.argos
The robots stand 0.5 m apart, with a radio range of 0.65 m. They compute distances
0.00m, 0.50m, 1.00m, 1.50m, 2.00m from fb0:
"""A metric gradient on ARGoS robots, without GPS."""
from phyelds.argos import label, led, source
from phyelds.calculus import aggregate
from phyelds.libraries.distances import neighbors_distances
from phyelds.libraries.spreading import distance_to
@aggregate
def main() -> float:
"""Show distance to the source, following the radio network."""
distance = float(distance_to(source.sense(), neighbors_distances()))
label.send(f"{distance:.2f}m")
led.send((255, 255, 255) if source.sense() else (0, 200, 255))
return distance
Use a phyelds_controller in the experiment, with
library="build/argos/libphyelds_argos" and
<params program="gradient:main" source="0" max_speed="0.1" />.
program is an importable module:function, not a file to execute. Robot names end
in a unique unsigned 32-bit integer (fb12 becomes device 12).
Any robot¶
The same phyelds_controller drives every robot: it uses the devices its experiment
declares, so the configuration of each robot names the devices it has.
| Robot | Radio | Motion | Obstacles | LEDs |
|---|---|---|---|---|
| foot-bot | range_and_bearing |
differential_steering |
footbot_proximity |
leds |
| e-puck | range_and_bearing |
differential_steering |
epuck_proximity |
leds |
| eye-bot | range_and_bearing |
quadrotor_speed |
eyebot_proximity |
leds |
| Spiri | range_and_bearing |
quadrotor_speed |
||
| Pi-Puck | simple_radios |
pipuck_differential_drive |
pipuck_rangefinders |
pipuck_leds (on or off) |
| BuilderBot | simple_radios |
builderbot_differential_drive |
builderbot_rangefinders |
builderbot_leds |
| drone | simple_radios |
drone_flight_system, actuator and sensor |
drone_leds |
|
| block | simple_radios |
directional_leds |
||
| prototype | simple_radios |
leds or directional_leds |
Every robot needs a radio, both its actuator and its sensor, and the positioning
sensor. The other devices are optional: a robot without them ignores the outputs it
cannot act on, so one program fits a mixed swarm, and robots of different types talk
when they share a medium. Robots from other ARGoS plugins work through the same
generic devices.
The range-and-bearing radio measures where each neighbor is, so programs need no
positions. Simple radios do not: with them, set gps="true" in the controller's
params, so that programs read their position and the geometry helpers compute
distances from shared positions.
Sensors and outputs¶
phyelds.argos names the sensors and actuators of the host once, as typed
Sensor and Actuator objects: a program reads
source.sense() and sends led.send(colour), and never repeats their names.
| Sensor | Meaning |
|---|---|
source |
Whether this device ID matches the configured source; false if omitted |
heading |
Heading unit vector from the compass |
obstacle |
Proximity repulsion vector, with a proximity sensor or rangefinders; None without |
The host also gives the time, the geometry of the neighbors and, on request, the position; the libraries of phyelds read them:
| Host sensor | Meaning | Read by |
|---|---|---|
time |
Simulation time in seconds | local_time() |
neighbors_distances |
Map from sender ID to RAB range in metres, with range_and_bearing |
neighbors_distances() |
neighbors_vectors |
Map from sender ID to its relative vector in metres, with range_and_bearing |
neighbors_vectors() |
position |
Position in metres, with gps="true" |
local_position() |
Vectors are coordinate tuples in the shared compass frame; the vectors to flying
neighbors have a z. Unless gps="true", the positioning sensor supplies
orientation only: absolute positions are never given to programs.
neighbors_distances() and the experimental neighbors_vectors() automatically use
the measured maps. They respect alignment and remove absent neighbors. Without the
maps, their existing position-based behavior is unchanged; an explicit position
argument always takes precedence.
| Actuator | Meaning |
|---|---|
velocity |
Desired global velocity, two or three components, in m/s; capped by max_speed (default 0.1). Wheeled robots turn towards it, quadrotors and drones fly it |
led |
RGB iterable with three channels in 0–255 |
label |
Text above the robot and in the final headless log |
Missing outputs mean a stopped robot, black LEDs and an empty label. The line
experiment includes the complete configuration of a foot-bot. The optional GUI user
function is phyelds_qtuser_functions, loaded from libphyelds_argos_qt; it draws a
halo and label under any robot without changing the simulation.
Some ARGoS models need care:
- Eye-bot:
pointmass3dmoves quadrotors by its physics step once per tick, so with its default ten iterations the eye-bot flies at a tenth of its speed; give ititerations="1". - Spiri: its speed controller oscillates in
pointmass3d, and diverges with one iteration: it flies the right way, but not steadily. - Pi-Puck: under
dynamics3dit barely turns in place;dynamics2dsteers it. - Drone: it flies to a target one second ahead, so it stops about a second after its velocity does, and it holds its place within a centimetre or so.
- BuilderBot: its
obstacleleaves out the two front rangefinders, which face its own end effector.
Messages and lifecycle¶
- Frames are
[u32 sender][u16 payload length][Device bytes], using ARGoSCByteArrayfor the header. On the range-and-bearing radio they are padded with zeros torab_data_size: userab_data_size="4096"as a starting point; the codec's JSON exports are larger than FCPP's binary exports. The host reports an error on overflow rather than truncating the message. It does not fragment frames. Simple radios send each frame once on every interface, such as each face of a block. - Compact paths are the default. For debugging set
paths="debug"on every communicating controller; program versions and path modes must match. - Each robot has independent aggregate state. A reset clears state, queued messages, wheels, LEDs and labels. Missing neighbors are forgotten after one round.
- CPython is initialized once for the process. Worker threads acquire the GIL for each round, so ARGoS may use multiple threads but Python rounds run serially.
- Python failures include the traceback, program name and robot ID.
trace="true"logs the label at every round; it is off by default.
The native host does not need FCPP, Boost.Python, pybind11 or phyelds-simulator.
Simulation-specific code stays in this optional package; the core calculus and codec
are reused unchanged. See the companion phyelds-argos-example project for metric
gradients, election/counting, dispersion, gathering and flocking with matching FCPP
arenas.