線形制御系設計

    線形システムの表現
    線形システムの特性解析
    制御器設計
    観測器設計

    モーションコントロール

    加速度制御
    剛体の姿勢制御

    モータドライブ

    駆動制御法
    磁極位置推定法

    システム同定

    ホワイトボックスモデル

階層システムの管理

アーキテクチャ設計で例示したように、システムの制御系は機能によって階層分類することができます。各階層のシステムは他階層のシステム構成変更等に柔軟に対応する拡張性が要求されます。これを実現する各階層のクラス設計とインスタンス管理の例を示します。

設計例

複数台の回転モータを有するシステムの制御を考えます。システム制御の階層として、モータドライブ・運動制御・指令値生成の層を設定します。本設計例では、下位二階層のオブジェクトを生成するクラスの設計例を示します。

モータドライブシステムのクラス設計

単一のモータを制御するオブジェクトを生成することを考えます。各回転モータは次の支配方程式に従って運動すると仮定します。
τ=Jd2dt2θ\begin{align} \tau = J\frac{d^2}{dt^2}\theta \end{align}
ここで、θ, τ, J\theta,\ \tau,\ Jは回転角、トルク、モータ慣性を表します。本システムは、回転角を状態とする動的システムがトルクを外因性入力として駆動する系となっています。ここでは所望のモータトルクを発生させられるものとし、各モータで観測可能な状態量は回転角としてクラスを設計します。簡略化のため、状態の時間発展は矩形積分を用いて模擬します。

lib/motor.h

class motor { private: double Ts; // Time step double J; // Inertia double x; // Angle double dx; // Angular velocity double ddx; // Angular acceleration public: motor(double SmplTime, double Jn); ~motor(); void InitializeState(double InitValue); void UpdateState(double torque); void ClearState(void); double GetState(void); };

lib/motor.cpp

#include <math.h> #include "motor.h" motor::motor(double SmplTime, double Jn) : J(Jn), Ts(SmplTime) { x = 0.0; dx = 0.0; ddx = 0.0; } motor::~motor() {}; void motor::InitializeState(double InitValue) { x = InitValue; dx = 0.0; ddx = 0.0; }; void motor::UpdateState(double torque) { const int div = 100; const double Tp = Ts / 100; for (int i = 0; i < div; i++) { x += dx * Tp; dx += ddx * Tp; ddx = torque / J; } }; void motor::ClearState() { x = 0.0; dx = 0.0; ddx = 0.0; }; double motor::GetState() { return x; };

運動制御器のクラス設計

各モータの回転角を所望の指令値に追従させることを目的としてPDフィードバック制御器を設置する例を示します。制御器の内部演算が微分を含むため、本システムは記憶システムとなります。そのため、過去の状態量をメンバ変数に設定する必要があります。

lib/PDcontroller.h

class PDcontroller { private: double Ts; // Time step double Cp; // P gain double Cd; // D gain double e; // Error double eZ1; // Error at 1 step before double de; // Derivative of error public: PDcontroller(double SmplTime, double nCp, double nCd); ~PDcontroller(); void setGain(double nCp, double nCd); double GenerateReference(double xcmd, double xsen); void ClearState(void); };

lib/PDcontroller.cpp

#include <math.h> #include "PDcontroller.h" PDcontroller::PDcontroller(double SmplTime, double nCp, double nCd) : Cp(nCp), Cd(nCd), Ts(SmplTime) { e = 0.0; de = 0.0; } PDcontroller::~PDcontroller() {}; void PDcontroller::setGain(double nCp, double nCd) { Cp = nCp; Cd = nCd; }; double PDcontroller::GenerateReference(double xcmd, double xsen) { e = xcmd - xsen; de = (e - eZ1) / Ts; eZ1 = e; return Cp * e + Cd * de; }; void PDcontroller::ClearState(void) { e = 0.0; de = 0.0; };

システム制御系の設計

設計したクラスから各階層のインスタンスを生成し、制御系を構築します。ここでは5台のモータの角度を制御するシステムを例示します。

main.cpp

#include "motor.h" #include "PDcontroller.h" int main (void) { // Setting const double Ts = 1e-3; // Sampling time const int motorNum = 5; const double Jn [motorNum] = { 1.2, 2.1, 3.2, 4.6, 5.2}; // Variables double t = 0.0; double x[motorNum] = { 0.0 }; double xcmd[motorNum] = { 0.0 }; double tau[motorNum] = { 0.0 }; // Controller setting double nCp[5] = { 0.0 }; double nCd[5] = { 0.0 }; const double wn = 20.0; // Natural frequency const double dn = 1.0; // Damping coefficient for (int j = 0; j < motorNum; j++) { nCp[j] = Jn[j] * wn * wn; nCd[j] = Jn[j] * 2.0 * dn * wn; } // Instance static motor* motors[motorNum]; static PDcontroller* controllers[motorNum]; for (int j = 0; j < motorNum; j++) { motors[j] = new motor(Ts, Jn[j]); controllers[j] = new PDcontroller(Ts, nCp[j], nCd[j]); } for (int i = 0; i < 5e4; i++) { // Observe for (int j = 0; j < motorNum; j++) x[j] = motors[j] -> GetState(); // Set reference for (int j = 0; j < motorNum; j++) xcmd[j] = (t > 1.0)? 1.0 : 0.0; // Calculate input for (int j = 0; j < motorNum; j++) tau[j] = controllers[j] -> GenerateReference(xcmd[j], x[j]); // Update for (int j = 0; j < motorNum; j++) motors[j] -> UpdateState(tau[j]); t += Ts; } for (int j = 0; j < motorNum; j++) { delete motors[j]; delete controllers[j]; } return 0; }

設計上の注意

システムに対して適切な階層分類を行うことができれば階層間の依存性を低減することができますが、不適切な分類はオブジェクト間の依存関係を複雑化し、クラスの管理性を著しく悪化させます。これはシステム全体のドメイン知識を有した設計者が適切にアーキテクチャ設計を行うことで回避することができます。

© DigitalServo