TransportDelay.java
/*
* Created on 2007/04/16
* Copyright (C) 2007 Koga Laboratory. All rights reserved.
*
*/
package org.mklab.tool.control.system.continuous;
import java.util.ArrayDeque;
import java.util.Deque;
import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.ode.EquationSolver;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.tool.control.system.parameter.Parameter;
import org.mklab.tool.control.system.parameter.ParameterUpdator;
import org.mklab.tool.control.system.parameter.SIunit;
import org.mklab.tool.control.system.parameter.StringExternalizable;
/**
* 入力を遅延させるシステム(無駄時間システム)を表わすクラスです。
*
* @author koga
* @version $Revision: 1.18 $, 2007/04/16
* @param <RS> type of real scalar
* @param <RM> type of real matrix
* @param <CS> type of complex scalar
* @param <CM> type of complex matrix
*/
public class TransportDelay<RS extends RealNumericalScalar<RS,RM,CS,CM>, RM extends RealNumericalMatrix<RS,RM,CS,CM>, CS extends ComplexNumericalScalar<RS,RM,CS,CM>, CM extends ComplexNumericalMatrix<RS,RM,CS,CM>> extends BaseContinuousStaticSystem<RS,RM,CS,CM> implements ParameterUpdator, StringExternalizable {
/** 無駄時間 */
@Parameter(name = "timeDelay", unit = SIunit.s, description = "TransportDelay.1", internationalization = true)
private RS timeDelay =this.sunit.create(1);
/** 初期出力 */
@Parameter(name = "initialOutput", description = "TransportDelay.3", update = true, internationalization = true)
private RM initialOutput = this.sunit.createZeroGrid(1, 1);
/** 初期バッファサイズ */
@Parameter(name = "initialBufferSize", description = "TransportDelay.5", internationalization = true)
private int initialBufferSize = 1024;
/** 時刻のキュー */
private Deque<RS> timeQue;
/** 入力のキュー */
private Deque<RM> inputQue;
/**
* 新しく生成された<code>TransportDelay</code>オブジェクトを初期化します。
* @param sunit unit of scalar
*/
public TransportDelay(RS sunit) {
this(sunit.create(1), sunit);
}
/**
* 新しく生成された<code>TransportDelay</code>オブジェクトを初期化します。
*
* @param timeDelay 無駄時間
* @param sunit unit of scalar
*/
public TransportDelay(final RS timeDelay, RS sunit) {
super(-1, -1, sunit);
setAutoSize(true);
setHasDirectFeedthrough(true);
this.timeDelay = timeDelay;
initialize();
}
/**
* 新しく生成された<code>TransportDelay</code>オブジェクトを初期化します。
*
* @param timeDelay 無駄時間
* @param initialOutput 初期出力
* @param sunit unit of scalar
*/
public TransportDelay(final RS timeDelay, final RM initialOutput, RS sunit) {
super(initialOutput.getRowSize(), initialOutput.getRowSize(), sunit);
setHasDirectFeedthrough(true);
this.timeDelay = timeDelay;
this.initialOutput = initialOutput.createClone();
initialize();
}
/**
* @see org.mklab.tool.control.system.continuous.BaseContinuousStaticSystem#initialize()
*/
@Override
public void initialize() {
this.timeQue = new ArrayDeque<>(this.initialBufferSize);
this.inputQue = new ArrayDeque<>(this.initialBufferSize);
}
/**
* {@inheritDoc}
*/
@Override
public RM outputEquation(final RS t, final RM u) {
final int dataSize = this.timeQue.size();
if (EquationSolver.isTrial() == false) {
if (dataSize == 0 || this.timeQue.getLast() != t) {
this.timeQue.add(t);
this.inputQue.add(u);
}
}
if (t.isLessThan(this.timeDelay) || dataSize == 0) {
return this.initialOutput.createClone();
}
final RS delayPoint = t.subtract(this.timeDelay);
if (dataSize == 1) {
final RS t2 = this.timeQue.getLast();
final RS t1 = this.sunit.create(0);
final RM u2 = this.inputQue.getLast();
final RM u1 = this.initialOutput;
return u2.subtract(u2.subtract(u1).multiply((delayPoint.subtract(t1)).divide((t2.subtract(t1)))));
}
if (this.timeQue.getLast().isLessThan(delayPoint)) {
final RS t2 = this.timeQue.pollLast();
final RS t1 = this.timeQue.pollLast();
final RM u2 = this.inputQue.pollLast();
final RM u1 = this.inputQue.pollLast();
this.timeQue.add(t1);
this.timeQue.add(t2);
this.inputQue.add(u1);
this.inputQue.add(u2);
return u1.add(u2.subtract(u1).multiply((delayPoint.subtract(t1)).divide((t2.subtract(t1)))));
}
RS t1 = this.timeQue.pollFirst();
RM u1 = this.inputQue.pollFirst();
for (int i = 0; i < dataSize; i++) {
RS t2 = this.timeQue.pollFirst();
final RM u2 = this.inputQue.pollFirst();
if (t2.isLessThan(delayPoint)) {
t1 = t2;
u1 = u2;
continue;
}
this.timeQue.addFirst(t2);
this.timeQue.addFirst(t1);
this.inputQue.addFirst(u2);
this.inputQue.addFirst(u1);
return u1.add(u2.subtract(u1).multiply((delayPoint.subtract(t1)).divide((t2.subtract(t1)))));
}
assert false : "never reached"; //$NON-NLS-1$
return this.initialOutput;
}
/**
* 無駄時間を設定します。
*
* @param timeDelay 無駄時間
*/
public void setTimeDelay(final RS timeDelay) {
this.timeDelay = timeDelay;
}
/**
* 無駄時間を返します。
*
* @return 無駄時間
*/
public RS getTimeDelay() {
return this.timeDelay;
}
/**
* 初期出力を設定します。
*
* @param initialOutput 初期出力
*/
public void setInitialOutput(final RM initialOutput) {
this.initialOutput = initialOutput.createClone();
final int size = initialOutput.getRowSize();
if (getInputSize() != size) {
super.setInputSize(size);
}
if (getOutputSize() != size) {
super.setOutputSize(size);
}
}
/**
* @see org.mklab.tool.control.system.SystemOperator#setInputSize(int)
*/
@Override
public void setInputSize(final int inputSize) {
if (inputSize != -1) {
super.setOutputSize(inputSize);
if (this.initialOutput == null || this.initialOutput.length() != inputSize) {
setInitialOutput(this.sunit.createZeroGrid(inputSize, 1));
}
}
super.setInputSize(inputSize);
}
/**
* @see org.mklab.tool.control.system.SystemOperator#setOutputSize(int)
*/
@Override
public void setOutputSize(final int outputSize) {
if (outputSize != -1) {
super.setInputSize(outputSize);
if (this.initialOutput == null || this.initialOutput.length() != outputSize) {
setInitialOutput(this.sunit.createZeroGrid(outputSize, 1));
}
}
super.setOutputSize(outputSize);
}
/**
* 初期出力を返します。
*
* @return 初期出力
*/
public RM getInitialOutput() {
return this.initialOutput.createClone();
}
/**
* 初期バッファサイズを設定します。
*
* @param initialBufferSize 初期バッファサイズ
*/
public void setInitialBufferSize(final int initialBufferSize) {
this.initialBufferSize = initialBufferSize;
}
/**
* 初期バッファサイズを返します。
*
* @return 初期バッファサイズ
*/
public int getInitialBufferSize() {
return this.initialBufferSize;
}
/**
* @see org.mklab.tool.control.system.parameter.ParameterUpdator#updateWith(java.lang.String)
*/
public boolean updateWith(String parameter) {
if (parameter.equals("initialOutput")) { //$NON-NLS-1$
final int size = this.initialOutput.getRowSize();
setInputSize(size);
setOutputSize(size);
return true;
}
return false;
}
/**
* @see org.mklab.tool.control.system.parameter.StringExternalizable#getString(java.lang.String)
*/
public String getString(String key) {
return Messages.getString(key);
}
/**
* @see org.mklab.tool.control.system.SystemOperator#equals(java.lang.Object)
*/
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!super.equals(o)) {
return false;
}
if (o == null) {
return false;
}
if (o.getClass() != getClass()) {
return false;
}
final TransportDelay<RS,RM,CS,CM> castedObj = (TransportDelay<RS,RM,CS,CM>)o;
return ((this.timeDelay == castedObj.timeDelay) && (this.initialOutput == null ? castedObj.initialOutput == null : this.initialOutput.equals(castedObj.initialOutput))
&& (this.initialBufferSize == castedObj.initialBufferSize) && (this.timeQue == null ? castedObj.timeQue == null : this.timeQue.equals(castedObj.timeQue)) && (this.inputQue == null
? castedObj.inputQue == null : this.inputQue.equals(castedObj.inputQue)));
}
/**
* @see org.mklab.tool.control.system.SystemOperator#hashCode()
*/
@Override
public int hashCode() {
int hashCode = super.hashCode();
hashCode = 31 * hashCode + (this.timeDelay.hashCode() ^ (this.timeDelay.hashCode() >>> 32));
hashCode = 31 * hashCode + (this.initialOutput == null ? 0 : this.initialOutput.hashCode());
hashCode = 31 * hashCode + this.initialBufferSize;
hashCode = 31 * hashCode + (this.timeQue == null ? 0 : this.timeQue.hashCode());
hashCode = 31 * hashCode + (this.inputQue == null ? 0 : this.inputQue.hashCode());
return hashCode;
}
}