【问题标题】:Controls Implementation using Dymola使用 Dymola 控制实施
【发布时间】:2013-07-04 13:18:49
【问题描述】:

我在 Modelica/Dymola 中实现内置控制算法 (LQR) 时遇到问题。我创建了一个更简单的模型来显示我遇到的问题。

基本上,我在外部调用 LQR 并向其传递一个矩阵,其中的条目(名为 Ctest)在每个时间步都会发生变化。这个 Ctest 也可以通过一个名为 findC 的外部函数找到。

有趣的是,如果您使 Ctest = 0,Dymola 将运行良好,但如果您在 if 循环中使 Ctest = 0,它会显示许多看起来像这样的错误: 不支持:在函数 Modelica_LinearSystems2.Math.Matrices.dare 中,变量 AT 被声明为维度“:”。 这在 dsmodel.c 中尚不支持,如果在模型中调用该函数将失败。

例如,我使用以下代码运行了 3 个不同的案例: 1. 在函数 findC 中,如果您将 C 定义为 0(如下所示),一切运行正常。 2. 如果您改为创建 C 仍为 0 的 if 循环,则模型将无法模拟。我复制了下面的 if 循环并将其注释掉。 3. 如果你保持 findC 与案例 1 一样,但只是取消注释“Real tether_l = 151.61;”,它会给出与案例 2 相同的错误。

任何帮助将不胜感激!

model SimplerModel
import Utilities;

Modelica.Mechanics.MultiBody.Joints.FreeMotion freeMotion(
 useQuaternions=false,
 angles_fixed=true,
r_rel_a(start={1,0,0}, fixed=true),
v_rel_a(start={0,0,0}, fixed=true),
a_rel_a(start={0,0,0}),
    angles_start={0,0,0},
    w_rel_a_fixed=true,
    w_rel_a_start={0,0,0},
    z_rel_a_fixed=false)
    annotation (Placement(transformation(extent={{-50,60},{-30,80}})));

  Modelica.Mechanics.MultiBody.Parts.BodyShape bodyShape(
    r={0,0,1},
    m=600,
    I_11=100,
    I_22=100,
    I_33=500,
    angles_start={0,0,0},
    sequence_start={1,2,3},
    w_0_start={0,0,0},
    z_0_start={0,0,0},
    r_0(start={0,0,0}),
    v_0(start={0,0,0}),
    a_0(start={0,0,0}),
    angles_fixed=false,
    w_0_fixed=false,
    z_0_fixed=false,
    r_CM={0,0,0.5})
    annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
      inner Modelica.Mechanics.MultiBody.World world
    annotation (Placement(transformation(extent={{-80,60},{-60,80}})));

 Real[6,6] restMat=
 [276533.0, 0.0, 0.0, 0.0, 0.0, 0.0;
 0.0, 276533.0, 0.0, 0.0, 0.0, 0.0;
 Ctest, 0.0, 319160000.0, 0.0, 0.0, 0.0;
 0.0, 0.0, 0.0, 86086300000.0, 0.0, 0.0;
 0.0, 0.0, 0.0, 0.0, 86086300000.0, 0.0;
 0.0, 0.0, 0.0, 0.0, 0.0, 146286000.0];

 Real Ctest = Utilities.findC(bodyShape.frame_a.r_0[1]);
 Real K_cat[:,:] = Utilities.findK(restMat);

equation 
  connect(freeMotion.frame_b, bodyShape.frame_a) annotation (Line(
      points={{-30,70},{-20,70},{-20,0},{-10,0}},
      color={95,95,95},
      thickness=0.5,
      smooth=Smooth.None));
  connect(world.frame_b, freeMotion.frame_a) annotation (Line(
      points={{-60,70},{-50,70}},
      color={95,95,95},
      thickness=0.5,
      smooth=Smooth.None));
  annotation (uses(Modelica(version="3.2")), Diagram(coordinateSystem(
          preserveAspectRatio=false, extent={{-100,-100},{100,100}}), graphics));
end SimplerModel;

函数 findK

function findK

  import Modelica_LinearSystems2;
  input Real[6,6] restoring;

Real cyl_mass = 8.21e6;
 Real[6,6] mass = [1.253e7, 0,0,0,-2.99e8,0;
 0,1.253e7,0,2.99e8,0,0;
 0,0,1.6746e6,0,0,0;
 0,2.99e8,0,9.549e9,0,0;
 -2.99e8,0,0,0,9.549e9,0;
 0,0,0,0,0,3.4728e7];

Real[6,6] damping = [1e5,0,0,0,0,0;
0,1e5,0,0,0,0;
0,0,1.3e5,0,0,0;
0,0,0,0,0,0;
0,0,0,0,0,0;
0,0,0,0,0,1.3e7];

Real Ipitroll = 384770000;
Real Iyaw = 291440000;

protected 
Real[6,6] addMassMat = [0,0,0,0,0,0;
0,0,0,0,0,0;
0,0,cyl_mass,0,0,0;
0,0,0,Ipitroll,0,0;
0,0,0,0,Ipitroll,0;
0,0,0,0,0,Iyaw];

