Skip to content

Conversation

@mpragnay
Copy link

No description provided.

Pragnay Mandavilli and others added 17 commits November 8, 2025 19:40
* Adding Interaction features

Notes:
- Need to add safeguards to load each map only once
- Might be slow if we increase num_agents per scenario, next step will
be torch.

I added some tests to see the distance and ttc computations are correct,
and metrics_sanity_check looks okay. I'll keep making some plots to
validate it.

* Added the additive smoothing logic for Bernoulli estimate.

Ref in original code:
message BernoulliEstimate {
    // Additive smoothing to apply to the underlying 2-bins histogram, to avoid
    // infinite values for empty bins.
    optional float additive_smoothing_pseudocount = 4 [default = 0.001];
  }

* Little cleanup of estimators.py

* Towards map-based realism metrics:

First step: extract the map from the vecenv

* Second step: Map features (signed distance to road edges)

A bunch of little tests in test_map_metric_features.py to ensure this do what it is supposed to do.

python -m pufferlib.ocean.benchmark.test_map_metrics

Next steps should be straightforward.

Will need to check at some point if doing this on numpy isnt too slow

* Map-based features.

This works, and passes all the tests, I would still want to make additionnal checks with the renderer because we never know.

With this, we have the whole set of WOSAC metrics (except for traffic lights), and we might also have the same issue as the original WOSAC code: it is slow.

Next step would be to transition from numpy to torch.

* Added a visual sanity check, plot random  trajectories and indicate when WOSAC sees an offorad or a collision

python pufferlib/ocean/benchmark/visual_sanity_check.py

* Update WOSAC control mode and ids.

* Eval mask for tracks_to_predict agents

* Replacing numpy by torch for the computation of interaction and map metrics.

It makes the computation way faster, and all the tests pass.

I didn't switch kinematics to torch because it was already fast, but I might make the change for consistency.

* Precommit

* Resolve small comments.

* More descriptive error message when going OOM.

---------

Co-authored-by: WaelDLZ <wawa@CRE1-W60060.vnet.valeo.com>
Co-authored-by: Waël Doulazmi <wawa@10-20-1-143.dynapool.wireless.nyu.edu>
Co-authored-by: Waël Doulazmi <wawa@Waels-MacBook-Air.local>
Co-authored-by: Daphne Cornelisse <cor.daphne@gmail.com>
Co-authored-by: Pragnay Mandavilli <pm3881@gr052.hpc.nyu.edu>
* Add option for targeted experiments.

* Rename for clarity.

* Minor

* Remove tag

* Add to help message and make deepcopy of args to prevent state pollution.
)

* Little optimizations to use less memory in interaction_features.py

They mostly consist in using in-place operations and deleting unused variables.

Code passes the tests.

Next steps:
- clean the .cpu().numpy() in ttc computation
- memory optimization for the map_features as well

* Add future todo.

---------

Co-authored-by: Waël Doulazmi <waeldoulazmi@gmail.com>
@greptile-apps
Copy link

greptile-apps bot commented Nov 25, 2025

Greptile Overview

Greptile Summary

This PR introduces dynamic agent initialization per world, allowing configurable numbers of agents to be spawned in each environment. Additionally, it significantly enhances the WOSAC evaluation framework with new interaction metrics (collision detection, time-to-collision, distance-to-nearest-object) and map-based metrics (distance-to-road-edge, offroad detection).

Key Changes:

  • Added dynamic_no_agents initialization mode where agents are dynamically spawned at valid positions with collision checking
  • Refactored map loading in C to support environments with placeholder agents that are initialized on demand
  • Extended agent state representation to include vehicle dimensions (length, width) for more accurate collision detection
  • Implemented road edge polyline extraction from scenarios for map-based metric computation
  • Added controlled experiment mode for systematic hyperparameter sweeps
  • Created comprehensive test suite for new geometric and metric computations
  • Moved from numpy to PyTorch for metric computation to leverage GPU acceleration

Issues Found:

  • Critical: Configuration validation bug in pufferlib/ocean/env_config.h:117 where num_agents_per_world validation depends on init_mode which may not be parsed yet, causing potential incorrect validation

Confidence Score: 4/5

  • Safe to merge with one critical configuration validation bug that should be fixed
  • Score reflects comprehensive implementation with good test coverage and modular design. The configuration validation ordering bug in env_config.h is a critical issue that could cause runtime errors with certain INI file orderings, preventing it from being a 5. The C code additions are substantial but well-structured with proper memory management and collision checking. The Python/benchmark code follows good practices with GPU acceleration support.
  • pufferlib/ocean/env_config.h requires immediate attention to fix the configuration validation ordering dependency

Important Files Changed

File Analysis

