flightdb

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 13, 2019 License: Apache-2.0 Imports: 24 Imported by: 4

README

flightdb - a database for flight tracks

Prerequisites:

Download and run things locally

  • go get github.com/skypies/flightdb/app/frontend (pulls down all dependencies)
  • goapp serve $GOPATH/github.com/skypies/flightdb/app/frontend (build & run locally)
  • Look at http://localhost:8080/ (appengine admin panel is http://localhost:8000/)

To deploy everything into a Google Cloud project:

$ gcloud app deploy --project=serfr0-fdb app/frontend --version=one
$ gcloud app deploy --project=serfr0-fdb app/backend  --version=one

$ gcloud app deploy --project=serfr0-fdb app/dispatch.yaml
$ gcloud app deploy --project=serfr0-fdb app/queues.yaml
$ gcloud app deploy --project=serfr0-fdb app/cron.yaml
$ gcloud app deploy --project=serfr0-fdb app/index.yaml

If you want it to accumulate realtime flight track data, you'll also want to:

  • deploy github.com/skypies/pi/skypi onto some Raspberry Pi receivers
  • deploy github.com/skypies/pi/consolidator into a VM inside your project

The skypies will post bundles of received ADSB (and perhaps MLAT) messages up to Google PubSub, every second or so. The consolidator will read those bundles, group them by airframe, and add them into the database.

If you have CSV dumps of historical flight track data (perhaps from the FAA), you can import it using the code in github.com/skypies/flightdb/app/backend/foia.go.

Documentation

Overview

This package contains all the types for the flight database. No AppEngine imports.

Index

Constants

View Source
const KWaypointTagPrefix = "^"
View Source
const (
	// This is the 'quantization' value, used to index a flight based on
	// which timeslots it overlaps. Never change this value once you've
	// started populating a database, unless you're going to regenerate it
	TimeslotDuration = 30 * time.Minute
)

Variables

View Source
var (
	OceanicAirports = map[string]int{
		"LIH": 1, "OGG": 1, "HNL": 1, "KOA": 1, "NRT": 1, "HND": 1, "KIX": 1, "PVG": 1, "PEK": 1, "CAN": 1,
		"CTU": 1, "WUH": 1, "HKG": 1, "TPE": 1, "ICN": 1, "MNL": 1, "NHL": 1, "SYD": 1, "VRD": 1, "AKL": 1,

		"NZAA": 1, "ZGGG": 1, "ZUUU": 1, "VHHH": 1, "RJTT": 1, "PHNL": 1, "RKSI": 1, "RJBB": 1, "PHKO": 1,
		"PHLI": 1, "RPLL": 1, "RJAA": 1, "ZBAA": 1, "PHOG": 1, "ZSPD": 1, "YSSY": 1, "RCTP": 1, "ZHHH": 1,
	}
	SouthwestAirports = map[string]int{
		"PHX": 1, "TUS": 1, "SBP": 1, "LAX": 1, "LGB": 1, "BUR": 1, "ONT": 1, "SNA": 1, "DCA": 1,
		"SBA": 1, "PSP": 1, "SAN": 1,
	}
	NorCalAirports = map[string]int{
		"SFO": 1, "SJC": 1, "OAK": 1,
	}
)

Find a better home for this config

View Source
var DefaultBlobEncoding = AsGzippedGob // Try and save some datastore GB-months.
View Source
var (
	KMemcacheFIFOSetKey = "singleton-gob:fifoset"
)
View Source
var (
	KWaypointSnapKM = 1.0
)
View Source
var NorCalProcedures = []Procedure{
	{
		Name:      "BIGSUR2",
		Waypoints: []string{"ANJEE", "SKUNK", "BOLDR", "MENLO"},
		Required:  map[string]int{"ANJEE": 1, "SKUNK": 1},
	},
	{
		Name:      "SERFR2",
		Waypoints: []string{"WWAVS", "EPICK", "EDDYY", "SWELS", "MENLO"},
		Required:  map[string]int{"WWAVS": 1, "EPICK": 1},
	},
	{
		Name:      "WWAVS1",
		Waypoints: []string{"WWAVS", "WPOUT", "THEEZ", "WESLA", "MVRKK"},
		Required:  map[string]int{"WWAVS": 1, "WPOUT": 1},
	},
}

Functions

func BlankGeoRestrictorIntoParams

func BlankGeoRestrictorIntoParams(p map[string]interface{})

Also called externally

func CallsignStringsEqual

func CallsignStringsEqual(c1, c2 string) bool

func DebugFlightSnapshotList

func DebugFlightSnapshotList(snaps []FlightSnapshot) string

func FormValueGeoRestrictor

func FormValueGeoRestrictor(r *http.Request) (geo.Restrictor, error)

func GeoRestrictorAsValues

func GeoRestrictorAsValues(gr geo.Restrictor) url.Values

TODO: Should figure out a nice way to get this into the geo.Restrictor interface, without making geo/ depend on util/widget

