Resource: turn about a joint, and the links and end-effectors that need it - #1249
Open
BioCam wants to merge 5 commits into
Open
Resource: turn about a joint, and the links and end-effectors that need it#1249BioCam wants to merge 5 commits into
Resource: turn about a joint, and the links and end-effectors that need it#1249BioCam wants to merge 5 commits into
Conversation
…need it An articulated device has joints that are not at a resource's own corner, and nothing in PyLabRobot could express one. A plate hotel's carousel, a centrifuge rotor, a hinge, and every link of an arm pivot on a point somewhere on the part; `Resource.rotate` has always turned about the left front bottom corner, so a link modelled today swings off its own joint. - `rotate` and `rotated` take an optional `reference`: the point to turn about, in the resource's own frame. The resource is carried by however far the turn moved that point, which leaves the point where it was and the resource swinging on it. `reference` is measured in the resource's frame while `location` is measured in the parent's, so the offset is taken back through the parent's rotation, a rotation matrix inverting by transposition. - `Link` is one rigid member of a chain: a line between two joints, with no width or depth, so the joint it turns on is its own origin. Material is `bolt_on`'d as children with their own offsets, which is how a robot description keeps a link's frame apart from the shape around it - the shape can overhang either joint without the kinematics noticing. - `MechanicalGripper` is a `Link`, because on an arm that is what it is: it spans the joint it turns on to the point it grips at, which is its tool centre point. Its body, fingers and pads are material bolted to that span, and how far apart the fingers stand is state rather than shape. Behaviour: `reference` defaults to None and the added path is skipped entirely without one, so every existing caller turns about the corner exactly as before. Tests: the primitives are new, so both carry their own - a chain folding on its joints, `turn_to` being absolute where `rotate` accumulates, `bolt_on` centring material across a link, the jaws standing symmetrically at a commanded width and refusing one they cannot reach, and a pad sitting the same way on both fingers. `resource_tests` covers the pivot itself, asserting on the reference point standing still rather than on the location that moves to keep it there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ce and tool centre point
The module docstring named a tool centre point without saying what it is measured from, and
justified the gripper being a `Link` by asserting it ("it is a link, because that is what it is on
an arm"). It now uses the vocabulary a reader arrives with - end-effector, tool and end-of-arm
tooling as one thing, fitted at the wrist flange - and states the tool centre point as an offset
from that flange, belonging to the tool rather than to the arm.
That offset is what makes the gripper a link: it spans the interface it is bolted to and the point
it grips at, which is the same separation ROS-Industrial draws between `flange` and a tool frame.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…esource` does not `Finger` added one attribute over `Resource`: a `pad` pointing at a resource `bolt_on` had already assigned as its child, so `finger.pad is finger.children[0]`. Nothing outside the module read it, nothing type-checked against the class, and the viewer tells a finger from a pad by category, which is set either way. The `cast(Finger, ...)` at its only construction existed to let mypy accept the `pad` assignment - the class's sole consumer was the attribute that was its sole reason to exist. Its docstring said as much: a list of two things it would carry "once there is something to read them from". It can come back the day one of them arrives with a field in it. The pads are kept as `self.pads`, which is how the one external caller already reaches them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`bolt_on` was a factory wrapped around `assign_child_resource`, and of the five things it added only one was geometry: `-size_y / 2`, centring material across the link it hangs on. The rest was naming, a model string, a `category` taken by splitting the name on an underscore, and an `of=` parameter with no caller left once `Finger` went. Its four arguments were also a bare five-number tuple - size, offset along, offset above - which says nothing at the call site about which number is which. Each part is now constructed and assigned where it is used, with the five numbers unpacked into named locals, so the placement rule is visible rather than applied out of sight. The pad no longer has its Y written and then overwritten a line later: the offset is computed once. Behaviour: both trees are byte-identical to what `bolt_on` built - every name, category, model and location - checked against a snapshot taken before the change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…-number tuple A part arrived as `(size_x, size_y, size_z, along, above)`, which says nothing at the call site about which number is which and puts two offsets in different axes beside three sizes. It is the shape an argument gets swapped in, and no type checker would notice. Each part is now a `Coordinate` for its size and a `Coordinate` for where it sits, which are the two types the resource model already has: `Resource` carries a size and a category, `assign_child_resource` takes a location, and `location` moves it afterwards. Nothing new is defined to hold them. A finger is the exception and now says so: it takes a size and an X and Z, and its Y belongs to `jaw_width` outright rather than being declared and overwritten. Behaviour: unchanged, and the tree is byte-identical to the one the tuples built. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An articulated device has joints that are not at a resource's own corner, and nothing in PyLabRobot can express one. A carousel, a rotor, a hinge, every link of an arm - all pivot on a point somewhere on the part, and
Resource.rotatehas always turned about the left front bottom corner, so a link modelled today swings off its joint rather than on it.rotateandrotatedtake an optionalreference: the point to turn about, in the resource's own frame. The resource is carried by however far the turn moved that point, so the point stays put and the resource swings on it. The offset is taken back through the parent's rotation, sincereferenceis measured in the resource's frame andlocationin the parent's.Linkis one rigid member of a chain - a line between two joints, no width or depth, so the joint it turns on is its own origin. Material hangs off it as children throughbolt_on, which keeps a link's frame apart from the shape around it.MechanicalGripperis aLink: it spans the joint it turns on to the point it grips at, its tool centre point. Body, fingers and pads are bolted to that span, and how far apart the fingers stand is state rather than shape.Behaviour: unchanged.
referencedefaults to None, and both the matrix build and the offset are skipped without one, sorotatecosts what it always did at any depth.Tests: the new primitives carry their own - a chain folding on its joints,
turn_tobeing absolute whererotateaccumulates,bolt_onplacing material, the jaws standing symmetrically and refusing a width they cannot reach, and a pad sitting the same way on both fingers.resource_testscovers the pivot, asserting the reference point stands still rather than that the location moved. Full suite passes, 3203 tests.A
referencegiven for a resource with nolocationis ignored rather than refused, which wants its own decision. This also touches the same three lines ofrotateas #1247, so whichever lands second carries a small merge.🤖 Generated with Claude Code