driving_physics 0.0.2.1 → 0.0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/test/disk.rb CHANGED
@@ -1,116 +1,78 @@
1
1
  require 'minitest/autorun'
2
2
  require 'driving_physics/disk'
3
+ require 'matrix'
3
4
 
4
- D = DrivingPhysics::Disk
5
+ include DrivingPhysics
5
6
 
6
- describe D do
7
+ describe Disk do
7
8
  describe "Disk.volume" do
8
9
  it "calculates the volume (m^3) of disk given radius and width" do
9
- cubic_m = D.volume(1.0, 1.0)
10
+ cubic_m = Disk.volume(1.0, 1.0)
10
11
  expect(cubic_m).must_equal Math::PI
11
12
 
12
- cubic_m = D.volume(0.35, 0.2)
13
+ cubic_m = Disk.volume(0.35, 0.2)
13
14
  expect(cubic_m).must_be_within_epsilon 0.076969
14
15
  end
15
16
  end
16
17
 
17
18
  describe "Disk.volume_l" do
18
19
  it "calculates the volume (L) of a disk given radius and width" do
19
- liters = D.volume_l(1.0, 1.0)
20
+ liters = Disk.volume_l(1.0, 1.0)
20
21
  expect(liters).must_equal Math::PI * 1000
21
22
 
22
- liters = D.volume_l(0.35, 0.2)
23
+ liters = Disk.volume_l(0.35, 0.2)
23
24
  expect(liters).must_be_within_epsilon 76.96902
24
25
  end
25
26
  end
26
27
 
27
28
  describe "Disk.density" do
28
29
  it "calculates the density (kg/L) given mass and volume" do
29
- expect(D.density(25.0, 25.0)).must_equal 1.0
30
- expect(D.density(50.0, 25.0)).must_equal 2.0
30
+ expect(Disk.density(25.0, 25.0)).must_equal 1.0
31
+ expect(Disk.density(50.0, 25.0)).must_equal 2.0
31
32
  end
32
33
  end
33
34
 
34
35
  describe "Disk.mass" do
35
36
  it "calculates the mass (kg) of a disk given radius, width, and density" do
36
- skip
37
- expect(D.mass(0.35, 0.2, D::DENSITY)).must_be_within_epsilon 25.015
37
+ expect(Disk.mass(0.35, 0.2, Disk::DENSITY)).must_be_within_epsilon 76.969
38
38
  end
39
39
  end
40
40
 
41
41
  describe "Disk.rotational_inertia" do
42
42
  it "calculates rotational inertia for a disk given radius and mass" do
43
- expect(D.rotational_inertia(0.35, 25.0)).must_be_within_epsilon 1.53125
43
+ expect(Disk.rotational_inertia(0.35, 25.0)).must_be_within_epsilon 1.53125
44
44
  end
45
45
  end
46
46
 
47
47
  describe "Disk.alpha" do
48
48
  it "calculates angular acceleration from torque and inertia" do
49
49
  scalar_torque = 1000
50
- inertia = D.rotational_inertia(0.35, 25.0)
51
- expect(D.alpha scalar_torque, inertia).must_be_within_epsilon 653.061
50
+ inertia = Disk.rotational_inertia(0.35, 25.0)
51
+ expect(Disk.alpha scalar_torque, inertia).must_be_within_epsilon 653.061
52
52
 
53
- skip # Vector
53
+ skip unless DrivingPhysics.has_vector?
54
54
  vector_torque = Vector[0, 0, 1000]
55
- vector_alpha = D.alpha vector_torque, inertia
55
+ vector_alpha = Disk.alpha vector_torque, inertia
56
56
  expect(vector_alpha).must_be_instance_of Vector
57
57
  expect(vector_alpha.size).must_equal 3
58
58
  expect(vector_alpha[2]).must_be_within_epsilon 653.06
59
59
  end
60
60
  end
61
61
 
