2

Link to previous question

I am using a tool called TraCI that lets a user control a simulation software called SUMO using Python. So, my code contains functions from traci module in Python. I have previously asked a question about traci code that you might want to see. However, I want to clarify that this question is about Python. I have mentioned traci only because you will see functions from that module.

What I want to do?

I want to combine the output dictionaries of multiple units into a pandas data frame. Following is my input data:

import numpy as np
import pandas as pd
from pandas import Series, DataFrame


data = {'ADO_name':['car1','car1','car1','car1','car1','car1',
                    'car2','car2','car2','car2','car2','car2'],
        'Time_sec':[0,1,2,3,4,5,
                    0,1,2,3,4,5],
        'Speed.mps':[13.9,15,18,20,21,22,
                     0,   0, 13.9,13.9,13.9,14.5]}
                     
dframe = DataFrame(data)

dframe = dframe.sort_values('Time_sec')  

How is data generated?

The input dframe above is used in a loop to run the two cars for a given time step and given speed as shown below:

step = 0

#running traci
while step <= 1:
    traci.simulationStep() # traci function to start a simulation step
    for ado in dframe["ADO_name"].unique():
        
        traci.vehicle.setSpeed(ado, dframe[(dframe.Time_sec == step) & (dframe.ADO_name == ado)]['Speed.kph']) # traci function to set the speed of both cars 
        print(traci.vehicle.getSubscriptionResults(ado)) # traci function to get results
             
    step += 1  

output

{64: 0.0, 80: 'highway1.1', 81: 'highway1.1_0', 86: 400.0}
{64: 0.0, 80: 'highway1.1', 81: 'highway1.1_1', 86: 100.0}
{64: 13.9, 80: 'highway1.1', 81: 'highway1.1_0', 86: 413.9}
{64: 0.0, 80: 'highway1.1', 81: 'highway1.1_1', 86: 100.0}  

The function traci.vehicle.getSubscriptionResults() produces the speed (key = 64), roadID (80), laneID (81) and lane position (86) variables as the output for each time step and each car. In the above results, the first 2 dictionaries represent the output of car1 and car2 (one after the other) in time step 0. Similarly, the last 2 represent the outputs in time step 1. I want to combine this output in one data frame.

Expected output

  ADO_name  Speed.mps        laneID  lane_pos      roadID  step
0     car1        0.0  highway1.1_0     400.0  highway1.1     0
1     car2        0.0  highway1.1_1     100.0  highway1.1     0
2     car1       13.9  highway1.1_0     413.9  highway1.1     1
3     car2        0.0  highway1.1_0     100.0  highway1.1     1

What I have tried?

I am new to Python and pandas so despite searching for hours to figure this out, I haven't been successful. I know that I can probably use dictionary functions e.g. traci.vehicle.getSubscriptionResults(ado).get(64) to get the speed variable. But I don't know how to append the results in each loop. I have also tried following:

print(DataFrame(traci.vehicle.getSubscriptionResults(ado), index = [step]))
>     64          80            81     86
0  0.0  highway1.1  highway1.1_0  400.0
    64          80            81     86
0  0.0  highway1.1  highway1.1_1  100.0
     64          80            81     86
1  13.9  highway1.1  highway1.1_0  413.9
    64          80            81     86
1  0.0  highway1.1  highway1.1_1  100.0 

But this is not what I expected. Please guide me on how to handle this problem? How can I collect results and clean the dictionary to get the final expected output? Any relevant examples/blogs will be helpful. Thanks.

Community
  • 1
  • 1
umair durrani
  • 5,597
  • 8
  • 45
  • 85

1 Answers1

1

The solution I see is to modify your simulation loop to append each dictionary into a list, insert new keys for ADO_name and step, and then pass that list of dicts to DataFrame after the loop.

Here's the modified loop. This is untested, but I believe the idea is right:

step = 0
# Create an empty list before the loop
list_of_dicts = []

#running traci
while step <= 1:
    traci.simulationStep() # traci function to start a simulation step
    for ado in dframe["ADO_name"].unique():

        traci.vehicle.setSpeed(ado, dframe[(dframe.Time_sec == step) & (dframe.ADO_name == ado)]['Speed.kph']) # traci function to set the speed of both cars 
        print(traci.vehicle.getSubscriptionResults(ado)) # traci function to get results

        # A block of new code
        d = traci.vehicle.getSubscriptionResults(ado)
        d['ADO_name'] = ado
        d['step'] = step
        list_of_dicts.append(d)

    step += 1  

Assuming the loop runs with no errors, you should end up with a list like this:

ds = [{64: 0.0, 80: 'highway1.1', 81: 'highway1.1_0', 86: 400.0, 'ADO_name': 'car1', 'step': 0}, 
      {64: 0.0, 80: 'highway1.1', 81: 'highway1.1_1', 86: 100.0, 'ADO_name': 'car2', 'step': 0},
      {64: 13.9, 80: 'highway1.1', 81: 'highway1.1_0', 86: 413.9, 'ADO_name': 'car1', 'step': 1}, 
      {64: 0.0, 80: 'highway1.1', 81: 'highway1.1_1', 86: 100.0, 'ADO_name': 'car2', 'step': 1}]

Final step to your desired output:

result = pd.DataFrame(ds).rename(columns={64: 'Speed.mps', 
                                          80: 'roadID', 
                                          81: 'laneID',
                                          86: 'lane_pos'})

result
   Speed.mps      roadID        laneID  lane_pos ADO_name  step
0        0.0  highway1.1  highway1.1_0     400.0     car1     0
1        0.0  highway1.1  highway1.1_1     100.0     car2     0
2       13.9  highway1.1  highway1.1_0     413.9     car1     1
3        0.0  highway1.1  highway1.1_1     100.0     car2     1
Peter Leimbigler
  • 10,775
  • 1
  • 23
  • 37