Real[6,6] massMat = Modelica.Math.Matrices.inv(mass + addMassMat);

Real[4, 4] A_cat = cat(1, cat(2,zeros(2,2), identity(2)), cat(2, -restoring[4:5,:]*massMat[:,4:5],-damping[4:5,:]*massMat[:,4:5]));
Real[4, 2] B_cat = cat(1, cat(1,zeros(2,2), 23/cyl_mass*identity(2)));
Real[2, 4] C_cat = cat(2, identity(2), zeros(2,2));
Real[2, 2] D_cat = zeros(2, 2);

Real[4,4] Q = [1e8,0,0,0;
 0,1e8,0,0;
 0,0,1e-8,0;
 0,0,0,1e-8];
Real[2,2] R = [1e-9,0;
 0,1e-9];

output Real K_cat[6,6];

algorithm 
K_cat := Modelica_LinearSystems2.StateSpace.Design.lqr(Modelica_LinearSystems2.StateSpace(A_cat,B_cat,C_cat,D_cat), Q, R);

end findK;

函数findC

function findC

input Real x;
output Real C;

   //Real tether_l = 151.61;
   //Real slope_ForceVsHeave = 3.1928e8;
   //Real intercept_ForceVsHeave = 0;
   //Real heave = tether_l - sqrt(tether_l^2 - x^2);

algorithm 
 //if abs(x) == 0.0 then
 //C := 0;
 //else C := 0;
 //end if;
    C:=0;
end findC;

非常感谢! :)

