habitat_sim.agent module

See also AgentConfiguration, AgentState and SixDOFPose for more information.

Actions

We currently have the following actions added by default. Any action not registered with an explicit name is given the snake case version of the class name, i.e. MoveForward can be accessed with the name move_forward. See registry.register_move_fn, SceneNodeControl, and ActuationSpec

    if constraint is not None:
        rotation = scene_node.rotation

        if (
            abs(float(rotation.angle())) > 0
            and 1.0 - abs(rotation.axis().normalized()[axis]) > 1e-3
        ):
            raise RuntimeError(
                "Constrained look only works for a singular look action type"
            )

        look_vector = rotation.transform_vector(FRONT)
        if axis == 0:
            look_angle = mn.Rad(np.arctan2(look_vector[1], -look_vector[2]))
        elif axis == 1:
            look_angle = -mn.Rad(np.arctan2(look_vector[0], -look_vector[2]))

        new_angle = look_angle + mn.Deg(theta)

        constraint = mn.Deg(constraint)

        if new_angle > constraint:
            theta = constraint - look_angle
        elif new_angle < -constraint:
            theta = -constraint - look_angle

    _rotate_local_fns[axis](scene_node, mn.Deg(theta))
    scene_node.rotation = scene_node.rotation.normalized()


@registry.register_move_fn(body_action=True)
class MoveBackward(SceneNodeControl):
    def __call__(self, scene_node: SceneNode, actuation_spec: ActuationSpec) -> None:
        _move_along(scene_node, actuation_spec.amount, _Z_AXIS)


@registry.register_move_fn(body_action=True)
class MoveForward(SceneNodeControl):
    def __call__(self, scene_node: SceneNode, actuation_spec: ActuationSpec) -> None:
        _move_along(scene_node, -actuation_spec.amount, _Z_AXIS)


@registry.register_move_fn(body_action=True)
class MoveRight(SceneNodeControl):
    def __call__(self, scene_node: SceneNode, actuation_spec: ActuationSpec) -> None:
        _move_along(scene_node, actuation_spec.amount, _X_AXIS)


@registry.register_move_fn(body_action=True)
class MoveLeft(SceneNodeControl):
    def __call__(self, scene_node: SceneNode, actuation_spec: ActuationSpec) -> None:
        _move_along(scene_node, -actuation_spec.amount, _X_AXIS)


@registry.register_move_fn(body_action=False)
class MoveUp(SceneNodeControl):
    def __call__(self, scene_node: SceneNode, actuation_spec: ActuationSpec) -> None:
        _move_along(scene_node, actuation_spec.amount, _Y_AXIS)


@registry.register_move_fn(body_action=False)
class MoveDown(SceneNodeControl):
    def __call__(self, scene_node: SceneNode, actuation_spec: ActuationSpec) -> None:
        _move_along(scene_node, -actuation_spec.amount, _Y_AXIS)


@registry.register_move_fn(body_action=False)
class LookLeft(SceneNodeControl):
    def __call__(self, scene_node: SceneNode, actuation_spec: ActuationSpec) -> None:
        _rotate_local(
            scene_node, actuation_spec.amount, _Y_AXIS, actuation_spec.constraint
        )


@registry.register_move_fn(body_action=False)
class LookRight(SceneNodeControl):
    def __call__(self, scene_node: SceneNode, actuation_spec: ActuationSpec) -> None:
        _rotate_local(
            scene_node, -actuation_spec.amount, _Y_AXIS, actuation_spec.constraint
        )


registry.register_move_fn(LookLeft, name="turn_left", body_action=True)
registry.register_move_fn(LookRight, name="turn_right", body_action=True)


@registry.register_move_fn(body_action=False)
class LookUp(SceneNodeControl):
    def __call__(self, scene_node: SceneNode, actuation_spec: ActuationSpec) -> None:
        _rotate_local(
            scene_node, actuation_spec.amount, _X_AXIS, actuation_spec.constraint
        )


