0

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

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

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

例如,我使用以下代码运行了 3 个不同的案例: 1. 在函数 findC 中,如果您将 C 定义为 0(如下所示),一切运行正常。2. 如果您改为创建 C 仍为 0 的 if 循环,则模型将无法模拟。我复制了下面的 if 循环并将其注释掉。3. 如果你在案例 1 中保留 findC,但只是取消注释“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;

非常感谢!:)

4

3 回答 3

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 中比较两个实数的相等性。

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

于 2013-07-05T10:49:28.977 回答
0

这是根据两个答案修改后的代码(声明所有矩阵的大小,在函数中保护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。一些变化会导致它工作,但这些变化与矩阵无关。

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

谢谢

于 2013-07-12T09:03:49.243 回答
0

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

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

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

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

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

希望解决这个问题可以解决问题。

于 2013-07-11T06:48:06.610 回答