如何用Odeint求解状态空间模型? [英] How to solve a state space model with Odeint?

查看:88
本文介绍了如何用Odeint求解状态空间模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Eigen和Odeint对状态空间模型进行数值模拟.我的麻烦是,我需要引用控制数据 U (集成前预定义),以便正确解决状态的 Ax + Bu 部分空间模型.我试图通过使用计数器来跟踪当前时间步长来实现此目的,但是由于某种原因,每次Odeint调用系统功能时,它都会重置为零.

I am trying to implement a numerical simulation of a state space model using Eigen and Odeint. My trouble is that I need to reference control data U (predefined before integration) in order to properly solve the Ax+Bu part of the state space model. I was trying to accomplish this by using a counter to keep track of the current time step, but for whatever reason, it is reset to zero every time the System Function is called by Odeint.

我该如何解决?我对状态空间系统建模的方法有缺陷吗?

How would I get around this? Is my approach to modeling the state space system flawed?

我的系统

struct Eigen_SS_NLTIV_Model
{
    Eigen_SS_NLTIV_Model(matrixXd &ssA, matrixXd &ssB, matrixXd &ssC, 
           matrixXd &ssD, matrixXd &ssU, matrixXd &ssY)
                :A(ssA), B(ssB), C(ssC), D(ssD), U(ssU), Y(ssY)
    {
        Y.resizeLike(U);
        Y.setZero();

        observerStep = 0;
        testPtr = &observerStep;
    }

    /* Observer Function:*/
    void operator()(matrixXd &x, double t)
    {
        Y.col(observerStep) = C*x + D*U.col(observerStep);
        observerStep += 1;
    }

    /* System Function:
     * ONLY the mathematical description of the system dynamics may be placed
     * here. Any data placed in here is destroyed after each iteration of the
     * stepper.
     */
    void operator()(matrixXd &x, matrixXd &dxdt, double t)
    {
        dxdt = A*x + B*U.col(*testPtr);
        //Cannot reference the variable "observerStep" directly as it gets reset 
        //every time this is called. *testPtr doesn't work either.
    }

    int observerStep;
    int *testPtr;
    matrixXd &A, &B, &C, &D, &U, &Y; //Input Vectors
};

我的ODE解算器设置

const double t_end = 3.0;
const double dt = 0.5;
int steps = (int)std::ceil(t_end / dt) + 1;

matrixXd A(2, 2), B(2, 2), C(2, 2), D(2, 2), x(2, 1);
matrixXd U = matrixXd::Constant(2, steps, 1.0);
matrixXd Y;

A << -0.5572, -0.7814, 0.7814, 0.0000;
B << 1.0, -1.0, 0.0, 2.0;
C << 1.9691, 6.4493, 1.9691, 6.4493;
D << 0.0, 0.0, 0.0, 0.0;
x << 0, 0;

Eigen_SS_NLTIV_Model matrixTest(A, B, C, D, U, Y);

odeint::integrate_const(odeint::runge_kutta4<matrixXd, double, matrixXd, double,
    odeint::vector_space_algebra>(),
    matrixTest, x, 0.0, t_end, dt, matrixTest);

//Ignore these two functions. They are there mostly for debugging.
writeCSV<matrixXd>(Y, "Y_OUT.csv");
prettyPrint<matrixXd>(Y, "Out Full");

推荐答案

对于经典的Runge-Kutta,您知道您的ODE模型函数每步被调用4次,每次的次数为 t,t + h/2,t +h/2,t + h .使用其他实现自适应步长的求解器,您无法事先知道调用ODE模型函数的 t 是什么.

With classical Runge-Kutta you know that your ODE model function is called 4 times per step with times t, t+h/2, t+h/2, t+h. With other solvers that implement adaptive step size you can not know in advance at what t the ODE model function is called.

您应该通过某种插值函数来实现 U ,在最简单的情况下,应作为步进函数,该步函数从 t 计算一些索引并返回 U 该索引的值.像

You should implement U via some kind of interpolation function, in the most simple case as step function that computes some index from t and returns the U value for that index. Something like

i = (int)(t/U_step)
dxdt = A*x + B*U.col(i);

这篇关于如何用Odeint求解状态空间模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