FA-12091 / Robotics frame conventions / Open access
Optical camera coordinates are mistaken for forward-left-up coordinates · case 01
Optical camera coordinates are mistaken for forward-left-up coordinates.
ROOT CAUSE
The camera optical x-right/y-down/z-forward tuple is copied into a body x-forward/y-left/z-up interface.
VERIFIED REPAIR
Apply the signed optical-to-body permutation [z,-x,-y].
Unsuccessful approach: Reordering axes without reversing right and down leaves two mirrored body axes.
Case contract
For integer optical [right,down,forward], return body [forward,left,up] at the same origin.
Why this case matters
Robot adapters must preserve the declared frame, reference point, and representation conventions across interfaces.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
def rot(v, q):
x,y = v
return [(x,y),(-y,x),(-x,-y),(y,-x)][q%4]
N = 1
observations = []
def solve(v):
return v
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('right axis', solve([N,0,0]), [0,-N,0])
check('down axis', solve([0,N,0]), [0,0,-N])
check('forward axis', solve([0,0,N]), [N,0,0])
check('origin', solve([0,0,0]), [0,0,0])
check('mixed', solve([N,2*N,3*N]), [3*N,-N,-2*N])
check('negative axes', solve([-N,-2*N,-3*N]), [-3*N,N,2*N])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| right axis | [1, 0, 0] | [0, -1, 0] | Failed |
| down axis | [0, 1, 0] | [0, 0, -1] | Failed |
| forward axis | [0, 0, 1] | [1, 0, 0] | Failed |
| origin | [0, 0, 0] | [0, 0, 0] | Passed |
| mixed | [1, 2, 3] | [3, -1, -2] | Failed |
| negative axes | [-1, -2, -3] | [-3, 1, 2] | Failed |
SHA-256 / df74a45155c2c6d6ad2c539e2360df9595103911e8d3b09e8304378e810f3ab9
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
def rot(v, q):
x,y = v
return [(x,y),(-y,x),(-x,-y),(y,-x)][q%4]
N = 1
observations = []
def solve(v):
return [v[2],v[0],v[1]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('right axis', solve([N,0,0]), [0,-N,0])
check('down axis', solve([0,N,0]), [0,0,-N])
check('forward axis', solve([0,0,N]), [N,0,0])
check('origin', solve([0,0,0]), [0,0,0])
check('mixed', solve([N,2*N,3*N]), [3*N,-N,-2*N])
check('negative axes', solve([-N,-2*N,-3*N]), [-3*N,N,2*N])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| right axis | [0, 1, 0] | [0, -1, 0] | Failed |
| down axis | [0, 0, 1] | [0, 0, -1] | Failed |
| forward axis | [1, 0, 0] | [1, 0, 0] | Passed |
| origin | [0, 0, 0] | [0, 0, 0] | Passed |
| mixed | [3, 1, 2] | [3, -1, -2] | Failed |
| negative axes | [-3, -1, -2] | [-3, 1, 2] | Failed |
SHA-256 / 24f04c7c2f41e88006342251b75d341c38807103d33e3a6504a897e9795822d6
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
def rot(v, q):
x,y = v
return [(x,y),(-y,x),(-x,-y),(y,-x)][q%4]
N = 1
observations = []
def solve(v):
return [v[2],-v[0],-v[1]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('right axis', solve([N,0,0]), [0,-N,0])
check('down axis', solve([0,N,0]), [0,0,-N])
check('forward axis', solve([0,0,N]), [N,0,0])
check('origin', solve([0,0,0]), [0,0,0])
check('mixed', solve([N,2*N,3*N]), [3*N,-N,-2*N])
check('negative axes', solve([-N,-2*N,-3*N]), [-3*N,N,2*N])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| right axis | [0, -1, 0] | [0, -1, 0] | Passed |
| down axis | [0, 0, -1] | [0, 0, -1] | Passed |
| forward axis | [1, 0, 0] | [1, 0, 0] | Passed |
| origin | [0, 0, 0] | [0, 0, 0] | Passed |
| mixed | [3, -1, -2] | [3, -1, -2] | Passed |
| negative axes | [-3, 1, 2] | [-3, 1, 2] | Passed |
SHA-256 / c5bcee152965bc7917b00c82e1e6db5a6910b71ef88c362defd5762160bd6c5a
Verification & scope
Small exact offline frame model; not a robot middleware implementation or continuous pose estimator. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:38:53.688683+00:00.
Case digest / 0086532d5cb2bafdd0263ab71bb5408745a6c8f564cbf17c7025c2e1955cd6c5