nickolasclarke / dispatch

A discrete-event simulation (DES) model for simulating deployment of EV bus fleets, using GTFS data
2 stars 0 forks source link

buses do not follow expected run_block() logic #89

Open nickolasclarke opened 4 years ago

nickolasclarke commented 4 years ago

Expected outcome:

  1. a bus is created and assigned to the block. its energy reserves and its starting depot_id are noted.
  2. Before any trip starts, a bus evaluates if it has enough energy to serve the full trip to its final destination.
  3. If it does have enough energy it completes the trip,substracting the energy required to serve the trip from its energy reserves.
    • If a charger is present at the termini where it completes its trip, the bus will opportunistically charge until it has to depart for its next assigned trip.
  4. It repeats this process until one of the following:
    • If it does not have enough energy, the bus returns to the starting depot, and another fully charged bus replaces it. This bus has no starting depot, as it starts in the middle of the block. It follows steps 1-4.
    • If it completes its block, it returns to the nearest depot and charges.

Current outcome:

  1. Buses are reassigned before finishing blocks
  2. buses return to the depot before finishing the block and then return to serve the block.

Further details: Details about Block_id: 93217702 in AC Transit, scenario 220kwh battery, 500kw nondepot chargers.

See this trips file. Strip the .log filetype after downloading, since GH doesnt permit .csv

Intro: This block has 3 buses that are used to complete the block: 672, 673, and 674.

First, lets see a summary of all trips in the block. We can see here that we start with bus 672, which leaves from depot 3 and performs a single trip. It then gets reassigned to another block (see details about the bus below) and is replaced by 673. 673 Continues the block until it is out of energy. Once it is out of energy, it returns to depot 3, charges fully (! this is surprising) and then completes one trip. Then Bus 674 takes over, and completing 3 trips and then returning to depot 3. The block is complete.

opti_trips = pd.read_csv('actransit/220kwh_500_kw_trips.csv', index_col=0)

opti_trips[opti_trips['block_id'] == 93217702].sort_values('end_arrival_time')[['bus_id','end_arrival_time','start_arrival_time','start_depot_id','end_depot_id','end_stop_id','start_stop_id','energy_left','distance']]
bus_id end_arrival_time start_arrival_time start_depot_id end_depot_id end_stop_id start_stop_id energy_left distance
5344 672 24000 21360 3 -9.22337e+18 4792 4733 197.247 18629.2
5345 673 27600 24900 -9.22337e+18 -9.22337e+18 4936 4221 182.63 17540.9
5346 673 31440 28500 -9.22337e+18 -9.22337e+18 4792 4733 167.106 18629.2
5347 673 35160 32400 -9.22337e+18 -9.22337e+18 4936 4221 152.488 17540.9
5348 673 38760 36000 -9.22337e+18 -9.22337e+18 4792 4733 136.964 18629.2
5349 673 42360 39600 -9.22337e+18 -9.22337e+18 4936 4221 122.347 17540.9
5350 673 45960 43200 -9.22337e+18 -9.22337e+18 4792 4733 106.822 18629.2
5351 673 49560 46800 -9.22337e+18 -9.22337e+18 4936 4221 92.2049 17540.9
5352 673 53160 50400 -9.22337e+18 -9.22337e+18 4792 4733 76.6806 18629.2
5353 673 57000 54000 -9.22337e+18 -9.22337e+18 4936 4221 62.0632 17540.9
5354 673 60660 57900 -9.22337e+18 -9.22337e+18 4792 4733 46.5389 18629.2
5355 673 64380 61380 -9.22337e+18 -9.22337e+18 4936 4221 31.9215 17540.9
5356 673 68040 65400 -9.22337e+18 3 4792 4733 9.46222 18629.2
5357 673 71400 68700 3 -9.22337e+18 4936 4221 197.414 17540.9
5358 674 74940 72300 -9.22337e+18 -9.22337e+18 4792 4733 181.89 18629.2
5359 674 78600 75900 -9.22337e+18 -9.22337e+18 4936 4221 167.273 17540.9
5360 674 82140 79500 -9.22337e+18 3 4792 4733 144.813 18629.2

Next lets look at what each of the buses themselves do. First up, Bus 672:

This bus starts on the block detailed above for one trip. It then gets reassigned to another block, 93217602. (why?) It then serves three trips for that block, completing the block and returning to the depot 3, nearly fully charged.

