Пример #1
0
    def test_setRigidBody(self):
        """
        Set and retrieve object attributes like position, velocity,
        acceleration, and rotation.
        """
        # Instantiate a Leonard.
        leo = getLeonard()

        # Test constants.
        body_new = {
            'imass': 2,
            'scale': 3,
            'cshapes': {'csempty': getCSEmpty()},
            'position': (1, 2, 5),
            'velocityLin': (8, 9, 10.5),
            'velocityRot': (9, 10, 11.5),
            'rotation': (11, 12.5, 13, 13.5)
        }

        # Create a test body.
        id_1 = 0
        body = getRigidBody(cshapes={'csempty': getCSEmpty()})

        # Add the object to the DB with ID=0.
        assert leoAPI.addCmdSpawn([(id_1, body)]).ok
        leo.processCommandsAndSync()

        # Modify the state vector for body with id_1.
        assert leoAPI.addCmdModifyBodyState(id_1, body_new).ok
        leo.processCommandsAndSync()

        # Query the body again and verify the changes are in effect.
        ret = leo.allBodies[id_1]
        assert ret.imass == body_new['imass']
        assert ret.scale == body_new['scale']
        assert np.array_equal(ret.position, body_new['position'])
        assert np.array_equal(ret.velocityLin, body_new['velocityLin'])
        assert np.array_equal(ret.velocityRot, body_new['velocityRot'])
        assert np.array_equal(ret.rotation, body_new['rotation'])

        # Query the AABB, update the collision shapes, and verify that the new
        # AABBs are in effect.
        assert leo.allAABBs[id_1] == {}

        # Modify the body state by adding a collision shape.
        body_new = {'cshapes': {'cssphere': getCSSphere(radius=1)}}
        assert body_new is not None
        assert leoAPI.addCmdModifyBodyState(id_1, body_new).ok
        leo.processCommandsAndSync()
        assert leo.allAABBs[id_1] == {'cssphere': [0, 0, 0, 1, 1, 1]}

        # Modify the body state by adding a collision shape.
        cs_a = getCSSphere(radius=1, pos=(1, 2, 3))
        cs_b = getCSSphere(radius=2, pos=(4, 5, 6))
        cshapes = {'1': cs_a, '2': getCSEmpty(), '3': cs_b}
        body_new = {'cshapes': cshapes}
        assert leoAPI.addCmdModifyBodyState(id_1, body_new).ok
        leo.processCommandsAndSync()
        correct = {'1': [1, 2, 3, 1, 1, 1], '3': [4, 5, 6, 2, 2, 2]}
        assert leo.allAABBs[id_1] == correct
Пример #2
0
    def test_move_single_object(self, clsLeonard):
        """
        Create a single object with non-zero initial speed and ensure
        Leonard moves it accordingly.
        """
        # Get a Leonard instance.
        leo = getLeonard(clsLeonard)

        # Constants and parameters for this test.
        id_0 = 0

        # Spawn an object.
        assert leoAPI.addCmdSpawn([(id_0, getRigidBody())]).ok

        # Advance the simulation by 1s and verify that nothing has moved.
        leo.step(1.0, 60)
        assert np.array_equal(leo.allBodies[id_0].position, [0, 0, 0])

        # Give the object a velocity.
        body = {'velocityLin': np.array([1, 0, 0])}
        assert leoAPI.addCmdModifyBodyState(id_0, body).ok
        del body

        # Advance the simulation by another second and verify the objects have
        # moved accordingly.
        leo.step(1.0, 60)
        body = leo.allBodies[id_0]
        assert 0.9 <= body.position[0] < 1.1
        assert body.position[1] == body.position[2] == 0
Пример #3
0
    def test_setRigidBody_advanced(self, clsLeonard):
        """
        Similar to test_setRigidBody_basic but modify the collision shape
        information as well, namely their mass- and type.
        """
        # Get a Leonard instance.
        leo = getLeonard(clsLeonard)

        # Parameters and constants for this test.
        cshape_box = {'1': getCSBox()}
        cshape_sphere = {'1': getCSSphere()}
        body = getRigidBody(imass=2, scale=3, cshapes=cshape_sphere)

        # Spawn an object.
        objID = 1
        assert leoAPI.addCmdSpawn([(objID, body)]).ok
        del body

        # Verify the body data.
        leo.processCommandsAndSync()
        assert leo.allBodies[objID].imass == 2
        assert leo.allBodies[objID].scale == 3
        assert leo.allBodies[objID].cshapes == cshape_sphere

        # Update the body.
        cs_new = {'imass': 4, 'scale': 5, 'cshapes': cshape_box}
        assert leoAPI.addCmdModifyBodyState(objID, cs_new).ok

        # Verify the body data.
        leo.processCommandsAndSync()
        ret = leo.allBodies[objID]
        assert (ret.imass == 4) and (ret.scale == 5)
        assert ret.cshapes == cshape_box
