def step(self, rl_actions):
    "Advance the environment by one step.\n\n        Assigns actions to autonomous and human-driven agents (i.e. vehicles,\n        traffic lights, etc...). Actions that are not assigned are left to the\n        control of the simulator. The actions are then used to advance the\n        simulator by the number of time steps requested per environment step.\n\n        Results from the simulations are processed through various classes,\n        such as the Vehicle and TrafficLight kernels, to produce standardized\n        methods for identifying specific network state features. Finally,\n        results from the simulator are used to generate appropriate\n        observations.\n\n        Parameters\n        ----------\n        rl_actions : array_like\n            an list of actions provided by the rl algorithm\n\n        Returns\n        -------\n        observation : array_like\n            agent's observation of the current environment\n        reward : float\n            amount of reward associated with the previous state/action pair\n        done : bool\n            indicates whether the episode has ended\n        info : dict\n            contains other diagnostic information from the previous action\n        "
    for _ in range(self.env_params.sims_per_step):
        self.time_counter += 1
        self.step_counter += 1
        if (len(self.k.vehicle.get_controlled_ids()) > 0):
            accel = []
            for veh_id in self.k.vehicle.get_controlled_ids():
                action = self.k.vehicle.get_acc_controller(veh_id).get_action(self)
                accel.append(action)
            self.k.vehicle.apply_acceleration(self.k.vehicle.get_controlled_ids(), accel)
        if (len(self.k.vehicle.get_controlled_lc_ids()) > 0):
            direction = []
            for veh_id in self.k.vehicle.get_controlled_lc_ids():
                target_lane = self.k.vehicle.get_lane_changing_controller(veh_id).get_action(self)
                direction.append(target_lane)
            self.k.vehicle.apply_lane_change(self.k.vehicle.get_controlled_lc_ids(), direction=direction)
        routing_ids = []
        routing_actions = []
        for veh_id in self.k.vehicle.get_ids():
            if (self.k.vehicle.get_routing_controller(veh_id) is not None):
                routing_ids.append(veh_id)
                route_contr = self.k.vehicle.get_routing_controller(veh_id)
                routing_actions.append(route_contr.choose_route(self))
        self.k.vehicle.choose_routes(routing_ids, routing_actions)
        self.apply_rl_actions(rl_actions)
        self.additional_command()
        self.k.simulation.simulation_step()
        self.k.update(reset=False)
        if self.sim_params.render:
            self.k.vehicle.update_vehicle_colors()
        crash = self.k.simulation.check_collision()
        if crash:
            break
        self.render()
    states = self.get_state()
    self.state = np.asarray(states).T
    next_observation = np.copy(states)
    done = ((self.time_counter >= (self.env_params.warmup_steps + self.env_params.horizon)) or self.stuck)
    if done:
        print('done')
        if self.stuck:
            print('stuck')
        else:
            print('time up')
    infos = {}
    if self.env_params.clip_actions:
        rl_clipped = self.clip_actions(rl_actions)
        reward = self.compute_reward(rl_clipped, fail=crash)
    else:
        reward = self.compute_reward(rl_actions, fail=crash)
    return (next_observation, reward, done, infos)
Advance the environment by one step.

Assigns actions to autonomous and human-driven agents (i.e. vehicles,
traffic lights, etc...). Actions that are not assigned are left to the
control of the simulator. The actions are then used to advance the
simulator by the number of time steps requested per environment step.

Results from the simulations are processed through various classes,
such as the Vehicle and TrafficLight kernels, to produce standardized
methods for identifying specific network state features. Finally,
results from the simulator are used to generate appropriate
observations.

Parameters
----------
rl_actions : array_like
    an list of actions provided by the rl algorithm

Returns
-------
observation : array_like
    agent's observation of the current environment
reward : float
    amount of reward associated with the previous state/action pair
done : bool
    indicates whether the episode has ended
info : dict
    contains other diagnostic information from the previous action
def step(self, rl_actions):
    "Advance the environment by one step.\n\n        Assigns actions to autonomous and human-driven agents (i.e. vehicles,\n        traffic lights, etc...). Actions that are not assigned are left to the\n        control of the simulator. The actions are then used to advance the\n        simulator by the number of time steps requested per environment step.\n\n        Results from the simulations are processed through various classes,\n        such as the Vehicle and TrafficLight kernels, to produce standardized\n        methods for identifying specific network state features. Finally,\n        results from the simulator are used to generate appropriate\n        observations.\n\n        Parameters\n        ----------\n        rl_actions : array_like\n            an list of actions provided by the rl algorithm\n\n        Returns\n        -------\n        observation : array_like\n            agent's observation of the current environment\n        reward : float\n            amount of reward associated with the previous state/action pair\n        done : bool\n            indicates whether the episode has ended\n        info : dict\n            contains other diagnostic information from the previous action\n        "
    for _ in range(self.env_params.sims_per_step):
        self.time_counter += 1
        self.step_counter += 1
        if (len(self.k.vehicle.get_controlled_ids()) > 0):
            accel = []
            for veh_id in self.k.vehicle.get_controlled_ids():
                action = self.k.vehicle.get_acc_controller(veh_id).get_action(self)
                accel.append(action)
            self.k.vehicle.apply_acceleration(self.k.vehicle.get_controlled_ids(), accel)
        if (len(self.k.vehicle.get_controlled_lc_ids()) > 0):
            direction = []
            for veh_id in self.k.vehicle.get_controlled_lc_ids():
                target_lane = self.k.vehicle.get_lane_changing_controller(veh_id).get_action(self)
                direction.append(target_lane)
            self.k.vehicle.apply_lane_change(self.k.vehicle.get_controlled_lc_ids(), direction=direction)
        routing_ids = []
        routing_actions = []
        for veh_id in self.k.vehicle.get_ids():
            if (self.k.vehicle.get_routing_controller(veh_id) is not None):
                routing_ids.append(veh_id)
                route_contr = self.k.vehicle.get_routing_controller(veh_id)
                routing_actions.append(route_contr.choose_route(self))
        self.k.vehicle.choose_routes(routing_ids, routing_actions)
        self.apply_rl_actions(rl_actions)
        self.additional_command()
        self.k.simulation.simulation_step()
        self.k.update(reset=False)
        if self.sim_params.render:
            self.k.vehicle.update_vehicle_colors()
        crash = self.k.simulation.check_collision()
        if crash:
            break
        self.render()
    states = self.get_state()
    self.state = np.asarray(states).T
    next_observation = np.copy(states)
    done = ((self.time_counter >= (self.env_params.warmup_steps + self.env_params.horizon)) or self.stuck)
    if done:
        print('done')
        if self.stuck:
            print('stuck')
        else:
            print('time up')
    infos = {}
    if self.env_params.clip_actions:
        rl_clipped = self.clip_actions(rl_actions)
        reward = self.compute_reward(rl_clipped, fail=crash)
    else:
        reward = self.compute_reward(rl_actions, fail=crash)
    return (next_observation, reward, done, infos)