Skip to content
This repository was archived by the owner on Sep 14, 2019. It is now read-only.

Commit 57eb918

Browse files
authored
Merge pull request #17 from kevinzwang/master
Implement Autonomous command
2 parents feb67e0 + 8fbce46 commit 57eb918

7 files changed

Lines changed: 764 additions & 120 deletions

File tree

Robot2018/src/org/usfirst/frc/team199/Robot2018/Robot.java

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11

22
package org.usfirst.frc.team199.Robot2018;
33

4+
import java.util.ArrayList;
5+
import java.util.HashMap;
6+
import java.util.Map;
7+
8+
import org.usfirst.frc.team199.Robot2018.autonomous.AutoUtils;
9+
import org.usfirst.frc.team199.Robot2018.commands.Autonomous;
10+
import org.usfirst.frc.team199.Robot2018.commands.Autonomous.Position;
11+
import org.usfirst.frc.team199.Robot2018.commands.Autonomous.Strategy;
412
import org.usfirst.frc.team199.Robot2018.subsystems.Climber;
513
import org.usfirst.frc.team199.Robot2018.subsystems.ClimberAssist;
614
import org.usfirst.frc.team199.Robot2018.subsystems.Drivetrain;
@@ -9,6 +17,8 @@
917
import org.usfirst.frc.team199.Robot2018.subsystems.Lift;
1018
import org.usfirst.frc.team199.Robot2018.subsystems.RightDrive;
1119

