001package jmri.jmrit.logix; 002 003import java.util.ArrayList; 004import java.util.ListIterator; 005 006/** 007 * This class holds a list of throttle setting to make a smooth acceleration or 008 * deceleration. It supplies iterators to cycle through the settings. 009 * Used when speed changes are called for by signaled speeds, block speed limits 010 * or user controls for speed halts and resumes. Also used to make NXWarrants. 011 * 012 * @author Pete Cressman Copyright (C) 2019 013*/ 014 015public class RampData { 016 017 private final int _timeInterval; 018 private final float _throttleInterval; 019 private ArrayList<Float> _settings; 020 private boolean _upRamp; 021 private final SpeedUtil _speedUtil; 022 private final float _fromSpeed; 023 private final float _toSpeed; 024 025 private static final float INCRE_RATE = 1.085f; // multiplier to increase throttle increments 026 027 RampData(SpeedUtil util, float throttleIncre, int timeIncre, float fromSet, float toSet) { 028 _throttleInterval = throttleIncre; 029 _timeInterval = timeIncre; 030 _speedUtil = util; 031 _fromSpeed = fromSet; 032 _toSpeed = toSet; 033 makeThrottleSettings(); 034 } 035 036 protected boolean isUpRamp() { 037 return _upRamp; 038 } 039 040 private void makeThrottleSettings() { 041 _upRamp = (_toSpeed >= _fromSpeed); 042 _settings = new ArrayList<>(); 043 float lowSetting; 044 float highSetting; 045 float momentumTime; 046 if (_upRamp) { 047 lowSetting = _fromSpeed; 048 highSetting = _toSpeed; 049 } else { 050 lowSetting = _toSpeed; 051 highSetting = _fromSpeed; 052 } 053 float low = 0.0f; 054 float throttleIncre = _throttleInterval; 055 while (low < lowSetting ) { 056 throttleIncre *= INCRE_RATE; 057 low += throttleIncre; 058 } 059 _settings.add(lowSetting); 060 lowSetting += throttleIncre; 061 while (lowSetting < highSetting) { 062 _settings.add(lowSetting); 063 momentumTime = _speedUtil.getMomentumTime(lowSetting, lowSetting + throttleIncre*INCRE_RATE); 064 if (momentumTime <= _timeInterval) { 065 throttleIncre *= INCRE_RATE; 066 } // if time of momentum change exceeds _throttleInterval, don't increase throttleIncre 067 lowSetting += throttleIncre; 068 } 069 _settings.add(highSetting); 070 } 071 072 protected float getRampLength() { 073 float rampLength = 0; 074 float nextSetting; 075 float prevSetting; 076 float momentumTime = 0; 077 float dist; 078 if (_upRamp) { 079 ListIterator<Float> iter = speedIterator(true); 080 prevSetting = iter.next(); // first setting is current speed 081 nextSetting = prevSetting; 082 while (iter.hasNext()) { 083 nextSetting = iter.next(); 084 dist = _speedUtil.getDistanceOfSpeedChange(prevSetting, nextSetting, _timeInterval); 085 rampLength += dist; 086 momentumTime = _speedUtil.getMomentumTime(prevSetting, nextSetting); 087 prevSetting = nextSetting; 088 } 089 } else { 090 ListIterator<Float> iter = speedIterator(false); 091 prevSetting = iter.previous(); // first setting is current speed 092 nextSetting = prevSetting; 093 while (iter.hasPrevious()) { 094 nextSetting = iter.previous(); 095 dist = _speedUtil.getDistanceOfSpeedChange(prevSetting, nextSetting, _timeInterval); 096 rampLength += dist; 097 momentumTime = _speedUtil.getMomentumTime(prevSetting, nextSetting); 098 prevSetting = nextSetting; 099 } 100 } 101 // distance of the last speed increment is only distance needed for momentum. 102 // _speedUtil.getDistanceOfSpeedChange will not return a distance greater than that needed by momentum 103 if (_timeInterval > momentumTime) { 104 rampLength -= _speedUtil.getTrackSpeed(nextSetting) * (_timeInterval - momentumTime); 105 } 106 return rampLength; 107 } 108 109 protected int getNumSteps() { 110 return _settings.size() - 1; 111 } 112 113 protected int getRamptime() { 114 return (_settings.size() - 1) * _timeInterval; 115 } 116 117 protected float getMaxSpeed() { 118 if (_settings == null) { 119 throw new IllegalArgumentException("Null array of throttle settings"); 120 } 121 return _settings.get(_settings.size() - 1); 122 } 123 124 protected ListIterator<Float> speedIterator(boolean up) { 125 if (up) { 126 return _settings.listIterator(0); 127 } else { 128 return _settings.listIterator(_settings.size()); 129 130 } 131 } 132 133 protected int getRampTimeIncrement() { 134 return _timeInterval; 135 } 136 137// private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RampData.class); 138}