【问题讨论】:

    标签: controls modelica dymola


    【解决方案1】:

    不支持:在 Modelica_LinearSystems2.Math.Matrices.dare 函数中 变量 AT 用维度“:”声明

    意味着您必须声明输入的维度,例如:

    ...
    input Integer n;
    input Real[n] C;
    ...
    

    因为如果编译,会导致错误:

    ...
    input Real[:] C;
    ...
    

    我认为你的 if 语句中的一个问题是

    如果 abs(x) == 0.0 那么

    应该替换为

    Modelica.Math.isEqual(abs(x),0,1e-15)
    

    因为您无法在 Modelica 中比较两个实数的相等性。

    我希望这会有所帮助, 马可

    【讨论】:

    • 感谢您的回答!我已经更改了 if 条件并声明了所有维度,但仍然出现错误。问题是,错误消息中的变量(如 AT)不是由我声明的,而是由 Dymola 声明的。我的怀疑是 Dymola 将我的模型转换为它自己的状态空间系统,试图区分指数减少的方程,因此引入了新变量。我不明白为什么要做一些像取消注释“tether_l = 151.61;”这样微不足道的事情会突然让 Dymola 以不同的方式声明它们的变量。你有什么见解吗?谢谢!
    【解决方案2】:

    我认为 Marco 是对的,问题在于您使用的函数包含未知维度的变量,而 Dymola 无法在模型中处理此问题。例如,dare 函数有:

    Real AT[:, :]=transpose(A);
    

    尝试重写代码,以便将所有 : 替换为大小,在某些情况下您可能必须创建函数来计算这些大小将是多少。

    您使用的是哪个版本的 Dymola?我将代码按原样放入 Dymola 2014 中,它返回了一长串“变量?被声明为维度“:”。”

    另外我认为函数中的所有 Real 变量都应该受到保护。

    希望能解决这个问题。

    【讨论】:

    • 感谢您的意见!我正在使用 Dymola 2014,它为我返回相同的警告列表。我更改了代码,以便用大小声明所有矩阵(仅 K_cat,在这种情况下应该是大小 [2,4])并保护所有实数,但没有运气。由于警告列表中显示的所有变量都是 Dymola 声明的,因此我也无法对它们的大小进行硬编码。但即使看起来与矩阵无关的更改也会导致错误(请参阅原始帖子中的第一个测试用例)。正因为如此,我真的对这些错误感到困惑,所以任何进一步的帮助将不胜感激! :)
    • 如果您发布该代码,我会看看它(可能只是下周的某个时候)
    • 当然,贴在下面!非常感谢:)
    • 好的,我认为您的代码现在还可以,需要修改的是 Modelica_LinearSystems2 代码。有两种不同的方法:
    • 1.要求负责图书馆的小组修改代码,以免再出现这些错误。 2. 复制库并修改它(通过查看错误消息指向的位置找到代码中需要修改的位置)。然后,当你让它编译没有错误时,将它发送到 Modelica_linearSystem2 组,并建议他们实现你的更改。我会选择第二种方法。
    【解决方案3】:

    这是根据两个答案修改后的代码(声明所有矩阵的大小,在函数中保护Reals,改变if条件):

    model SimplerModel
    import OnWind.Components.Substructure.Utilities;
    
    Modelica.Mechanics.MultiBody.Joints.FreeMotion freeMotion(
     useQuaternions=false,
     angles_fixed=true,
    r_rel_a(start={0.5,0,0}, fixed=true),
    v_rel_a(start={0,0,0}, fixed=true),
    a_rel_a(start={0,0,0}),
        angles_start={0,0,0},
        w_rel_a_fixed=true,
        w_rel_a_start={0,0,0},
        z_rel_a_fixed=false)
        annotation (Placement(transformation(extent={{-50,60},{-30,80}})));
    
      Modelica.Mechanics.MultiBody.Parts.BodyShape bodyShape
        annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
          inner Modelica.Mechanics.MultiBody.World world
        annotation (Placement(transformation(extent={{-80,60},{-60,80}})));
    
     //input Integer hi = 1;
     Real[6,6] restMat=
     [276533.0, 0.0, 0.0, 0.0, 0.0, 0.0;
     0.0, 276533.0, 0.0, 0.0, 0.0, 0.0;
     Ctest, 0.0, 319160000.0, 0.0, 0.0, 0.0;
     0.0, 0.0, 0.0, 86086300000.0, 0.0, 0.0;
     0.0, 0.0, 0.0, 0.0, 86086300000.0, 0.0;
     0.0, 0.0, 0.0, 0.0, 0.0, 146286000.0];
    
     Real Ctest = Utilities.findC(bodyShape.frame_b.r_0[1]);
     Real K_cat[2,4] = Utilities.findK(restMat);
    
    equation 
      connect(freeMotion.frame_b, bodyShape.frame_a) annotation (Line(
          points={{-30,70},{-20,70},{-20,0},{-10,0}},
          color={95,95,95},
          thickness=0.5,
          smooth=Smooth.None));
      connect(world.frame_b, freeMotion.frame_a) annotation (Line(
          points={{-60,70},{-50,70}},
          color={95,95,95},
          thickness=0.5,
          smooth=Smooth.None));
      annotation (uses(Modelica(version="3.2")), Diagram(coordinateSystem(
              preserveAspectRatio=false, extent={{-100,-100},{100,100}}), graphics));
    end SimplerModel;
    

    函数 findK

    function findK
    
      import Modelica_LinearSystems2;
      input Real[6,6] restoring;
    
    protected 
    Real cyl_mass = 8.21e6;
     Real[6,6] mass = [1.253e7, 0,0,0,-2.99e8,0;
     0,1.253e7,0,2.99e8,0,0;
     0,0,1.6746e6,0,0,0;
     0,2.99e8,0,9.549e9,0,0;
     -2.99e8,0,0,0,9.549e9,0;
     0,0,0,0,0,3.4728e7];
    
    Real[6,6] damping = [1e5,0,0,0,0,0;
    0,1e5,0,0,0,0;
    0,0,1.3e5,0,0,0;
    0,0,0,0,0,0;
    0,0,0,0,0,0;
    0,0,0,0,0,1.3e7];
    
    Real Ipitroll = 384770000;
    Real Iyaw = 291440000;
    
    Real[6,6] addMassMat = [0,0,0,0,0,0;
    0,0,0,0,0,0;
    0,0,cyl_mass,0,0,0;
    0,0,0,Ipitroll,0,0;
    0,0,0,0,Ipitroll,0;
    0,0,0,0,0,Iyaw];
    
    Real[6,6] massMat = Modelica.Math.Matrices.inv(mass + addMassMat);
    
    Real[4, 4] A_cat = cat(1, cat(2,zeros(2,2), identity(2)), cat(2, -restoring[4:5,:]*massMat[:,4:5],-damping[4:5,:]*massMat[:,4:5]));
    Real[4, 2] B_cat = cat(1, cat(1,zeros(2,2), 23/cyl_mass*identity(2)));
    Real[2, 4] C_cat = cat(2, identity(2), zeros(2,2));
    Real[2, 2] D_cat = zeros(2, 2);
    
    Real[4,4] Q = [1e8,0,0,0;
     0,1e8,0,0;
     0,0,1e-8,0;
     0,0,0,1e-8];
    Real[2,2] R = [1e-9,0;
     0,1e-9];
    
    output Real K_cat[2,4];
    
    algorithm 
    K_cat := Modelica_LinearSystems2.StateSpace.Design.lqr(Modelica_LinearSystems2.StateSpace(A_cat,B_cat,C_cat,D_cat), Q, R);
    
    end findK;
    

    函数 findC

    function findC
    
    input Real x;
    output Real C;
    
       //Real tether_l = 151.61;
    
    algorithm 
     C:=0;
    
    /* if Modelica.Math.isEqual(abs(x),0,1e-15) then
     C := 0;
     else C := 0;
     end if;  
     */
    end findC;
    

    这应该按原样运行。但是我已经注释掉了函数 findC 的必要部分以使其工作。 在 findC 中,取消注释未使用变量 tether_l 的声明(在我的实际代码中需要)或 if 语句(在我的代码中也需要,但在这里写成一个简单的语句只是为了这个更简单的例子)将导致它失败。

    总结一下,Dymola 会生成一长串“不支持:在函数 __ 中声明变量 __ 的维度为“:””。但所有这些变量实际上都是在 Dymola 函数中声明的 Dymola。一些变化会导致它工作,但这些变化与矩阵无关。

    不胜感激任何想法或建议! :)

    谢谢

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-28
      • 1970-01-01
      • 2013-01-21
      • 1970-01-01
      • 2016-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多