def _check_object_state_dict(cls, obj_state, scenario_length, object_id, valid_check=True):
        """Check the state dict of an object (the dynamic objects such as road users, vehicles or traffic lights).

        Args:
            obj_state: the state dict of the object.
            scenario_length: the length (# of timesteps) of the scenario.
            object_id: the ID of the object.
            valid_check: if True, we will examine the data at each timestep and see if it's non-zero when valid=False
                at that timestep.
        """
        # Check keys
        assert set(obj_state).issuperset(cls.STATE_DICT_KEYS)

        # Check type
        assert MetaDriveType.has_type(obj_state[cls.TYPE]
                                      ), "MetaDrive doesn't have this type: {}".format(obj_state[cls.TYPE])

        # Check set type
        assert obj_state[cls.TYPE] != MetaDriveType.UNSET, "Types should be set for objects and traffic lights"

        # Check state arrays temporal consistency
        assert isinstance(obj_state[cls.STATE], dict)
        for state_key, state_array in obj_state[cls.STATE].items():
            assert isinstance(state_array, (np.ndarray, list, tuple))
            assert len(state_array) == scenario_length

            if not isinstance(state_array, np.ndarray):
                continue

            assert state_array.ndim in [1, 2], "Haven't implemented test array with dim {} yet".format(state_array.ndim)
            if state_array.ndim == 2:
                assert state_array.shape[
                    1] != 0, "Please convert all state with dim 1 to a 1D array instead of 2D array."

            if state_key == "valid" and valid_check:
                assert np.sum(state_array) >= 1, "No frame valid for this object. Consider removing it"

            # check valid
            if "valid" in obj_state[cls.STATE] and valid_check:
                _array = state_array[..., :2] if state_key == "position" else state_array
                assert abs(np.sum(_array[np.where(obj_state[cls.STATE]["valid"], False, True)])) < 1e-2, \
                    "Valid array mismatches with {} array, some frames in {} have non-zero values, " \
                    "so it might be valid".format(state_key, state_key)

        # Check metadata
        assert isinstance(obj_state[cls.METADATA], dict)
        for metadata_key in (cls.TYPE, cls.OBJECT_ID):
            assert metadata_key in obj_state[cls.METADATA]

        # Check metadata alignment
        if cls.OBJECT_ID in obj_state[cls.METADATA]:
            assert obj_state[cls.METADATA][cls.OBJECT_ID] == object_id
Check the state dict of an object (the dynamic objects such as road users, vehicles or traffic lights).

        Args:
            obj_state: the state dict of the object.
            scenario_length: the length (# of timesteps) of the scenario.
            object_id: the ID of the object.
            valid_check: if True, we will examine the data at each timestep and see if it's non-zero when valid=False
                at that timestep.
        
metadrive/scenario/scenario_description.py