62
- describe "Disk.torque_vector" do
63
- it "calculates a torque in the 3rd dimension given 2D force and radius" do
64
- skip # Vector
65
- force = Vector[1000, 0]
66
- radius = Vector[0, 5]
67
- torque = D.torque_vector(force, radius)
68
- expect(torque).must_be_instance_of Vector
69
- expect(torque.size).must_equal 3
70
- expect(torque[2]).must_be_within_epsilon 5000.0
71
- end
72
- end
73
-
74
- describe "Disk.force_vector" do
75
- it "calculates a (3D) force given 3D torque and 2D radius" do
76
- skip # Vector
77
- # let's invert the Disk.torque_vector case from above:
78
- torque = Vector[0, 0, 5000]
79
- radius = Vector[0, 5]
80
- force = D.force_vector(torque, radius)
81
- expect(force).must_be_instance_of Vector
82
- expect(force.size).must_equal 3
83
- expect(force[0]).must_be_within_epsilon 1000.0
84
-
85
- # now let's rotate the radius into the x-dimension
86
- # right hand rule, positive torque means thumb into screen, clockwise
87
- # negative-x radius means positive-y force
88
- torque = Vector[0, 0, 500]
89
- radius = Vector[-5, 0]
90
- force = D.force_vector(torque, radius)
91
- expect(force).must_be_instance_of Vector
92
- expect(force.size).must_equal 3
93
- expect(force[1]).must_be_within_epsilon 100.0
94
- end
95
- end
96
-
97
62
  describe "instance methods" do
98
63
  before do
99
64
  @env = DrivingPhysics::Environment.new
100
- @disk = D.new(@env)
65
+ @disk = Disk.new(@env)
101
66
  end
102
67
 
103
68
  it "initializes" do
104
- skip
105
- expect(@disk).must_be_instance_of D
106
- expect(@disk.density).must_equal D::DENSITY # sanity check
107
- expect(@disk.mass).must_be_within_epsilon 25.01
108
-
109
- with_mass = D.new(@env) { |w|
110
- w.mass = 99.01
111
- }
69
+ expect(@disk).must_be_instance_of Disk
70
+ expect(@disk.density).must_equal Disk::DENSITY # sanity check
71
+ expect(@disk.mass).must_be_within_epsilon 76.969
72
+
73
+ with_mass = Disk.new(@env) { |w| w.mass = 99.01 }
112
74
  expect(with_mass.mass).must_equal 99.01
113
- expect(with_mass.density).wont_equal D::DENSITY
75
+ expect(with_mass.density).wont_equal Disk::DENSITY
114
76
  end
115
77
 
116
78
  it "has a string representation" do
@@ -125,8 +87,7 @@ describe D do
125
87
  end
126
88
 
127
89
  it "has inertia" do
128
- skip
129
- expect(@disk.rotational_inertia).must_be_within_epsilon 1.5321
90
+ expect(@disk.rotational_inertia).must_be_within_epsilon 4.714
130
91
  end
131
92
  end
132
93
  end
