grbl-LPC-CoreXY/script/Obsolete/trapezoid_simulator.rb
2013-01-17 23:25:18 -05:00

78 lines
2.9 KiB
Ruby

require 'pp'
def estimate_acceleration_distance(initial_rate, target_rate, acceleration)
(target_rate*target_rate-initial_rate*initial_rate)/(2*acceleration)
end
def intersection_distance(initial_rate, final_rate, acceleration, distance)
(2*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/(4*acceleration)
end
ACCELERATION_TICKS_PER_SECOND = 20
def trapezoid_params(step_event_count, nominal_rate, rate_delta, entry_factor, exit_factor)
initial_rate = (nominal_rate * entry_factor).round
final_rate = (nominal_rate * exit_factor).round
acceleration_per_minute = rate_delta*ACCELERATION_TICKS_PER_SECOND*60
accelerate_steps =
estimate_acceleration_distance(initial_rate, nominal_rate, acceleration_per_minute).round;
decelerate_steps =
estimate_acceleration_distance(nominal_rate, final_rate, -acceleration_per_minute).round;
# Calculate the size of Plateau of Nominal Rate.
plateau_steps = step_event_count-accelerate_steps-decelerate_steps;
# Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will
# have to use intersection_distance() to calculate when to abort acceleration and start braking
# in order to reach the final_rate exactly at the end of this block.
if (plateau_steps < 0)
accelerate_steps =
intersection_distance(initial_rate, final_rate, acceleration_per_minute, step_event_count).round
plateau_steps = 0;
end
accelerate_until = accelerate_steps;
decelerate_after = accelerate_steps+plateau_steps;
{:step_event_count => step_event_count,
:initial_rate => initial_rate,
:final_rate => final_rate,
:nominal_rate => nominal_rate,
:rate_delta => rate_delta,
:accelerate_until => accelerate_until,
:decelerate_after => decelerate_after}
end
def simulate_trapezoid(params)
result = {}
rate = params[:initial_rate]
step_event = 0.0
max_rate = 0
while(step_event < params[:step_event_count]) do
step_events_in_frame = rate/60.0/ACCELERATION_TICKS_PER_SECOND
step_event += step_events_in_frame
max_rate = rate if rate > max_rate
if (step_event < params[:accelerate_until])
rate += params[:rate_delta]
elsif (step_event > params[:decelerate_after])
if rate > params[:final_rate]
rate -= params[:rate_delta]
else
return :underflow_at => step_event, :final_rate => rate, :max_rate => max_rate
end
end
# puts "#{step_event} #{rate}"
end
{:final_rate => rate, :max_rate => max_rate}
end
(10..100).each do |rate|
(1..5).each do |steps|
params = trapezoid_params(steps*1000, rate*100, 10, 0.1, 0.1)
result = simulate_trapezoid(params)
# puts params.inspect
line = "#{steps*10} final: #{result[:final_rate]} == #{params[:final_rate]} peak: #{result[:max_rate]} == #{params[:nominal_rate]} d#{params[:nominal_rate]-result[:max_rate]} "
line << " (underflow at #{result[:underflow_at]})" if result[:underflow_at]
puts line
end
end