router: improve error handling -- more error types, remove some unwraps

This commit is contained in:
Mikolaj Wielgus 2024-05-29 23:49:24 +02:00
parent af9cbeba61
commit a4503a42c6
4 changed files with 61 additions and 43 deletions

View File

@ -22,7 +22,7 @@ use crate::{
rules::RulesTrait,
},
layout::{Layout, NodeIndex},
router::{navmesh::Navmesh, Router, RouterObserverTrait, RoutingError},
router::{navmesh::Navmesh, Router, RouterError, RouterObserverTrait},
triangulation::GetVertexIndex,
};
@ -73,12 +73,12 @@ impl Autoroute {
(None, None)
};
let router = Router::new_from_navmesh(
let mut router = Router::new_from_navmesh(
&mut autorouter.layout,
std::mem::replace(&mut self.navmesh, new_navmesh).unwrap(),
);
let Ok(band) = router.unwrap().route_band(100.0, observer) else {
let Ok(band) = router.route_band(100.0, observer) else {
return false;
};

View File

@ -11,6 +11,7 @@ use std::hash::Hash;
use petgraph::algo::Measure;
use petgraph::visit::{EdgeRef, GraphBase, IntoEdges};
use thiserror::Error;
use std::cmp::Ordering;
@ -105,7 +106,7 @@ where
fn estimate_cost(&mut self, node: G::NodeId) -> K;
}
struct Astar<G, K>
pub struct Astar<G, K>
where
G: IntoEdges,
G::NodeId: Eq + Hash,
@ -118,15 +119,21 @@ where
pub path_tracker: PathTracker<G>,
}
enum AstarStatus<G, K, R>
#[derive(Error, Debug, Clone)]
pub enum AstarError {
#[error("A* search found no path")]
NotFound,
}
pub enum AstarStatus<G, K, R>
where
G: IntoEdges,
G::NodeId: Eq + Hash,
K: Measure + Copy,
{
Running,
Success(K, Vec<G::NodeId>, R),
Failure,
Finished(K, Vec<G::NodeId>, R),
Error(AstarError),
}
impl<G, K> Astar<G, K>
@ -153,13 +160,13 @@ where
pub fn step<R>(&mut self, strategy: &mut impl AstarStrategy<G, K, R>) -> AstarStatus<G, K, R> {
let Some(MinScored(estimate_score, node)) = self.visit_next.pop() else {
return AstarStatus::Failure;
return AstarStatus::Error(AstarError::NotFound);
};
if let Some(result) = strategy.is_goal(node, &self.path_tracker) {
let path = self.path_tracker.reconstruct_path_to(node);
let cost = self.scores[&node];
return AstarStatus::Success(cost, path, result);
return AstarStatus::Finished(cost, path, result);
}
// This lookup can be unwrapped without fear of panic since the node was
@ -213,7 +220,7 @@ pub fn astar<G, K, R>(
graph: G,
start: G::NodeId,
strategy: &mut impl AstarStrategy<G, K, R>,
) -> Option<(K, Vec<G::NodeId>, R)>
) -> Result<(K, Vec<G::NodeId>, R), AstarError>
where
G: IntoEdges,
G::NodeId: Eq + Hash,
@ -221,9 +228,17 @@ where
{
let mut astar = Astar::new(graph, start, strategy);
while let AstarStatus::Running = astar.step(strategy) {
//
}
loop {
let status = astar.step(strategy);
None
/*if !matches!(status, AstarStatus::Running) {
return status;
}*/
match status {
AstarStatus::Running => (),
AstarStatus::Finished(cost, path, band) => return Ok((cost, path, band)),
AstarStatus::Error(err) => return Err(err),
}
}
}

View File

