Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/main/java/frc/robot/Robot.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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();
}

/**
Expand All @@ -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
Copy link
Contributor

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?

// Logs the Robot Data
if(m_logTime >= m_logInterval) {
m_logTime = 0;
m_logger.updateFields();
m_logger.log();
} else {
m_logTime += 20;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than incrementing this by a fixed 20 here, should we increment by the elapsed time since the last execution?

}

}

/** This function is called once each time the robot enters Disabled mode. */
Expand Down
36 changes: 36 additions & 0 deletions src/main/java/frc/robot/RobotContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

package frc.robot;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import edu.wpi.first.wpilibj.DriverStation;
import edu.wpi.first.wpilibj.GenericHID;
import edu.wpi.first.wpilibj.Joystick;
Expand All @@ -20,6 +23,7 @@
import frc.robot.subsystems.DrivetrainSubsystem;
import frc.robot.subsystems.ExampleSubsystem;
import frc.robot.subsystems.NavXGyroSubsystem;
import frc.robot.util.Logger;

/**
* This class is where the bulk of the robot should be declared. Since Command-based is a
Expand All @@ -35,7 +39,9 @@ public class RobotContainer {

private final ExampleCommand m_autoCommand = new ExampleCommand(m_exampleSubsystem);
private final BalanceCommand m_balancecommand;

private final DriveStraightCommand m_drivestraightcommand;

private DriveCommand teleopDriveCmd;

private DrivetrainSubsystem drivetrainSubsystem;
Expand All @@ -47,6 +53,8 @@ public class RobotContainer {

private XboxController xboxController;

private Logger m_logger;

public double getRightY() {
if (!DriverStation.isJoystickConnected(ControllerConstants.kXboxControllerPort)) {
return Math.abs(rightJoystick.getY()) > ControllerConstants.kDeadZoneRadius ? -rightJoystick.getY() : 0;
Expand Down Expand Up @@ -91,6 +99,25 @@ public RobotContainer() {
this.m_drivestraightcommand = new DriveStraightCommand(navxGyroSubsystem, drivetrainSubsystem, m_blinkinSubsystem, this::getLeftY,this::getRightY, this::getThrottle);
// this.colorSensorSubsystem.setDefaultCommand(colorSensorCommand); <--- Causes an error right now

// Creates the logger
m_logger = new Logger("/home/lvuser/logs/", "ezlog");

// Sets the data to
{
//DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
//LocalDateTime now = LocalDateTime.now();

//m_logger.createStaticField("Time", dtf.format(now)); //DOESN'T WORK
m_logger.createStaticField("Event", "CORI Preliminaries 1");
m_logger.recordFrequency(.250);

m_logger.createDynamicFieldDouble("Motor Speed", drivetrainSubsystem.getMotorSpeed(), drivetrainSubsystem::getMotorSpeed);

m_logger.setup();
}
// NOTE: The logs can be accessed through File Explorer by typing into the bar:
// ftp://roborio-1014-frc.local/home/lvuser/logs/

// Configure the button bindings
configureButtonBindings();
}
Expand Down Expand Up @@ -131,4 +158,13 @@ public Command getAutonomousCommand() {
// An ExampleCommand will run in autonomous
return m_autoCommand;
}

/**
* Use this to pass the logger to the main {@link Robot} class to schedule updates.
*
* @return the logger
*/
public Logger getLogger() {
return m_logger;
}
}
4 changes: 4 additions & 0 deletions src/main/java/frc/robot/subsystems/DrivetrainSubsystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,8 @@ private static double clampPower(double power) {
public void stop() {
m_driveTrain.stopMotor();
}

public double getMotorSpeed() {
return m_leftA.get();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should return both motor speeds (in an array for example). Otherwise we're only ever able to log the speed of one motor. Alternatively you could create a getLeftMotorSpeed and getRightMotorSpeed.

}
26 changes: 26 additions & 0 deletions src/main/java/frc/robot/util/DynamicField.java
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());
}
}
153 changes: 153 additions & 0 deletions src/main/java/frc/robot/util/Logger.java
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);
Copy link
Contributor

Choose a reason for hiding this comment

The 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;
}
}
30 changes: 30 additions & 0 deletions src/main/java/frc/robot/util/StaticField.java
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;
}
}