func GeoRestrictorIntoParams

func GeoRestrictorIntoParams(gr geo.Restrictor, p map[string]interface{})

func ParseIata

func ParseIata(s string) (string, int64, error)

func StringsToInt64s

func StringsToInt64s(in []string) ([]int64, error)

Types

type Airframe

type Airframe struct {
	Icao24         string
	Registration   string
	EquipmentType  string
	CallsignPrefix string
}

An Airframe is a thing that flies. We use Icao24 (ADS-B Mode-S) identifiers to identify them. Their registration and equipment type values should be constant over many flights. If we encounter an airframe using a Type-C callsign (e.g. "AAL353"), we snag the airline prefix (e.g. "AAL"), assuming that the aircraft is part of an airline's fleet.

func (Airframe) String

func (af Airframe) String() string

type AnalysisDisplayEnum

type AnalysisDisplayEnum int
const (
	AnalysisDisplayDefault AnalysisDisplayEnum = iota
	AnalysisDisplayOmit
	AnalysisDisplayHighlight // "red-large"
)

type BlobEncoding

type BlobEncoding int64
const (
	AsGob BlobEncoding = iota
	AsGzippedGob
)

type BoxMatcher

type BoxMatcher struct {
	Tag string
	geo.LatlongBox
}

type Callsign

type Callsign struct {
	Raw string

	CallsignType
	Registration string
	IcaoPrefix   string
	ATCSuffix    string // should be one char, really
	Number       int64
}

func NewCallsign

func NewCallsign(callsign string) (ret Callsign)

func (Callsign) Equal

func (c1 Callsign) Equal(c2 Callsign) bool

func (*Callsign) MaybeAddPrefix

func (c *Callsign) MaybeAddPrefix(prefix string)

func (Callsign) String

func (c Callsign) String() string

type CallsignType

type CallsignType int

https://en.wikipedia.org/wiki/Airline_codes#Call_signs_.28flight_identification_or_flight_ID.29

const (
	Undefined CallsignType = iota
	JunkCallsign
	Registration // Callsign Type A
	// Callsign Type B - we never see it, and it's useless anyway
	IcaoFlightNumber // Callsign Type C
	BareFlightNumber // Some airlines omit the Icao carrier code, grr

)

type CompareOutcome

type CompareOutcome struct {
	TimeDisposition geo.OverlapOutcome // how the tracks compare in terms of time overlap
	OverlapStart    time.Time          // If there *is* a time overlap, this is when it starts
	time.Duration                      // embedded; Duration of any overlap, or gap between non-overlapping tracks

	// If times overlap, figure out space overlap
	OverlapA         *Track
	OverlapB         *Track
	SpaceDisposition geo.OverlapOutcome
	SpaceOverlap     float64

	// Debugging junk
	Log string
}

func (CompareOutcome) String

func (o CompareOutcome) String() string

type CondensedFlight

type CondensedFlight struct {
	IdSpec           string    `json:"id,omitempty"`
	BestFlightNumber string    `json:"f,omitempty"` // IATA, unless it is ICAO
	IcaoId           string    `json:"icao,omitempty"`
	Start            time.Time `json:"s,omitempty"` // f.Times()
	End              time.Time `json:"e,omitempty"` // f.Times()

	Tags      []string
	Waypoints map[string]time.Time `json:"wp,omitempty"`
	Procedure FlownProcedure       `json:"proc,omitempty"`
}

A CondensedFlight is a very small standalone object that represents a flight. The intent is to be able to easily handle large volumes of them - in particular, to store a whole day's worth of NorCal in <1MB, and so be able to cache them in a single DataStore object.

func (CondensedFlight) String

func (cf CondensedFlight) String() string

func (CondensedFlight) WaypointList

func (cf CondensedFlight) WaypointList() []string

Use the waypoint sorting junk from flight.go

type DataProvider

type DataProvider string
const (
	DPUnknown DataProvider = "?"
	DPSkypi   DataProvider = "SkyPi" // AKA 'ADSB'
	DPFA      DataProvider = "FA"
	DPFR24    DataProvider = "fr24"
	DPFAAFOIA DataProvider = "FOIA"
)

func (DataProvider) LongString

func (dp DataProvider) LongString() string

type DataSystem

type DataSystem string
const (
	DSUnknown        DataSystem = "?"
	DSADSB           DataSystem = "A" // AKA TA
	DSMLAT           DataSystem = "M"
	DSRadar          DataSystem = "Z" // AKA TZ
	DSCorrectedRadar DataSystem = "F"
)

func (DataSystem) LongString

func (ds DataSystem) LongString() string

type FIFOItem

type FIFOItem struct {
	Created time.Time
	Item    FlightSnapshot
}

type FIFOSet

type FIFOSet map[string]FIFOItem

func (FIFOSet) AddIfNew

func (s FIFOSet) AddIfNew(fs FlightSnapshot) (addedOk bool)

func (FIFOSet) AgeOut

func (s FIFOSet) AgeOut(d time.Duration)

