Allow constructing control loops from flatbuffers
The core changes here are to:
* Allow constructing StateFeedbackLoop's from flatbuffers using the
code in *state_feedback_loop_converters.*
* Add constructors to the single-dof subsystem class to make use of
this.
* Add code to control_loops.py to generate JSON files with the requisite
constants (these end up containing identical information to the
generated .cc files).
* Add interfaces to actually support the new JSON codegen to single-dof
subsystem classes.
* Convert all of the drivetrains over to generating these. This I mostly
do so that I can write a test where Iconfirm that the .cc files and
the JSON files generate exactly the same content.
Change-Id: Iceac48f25ecac96200b7bf992c8f34a15fe6800c
Signed-off-by: James Kuszmaul <jabukuszmaul+collab@gmail.com>
diff --git a/frc971/control_loops/BUILD b/frc971/control_loops/BUILD
index 53d6b27..1c1b797 100644
--- a/frc971/control_loops/BUILD
+++ b/frc971/control_loops/BUILD
@@ -392,6 +392,7 @@
],
deps = [
":control_loops_ts_fbs",
+ ":state_feedback_loop_ts_fbs",
],
)
@@ -403,6 +404,7 @@
target_compatible_with = ["@platforms//os:linux"],
deps = [
":control_loops_fbs",
+ ":state_feedback_loop_fbs",
],
)
@@ -420,6 +422,8 @@
":profiled_subsystem_fbs",
":simple_capped_state_feedback_loop",
":state_feedback_loop",
+ ":state_feedback_loop_converters",
+ "//aos:flatbuffer_merge",
"//aos/util:trapezoid_profile",
"//frc971/control_loops:control_loop",
"//frc971/zeroing",
@@ -549,8 +553,10 @@
outs = [
"static_zeroing_single_dof_profiled_subsystem_test_plant.h",
"static_zeroing_single_dof_profiled_subsystem_test_plant.cc",
+ "static_zeroing_single_dof_profiled_subsystem_test_plant.json",
"static_zeroing_single_dof_profiled_subsystem_test_integral_plant.h",
"static_zeroing_single_dof_profiled_subsystem_test_integral_plant.cc",
+ "static_zeroing_single_dof_profiled_subsystem_test_integral_plant.json",
],
cmd = "$(location //frc971/control_loops/python:static_zeroing_single_dof_profiled_subsystem_test) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -686,3 +692,36 @@
],
target_compatible_with = ["@platforms//os:linux"],
)
+
+static_flatbuffer(
+ name = "state_feedback_loop_fbs",
+ srcs = ["state_feedback_loop.fbs"],
+ deps = ["//frc971/math:matrix_fbs"],
+)
+
+flatbuffer_ts_library(
+ name = "state_feedback_loop_ts_fbs",
+ srcs = ["state_feedback_loop.fbs"],
+ deps = ["//frc971/math:matrix_ts_fbs"],
+)
+
+cc_library(
+ name = "hybrid_state_feedback_loop_converters",
+ srcs = ["hybrid_state_feedback_loop_converters.h"],
+ deps = [
+ ":hybrid_state_feedback_loop",
+ ":state_feedback_loop_converters",
+ ":state_feedback_loop_fbs",
+ "//frc971/math:flatbuffers_matrix",
+ ],
+)
+
+cc_library(
+ name = "state_feedback_loop_converters",
+ srcs = ["state_feedback_loop_converters.h"],
+ deps = [
+ ":state_feedback_loop",
+ ":state_feedback_loop_fbs",
+ "//frc971/math:flatbuffers_matrix",
+ ],
+)
diff --git a/frc971/control_loops/hybrid_state_feedback_loop_converters.h b/frc971/control_loops/hybrid_state_feedback_loop_converters.h
new file mode 100644
index 0000000..588a4d5
--- /dev/null
+++ b/frc971/control_loops/hybrid_state_feedback_loop_converters.h
@@ -0,0 +1,105 @@
+#ifndef FRC971_CONTROL_LOOPS_HYBRID_STATE_FEEDBACK_LOOP_CONVERTERS_H_
+#define FRC971_CONTROL_LOOPS_HYBRID_STATE_FEEDBACK_LOOP_CONVERTERS_H_
+
+#include "frc971/control_loops/hybrid_state_feedback_loop.h"
+#include "frc971/control_loops/state_feedback_loop_converters.h"
+#include "frc971/control_loops/state_feedback_loop_static.h"
+
+namespace frc971::control_loops {
+// These converters are used for constructing a hybrid StateFeedbackLoop
+// object from a flatbuffer.
+// The only method that should typically be called by users is
+// MakeHybridStateFeedbackLoop().
+template <int number_of_states, int number_of_inputs, int number_of_outputs>
+std::unique_ptr<StateFeedbackHybridPlantCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>
+MakeStateFeedbackHybridPlantCoefficients(
+ const fbs::StateFeedbackHybridPlantCoefficients &coefficients) {
+ return std::make_unique<StateFeedbackHybridPlantCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>(
+ ToEigenOrDie<number_of_states, number_of_states>(
+ *CHECK_NOTNULL(coefficients.a_continuous())),
+ ToEigenOrDie<number_of_states, number_of_inputs>(
+ *CHECK_NOTNULL(coefficients.b_continuous())),
+ ToEigenOrDie<number_of_outputs, number_of_states>(
+ *CHECK_NOTNULL(coefficients.c())),
+ ToEigenOrDie<number_of_outputs, number_of_inputs>(
+ *CHECK_NOTNULL(coefficients.d())),
+ ToEigenOrDie<number_of_inputs, 1>(*CHECK_NOTNULL(coefficients.u_max())),
+ ToEigenOrDie<number_of_inputs, 1>(*CHECK_NOTNULL(coefficients.u_min())),
+ ToEigenOrDie<number_of_inputs, number_of_states>(
+ *CHECK_NOTNULL(coefficients.u_limit_coefficient())),
+ ToEigenOrDie<number_of_inputs, 1>(
+ *CHECK_NOTNULL(coefficients.u_limit_constant())),
+ coefficients.delayed_u());
+}
+
+template <int number_of_states, int number_of_inputs, int number_of_outputs>
+std::unique_ptr<HybridKalmanCoefficients<number_of_states, number_of_inputs,
+ number_of_outputs>>
+MakeHybridKalmanCoefficients(
+ const fbs::HybridKalmanCoefficients &coefficients) {
+ return std::make_unique<HybridKalmanCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>(
+ ToEigenOrDie<number_of_states, number_of_states>(
+ *CHECK_NOTNULL(coefficients.q_continuous())),
+ ToEigenOrDie<number_of_outputs, number_of_outputs>(
+ *CHECK_NOTNULL(coefficients.r_continuous())),
+ ToEigenOrDie<number_of_states, number_of_states>(
+ *CHECK_NOTNULL(coefficients.p_steady_state())),
+ coefficients.delayed_u());
+}
+template <int number_of_states, int number_of_inputs, int number_of_outputs>
+StateFeedbackLoop<
+ number_of_states, number_of_inputs, number_of_outputs, double,
+ StateFeedbackHybridPlant<number_of_states, number_of_inputs,
+ number_of_outputs>,
+ HybridKalman<number_of_states, number_of_inputs, number_of_outputs>>
+MakeHybridStateFeedbackLoop(
+ const flatbuffers::Vector<
+ flatbuffers::Offset<fbs::StateFeedbackHybridLoopCoefficients>>
+ &coefficients) {
+ CHECK_LE(1u, coefficients.size());
+ std::vector<std::unique_ptr<StateFeedbackHybridPlantCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>>
+ plant_coefficients;
+ std::vector<std::unique_ptr<StateFeedbackControllerCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>>
+ controller_coefficients;
+ std::vector<std::unique_ptr<HybridKalmanCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>>
+ observer_coefficients;
+ for (const fbs::StateFeedbackHybridLoopCoefficients *loop : coefficients) {
+ CHECK(loop->has_plant());
+ CHECK(loop->has_controller());
+ CHECK(loop->has_observer());
+ plant_coefficients.emplace_back(
+ MakeStateFeedbackHybridPlantCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>(
+ *loop->plant()));
+ controller_coefficients.emplace_back(
+ MakeStateFeedbackControllerCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>(
+ *loop->controller()));
+ observer_coefficients.emplace_back(
+ MakeHybridKalmanCoefficients<number_of_states, number_of_inputs,
+ number_of_outputs>(*loop->observer()));
+ }
+
+ return StateFeedbackLoop<
+ number_of_states, number_of_inputs, number_of_outputs, double,
+ StateFeedbackHybridPlant<number_of_states, number_of_inputs,
+ number_of_outputs>,
+ HybridKalman<number_of_states, number_of_inputs, number_of_outputs>>(
+ StateFeedbackHybridPlant<number_of_states, number_of_inputs,
+ number_of_outputs>(
+ std::move(plant_coefficients)),
+ StateFeedbackController<number_of_states, number_of_inputs,
+ number_of_outputs>(
+ std::move(controller_coefficients)),
+ HybridKalman<number_of_states, number_of_inputs, number_of_outputs>(
+ std::move(observer_coefficients)));
+}
+} // namespace frc971::control_loops
+
+#endif // FRC971_CONTROL_LOOPS_HYBRID_STATE_FEEDBACK_LOOP_CONVERTERS_H_
diff --git a/frc971/control_loops/profiled_subsystem.fbs b/frc971/control_loops/profiled_subsystem.fbs
index 049b52f..d4f64f8 100644
--- a/frc971/control_loops/profiled_subsystem.fbs
+++ b/frc971/control_loops/profiled_subsystem.fbs
@@ -1,4 +1,5 @@
include "frc971/control_loops/control_loops.fbs";
+include "frc971/control_loops/state_feedback_loop.fbs";
namespace frc971.control_loops;
@@ -287,3 +288,15 @@
// the goal + goal velocity directly to the control loop.
ignore_profile:bool (id: 3);
}
+
+// Stores everything but the zeroing information for a single-dof subsystem.
+// Because the subsystem will be templated on the zeroing information, it is
+// passed in separately (see types in //frc971/zeroing:constants.fbs).
+table StaticZeroingSingleDOFProfiledSubsystemCommonParams {
+ zeroing_voltage:double (id: 0);
+ operating_voltage:double (id: 1);
+ zeroing_profile_params:frc971.ProfileParameters (id: 2);
+ default_profile_params:frc971.ProfileParameters (id: 3);
+ range:frc971.Range (id: 4);
+ loop:[frc971.control_loops.fbs.StateFeedbackLoopCoefficients] (id: 5);
+}
diff --git a/frc971/control_loops/python/angular_system.py b/frc971/control_loops/python/angular_system.py
index c6ffb50..551f3d0 100755
--- a/frc971/control_loops/python/angular_system.py
+++ b/frc971/control_loops/python/angular_system.py
@@ -461,7 +461,8 @@
loop_writer.AddConstant(
control_loop.Constant('kFreeSpeed', '%f',
angular_systems[0].motor.free_speed))
- loop_writer.Write(plant_files[0], plant_files[1])
+ loop_writer.Write(plant_files[0], plant_files[1],
+ None if len(plant_files) < 3 else plant_files[2])
integral_loop_writer = control_loop.ControlLoopWriter(
'Integral' + name,
@@ -469,4 +470,6 @@
namespaces=year_namespaces,
plant_type=plant_type,
observer_type=observer_type)
- integral_loop_writer.Write(controller_files[0], controller_files[1])
+ integral_loop_writer.Write(
+ controller_files[0], controller_files[1],
+ None if len(controller_files) < 3 else controller_files[2])
diff --git a/frc971/control_loops/python/angular_system_current.py b/frc971/control_loops/python/angular_system_current.py
index 0dc9595..585f54a 100755
--- a/frc971/control_loops/python/angular_system_current.py
+++ b/frc971/control_loops/python/angular_system_current.py
@@ -501,7 +501,8 @@
loop_writer.AddConstant(
control_loop.Constant('kFreeSpeed', '%f',
angular_systems[0].motor.free_speed))
- loop_writer.Write(plant_files[0], plant_files[1])
+ loop_writer.Write(plant_files[0], plant_files[1],
+ None if len(plant_files) < 3 else plant_files[2])
integral_loop_writer = control_loop.ControlLoopWriter(
'Integral' + name,
@@ -509,4 +510,6 @@
namespaces=year_namespaces,
plant_type=plant_type,
observer_type=observer_type)
- integral_loop_writer.Write(controller_files[0], controller_files[1])
+ integral_loop_writer.Write(
+ controller_files[0], controller_files[1],
+ None if len(controller_files) < 3 else controller_files[2])
diff --git a/frc971/control_loops/python/control_loop.py b/frc971/control_loops/python/control_loop.py
index e179193..864a4e4 100644
--- a/frc971/control_loops/python/control_loop.py
+++ b/frc971/control_loops/python/control_loop.py
@@ -1,6 +1,7 @@
import frc971.control_loops.python.controls as controls
import numpy
import os
+import json
class Constant(object):
@@ -25,6 +26,16 @@
(self.comment, typestring, self.name, self.value)
+def MatrixToJson(matrix):
+ """Returns JSON representation of a numpy matrix."""
+ return {
+ "rows": matrix.shape[0],
+ "cols": matrix.shape[1],
+ "storage_order": "ColMajor",
+ "data": numpy.array(matrix).flatten(order='F').tolist()
+ }
+
+
class ControlLoopWriter(object):
def __init__(self,
@@ -83,10 +94,12 @@
os.path.basename(header_file).upper().replace(
'.', '_').replace('/', '_') + '_')
- def Write(self, header_file, cc_file):
+ def Write(self, header_file, cc_file, json_file=None):
"""Writes the loops to the specified files."""
self.WriteHeader(header_file)
self.WriteCC(os.path.basename(header_file), cc_file)
+ if json_file is not None:
+ self.WriteJson(json_file)
def _GenericType(self, typename, extra_args=None):
"""Returns a loop template using typename for the type."""
@@ -262,6 +275,19 @@
fd.write(self._namespace_end)
fd.write('\n')
+ def WriteJson(self, json_file):
+ """Writes a JSON file of the loop constants to the specified json_file."""
+ loops = []
+ for loop in self._loops:
+ loop_json = {}
+ loop_json["plant"] = loop.DumpPlantJson(self._PlantCoeffType())
+ loop_json["controller"] = loop.DumpControllerJson()
+ loop_json["observer"] = loop.DumbObserverJson(
+ self._ObserverCoeffType())
+ loops.append(loop_json)
+ with open(json_file, 'w') as f:
+ f.write(json.dumps(loops))
+
class ControlLoop(object):
@@ -389,6 +415,27 @@
return '%s Make%sPlantCoefficients();\n' % (plant_coefficient_type,
self._name)
+ def DumpPlantJson(self, plant_coefficient_type):
+ result = {
+ "c": MatrixToJson(self.C),
+ "d": MatrixToJson(self.D),
+ "u_min": MatrixToJson(self.U_min),
+ "u_max": MatrixToJson(self.U_max),
+ "u_limit_coefficient": MatrixToJson(self.U_limit_coefficient),
+ "u_limit_constant": MatrixToJson(self.U_limit_constant),
+ "delayed_u": self.delayed_u
+ }
+ if plant_coefficient_type.startswith('StateFeedbackPlant'):
+ result["a"] = MatrixToJson(self.A)
+ result["b"] = MatrixToJson(self.B)
+ result["dt"] = int(self.dt * 1e9)
+ elif plant_coefficient_type.startswith('StateFeedbackHybridPlant'):
+ result["a_continuous"] = MatrixToJson(self.A_continuous)
+ result["b_continuous"] = MatrixToJson(self.B_continuous)
+ else:
+ glog.fatal('Unsupported plant type %s', plant_coefficient_type)
+ return result
+
def DumpPlant(self, plant_coefficient_type, scalar_type):
"""Writes out a c++ function which will create a PlantCoefficients object.
@@ -475,6 +522,10 @@
num_states, num_inputs, num_outputs, scalar_type,
self.ControllerFunction())
+ def DumpControllerJson(self):
+ result = {"k": MatrixToJson(self.K), "kff": MatrixToJson(self.Kff)}
+ return result
+
def DumpController(self, scalar_type):
"""Returns a c++ function which will create a Controller object.
@@ -511,6 +562,32 @@
return '%s %s;\n' % (observer_coefficient_type,
self.ObserverFunction())
+ def GetObserverCoefficients(self):
+ if hasattr(self, 'KalmanGain'):
+ KalmanGain = self.KalmanGain
+ Q = self.Q
+ R = self.R
+ else:
+ KalmanGain = numpy.linalg.inv(self.A) * self.L
+ Q = numpy.zeros(self.A.shape)
+ R = numpy.zeros((self.C.shape[0], self.C.shape[0]))
+ return (KalmanGain, Q, R)
+
+ def DumbObserverJson(self, observer_coefficient_type):
+ result = {"delayed_u": self.delayed_u}
+ if observer_coefficient_type.startswith('StateFeedbackObserver'):
+ KalmanGain, Q, R = self.GetObserverCoefficients()
+ result["kalman_gain"] = MatrixToJson(KalmanGain)
+ result["q"] = MatrixToJson(Q)
+ result["r"] = MatrixToJson(R)
+ elif observer_coefficient_type.startswith('HybridKalman'):
+ result["q_continuous"] = MatrixToJson(self.Q_continuous)
+ result["r_continuous"] = MatrixToJson(self.R_continuous)
+ result["p_steady_state"] = MatrixToJson(self.P_steady_state)
+ else:
+ glog.fatal('Unsupported plant type %s', observer_coefficient_type)
+ return result
+
def DumpObserver(self, observer_coefficient_type, scalar_type):
"""Returns a c++ function which will create a Observer object.
@@ -523,14 +600,7 @@
delayed_u_string = str(self.delayed_u)
if observer_coefficient_type.startswith('StateFeedbackObserver'):
- if hasattr(self, 'KalmanGain'):
- KalmanGain = self.KalmanGain
- Q = self.Q
- R = self.R
- else:
- KalmanGain = numpy.linalg.inv(self.A) * self.L
- Q = numpy.zeros(self.A.shape)
- R = numpy.zeros((self.C.shape[0], self.C.shape[0]))
+ KalmanGain, Q, R = self.GetObserverCoefficients()
ans.append(self._DumpMatrix('KalmanGain', KalmanGain, scalar_type))
ans.append(self._DumpMatrix('Q', Q, scalar_type))
ans.append(self._DumpMatrix('R', R, scalar_type))
diff --git a/frc971/control_loops/python/drivetrain.py b/frc971/control_loops/python/drivetrain.py
index 5ff4404..65b30c0 100644
--- a/frc971/control_loops/python/drivetrain.py
+++ b/frc971/control_loops/python/drivetrain.py
@@ -525,7 +525,8 @@
"kHighOutputRatio", "%f",
drivetrain_high_high.G_high * drivetrain_high_high.r))
- dog_loop_writer.Write(drivetrain_files[0], drivetrain_files[1])
+ dog_loop_writer.Write(drivetrain_files[0], drivetrain_files[1],
+ drivetrain_files[2])
kf_loop_writer = control_loop.ControlLoopWriter("KFDrivetrain", [
kf_drivetrain_low_low, kf_drivetrain_low_high, kf_drivetrain_high_low,
@@ -533,7 +534,8 @@
],
namespaces=namespaces,
scalar_type=scalar_type)
- kf_loop_writer.Write(kf_drivetrain_files[0], kf_drivetrain_files[1])
+ kf_loop_writer.Write(kf_drivetrain_files[0], kf_drivetrain_files[1],
+ kf_drivetrain_files[2])
def PlotDrivetrainSprint(drivetrain_params):
diff --git a/frc971/control_loops/python/linear_system.py b/frc971/control_loops/python/linear_system.py
index 3bda4e1..e28c422 100755
--- a/frc971/control_loops/python/linear_system.py
+++ b/frc971/control_loops/python/linear_system.py
@@ -422,8 +422,11 @@
linear_systems[0].G * linear_systems[0].radius))
loop_writer.AddConstant(
control_loop.Constant('kRadius', '%f', linear_systems[0].radius))
- loop_writer.Write(plant_files[0], plant_files[1])
+ loop_writer.Write(plant_files[0], plant_files[1],
+ None if len(plant_files) < 3 else plant_files[2])
integral_loop_writer = control_loop.ControlLoopWriter(
'Integral' + name, integral_linear_systems, namespaces=year_namespaces)
- integral_loop_writer.Write(controller_files[0], controller_files[1])
+ integral_loop_writer.Write(
+ controller_files[0], controller_files[1],
+ None if len(controller_files) < 3 else controller_files[2])
diff --git a/frc971/control_loops/python/polydrivetrain.py b/frc971/control_loops/python/polydrivetrain.py
index a45d738..c3d47a6 100644
--- a/frc971/control_loops/python/polydrivetrain.py
+++ b/frc971/control_loops/python/polydrivetrain.py
@@ -490,7 +490,8 @@
namespaces=namespaces,
scalar_type=scalar_type)
- dog_loop_writer.Write(drivetrain_files[0], drivetrain_files[1])
+ dog_loop_writer.Write(drivetrain_files[0], drivetrain_files[1],
+ drivetrain_files[2])
hybrid_loop_writer = control_loop.ControlLoopWriter(
"HybridVelocityDrivetrain", [
@@ -504,12 +505,12 @@
plant_type='StateFeedbackHybridPlant',
observer_type='HybridKalman')
- hybrid_loop_writer.Write(hybrid_files[0], hybrid_files[1])
+ hybrid_loop_writer.Write(hybrid_files[0], hybrid_files[1], hybrid_files[2])
cim_writer = control_loop.ControlLoopWriter("CIM", [CIM()],
scalar_type=scalar_type)
- cim_writer.Write(motor_files[0], motor_files[1])
+ cim_writer.Write(motor_files[0], motor_files[1], motor_files[2])
def PlotPolyDrivetrainMotions(drivetrain_params):
diff --git a/frc971/control_loops/python/static_zeroing_single_dof_profiled_subsystem_test.py b/frc971/control_loops/python/static_zeroing_single_dof_profiled_subsystem_test.py
index 8080aff..92bed42 100644
--- a/frc971/control_loops/python/static_zeroing_single_dof_profiled_subsystem_test.py
+++ b/frc971/control_loops/python/static_zeroing_single_dof_profiled_subsystem_test.py
@@ -38,13 +38,14 @@
linear_system.PlotMotion(kIntake, R)
# Write the generated constants out to a file.
- if len(argv) != 5:
- glog.fatal('Expected .h file name and .cc file name for the \
+ if len(argv) != 7:
+ glog.fatal(
+ 'Expected .h, .cc, and .json filenames and .json file name for the \
static_zeroing_single_dof_profiled_subsystem_test and integral \
static_zeroing_single_dof_profiled_subsystem_test.')
else:
namespaces = ['frc971', 'control_loops']
- linear_system.WriteLinearSystem(kIntake, argv[1:3], argv[3:5],
+ linear_system.WriteLinearSystem(kIntake, argv[1:4], argv[4:7],
namespaces)
diff --git a/frc971/control_loops/python/test_drivetrain/BUILD b/frc971/control_loops/python/test_drivetrain/BUILD
new file mode 100644
index 0000000..63cc2a9
--- /dev/null
+++ b/frc971/control_loops/python/test_drivetrain/BUILD
@@ -0,0 +1,117 @@
+py_binary(
+ name = "drivetrain",
+ srcs = [
+ "drivetrain.py",
+ ],
+ legacy_create_init = False,
+ target_compatible_with = ["@platforms//cpu:x86_64"],
+ deps = [
+ ":python_init",
+ "//frc971/control_loops/python:drivetrain",
+ "@pip//glog",
+ "@pip//python_gflags",
+ ],
+)
+
+py_binary(
+ name = "polydrivetrain",
+ srcs = [
+ "drivetrain.py",
+ "polydrivetrain.py",
+ ],
+ legacy_create_init = False,
+ target_compatible_with = ["@platforms//cpu:x86_64"],
+ deps = [
+ ":python_init",
+ "//frc971/control_loops/python:polydrivetrain",
+ "@pip//glog",
+ "@pip//python_gflags",
+ ],
+)
+
+genrule(
+ name = "genrule_drivetrain",
+ outs = [
+ "drivetrain_dog_motor_plant.h",
+ "drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
+ "kalman_drivetrain_motor_plant.h",
+ "kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
+ ],
+ cmd = "$(location :drivetrain) $(OUTS)",
+ target_compatible_with = ["@platforms//os:linux"],
+ tools = [
+ ":drivetrain",
+ ],
+)
+
+genrule(
+ name = "genrule_polydrivetrain",
+ outs = [
+ "polydrivetrain_dog_motor_plant.h",
+ "polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
+ "polydrivetrain_cim_plant.h",
+ "polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
+ "hybrid_velocity_drivetrain.h",
+ "hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
+ ],
+ cmd = "$(location :polydrivetrain) $(OUTS)",
+ target_compatible_with = ["@platforms//os:linux"],
+ tools = [
+ ":polydrivetrain",
+ ],
+)
+
+cc_library(
+ name = "polydrivetrain_plants",
+ srcs = [
+ "drivetrain_dog_motor_plant.cc",
+ "hybrid_velocity_drivetrain.cc",
+ "kalman_drivetrain_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.cc",
+ ],
+ hdrs = [
+ "drivetrain_dog_motor_plant.h",
+ "hybrid_velocity_drivetrain.h",
+ "kalman_drivetrain_motor_plant.h",
+ "polydrivetrain_dog_motor_plant.h",
+ ],
+ target_compatible_with = ["@platforms//os:linux"],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//frc971/control_loops:hybrid_state_feedback_loop",
+ "//frc971/control_loops:state_feedback_loop",
+ ],
+)
+
+cc_test(
+ name = "drivetrain_json_test",
+ srcs = [
+ "drivetrain_json_test.cc",
+ ],
+ data = [
+ "drivetrain_dog_motor_plant.json",
+ "hybrid_velocity_drivetrain.json",
+ "kalman_drivetrain_motor_plant.json",
+ "polydrivetrain_cim_plant.json",
+ "polydrivetrain_dog_motor_plant.json",
+ ],
+ target_compatible_with = ["@platforms//os:linux"],
+ deps = [
+ ":polydrivetrain_plants",
+ "//aos/testing:googletest",
+ "//frc971/control_loops:hybrid_state_feedback_loop_converters",
+ ],
+)
+
+py_library(
+ name = "python_init",
+ srcs = ["__init__.py"],
+ target_compatible_with = ["@platforms//os:linux"],
+ visibility = ["//visibility:public"],
+ deps = ["//y2018/control_loops:python_init"],
+)
diff --git a/frc971/control_loops/python/test_drivetrain/__init__.py b/frc971/control_loops/python/test_drivetrain/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/frc971/control_loops/python/test_drivetrain/__init__.py
diff --git a/frc971/control_loops/python/test_drivetrain/drivetrain.py b/frc971/control_loops/python/test_drivetrain/drivetrain.py
new file mode 100644
index 0000000..0291487
--- /dev/null
+++ b/frc971/control_loops/python/test_drivetrain/drivetrain.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python3
+
+from __future__ import print_function
+from frc971.control_loops.python import drivetrain
+import sys
+
+import gflags
+import glog
+
+FLAGS = gflags.FLAGS
+
+gflags.DEFINE_bool('plot', False, 'If true, plot the loop response.')
+
+# Values stolen from y2018 (most recent year with shifters).
+kDrivetrain = drivetrain.DrivetrainParams(
+ J=6.0,
+ mass=68.0,
+ robot_radius=0.616 / 2.0,
+ wheel_radius=0.127 / 2.0 * 120.0 / 118.0,
+ G_low=46.0 / 60.0 * 20.0 / 48.0 * 14.0 / 62.0,
+ G_high=62.0 / 44.0 * 20.0 / 48.0 * 14.0 / 62.0,
+ q_pos_low=0.12,
+ q_pos_high=0.14,
+ q_vel_low=1.0,
+ q_vel_high=0.95,
+ efficiency=0.70,
+ has_imu=True,
+ force=True,
+ kf_q_voltage=13.0,
+ controller_poles=[0.82, 0.82],
+ robot_cg_offset=0.0,
+)
+
+
+def main(argv):
+ argv = FLAGS(argv)
+ glog.init()
+
+ if FLAGS.plot:
+ drivetrain.PlotDrivetrainMotions(kDrivetrain)
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json file names.")
+ else:
+ # Write the generated constants out to a file.
+ drivetrain.WriteDrivetrain(
+ argv[1:4], argv[4:7],
+ ['frc971', 'control_loops', 'python', 'test_drivetrain'],
+ kDrivetrain)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/frc971/control_loops/python/test_drivetrain/drivetrain_json_test.cc b/frc971/control_loops/python/test_drivetrain/drivetrain_json_test.cc
new file mode 100644
index 0000000..b280e99
--- /dev/null
+++ b/frc971/control_loops/python/test_drivetrain/drivetrain_json_test.cc
@@ -0,0 +1,121 @@
+#include "gtest/gtest.h"
+
+#include "aos/util/file.h"
+#include "frc971/control_loops/hybrid_state_feedback_loop_converters.h"
+#include "frc971/control_loops/python/test_drivetrain/drivetrain_dog_motor_plant.h"
+#include "frc971/control_loops/python/test_drivetrain/hybrid_velocity_drivetrain.h"
+#include "frc971/control_loops/python/test_drivetrain/kalman_drivetrain_motor_plant.h"
+#include "frc971/control_loops/python/test_drivetrain/polydrivetrain_dog_motor_plant.h"
+
+namespace frc971::control_loops::drivetrain::testing {
+
+class DrivetrainJsonTest : public ::testing::Test {
+ protected:
+ DrivetrainJsonTest() {}
+
+ aos::FlatbufferDetachedBuffer<fbs::StateFeedbackLoopCoefficientsVector>
+ ReadCoefficients(std::string_view file) {
+ const std::string json =
+ "{\"loops\": " + aos::util::ReadFileToStringOrDie(file) + "}";
+ return aos::JsonToFlatbuffer<fbs::StateFeedbackLoopCoefficientsVector>(
+ json);
+ }
+ aos::FlatbufferDetachedBuffer<fbs::StateFeedbackHybridLoopCoefficientsVector>
+ ReadHybridCoefficients(std::string_view file) {
+ const std::string json =
+ "{\"loops\": " + aos::util::ReadFileToStringOrDie(file) + "}";
+ return aos::JsonToFlatbuffer<
+ fbs::StateFeedbackHybridLoopCoefficientsVector>(json);
+ }
+};
+
+TEST_F(DrivetrainJsonTest, DrivetrainLoop) {
+ StateFeedbackLoop<4, 2, 2> made_loop =
+ python::test_drivetrain::MakeDrivetrainLoop();
+ auto coefs = ReadCoefficients(
+ "frc971/control_loops/python/test_drivetrain/"
+ "drivetrain_dog_motor_plant.json");
+
+ StateFeedbackLoop<4, 2, 2> json_loop =
+ MakeStateFeedbackLoop<4, 2, 2>(*CHECK_NOTNULL(coefs.message().loops()));
+ for (size_t index = 0; index < 4; ++index) {
+ ASSERT_TRUE(coefs.span().size() > 0u);
+ made_loop.set_index(index);
+ json_loop.set_index(index);
+#define COMPARE(matrix) \
+ EXPECT_EQ(json_loop.plant().coefficients().matrix, \
+ made_loop.plant().coefficients().matrix);
+ COMPARE(A);
+ COMPARE(B);
+ COMPARE(C);
+ COMPARE(D);
+ COMPARE(U_min);
+ COMPARE(U_max);
+ COMPARE(U_limit_coefficient);
+ COMPARE(U_limit_constant);
+ COMPARE(dt);
+ COMPARE(delayed_u);
+#undef COMPARE
+#define COMPARE(matrix) \
+ EXPECT_EQ(json_loop.controller().coefficients().matrix, \
+ made_loop.controller().coefficients().matrix);
+ COMPARE(K);
+ COMPARE(Kff);
+#undef COMPARE
+#define COMPARE(matrix) \
+ EXPECT_EQ(json_loop.observer().coefficients().matrix, \
+ made_loop.observer().coefficients().matrix);
+ COMPARE(KalmanGain);
+ COMPARE(Q);
+ COMPARE(R);
+ COMPARE(delayed_u);
+#undef COMPARE
+ }
+}
+
+typedef StateFeedbackLoop<2, 2, 2, double, StateFeedbackHybridPlant<2, 2, 2>,
+ HybridKalman<2, 2, 2>>
+ HybridLoop;
+TEST_F(DrivetrainJsonTest, HybridLoop) {
+ HybridLoop made_loop =
+ python::test_drivetrain::MakeHybridVelocityDrivetrainLoop();
+ auto coefs = ReadHybridCoefficients(
+ "frc971/control_loops/python/test_drivetrain/"
+ "hybrid_velocity_drivetrain.json");
+
+ HybridLoop json_loop = MakeHybridStateFeedbackLoop<2, 2, 2>(
+ *CHECK_NOTNULL(coefs.message().loops()));
+ for (size_t index = 0; index < 4; ++index) {
+ ASSERT_TRUE(coefs.span().size() > 0u);
+ made_loop.set_index(index);
+ json_loop.set_index(index);
+#define COMPARE(matrix) \
+ EXPECT_EQ(json_loop.plant().coefficients().matrix, \
+ made_loop.plant().coefficients().matrix);
+ COMPARE(A_continuous);
+ COMPARE(B_continuous);
+ COMPARE(C);
+ COMPARE(D);
+ COMPARE(U_min);
+ COMPARE(U_max);
+ COMPARE(U_limit_coefficient);
+ COMPARE(U_limit_constant);
+ COMPARE(delayed_u);
+#undef COMPARE
+#define COMPARE(matrix) \
+ EXPECT_EQ(json_loop.controller().coefficients().matrix, \
+ made_loop.controller().coefficients().matrix);
+ COMPARE(K);
+ COMPARE(Kff);
+#undef COMPARE
+#define COMPARE(matrix) \
+ EXPECT_EQ(json_loop.observer().coefficients().matrix, \
+ made_loop.observer().coefficients().matrix);
+ COMPARE(Q_continuous);
+ COMPARE(R_continuous);
+ COMPARE(P_steady_state);
+ COMPARE(delayed_u);
+#undef COMPARE
+ }
+}
+} // namespace frc971::control_loops::drivetrain::testing
diff --git a/frc971/control_loops/python/test_drivetrain/polydrivetrain.py b/frc971/control_loops/python/test_drivetrain/polydrivetrain.py
new file mode 100644
index 0000000..70ccb34
--- /dev/null
+++ b/frc971/control_loops/python/test_drivetrain/polydrivetrain.py
@@ -0,0 +1,35 @@
+#!/usr/bin/python3
+
+import sys
+from frc971.control_loops.python.test_drivetrain import drivetrain
+from frc971.control_loops.python import polydrivetrain
+
+import gflags
+import glog
+
+__author__ = 'Austin Schuh (austin.linux@gmail.com)'
+
+FLAGS = gflags.FLAGS
+
+try:
+ gflags.DEFINE_bool('plot', False, 'If true, plot the loop response.')
+except gflags.DuplicateFlagError:
+ pass
+
+
+def main(argv):
+ if FLAGS.plot:
+ polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
+ else:
+ polydrivetrain.WritePolyDrivetrain(
+ argv[1:4], argv[4:7], argv[7:10],
+ ['frc971', 'control_loops', 'python', 'test_drivetrain'],
+ drivetrain.kDrivetrain)
+
+
+if __name__ == '__main__':
+ argv = FLAGS(sys.argv)
+ glog.init()
+ sys.exit(main(argv))
diff --git a/frc971/control_loops/state_feedback_loop.fbs b/frc971/control_loops/state_feedback_loop.fbs
new file mode 100644
index 0000000..7c9bff8
--- /dev/null
+++ b/frc971/control_loops/state_feedback_loop.fbs
@@ -0,0 +1,76 @@
+include "frc971/math/matrix.fbs";
+
+namespace frc971.control_loops.fbs;
+
+// This file contains tables that represent the constants required
+// to initialize a control loop.
+// See frc971/control_loops/state_feedback_loop.h
+
+table StateFeedbackPlantCoefficients {
+ a:frc971.fbs.Matrix (id: 0);
+ b:frc971.fbs.Matrix (id: 1);
+ c:frc971.fbs.Matrix (id: 2);
+ d:frc971.fbs.Matrix (id: 3);
+ u_min:frc971.fbs.Matrix (id: 4);
+ u_max:frc971.fbs.Matrix (id: 5);
+ u_limit_coefficient:frc971.fbs.Matrix (id: 6);
+ u_limit_constant:frc971.fbs.Matrix (id: 7);
+ dt:uint64 (id: 8);
+ delayed_u:uint64 (id: 9);
+}
+
+table StateFeedbackHybridPlantCoefficients {
+ a_continuous:frc971.fbs.Matrix (id: 0);
+ b_continuous:frc971.fbs.Matrix (id: 1);
+ c:frc971.fbs.Matrix (id: 2);
+ d:frc971.fbs.Matrix (id: 3);
+ u_min:frc971.fbs.Matrix (id: 4);
+ u_max:frc971.fbs.Matrix (id: 5);
+ u_limit_coefficient:frc971.fbs.Matrix (id: 6);
+ u_limit_constant:frc971.fbs.Matrix (id: 7);
+ delayed_u:uint64 (id: 8);
+}
+
+table StateFeedbackControllerCoefficients {
+ k:frc971.fbs.Matrix (id: 0);
+ kff:frc971.fbs.Matrix (id: 1);
+}
+
+table StateFeedbackObserverCoefficients {
+ kalman_gain:frc971.fbs.Matrix (id: 0);
+ q:frc971.fbs.Matrix (id: 1);
+ r:frc971.fbs.Matrix (id: 2);
+ delayed_u:uint64 (id: 3);
+}
+
+table HybridKalmanCoefficients {
+ q_continuous:frc971.fbs.Matrix (id: 0);
+ r_continuous:frc971.fbs.Matrix (id: 1);
+ p_steady_state:frc971.fbs.Matrix (id: 2);
+ delayed_u:uint64 (id: 3);
+}
+
+// The tables below represent a single index within a
+// *Loop object. A vector of these will be necessary to initialize
+// the loop (the vector will be of length one except when using a
+// gain-scheduled controller).
+table StateFeedbackLoopCoefficients {
+ plant:StateFeedbackPlantCoefficients (id: 0);
+ controller:StateFeedbackControllerCoefficients (id: 1);
+ observer:StateFeedbackObserverCoefficients (id: 2);
+}
+
+table StateFeedbackHybridLoopCoefficients {
+ plant:StateFeedbackHybridPlantCoefficients (id: 0);
+ controller:StateFeedbackControllerCoefficients (id: 1);
+ observer:HybridKalmanCoefficients (id: 2);
+}
+
+// Helpers for when we need to be able to package just the loop coefficients.
+table StateFeedbackLoopCoefficientsVector {
+ loops:[StateFeedbackLoopCoefficients] (id: 0);
+}
+
+table StateFeedbackHybridLoopCoefficientsVector {
+ loops:[StateFeedbackHybridLoopCoefficients] (id: 0);
+}
diff --git a/frc971/control_loops/state_feedback_loop.h b/frc971/control_loops/state_feedback_loop.h
index c5d05c1..3c90434 100644
--- a/frc971/control_loops/state_feedback_loop.h
+++ b/frc971/control_loops/state_feedback_loop.h
@@ -463,7 +463,8 @@
private:
// Internal state estimate.
- Eigen::Matrix<Scalar, number_of_states, 1> X_hat_;
+ Eigen::Matrix<Scalar, number_of_states, 1> X_hat_ =
+ Eigen::Matrix<Scalar, number_of_states, 1>::Zero();
Eigen::Matrix<Scalar, number_of_inputs, Eigen::Dynamic> last_U_;
int index_ = 0;
diff --git a/frc971/control_loops/state_feedback_loop_converters.h b/frc971/control_loops/state_feedback_loop_converters.h
new file mode 100644
index 0000000..062257d
--- /dev/null
+++ b/frc971/control_loops/state_feedback_loop_converters.h
@@ -0,0 +1,113 @@
+#ifndef FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_CONVERTERS_H_
+#define FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_CONVERTERS_H_
+
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "frc971/control_loops/state_feedback_loop_static.h"
+#include "frc971/math/flatbuffers_matrix.h"
+
+namespace frc971::control_loops {
+// These converters are used for constructing a "default" StateFeedbackLoop
+// object from a flatbuffer.
+// The only method that should typically be called by users is
+// MakeStateFeedbackLoop().
+// Use hybrid_state_feedback_loop_converters.h for control loops that use the
+// hybrid kalman filters.
+template <int number_of_states, int number_of_inputs, int number_of_outputs>
+std::unique_ptr<StateFeedbackPlantCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>
+MakeStateFeedbackPlantCoefficients(
+ const fbs::StateFeedbackPlantCoefficients &coefficients) {
+ return std::make_unique<StateFeedbackPlantCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>(
+ ToEigenOrDie<number_of_states, number_of_states>(
+ *CHECK_NOTNULL(coefficients.a())),
+ ToEigenOrDie<number_of_states, number_of_inputs>(
+ *CHECK_NOTNULL(coefficients.b())),
+ ToEigenOrDie<number_of_outputs, number_of_states>(
+ *CHECK_NOTNULL(coefficients.c())),
+ ToEigenOrDie<number_of_outputs, number_of_inputs>(
+ *CHECK_NOTNULL(coefficients.d())),
+ ToEigenOrDie<number_of_inputs, 1>(*CHECK_NOTNULL(coefficients.u_max())),
+ ToEigenOrDie<number_of_inputs, 1>(*CHECK_NOTNULL(coefficients.u_min())),
+ ToEigenOrDie<number_of_inputs, number_of_states>(
+ *CHECK_NOTNULL(coefficients.u_limit_coefficient())),
+ ToEigenOrDie<number_of_inputs, 1>(
+ *CHECK_NOTNULL(coefficients.u_limit_constant())),
+ std::chrono::nanoseconds(coefficients.dt()), coefficients.delayed_u());
+}
+
+template <int number_of_states, int number_of_inputs, int number_of_outputs>
+std::unique_ptr<StateFeedbackControllerCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>
+MakeStateFeedbackControllerCoefficients(
+ const fbs::StateFeedbackControllerCoefficients &coefficients) {
+ return std::make_unique<StateFeedbackControllerCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>(
+ ToEigenOrDie<number_of_inputs, number_of_states>(
+ *CHECK_NOTNULL(coefficients.k())),
+ ToEigenOrDie<number_of_inputs, number_of_states>(
+ *CHECK_NOTNULL(coefficients.kff())));
+}
+
+template <int number_of_states, int number_of_inputs, int number_of_outputs>
+std::unique_ptr<StateFeedbackObserverCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>
+MakeStateFeedbackObserverCoefficients(
+ const fbs::StateFeedbackObserverCoefficients &coefficients) {
+ return std::make_unique<StateFeedbackObserverCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>(
+ ToEigenOrDie<number_of_states, number_of_outputs>(
+ *CHECK_NOTNULL(coefficients.kalman_gain())),
+ ToEigenOrDie<number_of_states, number_of_states>(
+ *CHECK_NOTNULL(coefficients.q())),
+ ToEigenOrDie<number_of_outputs, number_of_outputs>(
+ *CHECK_NOTNULL(coefficients.r())),
+ coefficients.delayed_u());
+}
+
+template <int number_of_states, int number_of_inputs, int number_of_outputs>
+StateFeedbackLoop<number_of_states, number_of_inputs, number_of_outputs>
+MakeStateFeedbackLoop(const flatbuffers::Vector<flatbuffers::Offset<
+ fbs::StateFeedbackLoopCoefficients>> &coefficients) {
+ CHECK_LE(1u, coefficients.size());
+ std::vector<std::unique_ptr<StateFeedbackPlantCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>>
+ plant_coefficients;
+ std::vector<std::unique_ptr<StateFeedbackControllerCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>>
+ controller_coefficients;
+ std::vector<std::unique_ptr<StateFeedbackObserverCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>>>
+ observer_coefficients;
+ for (const fbs::StateFeedbackLoopCoefficients *loop : coefficients) {
+ CHECK(loop->has_plant());
+ CHECK(loop->has_controller());
+ CHECK(loop->has_observer());
+ plant_coefficients.emplace_back(
+ MakeStateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
+ number_of_outputs>(*loop->plant()));
+ controller_coefficients.emplace_back(
+ MakeStateFeedbackControllerCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>(
+ *loop->controller()));
+ observer_coefficients.emplace_back(
+ MakeStateFeedbackObserverCoefficients<
+ number_of_states, number_of_inputs, number_of_outputs>(
+ *loop->observer()));
+ }
+
+ return StateFeedbackLoop<number_of_states, number_of_inputs,
+ number_of_outputs>(
+ StateFeedbackPlant<number_of_states, number_of_inputs, number_of_outputs>(
+ std::move(plant_coefficients)),
+ StateFeedbackController<number_of_states, number_of_inputs,
+ number_of_outputs>(
+ std::move(controller_coefficients)),
+ StateFeedbackObserver<number_of_states, number_of_inputs,
+ number_of_outputs>(
+ std::move(observer_coefficients)));
+}
+
+} // namespace frc971::control_loops
+
+#endif // FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_CONVERTERS_H_
diff --git a/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h b/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h
index 5c94bd5..b26f69c 100644
--- a/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h
+++ b/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h
@@ -1,7 +1,9 @@
#ifndef FRC971_CONTROL_LOOPS_STATIC_ZEROING_SINGLE_DOF_PROFILED_SUBSYSTEM_H_
#define FRC971_CONTROL_LOOPS_STATIC_ZEROING_SINGLE_DOF_PROFILED_SUBSYSTEM_H_
+#include "aos/flatbuffer_merge.h"
#include "frc971/control_loops/profiled_subsystem.h"
+#include "frc971/control_loops/state_feedback_loop_converters.h"
namespace frc971 {
namespace control_loops {
@@ -28,7 +30,52 @@
typename ZeroingEstimator::ZeroingConstants zeroing_constants;
// Function that makes the integral loop for the subsystem
- ::std::function<StateFeedbackLoop<3, 1, 1>()> make_integral_loop;
+ std::function<StateFeedbackLoop<3, 1, 1>()> make_integral_loop;
+
+ // Used by make_integral_loop when constructed from a flatbuffer.
+ std::shared_ptr<aos::FlatbufferDetachedBuffer<
+ StaticZeroingSingleDOFProfiledSubsystemCommonParams>>
+ loop_params;
+
+ StaticZeroingSingleDOFProfiledSubsystemParams(
+ double zeroing_voltage_in, double operating_voltage_in,
+ const ProfileParametersT &zeroing_profile_params_in,
+ const ProfileParametersT &default_profile_params_in,
+ const ::frc971::constants::Range &range_in,
+ const typename ZeroingEstimator::ZeroingConstants &zeroing_constants_in,
+ std::function<StateFeedbackLoop<3, 1, 1>()> make_integral_loop_in)
+ : zeroing_voltage(zeroing_voltage_in),
+ operating_voltage(operating_voltage_in),
+ zeroing_profile_params(zeroing_profile_params_in),
+ default_profile_params(default_profile_params_in),
+ range(range_in),
+ zeroing_constants(zeroing_constants_in),
+ make_integral_loop(make_integral_loop_in) {}
+
+ // Constructs the parameters from flatbuffer types.
+ StaticZeroingSingleDOFProfiledSubsystemParams(
+ const StaticZeroingSingleDOFProfiledSubsystemCommonParams *common,
+ const ZeroingEstimator::ZeroingConstants::TableType *zeroing)
+ : zeroing_voltage(common->zeroing_voltage()),
+ operating_voltage(common->operating_voltage()),
+ zeroing_profile_params(
+ aos::UnpackFlatbuffer(common->zeroing_profile_params())),
+ default_profile_params(
+ aos::UnpackFlatbuffer(common->default_profile_params())),
+ range(frc971::constants::Range::FromFlatbuffer(common->range())),
+ zeroing_constants(aos::UnpackFlatbuffer(zeroing)),
+ make_integral_loop([this]() {
+ return MakeStateFeedbackLoop<3, 1, 1>(
+ *CHECK_NOTNULL(loop_params->message().loop()));
+ }),
+ loop_params(std::make_shared<aos::FlatbufferDetachedBuffer<
+ StaticZeroingSingleDOFProfiledSubsystemCommonParams>>(
+ aos::RecursiveCopyFlatBuffer(common))) {}
+ StaticZeroingSingleDOFProfiledSubsystemParams() = default;
+ StaticZeroingSingleDOFProfiledSubsystemParams(
+ const StaticZeroingSingleDOFProfiledSubsystemParams &) = default;
+ StaticZeroingSingleDOFProfiledSubsystemParams &operator=(
+ const StaticZeroingSingleDOFProfiledSubsystemParams &) = default;
};
// Class for controlling and motion profiling a single degree of freedom
@@ -37,9 +84,20 @@
typename TSubsystemParams = TZeroingEstimator>
class StaticZeroingSingleDOFProfiledSubsystem {
public:
+ // Constructs the subsystem from flatbuffer types (appropriate when using the
+ // constants.h for the subsystem; the constants.json should be preferred for
+ // new subsystems).
StaticZeroingSingleDOFProfiledSubsystem(
const StaticZeroingSingleDOFProfiledSubsystemParams<TSubsystemParams>
¶ms);
+ // Constructs the subsystem from flatbuffer types (appropriate when using a
+ // constants.json for the subsystem).
+ StaticZeroingSingleDOFProfiledSubsystem(
+ const StaticZeroingSingleDOFProfiledSubsystemCommonParams *common,
+ const TZeroingEstimator::ZeroingConstants::TableType *zeroing)
+ : StaticZeroingSingleDOFProfiledSubsystem(
+ StaticZeroingSingleDOFProfiledSubsystemParams<TSubsystemParams>{
+ common, zeroing}) {}
using ZeroingEstimator = TZeroingEstimator;
using ProfiledJointStatus = TProfiledJointStatus;
@@ -58,8 +116,8 @@
void set_max_position(double max_position) { max_position_ = max_position; }
- // Sets a temporary acceleration limit. No accelerations faster than this may
- // be commanded.
+ // Sets a temporary acceleration limit. No accelerations faster than this
+ // may be commanded.
void set_max_acceleration(double max_acceleration) {
max_acceleration_ = max_acceleration;
}
@@ -111,9 +169,9 @@
const typename ZeroingEstimator::Position *position, double *output,
flatbuffers::FlatBufferBuilder *status_fbb);
- // Sets the current profile state to solve from. Useful for when an external
- // controller gives back control and we want the trajectory generator to
- // take over control again.
+ // Sets the current profile state to solve from. Useful for when an
+ // external controller gives back control and we want the trajectory
+ // generator to take over control again.
void ForceGoal(double goal, double goal_velocity);
// Resets the profiled subsystem and returns to uninitialized
diff --git a/frc971/math/BUILD b/frc971/math/BUILD
index 54df5bd..f33b9f9 100644
--- a/frc971/math/BUILD
+++ b/frc971/math/BUILD
@@ -1,4 +1,5 @@
load("//aos/flatbuffers:generate.bzl", "static_flatbuffer")
+load("@com_github_google_flatbuffers//:typescript.bzl", "flatbuffer_ts_library")
static_flatbuffer(
name = "matrix_fbs",
@@ -6,6 +7,14 @@
visibility = ["//visibility:public"],
)
+flatbuffer_ts_library(
+ name = "matrix_ts_fbs",
+ srcs = [
+ "matrix.fbs",
+ ],
+ visibility = ["//visibility:public"],
+)
+
cc_library(
name = "flatbuffers_matrix",
hdrs = ["flatbuffers_matrix.h"],
diff --git a/motors/seems_reasonable/BUILD b/motors/seems_reasonable/BUILD
index b899ffb..63fea8a 100644
--- a/motors/seems_reasonable/BUILD
+++ b/motors/seems_reasonable/BUILD
@@ -34,8 +34,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location :drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:none"],
@@ -49,10 +51,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location :polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:none"],
diff --git a/motors/seems_reasonable/drivetrain.py b/motors/seems_reasonable/drivetrain.py
index ad3d92a..1eeeb42 100644
--- a/motors/seems_reasonable/drivetrain.py
+++ b/motors/seems_reasonable/drivetrain.py
@@ -26,12 +26,12 @@
argv = FLAGS(argv)
glog.init()
- if len(argv) != 5:
- glog.error("Expected .h file name and .cc file name")
+ if len(argv) != 7:
+ glog.error("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3],
- argv[3:5], ['motors', 'seems_reasonable'],
+ drivetrain.WriteDrivetrain(argv[1:4],
+ argv[4:7], ['motors', 'seems_reasonable'],
kDrivetrain,
scalar_type='float')
diff --git a/motors/seems_reasonable/polydrivetrain.py b/motors/seems_reasonable/polydrivetrain.py
index 665739f..505ed38 100644
--- a/motors/seems_reasonable/polydrivetrain.py
+++ b/motors/seems_reasonable/polydrivetrain.py
@@ -20,12 +20,12 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3],
- argv[3:5],
- argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4],
+ argv[4:7],
+ argv[7:10],
['motors', 'seems_reasonable'],
drivetrain.kDrivetrain,
scalar_type='float')
diff --git a/y2014/control_loops/drivetrain/BUILD b/y2014/control_loops/drivetrain/BUILD
index f331b37..b185b4b 100644
--- a/y2014/control_loops/drivetrain/BUILD
+++ b/y2014/control_loops/drivetrain/BUILD
@@ -5,8 +5,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2014/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -21,10 +23,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2014/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2014/control_loops/python/drivetrain.py b/y2014/control_loops/python/drivetrain.py
index d72c222..41fbd27 100755
--- a/y2014/control_loops/python/drivetrain.py
+++ b/y2014/control_loops/python/drivetrain.py
@@ -31,11 +31,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2014', kDrivetrain)
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2014', kDrivetrain)
if __name__ == '__main__':
diff --git a/y2014/control_loops/python/polydrivetrain.py b/y2014/control_loops/python/polydrivetrain.py
index 05b6658..978567a 100755
--- a/y2014/control_loops/python/polydrivetrain.py
+++ b/y2014/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2014', drivetrain.kDrivetrain)
diff --git a/y2014_bot3/control_loops/drivetrain/BUILD b/y2014_bot3/control_loops/drivetrain/BUILD
index 9a5bb53..7f303b3 100644
--- a/y2014_bot3/control_loops/drivetrain/BUILD
+++ b/y2014_bot3/control_loops/drivetrain/BUILD
@@ -5,8 +5,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2014_bot3/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -21,10 +23,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2014_bot3/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2014_bot3/control_loops/python/drivetrain.py b/y2014_bot3/control_loops/python/drivetrain.py
index 955cf4c..4d4a059 100755
--- a/y2014_bot3/control_loops/python/drivetrain.py
+++ b/y2014_bot3/control_loops/python/drivetrain.py
@@ -32,11 +32,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2014_bot3',
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2014_bot3',
kDrivetrain)
diff --git a/y2014_bot3/control_loops/python/polydrivetrain.py b/y2014_bot3/control_loops/python/polydrivetrain.py
index 881b2b0..62552cc 100755
--- a/y2014_bot3/control_loops/python/polydrivetrain.py
+++ b/y2014_bot3/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2014_bot3',
drivetrain.kDrivetrain)
diff --git a/y2016/control_loops/drivetrain/BUILD b/y2016/control_loops/drivetrain/BUILD
index 0988e03..c48fa14 100644
--- a/y2016/control_loops/drivetrain/BUILD
+++ b/y2016/control_loops/drivetrain/BUILD
@@ -3,8 +3,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2016/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -18,10 +20,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2016/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2016/control_loops/python/drivetrain.py b/y2016/control_loops/python/drivetrain.py
index a0205e7..14f8210 100755
--- a/y2016/control_loops/python/drivetrain.py
+++ b/y2016/control_loops/python/drivetrain.py
@@ -33,11 +33,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2016', kDrivetrain)
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2016', kDrivetrain)
if __name__ == '__main__':
diff --git a/y2016/control_loops/python/polydrivetrain.py b/y2016/control_loops/python/polydrivetrain.py
index 69a7be9..e289cef 100755
--- a/y2016/control_loops/python/polydrivetrain.py
+++ b/y2016/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2016', drivetrain.kDrivetrain)
diff --git a/y2017/control_loops/drivetrain/BUILD b/y2017/control_loops/drivetrain/BUILD
index 86d923f..a4fcae3 100644
--- a/y2017/control_loops/drivetrain/BUILD
+++ b/y2017/control_loops/drivetrain/BUILD
@@ -5,8 +5,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2017/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -21,10 +23,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2017/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2017/control_loops/python/drivetrain.py b/y2017/control_loops/python/drivetrain.py
index b1ebcd8..b5d05e0 100755
--- a/y2017/control_loops/python/drivetrain.py
+++ b/y2017/control_loops/python/drivetrain.py
@@ -29,11 +29,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2017', kDrivetrain)
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2017', kDrivetrain)
if __name__ == '__main__':
diff --git a/y2017/control_loops/python/polydrivetrain.py b/y2017/control_loops/python/polydrivetrain.py
index e181ef5..682ac49 100755
--- a/y2017/control_loops/python/polydrivetrain.py
+++ b/y2017/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2017', drivetrain.kDrivetrain)
diff --git a/y2018/control_loops/drivetrain/BUILD b/y2018/control_loops/drivetrain/BUILD
index e9a75b8..9ae4916 100644
--- a/y2018/control_loops/drivetrain/BUILD
+++ b/y2018/control_loops/drivetrain/BUILD
@@ -3,8 +3,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2018/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -18,10 +20,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2018/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2018/control_loops/python/drivetrain.py b/y2018/control_loops/python/drivetrain.py
index 0e5ed43..ccc8a20 100644
--- a/y2018/control_loops/python/drivetrain.py
+++ b/y2018/control_loops/python/drivetrain.py
@@ -41,11 +41,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2018', kDrivetrain)
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2018', kDrivetrain)
if __name__ == '__main__':
diff --git a/y2018/control_loops/python/polydrivetrain.py b/y2018/control_loops/python/polydrivetrain.py
index f406aa2..45ed5dc 100644
--- a/y2018/control_loops/python/polydrivetrain.py
+++ b/y2018/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2018', drivetrain.kDrivetrain)
diff --git a/y2019/control_loops/drivetrain/BUILD b/y2019/control_loops/drivetrain/BUILD
index 9da671d..65857c6 100644
--- a/y2019/control_loops/drivetrain/BUILD
+++ b/y2019/control_loops/drivetrain/BUILD
@@ -7,8 +7,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2019/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -22,10 +24,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2019/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2019/control_loops/python/drivetrain.py b/y2019/control_loops/python/drivetrain.py
index 0ef54ef..efb080f 100644
--- a/y2019/control_loops/python/drivetrain.py
+++ b/y2019/control_loops/python/drivetrain.py
@@ -41,11 +41,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2019', kDrivetrain)
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2019', kDrivetrain)
if __name__ == '__main__':
diff --git a/y2019/control_loops/python/polydrivetrain.py b/y2019/control_loops/python/polydrivetrain.py
index a045af1..b83f38f 100644
--- a/y2019/control_loops/python/polydrivetrain.py
+++ b/y2019/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2019', drivetrain.kDrivetrain)
diff --git a/y2020/control_loops/drivetrain/BUILD b/y2020/control_loops/drivetrain/BUILD
index 5e859ab..0070156 100644
--- a/y2020/control_loops/drivetrain/BUILD
+++ b/y2020/control_loops/drivetrain/BUILD
@@ -8,8 +8,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2020/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -23,10 +25,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2020/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2020/control_loops/python/drivetrain.py b/y2020/control_loops/python/drivetrain.py
index ba43450..28c46da 100644
--- a/y2020/control_loops/python/drivetrain.py
+++ b/y2020/control_loops/python/drivetrain.py
@@ -35,11 +35,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2020', kDrivetrain)
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2020', kDrivetrain)
if __name__ == '__main__':
diff --git a/y2020/control_loops/python/polydrivetrain.py b/y2020/control_loops/python/polydrivetrain.py
index dbd5268..4dd4c0b 100644
--- a/y2020/control_loops/python/polydrivetrain.py
+++ b/y2020/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2020', drivetrain.kDrivetrain)
diff --git a/y2021_bot3/control_loops/drivetrain/BUILD b/y2021_bot3/control_loops/drivetrain/BUILD
index 3f9a3df..d35e46b 100644
--- a/y2021_bot3/control_loops/drivetrain/BUILD
+++ b/y2021_bot3/control_loops/drivetrain/BUILD
@@ -3,8 +3,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2021_bot3/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -18,10 +20,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2021_bot3/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2021_bot3/control_loops/python/drivetrain.py b/y2021_bot3/control_loops/python/drivetrain.py
index f3d4682..dfbdd91 100644
--- a/y2021_bot3/control_loops/python/drivetrain.py
+++ b/y2021_bot3/control_loops/python/drivetrain.py
@@ -36,11 +36,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2021_bot3',
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2021_bot3',
kDrivetrain)
diff --git a/y2021_bot3/control_loops/python/polydrivetrain.py b/y2021_bot3/control_loops/python/polydrivetrain.py
index f8c3417..9268967 100644
--- a/y2021_bot3/control_loops/python/polydrivetrain.py
+++ b/y2021_bot3/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2021_bot3',
drivetrain.kDrivetrain)
diff --git a/y2022/control_loops/drivetrain/BUILD b/y2022/control_loops/drivetrain/BUILD
index 148a998..97a7aba 100644
--- a/y2022/control_loops/drivetrain/BUILD
+++ b/y2022/control_loops/drivetrain/BUILD
@@ -5,8 +5,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2022/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -20,10 +22,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2022/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2022/control_loops/python/drivetrain.py b/y2022/control_loops/python/drivetrain.py
index 59b9651..095ae98 100644
--- a/y2022/control_loops/python/drivetrain.py
+++ b/y2022/control_loops/python/drivetrain.py
@@ -36,11 +36,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2022', kDrivetrain)
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2022', kDrivetrain)
if __name__ == '__main__':
diff --git a/y2022/control_loops/python/polydrivetrain.py b/y2022/control_loops/python/polydrivetrain.py
index cf54470..64ec11b 100644
--- a/y2022/control_loops/python/polydrivetrain.py
+++ b/y2022/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2022', drivetrain.kDrivetrain)
diff --git a/y2022_bot3/control_loops/drivetrain/BUILD b/y2022_bot3/control_loops/drivetrain/BUILD
index ecdcf6b..3bd4db7 100644
--- a/y2022_bot3/control_loops/drivetrain/BUILD
+++ b/y2022_bot3/control_loops/drivetrain/BUILD
@@ -5,8 +5,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2022_bot3/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -20,10 +22,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2022_bot3/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2022_bot3/control_loops/python/drivetrain.py b/y2022_bot3/control_loops/python/drivetrain.py
index 7db0a05..a49b8f2 100644
--- a/y2022_bot3/control_loops/python/drivetrain.py
+++ b/y2022_bot3/control_loops/python/drivetrain.py
@@ -36,11 +36,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2022_bot3',
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2022_bot3',
kDrivetrain)
diff --git a/y2022_bot3/control_loops/python/polydrivetrain.py b/y2022_bot3/control_loops/python/polydrivetrain.py
index 14b9285..13884ee 100644
--- a/y2022_bot3/control_loops/python/polydrivetrain.py
+++ b/y2022_bot3/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2022_bot3',
drivetrain.kDrivetrain)
diff --git a/y2023/control_loops/drivetrain/BUILD b/y2023/control_loops/drivetrain/BUILD
index 01c360b..ea2110e 100644
--- a/y2023/control_loops/drivetrain/BUILD
+++ b/y2023/control_loops/drivetrain/BUILD
@@ -6,8 +6,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2023/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -21,10 +23,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2023/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2023/control_loops/python/drivetrain.py b/y2023/control_loops/python/drivetrain.py
index 9d2b006..69d4f3e 100644
--- a/y2023/control_loops/python/drivetrain.py
+++ b/y2023/control_loops/python/drivetrain.py
@@ -36,11 +36,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2023', kDrivetrain)
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2023', kDrivetrain)
if __name__ == '__main__':
diff --git a/y2023/control_loops/python/polydrivetrain.py b/y2023/control_loops/python/polydrivetrain.py
index 2f2346d..8ce6b8c 100644
--- a/y2023/control_loops/python/polydrivetrain.py
+++ b/y2023/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2023', drivetrain.kDrivetrain)
diff --git a/y2023_bot3/control_loops/drivetrain/BUILD b/y2023_bot3/control_loops/drivetrain/BUILD
index 46654ec..62c213d 100644
--- a/y2023_bot3/control_loops/drivetrain/BUILD
+++ b/y2023_bot3/control_loops/drivetrain/BUILD
@@ -3,8 +3,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2023_bot3/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -18,10 +20,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2023_bot3/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2023_bot3/control_loops/python/drivetrain.py b/y2023_bot3/control_loops/python/drivetrain.py
index 26cb043..ac0da93 100644
--- a/y2023_bot3/control_loops/python/drivetrain.py
+++ b/y2023_bot3/control_loops/python/drivetrain.py
@@ -37,11 +37,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2023_bot3',
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2023_bot3',
kDrivetrain)
diff --git a/y2023_bot3/control_loops/python/polydrivetrain.py b/y2023_bot3/control_loops/python/polydrivetrain.py
index 80e4f13..bd9dc89 100644
--- a/y2023_bot3/control_loops/python/polydrivetrain.py
+++ b/y2023_bot3/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2023_bot3',
drivetrain.kDrivetrain)
diff --git a/y2024/control_loops/drivetrain/BUILD b/y2024/control_loops/drivetrain/BUILD
index e3c627a..0cca123 100644
--- a/y2024/control_loops/drivetrain/BUILD
+++ b/y2024/control_loops/drivetrain/BUILD
@@ -5,8 +5,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2024/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -20,10 +22,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2024/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2024/control_loops/python/drivetrain.py b/y2024/control_loops/python/drivetrain.py
index 64dcc47..caedada 100644
--- a/y2024/control_loops/python/drivetrain.py
+++ b/y2024/control_loops/python/drivetrain.py
@@ -36,11 +36,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2024', kDrivetrain)
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2024', kDrivetrain)
if __name__ == '__main__':
diff --git a/y2024/control_loops/python/polydrivetrain.py b/y2024/control_loops/python/polydrivetrain.py
index 99a9b53..9a9d2a7 100644
--- a/y2024/control_loops/python/polydrivetrain.py
+++ b/y2024/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2024', drivetrain.kDrivetrain)
diff --git a/y2024_defense/control_loops/drivetrain/BUILD b/y2024_defense/control_loops/drivetrain/BUILD
index 664f9a1..9f2349e 100644
--- a/y2024_defense/control_loops/drivetrain/BUILD
+++ b/y2024_defense/control_loops/drivetrain/BUILD
@@ -5,8 +5,10 @@
outs = [
"drivetrain_dog_motor_plant.h",
"drivetrain_dog_motor_plant.cc",
+ "drivetrain_dog_motor_plant.json",
"kalman_drivetrain_motor_plant.h",
"kalman_drivetrain_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.json",
],
cmd = "$(location //y2024_defense/control_loops/python:drivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
@@ -20,10 +22,13 @@
outs = [
"polydrivetrain_dog_motor_plant.h",
"polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_dog_motor_plant.json",
"polydrivetrain_cim_plant.h",
"polydrivetrain_cim_plant.cc",
+ "polydrivetrain_cim_plant.json",
"hybrid_velocity_drivetrain.h",
"hybrid_velocity_drivetrain.cc",
+ "hybrid_velocity_drivetrain.json",
],
cmd = "$(location //y2024_defense/control_loops/python:polydrivetrain) $(OUTS)",
target_compatible_with = ["@platforms//os:linux"],
diff --git a/y2024_defense/control_loops/python/drivetrain.py b/y2024_defense/control_loops/python/drivetrain.py
index 438eb24..a2f46e3 100644
--- a/y2024_defense/control_loops/python/drivetrain.py
+++ b/y2024_defense/control_loops/python/drivetrain.py
@@ -36,11 +36,11 @@
if FLAGS.plot:
drivetrain.PlotDrivetrainMotions(kDrivetrain)
- elif len(argv) != 5:
- print("Expected .h file name and .cc file name")
+ elif len(argv) != 7:
+ print("Expected .h, .cc, and .json filenames")
else:
# Write the generated constants out to a file.
- drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2024_defense',
+ drivetrain.WriteDrivetrain(argv[1:4], argv[4:7], 'y2024_defense',
kDrivetrain)
diff --git a/y2024_defense/control_loops/python/polydrivetrain.py b/y2024_defense/control_loops/python/polydrivetrain.py
index 301c7b5..a455f08 100644
--- a/y2024_defense/control_loops/python/polydrivetrain.py
+++ b/y2024_defense/control_loops/python/polydrivetrain.py
@@ -20,10 +20,10 @@
def main(argv):
if FLAGS.plot:
polydrivetrain.PlotPolyDrivetrainMotions(drivetrain.kDrivetrain)
- elif len(argv) != 7:
- glog.fatal('Expected .h file name and .cc file name')
+ elif len(argv) != 10:
+ glog.fatal('Expected .h, .cc, and .json filenames')
else:
- polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7],
+ polydrivetrain.WritePolyDrivetrain(argv[1:4], argv[4:7], argv[7:10],
'y2024_defense',
drivetrain.kDrivetrain)