20+
import edu.wpi.first.wpilibj.DriverStation;
21+
import edu.wpi.first.wpilibj.Preferences;
1222
import edu.wpi.first.wpilibj.TimedRobot;
1323
import edu.wpi.first.wpilibj.command.Command;
1424
import edu.wpi.first.wpilibj.command.Scheduler;
@@ -35,9 +45,13 @@ public class Robot extends TimedRobot {
3545
public static Listener listen;
3646

3747
public static OI oi;
48+
49+
public static Map<String, ArrayList<String[]>> autoScripts;
3850

3951
Command autonomousCommand;
40-
SendableChooser<Command> chooser = new SendableChooser<>();
52+
SendableChooser<Position> posChooser = new SendableChooser<Position>();
53+
Map<String, SendableChooser<Strategy>> stratChoosers = new HashMap<String, SendableChooser<Strategy>>();
54+
String[] fmsPossibilities = {"LL", "LR", "RL", "RR"};
4155

4256
public static double getConst(String key, double def) {
4357
if (!SmartDashboard.containsKey("Const/" + key)) {
@@ -69,9 +83,30 @@ public void robotInit() {
6983
ld = new LeftDrive();
7084
rd = new RightDrive();
7185
oi = new OI();
86+
87+
// auto position chooser
88+
for (Position p : Position.values()) {
89+
posChooser.addObject(p.getSDName(), p);
90+
}
91+
SmartDashboard.putData("Starting Position", posChooser);
92+
93+
// auto strategy choosers
94+
for (String input : fmsPossibilities) {
95+
SendableChooser<Strategy> chooser = new SendableChooser<Strategy>();
96+
for (Strategy s : Strategy.values()) {
97+
chooser.addObject(s.getSDName(), s);
98+
}
99+
SmartDashboard.putData(input, chooser);
100+
stratChoosers.put(input, chooser);
101+
}
102+
103+
// auto delay chooser
104+
SmartDashboard.putNumber("Auto Delay", 0);
105+
106+
// parse scripts from Preferences, which maintains values throughout reboots
107+
autoScripts = AutoUtils.parseScriptFile(Preferences.getInstance().getString("autoscripts", ""));
108+
72109
listen = new Listener();
73-
// chooser.addObject("My Auto", new MyAutoCommand());
74-
SmartDashboard.putData("Auto mode", chooser);
75110
}
76111

77112
/**
@@ -90,30 +125,25 @@ public void disabledPeriodic() {
90125
}
91126

92127
/**
93-
* This autonomous (along with the chooser code above) shows how to select
94-
* between different autonomous modes using the dashboard. The sendable chooser
95-
* code works with the Java SmartDashboard. If you prefer the LabVIEW Dashboard,
96-
* remove all of the chooser code and uncomment the getString code to get the
97-
* auto name from the text box below the Gyro
98-
*
99-
* You can add additional auto modes by adding additional commands to the
100-
* chooser code above (like the commented example) or additional comparisons to
101-
* the switch structure below with additional strings & commands.
128+
* This function is called once during the start of autonomous in order to
129+
* grab values from SmartDashboard and the FMS and call the Autonomous
130+
* command with those values.
102131
*/
103132
@Override
104133
public void autonomousInit() {
105-
autonomousCommand = chooser.getSelected();
106-
107-
/*
108-
* String autoSelected = SmartDashboard.getString("Auto Selector", "Default");
109-
* switch(autoSelected) { case "My Auto": autonomousCommand = new
110-
* MyAutoCommand(); break; case "Default Auto": default: autonomousCommand = new
111-
* ExampleCommand(); break; }
112-
*/
113-
114-
// schedule the autonomous command (example)
115-
if (autonomousCommand != null)
116-
autonomousCommand.start();
134+
String fmsInput = DriverStation.getInstance().getGameSpecificMessage();
135+
Position startPos = posChooser.getSelected();
136+
double autoDelay = SmartDashboard.getNumber("Auto Delay", 0);
137+
138+
Map<String, Strategy> strategies = new HashMap<String, Strategy>();
139+
for (Map.Entry<String, SendableChooser<Strategy>> entry : stratChoosers.entrySet()) {
140+
String key = entry.getKey();
141+
SendableChooser<Strategy> chooser = entry.getValue();
142+
strategies.put(key, chooser.getSelected());
143+
}
144+
145+
Autonomous auto = new Autonomous(startPos, strategies, autoDelay, fmsInput, false);
146+
auto.start();
117147
}
118148

119149
/**
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
package org.usfirst.frc.team199.Robot2018.autonomous;
2+
3+
import java.util.ArrayList;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
7+
public class AutoUtils {
8+
9+
/**
10+
* Parses the inputted script file into a map of scripts
11+
*
12+
* @param scriptFile the script file to parse
13+
* @return a map, with the key being the script name, and the argument
14+
* being a list of arrays that are instruction-argument pairs
15+
*/
16+
public static Map<String, ArrayList<String[]>> parseScriptFile(String scriptFile) {
17+
Map<String, ArrayList<String[]>> autoScripts = new HashMap<String, ArrayList<String[]>>();
18+
19+
String lines[] = scriptFile.split("\\r?\\n");
20+
21+
ArrayList<String[]> currScript = new ArrayList<String[]>();
22+
String currScriptName = "";
23+
24+
int count = 1;
25+
for (String line : lines) {
26+
// remove comments
27+
int commentIndex = line.indexOf("#");
28+
if (commentIndex != -1)
29+
line = line.substring(0, commentIndex);
30+
31+
// trim and remove extra whitespace just to make it neater
32+
line = line.trim().replaceAll("\\s+", " ");
33+
34+
// if there's no instruction on this line, skip
35+
if (line.equals("")) {
36+
continue;
37+
}
38+
39+
// if current line is a label, store the previous script and make a new empty one
40+
if (line.endsWith(":")) {
41+
autoScripts.put(currScriptName, currScript);
42+
currScript = new ArrayList<String[]>();
43+
currScriptName = line.substring(0, line.length() - 1);
44+
} else {
45+
46+
// first separate the command into instruction and args
47+
String instruction;
48+
String args;
49+
50+
int separator = line.indexOf(' ');
51+
if (separator == -1) {
52+
instruction = line;
53+
args = "";
54+
} else {
55+
instruction = line.substring(0, separator);
56+
args = line.substring(separator + 1);
57+
}
58+
59+
// if it's valid, put it into the script
60+
if (isValidCommand(instruction, args, count)) {
61+
String[] command = {instruction, args};
62+
currScript.add(command);
63+
}
64+
}
65+
count++;
66+
}
67+
68+
// puts the last script in
69+
autoScripts.put(currScriptName, currScript);
70+
71+
// remove the stray one in the beginning
72+
autoScripts.remove("");
73+
74+
return autoScripts;
75+
}
76+
77+
78+
/**
79+
* Validates the command inputted to see if it's AAA compliant
80+
*
81+
* @param instruction the instruction/command name
82+
* @param args the arguments provided to the instruction. A blank String if none
83+
* @param lineNumber the lineNumber in the script file. used for logging warnings
84+
* @return if the command is valid
85+
*/
86+
public static boolean isValidCommand (String instruction, String args, int lineNumber) {
87+
// moveto takes in a set of points, and the last arg can be a number
88+
if (instruction.equals("moveto")) {
89+
if (args == "") {
90+
logWarning(lineNumber, "The command `moveto` requires at least one argument.");
91+
return false;
92+
}
93+
94+
String[] splitArgs = args.split(" ");
95+
for (int i = 0; i < splitArgs.length - 1; i++) {
96+
if (!isPoint(splitArgs[i])) {
97+
logWarning(lineNumber, "The arguments for command `moveto` should be points formatted like this: "
98+
+ "`(x,y)`.");
99+
return false;
100+
}
101+
}
102+
103+
if (!isDouble(splitArgs[splitArgs.length - 1]) && !isPoint(splitArgs[splitArgs.length - 1])) {
104+
logWarning(lineNumber, "The last argument for command `moveto` should be a number, or a point "
105+
+ "formatted like this: `(x,y)`.");
106+
return false;
107+
}
108+
}
109+
110+
// turn can take a number or point
111+
else if (instruction.equals("turn")) {
112+
if (args.contains(" ")) {
113+
logWarning(lineNumber, "Command `turn` only accepts one argument.");
114+
return false;
115+
}
116+
117+
if (!isDouble(args) && !isPoint(args)) {
118+
logWarning(lineNumber, "The argument for command `turn` should be a number or a point formatted like "
119+
+ "this: `(x,y)`.");
120+
return false;
121+
}
122+
}
123+
124+
// move and wait can take only a number
125+
else if (instruction.equals("move") || instruction.equals("wait")) {
126+
if (args.contains(" ")) {
127+
logWarning(lineNumber, "Command `move` only accepts one argument.");
128+
return false;
129+
}
130+
131+
if (!isDouble(args)) {
132+
logWarning(lineNumber, "The argument for command `move` should be a number.");
133+
return false;
134+
}
135+
}
136+
137+
// switch, scale, exchange, intake, and end all don't have any args
138+
else if (instruction.equals("switch") || instruction.equals("scale") || instruction.equals("exchange")
139+
|| instruction.equals("intake") || instruction.equals("end")) {
140+
if (!args.equals("")) {
141+
logWarning(lineNumber, "Command `" + instruction + "` does not accept any arguments.");
142+
return false;
143+
}
144+
}
145+
146+
// Jump only takes one argument
147+
else if (instruction.equals("jump")) {
148+
if (args.contains(" ")) {
149+
logWarning(lineNumber, "Command `jump` only accepts one argument.");
150+
return false;
151+
}
152+
}
153+
154+
// if it's not even a valid instruction
155+
else {
156+
logWarning(lineNumber, "`" + instruction + "` is not a valid command.");
157+
return false;
158+
}
159+
160+
// if everything is all good
161+
return true;
162+
}
163+
164+
/**
165+
* Helper method used by isValidCommand() to log warnings for non-valid commands.
166+
*
167+
* @param lineNumber the line number in the script file
168+
* @param message the message to log
169+
*/
170+
private static void logWarning (int lineNumber, String message) {
171+
System.err.println("[WARNING] Line " + lineNumber + ": " + message);
172+
}
173+
174+
/**
175+
* Helper method used by isValidCommand() to check if an argument is a
176+
* point, characterized by parentheses on the left and right, with two
177+
* numbers separated by a comma, with no whitespace in between.
178+
*
179+
* @param s the argument
180+
* @return if the argument is a point
181+
*/
182+
private static boolean isPoint (String s) {
183+
// checks if it starts and ends with parentheses
184+
if (!s.startsWith("(") || !s.endsWith(")"))
185+
return false;
186+
187+
// checks that there's one, and only one comma (like this phrase)
188+
int indexOfComma = s.indexOf(',');
189+
int count = 0;
190+
while (indexOfComma != -1) {
191+
count++;
192+
indexOfComma = s.indexOf(',', indexOfComma + 1);
193+
}
194+
if (count != 1)
195+
return false;
196+
197+
198+
// really ugly, but just checks if the stuff between the parentheses are numbers
199+
if (!isDouble(s.substring(1, s.indexOf(',')))
200+
|| !isDouble(s.substring(s.indexOf(',') + 1, s.length() - 1)))
201+
return false;
202+
203+
return true;
204+
}
205+
206+
/**
207+
* Helper method used by isValidCommand() used to check if an argument is
208+
* able to be converted into a double
209+
*
210+
* @param s the argument
211+
* @return if the argument is a double
212+
*/
213+
private static boolean isDouble (String s) {
214+
try {
215+
Double.parseDouble(s);
216+
} catch (Exception e) {
217+
return false;
218+
}
219+
return true;
220+
}
221+
}

0 commit comments

Comments
 (0)