15 releases (6 stable)
1.3.1 | Apr 26, 2024 |
---|---|
1.3.0 | Dec 8, 2022 |
1.2.0 | Jun 16, 2021 |
1.1.1 | Apr 23, 2020 |
0.7.0 | Mar 14, 2018 |
#86 in Machine learning
244 downloads per month
Used in 2 crates
150KB
276 lines
movingai-rust
Map/Scenario Parser for the MovingAI benchmark format. It offers a quick way to parse scenario and map files, with the addition of some utilities to manage and query information from the maps.
Map Features
The crate parses map and scene files and provides several function for easy interaction and query.
Some of the functionalities are:
- Easy idiomatic access to the map data such as width, height and tiles at a specific coordinate.
- Check if a tile is traversable or not according the MovingAI format rules.
- Get the list of accessible neighbors from a specific tile.
- [TO DO] Convert bitmaps into
.map
files. - Serialize/Deserialzie
.map
and.scen
files into JSON/YAML using serde (activate--features serde
)
How to use
extern crate movingai;
use std::path::Path;
use movingai::parser::parse_map_file;
fn main() {
let map = parse_map_file(Path::new("./test/arena.map")).unwrap();
let width = map.width();
let tile = map[(4,5)]; // Access map location at row 4 and column 5.
}
As an example, you can see how we can use this crate to easily implement the A* pathfinding algorithm.
// A* shortest path algorithm.
fn shortest_path(map: &MovingAiMap, start: Coords2D, goal: Coords2D) -> Option<f64> {
let mut heap = BinaryHeap::new();
let mut visited = Vec::<Coords2D>::new();
// We're at `start`, with a zero cost
heap.push(SearchNode { f: 0.0, g:0.0, h: distance(start, goal), current: start });
while let Some(SearchNode { f: _f, g, h: _h, current }) = heap.pop() {
if current == goal { return Some(g); }
if visited.contains(¤t) {
continue;
}
visited.push(current);
for neigh in map.neighbors(current) {
let new_h = distance(neigh, goal);
let i = distance(neigh, current);
let next = SearchNode { f: g+i+new_h, g: g+i, h: new_h, current: neigh };
heap.push(next);
}
}
// Goal not reachable
None
}
And in this example we can see how to write a benchmark over a scen file.
fn main() {
let map = parse_map_file(Path::new("./tests/arena.map")).unwrap();
let scenes = parse_scen_file(Path::new("./tests/arena.map.scen")).unwrap();
for scene in scenes {
let start = scene.start_pos;
let goal = scene.goal_pos;
let t = Instant::now();
match shortest_path(&map, (1,3), (4,3)) {
Some(x) => {
let duration = t.elapsed();
let seconds = duration.as_secs();
let ms = (duration.subsec_nanos() as f64) / 1_000_000.0;
println!("{:?} -> {:?} \tin {:?} seconds and {:?} ms", start, goal, seconds, ms);
}
None => println!("None"),
}
}
}
Why cargo test
is failing?
Note that tests need to be compiled with the serde
feature enabled.
cargo test --feature=serde