driving_physics 0.0.1.2 → 0.0.3.1
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 +23 -1
- data/Rakefile +84 -0
- data/VERSION +1 -1
- data/demo/car.rb +85 -72
- data/demo/gearbox.rb +4 -3
- data/demo/motor.rb +12 -10
- data/demo/mruby/car.rb +184 -0
- data/demo/mruby/motor.rb +140 -0
- data/demo/pid_controller.rb +143 -0
- data/demo/powertrain.rb +1 -1
- data/driving_physics.gemspec +2 -1
- data/lib/driving_physics/car.rb +14 -5
- data/lib/driving_physics/cli.rb +7 -35
- data/lib/driving_physics/cockpit.rb +167 -0
- data/lib/driving_physics/disk.rb +10 -30
- data/lib/driving_physics/environment.rb +2 -0
- data/lib/driving_physics/gearbox.rb +62 -32
- data/lib/driving_physics/motor.rb +218 -63
- data/lib/driving_physics/mruby.rb +48 -0
- data/lib/driving_physics/pid_controller.rb +111 -0
- data/lib/driving_physics/powertrain.rb +8 -13
- data/lib/driving_physics/scalar_force.rb +2 -1
- data/lib/driving_physics/timer.rb +34 -0
- data/lib/driving_physics/tire.rb +6 -6
- data/lib/driving_physics/vector_force.rb +23 -0
- data/lib/driving_physics.rb +28 -22
- data/test/disk.rb +23 -59
- data/test/gearbox.rb +36 -0
- data/test/motor.rb +236 -0
- data/test/powertrain.rb +21 -0
- data/test/scalar_force.rb +3 -6
- data/test/tire.rb +25 -53
- data/test/vector_force.rb +76 -37
- metadata +28 -4
data/test/tire.rb
CHANGED
@@ -1,124 +1,94 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
2
|
require 'driving_physics/tire'
|
3
|
+
require 'driving_physics/vector_force'
|
3
4
|
|
4
|
-
|
5
|
+
include DrivingPhysics
|
5
6
|
|
6
|
-
describe
|
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 =
|
12
|
+
scalar_t = Tire.traction(scalar_nf, cof)
|
12
13
|
expect(scalar_t).must_equal 10780.0
|
13
14
|
|
15
|
+
skip unless DrivingPhysics.has_vector?
|
14
16
|
vector_nf = Vector[9800, 0]
|
15
|
-
vector_t =
|
17
|
+
vector_t = Tire.traction(vector_nf, cof)
|
16
18
|
expect(vector_t).must_equal Vector[10780.0, 0.0]
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
22
|
describe "Tire.volume" do
|
21
23
|
it "calculates the volume (m^3) of disk given radius and width" do
|
22
|
-
cubic_m =
|
24
|
+
cubic_m = Tire.volume(1.0, 1.0)
|
23
25
|
expect(cubic_m).must_equal Math::PI
|
24
26
|
|
25
|
-
cubic_m =
|
27
|
+
cubic_m = Tire.volume(0.35, 0.2)
|
26
28
|
expect(cubic_m).must_be_within_epsilon 0.076969
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
32
|
describe "Tire.volume_l" do
|
31
33
|
it "calculates the volume (L) of a disk given radius and width" do
|
32
|
-
liters =
|
34
|
+
liters = Tire.volume_l(1.0, 1.0)
|
33
35
|
expect(liters).must_equal Math::PI * 1000
|
34
36
|
|
35
|
-
liters =
|
37
|
+
liters = Tire.volume_l(0.35, 0.2)
|
36
38
|
expect(liters).must_be_within_epsilon 76.96902
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
42
|
describe "Tire.density" do
|
41
43
|
it "calculates the density (kg/L) given mass and volume" do
|
42
|
-
expect(
|
43
|
-
expect(
|
44
|
+
expect(Tire.density(25.0, 25.0)).must_equal 1.0
|
45
|
+
expect(Tire.density(50.0, 25.0)).must_equal 2.0
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
47
49
|
describe "Tire.mass" do
|
48
50
|
it "calculates the mass (kg) of a disk given radius, width, and density" do
|
49
|
-
expect(
|
51
|
+
expect(Tire.mass(0.35, 0.2, Tire::DENSITY)).must_be_within_epsilon 25.015
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
53
55
|
describe "Tire.rotational_inertia" do
|
54
56
|
it "calculates rotational inertia for a disk given radius and mass" do
|
55
|
-
expect(
|
57
|
+
expect(Tire.rotational_inertia(0.35, 25.0)).must_be_within_epsilon 1.53125
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
61
|
describe "Tire.alpha" do
|
60
62
|
it "calculates angular acceleration from torque and inertia" do
|
61
63
|
scalar_torque = 1000
|
62
|
-
inertia =
|
63
|
-
expect(
|
64
|
+
inertia = Tire.rotational_inertia(0.35, 25.0)
|
65
|
+
expect(Tire.alpha scalar_torque, inertia).must_be_within_epsilon 653.061
|
64
66
|
|
67
|
+
skip unless DrivingPhysics.has_vector?
|
65
68
|
vector_torque = Vector[0, 0, 1000]
|
66
|
-
vector_alpha =
|
69
|
+
vector_alpha = Tire.alpha vector_torque, inertia
|
67
70
|
expect(vector_alpha).must_be_instance_of Vector
|
68
71
|
expect(vector_alpha.size).must_equal 3
|
69
72
|
expect(vector_alpha[2]).must_be_within_epsilon 653.06
|
70
73
|
end
|
71
74
|
end
|
72
75
|
|
73
|
-
describe "Tire.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 = T.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 "Tire.force_vector" do
|
85
|
-
it "calculates a (3D) force given 3D torque and 2D radius" do
|
86
|
-
# let's invert the Tire.torque_vector case from above:
|
87
|
-
torque = Vector[0, 0, 5000]
|
88
|
-
radius = Vector[0, 5]
|
89
|
-
force = T.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 = T.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
76
|
describe "instance methods" do
|
107
77
|
before do
|
108
78
|
@env = DrivingPhysics::Environment.new
|
109
|
-
@tire =
|
79
|
+
@tire = Tire.new(@env)
|
110
80
|
end
|
111
81
|
|
112
82
|
it "initializes" do
|
113
|
-
expect(@tire).must_be_instance_of
|
114
|
-
expect(@tire.density).must_equal
|
83
|
+
expect(@tire).must_be_instance_of Tire
|
84
|
+
expect(@tire.density).must_equal Tire::DENSITY # sanity check
|
115
85
|
expect(@tire.mass).must_be_within_epsilon 25.01
|
116
86
|
|
117
|
-
with_mass =
|
87
|
+
with_mass = Tire.new(@env) { |w|
|
118
88
|
w.mass = 99.01
|
119
89
|
}
|
120
90
|
expect(with_mass.mass).must_equal 99.01
|
121
|
-
expect(with_mass.density).wont_equal
|
91
|
+
expect(with_mass.density).wont_equal Tire::DENSITY
|
122
92
|
end
|
123
93
|
|
124
94
|
it "has a string representation" do
|
@@ -154,6 +124,7 @@ describe T do
|
|
154
124
|
expect(@tire.traction scalar_nf).must_equal 10780.0
|
155
125
|
expect(@tire.traction scalar_nf, static: false).must_equal 6860.0
|
156
126
|
|
127
|
+
skip unless DrivingPhysics.has_vector?
|
157
128
|
vector_nf = Vector[9800, 0]
|
158
129
|
expect(@tire.traction vector_nf).must_equal Vector[10780.0, 0.0]
|
159
130
|
expect(@tire.traction vector_nf, static: false).
|
@@ -173,6 +144,7 @@ describe T do
|
|
173
144
|
expect(kin_tq).must_be_within_epsilon 2401.0
|
174
145
|
|
175
146
|
# not sure about how torque vectors work, but the "math" "works":
|
147
|
+
skip unless DrivingPhysics.has_vector?
|
176
148
|
vector_nf = Vector[9800, 0]
|
177
149
|
expect(@tire.tractable_torque(vector_nf)[0]).
|
178
150
|
must_be_within_epsilon 3773.0
|
data/test/vector_force.rb
CHANGED
@@ -1,52 +1,91 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
2
|
require 'driving_physics/vector_force'
|
3
3
|
|
4
|
-
|
4
|
+
describe DrivingPhysics do
|
5
|
+
describe "random_centered_zero" do
|
6
|
+
it "generates uniformly random numbers centered on zero" do
|
7
|
+
hsh = {}
|
8
|
+
110_000.times {
|
9
|
+
num = DrivingPhysics.random_centered_zero(5)
|
10
|
+
hsh[num] ||= 0
|
11
|
+
hsh[num] += 1
|
12
|
+
}
|
13
|
+
# note, this will fail occasionally due to chance
|
14
|
+
hsh.values.each { |count|
|
15
|
+
expect(count).must_be(:>=, 9000)
|
16
|
+
expect(count).must_be(:<=, 11000)
|
17
|
+
}
|
18
|
+
end
|
5
19
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@mass = 1000
|
11
|
-
@weight = @mass * G
|
20
|
+
it "coerces magnitude=0 to magnitude=1" do
|
21
|
+
a = Array.new(999) { DrivingPhysics.random_centered_zero(0) }
|
22
|
+
expect(a.all? { |i| i == 0 }).must_equal false
|
23
|
+
end
|
12
24
|
end
|
13
25
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
+
describe "random_unit_vector" do
|
27
|
+
it "generates a random unit vector" do
|
28
|
+
low_res = DrivingPhysics.random_unit_vector(2, resolution: 1)
|
29
|
+
if low_res[0] == 0.0
|
30
|
+
expect(low_res[1].abs).must_equal 1.0
|
31
|
+
elsif low_res[0].abs == 1.0
|
32
|
+
expect(low_res[1]).must_equal 0.0
|
33
|
+
elsif low_res[0].abs.round(3) == 0.707
|
34
|
+
expect(low_res[1].abs.round(3)) == 0.707
|
35
|
+
else
|
36
|
+
p low_res
|
37
|
+
raise "unexpected"
|
38
|
+
end
|
39
|
+
|
40
|
+
9.times {
|
41
|
+
high_res = DrivingPhysics.random_unit_vector(3, resolution: 9)
|
42
|
+
expect(high_res.magnitude).must_be_within_epsilon 1.0
|
43
|
+
}
|
44
|
+
end
|
26
45
|
end
|
27
46
|
|
28
|
-
|
29
|
-
a
|
30
|
-
|
47
|
+
describe "torque_vector" do
|
48
|
+
it "calculates a torque in the 3rd dimension given 2D force and radius" do
|
49
|
+
force = Vector[1000, 0]
|
50
|
+
radius = Vector[0, 5]
|
51
|
+
torque = DrivingPhysics.torque_vector(force, radius)
|
52
|
+
expect(torque).must_be_instance_of Vector
|
53
|
+
expect(torque.size).must_equal 3
|
54
|
+
expect(torque[2]).must_be_within_epsilon 5000.0
|
55
|
+
end
|
31
56
|
end
|
32
57
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
expect(
|
41
|
-
|
42
|
-
|
43
|
-
|
58
|
+
describe "force_vector" do
|
59
|
+
it "calculates a (3D) force given 3D torque and 2D radius" do
|
60
|
+
# let's invert the DrivingPhysics.torque_vector case from above:
|
61
|
+
torque = Vector[0, 0, 5000]
|
62
|
+
radius = Vector[0, 5]
|
63
|
+
force = DrivingPhysics.force_vector(torque, radius)
|
64
|
+
expect(force).must_be_instance_of Vector
|
65
|
+
expect(force.size).must_equal 3
|
66
|
+
expect(force[0]).must_be_within_epsilon 1000.0
|
67
|
+
|
68
|
+
# now let's rotate the radius into the x-dimension
|
69
|
+
# right hand rule, positive torque means thumb into screen, clockwise
|
70
|
+
# negative-x radius means positive-y force
|
71
|
+
torque = Vector[0, 0, 500]
|
72
|
+
radius = Vector[-5, 0]
|
73
|
+
force = DrivingPhysics.force_vector(torque, radius)
|
74
|
+
expect(force).must_be_instance_of Vector
|
75
|
+
expect(force.size).must_equal 3
|
76
|
+
expect(force[1]).must_be_within_epsilon 100.0
|
44
77
|
end
|
78
|
+
end
|
79
|
+
end
|
45
80
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
81
|
+
include DrivingPhysics
|
82
|
+
|
83
|
+
describe VectorForce do
|
84
|
+
before do
|
85
|
+
@drive_force = Vector[7000.0, 0.0]
|
86
|
+
@v = Vector[3.0, 0]
|
87
|
+
@mass = 1000
|
88
|
+
@weight = @mass * G
|
50
89
|
end
|
51
90
|
|
52
91
|
it "calculates air resistance as the square of velocity" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: driving_physics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1
|
4
|
+
version: 0.0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rick Hull
|
@@ -9,7 +9,21 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 1980-01-01 00:00:00.000000000 Z
|
12
|
-
dependencies:
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: device_control
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.3'
|
13
27
|
description: WIP
|
14
28
|
email:
|
15
29
|
executables: []
|
@@ -23,6 +37,9 @@ files:
|
|
23
37
|
- demo/disk.rb
|
24
38
|
- demo/gearbox.rb
|
25
39
|
- demo/motor.rb
|
40
|
+
- demo/mruby/car.rb
|
41
|
+
- demo/mruby/motor.rb
|
42
|
+
- demo/pid_controller.rb
|
26
43
|
- demo/powertrain.rb
|
27
44
|
- demo/scalar_force.rb
|
28
45
|
- demo/tire.rb
|
@@ -31,18 +48,25 @@ files:
|
|
31
48
|
- lib/driving_physics.rb
|
32
49
|
- lib/driving_physics/car.rb
|
33
50
|
- lib/driving_physics/cli.rb
|
51
|
+
- lib/driving_physics/cockpit.rb
|
34
52
|
- lib/driving_physics/disk.rb
|
35
53
|
- lib/driving_physics/environment.rb
|
36
54
|
- lib/driving_physics/gearbox.rb
|
37
55
|
- lib/driving_physics/imperial.rb
|
38
56
|
- lib/driving_physics/motor.rb
|
57
|
+
- lib/driving_physics/mruby.rb
|
58
|
+
- lib/driving_physics/pid_controller.rb
|
39
59
|
- lib/driving_physics/power.rb
|
40
60
|
- lib/driving_physics/powertrain.rb
|
41
61
|
- lib/driving_physics/scalar_force.rb
|
62
|
+
- lib/driving_physics/timer.rb
|
42
63
|
- lib/driving_physics/tire.rb
|
43
64
|
- lib/driving_physics/vector_force.rb
|
44
65
|
- test/disk.rb
|
45
66
|
- test/driving_physics.rb
|
67
|
+
- test/gearbox.rb
|
68
|
+
- test/motor.rb
|
69
|
+
- test/powertrain.rb
|
46
70
|
- test/scalar_force.rb
|
47
71
|
- test/tire.rb
|
48
72
|
- test/vector_force.rb
|
@@ -65,8 +89,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
89
|
- !ruby/object:Gem::Version
|
66
90
|
version: '0'
|
67
91
|
requirements: []
|
68
|
-
rubygems_version: 3.
|
92
|
+
rubygems_version: 3.4.4
|
69
93
|
signing_key:
|
70
94
|
specification_version: 4
|
71
|
-
summary:
|
95
|
+
summary: 'Physics from first principles: mass, friction, rotation, etc'
|
72
96
|
test_files: []
|