AirStack 0.19.0 #399
andrewjong
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Added
Intent flags on
airstack up—--sim isaac|airsim,--robots N,--headless,--play/--no-play,--no-autolaunch,--wait,--dry-run— deriving the coordinated env-var sets (compose profiles, URDF, single/multi Isaac launch script) as exported leaf values, with a resolved-config banner and a per-run.airstack/runs/<ts>/effective_config.envdump; contract-tested intests/meta/test_launch_intent_contract.py(unit mark)airstack ready(andairstack up --wait): staged flight-readiness gates mirroring the system-test budgets — containers → sim/clock→ per-robot sentinel nodes → PX4 MAVROS-connected +local_position/odomstreaming (the armable signal) — with per-gate diagnostics and--jsonfor scriptsPreflight validation in
airstack upon resolved configuration (env >--env-file>.env): one-simulator guard no longer bypassed by--env-file;NUM_ROBOTS>1with the single-drone Isaac script is a named hard error; missing images are listed with animage-pullhint before compose starts an implicit build; missingomni_pass.env/ empty Pegasus submodule / Docker < 29 surfaced on the host (AIRSTACK_SKIP_PREFLIGHT=1downgrades errors to warnings)tmux pane output is mirrored to container stdout via shared
.tmux.confhooks, sodocker logs/airstack logsnow show colcon builds,ros2 launchoutput, sim loading, and crashesAutomatic
unit-tests.ymlPR gate onubuntu-latest, plusrun_meta.jsonoutcome metadata so reports distinguish completed simulation campaigns from collection errors, empty selections, timeouts, and cancellationsoverrides/isaac-optitrack-simulation.env— brings up Isaac Sim with the NatNet emulator and PX4 flying on mocap EKF2 external vision (GPS/baro/range aiding off), i.e. the configurationtests/system/test_optitrack_e2e.pyruns, reproducible by handoverrides/l4t-optitrack-realrobot.env— deployment override for a real Jetson robot flying on OptiTrack mocap (PX4 EKF2 external vision instead of GPS): the NatNet server/body settings, plus the multi-NIC and FCU-parameter notes that path needsFeature notebook workflow (
use-feature-notebookskill): every agent-implemented feature gets a local, gitignorednotebook/NNN-feature-slug/entry with a status-trackeddesign_spec.md(written before coding) andresults/artifacts + self-containedresults_summary.mdthat populate the feature's PR descriptionBattery and telemetry display in GCS RQT control panel (voltage and percentage per robot when MAVROS battery topic is bridged)
TARGET_ARCHbuild arg (defaultx86_64) inDockerfile.robotto arch-parametrizeLD_LIBRARY_PATH;docker-compose.yamlpassesTARGET_ARCH: aarch64to thevoxlandl4treal-robot image buildsros-${ROS_DISTRO}-mavros-extrasin the robot image (provides the vision_pose plugin used for external-pose deployments)overrides/l4t-px4-realrobot.env— site-agnostic deployment override for a single real PX4 robot on a Jetson (aarch64/l4t)integrationtest tier (tests/integration/,integrationmark) with a sharedrobot_autonomy_stackfixture (robot container, no sim/GPU)waypoint_flightsystem test (tests/system/test_waypoint_flight.py): takeoff → ordered waypoint route viaNavigateTask(dispatched as a dense plan) → land, judged on the odometry track by the standalone stdlib-onlytests/waypoint_checker.py(in-order corridor arrival within--waypoint-tolerance, final goal within--goal-tolerance, per-waypoint--waypoint-timeout); validated end-to-end in Isaac Sim; serves as the standard acceptance check after integrating or swapping a planner moduleReal-robot PX4 external-vision fusion in
natnet_ros2(OptiTrack mocap → EKF2):mavros_gp_origin(geoid-corrected synthetic GPS origin solocal_position.z== OptiTrack z, fixing the ~36 m boot offset),vision_pose_converter, and a PX4 param checker (px4_param_setter,auto_setoff by default;on_mismatchwarn/halt) — setup guide atdocs/robot/px4_external_vision.mdNatNet server emulator (
optitrack.natnet.emulator, protocol core) — pure-Python OptiTrack Motive server emulation sonatnet_ros2can be driven without hardware; host integration tests (tests/integration/natnet/) wire it to the robot clientIsaac wrapper for the NatNet emulator (USD scene → server) + natnet Pegasus launch scripts, and a dedicated OptiTrack sim e2e test (
optitrackmark,tests/system/test_optitrack_e2e.py) that flies a Circle trajectory on mocap EKF2 fusion — GPS, baro and range aiding are disabled for the run, so the OptiTrack stream is the vehicle's only position source and cross-track error scores the whole chainChanged
Isaac launch scripts deduplicated onto a shared
pegasus_app.PegasusAppbase (simulation/isaac-sim/launch_scripts/pegasus_app.py): the six scripts become scenario declarations (~40–170 lines each, net −438 lines) with hooks for NatNet/scene-import extras; behavior verified by full system-test parity (liveliness, sensors, takeoff/hover/land on Isaac).ISAAC_SIM_HEADLESSandISAAC_SIM_LIVESTREAMnow work uniformly in every launch script (previously each was honored by only half of them)Launch-workflow docs corrected against actual behavior:
ISAAC_SIM_SCENE(nonexistent) replaced byISAAC_SIM_SCRIPT_NAME/ISAAC_SIM_GUI, getting-started reflects the paused-by-default sim and Foxglove UI, isaac docker.md defaults table matches.env, ms-airsim MAVROS ports/FOV/vehicle naming fixed, AGENTS.md uses the realdown/image-buildcommand namesUnit-test documentation now matches the co-located layout: the
add-unit-testsandrun-system-testsskills and the testing docs record which runner each language uses (C++ gtests viacolcon testunder thebuild_packagesmark; Python via the root harness, pluscolcon testforament_pythonpackages), and stop instructing authors to write@pytest.mark.unitby hand —conftest.pyapplies it by file locationEphemeral CI GPU runners spawn via NVIDIA OSMO (not OpenStack);
system-tests.yml/docker-build.ymlstill useairstack-ephemeralDefault system-test
--simisisaacsim; pass--sim msairsimto opt in to Microsoft AirSim-m build_packagesCI runs pullcache_*images instead of baking sim imagesdocker-build.ymlretags unchanged images on VERSION bumps (content fingerprint) instead of always rebuilding; floatingcache_*tags still seed PR layer cacheAutomatic OSMO validation runs the pull-only
build_packagesgate whenever a PR is opened, updated, or reopened; GPU-intensive simulation campaigns (including OptiTrack) are selected through/pytestorworkflow_dispatchrobot-l4tcompose service knobs are now env-overridable (AUTONOMY_ROLE,FCU_URL, and the rosbag path viaBAG_STORAGE_PATH);FCU_URLunquoted so the literal serial path reaches MAVROSzed-l4timage: ZED SDK 4.2 → 5.2 with the coupled ROS deps (zed_msgs5.2.1,point_cloud_transport(_plugins)4.x, addbackward_ros)Unit tests are defined by
tests/colcon_unit_test_packages.yaml:conftest.pycollects each listed package's co-locatedtest/dir under--import-mode=importliband marks itunit(ament lint files are skipped and run undercolcon test)Removed
tests/robot/(which instructed authors to add tests in directories tests no longer live in) andtests/sim/motive_emulator/README.md(superseded bysimulation/isaac-sim/extensions/optitrack.natnet.emulator/andtests/integration/natnet/)Fixed
barebones_pegasus_launch.py(the documented template script) crashed withNameError: oson constructionisaac-sim-livestreamcompose service silently produced a black stream whenISAAC_SIM_SCRIPT_NAMEwas a multi-drone script (livestream setup existed only in the single-drone scripts)NATNET_BODY_NAME/NATNET_TARGET_NAMEenv overrides documented by the single-drone NatNet script now actually workairstack upguards (one-simulator, URDF pairing) validated.envonly and were bypassed by--env-file overrides/...; they now check the resolved configurationpytest tests/now collects the co-located unit tests before mark filtering. The old guard skipped injection whenever any path was on the command line, andtests/is a path — CI collected 97 of 252 items and the Python unit tests ran nowhere. Narrowing (pytest tests/system/test_x.py) still skips injection; repository-root and empty-path collection are rejectedpytest tests/ ""and recurse through the repository; collection/import, setup/teardown, partial, and interrupted artifacts are reported as non-comparable instead of false 0% simulation-policy results, and metric regression runs only for an identical simulation campaign fingerprintubuntu.shno longer fails dpkg configure on the NVIDIA base (ca-certificates/software-properties-common); use--no-nuttx --no-sim-toolslike ms-airsimpytest<8.1and disablelaunch_testingfor colcon unit tests so ROS Jazzy's outdated pytest hook does not abortcolcon testROBOT_NAME(e.g. injected via docker compose) instead of always overriding it from the container/hostname mapping (robot/docker/.bashrc)unknown_robot(valid ROS namespace token) instead ofunknown-robot(default_robot_name_map.yaml)/ros_entrypoint.shwith a passthrough so its prebuilt source-ROS libs (olderfastcdr) no longer shadow the apt Jazzy runtime and crash apt-built nodes like MAVROSRECORD_BAGS=truenever brought the bag recorder up on a robot:logging.launch.xmlhardcodedrecord_bag=falseandonboard_autonomy_all.launch.xmlincludes it with no arguments, so the variable was forwarded into the container and read by nobody (onlygcs.launch.xmlconsumed it). With nobag_recordnode running, the GCS control panel'sset_recording_statustoggle had nothing to reach despite being bridged indomain_bridge.yaml/dds_router.yaml. It now readsRECORD_BAGSand selects its topic set viaLOG_CONFIGunknown_robot/ domain 0 now logs a warning naming both fixes (rename the devicerobot-<n>on the host, or supply aROBOT_NAME_MAP_CONFIG_FILEmatching your hostnames). The fallback itself is unchanged — it deliberately keeps an unidentified robot out of every real robot's namespace — but it used to resolve silently, so the symptoms surfaced far from the causeROBOT_NAME/ROS_DOMAIN_IDfromoverrides/l4t-px4-realrobot.env: no compose service declares either, so an env file could never set them and the lines were inertbag_record/bag_recording_statuswas bridged GCS -> robot indomain_bridge.yaml, the same direction as the command it answers, so recorder status never reached the GCS and every recording indicator stayed blankbag_record_nodepassed--excludetoros2 bag record, which Jazzy renamed to--exclude-regex. It is now an ambiguous prefix of four options, so argparse rejected the command and any section usingexclude:(includinglog.yaml'sairstacksection, i.e. everything but the cameras) recorded nothing — surfacing only as a usage dump in the node's stdout. Multipleexclude:entries are now alternated into one regex instead of repeating a single-valued flag, which had silently kept only the lastnatnet_config.yaml's$(env NATNET_SERVER_IP ...)could never resolve: no compose service declared the variable, so the NatNet client always fell back to its hardcoded default and could reach neither the in-sim emulator nor a real Motive host. It is now forwarded inrobot-base-docker-compose.yaml, defaulting to the in-sim emulatorrobot_1defaulted to a site-specific body (id 1146) that no emulator streams; since the client filters frames by numeric id, that produced a connected client that never published. It now defaults to the emulator's body (Drone, id 1). Per-robot bodies are configured in each robot's profile innatnet_config.yaml, selected byROBOT_NAMEEKF2_EV_DELAY8.0 → 7.0 andEKF2_EVP_NOISE0.01 → 0.05. The old 0.01 gave a 5 cm innovation gate (EKF2_EVP_GATE× 5σ) that rejected valid mocap updates and blocked arming;px4_params.yamlnow records the supporting measurements and the drift-and-snap misdiagnosis so neither is repeateddesired_floor_amsl: 36.0, i.e. 90 m ellipsoidal in AMSL) rather than at sea level, so a mocap robot's reported global altitude agrees with sim and the GCS.local_position.zstill equals the OptiTrack height either wayegm96-5geoid: mavros'install_geographiclib_datasets.shswallows a failed download and still exits 0, so theRUNlayer succeeded either way, andgeographiclib-toolswas only ever a transitive dependency. MAVROS builds that geoid in its UAS core before any plugin loads and throws if it is missing, somavros_nodedied at startup on affected images.Dockerfile.robotnow pins the tool and asserts the file exists, failing the build insteadconnection_typeinnatnet_config.yamlsilently fell back tounicast, so a typo produced a client that connected on the wrong transport and never received frames.validate_connection_typenow throws andnatnet_ros2_nodefails at startup naming the offending valuenatnet_ros2_nodeonrobot_1now compares the NatNet server's MODELDEF drone-body count (Drone/Drone1…DroneN, excludingTargetand skeleton bones) againstNUM_ROBOTSafter the handshake and logs an error on mismatch, so a sim launch script andnatnet_config.yamlthat disagree about how many drones exist is caught at startup rather than as a robot that silently never receives frames.NUM_ROBOTSis forwarded into the robot container for itEKF2_EV_CTRLdefaults to 0 and the isaac compose set no PX4 parameters, so the emulator could stream perfectly while PX4 flew on sim GPS. The compose now passes the EKF2 external-vision set asPX4_PARAM_*(applied by PX4 SITL'srcSat boot), each defaulting to PX4's own default so non-mocap sims are unaffected; the mocap path opts inNATNET_BODY_ID, so a real Motive id desynced the two into a connected client that never published (example_one_px4_pegasus_natnet_launch_script.py)test_optitrack_e2e.py::test_px4_fuses_visionasserted only thatlocal_position/posepublishes, which it does off GPS — the check passed with external vision disabled. It is now the pre-flight gate (an estimate exists) and the Circle flight is the actual proof of fusionDockerfile.isaac-rospip-installs it editable into the Isaac python and bind-mounts the repo copy over it (the same pattern aspegasus.simulator), and the natnet launch scriptsenable_extensionit before importing. Being on a Kit--ext-foldersearch path only makes Kit aware of an extension — it does not put the package onsys.path— so the scripts previously died withModuleNotFoundError: No module named 'optitrack'This discussion was created from the release AirStack 0.19.0.
All reactions