Пример #4
0
    def test_setRigidBody_basic(self, clsLeonard):
        """
        Spawn an object, specify its State Variables explicitly, and verify the
        change propagated through Azrael.
        """
        # Get a Leonard instance.
        leo = getLeonard(clsLeonard)

        # Parameters and constants for this test.
        id_1 = 1

        # Body data.
        p = np.array([1, 2, 5])
        vl = np.array([8, 9, 10.5])
        vr = vl + 1
        body = {'position': p, 'velocityLin': vl, 'velocityRot': vr}
        del p, vl, vr

        # Spawn a new object. It must have ID=1.
        assert leoAPI.addCmdSpawn([(id_1, getRigidBody())]).ok

        # Update the object's body.
        assert leoAPI.addCmdModifyBodyState(id_1, body).ok

        # Sync the commands to Leonard.
        leo.processCommandsAndSync()

        # Verify that the attributes were correctly updated.
        ret = leo.allBodies[id_1]
        assert np.array_equal(ret.position, body['position'])
        assert np.array_equal(ret.velocityLin, body['velocityLin'])
        assert np.array_equal(ret.velocityRot, body['velocityRot'])
Пример #5
0
    def test_processCommandQueue(self):
        """
        Create commands to spawn-, delete, and modify objects or their booster
        values. Then verify that ``processCommandQueue`` corrently updates
        Leonard's object cache.
        """
        # Get a Leonard instance.
        leo = getLeonard(azrael.leonard.LeonardDistributedZeroMQ)

        # Convenience.
        body_1 = getRigidBody(imass=1)
        body_2 = getRigidBody(imass=2)
        id_1, id_2 = 1, 2

        # Cache must be empty.
        assert len(leo.allBodies) == len(leo.allForces) == 0

        # Spawn two objects.
        tmp = [(id_1, body_1), (id_2, body_2)]
        assert leoAPI.addCmdSpawn(tmp).ok
        leo.processCommandsAndSync()

        # Verify the local cache (forces and torques must default to zero).
        assert getRigidBody(*leo.allBodies[id_1]) == body_1
        assert getRigidBody(*leo.allBodies[id_2]) == body_2
        tmp = leo.allForces[id_1]
        assert tmp.forceDirect == tmp.torqueDirect == [0, 0, 0]
        assert tmp.forceBoost == tmp.torqueBoost == [0, 0, 0]
        del tmp

        # Remove first object.
        assert leoAPI.addCmdRemoveObject(id_1).ok
        leo.processCommandsAndSync()
        assert id_1 not in leo.allBodies
        assert id_1 not in leo.allForces

        # Change the State Vector of id_2.
        pos = (10, 11.5, 12)
        body_3 = {'position': pos}
        assert leo.allBodies[id_2].position == (0, 0, 0)
        assert leoAPI.addCmdModifyBodyState(id_2, body_3).ok
        leo.processCommandsAndSync()
        assert leo.allBodies[id_2].position == pos

        # Apply a direct force and torque to id_2.
        force, torque = [1, 2, 3], [4, 5, 6]
        assert leoAPI.addCmdDirectForce(id_2, force, torque).ok
        leo.processCommandsAndSync()
        assert leo.allForces[id_2].forceDirect == force
        assert leo.allForces[id_2].torqueDirect == torque

        # Specify a new force- and torque value due to booster activity.
        force, torque = [1, 2, 3], [4, 5, 6]
        assert leoAPI.addCmdBoosterForce(id_2, force, torque).ok
        leo.processCommandsAndSync()
        assert leo.allForces[id_2].forceBoost == force
        assert leo.allForces[id_2].torqueBoost == torque
Пример #6
0
    def test_setRigidBody(self):
        """
        Set and retrieve object attributes like position, velocity,
        acceleration, and rotation.
        """
        # Instantiate a Leonard.
        leo = getLeonard()

        # Test constants.
        body_new = {
            'imass': 2,
            'scale': 3,
            'cshapes': {
                'csempty': getCSEmpty()
            },
            'position': (1, 2, 5),
            'velocityLin': (8, 9, 10.5),
            'velocityRot': (9, 10, 11.5),
            'rotation': (11, 12.5, 13, 13.5)
        }

        # Create a test body.
        id_1 = '0'
        body = getRigidBody(cshapes={'csempty': getCSEmpty()})

        # Add the object to the DB with ID=0.
        assert leoAPI.addCmdSpawn([(id_1, body)]).ok
        leo.processCommandsAndSync()

        # Modify the state vector for body with id_1.
        assert leoAPI.addCmdModifyBodyState(id_1, body_new).ok
        leo.processCommandsAndSync()

        # Query the body again and verify the changes are in effect.
        ret = leo.allBodies[id_1]
        assert ret.imass == body_new['imass']
        assert ret.scale == body_new['scale']
        assert np.array_equal(ret.position, body_new['position'])
        assert np.array_equal(ret.velocityLin, body_new['velocityLin'])
        assert np.array_equal(ret.velocityRot, body_new['velocityRot'])
        assert np.array_equal(ret.rotation, body_new['rotation'])

        # Query the AABB, update the collision shapes, and verify that the new
        # AABBs are in effect.
        assert leo.allAABBs[id_1] == {}

        # Modify the body state by adding a collision shape.
        body_new = {'cshapes': {'cssphere': getCSSphere(radius=1)}}
        assert body_new is not None
        assert leoAPI.addCmdModifyBodyState(id_1, body_new).ok
        leo.processCommandsAndSync()
        assert leo.allAABBs[id_1] == {'cssphere': [0, 0, 0, 1, 1, 1]}

        # Modify the body state by adding a collision shape.
        cs_a = getCSSphere(radius=1, pos=(1, 2, 3))
        cs_b = getCSSphere(radius=2, pos=(4, 5, 6))
        cshapes = {'1': cs_a, '2': getCSEmpty(), '3': cs_b}
        body_new = {'cshapes': cshapes}
        assert leoAPI.addCmdModifyBodyState(id_1, body_new).ok
        leo.processCommandsAndSync()
        correct = {'1': [1, 2, 3, 1, 1, 1], '3': [4, 5, 6, 2, 2, 2]}
        assert leo.allAABBs[id_1] == correct
Пример #7
0
    def test_commandQueue(self):
        """
        Add-, query, and remove commands from the command queue.
        """
        # Convenience.
        body_1 = getRigidBody()
        body_2 = {'imass': 2, 'scale': 3}
        id_1, id_2 = '0', '1'

        # The command queue must be empty for every category.
        ret = leoAPI.dequeueCommands()
        assert ret.ok
        assert ret.data['spawn'] == []
        assert ret.data['remove'] == []
        assert ret.data['modify'] == []
        assert ret.data['direct_force'] == []
        assert ret.data['booster_force'] == []

        # Spawn two objects with id_1 and id_2.
        tmp = [(id_1, body_1), (id_2, body_1)]
        assert leoAPI.addCmdSpawn(tmp).ok

        # Verify that the spawn commands were added.
        ret = leoAPI.dequeueCommands()
        assert ret.ok
        spawn = ret.data['spawn']
        assert {spawn[0]['objID'], spawn[1]['objID']} == {id_1, id_2}
        assert ret.data['remove'] == []
        assert ret.data['modify'] == []
        assert ret.data['direct_force'] == []
        assert ret.data['booster_force'] == []

        # De-queuing the commands once more must not return any results because
        # they have already been removed.
        ret = leoAPI.dequeueCommands()
        assert ret.ok
        assert ret.data['spawn'] == []
        assert ret.data['remove'] == []
        assert ret.data['modify'] == []
        assert ret.data['direct_force'] == []
        assert ret.data['booster_force'] == []

        # Modify state variable for body with id_1.
        newSV = {'imass': 10, 'position': [3, 4, 5]}
        assert leoAPI.addCmdModifyBodyState(id_1, newSV).ok
        ret = leoAPI.dequeueCommands()
        modify = ret.data['modify']
        assert ret.ok and len(modify) == 1
        assert modify[0]['objID'] == id_1
        assert modify[0]['rbs'] == newSV
        del newSV

        # Set the direct force and torque for id_2.
        force, torque = [1, 2, 3], [4, 5, 6]
        assert leoAPI.addCmdDirectForce(id_2, force, torque).ok
        ret = leoAPI.dequeueCommands()
        fat = ret.data['direct_force']
        assert ret.ok
        assert len(fat) == 1
        assert fat[0]['objID'] == id_2
        assert fat[0]['force'] == force
        assert fat[0]['torque'] == torque

        # Set the booster force and torque for id_1.
        force, torque = [1, 2, 3], [4, 5, 6]
        assert leoAPI.addCmdBoosterForce(id_1, force, torque).ok
        ret = leoAPI.dequeueCommands()
        fat = ret.data['booster_force']
        assert ret.ok
        assert len(fat) == 1
        assert fat[0]['objID'] == id_1
        assert fat[0]['force'] == force
        assert fat[0]['torque'] == torque

        # Remove an object.
        assert leoAPI.addCmdRemoveObject(id_1).ok
        ret = leoAPI.dequeueCommands()
        assert ret.ok and ret.data['remove'][0]['objID'] == id_1

        # Add commands for two objects (it is perfectly ok to add commands for
        # non-existing body IDs since this is just a command queue - Leonard
        # will skip commands for non-existing IDs automatically).
        force, torque = [7, 8, 9], [10, 11.5, 12.5]
        for objID in (id_1, id_2):
            assert leoAPI.addCmdSpawn([(objID, body_1)]).ok
            assert leoAPI.addCmdModifyBodyState(objID, body_2).ok
            assert leoAPI.addCmdRemoveObject(objID).ok
            assert leoAPI.addCmdDirectForce(objID, force, torque).ok
            assert leoAPI.addCmdBoosterForce(objID, force, torque).ok

        # De-queue all commands.
        ret = leoAPI.dequeueCommands()
        assert ret.ok
        assert len(ret.data['spawn']) == 2
        assert len(ret.data['remove']) == 2
        assert len(ret.data['modify']) == 2
        assert len(ret.data['direct_force']) == 2
        assert len(ret.data['booster_force']) == 2
