Repository navigation
Restructure example docs #138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
a6e7528
Split examples into topic pages and add splat rendering docs
ratheron 2f283a0
Update example docs and fix examples
ratheron c3f8f24
Remove splat media from the example docs
ratheron 285d25c
Apply batched suggestions from code review
ratheron 923dd2c
Remove np.asarray where not needed. Closes #131
ratheron 6c994ee
Fix linting
ratheron File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # Contact examples | ||
|
|
||
| Querying contacts between drones and the scene, and choosing the collision geometry of the drone. See [MuJoCo Integration](../user-guide/mujoco.md) for how the scene is built. | ||
|
|
||
| --- | ||
|
|
||
| ## Contact queries | ||
|
|
||
| <div class="example-media-grid example-media-grid--contacts"> | ||
| <figure> | ||
| <img src="../../img/examples/contact_sphere.png" alt="Contact query visualization using the default sphere collision geometry"> | ||
| </figure> | ||
| <figure> | ||
| <img src="../../img/examples/contact_box.png" alt="Contact query visualization using the oriented box collision geometry"> | ||
| </figure> | ||
| </div> | ||
|
|
||
| --8<-- example "examples/contacts/contacts.py" | ||
|
|
||
| --- | ||
|
|
||
| ## Crash detection | ||
|
|
||
| --8<-- example "examples/contacts/crash.py" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| # Control examples | ||
|
|
||
| Flying drones with the different control modes, from state commands down to force and torque, comparing the dynamics models, and model-based control. See [Control Modes](../user-guide/control/index.md) for the controller behind each mode. | ||
|
|
||
| --- | ||
|
|
||
| ## Hover | ||
|
|
||
| --8<-- example "examples/control/hover.py" | ||
|
|
||
| --- | ||
|
|
||
| ## Changing the state | ||
|
|
||
| --8<-- example "examples/control/change_pos.py" | ||
|
|
||
| --- | ||
|
|
||
| ## Spirals | ||
|
|
||
| --8<-- example "examples/control/spiral.py" | ||
|
|
||
| --- | ||
|
|
||
| ## Attitude control | ||
|
|
||
| --8<-- example "examples/control/attitude.py" | ||
|
|
||
| --- | ||
|
|
||
| ## Body rate control | ||
|
|
||
| --8<-- example "examples/control/body_rate.py" | ||
|
|
||
| --- | ||
|
|
||
| ## Force and torque control | ||
|
|
||
| --8<-- example "examples/control/force_torque.py" | ||
|
|
||
| --- | ||
|
|
||
| ## Comparing integrators | ||
|
|
||
| --8<-- example "examples/control/integrators.py" | ||
|
|
||
| --- | ||
|
|
||
| ## Comparing dynamics models | ||
|
|
||
| --8<-- example "examples/control/dynamics.py" | ||
|
|
||
| --- | ||
|
|
||
| ## Symbolic dynamics | ||
|
|
||
| --8<-- example "examples/control/symbolic.py" | ||
|
|
||
| --- | ||
|
|
||
| ## Sampling-based MPC | ||
|
|
||
| --8<-- example "examples/control/sampling.py" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # Environment examples | ||
|
|
||
| Running the Gymnasium environments that wrap `Sim` for reinforcement learning. See [Gymnasium Environments](../user-guide/gymnasium-envs.md) for the available environments. | ||
|
|
||
| --- | ||
|
|
||
| ## Figure-eight environment | ||
|
|
||
| --8<-- example "examples/environments/figure8.py" | ||
|
|
||
| --- | ||
|
|
||
| ## Reach-position environment | ||
|
|
||
| --8<-- example "examples/environments/gymnasium_env.py" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,259 +1,10 @@ | ||
| # Examples | ||
|
|
||
| These runnable examples cover control, JAX transformations, pipeline extensions, rendering, contacts, and Gymnasium environments. Start with hover if you're new, or jump to the section that matches your use case. | ||
|
|
||
| --- | ||
|
|
||
| ## Hover | ||
|
|
||
| A single drone commanded to hold a fixed height using state control. This is the minimal end-to-end loop: create a `Sim`, reset it, apply a state command, and step forward. | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/control/hover.py" | ||
| ``` | ||
|
|
||
| ```bash | ||
| python examples/control/hover.py | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Attitude control | ||
|
|
||
| Commanding roll, pitch, yaw, and collective thrust directly. This level bypasses the Mellinger position loop and is typical for RL agents that output attitude targets. | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/control/attitude.py" | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Body rate control | ||
|
|
||
| Commanding body-frame angular rates and collective thrust. The firmware controller has no dedicated body rate mode and levels the drone with its attitude terms, so the example sets the `kR` and `ki_m` gains of the body rate controller to zero. | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/control/body_rate.py" | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Sampling-based MPC | ||
|
|
||
| A sampling-based model predictive controller tracks a Lissajous curve while avoiding a grid of obstacles. It rolls out thousands of candidate control sequences in parallel using identified dynamics, then applies the first action from a cost-weighted update of the best samples. The controller automatically uses a GPU when one is available and lowers the sample count on CPU. | ||
|
|
||
| ```bash | ||
| python examples/control/sampling.py | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Gradient descent through dynamics | ||
|
|
||
| Because the simulator is built entirely from JAX operations, `jax.grad` can differentiate through it. Starting the drone above the target height keeps it away from the floor, so the floor-clipping stage never fires and gradients flow freely through the entire trajectory. | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/jax/gradient.py" | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Gradients and command clipping | ||
|
|
||
| Hard clips such as the `clip_rotor_vel_cmd` stage zero the gradients while the command is saturated. This example ramps a motor command beyond the rotor limits and compares the rotor state and the gradient of the vertical acceleration w.r.t. the command for three options: the default clip, a straight-through clip (clipped forward pass, unclipped gradients), and no clip. Replacing the default clip with the straight-through variant can help gradient-based methods such as trajectory optimization or policy learning, which would otherwise receive zero gradients whenever the motors saturate. | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/jax/gradient_clipping.py" | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Sharding across devices | ||
|
|
||
| We can also distribute the simulation across devices. The host backend is asked for four logical devices. We then compare this against running on a single device. See [Sharding](../user-guide/sharding.md) for the details. | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/jax/sharding.py" | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Domain randomization | ||
|
|
||
| Randomizing mass, inertia and drag per drone, and thrust and torque curves, rotor dynamics, arm lengths and propeller inertias per motor through the reset pipeline, each by a uniform factor around its default value. An optional mask limits randomization to selected worlds. | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/plugins/randomize.py" | ||
| ``` | ||
|
|
||
| ```bash | ||
| python examples/plugins/randomize.py | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Disturbance injection | ||
|
|
||
| Inserting a random external force and torque into the step pipeline. The disturbance fires on every dynamics tick, so the drone fights wind-like perturbations. | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/plugins/disturbance.py" | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Downwash | ||
|
|
||
| Modeling downwash between identical Crazyflies with a far-field jet model. The plugin samples the flow at each target rotor and center of mass, computes rotor thrust loss and drag, and writes the resulting world-frame external force and torque. | ||
|
|
||
| The demo holds one `cf21B_500` drone in hover while a second makes three passes underneath at different speeds and heights. | ||
|
|
||
| <div class="example-media-grid example-media-grid--contacts"> | ||
| <figure class="example-media"> | ||
| <img src="../img/examples/downwash_example.gif" alt="Drone flying through downwash cone"> | ||
| </figure> | ||
| <figure> | ||
| <img src="../img/examples/downwash_field.png" alt="Downwash field generated by hovering drone"> | ||
| </figure> | ||
| </div> | ||
|
|
||
| ```bash | ||
| python examples/plugins/downwash.py | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Ground effect | ||
|
|
||
| Modeling the increase in thrust near the floor for a `cf21B_500` drone. The plugin computes nominal thrust from the rotor speeds, applies a height-dependent gain, and adds the extra thrust along the drone's body z-axis as a world-frame external force. | ||
|
|
||
| <!-- notest: imported script --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/plugins/ground_effect.py" | ||
| ``` | ||
|
|
||
| ```bash | ||
| python examples/plugins/ground_effect.py | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## State derivatives | ||
|
|
||
| Adding the state derivatives, which are not stored by default, to the step pipeline with plugins. One plugin calls the dynamics at the end of each step, which gives the exact derivative at the current state. The other uses finite differences of the states, which give the exact average derivative from the last to the current step. Both store a `SimStateDeriv` in the plugins dict. The plot compares them while the drone flies a figure-eight. | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/plugins/derivatives.py" | ||
| ``` | ||
|
|
||
| ```bash | ||
| python examples/plugins/derivatives.py | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## IMU | ||
|
|
||
| Simulating an IMU as a plugin. The accelerometer measures the specific force and the gyroscope the body rates, both with noise and drifting biases, while the drone flies loops of a figure-eight. The plot compares the readings with the true state, skipping the first loop. | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/plugins/imu.py" | ||
| ``` | ||
|
|
||
| ```bash | ||
| python examples/plugins/imu.py | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Cameras and RGBD | ||
|
|
||
| Offscreen rendering returns RGB-D images on every frame. The FPV camera (`fpv_cam`) is attached to the drone and moves with it. | ||
|
|
||
| <figure class="example-media"> | ||
| <img src="../img/examples/cameras.gif" alt="RGB-D camera outputs from a Crazyflow drone simulation"> | ||
| </figure> | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/rendering/cameras.py" | ||
| ``` | ||
|
|
||
| ```bash | ||
| python examples/rendering/cameras.py | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## LED deck and materials | ||
|
|
||
| `change_material` updates the RGBA colour and emission of any named material on any subset of drones at runtime. | ||
|
|
||
| <figure class="example-media example-media--compact"> | ||
| <img src="../img/examples/led_decks.png" alt="Crazyflow drones with runtime-controlled LED deck materials"> | ||
| </figure> | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/rendering/led_deck.py" | ||
| ``` | ||
|
|
||
| ```bash | ||
| python examples/rendering/led_deck.py | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Contact queries | ||
|
|
||
| The default collision geometry is a sphere around the drone frame. `use_box_collision` replaces it with a tighter oriented box, useful for narrow-gap flight and accurate contact debugging. | ||
|
|
||
| <div class="example-media-grid example-media-grid--contacts"> | ||
| <figure> | ||
| <img src="../img/examples/contact_sphere.png" alt="Contact query visualization using the default sphere collision geometry"> | ||
| </figure> | ||
| <figure> | ||
| <img src="../img/examples/contact_box.png" alt="Contact query visualization using the oriented box collision geometry"> | ||
| </figure> | ||
| </div> | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/contacts/contacts.py" | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Raycasting and depth sensing | ||
|
|
||
| `render_depth` fires rays from a camera and returns per-pixel distances. This is faster than full RGB rendering and useful for obstacle sensing or depth-based controllers. | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/rendering/raycasting.py" | ||
| ``` | ||
|
|
||
| ```bash | ||
| python examples/rendering/raycasting.py | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Gymnasium environment | ||
|
|
||
| Evaluating a random policy in the figure-8 environment. The env wraps `Sim` behind the standard Gymnasium `VectorEnv` interface. | ||
|
|
||
| <!-- notest: imported script, covered by tests/integration/test_examples.py --> | ||
| ```{ .python notest } | ||
| --8<-- "examples/environments/figure8.py" | ||
| ``` | ||
| The runnable examples are grouped by topic, following the folders in `examples/`. Start with [hover](control.md#hover) if you're new, or jump to the group that matches your use case. Run an example from the repository root with `python examples/<group>/<script>.py`. | ||
|
|
||
| - [Control](control.md) — how to command the drones at different levels, such as positions, attitudes, or body rates, and how to build your own controllers on top | ||
| - [JAX](jax.md) — how to use JAX transformations on the simulation, such as gradients through the dynamics or sharding across devices | ||
| - [Plugins](plugins.md) — how to easily add features to the simulation, such as domain randomization, disturbances, or aerodynamic effects | ||
| - [Rendering](rendering.md) — how to render the simulation with MuJoCo or gaussian splats and extract sensor data, such as camera images or depth maps | ||
| - [Contacts](contacts.md) — how to detect collisions between drones and their environment | ||
| - [Environments](environments.md) — how to train and evaluate reinforcement learning policies with Gymnasium environments | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.