| | 1315 | package Joints |
| | 1316 | package Internal |
| | 1317 | model RevoluteWithLengthConstraint |
| | 1318 | "Obsolete model. Use instead Modelica.Mechanics.MultiBody.Joints.Internal.RevoluteWithLengthConstraint" |
| | 1319 | |
| | 1320 | import SI = Modelica.SIunits; |
| | 1321 | import Cv = Modelica.SIunits.Conversions; |
| | 1322 | extends Modelica.Mechanics.MultiBody.Interfaces.PartialTwoFrames; |
| | 1323 | extends ObsoleteModelica3.Icons.ObsoleteModel; |
| | 1324 | Modelica.Mechanics.Rotational.Interfaces.Flange_a axis |
| | 1325 | "1-dim. rotational flange that drives the joint" |
| | 1326 | annotation (Placement(transformation(extent={{10,90},{-10,110}}, rotation=0))); |
| | 1327 | Modelica.Mechanics.Rotational.Interfaces.Flange_b bearing |
| | 1328 | "1-dim. rotational flange of the drive bearing" |
| | 1329 | annotation (Placement(transformation(extent={{-50,90},{-70,110}}, rotation= |
| | 1330 | 0))); |
| | 1331 | |
| | 1332 | Modelica.Blocks.Interfaces.RealInput position_a[3] |
| | 1333 | "Position vector from frame_a to frame_a side of length constraint, resolved in frame_a of revolute joint" |
| | 1334 | annotation (Placement(transformation(extent={{-140,-80},{-100,-40}}, |
| | 1335 | rotation=0))); |
| | 1336 | Modelica.Blocks.Interfaces.RealInput position_b[3] |
| | 1337 | "Position vector from frame_b to frame_b side of length constraint, resolved in frame_b of revolute joint" |
| | 1338 | annotation (Placement(transformation(extent={{140,-80},{100,-40}}, rotation= |
| | 1339 | 0))); |
| | 1340 | |
| | 1341 | parameter Boolean animation=true |
| | 1342 | "= true, if animation shall be enabled"; |
| | 1343 | parameter SI.Position lengthConstraint=1 |
| | 1344 | "Fixed length of length constraint"; |
| | 1345 | parameter Modelica.Mechanics.MultiBody.Types.Axis n={0,0,1} |
| | 1346 | "Axis of rotation resolved in frame_a (= same as in frame_b)" |
| | 1347 | annotation (Evaluate=true); |
| | 1348 | parameter Cv.NonSIunits.Angle_deg phi_offset=0 |
| | 1349 | "Relative angle offset (angle = phi + from_deg(phi_offset))"; |
| | 1350 | parameter Cv.NonSIunits.Angle_deg phi_guess=0 |
| | 1351 | "Select the configuration such that at initial time |phi - from_deg(phi_guess)|is minimal"; |
| | 1352 | parameter SI.Distance cylinderLength=world.defaultJointLength |
| | 1353 | "Length of cylinder representing the joint axis" |
| | 1354 | annotation (Dialog(tab="Animation", group="if animation = true", enable=animation)); |
| | 1355 | parameter SI.Distance cylinderDiameter=world.defaultJointWidth |
| | 1356 | "Diameter of cylinder representing the joint axis" |
| | 1357 | annotation (Dialog(tab="Animation", group="if animation = true", enable=animation)); |
| | 1358 | input Modelica.Mechanics.MultiBody.Types.Color cylinderColor=Modelica.Mechanics.MultiBody.Types.Defaults.JointColor |
| | 1359 | "Color of cylinder representing the joint axis" |
| | 1360 | annotation (Dialog(tab="Animation", group="if animation = true", enable=animation)); |
| | 1361 | input Modelica.Mechanics.MultiBody.Types.SpecularCoefficient |
| | 1362 | specularCoefficient=world.defaultSpecularCoefficient |
| | 1363 | "Reflection of ambient light (= 0: light is completely absorbed)" |
| | 1364 | annotation (Dialog(tab="Animation", group="if animation = true", enable=animation)); |
| | 1365 | |
| | 1366 | parameter Boolean axisTorqueBalance=true |
| | 1367 | "= true, if torque balance of flange axis with the frame_b connector (axis.tau = -e*frame_b.t) shall be defined. Otherwise this equation has to be provided outside of this joint" |
| | 1368 | annotation (Dialog(tab="Advanced")); |
| | 1369 | final parameter Boolean positiveBranch(fixed=false) |
| | 1370 | "Based on phi_guess, selection of one of the two solutions of the non-linear constraint equation"; |
| | 1371 | final parameter Real e[3](each final unit="1")=Modelica.Math.Vectors.normalize( n) |
| | 1372 | "Unit vector in direction of rotation axis, resolved in frame_a"; |
| | 1373 | |
| | 1374 | SI.Angle phi "Rotation angle of revolute joint"; |
| | 1375 | Modelica.Mechanics.MultiBody.Frames.Orientation R_rel |
| | 1376 | "Relative orientation object from frame_a to frame_b"; |
| | 1377 | SI.Angle angle |
| | 1378 | "= phi + from_deg(phi_offset) (relative rotation angle between frame_a and frame_b)"; |
| | 1379 | SI.Torque tau "= axis.tau (driving torque in the axis)"; |
| | 1380 | |
| | 1381 | annotation ( |
| | 1382 | structurallyIncomplete, |
| | 1383 | preferedView="info", |
| | 1384 | __Dymola_obsolete="Obsolete model that is not balanced. Use instead Modelica.Mechanics.MultiBody.Joints.Internal.RevoluteWithLengthConstraint", |
| | 1385 | Window( |
| | 1386 | x=0.05, |
| | 1387 | y=0.09, |
| | 1388 | width=0.65, |
| | 1389 | height=0.69), |
| | 1390 | Icon(coordinateSystem( |
| | 1391 | preserveAspectRatio=false, |
| | 1392 | extent={{-100,-100},{100,100}}, |
| | 1393 | grid={1,1}), graphics={ |
| | 1394 | Rectangle( |
| | 1395 | extent={{-30,10},{10,-10}}, |
| | 1396 | lineColor={0,0,0}, |
| | 1397 | fillColor={192,192,192}, |
| | 1398 | fillPattern=FillPattern.Solid), |
| | 1399 | Rectangle( |
| | 1400 | extent={{-100,-60},{-30,60}}, |
| | 1401 | lineColor={0,0,0}, |
| | 1402 | fillPattern=FillPattern.HorizontalCylinder, |
| | 1403 | fillColor={192,192,192}), |
| | 1404 | Rectangle( |
| | 1405 | extent={{30,-60},{100,60}}, |
| | 1406 | lineColor={0,0,0}, |
| | 1407 | fillPattern=FillPattern.HorizontalCylinder, |
| | 1408 | fillColor={192,192,192}), |
| | 1409 | Text(extent={{-139,-168},{137,-111}}, textString="%name"), |
| | 1410 | Rectangle(extent={{-100,60},{-30,-60}}, lineColor={0,0,0}), |
| | 1411 | Rectangle(extent={{30,60},{100,-60}}, lineColor={0,0,0}), |
| | 1412 | Text( |
| | 1413 | extent={{-142,-108},{147,-69}}, |
| | 1414 | lineColor={0,0,0}, |
| | 1415 | textString="n=%n"), |
| | 1416 | Line(points={{-60,60},{-60,90}}, color={0,0,0}), |
| | 1417 | Line(points={{-20,70},{-60,70}}, color={0,0,0}), |
| | 1418 | Line(points={{-20,80},{-20,60}}, color={0,0,0}), |
| | 1419 | Line(points={{20,80},{20,60}}, color={0,0,0}), |
| | 1420 | Line(points={{20,70},{41,70}}, color={0,0,0}), |
| | 1421 | Polygon( |
| | 1422 | points={{-9,30},{10,30},{30,50},{-29,50},{-9,30}}, |
| | 1423 | lineColor={0,0,0}, |
| | 1424 | fillColor={192,192,192}, |
| | 1425 | fillPattern=FillPattern.Solid), |
| | 1426 | Polygon( |
| | 1427 | points={{10,30},{30,50},{30,-51},{10,-31},{10,30}}, |
| | 1428 | lineColor={0,0,0}, |
| | 1429 | fillColor={192,192,192}, |
| | 1430 | fillPattern=FillPattern.Solid), |
| | 1431 | Rectangle( |
| | 1432 | extent={{-10,90},{10,50}}, |
| | 1433 | lineColor={0,0,0}, |
| | 1434 | fillPattern=FillPattern.VerticalCylinder, |
| | 1435 | fillColor={192,192,192})}), |
| | 1436 | Diagram(coordinateSystem( |
| | 1437 | preserveAspectRatio=false, |
| | 1438 | extent={{-100,-100},{100,100}}, |
| | 1439 | grid={1,1}), graphics={ |
| | 1440 | Rectangle( |
| | 1441 | extent={{-100,-60},{-30,60}}, |
| | 1442 | lineColor={0,0,0}, |
| | 1443 | fillPattern=FillPattern.HorizontalCylinder, |
| | 1444 | fillColor={192,192,192}), |
| | 1445 | Rectangle( |
| | 1446 | extent={{-30,10},{10,-10}}, |
| | 1447 | lineColor={0,0,0}, |
| | 1448 | fillColor={192,192,192}, |
| | 1449 | fillPattern=FillPattern.Solid), |
| | 1450 | Rectangle( |
| | 1451 | extent={{30,-60},{100,60}}, |
| | 1452 | lineColor={0,0,0}, |
| | 1453 | fillPattern=FillPattern.HorizontalCylinder, |
| | 1454 | fillColor={192,192,192}), |
| | 1455 | Line(points={{-60,60},{-60,96}}, color={0,0,0}), |
| | 1456 | Line(points={{-20,70},{-60,70}}, color={0,0,0}), |
| | 1457 | Line(points={{-20,80},{-20,60}}, color={0,0,0}), |
| | 1458 | Line(points={{20,80},{20,60}}, color={0,0,0}), |
| | 1459 | Line(points={{20,70},{41,70}}, color={0,0,0}), |
| | 1460 | Polygon( |
| | 1461 | points={{-9,30},{10,30},{30,50},{-29,50},{-9,30}}, |
| | 1462 | lineColor={0,0,0}, |
| | 1463 | fillColor={192,192,192}, |
| | 1464 | fillPattern=FillPattern.Solid), |
| | 1465 | Polygon( |
| | 1466 | points={{10,30},{30,50},{30,-51},{10,-31},{10,30}}, |
| | 1467 | lineColor={0,0,0}, |
| | 1468 | fillColor={192,192,192}, |
| | 1469 | fillPattern=FillPattern.Solid), |
| | 1470 | Rectangle( |
| | 1471 | extent={{-10,50},{10,100}}, |
| | 1472 | lineColor={0,0,0}, |
| | 1473 | fillPattern=FillPattern.VerticalCylinder, |
| | 1474 | fillColor={192,192,192})}), |
| | 1475 | Documentation(info="<HTML> |
| | 1476 | <p> |
| | 1477 | Joint where frame_b rotates around axis n which is fixed in frame_a. |
| | 1478 | The two frames coincide when \"phi + phi_offset = 0\", where |
| | 1479 | \"phi_offset\" is a parameter with a zero default |
| | 1480 | and \"phi\" is the rotation angle. |
| | 1481 | </p> |
| | 1482 | <p> |
| | 1483 | This variant of the revolute joint is designed to work together |
| | 1484 | with a length constraint in a kinematic loop. This means that the |
| | 1485 | angle of the revolute joint, phi, is computed such that the |
| | 1486 | length constraint is fulfilled. |
| | 1487 | </p> |
| | 1488 | <p> |
| | 1489 | <b>Usually, this joint should not be used by a user of the MultiBody |
| | 1490 | library. It is only provided to built-up the Modelica.Mechanics.MultiBody.Joints.Assemblies.JointXYZ |
| | 1491 | joints.</b> |
| | 1492 | </p> |
| | 1493 | </HTML> |
| | 1494 | "), uses(Modelica(version="3.0"))); |
| | 1495 | |
| | 1496 | protected |
| | 1497 | SI.Position r_a[3]=position_a |
| | 1498 | "Position vector from frame_a to frame_a side of length constraint, resolved in frame_a of revolute joint"; |
| | 1499 | SI.Position r_b[3]=position_b |
| | 1500 | "Position vector from frame_b to frame_b side of length constraint, resolved in frame_b of revolute joint"; |
| | 1501 | Real e_r_a "Projection of r_a on e"; |
| | 1502 | Real e_r_b "Projection of r_b on e"; |
| | 1503 | Real A "Coefficient A of equation: A*cos(phi) + B*sin(phi) + C = 0"; |
| | 1504 | Real B "Coefficient B of equation: A*cos(phi) + B*sin(phi) + C = 0"; |
| | 1505 | Real C "Coefficient C of equation: A*cos(phi) + B*sin(phi) + C = 0"; |
| | 1506 | Real k1 "Constant of quadratic equation"; |
| | 1507 | Real k2 "Constant of quadratic equation"; |
| | 1508 | Real k1a(start=1); |
| | 1509 | Real k1b; |
| | 1510 | Real kcos_angle "= k1*cos(angle)"; |
| | 1511 | Real ksin_angle "= k1*sin(angle)"; |
| | 1512 | |
| | 1513 | Modelica.Mechanics.MultiBody.Visualizers.Advanced.Shape cylinder( |
| | 1514 | shapeType="cylinder", |
| | 1515 | color=cylinderColor, |
| | 1516 | specularCoefficient=specularCoefficient, |
| | 1517 | length=cylinderLength, |
| | 1518 | width=cylinderDiameter, |
| | 1519 | height=cylinderDiameter, |
| | 1520 | lengthDirection=e, |
| | 1521 | widthDirection={0,1,0}, |
| | 1522 | r_shape=-e*(cylinderLength/2), |
| | 1523 | r=frame_a.r_0, |
| | 1524 | R=frame_a.R) if world.enableAnimation and animation; |
| | 1525 | |
| | 1526 | function selectBranch |
| | 1527 | "Determine branch which is closest to initial angle=0" |
| | 1528 | |
| | 1529 | import Modelica.Math.*; |
| | 1530 | input SI.Length L "Length of length constraint"; |
| | 1531 | input Real e[3](each final unit="1") |
| | 1532 | "Unit vector along axis of rotation, resolved in frame_a (= same in frame_b)"; |
| | 1533 | input SI.Angle angle_guess |
| | 1534 | "Select the configuration such that at initial time |angle-angle_guess|is minimal (angle=0: frame_a and frame_b coincide)"; |
| | 1535 | input SI.Position r_a[3] |
| | 1536 | "Position vector from frame_a to frame_a side of length constraint, resolved in frame_a of revolute joint"; |
| | 1537 | input SI.Position r_b[3] |
| | 1538 | "Position vector from frame_b to frame_b side of length constraint, resolved in frame_b of revolute joint"; |
| | 1539 | output Boolean positiveBranch "Branch of the initial solution"; |
| | 1540 | protected |
| | 1541 | Real e_r_a "Projection of r_a on e"; |
| | 1542 | Real e_r_b "Projection of r_b on e"; |
| | 1543 | Real A |
| | 1544 | "Coefficient A of equation: A*cos(phi) + B*sin(phi) + C = 0"; |
| | 1545 | Real B |
| | 1546 | "Coefficient B of equation: A*cos(phi) + B*sin(phi) + C = 0"; |
| | 1547 | Real C |
| | 1548 | "Coefficient C of equation: A*cos(phi) + B*sin(phi) + C = 0"; |
| | 1549 | Real k1 "Constant of quadratic equation"; |
| | 1550 | Real k2 "Constant of quadratic equation"; |
| | 1551 | Real kcos1 "k1*cos(angle1)"; |
| | 1552 | Real ksin1 "k1*sin(angle1)"; |
| | 1553 | Real kcos2 "k2*cos(angle2)"; |
| | 1554 | Real ksin2 "k2*sin(angle2)"; |
| | 1555 | SI.Angle angle1 "solution 1 of nonlinear equation"; |
| | 1556 | SI.Angle angle2 "solution 2 of nonlinear equation"; |
| | 1557 | algorithm |
| | 1558 | /* The position vector r_rel from frame_a to frame_b of the length constraint |
| | 1559 | element, resolved in frame_b of the revolute joint is given by |
| | 1560 | (T_rel is the planar transformation matrix from frame_a to frame_b of |
| | 1561 | the revolute joint): |
| | 1562 | r_rel = r_b - T_rel*r_a |
| | 1563 | The length constraint can therefore be formulated as: |
| | 1564 | r_rel*r_rel = L*L |
| | 1565 | with |
| | 1566 | (r_b - T_rel*r_a)*(r_b - T_rel*r_a) |
| | 1567 | = r_b*r_b - 2*r_b*T_rel*r_a + r_a*transpose(T_rel)*T_rel*r_a |
| | 1568 | = r_b*r_b + r_a*r_a - 2*r_b*T_rel*r_a |
| | 1569 | follows |
| | 1570 | (1) 0 = r_a*r_a + r_b*r_b - 2*r_b*T_rel*r_a - L*L |
| | 1571 | The vectors r_a, r_b and parameter L are NOT a function of |
| | 1572 | the angle of the revolute joint. Since T_rel = T_rel(angle) is a function |
| | 1573 | of the unknown angle of the revolute joint, this is a non-linear |
| | 1574 | equation in this angle. |
| | 1575 | T_rel = [e]*tranpose([e]) + (identity(3) - [e]*transpose([e]))*cos(angle) |
| | 1576 | - skew(e)*sin(angle); |
| | 1577 | with |
| | 1578 | r_b*T_rel*r_a |
| | 1579 | = r_b*(e*(e*r_a) + (r_a - e*(e*r_a))*cos(angle) - cross(e,r_a)*sin(angle) |
| | 1580 | = (e*r_b)*(e*r_a) + (r_b*r_a - (e*r_b)*(e*r_a))*cos(angle) - r_b*cross(e,r_a)*sin(angle) |
| | 1581 | follows for the constraint equation (1) |
| | 1582 | (2) 0 = r_a*r_a + r_b*r_b - L*L |
| | 1583 | - 2*(e*r_b)*(e*r_a) |
| | 1584 | - 2*(r_b*r_a - (e*r_b)*(e*r_a))*cos(angle) |
| | 1585 | + 2*r_b*cross(e,r_a)*sin(angle) |
| | 1586 | or |
| | 1587 | (3) A*cos(angle) + B*sin(angle) + C = 0 |
| | 1588 | with |
| | 1589 | A = -2*(r_b*r_a - (e*r_b)*(e*r_a)) |
| | 1590 | B = 2*r_b*cross(e,r_a) |
| | 1591 | C = r_a*r_a + r_b*r_b - L*L - 2*(e*r_b)*(e*r_a) |
| | 1592 | Equation (3) is solved by computing sin(angle) and cos(angle) |
| | 1593 | independently from each other. This allows to compute |
| | 1594 | angle in the range: -180 deg <= angle <= 180 deg |
| | 1595 | */ |
| | 1596 | e_r_a := e*r_a; |
| | 1597 | e_r_b := e*r_b; |
| | 1598 | A := -2*(r_b*r_a - e_r_b*e_r_a); |
| | 1599 | B := 2*r_b*cross(e, r_a); |
| | 1600 | C := r_a*r_a + r_b*r_b - L*L - 2*e_r_b*e_r_a; |
| | 1601 | k1 := A*A + B*B; |
| | 1602 | k2 := sqrt(k1 - C*C); |
| | 1603 | |
| | 1604 | kcos1 := -A*C + B*k2; |
| | 1605 | ksin1 := -B*C - A*k2; |
| | 1606 | angle1 := atan2(ksin1, kcos1); |
| | 1607 | |
| | 1608 | kcos2 := -A*C - B*k2; |
| | 1609 | ksin2 := -B*C + A*k2; |
| | 1610 | angle2 := atan2(ksin2, kcos2); |
| | 1611 | |
| | 1612 | if abs(angle1 - angle_guess) <= abs(angle2 - angle_guess) then |
| | 1613 | positiveBranch := true; |
| | 1614 | else |
| | 1615 | positiveBranch := false; |
| | 1616 | end if; |
| | 1617 | end selectBranch; |
| | 1618 | initial equation |
| | 1619 | positiveBranch = selectBranch(lengthConstraint, e, Cv.from_deg(phi_offset |
| | 1620 | + phi_guess), r_a, r_b); |
| | 1621 | equation |
| | 1622 | Connections.branch(frame_a.R, frame_b.R); |
| | 1623 | axis.tau = tau; |
| | 1624 | axis.phi = phi; |
| | 1625 | bearing.phi = 0; |
| | 1626 | |
| | 1627 | angle = Cv.from_deg(phi_offset) + phi; |
| | 1628 | |
| | 1629 | // transform kinematic quantities from frame_a to frame_b |
| | 1630 | frame_b.r_0 = frame_a.r_0; |
| | 1631 | |
| | 1632 | R_rel = Modelica.Mechanics.MultiBody.Frames.planarRotation( |
| | 1633 | e, |
| | 1634 | angle, |
| | 1635 | der(angle)); |
| | 1636 | frame_b.R = Modelica.Mechanics.MultiBody.Frames.absoluteRotation(frame_a.R, |
| | 1637 | R_rel); |
| | 1638 | |
| | 1639 | // Transform the force and torque acting at frame_b to frame_a |
| | 1640 | zeros(3) = frame_a.f + Modelica.Mechanics.MultiBody.Frames.resolve1(R_rel, |
| | 1641 | frame_b.f); |
| | 1642 | zeros(3) = frame_a.t + Modelica.Mechanics.MultiBody.Frames.resolve1(R_rel, |
| | 1643 | frame_b.t); |
| | 1644 | |
| | 1645 | if axisTorqueBalance then |
| | 1646 | /* Note, if axisTorqueBalance is false, the force in the |
| | 1647 | length constraint must be calculated such that the driving |
| | 1648 | Torque in direction of the rotation axis is: |
| | 1649 | axis.tau = -e*frame_b.t; |
| | 1650 | If axisTorqueBalance=true, this equation is provided here. |
| | 1651 | As a consequence, the force in the length constraint and the second |
| | 1652 | derivative of 'angle' will be part of a linear algebraic system of |
| | 1653 | equations (otherwise, it might be possible to remove this force |
| | 1654 | from the linear system). |
| | 1655 | */ |
| | 1656 | tau = -e*frame_b.t; |
| | 1657 | end if; |
| | 1658 | |
| | 1659 | // Compute rotation angle (details, see function "selectBranch") |
| | 1660 | e_r_a = e*r_a; |
| | 1661 | e_r_b = e*r_b; |
| | 1662 | A = -2*(r_b*r_a - e_r_b*e_r_a); |
| | 1663 | B = 2*r_b*cross(e, r_a); |
| | 1664 | C = r_a*r_a + r_b*r_b - lengthConstraint*lengthConstraint - 2*e_r_b*e_r_a; |
| | 1665 | k1 = A*A + B*B; |
| | 1666 | k1a = k1 - C*C; |
| | 1667 | |
| | 1668 | assert(k1a > 1.e-10, " |
| | 1669 | Singular position of loop (either no or two analytic solutions; |
| | 1670 | the mechanism has lost one-degree-of freedom in this position). |
| | 1671 | Try first to use another Modelica.Mechanics.MultiBody.Joints.Assemblies.JointXXX component. |
| | 1672 | In most cases it is best that the joints outside of the JointXXX |
| | 1673 | component are revolute and NOT prismatic joints. If this also |
| | 1674 | lead to singular positions, it could be that this kinematic loop |
| | 1675 | cannot be solved analytically. In this case you have to build |
| | 1676 | up the loop with basic joints (NO aggregation JointXXX components) |
| | 1677 | and rely on dynamic state selection, i.e., during simulation |
| | 1678 | the states will be dynamically selected in such a way that in no |
| | 1679 | position a degree of freedom is lost. |
| | 1680 | "); |
| | 1681 | |
| | 1682 | k1b = Modelica.Mechanics.MultiBody.Frames.Internal.maxWithoutEvent(k1a, |
| | 1683 | 1.0e-12); |
| | 1684 | k2 = sqrt(k1b); |
| | 1685 | kcos_angle = -A*C + (if positiveBranch then B else -B)*k2; |
| | 1686 | ksin_angle = -B*C + (if positiveBranch then -A else A)*k2; |
| | 1687 | |
| | 1688 | angle = Modelica.Math.atan2(ksin_angle, kcos_angle); |
| | 1689 | end RevoluteWithLengthConstraint; |
| | 1690 | |
| | 1691 | model PrismaticWithLengthConstraint |
| | 1692 | "Obsolete model. Use instead Modelica.Mechanics.MultiBody.Joints.Internal.PrismaticWithLengthConstraint" |
| | 1693 | |
| | 1694 | import SI = Modelica.SIunits; |
| | 1695 | import Cv = Modelica.SIunits.Conversions; |
| | 1696 | extends Modelica.Mechanics.MultiBody.Interfaces.PartialTwoFrames; |
| | 1697 | extends ObsoleteModelica3.Icons.ObsoleteModel; |
| | 1698 | Modelica.Mechanics.Translational.Interfaces.Flange_a axis |
| | 1699 | "1-dim. translational flange that drives the joint" |
| | 1700 | annotation (Placement(transformation(extent={{70,80},{90,60}}, rotation=0))); |
| | 1701 | Modelica.Mechanics.Translational.Interfaces.Flange_b bearing |
| | 1702 | "1-dim. translational flange of the drive bearing" |
| | 1703 | annotation (Placement(transformation(extent={{-30,80},{-50,60}}, rotation=0))); |
| | 1704 | Modelica.Blocks.Interfaces.RealInput position_a[3] |
| | 1705 | "Position vector from frame_a to frame_a side of length constraint, resolved in frame_a of revolute joint" |
| | 1706 | annotation (Placement(transformation(extent={{-140,-80},{-100,-40}}, |
| | 1707 | rotation=0))); |
| | 1708 | Modelica.Blocks.Interfaces.RealInput position_b[3] |
| | 1709 | "Position vector from frame_b to frame_b side of length constraint, resolved in frame_b of revolute joint" |
| | 1710 | annotation (Placement(transformation(extent={{140,-80},{100,-40}}, rotation= |
| | 1711 | 0))); |
| | 1712 | |
| | 1713 | parameter Boolean animation=true |
| | 1714 | "= true, if animation shall be enabled"; |
| | 1715 | parameter SI.Position length=1 "Fixed length of length constraint"; |
| | 1716 | parameter Modelica.Mechanics.MultiBody.Types.Axis n={1,0,0} |
| | 1717 | "Axis of translation resolved in frame_a (= same as in frame_b)" |
| | 1718 | annotation (Evaluate=true); |
| | 1719 | parameter SI.Position s_offset=0 |
| | 1720 | "Relative distance offset (distance between frame_a and frame_b = s(t) + s_offset)"; |
| | 1721 | parameter SI.Position s_guess=0 |
| | 1722 | "Select the configuration such that at initial time |s(t0)-s_guess|is minimal"; |
| | 1723 | parameter Modelica.Mechanics.MultiBody.Types.Axis boxWidthDirection |
| | 1724 | = {0,1,0} |
| | 1725 | "Vector in width direction of box, resolved in frame_a" |
| | 1726 | annotation (Evaluate=true, Dialog(tab="Animation", group= |
| | 1727 | "if animation = true", enable=animation)); |
| | 1728 | parameter SI.Distance boxWidth=world.defaultJointWidth |
| | 1729 | "Width of prismatic joint box" |
| | 1730 | annotation (Dialog(tab="Animation", group="if animation = true", enable=animation)); |
| | 1731 | parameter SI.Distance boxHeight=boxWidth |
| | 1732 | "Height of prismatic joint box" |
| | 1733 | annotation (Dialog(tab="Animation", group="if animation = true", enable=animation)); |
| | 1734 | input Modelica.Mechanics.MultiBody.Types.Color boxColor=Modelica.Mechanics.MultiBody.Types.Defaults.JointColor |
| | 1735 | "Color of prismatic joint box" |
| | 1736 | annotation (Dialog(tab="Animation", group="if animation = true", enable=animation)); |
| | 1737 | input Modelica.Mechanics.MultiBody.Types.SpecularCoefficient |
| | 1738 | specularCoefficient=world.defaultSpecularCoefficient |
| | 1739 | "Reflection of ambient light (= 0: light is completely absorbed)" |
| | 1740 | annotation (Dialog(tab="Animation", group="if animation = true", enable=animation)); |
| | 1741 | |
| | 1742 | parameter Boolean axisForceBalance=true |
| | 1743 | "= true, if force balance of flange axis with the frame_b connector (axis.f = -e*frame_b.f) shall be defined. Otherwise this equation has to be provided outside of this joint" |
| | 1744 | annotation (Dialog(tab="Advanced")); |
| | 1745 | final parameter Boolean positiveBranch(fixed=false) |
| | 1746 | "Selection of one of the two solutions of the non-linear constraint equation"; |
| | 1747 | final parameter Real e[3](each final unit="1")=Modelica.Math.Vectors.normalize( n) |
| | 1748 | "Unit vector in direction of translation axis, resolved in frame_a"; |
| | 1749 | SI.Position s |
| | 1750 | "Relative distance between frame_a and frame_b along axis n = s + s_offset)"; |
| | 1751 | SI.Position distance |
| | 1752 | "Relative distance between frame_a and frame_b along axis n"; |
| | 1753 | SI.Position r_rel_a[3] |
| | 1754 | "Position vector from frame_a to frame_b resolved in frame_a"; |
| | 1755 | SI.Force f "= axis.f (driving force in the axis)"; |
| | 1756 | |
| | 1757 | annotation ( |
| | 1758 | structurallyIncomplete, |
| | 1759 | preferedView="info", |
| | 1760 | __Dymola_obsolete="Obsolete model that is not balanced. Use instead Modelica.Mechanics.MultiBody.Joints.Internal.PrismaticWithLengthConstraint", |
| | 1761 | Window( |
| | 1762 | x=0.05, |
| | 1763 | y=0.09, |
| | 1764 | width=0.65, |
| | 1765 | height=0.69), |
| | 1766 | Icon(coordinateSystem( |
| | 1767 | preserveAspectRatio=false, |
| | 1768 | extent={{-100,-100},{100,100}}, |
| | 1769 | grid={1,1}), graphics={ |
| | 1770 | Rectangle( |
| | 1771 | extent={{-30,-40},{100,30}}, |
| | 1772 | lineColor={0,0,255}, |
| | 1773 | pattern=LinePattern.None, |
| | 1774 | fillColor={192,192,192}, |
| | 1775 | fillPattern=FillPattern.Solid), |
| | 1776 | Rectangle(extent={{-30,40},{100,-40}}, lineColor={0,0,0}), |
| | 1777 | Rectangle( |
| | 1778 | extent={{-100,-60},{-30,50}}, |
| | 1779 | lineColor={0,0,255}, |
| | 1780 | pattern=LinePattern.None, |
| | 1781 | fillColor={192,192,192}, |
| | 1782 | fillPattern=FillPattern.Solid), |
| | 1783 | Rectangle( |
| | 1784 | extent={{-100,50},{-30,60}}, |
| | 1785 | lineColor={0,0,255}, |
| | 1786 | pattern=LinePattern.None, |
| | 1787 | fillColor={0,0,0}, |
| | 1788 | fillPattern=FillPattern.Solid), |
| | 1789 | Rectangle( |
| | 1790 | extent={{-30,30},{100,40}}, |
| | 1791 | lineColor={0,0,255}, |
| | 1792 | pattern=LinePattern.None, |
| | 1793 | fillColor={0,0,0}, |
| | 1794 | fillPattern=FillPattern.Solid), |
| | 1795 | Text(extent={{-136,-170},{140,-113}}, textString="%name"), |
| | 1796 | Rectangle(extent={{-100,60},{-30,-60}}, lineColor={0,0,0}), |
| | 1797 | Line(points={{100,-40},{100,-60}}), |
| | 1798 | Rectangle( |
| | 1799 | extent={{100,40},{90,80}}, |
| | 1800 | lineColor={0,0,0}, |
| | 1801 | fillColor={192,192,192}, |
| | 1802 | fillPattern=FillPattern.Solid), |
| | 1803 | Text( |
| | 1804 | extent={{-136,-116},{153,-77}}, |
| | 1805 | lineColor={0,0,0}, |
| | 1806 | textString="n=%n")}), |
| | 1807 | Diagram(coordinateSystem( |
| | 1808 | preserveAspectRatio=false, |
| | 1809 | extent={{-100,-100},{100,100}}, |
| | 1810 | grid={1,1}), graphics={ |
| | 1811 | Line(points={{-30,-50},{-30,50}}, color={0,0,0}), |
| | 1812 | Line(points={{0,-67},{90,-67}}, color={128,128,128}), |
| | 1813 | Text( |
| | 1814 | extent={{31,-68},{68,-81}}, |
| | 1815 | lineColor={128,128,128}, |
| | 1816 | textString="s"), |
| | 1817 | Line(points={{-100,-67},{0,-67}}, color={128,128,128}), |
| | 1818 | Polygon( |
| | 1819 | points={{-39,-64},{-29,-67},{-39,-70},{-39,-64}}, |
| | 1820 | lineColor={128,128,128}, |
| | 1821 | fillColor={128,128,128}, |
| | 1822 | fillPattern=FillPattern.Solid), |
| | 1823 | Text( |
| | 1824 | extent={{-77,-70},{-43,-85}}, |
| | 1825 | lineColor={128,128,128}, |
| | 1826 | textString="s_offset"), |
| | 1827 | Line(points={{-100,-71},{-100,-51}}, color={128,128,128}), |
| | 1828 | Line(points={{-30,-73},{-30,-33}}, color={128,128,128}), |
| | 1829 | Line(points={{100,-70},{100,-30}}, color={128,128,128}), |
| | 1830 | Polygon( |
| | 1831 | points={{90,-64},{100,-67},{90,-70},{90,-64}}, |
| | 1832 | lineColor={128,128,128}, |
| | 1833 | fillColor={128,128,128}, |
| | 1834 | fillPattern=FillPattern.Solid), |
| | 1835 | Rectangle( |
| | 1836 | extent={{-100,50},{-30,60}}, |
| | 1837 | lineColor={0,0,255}, |
| | 1838 | pattern=LinePattern.None, |
| | 1839 | fillColor={0,0,0}, |
| | 1840 | fillPattern=FillPattern.Solid), |
| | 1841 | Rectangle( |
| | 1842 | extent={{-100,-60},{-30,50}}, |
| | 1843 | lineColor={0,0,255}, |
| | 1844 | pattern=LinePattern.None, |
| | 1845 | fillColor={192,192,192}, |
| | 1846 | fillPattern=FillPattern.Solid), |
| | 1847 | Rectangle(extent={{-30,40},{100,-40}}, lineColor={0,0,0}), |
| | 1848 | Rectangle( |
| | 1849 | extent={{-30,-40},{100,30}}, |
| | 1850 | lineColor={0,0,255}, |
| | 1851 | pattern=LinePattern.None, |
| | 1852 | fillColor={192,192,192}, |
| | 1853 | fillPattern=FillPattern.Solid), |
| | 1854 | Rectangle( |
| | 1855 | extent={{-30,30},{100,40}}, |
| | 1856 | lineColor={0,0,255}, |
| | 1857 | pattern=LinePattern.None, |
| | 1858 | fillColor={0,0,0}, |
| | 1859 | fillPattern=FillPattern.Solid), |
| | 1860 | Rectangle(extent={{-100,60},{-30,-60}}, lineColor={0,0,0}), |
| | 1861 | Line(points={{100,-40},{100,-60}}), |
| | 1862 | Text(extent={{42,91},{57,76}}, textString="f"), |
| | 1863 | Line(points={{40,75},{70,75}}, color={0,0,255}), |
| | 1864 | Polygon( |
| | 1865 | points={{-21,78},{-31,75},{-21,72},{-21,78}}, |
| | 1866 | lineColor={0,0,255}, |
| | 1867 | fillColor={0,0,255}, |
| | 1868 | fillPattern=FillPattern.Solid), |
| | 1869 | Line(points={{-8,75},{-31,75}}, color={0,0,255}), |
| | 1870 | Text(extent={{-21,90},{-6,75}}, textString="f"), |
| | 1871 | Polygon( |
| | 1872 | points={{60,78},{70,75},{60,72},{60,78}}, |
| | 1873 | lineColor={0,0,255}, |
| | 1874 | fillColor={0,0,255}, |
| | 1875 | fillPattern=FillPattern.Solid), |
| | 1876 | Line(points={{-30,64},{70,64}}, color={128,128,128}), |
| | 1877 | Polygon( |
| | 1878 | points={{60,67},{70,64},{60,61},{60,67}}, |
| | 1879 | lineColor={128,128,128}, |
| | 1880 | fillColor={128,128,128}, |
| | 1881 | fillPattern=FillPattern.Solid), |
| | 1882 | Text( |
| | 1883 | extent={{0,63},{37,50}}, |
| | 1884 | lineColor={128,128,128}, |
| | 1885 | textString="s"), |
| | 1886 | Rectangle( |
| | 1887 | extent={{100,40},{90,80}}, |
| | 1888 | lineColor={0,0,0}, |
| | 1889 | fillColor={192,192,192}, |
| | 1890 | fillPattern=FillPattern.Solid)}), |
| | 1891 | Documentation(info="<HTML> |
| | 1892 | <p> |
| | 1893 | Joint where frame_b is translated along axis n which is fixed in frame_a. |
| | 1894 | The two frames coincide when \"s + s_offset = 0\", where |
| | 1895 | \"s_offset\" is a parameter with a zero default |
| | 1896 | and \"s\" is the relative distance. |
| | 1897 | </p> |
| | 1898 | <p> |
| | 1899 | This variant of the prismatic joint is designed to work together |
| | 1900 | with a length constraint in a kinematic loop. This means that the |
| | 1901 | relative distance \"s\" of the joint is computed such that the |
| | 1902 | length constraint is fulfilled. |
| | 1903 | </p> |
| | 1904 | <p> |
| | 1905 | <b>Usually, this joint should not be used by a user of the MultiBody |
| | 1906 | library. It is only provided to built-up the Modelica.Mechanics.MultiBody.Joints.Assemblies.JointXYZ |
| | 1907 | joints.</b> |
| | 1908 | </p> |
| | 1909 | </HTML> |
| | 1910 | "), uses(Modelica(version="3.0"))); |
| | 1911 | |
| | 1912 | &nb |