Skip to content

Add support for real-world scheduled traffic - #933

Open
planevan wants to merge 20 commits into
mmp:masterfrom
planevan:feature/real-world-schedules
Open

Add support for real-world scheduled traffic#933
planevan wants to merge 20 commits into
mmp:masterfrom
planevan:feature/real-world-schedules

Conversation

@planevan

Copy link
Copy Markdown

This pull request adds support for generating traffic from real-world airline schedules.

Instead of relying entirely on randomly generated departures and arrivals, Vice can now load scheduled departures and arrivals from CSV files and generate traffic that closely follows real-world airline operations.

The initial implementation includes a built-in MSP weekday schedule as a proof-of-concept implementation in the M98 Scenario.

Features

  • Adds a Real World Schedules traffic source.
  • Loads schedules from CSV files.
  • Supports built-in schedule catalogs.
  • Matches scheduled flights to available airlines and aircraft types.
  • Preserves existing random traffic generation for airports without schedules.
  • Adds realistic departure gate/taxi timing and queuing for scheduled departures.
  • Preserves existing random traffic generation when real-world schedules are not used.

Testing

Tested using the included MSP weekday schedule.

Verified:

  • Schedule loading
  • Arrival generation
  • Departure generation
  • Realistic departure timing
  • Multiple traffic sessions without crashes

The feature compiles successfully, existing tests pass, and simulator testing showed significantly more realistic traffic flow compared to immediate scheduled departures.

This is intended as a foundation for additional airports and schedules. Eventual additions will include the ability for users to create their own schedules by simply creating an airport file in the schedules folder and dropping their CSV in there. Currently, a schedule.json needs to be used.

Future improvements may include automatic schedule discovery, additional built-in schedules, further refinement of departure sequencing, and arrivals spawning inside TRACON to simulate taking over from another controller.

@mmp mmp left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This is a great addition and I think will be a huge step forward for the realism of vice. Lots of comments below, some small things, some bigger changes, but overall I think the general form of this is quite good.

Comment thread sim/schedule_catalog_test.go Outdated
Comment thread resources/schedules/KMSP/schedule.json Outdated
@@ -0,0 +1,13 @@
{
"airport": "KMSP",

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

"airport": "KMSP" is somewhat redundant since the airport name is in the folder name. What about a) renaming this file to schedules.json and then b) having the contents be like:

[
    {
      "id": "summer_weekday",
      "name": "MSP Summer Weekday",
      "file": "summer_weekday.csv",
      "description": "Full-day real-world MSP schedule.",
      "timezone": "America/Chicago"
    }
  ]

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good point. I'll refactor it to use a schedules.json catalog within each airport directory.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Rather than documenting it here, could you add a short section to website/facility-engineering.html? Maybe a new section after "Arrivals and Overflights" and before"VFR Aircraft" under "Scenario Groups"?

It would also be nice to mention there that routes are taken from existing routes in the scenario file if the departure/destination airports match up.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I moved the schedule documentation into facility-engineering.html, added a new "Real World Schedules" section (including the route reuse behavior), added it to the navigation sidebar, and reduced the README to a pointer to the engineering documentation.

Comment thread sim/traffic_provider.go Outdated

departures []scheduledDeparture
nextDeparture int
departuresInitialized bool

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I believe this is unused and could be deleted.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

oops This was left over from an earlier version of the traffic provider and wasn't being used anymore. Removed.

Comment thread sim/spawn.go
depState := s.DepartureState[ac.FlightPlan.DepartureAirport][runway]
if ac.FlightPlan.Rules == av.FlightRulesIFR {
if manualLaunch {
// Keep them moving and for HFR, request the release immediately.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Please restore this comment.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Restored!

Comment thread cmd/vice/simconfig.go
validDuration := apMETAR[idx+1].Time.Sub(sampledMETAR.Time)
startTime = startTime.Add(rand.Make().DurationRange(0, validDuration))
}
c.StartTime = startTime

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Currently the local time in the UI is shown as "00:00" (unless it's manually edited). I think that if we have if TrafficSoruce == RealWorldSchedule and then do something like

  loc, err := time.LoadLocation(schedule.Timezone)
  local := c.StartTime.In(loc)
  lc.ScheduleStartMinute = local.Hour()*60 + local.Minute()
  c.scheduleStartTimeText = formatScheduleStartTime(lc.ScheduleStartMinute)

it will stay in sync.

Comment thread sim/traffic_provider.go

}

// initializeDepartures generates one taxi-out duration for each scheduled

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

stale comment?

Comment thread sim/schedule_catalog.go

const scheduleCatalogFilename = "schedule.json"

// BuiltInSchedule describes one schedule distributed in Vice's resources.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

How about renaming this to FlightSchedule (and similarly for BuiltInScheduleCatalog and BuiltInScheduleSummary)? The rationale being that "built-in" is sort of implied and "flight" more accurately describes what it's holding.

Comment thread server/scenario.go
}

lg.Infof("LoadScenarioGroups total: %s", time.Since(start))
return scenarioGroups, catalogs, mapSpecs, briefs, extraScenarioErrors

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Let's also return scheduleCatalog here, so that we don't end up re-loading the schedules in newScheduleTrafficProvider. In that way, we load and validate schedules just once, which matches how the scenario loading flow works currently for other things. (Generally, we do all the error checking for scenarios at initial loading time and then the rest of the code can assume that things are reasonable, since we error out and exit if there are scenario errors.)

Roughly, if we then store the full schedule catalog in SimManager, then pass the selected schedule (if any) to NewSim in sim.NewSimConfiguration, then we can store it directly in the Sim. Then Sim.activeTrafficProvider() can be simplified to just pass the schedule to newScheduleTrafficProvider without needing to load it.

Comment thread sim/schedule.go
}
}

func normalizeScheduledAircraftType(value string) string {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Just thinking out loud, should these rewrites be encoded in a JSON file in resources so that people doing facility engineering can add them? Should we just require that the schedule CSV files have these rewrites already done? This partially connects to the question of where the data comes from and how we want to be importing it.

@planevan planevan left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Restored comments.

Comment thread sim/spawn_departures.go
nasFp.AssignedAltitude = util.Select(!isTRACON, ac.FlightPlan.Altitude, 0)
nasFp.RNAV = s.State.FacilityAdaptation.Datablocks.DisplayRNAVSymbol && exitRoute.IsRNAV

ac.HoldForRelease = (ap.HoldForRelease || exitRoute.HoldForRelease) && ac.FlightPlan.Rules == av.FlightRulesIFR // VFRs aren't held

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Restored.

Comment thread sim/spawn_departures.go
return nil, err
}

// Departures aren't immediately associated, but the STARSComputer will

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Restored.

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