func (FIFOSet) Exists

func (s FIFOSet) Exists(fs FlightSnapshot) bool

func (FIFOSet) FindNew

func (f FIFOSet) FindNew(input []FlightSnapshot) []FlightSnapshot

Updates the FIFOSet, adding newly flights; returns just those flights that were previousy unknown

func (FIFOSet) Remove

func (s FIFOSet) Remove(fs FlightSnapshot)

func (FIFOSet) String

func (s FIFOSet) String() string

type Flight

type Flight struct {
	Identity  // embedded
	Airframe  // embedded
	Tracks    map[string]*Track
	Tags      map[string]int
	Waypoints map[string]time.Time

	DebugLog string
	// contains filtered or unexported fields
}

func BlankFlight

func BlankFlight() Flight

func NewFlightFromTrackFragment

func NewFlightFromTrackFragment(frag *TrackFragment) *Flight

func (*Flight) Analyse

func (f *Flight) Analyse() (error, string)

func (*Flight) AnalyseWaypoints

func (f *Flight) AnalyseWaypoints()

This is all so horrid.

func (Flight) AnyTrack

func (f Flight) AnyTrack() Track

func (Flight) AnyTrackWithName

func (f Flight) AnyTrackWithName() (Track, string)

func (*Flight) ArbitraryTimeslots

func (f *Flight) ArbitraryTimeslots(d time.Duration) []time.Time

func (Flight) AtWaypoint

func (f Flight) AtWaypoint(wpName string) (string, int)

Find the point in a track at which we intersected waypoint. Empty string means no match

func (*Flight) ComputeIndicatedAltitudes

func (f *Flight) ComputeIndicatedAltitudes(metars *metar.Archive)

ComputeIndicatedAltitudes Would be nice to find a better home for this, to not pollute metar with this file

func (*Flight) Condense

func (f *Flight) Condense() *CondensedFlight

func (*Flight) DetermineFlownProcedure

func (f *Flight) DetermineFlownProcedure() FlownProcedure

func (*Flight) DetermineFlownProcedures

func (f *Flight) DetermineFlownProcedures() []FlownProcedure

func (*Flight) DropTag

func (f *Flight) DropTag(tag string)

func (*Flight) FlewProcedure

func (f *Flight) FlewProcedure(p Procedure) (bool, string)

Did the flight fly the 'Required' waypoints of the procedure ? The string is the name of the final waypoint of the procedure that was flown - i.e. the flight was vectored off-procedure after that waypoint.

func (Flight) FlightawareUrl

func (f Flight) FlightawareUrl() string

func (*Flight) ForBigQuery

func (f *Flight) ForBigQuery() *FlightForBigQuery

func (*Flight) GetDatastoreKey

func (f *Flight) GetDatastoreKey() string

Functions to support indexing & retrieval in the DB

func (*Flight) GetIntersectableTrack

func (f *Flight) GetIntersectableTrack() IntersectableTrack

GetIntersectableTrack contains the logic that decides which particular track(s) within a flight is best suited for georestriction analysis. Those tracks are potentially mutated, and the output is returned as a track with pre-computed junk.

func (*Flight) GetLastUpdate

func (f *Flight) GetLastUpdate() time.Time

func (*Flight) HasDestinationMatch

func (f *Flight) HasDestinationMatch(dests map[string]int) bool

func (*Flight) HasOriginMatch

func (f *Flight) HasOriginMatch(origins map[string]int) bool

func (*Flight) HasTag

func (f *Flight) HasTag(tag string) bool

func (Flight) HasTrack

func (f Flight) HasTrack(name string) bool

func (*Flight) HasWaypoint

func (f *Flight) HasWaypoint(wp string) bool

func (Flight) IdSpec

func (f Flight) IdSpec() IdSpec

func (Flight) IdSpecString

func (f Flight) IdSpecString() string

func (Flight) IdentString

func (f Flight) IdentString() string

func (Flight) IdentityString

func (f Flight) IdentityString() string

USE THIS ONE AT ALL TIMES

func (*Flight) IndexTagList

func (f *Flight) IndexTagList() []string

Real tags, and things we want to search on

func (Flight) Legend

func (f Flight) Legend() string

func (Flight) ListTracks

func (f Flight) ListTracks() []string

func (*Flight) MergeIdentityFrom

func (f1 *Flight) MergeIdentityFrom(f2 Flight) bool

Returns true if f1 was updated

func (Flight) MidTime

func (f Flight) MidTime() time.Time

func (*Flight) NormalizedCallsignString

func (f *Flight) NormalizedCallsignString() string

Normalization: only applies to the ICAO style ones (and then, really just SWA, etc) 1. Remove all zero padding on numbers 2. Incorporate missing carrier code, if we have it from airframe

func (Flight) OldIdentifier

func (f Flight) OldIdentifier() string

func (*Flight) OverlayAirframe

func (f *Flight) OverlayAirframe(af Airframe)

func (*Flight) ParseCallsign