@ -6,6 +6,7 @@ use itertools::Itertools;
use petgraph::visit::{self, NodeIndexable};
use petgraph::{stable_graph::NodeIndex, visit::EdgeRef};
use spade::{HasPosition, InsertionError, Point2};
use thiserror::Error;
use crate::drawing::graph::{GetLayer, GetMaybeNet};
use crate::geometry::shape::ShapeTrait;
@ -85,12 +86,18 @@ pub struct Navmesh {
to: FixedDotIndex,
}
#[derive(Error, Debug, Clone)]
pub enum NavmeshError {
#[error("failed to insert vertex in navmesh")]
Insertion(#[from] InsertionError),
}
impl Navmesh {
pub fn new(
layout: &Layout<impl RulesTrait>,
from: FixedDotIndex,
to: FixedDotIndex,
) -> Result<Self, InsertionError> {
) -> Result<Self, NavmeshError> {
let mut this = Self {
triangulation: Triangulation::new(layout.drawing().geometry().graph().node_bound()),
vertex_to_triangulation_vertex: Vec::new(),

View File

@ -6,31 +6,28 @@ use petgraph::visit::EdgeRef;
use spade::InsertionError;
use thiserror::Error;
use crate::drawing::band::BandIndex;
use crate::drawing::graph::{GetLayer, GetMaybeNet};
use crate::drawing::guide::HeadTrait;
use crate::geometry::primitive::PrimitiveShapeTrait;
use crate::layout::Layout;
use crate::{
drawing::{
band::BandIndex,
dot::FixedDotIndex,
graph::{MakePrimitive, PrimitiveIndex},
guide::HeadTrait,
primitive::MakePrimitiveShape,
rules::RulesTrait,
},
geometry::shape::ShapeTrait,
layout::Layout,
router::{
astar::{astar, AstarError, AstarStrategy, PathTracker},
draw::DrawException,
navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, VertexIndex},
tracer::{Trace, Tracer},
},
};
use crate::router::{
astar::{astar, AstarStrategy, PathTracker},
draw::DrawException,
navmesh::{Navmesh, NavmeshEdgeReference, VertexIndex},
tracer::{Trace, Tracer},
};
#[derive(Error, Debug, Clone, Copy)]
/*#[derive(Error, Debug, Clone, Copy)]
#[error("failed to route from {from:?} to {to:?}")] // this should eventually use Display
pub struct RoutingError {
pub struct RouterError {
from: FixedDotIndex,
to: FixedDotIndex,
source: RoutingErrorKind,
@ -44,6 +41,13 @@ pub enum RoutingErrorKind {
// TODO more descriptive message
#[error("A* found no path")]
AStar,
}*/
#[derive(Error, Debug, Clone)]
#[error("routing failed")]
pub enum RouterError {
Navmesh(#[from] NavmeshError),
Astar(#[from] AstarError),
}
pub trait RouterObserverTrait<R: RulesTrait> {
@ -169,26 +173,23 @@ impl<'a, R: RulesTrait> Router<'a, R> {
layout: &'a mut Arc<Mutex<Layout<R>>>,
from: FixedDotIndex,
to: FixedDotIndex,
) -> Result<Self, InsertionError> {
) -> Result<Self, RouterError> {
let navmesh = {
let layout = layout.lock().unwrap();
Navmesh::new(&layout, from, to)?
};
Self::new_from_navmesh(layout, navmesh)
Ok(Self::new_from_navmesh(layout, navmesh))
}
pub fn new_from_navmesh(
layout: &'a mut Arc<Mutex<Layout<R>>>,
navmesh: Navmesh,
) -> Result<Self, InsertionError> {
Ok(Self { layout, navmesh })
pub fn new_from_navmesh(layout: &'a mut Arc<Mutex<Layout<R>>>, navmesh: Navmesh) -> Self {
Self { layout, navmesh }
}
pub fn route_band(
&mut self,
width: f64,
observer: &mut impl RouterObserverTrait<R>,
) -> Result<BandIndex, RoutingError> {
) -> Result<BandIndex, RouterError> {
let mut tracer = self.tracer();
let trace = tracer.start(self.navmesh.from(), width);
@ -196,12 +197,7 @@ impl<'a, R: RulesTrait> Router<'a, R> {
&self.navmesh,
self.navmesh.from().into(),
&mut RouterAstarStrategy::new(tracer, trace, self.navmesh.to(), observer),
)
.ok_or(RoutingError {
from: self.navmesh.from(),
to: self.navmesh.to(),
source: RoutingErrorKind::AStar,
})?;
)?;
Ok(band)
}