Skip to content

Commit

Permalink
WebAssembly bindings added
Browse files Browse the repository at this point in the history
  • Loading branch information
ReeceHumphreys committed Jan 23, 2024
1 parent 8f3bfd8 commit 9725ddb
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 27 deletions.
9 changes: 8 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,19 @@ Kessler is a library for simulating fragmentation events in low Earth orbit.

[dependencies]
blas-src = { version = "0.8", features = ["openblas"] }
ndarray = { version = "=0.15.6", features = ["blas", "rayon"] }
js-sys = "0.3.67"
ndarray = { version = "=0.15.6", features = ["blas", "rayon", "serde"] }
ndarray-linalg = "0.14"
ndarray-rand = "0.13.0"
openblas-src = { version = "0.10", features = ["cblas", "system"] }
rand = "0.8.5"
rand_distr = "0.4.3"
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
wasm-bindgen = { version = "0.2.90", features = ["serde"]}

[lib]
crate-type = ["cdylib", "rlib"]

[profile.release]
strip = true # Strip symbols from the binary
Expand Down
35 changes: 23 additions & 12 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::satellite::{SatKind, Satellite};

use ndarray::*;
use ndarray_linalg::*;
use wasm_bindgen::prelude::*;

pub trait FragmentationEvent {
fn fragment_count(&self, min_characteristic_len: f32) -> f32;
Expand All @@ -14,19 +15,22 @@ pub trait FragmentationEvent {
fn delta_velocity_offset(&self) -> [f32; 2];
}

#[wasm_bindgen]
#[derive(Debug)]
pub struct CollisionEvent {
pub min_characteristic_length: f32,
pub sat_kind: SatKind,
pub input_mass: f32,
pub satellites: Array1<Satellite>,
pub max_characteristic_length: f32,
satellites: Vec<Satellite>,
}

#[wasm_bindgen]
impl CollisionEvent {
pub fn new(satellites: &[Satellite], min_characteristic_length: f32) -> CollisionEvent {
let mut satellite_1 = satellites[0].clone();
let mut satellite_2 = satellites[1].clone();
#[wasm_bindgen(constructor)]
pub fn new(satellites: Vec<Satellite>, min_characteristic_length: f32) -> CollisionEvent {
let mut satellite_1 = satellites[0].to_owned();
let mut satellite_2 = satellites[1].to_owned();
let max_characteristic_length = satellite_1.characteristic_length.max(satellite_2.characteristic_length);
let mut sat_kind = SatKind::Soc;
if satellite_1.sat_kind == SatKind::Rb || satellite_2.sat_kind == SatKind::Rb {
Expand All @@ -39,14 +43,14 @@ impl CollisionEvent {
if satellite_2.characteristic_length > satellite_1.characteristic_length {
std::mem::swap(&mut satellite_1, &mut satellite_2)
}
let satellites = array![satellite_1, satellite_2];
let satellites = vec![satellite_1, satellite_2];

CollisionEvent {
min_characteristic_length,
sat_kind,
input_mass,
satellites,
max_characteristic_length
max_characteristic_length,
}
}

Expand Down Expand Up @@ -90,7 +94,9 @@ impl FragmentationEvent for CollisionEvent {
let satellite_2 = &self.satellites[1];

// Determine impact velocity
let v_impact = (&satellite_1.velocity - &satellite_2.velocity).norm();
let v1 = satellite_1.get_velocity();
let v2 = satellite_2.get_velocity();
let v_impact = (Array1::from_vec(v1) - Array1::from_vec(v2)).norm();

// Target is the larger satellite
let m_targ = satellite_1.mass;
Expand All @@ -104,7 +110,8 @@ impl FragmentationEvent for CollisionEvent {
}

fn location(&self) -> Array1<f32> {
self.satellites[0].position.to_owned()
let position = self.satellites[0].get_position();
Array1::from_vec(position)
}

fn min_characteristic_length(&self) -> f32 {
Expand All @@ -128,16 +135,19 @@ impl FragmentationEvent for CollisionEvent {
}
}

#[wasm_bindgen]
#[derive(Debug, Clone)]
pub struct ExplosionEvent {
pub min_characteristic_length: f32,
pub sat_type: SatKind,
pub input_mass: f32,
pub satellites: Array1<Satellite>,
pub max_characteristic_length: f32,
satellites: Vec<Satellite>,
}

#[wasm_bindgen]
impl ExplosionEvent {
#[wasm_bindgen(constructor)]
pub fn new(satellite: Satellite, min_characteristic_length: f32) -> ExplosionEvent {
let input_mass = satellite.mass;
let sat_type = satellite.sat_kind.clone();
Expand All @@ -147,8 +157,8 @@ impl ExplosionEvent {
min_characteristic_length,
input_mass,
sat_type,
satellites: array![satellite],
max_characteristic_length
satellites: vec![satellite],
max_characteristic_length,
}
}
}
Expand All @@ -164,7 +174,8 @@ impl FragmentationEvent for ExplosionEvent {
}

fn location(&self) -> Array1<f32> {
self.satellites.get(0).unwrap().position.to_owned()
let position = self.satellites.get(0).unwrap().get_position();
Array1::from_vec(position)
}

fn min_characteristic_length(&self) -> f32 {
Expand Down
17 changes: 17 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,24 @@ use ndarray::{s, Array, Array1, Array2, Array3};
use rand::distributions::{Distribution, Uniform};
use rand_distr::{Normal, UnitSphere};

// Non-WebAssembly bindings
#[cfg(not(target_arch = "wasm32"))]
pub fn run(event: &impl FragmentationEvent) -> Array3<f32> {
run_core(event)
}

// WebAssembly bindings
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::{prelude::*, JsValue};

#[cfg(target_arch = "wasm32")]
pub fn run(event: &impl FragmentationEvent) -> Option<JsValue> {
let result = run_core(event);
// Convert the result to JsValue
serde_wasm_bindgen::to_value(&result).ok()
}

fn run_core(event: &impl FragmentationEvent) -> Array3<f32> {
let characteristic_len_min = event.min_characteristic_length();
let fragment_count = event.fragment_count(characteristic_len_min).floor() as usize;
let location = event.location();
Expand Down
38 changes: 27 additions & 11 deletions src/satellite.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,48 @@
use ndarray::prelude::*;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
#[derive(Debug, Clone)]
pub struct Satellite {
pub position: Array1<f32>,
pub velocity: Array1<f32>,
pub mass: f32,
pub characteristic_length: f32,
pub sat_kind: SatKind,
position: Array1<f32>,
velocity: Array1<f32>,
}

#[wasm_bindgen]
impl Satellite {
pub fn new(
position: impl Into<[f32; 3]>,
velocity: impl Into<[f32; 3]>,
mass: f32,
sat_kind: SatKind,
) -> Self {
#[wasm_bindgen(constructor)]
pub fn new(position: Vec<f32>, velocity: Vec<f32>, mass: f32, sat_kind: SatKind) -> Self {
Self {
position: Array1::from(position.into().to_vec()),
velocity: Array1::from(velocity.into().to_vec()),
position: Array1::from_vec(position),
velocity: Array1::from_vec(velocity),
mass,
characteristic_length: calculate_characteristic_length_from_mass(mass),
sat_kind,
}
}

pub fn set_position(&mut self, position: &[f32]) {
self.position = Array1::from_vec(position.to_vec());
}

pub fn set_velocity(&mut self, velocity: &[f32]) {
self.velocity = Array1::from_vec(velocity.to_vec());
}

pub fn get_position(&self) -> Vec<f32> {
self.position.to_vec()
}

pub fn get_velocity(&self) -> Vec<f32> {
self.velocity.to_vec()
}
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[wasm_bindgen]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum SatKind {
Rb = 0,
Soc = 1,
Expand Down
5 changes: 2 additions & 3 deletions tests/explosion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ use kessler::{run, ExplosionEvent, SatKind, Satellite};

#[test]
fn explosion_nimbus() {

// Define the initial position, velocity, mass, characteristic length, and kind of a satellite.
let position = [0.0, 0.0, 0.0]; // position vector [m] relative to Earth's center
let velocity = [0.0, 0.0, 0.0]; // velocity vector [m/s]
let position = vec![0.0, 0.0, 0.0]; // position vector [m] relative to Earth's center
let velocity = vec![0.0, 0.0, 0.0]; // velocity vector [m/s]
let mass = 849.0; // kg
let characteristic_length = 0.1; // m
let sat_kind = SatKind::Rb; // kind of satellite (Rb, Debris, or Satellite)
Expand Down

0 comments on commit 9725ddb

Please sign in to comment.