Skip to main content

oxmpl_js/base/
compound_state_space.rs

1// Copyright (c) 2025 Junior Sundar
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5use std::sync::{Arc, Mutex};
6
7use oxmpl::base::space::{AnyStateSpace, CompoundStateSpace, StateSpace};
8use rand::rng;
9use wasm_bindgen::prelude::*;
10
11use crate::base::{
12    JsCompoundState, JsRealVectorStateSpace, JsSE2StateSpace, JsSE3StateSpace, JsSO2StateSpace,
13    JsSO3StateSpace,
14};
15
16#[wasm_bindgen(js_name = CompoundStateSpace)]
17pub struct JsCompoundStateSpace {
18    #[wasm_bindgen(skip)]
19    pub inner: Arc<Mutex<CompoundStateSpace>>,
20}
21
22#[wasm_bindgen(js_class = CompoundStateSpace)]
23impl JsCompoundStateSpace {
24    #[wasm_bindgen(js_name = sample)]
25    pub fn sample(&self) -> Result<JsCompoundState, String> {
26        let mut rng = rng();
27        match self.inner.lock().unwrap().sample_uniform(&mut rng) {
28            Ok(state) => Ok(JsCompoundState {
29                inner: Arc::new(state),
30            }),
31            Err(e) => Err(e.to_string()),
32        }
33    }
34
35    #[wasm_bindgen(js_name = distance)]
36    pub fn distance(&self, state1: &JsCompoundState, state2: &JsCompoundState) -> f64 {
37        self.inner
38            .lock()
39            .unwrap()
40            .distance(&state1.inner, &state2.inner)
41    }
42
43    #[wasm_bindgen(js_name = satisfiesBounds)]
44    pub fn satisfies_bounds(&self, state: &JsCompoundState) -> bool {
45        self.inner.lock().unwrap().satisfies_bounds(&state.inner)
46    }
47
48    #[wasm_bindgen(js_name = enforceBounds)]
49    pub fn enforce_bounds(&self, state: &JsCompoundState) -> JsCompoundState {
50        let mut new_state = (*state.inner).clone();
51        self.inner.lock().unwrap().enforce_bounds(&mut new_state);
52        JsCompoundState {
53            inner: Arc::new(new_state),
54        }
55    }
56
57    #[wasm_bindgen(js_name = interpolate)]
58    pub fn interpolate(
59        &self,
60        from: &JsCompoundState,
61        to: &JsCompoundState,
62        t: f64,
63    ) -> JsCompoundState {
64        let mut result_state = (*from.inner).clone();
65        self.inner
66            .lock()
67            .unwrap()
68            .interpolate(&from.inner, &to.inner, t, &mut result_state);
69        JsCompoundState {
70            inner: Arc::new(result_state),
71        }
72    }
73
74    #[wasm_bindgen(js_name = getLongestValidSegmentLength)]
75    pub fn get_longest_valid_segment_length(&self) -> f64 {
76        self.inner
77            .lock()
78            .unwrap()
79            .get_longest_valid_segment_length()
80    }
81}
82
83#[wasm_bindgen(js_name = CompoundStateSpaceBuilder)]
84pub struct JsCompoundStateSpaceBuilder {
85    subspaces: Vec<Box<dyn AnyStateSpace>>,
86    weights: Vec<f64>,
87}
88
89impl Default for JsCompoundStateSpaceBuilder {
90    fn default() -> Self {
91        Self::new()
92    }
93}
94
95#[wasm_bindgen(js_class = CompoundStateSpaceBuilder)]
96impl JsCompoundStateSpaceBuilder {
97    #[wasm_bindgen(constructor)]
98    pub fn new() -> Self {
99        Self {
100            subspaces: Vec::new(),
101            weights: Vec::new(),
102        }
103    }
104
105    #[wasm_bindgen(js_name = addRealVectorStateSpace)]
106    pub fn add_real_vector_state_space(&mut self, space: &JsRealVectorStateSpace, weight: f64) {
107        self.subspaces
108            .push(Box::new(space.inner.lock().unwrap().clone()));
109        self.weights.push(weight);
110    }
111
112    #[wasm_bindgen(js_name = addSO2StateSpace)]
113    pub fn add_so2_state_space(&mut self, space: &JsSO2StateSpace, weight: f64) {
114        self.subspaces
115            .push(Box::new(space.inner.lock().unwrap().clone()));
116        self.weights.push(weight);
117    }
118
119    #[wasm_bindgen(js_name = addSO3StateSpace)]
120    pub fn add_so3_state_space(&mut self, space: &JsSO3StateSpace, weight: f64) {
121        self.subspaces
122            .push(Box::new(space.inner.lock().unwrap().clone()));
123        self.weights.push(weight);
124    }
125
126    #[wasm_bindgen(js_name = addSE2StateSpace)]
127    pub fn add_se2_state_space(&mut self, space: &JsSE2StateSpace, weight: f64) {
128        self.subspaces
129            .push(Box::new(space.inner.lock().unwrap().clone()));
130        self.weights.push(weight);
131    }
132
133    #[wasm_bindgen(js_name = addSE3StateSpace)]
134    pub fn add_se3_state_space(&mut self, space: &JsSE3StateSpace, weight: f64) {
135        self.subspaces
136            .push(Box::new(space.inner.lock().unwrap().clone()));
137        self.weights.push(weight);
138    }
139
140    #[wasm_bindgen(js_name = addCompoundStateSpace)]
141    pub fn add_compound_state_space(&mut self, space: &JsCompoundStateSpace, weight: f64) {
142        self.subspaces
143            .push(Box::new(space.inner.lock().unwrap().clone()));
144        self.weights.push(weight);
145    }
146
147    pub fn build(self) -> JsCompoundStateSpace {
148        let space = CompoundStateSpace::new(self.subspaces, self.weights);
149        JsCompoundStateSpace {
150            inner: Arc::new(Mutex::new(space)),
151        }
152    }
153}