예제 #1
0
    def run(self):
        # Return immediately if no resets are required.
        if self.period == -1:
            return

        # Establish connection to Azrael.
        client = azrael.client.Client()

        # Query all objects in the scene. These are the only objects that will
        # survive the reset.
        ret = client.getAllObjectIDs()
        assert ret.ok
        ret = client.getRigidBodies(ret.data)
        assert ret.ok
        allowed_objIDs = {k: v["rbs"] for k, v in ret.data.items() if v is not None}
        print("Took simulation snapshot for reset: ({} objects)".format(len(allowed_objIDs)))

        # Periodically reset the SV values. Set them several times because it
        # is well possible that not all State Variables reach Leonard in the
        # same frame, which means some objects will be reset while other are
        # not. This in turn may cause strange artefacts in the next physics
        # update step, especially when the objects now partially overlap.
        while True:
            # Wait until the timeout expires.
            time.sleep(self.period)

            # Remove all newly added objects.
            ret = client.getAllObjectIDs()
            for objID in ret.data:
                if objID not in allowed_objIDs:
                    client.removeObject(objID)

            # Forcefully reset the position and velocity of every object. Do
            # this several times since network latency may result in some
            # objects being reset sooner than others.
            for ii in range(5):
                for objID, SV in allowed_objIDs.items():
                    tmp = {
                        "position": SV.position,
                        "velocityLin": SV.velocityLin,
                        "velocityRot": SV.velocityRot,
                        "rotation": SV.rotation,
                    }
                    assert client.setRigidBodies({objID: tmp}).ok
                time.sleep(0.1)
예제 #2
0
def placeTarget(host, numTargets=1):
    """
    Spawn ``numTargets`` in the scene.

    The targets visually oscillate in size. They also have no collision
    shapes and are thus unaffected by physics (ie they cannot collide
    with anything).
    """
    # Connect to Azrael.
    client = azrael.client.Client(ip=host)

    # Spawn the target object from the 'BoosterCube_1' template (defined in
    # 'demo_boostercube' that must already be running at this point).
    init = []
    for ii in range(numTargets):
        tmp = {
            'templateID': 'BoosterCube_1',
            'rbs': {'imass': 0, 'position': (0, 0, 3 * ii)}
        }
        init.append(tmp)
    ret = client.spawn(init)

    # Check for errors and abort if there are any.
    if not ret.ok:
        print(ret)
        sys.exit(1)

    # Extract the IDs of the spawned target objects.
    targetIDs = ret.data
    print('Spawned {} targets'.format(len(targetIDs)))
    del init, ret

    # Replace the collision shape with an empty one to disable the physics for
    # those targets.
    cs = types.CollShapeEmpty()
    cs = types.CollShapeMeta('empty', (0, 0, 0), (0, 0, 0, 1), cs)
    cmd = {targetID: {'cshapes': {'cssphere': cs}} for targetID in targetIDs}
    assert client.setRigidBodies(cmd).ok
    del cs

    # Tag the object with target. This is necessary because the
    # `PyConBrisbaneClient.selectNewTarget` method will use to distinguish
    # targets from other objects.
    cmd = {targetID: 'Target' for targetID in targetIDs}
    assert client.setCustomData(cmd)

    # Create a random phase offset in the oscillation pattern (pure eye candy
    # to avoid all targets scale synchronously).
    phi = 2 * np.pi * np.random.rand(len(targetIDs))

    # Modify the scale of the target every 100ms.
    cnt = 0
    while True:
        time.sleep(0.1)

        # Compile the payload for the update command, then send it to Azrael.
        # The fragment names (eg 'frag_1') are hard coded in the Template
        # (don't worry about them, just accept that they exist).
        cmd = {}
        for idx, targetID in enumerate(targetIDs):
            # Compute the new scale value.
            scale = 1 + np.sin(2 * np.pi * 0.1 * cnt + phi[idx])
            scale *= 0.1

            tmp = {
                'frag_1': {'scale': scale},
                'frag_2': {'scale': scale},
            }
            cmd[targetID] = tmp
        assert client.setFragments(cmd).ok

        # Randomly update the target's position every 10s.
        if (cnt % 100) == 0:
            cmd = {}
            for targetID in targetIDs:
                pos = 15 * np.random.rand(3) - 10
                cmd[targetID] = {'position': pos.tolist()}
            assert client.setRigidBodies(cmd).ok
        cnt += 1