mirror of https://codeberg.org/topola/topola.git
router: improve error handling -- more error types, remove some unwraps
This commit is contained in:
parent
af9cbeba61
commit
a4503a42c6
|
|
@ -22,7 +22,7 @@ use crate::{
|
||||||
rules::RulesTrait,
|
rules::RulesTrait,
|
||||||
},
|
},
|
||||||
layout::{Layout, NodeIndex},
|
layout::{Layout, NodeIndex},
|
||||||
router::{navmesh::Navmesh, Router, RouterObserverTrait, RoutingError},
|
router::{navmesh::Navmesh, Router, RouterError, RouterObserverTrait},
|
||||||
triangulation::GetVertexIndex,
|
triangulation::GetVertexIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -73,12 +73,12 @@ impl Autoroute {
|
||||||
(None, None)
|
(None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
let router = Router::new_from_navmesh(
|
let mut router = Router::new_from_navmesh(
|
||||||
&mut autorouter.layout,
|
&mut autorouter.layout,
|
||||||
std::mem::replace(&mut self.navmesh, new_navmesh).unwrap(),
|
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;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ use std::hash::Hash;
|
||||||
|
|
||||||
use petgraph::algo::Measure;
|
use petgraph::algo::Measure;
|
||||||
use petgraph::visit::{EdgeRef, GraphBase, IntoEdges};
|
use petgraph::visit::{EdgeRef, GraphBase, IntoEdges};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
|
@ -105,7 +106,7 @@ where
|
||||||
fn estimate_cost(&mut self, node: G::NodeId) -> K;
|
fn estimate_cost(&mut self, node: G::NodeId) -> K;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Astar<G, K>
|
pub struct Astar<G, K>
|
||||||
where
|
where
|
||||||
G: IntoEdges,
|
G: IntoEdges,
|
||||||
G::NodeId: Eq + Hash,
|
G::NodeId: Eq + Hash,
|
||||||
|
|
@ -118,15 +119,21 @@ where
|
||||||
pub path_tracker: PathTracker<G>,
|
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
|
where
|
||||||
G: IntoEdges,
|
G: IntoEdges,
|
||||||
G::NodeId: Eq + Hash,
|
G::NodeId: Eq + Hash,
|
||||||
K: Measure + Copy,
|
K: Measure + Copy,
|
||||||
{
|
{
|
||||||
Running,
|
Running,
|
||||||
Success(K, Vec<G::NodeId>, R),
|
Finished(K, Vec<G::NodeId>, R),
|
||||||
Failure,
|
Error(AstarError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G, K> Astar<G, K>
|
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> {
|
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 {
|
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) {
|
if let Some(result) = strategy.is_goal(node, &self.path_tracker) {
|
||||||
let path = self.path_tracker.reconstruct_path_to(node);
|
let path = self.path_tracker.reconstruct_path_to(node);
|
||||||
let cost = self.scores[&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
|
// 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,
|
graph: G,
|
||||||
start: G::NodeId,
|
start: G::NodeId,
|
||||||
strategy: &mut impl AstarStrategy<G, K, R>,
|
strategy: &mut impl AstarStrategy<G, K, R>,
|
||||||
) -> Option<(K, Vec<G::NodeId>, R)>
|
) -> Result<(K, Vec<G::NodeId>, R), AstarError>
|
||||||
where
|
where
|
||||||
G: IntoEdges,
|
G: IntoEdges,
|
||||||
G::NodeId: Eq + Hash,
|
G::NodeId: Eq + Hash,
|
||||||
|
|
@ -221,9 +228,17 @@ where
|
||||||
{
|
{
|
||||||
let mut astar = Astar::new(graph, start, strategy);
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use itertools::Itertools;
|
||||||
use petgraph::visit::{self, NodeIndexable};
|
use petgraph::visit::{self, NodeIndexable};
|
||||||
use petgraph::{stable_graph::NodeIndex, visit::EdgeRef};
|
use petgraph::{stable_graph::NodeIndex, visit::EdgeRef};
|
||||||
use spade::{HasPosition, InsertionError, Point2};
|
use spade::{HasPosition, InsertionError, Point2};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::drawing::graph::{GetLayer, GetMaybeNet};
|
use crate::drawing::graph::{GetLayer, GetMaybeNet};
|
||||||
use crate::geometry::shape::ShapeTrait;
|
use crate::geometry::shape::ShapeTrait;
|
||||||
|
|
@ -85,12 +86,18 @@ pub struct Navmesh {
|
||||||
to: FixedDotIndex,
|
to: FixedDotIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug, Clone)]
|
||||||
|
pub enum NavmeshError {
|
||||||
|
#[error("failed to insert vertex in navmesh")]
|
||||||
|
Insertion(#[from] InsertionError),
|
||||||
|
}
|
||||||
|
|
||||||
impl Navmesh {
|
impl Navmesh {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
layout: &Layout<impl RulesTrait>,
|
layout: &Layout<impl RulesTrait>,
|
||||||
from: FixedDotIndex,
|
from: FixedDotIndex,
|
||||||
to: FixedDotIndex,
|
to: FixedDotIndex,
|
||||||
) -> Result<Self, InsertionError> {
|
) -> Result<Self, NavmeshError> {
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
triangulation: Triangulation::new(layout.drawing().geometry().graph().node_bound()),
|
triangulation: Triangulation::new(layout.drawing().geometry().graph().node_bound()),
|
||||||
vertex_to_triangulation_vertex: Vec::new(),
|
vertex_to_triangulation_vertex: Vec::new(),
|
||||||
|
|
|
||||||
|
|
@ -6,31 +6,28 @@ use petgraph::visit::EdgeRef;
|
||||||
use spade::InsertionError;
|
use spade::InsertionError;
|
||||||
use thiserror::Error;
|
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::{
|
use crate::{
|
||||||
drawing::{
|
drawing::{
|
||||||
|
band::BandIndex,
|
||||||
dot::FixedDotIndex,
|
dot::FixedDotIndex,
|
||||||
graph::{MakePrimitive, PrimitiveIndex},
|
graph::{MakePrimitive, PrimitiveIndex},
|
||||||
|
guide::HeadTrait,
|
||||||
primitive::MakePrimitiveShape,
|
primitive::MakePrimitiveShape,
|
||||||
rules::RulesTrait,
|
rules::RulesTrait,
|
||||||
},
|
},
|
||||||
geometry::shape::ShapeTrait,
|
geometry::shape::ShapeTrait,
|
||||||
|
layout::Layout,
|
||||||
|
router::{
|
||||||
|
astar::{astar, AstarError, AstarStrategy, PathTracker},
|
||||||
|
draw::DrawException,
|
||||||
|
navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, VertexIndex},
|
||||||
|
tracer::{Trace, Tracer},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::router::{
|
/*#[derive(Error, Debug, Clone, Copy)]
|
||||||
astar::{astar, AstarStrategy, PathTracker},
|
|
||||||
draw::DrawException,
|
|
||||||
navmesh::{Navmesh, NavmeshEdgeReference, VertexIndex},
|
|
||||||
tracer::{Trace, Tracer},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Error, Debug, Clone, Copy)]
|
|
||||||
#[error("failed to route from {from:?} to {to:?}")] // this should eventually use Display
|
#[error("failed to route from {from:?} to {to:?}")] // this should eventually use Display
|
||||||
pub struct RoutingError {
|
pub struct RouterError {
|
||||||
from: FixedDotIndex,
|
from: FixedDotIndex,
|
||||||
to: FixedDotIndex,
|
to: FixedDotIndex,
|
||||||
source: RoutingErrorKind,
|
source: RoutingErrorKind,
|
||||||
|
|
@ -44,6 +41,13 @@ pub enum RoutingErrorKind {
|
||||||
// TODO more descriptive message
|
// TODO more descriptive message
|
||||||
#[error("A* found no path")]
|
#[error("A* found no path")]
|
||||||
AStar,
|
AStar,
|
||||||
|
}*/
|
||||||
|
|
||||||
|
#[derive(Error, Debug, Clone)]
|
||||||
|
#[error("routing failed")]
|
||||||
|
pub enum RouterError {
|
||||||
|
Navmesh(#[from] NavmeshError),
|
||||||
|
Astar(#[from] AstarError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RouterObserverTrait<R: RulesTrait> {
|
pub trait RouterObserverTrait<R: RulesTrait> {
|
||||||
|
|
@ -169,26 +173,23 @@ impl<'a, R: RulesTrait> Router<'a, R> {
|
||||||
layout: &'a mut Arc<Mutex<Layout<R>>>,
|
layout: &'a mut Arc<Mutex<Layout<R>>>,
|
||||||
from: FixedDotIndex,
|
from: FixedDotIndex,
|
||||||
to: FixedDotIndex,
|
to: FixedDotIndex,
|
||||||
) -> Result<Self, InsertionError> {
|
) -> Result<Self, RouterError> {
|
||||||
let navmesh = {
|
let navmesh = {
|
||||||
let layout = layout.lock().unwrap();
|
let layout = layout.lock().unwrap();
|
||||||
Navmesh::new(&layout, from, to)?
|
Navmesh::new(&layout, from, to)?
|
||||||
};
|
};
|
||||||
Self::new_from_navmesh(layout, navmesh)
|
Ok(Self::new_from_navmesh(layout, navmesh))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_from_navmesh(
|
pub fn new_from_navmesh(layout: &'a mut Arc<Mutex<Layout<R>>>, navmesh: Navmesh) -> Self {
|
||||||
layout: &'a mut Arc<Mutex<Layout<R>>>,
|
Self { layout, navmesh }
|
||||||
navmesh: Navmesh,
|
|
||||||
) -> Result<Self, InsertionError> {
|
|
||||||
Ok(Self { layout, navmesh })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn route_band(
|
pub fn route_band(
|
||||||
&mut self,
|
&mut self,
|
||||||
width: f64,
|
width: f64,
|
||||||
observer: &mut impl RouterObserverTrait<R>,
|
observer: &mut impl RouterObserverTrait<R>,
|
||||||
) -> Result<BandIndex, RoutingError> {
|
) -> Result<BandIndex, RouterError> {
|
||||||
let mut tracer = self.tracer();
|
let mut tracer = self.tracer();
|
||||||
let trace = tracer.start(self.navmesh.from(), width);
|
let trace = tracer.start(self.navmesh.from(), width);
|
||||||
|
|
||||||
|
|
@ -196,12 +197,7 @@ impl<'a, R: RulesTrait> Router<'a, R> {
|
||||||
&self.navmesh,
|
&self.navmesh,
|
||||||
self.navmesh.from().into(),
|
self.navmesh.from().into(),
|
||||||
&mut RouterAstarStrategy::new(tracer, trace, self.navmesh.to(), observer),
|
&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)
|
Ok(band)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue