v / examples / pendulum-simulation / modules / sim / params.v
95 lines · 76 sloc · 2.83 KB · 008aaad99981918c51194d7aaaaaccb4c258f244
Raw
1module sim
2
3import math
4
5pub const default_rope_length = 0.25
6pub const default_bearing_mass = 0.03
7pub const default_magnet_spacing = 0.05
8pub const default_magnet_height = 0.03
9pub const default_magnet_strength = 10.0
10pub const default_gravity = 4.9
11
12@[params]
13pub struct SimParams {
14pub:
15 rope_length f64 = default_rope_length
16 bearing_mass f64 = default_bearing_mass
17 magnet_spacing f64 = default_magnet_spacing
18 magnet_height f64 = default_magnet_height
19 magnet_strength f64 = default_magnet_strength
20 gravity f64 = default_gravity
21}
22
23pub fn sim_params(params SimParams) SimParams {
24 return SimParams{
25 ...params
26 }
27}
28
29pub fn (params SimParams) get_rope_vector(state SimState) Vector3D {
30 rope_origin := vector(z: params.rope_length)
31
32 return state.position + rope_origin.scale(-1)
33}
34
35pub fn (params SimParams) get_forces_sum(state SimState) Vector3D {
36 // force due to gravity
37 f_gravity := params.get_grav_force(state)
38
39 // force due to magnets
40 f_magnet1 := params.get_magnet1_force(state)
41 f_magnet2 := params.get_magnet2_force(state)
42 f_magnet3 := params.get_magnet3_force(state)
43
44 mut f_passive := vector(x: 0.0, y: 0.0, z: 0.0)
45 for force in [f_gravity, f_magnet1, f_magnet2, f_magnet3] {
46 f_passive = f_passive + force
47 }
48
49 // force due to tension of the rope
50 f_tension := params.get_tension_force(state, f_passive)
51
52 return f_passive + f_tension
53}
54
55pub fn (params SimParams) get_grav_force(state SimState) Vector3D {
56 return vector(z: -params.bearing_mass * params.gravity)
57}
58
59pub fn (params SimParams) get_magnet_position(theta f64) Vector3D {
60 return vector(
61 x: math.cos(theta) * params.magnet_spacing
62 y: math.sin(theta) * params.magnet_spacing
63 z: -params.magnet_height
64 )
65}
66
67pub fn (params SimParams) get_magnet_force(theta f64, state SimState) Vector3D {
68 magnet_position := params.get_magnet_position(theta)
69 mut diff := magnet_position + state.position.scale(-1)
70 distance_squared := diff.norm_squared()
71 diff = diff.scale(1.0 / math.sqrt(distance_squared))
72 return diff.scale(params.magnet_strength / distance_squared)
73}
74
75pub fn (params SimParams) get_magnet_dist(theta f64, state SimState) f64 {
76 return (params.get_magnet_position(theta) + state.position.scale(-1)).norm()
77}
78
79pub fn (params SimParams) get_magnet1_force(state SimState) Vector3D {
80 return params.get_magnet_force(0.0 * math.pi / 3.0, state)
81}
82
83pub fn (params SimParams) get_magnet2_force(state SimState) Vector3D {
84 return params.get_magnet_force(2.0 * math.pi / 3.0, state)
85}
86
87pub fn (params SimParams) get_magnet3_force(state SimState) Vector3D {
88 return params.get_magnet_force(4.0 * math.pi / 3.0, state)
89}
90
91pub fn (params SimParams) get_tension_force(state SimState, f_passive Vector3D) Vector3D {
92 rope_vector := params.get_rope_vector(state)
93 rope_vector_norm := rope_vector.scale(1.0 / rope_vector.norm())
94 return rope_vector_norm.scale(-1.0 * (rope_vector_norm * f_passive))
95}
96