driving_physics 0.0.0.2 → 0.0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +12 -1
- data/Rakefile +11 -4
- data/VERSION +1 -1
- data/demo/car.rb +165 -18
- data/demo/disk.rb +83 -0
- data/demo/gearbox.rb +52 -0
- data/demo/motor.rb +141 -0
- data/demo/powertrain.rb +47 -0
- data/demo/scalar_force.rb +41 -15
- data/demo/tire.rb +80 -162
- data/demo/vector_force.rb +46 -16
- data/lib/driving_physics/car.rb +77 -248
- data/lib/driving_physics/cli.rb +51 -0
- data/lib/driving_physics/disk.rb +185 -0
- data/lib/driving_physics/gearbox.rb +109 -0
- data/lib/driving_physics/imperial.rb +6 -0
- data/lib/driving_physics/motor.rb +103 -0
- data/lib/driving_physics/power.rb +20 -0
- data/lib/driving_physics/powertrain.rb +50 -0
- data/lib/driving_physics/scalar_force.rb +6 -3
- data/lib/driving_physics/tire.rb +90 -258
- data/lib/driving_physics/vector_force.rb +15 -2
- data/lib/driving_physics.rb +2 -0
- data/test/disk.rb +129 -0
- data/test/scalar_force.rb +7 -5
- data/test/tire.rb +144 -88
- data/test/vector_force.rb +7 -1
- metadata +12 -5
- data/demo/wheel.rb +0 -84
- data/lib/driving_physics/wheel.rb +0 -191
- data/test/car.rb +0 -156
- data/test/wheel.rb +0 -177
data/test/car.rb
DELETED
@@ -1,156 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'driving_physics/car'
|
3
|
-
|
4
|
-
C = DrivingPhysics::Car
|
5
|
-
|
6
|
-
describe C do
|
7
|
-
before do
|
8
|
-
@env = DrivingPhysics::Environment.new
|
9
|
-
@c = C.new(@env)
|
10
|
-
end
|
11
|
-
|
12
|
-
def get_moving
|
13
|
-
@c.controls.brake_pedal = 0.0
|
14
|
-
@c.controls.drive_pedal = 1.0
|
15
|
-
@c.add_fuel 10
|
16
|
-
50.times { @c.tick! }
|
17
|
-
expect(@c.condition.speed).must_be :>, 0.0
|
18
|
-
end
|
19
|
-
|
20
|
-
|
21
|
-
it "initializes" do
|
22
|
-
expect(@c).must_be_instance_of C
|
23
|
-
end
|
24
|
-
|
25
|
-
it "has a string representation" do
|
26
|
-
str = @c.to_s
|
27
|
-
expect(str).must_be_instance_of String
|
28
|
-
expect(str.length).must_be(:>, 5)
|
29
|
-
end
|
30
|
-
|
31
|
-
it "adds fuel and reports overflow" do
|
32
|
-
expect(@c.condition.fuel).must_equal 0.0
|
33
|
-
@c.add_fuel 10.0
|
34
|
-
expect(@c.condition.fuel).must_equal 10.0
|
35
|
-
overflow = @c.add_fuel @c.fuel_capacity
|
36
|
-
expect(@c.condition.fuel).must_equal @c.fuel_capacity
|
37
|
-
expect(overflow).must_equal 10.0
|
38
|
-
end
|
39
|
-
|
40
|
-
it "varies drive_force based on drive_pedal and available fuel" do
|
41
|
-
expect(@c.drive_force).must_equal 0.0 # no pedal
|
42
|
-
@c.controls.drive_pedal = 1.0
|
43
|
-
expect(@c.drive_force).must_equal 0.0 # no fuel
|
44
|
-
@c.add_fuel 10
|
45
|
-
|
46
|
-
expect(@c.drive_force).must_equal @c.max_drive_force # vroom!
|
47
|
-
end
|
48
|
-
|
49
|
-
it "has a drive vector in direction of @dir" do
|
50
|
-
@c.add_fuel 10
|
51
|
-
@c.controls.drive_pedal = 1.0
|
52
|
-
dv = @c.drive_force_vector
|
53
|
-
expect(dv).must_be_instance_of Vector
|
54
|
-
dvn = dv.normalize
|
55
|
-
[0,1].each { |dim|
|
56
|
-
expect(dvn[dim]).must_be_within_epsilon @c.condition.dir[dim]
|
57
|
-
}
|
58
|
-
end
|
59
|
-
|
60
|
-
it "varies brake_force based on brake_pedal" do
|
61
|
-
expect(@c.brake_force).must_equal 0.0 # no pedal
|
62
|
-
@c.controls.brake_pedal = 1.0
|
63
|
-
expect(@c.brake_force).must_equal @c.max_brake_force
|
64
|
-
end
|
65
|
-
|
66
|
-
it "has a brake vector opposing movement or @dir" do
|
67
|
-
# hmm, no good way to go in reverse
|
68
|
-
# just test against forward movement for now
|
69
|
-
@c.controls.brake_pedal = 1.0
|
70
|
-
bv = @c.brake_force_vector
|
71
|
-
expect(bv).must_be_instance_of Vector
|
72
|
-
bvn = bv.normalize
|
73
|
-
[0,1].each { |dim|
|
74
|
-
expect(bvn[dim]).must_be_within_epsilon @c.condition.dir[dim] * -1
|
75
|
-
}
|
76
|
-
|
77
|
-
get_moving
|
78
|
-
|
79
|
-
@c.controls.drive_pedal = 0.0
|
80
|
-
@c.controls.brake_pedal = 1.0
|
81
|
-
bdir = @c.brake_force_vector.normalize
|
82
|
-
vdir = @c.condition.vel.normalize
|
83
|
-
[0,1].each { |dim|
|
84
|
-
expect(bdir[dim]).must_be_within_epsilon vdir[dim] * -1
|
85
|
-
}
|
86
|
-
end
|
87
|
-
|
88
|
-
it "tracks the mass of remaining fuel" do
|
89
|
-
expect(@c.fuel_mass).must_equal 0.0
|
90
|
-
@c.add_fuel 10
|
91
|
-
expect(@c.fuel_mass).must_be_within_epsilon 7.1
|
92
|
-
end
|
93
|
-
|
94
|
-
it "tracks total_mass including fuel and driver" do
|
95
|
-
expect(@c.total_mass).must_equal @c.mass + @c.driver_mass
|
96
|
-
@c.add_fuel 10
|
97
|
-
expect(@c.total_mass).must_equal @c.mass + @c.fuel_mass + @c.driver_mass
|
98
|
-
end
|
99
|
-
|
100
|
-
it "computes the total weight based on G" do
|
101
|
-
expect(@c.weight).must_be_within_epsilon 10535.0
|
102
|
-
end
|
103
|
-
|
104
|
-
it "computes resistance forces based on instance variables" do
|
105
|
-
air = @c.air_resistance
|
106
|
-
expect(air).must_be_kind_of Vector
|
107
|
-
expect(air.magnitude).must_equal 0.0
|
108
|
-
|
109
|
-
rot = @c.rotational_resistance
|
110
|
-
expect(rot).must_be_kind_of Vector
|
111
|
-
expect(rot.magnitude).must_equal 0.0
|
112
|
-
|
113
|
-
roll = @c.rolling_resistance
|
114
|
-
expect(roll).must_be_kind_of Vector
|
115
|
-
expect(roll.magnitude).must_be :>, 0
|
116
|
-
end
|
117
|
-
|
118
|
-
describe C::Condition do
|
119
|
-
before do
|
120
|
-
@cond = @c.condition
|
121
|
-
end
|
122
|
-
|
123
|
-
it "intializes" do
|
124
|
-
expect(@cond).must_be_kind_of C::Condition
|
125
|
-
end
|
126
|
-
|
127
|
-
it "has a string representation" do
|
128
|
-
str = @cond.to_s
|
129
|
-
expect(str).must_be_kind_of String
|
130
|
-
expect(str.length).must_be :>, 5
|
131
|
-
end
|
132
|
-
|
133
|
-
it "has a lateral direction clockwise from @dir" do
|
134
|
-
lat = @cond.lat_dir
|
135
|
-
expect(lat).must_be_kind_of Vector
|
136
|
-
expect(lat.magnitude).must_be_within_epsilon 1.0
|
137
|
-
expect(lat.independent?(@cond.dir)).must_equal true
|
138
|
-
end
|
139
|
-
|
140
|
-
it "has a movement_dir based on velocity, or @dir when stopped" do
|
141
|
-
md = @cond.movement_dir
|
142
|
-
expect(md).must_be_kind_of Vector
|
143
|
-
expect(md.magnitude).must_be_within_epsilon 1.0
|
144
|
-
expect(md).must_equal @cond.dir
|
145
|
-
|
146
|
-
get_moving
|
147
|
-
md = @cond.movement_dir
|
148
|
-
expect(md).must_be_kind_of Vector
|
149
|
-
expect(md.magnitude).must_be_within_epsilon 1.0
|
150
|
-
vd = @cond.vel.normalize
|
151
|
-
[0,1].each { |dim|
|
152
|
-
expect(md[dim]).must_be_within_epsilon vd[dim]
|
153
|
-
}
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
data/test/wheel.rb
DELETED
@@ -1,177 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'driving_physics/wheel'
|
3
|
-
|
4
|
-
W = DrivingPhysics::Wheel
|
5
|
-
|
6
|
-
describe W do
|
7
|
-
describe "Wheel.traction" do
|
8
|
-
it "calculates traction force from normal force and coeff of friction" do
|
9
|
-
scalar_nf = 9800 # N
|
10
|
-
cof = 1.1
|
11
|
-
scalar_t = W.traction(scalar_nf, cof)
|
12
|
-
expect(scalar_t).must_equal 10780.0
|
13
|
-
|
14
|
-
vector_nf = Vector[9800, 0]
|
15
|
-
vector_t = W.traction(vector_nf, cof)
|
16
|
-
expect(vector_t).must_equal Vector[10780.0, 0.0]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
describe "Wheel.volume" do
|
21
|
-
it "calculates the volume (m^3) of disk given radius and width" do
|
22
|
-
cubic_m = W.volume(1.0, 1.0)
|
23
|
-
expect(cubic_m).must_equal Math::PI
|
24
|
-
|
25
|
-
cubic_m = W.volume(0.35, 0.2)
|
26
|
-
expect(cubic_m).must_be_within_epsilon 0.076969
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe "Wheel.volume_l" do
|
31
|
-
it "calculates the volume (L) of a disk given radius and width" do
|
32
|
-
liters = W.volume_l(1.0, 1.0)
|
33
|
-
expect(liters).must_equal Math::PI * 1000
|
34
|
-
|
35
|
-
liters = W.volume_l(0.35, 0.2)
|
36
|
-
expect(liters).must_be_within_epsilon 76.96902
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "Wheel.density" do
|
41
|
-
it "calculates the density (kg/L) given mass and volume" do
|
42
|
-
expect(W.density(25.0, 25.0)).must_equal 1.0
|
43
|
-
expect(W.density(50.0, 25.0)).must_equal 2.0
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe "Wheel.mass" do
|
48
|
-
it "calculates the mass (kg) of a disk given radius, width, and density" do
|
49
|
-
expect(W.mass(0.35, 0.2, W::DENSITY)).must_be_within_epsilon 25.015
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "Wheel.rotational_inertia" do
|
54
|
-
it "calculates rotational inertia for a disk given radius and mass" do
|
55
|
-
expect(W.rotational_inertia(0.35, 25.0)).must_be_within_epsilon 1.53125
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe "Wheel.alpha" do
|
60
|
-
it "calculates angular acceleration from torque and inertia" do
|
61
|
-
scalar_torque = 1000
|
62
|
-
inertia = W.rotational_inertia(0.35, 25.0)
|
63
|
-
expect(W.alpha scalar_torque, inertia).must_be_within_epsilon 653.061
|
64
|
-
|
65
|
-
vector_torque = Vector[0, 0, 1000]
|
66
|
-
vector_alpha = W.alpha vector_torque, inertia
|
67
|
-
expect(vector_alpha).must_be_instance_of Vector
|
68
|
-
expect(vector_alpha.size).must_equal 3
|
69
|
-
expect(vector_alpha[2]).must_be_within_epsilon 653.06
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
describe "Wheel.torque_vector" do
|
74
|
-
it "calculates a torque in the 3rd dimension given 2D force and radius" do
|
75
|
-
force = Vector[1000, 0]
|
76
|
-
radius = Vector[0, 5]
|
77
|
-
torque = W.torque_vector(force, radius)
|
78
|
-
expect(torque).must_be_instance_of Vector
|
79
|
-
expect(torque.size).must_equal 3
|
80
|
-
expect(torque[2]).must_be_within_epsilon 5000.0
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
describe "Wheel.force_vector" do
|
85
|
-
it "calculates a (3D) force given 3D torque and 2D radius" do
|
86
|
-
# let's invert the Wheel.torque_vector case from above:
|
87
|
-
torque = Vector[0, 0, 5000]
|
88
|
-
radius = Vector[0, 5]
|
89
|
-
force = W.force_vector(torque, radius)
|
90
|
-
expect(force).must_be_instance_of Vector
|
91
|
-
expect(force.size).must_equal 3
|
92
|
-
expect(force[0]).must_be_within_epsilon 1000.0
|
93
|
-
|
94
|
-
# now let's rotate the radius into the x-dimension
|
95
|
-
# right hand rule, positive torque means thumb into screen, clockwise
|
96
|
-
# negative-x radius means positive-y force
|
97
|
-
torque = Vector[0, 0, 500]
|
98
|
-
radius = Vector[-5, 0]
|
99
|
-
force = W.force_vector(torque, radius)
|
100
|
-
expect(force).must_be_instance_of Vector
|
101
|
-
expect(force.size).must_equal 3
|
102
|
-
expect(force[1]).must_be_within_epsilon 100.0
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
describe "instance methods" do
|
107
|
-
before do
|
108
|
-
@env = DrivingPhysics::Environment.new
|
109
|
-
@w = W.new(@env)
|
110
|
-
end
|
111
|
-
|
112
|
-
it "initializes" do
|
113
|
-
expect(@w).must_be_instance_of W
|
114
|
-
expect(@w.density).must_equal W::DENSITY # sanity check
|
115
|
-
expect(@w.mass).must_be_within_epsilon 25.01
|
116
|
-
|
117
|
-
with_mass = W.new(@env, mass: 99.01)
|
118
|
-
expect(with_mass.mass).must_equal 99.01
|
119
|
-
expect(with_mass.density).wont_equal W::DENSITY
|
120
|
-
end
|
121
|
-
|
122
|
-
it "has a string representation" do
|
123
|
-
str = @w.to_s
|
124
|
-
expect(str).must_be_instance_of String
|
125
|
-
expect(str.length).must_be(:>, 5)
|
126
|
-
end
|
127
|
-
|
128
|
-
it "loses radius as it wears" do
|
129
|
-
expect(@w.radius).must_equal 350.0
|
130
|
-
@w.wear!(50)
|
131
|
-
expect(@w.radius).must_equal 300.0
|
132
|
-
end
|
133
|
-
|
134
|
-
it "calculates mass from current radius" do
|
135
|
-
expect(@w.mass).must_be_within_epsilon 25.01
|
136
|
-
@w.wear!(50)
|
137
|
-
expect(@w.mass).must_be_within_epsilon 18.378
|
138
|
-
end
|
139
|
-
|
140
|
-
it "has volume" do
|
141
|
-
expect(@w.volume).must_be_within_epsilon 0.07697
|
142
|
-
expect(@w.volume_l).must_be_within_epsilon 76.96902
|
143
|
-
end
|
144
|
-
|
145
|
-
it "has inertia" do
|
146
|
-
expect(@w.rotational_inertia).must_be_within_epsilon 1.5321
|
147
|
-
end
|
148
|
-
|
149
|
-
it "has traction force based on normal force" do
|
150
|
-
scalar_nf = 9800
|
151
|
-
expect(@w.traction scalar_nf).must_equal 10780.0
|
152
|
-
expect(@w.traction scalar_nf, static: false).must_equal 6860.0
|
153
|
-
|
154
|
-
vector_nf = Vector[9800, 0]
|
155
|
-
expect(@w.traction vector_nf).must_equal Vector[10780.0, 0.0]
|
156
|
-
expect(@w.traction vector_nf, static: false).
|
157
|
-
must_equal Vector[6860.0, 0.0]
|
158
|
-
end
|
159
|
-
|
160
|
-
it "determines (e.g. thrust) force based on axle torque" do
|
161
|
-
expect(@w.force 1000).must_be_within_epsilon 2857.143
|
162
|
-
@w.wear! 50
|
163
|
-
expect(@w.force 1000).must_be_within_epsilon 3333.333
|
164
|
-
end
|
165
|
-
|
166
|
-
it "determines tractable torque" do
|
167
|
-
scalar_nf = 9800
|
168
|
-
expect(@w.tractable_torque scalar_nf).must_be_within_epsilon 3773.0
|
169
|
-
kin_tq = @w.tractable_torque scalar_nf, static: false
|
170
|
-
expect(kin_tq).must_be_within_epsilon 2401.0
|
171
|
-
|
172
|
-
# not sure about how torque vectors work, but the "math" "works":
|
173
|
-
vector_nf = Vector[9800, 0]
|
174
|
-
expect(@w.tractable_torque(vector_nf)[0]).must_be_within_epsilon 3773.0
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|