opti_trips[opti_trips['bus_id'] == 672].sort_values('end_arrival_time')[['block_id',      'end_arrival_time','start_arrival_time','start_depot_id','end_depot_id','end_stop_id','start_stop_id','energy_left','distance']]
block_id end_arrival_time start_arrival_time start_depot_id end_depot_id end_stop_id start_stop_id energy_left distance
5344 9.32177e+07 24000 21360 3 -9.22337e+18 4792 4733 197.247 18629.2
5341 9.32176e+07 73800 71100 -9.22337e+18 -9.22337e+18 4936 4221 182.63 17540.9
5342 9.32176e+07 77640 75000 -9.22337e+18 -9.22337e+18 4792 4733 167.106 18629.2
5343 9.32176e+07 81000 78300 -9.22337e+18 3 4936 4221 145.412 17540.9

Next Bus 673: Since 672 is reassigned, 673 picks up. Since it starts in the middle of the block, it does not have a starting depot listed. It travels to the start of the next trip in the block and continues to serve those trips until it no longer has enough energy to serve the next trip. It returns to depot 3 and charges fully (this is unexpected) then returns to finish the block. I need to dig more to see if it actually meets the required starting time of the next trip in the block, given that it has time to return and fully charge. It then serves one additional trip in the block, then returns to the depot before block has been completed, almost fully charged. It is not deployed again.

opti_trips[opti_trips['bus_id'] == 673].sort_values('end_arrival_time')[['block_id',   'end_arrival_time','start_arrival_time','start_depot_id','end_depot_id','end_stop_id','start_stop_id','energy_left','distance']]
block_id end_arrival_time start_arrival_time start_depot_id end_depot_id end_stop_id start_stop_id energy_left distance
5345 9.32177e+07 27600 24900 -9.22337e+18 -9.22337e+18 4936 4221 182.63 17540.9
5346 9.32177e+07 31440 28500 -9.22337e+18 -9.22337e+18 4792 4733 167.106 18629.2
5347 9.32177e+07 35160 32400 -9.22337e+18 -9.22337e+18 4936 4221 152.488 17540.9
5348 9.32177e+07 38760 36000 -9.22337e+18 -9.22337e+18 4792 4733 136.964 18629.2
5349 9.32177e+07 42360 39600 -9.22337e+18 -9.22337e+18 4936 4221 122.347 17540.9
5350 9.32177e+07 45960 43200 -9.22337e+18 -9.22337e+18 4792 4733 106.822 18629.2
5351 9.32177e+07 49560 46800 -9.22337e+18 -9.22337e+18 4936 4221 92.2049 17540.9
5352 9.32177e+07 53160 50400 -9.22337e+18 -9.22337e+18 4792 4733 76.6806 18629.2
5353 9.32177e+07 57000 54000 -9.22337e+18 -9.22337e+18 4936 4221 62.0632 17540.9
5354 9.32177e+07 60660 57900 -9.22337e+18 -9.22337e+18 4792 4733 46.5389 18629.2
5355 9.32177e+07 64380 61380 -9.22337e+18 -9.22337e+18 4936 4221 31.9215 17540.9
5356 9.32177e+07 68040 65400 -9.22337e+18 3 4792 4733 9.46222 18629.2
5357 9.32177e+07 71400 68700 3 -9.22337e+18 4936 4221 197.414 17540.9

And finally Bus 674:

Since bus 673 returns to the depot, bus 674 is assigned. It, however, does have a starting depot unlike 673 did. (why?) It continues to serve the remaining trips in the block, and then once the block is complete, it returns to the depot.

opti_trips[opti_trips['bus_id'] == 674].sort_values('end_arrival_time')[['block_id',       'end_arrival_time','start_arrival_time','start_depot_id','end_depot_id','end_stop_id','start_stop_id','energy_left','distance']]
block_id end_arrival_time start_arrival_time start_depot_id end_depot_id end_stop_id start_stop_id energy_left distance
5361 9.32178e+07 25500 22800 3 -9.22337e+18 4936 4221 197.414 17540.9
5358 9.32177e+07 74940 72300 -9.22337e+18 -9.22337e+18 4792 4733 181.89 18629.2
5359 9.32177e+07 78600 75900 -9.22337e+18 -9.22337e+18 4936 4221 167.273 17540.9
5360 9.32177e+07 82140 79500 -9.22337e+18 3 4792 4733 144.813 18629.2