Skip to content

Commit

Permalink
Merge branch 'CUTR-at-USF-develop_issue_127_138_139_for_pr'
Browse files Browse the repository at this point in the history
Conflicts:
	.travis.yml
	onebusaway-api-webapp/src/main/java/org/onebusaway/api/actions/api/gtfs_realtime/TripUpdatesForAgencyAction.java
	onebusaway-transit-data/src/main/java/org/onebusaway/transit_data/model/trips/TripStatusBean.java
  • Loading branch information
sheldonabrown committed Oct 26, 2015
2 parents 612f554 + 604864e commit 51448a9
Show file tree
Hide file tree
Showing 28 changed files with 1,548 additions and 95 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -2,4 +2,4 @@ language: java
sudo: false
cache:
directories:
- $HOME/.m2
- $HOME/.m2
@@ -1,5 +1,6 @@
/**
* Copyright (C) 2013 Google, Inc.
* Copyright (C) 2015 University of South Florida
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -27,10 +28,11 @@
import com.google.transit.realtime.GtfsRealtime.TripDescriptor;
import com.google.transit.realtime.GtfsRealtime.TripUpdate;
import com.google.transit.realtime.GtfsRealtime.VehicleDescriptor;
import org.onebusaway.transit_data.model.trips.TimepointPredictionBean;

public class TripUpdatesForAgencyAction extends GtfsRealtimeActionSupport {

private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 2L;

@Override
protected void fillFeedMessage(FeedMessage.Builder feed, String agencyId,
Expand Down Expand Up @@ -58,16 +60,36 @@ protected void fillFeedMessage(FeedMessage.Builder feed, String agencyId,
VehicleDescriptor.Builder vehicleDesc = tripUpdate.getVehicleBuilder();
vehicleDesc.setId(normalizeId(vehicle.getVehicleId()));

StopBean nextStop = tripStatus.getNextStop();
if (nextStop != null) {
TripUpdate.StopTimeUpdate.Builder stopTimeUpdate = tripUpdate.addStopTimeUpdateBuilder();
stopTimeUpdate.setStopId(normalizeId(nextStop.getId()));
TripUpdate.StopTimeEvent.Builder departure = stopTimeUpdate.getDepartureBuilder();
departure.setTime(timestamp / 1000 + tripStatus.getNextStopTimeOffset());
}
if (tripStatus.getTimepointPredictions() != null && tripStatus.getTimepointPredictions().size() > 0) {
for (TimepointPredictionBean timepointPrediction: tripStatus.getTimepointPredictions()) {
TripUpdate.StopTimeUpdate.Builder stopTimeUpdate = tripUpdate.addStopTimeUpdateBuilder();
stopTimeUpdate.setStopId(normalizeId(timepointPrediction.getTimepointId()));
TripUpdate.StopTimeEvent.Builder arrival = stopTimeUpdate.getArrivalBuilder();
if (timepointPrediction.getTimepointPredictedArrivalTime() != -1) {
arrival.setTime(timepointPrediction.getTimepointPredictedArrivalTime());
}

TripUpdate.StopTimeEvent.Builder departure = stopTimeUpdate.getDepartureBuilder();
if (timepointPrediction.getTimepointPredictedDepartureTime() != -1) {
departure.setTime(timepointPrediction.getTimepointPredictedDepartureTime());
}

tripUpdate.setTimestamp(vehicle.getLastUpdateTime() / 1000);

}

tripUpdate.setTimestamp(vehicle.getLastUpdateTime() / 1000);
} else {
StopBean nextStop = tripStatus.getNextStop();
if (nextStop != null) {
TripUpdate.StopTimeUpdate.Builder stopTimeUpdate = tripUpdate.addStopTimeUpdateBuilder();
stopTimeUpdate.setStopId(normalizeId(nextStop.getId()));
TripUpdate.StopTimeEvent.Builder departure = stopTimeUpdate.getDepartureBuilder();
departure.setTime(timestamp / 1000 + tripStatus.getNextStopTimeOffset());
}

}
tripUpdate.setDelay((int) tripStatus.getScheduleDeviation());
tripUpdate.setTimestamp(vehicle.getLastUpdateTime() / 1000);
}
}
}
@@ -0,0 +1,37 @@
/**
* Copyright (C) 2015 University of South Florida
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onebusaway.utility;

/**
* Defines the strategy to use when interpolating a key that is inside the key
* range of the key-value map
*/
public enum EInRangeStrategy {

/**
* As long as two key-values are present in the map, we we will attempt to
* interpolate the value for a key that is inside the key range of the
* key-value map. If only one key-value pair is present in the map, that value
* will be used.
*/
INTERPOLATE,

/**
* Returns the value in the key-value map closest to the target value, where the
* index for the returned value is less than the index of the target value.
*/
PREVIOUS_VALUE;
}
@@ -1,5 +1,6 @@
/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
* Copyright (C) 2015 University of South Florida
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -23,6 +24,9 @@
* Generic methods to support interpolation of values against a sorted key-value
* map given a new target key.
*
* Note that these interpolation methods do not conform to the GTFS-rt spec. For GTFS-rt
* compliant interpolation/extrapolation, see {@link TransitInterpolationLibrary}.
*
* @author bdferris
*/
public class InterpolationLibrary {
Expand Down Expand Up @@ -91,7 +95,12 @@ public static <K extends Number, V> V nearestNeighbor(SortedMap<K, V> values,
}

public static double interpolate(double[] keys, double[] values,
double target, EOutOfRangeStrategy outOfRangeStrategy) {
double target, EOutOfRangeStrategy outOfRangeStrategy) {
return interpolate(keys, values, target, outOfRangeStrategy, null);
}

public static double interpolate(double[] keys, double[] values,
double target, EOutOfRangeStrategy outOfRangeStrategy, EInRangeStrategy inRangeStrategy) {

if (values.length == 0)
throw new IndexOutOfBoundsException(OUT_OF_RANGE);
Expand Down Expand Up @@ -130,8 +139,17 @@ public static double interpolate(double[] keys, double[] values,
}
}

return interpolatePair(keys[index - 1], values[index - 1], keys[index],
values[index], target);
if (inRangeStrategy == null) {
inRangeStrategy = EInRangeStrategy.INTERPOLATE;
}

switch (inRangeStrategy) {
case PREVIOUS_VALUE:
return values[index - 1];
default:
return interpolatePair(keys[index - 1], values[index - 1], keys[index],
values[index], target);
}
}

