2024-01-05 14:50:23 -05:00
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <string>
|
2024-01-05 15:22:52 -08:00
|
|
|
#include <string_view>
|
2024-01-05 14:50:23 -05:00
|
|
|
|
|
|
|
|
#include <units/acceleration.h>
|
|
|
|
|
#include <units/angle.h>
|
|
|
|
|
#include <units/angular_acceleration.h>
|
|
|
|
|
#include <units/angular_velocity.h>
|
|
|
|
|
#include <units/current.h>
|
|
|
|
|
#include <units/length.h>
|
|
|
|
|
#include <units/velocity.h>
|
|
|
|
|
#include <units/voltage.h>
|
2025-02-19 23:08:17 -06:00
|
|
|
#include <wpi/datalog/DataLog.h>
|
2024-01-05 14:50:23 -05:00
|
|
|
|
|
|
|
|
namespace frc::sysid {
|
|
|
|
|
|
2024-01-05 16:03:52 -08:00
|
|
|
/**
|
|
|
|
|
* Possible state of a SysId routine.
|
|
|
|
|
*/
|
2024-01-05 14:50:23 -05:00
|
|
|
enum class State {
|
2024-01-05 16:03:52 -08:00
|
|
|
/// Quasistatic forward test.
|
2024-01-05 14:50:23 -05:00
|
|
|
kQuasistaticForward,
|
2024-01-05 16:03:52 -08:00
|
|
|
/// Quasistatic reverse test.
|
2024-01-05 14:50:23 -05:00
|
|
|
kQuasistaticReverse,
|
2024-01-05 16:03:52 -08:00
|
|
|
/// Dynamic forward test.
|
2024-01-05 14:50:23 -05:00
|
|
|
kDynamicForward,
|
2024-01-05 16:03:52 -08:00
|
|
|
/// Dynamic reverse test.
|
2024-01-05 14:50:23 -05:00
|
|
|
kDynamicReverse,
|
2024-01-05 16:03:52 -08:00
|
|
|
/// No test.
|
2024-01-05 14:50:23 -05:00
|
|
|
kNone
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Utility for logging data from a SysId test routine. Each complete routine
|
|
|
|
|
* (quasistatic and dynamic, forward and reverse) should have its own
|
|
|
|
|
* SysIdRoutineLog instance, with a unique log name.
|
|
|
|
|
*/
|
|
|
|
|
class SysIdRoutineLog {
|
|
|
|
|
using MotorEntries = wpi::StringMap<wpi::log::DoubleLogEntry>;
|
|
|
|
|
using LogEntries = wpi::StringMap<MotorEntries>;
|
|
|
|
|
|
|
|
|
|
public:
|
2024-01-06 01:05:09 -05:00
|
|
|
/** Logs data from a single motor during a SysIdRoutine. */
|
2024-01-05 14:50:23 -05:00
|
|
|
class MotorLog {
|
|
|
|
|
public:
|
2024-01-06 01:05:09 -05:00
|
|
|
/**
|
|
|
|
|
* Log a generic data value from the motor.
|
|
|
|
|
*
|
|
|
|
|
* @param name The name of the data field being recorded.
|
|
|
|
|
* @param value The numeric value of the data field.
|
|
|
|
|
* @param unit The unit string of the data field.
|
|
|
|
|
* @return The motor log (for call chaining).
|
|
|
|
|
*/
|
2024-01-05 15:22:52 -08:00
|
|
|
MotorLog& value(std::string_view name, double value, std::string_view unit);
|
2024-01-05 14:50:23 -05:00
|
|
|
|
2024-01-06 01:05:09 -05:00
|
|
|
/**
|
|
|
|
|
* Log the voltage applied to the motor.
|
|
|
|
|
*
|
|
|
|
|
* @param voltage The voltage to record.
|
|
|
|
|
* @return The motor log (for call chaining).
|
|
|
|
|
*/
|
2024-01-05 14:50:23 -05:00
|
|
|
MotorLog& voltage(units::volt_t voltage) {
|
|
|
|
|
return value("voltage", voltage.value(), voltage.name());
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-06 01:05:09 -05:00
|
|
|
/**
|
|
|
|
|
* Log the linear position of the motor.
|
|
|
|
|
*
|
|
|
|
|
* @param position The linear position to record.
|
|
|
|
|
* @return The motor log (for call chaining).
|
|
|
|
|
*/
|
2024-01-05 14:50:23 -05:00
|
|
|
MotorLog& position(units::meter_t position) {
|
|
|
|
|
return value("position", position.value(), position.name());
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-06 01:05:09 -05:00
|
|
|
/**
|
|
|
|
|
* Log the angular position of the motor.
|
|
|
|
|
*
|
|
|
|
|
* @param position The angular position to record.
|
|
|
|
|
* @return The motor log (for call chaining).
|
|
|
|
|
*/
|
2024-01-05 14:50:23 -05:00
|
|
|
MotorLog& position(units::turn_t position) {
|
|
|
|
|
return value("position", position.value(), position.name());
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-06 01:05:09 -05:00
|
|
|
/**
|
|
|
|
|
* Log the linear velocity of the motor.
|
|
|
|
|
*
|
|
|
|
|
* @param velocity The linear velocity to record.
|
|
|
|
|
* @return The motor log (for call chaining).
|
|
|
|
|
*/
|
2024-01-05 14:50:23 -05:00
|
|
|
MotorLog& velocity(units::meters_per_second_t velocity) {
|
|
|
|
|
return value("velocity", velocity.value(), velocity.name());
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-06 01:05:09 -05:00
|
|
|
/**
|
|
|
|
|
* Log the angular velocity of the motor.
|
|
|
|
|
*
|
|
|
|
|
* @param velocity The angular velocity to record.
|
|
|
|
|
* @return The motor log (for call chaining).
|
|
|
|
|
*/
|
2024-01-05 14:50:23 -05:00
|
|
|
MotorLog& velocity(units::turns_per_second_t velocity) {
|
|
|
|
|
return value("velocity", velocity.value(), velocity.name());
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-06 01:05:09 -05:00
|
|
|
/**
|
|
|
|
|
* Log the linear acceleration of the motor.
|
|
|
|
|
*
|
2024-01-10 20:48:23 -08:00
|
|
|
* This is optional; SysId can perform an accurate fit without it.
|
|
|
|
|
*
|
2024-01-06 01:05:09 -05:00
|
|
|
* @param acceleration The linear acceleration to record.
|
|
|
|
|
* @return The motor log (for call chaining).
|
|
|
|
|
*/
|
2024-01-05 14:50:23 -05:00
|
|
|
MotorLog& acceleration(units::meters_per_second_squared_t acceleration) {
|
|
|
|
|
return value("acceleration", acceleration.value(), acceleration.name());
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-06 01:05:09 -05:00
|
|
|
/**
|
|
|
|
|
* Log the angular acceleration of the motor.
|
|
|
|
|
*
|
2024-01-10 20:48:23 -08:00
|
|
|
* This is optional; SysId can perform an accurate fit without it.
|
|
|
|
|
*
|
2024-01-06 01:05:09 -05:00
|
|
|
* @param acceleration The angular acceleration to record.
|
|
|
|
|
* @return The motor log (for call chaining).
|
|
|
|
|
*/
|
2024-01-05 14:50:23 -05:00
|
|
|
MotorLog& acceleration(units::turns_per_second_squared_t acceleration) {
|
|
|
|
|
return value("acceleration", acceleration.value(), acceleration.name());
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-06 01:05:09 -05:00
|
|
|
/**
|
|
|
|
|
* Log the current applied to the motor.
|
|
|
|
|
*
|
2024-01-10 20:48:23 -08:00
|
|
|
* This is optional; SysId can perform an accurate fit without it.
|
|
|
|
|
*
|
2024-01-06 01:05:09 -05:00
|
|
|
* @param current The current to record.
|
|
|
|
|
* @return The motor log (for call chaining).
|
|
|
|
|
*/
|
2024-01-05 14:50:23 -05:00
|
|
|
MotorLog& current(units::ampere_t current) {
|
|
|
|
|
return value("current", current.value(), current.name());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2024-01-06 01:05:09 -05:00
|
|
|
friend class SysIdRoutineLog;
|
|
|
|
|
/**
|
|
|
|
|
* Create a new SysId motor log handle.
|
|
|
|
|
*
|
|
|
|
|
* @param motorName The name of the motor whose data is being logged.
|
|
|
|
|
* @param logName The name of the SysIdRoutineLog that this motor belongs
|
|
|
|
|
* to.
|
|
|
|
|
* @param logEntries The DataLog entries of the SysIdRoutineLog that this
|
|
|
|
|
* motor belongs to.
|
|
|
|
|
*/
|
|
|
|
|
MotorLog(std::string_view motorName, std::string_view logName,
|
|
|
|
|
LogEntries* logEntries);
|
2024-01-05 14:50:23 -05:00
|
|
|
std::string m_motorName;
|
|
|
|
|
std::string m_logName;
|
|
|
|
|
LogEntries* m_logEntries;
|
|
|
|
|
};
|
2024-01-05 15:22:52 -08:00
|
|
|
|
2024-01-05 14:50:23 -05:00
|
|
|
/**
|
|
|
|
|
* Create a new logging utility for a SysId test routine.
|
|
|
|
|
*
|
|
|
|
|
* @param logName The name for the test routine in the log. Should be unique
|
2024-01-05 15:22:52 -08:00
|
|
|
* between complete test routines (quasistatic and dynamic, forward and
|
|
|
|
|
* reverse). The current state of this test (e.g. "quasistatic-forward")
|
|
|
|
|
* will appear in WPILog under the "sysid-test-state-logName" entry.
|
2024-01-05 14:50:23 -05:00
|
|
|
*/
|
2024-01-05 15:22:52 -08:00
|
|
|
explicit SysIdRoutineLog(std::string_view logName);
|
|
|
|
|
|
2024-01-05 14:50:23 -05:00
|
|
|
/**
|
|
|
|
|
* Records the current state of the SysId test routine. Should be called once
|
|
|
|
|
* per iteration during tests with the type of the current test, and once upon
|
|
|
|
|
* test end with state `none`.
|
|
|
|
|
*
|
|
|
|
|
* @param state The current state of the SysId test routine.
|
|
|
|
|
*/
|
|
|
|
|
void RecordState(State state);
|
|
|
|
|
|
2024-01-06 01:05:09 -05:00
|
|
|
/**
|
|
|
|
|
* Log data from a motor during a SysId routine.
|
|
|
|
|
*
|
|
|
|
|
* @param motorName The name of the motor.
|
|
|
|
|
* @return Handle with chainable callbacks to log individual data fields.
|
|
|
|
|
*/
|
2024-01-05 15:22:52 -08:00
|
|
|
MotorLog Motor(std::string_view motorName);
|
2024-01-05 14:50:23 -05:00
|
|
|
|
|
|
|
|
static std::string StateEnumToString(State state);
|
|
|
|
|
|
|
|
|
|
private:
|
2024-01-05 15:22:52 -08:00
|
|
|
LogEntries m_logEntries;
|
|
|
|
|
std::string m_logName;
|
2024-02-10 12:40:38 -06:00
|
|
|
bool m_stateInitialized = false;
|
2024-01-05 15:22:52 -08:00
|
|
|
wpi::log::StringLogEntry m_state;
|
2024-01-05 14:50:23 -05:00
|
|
|
};
|
|
|
|
|
} // namespace frc::sysid
|