Class: DrivingPhysics::Wheel
- Inherits:
-
Object
- Object
- DrivingPhysics::Wheel
- Defined in:
- lib/driving_physics/wheel.rb
Overview
Rotational complements to acc/vel/pos alpha - angular acceleration omega - angular velocity (radians / s) theta - radians
Constant Summary collapse
- DENSITY =
Note, this is not the density of solid rubber. This density yields a sensible mass for a wheel / tire combo at common radius and width, assuming a uniform density e.g. 25kg at 350mm R x 200mm W
0.325
Instance Attribute Summary collapse
-
#density ⇒ Object
readonly
Returns the value of attribute density.
-
#env ⇒ Object
readonly
Returns the value of attribute env.
-
#mu_k ⇒ Object
readonly
Returns the value of attribute mu_k.
-
#mu_s ⇒ Object
readonly
Returns the value of attribute mu_s.
-
#omega_friction ⇒ Object
readonly
Returns the value of attribute omega_friction.
-
#radius ⇒ Object
readonly
Returns the value of attribute radius.
-
#radius_m ⇒ Object
readonly
Returns the value of attribute radius_m.
-
#temp ⇒ Object
readonly
Returns the value of attribute temp.
-
#width ⇒ Object
readonly
Returns the value of attribute width.
-
#width_m ⇒ Object
readonly
Returns the value of attribute width_m.
Class Method Summary collapse
-
.alpha(torque, inertia) ⇒ Object
angular acceleration.
- .density(mass, volume_l) ⇒ Object
- .force(axle_torque, radius_m) ⇒ Object
-
.force_vector(torque, radius) ⇒ Object
vectors only.
- .mass(radius_m, width_m, density) ⇒ Object
-
.moment_of_inertia ⇒ Object
I = 1/2 (m)(r^2) for a disk.
-
.rotational_inertia(radius_m, mass) ⇒ Object
I = 1/2 (m)(r^2) for a disk.
- .tangential(rotational, radius_m) ⇒ Object (also: tangential_a, tangential_v, tangential_p)
-
.torque_vector(force, radius) ⇒ Object
vectors only.
-
.traction(normal_force, cof) ⇒ Object
-
the traction force opposes the axle torque / drive force thus, driving the car forward * if the drive force exceeds the traction force, slippage occurs * slippage reduces the available traction force further * if the drive force is not reduced, the slippage increases until resistance forces equal the drive force.
-
-
.volume(radius_m, width_m) ⇒ Object
in m^3.
-
.volume_l(radius_m, width_m) ⇒ Object
in L.
Instance Method Summary collapse
- #force(axle_torque) ⇒ Object
- #heat!(amount_deg_c) ⇒ Object
-
#inertial_loss(axle_torque, total_driven_mass) ⇒ Object
inertial loss in terms of axle torque when used as a drive wheel.
-
#inertial_torque(alpha) ⇒ Object
how much torque to accelerate rotational inertia at alpha.
-
#initialize(env, radius: 350, width: 200, density: DENSITY, temp: nil, mass: nil, mu_s: 1.1, mu_k: 0.7, omega_friction: 0.002) ⇒ Wheel
constructor
A new instance of Wheel.
- #mass ⇒ Object
- #rotational_inertia ⇒ Object (also: #moment_of_inertia)
- #to_s ⇒ Object
-
#tractable_torque(nf, static: true) ⇒ Object
this doesn’t take inertial losses or internal frictional losses into account.
- #traction(nf, static: true) ⇒ Object
-
#volume ⇒ Object
in m^3.
-
#volume_l ⇒ Object
in L.
- #wear!(amount_mm) ⇒ Object
Constructor Details
#initialize(env, radius: 350, width: 200, density: DENSITY, temp: nil, mass: nil, mu_s: 1.1, mu_k: 0.7, omega_friction: 0.002) ⇒ Wheel
Returns a new instance of Wheel.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/driving_physics/wheel.rb', line 100 def initialize(env, radius: 350, width: 200, density: DENSITY, temp: nil, mass: nil, mu_s: 1.1, mu_k: 0.7, omega_friction: 0.002) @env = env @radius = radius.to_f # mm @radius_m = @radius / 1000 @width = width.to_f # mm @width_m = @width / 1000 @mu_s = mu_s.to_f # static friction @mu_k = mu_k.to_f # kinetic friction @omega_friction = omega_friction # scales with speed @density = mass.nil? ? density : self.class.density(mass, volume_l) @temp = temp.to_f || @env.air_temp end |
Instance Attribute Details
#density ⇒ Object (readonly)
Returns the value of attribute density.
97 98 99 |
# File 'lib/driving_physics/wheel.rb', line 97 def density @density end |
#env ⇒ Object (readonly)
Returns the value of attribute env.
97 98 99 |
# File 'lib/driving_physics/wheel.rb', line 97 def env @env end |
#mu_k ⇒ Object (readonly)
Returns the value of attribute mu_k.
97 98 99 |
# File 'lib/driving_physics/wheel.rb', line 97 def mu_k @mu_k end |
#mu_s ⇒ Object (readonly)
Returns the value of attribute mu_s.
97 98 99 |
# File 'lib/driving_physics/wheel.rb', line 97 def mu_s @mu_s end |
#omega_friction ⇒ Object (readonly)
Returns the value of attribute omega_friction.
97 98 99 |
# File 'lib/driving_physics/wheel.rb', line 97 def omega_friction @omega_friction end |
#radius ⇒ Object (readonly)
Returns the value of attribute radius.
97 98 99 |
# File 'lib/driving_physics/wheel.rb', line 97 def radius @radius end |
#radius_m ⇒ Object (readonly)
Returns the value of attribute radius_m.
97 98 99 |
# File 'lib/driving_physics/wheel.rb', line 97 def radius_m @radius_m end |
#temp ⇒ Object (readonly)
Returns the value of attribute temp.
97 98 99 |
# File 'lib/driving_physics/wheel.rb', line 97 def temp @temp end |
#width ⇒ Object (readonly)
Returns the value of attribute width.
97 98 99 |
# File 'lib/driving_physics/wheel.rb', line 97 def width @width end |
#width_m ⇒ Object (readonly)
Returns the value of attribute width_m.
97 98 99 |
# File 'lib/driving_physics/wheel.rb', line 97 def width_m @width_m end |
Class Method Details
.alpha(torque, inertia) ⇒ Object
angular acceleration
59 60 61 |
# File 'lib/driving_physics/wheel.rb', line 59 def self.alpha(torque, inertia) torque / inertia end |
.density(mass, volume_l) ⇒ Object
42 43 44 |
# File 'lib/driving_physics/wheel.rb', line 42 def self.density(mass, volume_l) mass.to_f / volume_l end |
.force(axle_torque, radius_m) ⇒ Object
28 29 30 |
# File 'lib/driving_physics/wheel.rb', line 28 def self.force(axle_torque, radius_m) axle_torque / radius_m.to_f end |
.force_vector(torque, radius) ⇒ Object
vectors only
86 87 88 89 90 91 92 93 94 95 |
# File 'lib/driving_physics/wheel.rb', line 86 def self.force_vector(torque, radius) if !torque.is_a?(Vector) or torque.size != 3 raise(ArgumentError, "torque must be a 3D vector") end if !radius.is_a?(Vector) or radius.size != 2 raise(ArgumentError, "radius must be a 2D vector") end radius = Vector[radius[0], radius[1], 0] radius.cross(torque) / radius.dot(radius) end |
.mass(radius_m, width_m, density) ⇒ Object
46 47 48 |
# File 'lib/driving_physics/wheel.rb', line 46 def self.mass(radius_m, width_m, density) density * volume_l(radius_m, width_m) end |
.moment_of_inertia ⇒ Object
I = 1/2 (m)(r^2) for a disk
55 56 57 |
# File 'lib/driving_physics/wheel.rb', line 55 def self.rotational_inertia(radius_m, mass) mass * radius_m**2 / 2.0 end |
.rotational_inertia(radius_m, mass) ⇒ Object
I = 1/2 (m)(r^2) for a disk
51 52 53 |
# File 'lib/driving_physics/wheel.rb', line 51 def self.rotational_inertia(radius_m, mass) mass * radius_m**2 / 2.0 end |
.tangential(rotational, radius_m) ⇒ Object Also known as: tangential_a, tangential_v, tangential_p
63 64 65 |
# File 'lib/driving_physics/wheel.rb', line 63 def self.tangential(rotational, radius_m) rotational * radius_m end |
.torque_vector(force, radius) ⇒ Object
vectors only
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/driving_physics/wheel.rb', line 73 def self.torque_vector(force, radius) if !force.is_a?(Vector) or force.size != 2 raise(ArgumentError, "force must be a 2D vector") end if !radius.is_a?(Vector) or radius.size != 2 raise(ArgumentError, "radius must be a 2D vector") end force = Vector[force[0], force[1], 0] radius = Vector[radius[0], radius[1], 0] force.cross(radius) end |
.traction(normal_force, cof) ⇒ Object
-
the traction force opposes the axle torque / drive force thus, driving the car forward
-
if the drive force exceeds the traction force, slippage occurs
-
slippage reduces the available traction force further
-
if the drive force is not reduced, the slippage increases until resistance forces equal the drive force
24 25 26 |
# File 'lib/driving_physics/wheel.rb', line 24 def self.traction(normal_force, cof) normal_force * cof end |
.volume(radius_m, width_m) ⇒ Object
in m^3
33 34 35 |
# File 'lib/driving_physics/wheel.rb', line 33 def self.volume(radius_m, width_m) Math::PI * radius_m ** 2 * width_m.to_f end |
.volume_l(radius_m, width_m) ⇒ Object
in L
38 39 40 |
# File 'lib/driving_physics/wheel.rb', line 38 def self.volume_l(radius_m, width_m) volume(radius_m, width_m) * 1000 end |
Instance Method Details
#force(axle_torque) ⇒ Object
159 160 161 |
# File 'lib/driving_physics/wheel.rb', line 159 def force(axle_torque) self.class.force(axle_torque, @radius_m) end |
#heat!(amount_deg_c) ⇒ Object
132 133 134 |
# File 'lib/driving_physics/wheel.rb', line 132 def heat!(amount_deg_c) @temp += amount_deg_c end |
#inertial_loss(axle_torque, total_driven_mass) ⇒ Object
inertial loss in terms of axle torque when used as a drive wheel
176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/driving_physics/wheel.rb', line 176 def inertial_loss(axle_torque, total_driven_mass) drive_force = self.force(axle_torque) force_loss = 0 # The force loss depends on the acceleration, but the acceleration # depends on the force loss. Converge the value via 5 round trips. # This is a rough way to compute an integral and should be accurate # to 8+ digits. 5.times { acc = DrivingPhysics.acc(drive_force - force_loss, total_driven_mass) alpha = acc / @radius_m force_loss = self.inertial_torque(alpha) / @radius_m } force_loss * @radius_m end |
#inertial_torque(alpha) ⇒ Object
how much torque to accelerate rotational inertia at alpha
164 165 166 |
# File 'lib/driving_physics/wheel.rb', line 164 def inertial_torque(alpha) alpha * self.rotational_inertia end |
#mass ⇒ Object
136 137 138 |
# File 'lib/driving_physics/wheel.rb', line 136 def mass self.class.mass(@radius_m, @width_m, @density) end |
#rotational_inertia ⇒ Object Also known as: moment_of_inertia
150 151 152 |
# File 'lib/driving_physics/wheel.rb', line 150 def rotational_inertia self.class.rotational_inertia(@radius_m, self.mass) end |
#to_s ⇒ Object
117 118 119 120 121 122 123 124 125 |
# File 'lib/driving_physics/wheel.rb', line 117 def to_s [[format("%d mm (R) x %d mm (W)", @radius, @width), format("Mass: %.1f kg %.3f kg/L", self.mass, @density), format("cF: %.1f / %.1f", @mu_s, @mu_k), ].join(" | "), [format("Temp: %.1f C", @temp), ].join(" | "), ].join("\n") end |
#tractable_torque(nf, static: true) ⇒ Object
this doesn’t take inertial losses or internal frictional losses into account. input torque required to saturate traction will be higher than what this method returns
171 172 173 |
# File 'lib/driving_physics/wheel.rb', line 171 def tractable_torque(nf, static: true) traction(nf, static: static) * @radius_m end |
#traction(nf, static: true) ⇒ Object
155 156 157 |
# File 'lib/driving_physics/wheel.rb', line 155 def traction(nf, static: true) self.class.traction(nf, static ? @mu_s : @mu_k) end |
#volume ⇒ Object
in m^3
141 142 143 |
# File 'lib/driving_physics/wheel.rb', line 141 def volume self.class.volume(@radius_m, @width_m) end |
#volume_l ⇒ Object
in L
146 147 148 |
# File 'lib/driving_physics/wheel.rb', line 146 def volume_l self.class.volume_l(@radius_m, @width_m) end |
#wear!(amount_mm) ⇒ Object
127 128 129 130 |
# File 'lib/driving_physics/wheel.rb', line 127 def wear!(amount_mm) @radius -= amount_mm @radius_m = @radius / 1000 end |