/**
Expand Down
@@ -0,0 +1,129 @@
/**
* Copyright (C) 2015 University of South Florida
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onebusaway.utility;

import java.util.Arrays;

/**
* Transit-specific methods to support searching for deviations (produced from real-time
* predictions) for a given stop. Interpolation behavior is consistent
* with the GTFS-realtime spec (https://developers.google.com/transit/gtfs-realtime/) when
* using the {@link EInRangeStrategy.PREVIOUS_VALUE} and {@link EOutOfRangeStrategy.LAST_VALUE}
* strategies - in particular, this applies to the propagation of delays downstream in a trip.
* The {@link EInRangeStrategy.INTERPOLATE} and {@link EOutOfRangeStrategy.INTERPOLATE}
* strategies have behavior consistent with the normal {@link InterpolationLibrary}, which
* do not conform to the GTFS-rt spec.
*
*/
public class TransitInterpolationLibrary {

private static final String OUT_OF_RANGE = "no values provided";

public static Double interpolate(double[] keys, double[] values,
double target, EOutOfRangeStrategy outOfRangeStrategy) {
return interpolate(keys, values, target, outOfRangeStrategy, null);
}

/**
* Find the deviation that should be used for a particular stop, given sorted keys (arrival times)
* and values (deviations) arrays. The {@code target} is the arrival time for the stop
* we're searching for. Delay propagation is consistent with the GTFS-realtime spec
* (https://developers.google.com/transit/gtfs-realtime/) when using the
* {@link EInRangeStrategy.PREVIOUS_VALUE} and {@link EOutOfRangeStrategy.LAST_VALUE} strategies. If
* {@link EOutOfRangeStrategy.LAST_VALUE} is provided and all deviations are downstream from the target stop,
* null will be returned to indicate that no real-time information is available for the target stop.
* If {@link EInRangeStrategy.INTERPOLATE} is provided, this method will interpolate using
* linear interpolation and produce a value for a target key within the key-range of the map.
* For a key outside the range of the keys of the map, the {@code outOfRange} {@link EOutOfRangeStrategy}
* strategy will determine the interpolation behavior. {@link EOutOfRangeStrategy.INTERPOLATE}
* will linearly extrapolate the value.
*
* @param keys sorted array of keys (the scheduled arrival time of the stop)
* @param values sorted arrays of values (the list of real-time deviations for the provided stops)
* @param target the target key used to interpolate a value (the scheduled arrival time of the stop)
* @param outOfRangeStrategy the strategy to use for a target key that outside
* the key-range of the value map (use {@link EOutOfRangeStrategy.LAST_VALUE} for GTFS-rt behavior)
* @param inRangeStrategy the strategy to use for a target key that inside
* the key-range of the value map (use {@link EInRangeStrategy.PREVIOUS_VALUE} for GTFS-rt behavior)
* @return an interpolated value (deviation) for the target key, or null if the target is upstream of the deviations
*/
public static Double interpolate(double[] keys, double[] values,
double target, EOutOfRangeStrategy outOfRangeStrategy,
EInRangeStrategy inRangeStrategy) {

if (values.length == 0)
throw new IndexOutOfBoundsException(OUT_OF_RANGE);

int index = Arrays.binarySearch(keys, target);
if (index >= 0) {
// There is a real-time prediction provided for this stop - return it
return values[index];
}

// If we get this far, the target value wasn't contained in the keys. Convert the returned index into the insertion
// index for target, which is the index of the first element greater than the target key (see Arrays.binarySearch()).
index = -(index + 1);

if (index == values.length) {
// We're searching for a stop that is downstream of the predictions
switch (outOfRangeStrategy) {
case INTERPOLATE:
if (values.length > 1)
return InterpolationLibrary.interpolatePair(keys[index - 2],
values[index - 2], keys[index - 1], values[index - 1], target);
return values[index - 1];
case LAST_VALUE:
// Return the closest upstream deviation (i.e., propagate the last deviation in values downstream)
return values[index - 1];
case EXCEPTION:
throw new IndexOutOfBoundsException(OUT_OF_RANGE);
}
}

if (index == 0) {
// We're searching for a stop that is upstream of the predictions
switch (outOfRangeStrategy) {
case INTERPOLATE:
if (values.length > 1)
return InterpolationLibrary.interpolatePair(keys[0], values[0],
keys[1], values[1], target);
return values[0];
case LAST_VALUE:
// We shouldn't propagate deviations upstream, so return null to indicate no prediction
// should be used, and schedule data should be used instead.
return null;
case EXCEPTION:
throw new IndexOutOfBoundsException(OUT_OF_RANGE);
}
}

if (inRangeStrategy == null) {
inRangeStrategy = EInRangeStrategy.INTERPOLATE;
}

// We're searching for a stop that is within the window of predictions, but no prediction is provided for
// the target stop
switch (inRangeStrategy) {
case PREVIOUS_VALUE:
// Return the closest upstream deviation (i.e., propagate the closest deviation in values downstream)
return values[index - 1];
default:
return InterpolationLibrary.interpolatePair(keys[index - 1],
values[index - 1], keys[index], values[index], target);
}
}

}
@@ -1,5 +1,6 @@
/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
* Copyright (C) 2015 University of South Florida
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,24 +22,33 @@

