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
dthe hypothesis moves topose · 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
Add this observation's evidence to the hypotheses worth testing.
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
Functions
@spec compute_evidence( t(), %{optional(String.t()) => map()}, float(), String.t(), Monty.Frameworks.Models.EvidenceMatching.Hypotheses.t(), keyword() ) :: {Monty.Frameworks.Models.EvidenceMatching.Hypotheses.t(), Monty.Frameworks.Models.EvidenceMatching.HypothesesDisplacer.HypothesisDisplacerTelemetry.t()}
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, fromnode_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.
@spec displace_hypotheses( t(), Monty.Frameworks.Models.EvidenceMatching.Hypotheses.t(), [number()] ) :: Monty.Frameworks.Models.EvidenceMatching.Hypotheses.t()
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.
@spec new(Monty.Frameworks.Models.GraphMatching.GraphMemory.t(), keyword()) :: t()
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.
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.
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.