@registry.register_move_fn(body_action=False)
class LookDown(SceneNodeControl):
    def __call__(self, scene_node: SceneNode, actuation_spec: ActuationSpec) -> None:
        _rotate_local(
            scene_node, -actuation_spec.amount, _X_AXIS, actuation_spec.constraint
        )


@registry.register_move_fn(body_action=False)
class RotateSensorClockwise(SceneNodeControl):
    def __call__(self, scene_node: SceneNode, actuation_spec: ActuationSpec) -> None:
        _rotate_local(
            scene_node, actuation_spec.amount, _Z_AXIS, actuation_spec.constraint
        )


@registry.register_move_fn(body_action=False)
class RotateSensorAntiClockwise(SceneNodeControl):
    def __call__(self, scene_node: SceneNode, actuation_spec: ActuationSpec) -> None:
        _rotate_local(
            scene_node, -actuation_spec.amount, _Z_AXIS, actuation_spec.constraint
        )

And noisy actions from PyRobot. See PyRobotNoisyActuationSpec

    # Same deal with rotation about + EPS and why we multiply by the sign
    rot_noise *= np.sign(rotate_amount + 1e-8)

    scene_node.rotate_y_local(mn.Deg(rotate_amount) + mn.Rad(rot_noise))
    scene_node.rotation = scene_node.rotation.normalized()


@registry.register_move_fn(body_action=True)
class PyrobotNoisyMoveBackward(SceneNodeControl):
    def __call__(
        self, scene_node: hsim.SceneNode, actuation_spec: ActuationSpec
    ) -> None:
        assert isinstance(actuation_spec, PyRobotNoisyActuationSpec)
        _noisy_action_impl(
            scene_node,
            -actuation_spec.amount,
            0.0,
            actuation_spec.noise_multiplier,
            pyrobot_noise_models[actuation_spec.robot][
                actuation_spec.controller
            ].linear_motion,
            "linear",
        )


@registry.register_move_fn(body_action=True)
class PyrobotNoisyMoveForward(SceneNodeControl):
    def __call__(
        self, scene_node: hsim.SceneNode, actuation_spec: ActuationSpec
    ) -> None:
        assert isinstance(actuation_spec, PyRobotNoisyActuationSpec)
        _noisy_action_impl(
            scene_node,
            actuation_spec.amount,
            0.0,
            actuation_spec.noise_multiplier,
            pyrobot_noise_models[actuation_spec.robot][
                actuation_spec.controller
            ].linear_motion,
            "linear",
        )


@registry.register_move_fn(body_action=True)
class PyrobotNoisyTurnLeft(SceneNodeControl):
    def __call__(
        self, scene_node: hsim.SceneNode, actuation_spec: ActuationSpec
    ) -> None:
        assert isinstance(actuation_spec, PyRobotNoisyActuationSpec)
        _noisy_action_impl(
            scene_node,
            0.0,
            actuation_spec.amount,
            actuation_spec.noise_multiplier,
            pyrobot_noise_models[actuation_spec.robot][
                actuation_spec.controller
            ].rotational_motion,
            "rotational",
        )


@registry.register_move_fn(body_action=True)
class PyrobotNoisyTurnRight(SceneNodeControl):
    def __call__(
        self, scene_node: hsim.SceneNode, actuation_spec: ActuationSpec
    ) -> None:
        assert isinstance(actuation_spec, PyRobotNoisyActuationSpec)
        _noisy_action_impl(
            scene_node,
            0.0,
            -actuation_spec.amount,
            actuation_spec.noise_multiplier,
            pyrobot_noise_models[actuation_spec.robot][
                actuation_spec.controller
            ].rotational_motion,
            "rotational",
        )

Action space path finding

See the nav.GreedyGeodesicFollower class.

Classes

class ActionSpec
Defines how a specific action is implemented
class SixDOFPose
Specifies a position with 6 degrees of freedom
class AgentState
class AgentConfiguration
class Agent
Implements an agent with multiple sensors
class ActuationSpec
Struct to hold parameters for the default actions
class ObjectControls
Used to implement actions
class SceneNodeControl
Base class for all controls
class PyRobotNoisyActuationSpec
Struct to hold parameters for pyrobot noise model