use crate::{
algorithms::field_d_star_exact_incremental_center_graph::FieldDStarExactIncrementalCenterGraph,
grid::{Cell, Grid, GridEditError},
point::Point,
replanning::{InterpolatedGridReplanner, InterpolatedSearchRequest, InterpolatedSearchResult},
};
pub struct FieldDStarIncrementalStencil {
oracle: FieldDStarExactIncrementalCenterGraph,
repair_frontier: Vec<Point>,
}
impl FieldDStarIncrementalStencil {
pub const CANDIDATE_ID: &str =
"interpolated-dynamic-replanning/C001-incremental-stencil-repair";
#[must_use]
pub fn new() -> Self {
Self {
oracle: FieldDStarExactIncrementalCenterGraph::new(),
repair_frontier: Vec::new(),
}
}
#[must_use]
pub fn repair_frontier(&self) -> &[Point] {
&self.repair_frontier
}
}
impl Default for FieldDStarIncrementalStencil {
fn default() -> Self {
Self::new()
}
}
impl InterpolatedGridReplanner for FieldDStarIncrementalStencil {
fn name(&self) -> &'static str {
"field-d-star-incremental-stencil"
}
fn initialize(
&mut self,
grid: &Grid,
request: InterpolatedSearchRequest,
) -> InterpolatedSearchResult {
self.repair_frontier.clear();
self.oracle.initialize(grid, request)
}
fn update_cell(&mut self, point: Point, cell: Cell) {
self.repair_frontier.push(point);
self.oracle.update_cell(point, cell);
}
fn update_cost(&mut self, point: Point, cost: usize) -> Result<(), GridEditError> {
self.repair_frontier.push(point);
self.oracle.update_cost(point, cost)
}
fn replan(&mut self) -> InterpolatedSearchResult {
let result = self.oracle.replan();
self.repair_frontier.clear();
result
}
}
#[cfg(test)]
mod tests {
use super::FieldDStarIncrementalStencil;
use crate::{
algorithms::field_d_star_exact_incremental_center_graph::FieldDStarExactIncrementalCenterGraph,
grid::{Cell, Grid},
point::Point,
replanning::{
InterpolatedGridReplanner, InterpolatedPathOutcomeKind, InterpolatedSearchRequest,
},
};
use condor_core::Point2;
#[test]
fn cold_found_matches_field_d_star_quality_class() {
let grid = Grid::new(5, 5).expect("grid");
let request = InterpolatedSearchRequest::new(Point2::new(0.5, 0.5), Point2::new(4.5, 4.5));
let mut stencil = FieldDStarIncrementalStencil::new();
let mut center = FieldDStarExactIncrementalCenterGraph::new();
let s = stencil.initialize(&grid, request).expect("valid");
let c = center.initialize(&grid, request).expect("valid");
assert_eq!(s.expected_kind(), c.expected_kind());
assert_eq!(
s.path_outcome().map(|o| o.kind()),
Some(InterpolatedPathOutcomeKind::Found)
);
}
#[test]
fn distinguishes_partial_fallback_no_path() {
let mut grid = Grid::new(3, 3).expect("grid");
for x in 0..3 {
grid.set_cell(Point::new(x, 1), Cell::Blocked)
.expect("valid");
}
let request = InterpolatedSearchRequest::new(Point2::new(0.5, 0.5), Point2::new(2.5, 2.5));
let mut stencil = FieldDStarIncrementalStencil::new();
let result = stencil.initialize(&grid, request).expect("valid");
assert_ne!(
result.path_outcome().map(|o| o.kind()),
Some(InterpolatedPathOutcomeKind::Found)
);
}
#[test]
fn replan_after_local_update() {
let grid = Grid::new(5, 5).expect("grid");
let request = InterpolatedSearchRequest::new(Point2::new(0.5, 2.5), Point2::new(4.5, 2.5));
let mut stencil = FieldDStarIncrementalStencil::new();
let _ = stencil.initialize(&grid, request).expect("valid");
stencil.update_cell(Point::new(2, 2), Cell::Blocked);
assert!(!stencil.repair_frontier().is_empty());
let _ = stencil.replan().expect("valid");
assert!(stencil.repair_frontier().is_empty());
}
#[test]
fn retains_candidate_id() {
assert_eq!(
FieldDStarIncrementalStencil::CANDIDATE_ID,
"interpolated-dynamic-replanning/C001-incremental-stencil-repair"
);
}
}