Skip to content

6 bernhard dev - #580

Open
Kait0 wants to merge 184 commits into
3.0from
6_bernhard_dev
Open

6 bernhard dev#580
Kait0 wants to merge 184 commits into
3.0from
6_bernhard_dev

Conversation

@Kait0

@Kait0 Kait0 commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Changes I made while the others were on vacation.

  • Update maps, fixes holes, add traffic light group information (can be used optionally to control TL during eval)
  • Update default parameters to match GIGAFLOW more closely
  • Fix phantom braking and match to uniform distribution in the paper
  • Add true FP32 support (with TF32 / 19 bit turned off)
  • Fix a bunch of smaller bugs around spawning
  • Made red light infraction be relative to the vehicle center to avoid problems with virtually making the vehicle bigger during eval
  • Added jerk threshold for starting to drive when standing still. Remove a bunch of long tail infractions due to low probabilites making the vehicle creep.
  • Move noralization more to -1, 1 window
  • Average logging acros GPUs.
  • remove constant observation
  • Add acceleration clipping
  • Visualize ego inputs as well
  • Disentangle gradient clipping of actor and critic if they are seperate networks
  • Implement adavantage filter leakage option that keep a small percent of random samples to prevent bias. Turned off by default
  • Add option to visualize training in HTML (removed old EGL stuff)
  • Better training cleanup for multinode
  • Add paralizable evals
  • Some unit tests.

https://wandb.ai/emerge_/nightly-multi-long/runs/k_scaled_0028_1000
1T run. Model gets around 200k km/infraction, which is a new best.

Kait0 added 30 commits August 12, 2026 18:13
    env.goal_source=route \
    env.max_goal_spacing=60 \
…ed on the date and I do not need to touch the script anymore.,
Comment thread pufferlib/config/puffer_drive.yaml Outdated
Comment on lines +104 to +105
# Replay-mode agents flagged mark_as_expert are log-replayed (1) or treated like any other agent (0)
replay_expert_agents: 1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

duplicated config

you should be able to do the same thing with

Controller used by non-SDC vehicles.

options: "static", "policy", "replay", "idm"

non_sdc_controller: policy

Controller used by non-vehicle agents. "auto" follows non_sdc_controller unless it is "idm", then it uses "replay".

options: "auto", "static", "policy", "replay", "idm"

non_vehicle_controller: auto

in replay

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

So I only use replay_expert_agents: 0
for nuPlan and CARLA

Claude claims the 1 branch is necessary for compatibility with WOMD, but I never used WOMD, so idk.
The controllers are category-wide, whereas this flag uses the expert/non-expert flag from the dataset
I would keep it if it doesn't bother.

@vcharraut vcharraut Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I see, I quoted the wrong config then

You could add a new option to control_mode like control_all_vehicles that would actually control all valid cars, enforcing controlling the mark_as_expert ones

Ideally we don't want to create one config variable for every behavior we rather try to merge into existing one when possible

Comment on lines +1745 to 1751
PyObject *tuple = PyTuple_New(4);
PyTuple_SetItem(tuple, 0, agent_offsets);
PyTuple_SetItem(tuple, 1, map_ids_list);
PyTuple_SetItem(tuple, 2, PyLong_FromLong(env_count));
PyTuple_SetItem(tuple, 3, PyLong_FromLong(env_count));
return tuple;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this seems useless

Comment on lines +1681 to 1687
PyObject *tuple = PyTuple_New(4);
PyTuple_SetItem(tuple, 0, agent_offsets);
PyTuple_SetItem(tuple, 1, map_ids_list);
PyTuple_SetItem(tuple, 2, PyLong_FromLong(env_count));
PyTuple_SetItem(tuple, 3, PyLong_FromLong(env_count));
return tuple;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this seems useless

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Slot 3 is maps_consumed, Slot 2 is num_envs. Both are used in the code. We could also set the equivalence elsewhere I guess?

Comment on lines +459 to +461
// Per-episode perturbation rates: uniform in [0, configured max]
env->episode_partner_blindness_prob = sample_uniform(&env->rng_state, 0.0f, env->partner_blindness_prob);
env->episode_phantom_braking_prob = sample_uniform(&env->rng_state, 0.0f, env->phantom_braking_prob);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why do we want a probability for all agents inside an episode vs having a probality per agent ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

To match the gigaflow paper which have an up to 5% number of phantom brakers. That is the total number of phatom brakers in an episode.
The individual phantom braker still has a probability for it to trigger.
We want agents that experience clean episodes and agents that experience crazy epsiodes I think.
Having it per agent would mean that on average all scenarios look the same due to many draws?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Ok I understand. In my comprehension of the paper, the "Up to 10% of agents" refers to all the agents batch-wise, so not per episode

I have no idea which one is correct

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yeah, we can ask eugene when he is back. The uniform distribution I use is also an assumption. Though I think this change did help to reduce the rear end collisions, so I would keep it unless eugene says he has a better solution.

