Monty.Frameworks.Models.MotorPolicies.InformedPolicy (ExTbpMonty.Core v0.1.0)

Copy Markdown View Source

A policy that reads the percept: stay on the object, or step back onto it.

Mirrors tbp/monty/frameworks/models/motor_policies.py::InformedPolicy, the first policy that is worth running. It samples an action while the sensor is on the object; when the sensor arrives somewhere with nothing under it, it takes the opposite of the last action, which is Monty's way of getting back onto the object without a map. The remembered action is inverted again each time it is used, so a sensor that keeps leaving the object walks back and forth across the edge instead of walking away.

Jumps

With :use_goal_driven_actions it will also teleport — SetAgentPose at the goal's location, facing along the goal's direction — which is how a goal generator's "look at this part of the mug" reaches the body. A jump can land in empty space or inside an object, so the next step judges it from the depth at the centre of the view finder: more than a metre means nothing is there, and the jump is undone with the pose and sensor rotation it started from.

Monty's _handle_successful_jump hook is handle_successful_jump/1, a no-op here and overridden by SurfacePolicy. The jump step itself, goal_driven_actions/4, is public for the same reason: SurfacePolicy is a subclass in Monty and a second struct here, so it calls the shared step rather than inheriting it (docs/monty-differences.md §2.9).

What "empty space" means

_should_undo_jump reads observations[agent_id][sensor_id]["depth"] and takes its centre pixel, as Monty's positioning procedure does. That is the shape Monty's habitats report and the shape this reads; when an environment is ported, the reader moves to PositioningProcedures where Monty keeps it (docs/monty-differences.md §2.7).

Summary

Types

A policy that can be driven by goals: the fields the jump machinery reads.

t()

Functions

One step: a jump if one was asked for, otherwise a sample or a step back.

One step's worth of goal-driven work: judge a jump in flight, or start one.

What to do once a jump has landed with the object in view.

A policy that samples for :agent_id, and jumps when :use_goal_driven_actions.

Starts the next episode: no jump in flight, and no action to undo.

The pose that looks along the goal's direction, from the goal's location.

The orientation every sensor shares, or a refusal to plan a jump.

Nothing to report: what it knows is the action it would undo.

Types

jump_state()

@type jump_state() :: %{
  :agent_id => atom() | String.t(),
  :use_goal_driven_actions => boolean(),
  :is_jumping => boolean(),
  :is_undoing_jump => boolean(),
  :pre_jump_state =>
    Monty.Frameworks.Models.MotorSystemState.AgentState.t() | nil,
  :undo_jump_actions => [Monty.Frameworks.Actions.Action.t()],
  optional(atom()) => term()
}

A policy that can be driven by goals: the fields the jump machinery reads.

Both policies have them, because Monty gives every subclass the jump state through inheritance; here they are matched as a map instead (docs/monty-differences.md §2.9).

t()

@type t() :: %Monty.Frameworks.Models.MotorPolicies.InformedPolicy{
  action_sampler: Monty.Frameworks.Actions.ActionSamplers.ActionSampler.t(),
  agent_id: atom() | String.t(),
  is_jumping: boolean(),
  is_undoing_jump: boolean(),
  pre_jump_state: Monty.Frameworks.Models.MotorSystemState.AgentState.t() | nil,
  rng: :rand.state() | nil,
  undo_action: Monty.Frameworks.Actions.Action.t() | nil,
  undo_jump_actions: [Monty.Frameworks.Actions.Action.t()],
  use_goal_driven_actions: boolean()
}

Functions

call(policy, ctx, observations, state, percept, goal)

One step: a jump if one was asked for, otherwise a sample or a step back.

A jump that is still in flight is judged here first: undoing it takes the whole step, and landing on something means the sample can continue as usual.

goal_driven_actions(policy, observations, state, goal)

@spec goal_driven_actions(jump_state(), map() | nil, map(), Monty.Cmp.Goal.t() | nil) ::
  {:result, Monty.Frameworks.Models.MotorPolicies.MotorPolicyResult.t(),
   jump_state()}
  | {:continue, jump_state()}

One step's worth of goal-driven work: judge a jump in flight, or start one.

Answers {:result, result, policy} when the step is decided here, and {:continue, policy} when the caller should go on to its own behaviour.

handle_successful_jump(policy)

@spec handle_successful_jump(t()) :: t()

What to do once a jump has landed with the object in view.

Monty's _handle_successful_jump, a no-op here and overridden by SurfacePolicy; the policy's own module is asked, because a struct cannot override a private function (docs/monty-differences.md §2.9).

new(options)

@spec new(keyword()) :: t()

A policy that samples for :agent_id, and jumps when :use_goal_driven_actions.

reset(policy)

@spec reset(jump_state()) :: jump_state()

Starts the next episode: no jump in flight, and no action to undo.

set_agent_pose_from_goal(policy, goal)

@spec set_agent_pose_from_goal(
  %{:agent_id => atom() | String.t(), optional(atom()) => term()},
  Monty.Cmp.Goal.t()
) :: Monty.Frameworks.Actions.SetAgentPose.t()

The pose that looks along the goal's direction, from the goal's location.

Monty's _derive_set_agent_pose_from_goal, in both InformedPolicy and JumpToGoal.

shared_sensor_rotation(map)

@spec shared_sensor_rotation(%{sensors: map()}) :: Monty.Geometry.Rotation.t()

The orientation every sensor shares, or a refusal to plan a jump.

Every sensor an action moves is moved at once, so they all keep the orientation the jump was planned in. Monty asserts it rather than assuming it, and so does this — with the empty case spelled out, which Monty's loop does not (docs/monty-differences.md §1.5). Public because JumpToGoal needs the same check and Monty writes it out twice (§2.9).

state_dict(informed_policy)

@spec state_dict(t()) :: map()

Nothing to report: what it knows is the action it would undo.