LinkedBoomConnectionNoVisuals is BoomConnectionTemplate:
    guide_links is Linkages.LinkPairNoVisuals:
        separation: boom_1.guide_separation
    drive_links is Linkages.LinkPairNoVisuals:
        separation: boom_2.drive_separation

    # Connect the different parts using AxleBearingConnection's
    guide_links_cylinder_connection is Connections.AxleBearingConnection:
        input: cylinder.rod.axle_bearing_interface
        output: guide_links.output
    drive_links_cylinder_connection is Connections.AxleBearingConnection:
        input: cylinder.rod.axle_bearing_interface
        output: drive_links.input
    guide_link_snap is Connections.AxleBearingConnection:
        input: boom_1.guide
        output: guide_links.input
    drive_link_snap is Connections.AxleBearingConnection:
        input: boom_2.drive
        output: drive_links.output


    # Snap assembles Mate by Mate
    # Snap will, as long as it is possible,
    # only move objects to already assembled objects.
    # If the number of Mates is too few to assemble everything,
    # snap will force some objects. If the number of Mates is too large,
    # there might be Mates that will not be possible to assemble,
    # however, the physics will still be enabled.
    # Where we have junctions, like where both link pairs connect
    # to the hydraulic cylinder, snap require one Mate for each pair
    # The AxleBearingConnections above cover all of the physics,
    # but there is nothing that would snap the guide links to the
    # drive links. And the order of assembly could require that.
    # In the CraneAngle model below, the links need to meet first,
    # for the cylinder to afterward be pulled and rotated into place.
    # Therefore we need a snap_hinge for this.
    snap_hinge is Physics3D.Interactions.Hinge:
        enabled: false
        connectors: [guide_links.snap_output, drive_links.snap_input]

    # The snap_range may limit the valid range for the guide / drive links
    # to limit the possible solutions for the problem with two roots
    snap_range is Physics3D.Interactions.RotationalRange:
        # Disable the physics
        enabled: false
        connectors: snap_hinge.connectors
        start: -Math.PI
        end: Math.PI


    # Lock translational DOF of links to crane bodies
    guide_lock_left is Connections.AxleLock:
        connectors: [guide_links.left.input, boom_1.guide_bearing_left]
    guide_lock_right is Connections.AxleLock:
        connectors: [guide_links.right.input, boom_1.guide_bearing_right]
    drive_lock_left is Connections.AxleLock:
        connectors: [drive_links.left.output, boom_2.drive_bearing_left]
    drive_lock_right is Connections.AxleLock:
        connectors: [drive_links.right.output, boom_2.drive_bearing_right]

LinkedBoomConnection is LinkedBoomConnectionNoVisuals:
    guide_links becomes Linkages.TelescopicLinkPair
    drive_links becomes Linkages.TelescopicLinkPair
