Skip to content
LIBRARY
PlanarMechanics.examples.two_joint_robot.TwoJointPlanarRobotPIDCartesian.md

PlanarMechanics.examples.two_joint_robot.TwoJointPlanarRobotPIDCartesian

Planar 2-joint serial robot tracking a jerk-bounded reference specified in Cartesian tool-flange space. A single inverse instance of the arm solves both the inverse kinematics and the inverse dynamics: its tool flange is constrained to the Cartesian reference without applying force there, while its joints are actuated by unknown torques (InverseKinematicsDriver). The unknown torques constitute the computed-torque feedforward, and joint angle and velocity references for the per-joint JointController feedback controllers are measured on the same inverse instance.

Usage

MultibodyComponents.PlanarMechanics.examples.two_joint_robot.TwoJointPlanarRobotPIDCartesian(phi1_0=1.5707963267948966, phi2_0=-1.5707963267948966, k1=100.0, k2=50.0, Ti1=0.1, Ti2=0.1, Td1=1.0, Td2=1.0, y_max=200.0, T=0.005)

Parameters:

NameDescriptionUnitsDefault value
phi1_0Initial angle of joint 1, consistent with the Cartesian trajectory start pointrad1.5707963267948966
phi2_0Initial angle of joint 2, consistent with the Cartesian trajectory start pointrad-1.5707963267948966
k1Proportional gain for joint 1100.0
k2Proportional gain for joint 250.0
Ti1Integrator time constant for joint 1s0.1
Ti2Integrator time constant for joint 2s0.1
Td1Derivative gain for joint 11.0
Td2Derivative gain for joint 21.0
y_maxMaximum torque of both controllers200.0
TVelocity filter time constant of both controllerss0.005

Behavior

Source

