1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
8#[serde(rename_all = "kebab-case")]
9pub enum DomainType {
10 RigidBodyDynamics,
12 ConvexCollision,
14 Mpm,
16 Electromagnetic,
18 MolecularDynamics,
20 QuantumFieldTheory,
22 Gravity,
24 LatticeBoltzmann,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct Domain {
31 #[serde(rename = "type")]
33 pub domain_type: DomainType,
34
35 #[serde(flatten)]
37 pub config: HashMap<String, serde_json::Value>,
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct RigidBodyDomain {
43 pub bodies: Vec<BodySpec>,
45 pub joints: Vec<JointSpec>,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct BodySpec {
52 pub name: String,
54 pub mass: f64,
56 pub inertia: [f64; 6],
58 #[serde(default)]
60 pub center_of_mass: [f64; 3],
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct JointSpec {
66 #[serde(rename = "type")]
68 pub joint_type: JointTypeSpec,
69 pub parent: String,
71 pub child: String,
73 #[serde(default)]
75 pub axis: [f64; 3],
76 #[serde(default)]
78 pub position: [f64; 3],
79 #[serde(default = "default_quaternion")]
81 pub orientation: [f64; 4],
82 #[serde(default)]
84 pub limits: Option<[f64; 2]>,
85 #[serde(default)]
87 pub damping: f64,
88}
89
90fn default_quaternion() -> [f64; 4] {
91 [1.0, 0.0, 0.0, 0.0]
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
96#[serde(rename_all = "lowercase")]
97pub enum JointTypeSpec {
98 Free,
100 Revolute,
102 Prismatic,
104 Spherical,
106 Fixed,
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct CollisionDomain {
113 pub geometries: Vec<GeometrySpec>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct GeometrySpec {
120 pub body: String,
122 pub shape: ShapeType,
124 #[serde(flatten)]
126 pub params: HashMap<String, serde_json::Value>,
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
131#[serde(rename_all = "lowercase")]
132pub enum ShapeType {
133 Box,
135 Sphere,
137 Capsule,
139 Cylinder,
141 Mesh,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct ParticleDomain {
148 pub material: String,
150 pub particles: usize,
152 pub grid_resolution: [usize; 3],
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn test_domain_type_serialization() {
162 let domain_type = DomainType::RigidBodyDynamics;
163 let json = serde_json::to_string(&domain_type).unwrap();
164 assert_eq!(json, "\"rigid-body-dynamics\"");
165
166 let parsed: DomainType = serde_json::from_str(&json).unwrap();
167 assert_eq!(parsed, domain_type);
168 }
169
170 #[test]
171 fn test_body_spec_serialization() {
172 let body = BodySpec {
173 name: "torso".to_string(),
174 mass: 1.0,
175 inertia: [1.0, 1.0, 1.0, 0.0, 0.0, 0.0],
176 center_of_mass: [0.0, 0.0, 0.0],
177 };
178
179 let json = serde_json::to_string(&body).unwrap();
180 let parsed: BodySpec = serde_json::from_str(&json).unwrap();
181
182 assert_eq!(parsed.name, "torso");
183 assert_eq!(parsed.mass, 1.0);
184 }
185
186 #[test]
187 fn test_joint_spec_serialization() {
188 let joint = JointSpec {
189 joint_type: JointTypeSpec::Revolute,
190 parent: "world".to_string(),
191 child: "link1".to_string(),
192 axis: [0.0, 0.0, 1.0],
193 position: [0.0, 0.0, 0.0],
194 orientation: [1.0, 0.0, 0.0, 0.0],
195 limits: Some([-3.14, 3.14]),
196 damping: 0.1,
197 };
198
199 let json = serde_json::to_string(&joint).unwrap();
200 let parsed: JointSpec = serde_json::from_str(&json).unwrap();
201
202 assert_eq!(parsed.joint_type, JointTypeSpec::Revolute);
203 assert_eq!(parsed.parent, "world");
204 }
205}