private static double getAvgVelocityToNextStop(Observation obs, BlockState blockState) { StopTimeEntry stop = blockState.getBlockLocation().getNextStop().getStopTime(); final double distToDest = TurboButton.distance(obs.getLocation(), stop.getStop().getStopLocation()); final int currSchedTime = (int) (obs.getTime() - blockState.getBlockInstance().getServiceDate()) / 1000; final double expectedVelocity; if (currSchedTime >= stop.getArrivalTime()) { /* * Assumption here is that the driver will speed up to get to the stop on time. * TODO: check this. */ expectedVelocity = _avgVelocity * 3d / 2d; } else { expectedVelocity = distToDest / (stop.getArrivalTime() - currSchedTime); } return expectedVelocity; }
private static final SensorModelResult computeEdgeMovementLogProb( Observation obs, VehicleState state, VehicleState parentState, boolean hasMoved, boolean isDuring) throws BadProbabilityParticleFilterException { final BlockState blockState = state.getBlockState(); final BlockState parentBlockState = parentState.getBlockState(); final double currentDab; final double prevDab; if (!blockState.getBlockInstance().equals(parentBlockState.getBlockInstance())) { /* * Note: this isn't really working like we want it to, since there are * separate shapes that share the same segments of geometry. */ if (!Objects.equal( parentBlockState.getBlockLocation().getActiveTrip().getTrip().getShapeId(), blockState.getBlockLocation().getActiveTrip().getTrip().getShapeId())) { return computeNoEdgeMovementLogProb(state, parentState, obs); } currentDab = blockState.getBlockLocation().getDistanceAlongBlock() - blockState.getBlockLocation().getActiveTrip().getDistanceAlongBlock(); prevDab = parentBlockState.getBlockLocation().getDistanceAlongBlock() - parentBlockState.getBlockLocation().getActiveTrip().getDistanceAlongBlock(); } else { currentDab = blockState.getBlockLocation().getDistanceAlongBlock(); prevDab = parentBlockState.getBlockLocation().getDistanceAlongBlock(); } final SensorModelResult result = new SensorModelResult("edge-move"); final double dabDelta = currentDab - prevDab; if (ParticleFilter.getDebugEnabled()) result.addResult("dist: " + dabDelta, 0d); final double obsTimeDelta = (obs.getTime() - obs.getPreviousObservation().getTime()) / 1000d; final double expAvgDist; if (hasMoved) { if (!isDuring || blockState.getBlockLocation().getNextStop() == null) { expAvgDist = getAvgVelocityBetweenStops(blockState) * obsTimeDelta; } else { expAvgDist = getAvgVelocityToNextStop(obs, blockState) * obsTimeDelta; } } else { expAvgDist = 0d; } if (ParticleFilter.getDebugEnabled()) result.addResult("expAvgDist: " + expAvgDist, 0d); final double x = dabDelta - expAvgDist; /* * Now, we need to measure the state transition likelihood * wrt. heading. * For the in-progress -> in-progress transition, we need * to calculate the expected turn-rate/orientation between the two states. */ double obsOrientation = Math.toRadians(obs.getOrientation()); if (Double.isNaN(obsOrientation)) { obsOrientation = Math.toRadians(blockState.getBlockLocation().getOrientation()); } if (ParticleFilter.getDebugEnabled()) result.addResult("obsOrient:" + obsOrientation, 0d); final double orientDiff; final double logpOrient; if (hasMoved) { if (!isDuring || blockState.getBlockLocation().getNextStop() == null) { /* * TODO * We could use a polar velocity model and the turn rate... */ final double prevOrientation = Math.toRadians(parentBlockState.getBlockLocation().getOrientation()); final double currentOrientation = Math.toRadians(blockState.getBlockLocation().getOrientation()); final double angleDiff = Angle.diff(prevOrientation, currentOrientation); final double avgExpOrientation = Angle.normalizePositive( prevOrientation + (Angle.getTurn(prevOrientation, currentOrientation) == Angle.CLOCKWISE ? -1d : 1d) * angleDiff / 2d); orientDiff = Angle.diff(obsOrientation, avgExpOrientation); if (ParticleFilter.getDebugEnabled()) result.addResult("expOrient: " + avgExpOrientation, 0d); logpOrient = _inProgressProb * logVonMisesPdf(orientDiff, _inProgressConcParam); } else { /* * The orientation is wrt. the next stop destination, i.e. * we want to check that we're heading toward it. */ double pathOrDestOrientation = Math.toRadians( SphericalGeometryLibrary.getOrientation( obs.getLocation().getLat(), obs.getLocation().getLon(), blockState .getBlockLocation() .getNextStop() .getStopTime() .getStop() .getStopLocation() .getLat(), blockState .getBlockLocation() .getNextStop() .getStopTime() .getStop() .getStopLocation() .getLon())); if (Double.isNaN(pathOrDestOrientation)) { pathOrDestOrientation = obsOrientation; } orientDiff = Angle.diff(obsOrientation, pathOrDestOrientation); if (ParticleFilter.getDebugEnabled()) result.addResult("expOrient: " + pathOrDestOrientation, 0d); logpOrient = _inProgressProb * logVonMisesPdf(orientDiff, _deadheadEntranceConcParam); } } else { // /* // * What if we're switching trips while in the middle of doing one? // * We assume that it's unlikely to do a complete 180 when we're // * stopped. // */ // if (parentState.getJourneyState().getPhase() == EVehiclePhase.IN_PROGRESS // && state.getJourneyState().getPhase() == EVehiclePhase.IN_PROGRESS) { // orientDiff = Math.toRadians(blockState.getBlockLocation().getOrientation() // - parentBlockState.getBlockLocation().getOrientation()); // } else { orientDiff = Angle.diff( obsOrientation, Math.toRadians(blockState.getBlockLocation().getOrientation())); // } if (ParticleFilter.getDebugEnabled()) result.addResult("orientDiff (stopped):" + orientDiff, 0d); logpOrient = _inProgressProb * logVonMisesPdf(orientDiff, _stoppedConcParam); } final double logpMove = UnivariateGaussian.PDF.logEvaluate(x, 0d, Math.pow(obsTimeDelta, 4) / 4d) + logpOrient; result.addLogResultAsAnd("lik", logpMove); return result; }