dyad
"Planar 2-joint serial robot tracking a jerk-bounded reference specified in Cartesian tool-flange space. A single inverse instance of the arm solves both the inverse kinematics and the inverse dynamics: its tool flange is constrained to the Cartesian reference without applying force there, while its joints are actuated by unknown torques (InverseKinematicsDriver). The unknown torques constitute the computed-torque feedforward, and joint angle and velocity references for the per-joint JointController feedback controllers are measured on the same inverse instance."
example component TwoJointPlanarRobotPIDCartesian
  world = MultibodyComponents.PlanarMechanics.World() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 1170, "y1": 220, "x2": 1070, "y2": 320, "rot": 0}
      },
      "tags": []
    }
  }
  robot = TwoJointPlanarArm(final phi1_start = phi1_0, final phi2_start = phi2_0) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 930, "y1": 220, "x2": 1030, "y2": 320, "rot": 0}
      },
      "tags": []
    }
  }
  "Inverse model of the robot used to solve the inverse kinematics and compute torque feedforward"
  inverse_robot = TwoJointPlanarArm(render = false, final phi1_start = phi1_0, final phi2_start = phi2_0) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 930, "y1": 30, "x2": 1030, "y2": -70, "rot": 0}
      },
      "tags": []
    }
  }
  "Cartesian tool-position reference trajectory; phase synchronization makes the path an exact straight line"
  ptp = MultibodyComponents.KinematicPTPBoundedJerk(nout = 2, q0 = [1.0, 1.0], q1 = [0.5, 1.3], qd_max = [1.0, 1.0], qdd_max = [2.0, 2.0], qddd_max = [10.0, 10.0], phase_synchronization = true) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 110, "y1": -40, "x2": 210, "y2": 60, "rot": 0}
      },
      "tags": []
    }
  }
  ctrl1 = JointController(index = 1, final k = k1, final Ti = Ti1, final Td = Td1, y_max = y_max, T = T) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 470, "y1": 150, "x2": 570, "y2": 250, "rot": 0}
      },
      "tags": []
    }
  }
  ctrl2 = JointController(index = 2, final k = k2, final Ti = Ti2, final Td = Td2, y_max = y_max, T = T) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 530, "y1": 610, "x2": 630, "y2": 710, "rot": 0}
      },
      "tags": []
    }
  }
  ik = InverseKinematicsDriver() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 490, "y1": 30, "x2": 590, "y2": -70, "rot": 0}
      },
      "tags": []
    }
  }
  torque1 = RotationalComponents.Sources.TorqueSource() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 730, "y1": 150, "x2": 830, "y2": 250, "rot": 0}
      },
      "tags": []
    }
  }
  torque2 = RotationalComponents.Sources.TorqueSource() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 730, "y1": 710, "x2": 830, "y2": 610, "rot": 0}
      },
      "tags": []
    }
  }
  angle1 = RotationalComponents.Sensors.AngleSensor() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 460, "y1": 230, "x2": 360, "y2": 330, "rot": 0}
      },
      "tags": []
    }
  }
  angle2 = RotationalComponents.Sensors.AngleSensor() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 460, "y1": 700, "x2": 360, "y2": 800, "rot": 0}
      },
      "tags": []
    }
  }
  vel1 = RotationalComponents.Sensors.VelocitySensor() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 460, "y1": 360, "x2": 360, "y2": 460, "rot": 0}
      },
      "tags": []
    }
  }
  vel2 = RotationalComponents.Sensors.VelocitySensor() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 460, "y1": 820, "x2": 360, "y2": 920, "rot": 0}
      },
      "tags": []
    }
  }
  fixed = RotationalComponents.Components.Fixed() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 800, "y1": 430, "x2": 900, "y2": 530, "rot": 270}
      },
      "tags": []
    }
  }
  fixed1 = RotationalComponents.Components.Fixed() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 520, "y1": -130, "x2": 560, "y2": -170, "rot": 0}
      },
      "tags": []
    }
  }
  "Initial angle of joint 1, consistent with the Cartesian trajectory start point"
  parameter phi1_0::Angle = 1.5707963267948966
  "Initial angle of joint 2, consistent with the Cartesian trajectory start point"
  parameter phi2_0::Angle = -1.5707963267948966
  "Proportional gain for joint 1"
  parameter k1::Real = 100.0
  "Proportional gain for joint 2"
  parameter k2::Real = 50.0
  "Integrator time constant for joint 1"
  parameter Ti1::Time = 0.1
  "Integrator time constant for joint 2"
  parameter Ti2::Time = 0.1
  "Derivative gain for joint 1"
  parameter Td1::Real = 1.0
  "Derivative gain for joint 2"
  parameter Td2::Real = 1.0
  "Maximum torque of both controllers"
  parameter y_max::Real = 200.0
  "Velocity filter time constant of both controllers"
  parameter T::Time = 0.005
relations
  connect(robot.flange1, torque1.spline) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 900, "y": 244}, {"x": 900, "y": 200}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(torque1.support, fixed.spline) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 780, "y": 480}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(angle1.phi, ctrl1.phi) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 310, "y": 280}, {"x": 310, "y": 220}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(vel1.w, ctrl1.w) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 290, "y": 410}, {"x": 290, "y": 200}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(ctrl1.y, torque1.tau) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(robot.flange2, torque2.spline, vel2.spline, angle2.spline) {
    "Dyad": {
      "edges": [
        {"S": -1, "M": [{"x": 920, "y": 295}], "E": 1},
        {"S": 2, "M": [], "E": -1},
        {"S": 3, "M": [], "E": -2},
        {"S": -2, "M": [{"x": 920, "y": 870}], "E": -1},
        {"S": 4, "M": [{"x": 500, "y": 750}], "E": -2}
      ],
      "junctions": [{"x": 920, "y": 660}, {"x": 500, "y": 870}],
      "renderStyle": "standard"
    }
  }
  connect(torque2.support, fixed.spline) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 780, "y": 480}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(ik.q, ctrl2.q, ctrl1.q) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 504, "y": 90}, {"x": 270, "y": 90}], "E": -1},
        {"S": -1, "M": [{"x": 270, "y": 620}], "E": 2},
        {"S": 3, "M": [], "E": -1}
      ],
      "junctions": [{"x": 270, "y": 160}],
      "renderStyle": "standard"
    }
  }
  connect(ik.qd, ctrl2.qd, ctrl1.qd) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 528, "y": 71}, {"x": 250, "y": 71}], "E": -1},
        {"S": -1, "M": [{"x": 250, "y": 640}], "E": 2},
        {"S": 3, "M": [], "E": -1}
      ],
      "junctions": [{"x": 250, "y": 180}],
      "renderStyle": "standard"
    }
  }
  connect(angle2.phi, ctrl2.phi) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 270, "y": 750}, {"x": 270, "y": 680}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(vel2.w, ctrl2.w) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 250, "y": 870}, {"x": 250, "y": 660}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(ctrl2.y, torque2.tau) {}
  connect(angle1.spline, robot.flange1, vel1.spline) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [], "E": -1},
        {"S": -1, "M": [{"x": 900, "y": 280}, {"x": 900, "y": 244}], "E": 2},
        {"S": 3, "M": [{"x": 500, "y": 410}], "E": -1}
      ],
      "junctions": [{"x": 500, "y": 280}],
      "renderStyle": "standard"
    }
  }
  connect(ptp.q, ik.r_ref) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 350, "y": -25}, {"x": 350, "y": -21}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(ik.frame, inverse_robot.frame_tool) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(ik.flange1, inverse_robot.flange1) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 640, "y": 8}, {"x": 640, "y": 6}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(ik.flange2, inverse_robot.flange2) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 640, "y": -46}, {"x": 640, "y": -45}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(fixed1.spline, ik.support) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(ik.tau1, ctrl1.u_ff) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 552, "y": 108}, {"x": 520, "y": 108}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(ik.tau2, ctrl2.u_ff) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 576, "y": 570}, {"x": 580, "y": 570}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(robot.frame_a, world.frame_b, inverse_robot.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": 2}, {"S": 2, "M": [{"x": 1070, "y": -20}], "E": 3}],
      "renderStyle": "standard"
    }
  }
  u1: analysis_point(ctrl1.y, torque1.tau)
  u2: analysis_point(ctrl2.y, torque2.tau)
  ya1: analysis_point(angle1.phi, ctrl1.phi)
  yv1: analysis_point(vel1.w, ctrl1.w)
  ya2: analysis_point(angle2.phi, ctrl2.phi)
  yv2: analysis_point(vel2.w, ctrl2.w)
  uff1: analysis_point(ik.tau1, ctrl1.u_ff)
  uff2: analysis_point(ik.tau2, ctrl2.u_ff)
