-
Notifications
You must be signed in to change notification settings - Fork 0
66-logging-util Initial Implementation #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: tank-bot
Are you sure you want to change the base?
Changes from 4 commits
f780dc8
b3ca771
674e254
f4a560c
ca6ab22
1966ed9
86fb5d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ | |
| import edu.wpi.first.wpilibj.TimedRobot; | ||
| import edu.wpi.first.wpilibj2.command.Command; | ||
| import edu.wpi.first.wpilibj2.command.CommandScheduler; | ||
| import frc.robot.util.Logger; | ||
|
|
||
| /** | ||
| * The VM is configured to automatically run this class, and to call the functions corresponding to | ||
|
|
@@ -18,6 +19,10 @@ public class Robot extends TimedRobot { | |
| private Command m_autonomousCommand; | ||
|
|
||
| private RobotContainer m_robotContainer; | ||
| private Logger m_logger; | ||
|
|
||
| private final double m_logInterval = 6000; | ||
| private double m_logTime = 0; | ||
|
|
||
| /** | ||
| * This function is run when the robot is first started up and should be used for any | ||
|
|
@@ -28,6 +33,7 @@ public void robotInit() { | |
| // Instantiate our RobotContainer. This will perform all our button bindings, and put our | ||
| // autonomous chooser on the dashboard. | ||
| m_robotContainer = new RobotContainer(); | ||
| m_logger = m_robotContainer.getLogger(); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -44,6 +50,17 @@ public void robotPeriodic() { | |
| // and running subsystem periodic() methods. This must be called from the robot's periodic | ||
| // block in order for anything in the Command-based framework to work. | ||
| CommandScheduler.getInstance().run(); | ||
|
|
||
| // REMEMBER TO MOVE THIS OUT OF ROBOT PERIODIC | ||
| // Logs the Robot Data | ||
| if(m_logTime >= m_logInterval) { | ||
| m_logTime = 0; | ||
| m_logger.updateFields(); | ||
| m_logger.log(); | ||
| } else { | ||
| m_logTime += 20; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than incrementing this by a fixed |
||
| } | ||
|
|
||
| } | ||
|
|
||
| /** This function is called once each time the robot enters Disabled mode. */ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -87,4 +87,8 @@ private static double clampPower(double power) { | |
| public void stop() { | ||
| m_driveTrain.stopMotor(); | ||
| } | ||
|
|
||
| public double getMotorSpeed() { | ||
| return m_leftA.get(); | ||
| } | ||
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package frc.robot.util; | ||
|
|
||
| import java.util.function.Supplier; | ||
|
|
||
| public class DynamicField extends StaticField { | ||
|
|
||
| private Supplier<Object> supplier; | ||
|
|
||
| /** | ||
| * A supplier "broker". Stores the name of the measurement, latest value, and the supplier of the values. | ||
| * Uses Object as a flexible data type. | ||
| * | ||
| * @param n field name | ||
| * @param v initial value | ||
| * @param s value supplier/source | ||
| */ | ||
| public DynamicField(String n, Object v, Supplier<Object> s) { | ||
| super(n,v); | ||
|
|
||
| supplier = s; | ||
| } | ||
|
|
||
| public void update() { | ||
| super.setValue(supplier.get()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| package frc.robot.util; | ||
|
|
||
| import java.io.*; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.Objects; | ||
| import java.util.StringJoiner; | ||
| import java.util.function.Supplier; | ||
|
|
||
| /** | ||
| * Responsible for recording the sensor data | ||
| */ | ||
| public class Logger { | ||
|
|
||
| private String path; | ||
| private File file; | ||
|
|
||
| List<DynamicField> dynamicFields; | ||
|
|
||
| // TODO: Look into the datalog tool to be able to automatically pull the log file off the robot | ||
| // TODO: Use the RobotSimulation to test the logging utility | ||
| // TODO: Track Autonomous and Teleop Status | ||
| public Logger(String p, String name) { | ||
| path = p; | ||
| try { | ||
| file = new File(path + name + ".csv"); | ||
| if (file.createNewFile()) { | ||
| System.out.println("File Created: " + file.getName()); | ||
| } else { | ||
| System.out.println("File already exists."); | ||
| } | ||
|
|
||
| // Wipes the log if it already contains text | ||
| FileWriter myWriter = new FileWriter(file,false); | ||
| myWriter.close(); | ||
|
|
||
| } catch (IOException e) { | ||
| System.out.println("Unable to create a file. "); | ||
| e.printStackTrace(); | ||
| } | ||
|
|
||
| dynamicFields = new ArrayList<>(); | ||
| } | ||
|
|
||
| public void log() { | ||
| try { | ||
| // TODO: Do not close the writer after each write | ||
| FileWriter myWriter = new FileWriter(file,true); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you can accomplish this by simply initializing a private instance variable in your constructor. |
||
|
|
||
| myWriter.write("\n"); | ||
|
|
||
| List<String> values = new ArrayList<>(); | ||
|
|
||
| for(DynamicField dF : dynamicFields) { | ||
| values.add(dF.getValue().toString()); | ||
| } | ||
|
|
||
| myWriter.write(String.join(",", values)); | ||
| myWriter.close(); | ||
| } catch (IOException e) { | ||
| System.out.println("Could not write to file."); | ||
| e.printStackTrace(); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Sets up the Dynamic Fields | ||
| */ | ||
| public void setup() { | ||
| try { | ||
| FileWriter myWriter = new FileWriter(file,true); | ||
|
|
||
| //myWriter.write("Created using FREZ Log"); | ||
|
|
||
| myWriter.write("---\n"); | ||
|
|
||
| List<String> variableNames = new ArrayList<>(); | ||
|
|
||
| for(DynamicField dF : dynamicFields) { | ||
| variableNames.add(dF.getName()); | ||
| } | ||
|
|
||
| myWriter.write(String.join(",", variableNames)); | ||
|
|
||
| myWriter.close(); | ||
| } catch (IOException e) { | ||
| System.out.println("Could not write to file."); | ||
| e.printStackTrace(); | ||
| } | ||
| } | ||
|
|
||
| public void createDynamicFieldDouble(String n, Double v, Supplier<Double> s){ | ||
| // This causes a runtime error which can prevent logging a value of a wrong type | ||
| createDynamicField(n, v, () -> s.get()); | ||
| } | ||
|
|
||
| public void createDynamicFieldString(String n, Object v, Supplier<String> s){ | ||
| // This causes a runtime error which can prevent logging a value of a wrong type | ||
| createDynamicField(n, v, () -> s.get()); | ||
| } | ||
|
|
||
| public void createDynamicFieldBoolean(String n, Boolean v, Supplier<Boolean> s){ | ||
| // This causes a runtime error which can prevent logging a value of a wrong type | ||
| createDynamicField(n, booleanToInt(v), () -> booleanToInt(s.get())); | ||
| } | ||
|
|
||
| private void createDynamicField(String n, Object v, Supplier<Object> s) { | ||
| DynamicField newField = new DynamicField(n, v, s); | ||
| dynamicFields.add(newField); | ||
| } | ||
|
|
||
| public void createStaticField(String n, Object v) { | ||
| StaticField newField = new StaticField(n, v); | ||
| writeStaticField(n, v); | ||
| } | ||
|
|
||
| /** | ||
| * Records the Frequency of the Logs (does not determine how often they are actually created) | ||
| * | ||
| * @param timeUnit - decimal of a second that represents how often the logs are updated | ||
| */ | ||
| public void recordFrequency(double timeUnit) { | ||
| // t? is the property tag to signify time unit | ||
| createStaticField("t?Time Unit", timeUnit); | ||
| } | ||
|
|
||
| public void writeStaticField(String n, Object v) { | ||
| try { | ||
| FileWriter myWriter = new FileWriter(file,true); | ||
|
|
||
| myWriter.write(n+","+v+"\n"); | ||
|
|
||
| myWriter.close(); | ||
| } catch (IOException e) { | ||
| System.out.println("Could not write to file."); | ||
| e.printStackTrace(); | ||
| } | ||
| } | ||
|
|
||
| public void updateFields() { | ||
| for(DynamicField field : dynamicFields) { | ||
| field.update(); | ||
| } | ||
|
|
||
| System.out.println("Updated Dynamic Fields."); | ||
| } | ||
|
|
||
| public int booleanToInt(boolean bool) { | ||
| if(bool) | ||
| return 1; | ||
| return 0; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package frc.robot.util; | ||
|
|
||
| import java.util.Objects; | ||
| import java.util.function.Supplier; | ||
|
|
||
| /** | ||
| * Struct for storing the sensor data field | ||
| */ | ||
|
|
||
| public class StaticField{ | ||
| private String name; | ||
| private Object value; | ||
|
|
||
| public StaticField(String n, Object v) { | ||
| name = n; | ||
| value = v; | ||
| } | ||
|
|
||
| public Object getValue() { | ||
| return value; | ||
| } | ||
|
|
||
| public void setValue(Object v) { | ||
| value = v; | ||
| } | ||
|
|
||
| public String getName() { | ||
| return name; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this comment outdated or do you still intend to move this out?