Ejemplo n.º 1
0
  public Dispatcher(int numFloors, SimTime period, boolean verbose) {
    super("Dispatcher", verbose);

    this.period = period;
    this.numFloors = numFloors;
    lastClosedAt = 0;
    overweight = false;
    curr_f = 1;
    lastFloor = 1;
    curr_pos = 0;
    curr_h = Hallway.BOTH;
    curr_d = Direction.STOP;
    floor = 1;
    hallway = Hallway.BACK;
    // represents the next direction
    direction = Direction.STOP;
    // promised_d = Direction.STOP;
    nextHallCall = Direction.STOP;
    waitForCall = false;
    log("Created Dispatcher with period = ", period);

    // Initialize network interface
    // Outputs
    networkDesiredFloor = CanMailbox.getWriteableCanMailbox(MessageDictionary.DESIRED_FLOOR_CAN_ID);
    mDesiredFloor = new DesiredFloorCanPayloadTranslator(networkDesiredFloor);

    canInterface.sendTimeTriggered(networkDesiredFloor, period);

    // Inputs
    // CarWeight
    networkCarWeight = CanMailbox.getReadableCanMailbox(MessageDictionary.CAR_WEIGHT_CAN_ID);
    mCarWeight = new CarWeightCanPayloadTranslator(networkCarWeight);
    canInterface.registerTimeTriggered(networkCarWeight);

    // AtFloor
    networkAtFloor = new CanMailbox.ReadableCanMailbox[Elevator.numFloors * 2];
    mAtFloor = new AtFloorCanPayloadTranslator[Elevator.numFloors * 2];
    for (int floors = 1; floors <= Elevator.numFloors; floors++) {
      for (Hallway h : Hallway.replicationValues) {
        int index = ReplicationComputer.computeReplicationId(floors, h);
        networkAtFloor[index] =
            CanMailbox.getReadableCanMailbox(
                MessageDictionary.AT_FLOOR_BASE_CAN_ID
                    + ReplicationComputer.computeReplicationId(floors, h));
        mAtFloor[index] = new AtFloorCanPayloadTranslator(networkAtFloor[index], floors, h);
        canInterface.registerTimeTriggered(networkAtFloor[index]);
      }
    }

    // DoorClosed
    networkDoorClosed = new CanMailbox.ReadableCanMailbox[4];
    mDoorClosed = new DoorClosedCanPayloadTranslator[4];
    for (Hallway h : Hallway.replicationValues) {
      for (Side s : Side.values()) {
        int index = ReplicationComputer.computeReplicationId(h, s);
        networkDoorClosed[index] =
            CanMailbox.getReadableCanMailbox(
                MessageDictionary.DOOR_CLOSED_SENSOR_BASE_CAN_ID
                    + ReplicationComputer.computeReplicationId(h, s));
        mDoorClosed[index] = new DoorClosedCanPayloadTranslator(networkDoorClosed[index], h, s);
        canInterface.registerTimeTriggered(networkDoorClosed[index]);
      }
    }

    // HallCall
    networkHallCall = new CanMailbox.ReadableCanMailbox[Elevator.numFloors * 4];
    mHallCall = new HallCallCanPayloadTranslator[Elevator.numFloors * 4];
    for (int floors = 1; floors <= Elevator.numFloors; floors++) {
      for (Hallway h : Hallway.replicationValues) {
        for (Direction d : Direction.replicationValues) {
          int index = ReplicationComputer.computeReplicationId(floors, h, d);
          networkHallCall[index] =
              CanMailbox.getReadableCanMailbox(
                  MessageDictionary.HALL_CALL_BASE_CAN_ID
                      + ReplicationComputer.computeReplicationId(floors, h, d));
          mHallCall[index] = new HallCallCanPayloadTranslator(networkHallCall[index], floors, h, d);
          canInterface.registerTimeTriggered(networkHallCall[index]);
        }
      }
    }

    // CarCall
    networkCarCall = new CanMailbox.ReadableCanMailbox[Elevator.numFloors * 2];
    mCarCall = new CarCallCanPayloadTranslator[Elevator.numFloors * 2];
    for (int floors = 1; floors <= Elevator.numFloors; floors++) {
      for (Hallway h : Hallway.replicationValues) {
        int index = ReplicationComputer.computeReplicationId(floors, h);
        networkCarCall[index] =
            CanMailbox.getReadableCanMailbox(
                MessageDictionary.CAR_CALL_BASE_CAN_ID
                    + ReplicationComputer.computeReplicationId(floors, h));
        mCarCall[index] = new CarCallCanPayloadTranslator(networkCarCall[index], floors, h);
        canInterface.registerTimeTriggered(networkCarCall[index]);
      }
    }

    // Car Level Position
    networkCarLevelPosition =
        CanMailbox.getReadableCanMailbox(MessageDictionary.CAR_LEVEL_POSITION_CAN_ID);
    mCarLevelPosition = new CarLevelPositionCanPayloadTranslator(networkCarLevelPosition);
    canInterface.registerTimeTriggered(networkCarLevelPosition);

    // Drive Speed
    networkDriveSpeed = CanMailbox.getReadableCanMailbox(MessageDictionary.DRIVE_SPEED_CAN_ID);
    mDriveSpeed = new DriveSpeedCanPayloadTranslator(networkDriveSpeed);
    canInterface.registerTimeTriggered(networkDriveSpeed);

    // initially set target to lobby.

    mDesiredFloor.set(floor, hallway, direction);

    timer.start(period);
  }