end
Flattened Source
dyad
"Planar 2-joint serial robot tracking a jerk-bounded reference specified in Cartesian tool-flange space. A single inverse instance of the arm solves both the inverse kinematics and the inverse dynamics: its tool flange is constrained to the Cartesian reference without applying force there, while its joints are actuated by unknown torques (InverseKinematicsDriver). The unknown torques constitute the computed-torque feedforward, and joint angle and velocity references for the per-joint JointController feedback controllers are measured on the same inverse instance."
example component TwoJointPlanarRobotPIDCartesian
  world = MultibodyComponents.PlanarMechanics.World() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 1170, "y1": 220, "x2": 1070, "y2": 320, "rot": 0}
      },
      "tags": []
    }
  }
  robot = TwoJointPlanarArm(final phi1_start = phi1_0, final phi2_start = phi2_0) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 930, "y1": 220, "x2": 1030, "y2": 320, "rot": 0}
      },
      "tags": []
    }
  }
  "Inverse model of the robot used to solve the inverse kinematics and compute torque feedforward"
  inverse_robot = TwoJointPlanarArm(render = false, final phi1_start = phi1_0, final phi2_start = phi2_0) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 930, "y1": 30, "x2": 1030, "y2": -70, "rot": 0}
      },
      "tags": []
    }
  }
  "Cartesian tool-position reference trajectory; phase synchronization makes the path an exact straight line"
  ptp = MultibodyComponents.KinematicPTPBoundedJerk(nout = 2, q0 = [1.0, 1.0], q1 = [0.5, 1.3], qd_max = [1.0, 1.0], qdd_max = [2.0, 2.0], qddd_max = [10.0, 10.0], phase_synchronization = true) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 110, "y1": -40, "x2": 210, "y2": 60, "rot": 0}
      },
      "tags": []
    }
  }
  ctrl1 = JointController(index = 1, final k = k1, final Ti = Ti1, final Td = Td1, y_max = y_max, T = T) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 470, "y1": 150, "x2": 570, "y2": 250, "rot": 0}
      },
      "tags": []
    }
  }
  ctrl2 = JointController(index = 2, final k = k2, final Ti = Ti2, final Td = Td2, y_max = y_max, T = T) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 530, "y1": 610, "x2": 630, "y2": 710, "rot": 0}
      },
      "tags": []
    }
  }
  ik = InverseKinematicsDriver() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 490, "y1": 30, "x2": 590, "y2": -70, "rot": 0}
      },
      "tags": []
    }
  }
  torque1 = RotationalComponents.Sources.TorqueSource() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 730, "y1": 150, "x2": 830, "y2": 250, "rot": 0}
      },
      "tags": []
    }
  }
  torque2 = RotationalComponents.Sources.TorqueSource() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 730, "y1": 710, "x2": 830, "y2": 610, "rot": 0}
      },
      "tags": []
    }
  }
  angle1 = RotationalComponents.Sensors.AngleSensor() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 460, "y1": 230, "x2": 360, "y2": 330, "rot": 0}
      },
      "tags": []
    }
  }
  angle2 = RotationalComponents.Sensors.AngleSensor() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 460, "y1": 700, "x2": 360, "y2": 800, "rot": 0}
      },
      "tags": []
    }
  }
  vel1 = RotationalComponents.Sensors.VelocitySensor() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 460, "y1": 360, "x2": 360, "y2": 460, "rot": 0}
      },
      "tags": []
    }
  }
  vel2 = RotationalComponents.Sensors.VelocitySensor() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 460, "y1": 820, "x2": 360, "y2": 920, "rot": 0}
      },
      "tags": []
    }
  }
  fixed = RotationalComponents.Components.Fixed() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 800, "y1": 430, "x2": 900, "y2": 530, "rot": 270}
      },
      "tags": []
    }
  }
  fixed1 = RotationalComponents.Components.Fixed() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 520, "y1": -130, "x2": 560, "y2": -170, "rot": 0}
      },
      "tags": []
    }
  }
  "Initial angle of joint 1, consistent with the Cartesian trajectory start point"
  parameter phi1_0::Angle = 1.5707963267948966
  "Initial angle of joint 2, consistent with the Cartesian trajectory start point"
  parameter phi2_0::Angle = -1.5707963267948966
  "Proportional gain for joint 1"
  parameter k1::Real = 100.0
  "Proportional gain for joint 2"
  parameter k2::Real = 50.0
  "Integrator time constant for joint 1"
  parameter Ti1::Time = 0.1
  "Integrator time constant for joint 2"
  parameter Ti2::Time = 0.1
  "Derivative gain for joint 1"
  parameter Td1::Real = 1.0
  "Derivative gain for joint 2"
  parameter Td2::Real = 1.0
  "Maximum torque of both controllers"
  parameter y_max::Real = 200.0
  "Velocity filter time constant of both controllers"
  parameter T::Time = 0.005
