POMDPPlanners.environments.push_pomdp package
Push POMDP Environment Module.
This module provides the Push POMDP environment implementation and related components for robotic manipulation tasks.
- Classes:
PushPOMDP: Main POMDP environment for robotic push tasks PushPOMDPVisualizer: Visualization utilities for Push POMDP episodes ContinuousPushPOMDP: Continuous-action Push POMDP environment ContinuousPushPOMDPDiscreteActions: Discrete-action wrapper
- class POMDPPlanners.environments.push_pomdp.ContinuousPushPOMDP(discount_factor, grid_size=10, push_threshold=1.0, friction_coefficient=0.3, max_push=2.0, observation_noise=0.1, obstacles=None, obstacle_penalty=-10.0, obstacle_hit_probability=1.0, dangerous_areas=None, dangerous_area_radius=0.5, dangerous_area_penalty=-10.0, dangerous_area_hit_probability=1.0, reward_model_type=RewardModelType.CONSTANT_HAZARD_PENALTY, penalty_decay=1.0, robot_radius=0.3, state_transition_cov_matrix=array([[0.1, 0.], [0., 0.1]]), initial_state=None, name='ContinuousPushPOMDP', output_dir=None, debug=False, use_queue_logger=False)[source]
Bases:
EnvironmentContinuous-action Push POMDP environment.
A robot (circle) must push an object (point) to a target location on a 2D grid. The robot moves via continuous 2D action vectors with Gaussian noise; obstacles are axis-aligned squares.
State: [robot_x, robot_y, object_x, object_y, target_x, target_y] Actions: 2D numpy vectors Observations: [robot_x, robot_y, noisy_obj_x, noisy_obj_y, target_x, target_y]
- Stochasticity:
The obstacle-collision penalty can be applied either deterministically (the default) or stochastically. When
obstacle_hit_probability == 1.0(default), the penalty is applied every time the post-action robot position overlaps an obstacle AABB, matching legacy behavior. Whenobstacle_hit_probability < 1.0, the penalty is applied only with that probability perreward()/reward_batch()call (one Bernoulli draw per state), producing a heavy-tailed return distribution suitable for benchmarking risk-sensitive planners (e.g. ICVaR-aware MCTS) against expected-value MCTS on the same env. Note that this makesreward(state, action)non- deterministic given a state-action pair, so any external caching that assumes deterministic rewards must be aware of this.transition_log_probabilityis unaffected. The native C++ rollout applies the Bernoulliobstacle_hit_probabilitydraw internally, sosimulate_random_rolloutalways routes through the native kernel.- Dangerous areas:
dangerous_areasis a separate, additive concept fromobstacles. Each entry is a circular region centred at(x, y)with radiusdangerous_area_radius. Entering a dangerous area appliesdangerous_area_penalty(a negative number, added to reward) but does NOT block movement (unlike obstacles, which act as walls in the continuous variant). The penalty fires when the post-action robot position lies inside any dangerous area; the object position is ignored. At most onedangerous_area_penaltyis applied per step even when multiple zones overlap. Like obstacles, the penalty supports a Bernoullidangerous_area_hit_probability(default 1.0) for risk-sensitive planning. The native C++ rollout applies the Bernoulli draw internally, so all rollouts route through the native kernel regardless of the configured probability.
Example
>>> import numpy as np >>> np.random.seed(42) >>> >>> env = ContinuousPushPOMDP(discount_factor=0.99) >>> >>> initial_state = env.initial_state_dist().sample()[0] >>> >>> action = np.array([1.0, 0.0]) >>> next_state, observation, reward = env.sample_next_step(initial_state, action) >>> >>> env.is_terminal(initial_state) False
- Parameters:
discount_factor (float)
grid_size (int)
push_threshold (float)
friction_coefficient (float)
max_push (float)
observation_noise (float)
obstacle_penalty (float)
obstacle_hit_probability (float)
dangerous_area_radius (float)
dangerous_area_penalty (float)
dangerous_area_hit_probability (float)
reward_model_type (RewardModelType)
penalty_decay (float)
robot_radius (float)
state_transition_cov_matrix (ndarray)
initial_state (ndarray | None)
name (str)
output_dir (Path | None)
debug (bool)
use_queue_logger (bool)
- cache_visualization(history, cache_path)[source]
Cache animated visualization of the continuous push episode.
Creates an animated GIF showing the robot pushing the object toward the target, with rectangular obstacles, collision detection, distance indicators, and success feedback.
- Parameters:
- Raises:
ValueError – If history is empty or cache_path doesn’t end with .gif.
TypeError – If cache_path is not a Path object.
- Return type:
- compute_metrics(histories)[source]
Compute environment-specific metrics from episode histories.
This method can be overridden by subclasses to provide custom metric calculations beyond standard return and episode length.
- hash_action(action)[source]
Return a hashable key consistent with action equality.
Used by tree-search planners to index action children of a belief node in O(1). The returned key MUST satisfy:
action_a == action_b (per env's notion of equality) ==> hash_action(action_a) == hash_action(action_b)
Subclasses with non-hashable actions (e.g.
np.ndarray) must override to return a hashable surrogate (tobytes()is the standard choice for ndarray actions, which mirrors thenp.array_equalsemantics used by the linear-scan fallback).
- initial_observation_dist()[source]
Get the initial observation distribution.
- Return type:
- Returns:
Distribution over initial observations
Note
Subclasses must implement this method to define initial observations.
- initial_state_dist()[source]
Get the initial state distribution.
- Return type:
- Returns:
Distribution over initial states
Note
Subclasses must implement this method to define the starting distribution.
- is_equal_observation(observation1, observation2)[source]
Check if two observations are equal.
- Parameters:
- Return type:
- Returns:
True if observations are considered equal, False otherwise
Note
Subclasses must implement this method to define observation equality. This is particularly important for discrete observation spaces.
- is_terminal(state)[source]
Check if a state is terminal.
- Parameters:
state (
ndarray) – State to check for terminal condition- Return type:
- Returns:
True if the state is terminal, False otherwise
Note
Subclasses must implement this method to define terminal conditions.
- observation_log_probability(next_state, action, observations)[source]
Log-probability of each candidate observation under
(next_state, action).Returns
np.ndarrayof shape(N,)where N is the number of candidate observations. Subclasses must implement.
- observation_log_probability_per_state(next_states, action, observation)[source]
Log-probability of one observation under each candidate next-state.
Used by particle filters: given N candidate next-states and ONE observation, return N log-likelihoods.
The default implementation falls back to a per-state Python loop delegating to
observation_log_probability(). Native-backed envs (those whose observation kernel exposesbatch_log_likelihood(next_states_array, observation_array)) should override to avoid the loop.
- reward(state, action, next_state=None)[source]
Calculate the immediate reward for a state-action(-next_state) tuple.
next_stateis the realised post-transition state when known (e.g. threaded bysample_next_step()), allowing rewards that depend on stochastic transition outcomes to use the same draw as the trajectory instead of resampling. Subclasses whose reward is a pure function of(state, action)may ignore it; subclasses whose reward depends on the realised next state (collision penalties, win bonuses) should consume it when provided and fall back to drawing/computing one whenNone.- Parameters:
- Return type:
- Returns:
Immediate reward value.
Note
Subclasses must implement this method to define reward structure.
- reward_batch(states, action, next_states=None)[source]
Calculate rewards for a batch of states given a single action.
Provides a loop-based default that subclasses can override with vectorized numpy implementations for better performance.
- Parameters:
- Return type:
- Returns:
1-D array of reward values with shape
(N,).
- sample_next_state(state, action, n_samples=1)[source]
Sample one or more next states for
(state, action).Hot-path entry point used by MCTS planners and particle filters. Subclasses must implement.
- sample_next_state_batch(states, action)[source]
Sample one next state per input state, all under the same action.
Used by particle filters: given N current particles and one action, draw N next states (one per particle) in a single vectorized call.
The default implementation falls back to a per-state Python loop delegating to
sample_next_state(). Native-backed envs (those whose state-transition kernel exposesbatch_sample(states_array)) should override to avoid the loop.
- sample_observation(next_state, action, n_samples=1)[source]
Sample one or more observations for
(next_state, action).Hot-path entry point used by MCTS planners and particle filters. Subclasses must implement.
- simulate_random_rollout(state, action_sampler, max_depth, discount_factor, depth=0)[source]
Random rollout dispatched to native C++ when a fixed action set is available.
Uses the
cont_simulate_rolloutnative kernel whenselfhas anaction_to_vectormapping (i.e. the discrete-action subclass). Falls back to the Python base-class loop for pure continuous-action environments where no finite action set exists.- Parameters:
state (
Any) – Current 6-D state[rx, ry, ox, oy, tx, ty].action_sampler (
Any) – Object with asample()method; used only for the Python fallback path.max_depth (
int) – Maximum rollout depth.discount_factor (
float) – Per-step discount factor.depth (
int) – Depth already consumed by the search tree. Defaults to 0.
- Return type:
- Returns:
Discounted sum of immediate rewards along the sampled trajectory.
- class POMDPPlanners.environments.push_pomdp.ContinuousPushPOMDPDiscreteActions(discount_factor, grid_size=10, push_threshold=1.0, friction_coefficient=0.3, max_push=2.0, observation_noise=0.1, obstacles=None, obstacle_penalty=-10.0, obstacle_hit_probability=1.0, dangerous_areas=None, dangerous_area_radius=0.5, dangerous_area_penalty=-10.0, dangerous_area_hit_probability=1.0, reward_model_type=RewardModelType.CONSTANT_HAZARD_PENALTY, penalty_decay=1.0, robot_radius=0.3, state_transition_cov_matrix=array([[0.1, 0.], [0., 0.1]]), initial_state=None, name='ContinuousPushPOMDPDiscreteActions', output_dir=None, debug=False, use_queue_logger=False)[source]
Bases:
ContinuousPushPOMDP,DiscreteActionsEnvironmentDiscrete-action wrapper for the Continuous Push POMDP.
Maps string actions
["up", "down", "right", "left"]to unit vectors and delegates to the continuous parent.Example
>>> import numpy as np >>> np.random.seed(42) >>> >>> env = ContinuousPushPOMDPDiscreteActions(discount_factor=0.99) >>> >>> initial_state = env.initial_state_dist().sample()[0] >>> actions = env.get_actions() >>> >>> action = actions[0] >>> next_state, observation, reward = env.sample_next_step(initial_state, action) >>> >>> env.is_terminal(initial_state) False
- Parameters:
discount_factor (float)
grid_size (int)
push_threshold (float)
friction_coefficient (float)
max_push (float)
observation_noise (float)
obstacle_penalty (float)
obstacle_hit_probability (float)
dangerous_area_radius (float)
dangerous_area_penalty (float)
dangerous_area_hit_probability (float)
reward_model_type (RewardModelType)
penalty_decay (float)
robot_radius (float)
state_transition_cov_matrix (ndarray)
initial_state (ndarray | None)
name (str)
output_dir (Path | None)
debug (bool)
use_queue_logger (bool)
- get_actions()[source]
Get all possible actions in the discrete action space.
Note
Subclasses must implement this method to enumerate all possible actions. This is used by planning algorithms that need to iterate over actions.
- hash_action(action)[source]
Return a hashable key consistent with action equality.
Used by tree-search planners to index action children of a belief node in O(1). The returned key MUST satisfy:
action_a == action_b (per env's notion of equality) ==> hash_action(action_a) == hash_action(action_b)
Subclasses with non-hashable actions (e.g.
np.ndarray) must override to return a hashable surrogate (tobytes()is the standard choice for ndarray actions, which mirrors thenp.array_equalsemantics used by the linear-scan fallback).
- observation_log_probability(next_state, action, observations)[source]
Log-probability of each candidate observation under
(next_state, action).Returns
np.ndarrayof shape(N,)where N is the number of candidate observations. Subclasses must implement.
- observation_log_probability_per_state(next_states, action, observation)[source]
Log-probability of one observation under each candidate next-state.
Used by particle filters: given N candidate next-states and ONE observation, return N log-likelihoods.
The default implementation falls back to a per-state Python loop delegating to
observation_log_probability(). Native-backed envs (those whose observation kernel exposesbatch_log_likelihood(next_states_array, observation_array)) should override to avoid the loop.
- reward(state, action, next_state=None)[source]
Calculate the immediate reward for a state-action(-next_state) tuple.
next_stateis the realised post-transition state when known (e.g. threaded bysample_next_step()), allowing rewards that depend on stochastic transition outcomes to use the same draw as the trajectory instead of resampling. Subclasses whose reward is a pure function of(state, action)may ignore it; subclasses whose reward depends on the realised next state (collision penalties, win bonuses) should consume it when provided and fall back to drawing/computing one whenNone.- Parameters:
- Return type:
- Returns:
Immediate reward value.
Note
Subclasses must implement this method to define reward structure.
- reward_batch(states, action, next_states=None)[source]
Calculate rewards for a batch of states given a single action.
Provides a loop-based default that subclasses can override with vectorized numpy implementations for better performance.
- Parameters:
- Return type:
- Returns:
1-D array of reward values with shape
(N,).
- sample_next_state(state, action, n_samples=1)[source]
Sample one or more next states for
(state, action).Hot-path entry point used by MCTS planners and particle filters. Subclasses must implement.
- sample_next_state_batch(states, action)[source]
Sample one next state per input state, all under the same action.
Used by particle filters: given N current particles and one action, draw N next states (one per particle) in a single vectorized call.
The default implementation falls back to a per-state Python loop delegating to
sample_next_state(). Native-backed envs (those whose state-transition kernel exposesbatch_sample(states_array)) should override to avoid the loop.
- sample_observation(next_state, action, n_samples=1)[source]
Sample one or more observations for
(next_state, action).Hot-path entry point used by MCTS planners and particle filters. Subclasses must implement.
- class POMDPPlanners.environments.push_pomdp.ContinuousPushPOMDPVisualizer(env)[source]
Bases:
objectHandles visualization and animation for Continuous Push POMDP environments.
This class encapsulates all visualization logic for Continuous Push POMDP episodes, creating animated GIFs showing robot movement (with circular body), object pushing, rectangular obstacle collisions, and task completion.
- Parameters:
env (ContinuousPushPOMDP)
- env
Reference to the ContinuousPushPOMDP environment instance.
- grid_size
Size of the grid environment.
- push_threshold
Distance threshold for robot to push object.
- obstacles
Shape
(M, 4)AABB array(cx, cy, hx, hy).
- robot_radius
Radius of the robot body.
- create_visualization(history, cache_path)[source]
Create animated visualization of a Continuous Push POMDP episode.
Creates an animated GIF showing the robot pushing the object toward the target, with rectangular obstacles, collision detection, distance indicators, and success feedback.
- Parameters:
- Raises:
ValueError – If history is empty or cache_path doesn’t end with .gif.
TypeError – If cache_path is not a Path object.
- Return type:
- class POMDPPlanners.environments.push_pomdp.PushPOMDP(discount_factor, grid_size=10, push_threshold=1.0, friction_coefficient=0.3, observation_noise=0.1, obstacles=None, obstacle_radius=0.5, obstacle_penalty=-10.0, obstacle_hit_probability=1.0, dangerous_areas=None, dangerous_area_radius=0.5, dangerous_area_penalty=-10.0, dangerous_area_hit_probability=1.0, reward_model_type=RewardModelType.CONSTANT_HAZARD_PENALTY, penalty_decay=1.0, initial_state=None, transition_error_prob=0.0, name='PushPOMDP', output_dir=None, debug=False, use_queue_logger=False)[source]
Bases:
DiscreteActionsEnvironmentRobotic push task formulated as a POMDP.
This environment simulates a robot that must push an object to a target location on a 2D grid. The robot can move in four directions and pushes objects when close enough, with partial observability through noisy object position measurements.
Problem Structure: - State: [robot_x, robot_y, object_x, object_y, target_x, target_y] (continuous) - Actions: [“up”, “down”, “left”, “right”] (discrete) - Observations: [robot_x, robot_y, noisy_object_x, noisy_object_y, target_x, target_y] - Rewards: -distance_to_target + 100 (when object reaches target) - Termination: Object within 0.5 units of target position
Key Features: - Physics-based pushing with configurable friction - Distance-based pushing threshold - Noisy observations of object position only - Dense reward signal based on object-target distance - Obstacle collision detection with configurable penalties - Obstacles prevent robot and object movement through them
- Stochasticity:
The obstacle-collision penalty can be applied either deterministically (the default) or stochastically. When
obstacle_hit_probability == 1.0(default), the penalty is applied every time the robot’s intended next position lies inside an obstacle, matching legacy behavior. Whenobstacle_hit_probability < 1.0, the penalty is applied only with that probability perreward()/reward_batch()call (one Bernoulli draw per state), producing a heavy-tailed return distribution suitable for benchmarking risk-sensitive planners (e.g. ICVaR-aware MCTS) against expected-value MCTS on the same env. Note that this makesreward(state, action)non- deterministic given a state-action pair, so any external caching that assumes deterministic rewards must be aware of this.transition_log_probabilityis unaffected; the obstacle still deterministically blocks movement. The native C++ rollout applies the Bernoulliobstacle_hit_probabilitydraw internally, sosimulate_random_rolloutalways routes through the native kernel.- Dangerous areas:
dangerous_areasis a separate, additive concept fromobstacles. Each entry is a circular region centred at(x, y)with radiusdangerous_area_radius. Entering a dangerous area appliesdangerous_area_penalty(a negative number, added to reward — same sign convention asobstacle_penalty) but does NOT block movement. Penalty fires when the robot’s intended next position lies inside any dangerous area; the object position is ignored. At most onedangerous_area_penaltyis applied per step even when multiple zones overlap. Like obstacles, the penalty supports a Bernoullidangerous_area_hit_probability(default 1.0) for risk-sensitive planning. The native C++ rollout applies the Bernoulli draw internally, so all rollouts route through the native kernel regardless of the configured probability.
Example
>>> import numpy as np >>> np.random.seed(42) # For reproducible results >>> >>> # Initialize environment >>> env = PushPOMDP(discount_factor=0.99) >>> >>> # Get initial state and actions >>> initial_state = env.initial_state_dist().sample()[0] >>> actions = env.get_actions() >>> >>> # Sample complete step using convenience method >>> action = actions[0] >>> next_state, observation, reward = env.sample_next_step(initial_state, action) >>> >>> # Check terminal condition >>> env.is_terminal(initial_state) False
- Parameters:
discount_factor (float)
grid_size (int)
push_threshold (float)
friction_coefficient (float)
observation_noise (float)
obstacle_radius (float)
obstacle_penalty (float)
obstacle_hit_probability (float)
dangerous_area_radius (float)
dangerous_area_penalty (float)
dangerous_area_hit_probability (float)
reward_model_type (RewardModelType)
penalty_decay (float)
initial_state (ndarray | None)
transition_error_prob (float)
name (str)
output_dir (Path | None)
debug (bool)
use_queue_logger (bool)
- cache_visualization(history, cache_path)[source]
Cache animated visualization of the push episode.
Creates an animated GIF showing the robot pushing the object toward the target, with obstacles, collision detection, distance indicators, and success feedback.
- Parameters:
- Raises:
ValueError – If history is empty or cache_path doesn’t end with .gif
TypeError – If cache_path is not a Path object
- Return type:
- compute_metrics(histories)[source]
Compute environment-specific metrics from episode histories.
This method can be overridden by subclasses to provide custom metric calculations beyond standard return and episode length.
- get_actions()[source]
Get all possible actions in the discrete action space.
Note
Subclasses must implement this method to enumerate all possible actions. This is used by planning algorithms that need to iterate over actions.
- hash_action(action)[source]
Return a hashable key consistent with action equality.
Used by tree-search planners to index action children of a belief node in O(1). The returned key MUST satisfy:
action_a == action_b (per env's notion of equality) ==> hash_action(action_a) == hash_action(action_b)
Subclasses with non-hashable actions (e.g.
np.ndarray) must override to return a hashable surrogate (tobytes()is the standard choice for ndarray actions, which mirrors thenp.array_equalsemantics used by the linear-scan fallback).
- hash_observation(observation)[source]
Return a hashable key consistent with
is_equal_observation().Used by tree-search planners to index belief children by observation in O(1). The returned key MUST satisfy the contract:
is_equal_observation(a, b) implies hash_observation(a) == hash_observation(b)
- Parameters:
observation (
Any) – Observation to hash.- Returns:
the observation itself when it is already hashable).
- Return type:
- Raises:
NotImplementedError – If the observation is not hashable and the subclass has not provided an override. Subclasses with non-hashable observations (e.g.
np.ndarray) MUST override.
- initial_observation_dist()[source]
Get the initial observation distribution.
- Return type:
- Returns:
Distribution over initial observations
Note
Subclasses must implement this method to define initial observations.
- initial_state_dist()[source]
Get the initial state distribution.
- Return type:
- Returns:
Distribution over initial states
Note
Subclasses must implement this method to define the starting distribution.
- is_equal_observation(observation1, observation2)[source]
Check if two observations are equal.
- Parameters:
- Return type:
- Returns:
True if observations are considered equal, False otherwise
Note
Subclasses must implement this method to define observation equality. This is particularly important for discrete observation spaces.
- is_terminal(state)[source]
Check if a state is terminal.
- Parameters:
state (
ndarray) – State to check for terminal condition- Return type:
- Returns:
True if the state is terminal, False otherwise
Note
Subclasses must implement this method to define terminal conditions.
- observation_log_probability(next_state, action, observations)[source]
Log-probability of each candidate observation under
(next_state, action).Returns
np.ndarrayof shape(N,)where N is the number of candidate observations. Subclasses must implement.
- observation_log_probability_per_state(next_states, action, observation)[source]
Log-probability of one observation under each candidate next-state.
Used by particle filters: given N candidate next-states and ONE observation, return N log-likelihoods.
The default implementation falls back to a per-state Python loop delegating to
observation_log_probability(). Native-backed envs (those whose observation kernel exposesbatch_log_likelihood(next_states_array, observation_array)) should override to avoid the loop.
- observation_log_probability_single(next_state, action, observation)[source]
Scalar log-likelihood for one
(next_state, observation)pair.Per-state fast-path used by incremental belief updates (e.g. POMCPOW’s
WeightedParticleBeliefStateUpdate.inplace_update()) to skip the per-call numpy setup overhead of the batchedobservation_log_probability()path on a singleton input.The default falls back to the batched method with a one-element observations list. Envs with cheap scalar likelihoods (e.g. the 2-D Gaussian on Push or the cached-inverse-cov path on ContinuousLightDark) should override to skip array allocation.
- reward(state, action, next_state=None)[source]
Calculate the immediate reward for a state-action(-next_state) tuple.
next_stateis the realised post-transition state when known (e.g. threaded bysample_next_step()), allowing rewards that depend on stochastic transition outcomes to use the same draw as the trajectory instead of resampling. Subclasses whose reward is a pure function of(state, action)may ignore it; subclasses whose reward depends on the realised next state (collision penalties, win bonuses) should consume it when provided and fall back to drawing/computing one whenNone.- Parameters:
- Return type:
- Returns:
Immediate reward value.
Note
Subclasses must implement this method to define reward structure.
- reward_batch(states, action, next_states=None)[source]
Calculate rewards for a batch of states given a single action.
When
next_statesis supplied (e.g. by a caller that has already sampled the realised batch transition), it is used directly; otherwise N next states are drawn here via the cachedPushVectorizedUpdater. Per-particle rewards are computed in the C++push_reward_batchkernel (variant-aware: CONSTANT_HAZARD_PENALTY, ZERO_MEAN_HAZARD_SHOCK, DISTANCE_DECAYED_HAZARD_PENALTY) so the batch cost is a single round-trip into native code.
- sample_next_state(state, action, n_samples=1)[source]
Sample one or more next states for
(state, action).Hot-path entry point used by MCTS planners and particle filters. Subclasses must implement.
- sample_next_state_batch(states, action)[source]
Sample one next state per input state, all under the same action.
Used by particle filters: given N current particles and one action, draw N next states (one per particle) in a single vectorized call.
The default implementation falls back to a per-state Python loop delegating to
sample_next_state(). Native-backed envs (those whose state-transition kernel exposesbatch_sample(states_array)) should override to avoid the loop.
- sample_next_step(state, action)[source]
Sample a complete state transition step.
This convenience method combines state transition, observation generation, and reward calculation in a single operation.
- sample_observation(next_state, action, n_samples=1)[source]
Sample one or more observations for
(next_state, action).Hot-path entry point used by MCTS planners and particle filters. Subclasses must implement.
- class POMDPPlanners.environments.push_pomdp.PushPOMDPVisualizer(env)[source]
Bases:
objectHandles visualization and animation for Push POMDP environments.
This class encapsulates all visualization logic for Push POMDP episodes, creating animated GIFs showing robot movement, object pushing, obstacle collisions, and task completion.
- Parameters:
env (PushPOMDP)
- env
Reference to the PushPOMDP environment instance
- grid_size
Size of the grid environment
- push_threshold
Distance threshold for robot to push object
- obstacles
List of obstacle positions
- obstacle_radius
Radius of obstacles for collision detection
- create_visualization(history, cache_path)[source]
Create animated visualization of a Push POMDP episode.
Creates an animated GIF showing the robot pushing the object toward the target, with obstacles, collision detection, distance indicators, and success feedback.
- Parameters:
- Raises:
ValueError – If history is empty or cache_path doesn’t end with .gif
TypeError – If cache_path is not a Path object
- Return type:
Subpackages
- POMDPPlanners.environments.push_pomdp.push_pomdp_beliefs package
ContinuousPushVectorizedUpdaterContinuousPushVectorizedUpdater.obs_distContinuousPushVectorizedUpdater.grid_sizeContinuousPushVectorizedUpdater.push_thresholdContinuousPushVectorizedUpdater.friction_coefficientContinuousPushVectorizedUpdater.max_pushContinuousPushVectorizedUpdater.obstaclesContinuousPushVectorizedUpdater.robot_radiusContinuousPushVectorizedUpdater.batch_observation_log_likelihood()ContinuousPushVectorizedUpdater.batch_transition()ContinuousPushVectorizedUpdater.config_idContinuousPushVectorizedUpdater.from_environment()
PushVectorizedUpdaterPushVectorizedUpdater.obs_distPushVectorizedUpdater.grid_sizePushVectorizedUpdater.push_thresholdPushVectorizedUpdater.friction_coefficientPushVectorizedUpdater.obstaclesPushVectorizedUpdater.obstacle_radiusPushVectorizedUpdater.transition_error_probPushVectorizedUpdater.ACTION_NAME_TO_INDEXPushVectorizedUpdater.ACTION_VECTORSPushVectorizedUpdater.batch_observation_log_likelihood()PushVectorizedUpdater.batch_transition()PushVectorizedUpdater.config_idPushVectorizedUpdater.from_environment()
create_continuous_push_belief()create_push_belief()- Submodules
- POMDPPlanners.environments.push_pomdp.push_pomdp_beliefs.continuous_push_belief_factory module
- POMDPPlanners.environments.push_pomdp.push_pomdp_beliefs.continuous_push_vectorized_updater module
ContinuousPushVectorizedUpdaterContinuousPushVectorizedUpdater.obs_distContinuousPushVectorizedUpdater.grid_sizeContinuousPushVectorizedUpdater.push_thresholdContinuousPushVectorizedUpdater.friction_coefficientContinuousPushVectorizedUpdater.max_pushContinuousPushVectorizedUpdater.obstaclesContinuousPushVectorizedUpdater.robot_radiusContinuousPushVectorizedUpdater.batch_observation_log_likelihood()ContinuousPushVectorizedUpdater.batch_transition()ContinuousPushVectorizedUpdater.config_idContinuousPushVectorizedUpdater.from_environment()
- POMDPPlanners.environments.push_pomdp.push_pomdp_beliefs.push_belief_factory module
- POMDPPlanners.environments.push_pomdp.push_pomdp_beliefs.push_vectorized_updater module
PushVectorizedUpdaterPushVectorizedUpdater.obs_distPushVectorizedUpdater.grid_sizePushVectorizedUpdater.push_thresholdPushVectorizedUpdater.friction_coefficientPushVectorizedUpdater.obstaclesPushVectorizedUpdater.obstacle_radiusPushVectorizedUpdater.transition_error_probPushVectorizedUpdater.ACTION_NAME_TO_INDEXPushVectorizedUpdater.ACTION_VECTORSPushVectorizedUpdater.batch_observation_log_likelihood()PushVectorizedUpdater.batch_transition()PushVectorizedUpdater.config_idPushVectorizedUpdater.from_environment()
- POMDPPlanners.environments.push_pomdp.push_pomdp_utils package
- Submodules
- POMDPPlanners.environments.push_pomdp.push_pomdp_utils.push_reward_models module
Submodules
POMDPPlanners.environments.push_pomdp.continuous_push_geometry module
Geometry utilities for the Continuous Push POMDP.
Provides circle-AABB overlap tests, point-in-AABB tests, collision resolution and grid clamping used by the continuous push environment and its vectorized belief updater.
Wall AABBs (obstacles) are stored as rows (cx, cy, hx, hy) where
(cx, cy) is the center and (hx, hy) the half-extents. For
square obstacles hx == hy.
- Functions:
circle_aabb_overlap: Boolean circle-AABB overlap test. point_inside_aabb: Boolean point-inside-AABB test. resolve_circle_wall_collision: Push a circle out of overlapping AABBs. clamp_circle_to_grid: Clamp a circle center so the circle stays in-bounds. clamp_point_to_grid: Clamp a point to
[0, grid_size-1]. batch_resolve_circle_wall_collision: Vectorized circle-AABB resolution. batch_clamp_circle_to_grid: Vectorized circle grid clamping. batch_point_inside_aabb: Vectorized point-inside-AABB test. batch_clamp_point_to_grid: Vectorized point grid clamping.
- POMDPPlanners.environments.push_pomdp.continuous_push_geometry.batch_clamp_circle_to_grid(positions, radius, grid_size)[source]
Clamp an array of circle centers so circles stay in-bounds.
- POMDPPlanners.environments.push_pomdp.continuous_push_geometry.batch_clamp_point_to_grid(positions, grid_size)[source]
Clamp an array of points to
[0, grid_size-1].
- POMDPPlanners.environments.push_pomdp.continuous_push_geometry.batch_point_inside_aabb(points, walls)[source]
Test whether each point lies inside any AABB.
- POMDPPlanners.environments.push_pomdp.continuous_push_geometry.batch_resolve_circle_wall_collision(positions, radius, walls)[source]
Resolve circle-AABB collisions for an array of positions.
- POMDPPlanners.environments.push_pomdp.continuous_push_geometry.circle_aabb_overlap(center, radius, wall)[source]
Test whether a circle overlaps an axis-aligned bounding box.
- POMDPPlanners.environments.push_pomdp.continuous_push_geometry.clamp_circle_to_grid(pos, radius, grid_size)[source]
Clamp a circle center so the full circle stays within
[0, grid_size-1].
- POMDPPlanners.environments.push_pomdp.continuous_push_geometry.clamp_point_to_grid(pos, grid_size)[source]
Clamp a point to
[0, grid_size-1].
- POMDPPlanners.environments.push_pomdp.continuous_push_geometry.point_inside_aabb(point, wall)[source]
Test whether a point lies inside an axis-aligned bounding box.
POMDPPlanners.environments.push_pomdp.continuous_push_pomdp module
Continuous Push POMDP Environment Implementation.
This module implements a continuous-action variant of the Push POMDP where the robot moves via 2D action vectors with Gaussian noise, has a configurable radius, and obstacles are axis-aligned squares.
The Continuous Push POMDP features: - Continuous 2D state space: [robot_x, robot_y, object_x, object_y, target_x, target_y] - Continuous action space (2D movement vectors) - Robot modelled as a circle with configurable radius - Object modelled as a point - Square obstacles defined as axis-aligned bounding boxes - Gaussian transition noise on robot movement - Capped push force with friction - Noisy observations of object position
- Classes:
ContinuousPushPOMDP: Main environment with continuous actions. ContinuousPushPOMDPDiscreteActions: Discrete action wrapper.
- class POMDPPlanners.environments.push_pomdp.continuous_push_pomdp.ContinuousPushPOMDP(discount_factor, grid_size=10, push_threshold=1.0, friction_coefficient=0.3, max_push=2.0, observation_noise=0.1, obstacles=None, obstacle_penalty=-10.0, obstacle_hit_probability=1.0, dangerous_areas=None, dangerous_area_radius=0.5, dangerous_area_penalty=-10.0, dangerous_area_hit_probability=1.0, reward_model_type=RewardModelType.CONSTANT_HAZARD_PENALTY, penalty_decay=1.0, robot_radius=0.3, state_transition_cov_matrix=array([[0.1, 0.], [0., 0.1]]), initial_state=None, name='ContinuousPushPOMDP', output_dir=None, debug=False, use_queue_logger=False)[source]
Bases:
EnvironmentContinuous-action Push POMDP environment.
A robot (circle) must push an object (point) to a target location on a 2D grid. The robot moves via continuous 2D action vectors with Gaussian noise; obstacles are axis-aligned squares.
State: [robot_x, robot_y, object_x, object_y, target_x, target_y] Actions: 2D numpy vectors Observations: [robot_x, robot_y, noisy_obj_x, noisy_obj_y, target_x, target_y]
- Stochasticity:
The obstacle-collision penalty can be applied either deterministically (the default) or stochastically. When
obstacle_hit_probability == 1.0(default), the penalty is applied every time the post-action robot position overlaps an obstacle AABB, matching legacy behavior. Whenobstacle_hit_probability < 1.0, the penalty is applied only with that probability perreward()/reward_batch()call (one Bernoulli draw per state), producing a heavy-tailed return distribution suitable for benchmarking risk-sensitive planners (e.g. ICVaR-aware MCTS) against expected-value MCTS on the same env. Note that this makesreward(state, action)non- deterministic given a state-action pair, so any external caching that assumes deterministic rewards must be aware of this.transition_log_probabilityis unaffected. The native C++ rollout applies the Bernoulliobstacle_hit_probabilitydraw internally, sosimulate_random_rolloutalways routes through the native kernel.- Dangerous areas:
dangerous_areasis a separate, additive concept fromobstacles. Each entry is a circular region centred at(x, y)with radiusdangerous_area_radius. Entering a dangerous area appliesdangerous_area_penalty(a negative number, added to reward) but does NOT block movement (unlike obstacles, which act as walls in the continuous variant). The penalty fires when the post-action robot position lies inside any dangerous area; the object position is ignored. At most onedangerous_area_penaltyis applied per step even when multiple zones overlap. Like obstacles, the penalty supports a Bernoullidangerous_area_hit_probability(default 1.0) for risk-sensitive planning. The native C++ rollout applies the Bernoulli draw internally, so all rollouts route through the native kernel regardless of the configured probability.
Example
>>> import numpy as np >>> np.random.seed(42) >>> >>> env = ContinuousPushPOMDP(discount_factor=0.99) >>> >>> initial_state = env.initial_state_dist().sample()[0] >>> >>> action = np.array([1.0, 0.0]) >>> next_state, observation, reward = env.sample_next_step(initial_state, action) >>> >>> env.is_terminal(initial_state) False
- Parameters:
discount_factor (float)
grid_size (int)
push_threshold (float)
friction_coefficient (float)
max_push (float)
observation_noise (float)
obstacle_penalty (float)
obstacle_hit_probability (float)
dangerous_area_radius (float)
dangerous_area_penalty (float)
dangerous_area_hit_probability (float)
reward_model_type (RewardModelType)
penalty_decay (float)
robot_radius (float)
state_transition_cov_matrix (ndarray)
initial_state (ndarray | None)
name (str)
output_dir (Path | None)
debug (bool)
use_queue_logger (bool)
- cache_visualization(history, cache_path)[source]
Cache animated visualization of the continuous push episode.
Creates an animated GIF showing the robot pushing the object toward the target, with rectangular obstacles, collision detection, distance indicators, and success feedback.
- Parameters:
- Raises:
ValueError – If history is empty or cache_path doesn’t end with .gif.
TypeError – If cache_path is not a Path object.
- Return type:
- compute_metrics(histories)[source]
Compute environment-specific metrics from episode histories.
This method can be overridden by subclasses to provide custom metric calculations beyond standard return and episode length.
- hash_action(action)[source]
Return a hashable key consistent with action equality.
Used by tree-search planners to index action children of a belief node in O(1). The returned key MUST satisfy:
action_a == action_b (per env's notion of equality) ==> hash_action(action_a) == hash_action(action_b)
Subclasses with non-hashable actions (e.g.
np.ndarray) must override to return a hashable surrogate (tobytes()is the standard choice for ndarray actions, which mirrors thenp.array_equalsemantics used by the linear-scan fallback).
- initial_observation_dist()[source]
Get the initial observation distribution.
- Return type:
- Returns:
Distribution over initial observations
Note
Subclasses must implement this method to define initial observations.
- initial_state_dist()[source]
Get the initial state distribution.
- Return type:
- Returns:
Distribution over initial states
Note
Subclasses must implement this method to define the starting distribution.
- is_equal_observation(observation1, observation2)[source]
Check if two observations are equal.
- Parameters:
- Return type:
- Returns:
True if observations are considered equal, False otherwise
Note
Subclasses must implement this method to define observation equality. This is particularly important for discrete observation spaces.
- is_terminal(state)[source]
Check if a state is terminal.
- Parameters:
state (
ndarray) – State to check for terminal condition- Return type:
- Returns:
True if the state is terminal, False otherwise
Note
Subclasses must implement this method to define terminal conditions.
- observation_log_probability(next_state, action, observations)[source]
Log-probability of each candidate observation under
(next_state, action).Returns
np.ndarrayof shape(N,)where N is the number of candidate observations. Subclasses must implement.
- observation_log_probability_per_state(next_states, action, observation)[source]
Log-probability of one observation under each candidate next-state.
Used by particle filters: given N candidate next-states and ONE observation, return N log-likelihoods.
The default implementation falls back to a per-state Python loop delegating to
observation_log_probability(). Native-backed envs (those whose observation kernel exposesbatch_log_likelihood(next_states_array, observation_array)) should override to avoid the loop.
- reward(state, action, next_state=None)[source]
Calculate the immediate reward for a state-action(-next_state) tuple.
next_stateis the realised post-transition state when known (e.g. threaded bysample_next_step()), allowing rewards that depend on stochastic transition outcomes to use the same draw as the trajectory instead of resampling. Subclasses whose reward is a pure function of(state, action)may ignore it; subclasses whose reward depends on the realised next state (collision penalties, win bonuses) should consume it when provided and fall back to drawing/computing one whenNone.- Parameters:
- Return type:
- Returns:
Immediate reward value.
Note
Subclasses must implement this method to define reward structure.
- reward_batch(states, action, next_states=None)[source]
Calculate rewards for a batch of states given a single action.
Provides a loop-based default that subclasses can override with vectorized numpy implementations for better performance.
- Parameters:
- Return type:
- Returns:
1-D array of reward values with shape
(N,).
- sample_next_state(state, action, n_samples=1)[source]
Sample one or more next states for
(state, action).Hot-path entry point used by MCTS planners and particle filters. Subclasses must implement.
- sample_next_state_batch(states, action)[source]
Sample one next state per input state, all under the same action.
Used by particle filters: given N current particles and one action, draw N next states (one per particle) in a single vectorized call.
The default implementation falls back to a per-state Python loop delegating to
sample_next_state(). Native-backed envs (those whose state-transition kernel exposesbatch_sample(states_array)) should override to avoid the loop.
- sample_observation(next_state, action, n_samples=1)[source]
Sample one or more observations for
(next_state, action).Hot-path entry point used by MCTS planners and particle filters. Subclasses must implement.
- simulate_random_rollout(state, action_sampler, max_depth, discount_factor, depth=0)[source]
Random rollout dispatched to native C++ when a fixed action set is available.
Uses the
cont_simulate_rolloutnative kernel whenselfhas anaction_to_vectormapping (i.e. the discrete-action subclass). Falls back to the Python base-class loop for pure continuous-action environments where no finite action set exists.- Parameters:
state (
Any) – Current 6-D state[rx, ry, ox, oy, tx, ty].action_sampler (
Any) – Object with asample()method; used only for the Python fallback path.max_depth (
int) – Maximum rollout depth.discount_factor (
float) – Per-step discount factor.depth (
int) – Depth already consumed by the search tree. Defaults to 0.
- Return type:
- Returns:
Discounted sum of immediate rewards along the sampled trajectory.
- class POMDPPlanners.environments.push_pomdp.continuous_push_pomdp.ContinuousPushPOMDPDiscreteActions(discount_factor, grid_size=10, push_threshold=1.0, friction_coefficient=0.3, max_push=2.0, observation_noise=0.1, obstacles=None, obstacle_penalty=-10.0, obstacle_hit_probability=1.0, dangerous_areas=None, dangerous_area_radius=0.5, dangerous_area_penalty=-10.0, dangerous_area_hit_probability=1.0, reward_model_type=RewardModelType.CONSTANT_HAZARD_PENALTY, penalty_decay=1.0, robot_radius=0.3, state_transition_cov_matrix=array([[0.1, 0.], [0., 0.1]]), initial_state=None, name='ContinuousPushPOMDPDiscreteActions', output_dir=None, debug=False, use_queue_logger=False)[source]
Bases:
ContinuousPushPOMDP,DiscreteActionsEnvironmentDiscrete-action wrapper for the Continuous Push POMDP.
Maps string actions
["up", "down", "right", "left"]to unit vectors and delegates to the continuous parent.Example
>>> import numpy as np >>> np.random.seed(42) >>> >>> env = ContinuousPushPOMDPDiscreteActions(discount_factor=0.99) >>> >>> initial_state = env.initial_state_dist().sample()[0] >>> actions = env.get_actions() >>> >>> action = actions[0] >>> next_state, observation, reward = env.sample_next_step(initial_state, action) >>> >>> env.is_terminal(initial_state) False
- Parameters:
discount_factor (float)
grid_size (int)
push_threshold (float)
friction_coefficient (float)
max_push (float)
observation_noise (float)
obstacle_penalty (float)
obstacle_hit_probability (float)
dangerous_area_radius (float)
dangerous_area_penalty (float)
dangerous_area_hit_probability (float)
reward_model_type (RewardModelType)
penalty_decay (float)
robot_radius (float)
state_transition_cov_matrix (ndarray)
initial_state (ndarray | None)
name (str)
output_dir (Path | None)
debug (bool)
use_queue_logger (bool)
- get_actions()[source]
Get all possible actions in the discrete action space.
Note
Subclasses must implement this method to enumerate all possible actions. This is used by planning algorithms that need to iterate over actions.
- hash_action(action)[source]
Return a hashable key consistent with action equality.
Used by tree-search planners to index action children of a belief node in O(1). The returned key MUST satisfy:
action_a == action_b (per env's notion of equality) ==> hash_action(action_a) == hash_action(action_b)
Subclasses with non-hashable actions (e.g.
np.ndarray) must override to return a hashable surrogate (tobytes()is the standard choice for ndarray actions, which mirrors thenp.array_equalsemantics used by the linear-scan fallback).
- observation_log_probability(next_state, action, observations)[source]
Log-probability of each candidate observation under
(next_state, action).Returns
np.ndarrayof shape(N,)where N is the number of candidate observations. Subclasses must implement.
- observation_log_probability_per_state(next_states, action, observation)[source]
Log-probability of one observation under each candidate next-state.
Used by particle filters: given N candidate next-states and ONE observation, return N log-likelihoods.
The default implementation falls back to a per-state Python loop delegating to
observation_log_probability(). Native-backed envs (those whose observation kernel exposesbatch_log_likelihood(next_states_array, observation_array)) should override to avoid the loop.
- reward(state, action, next_state=None)[source]
Calculate the immediate reward for a state-action(-next_state) tuple.
next_stateis the realised post-transition state when known (e.g. threaded bysample_next_step()), allowing rewards that depend on stochastic transition outcomes to use the same draw as the trajectory instead of resampling. Subclasses whose reward is a pure function of(state, action)may ignore it; subclasses whose reward depends on the realised next state (collision penalties, win bonuses) should consume it when provided and fall back to drawing/computing one whenNone.- Parameters:
- Return type:
- Returns:
Immediate reward value.
Note
Subclasses must implement this method to define reward structure.
- reward_batch(states, action, next_states=None)[source]
Calculate rewards for a batch of states given a single action.
Provides a loop-based default that subclasses can override with vectorized numpy implementations for better performance.
- Parameters:
- Return type:
- Returns:
1-D array of reward values with shape
(N,).
- sample_next_state(state, action, n_samples=1)[source]
Sample one or more next states for
(state, action).Hot-path entry point used by MCTS planners and particle filters. Subclasses must implement.
- sample_next_state_batch(states, action)[source]
Sample one next state per input state, all under the same action.
Used by particle filters: given N current particles and one action, draw N next states (one per particle) in a single vectorized call.
The default implementation falls back to a per-state Python loop delegating to
sample_next_state(). Native-backed envs (those whose state-transition kernel exposesbatch_sample(states_array)) should override to avoid the loop.
- sample_observation(next_state, action, n_samples=1)[source]
Sample one or more observations for
(next_state, action).Hot-path entry point used by MCTS planners and particle filters. Subclasses must implement.
- class POMDPPlanners.environments.push_pomdp.continuous_push_pomdp.ContinuousPushPOMDPMetrics(*values)[source]
Bases:
EnumMetric names for Continuous Push POMDP environment.
- DANGEROUS_AREA_RATE = 'dangerous_area_rate'
- GOAL_REACHING_RATE = 'goal_reaching_rate'
- OBJECT_OBSTACLE_COLLISION_RATE = 'object_obstacle_collision_rate'
- ROBOT_OBSTACLE_COLLISION_RATE = 'robot_obstacle_collision_rate'
- TOTAL_ALL_OBSTACLE_COLLISIONS = 'total_all_obstacle_collisions'
- TOTAL_DANGEROUS_AREA_STEPS = 'total_dangerous_area_steps'
- TOTAL_OBJECT_OBSTACLE_COLLISIONS = 'total_object_obstacle_collisions'
- TOTAL_OBSTACLE_COLLISION_RATE = 'total_obstacle_collision_rate'
- TOTAL_ROBOT_OBSTACLE_COLLISIONS = 'total_robot_obstacle_collisions'
POMDPPlanners.environments.push_pomdp.continuous_push_pomdp_visualizer module
Visualization module for Continuous Push POMDP Environment.
This module provides visualization capabilities for Continuous Push POMDP episodes, creating animated GIFs showing robot movement, object pushing, obstacle collisions, and task completion.
Obstacles are axis-aligned bounding boxes rendered as rectangles. The robot is drawn as a circle with its configured radius. Actions are displayed as formatted 2D vectors.
- Classes:
- ContinuousPushPOMDPVisualizer: Handles all visualization logic for
Continuous Push POMDP
- class POMDPPlanners.environments.push_pomdp.continuous_push_pomdp_visualizer.ContinuousPushPOMDPVisualizer(env)[source]
Bases:
objectHandles visualization and animation for Continuous Push POMDP environments.
This class encapsulates all visualization logic for Continuous Push POMDP episodes, creating animated GIFs showing robot movement (with circular body), object pushing, rectangular obstacle collisions, and task completion.
- Parameters:
env (ContinuousPushPOMDP)
- env
Reference to the ContinuousPushPOMDP environment instance.
- grid_size
Size of the grid environment.
- push_threshold
Distance threshold for robot to push object.
- obstacles
Shape
(M, 4)AABB array(cx, cy, hx, hy).
- robot_radius
Radius of the robot body.
- create_visualization(history, cache_path)[source]
Create animated visualization of a Continuous Push POMDP episode.
Creates an animated GIF showing the robot pushing the object toward the target, with rectangular obstacles, collision detection, distance indicators, and success feedback.
- Parameters:
- Raises:
ValueError – If history is empty or cache_path doesn’t end with .gif.
TypeError – If cache_path is not a Path object.
- Return type:
POMDPPlanners.environments.push_pomdp.push_pomdp module
Push POMDP Environment Implementation.
This module implements a robotic push task as a POMDP, where a robot must push an object to a target location on a 2D grid. The robot can move in four directions and pushes objects when within range, with noisy observations of the object’s position.
The Push POMDP features: - Continuous 2D state space: [robot_x, robot_y, object_x, object_y, target_x, target_y] - Discrete action space: [“up”, “down”, “left”, “right”] - Noisy observations of object position (robot and target positions are known) - Physics-based pushing mechanics with friction - Distance-based rewards encouraging object movement toward target
Key mechanics: - Robot must be within push_threshold distance to move objects - Friction reduces the effectiveness of pushes - Object position observations include Gaussian noise - Episode terminates when object reaches target
- Classes:
PushPOMDP: Main push task environment with POMDP formulation
- class POMDPPlanners.environments.push_pomdp.push_pomdp.FixedStateDistribution(state)[source]
Bases:
DistributionDeterministic distribution that always returns the same fixed state.
- Parameters:
state (ndarray)
- sample(n_samples=1)[source]
Sample values from the distribution.
- Parameters:
n_samples (
int) – Number of samples to return. Defaults to 1.- Return type:
- Returns:
List of n_samples independent samples from the distribution
Note
Subclasses must implement this method according to their specific distribution type and parameters.
- class POMDPPlanners.environments.push_pomdp.push_pomdp.PushPOMDP(discount_factor, grid_size=10, push_threshold=1.0, friction_coefficient=0.3, observation_noise=0.1, obstacles=None, obstacle_radius=0.5, obstacle_penalty=-10.0, obstacle_hit_probability=1.0, dangerous_areas=None, dangerous_area_radius=0.5, dangerous_area_penalty=-10.0, dangerous_area_hit_probability=1.0, reward_model_type=RewardModelType.CONSTANT_HAZARD_PENALTY, penalty_decay=1.0, initial_state=None, transition_error_prob=0.0, name='PushPOMDP', output_dir=None, debug=False, use_queue_logger=False)[source]
Bases:
DiscreteActionsEnvironmentRobotic push task formulated as a POMDP.
This environment simulates a robot that must push an object to a target location on a 2D grid. The robot can move in four directions and pushes objects when close enough, with partial observability through noisy object position measurements.
Problem Structure: - State: [robot_x, robot_y, object_x, object_y, target_x, target_y] (continuous) - Actions: [“up”, “down”, “left”, “right”] (discrete) - Observations: [robot_x, robot_y, noisy_object_x, noisy_object_y, target_x, target_y] - Rewards: -distance_to_target + 100 (when object reaches target) - Termination: Object within 0.5 units of target position
Key Features: - Physics-based pushing with configurable friction - Distance-based pushing threshold - Noisy observations of object position only - Dense reward signal based on object-target distance - Obstacle collision detection with configurable penalties - Obstacles prevent robot and object movement through them
- Stochasticity:
The obstacle-collision penalty can be applied either deterministically (the default) or stochastically. When
obstacle_hit_probability == 1.0(default), the penalty is applied every time the robot’s intended next position lies inside an obstacle, matching legacy behavior. Whenobstacle_hit_probability < 1.0, the penalty is applied only with that probability perreward()/reward_batch()call (one Bernoulli draw per state), producing a heavy-tailed return distribution suitable for benchmarking risk-sensitive planners (e.g. ICVaR-aware MCTS) against expected-value MCTS on the same env. Note that this makesreward(state, action)non- deterministic given a state-action pair, so any external caching that assumes deterministic rewards must be aware of this.transition_log_probabilityis unaffected; the obstacle still deterministically blocks movement. The native C++ rollout applies the Bernoulliobstacle_hit_probabilitydraw internally, sosimulate_random_rolloutalways routes through the native kernel.- Dangerous areas:
dangerous_areasis a separate, additive concept fromobstacles. Each entry is a circular region centred at(x, y)with radiusdangerous_area_radius. Entering a dangerous area appliesdangerous_area_penalty(a negative number, added to reward — same sign convention asobstacle_penalty) but does NOT block movement. Penalty fires when the robot’s intended next position lies inside any dangerous area; the object position is ignored. At most onedangerous_area_penaltyis applied per step even when multiple zones overlap. Like obstacles, the penalty supports a Bernoullidangerous_area_hit_probability(default 1.0) for risk-sensitive planning. The native C++ rollout applies the Bernoulli draw internally, so all rollouts route through the native kernel regardless of the configured probability.
Example
>>> import numpy as np >>> np.random.seed(42) # For reproducible results >>> >>> # Initialize environment >>> env = PushPOMDP(discount_factor=0.99) >>> >>> # Get initial state and actions >>> initial_state = env.initial_state_dist().sample()[0] >>> actions = env.get_actions() >>> >>> # Sample complete step using convenience method >>> action = actions[0] >>> next_state, observation, reward = env.sample_next_step(initial_state, action) >>> >>> # Check terminal condition >>> env.is_terminal(initial_state) False
- Parameters:
discount_factor (float)
grid_size (int)
push_threshold (float)
friction_coefficient (float)
observation_noise (float)
obstacle_radius (float)
obstacle_penalty (float)
obstacle_hit_probability (float)
dangerous_area_radius (float)
dangerous_area_penalty (float)
dangerous_area_hit_probability (float)
reward_model_type (RewardModelType)
penalty_decay (float)
initial_state (ndarray | None)
transition_error_prob (float)
name (str)
output_dir (Path | None)
debug (bool)
use_queue_logger (bool)
- cache_visualization(history, cache_path)[source]
Cache animated visualization of the push episode.
Creates an animated GIF showing the robot pushing the object toward the target, with obstacles, collision detection, distance indicators, and success feedback.
- Parameters:
- Raises:
ValueError – If history is empty or cache_path doesn’t end with .gif
TypeError – If cache_path is not a Path object
- Return type:
- compute_metrics(histories)[source]
Compute environment-specific metrics from episode histories.
This method can be overridden by subclasses to provide custom metric calculations beyond standard return and episode length.
- get_actions()[source]
Get all possible actions in the discrete action space.
Note
Subclasses must implement this method to enumerate all possible actions. This is used by planning algorithms that need to iterate over actions.
- hash_action(action)[source]
Return a hashable key consistent with action equality.
Used by tree-search planners to index action children of a belief node in O(1). The returned key MUST satisfy:
action_a == action_b (per env's notion of equality) ==> hash_action(action_a) == hash_action(action_b)
Subclasses with non-hashable actions (e.g.
np.ndarray) must override to return a hashable surrogate (tobytes()is the standard choice for ndarray actions, which mirrors thenp.array_equalsemantics used by the linear-scan fallback).
- hash_observation(observation)[source]
Return a hashable key consistent with
is_equal_observation().Used by tree-search planners to index belief children by observation in O(1). The returned key MUST satisfy the contract:
is_equal_observation(a, b) implies hash_observation(a) == hash_observation(b)
- Parameters:
observation (
Any) – Observation to hash.- Returns:
the observation itself when it is already hashable).
- Return type:
- Raises:
NotImplementedError – If the observation is not hashable and the subclass has not provided an override. Subclasses with non-hashable observations (e.g.
np.ndarray) MUST override.
- initial_observation_dist()[source]
Get the initial observation distribution.
- Return type:
- Returns:
Distribution over initial observations
Note
Subclasses must implement this method to define initial observations.
- initial_state_dist()[source]
Get the initial state distribution.
- Return type:
- Returns:
Distribution over initial states
Note
Subclasses must implement this method to define the starting distribution.
- is_equal_observation(observation1, observation2)[source]
Check if two observations are equal.
- Parameters:
- Return type:
- Returns:
True if observations are considered equal, False otherwise
Note
Subclasses must implement this method to define observation equality. This is particularly important for discrete observation spaces.
- is_terminal(state)[source]
Check if a state is terminal.
- Parameters:
state (
ndarray) – State to check for terminal condition- Return type:
- Returns:
True if the state is terminal, False otherwise
Note
Subclasses must implement this method to define terminal conditions.
- observation_log_probability(next_state, action, observations)[source]
Log-probability of each candidate observation under
(next_state, action).Returns
np.ndarrayof shape(N,)where N is the number of candidate observations. Subclasses must implement.
- observation_log_probability_per_state(next_states, action, observation)[source]
Log-probability of one observation under each candidate next-state.
Used by particle filters: given N candidate next-states and ONE observation, return N log-likelihoods.
The default implementation falls back to a per-state Python loop delegating to
observation_log_probability(). Native-backed envs (those whose observation kernel exposesbatch_log_likelihood(next_states_array, observation_array)) should override to avoid the loop.
- observation_log_probability_single(next_state, action, observation)[source]
Scalar log-likelihood for one
(next_state, observation)pair.Per-state fast-path used by incremental belief updates (e.g. POMCPOW’s
WeightedParticleBeliefStateUpdate.inplace_update()) to skip the per-call numpy setup overhead of the batchedobservation_log_probability()path on a singleton input.The default falls back to the batched method with a one-element observations list. Envs with cheap scalar likelihoods (e.g. the 2-D Gaussian on Push or the cached-inverse-cov path on ContinuousLightDark) should override to skip array allocation.
- reward(state, action, next_state=None)[source]
Calculate the immediate reward for a state-action(-next_state) tuple.
next_stateis the realised post-transition state when known (e.g. threaded bysample_next_step()), allowing rewards that depend on stochastic transition outcomes to use the same draw as the trajectory instead of resampling. Subclasses whose reward is a pure function of(state, action)may ignore it; subclasses whose reward depends on the realised next state (collision penalties, win bonuses) should consume it when provided and fall back to drawing/computing one whenNone.- Parameters:
- Return type:
- Returns:
Immediate reward value.
Note
Subclasses must implement this method to define reward structure.
- reward_batch(states, action, next_states=None)[source]
Calculate rewards for a batch of states given a single action.
When
next_statesis supplied (e.g. by a caller that has already sampled the realised batch transition), it is used directly; otherwise N next states are drawn here via the cachedPushVectorizedUpdater. Per-particle rewards are computed in the C++push_reward_batchkernel (variant-aware: CONSTANT_HAZARD_PENALTY, ZERO_MEAN_HAZARD_SHOCK, DISTANCE_DECAYED_HAZARD_PENALTY) so the batch cost is a single round-trip into native code.
- sample_next_state(state, action, n_samples=1)[source]
Sample one or more next states for
(state, action).Hot-path entry point used by MCTS planners and particle filters. Subclasses must implement.
- sample_next_state_batch(states, action)[source]
Sample one next state per input state, all under the same action.
Used by particle filters: given N current particles and one action, draw N next states (one per particle) in a single vectorized call.
The default implementation falls back to a per-state Python loop delegating to
sample_next_state(). Native-backed envs (those whose state-transition kernel exposesbatch_sample(states_array)) should override to avoid the loop.
- sample_next_step(state, action)[source]
Sample a complete state transition step.
This convenience method combines state transition, observation generation, and reward calculation in a single operation.
- sample_observation(next_state, action, n_samples=1)[source]
Sample one or more observations for
(next_state, action).Hot-path entry point used by MCTS planners and particle filters. Subclasses must implement.
- class POMDPPlanners.environments.push_pomdp.push_pomdp.PushPOMDPMetrics(*values)[source]
Bases:
EnumMetric names for Push POMDP environment.
- DANGEROUS_AREA_RATE = 'dangerous_area_rate'
- GOAL_REACHING_RATE = 'goal_reaching_rate'
- OBJECT_OBSTACLE_COLLISION_RATE = 'object_obstacle_collision_rate'
- ROBOT_OBSTACLE_COLLISION_RATE = 'robot_obstacle_collision_rate'
- TOTAL_ALL_OBSTACLE_COLLISIONS = 'total_all_obstacle_collisions'
- TOTAL_DANGEROUS_AREA_STEPS = 'total_dangerous_area_steps'
- TOTAL_OBJECT_OBSTACLE_COLLISIONS = 'total_object_obstacle_collisions'
- TOTAL_OBSTACLE_COLLISION_RATE = 'total_obstacle_collision_rate'
- TOTAL_ROBOT_OBSTACLE_COLLISIONS = 'total_robot_obstacle_collisions'
- class POMDPPlanners.environments.push_pomdp.push_pomdp.RandomInitialStateDistribution(grid_size, target_pos, obstacles, obstacle_radius, parent)[source]
Bases:
DistributionRandom initial state distribution for Push POMDP.
- Parameters:
- sample(n_samples=1)[source]
Sample values from the distribution.
- Parameters:
n_samples (
int) – Number of samples to return. Defaults to 1.- Return type:
- Returns:
List of n_samples independent samples from the distribution
Note
Subclasses must implement this method according to their specific distribution type and parameters.
POMDPPlanners.environments.push_pomdp.push_pomdp_visualizer module
Visualization module for Push POMDP Environment.
This module provides visualization capabilities for Push POMDP episodes, creating animated GIFs showing robot movement, object pushing, obstacle collisions, and task completion.
- Classes:
PushPOMDPVisualizer: Handles all visualization logic for Push POMDP
- class POMDPPlanners.environments.push_pomdp.push_pomdp_visualizer.PushPOMDPVisualizer(env)[source]
Bases:
objectHandles visualization and animation for Push POMDP environments.
This class encapsulates all visualization logic for Push POMDP episodes, creating animated GIFs showing robot movement, object pushing, obstacle collisions, and task completion.
- Parameters:
env (PushPOMDP)
- env
Reference to the PushPOMDP environment instance
- grid_size
Size of the grid environment
- push_threshold
Distance threshold for robot to push object
- obstacles
List of obstacle positions
- obstacle_radius
Radius of obstacles for collision detection
- create_visualization(history, cache_path)[source]
Create animated visualization of a Push POMDP episode.
Creates an animated GIF showing the robot pushing the object toward the target, with obstacles, collision detection, distance indicators, and success feedback.
- Parameters:
- Raises:
ValueError – If history is empty or cache_path doesn’t end with .gif
TypeError – If cache_path is not a Path object
- Return type: