Merge changes I97756b30,I0529fc0c
* changes:
Merge commit 'fe830c78bac85aea842c4d329b9a90087ddc6537' into master
Squashed 'third_party/autocxx/' changes from c35090b75..fdfb26e26
diff --git a/WORKSPACE b/WORKSPACE
index 51f9c8f..1be9988 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -724,29 +724,29 @@
)
http_archive(
- name = "ctre_phoenixpro_api_cpp_headers",
+ name = "ctre_phoenix6_api_cpp_headers",
build_file_content = """
cc_library(
name = 'api-cpp',
visibility = ['//visibility:public'],
- hdrs = glob(['ctre/phoenixpro/**/*.hpp', 'units/*.h']),
+ hdrs = glob(['ctre/phoenix6/**/*.hpp', 'units/*.h']),
includes = ["."],
deps = ["@//third_party/allwpilib/wpimath"],
)
""",
- sha256 = "340a9c8e726e2eb365b7a40a722df05fe7c7072c5c4a617fa0218eb6d074ad9f",
+ sha256 = "3c4da9f46c751d4981697da26d3c8680f40c87090782f5adf63412e34508f372",
urls = [
- "https://maven.ctr-electronics.com/release/com/ctre/phoenixpro/api-cpp/23.0.11/api-cpp-23.0.11-headers.zip",
+ "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/api-cpp/23.2.2/api-cpp-23.2.2-headers.zip",
],
)
http_archive(
- name = "ctre_phoenixpro_api_cpp_athena",
+ name = "ctre_phoenix6_api_cpp_athena",
build_file_content = """
filegroup(
name = 'shared_libraries',
srcs = [
- 'linux/athena/shared/libCTRE_PhoenixPro.so',
+ 'linux/athena/shared/libCTRE_Phoenix6.so',
],
visibility = ['//visibility:public'],
)
@@ -754,18 +754,18 @@
cc_library(
name = 'api-cpp',
visibility = ['//visibility:public'],
- srcs = ['linux/athena/shared/libCTRE_PhoenixPro.so'],
+ srcs = ['linux/athena/shared/libCTRE_Phoenix6.so'],
target_compatible_with = ['@//tools/platforms/hardware:roborio'],
)
""",
- sha256 = "11f392bebfe54f512be9ef59809e1a10c4497e0ce92970645f054e7e04fe7ef6",
+ sha256 = "8391cbd24582c951a8fdbcff533243be718fc54e091c068d5441bb0c18ff822c",
urls = [
- "https://maven.ctr-electronics.com/release/com/ctre/phoenixpro/api-cpp/23.0.11/api-cpp-23.0.11-linuxathena.zip",
+ "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/api-cpp/23.2.2/api-cpp-23.2.2-linuxathena.zip",
],
)
http_archive(
- name = "ctre_phoenixpro_tools_headers",
+ name = "ctre_phoenix6_tools_headers",
build_file_content = """
cc_library(
name = 'tools',
@@ -773,14 +773,14 @@
hdrs = glob(['ctre/**/*.h', 'ctre/**/*.hpp']),
)
""",
- sha256 = "7585e1bd9e581dd745e7f040ab521b966b40a04d05bc7fa82d6dafe2fb65764e",
+ sha256 = "33781c9db0a204e257928351c700295aec2bf6e2abb6a49ef237a95e98442a18",
urls = [
- "https://maven.ctr-electronics.com/release/com/ctre/phoenixpro/tools/23.0.11/tools-23.0.11-headers.zip",
+ "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/tools/23.2.2/tools-23.2.2-headers.zip",
],
)
http_archive(
- name = "ctre_phoenixpro_tools_athena",
+ name = "ctre_phoenix6_tools_athena",
build_file_content = """
filegroup(
name = 'shared_libraries',
@@ -797,9 +797,9 @@
target_compatible_with = ['@//tools/platforms/hardware:roborio'],
)
""",
- sha256 = "b1daadfe782c43ed32c2e1a3956998f9604a3fc9282ef866fd8dc1482f3b8cc9",
+ sha256 = "75ec607f81ab470bc7c01fda2b8ca7b71b7dc3378b370f806f8646db27600504",
urls = [
- "https://maven.ctr-electronics.com/release/com/ctre/phoenixpro/tools/23.0.11/tools-23.0.11-linuxathena.zip",
+ "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/tools/23.2.2/tools-23.2.2-linuxathena.zip",
],
)
diff --git a/aos/events/BUILD b/aos/events/BUILD
index 07c1f3a..eb77036 100644
--- a/aos/events/BUILD
+++ b/aos/events/BUILD
@@ -3,7 +3,7 @@
load("//aos:flatbuffers.bzl", "cc_static_flatbuffer")
load("//aos:config.bzl", "aos_config")
load("//tools/build_rules:autocxx.bzl", "autocxx_library")
-load("@rules_rust//rust:defs.bzl", "rust_doc_test", "rust_test")
+load("@rules_rust//rust:defs.bzl", "rust_doc", "rust_doc_test", "rust_test")
package(default_visibility = ["//visibility:public"])
@@ -181,6 +181,12 @@
],
)
+rust_doc(
+ name = "event_loop_runtime_doc",
+ crate = ":event_loop_runtime",
+ target_compatible_with = ["@platforms//cpu:x86_64"],
+)
+
rust_doc_test(
name = "event_loop_runtime_doc_test",
crate = ":event_loop_runtime",
@@ -520,6 +526,15 @@
],
)
+cc_library(
+ name = "shm_event_loop_for_rust",
+ hdrs = ["shm_event_loop_for_rust.h"],
+ deps = [
+ ":event_loop",
+ ":simulated_event_loop",
+ ],
+)
+
autocxx_library(
name = "simulated_event_loop_rs",
srcs = ["simulated_event_loop.rs"],
@@ -560,6 +575,66 @@
],
)
+autocxx_library(
+ name = "shm_event_loop_rs",
+ srcs = ["shm_event_loop.rs"],
+ crate_name = "aos_events_shm_event_loop",
+ libs = [
+ ":shm_event_loop",
+ ":shm_event_loop_for_rust",
+ ],
+ rs_deps = [
+ "@com_github_google_flatbuffers//rust",
+ "@crate_index//:futures",
+ "//aos:configuration_rust_fbs",
+ "//aos:flatbuffers_rs",
+ ],
+ target_compatible_with = select({
+ "//conditions:default": ["//tools/platforms/rust:has_support"],
+ "//tools:has_msan": ["@platforms//:incompatible"],
+ }),
+ visibility = ["//visibility:public"],
+ deps = [
+ ":event_loop_runtime",
+ "//aos:configuration_rs",
+ ],
+)
+
+rust_doc(
+ name = "shm_event_loop_rs_doc",
+ crate = ":shm_event_loop_rs",
+ target_compatible_with = ["@platforms//cpu:x86_64"],
+)
+
+rust_test(
+ name = "shm_event_loop_rs_test",
+ crate = ":shm_event_loop_rs",
+ data = [":pingpong_config"],
+ # TODO: Make Rust play happy with pic vs nopic. Details at:
+ # https://github.com/bazelbuild/rules_rust/issues/118
+ rustc_flags = ["-Crelocation-model=static"],
+ target_compatible_with = select({
+ "//conditions:default": ["//tools/platforms/rust:has_support"],
+ "//tools:has_msan": ["@platforms//:incompatible"],
+ }),
+ deps = [
+ ":ping_rust_fbs",
+ "//aos:init_rs",
+ "@crate_index//:futures",
+ "@rules_rust//tools/runfiles",
+ ],
+)
+
+rust_doc_test(
+ name = "shm_event_loop_rs_doc_test",
+ crate = ":shm_event_loop_rs",
+ target_compatible_with = ["@platforms//cpu:x86_64"],
+ deps = [
+ ":ping_rust_fbs",
+ ":pong_rust_fbs",
+ ],
+)
+
cc_test(
name = "event_scheduler_test",
srcs = ["event_scheduler_test.cc"],
diff --git a/aos/events/shm_event_loop.rs b/aos/events/shm_event_loop.rs
new file mode 100644
index 0000000..3e387ef
--- /dev/null
+++ b/aos/events/shm_event_loop.rs
@@ -0,0 +1,302 @@
+pub use aos_configuration::{Configuration, ConfigurationExt};
+pub use aos_events_event_loop_runtime::EventLoop;
+pub use aos_events_event_loop_runtime::{CppExitHandle, EventLoopRuntime, ExitHandle};
+
+use aos_configuration_fbs::aos::Configuration as RustConfiguration;
+use aos_flatbuffers::{transmute_table_to, Flatbuffer};
+use autocxx::WithinBox;
+use core::marker::PhantomData;
+use core::pin::Pin;
+use std::boxed::Box;
+use std::ops::{Deref, DerefMut};
+
+autocxx::include_cpp! (
+#include "aos/events/shm_event_loop.h"
+#include "aos/events/shm_event_loop_for_rust.h"
+
+safety!(unsafe)
+
+generate!("aos::ShmEventLoopForRust")
+
+extern_cpp_type!("aos::ExitHandle", crate::CppExitHandle)
+extern_cpp_type!("aos::Configuration", crate::Configuration)
+extern_cpp_type!("aos::EventLoop", crate::EventLoop)
+);
+
+/// A Rust-owned C++ `ShmEventLoop` object.
+pub struct ShmEventLoop<'config> {
+ inner: Pin<Box<ffi::aos::ShmEventLoopForRust>>,
+ _config: PhantomData<&'config Configuration>,
+}
+
+impl<'config> ShmEventLoop<'config> {
+ /// Creates a Rust-owned ShmEventLoop.
+ pub fn new(config: &'config impl Flatbuffer<RustConfiguration<'static>>) -> Self {
+ // SAFETY: The `_config` represents the lifetime of this pointer we're handing off to c++ to
+ // store.
+ let event_loop = unsafe {
+ ffi::aos::ShmEventLoopForRust::new(transmute_table_to::<Configuration>(
+ &config.message()._tab,
+ ))
+ }
+ .within_box();
+
+ Self {
+ inner: event_loop,
+ _config: PhantomData,
+ }
+ }
+
+ /// Provides a runtime to construct the application and runs the event loop.
+ ///
+ /// The runtime is the only way to interact with the event loop. It provides the functionality
+ /// to spawn a task, construct timers, watchers, fetchers, and so on.
+ ///
+ /// Making an [`EventLoopRuntime`] is tricky since the lifetime of the runtime is invariant
+ /// w.r.t the event loop. In other words, the runtime and the event loop must have the same
+ /// lifetime. By providing access to the runtime through an [`FnOnce`], we can guarantee
+ /// that the runtime and the event loop both have the same lifetime.
+ ///
+ /// # Examples
+ ///
+ /// A ping application might do something like the following
+ ///
+ /// ```no_run
+ /// # use aos_events_shm_event_loop::*;
+ /// use ping_rust_fbs::aos::examples as ping;
+ /// use pong_rust_fbs::aos::examples as pong;
+ /// use std::cell::Cell;
+ /// use std::path::Path;
+ /// use aos_configuration::read_config_from;
+ /// use aos_events_event_loop_runtime::{Sender, Watcher};
+ ///
+ /// let config = read_config_from(Path::new("path/to/aos_config.json")).unwrap();
+ /// let event_loop = ShmEventLoop::new(&config);
+ /// event_loop.run_with(|runtime| {
+ /// // One task will send a ping, the other will listen to pong messages.
+ /// let mut sender: Sender<ping::Ping> = runtime
+ /// .make_sender("/test")
+ /// .expect("Can't create `Ping` sender");
+ ///
+ /// let on_run = runtime.on_run();
+ /// // Sends a single ping message.
+ /// let send_task = async move {
+ /// on_run.await;
+ /// let mut builder = sender.make_builder();
+ /// let mut ping = ping::PingBuilder::new(builder.fbb());
+ /// ping.add_value(10);
+ /// let ping = ping.finish();
+ /// builder.send(ping).expect("Can't send ping");
+ /// };
+ ///
+ /// let mut watcher: Watcher<pong::Pong> = runtime
+ /// .make_watcher("/test")
+ /// .expect("Can't create `Ping` watcher");
+ ///
+ /// // Listens to pong messages and prints them.
+ /// let receive_task = async move {
+ /// loop {
+ /// let pong = dbg!(watcher.next().await);
+ /// }
+ /// };
+ ///
+ /// runtime.spawn(async move {
+ /// futures::join!(send_task, receive_task);
+ /// std::future::pending().await
+ /// });
+ /// }); // Event loop starts runnning...
+ /// unreachable!("This can't be reached since no ExitHandle was made");
+ /// ```
+ ///
+ /// `run_with` can also borrow data from the outer scope that can be used in the async task.
+ ///
+ /// ```no_run
+ /// # use aos_events_shm_event_loop::*;
+ /// # use std::cell::Cell;
+ /// # use std::path::Path;
+ /// # use aos_configuration::read_config_from;
+ /// let config = read_config_from(Path::new("path/to/aos_config.json")).unwrap();
+ /// let shared_data = Cell::new(971);
+ /// let shared_data = &shared_data;
+ /// let event_loop = ShmEventLoop::new(&config);
+ /// event_loop.run_with(|runtime| {
+ /// // Note how `Cell` is enough since the event loop is single threaded.
+ /// let t1 = async move {
+ /// shared_data.set(shared_data.get() + 1);
+ /// };
+ /// let t2 = async move {
+ /// shared_data.set(shared_data.get() + 1);
+ /// };
+ ///
+ /// runtime.spawn(async move {
+ /// futures::join!(t1, t2);
+ /// std::future::pending().await
+ /// });
+ /// });
+ /// unreachable!("This can't be reached since no ExitHandle was made");
+ /// ```
+ ///
+ /// However, the spawned future must outlive `run_with`.
+ ///
+ /// ```compile_fail
+ /// # use aos_events_shm_event_loop::*;
+ /// # use std::cell::Cell;
+ /// # use std::path::Path;
+ /// # use aos_configuration::read_config_from;
+ /// let config = read_config_from(Path::new("path/to/aos_config.json")).unwrap();
+ /// let event_loop = ShmEventLoop::new(&config);
+ /// event_loop.run_with(|runtime| {
+ /// // ERROR: `shared_data` doesn't live long enough.
+ /// let shared_data = Cell::new(971);
+ /// let t1 = async {
+ /// shared_data.set(shared_data.get() + 1);
+ /// };
+ /// let t2 = async {
+ /// shared_data.set(shared_data.get() + 1);
+ /// };
+ ///
+ /// runtime.spawn(async move {
+ /// futures::join!(t1, t2);
+ /// std::future::pending().await
+ /// });
+ /// });
+ /// ```
+ pub fn run_with<'env, F>(mut self, fun: F)
+ where
+ F: for<'event_loop> FnOnce(&mut Scoped<'event_loop, 'env, EventLoopRuntime<'event_loop>>),
+ {
+ // SAFETY: The runtime and the event loop (i.e. self) both get destroyed at the end of this
+ // scope: first the runtime followed by the event loop. The runtime gets exclusive access
+ // during initialization in `fun` while the event loop remains unused.
+ let runtime = unsafe { EventLoopRuntime::new(self.inner.as_mut().event_loop_mut()) };
+ let mut runtime = Scoped::new(runtime);
+ fun(&mut runtime);
+ self.run();
+ }
+
+ /// Makes an exit handle.
+ ///
+ /// Awaiting on the exit handle is the only way to actually exit the event loop
+ /// task, other than panicking.
+ pub fn make_exit_handle(&mut self) -> ExitHandle {
+ self.inner.as_mut().MakeExitHandle().into()
+ }
+
+ /// Runs the spawned task to completion.
+ fn run(&mut self) {
+ self.inner.as_mut().Run();
+ }
+}
+
+/// A wrapper over some data that lives for the duration of a scope.
+///
+/// This struct ensures the existence of some `'env` which outlives `'scope`. In
+/// the presence of higher-ranked trait bounds which require types that work for
+/// any `'scope`, this allows the compiler to propagate lifetime bounds which
+/// outlive any of the possible `'scope`. This is the simplest way to express
+/// this concept to the compiler right now.
+pub struct Scoped<'scope, 'env: 'scope, T: 'scope> {
+ data: T,
+ _env: PhantomData<fn(&'env ()) -> &'env ()>,
+ _scope: PhantomData<fn(&'scope ()) -> &'scope ()>,
+}
+
+impl<'scope, 'env: 'scope, T: 'scope> Scoped<'scope, 'env, T> {
+ /// Makes the [`Scoped`].
+ pub fn new(data: T) -> Self {
+ Self {
+ data,
+ _env: PhantomData,
+ _scope: PhantomData,
+ }
+ }
+}
+
+impl<'scope, 'env: 'scope, T: 'scope> Deref for Scoped<'scope, 'env, T> {
+ type Target = T;
+ fn deref(&self) -> &Self::Target {
+ &self.data
+ }
+}
+
+impl<'scope, 'env: 'scope, T: 'scope> DerefMut for Scoped<'scope, 'env, T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.data
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ use runfiles::Runfiles;
+
+ use aos_configuration::read_config_from;
+ use aos_events_event_loop_runtime::{Sender, Watcher};
+ use aos_init::test_init;
+ use ping_rust_fbs::aos::examples as ping;
+ use std::sync::atomic::{AtomicUsize, Ordering};
+ use std::sync::Barrier;
+
+ /// Tests basic functionality with 2 threads operating their own event loops.
+ #[test]
+ fn smoke_test() {
+ test_init();
+
+ let r = Runfiles::create().unwrap();
+ let config =
+ read_config_from(&r.rlocation("org_frc971/aos/events/pingpong_config.json")).unwrap();
+
+ const VALUE: i32 = 971;
+ let barrier = Barrier::new(2);
+ let count = AtomicUsize::new(0);
+
+ std::thread::scope(|s| {
+ let config = &config;
+ let barrier = &barrier;
+ let count = &count;
+ s.spawn(move || {
+ let mut event_loop = ShmEventLoop::new(config);
+ let exit_handle = event_loop.make_exit_handle();
+ event_loop.run_with(|runtime| {
+ let mut watcher: Watcher<ping::Ping> = runtime
+ .make_watcher("/test")
+ .expect("Can't create `Ping` watcher");
+ let on_run = runtime.on_run();
+ runtime.spawn(async move {
+ on_run.await;
+ barrier.wait();
+ let ping = watcher.next().await;
+ assert_eq!(ping.message().unwrap().value(), VALUE);
+ count.fetch_add(1, Ordering::Relaxed);
+ exit_handle.exit().await
+ });
+ });
+ });
+ s.spawn(move || {
+ let mut event_loop = ShmEventLoop::new(config);
+ let exit_handle = event_loop.make_exit_handle();
+ event_loop.run_with(|runtime| {
+ let mut sender: Sender<ping::Ping> = runtime
+ .make_sender("/test")
+ .expect("Can't create `Ping` sender");
+ let on_run = runtime.on_run();
+ runtime.spawn(async move {
+ on_run.await;
+ // Give the waiting thread a chance to start.
+ barrier.wait();
+ let mut sender = sender.make_builder();
+ let mut ping = ping::PingBuilder::new(sender.fbb());
+ ping.add_value(VALUE);
+ let ping = ping.finish();
+ sender.send(ping).expect("send should succeed");
+ count.fetch_add(1, Ordering::Relaxed);
+ exit_handle.exit().await
+ });
+ });
+ });
+ });
+
+ assert_eq!(count.into_inner(), 2, "Not all event loops ran.");
+ }
+}
diff --git a/aos/events/shm_event_loop_for_rust.h b/aos/events/shm_event_loop_for_rust.h
new file mode 100644
index 0000000..3a815e1
--- /dev/null
+++ b/aos/events/shm_event_loop_for_rust.h
@@ -0,0 +1,31 @@
+#ifndef AOS_EVENTS_SHM_EVENT_LOOP_FOR_RUST_H_
+#define AOS_EVENTS_SHM_EVENT_LOOP_FOR_RUST_H_
+
+#include <memory>
+
+#include "aos/events/event_loop.h"
+#include "aos/events/shm_event_loop.h"
+
+namespace aos {
+
+class ShmEventLoopForRust {
+ public:
+ ShmEventLoopForRust(const Configuration *configuration)
+ : event_loop_(configuration) {}
+
+ const EventLoop *event_loop() const { return &event_loop_; }
+ EventLoop *event_loop_mut() { return &event_loop_; }
+
+ std::unique_ptr<ExitHandle> MakeExitHandle() {
+ return event_loop_.MakeExitHandle();
+ }
+
+ void Run() { event_loop_.Run(); }
+
+ private:
+ ShmEventLoop event_loop_;
+};
+
+} // namespace aos
+
+#endif // AOS_EVENTS_SHM_EVENT_LOOP_FOR_RUST_H_
diff --git a/frc971/BUILD b/frc971/BUILD
index d6a3af8..5613737 100644
--- a/frc971/BUILD
+++ b/frc971/BUILD
@@ -1,3 +1,5 @@
+load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
+
package(default_visibility = ["//visibility:public"])
cc_library(
@@ -21,3 +23,12 @@
target_compatible_with = ["@platforms//os:linux"],
visibility = ["//visibility:public"],
)
+
+flatbuffer_cc_library(
+ name = "can_configuration_fbs",
+ srcs = [
+ ":can_configuration.fbs",
+ ],
+ gen_reflections = 1,
+ visibility = ["//visibility:public"],
+)
diff --git a/y2023/can_configuration.fbs b/frc971/can_configuration.fbs
similarity index 93%
rename from y2023/can_configuration.fbs
rename to frc971/can_configuration.fbs
index 75e2691..4ce70ab 100644
--- a/y2023/can_configuration.fbs
+++ b/frc971/can_configuration.fbs
@@ -1,4 +1,4 @@
-namespace y2023;
+namespace frc971;
// Message which triggers wpilib_interface to print out the current
// configuration, and optionally re-apply it.
diff --git a/frc971/wpilib/BUILD b/frc971/wpilib/BUILD
index a9d4ebf..33a3cd1 100644
--- a/frc971/wpilib/BUILD
+++ b/frc971/wpilib/BUILD
@@ -506,11 +506,12 @@
target_compatible_with = ["//tools/platforms/hardware:roborio"],
deps = [
"//aos:init",
+ "//aos:math",
"//aos/events:shm_event_loop",
"//aos/logging",
"//frc971/control_loops/drivetrain:drivetrain_can_position_fbs",
"//third_party:phoenix",
- "//third_party:phoenixpro",
+ "//third_party:phoenix6",
"//third_party:wpilib",
"@com_github_google_glog//:glog",
],
diff --git a/frc971/wpilib/can_sensor_reader.cc b/frc971/wpilib/can_sensor_reader.cc
index 5a19e8f..ad244fb 100644
--- a/frc971/wpilib/can_sensor_reader.cc
+++ b/frc971/wpilib/can_sensor_reader.cc
@@ -5,18 +5,19 @@
CANSensorReader::CANSensorReader(
aos::EventLoop *event_loop,
- std::vector<ctre::phoenixpro::BaseStatusSignalValue *> signals_registry,
- std::vector<std::shared_ptr<Falcon>> falcons)
+ std::vector<ctre::phoenix6::BaseStatusSignal *> signals_registry,
+ std::vector<std::shared_ptr<Falcon>> falcons,
+ std::function<void(ctre::phoenix::StatusCode status)> flatbuffer_callback)
: event_loop_(event_loop),
signals_(signals_registry.begin(), signals_registry.end()),
- can_position_sender_(
- event_loop->MakeSender<control_loops::drivetrain::CANPosition>(
- "/drivetrain")),
- falcons_(falcons) {
+ falcons_(falcons),
+ flatbuffer_callback_(flatbuffer_callback) {
event_loop->SetRuntimeRealtimePriority(40);
// TODO(max): Decide if we want to keep this on this core.
event_loop->SetRuntimeAffinity(aos::MakeCpusetFromCpus({1}));
+
+ CHECK(flatbuffer_callback_);
timer_handler_ = event_loop->AddTimer([this]() { Loop(); });
timer_handler_->set_name("CANSensorReader Loop");
@@ -28,37 +29,12 @@
void CANSensorReader::Loop() {
ctre::phoenix::StatusCode status =
- ctre::phoenixpro::BaseStatusSignalValue::WaitForAll(20_ms, signals_);
+ ctre::phoenix6::BaseStatusSignal::WaitForAll(20_ms, signals_);
if (!status.IsOK()) {
AOS_LOG(ERROR, "Failed to read signals from falcons: %s: %s",
status.GetName(), status.GetDescription());
}
- auto builder = can_position_sender_.MakeBuilder();
-
- for (auto falcon : falcons_) {
- falcon->RefreshNontimesyncedSignals();
- falcon->SerializePosition(builder.fbb());
- }
-
- auto falcon_offsets =
- builder.fbb()
- ->CreateVector<flatbuffers::Offset<control_loops::CANFalcon>>(
- falcons_.size(), [this](size_t index) {
- auto offset = falcons_.at(index)->TakeOffset();
- CHECK(offset.has_value());
- return offset.value();
- });
-
- control_loops::drivetrain::CANPosition::Builder can_position_builder =
- builder.MakeBuilder<control_loops::drivetrain::CANPosition>();
-
- can_position_builder.add_falcons(falcon_offsets);
- if (!falcons_.empty()) {
- can_position_builder.add_timestamp(falcons_.at(0)->GetTimestamp());
- }
- can_position_builder.add_status(static_cast<int>(status));
-
- builder.CheckOk(builder.Send(can_position_builder.Finish()));
+ flatbuffer_callback_(status);
}
diff --git a/frc971/wpilib/can_sensor_reader.h b/frc971/wpilib/can_sensor_reader.h
index 2e1a406..764a041 100644
--- a/frc971/wpilib/can_sensor_reader.h
+++ b/frc971/wpilib/can_sensor_reader.h
@@ -15,16 +15,17 @@
public:
CANSensorReader(
aos::EventLoop *event_loop,
- std::vector<ctre::phoenixpro::BaseStatusSignalValue *> signals_registry,
- std::vector<std::shared_ptr<Falcon>> falcons);
+ std::vector<ctre::phoenix6::BaseStatusSignal *> signals_registry,
+ std::vector<std::shared_ptr<Falcon>> falcons,
+ std::function<void(ctre::phoenix::StatusCode status)>
+ flatbuffer_callback);
private:
void Loop();
aos::EventLoop *event_loop_;
- const std::vector<ctre::phoenixpro::BaseStatusSignalValue *> signals_;
- aos::Sender<control_loops::drivetrain::CANPosition> can_position_sender_;
+ const std::vector<ctre::phoenix6::BaseStatusSignal *> signals_;
// This is a vector of falcons becuase we don't need to care
// about falcons individually.
@@ -32,6 +33,9 @@
// Pointer to the timer handler used to modify the wakeup.
::aos::TimerHandler *timer_handler_;
+
+ // Callback used to send the CANPosition flatbuffer
+ std::function<void(ctre::phoenix::StatusCode status)> flatbuffer_callback_;
};
} // namespace wpilib
} // namespace frc971
diff --git a/frc971/wpilib/falcon.cc b/frc971/wpilib/falcon.cc
index 2dee390..6be83aa 100644
--- a/frc971/wpilib/falcon.cc
+++ b/frc971/wpilib/falcon.cc
@@ -1,9 +1,10 @@
#include "frc971/wpilib/falcon.h"
using frc971::wpilib::Falcon;
+using frc971::wpilib::kMaxBringupPower;
Falcon::Falcon(int device_id, std::string canbus,
- std::vector<ctre::phoenixpro::BaseStatusSignalValue *> *signals,
+ std::vector<ctre::phoenix6::BaseStatusSignal *> *signals,
double stator_current_limit, double supply_current_limit)
: talon_(device_id, canbus),
device_id_(device_id),
@@ -37,7 +38,7 @@
}
void Falcon::PrintConfigs() {
- ctre::phoenixpro::configs::TalonFXConfiguration configuration;
+ ctre::phoenix6::configs::TalonFXConfiguration configuration;
ctre::phoenix::StatusCode status =
talon_.GetConfigurator().Refresh(configuration);
if (!status.IsOK()) {
@@ -47,23 +48,22 @@
AOS_LOG(INFO, "configuration: %s", configuration.ToString().c_str());
}
-void Falcon::WriteConfigs(ctre::phoenixpro::signals::InvertedValue invert) {
+void Falcon::WriteConfigs(ctre::phoenix6::signals::InvertedValue invert) {
inverted_ = invert;
- ctre::phoenixpro::configs::CurrentLimitsConfigs current_limits;
+ ctre::phoenix6::configs::CurrentLimitsConfigs current_limits;
current_limits.StatorCurrentLimit = stator_current_limit_;
current_limits.StatorCurrentLimitEnable = true;
current_limits.SupplyCurrentLimit = supply_current_limit_;
current_limits.SupplyCurrentLimitEnable = true;
- ctre::phoenixpro::configs::MotorOutputConfigs output_configs;
- output_configs.NeutralMode =
- ctre::phoenixpro::signals::NeutralModeValue::Brake;
+ ctre::phoenix6::configs::MotorOutputConfigs output_configs;
+ output_configs.NeutralMode = ctre::phoenix6::signals::NeutralModeValue::Brake;
output_configs.DutyCycleNeutralDeadband = 0;
output_configs.Inverted = inverted_;
- ctre::phoenixpro::configs::TalonFXConfiguration configuration;
+ ctre::phoenix6::configs::TalonFXConfiguration configuration;
configuration.CurrentLimits = current_limits;
configuration.MotorOutput = output_configs;
@@ -77,6 +77,23 @@
PrintConfigs();
}
+ctre::phoenix::StatusCode Falcon::WriteCurrent(double current,
+ double max_voltage) {
+ ctre::phoenix6::controls::TorqueCurrentFOC control(
+ static_cast<units::current::ampere_t>(current));
+ // Using 0_Hz here makes it a one-shot update.
+ control.UpdateFreqHz = 0_Hz;
+ control.MaxAbsDutyCycle =
+ ::aos::Clip(max_voltage, -kMaxBringupPower, kMaxBringupPower) / 12.0;
+ ctre::phoenix::StatusCode status = talon()->SetControl(control);
+ if (!status.IsOK()) {
+ AOS_LOG(ERROR, "Failed to write control to falcon %d: %s: %s", device_id(),
+ status.GetName(), status.GetDescription());
+ }
+
+ return status;
+}
+
void Falcon::SerializePosition(flatbuffers::FlatBufferBuilder *fbb) {
control_loops::CANFalcon::Builder builder(*fbb);
builder.add_id(device_id_);
diff --git a/frc971/wpilib/falcon.h b/frc971/wpilib/falcon.h
index 7137d82..8f0f1f0 100644
--- a/frc971/wpilib/falcon.h
+++ b/frc971/wpilib/falcon.h
@@ -5,9 +5,10 @@
#include <cinttypes>
#include <vector>
-#include "ctre/phoenixpro/TalonFX.hpp"
+#include "ctre/phoenix6/TalonFX.hpp"
#include "glog/logging.h"
+#include "aos/commonmath.h"
#include "aos/init.h"
#include "aos/logging/logging.h"
#include "frc971/control_loops/drivetrain/drivetrain_can_position_generated.h"
@@ -18,19 +19,21 @@
namespace wpilib {
static constexpr units::frequency::hertz_t kCANUpdateFreqHz = 200_Hz;
+static constexpr double kMaxBringupPower = 12.0;
// Gets info from and writes to falcon motors using the TalonFX controller.
class Falcon {
public:
Falcon(int device_id, std::string canbus,
- std::vector<ctre::phoenixpro::BaseStatusSignalValue *> *signals,
+ std::vector<ctre::phoenix6::BaseStatusSignal *> *signals,
double stator_current_limit, double supply_current_limit);
void PrintConfigs();
- void WriteConfigs(ctre::phoenixpro::signals::InvertedValue invert);
+ void WriteConfigs(ctre::phoenix6::signals::InvertedValue invert);
+ ctre::phoenix::StatusCode WriteCurrent(double current, double max_voltage);
- ctre::phoenixpro::hardware::TalonFX *talon() { return &talon_; }
+ ctre::phoenix6::hardware::TalonFX *talon() { return &talon_; }
void SerializePosition(flatbuffers::FlatBufferBuilder *fbb);
@@ -66,19 +69,17 @@
}
private:
- ctre::phoenixpro::hardware::TalonFX talon_;
+ ctre::phoenix6::hardware::TalonFX talon_;
int device_id_;
- ctre::phoenixpro::signals::InvertedValue inverted_;
+ ctre::phoenix6::signals::InvertedValue inverted_;
- ctre::phoenixpro::StatusSignalValue<units::temperature::celsius_t>
- device_temp_;
- ctre::phoenixpro::StatusSignalValue<units::voltage::volt_t> supply_voltage_;
- ctre::phoenixpro::StatusSignalValue<units::current::ampere_t> supply_current_,
+ ctre::phoenix6::StatusSignal<units::temperature::celsius_t> device_temp_;
+ ctre::phoenix6::StatusSignal<units::voltage::volt_t> supply_voltage_;
+ ctre::phoenix6::StatusSignal<units::current::ampere_t> supply_current_,
torque_current_;
- ctre::phoenixpro::StatusSignalValue<units::angle::turn_t> position_;
- ctre::phoenixpro::StatusSignalValue<units::dimensionless::scalar_t>
- duty_cycle_;
+ ctre::phoenix6::StatusSignal<units::angle::turn_t> position_;
+ ctre::phoenix6::StatusSignal<units::dimensionless::scalar_t> duty_cycle_;
double stator_current_limit_;
double supply_current_limit_;
diff --git a/frc971/wpilib/swerve/BUILD b/frc971/wpilib/swerve/BUILD
new file mode 100644
index 0000000..9f559f6
--- /dev/null
+++ b/frc971/wpilib/swerve/BUILD
@@ -0,0 +1,30 @@
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+ name = "swerve_drivetrain_writer",
+ srcs = [
+ "swerve_drivetrain_writer.cc",
+ ],
+ hdrs = [
+ "swerve_drivetrain_writer.h",
+ ],
+ deps = [
+ ":swerve_module",
+ "//aos/logging",
+ "//frc971:can_configuration_fbs",
+ "//frc971/control_loops/drivetrain/swerve:swerve_drivetrain_output_fbs",
+ "//frc971/wpilib:falcon",
+ "//frc971/wpilib:loop_output_handler",
+ "//third_party:phoenix6",
+ ],
+)
+
+cc_library(
+ name = "swerve_module",
+ hdrs = [
+ "swerve_module.h",
+ ],
+ deps = [
+ "//frc971/wpilib:falcon",
+ ],
+)
diff --git a/frc971/wpilib/swerve/swerve_drivetrain_writer.cc b/frc971/wpilib/swerve/swerve_drivetrain_writer.cc
new file mode 100644
index 0000000..2b6ef9e
--- /dev/null
+++ b/frc971/wpilib/swerve/swerve_drivetrain_writer.cc
@@ -0,0 +1,60 @@
+#include "frc971/wpilib/swerve/swerve_drivetrain_writer.h"
+
+using frc971::wpilib::swerve::DrivetrainWriter;
+
+DrivetrainWriter::DrivetrainWriter(::aos::EventLoop *event_loop,
+ int drivetrain_writer_priority,
+ double max_voltage)
+ : ::frc971::wpilib::LoopOutputHandler<
+ ::frc971::control_loops::drivetrain::swerve::Output>(event_loop,
+ "/drivetrain"),
+ max_voltage_(max_voltage) {
+ event_loop->SetRuntimeRealtimePriority(drivetrain_writer_priority);
+
+ event_loop->OnRun([this]() { WriteConfigs(); });
+}
+
+void DrivetrainWriter::set_falcons(std::shared_ptr<SwerveModule> front_left,
+ std::shared_ptr<SwerveModule> front_right,
+ std::shared_ptr<SwerveModule> back_left,
+ std::shared_ptr<SwerveModule> back_right) {
+ front_left_ = std::move(front_left);
+ front_right_ = std::move(front_right);
+ back_left_ = std::move(back_left);
+ back_right_ = std::move(back_right);
+}
+
+void DrivetrainWriter::HandleCANConfiguration(
+ const CANConfiguration &configuration) {
+ for (auto module : {front_left_, front_right_, back_left_, back_right_}) {
+ module->rotation->PrintConfigs();
+ module->translation->PrintConfigs();
+ }
+ if (configuration.reapply()) {
+ WriteConfigs();
+ }
+}
+
+void DrivetrainWriter::WriteConfigs() {
+ for (auto module : {front_left_, front_right_, back_left_, back_right_}) {
+ module->rotation->WriteConfigs(false);
+ module->translation->WriteConfigs(false);
+ }
+}
+
+void DrivetrainWriter::Write(
+ const ::frc971::control_loops::drivetrain::swerve::Output &output) {
+ front_left_->WriteModule(output.front_left_output(), max_voltage_);
+ front_right_->WriteModule(output.front_right_output(), max_voltage_);
+ back_left_->WriteModule(output.back_left_output(), max_voltage_);
+ back_right_->WriteModule(output.back_right_output(), max_voltage_);
+}
+
+void DrivetrainWriter::Stop() {
+ AOS_LOG(WARNING, "drivetrain output too old\n");
+
+ for (auto module : {front_left_, front_right_, back_left_, back_right_}) {
+ module->rotation->WriteCurrent(0, 0);
+ module->translation->WriteCurrent(0, 0);
+ }
+}
diff --git a/frc971/wpilib/swerve/swerve_drivetrain_writer.h b/frc971/wpilib/swerve/swerve_drivetrain_writer.h
new file mode 100644
index 0000000..4bd6639
--- /dev/null
+++ b/frc971/wpilib/swerve/swerve_drivetrain_writer.h
@@ -0,0 +1,52 @@
+#ifndef FRC971_WPILIB_SWERVE_DRIVETRAIN_WRITER_H_
+#define FRC971_WPILIB_SWERVE_DRIVETRAIN_WRITER_H_
+
+#include "ctre/phoenix6/TalonFX.hpp"
+
+#include "frc971/can_configuration_generated.h"
+#include "frc971/control_loops/drivetrain/swerve/swerve_drivetrain_output_generated.h"
+#include "frc971/wpilib/falcon.h"
+#include "frc971/wpilib/loop_output_handler.h"
+#include "frc971/wpilib/swerve/swerve_module.h"
+
+namespace frc971 {
+namespace wpilib {
+namespace swerve {
+
+// Reads from the swerve output flatbuffer and uses wpilib to set the current
+// for each motor.
+class DrivetrainWriter
+ : public ::frc971::wpilib::LoopOutputHandler<
+ ::frc971::control_loops::drivetrain::swerve::Output> {
+ public:
+ DrivetrainWriter(::aos::EventLoop *event_loop, int drivetrain_writer_priority,
+ double max_voltage);
+
+ void set_falcons(std::shared_ptr<SwerveModule> front_left,
+ std::shared_ptr<SwerveModule> front_right,
+ std::shared_ptr<SwerveModule> back_left,
+ std::shared_ptr<SwerveModule> back_right);
+
+ void HandleCANConfiguration(const CANConfiguration &configuration);
+
+ private:
+ void WriteConfigs();
+
+ void Write(const ::frc971::control_loops::drivetrain::swerve::Output &output)
+ override;
+
+ void Stop() override;
+
+ double SafeSpeed(double voltage);
+
+ std::shared_ptr<SwerveModule> front_left_, front_right_, back_left_,
+ back_right_;
+
+ double max_voltage_;
+};
+
+} // namespace swerve
+} // namespace wpilib
+} // namespace frc971
+
+#endif // FRC971_WPILIB_SWERVE_DRIVETRAIN_WRITER_H_
diff --git a/frc971/wpilib/swerve/swerve_module.h b/frc971/wpilib/swerve/swerve_module.h
new file mode 100644
index 0000000..534f0ce
--- /dev/null
+++ b/frc971/wpilib/swerve/swerve_module.h
@@ -0,0 +1,44 @@
+#ifndef FRC971_WPILIB_SWERVE_SWERVE_MODULE_H_
+#define FRC971_WPILIB_SWERVE_SWERVE_MODULE_H_
+
+#include "frc971/wpilib/falcon.h"
+
+namespace frc971 {
+namespace wpilib {
+namespace swerve {
+
+struct SwerveModule {
+ SwerveModule(int rotation_id, int translation_id, std::string canbus,
+ std::vector<ctre::phoenix6::BaseStatusSignal *> *signals,
+ double stator_current_limit, double supply_current_limit)
+ : rotation(std::make_shared<Falcon>(rotation_id, canbus, signals,
+ stator_current_limit,
+ supply_current_limit)),
+ translation(std::make_shared<Falcon>(translation_id, canbus, signals,
+ stator_current_limit,
+ supply_current_limit)) {}
+
+ void WriteModule(
+ const frc971::control_loops::drivetrain::swerve::SwerveModuleOutput
+ *module_output,
+ double max_voltage) {
+ double rotation_current = 0.0;
+ double translation_current = 0.0;
+
+ if (module_output != nullptr) {
+ rotation_current = module_output->rotation_current();
+ translation_current = module_output->translation_current();
+ }
+
+ rotation->WriteCurrent(rotation_current, max_voltage);
+ translation->WriteCurrent(translation_current, max_voltage);
+ }
+
+ std::shared_ptr<Falcon> rotation;
+ std::shared_ptr<Falcon> translation;
+};
+
+} // namespace swerve
+} // namespace wpilib
+} // namespace frc971
+#endif // FRC971_WPILIB_SWERVE_SWERVE_MODULE_H_
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/rustfmt.toml
diff --git a/scouting/BUILD b/scouting/BUILD
index d6c09b2..b7e50fa 100644
--- a/scouting/BUILD
+++ b/scouting/BUILD
@@ -19,6 +19,11 @@
],
)
+# TODO(philipp): Sandbox the following:
+# - libnss3
+# - libdrm2
+# - libgbm1
+# - x11-xkb-utils (See TODO in scouting/scouting_test_runner.js)
cypress_test(
name = "scouting_test",
data = [
diff --git a/scouting/scouting_test_runner.js b/scouting/scouting_test_runner.js
index 3106ee7..c2ef027 100644
--- a/scouting/scouting_test_runner.js
+++ b/scouting/scouting_test_runner.js
@@ -4,9 +4,13 @@
const cypress = require('cypress');
// Set up the xvfb binary.
-process.env[
- 'PATH'
-] = `${process.env.RUNFILES_DIR}/xvfb_amd64/wrapped_bin:${process.env.PATH}`;
+// TODO(philipp): Figure out how to point Xvfb at the sandboxed usr/bin
+// directory. Currently impossible as it's hardcoded to use /usr/bin.
+process.env['PATH'] = [
+ `${process.env.RUNFILES_DIR}/xvfb_amd64/wrapped_bin`,
+ `${process.env.RUNFILES_DIR}/xvfb_amd64/usr/bin`,
+ process.env.PATH,
+].join(':');
// Start the web server, database, and fake TBA server.
// We use file descriptor 3 ('pipe') for the test server to let us know when
diff --git a/third_party/BUILD b/third_party/BUILD
index 53b5d24..7195123 100644
--- a/third_party/BUILD
+++ b/third_party/BUILD
@@ -31,17 +31,17 @@
target_compatible_with = ["//tools/platforms/hardware:roborio"],
visibility = ["//visibility:public"],
deps = [
+ "@ctre_phoenix6_tools_athena//:tools",
+ "@ctre_phoenix6_tools_headers//:tools",
"@ctre_phoenix_api_cpp_athena//:api-cpp",
"@ctre_phoenix_api_cpp_headers//:api-cpp",
"@ctre_phoenix_cci_athena//:cci",
"@ctre_phoenix_cci_headers//:cci",
- "@ctre_phoenixpro_tools_athena//:tools",
- "@ctre_phoenixpro_tools_headers//:tools",
],
)
cc_library(
- name = "phoenixpro",
+ name = "phoenix6",
linkopts = [
"-Wl,-rpath",
"-Wl,.",
@@ -49,10 +49,10 @@
target_compatible_with = ["//tools/platforms/hardware:roborio"],
visibility = ["//visibility:public"],
deps = [
- "@ctre_phoenixpro_api_cpp_athena//:api-cpp",
- "@ctre_phoenixpro_api_cpp_headers//:api-cpp",
- "@ctre_phoenixpro_tools_athena//:tools",
- "@ctre_phoenixpro_tools_headers//:tools",
+ "@ctre_phoenix6_api_cpp_athena//:api-cpp",
+ "@ctre_phoenix6_api_cpp_headers//:api-cpp",
+ "@ctre_phoenix6_tools_athena//:tools",
+ "@ctre_phoenix6_tools_headers//:tools",
],
)
diff --git a/y2022/BUILD b/y2022/BUILD
index f8bf59f..f25925e 100644
--- a/y2022/BUILD
+++ b/y2022/BUILD
@@ -18,10 +18,10 @@
data = [
":aos_config",
":message_bridge_client.sh",
+ "@ctre_phoenix6_api_cpp_athena//:shared_libraries",
+ "@ctre_phoenix6_tools_athena//:shared_libraries",
"@ctre_phoenix_api_cpp_athena//:shared_libraries",
"@ctre_phoenix_cci_athena//:shared_libraries",
- "@ctre_phoenixpro_api_cpp_athena//:shared_libraries",
- "@ctre_phoenixpro_tools_athena//:shared_libraries",
],
dirs = [
"//y2022/actors:splines",
@@ -270,7 +270,7 @@
"//frc971/wpilib:wpilib_interface",
"//frc971/wpilib:wpilib_robot_base",
"//third_party:phoenix",
- "//third_party:phoenixpro",
+ "//third_party:phoenix6",
"//third_party:wpilib",
"//y2022/control_loops/superstructure:led_indicator_lib",
"//y2022/control_loops/superstructure:superstructure_can_position_fbs",
diff --git a/y2022_bot3/BUILD b/y2022_bot3/BUILD
index e7146ce..29debe7 100644
--- a/y2022_bot3/BUILD
+++ b/y2022_bot3/BUILD
@@ -8,8 +8,8 @@
],
data = [
":aos_config",
- "@ctre_phoenixpro_api_cpp_athena//:shared_libraries",
- "@ctre_phoenixpro_tools_athena//:shared_libraries",
+ "@ctre_phoenix6_api_cpp_athena//:shared_libraries",
+ "@ctre_phoenix6_tools_athena//:shared_libraries",
],
dirs = [
"//y2022_bot3/actors:splines",
diff --git a/y2023/BUILD b/y2023/BUILD
index ed8f347..e200f87 100644
--- a/y2023/BUILD
+++ b/y2023/BUILD
@@ -1,7 +1,6 @@
load("//frc971:downloader.bzl", "robot_downloader")
load("//aos:config.bzl", "aos_config")
load("//tools/build_rules:template.bzl", "jinja2_template")
-load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
load("//aos/util:config_validator_macro.bzl", "config_validator_test")
config_validator_test(
@@ -21,10 +20,10 @@
"//aos/starter:roborio_irq_config.json",
"//y2023/constants:constants.json",
"//y2023/control_loops/superstructure/arm:arm_trajectories_generated.bfbs",
+ "@ctre_phoenix6_api_cpp_athena//:shared_libraries",
+ "@ctre_phoenix6_tools_athena//:shared_libraries",
"@ctre_phoenix_api_cpp_athena//:shared_libraries",
"@ctre_phoenix_cci_athena//:shared_libraries",
- "@ctre_phoenixpro_api_cpp_athena//:shared_libraries",
- "@ctre_phoenixpro_tools_athena//:shared_libraries",
],
dirs = [
"//y2023/www:www_files",
@@ -203,7 +202,7 @@
name = "config_roborio",
src = "y2023_roborio.json",
flatbuffers = [
- ":can_configuration_fbs",
+ "//frc971:can_configuration_fbs",
"//aos/network:remote_message_fbs",
"//aos/network:message_bridge_client_fbs",
"//aos/network:message_bridge_server_fbs",
@@ -271,7 +270,6 @@
],
target_compatible_with = ["//tools/platforms/hardware:roborio"],
deps = [
- ":can_configuration_fbs",
":constants",
"//aos:init",
"//aos:math",
@@ -283,6 +281,7 @@
"//aos/util:log_interval",
"//aos/util:phased_loop",
"//aos/util:wrapping_counter",
+ "//frc971:can_configuration_fbs",
"//frc971/autonomous:auto_mode_fbs",
"//frc971/control_loops:control_loop",
"//frc971/control_loops:control_loops_fbs",
@@ -303,7 +302,7 @@
"//frc971/wpilib:wpilib_interface",
"//frc971/wpilib:wpilib_robot_base",
"//third_party:phoenix",
- "//third_party:phoenixpro",
+ "//third_party:phoenix6",
"//third_party:wpilib",
"//y2023/control_loops/superstructure:led_indicator_lib",
"//y2023/control_loops/superstructure:superstructure_output_fbs",
@@ -384,12 +383,3 @@
"@com_github_google_glog//:glog",
],
)
-
-flatbuffer_cc_library(
- name = "can_configuration_fbs",
- srcs = [
- ":can_configuration.fbs",
- ],
- gen_reflections = 1,
- visibility = ["//visibility:public"],
-)
diff --git a/y2023/wpilib_interface.cc b/y2023/wpilib_interface.cc
index d043e6f..abf11da 100644
--- a/y2023/wpilib_interface.cc
+++ b/y2023/wpilib_interface.cc
@@ -26,7 +26,7 @@
#include "ctre/phoenix/cci/Diagnostics_CCI.h"
#include "ctre/phoenix/motorcontrol/can/TalonFX.h"
#include "ctre/phoenix/motorcontrol/can/TalonSRX.h"
-#include "ctre/phoenixpro/TalonFX.hpp"
+#include "ctre/phoenix6/TalonFX.hpp"
#include "aos/commonmath.h"
#include "aos/containers/sized_array.h"
@@ -40,6 +40,7 @@
#include "aos/util/phased_loop.h"
#include "aos/util/wrapping_counter.h"
#include "frc971/autonomous/auto_mode_generated.h"
+#include "frc971/can_configuration_generated.h"
#include "frc971/control_loops/drivetrain/drivetrain_can_position_generated.h"
#include "frc971/control_loops/drivetrain/drivetrain_position_generated.h"
#include "frc971/input/robot_state_generated.h"
@@ -56,7 +57,6 @@
#include "frc971/wpilib/pdp_fetcher.h"
#include "frc971/wpilib/sensor_reader.h"
#include "frc971/wpilib/wpilib_robot_base.h"
-#include "y2023/can_configuration_generated.h"
#include "y2023/constants.h"
#include "y2023/control_loops/superstructure/led_indicator.h"
#include "y2023/control_loops/superstructure/superstructure_output_generated.h"
@@ -67,6 +67,7 @@
"devices on the CAN bus using Phoenix Tuner");
using ::aos::monotonic_clock;
+using ::frc971::CANConfiguration;
using ::y2023::constants::Values;
namespace superstructure = ::y2023::control_loops::superstructure;
namespace drivetrain = ::y2023::control_loops::drivetrain;
@@ -121,7 +122,7 @@
class Falcon {
public:
Falcon(int device_id, std::string canbus,
- std::vector<ctre::phoenixpro::BaseStatusSignalValue *> *signals)
+ std::vector<ctre::phoenix6::BaseStatusSignal *> *signals)
: talon_(device_id, canbus),
device_id_(device_id),
device_temp_(talon_.GetDeviceTemp()),
@@ -152,7 +153,7 @@
}
void PrintConfigs() {
- ctre::phoenixpro::configs::TalonFXConfiguration configuration;
+ ctre::phoenix6::configs::TalonFXConfiguration configuration;
ctre::phoenix::StatusCode status =
talon_.GetConfigurator().Refresh(configuration);
if (!status.IsOK()) {
@@ -162,10 +163,10 @@
AOS_LOG(INFO, "configuration: %s", configuration.ToString().c_str());
}
- void WriteConfigs(ctre::phoenixpro::signals::InvertedValue invert) {
+ void WriteConfigs(ctre::phoenix6::signals::InvertedValue invert) {
inverted_ = invert;
- ctre::phoenixpro::configs::CurrentLimitsConfigs current_limits;
+ ctre::phoenix6::configs::CurrentLimitsConfigs current_limits;
current_limits.StatorCurrentLimit =
constants::Values::kDrivetrainStatorCurrentLimit();
current_limits.StatorCurrentLimitEnable = true;
@@ -173,14 +174,14 @@
constants::Values::kDrivetrainSupplyCurrentLimit();
current_limits.SupplyCurrentLimitEnable = true;
- ctre::phoenixpro::configs::MotorOutputConfigs output_configs;
+ ctre::phoenix6::configs::MotorOutputConfigs output_configs;
output_configs.NeutralMode =
- ctre::phoenixpro::signals::NeutralModeValue::Brake;
+ ctre::phoenix6::signals::NeutralModeValue::Brake;
output_configs.DutyCycleNeutralDeadband = 0;
output_configs.Inverted = inverted_;
- ctre::phoenixpro::configs::TalonFXConfiguration configuration;
+ ctre::phoenix6::configs::TalonFXConfiguration configuration;
configuration.CurrentLimits = current_limits;
configuration.MotorOutput = output_configs;
@@ -195,7 +196,7 @@
}
void WriteRollerConfigs() {
- ctre::phoenixpro::configs::CurrentLimitsConfigs current_limits;
+ ctre::phoenix6::configs::CurrentLimitsConfigs current_limits;
current_limits.StatorCurrentLimit =
constants::Values::kRollerStatorCurrentLimit();
current_limits.StatorCurrentLimitEnable = true;
@@ -203,12 +204,12 @@
constants::Values::kRollerSupplyCurrentLimit();
current_limits.SupplyCurrentLimitEnable = true;
- ctre::phoenixpro::configs::MotorOutputConfigs output_configs;
+ ctre::phoenix6::configs::MotorOutputConfigs output_configs;
output_configs.NeutralMode =
- ctre::phoenixpro::signals::NeutralModeValue::Brake;
+ ctre::phoenix6::signals::NeutralModeValue::Brake;
output_configs.DutyCycleNeutralDeadband = 0;
- ctre::phoenixpro::configs::TalonFXConfiguration configuration;
+ ctre::phoenix6::configs::TalonFXConfiguration configuration;
configuration.CurrentLimits = current_limits;
configuration.MotorOutput = output_configs;
@@ -222,7 +223,7 @@
PrintConfigs();
}
- ctre::phoenixpro::hardware::TalonFX *talon() { return &talon_; }
+ ctre::phoenix6::hardware::TalonFX *talon() { return &talon_; }
flatbuffers::Offset<frc971::control_loops::CANFalcon> WritePosition(
flatbuffers::FlatBufferBuilder *fbb) {
@@ -235,8 +236,7 @@
builder.add_duty_cycle(duty_cycle());
double invert =
- (inverted_ ==
- ctre::phoenixpro::signals::InvertedValue::Clockwise_Positive
+ (inverted_ == ctre::phoenix6::signals::InvertedValue::Clockwise_Positive
? 1
: -1);
@@ -266,26 +266,24 @@
void RefreshNontimesyncedSignals() { device_temp_.Refresh(); };
private:
- ctre::phoenixpro::hardware::TalonFX talon_;
+ ctre::phoenix6::hardware::TalonFX talon_;
int device_id_;
- ctre::phoenixpro::signals::InvertedValue inverted_;
+ ctre::phoenix6::signals::InvertedValue inverted_;
- ctre::phoenixpro::StatusSignalValue<units::temperature::celsius_t>
- device_temp_;
- ctre::phoenixpro::StatusSignalValue<units::voltage::volt_t> supply_voltage_;
- ctre::phoenixpro::StatusSignalValue<units::current::ampere_t> supply_current_,
+ ctre::phoenix6::StatusSignal<units::temperature::celsius_t> device_temp_;
+ ctre::phoenix6::StatusSignal<units::voltage::volt_t> supply_voltage_;
+ ctre::phoenix6::StatusSignal<units::current::ampere_t> supply_current_,
torque_current_;
- ctre::phoenixpro::StatusSignalValue<units::angle::turn_t> position_;
- ctre::phoenixpro::StatusSignalValue<units::dimensionless::scalar_t>
- duty_cycle_;
+ ctre::phoenix6::StatusSignal<units::angle::turn_t> position_;
+ ctre::phoenix6::StatusSignal<units::dimensionless::scalar_t> duty_cycle_;
};
class CANSensorReader {
public:
CANSensorReader(
aos::EventLoop *event_loop,
- std::vector<ctre::phoenixpro::BaseStatusSignalValue *> signals_registry)
+ std::vector<ctre::phoenix6::BaseStatusSignal *> signals_registry)
: event_loop_(event_loop),
signals_(signals_registry.begin(), signals_registry.end()),
can_position_sender_(
@@ -328,7 +326,7 @@
private:
void Loop() {
ctre::phoenix::StatusCode status =
- ctre::phoenixpro::BaseStatusSignalValue::WaitForAll(2000_ms, signals_);
+ ctre::phoenix6::BaseStatusSignal::WaitForAll(2000_ms, signals_);
if (!status.IsOK()) {
AOS_LOG(ERROR, "Failed to read signals from falcons: %s: %s",
@@ -384,7 +382,7 @@
aos::EventLoop *event_loop_;
- const std::vector<ctre::phoenixpro::BaseStatusSignalValue *> signals_;
+ const std::vector<ctre::phoenix6::BaseStatusSignal *> signals_;
aos::Sender<frc971::control_loops::drivetrain::CANPosition>
can_position_sender_;
@@ -761,7 +759,7 @@
void WriteConfigs() { roller_falcon_->WriteRollerConfigs(); }
void Write(const superstructure::Output &output) override {
- ctre::phoenixpro::controls::DutyCycleOut roller_control(
+ ctre::phoenix6::controls::DutyCycleOut roller_control(
SafeSpeed(-output.roller_voltage()));
roller_control.UpdateFreqHz = 0_Hz;
roller_control.EnableFOC = true;
@@ -777,7 +775,7 @@
void Stop() override {
AOS_LOG(WARNING, "Superstructure CAN output too old.\n");
- ctre::phoenixpro::controls::DutyCycleOut stop_command(0.0);
+ ctre::phoenix6::controls::DutyCycleOut stop_command(0.0);
stop_command.UpdateFreqHz = 0_Hz;
stop_command.EnableFOC = true;
@@ -818,11 +816,11 @@
left_under_ = std::move(left_under);
}
- void set_right_inverted(ctre::phoenixpro::signals::InvertedValue invert) {
+ void set_right_inverted(ctre::phoenix6::signals::InvertedValue invert) {
right_inverted_ = invert;
}
- void set_left_inverted(ctre::phoenixpro::signals::InvertedValue invert) {
+ void set_left_inverted(ctre::phoenix6::signals::InvertedValue invert) {
left_inverted_ = invert;
}
@@ -851,12 +849,12 @@
void Write(
const ::frc971::control_loops::drivetrain::Output &output) override {
- ctre::phoenixpro::controls::DutyCycleOut left_control(
+ ctre::phoenix6::controls::DutyCycleOut left_control(
SafeSpeed(output.left_voltage()));
left_control.UpdateFreqHz = 0_Hz;
left_control.EnableFOC = true;
- ctre::phoenixpro::controls::DutyCycleOut right_control(
+ ctre::phoenix6::controls::DutyCycleOut right_control(
SafeSpeed(output.right_voltage()));
right_control.UpdateFreqHz = 0_Hz;
right_control.EnableFOC = true;
@@ -886,7 +884,7 @@
void Stop() override {
AOS_LOG(WARNING, "drivetrain output too old\n");
- ctre::phoenixpro::controls::DutyCycleOut stop_command(0.0);
+ ctre::phoenix6::controls::DutyCycleOut stop_command(0.0);
stop_command.UpdateFreqHz = 0_Hz;
stop_command.EnableFOC = true;
@@ -901,7 +899,7 @@
return (::aos::Clip(voltage, -kMaxBringupPower, kMaxBringupPower) / 12.0);
}
- ctre::phoenixpro::signals::InvertedValue left_inverted_, right_inverted_;
+ ctre::phoenix6::signals::InvertedValue left_inverted_, right_inverted_;
std::shared_ptr<Falcon> right_front_, right_back_, right_under_, left_front_,
left_back_, left_under_;
};
@@ -934,7 +932,7 @@
std::shared_ptr<frc::DigitalOutput> superstructure_reading =
make_unique<frc::DigitalOutput>(25);
- std::vector<ctre::phoenixpro::BaseStatusSignalValue *> signals_registry;
+ std::vector<ctre::phoenix6::BaseStatusSignal *> signals_registry;
std::shared_ptr<Falcon> right_front =
std::make_shared<Falcon>(1, "Drivetrain Bus", &signals_registry);
std::shared_ptr<Falcon> right_back =
@@ -1013,9 +1011,9 @@
drivetrain_writer.set_falcons(right_front, right_back, right_under,
left_front, left_back, left_under);
drivetrain_writer.set_right_inverted(
- ctre::phoenixpro::signals::InvertedValue::Clockwise_Positive);
+ ctre::phoenix6::signals::InvertedValue::Clockwise_Positive);
drivetrain_writer.set_left_inverted(
- ctre::phoenixpro::signals::InvertedValue::CounterClockwise_Positive);
+ ctre::phoenix6::signals::InvertedValue::CounterClockwise_Positive);
SuperstructureCANWriter superstructure_can_writer(&can_output_event_loop);
superstructure_can_writer.set_roller_falcon(roller);
diff --git a/y2023/y2023_roborio.json b/y2023/y2023_roborio.json
index 33d9904..c1e42e6 100644
--- a/y2023/y2023_roborio.json
+++ b/y2023/y2023_roborio.json
@@ -300,7 +300,7 @@
},
{
"name": "/roborio",
- "type": "y2023.CANConfiguration",
+ "type": "frc971.CANConfiguration",
"source_node": "roborio",
"frequency": 2
},