data/test/gearbox.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'minitest/autorun'
2
+ require 'driving_physics/gearbox'
3
+
4
+ include DrivingPhysics
5
+
6
+ describe Gearbox do
7
+ it "has gear ratios" do
8
+ end
9
+
10
+ it "has a final drive" do
11
+ end
12
+
13
+ it "has a neutral gear" do
14
+ end
15
+
16
+ it "has a clutch with state" do
17
+ end
18
+
19
+ it "has mass" do
20
+ end
21
+
22
+ it "has rotating mass" do
23
+ end
24
+
25
+ it "converts crank torque to axle torque" do
26
+ end
27
+
28
+ it "has losses due to inertia and friction" do
29
+ end
30
+
31
+ it "converts crank omega to axle omega (and vice versa)" do
32
+ end
33
+
34
+ it "varies torque delivery based on gear ratio and clutch" do
35
+ end
36
+ end
data/test/motor.rb ADDED
@@ -0,0 +1,236 @@
1
+ require 'minitest/autorun'
2
+ require 'driving_physics/motor'
3
+
4
+ include DrivingPhysics
5
+
6
+ describe "interpolate" do
7
+ it "validates xs and ys match in size" do
8
+ xs = [0, 5, 10, 15, 20]
9
+ ys = [10, 10, 10, 10, 5]
10
+ expect(DrivingPhysics.interpolate(1, xs: xs, ys: ys)).must_equal 10
11
+ expect { DrivingPhysics.interpolate(1, xs: xs + [10], ys: ys) }.must_raise
12
+ expect { DrivingPhysics.interpolate(1, xs: xs, ys: ys + [10]) }.must_raise
13
+ end
14
+
15
+ it "validates x is within the range of xs" do
16
+ xs = [0, 5, 10, 15, 20]
17
+ ys = [10, 10, 10, 10, 5]
18
+ expect(DrivingPhysics.interpolate(1, xs: xs, ys: ys)).must_equal 10
19
+ expect { DrivingPhysics.interpolate(-1, xs: xs, ys: ys) }.must_raise
20
+ expect { DrivingPhysics.interpolate(25, xs: xs, ys: ys) }.must_raise
21
+ end
22
+
23
+ it "validates the xs are in ascending order" do
24
+ xs = [0, 5, 10, 15, 20]
25
+ ys = [10, 10, 10, 10, 5]
26
+ expect(DrivingPhysics.interpolate(1, xs: xs, ys: ys)).must_equal 10
27
+ xs[1] = 15
28
+ expect {
29
+ DrivingPhysics.interpolate(16, xs: xs, ys: ys)
30
+ }.must_raise
31
+ end
32
+
33
+ it "performs linear interpolation to yield a y value for a valid x" do
34
+ xs = [0, 5, 10, 15, 20]
35
+ ys = [5, 5, 10, 10, 15]
36
+
37
+ expect(DrivingPhysics.interpolate(0, xs: xs, ys: ys)).must_equal 5
38
+ expect(DrivingPhysics.interpolate(1, xs: xs, ys: ys)).must_equal 5
39
+ expect(DrivingPhysics.interpolate(4, xs: xs, ys: ys)).must_equal 5
40
+ expect(DrivingPhysics.interpolate(5, xs: xs, ys: ys)).must_equal 5
41
+ expect(DrivingPhysics.interpolate(6, xs: xs, ys: ys)).must_equal 6
42
+ expect(DrivingPhysics.interpolate(7, xs: xs, ys: ys)).must_equal 7
43
+ expect(DrivingPhysics.interpolate(8, xs: xs, ys: ys)).must_equal 8
44
+ expect(DrivingPhysics.interpolate(9, xs: xs, ys: ys)).must_equal 9
45
+ expect(DrivingPhysics.interpolate(10, xs: xs, ys: ys)).must_equal 10
46
+ expect(DrivingPhysics.interpolate(11, xs: xs, ys: ys)).must_equal 10
47
+ expect(DrivingPhysics.interpolate(12, xs: xs, ys: ys)).must_equal 10
48
+ expect(DrivingPhysics.interpolate(14, xs: xs, ys: ys)).must_equal 10
49
+ expect(DrivingPhysics.interpolate(15, xs: xs, ys: ys)).must_equal 10
50
+ expect(DrivingPhysics.interpolate(16, xs: xs, ys: ys)).must_equal 11
51
+ expect(DrivingPhysics.interpolate(17, xs: xs, ys: ys)).must_equal 12
52
+ expect(DrivingPhysics.interpolate(18, xs: xs, ys: ys)).must_equal 13
53
+ expect(DrivingPhysics.interpolate(19, xs: xs, ys: ys)).must_equal 14
54
+ expect(DrivingPhysics.interpolate(20, xs: xs, ys: ys)).must_equal 15
55
+ end
56
+ end
57
+
58
+ # shorthand
59
+ def tc(rpms, torques)
60
+ TorqueCurve.new(rpms: rpms, torques: torques)
61
+ end
62
+
63
+ describe TorqueCurve do
64
+ before do
65
+ @default = TorqueCurve.new
66
+ @rpms = [500, 1000, 3500, 6000, 7000, 7100]
67
+ @torques = [ 0, 100, 300, 300, 250, 0]
68
+ @minr = [0, 1]
69
+ @mint = [0, 0]
70
+ end
71
+
72
+ it "maps rpm values to torque values" do
73
+ expect(@default.torque(3500)).must_be(:>, 100)
74
+ end
75
+
76
+ describe "initialize" do
77
+ it "accepts two arrays: rpms, and the corresponding torques" do
78
+ expect(tc(@rpms, @torques)).must_be_kind_of(TorqueCurve)
79
+ end
80
+
81
+ it "has defaults for rpms and torques" do
82
+ expect(@default).must_be_kind_of(TorqueCurve)
83
+ end
84
+
85
+ it "validates size match for rpms and torques" do
86
+ expect( tc( @minr, @mint) ).must_be_kind_of TorqueCurve
87
+ expect { tc( [0], @mint) }.must_raise
88
+ expect { tc([0,1,2], @mint) }.must_raise
89
+ expect { tc(@minr, [0]) }.must_raise
90
+ expect { tc(@minr, [0,1,0]) }.must_raise
91
+
92
+ rpms = [100, 2000, 30_000]
93
+ torques = [0, 500, 0]
94
+
95
+ expect( tc( rpms, torques) ).must_be_kind_of TorqueCurve
96
+ expect { tc( rpms, [0, 0]) }.must_raise
97
+ expect { tc([1,2], torques) }.must_raise
98
+ expect { tc([1,2,3,4], torques) }.must_raise
99
+ end
100
+
101
+
102
+ describe "rpms" do
103
+ it "validates rpms are positive" do
104
+ expect( tc( @minr, @mint) ).must_be_kind_of TorqueCurve
105
+ expect { tc([-10, 10], @mint) }.must_raise
106
+ end
107
+
108
+ it "validates rpms are in ascending order" do
109
+ expect( tc( @minr, @mint) ).must_be_kind_of TorqueCurve
110
+ expect { tc([0, 0], @mint) }.must_raise
111
+ expect( tc([99, 100], @mint) ).must_be_kind_of TorqueCurve
112
+ expect { tc([100, 99], @mint) }.must_raise
113
+ end
114
+ end
115
+
116
+ describe "torques" do
117
+ it "validates that torques start and end at zero" do
118
+ expect( tc(@minr, @mint) ).must_be_kind_of TorqueCurve
119
+ expect { tc(@minr, [1,0]) }.must_raise
120
+ expect { tc(@minr, [0,1]) }.must_raise
121
+ expect { tc(@minr, [1,1]) }.must_raise
122
+
123
+ expect( tc([1,2,3], [0,500,0]) ).must_be_kind_of TorqueCurve
124
+ expect { tc([1,2,3], [1,500,0]) }.must_raise
125
+ expect { tc([1,2,3], [0,500,1]) }.must_raise
126
+ end
127
+
128
+ it "validates that torques are positive" do
129
+ expect( tc([1,2,3], [0, 5,0]) ).must_be_kind_of TorqueCurve
130
+ expect { tc([1,2,3], [0,-5,0]) }.must_raise
131
+ end
132
+ end
133
+ end
134
+
135
+ it "finds the peak torque and corresponding RPM" do
136
+ rpm, torque = *@default.peak
137
+ expect(rpm).must_be(:>, 1000)
138
+ expect(rpm).must_be(:<, 10_000)
139
+ expect(torque).must_be(:>, 0)
140
+ expect(torque).must_be(:<, 10_000)
141
+ end
142
+
143
+ it "interpolates to find the torque for a valid RPM" do
144
+ tc = tc(@rpms, @torques)
145
+ r1 = @rpms[1]
146
+ r2 = @rpms[2]
147
+
148
+ expect(tc.torque(r1)).must_equal @torques[1]
149
+ expect(tc.torque(r2)).must_equal @torques[2]
150
+
151
+ r3 = (r1 + r2) / 2
152
+ t3 = tc.torque(r3)
153
+ t3_expect = (@torques[1] + @torques[2]) / 2.0
154
+
155
+ expect(t3).must_be :>, @torques[1]
156
+ expect(t3).must_be :<, @torques[2]
157
+ expect(t3).must_be :>=, t3_expect.floor
158
+ expect(t3).must_be :<=, t3_expect.ceil
159
+ end
160
+
161
+ it "tracks min, idle, redline, and max rpms" do
162
+ expect(@default.min).must_be :>, 0
163
+ expect(@default.min).must_be :<, 1000
164
+ expect(@default.idle).must_be :>, @default.min
165
+ expect(@default.idle).must_be :<, 3000
166
+ expect(@default.redline).must_be :>, @default.idle
167
+ expect(@default.redline).must_be :<, 20_000
168
+ expect(@default.max).must_be :>, @default.redline
169
+ expect(@default.max).must_be :<, 20_000
170
+ end
171
+ end
172
+
173
+ describe Motor do
174
+ before do
175
+ @default = Motor.new(Environment.new)
176
+ end
177
+
178
+ it "has a throttle with state" do
179
+ expect(@default.throttle).must_equal 0.0
180
+ @default.throttle = 0.5
181
+ expect(@default.throttle).must_equal 0.5
182
+ expect(@default.throttle_pct).must_equal "50.0%"
183
+
184
+ expect { @default.throttle = 1.5 }.must_raise
185
+ end
186
+
187
+ it "has mass" do
188
+ expect(@default.mass).must_be :>, 0
189
+ expect(@default.fixed_mass).must_be :>, 0
190
+ expect(@default.rotating_mass).must_be :>, 0
191
+ end
192
+
193
+ it "has a torque curve" do
194
+ expect(@default.torque_curve).must_be_kind_of TorqueCurve
195
+ end
196
+
197
+ it "has idle RPM and redline RPM" do
198
+ expect(@default.idle).must_be :>, 500
199
+ expect(@default.idle).must_be :<, 1500
200
+
201
+ expect(@default.redline).must_be :>, @default.idle
202
+ expect(@default.redline).must_be :<, 10_000
203
+ end
204
+
205
+ it "has inertia and energy" do
206
+ expect(@default.inertia).must_be :>, 0
207
+ expect(@default.energy(99)).must_be :>, 0
208
+ end
209
+
210
+ it "determines crank alpha from torque" do
211
+ expect(@default.alpha(50)).must_be :>, 0
212
+ end
213
+
214
+ it "determines torque from crank alpha" do
215
+ a = @default.alpha(50, omega: 20)
216
+ t = @default.implied_torque(a)
217
+ # frictional losses
218
+ expect(t).must_be :>, 40
219
+ expect(t).must_be :<, 50
220
+ end
221
+
222
+ it "determines torque based on torque curve, RPM and throttle" do
223
+ @default.throttle = 1.0
224
+ expect(@default.torque(1000)).must_be :>, 0
225
+ expect(@default.torque(3500)).must_be :>, @default.torque(1000)
226
+ end
227
+
228
+ it "has an engine braking effect when the throttle is closed" do
229
+ @default.throttle = 0
230
+ expect(@default.torque(3500)).must_be :<, 0
231
+ end
232
+
233
+ it "has a starter motor to get running" do
234
+ expect(@default.starter_torque).must_be :>, 0
235
+ end
236
+ end
@@ -0,0 +1,21 @@
1
+ require 'minitest/autorun'
2
+ require 'driving_physics/powertrain'
3
+
4
+ include DrivingPhysics
5
+
6
+ describe Powertrain do
7
+ it "has a motor and a gearbox" do
8
+ end
9
+
10
+ it "has mass" do
11
+ end
12
+
13
+ it "coverts rpm to axle torque" do
14
+ end
15
+
16
+ it "converts rpm to axle omega" do
17
+ end
18
+
19
+ it "determines crank rpm from axle_omega" do
20
+ end
21
+ end
data/test/scalar_force.rb CHANGED
@@ -12,8 +12,7 @@ describe ScalarForce do
12
12
  # ROT_COF's value is from observing that rotational resistance