Ejemplo n.º 2
0
  @Override
  public void timerExpired(Object callbackData) {
    State newState = state;
    curr_pos = mCarLevelPosition.getPosition();
    // We add 100 in order to make sure the floor is being updated correctly.
    curr_f = (curr_pos + 100) / 5000 + 1;
    if (curr_f != lastFloor) {
      lastFloor = curr_f;
      // System.out.println("resetting overweight");
      overweight = false;
      lastClosedAt = 0;
    }
    // System.out.println("curr_pos is " + curr_pos + " and curr_f is " + curr_f);
    if (Elevator.hasLanding(curr_f, Hallway.FRONT)) {
      if (Elevator.hasLanding(curr_f, Hallway.BACK)) curr_h = Hallway.BOTH;
      else curr_h = Hallway.FRONT;
    } else curr_h = Hallway.BACK;
    // State Machine
    switch (state) {
        // #state State 2: Doors Open
      case STATE_DOORSOPEN:
        // State actions for 'DOORSOPEN'
        waitCounter = waitTime;
        // If mDesiredDirection.d is STOP, we continue to look for hall and car halls.
        // mDesiredDirection.d is also set at curr_d
        // System.out.println("1current desired direction:" + mDesiredFloor.getDirection());
        if (mDesiredFloor.getDirection() == Direction.STOP) {
          /*
           * NOTE: When nextTarget is called, curr_d is set to the desired direction,
           * direction is set to the NEXT desired direction and floor is set to
           * the NEXT target floor. BUT we only want to change the directional
           * portion of mDesiredFloor, hence we use hallway, curr_f, and curr_d
           * to set the next Desired Floor.
           *
           * If no additional floors are found. Nothing changes so it is safe to
           * set mDesired dwell to curr_f, hallway, and curr_d still.
           */
          nextTarget(mDriveSpeed.getSpeed(), mCarLevelPosition.getPosition(), curr_d);
          // Now set the next target.
          // System.out.println("open floor is " + floor + " next direction is " + direction + "
          // current direction is " + curr_d + " hallway " + hallway);
          // System.out.println("changing direction to " + curr_d);
          mDesiredFloor.set(curr_f, curr_d, hallway);
          // System.out.println("2current desired direction:" + mDesiredFloor.getDirection());
        }
        // If the car is overweight, dont answer hall calls at this floor until later!
        if (mCarWeight.getValue() > Elevator.MaxCarCapacity) {
          overweight = true;
        }

        if (hallway == Hallway.BOTH) {
          // If either side of doors open and we're not at the floor, emergency!
          // #transition 11.T.4
          if ((!mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.FRONT, Side.LEFT)]
                      .getValue()
                  || !mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.BACK, Side.LEFT)]
                      .getValue())
              && !mAtFloor[ReplicationComputer.computeReplicationId(curr_f, Hallway.FRONT)]
                  .getValue()) {
            newState = State.STATE_EMERGENCY;
          }
          // #transition 11.T.3 when doors closed.
          else if ((mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.FRONT, Side.LEFT)]
                  .getValue()
              && mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.BACK, Side.LEFT)]
                  .getValue())) lastClosedAt = curr_f;
          newState = State.STATE_DOORSCLOSED;
        }
        // if it is not at ANY floor and ANY doors are open, jump to emergency state
        // #transition 11.T.4
        else if ((!mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.FRONT, Side.LEFT)]
                    .getValue()
                || !mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.BACK, Side.LEFT)]
                    .getValue())
            && !mAtFloor[ReplicationComputer.computeReplicationId(curr_f, hallway)].getValue()) {
          newState = State.STATE_EMERGENCY;
        }
        // if no issues, move to the next state when doors closed
        // #transition 11.T.3
        else if ((mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.FRONT, Side.LEFT)]
                .getValue()
            && mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.BACK, Side.LEFT)]
                .getValue())) {
          lastClosedAt = curr_f;
          newState = State.STATE_DOORSCLOSED;
        } else newState = state;
        break;

        // State actions for 'Doors Closed'
        // #state State 1: Doors Closed
      case STATE_DOORSCLOSED:
        // If waitForCall flag set, wait for 2 seconds for passenger to make car call.
        if (waitForCall) {
          // System.out.println("waiting");
          // while counter is greater than zero, keep subtracting;
          if (waitCounter.isPositive()) waitCounter = SimTime.subtract(waitCounter, period);
          else {
            // Reset waitCounter for next time and set waitForCall false
            waitForCall = false;
          }
          break;
        } else {
          // System.out.println("not waiting");
          // Check both sides for closed doors if that is the case.
          if (hallway == Hallway.BOTH || curr_h == Hallway.BOTH) {
            // If we're at the next target floor AND doors are opening, jump to DOORSOPEN
            // #transition 11.T.1
            if (mAtFloor[ReplicationComputer.computeReplicationId(floor, Hallway.FRONT)].getValue()
                && ((!mDoorClosed[
                        ReplicationComputer.computeReplicationId(Hallway.FRONT, Side.LEFT)]
                        .getValue()
                    || !mDoorClosed[
                        ReplicationComputer.computeReplicationId(Hallway.BACK, Side.LEFT)]
                        .getValue()))) {
              newState = State.STATE_DOORSOPEN;
              // If car is answering a hall call, wait for carcall after doors close.
              if (mDesiredFloor.getDirection() != Direction.STOP) waitForCall = true;
              // curr_d updated within nextTarget() but also updated when we open doors.
              curr_d = direction;
              // promised_d = direction;
            }
            // If either side of doors open and we're not at any floor, emergency!
            // #transition 11.T.2
            else if ((!mDoorClosed[
                        ReplicationComputer.computeReplicationId(Hallway.FRONT, Side.LEFT)]
                        .getValue()
                    || !mDoorClosed[
                        ReplicationComputer.computeReplicationId(Hallway.BACK, Side.LEFT)]
                        .getValue())
                && !(mAtFloor[ReplicationComputer.computeReplicationId(curr_f, Hallway.FRONT)]
                        .getValue()
                    || mAtFloor[ReplicationComputer.computeReplicationId(curr_f, Hallway.BACK)]
                        .getValue())
                && !mAtFloor[ReplicationComputer.computeReplicationId(floor, Hallway.FRONT)]
                    .getValue()) {
              newState = State.STATE_EMERGENCY;
            } else newState = state;
          }
          // If we're at the next target floor AND doors are opening, jump to DOORSOPEN
          // #transition 11.T.1
          else if (mAtFloor[ReplicationComputer.computeReplicationId(floor, hallway)].getValue()
              && ((!mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.FRONT, Side.LEFT)]
                      .getValue()
                  || !mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.BACK, Side.LEFT)]
                      .getValue()))) {
            newState = State.STATE_DOORSOPEN;
            curr_d = direction;
            // promised_d = direction;
            if (mDesiredFloor.getDirection() != Direction.STOP) waitForCall = true;
          }

          // If either side of doors open and we're not at any floor, emergency!
          // #transition 11.T.2
          else if ((!mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.FRONT, Side.LEFT)]
                      .getValue()
                  || !mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.BACK, Side.LEFT)]
                      .getValue())
              && !mAtFloor[ReplicationComputer.computeReplicationId(curr_f, curr_h)].getValue()
              && !mAtFloor[ReplicationComputer.computeReplicationId(floor, hallway)].getValue()) {
            newState = State.STATE_EMERGENCY;
          } else newState = state;
        }
        // Only change nextTarget if we're not transitioning states
        if (newState == state) {
          // Set next Direction and  next target Floor
          nextTarget(mDriveSpeed.getSpeed(), mCarLevelPosition.getPosition(), curr_d);

          /*This code is invalid. Must check if landing has call as well.
           * Decide which hallway is valid. If front and back, then both, else either front or back.*/
          hallIndexF = ReplicationComputer.computeReplicationId(floor, Hallway.FRONT, direction);
          carIndexF = ReplicationComputer.computeReplicationId(floor, Hallway.FRONT);
          hallIndexB = ReplicationComputer.computeReplicationId(floor, Hallway.BACK, direction);
          carIndexB = ReplicationComputer.computeReplicationId(floor, Hallway.BACK);
          if (Elevator.hasLanding(floor, Hallway.FRONT)) {
            if (Elevator.hasLanding(floor, Hallway.BACK)) {
              // Check both landings for valid calls. If not both, then select one.
              if ((mHallCall[hallIndexF].getValue() || mCarCall[carIndexF].getValue())
                  && (mHallCall[hallIndexB].getValue() || mCarCall[carIndexB].getValue())) {
                hallway = Hallway.BOTH;
              } else if (mHallCall[hallIndexF].getValue() || mCarCall[carIndexF].getValue()) {
                hallway = Hallway.FRONT;
              } else if (mHallCall[hallIndexB].getValue() || mCarCall[carIndexB].getValue()) {
                hallway = Hallway.BACK;
              }
            } else {
              if (mHallCall[hallIndexF].getValue() || mCarCall[carIndexF].getValue()) {
                hallway = Hallway.FRONT;
              }
            }
          } else {
            if (mHallCall[hallIndexB].getValue() || mCarCall[carIndexB].getValue()) {
              hallway = Hallway.BACK;
            }
          }
          /*if(promised_d != Direction.STOP && promised_d != curr_d ){
          	mDesiredFloor.setDirection(curr_d);
          }*/
          // log("floor is ", floor, " next direction is ", direction, " current direction is",
          // curr_d);
          // System.out.println("Closed floor is " + floor + " next direction is " + direction + "
          // current direction is " + curr_d + " hallway " + hallway);
          // Now set the next target.
          // else{
          mDesiredFloor.set(floor, direction, hallway);
          // }
        }
        break;

        // State actions for 'EMERGENCY'
        // #state State 3: Emergency
      case STATE_EMERGENCY:
        // System.out.println("emergency at supposedly" + curr_f + " but at postion " +
        // mCarLevelPosition.getPosition() +
        //		" with desiredfloor " +
        // mDesiredFloor.getFloor()+mDesiredFloor.getHallway()+mDesiredFloor.getDirection());
        floor = 1;
        hallway = Hallway.BOTH;
        direction = Direction.STOP;
        // Set the desired floor back down to the lobby!
        mDesiredFloor.set(floor, hallway, direction);

        // Once the doors have opened at the lobby, we can return to normal operation.
        // #transition 11.T.5
        if (!mDoorClosed[ReplicationComputer.computeReplicationId(Hallway.FRONT, Side.LEFT)]
                .getValue()
            && mAtFloor[ReplicationComputer.computeReplicationId(1, Hallway.FRONT)].getValue())
          newState = State.STATE_DOORSOPEN;
        else newState = state;
        break;

      default:
        throw new RuntimeException("State " + state + " was not recognized.");
    }

    /*log the results of this iteration
    if (state == newState) {
    	log("remains in state: ",state);
    } else {
    	log("Transition:",state,"->",newState);
    }
     */
    // update the state variable
    state = newState;

    // report the current state
    setState(STATE_KEY, newState.toString());

    // schedule the next iteration of the controller
    // you must do this at the end of the timer callback in order to restart
    // the timer
    timer.start(period);
  }