DiscreteObserverDesigner.java

/*
 * $Id: DiscreteObserverDesigner.java,v 1.4 2008/03/30 00:30:47 koga Exp $
 *
 * Copyright (C) 2004 Koga Laboratory. All rights reserved.
 *
 */
package org.mklab.tool.control.system.controller;

import java.util.List;

import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.tool.control.C2d;
import org.mklab.tool.control.system.LinearSystemOperator;
import org.mklab.tool.control.system.discrete.DiscreteLinearDynamicSystem;


/**
 * 連続時間オブザーバを離散化した離散時間オブザーバを求めるクラスです。
 * 
 * @author koga
 * @version $Revision: 1.4 $, 2004/05/31
 * @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 DiscreteObserverDesigner<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>> {

  /** サンプリング周期[s] */
  private RS samplingInterval;
  /** 連続時間オブザーバーの設計器 */
  private ObserverDesigner<RS,RM,CS,CM> observerDesigner;
  /** サンプリング周期が設定済みならばtrue、そうでなければfalse */
  private boolean samplingIntervalAvailable;
  /** 離散時間オブザーバー */
  private DiscreteLinearDynamicSystem<RS,RM,CS,CM> observer;
  
  /** unit of scalar */
  private RS sunit;

  /**
   * コンストラクター
   * 
   * @param plant 状態推定の対象(連続時間線形システム)
   */
  public DiscreteObserverDesigner(LinearSystemOperator<RS,RM,CS,CM> plant) {
    this.sunit = plant.getA().getElement(1,1).createUnit();
    this.observerDesigner = new ObserverDesigner<>(plant);
  }

  /**
   * 離散時間オブザーバを返します。
   * 
   * @return 離散時間オブザーバ
   */
  public DiscreteLinearDynamicSystem<RS,RM,CS,CM> getObserver() {
    design();
    return this.observer;
  }

  /**
   * 連続時間オブザーバを離散化した離散時間オブザーバを求めます。
   */
  private void design() {
    final LinearSystemOperator<RS,RM,CS,CM> cObserver = this.observerDesigner.getObserver();
    final List<RM> ab = C2d.c2d(cObserver.getA(), cObserver.getB(), this.samplingInterval);
    this.observer = new DiscreteLinearDynamicSystem<>(ab.get(0), ab.get(1), cObserver.getC(), cObserver.getD(), this.sunit);
    this.observer.setSamplingInterval(this.samplingInterval);
  }

  /**
   * サンプリング周期を設定します。
   * 
   * @param samplingInterval サンプリング周期
   */
  public void setSamplingInterval(RS samplingInterval) {
    this.samplingInterval = samplingInterval;
    this.samplingIntervalAvailable = true;
  }

  /**
   * 連続時間オブザーバーの極を設定します。
   * 
   * @param continuousObserverPoles 連続時間オブザーバーの極
   */
  public void setContinuousObserverPoles(CM continuousObserverPoles) {
    this.observerDesigner.setObserverPoles(continuousObserverPoles);
  }

  /**
   * オブザーバの係数行列を表示します。
   */
  @SuppressWarnings("nls")
  public void showObserver() {
    design();

    final int inputSize = this.observerDesigner.getPlantInputSize();
    final int outputSize = this.observerDesigner.getPlantOutputSize();

    final RM Ahd = this.observer.getA();
    final RM Jhd = this.observer.getB().getColumnVectors(1, inputSize);
    final RM Bhd = this.observer.getB().getColumnVectors(inputSize + 1, inputSize + outputSize);
    final RM Chd = this.observer.getC();
    final RM Dhd = this.observer.getD().getColumnVectors(inputSize + 1, inputSize + outputSize);

    Ahd.print("Ahd");
    System.out.println("");
    Jhd.print("Jhd");
    System.out.println("");
    Bhd.print("Bhd");
    System.out.println("");
    Chd.print("Chd");
    System.out.println("");
    Dhd.print("Dhd");
    System.out.println("");
  }

  //
  // /**
  // * メインメソッド
  // *
  // * @param args
  // * コマンドライン引数
  // */
  // public static void main(String[] args) {
  // RM observerPoles = new DoubleComplexMatrix(new double[] {-20, -20}, new
  // double[] {0, 0}).transpose();
  // double samplingInterval = 0.005;
  // DiscreteObserverDesigner dDesigner = new DiscreteObserverDesigner(new
  // LinearSinglePendulum());
  // dDesigner.setSamplingInterval(samplingInterval);
  // dDesigner.setContinuousObserverPoles(observerPoles);
  // dDesigner.showObserver();
  // }

  /**
   * オブザーバーの極とサンプリング周期が設定済みで、オブザーバーが設計可能であるか判定します。
   * 
   * @return オブザーバーが設計可能であればtrue、そうでなければfalse
   */
  public boolean isAvailable() {
    return this.samplingIntervalAvailable && this.observerDesigner.isAvailable();
  }

}