13
13
  # matches air resistance at roughly 30 m/s in street cars
14
14
  it "approximates a reasonable rotational resistance constant" do
15
- expect(30 * ScalarForce.air_resistance(1)).
16
- must_be_within_epsilon(-1 * ROT_COF)
15
+ _(30 * ScalarForce.air_resistance(1)).must_be_within_epsilon(-1 * ROT_COF)
17
16
  end
18
17
 
19
18
  it "approximates a positive drag force" do
@@ -21,12 +20,10 @@ describe ScalarForce do
21
20
  end
22
21
 
23
22
  it "approximates a positive rotational resistance force" do
24
- expect(ScalarForce.rotational_resistance 30).
25
- must_be_within_epsilon(-383.13)
23
+ _(ScalarForce.rotational_resistance 30).must_be_within_epsilon(-383.13)
26
24
  end
27
25
 
28
26
  it "approximates a positive rolling resistance force" do
29
- nf = 1000 * G
30
- expect(ScalarForce.rolling_resistance nf).must_be_within_epsilon(-98.0)
27
+ _(ScalarForce.rolling_resistance(1000 * G)).must_be_within_epsilon(-98.0)
31
28
  end
32
29
  end
data/test/tire.rb CHANGED
@@ -1,128 +1,94 @@
1
1
  require 'minitest/autorun'