Filename Score Overview
pufferlib/ocean/env_config.h 3/5 Added dynamic agent mode with new Init_Mode enum and config validation, but has ordering-dependent validation bug
pufferlib/ocean/drive/binding.c 4/5 Refactored to support dynamic agents per world, improved map allocation logic with better error handling
pufferlib/ocean/env_binding.h 4/5 Added length/width parameters to agent state functions and new road edge polyline functions
pufferlib/ocean/drive/drive.h 4/5 Major additions: dynamic agent initialization, goal validation, spawn point collision checking, and grid map enhancements
pufferlib/pufferl.py 4/5 Added controlled experiment mode for systematic parameter sweeps and updated evaluation with new metrics
pufferlib/ocean/benchmark/evaluator.py 4/5 Added interaction features (collision, TTC, distance to objects) and map features (road edge distance, offroad detection)
pufferlib/ocean/benchmark/metrics.py 4/5 Moved kinematic feature computation to separate module and added new interaction/map feature computations

Sequence Diagram

sequenceDiagram
    participant User
    participant Python as drive.py
    participant Binding as binding.c
    participant Config as env_config.h
    participant Core as drive.h/drive.c
    participant GridMap as GridMap
    
    User->>Python: Initialize Drive(init_mode="dynamic_no_agents")
    Python->>Binding: shared(num_agents, num_maps, ini_file)
    Binding->>Config: ini_parse(ini_file, handler)
    Config-->>Binding: env_init_config with init_mode
    
    alt Dynamic Agents Mode
        Binding->>Binding: Allocate num_agents_per_world per map
        Binding->>Core: load_map_binary(map_file)
        Core->>Core: Read only road entities from binary
        Core->>Core: Create placeholder vehicle entities
        Core-->>Binding: entities with uninitialized agents
    else Standard Mode
        Binding->>Core: load_map_binary(map_file)
        Core->>Core: Read all entities from binary
        Core->>Core: set_active_agents()
        Core-->>Binding: entities with active agents
        Binding->>Binding: Skip maps with no controllable agents
    end
    
    Binding-->>Python: agent_offsets, map_ids, num_envs
    
    Python->>Binding: env_init() for each environment
    Binding->>Core: Initialize Drive environment
    Core->>GridMap: Build grid map with roads
    Core->>Core: Initialize dynamic spawn if needed
    Core-->>Python: Environment ready
    
    User->>Python: reset()
    Python->>Binding: vec_reset()
    Binding->>Core: c_reset()
    
    alt Dynamic Agents Mode
        Core->>Core: get_valid_goal() for each agent
        Core->>Core: is_valid_spawn_point()
        Core->>Core: Initialize agent at valid position
    else Standard Mode
        Core->>Core: Reset to init_steps position
    end
    
    Core-->>Python: Initial observations
    
    User->>Python: step(actions)
    Python->>Binding: vec_step()
    Binding->>Core: c_step() for each env
    Core->>Core: Apply agent actions
    Core->>Core: Update physics/dynamics
    Core->>Core: Check collisions via GridMap
    Core->>Core: Compute rewards
    Core-->>Python: obs, rewards, terminals
    
    User->>Python: get_global_agent_state()
    Python->>Binding: vec_get_global_agent_state()
    Binding->>Core: c_get_global_agent_state()
    Core-->>Python: x, y, z, heading, id, length, width
    
    User->>Python: get_road_edge_polylines()
    Python->>Binding: vec_get_road_edge_polylines()
    Binding->>Core: c_get_road_edge_polylines()
    Core-->>Python: Road edge geometry data
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

28 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +117 to +119
if(env_config->num_agents_per_world <= 0 && env_config->init_mode == DYNAMIC_AGENTS_PER_ENV) {
raise_error_with_message(ERROR_INVALID_CONFIG, "num_agents_per_world must be positive for dynamic_agents_per_env init_mode");
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: validation depends on init_mode being set, but init_mode may not have been parsed yet

If the INI file has num_agents_per_world before init_mode, the validation check on line 117 will use an uninitialized or default value for init_mode, causing incorrect behavior.

Parse init_mode first before validating num_agents_per_world, or defer validation until after all config values are read.

Prompt To Fix With AI
This is a comment left during a code review.
Path: pufferlib/ocean/env_config.h
Line: 117:119

Comment:
**logic:** validation depends on `init_mode` being set, but `init_mode` may not have been parsed yet

If the INI file has `num_agents_per_world` before `init_mode`, the validation check on line 117 will use an uninitialized or default value for `init_mode`, causing incorrect behavior.

Parse `init_mode` first before validating `num_agents_per_world`, or defer validation until after all config values are read.

How can I resolve this? If you propose a fix, please make it concise.

@daphne-cornelisse daphne-cornelisse added this to the 3.0 milestone Dec 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants