Grasping analysis API
The interactive grasping demo uses a randomly wandering ball. The analysis package
supports measured comparisons by presenting the same predefined ball visit to each
robot. These tools are separate from GraspingWorld: they configure and observe the
demonstrated behavior without changing a robot’s decisions.
A GraspingEncounter defines the ball’s starting distance and movement. Negative
velocity approaches the jaws and positive velocity moves away. Its opportunity
interval states when capture counts as a valid response; the robots cannot read this
interval. Optional noise, dropouts, and false detections alter only the proximity
reading.
from qrobot_simulator.grasping_world import ClassicalGripper
from qrobot_simulator.grasping_world.analysis import (
ControlledGraspingWorld,
GraspingEncounter,
MotionSegment,
ProximityDisturbance,
TimeInterval,
record_encounter,
)
encounter = GraspingEncounter(
initial_distance=24.0,
motion=(
MotionSegment(duration=2.0, velocity=-5.0),
MotionSegment(duration=2.5, velocity=0.0),
MotionSegment(duration=2.0, velocity=5.0),
),
opportunity=TimeInterval(start=1.8, duration=2.7),
disturbance=ProximityDisturbance(noise_standard_deviation=0.05),
)
world = ControlledGraspingWorld.create(ClassicalGripper(), encounter, seed=7)
record = record_encounter(world, duration=encounter.duration, dt=0.05)
print(record.outcome.label, record.outcome.capture_latency)
record.samples contains the readings, jaw command, and physical state at each
step. record.events identifies closing, capture, consumption, opening, and failed
actions. record.outcome derives the encounter result and response times from those
events. record.metadata retains the configurations, seeds, duration, and physics
step needed to identify the run. Trial generation, parameter selection, aggregate
statistics, and paper figures belong in the experiment repository.
- class qrobot_simulator.grasping_world.analysis.ControlledGraspingWorld(arena: GraspingArena, gripper: BaseGripper, ball: BallPrey, config: GraspingWorldConfig = GraspingWorldConfig(near_distance=5.0, far_distance=20.0, minimum_distance=5.0, grippable_distance=15.0, consumption_time=2.5, ball_distance_scale=0.16, sensor_offset_x=0.55, arena_width=12.0, arena_height=6.0, arena_cell_size=1.0), prey_config: BallPreyConfig = BallPreyConfig(radius=0.32, color='#2878d0', max_distance=45.0, initial_distance_range=(24.0, 40.0), respawn_distance_range=(30.0, 45.0), initial_velocity_range=(-1.0, 1.0), velocity_kick_range=(-4.0, 4.0), max_speed=7.0, motion_change_interval=(0.35, 1.1), max_near_duration=1.0, escape_speed=5.0), elapsed: float = 0.0, touch_pressed: bool = False, readings: dict[str, float]=<factory>, correct_grips: int = 0, missed_grips: int = 0, empty_grips: int = 0, consumed_prey: int = 0, premature_releases: int = 0, seed: int | None = None, grip_response_times: list[float] = <factory>, _inside_visit: bool = False, _visit_gripped: bool = False, _consumption_started_at: float | None = None, _visit_started_at: float | None = None, _rng: Random = <factory>)[source]
Present one predefined ball visit instead of randomly wandering prey.
This class uses the sensors and physical interactions of GraspingWorld, but the analysis code supplies the ball’s starting distance, movement, and optional sensor errors. Consumed prey does not respawn because each instance represents one visit. The random demonstration remains entirely in GraspingWorld.
- classmethod create(gripper: BaseGripper, encounter: GraspingEncounter, seed: int | None = None, disturbance_seed: int | None = None, config: GraspingWorldConfig = GraspingWorldConfig(near_distance=5.0, far_distance=20.0, minimum_distance=5.0, grippable_distance=15.0, consumption_time=2.5, ball_distance_scale=0.16, sensor_offset_x=0.55, arena_width=12.0, arena_height=6.0, arena_cell_size=1.0), prey_config: BallPreyConfig = BallPreyConfig(radius=0.32, color='#2878d0', max_distance=45.0, initial_distance_range=(24.0, 40.0), respawn_distance_range=(30.0, 45.0), initial_velocity_range=(-1.0, 1.0), velocity_kick_range=(-4.0, 4.0), max_speed=7.0, motion_change_interval=(0.35, 1.1), max_near_duration=1.0, escape_speed=5.0)) ControlledGraspingWorld[source]
Create one repeatable visit for a classical or quantum gripper.
- class qrobot_simulator.grasping_world.analysis.GraspingEncounter(initial_distance: float, motion: tuple[MotionSegment, ...], opportunity: TimeInterval | None, disturbance: ProximityDisturbance = ProximityDisturbance(noise_standard_deviation=0.0, dropouts=(), false_positives=()))[source]
Define the exogenous inputs and ground truth of one paired encounter.
motionis a sequence of constant-velocity segments. Negative velocity approaches the gripper and positive velocity moves away.opportunityis ground-truth metadata for experiment scoring; it does not alter the physics.- property duration: float
Return the total simulated duration of all motion segments.
- class qrobot_simulator.grasping_world.analysis.MotionSegment(duration: float, velocity: float)[source]
Command one constant ball velocity for a simulated duration.
- class qrobot_simulator.grasping_world.analysis.TimeInterval(start: float, duration: float)[source]
Represent one half-open interval in simulated seconds.
- class qrobot_simulator.grasping_world.analysis.ProximityDisturbance(noise_standard_deviation: float = 0.0, dropouts: tuple[TimeInterval, ...] = (), false_positives: tuple[TimeInterval, ...] = ())[source]
Configure repeatable noise, dropouts, and false-positive intervals.
Dropouts and false positives replace the clean reading during their configured intervals. A dropout takes precedence if the two kinds of interval overlap. Gaussian noise is then added and the result is clipped to the sensor range.
- class qrobot_simulator.grasping_world.analysis.GraspingRunRecord(samples: tuple[GraspingSample, ...], events: tuple[GraspingEvent, ...], metadata: GraspingRunMetadata, outcome: GraspingOutcome)[source]
Collect raw samples, events, setup metadata, and the derived result.
- class qrobot_simulator.grasping_world.analysis.GraspingSample(elapsed: float, ball_distance: float, ball_velocity: float, ball_present: bool, ball_caught: bool, gripper_closed: bool, activation: float, proximity: float, touch: float, valid_opportunity: bool, diagnostics: dict[str, float | None])[source]
Store everything needed to inspect one instant of the simulation.
The sample contains the readings available to the brain, its returned jaw command, and the physical state after that command has been applied.
- class qrobot_simulator.grasping_world.analysis.GraspingEvent(elapsed: float, kind: Literal['jaws_closed', 'prey_captured', 'empty_closure', 'prey_consumed', 'jaws_opened', 'premature_release'])[source]
Record one discrete physical action or consequence and when it occurred.
- class qrobot_simulator.grasping_world.analysis.GraspingOutcome(label: Literal['true_positive', 'false_positive', 'false_negative', 'correct_rejection'], capture_latency: float | None, release_latency: float | None, premature_releases: int, extra_closures: int, failed_release: bool)[source]
Summarize whether the robot acted correctly during one encounter.
A valid encounter is a true positive when prey is captured during the declared opportunity and a false negative otherwise. An encounter without an opportunity is a false positive when the robot closes its jaws and a correct rejection when it leaves them open.
Capture latency measures the delay from the start of a valid opportunity to capture. Release latency measures the delay from consumption to the first subsequent opening.
failed_releaseis true when consumed prey disappears but the robot is still closed when recording ends.
- class qrobot_simulator.grasping_world.analysis.GraspingRunMetadata(encounter: GraspingEncounter, world_config: GraspingWorldConfig, prey_config: BallPreyConfig, gripper_config: BaseGripperConfig, seed: int | None, disturbance_seed: int | None, duration: float, physics_step: float)[source]
Identify the complete setup required to repeat one recorded run.