An abstraction layer for kartoffels by Patryk27 that is intended to simplify the development of complex bots. It is mainly intended to be used with an async runtime like embassy, but also (mostly) includes blocking variants.
In the cross/src/bin directory there are a few example bots. These are:
| name | description |
|---|---|
| challenge-roomba.rs | solution to the roomba challenge |
| runner-gps.rs | navigates to a hardcoded location, evading and killing bots on its way |
| runner-simple.rs | evades and kills bots |
| runner-slam.rs | evades and kills bots, while creating a map of the terrain |
| tutorial-stab.rs | stabbing tutorial with multiple concurrent tasks |
| tutorial-line.rs | line following tutorial with multiple concurrent tasks |
The runner-gps bot can be spectated at the official webpage by joining one of the following ids:
- d446-2f32-3373-5147
- ea1b-f81f-9089-6f07
- 905f-47de-08a1-75fc
- fc25-50df-6b90-2789
To build the bots, navigate to the cross directory,
cd crossthen
cargo build --release --binsThen convert the binaries to base64 and copy to clipboard, e.g. like this (linux and wayland)
base64 target/riscv32-kartoffel-bot/release/runner-gps | wl-copyFor other systems, check the build script in the default starter pack.
The different crates provide different functionality:
- Contains safe and convenient abstractions
Motor,Arm,Radar, ... For radar scan, anRc-like implementation is used to prevent new scan from overwriting old ones. - Moving the bot, stabbing, scanning etc. mutate global state. This is
represented by encapsulating these functions in singletons. They can be aquired
exactly once using
Bot::take(). This way you can be sure that if you keep a reference tomotor, and checkedmotor.is_ready(), the motor stays ready. asyncAPI that does not block the execution of other code, likemotor.step_fw().await. There are also non-async variants such asmotor.wait_blocking()ormotor.try_step_fw().
- Easily keep track of absolute
Position, relative position (Vec2) in global (north, east, south, west) and local (front, right, back, left) coordinate frames,Rotations andDirections. InstantandDurationtyes forTimers
- Contains mapping, exploration, and navigation utilities and algorithms.
- Algorithms are implemented in async functions, where special care was taken to ensure they don't block for too long, so that fast reaction times are still possible.
StatsDog: Utility for gathering latency and execution time stats- Measure distances: Manhattan (taxi-cab), minimum, maximum, bot clock cycles, ...
- Provided with a map of the terrain, the exact global location can be uniquely identified by analysing terrain features.
- The provided map is stored in memory and can be used.
- Additionally, the provided map is analysed at compile time to allow fast and efficient navigation to any location.
- Can be used to write unit tests.
There may be some bugs, especially in the async-algorithm crate. The async-kartoffel crate is
relatively stable.
Possible improvements:
- tests for binaries
- logging
- inventory
- timer queue, better wakers
- benchmarks and optimization
The bot only has 4096 bytes of stack memory. Large arrays can easily cause a stack overflow. To
prevent this, use the provided allocator to heap allocate these arrays. You can use
cargo-call-stack (with updated llvm-sys to
match llvm version, at time of writing llvm-sys = "201.0.1") to analyse the stack requirements of
each function.
cargo call-stack -i target/riscv32-kartoffel-bot/release/runner-gps --target riscv32-unknown-none -v > cg.dot
dot -Tsvg cg.dot > cg.svgThe unstable custom_test_frameworks is used for test. The build command is e.g. (linux and wayland)
cd cross
cargo build --release --tests --all
base64 target/riscv32-kartoffel-bot/release/deps/async_kartoffel-e58abfc84af62516 | wl-copyThe hash (e58a...) may need to be adapted.
Add the following lines
#![feature(custom_test_frameworks)]
#![reexport_test_harness_main = "test_main"]
#![test_runner(test_kartoffel::runner)]add the top of your library to enable tests. Might not work for binaries though.
As recommended for embedded targets by
ferrocene, the project consists of two nested
workspaces. The outer one (Cargo.toml) is architecture agnostic and can therefore be tested on the
native system, while the inner one (cross/Cargo.toml) work only on the riscv32-kartoffel-bot
target. rust-analyzer by default does only work in the outer workspace. To configure rust-analyzher
to work in both, you can either e.g. add the following to your
In VS Code, you can add the following to .vscode/settings.json
{
"rust-analyzer.linkedProjects": [
// order is important (rust-analyzer/rust-analyzer#7764)
"Cargo.toml",
"cross/Cargo.toml",
]
}For Neovim, you can run the provided lua script after the rust-analyzer LSP has been started:
:source nvim-rust-analyzer-nested.lua