running Multiview

This commit is contained in:
chk
2026-05-28 17:55:00 +02:00
parent bb6a44e952
commit 18f0e61f49
10 changed files with 520 additions and 404 deletions

View File

@@ -488,6 +488,77 @@ def project_points(
return projected.reshape(-1, 2)
def compute_soft_constraint_residuals(
robot_state: Dict[str, float],
robot_markers: Dict[int, Dict[str, Any]],
link_transforms: Dict[str, np.ndarray],
robot: Dict[str, Any],
enabled_constraints: Dict[str, ConstraintResult]
) -> List[float]:
"""
Compute residuals from soft constraints (kinematic consistency, rigid body distances).
Returns a list of constraint residuals to append to the total residual vector.
"""
residuals = []
weight_scale = 0.1 # Weight for soft constraints relative to reprojection errors
# Constraint 1: Rigid body distances within each link
if enabled_constraints['RigidBodyDistances'].enabled:
for link_name in ['Arm1', 'Ellbow', 'Arm2']:
link_markers = [m for m in robot_markers.values() if m['link_name'] == link_name]
if len(link_markers) < 2:
continue
# Compute all pairwise distances in world coords
for i in range(len(link_markers)):
for j in range(i + 1, len(link_markers)):
m_i = link_markers[i]
m_j = link_markers[j]
pos_i = compute_marker_world_position(m_i, link_transforms)
pos_j = compute_marker_world_position(m_j, link_transforms)
dist_world = np.linalg.norm(pos_i - pos_j)
# Reference distance in local coords
dist_local = np.linalg.norm(m_i['position_m'] - m_j['position_m'])
# Residual: difference should be zero (rigid body)
error = dist_world - dist_local
residuals.append(error * weight_scale * 0.1) # Very soft weight
# Constraint 2: Fixed X-distances between links (Arm1 <-> Ellbow)
if enabled_constraints['InterLinkXDistances'].enabled:
arm1_markers = [m for m in robot_markers.values() if m['link_name'] == 'Arm1']
ellbow_markers = [m for m in robot_markers.values() if m['link_name'] == 'Ellbow']
if len(arm1_markers) >= 1 and len(ellbow_markers) >= 1:
# Get first marker from each link
m_arm1 = arm1_markers[0]
m_ellbow = ellbow_markers[0]
pos_arm1 = compute_marker_world_position(m_arm1, link_transforms)
pos_ellbow = compute_marker_world_position(m_ellbow, link_transforms)
# X-distance in world should match reference (relative position)
# Since both rotate around X-axis at different points, we check consistency
x_diff_world = pos_ellbow[0] - pos_arm1[0]
x_diff_ref = m_ellbow['position_m'][0] - m_arm1['position_m'][0]
error = x_diff_world - x_diff_ref
residuals.append(error * weight_scale)
return residuals
def compute_marker_world_position(marker: Dict[str, Any], link_transforms: Dict[str, np.ndarray]) -> np.ndarray:
"""Compute the world position of a marker given current link transforms."""
link_transform = link_transforms[marker['link_name']]
local_pos = np.concatenate([marker['position_m'], [1.0]])
world_pos = (link_transform @ local_pos)[:3]
return world_pos
# ------------------------------------------------------------------
# Optimization
# ------------------------------------------------------------------
@@ -520,12 +591,15 @@ def residuals_for_parameters(
robot_markers: Dict[int, Dict[str, Any]],
robot: Dict[str, Any],
scale: float,
default_state: Dict[str, float]
default_state: Dict[str, float],
enabled_constraints: Dict[str, ConstraintResult]
) -> np.ndarray:
robot_state, camera_params = unpack_parameters(params, len(views))
link_transforms = compute_link_transforms(robot, robot_state, scale)
residuals = []
# Reprojection residuals (primary observation)
for obs in observations:
marker = robot_markers[obs['marker_id']]
world_corners = compute_marker_world_corners(marker, link_transforms)
@@ -535,6 +609,7 @@ def residuals_for_parameters(
weight = math.sqrt(obs['confidence'])
residuals.extend((diffs * weight).reshape(-1))
# Weak priors on robot state
for key in STATE_KEYS:
diff = robot_state[key] - default_state.get(key, 0.0)
if key in ('x', 'y', 'z', 'e'):
@@ -543,9 +618,16 @@ def residuals_for_parameters(
w = 0.01
residuals.append(diff * w)
# Soft constraints (kinematic consistency, rigid body constraints)
soft_constraint_residuals = compute_soft_constraint_residuals(
robot_state, robot_markers, link_transforms, robot, enabled_constraints
)
residuals.extend(soft_constraint_residuals)
return np.asarray(residuals, dtype=np.float64)
def estimate_uncertainty(result: Any, n_params: int) -> np.ndarray:
if result.jac is None:
return np.full(n_params, float('nan'), dtype=np.float64)
@@ -563,9 +645,97 @@ def estimate_uncertainty(result: Any, n_params: int) -> np.ndarray:
return np.sqrt(np.diag(cov))
# ------------------------------------------------------------------
# Output assembly
# ------------------------------------------------------------------
def print_constraint_sanity_check(
robot_state: Dict[str, float],
robot_markers: Dict[int, Dict[str, Any]],
link_transforms: Dict[str, np.ndarray],
robot: Dict[str, Any],
enabled_constraints: Dict[str, ConstraintResult]
) -> None:
"""
Print sanity checks for all constraints to verify the optimization result.
"""
print("\n" + "=" * 70)
print("CONSTRAINT SANITY CHECKS (after optimization)")
print("=" * 70)
# Check 1: Rigid body distances
if enabled_constraints['RigidBodyDistances'].enabled:
print("\n1. RIGID BODY DISTANCES")
for link_name in ['Arm1', 'Ellbow', 'Arm2']:
link_markers = [m for m in robot_markers.values() if m['link_name'] == link_name]
if len(link_markers) < 2:
continue
max_error = 0.0
for i in range(len(link_markers)):
for j in range(i + 1, len(link_markers)):
m_i = link_markers[i]
m_j = link_markers[j]
pos_i = compute_marker_world_position(m_i, link_transforms)
pos_j = compute_marker_world_position(m_j, link_transforms)
dist_world = np.linalg.norm(pos_i - pos_j)
dist_local = np.linalg.norm(m_i['position_m'] - m_j['position_m'])
error = abs(dist_world - dist_local)
max_error = max(max_error, error)
status = "" if max_error < 1.0 else "" if max_error < 5.0 else ""
print(f" {link_name:10s}: max_error = {max_error:.3f} mm {status}")
# Check 2: Inter-link X distances
if enabled_constraints['InterLinkXDistances'].enabled:
print("\n2. INTER-LINK X-DISTANCES")
arm1_markers = [m for m in robot_markers.values() if m['link_name'] == 'Arm1']
ellbow_markers = [m for m in robot_markers.values() if m['link_name'] == 'Ellbow']
if len(arm1_markers) >= 1 and len(ellbow_markers) >= 1:
m_arm1 = arm1_markers[0]
m_ellbow = ellbow_markers[0]
pos_arm1 = compute_marker_world_position(m_arm1, link_transforms)
pos_ellbow = compute_marker_world_position(m_ellbow, link_transforms)
x_diff_world = pos_ellbow[0] - pos_arm1[0]
x_diff_ref = m_ellbow['position_m'][0] - m_arm1['position_m'][0]
error = abs(x_diff_world - x_diff_ref)
status = "" if error < 1.0 else "" if error < 5.0 else ""
print(f" Arm1 <-> Ellbow: error = {error:.3f} mm {status}")
# Check 3: Arm2 sin(a) dependency
if enabled_constraints['Arm2SinADependency'].enabled:
print("\n3. ARM2 sin(a) DEPENDENCY (sanity check)")
arm2_markers = [m for m in robot_markers.values() if m['link_name'] == 'Arm2']
if len(arm2_markers) >= 2:
# Check that markers with different Z values have different X spreads
a_rad = math.radians(robot_state['a'])
sin_a = math.sin(a_rad)
cos_a = math.cos(a_rad)
z_variations = {}
for m in arm2_markers:
z_local = m['position_m'][2]
x_local = m['position_m'][0]
pos_world = compute_marker_world_position(m, link_transforms)
x_world = pos_world[0]
# Expected: x_world = 90 + x_local * cos(a) - z_local * sin(a)
x_expected = 90 * (robot.get('renderingInfo', {}).get('metric', 'mm') == 'mm' and 0.09 or 0.09) + x_local * cos_a - z_local * sin_a
x_error = abs(x_world - x_expected)
if z_local not in z_variations:
z_variations[z_local] = []
z_variations[z_local].append(x_error)
max_error = max(max(errors) for errors in z_variations.values()) if z_variations else 0.0
status = "" if max_error < 5.0 else "" if max_error < 10.0 else ""
print(f" X-consistency with sin(a): max_error = {max_error:.3f} mm {status}")
print(f" (Note: this is a consistency check, not a hard constraint)")
print("=" * 70)
def camera_position_world(rvec: np.ndarray, tvec: np.ndarray) -> np.ndarray:
R, _ = cv2.Rodrigues(rvec)
@@ -705,6 +875,16 @@ def main() -> None:
}
robot_markers = extract_markers(robot, scale)
# Validate constraints
print("\n" + "=" * 70)
print("CONSTRAINT VALIDATION")
print("=" * 70)
enabled_constraints = validate_constraints(robot, robot_markers)
for constraint_name, result in enabled_constraints.items():
print(result)
print("=" * 70)
views, observations = collect_views_and_observations(args.detections, robot_markers)
camera_guesses = []
@@ -725,7 +905,7 @@ def main() -> None:
progress['iter'] += 1
now = time.time()
if progress['iter'] == 1 or now - progress['last_print'] >= 1.0:
res = residuals_for_parameters(xk, views, observations, robot_markers, robot, scale, default_state)
res = residuals_for_parameters(xk, views, observations, robot_markers, robot, scale, default_state, enabled_constraints)
cost = 0.5 * float(np.dot(res, res))
delta_cost = None
convergence = ''
@@ -751,7 +931,7 @@ def main() -> None:
result = least_squares(
residuals_for_parameters,
x0,
args=(views, observations, robot_markers, robot, scale, default_state),
args=(views, observations, robot_markers, robot, scale, default_state, enabled_constraints),
jac='2-point',
method='trf',
loss='soft_l1',
@@ -762,6 +942,10 @@ def main() -> None:
robot_state, camera_params = unpack_parameters(result.x, len(views))
uncertainties = estimate_uncertainty(result, len(result.x))
# Print constraint sanity checks
link_transforms = compute_link_transforms(robot, robot_state, scale)
print_constraint_sanity_check(robot_state, robot_markers, link_transforms, robot, enabled_constraints)
output = build_output(robot_state, uncertainties[:len(STATE_KEYS)], views, camera_params, observations, robot_markers, scale, robot, robot_json_path)

File diff suppressed because it is too large Load Diff

View File

@@ -1,31 +1,31 @@
{
"final_cost": 25086.49759096419,
"final_cost": 24986.21700952237,
"status": 0,
"message": "The maximum number of function evaluations is exceeded.",
"robot_state": {
"state": {
"x": 100.74147204793623,
"y": 29.650679871841962,
"z": -35.519338413527834,
"a": -119.76253895286006,
"b": 22.000000000000124,
"c": 91.00000000000006,
"e": 9.999999999999991
"x": 100.65052085564044,
"y": 29.661249073864987,
"z": -35.948789524024555,
"a": -119.85307495241203,
"b": 21.99999999999959,
"c": 90.99999999999991,
"e": 10.000000000000025
},
"uncertainty": {
"x_mm": 5958.291819057341,
"y_mm": 1161.4246555312698,
"z_mm": 548.5614212936815,
"a_deg": 3375.9445110397996,
"b_deg": 13762.367585907954,
"c_deg": 13762.368814943879,
"e_mm": 137623.68210441121
"x_mm": 1490.1455410993876,
"y_mm": 429.51650769405427,
"z_mm": 477.27281993275335,
"a_deg": 3533.703361743133,
"b_deg": 13152.589314453906,
"c_deg": 13152.589314528996,
"e_mm": 131525.9153573403
},
"confidence": {
"x": 1.7166198945166287e-259,
"y": 3.630513831255408e-51,
"z": 1.5006526335068334e-24,
"a": 2.424335742250214e-147,
"x": 1.922212631331247e-65,
"y": 2.219908541429891e-19,
"z": 1.8719954726562647e-21,
"a": 3.4136023686230135e-154,
"b": 0.0,
"c": 0.0,
"e": 0.36787944117144233

View File

@@ -1,6 +1,6 @@
{
"schema_version": "1.0",
"created_utc": "2026-05-28T15:11:26Z",
"created_utc": "2026-05-28T15:43:43Z",
"vision_config": {
"MarkerType": "DICT_4X4_250",
"MarkerSize": 0.025
@@ -46,7 +46,7 @@
},
"detections": [
{
"observation_id": "a0864373-2016-4c0c-be4d-c8b66b185bd7",
"observation_id": "713817fc-5f5b-486d-850a-2b1915ab7eac",
"type": "aruco",
"marker_id": 102,
"marker_size_m": 0.025,
@@ -100,7 +100,7 @@
"confidence": 0.9494437061622057
},
{
"observation_id": "2d237a4b-33db-4a97-aad0-2b69922e5c27",
"observation_id": "cc667670-1b39-4632-8f1c-1a5fdf0e0c7e",
"type": "aruco",
"marker_id": 243,
"marker_size_m": 0.025,
@@ -154,7 +154,7 @@
"confidence": 0.8899728634608616
},
{
"observation_id": "a01227d1-d980-435e-ad0f-453789a6e941",
"observation_id": "0cd34a97-e5d7-4bbf-aac9-a4e203b31583",
"type": "aruco",
"marker_id": 210,
"marker_size_m": 0.025,
@@ -208,7 +208,7 @@
"confidence": 0.5673043275049208
},
{
"observation_id": "8044b2a7-1af6-457d-b112-8566c669e961",
"observation_id": "5632f4b1-0db1-4a98-b8d3-9ebbbb4b126f",
"type": "aruco",
"marker_id": 247,
"marker_size_m": 0.025,
@@ -262,7 +262,7 @@
"confidence": 0.8796777163094818
},
{
"observation_id": "dac561f0-1939-438d-9ed1-5d057d5132dd",
"observation_id": "75ae283a-9ba7-43bc-bb54-ba44e24e235f",
"type": "aruco",
"marker_id": 246,
"marker_size_m": 0.025,
@@ -316,7 +316,7 @@
"confidence": 0.8015179238063419
},
{
"observation_id": "33c3c11c-f7d2-4038-ac2c-e4332bcf5b79",
"observation_id": "7c280cd2-7b94-476a-be3e-7d89e6e35ed3",
"type": "aruco",
"marker_id": 101,
"marker_size_m": 0.025,
@@ -370,7 +370,7 @@
"confidence": 0.3325004465415643
},
{
"observation_id": "3ae8ec72-f806-457c-8c60-403428368c0a",
"observation_id": "2e554970-1749-4924-ac98-3ac4debec51b",
"type": "aruco",
"marker_id": 215,
"marker_size_m": 0.025,
@@ -424,7 +424,7 @@
"confidence": 0.7952557920267838
},
{
"observation_id": "755f017d-cb90-461d-bd57-25768e592696",
"observation_id": "cc766bc2-4f75-4520-baf3-e10c62f6c25d",
"type": "aruco",
"marker_id": 124,
"marker_size_m": 0.025,
@@ -478,7 +478,7 @@
"confidence": 0.34091855704160245
},
{
"observation_id": "45854ae6-7ba9-4906-87a6-2c7d9356cb85",
"observation_id": "c7cc54fc-982b-46e8-b176-82eefba18404",
"type": "aruco",
"marker_id": 229,
"marker_size_m": 0.025,
@@ -532,7 +532,7 @@
"confidence": 0.26810902547334975
},
{
"observation_id": "de3abf0b-4ae2-4fee-9215-2039b0f5e3da",
"observation_id": "7cd2ae3d-740e-4005-a8b8-b23b0ea0082a",
"type": "aruco",
"marker_id": 122,
"marker_size_m": 0.025,
@@ -586,7 +586,7 @@
"confidence": 0.18665602922528673
},
{
"observation_id": "5577fb36-2186-41f8-8fbf-40266f9e767c",
"observation_id": "95fcb10e-a4e9-4d43-8950-8d0523fe95aa",
"type": "aruco",
"marker_id": 198,
"marker_size_m": 0.025,
@@ -640,7 +640,7 @@
"confidence": 0.20150745250271476
},
{
"observation_id": "54aec13c-2b54-49d8-a9c6-e873eb94dfef",
"observation_id": "e14fdb7d-e877-4a87-9e58-430ac0f56f18",
"type": "aruco",
"marker_id": 211,
"marker_size_m": 0.025,
@@ -694,7 +694,7 @@
"confidence": 0.6412317666518965
},
{
"observation_id": "4cf08f15-d8f2-416d-8397-8a68f564d0a8",
"observation_id": "7a8a865f-1251-4024-9255-278cb4cb527f",
"type": "aruco",
"marker_id": 208,
"marker_size_m": 0.025,
@@ -748,7 +748,7 @@
"confidence": 0.6280424706698967
},
{
"observation_id": "72d6524a-3710-46b2-b036-5031b7d2e648",
"observation_id": "d920e29d-6dd3-41f5-affb-0d25e5bdb1f7",
"type": "aruco",
"marker_id": 217,
"marker_size_m": 0.025,
@@ -802,7 +802,7 @@
"confidence": 0.35596573288593486
},
{
"observation_id": "160f705f-87e0-41e2-90f6-b39252bff719",
"observation_id": "4024cff0-440d-4688-add4-aaef71fd8566",
"type": "aruco",
"marker_id": 206,
"marker_size_m": 0.025,
@@ -856,7 +856,7 @@
"confidence": 0.33820423087105295
},
{
"observation_id": "03b79b60-9fb5-4aa8-82b6-303911389999",
"observation_id": "7019c1d8-7fcf-44ef-8ea5-407577eff29c",
"type": "aruco",
"marker_id": 205,
"marker_size_m": 0.025,
@@ -910,7 +910,7 @@
"confidence": 0.28724459014346065
},
{
"observation_id": "bc11412b-140e-48b9-9c27-aed1d54bd4b2",
"observation_id": "17746037-a944-46b0-a817-efcd1d0fddb5",
"type": "aruco",
"marker_id": 207,
"marker_size_m": 0.025,

View File

@@ -1,68 +0,0 @@
{
"source_detection_json": "C:\\Users\\kech\\SynologyDrive\\2026-AppServer-AppRobot\\appRobotRendering\\pipeline\\render_1a_aruco_detection.json",
"camera_pose": {
"camera_position_world_mm": [
-170.9856733813686,
-471.25256740269396,
878.0637115557477
],
"rotation_matrix_world_to_camera": [
[
0.6349401350180643,
-0.7720226356185085,
0.028845710875162883
],
[
-0.5994288656515463,
-0.5158601484722065,
-0.6120239719503914
],
[
0.48737671258169724,
0.3713076316356623,
-0.7903129650475013
]
],
"rotation_matrix_camera_to_world": [
[
0.6349401350180643,
-0.5994288656515463,
0.48737671258169724
],
[
-0.7720226356185085,
-0.5158601484722065,
0.3713076316356623
],
[
0.028845710875162883,
-0.6120239719503914,
-0.7903129650475013
]
],
"rvec": [
2.291386890593113,
-1.0684818045197042,
0.4021828449915483
],
"tvec": [
-280.5803545388054,
191.8018727459298,
952.2592454759357
]
},
"reprojection_error_px": {
"mean": 2.4146498455755063,
"max": 4.819015530727733,
"per_marker": {
"210": 2.3216790986770164,
"215": 2.074953107734691,
"211": 4.819015530727733,
"208": 1.4794063810568414,
"217": 1.782847281148554,
"206": 2.714840043046132,
"205": 2.5310207449984325,
"207": 1.593436577214649
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

View File

@@ -1,6 +1,6 @@
{
"schema_version": "1.0",
"created_utc": "2026-05-28T15:11:26Z",
"created_utc": "2026-05-28T15:43:43Z",
"vision_config": {
"MarkerType": "DICT_4X4_250",
"MarkerSize": 0.025
@@ -46,7 +46,7 @@
},
"detections": [
{
"observation_id": "5f47acb3-66c2-48ba-b83b-d8e07aa2f6ec",
"observation_id": "b47ae404-2374-4364-bddc-c3e6282f9754",
"type": "aruco",
"marker_id": 102,
"marker_size_m": 0.025,
@@ -100,7 +100,7 @@
"confidence": 0.8913851020933449
},
{
"observation_id": "4d7aea08-c7e4-45a9-8fba-c738360a4a09",
"observation_id": "5643f91d-1fc0-43db-b40b-78ef116132a8",
"type": "aruco",
"marker_id": 124,
"marker_size_m": 0.025,
@@ -154,7 +154,7 @@
"confidence": 0.4804167810936165
},
{
"observation_id": "3675fbfb-7387-4ab7-8cdd-c581dbb46a48",
"observation_id": "eb068542-bc32-4241-9f94-ae93cba29146",
"type": "aruco",
"marker_id": 243,
"marker_size_m": 0.025,
@@ -208,7 +208,7 @@
"confidence": 0.9132502955127223
},
{
"observation_id": "f430fa70-8024-4ea7-9318-ad33908e0622",
"observation_id": "98da437d-8a22-4a73-8075-137b743bca43",
"type": "aruco",
"marker_id": 122,
"marker_size_m": 0.025,
@@ -262,7 +262,7 @@
"confidence": 0.9456847621099602
},
{
"observation_id": "3351b253-537e-4499-8114-52e7873706c4",
"observation_id": "f0ec764f-dbdf-4170-8cff-c3f5c940e82b",
"type": "aruco",
"marker_id": 247,
"marker_size_m": 0.025,
@@ -316,7 +316,7 @@
"confidence": 0.7448005120854795
},
{
"observation_id": "d39337f3-7a27-4ce7-adf0-24fbe9ac65ea",
"observation_id": "bddd6015-4815-41b2-bd83-dd9acce3a41b",
"type": "aruco",
"marker_id": 246,
"marker_size_m": 0.025,
@@ -370,7 +370,7 @@
"confidence": 0.7581700566520715
},
{
"observation_id": "f3bd397e-3c02-4645-b43a-3f292bdf29fa",
"observation_id": "6bb1f556-4a03-4bf1-90ce-59aedab7b2ee",
"type": "aruco",
"marker_id": 215,
"marker_size_m": 0.025,
@@ -424,7 +424,7 @@
"confidence": 0.826449608683203
},
{
"observation_id": "e76f83e2-0558-4588-bed4-de9ba1644b18",
"observation_id": "dd82dba6-3cea-4e60-b64a-6ad94127dd37",
"type": "aruco",
"marker_id": 210,
"marker_size_m": 0.025,
@@ -478,7 +478,7 @@
"confidence": 0.7813266383036261
},
{
"observation_id": "36a7eaf1-6608-450c-90c2-6a8284457c88",
"observation_id": "ed953a44-f516-4275-bc07-b6857fe8f8ee",
"type": "aruco",
"marker_id": 229,
"marker_size_m": 0.025,
@@ -532,7 +532,7 @@
"confidence": 0.18684041285479083
},
{
"observation_id": "18049602-5f59-48b6-914b-cefe7203fe3b",
"observation_id": "27bccaa2-ec68-4f8b-991b-585a270ca491",
"type": "aruco",
"marker_id": 198,
"marker_size_m": 0.025,

View File

@@ -1,6 +1,6 @@
{
"schema_version": "1.0",
"created_utc": "2026-05-28T15:11:27Z",
"created_utc": "2026-05-28T15:43:44Z",
"vision_config": {
"MarkerType": "DICT_4X4_250",
"MarkerSize": 0.025
@@ -46,7 +46,7 @@
},
"detections": [
{
"observation_id": "2dd90714-6c72-4eef-add7-476c5f768882",
"observation_id": "981a123d-7560-4fbe-93f1-d47980472b76",
"type": "aruco",
"marker_id": 102,
"marker_size_m": 0.025,
@@ -100,7 +100,7 @@
"confidence": 0.7012635429952238
},
{
"observation_id": "2b3b1621-eabd-4e73-8638-4830ff614dca",
"observation_id": "7676c338-2b2b-4bdb-864d-b6839291742b",
"type": "aruco",
"marker_id": 122,
"marker_size_m": 0.025,
@@ -154,7 +154,7 @@
"confidence": 0.5749326438029929
},
{
"observation_id": "c87294de-3f5e-4ecd-b7ad-1665989bc0ae",
"observation_id": "1476f720-1d72-4d94-b24b-b02e5e2d1a76",
"type": "aruco",
"marker_id": 243,
"marker_size_m": 0.025,
@@ -208,7 +208,7 @@
"confidence": 0.9491420540234864
},
{
"observation_id": "34650367-22d5-4d90-9a88-282957232989",
"observation_id": "f1bcb96e-0cf8-4c69-a4c1-fbeb03650fa2",
"type": "aruco",
"marker_id": 246,
"marker_size_m": 0.025,
@@ -262,7 +262,7 @@
"confidence": 0.4780463267147134
},
{
"observation_id": "e1603207-bb10-4f2c-9dd8-353447302ecf",
"observation_id": "a8bf2494-ddd8-4bf6-b87d-42182112e4e3",
"type": "aruco",
"marker_id": 247,
"marker_size_m": 0.025,
@@ -316,7 +316,7 @@
"confidence": 0.5106218488640142
},
{
"observation_id": "bbb6f5cd-12a4-4078-9f2b-d1c7160eb5f4",
"observation_id": "642b867d-25d1-4407-9011-f7a62feed435",
"type": "aruco",
"marker_id": 214,
"marker_size_m": 0.025,
@@ -370,7 +370,7 @@
"confidence": 0.6041252446922665
},
{
"observation_id": "c88f0aac-ae92-4559-9469-8ae96275d717",
"observation_id": "623e960d-2058-4672-b06c-5316a5861158",
"type": "aruco",
"marker_id": 210,
"marker_size_m": 0.025,