func (f *Flight) ParseCallsign() CallsignType

This happens at the flight level, as we shuffle data between identity & airframe

func (Flight) PreferredTrack

func (f Flight) PreferredTrack(pref []string) (string, Track)

func (*Flight) PruneTrackContents

func (f *Flight) PruneTrackContents()

This is to help save RAM when compiling lists of flights

func (*Flight) SatisfiesGeoRestrictorSet

func (f *Flight) SatisfiesGeoRestrictorSet(grs GeoRestrictorSet) (bool, RestrictorSetIntersectOutcome)

Kinda useless without the outcome intersections

func (*Flight) SetAirportComboTagsFor

func (f *Flight) SetAirportComboTagsFor(airports map[string]int, stem string)

If the aircraft flies to/from any of the airports in the list, set two tags:

to airport:    :STEM   :STEM:
from airport:  STEM:   :STEM:

func (*Flight) SetDatastoreKey

func (f *Flight) SetDatastoreKey(k string)

func (*Flight) SetLastUpdate

func (f *Flight) SetLastUpdate(t time.Time)

func (*Flight) SetTag

func (f *Flight) SetTag(tag string)

func (*Flight) SetTags

func (f *Flight) SetTags(tags []string)

func (*Flight) SetWaypoint

func (f *Flight) SetWaypoint(wp string, t time.Time)

func (Flight) String

func (f Flight) String() string

func (*Flight) TagCoarseFlightpathForSFO

func (f *Flight) TagCoarseFlightpathForSFO()

:SFO_W for western arrivals (oceanic) to SFO. :SFO_E for eastern arrivals to SFO. :SFO_N for northen arrivals to SFO. :SFO_NE are SFO_N that loop over FINSH :SFO_NW are SFO_N that pass over BRIXX(KSFO) at >5000' :SFO_S for southern arrivals: :SFO && 30 km box around ANJEE, WWAVS, or their midpoint) SFO_S: for southern departures: (SFO: ||OAK:) && 30 km (TBR) box around PPEGS :SJC_N arrivals into SJC that pass through BRIXX (i.e. over KSFO)

func (Flight) TagList

func (f Flight) TagList() []string

func (*Flight) TakeSnapshotAt

func (f *Flight) TakeSnapshotAt(t time.Time) *FlightSnapshot

Returns nil if flight not known at that time. Does not interpolate; returns the 'most recent' trackpoint to the specified time

func (Flight) Times

func (f Flight) Times() (s, e time.Time)

func (*Flight) Timeslots

func (f *Flight) Timeslots() []time.Time

func (*Flight) ToBlob

func (f *Flight) ToBlob() (*IndexedFlightBlob, error)

func (Flight) TrackUrl

func (f Flight) TrackUrl() string

func (Flight) WaypointList

func (f Flight) WaypointList() []string

type FlightForBigQuery

type FlightForBigQuery struct {
	FdbId string // ID back into the flight database

	ModeS        string
	Registration string
	Equip        string // e.g. B744, A320 etc

	Start, End   time.Time // start and end of track data points
	DatePST      string    // Bleargh. This is somewhat approximate.
	TrackSources []string
	Tags         []string

	Waypoint  []WaypointForBigQuery // Not 'Waypoints', so that the SQL reads more naturally
	Procedure []FlownProcedure

	// These fields only defined if we have schedule data for the flight
	FlightNumber string // IATA scheduled flight number
	FlightKey    string // A {flightnumber+date} value; can be used to join against complaints
	Airline      string // IATA airline code, if known
	Callsign     string
	Orig, Dest   string // airport codes
}

FlightForBigQuery is a represenation of a Flight that is slightly denormalized, with a track summary instead of a track. It is designed for import into BigQuery, for analysis. It has a *lot* in common with CondensedFlight ... perhaps they should be combined ?

func (FlightForBigQuery) String

func (fbq FlightForBigQuery) String() string

type FlightSnapshot

type FlightSnapshot struct {
	Flight
	Trackpoint

	PrevPos Trackpoint // Where the aircraft is at this point in time (contains a timestamp)
	NextPos Trackpoint // For historic results, the trackpoint that follows the time

	// If we have a reference point, figure out where this flight is in relation to it
	Reference          geo.Latlong
	DistToReferenceKM  float64 // 2D distance, between latlongs
	Dist3ToReferenceKM float64 // 3D distance, accounting for altitude (not yet elevation though)
	BearingToReference float64 // [0,360)
}

func (*FlightSnapshot) LocalizeTo

func (fs *FlightSnapshot) LocalizeTo(refpt geo.Latlong, elevation float64)

func (FlightSnapshot) String

func (fs FlightSnapshot) String() string

type FlightSnapshotsByDist

type FlightSnapshotsByDist []FlightSnapshot

func (FlightSnapshotsByDist) Len

func (s FlightSnapshotsByDist) Len() int

func (FlightSnapshotsByDist) Less

func (s FlightSnapshotsByDist) Less(i, j int) bool

