driving_physics 0.0.0.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.
data/test/car.rb ADDED
@@ -0,0 +1,156 @@
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
@@ -0,0 +1,29 @@
1
+ require 'minitest/autorun'
2
+ require 'driving_physics'
3
+
4
+ describe DrivingPhysics do
5
+ it "displays elapsed ms in a friendly form" do
6
+ expect(DrivingPhysics.elapsed_display 12572358).must_equal "03:29:32.358"
7
+ end
8
+
9
+ it "calculates kph from m/s" do
10
+ expect(DrivingPhysics.kph 23.2).must_equal 83.52
11
+ end
12
+
13
+ describe "Scalar Physics" do
14
+ # these functions also work with vectors
15
+ it "uses F=ma to calculate acceleration given force and mass" do
16
+ expect(DrivingPhysics.acc 7000, 1000).must_equal 7.0
17
+ end
18
+
19
+ it "calculates a new velocity given acceleration" do
20
+ expect(DrivingPhysics.vel 0.0, 7.0).must_be_within_epsilon 0.007
21
+ expect(DrivingPhysics.vel 1.1, 7.1).must_be_within_epsilon 1.1071
22
+ end
23
+
24
+ it "calculates a new position given velocity" do
25
+ expect(DrivingPhysics.pos 0.0, 3.0).must_be_within_epsilon 0.003
26
+ expect(DrivingPhysics.pos 2.2, 3.5).must_be_within_epsilon 2.2035
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ require 'minitest/autorun'
2
+ require 'driving_physics/scalar_force'
3
+
4
+ include DrivingPhysics
5
+
6
+ describe ScalarForce do
7
+ # i.e. multiply this number times speed^2 to approximate drag force
8
+ it "calculates a reasonable drag constant" do
9
+ expect(ScalarForce.air_resistance 1).must_be_within_epsilon DRAG
10
+ end
11
+
12
+ # ROT_COF's value is from observing that rotational resistance
13
+ # matches air resistance at roughly 30 m/s in street cars
14
+ it "approximates a reasonable rotational resistance constant" do
15
+ expect(30 * ScalarForce.air_resistance(1)).must_be_within_epsilon ROT_COF
16
+ end
17
+
18
+ it "approximates a positive drag force" do
19
+ expect(ScalarForce.air_resistance 30).must_be_within_epsilon 383.13
20
+ end
21
+
22
+ it "approximates a positive rotational resistance force" do
23
+ expect(ScalarForce.rotational_resistance 30).must_be_within_epsilon 383.13
24
+ end
25
+
26
+ it "approximates a positive rolling resistance force" do
27
+ nf = 1000 * G
28
+ expect(ScalarForce.rolling_resistance nf).must_be_within_epsilon 98.0
29
+ end
30
+ end
data/test/tire.rb ADDED
@@ -0,0 +1,125 @@
1
+ require 'driving_physics/tire'
2
+ require 'minitest/autorun'
3
+
4
+ include DrivingPhysics
5
+
6
+ describe Tire do
7
+ TP = Tire::TemperatureProfile
8
+
9
+ describe TP do
10
+ before do
11
+ @tp = TP.new
12
+ end
13
+
14
+ it "initializes with two same-sized arrays" do
15
+ expect(@tp).must_be_kind_of TP
16
+ expect(TP.new([0,1,2,3], [0,1.0,0.7,0.4])).wont_be_nil
17
+ expect { TP.new('', '') }.must_raise ArgumentError
18
+ expect { TP.new([]) }.must_raise ArgumentError
19
+ expect { TP.new([0], []) }.must_raise ArgumentError
20
+ expect { TP.new([], [0.0]) }.must_raise ArgumentError
21
+ end
22
+
23
+ it "determines a grip number from a temp number" do
24
+ { -500 => TP::MIN_GRIP,
25
+ -100 => 0.1,
26
+ -0.0001 => 0.1,
27
+ 0.0 => 0.5
28
+ }.each { |temp, gf| expect(@tp.grip_factor(temp)).must_equal gf }
29
+ end
30
+
31
+ it "has a critical_temp above the temp for 100%" do
32
+ expect(@tp.critical_temp).must_be(:>, 90)
33
+ expect(@tp.critical_temp).must_equal 105
34
+ end
35
+
36
+ it "has a map that increases to 100% and decreases below 80%" do
37
+ expect {
38
+ TP.new([0,1,2,3,4], [0.0,0.1,0.2,0.3,0.4])
39
+ }.must_raise TP::Error
40
+
41
+ expect {
42
+ TP.new([0,1,2,3,4], [0.0, 1.0, 0.99, 0.98, 0.97])
43
+ }.must_raise TP::Error
44
+ end
45
+ end
46
+
47
+ before do
48
+ @t = Tire.new
49
+ end
50
+
51
+ it "initializes with default values without a block" do
52
+ expect(@t).must_be_kind_of Tire
53
+ end
54
+
55
+ it "accepts a block to initialize with custom values" do
56
+ t = Tire.new { |x|
57
+ x.tread_mm = 9999
58
+ x.g_factor = -0.1234
59
+ }
60
+
61
+ expect(t.tread_mm).must_equal 9999
62
+ expect(t.g_factor).must_equal(-0.1234)
63
+ end
64
+
65
+ it "knows when the tread is gone" do
66
+ expect(@t.tread_left?).must_equal true
67
+
68
+ @t.condition.tread_mm = 0.00001
69
+ expect(@t.tread_left?).must_equal true
70
+
71
+ @t.condition.tread_mm = 0.0
72
+ expect(@t.tread_left?).must_equal false
73
+ end
74
+
75
+ it "has 50% grip when down to the cords" do
76
+ expect(@t.tread_factor).must_equal 1.0
77
+
78
+ @t.condition.tread_mm = 0.0
79
+ expect(@t.tread_factor).must_be_within_epsilon 0.5
80
+ end
81
+
82
+ it "has less than 10% tread factor when the cords start to wear" do
83
+ expect(@t.tread_factor).must_equal 1.0
84
+
85
+ @t.condition.tread_mm = 5.0
86
+ expect(@t.tread_factor).must_equal 1.0
87
+
88
+ @t.condition.tread_mm = 0.0
89
+ expect(@t.tread_factor).must_be_within_epsilon 0.5
90
+
91
+ @t.condition.cords_mm = 0.9
92
+ expect(@t.tread_factor).must_be_within_epsilon 0.45
93
+ end
94
+
95
+ it "has decreasing heat cycle factor" do
96
+ expect(@t.condition.heat_cycles).must_equal 0
97
+ expect(@t.heat_cycle_factor).must_equal 1.0
98
+
99
+ @t.condition.heat_cycles = 20
100
+ expect(@t.heat_cycle_factor).must_be(:<, 1.0)
101
+ end
102
+
103
+ it "has a temp factor according to temperature profile" do
104
+ expect(@t.condition.temp_c).must_equal 25
105
+ expect(@t.temp_factor).must_equal 0.75
106
+
107
+ @t.condition.temp_c = 90
108
+ expect(@t.temp_factor).must_equal 1.0
109
+ end
110
+
111
+ it "incorporates temp, heat_cycles, and tread depth into available grip" do
112
+ @t.condition.temp_c = 60
113
+ expect(@t.temp_factor).must_be_within_epsilon 0.8
114
+
115
+ @t.condition.heat_cycles = 10
116
+ expect(@t.heat_cycle_factor).must_be_within_epsilon 0.96
117
+
118
+ @t.condition.tread_mm = 5.0
119
+ expect(@t.tread_factor).must_equal 1.0
120
+ expect(@t.max_g).must_be_within_epsilon 0.768
121
+
122
+ @t.condition.tread_mm = 0.0
123
+ expect(@t.max_g).must_be_within_epsilon 0.384
124
+ end
125
+ end
@@ -0,0 +1,90 @@
1
+ require 'minitest/autorun'
2
+ require 'driving_physics/vector_force'
3
+
4
+ include DrivingPhysics
5
+
6
+ describe VectorForce do
7
+ before do
8
+ @drive_force = Vector[7000.0, 0.0]
9
+ @v = Vector[3.0, 0]
10
+ @mass = 1000
11
+ @weight = @mass * G
12
+ end
13
+
14
+ it "generates uniformly random numbers centered on zero" do
15
+ hsh = {}
16
+ 110_000.times {
17
+ num = DrivingPhysics.random_centered_zero(5)
18
+ hsh[num] ||= 0
19
+ hsh[num] += 1
20
+ }
21
+ # note, this will fail occasionally due to chance
22
+ hsh.values.each { |count|
23
+ expect(count).must_be(:>=, 9000)
24
+ expect(count).must_be(:<=, 11000)
25
+ }
26
+ end
27
+
28
+ it "coerces magnitude=0 to magnitude=1" do
29
+ a = Array.new(999) { DrivingPhysics.random_centered_zero(0) }
30
+ expect(a.all? { |i| i == 0 }).must_equal false
31
+ end
32
+
33
+ it "generates a random unit vector" do
34
+ low_res = DrivingPhysics.random_unit_vector(2, resolution: 1)
35
+ if low_res[0] == 0.0
36
+ expect(low_res[1].abs).must_equal 1.0
37
+ elsif low_res[0].abs == 1.0
38
+ expect(low_res[1]).must_equal 0.0
39
+ elsif low_res[0].abs.round(3) == 0.707
40
+ expect(low_res[1].abs.round(3)) == 0.707
41
+ else
42
+ p low_res
43
+ raise "unexpected"
44
+ end
45
+
46
+ 9.times {
47
+ high_res = DrivingPhysics.random_unit_vector(3, resolution: 9)
48
+ expect(high_res.magnitude).must_be_within_epsilon 1.0
49
+ }
50
+ end
51
+
52
+ it "calculates air resistance as the square of velocity" do
53
+ df = VectorForce.air_resistance(@v,
54
+ frontal_area: 3,
55
+ drag_cof: 0.1,
56
+ air_density: 0.5)
57
+
58
+ # double the velocity, drag force goes up by 4
59
+ df2 = VectorForce.air_resistance(@v * 2,
60
+ frontal_area: 3,
61
+ drag_cof: 0.1,
62
+ air_density: 0.5)
63
+
64
+ expect(df2).must_equal df * 4
65
+ end
66
+
67
+ it "calculates the rolling resistance as a function of the normal force" do
68
+ rr = VectorForce.rolling_resistance(@weight, dir: @v)
69
+
70
+ # double the normal force, rolling resistance goes up by 2 (linear)
71
+ rr2 = VectorForce.rolling_resistance(@weight * 2, dir: @v)
72
+
73
+ expect(rr2).must_equal rr * 2
74
+ end
75
+
76
+ it "calculates the rotational resistance as a function of velocity" do
77
+ rr = VectorForce.rotational_resistance(@v)
78
+ rr2 = VectorForce.rotational_resistance(@v * 2)
79
+ expect(rr2).must_equal rr * 2
80
+ end
81
+
82
+ it "sums resistance forces" do
83
+ rf = VectorForce.all_resistance(@v, dir: @v, nf_mag: @weight)
84
+ # opposite direction
85
+ expect(rf.normalize).must_equal(-1 * @v.normalize)
86
+
87
+ # smaller magnitude
88
+ expect(rf.magnitude).must_be(:<, @drive_force.magnitude)
89
+ end
90
+ end
data/test/wheel.rb ADDED
@@ -0,0 +1,177 @@
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
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: driving_physics
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Rick Hull
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 1980-01-01 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: WIP
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - README.md
20
+ - Rakefile
21
+ - VERSION
22
+ - demo/car.rb
23
+ - demo/scalar_force.rb
24
+ - demo/tire.rb
25
+ - demo/vector_force.rb
26
+ - demo/wheel.rb
27
+ - driving_physics.gemspec
28
+ - lib/driving_physics.rb
29
+ - lib/driving_physics/car.rb
30
+ - lib/driving_physics/environment.rb
31
+ - lib/driving_physics/imperial.rb
32
+ - lib/driving_physics/scalar_force.rb
33
+ - lib/driving_physics/tire.rb
34
+ - lib/driving_physics/vector_force.rb
35
+ - lib/driving_physics/wheel.rb
36
+ - test/car.rb
37
+ - test/driving_physics.rb
38
+ - test/scalar_force.rb
39
+ - test/tire.rb
40
+ - test/vector_force.rb
41
+ - test/wheel.rb
42
+ homepage: https://github.com/rickhull/driving_physics
43
+ licenses:
44
+ - LGPL-3.0
45
+ metadata: {}
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">"
53
+ - !ruby/object:Gem::Version
54
+ version: '2'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubygems_version: 3.2.26
62
+ signing_key:
63
+ specification_version: 4
64
+ summary: WIP
65
+ test_files: []