2
2
  require 'driving_physics/tire'
3
+ require 'driving_physics/vector_force'
3
4
 
4
- T = DrivingPhysics::Tire
5
+ include DrivingPhysics
5
6
 
6
- describe T do
7
+ describe Tire do
7
8
  describe "Tire.traction" do
8
9
  it "calculates traction force from normal force and coeff of friction" do
9
10
  scalar_nf = 9800 # N
10
11
  cof = 1.1
11
- scalar_t = T.traction(scalar_nf, cof)
12
+ scalar_t = Tire.traction(scalar_nf, cof)
12
13
  expect(scalar_t).must_equal 10780.0
13
14
 
14
- skip # Vector
15
+ skip unless DrivingPhysics.has_vector?
15
16
  vector_nf = Vector[9800, 0]
16
- vector_t = T.traction(vector_nf, cof)
17
+ vector_t = Tire.traction(vector_nf, cof)
17
18
  expect(vector_t).must_equal Vector[10780.0, 0.0]
18
19
  end
19
20
  end
20
21
 
21
22
  describe "Tire.volume" do
22
23
  it "calculates the volume (m^3) of disk given radius and width" do
23
- cubic_m = T.volume(1.0, 1.0)
24
+ cubic_m = Tire.volume(1.0, 1.0)
24
25
  expect(cubic_m).must_equal Math::PI
