1use crate::base::{
6 goal::JsGoal,
7 path::JsPath,
8 planner::JsPlannerConfig,
9 problem_definition::{JsProblemDefinition, ProblemDefinitionVariant},
10 state_validity_checker::JsStateValidityChecker,
11};
12use oxmpl::base::{
13 planner::Planner,
14 space::{
15 CompoundStateSpace, RealVectorStateSpace, SE2StateSpace, SE3StateSpace, SO2StateSpace,
16 SO3StateSpace,
17 },
18 state::{CompoundState, RealVectorState, SE2State, SE3State, SO2State, SO3State},
19};
20use oxmpl::geometric::RRTConnect;
21use std::sync::Arc;
22use std::time::Duration;
23use wasm_bindgen::prelude::*;
24
25enum RRTConnectVariant {
26 RealVector(RRTConnect<RealVectorState, RealVectorStateSpace, JsGoal>),
27 SO2(RRTConnect<SO2State, SO2StateSpace, JsGoal>),
28 SO3(RRTConnect<SO3State, SO3StateSpace, JsGoal>),
29 Compound(RRTConnect<CompoundState, CompoundStateSpace, JsGoal>),
30 SE2(RRTConnect<SE2State, SE2StateSpace, JsGoal>),
31 SE3(RRTConnect<SE3State, SE3StateSpace, JsGoal>),
32}
33
34#[wasm_bindgen(js_name = RRTConnect)]
35pub struct JsRRTConnect {
36 planner: RRTConnectVariant,
37 pd: ProblemDefinitionVariant,
38}
39
40#[wasm_bindgen(js_class = RRTConnect)]
41impl JsRRTConnect {
42 #[wasm_bindgen(constructor)]
43 pub fn new(
44 max_distance: f64,
45 goal_bias: f64,
46 problem_def: &JsProblemDefinition,
47 config: &JsPlannerConfig,
48 ) -> Self {
49 let planner_config = config.into();
50 match &problem_def.inner {
51 ProblemDefinitionVariant::RealVector(pd) => Self {
52 planner: RRTConnectVariant::RealVector(RRTConnect::new(
53 max_distance,
54 goal_bias,
55 &planner_config,
56 )),
57 pd: ProblemDefinitionVariant::RealVector(pd.clone()),
58 },
59 ProblemDefinitionVariant::SO2(pd) => Self {
60 planner: RRTConnectVariant::SO2(RRTConnect::new(
61 max_distance,
62 goal_bias,
63 &planner_config,
64 )),
65 pd: ProblemDefinitionVariant::SO2(pd.clone()),
66 },
67 ProblemDefinitionVariant::SO3(pd) => Self {
68 planner: RRTConnectVariant::SO3(RRTConnect::new(
69 max_distance,
70 goal_bias,
71 &planner_config,
72 )),
73 pd: ProblemDefinitionVariant::SO3(pd.clone()),
74 },
75 ProblemDefinitionVariant::Compound(pd) => Self {
76 planner: RRTConnectVariant::Compound(RRTConnect::new(
77 max_distance,
78 goal_bias,
79 &planner_config,
80 )),
81 pd: ProblemDefinitionVariant::Compound(pd.clone()),
82 },
83 ProblemDefinitionVariant::SE2(pd) => Self {
84 planner: RRTConnectVariant::SE2(RRTConnect::new(
85 max_distance,
86 goal_bias,
87 &planner_config,
88 )),
89 pd: ProblemDefinitionVariant::SE2(pd.clone()),
90 },
91 ProblemDefinitionVariant::SE3(pd) => Self {
92 planner: RRTConnectVariant::SE3(RRTConnect::new(
93 max_distance,
94 goal_bias,
95 &planner_config,
96 )),
97 pd: ProblemDefinitionVariant::SE3(pd.clone()),
98 },
99 }
100 }
101
102 pub fn setup(&mut self, validity_checker: &JsStateValidityChecker) {
103 let checker = Arc::new(validity_checker.clone());
104 match &mut self.planner {
105 RRTConnectVariant::RealVector(p) => {
106 if let ProblemDefinitionVariant::RealVector(pd) = &self.pd {
107 p.setup(pd.clone(), checker);
108 }
109 }
110 RRTConnectVariant::SO2(p) => {
111 if let ProblemDefinitionVariant::SO2(pd) = &self.pd {
112 p.setup(pd.clone(), checker);
113 }
114 }
115 RRTConnectVariant::SO3(p) => {
116 if let ProblemDefinitionVariant::SO3(pd) = &self.pd {
117 p.setup(pd.clone(), checker);
118 }
119 }
120 RRTConnectVariant::Compound(p) => {
121 if let ProblemDefinitionVariant::Compound(pd) = &self.pd {
122 p.setup(pd.clone(), checker);
123 }
124 }
125 RRTConnectVariant::SE2(p) => {
126 if let ProblemDefinitionVariant::SE2(pd) = &self.pd {
127 p.setup(pd.clone(), checker);
128 }
129 }
130 RRTConnectVariant::SE3(p) => {
131 if let ProblemDefinitionVariant::SE3(pd) = &self.pd {
132 p.setup(pd.clone(), checker);
133 }
134 }
135 }
136 }
137
138 pub fn solve(&mut self, timeout_secs: f32) -> Result<JsPath, String> {
139 let timeout = Duration::from_secs_f32(timeout_secs);
140 match &mut self.planner {
141 RRTConnectVariant::RealVector(p) => p
142 .solve(timeout)
143 .map(JsPath::from)
144 .map_err(|e| e.to_string()),
145 RRTConnectVariant::SO2(p) => p
146 .solve(timeout)
147 .map(JsPath::from)
148 .map_err(|e| e.to_string()),
149 RRTConnectVariant::SO3(p) => p
150 .solve(timeout)
151 .map(JsPath::from)
152 .map_err(|e| e.to_string()),
153 RRTConnectVariant::Compound(p) => p
154 .solve(timeout)
155 .map(JsPath::from)
156 .map_err(|e| e.to_string()),
157 RRTConnectVariant::SE2(p) => p
158 .solve(timeout)
159 .map(JsPath::from)
160 .map_err(|e| e.to_string()),
161 RRTConnectVariant::SE3(p) => p
162 .solve(timeout)
163 .map(JsPath::from)
164 .map_err(|e| e.to_string()),
165 }
166 }
167}