func (FlightSnapshotsByDist) Swap

func (s FlightSnapshotsByDist) Swap(i, j int)

type FlightSnapshotsByDist3

type FlightSnapshotsByDist3 []FlightSnapshot

func (FlightSnapshotsByDist3) Len

func (s FlightSnapshotsByDist3) Len() int

func (FlightSnapshotsByDist3) Less

func (s FlightSnapshotsByDist3) Less(i, j int) bool

func (FlightSnapshotsByDist3) Swap

func (s FlightSnapshotsByDist3) Swap(i, j int)

type FlownProcedure

type FlownProcedure struct {
	Name          string `json:"name,omitempty"`          // Name of the proecdure itself
	VectoredAfter string `json:"vectoredafter,omitempty"` // Name of the final on-procedure waypoint
}

func (FlownProcedure) String

func (fp FlownProcedure) String() string

type GeoRestrictorSet

type GeoRestrictorSet struct {
	Name  string
	User  string
	Logic RestrictorCombinationLogic
	Tags  []string

	R []geo.Restrictor

	DSKey string
}

func (GeoRestrictorSet) Debug

func (grs GeoRestrictorSet) Debug() string

func (GeoRestrictorSet) IsAdhoc

func (grs GeoRestrictorSet) IsAdhoc() bool

func (GeoRestrictorSet) IsNil

func (grs GeoRestrictorSet) IsNil() bool

func (GeoRestrictorSet) OnelineString

func (grs GeoRestrictorSet) OnelineString() string

func (GeoRestrictorSet) String

func (grs GeoRestrictorSet) String() string

func (*GeoRestrictorSet) ToBlob

type IdSpec

type IdSpec struct {
	IcaoId        string
	Registration  string
	Callsign      string
	time.Time     // embed
	time.Duration // embed; optional; for when we're given a time range.
}

An identifier specifier - something we receive (or generate) that uniquely identifies a flight. Can be {airframe+time}, or {callsign+time}; maybe later we'll support flight designators.

func NewIdSpec

func NewIdSpec(idspecString string) (IdSpec, error)

Parse a string into a new spec

A23A23@14123123123123  (IcaoId at an epoch time)
A23A23@2006-01-02T15:04:05Z07:00  (IcaoId at an RFC3339 time)
A23A23@14111111111111:14222222222222  (IcaoId within time range; could be multiple matches)
UAL123@14123123123123  (IATACallsign instead of IcaoId)
N1234S@14123123123123  (Registration Callsign instead of IcaoId)

func (IdSpec) String

func (idspec IdSpec) String() string

The string serialization is used as a basic ID in many places (e.g. the idspec CGI arg)

type Identity

type Identity struct {
	IcaoId string // hex string (cf. adsb.IcaoId)

	// For callsigns, consider f.NormalizedCallsignString() instead, or the stuff in callsign.go
	Callsign string // This is raw, as found in ADS-B transmission.

	Schedule // embedded; not always populated

	ForeignKeys map[string]string // fr24, fa, fdbV1(?), etc
}

func (Identity) FullString

func (id Identity) FullString() string

func (Identity) IdentString

func (id Identity) IdentString() string

func (Identity) IsScheduled

func (id Identity) IsScheduled() bool

func (*Identity) ParseIata

func (id *Identity) ParseIata(s string) error

type IndexedFlightBlob

type IndexedFlightBlob struct {
	Blob         []byte `datastore:",noindex"`
	BlobEncoding BlobEncoding

	Icao24     string
	Ident      string    // Right now, this is the ADS-B callsign (SKW2848, or N1J421)
	LastUpdate time.Time // Used to identify most-recent instance of Icao24 for ADS-B
	Timeslots  []time.Time
	Tags       []string

	// DO NOT POPULATE
	Waypoints []string //`datastore:",noindex"`
}

An indexed flight blob is the thing we persist into datastore (or other blobstores)

func (*IndexedFlightBlob) ToFlight

func (blob *IndexedFlightBlob) ToFlight(key string) (*Flight, error)

type IndexedRestrictorSetBlob

type IndexedRestrictorSetBlob struct {
	Blob []byte `datastore:",noindex"`

	Name string
	Tags []string
	User string
}

This is the object which is persisted into Datastore

func (*IndexedRestrictorSetBlob) ToRestrictorSet

func (blob *IndexedRestrictorSetBlob) ToRestrictorSet(key string) (*GeoRestrictorSet, error)

type InterpolatedTrackpoint

type InterpolatedTrackpoint struct {
	Trackpoint // Embedded struct; only the interpolatable bits will be populated

	Pre, Post *Trackpoint // The points we were interpolated from
	Ratio     float64     // How far we were inbetween them

	Ref  geo.Latlong     // The point we were in reference to
	Line geo.LatlongLine // The line that connects the ref point to the line {pre->post}
	Perp geo.LatlongLine
}

type IntersectableTrack

type IntersectableTrack struct {
	Track // embed
	// contains filtered or unexported fields
}