25
26
 
26
- cubic_m = T.volume(0.35, 0.2)
27
+ cubic_m = Tire.volume(0.35, 0.2)
27
28
  expect(cubic_m).must_be_within_epsilon 0.076969
28
29
  end
29
30
  end
30
31
 
31
32
  describe "Tire.volume_l" do
32
33
  it "calculates the volume (L) of a disk given radius and width" do
33
- liters = T.volume_l(1.0, 1.0)
34
+ liters = Tire.volume_l(1.0, 1.0)
34
35
  expect(liters).must_equal Math::PI * 1000
35
36
 
36
- liters = T.volume_l(0.35, 0.2)
37
+ liters = Tire.volume_l(0.35, 0.2)
37
38
  expect(liters).must_be_within_epsilon 76.96902
38
39
  end
39
40
  end
40
41
 
41
42
  describe "Tire.density" do
42
43
  it "calculates the density (kg/L) given mass and volume" do
43
- expect(T.density(25.0, 25.0)).must_equal 1.0
44
- expect(T.density(50.0, 25.0)).must_equal 2.0
44
+ expect(Tire.density(25.0, 25.0)).must_equal 1.0
45
+ expect(Tire.density(50.0, 25.0)).must_equal 2.0
45
46
  end
46
47
  end
47
48
 
48
49
  describe "Tire.mass" do
49
50
  it "calculates the mass (kg) of a disk given radius, width, and density" do
50
- expect(T.mass(0.35, 0.2, T::DENSITY)).must_be_within_epsilon 25.015
51
+ expect(Tire.mass(0.35, 0.2, Tire::DENSITY)).must_be_within_epsilon 25.015
51
52
  end
52
53
  end
53
54
 
54
55
  describe "Tire.rotational_inertia" do
55
56
  it "calculates rotational inertia for a disk given radius and mass" do
56
- expect(T.rotational_inertia(0.35, 25.0)).must_be_within_epsilon 1.53125
57
+ expect(Tire.rotational_inertia(0.35, 25.0)).must_be_within_epsilon 1.53125
57
58
  end
58
59
  end
59
60
 
60
61
  describe "Tire.alpha" do
61
62
  it "calculates angular acceleration from torque and inertia" do
62
63
  scalar_torque = 1000
63
- inertia = T.rotational_inertia(0.35, 25.0)
64
- expect(T.alpha scalar_torque, inertia).must_be_within_epsilon 653.061
64
+ inertia = Tire.rotational_inertia(0.35, 25.0)
65
+ expect(Tire.alpha scalar_torque, inertia).must_be_within_epsilon 653.061
65
66
 
66
- skip # Vector
67
+ skip unless DrivingPhysics.has_vector?
67
68
  vector_torque = Vector[0, 0, 1000]
68
- vector_alpha = T.alpha vector_torque, inertia
69
+ vector_alpha = Tire.alpha vector_torque, inertia
69
70
  expect(vector_alpha).must_be_instance_of Vector
70
71
  expect(vector_alpha.size).must_equal 3
71
72
  expect(vector_alpha[2]).must_be_within_epsilon 653.06
72
73
  end
73
74
  end
74
75
 
75
- describe "Tire.torque_vector" do
76
- it "calculates a torque in the 3rd dimension given 2D force and radius" do
77
- skip # Vector
78
- force = Vector[1000, 0]
79
- radius = Vector[0, 5]
80
- torque = T.torque_vector(force, radius)
81
- expect(torque).must_be_instance_of Vector
82
- expect(torque.size).must_equal 3
83
- expect(torque[2]).must_be_within_epsilon 5000.0
84
- end
85
- end
86
-
87
- describe "Tire.force_vector" do
88
- it "calculates a (3D) force given 3D torque and 2D radius" do
89
- # let's invert the Tire.torque_vector case from above:
90
- skip # Vector
91
- torque = Vector[0, 0, 5000]
92
- radius = Vector[0, 5]
93
- force = T.force_vector(torque, radius)
94
- expect(force).must_be_instance_of Vector
95
- expect(force.size).must_equal 3
96
- expect(force[0]).must_be_within_epsilon 1000.0
97
-
98
- # now let's rotate the radius into the x-dimension
99
- # right hand rule, positive torque means thumb into screen, clockwise
100
- # negative-x radius means positive-y force
101
- torque = Vector[0, 0, 500]
102
- radius = Vector[-5, 0]
103
- force = T.force_vector(torque, radius)
104
- expect(force).must_be_instance_of Vector
105
- expect(force.size).must_equal 3
106
- expect(force[1]).must_be_within_epsilon 100.0
107
- end
108
- end
109
-
110
76
  describe "instance methods" do
111
77
  before do
112
78
  @env = DrivingPhysics::Environment.new
113
- @tire = T.new(@env)
79
+ @tire = Tire.new(@env)
114
80
  end
115
81
 
116
82
  it "initializes" do
117
- expect(@tire).must_be_instance_of T
118
- expect(@tire.density).must_equal T::DENSITY # sanity check
83
+ expect(@tire).must_be_instance_of Tire
84
+ expect(@tire.density).must_equal Tire::DENSITY # sanity check
119
85
  expect(@tire.mass).must_be_within_epsilon 25.01
120
86
 
121
- with_mass = T.new(@env) { |w|
87
+ with_mass = Tire.new(@env) { |w|
122
88
  w.mass = 99.01
123
89
  }
124
90
  expect(with_mass.mass).must_equal 99.01
125
- expect(with_mass.density).wont_equal T::DENSITY
91
+ expect(with_mass.density).wont_equal Tire::DENSITY
126
92
  end
127
93
 
128
94
  it "has a string representation" do
@@ -158,7 +124,7 @@ describe T do
158
124
  expect(@tire.traction scalar_nf).must_equal 10780.0
159
125
  expect(@tire.traction scalar_nf, static: false).must_equal 6860.0
160
126
 
161
- skip # Vector
127
+ skip unless DrivingPhysics.has_vector?
162
128
  vector_nf = Vector[9800, 0]
163
129
  expect(@tire.traction vector_nf).must_equal Vector[10780.0, 0.0]
164
130
  expect(@tire.traction vector_nf, static: false).
@@ -178,7 +144,7 @@ describe T do
178
144
  expect(kin_tq).must_be_within_epsilon 2401.0
179
145
 
180
146
  # not sure about how torque vectors work, but the "math" "works":
181
- skip # Vector
147
+ skip unless DrivingPhysics.has_vector?
182
148
  vector_nf = Vector[9800, 0]
183
149
  expect(@tire.tractable_torque(vector_nf)[0]).
184
150
  must_be_within_epsilon 3773.0