public void changeLane(ChangeLaneType changeLaneType, double changingLaneDistance) {
   RouteStateInfo stateInfo = innerState.getStateInfo();
   if (!stateInfo.isOnRoad() || stateInfo.isChangingLane()) {
     return;
   }
   int nextLane = stateInfo.getLane();
   if (changeLaneType == ChangeLaneType.LEFT) {
     nextLane = Math.max(0, nextLane - 1);
   } else {
     nextLane = Math.min(stateInfo.getNumLanes() - 1, nextLane + 1);
   }
   if (nextLane == stateInfo.getLane()) {
     return;
   }
   nextRoadLane = nextLane;
   innerState =
       new ChangingLaneState(
           stateInfo.getRoute(),
           stateInfo.getCurrentRoad(),
           stateInfo.getLane(),
           stateInfo.getCurrentSegment(),
           stateInfo.getCurveParameter(),
           changeLaneType,
           changingLaneDistance);
 }
 private void changeInnerState() {
   RouteStateInfo stateInfo = innerState.getStateInfo();
   if (stateInfo.isChangingLane()) {
     innerState =
         new DirectedRoadState(
             stateInfo.getRoute(),
             stateInfo.getCurrentRoad(),
             stateInfo.getLaneAfterChange(),
             stateInfo.getSegmentAfterLaneChange(),
             stateInfo.getCurveParameterAfterLaneChange());
   } else if (stateInfo.isOnRoad()) {
     if (stateInfo.getNextRoad() == null) {
       innerState = new ReachedDestinationState(stateInfo.getRoute());
     } else {
       nextRoadLane = Math.min(nextRoadLane, stateInfo.getNextRoad().getNumLanes());
       innerState =
           new InnerNodeState(
               stateInfo.getRoute(),
               stateInfo.getNextNode(),
               stateInfo.getCurrentRoad(),
               stateInfo.getLane(),
               stateInfo.getNextRoad(),
               nextRoadLane);
     }
   } else {
     innerState =
         new DirectedRoadState(
             stateInfo.getRoute(), stateInfo.getNextRoad(), stateInfo.getLaneAfterNode());
   }
 }