Comment on lines +872 to +919
static bool walk_to_next_goal(
Drive *env,
const int *route,
int route_length,
int cursor_idx,
float s_on_lane,
float spacing_meters,
float prev_heading,
float *out_x,
float *out_y,
float *out_z,
int *out_lane_idx,
int *out_cursor_idx,
float *out_s_on_lane,
float *out_heading) {
// One goal step forward. In free-roam mode with goal_heading_max_deg > 0, re-samples the spacing until the
// landed lane heading is within that angle of prev_heading; accepts the last attempt if none qualifies.
bool constrain_heading = route == NULL && env->goal_heading_max_deg > 0.0f;
float max_heading_delta_rad = env->goal_heading_max_deg * (float) M_PI / 180.0f;
for (int attempt_idx = 0; attempt_idx < GOAL_HEADING_MAX_ATTEMPTS; attempt_idx++) {
if (attempt_idx > 0) {
spacing_meters = sample_uniform(&env->rng_state, env->min_goal_spacing, env->max_goal_spacing);
}
if (!route_point_at_distance(
env,
route,
route_length,
cursor_idx,
s_on_lane,
spacing_meters,
out_x,
out_y,
out_z,
out_lane_idx,
out_cursor_idx,
out_s_on_lane,
out_heading)) {
return false;
}
if (!constrain_heading) {
return true;
}
if (fabsf(normalize_heading(*out_heading - prev_heading)) <= max_heading_delta_rad) {
return true;
}
}
return true;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

do you know if without this we actually have a lot of goals that are not respecting the constraint ?

I have deliberatly skipped this constraint because I assumed the goal sampling for GIGAFLOW paper was only done by doing a random sampling of a lane point within an euclidian distance. But if we follow the lane topology, I expect that we have goals with no shard heading most of time

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I just tried to match it to the gigaflow implementation. I don't think this made any major difference

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm afraid this implementation can favorise closer goals -> the closer the goal is, the more likely it is to respect the 60 degrees contrainst

It would be preferable to move this change to a dedicated PR so we can better emphasize the impact of it

Comment thread pufferlib/ocean/drive/drive.h Outdated
Comment thread pufferlib/ocean/drive/drive.h Outdated
Comment on lines +2596 to +2689
static bool log_pose_overlaps_created_agent(
Drive *env,
Agent *agent,
const int *created_agent_indices,
int created_agent_count) {
for (int i = 0; i < created_agent_count; i++) {
Agent *other = &env->agents[created_agent_indices[i]];
float dx = other->sim_x - agent->sim_x;
float dy = other->sim_y - agent->sim_y;
float max_overlap_dist = agent->radius + other->radius;
if (dx * dx + dy * dy > max_overlap_dist * max_overlap_dist) {
continue;
}
if (fabsf(other->sim_z - agent->sim_z) > Z_BUFFER) {
continue;
}
if (check_obb_collision(agent, other)) {
return true;
}
}
return false;
}

static bool spawn_near_drivable_lane(Drive *env, Agent *agent) {
GridMapEntity entity_list[ROAD_QUERY_ENTITY_COUNT];
int list_size = get_neighbors_entities(
env,
agent->sim_x,
agent->sim_y,
entity_list,
ROAD_QUERY_ENTITY_COUNT,
ROAD_OFFSETS,
25);
for (int i = 0; i < list_size; i++) {
int entity_idx = entity_list[i].entity_idx;
int geometry_idx = entity_list[i].geometry_idx;
RoadMapElement *element = &env->road_elements[entity_idx];
if (!is_drivable_road_lane(element->type)) {
continue;
}
if (fabsf(element->z[geometry_idx] - agent->sim_z) > Z_BUFFER) {
continue;
}
float lane_distance = compute_point_to_segment_distance(
agent->sim_x,
agent->sim_y,
element->x[geometry_idx],
element->y[geometry_idx],
element->x[geometry_idx + 1],
element->y[geometry_idx + 1]);
if (lane_distance <= REPLAY_SPAWN_MAX_LANE_DISTANCE_M) {
return true;
}
}
return false;
}

static bool replay_spawn_fit_for_control(
Drive *env,
Agent *agent,
const int *created_agent_indices,
int created_agent_count) {
if (agent->sim_length > REPLAY_MAX_CONTROLLED_LENGTH_M) {
return false;
}
if (!spawn_near_drivable_lane(env, agent)) {
return false;
}
if (check_spawn_offroad(env, agent, REPLAY_SPAWN_EDGE_CLEARANCE_M)) {
return false;
}
Agent inflated = *agent;
inflated.sim_length += 2.0f * REPLAY_SPAWN_LONGITUDINAL_CLEARANCE_M;
update_agent_radius(&inflated);
for (int i = 0; i < created_agent_count; i++) {
Agent *other = &env->agents[created_agent_indices[i]];
if (other == agent) {
continue;
}
float dx = other->sim_x - inflated.sim_x;
float dy = other->sim_y - inflated.sim_y;
float max_overlap_dist = inflated.radius + other->radius;
if (dx * dx + dy * dy > max_overlap_dist * max_overlap_dist) {
continue;
}
if (fabsf(other->sim_z - inflated.sim_z) > Z_BUFFER) {
continue;
}
if (check_obb_collision(&inflated, other)) {
return false;
}
}
return true;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Ideally this code should be in 123Drive.
But for direct solution as it is, it would better to do inside the init function, similar to remove_bad_trajectories. Either enhance this function or append a new function after

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I think spawn point selection, is somewhat user specific not map specific?
Think this is called twice throughout the code so in the init doesn't make so much sense.

Comment on lines +299 to +300
# Also keep this random fraction of below-threshold transitions; 0 disables the leak
adv_filter_leak_fraction: 0.0

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

is this used in training ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Currently no. I tried 5% leak but no conclusive improvement. Left it there because I think it is a sensible idea that I might want to revisit later.

anneal_lr: true
precision: bfloat16
# false: pure float32 matmuls/convs (no TensorFloat-32); requires precision float32
tf32: true

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

i think we want a better naming for this one

Comment on lines +1564 to +1567
float center_x = agent->sim_x;
float center_y = agent->sim_y;
float prev_center_x = agent->prev_x;
float prev_center_y = agent->prev_y;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

use directly the variable, no need for aliases

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.

2 participants