Пример #8
0
    def test_commandQueue(self):
        """
        Add-, query, and remove commands from the command queue.
        """
        # Convenience.
        body_1 = getRigidBody()
        body_2 = {'imass': 2, 'scale': 3}
        id_1, id_2 = 0, 1

        # The command queue must be empty for every category.
        ret = leoAPI.dequeueCommands()
        assert ret.ok
        assert ret.data['spawn'] == []
        assert ret.data['remove'] == []
        assert ret.data['modify'] == []
        assert ret.data['direct_force'] == []
        assert ret.data['booster_force'] == []

        # Spawn two objects with id_1 and id_2.
        tmp = [(id_1, body_1), (id_2, body_1)]
        assert leoAPI.addCmdSpawn(tmp).ok

        # Verify that the spawn commands were added.
        ret = leoAPI.dequeueCommands()
        assert ret.ok
        assert ret.data['spawn'][0]['objID'] == id_1
        assert ret.data['spawn'][1]['objID'] == id_2
        assert ret.data['remove'] == []
        assert ret.data['modify'] == []
        assert ret.data['direct_force'] == []
        assert ret.data['booster_force'] == []

        # De-queuing the commands once more must not return any results because
        # they have already been removed.
        ret = leoAPI.dequeueCommands()
        assert ret.ok
        assert ret.data['spawn'] == []
        assert ret.data['remove'] == []
        assert ret.data['modify'] == []
        assert ret.data['direct_force'] == []
        assert ret.data['booster_force'] == []

        # Modify state variable for body with id_1.
        newSV = {'imass': 10, 'position': [3, 4, 5]}
        assert leoAPI.addCmdModifyBodyState(id_1, newSV).ok
        ret = leoAPI.dequeueCommands()
        modify = ret.data['modify']
        assert ret.ok and len(modify) == 1
        assert modify[0]['objID'] == id_1
        assert modify[0]['rbs'] == newSV
        del newSV

        # Set the direct force and torque for id_2.
        force, torque = [1, 2, 3], [4, 5, 6]
        assert leoAPI.addCmdDirectForce(id_2, force, torque).ok
        ret = leoAPI.dequeueCommands()
        fat = ret.data['direct_force']
        assert ret.ok
        assert len(fat) == 1
        assert fat[0]['objID'] == id_2
        assert fat[0]['force'] == force
        assert fat[0]['torque'] == torque

        # Set the booster force and torque for id_1.
        force, torque = [1, 2, 3], [4, 5, 6]
        assert leoAPI.addCmdBoosterForce(id_1, force, torque).ok
        ret = leoAPI.dequeueCommands()
        fat = ret.data['booster_force']
        assert ret.ok
        assert len(fat) == 1
        assert fat[0]['objID'] == id_1
        assert fat[0]['force'] == force
        assert fat[0]['torque'] == torque

        # Remove an object.
        assert leoAPI.addCmdRemoveObject(id_1).ok
        ret = leoAPI.dequeueCommands()
        assert ret.ok and ret.data['remove'][0]['objID'] == id_1

        # Add commands for two objects (it is perfectly ok to add commands for
        # non-existing body IDs since this is just a command queue - Leonard
        # will skip commands for non-existing IDs automatically).
        force, torque = [7, 8, 9], [10, 11.5, 12.5]
        for objID in (id_1, id_2):
            assert leoAPI.addCmdSpawn([(objID, body_1)]).ok
            assert leoAPI.addCmdModifyBodyState(objID, body_2).ok
            assert leoAPI.addCmdRemoveObject(objID).ok
            assert leoAPI.addCmdDirectForce(objID, force, torque).ok
            assert leoAPI.addCmdBoosterForce(objID, force, torque).ok

        # De-queue all commands.
        ret = leoAPI.dequeueCommands()
        assert ret.ok
        assert len(ret.data['spawn']) == 2
        assert len(ret.data['remove']) == 2
        assert len(ret.data['modify']) == 2
        assert len(ret.data['direct_force']) == 2
        assert len(ret.data['booster_force']) == 2