diff --git a/UI Documentation.pdf b/UI Documentation.pdf new file mode 100644 index 0000000..4a15819 Binary files /dev/null and b/UI Documentation.pdf differ diff --git a/build.gradle b/build.gradle index 681683b..18ff4b1 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,7 @@ dependencies { implementation "com.neuronrobotics:SimplePacketComsJava:0.10.1" implementation "com.neuronrobotics:SimplePacketComsJava-HID:0.13.1" + compile 'com.googlecode.json-simple:json-simple:1.1.1' //implementation project(":SimplePacketComsJava") } diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/InterfaceController.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/InterfaceController.java index e3066ec..70fe7ec 100644 --- a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/InterfaceController.java +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/InterfaceController.java @@ -199,7 +199,7 @@ public class InterfaceController { private LineChart pidGraphVel; // private ArrayList pidGraphSeriesVel = new ArrayList<>(); // private ArrayList pidGraphSeries = new ArrayList<>(); - private WarehouseRobotStatus status = WarehouseRobotStatus.Fault_E_Stop_pressed; + private WarehouseRobotStatus status = WarehouseRobotStatus.Halting; private ObservableList weights = FXCollections.observableArrayList("Aluminum", "Plastic"); private ObservableList sides = FXCollections.observableArrayList("25", "45"); private ObservableList pos = FXCollections.observableArrayList("1", "2"); @@ -421,8 +421,8 @@ private void setFieldSim(ISimplePIDRobot r) { heartBeat.setText(status.name()); }); Platform.runLater(() -> { - if (status == WarehouseRobotStatus.Waiting_for_approval_to_pickup - || status == WarehouseRobotStatus.Waiting_for_approval_to_dropoff) + if (status == WarehouseRobotStatus.Initial_State//This will no longer work since we changed the statuses in Warehouse robot. Changed status so this compiles + || status == WarehouseRobotStatus.HomingLift) approveButton.setDisable(false); else approveButton.setDisable(true); diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/InventoryManager.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/InventoryManager.java new file mode 100644 index 0000000..803f162 --- /dev/null +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/InventoryManager.java @@ -0,0 +1,140 @@ +package edu.wpi.rbe.rbe2001.fieldsimulator.gui; +import javafx.collections.FXCollections; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.Iterator; +public class InventoryManager { + private String InventoryLoc; + private String BorrowedInventoryLoc; + private JSONObject Inventory; + private JSONObject BorrowedInventory; + + public InventoryManager(String InventoryLocation, String BorrowedInventoryLocation){ + this.InventoryLoc = System.getProperty("user.home")+ File.separator+"Documents"+File.separator+"WareHouseRobot"+File.separator+InventoryLocation; + this.BorrowedInventoryLoc = System.getProperty("user.home")+ File.separator+"Documents"+File.separator+"WareHouseRobot"+File.separator+BorrowedInventoryLocation; + verifyFoldersExist(); + + } + public void verifyFoldersExist(){ + String localDirectory = System.getProperty("user.home")+ File.separator+"Documents"; + File dir = new File(localDirectory+File.separator+"WareHouseRobot"); + File Inventory = new File(InventoryLoc); + File BorrowedInventory = new File(BorrowedInventoryLoc); + try{//This verifies the files are there and if not creates them + dir.mkdir(); + Inventory.createNewFile(); + BorrowedInventory.createNewFile(); + } + catch (IOException e){ + e.printStackTrace(); + } + } + + public void removeItemsFromInventory(ListViewPart part, int numBorrowed){ + JSONArray InventoryList = (JSONArray)Inventory.get("inventory"); + JSONArray tempList = new JSONArray(); + Iterator iterator = InventoryList.iterator(); + while (iterator.hasNext()) { + JSONObject it = iterator.next(); + if((it.get("name")).equals(part.getName())) { + it.put("numberAvailable", (long)it.get("numberAvailable")-numBorrowed); + + } + tempList.add(it); + } + Inventory.put("inventory", tempList); + writeInventory(); + //refresh observable list + Main.partList = FXCollections.observableArrayList(); + JSONArray inventoryList2 = (JSONArray) Inventory.get("inventory"); + Iterator iterator2 = inventoryList2.iterator(); + int i = 0; + while (iterator2.hasNext()) { + JSONObject it = iterator2.next(); + Main.partList.add(new ListViewPart((String)it.get("name"), (long)it.get("numberAvailable"), (long)it.get("row"), (long)it.get("col"), (long)it.get("height"),(boolean)it.get("returnRequired"))); + i++; + } + } + + public void addBorrowedParts(ListViewPart part, int numBorrowed, long ID, String forClass){ + JSONArray borrowedList = (JSONArray)BorrowedInventory.get("borrowedInventory"); + Iterator iterator = borrowedList.iterator(); + JSONArray tempBorrowedList = new JSONArray(); + boolean idFound = false; + while (iterator.hasNext()) { + JSONObject it = iterator.next(); + if((long)it.get("ID")==ID){ + idFound = true; + JSONArray parts = (JSONArray)it.get("Parts"); + JSONObject newPart = new JSONObject(); + newPart.put("name", part.getName()); + newPart.put("numberBorrowed",numBorrowed); + newPart.put("Class", forClass); + parts.add(newPart); + it.put("Parts", parts); + } + tempBorrowedList.add(it); + } + if(!idFound){ + JSONObject newUser = new JSONObject(); + newUser.put("ID", ID); + JSONArray parts = new JSONArray(); + JSONObject newPart = new JSONObject(); + newPart.put("name", part.getName()); + newPart.put("numberBorrowed",numBorrowed); + newPart.put("Class", forClass); + parts.add(newPart); + newUser.put("Parts", parts); + tempBorrowedList.add(newUser); + } + BorrowedInventory.put("borrowedInventory", tempBorrowedList); + writeBorrowedInventory(); + } + + public void loadInventory(){ + JSONParser parser = new JSONParser(); + try { + Object obj = parser.parse(new FileReader(InventoryLoc)); + Inventory = (JSONObject) obj; + JSONArray inventoryList = (JSONArray) Inventory.get("inventory"); + Iterator iterator = inventoryList.iterator(); + while (iterator.hasNext()) { + JSONObject it = iterator.next(); + Main.partList.add(new ListViewPart((String)it.get("name"), (long)it.get("numberAvailable"), (long)it.get("row"), (long)it.get("col"),(long)it.get("height"), (boolean)it.get("returnRequired"))); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + public void loadBorrowedInventory(){ + JSONParser parser = new JSONParser(); + try { + Object obj = parser.parse(new FileReader(BorrowedInventoryLoc)); + BorrowedInventory = (JSONObject) obj; + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void writeInventory(){ + try (FileWriter file = new FileWriter(InventoryLoc)) { + file.write(Inventory.toJSONString()); + file.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void writeBorrowedInventory(){ + try (FileWriter file = new FileWriter(BorrowedInventoryLoc)) { + file.write(BorrowedInventory.toJSONString()); + file.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/ItemCheckOutScreenController.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/ItemCheckOutScreenController.java new file mode 100644 index 0000000..65098f8 --- /dev/null +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/ItemCheckOutScreenController.java @@ -0,0 +1,92 @@ +package edu.wpi.rbe.rbe2001.fieldsimulator.gui; +import edu.wpi.rbe.rbe2001.fieldsimulator.gui.Main; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.ResourceBundle; + +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.IRBE2001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.IRBE2002Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.RBE2001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.RBE3001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.ISimplePIDRobot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.WarehouseRobotStatus; +import javafx.application.Platform; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.chart.LineChart; +import javafx.scene.chart.ScatterChart; +import javafx.scene.control.*; +import javafx.scene.chart.XYChart; +import javafx.scene.chart.XYChart.Series; + +public class ItemCheckOutScreenController implements Initializable { + + @FXML + private Label name; + + @FXML + private Label numStock; + + @FXML + private Label PartReturn; + + @FXML + private Spinner quantityDesired; + + @FXML + private Button confirm; + + @FXML + private Button cancel; + + @FXML + private TextField rbeclassEntry; + + public void initialize(URL location, ResourceBundle resources) { + SpinnerValueFactory valueFactory = // + new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 10, 1); + quantityDesired.setValueFactory(valueFactory); + } + public void setScreenInfo(String nameOfPart, long numberInStock, boolean needToReturn){ + name.setText(nameOfPart); + if(needToReturn){ + PartReturn.setText("End Of Term"); + } + else{ + PartReturn.setText("Do Not Return"); + } + rbeclassEntry.setText(""); + if(numberInStock==0){ + numStock.setText("0"); + confirm.setDisable(true); + quantityDesired.getValueFactory().setValue(1); + quantityDesired.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 1, 1)); + } + else{ + confirm.setDisable(false); + numStock.setText(Integer.toString((int)numberInStock)); + quantityDesired.getValueFactory().setValue(1); + quantityDesired.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(1, (int)numberInStock, 1)); + } + } + public void confirm(){ + Main.numberRequested = quantityDesired.getValue(); + Main.updateInventory(Main.currentPart, Main.numberRequested, Main.currentIDNum, rbeclassEntry.getText()); + Main.BackendRobotController.setDeliverIsTest(false); + Main.BackendRobotController.sendDeliverBin(Main.currentPart.getRow(), Main.currentPart.getCol(), Main.currentPart.getHeight()); + Main.setRobotActionScene(0); + } + + public void cancelCallback(){ + Main.setItemSelectScene(); + } +} diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/ItemSelectScreenController.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/ItemSelectScreenController.java new file mode 100644 index 0000000..a6aeab9 --- /dev/null +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/ItemSelectScreenController.java @@ -0,0 +1,54 @@ +package edu.wpi.rbe.rbe2001.fieldsimulator.gui; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.ResourceBundle; + +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.IRBE2001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.IRBE2002Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.RBE2001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.RBE3001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.ISimplePIDRobot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.WarehouseRobotStatus; +import javafx.application.Platform; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.chart.LineChart; +import javafx.scene.chart.ScatterChart; +import javafx.scene.control.*; +import javafx.scene.chart.XYChart; +import javafx.scene.chart.XYChart.Series; + +public class ItemSelectScreenController implements Initializable { + @FXML + private Button Finished; + + @FXML + private ListView partsList; + + public ItemSelectScreenController(){ + + } + @Override + public void initialize(URL location, ResourceBundle resources) { + partsList.setItems(Main.partList); + partsList.setCellFactory(partListView->new ListViewPartCell()); + } + public void finishedCallback(){ + Main.setWelcomeScene(); + Main.BackendRobotController.sendPark(Main.BackendRobotController.defaultParkLocation[0], Main.BackendRobotController.defaultParkLocation[1]);} + + public void itemSelectedCallback(){ + ListViewPart sP = partsList.getSelectionModel().getSelectedItem(); + Main.currentPart = sP; + Main.setItemCheckOutScene(sP.getName(), sP.getNumAvailable(), sP.getreturnRequired()); + } +} diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/ListViewPart.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/ListViewPart.java new file mode 100644 index 0000000..0224efc --- /dev/null +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/ListViewPart.java @@ -0,0 +1,33 @@ +package edu.wpi.rbe.rbe2001.fieldsimulator.gui; + +public class ListViewPart { + private String Name; + private long NumAvailable; + private long Row; + private long Col; + private long height; + private boolean returnRequired; + public ListViewPart(String name, long numAvailable, long row, long col, long height, boolean returnRequired) + { + this.Name = name; + this.NumAvailable = numAvailable; + this.Row = row; + this.Col = col; + this.height =height; + this.returnRequired = returnRequired; + } + public String getName(){ + return Name; + } + public long getNumAvailable(){ + return NumAvailable; + } + public long getRow(){ + return Row; + } + public long getCol(){ + return Col; + } + public long getHeight(){ return height;} + public boolean getreturnRequired(){return returnRequired;} +} diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/ListViewPartCell.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/ListViewPartCell.java new file mode 100644 index 0000000..302827f --- /dev/null +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/ListViewPartCell.java @@ -0,0 +1,49 @@ +package edu.wpi.rbe.rbe2001.fieldsimulator.gui; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.control.Label; +import javafx.scene.control.ListCell; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; + +import java.io.IOException; + +public class ListViewPartCell extends ListCell{ + + @FXML + private Label name; + + @FXML + private Label numAvailable; + + @FXML + private HBox box; + + private FXMLLoader mLLoader; + + @Override + protected void updateItem(ListViewPart part, boolean empty) { + super.updateItem(part, empty); + if(empty || part == null) { + + setText(null); + setGraphic(null); + } + else { + if (mLLoader == null) { + mLLoader = new FXMLLoader(getClass().getResource("/fxml/partListCell.fxml")); + mLLoader.setController(this); + + try { + mLLoader.load(); + } catch (IOException e) { + e.printStackTrace(); + } + name.setText(String.valueOf(part.getName())); + numAvailable.setText(String.valueOf(part.getNumAvailable())); + setText(null); + setGraphic(box); + } + } + } +} diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/Main.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/Main.java index 0bd17ef..776b503 100644 --- a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/Main.java +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/Main.java @@ -1,31 +1,126 @@ package edu.wpi.rbe.rbe2001.fieldsimulator.gui; import javafx.application.Application; +import javafx.application.Platform; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; +import java.io.IOException; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; + public class Main extends Application { + private static Stage theStage; + private static Scene WelcomeScene = null; + private static Scene ItemSelectScene = null; + private static Scene ItemCheckOutScene = null; + private static Scene RobotActionScene = null; + private static Scene RobotManagerScene = null; + private static InventoryManager inventoryManager; + private static FXMLLoader ICOController = null; + private static FXMLLoader RobotActionController = null; + private static FXMLLoader RobotManagerController = null; + public static RobotInterface BackendRobotController; + //Shared Screen Data + public static ObservableList partList = FXCollections.observableArrayList(); + public static long currentIDNum = 0; + public static ListViewPart currentPart = null; + public static int numberRequested = 0; + @Override - public void start(Stage primaryStage) throws Exception { - Parent root = FXMLLoader.load(getClass().getResource("/fxml/MainScreen.fxml")); - primaryStage.setTitle("RBE 2001 Controller"); + public void start(Stage stage) throws Exception { + theStage = stage; + inventoryManager = new InventoryManager("Inventory.json", "BorrowedInventory.json"); + inventoryManager.loadInventory(); + inventoryManager.loadBorrowedInventory(); + Parent WelcomeScreen = FXMLLoader.load(getClass().getResource("/fxml/WelcomeScreen.fxml")); + ICOController = new FXMLLoader(getClass().getResource("/fxml/ItemCheckOutScreen.fxml")); + RobotActionController = new FXMLLoader(getClass().getResource("/fxml/RobotActionScreen.fxml")); + RobotManagerController = new FXMLLoader(getClass().getResource("/fxml/RobotManagerScreen.fxml")); + Parent ItemCheckOutScreen = ICOController.load(); + Parent RobotActionScreen = RobotActionController.load(); + Parent RobotManagerScreen = RobotManagerController.load(); + Parent ItemSelectScreen = FXMLLoader.load(Main.class.getResource("/fxml/ItemSelectScreen.fxml")); + theStage.setTitle("RBE Warehouse"); + theStage.setResizable(false); + WelcomeScene = new Scene(WelcomeScreen); + ItemSelectScene = new Scene(ItemSelectScreen); + ItemCheckOutScene = new Scene(ItemCheckOutScreen); + RobotActionScene = new Scene(RobotActionScreen); + RobotManagerScene = new Scene(RobotManagerScreen); + //Parent root = FXMLLoader.load(getClass().getResource("/fxml/MainScreen.fxml")); //root.getStylesheets().add("/materialfx-material-design-for-javafx/material-fx-v0_3.css"); - primaryStage.setScene(new Scene(root, 1011, 665)); - //primaryStage.setResizable(false); - - primaryStage.show(); - primaryStage.getScene().setRoot(root); - primaryStage.setOnCloseRequest(event -> { - - InterfaceController.disconnect(); - - }); + //theStage.setScene(new Scene(root, 1011, 665)); + theStage.setScene(WelcomeScene); + BackendRobotController = new RobotInterface(); + theStage.show(); + } public static void main(String[] args) { launch(args); } + + public static void setWelcomeScene(){theStage.setScene(WelcomeScene);} + public static void setItemSelectScene(){theStage.setScene(ItemSelectScene);} + public static void setItemCheckOutScene(String nameOfPart, long numberInStock, boolean needToReturn){ + ItemCheckOutScreenController ICOSController = ICOController.getController(); + ICOSController.setScreenInfo(nameOfPart, numberInStock, needToReturn); + theStage.setScene(ItemCheckOutScene); + } + + public static void setRobotActionScene(int phase){ + RobotActionScreenController controller = RobotActionController.getController(); + theStage.setScene(RobotActionScene); + if(phase==0){ + controller.setRetrieve(); + } + else if(phase == 1){ + controller.setWaitForDone(numberRequested); + } + else if(phase == 2){ + controller.setPutBack(); + } + else if(phase == 3){ + controller.setNoBinOnShelf(); + } + else if(phase == 4){ + controller.setFailedProcurement(); + } + } + public static void setRobotActionSceneWarning(){ + RobotActionScreenController controller = RobotActionController.getController(); + controller.setErrorWarningVisible(); + } + public static void setRobotManagerScene(){theStage.setScene(RobotManagerScene);} + public static void updateInventory(ListViewPart part, int numBorrowed, long ID, String forClass){ + inventoryManager.addBorrowedParts(part, numBorrowed, ID, forClass); + inventoryManager.removeItemsFromInventory(part, numBorrowed); + try{//has to remake scene because the listview gets messed up when editing it + Parent ItemSelectScreen = FXMLLoader.load(Main.class.getResource("/fxml/ItemSelectScreen.fxml")); + ItemSelectScene = new Scene(ItemSelectScreen); + } + catch(IOException e){ + e.printStackTrace(); + } + + } + public static void SetMaintenanceScreenRobotName(String name){ + RobotManagerScreenController controller = RobotManagerController.getController(); + Platform.runLater(()->controller.setRobotNameLabel(name)); + if(name.equals("None")){ + Platform.runLater(Main::setRobotManagerScene); + } + } + public static void SetMaintenanceScreenRobotStatus(String status){ + RobotManagerScreenController controller = RobotManagerController.getController(); + Platform.runLater(()->controller.setRobotStatusLabel(status)); + } + } diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/RobotActionScreenController.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/RobotActionScreenController.java new file mode 100644 index 0000000..e700e16 --- /dev/null +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/RobotActionScreenController.java @@ -0,0 +1,106 @@ +package edu.wpi.rbe.rbe2001.fieldsimulator.gui; +import edu.wpi.rbe.rbe2001.fieldsimulator.gui.Main; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.ResourceBundle; + +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.IRBE2001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.IRBE2002Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.RBE2001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.RBE3001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.ISimplePIDRobot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.WarehouseRobotStatus; +import javafx.application.Platform; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.chart.LineChart; +import javafx.scene.chart.ScatterChart; +import javafx.scene.control.*; +import javafx.scene.chart.XYChart; +import javafx.scene.chart.XYChart.Series; + +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; + +public class RobotActionScreenController implements Initializable{ + @FXML + Label actionLabel; + + @FXML + Button done; + + @FXML + Label ErrorWarning; + + @FXML + Button returnBTN; + + public void initialize(URL location, ResourceBundle resources) { + actionLabel.setText("Please Wait As The Part Bin Is Retrieved"); + done.setVisible(false); + ErrorWarning.setVisible(false); + returnBTN.setVisible(false); + } + + public void setRetrieve(){ + actionLabel.setText("Please Wait As The Part Bin Is Retrieved"); + done.setVisible(false); + ErrorWarning.setVisible(false); + returnBTN.setVisible(false); + } + + public void setWaitForDone(int numParts){ + String num = Integer.toString(numParts); + actionLabel.setText("Please Take "+num+" Parts From The Bin And Press Done When Finished"); + done.setVisible(true); + ErrorWarning.setVisible(false); + returnBTN.setVisible(false); + } + public void setPutBack(){ + //Call some method to command robot here + actionLabel.setText("Please Wait As The Part Bin Is Placed Back On The Shelf"); + done.setVisible(false); + ErrorWarning.setVisible(false); + returnBTN.setVisible(false); + } + public void setNoBinOnShelf(){ + //Call some method to command robot here + actionLabel.setText("Error: No Bin On Shelf. Please Contact a System Maintainer"); + done.setVisible(false); + ErrorWarning.setVisible(false); + returnBTN.setVisible(true); + } + + public void setFailedProcurement(){ + //Call some method to command robot here + actionLabel.setText("Error: Unable To Grab Bin. Please Contact a System Maintainer"); + done.setVisible(false); + ErrorWarning.setVisible(false); + returnBTN.setVisible(true); + } + + public void donePressed(){ + Main.BackendRobotController.setReturnIsTest(false); + Main.BackendRobotController.sendReturnBin(Main.currentPart.getRow(), Main.currentPart.getCol(), Main.currentPart.getHeight()); + } + + @FXML + public void returnPressed(){ + Main.setItemSelectScene(); + } + + public void setErrorWarningVisible(){ + Platform.runLater(()->ErrorWarning.setVisible(true)); + } + +} diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/RobotInterface.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/RobotInterface.java new file mode 100644 index 0000000..6e74dcb --- /dev/null +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/RobotInterface.java @@ -0,0 +1,160 @@ +package edu.wpi.rbe.rbe2001.fieldsimulator.gui; + +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.*; +import javafx.application.Platform; + +public class RobotInterface { + private IWarehouseRobot robot; + private WarehouseRobotStatus oldStatus = WarehouseRobotStatus.Initial_State; + private final int numPIDControllersOnDevice = 3; + private boolean DeliverIsTest = false; + private boolean ReturnIsTest = false; + public double defaultParkLocation[] = {1,0}; + public RobotInterface(){ + connectToDevice(); + } + + public void connectToDevice() { + if (getRobot() == null) { + new Thread(() -> { + String name = "*";//TODO Change to robot name + + try { + setFieldSim(new WarehouseRobot(name)); + // getFieldSim().setReadTimeout(1000); + if (getRobot() != null) { + Main.SetMaintenanceScreenRobotName(robot.toString()); + } + + } catch (Exception ex) { + ex.printStackTrace(); + } + if(getRobot()==null){ + Main.SetMaintenanceScreenRobotName("None"); + } + + }).start(); + } + } + private IWarehouseRobot getRobot() { + return robot; + } + + private void setFieldSim(IWarehouseRobot r) { + // fieldSim.setReadTimeout(1000); + try { + Thread.sleep(1000);//I think this must wait to let the UDP device respond + } catch (InterruptedException e) { + e.printStackTrace(); + } + robot = r; + //Add events here + if(robot!=null){ + robot.addWarehouseRobot(); + robot.addEvent(robot.getStatus.idOfCommand, () -> { + robot.readBytes(robot.getStatus.idOfCommand, robot.status); + if(robot.getStatus()!= oldStatus){ + switch(robot.getStatus()){ + case StartingUp: + Main.SetMaintenanceScreenRobotStatus("Starting Robot"); + break; + case StartRunning: + Main.SetMaintenanceScreenRobotStatus("Start Running"); + break; + case Idle: + Main.SetMaintenanceScreenRobotStatus("Idle"); + break; + case Halting: + Main.SetMaintenanceScreenRobotStatus("Halting"); + break; + case Halt: + Main.SetMaintenanceScreenRobotStatus("Halted"); + break; + case WAIT_FOR_MOTORS_TO_FINISH: + Main.SetMaintenanceScreenRobotStatus("Waiting For Motors to Finish"); + break; + case WAIT_FOR_TIME: + Main.SetMaintenanceScreenRobotStatus("Waiting for time"); + break; + case Testing: + Main.SetMaintenanceScreenRobotStatus("Testing"); + break; + case Navigating: + Main.SetMaintenanceScreenRobotStatus("Navigating"); + break; + case ParkingRobot: + Main.SetMaintenanceScreenRobotStatus("Parking Robot"); + break; + case HomingLift: + Main.SetMaintenanceScreenRobotStatus("Homing Lift"); + break; + case MovingLift: + Main.SetMaintenanceScreenRobotStatus("Moving Lift"); + break; + case Delivering: + Main.SetMaintenanceScreenRobotStatus("Delivering Bin"); + break; + case Returning: + Main.SetMaintenanceScreenRobotStatus("Returning Bin"); + Platform.runLater(()->Main.setRobotActionScene(2)); + break; + case Delivery_Done: + Main.SetMaintenanceScreenRobotStatus("Delivery Done"); + if(!DeliverIsTest) { + Platform.runLater(()->Main.setRobotActionScene(1)); + } + break; + case Returning_Done: + Main.SetMaintenanceScreenRobotStatus("Returning Done"); + if(!ReturnIsTest){ + Platform.runLater(Main::setItemSelectScene); + } + break; + case Bin_Not_On_Cleat: + Main.SetMaintenanceScreenRobotStatus("Bin Not On Cleat"); + Platform.runLater(Main::setRobotActionSceneWarning); + break; + case Bin_Not_On_Shelf: + Main.SetMaintenanceScreenRobotStatus("Bin Not On Shelf"); + Platform.runLater(()->Main.setRobotActionScene(3)); + break; + case Delivery_Failure: + Main.SetMaintenanceScreenRobotStatus("Delivery Failed"); + Platform.runLater(()->Main.setRobotActionScene(4)); + break; + case Timed_Out: + Main.SetMaintenanceScreenRobotStatus("Timed Out"); + break; + default: + Main.SetMaintenanceScreenRobotStatus("No Status"); + break; + } + oldStatus = robot.getStatus(); + } + }); + } + + } + public void sendPark(double row, double col){ + robot.sendPark(row, col); + } + + public void sendNavGoal(double row, double col){ + robot.sendNavGoal(row, col); + } + public void sendDeliverBin(double row, double col, double height){ + robot.sendDeliverBin(row, col, height); + } + public void sendReturnBin(double row, double col, double height){ + robot.sendReturnBin(row, col, height); + } + public void sendHomeLift(){robot.sendHomeLift();} + public void sendMoveLift(double mm){robot.sendMoveLift(mm);} + + public void setDeliverIsTest(boolean wellIsIt){ + DeliverIsTest = wellIsIt; + } + public void setReturnIsTest(boolean wellIsIt){ + ReturnIsTest = wellIsIt; + } +} diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/RobotManagerScreenController.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/RobotManagerScreenController.java new file mode 100644 index 0000000..5ecfbfd --- /dev/null +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/RobotManagerScreenController.java @@ -0,0 +1,186 @@ +package edu.wpi.rbe.rbe2001.fieldsimulator.gui; +import edu.wpi.rbe.rbe2001.fieldsimulator.gui.Main; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.ResourceBundle; + +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.IRBE2001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.IRBE2002Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.RBE2001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.RBE3001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.ISimplePIDRobot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.WarehouseRobotStatus; +import javafx.application.Platform; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.chart.LineChart; +import javafx.scene.chart.ScatterChart; +import javafx.scene.control.*; +import javafx.scene.chart.XYChart; +import javafx.scene.chart.XYChart.Series; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Label; + +import java.net.URL; +import java.util.ResourceBundle; + +public class RobotManagerScreenController implements Initializable { + + @FXML + private Label robotName; + + @FXML + private Label robotStatus; + + @FXML + private Button ExitBTN; + + @FXML + private TextField rowEntry; + + @FXML + private TextField colEntry; + + @FXML + private TextField heightEntry; + + @FXML + private TextField HeightMMEntry; + + @FXML + private Button NavigateBTN; + + @FXML + private Button ParkBTN; + + @FXML + private Button DeliverBTN; + + @FXML + private Button ReturnBTN; + + @FXML + private Button HomeLiftBTN; + + @FXML + private Button MoveLiftBTN; + + public void initialize(URL location, ResourceBundle resources) { + + } + public void setRobotNameLabel(String Name){ + robotName.setText(Name); + } + + public void setRobotStatusLabel(String status){robotStatus.setText(status);} + + @FXML + public void ExitBTNCallback(){ + Main.setWelcomeScene(); + } + @FXML + public void ReconnectBTNCallback(){ + Main.BackendRobotController.connectToDevice(); + } + + @FXML + public void NavBTNPressed(){ + double row = 2; + double col = 3; + boolean formatCorrect = true; + try{ + row = Double.parseDouble(rowEntry.getText()); + col = Double.parseDouble(colEntry.getText()); + } + catch(Exception ex){ + formatCorrect = false; + } + if(formatCorrect){ + Main.BackendRobotController.sendNavGoal(row, col); + } + } + @FXML + public void ParkBTNPressed(){ + double row = 0; + double col = 0; + boolean formatCorrect = true; + try{ + row = Double.parseDouble(rowEntry.getText()); + col = Double.parseDouble(colEntry.getText()); + } + catch(Exception ex){ + formatCorrect = false; + } + if(formatCorrect){ + Main.BackendRobotController.sendPark(row, col); + } + } + @FXML + public void DeliverBTNPressed(){ + double row = 0; + double col = 0; + double height = 0; + boolean formatCorrect = true; + try{ + row = Double.parseDouble(rowEntry.getText()); + col = Double.parseDouble(colEntry.getText()); + height = Double.parseDouble(heightEntry.getText()); + } + catch(Exception ex){ + formatCorrect = false; + } + if(formatCorrect){ + Main.BackendRobotController.setDeliverIsTest(true); + Main.BackendRobotController.sendDeliverBin(row, col, height); + } + } + @FXML + public void ReturnBTNPressed(){ + double row = 0; + double col = 0; + double height = 0; + boolean formatCorrect = true; + try{ + row = Double.parseDouble(rowEntry.getText()); + col = Double.parseDouble(colEntry.getText()); + height = Double.parseDouble(heightEntry.getText()); + } + catch(Exception ex){ + formatCorrect = false; + } + if(formatCorrect){ + Main.BackendRobotController.setReturnIsTest(true); + Main.BackendRobotController.sendReturnBin(row, col, height); + } + } + @FXML + public void MoveLiftBTNPressed(){ + double height= 0; + boolean formatCorrect = true; + try{ + + height = Double.parseDouble(HeightMMEntry.getText()); + } + catch(Exception ex){ + formatCorrect = false; + } + if(formatCorrect){ + System.out.println("Sent Height"); + Main.BackendRobotController.sendMoveLift(height); + } + } + @FXML + public void HomeLiftPressed(){ + Main.BackendRobotController.sendHomeLift(); + } +} diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/WelcomeScreenController.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/WelcomeScreenController.java new file mode 100644 index 0000000..d6fd4d7 --- /dev/null +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/gui/WelcomeScreenController.java @@ -0,0 +1,86 @@ +package edu.wpi.rbe.rbe2001.fieldsimulator.gui; +import edu.wpi.rbe.rbe2001.fieldsimulator.gui.Main; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.ResourceBundle; + +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.IRBE2001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.IRBE2002Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.RBE2001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.RBE3001Robot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.ISimplePIDRobot; +import edu.wpi.rbe.rbe2001.fieldsimulator.robot.WarehouseRobotStatus; +import javafx.application.Platform; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.chart.LineChart; +import javafx.scene.chart.ScatterChart; +import javafx.scene.control.Button; +import javafx.scene.control.ChoiceBox; +import javafx.scene.control.Label; +import javafx.scene.control.RadioButton; +import javafx.scene.control.SingleSelectionModel; +import javafx.scene.control.Tab; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; +import javafx.scene.chart.XYChart; +import javafx.scene.chart.XYChart.Series; +import javafx.scene.control.CheckBox; + + +public class WelcomeScreenController implements Initializable { + + @FXML + private Button Enter; + + @FXML + private Label error; + + @FXML + private TextField IDEntry; + + @FXML + private Button MaintenanceBTN; + + @Override + public void initialize(URL location, ResourceBundle resources) { + error.setVisible(false); + } + + @FXML + public void enterCallback(){ + long ID = 0; + boolean idValid = true; + try{ + ID = Long.parseLong(IDEntry.getText()); + if(IDEntry.getText().length()!=9){ + idValid = false; + } + } + catch (NumberFormatException e){ + idValid = false; + } + if(idValid) { + Main.currentIDNum = ID; + error.setVisible(false); + IDEntry.setText(""); + Main.setItemSelectScene(); + } + else{ + error.setVisible(true); + } + } + @FXML + public void MaintainenceBTNCallback(){ + Main.setRobotManagerScene(); + } +} diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/robot/IWarehouseRobot.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/robot/IWarehouseRobot.java new file mode 100644 index 0000000..090803d --- /dev/null +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/robot/IWarehouseRobot.java @@ -0,0 +1,116 @@ +package edu.wpi.rbe.rbe2001.fieldsimulator.robot; + +import java.util.Arrays; + +import edu.wpi.SimplePacketComs.BytePacketType; +import edu.wpi.SimplePacketComs.FloatPacketType; +import edu.wpi.SimplePacketComs.PacketType; + +public interface IWarehouseRobot { + // add new packets here + PacketType estop = new BytePacketType(1989, 64); + PacketType getStatus = new BytePacketType(2012, 64); + PacketType clearFaults = new BytePacketType(1871, 64); + PacketType park = new FloatPacketType(1945, 64); + PacketType navigate = new FloatPacketType(1966, 64); + PacketType deliverBin = new FloatPacketType(1908, 64); + PacketType returnBin = new FloatPacketType(1912, 64); + PacketType homeLift = new FloatPacketType(2077, 64); + PacketType setLiftHeight = new FloatPacketType(2020, 64); + byte[] status = new byte[1]; + double[] driveStatus = new double[1]; + double[] desiredLocation = new double[3]; + double[] liftHeightMM = new double[1]; + double[] placeholder = new double[1]; + + default public void addWarehouseRobot() { + + clearFaults.waitToSendMode(); + estop.waitToSendMode(); + park.waitToSendMode(); + navigate.waitToSendMode(); + deliverBin.waitToSendMode(); + returnBin.waitToSendMode(); + getStatus.pollingMode(); + homeLift.waitToSendMode(); + setLiftHeight.waitToSendMode(); + for (PacketType pt : Arrays.asList(clearFaults, getStatus, estop, park, navigate, deliverBin, returnBin, homeLift, setLiftHeight)) { + addPollingPacket(pt); + } + } + + default public void sendPark(double row, double col){ + desiredLocation[0] = row; + desiredLocation[1] = col; + desiredLocation[2] = 0; + writeFloats(park.idOfCommand, desiredLocation); + park.oneShotMode(); + System.out.println("Send Park"); + System.out.println(Arrays.toString(desiredLocation)); + } + + default public void sendNavGoal(double row, double col){ + desiredLocation[0] = row; + desiredLocation[1] = col; + desiredLocation[2] = 0; + writeFloats(navigate.idOfCommand, desiredLocation); + navigate.oneShotMode(); + System.out.println(Arrays.toString(desiredLocation)); + System.out.println("Send Nav"); + } + default public void sendDeliverBin(double row, double col, double height){ + desiredLocation[0] = row; + desiredLocation[1] = col; + desiredLocation[2] = height; + writeFloats(deliverBin.idOfCommand, desiredLocation); + deliverBin.oneShotMode(); + System.out.println(Arrays.toString(desiredLocation)); + System.out.println("Send DLV"); + } + default public void sendReturnBin(double row, double col, double height){ + desiredLocation[0] = row; + desiredLocation[1] = col; + desiredLocation[2] = height; + writeFloats(returnBin.idOfCommand, desiredLocation); + returnBin.oneShotMode(); + System.out.println(Arrays.toString(desiredLocation)); + System.out.println("Send Return"); + } + + default public void sendHomeLift(){ + placeholder[0] = 1; + writeFloats(homeLift.idOfCommand,placeholder ); + homeLift.oneShotMode(); + } + + default public void sendMoveLift(double mm){ + liftHeightMM[0] = mm; + writeFloats(setLiftHeight.idOfCommand, liftHeightMM); + setLiftHeight.oneShotMode(); + } + + default public void estop() { + estop.oneShotMode(); + } + + default public double getDriveStatus() { + return driveStatus[0]; + } + + default public WarehouseRobotStatus getStatus() { + return WarehouseRobotStatus.fromValue(status[0]); + } + + default public void clearFaults() { + clearFaults.oneShotMode(); + + } + + void addPollingPacket(PacketType packet); + + public void addEvent(Integer id, Runnable event); + + void readBytes(int id, byte[] values); + + void writeFloats(int idOfCommand, double[] data); +} diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/robot/WarehouseRobot.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/robot/WarehouseRobot.java new file mode 100644 index 0000000..f891028 --- /dev/null +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/robot/WarehouseRobot.java @@ -0,0 +1,18 @@ +package edu.wpi.rbe.rbe2001.fieldsimulator.robot; + +import edu.wpi.SimplePacketComs.device.UdpDevice; + +public class WarehouseRobot extends UdpDevice implements IWarehouseRobot{ + + public WarehouseRobot(String add) throws Exception { + super(add); + connect(); + } + + @Override + public String toString() { + return getName(); + } + + +} diff --git a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/robot/WarehouseRobotStatus.java b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/robot/WarehouseRobotStatus.java index b9a1474..f940ccf 100644 --- a/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/robot/WarehouseRobotStatus.java +++ b/src/main/java/edu/wpi/rbe/rbe2001/fieldsimulator/robot/WarehouseRobotStatus.java @@ -4,19 +4,28 @@ import java.util.Map; public enum WarehouseRobotStatus { - Ready_for_new_task ( (byte)0), - Heading_to_pickup ( (byte)1), - Waiting_for_approval_to_pickup( (byte)2), - Picking_up ( (byte)3), - Heading_to_Dropoff ((byte) 4), - Waiting_for_approval_to_dropoff( (byte)5), - Dropping_off ( (byte)6), - Heading_to_safe_zone ((byte) 7), - Fault_failed_pickup ( (byte)8), - Fault_failed_dropoff ((byte) 9), - Fault_excessive_load ((byte) 10), - Fault_obstructed_path ((byte) 11), - Fault_E_Stop_pressed ( (byte)12); + StartingUp( (byte)0), + StartRunning ( (byte) 1), + Idle ( (byte) 2), + Halting ( (byte) 3), + Halt ( (byte) 4), + WAIT_FOR_MOTORS_TO_FINISH ( (byte)5), + WAIT_FOR_TIME ( (byte)6), + Testing ( (byte) 7), + Navigating ( (byte) 8), + ParkingRobot ( (byte) 9), + HomingLift( (byte)10), + MovingLift( (byte)11), + Delivering((byte) 12), + Returning((byte) 13), + Delivery_Done( (byte)14), + Returning_Done( (byte)15), + Bin_Not_On_Cleat( (byte)16), + Bin_Not_On_Shelf( (byte)17), + Delivery_Failure( (byte) 18), + Timed_Out( (byte) 19), + Initial_State( (byte)20);// For use with Gui + private static final Map lookup = new HashMap<>(); static { diff --git a/src/main/resources/fxml/ItemCheckOutScreen.fxml b/src/main/resources/fxml/ItemCheckOutScreen.fxml new file mode 100644 index 0000000..e67f176 --- /dev/null +++ b/src/main/resources/fxml/ItemCheckOutScreen.fxml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/fxml/RobotActionScreen.fxml b/src/main/resources/fxml/RobotActionScreen.fxml new file mode 100644 index 0000000..3dd3f43 --- /dev/null +++ b/src/main/resources/fxml/RobotActionScreen.fxml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + diff --git a/src/main/resources/fxml/RobotManagerScreen.fxml b/src/main/resources/fxml/RobotManagerScreen.fxml new file mode 100644 index 0000000..0680653 --- /dev/null +++ b/src/main/resources/fxml/RobotManagerScreen.fxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + +