Monty.Frameworks.Models.EvidenceMatching.HypothesesDisplacer (ExTbpMonty.Core v0.1.0)

Copy Markdown View Source

Where hypotheses move to, and how much evidence they earn there.

Mirrors tbp/monty/frameworks/models/evidence_matching/hypotheses_displacer.py. Two jobs:

  • displacement — a hypothesis says "the sensor is here and the object is turned this way", so when the sensor moves by d the hypothesis moves to pose · d. Every hypothesis is moved, not just the likely ones: dropping one would lose the path information it carries.
  • evidence — for each hypothesis worth testing, find the graph nodes around its search location and score the sensed pose and features there.

The range evidence has

Pose evidence is in [-1, 1]: -0.5 for the surface normal plus -0.5 for the first curvature direction, each mapped so a perfect match scores +0.5 and a perpendicular one -0.5. Feature evidence is [0, 1], so one channel contributes [-1, 2] — MIN_EVIDENCE, MAX_EVIDENCE below. Summed over C channels that is [-C, 2C], which is why the prediction error divides by EVIDENCE_RANGE * C. A hypothesis with no node within max_match_distance scores -1: being wrong is worse than being uninformative.

Summary

Functions

Move every hypothesis by displacement, as its own object orientation sees it.

A displacer over memory.

What each stored node is worth against the sensed features, for one channel.

Evidence from how far two object orientations are apart, in [-1, 1].

Types

t()

@type t() :: %Monty.Frameworks.Models.EvidenceMatching.HypothesesDisplacer{
  feature_evidence_scorer: term(),
  feature_weights: term(),
  graph_memory: term(),
  max_match_distance: term(),
  max_nneighbors: term(),
  past_weight: term(),
  present_weight: term()
}

Functions

compute_evidence(displacer, features, evidence_update_threshold, graph_id, hypotheses, options \\ [])

Add this observation's evidence to the hypotheses worth testing.

Hypotheses below evidence_update_threshold keep their evidence and gain nothing from this step: a cheap way to keep the space bounded without throwing the alternatives away.

Options:

  • :node_feature_evidence — what each stored node is worth for one channel, from node_feature_evidence/4. The same comparison decides which nodes burst sampling draws from and what a hypothesis earns at a node, so the sampler hands its answer over rather than having it computed twice per step. Absent, it is computed here.

displace_hypotheses(hypotheses_displacer, hypotheses, displacement)

Move every hypothesis by displacement, as its own object orientation sees it.

The locations stay in the form they are held in: a kernel writes the moved rows straight into the bytes a step keeps, where the reference builds a list and three boxed floats for every hypothesis and then throws them away.

new(memory, options)

A displacer over memory.

:max_match_distance is how far a search location may sit from a stored node and still match it. :past_weight and :present_weight decide how much of a hypothesis' history survives each observation; adding to one bounds the evidence, which is Monty's reason for having both.

node_feature_evidence(displacer, graph_id, input_channel, channel_features)

@spec node_feature_evidence(t(), String.t(), String.t(), map()) :: [number()]

What each stored node is worth against the sensed features, for one channel.

One comparison per node, in the nodes' own order: burst sampling draws from it when it decides where to put new hypotheses, and the evidence kernel reads it when it decides what a hypothesis earns at a node. Both ask the same question of the same graph and channel in the same step, so it is answered once.

object_pose_evidence(query_poses, node_poses)

@spec object_pose_evidence([[[number()]]], [[[number()]]]) :: [[float()]]

Evidence from how far two object orientations are apart, in [-1, 1].

Monty's _object_pose_evidence: the channel's pose is an OrientationMatrix rather than a surface, so the comparison is between rotations and not between a normal and a curvature direction. The angle between the hypothesised orientation of the sensed object (query_poses) and the stored one comes off the trace of their relative rotation — trace(R) = 1 + 2 cos θ — which is one element-wise product per hypothesis and node, and no Rotation at all. Scaled linearly so 0° is 1 and 180° is -1.

Rows are hypotheses and columns are the neighbours of each: query_poses is H orientations of three rows, node_poses is H lists of K stored pose vectors, each nine numbers row by row.

A channel whose pose is a surface is scored by pose_evidence/6 instead; this one is what Monty chooses for an object-orientation channel.