public class TimepointPredictionRecord implements Serializable {

private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 2L;

/**
*
*/
private AgencyAndId timepointId;

private AgencyAndId tripId;

private int stopSequence = -1;

private long timepointScheduledTime;

private long timepointPredictedTime;
private long timepointPredictedArrivalTime = -1;

private long timepointPredictedDepartureTime = -1;

public TimepointPredictionRecord() {

}

public TimepointPredictionRecord(TimepointPredictionRecord r) {
this.timepointId = r.timepointId;
this.timepointPredictedTime = r.timepointPredictedTime;
this.tripId = r.tripId;
this.stopSequence = r.stopSequence;
this.timepointPredictedArrivalTime = r.timepointPredictedArrivalTime;
this.timepointPredictedDepartureTime = r.timepointPredictedDepartureTime;
this.timepointScheduledTime = r.timepointScheduledTime;
}

Expand All @@ -58,11 +68,36 @@ public void setTimepointScheduledTime(long timepointScheduledTime) {
this.timepointScheduledTime = timepointScheduledTime;
}

public long getTimepointPredictedTime() {
return timepointPredictedTime;
public AgencyAndId getTripId() {
return tripId;
}

public void setTripId(AgencyAndId tripId) {
this.tripId = tripId;
}

public int getStopSequence() {
return stopSequence;
}

public void setStopSequence(int stopSequence) {
this.stopSequence = stopSequence;
}

public long getTimepointPredictedArrivalTime() {
return timepointPredictedArrivalTime;
}

public void setTimepointPredictedArrivalTime(long timepointPredictedArrivalTime) {
this.timepointPredictedArrivalTime = timepointPredictedArrivalTime;
}

public long getTimepointPredictedDepartureTime() {
return timepointPredictedDepartureTime;
}

public void setTimepointPredictedTime(long timepointPredictedTime) {
this.timepointPredictedTime = timepointPredictedTime;
public void setTimepointPredictedDepartureTime(
long timepointPredictedDepartureTime) {
this.timepointPredictedDepartureTime = timepointPredictedDepartureTime;
}
}
@@ -1,4 +1,5 @@
/**
* Copyright (C) 2013 Kurt Raschke <kurt@kurtraschke.com>
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -139,6 +140,7 @@ private List<StopTimeEntryImpl> createInitialStopTimeEntries(

stopTimeEntry.setId(stopTime.getId());
stopTimeEntry.setSequence(sequence);
stopTimeEntry.setGtfsSequence(stopTime.getStopSequence());
stopTimeEntry.setDropOffType(stopTime.getDropOffType());
stopTimeEntry.setPickupType(stopTime.getPickupType());
stopTimeEntry.setStop(stopEntry);
Expand Down

0 comments on commit 51448a9

Please sign in to comment.