demo/motor.rb in driving_physics-0.0.1.1 vs demo/motor.rb in driving_physics-0.0.1.2

- old
+ new

@@ -1,29 +1,55 @@ require 'driving_physics/motor' require 'driving_physics/cli' +require 'driving_physics/power' -# fun idea for a different demo: keep increasing torque until idle is -# maintained +# next fun idea: PID controller include DrivingPhysics env = Environment.new motor = Motor.new(env) puts env puts motor +puts puts "Rev it up!" -800.upto(7000) { |rpm| - next unless rpm % 200 == 0 - tq = motor.torque(rpm).to_f - puts format("%s RPM: %s Nm\t%s", - rpm.to_s.rjust(4, ' '), - tq.round(1).to_s.rjust(5, ' '), - '#' * (tq.to_f / 10).round) +motor.throttle = 1.0 +[:torque, :power].each { |run| + puts + puts run.to_s.upcase + ':' + + 800.upto(7000) { |rpm| + next unless rpm % 200 == 0 + omega = DrivingPhysics.omega(rpm) + torque = motor.torque(rpm) + case run + when :torque + count = (torque.to_f / 10).round + char = 'T' + val = torque.round.to_s.rjust(5, ' ') + fmt = "%s Nm" + when :power + power = DrivingPhysics.power(torque, omega) + kw = power.to_f / 1000 + count = (kw / 5).round + char = 'P' + val = kw.round(1).to_s.rjust(5, ' ') + fmt = "%s kW" + else + raise "unknown" + end + puts format("%s RPM: #{fmt}\t%s", + rpm.to_s.rjust(4, ' '), + val, + char * count) + } } puts +puts "Now, the simulation begins..." +puts "---" puts "* Spin the motor up to #{motor.idle_rpm} RPM with the starter motor." puts "* Rev it up with the throttle." puts "* Let it die." CLI.pause @@ -34,16 +60,20 @@ duration = 60 status = :ignition rpm = 0 -(duration * env.hz + 1).times { |i| +paused = 0.0 +num_ticks = duration * env.hz + 1 +start = Timer.now + +num_ticks.times { |i| # this is an input torque; alpha is determined after inertia and friction torque = case status when :ignition motor.starter_torque - when :running + when :running, :off_throttle, :idling motor.torque(rpm) else 0 end @@ -56,34 +86,56 @@ # prevent silly oscillations due to tiny floating point errors omega = 0 if omega < 0.00001 rpm = DrivingPhysics.rpm(omega) + power = DrivingPhysics.power(net_torque, omega) + if rpm > motor.idle_rpm and status == :ignition status = :running flag = true end if rpm > 7000 and status == :running - status = :off + status = :off_throttle + motor.throttle = 0.0 flag = true end + if rpm < 1000 and status == :off_throttle + status = :idling + motor.throttle = 0.06 + flag = true + end + + if status == :idling + if rpm < 999 + motor.throttle += (1.0 - motor.throttle) * 0.005 + elsif rpm > 1001 + motor.throttle -= motor.throttle * 0.005 + end + end + if flag or (i < 10) or (i < 100 and i % 10 == 0) or (i < 1000 and i % 100 == 0) or (i < 10_000 and i % 500 == 0) or - i % 5000 == 0 - puts DrivingPhysics.elapsed_display(i) - puts format("%d RPM %.1f Nm (%d Nm) Friction: %.1f Nm", + (i % 5000 == 0) or + (status == :idling and i % 100 == 0) + puts Timer.display(i) + puts format("Throttle: %.1f%%", motor.throttle * 100) + puts format("%d RPM %.1f Nm (%d Nm) %.1f kW Friction: %.1f Nm", DrivingPhysics.rpm(omega), net_torque, torque, + power / 1000, motor.spinner.rotating_friction(omega)) puts format("%d rad %.1f rad/s %.1f rad/s/s", theta, omega, alpha) puts - CLI.pause if flag + paused += CLI.pause if flag flag = false end } + +puts Timer.summary(start, num_ticks, paused)