@@ -473,9 +473,53 @@ static PyObject *vectorize(PyObject *self, PyObject *args) {
473473 return PyLong_FromVoidPtr (vec );
474474}
475475
476+ void apply_parameters (VecEnv * vec , PyObject * params_dict ) {
477+ if (params_dict == NULL || !PyDict_Check (params_dict )) {
478+ return ;
479+ }
480+
481+ // Helper to extract float parameter and apply to all envs
482+ #define APPLY_REWARD_BOUND (param_min_name , param_max_name , coef_index ) \
483+ { \
484+ PyObject *val_min = PyDict_GetItemString(params_dict, param_min_name); \
485+ PyObject *val_max = PyDict_GetItemString(params_dict, param_max_name); \
486+ if (val_min != NULL && PyFloat_Check(val_min)) { \
487+ for (int i = 0; i < vec->num_envs; i++) { \
488+ Drive *drive = (Drive *)vec->envs[i]; \
489+ drive->reward_bounds[coef_index].min_val = (float)PyFloat_AsDouble(val_min); \
490+ } \
491+ } \
492+ if (val_max != NULL && PyFloat_Check(val_max)) { \
493+ for (int i = 0; i < vec->num_envs; i++) { \
494+ Drive *drive = (Drive *)vec->envs[i]; \
495+ drive->reward_bounds[coef_index].max_val = (float)PyFloat_AsDouble(val_max); \
496+ } \
497+ } \
498+ }
499+
500+ APPLY_REWARD_BOUND ("reward_bound_goal_radius_min" , "reward_bound_goal_radius_max" , REWARD_COEF_GOAL_RADIUS );
501+ APPLY_REWARD_BOUND ("reward_bound_collision_min" , "reward_bound_collision_max" , REWARD_COEF_COLLISION );
502+ APPLY_REWARD_BOUND ("reward_bound_offroad_min" , "reward_bound_offroad_max" , REWARD_COEF_OFFROAD );
503+ APPLY_REWARD_BOUND ("reward_bound_comfort_min" , "reward_bound_comfort_max" , REWARD_COEF_COMFORT );
504+ APPLY_REWARD_BOUND ("reward_bound_lane_align_min" , "reward_bound_lane_align_max" , REWARD_COEF_LANE_ALIGN );
505+ APPLY_REWARD_BOUND ("reward_bound_lane_center_min" , "reward_bound_lane_center_max" , REWARD_COEF_LANE_CENTER );
506+ APPLY_REWARD_BOUND ("reward_bound_velocity_min" , "reward_bound_velocity_max" , REWARD_COEF_VELOCITY );
507+ APPLY_REWARD_BOUND ("reward_bound_traffic_light_min" , "reward_bound_traffic_light_max" , REWARD_COEF_TRAFFIC_LIGHT );
508+ APPLY_REWARD_BOUND ("reward_bound_center_bias_min" , "reward_bound_center_bias_max" , REWARD_COEF_CENTER_BIAS );
509+ APPLY_REWARD_BOUND ("reward_bound_vel_align_min" , "reward_bound_vel_align_max" , REWARD_COEF_VEL_ALIGN );
510+ APPLY_REWARD_BOUND ("reward_bound_overspeed_min" , "reward_bound_overspeed_max" , REWARD_COEF_OVERSPEED );
511+ APPLY_REWARD_BOUND ("reward_bound_timestep_min" , "reward_bound_timestep_max" , REWARD_COEF_TIMESTEP );
512+ APPLY_REWARD_BOUND ("reward_bound_reverse_min" , "reward_bound_reverse_max" , REWARD_COEF_REVERSE );
513+ APPLY_REWARD_BOUND ("reward_bound_throttle_min" , "reward_bound_throttle_max" , REWARD_COEF_THROTTLE );
514+ APPLY_REWARD_BOUND ("reward_bound_steer_min" , "reward_bound_steer_max" , REWARD_COEF_STEER );
515+ APPLY_REWARD_BOUND ("reward_bound_acc_min" , "reward_bound_acc_max" , REWARD_COEF_ACC );
516+
517+ #undef APPLY_REWARD_BOUND
518+ }
519+
476520static PyObject * vec_reset (PyObject * self , PyObject * args ) {
477- if (PyTuple_Size (args ) != 2 ) {
478- PyErr_SetString (PyExc_TypeError , "vec_reset requires 2 arguments" );
521+ if (PyTuple_Size (args ) != 3 ) {
522+ PyErr_SetString (PyExc_TypeError , "vec_reset requires 3 arguments" );
479523 return NULL ;
480524 }
481525
@@ -484,6 +528,17 @@ static PyObject *vec_reset(PyObject *self, PyObject *args) {
484528 return NULL ;
485529 }
486530
531+ PyObject * params = PyTuple_GetItem (args , 2 );
532+
533+ if (params == Py_None ) {
534+ // skip parameter logic
535+ } else if (!PyDict_Check (params )) {
536+ PyErr_SetString (PyExc_TypeError , "parameters must be dict or None" );
537+ return NULL ;
538+ } else {
539+ apply_parameters (vec , params );
540+ }
541+
487542 PyObject * seed_arg = PyTuple_GetItem (args , 1 );
488543 if (!PyObject_TypeCheck (seed_arg , & PyLong_Type )) {
489544 PyErr_SetString (PyExc_TypeError , "seed must be an integer" );
0 commit comments