IntersectableTrack contains a track, and data structures for efficient intersections against geo.Restrictors

func (IntersectableTrack) SatisfiesRestrictor

func (it IntersectableTrack) SatisfiesRestrictor(gr geo.Restrictor) RestrictorIntersectOutcome

Area restrictions: the first and last contained points are returned. Edge cases:

  1. No points actually inside area: if the line between two points intersects (and the far end meets any altitude limits), then those two points are returned.
  2. One point is inside: then that single point is returned

Vertical planes: the first point on the 'other side' is returned, if (a) it meeets altitude

restrictions, and (b) the line to it from previous point intersects the bounded plane.

func (IntersectableTrack) SatisfiesRestrictorSet

func (it IntersectableTrack) SatisfiesRestrictorSet(grs GeoRestrictorSet) RestrictorSetIntersectOutcome

type Procedure

type Procedure struct {
	Name      string         // E.g. SERFR2
	Waypoints []string       // The sequence of waypoints that makes it up
	Required  map[string]int // Which of the waypoints can't be omitted
}

type QTPoint

type QTPoint struct {
	I int // index into the track (should move this into the trackpoint ?!)
	Trackpoint
}

func (QTPoint) Point

func (qtp QTPoint) Point() *quadgeo.Point

type RestrictorCombinationLogic

type RestrictorCombinationLogic int
const (
	CombinationLogicAll RestrictorCombinationLogic = iota
	CombinationLogicAny
)

func (RestrictorCombinationLogic) String

type RestrictorIntersectOutcome

type RestrictorIntersectOutcome struct {
	TrackIntersection // a line segment, relating to a specific track.
	Satisfies         bool
	Debug             string
}

RestrictorIntersectOutcome represesnts the findings from comparing against a geo.Restrictor

type RestrictorSetIntersectOutcome

type RestrictorSetIntersectOutcome struct {
	Outcomes []RestrictorIntersectOutcome
}

RestrictorSetIntersectOutcome gathers together the outcomes from the individual restrictors

func (RestrictorSetIntersectOutcome) BlameString

func (RestrictorSetIntersectOutcome) Debug

func (RestrictorSetIntersectOutcome) Satisfies

Satsifies applies the combination logic to the individual outcomes to get a final outcome.

type Schedule

type Schedule struct {
	Number int64
	IATA   string // 2 chars
	ICAO   string // 3 chars

	PlannedDepartureUTC time.Time
	PlannedArrivalUTC   time.Time
	//ActualDepartureUTC time.Time
	//ActualArrivalUTC time.Time
	ArrivalLocationName   string // For extra credit ;)
	DepartureLocationName string // For extra credit ;)

	Origin      string
	Destination string
}

For scheduled flights, get what data we can about it

func (Schedule) BestFlightNumber

func (s Schedule) BestFlightNumber() string

func (Schedule) IataFlight

func (s Schedule) IataFlight() string

func (Schedule) IcaoFlight

func (s Schedule) IcaoFlight() string

type Track

type Track []Trackpoint

A Track is a slice of Trackpoints. They are ordered in time, beginning to end.

func (Track) AdjustAltitudes

func (t Track) AdjustAltitudes(metars *metar.Archive)

func (Track) AsContiguousBoxes

func (t Track) AsContiguousBoxes() []geo.LatlongTimeBox

If there are gaps in the track, this will interpolate between them. Will also fatten up the boxes, if they're too flat or too tall

func (Track) AsLinesSampledEvery

func (t Track) AsLinesSampledEvery(d time.Duration) []geo.LatlongLine

Consider caching this in an ephemeral field ?

func (Track) AsSanityFilteredTrack

func (in Track) AsSanityFilteredTrack() Track

Strip out any trackpoints that look really bogus. Leaves original track entirely untouched, and returns a completely separate new copy.

func (*Track) Base64Decode

func (t *Track) Base64Decode(str string) error

func (Track) Base64Encode

func (t Track) Base64Encode() (string, error)

func (Track) ClipTo

func (t Track) ClipTo(s, e time.Time) []Trackpoint

Returns copies of the trackpoints within the timerange; or empty track if none were found.

func (Track) ClosestTo

func (t Track) ClosestTo(ref geo.Latlong, minAltitude, maxAltitude float64) int

returns the index of the trackpoint that was closest to the reference point and within the altitude range, or -1 if track has no points within the altitude range. Set maxAltitude to zero to disable altitude checks.

func (*Track) Compare

func (t1 *Track) Compare(t2 *Track) CompareOutcome

func (*Track) CompareInSpace

func (t1 *Track) CompareInSpace(t2 *Track) (geo.OverlapOutcome, float64)

OverlapOutcome is abused here; only use the return value for .IsDisjoint() checks.

func (Track) DataSourceIsFAA

func (t Track) DataSourceIsFAA() bool

func (Track) Duration

func (t Track) Duration() time.Duration

func (Track) End

func (t Track) End() time.Time

func (Track) FullBoundingBox

func (t Track) FullBoundingBox() geo.LatlongBox

Full bounding box involves a full traversal of the track.

func (Track) IndexAtTime

func (t Track) IndexAtTime(tm time.Time) int

Returns -1 if not found Finds the largest index whose trackpoint does not come before the specified time

func (Track) IndicesAtDistKMsFrom

func (t Track) IndicesAtDistKMsFrom(refpt geo.Latlong, distsKM []float64) []int

This is not a very smart algorithm. It assumes that dist to refpt is monotonic and decreasing.

func (Track) LongSource

func (t Track) LongSource() string

func (Track) LongString

func (t Track) LongString() string

func (Track) MatchWaypoints

func (t Track) MatchWaypoints(waypoints map[string]geo.Latlong) map[string]time.Time

This is pretty dumb

func (Track) MediumString

func (t Track) MediumString() string

func (*Track) Merge

func (t1 *Track) Merge(t2 *Track)

func (Track) Notes

func (t Track) Notes() string

func (Track) OverlapsWith

func (t1 Track) OverlapsWith(t2 Track) (overlaps bool, conf float64, debug string)

overlaps: if we should consider them the same thing conf: how confident we are debug: some debug text about it.

func (*Track) PaddedTrimToTimes

func (t *Track) PaddedTrimToTimes(s, e time.Time, n int) *Track

func (*Track) PlausibleContribution

func (t1 *Track) PlausibleContribution(t2 *Track) (bool, string)

Does t2 seem like it could be glued onto/into t1 ?

func (*Track) PlausibleExtension

func (t1 *Track) PlausibleExtension(t2 *Track) (bool, string)

Does t2 more or less continue where t1 left off ?

func (Track) PostProcess

func (t Track) PostProcess()

Derive a bunch of data fields from the raw data. NOTE - the vertical data gets too jerky with ADSB, because altitude change appears more like an occasional step function when the datapoints are too close. You should use t.SampleEvery() to space things out a bit before using those fields.

func (Track) SampleEvery

func (t Track) SampleEvery(d time.Duration, interpolate bool) Track

Returns a track that has (more or less) one point per time.Duration. If interpolate is true, then we interpolate through gaps that are too long. The returned track contains copies of the trackpoints

func (Track) SampleEveryDist

func (t Track) SampleEveryDist(distKM float64, interpolate bool) Track

Returns a track that has (more or less) one point per distance unit (as flown along the path). If interpolate is true, then we interpolate through gaps that are too long; else they remain. The returned track contains copies of the trackpoints.

func (Track) ShortString

func (t Track) ShortString() string

func (Track) Start

func (t Track) Start() time.Time

func (Track) StartEndBoundingBox

func (t Track) StartEndBoundingBox() geo.LatlongBox

func (Track) String

func (t Track) String() string

func (Track) Times

func (t Track) Times() (s, e time.Time)

func (Track) ToIntersectableTrack

func (t Track) ToIntersectableTrack() IntersectableTrack

func (Track) ToIntersectableTrackSampleEvery

func (t Track) ToIntersectableTrackSampleEvery(d time.Duration) IntersectableTrack

func (Track) ToJSVar

func (t Track) ToJSVar() template.JS

func (Track) ToQuadtree

func (t Track) ToQuadtree() *quadtree.Quadtree

func (*Track) TrimToTimes

func (t *Track) TrimToTimes(s, e time.Time) *Track

Returns a (possibly empty) subtrack of points within [s,e] (inclusive). If padding is non-zero, we include that many additional points just to either side of the [s,e] (i.e neighboring points that don't quite lie in the range)

func (Track) WindowedAverageAt

func (t Track) WindowedAverageAt(i int, window time.Duration) Trackpoint

Returns a synthetic trackpoint with values for {ground|vertical}{speed|acceleration} computed from a sliding window, based on position/altitude/time data. The time window is centered on trackpoint i.

type TrackByTimestampAscending

type TrackByTimestampAscending Track

func (TrackByTimestampAscending) Len

func (TrackByTimestampAscending) Less

func (a TrackByTimestampAscending) Less(i, j int) bool

func (TrackByTimestampAscending) Swap

func (a TrackByTimestampAscending) Swap(i, j int)

type TrackFragment

type TrackFragment struct {
	IcaoId     adsb.IcaoId
	Callsign   string // Might not yet be populated
	Track             // embedded Track
	DataSystem        // embedded; e.g. MLAT vs. ADSB
}

func MessagesToTrackFragment

func MessagesToTrackFragment(msgs []*adsb.CompositeMsg) *TrackFragment

func (TrackFragment) String

func (frag TrackFragment) String() string

func (TrackFragment) TrackName

func (frag TrackFragment) TrackName() string

Remains backward compatible with existing tracks. More generally, this should be in trackpoint-data, as a function on the trackpoint

type TrackIntersection

type TrackIntersection struct {
	Start, End Trackpoint
	TrackName  string
	I, J       int
}

func (TrackIntersection) IsPointIntersection

func (ti TrackIntersection) IsPointIntersection() bool

func (TrackIntersection) RowHTML

func (ev TrackIntersection) RowHTML() []string

func (TrackIntersection) String

func (ev TrackIntersection) String() string

type Trackpoint

type Trackpoint struct {
	DataSource string // What kind of trackpoint is this; flightaware radar, local ADSB, etc

	ReceiverName string // For local ADSB

	TimestampUTC time.Time // Always in UTC, to make life SIMPLE

	geo.Latlong // Embedded type, so we can call all the geo stuff directly on trackpoints

	Altitude     float64 // This is pressure altitude (i.e. altitude in a standard atmosphere)
	GroundSpeed  float64 // In knots
	Heading      float64 // [0.0, 360.0) degrees. Direction plane is pointing in. Mag or real north?
	VerticalRate float64 // In feet per minute (multiples of 64)
	Squawk       string  // Generally, a string of four digits.

	// These two are transient fields, populated during analysis, and displayed on the map view
	AnalysisAnnotation string              `datastore:"-" json:"-"`
	AnalysisDisplay    AnalysisDisplayEnum `datastore:"-" json:"-"`

	// These fields are derived
	IndicatedAltitude         float64 `datastore:"-" json:"-"` // Corrected for local air pressure
	DistanceTravelledKM       float64 `datastore:"-" json:"-"` // Totted up from point to point
	GroundAccelerationKPS     float64 `datastore:"-" json:"-"` // In knots per second
	VerticalSpeedFPM          float64 `datastore:"-" json:"-"` // Feet per minute (~== VerticalRate)
	VerticalAccelerationFPMPS float64 `datastore:"-" json:"-"` // In (feet per minute) per second
	AngleOfInclination        float64 `datastore:"-" json:"-"` // In degrees. +ve means climbing

	// Populated just in first trackpoint, to hold transient notes for the whole track.
	Notes string `datastore:"-" json:"-"`
}

Trackpoint is a data point that locates an aircraft in space and time, etc

func TrackpointFromADSB

func TrackpointFromADSB(m *adsb.CompositeMsg) Trackpoint

func TrackpointFromAverage

func TrackpointFromAverage(in []Trackpoint) Trackpoint

func (Trackpoint) GetDataProvider

func (tp Trackpoint) GetDataProvider() DataProvider

func (Trackpoint) GetDataSystem

func (tp Trackpoint) GetDataSystem() DataSystem

These two functions serve as a backwards-compatibility layer

func (Trackpoint) InterpolateTo

func (from Trackpoint) InterpolateTo(to Trackpoint, ratio float64) InterpolatedTrackpoint

func (Trackpoint) LatlongTimeBoxTo

func (from Trackpoint) LatlongTimeBoxTo(to Trackpoint) geo.LatlongTimeBox

func (Trackpoint) LongSource

func (tp Trackpoint) LongSource() string

func (Trackpoint) RepositionByTime

func (s Trackpoint) RepositionByTime(d time.Duration) Trackpoint

RepositionByTime returns a trackpoint that has been repositioned, assuming it was travelling at constant velocity. The duration passed in determines how far to move in either direction.

func (Trackpoint) ShortString

func (tp Trackpoint) ShortString() string

func (Trackpoint) String

func (tp Trackpoint) String() string

func (Trackpoint) ToJSString

func (tp Trackpoint) ToJSString() string

type WaypointAndTime

type WaypointAndTime struct {
	WP string
	time.Time
}

Yay, sorting funtime here again !

type WaypointAndTimeList

type WaypointAndTimeList []WaypointAndTime

func (WaypointAndTimeList) Len

func (a WaypointAndTimeList) Len() int

func (WaypointAndTimeList) Less

func (a WaypointAndTimeList) Less(i, j int) bool

func (WaypointAndTimeList) Swap

func (a WaypointAndTimeList) Swap(i, j int)

type WaypointForBigQuery

type WaypointForBigQuery struct {
	Name string
	Time time.Time
}

Directories

Path Synopsis
app
backend
Use a shared workqueue ('batch') to do some processing against the entire database.
Use a shared workqueue ('batch') to do some processing against the entire database.
cmd
fdb
This package contains types and functions for storing / retrieving flight objects from datastore, memcache, and other AppEngine things.
This package contains types and functions for storing / retrieving flight objects from datastore, memcache, and other AppEngine things.
Provides routines to render flights as PDFs in various ways
Provides routines to render flights as PDFs in various ways
Package Metar provides tools for retrieving, storing and parsing Metar weather records.
Package Metar provides tools for retrieving, storing and parsing Metar weather records.
Package ref contains some reference lookups, implemented as singletons Package ref contains some reference lookups, implemented as singletons Package ref contains some reference lookups, implemented as singletons
Package ref contains some reference lookups, implemented as singletons Package ref contains some reference lookups, implemented as singletons Package ref contains some reference lookups, implemented as singletons

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL