math.acos 与 backlash 元素组合时出现域外错误
math.acos out of domain error when combined with backlash element
我 运行 遇到涉及 modelica 三角函数的域外错误问题,我只是不知道我能做什么。
我的模型是非线性旋转 spring(扭矩取决于几何关系)+ 硬停止(使用标准反冲元件)。
Model schematic with elastogap - doesnt work
我在 OpenModelica 中得到的错误是:
acos(variable) outside domain -1.0 <= -1 <= +1.0
这意味着错误似乎出现在我的自定义 spring 模型中。
现在,我认为应该起作用的普通解决方案是限制变量,以便 acos 使用 if 条件留在域中。我还遵循了关于 noEvent() 运算符的建议 given here。但是,这没有用。我什至过分使用 "safekeeping",但无济于事。
为了补全,this是spring的几何关系。我确信它是正确的。
我使用从 phi= -2° 到 108° 的输入斜坡。 elastogap 允许从 phi = 0° 到 106° 的无力运动。
Without the backlash 元素我的 spring 工作正常。域外没有问题。连同这种强烈反对,我得到了域问题,即使我在我的自定义 spring 模型中的每个三角函数之前添加了 "domain-limits"。
有没有人知道问题可能是什么/我可以尝试什么?
我注意到,如果我将反冲的范围更改为具有不同的限制(例如 b=105.9*pi/180 ;phi_rel0=-52.95*pi/180),它也会没有域错误,但我想深入了解这个问题。
模型(有错误):
package test
model LD_Abwickel_ZF_VAL
Modelica.Blocks.Sources.Ramp ramp2(duration = 1.24, height = 122, offset = -2);
Modelica.Mechanics.Rotational.Components.ElastoBacklash2 elastoBacklash(b = 1.85005, c = 1e4, d = 1e2, phi_rel0 = -0.925025);
Modelica.Mechanics.Rotational.Components.Fixed fixed2;
Modelica.Mechanics.Rotational.Sources.Position position1(exact = true);
Modelica.Blocks.Math.UnitConversions.From_deg from_deg1;
test.LD_Pendelarm_ZugfederF2 lD_Pendelarm_ZugfederF21;
equation
connect(position1.flange, lD_Pendelarm_ZugfederF21.flange);
connect(elastoBacklash.flange_a, lD_Pendelarm_ZugfederF21.flange);
connect(ramp2.y, from_deg1.u);
connect(from_deg1.y, position1.phi_ref);
connect(elastoBacklash.flange_b, fixed2.flange);
end LD_Abwickel_ZF_VAL;
model LD_Pendelarm_ZugfederF2
Modelica.Mechanics.Rotational.Interfaces.Flange_a flange;
.Modelica.SIunits.Angle phi(displayUnit = "deg");
.Modelica.SIunits.Torque M;
parameter .Modelica.SIunits.Length a(displayUnit = "mm") = 25.49e-3;
parameter .Modelica.SIunits.Length b(displayUnit = "mm") = 23.38e-3;
parameter .Modelica.SIunits.Length d(displayUnit = "mm") = 43.89e-3;
parameter .Modelica.SIunits.Length L0(displayUnit = "mm") = 59.5e-3 "Ungespannte Laenge d. Feder";
parameter .Modelica.SIunits.Length Lk(displayUnit = "mm") = 47.19e-3 "Laenge unbelasteter Federkörper";
parameter .Modelica.SIunits.Force F0 = 4.1 "innere Vorspannkraft Feder";
parameter .Modelica.SIunits.TranslationalSpringConstant R(displayUnit = "N/mm") = 0.868e+3 "Federkonstante";
parameter Integer z = 2 "Anzahl Federn";
.Modelica.SIunits.Length c(displayUnit = "mm");
.Modelica.SIunits.Angle delta(displayUnit = "deg", min = -2 * .Modelica.Constants.pi, max = 2 * .Modelica.Constants.pi, nominal = 0);
.Modelica.SIunits.Angle alpha(displayUnit = "deg", min = -2 * .Modelica.Constants.pi, max = 2 * .Modelica.Constants.pi, nominal = 0.5 * .Modelica.Constants.pi);
.Modelica.SIunits.Angle beta(displayUnit = "deg", min = -4 * .Modelica.Constants.pi, max = 4 * .Modelica.Constants.pi, nominal = .Modelica.Constants.pi);
.Modelica.SIunits.Angle psi(displayUnit = "deg", min = -4 * .Modelica.Constants.pi, max = 4 * .Modelica.Constants.pi, nominal = 0);
.Modelica.SIunits.Length L_gerade(displayUnit = "mm");
.Modelica.SIunits.Length L_bogen(displayUnit = "mm") = 46.1e-3;
.Modelica.SIunits.Length L_c(displayUnit = "mm") "rel. Federlaenge (gesamt)";
.Modelica.SIunits.Force F_c "Summe Federkraft";
Real cosalpha(min = -1, max = 1, nominal = 0);
Real cosdelta(min = -1, max = 1, nominal = 0);
Real cosbeta(min = -1, max = 1, nominal = 0);
equation
flange.phi = phi;
flange.tau = M;
if noEvent(phi <= 0) then
c = a - b;
cosdelta = 1;
delta = 0;
L_gerade = sqrt(c ^ 2 + d ^ 2);
cosalpha = -1;
alpha = .Modelica.Constants.pi;
else
c = sqrt(a ^ 2 + b ^ 2 - 2 * a * b * cos(phi));
cosdelta = (b ^ 2 - a ^ 2 - c ^ 2) / (-2 * a * c);
if noEvent(cosdelta <= 0.999999 and cosdelta >= (-0.999999)) then
cos(delta) = cosdelta;
else
delta = if noEvent(sign(cosdelta) > 0) then 0 else .Modelica.Constants.pi;
end if;
L_gerade = sqrt(c ^ 2 + d ^ 2 - 2 * c * d * cos(delta + .Modelica.Constants.pi * 0.5));
cosalpha = (a ^ 2 - b ^ 2 - c ^ 2) / (-2 * b * c);
if noEvent(cosalpha <= 0.999999 and cosalpha >= (-0.999999)) then
cos(alpha) = cosalpha;
else
alpha = if noEvent(sign(cosalpha) > 0) then 0 else .Modelica.Constants.pi;
end if;
end if;
cosbeta = (d ^ 2 - c ^ 2 - L_gerade ^ 2) / (-2 * c * L_gerade);
if noEvent(cosbeta <= 0.999999 and cosbeta >= (-0.999999)) then
cos(beta) = cosbeta;
else
beta = if noEvent(sign(cosbeta) > 0) then 0 else .Modelica.Constants.pi;
end if;
psi = alpha - beta;
L_c = L_gerade + L_bogen - (L0 - Lk) - Lk;
F_c = z * (R * L_c + F0);
M = F_c * sin(psi);
end LD_Pendelarm_ZugfederF2;
end test;
所以当然它在我的机器上运行良好,但从代码中我知道它有问题并且可能会随机失败。问题是你有像 cos(beta) = cosbeta
这样的东西,它被解决为 beta = acos(cosbeta)
.
但是 OpenModelica 添加了一个用于公共子表达式消除的错误方程 someTmpVar = acos(cosbeta)
,无论您使用什么 if 方程来保护它,它总是 运行s。扩展似乎发生了 感觉像 bug 向 OpenModelica 报告,因为它发生在代码生成期间并且只产生 lD_Pendelarm_ZugfederF21._delta = if noEvent(from_deg1.y <= 0.0) then 0.0 else if noEvent(lD_Pendelarm_ZugfederF21.cosdelta <= 0.999999) and noEvent(lD_Pendelarm_ZugfederF21.cosdelta >= -0.999999) then if noEvent(abs($TMP$VAR[=13=]x1$COS - $TMP$VAR[=13=]PREX$COS) < abs($TMP$VAR[=13=]x2$COS - $TMP$VAR[=13=]PREX$COS)) then $TMP$VAR[=13=]x1$COS else $TMP$VAR[=13=]x2$COS else if noEvent(sign(lD_Pendelarm_ZugfederF21.cosdelta) > 0) then 0.0 else 3.141592653589793
,它不会比以前更快 运行 并且可能产生域错误。
一个可能的解决方法是使用算法部分,因为它不会被 OpenModelica 大量操纵。
我 运行 遇到涉及 modelica 三角函数的域外错误问题,我只是不知道我能做什么。
我的模型是非线性旋转 spring(扭矩取决于几何关系)+ 硬停止(使用标准反冲元件)。
Model schematic with elastogap - doesnt work
我在 OpenModelica 中得到的错误是:
acos(variable) outside domain -1.0 <= -1 <= +1.0
这意味着错误似乎出现在我的自定义 spring 模型中。
现在,我认为应该起作用的普通解决方案是限制变量,以便 acos 使用 if 条件留在域中。我还遵循了关于 noEvent() 运算符的建议 given here。但是,这没有用。我什至过分使用 "safekeeping",但无济于事。
为了补全,this是spring的几何关系。我确信它是正确的。
我使用从 phi= -2° 到 108° 的输入斜坡。 elastogap 允许从 phi = 0° 到 106° 的无力运动。
Without the backlash 元素我的 spring 工作正常。域外没有问题。连同这种强烈反对,我得到了域问题,即使我在我的自定义 spring 模型中的每个三角函数之前添加了 "domain-limits"。
有没有人知道问题可能是什么/我可以尝试什么?
我注意到,如果我将反冲的范围更改为具有不同的限制(例如 b=105.9*pi/180 ;phi_rel0=-52.95*pi/180),它也会没有域错误,但我想深入了解这个问题。
模型(有错误):
package test
model LD_Abwickel_ZF_VAL
Modelica.Blocks.Sources.Ramp ramp2(duration = 1.24, height = 122, offset = -2);
Modelica.Mechanics.Rotational.Components.ElastoBacklash2 elastoBacklash(b = 1.85005, c = 1e4, d = 1e2, phi_rel0 = -0.925025);
Modelica.Mechanics.Rotational.Components.Fixed fixed2;
Modelica.Mechanics.Rotational.Sources.Position position1(exact = true);
Modelica.Blocks.Math.UnitConversions.From_deg from_deg1;
test.LD_Pendelarm_ZugfederF2 lD_Pendelarm_ZugfederF21;
equation
connect(position1.flange, lD_Pendelarm_ZugfederF21.flange);
connect(elastoBacklash.flange_a, lD_Pendelarm_ZugfederF21.flange);
connect(ramp2.y, from_deg1.u);
connect(from_deg1.y, position1.phi_ref);
connect(elastoBacklash.flange_b, fixed2.flange);
end LD_Abwickel_ZF_VAL;
model LD_Pendelarm_ZugfederF2
Modelica.Mechanics.Rotational.Interfaces.Flange_a flange;
.Modelica.SIunits.Angle phi(displayUnit = "deg");
.Modelica.SIunits.Torque M;
parameter .Modelica.SIunits.Length a(displayUnit = "mm") = 25.49e-3;
parameter .Modelica.SIunits.Length b(displayUnit = "mm") = 23.38e-3;
parameter .Modelica.SIunits.Length d(displayUnit = "mm") = 43.89e-3;
parameter .Modelica.SIunits.Length L0(displayUnit = "mm") = 59.5e-3 "Ungespannte Laenge d. Feder";
parameter .Modelica.SIunits.Length Lk(displayUnit = "mm") = 47.19e-3 "Laenge unbelasteter Federkörper";
parameter .Modelica.SIunits.Force F0 = 4.1 "innere Vorspannkraft Feder";
parameter .Modelica.SIunits.TranslationalSpringConstant R(displayUnit = "N/mm") = 0.868e+3 "Federkonstante";
parameter Integer z = 2 "Anzahl Federn";
.Modelica.SIunits.Length c(displayUnit = "mm");
.Modelica.SIunits.Angle delta(displayUnit = "deg", min = -2 * .Modelica.Constants.pi, max = 2 * .Modelica.Constants.pi, nominal = 0);
.Modelica.SIunits.Angle alpha(displayUnit = "deg", min = -2 * .Modelica.Constants.pi, max = 2 * .Modelica.Constants.pi, nominal = 0.5 * .Modelica.Constants.pi);
.Modelica.SIunits.Angle beta(displayUnit = "deg", min = -4 * .Modelica.Constants.pi, max = 4 * .Modelica.Constants.pi, nominal = .Modelica.Constants.pi);
.Modelica.SIunits.Angle psi(displayUnit = "deg", min = -4 * .Modelica.Constants.pi, max = 4 * .Modelica.Constants.pi, nominal = 0);
.Modelica.SIunits.Length L_gerade(displayUnit = "mm");
.Modelica.SIunits.Length L_bogen(displayUnit = "mm") = 46.1e-3;
.Modelica.SIunits.Length L_c(displayUnit = "mm") "rel. Federlaenge (gesamt)";
.Modelica.SIunits.Force F_c "Summe Federkraft";
Real cosalpha(min = -1, max = 1, nominal = 0);
Real cosdelta(min = -1, max = 1, nominal = 0);
Real cosbeta(min = -1, max = 1, nominal = 0);
equation
flange.phi = phi;
flange.tau = M;
if noEvent(phi <= 0) then
c = a - b;
cosdelta = 1;
delta = 0;
L_gerade = sqrt(c ^ 2 + d ^ 2);
cosalpha = -1;
alpha = .Modelica.Constants.pi;
else
c = sqrt(a ^ 2 + b ^ 2 - 2 * a * b * cos(phi));
cosdelta = (b ^ 2 - a ^ 2 - c ^ 2) / (-2 * a * c);
if noEvent(cosdelta <= 0.999999 and cosdelta >= (-0.999999)) then
cos(delta) = cosdelta;
else
delta = if noEvent(sign(cosdelta) > 0) then 0 else .Modelica.Constants.pi;
end if;
L_gerade = sqrt(c ^ 2 + d ^ 2 - 2 * c * d * cos(delta + .Modelica.Constants.pi * 0.5));
cosalpha = (a ^ 2 - b ^ 2 - c ^ 2) / (-2 * b * c);
if noEvent(cosalpha <= 0.999999 and cosalpha >= (-0.999999)) then
cos(alpha) = cosalpha;
else
alpha = if noEvent(sign(cosalpha) > 0) then 0 else .Modelica.Constants.pi;
end if;
end if;
cosbeta = (d ^ 2 - c ^ 2 - L_gerade ^ 2) / (-2 * c * L_gerade);
if noEvent(cosbeta <= 0.999999 and cosbeta >= (-0.999999)) then
cos(beta) = cosbeta;
else
beta = if noEvent(sign(cosbeta) > 0) then 0 else .Modelica.Constants.pi;
end if;
psi = alpha - beta;
L_c = L_gerade + L_bogen - (L0 - Lk) - Lk;
F_c = z * (R * L_c + F0);
M = F_c * sin(psi);
end LD_Pendelarm_ZugfederF2;
end test;
所以当然它在我的机器上运行良好,但从代码中我知道它有问题并且可能会随机失败。问题是你有像 cos(beta) = cosbeta
这样的东西,它被解决为 beta = acos(cosbeta)
.
但是 OpenModelica 添加了一个用于公共子表达式消除的错误方程 someTmpVar = acos(cosbeta)
,无论您使用什么 if 方程来保护它,它总是 运行s。扩展似乎发生了 感觉像 bug 向 OpenModelica 报告,因为它发生在代码生成期间并且只产生 lD_Pendelarm_ZugfederF21._delta = if noEvent(from_deg1.y <= 0.0) then 0.0 else if noEvent(lD_Pendelarm_ZugfederF21.cosdelta <= 0.999999) and noEvent(lD_Pendelarm_ZugfederF21.cosdelta >= -0.999999) then if noEvent(abs($TMP$VAR[=13=]x1$COS - $TMP$VAR[=13=]PREX$COS) < abs($TMP$VAR[=13=]x2$COS - $TMP$VAR[=13=]PREX$COS)) then $TMP$VAR[=13=]x1$COS else $TMP$VAR[=13=]x2$COS else if noEvent(sign(lD_Pendelarm_ZugfederF21.cosdelta) > 0) then 0.0 else 3.141592653589793
,它不会比以前更快 运行 并且可能产生域错误。
一个可能的解决方法是使用算法部分,因为它不会被 OpenModelica 大量操纵。