relations
  connect(robot.flange1, torque1.spline) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 900, "y": 244}, {"x": 900, "y": 200}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(torque1.support, fixed.spline) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 780, "y": 480}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(angle1.phi, ctrl1.phi) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 310, "y": 280}, {"x": 310, "y": 220}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(vel1.w, ctrl1.w) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 290, "y": 410}, {"x": 290, "y": 200}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(ctrl1.y, torque1.tau) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(robot.flange2, torque2.spline, vel2.spline, angle2.spline) {
    "Dyad": {
      "edges": [
        {"S": -1, "M": [{"x": 920, "y": 295}], "E": 1},
        {"S": 2, "M": [], "E": -1},
        {"S": 3, "M": [], "E": -2},
        {"S": -2, "M": [{"x": 920, "y": 870}], "E": -1},
        {"S": 4, "M": [{"x": 500, "y": 750}], "E": -2}
      ],
      "junctions": [{"x": 920, "y": 660}, {"x": 500, "y": 870}],
      "renderStyle": "standard"
    }
  }
  connect(torque2.support, fixed.spline) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 780, "y": 480}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(ik.q, ctrl2.q, ctrl1.q) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 504, "y": 90}, {"x": 270, "y": 90}], "E": -1},
        {"S": -1, "M": [{"x": 270, "y": 620}], "E": 2},
        {"S": 3, "M": [], "E": -1}
      ],
      "junctions": [{"x": 270, "y": 160}],
      "renderStyle": "standard"
    }
  }
  connect(ik.qd, ctrl2.qd, ctrl1.qd) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 528, "y": 71}, {"x": 250, "y": 71}], "E": -1},
        {"S": -1, "M": [{"x": 250, "y": 640}], "E": 2},
        {"S": 3, "M": [], "E": -1}
      ],
      "junctions": [{"x": 250, "y": 180}],
      "renderStyle": "standard"
    }
  }
  connect(angle2.phi, ctrl2.phi) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 270, "y": 750}, {"x": 270, "y": 680}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(vel2.w, ctrl2.w) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 250, "y": 870}, {"x": 250, "y": 660}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(ctrl2.y, torque2.tau) {}
  connect(angle1.spline, robot.flange1, vel1.spline) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [], "E": -1},
        {"S": -1, "M": [{"x": 900, "y": 280}, {"x": 900, "y": 244}], "E": 2},
        {"S": 3, "M": [{"x": 500, "y": 410}], "E": -1}
      ],
      "junctions": [{"x": 500, "y": 280}],
      "renderStyle": "standard"
    }
  }
  connect(ptp.q, ik.r_ref) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 350, "y": -25}, {"x": 350, "y": -21}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(ik.frame, inverse_robot.frame_tool) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(ik.flange1, inverse_robot.flange1) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 640, "y": 8}, {"x": 640, "y": 6}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(ik.flange2, inverse_robot.flange2) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 640, "y": -46}, {"x": 640, "y": -45}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(fixed1.spline, ik.support) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(ik.tau1, ctrl1.u_ff) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 552, "y": 108}, {"x": 520, "y": 108}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(ik.tau2, ctrl2.u_ff) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 576, "y": 570}, {"x": 580, "y": 570}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(robot.frame_a, world.frame_b, inverse_robot.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": 2}, {"S": 2, "M": [{"x": 1070, "y": -20}], "E": 3}],
      "renderStyle": "standard"
    }
  }
  u1: analysis_point(ctrl1.y, torque1.tau)
  u2: analysis_point(ctrl2.y, torque2.tau)
  ya1: analysis_point(angle1.phi, ctrl1.phi)
  yv1: analysis_point(vel1.w, ctrl1.w)
  ya2: analysis_point(angle2.phi, ctrl2.phi)
  yv2: analysis_point(vel2.w, ctrl2.w)
  uff1: analysis_point(ik.tau1, ctrl1.u_ff)
  uff2: analysis_point(ik.tau2, ctrl2.u_ff)
metadata {}
end


Test Cases

No test cases defined.

  • Examples

  • Experiments

  • Analyses