Merge changes I631ff230,Ic97f5f67
* changes:
Add a driver for the new IMU
Fix bounds of SPI AutoRead sizes
diff --git a/WORKSPACE b/WORKSPACE
index 5f29700..d0d6347 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -50,6 +50,10 @@
"//debian:python_gtk.bzl",
python_gtk_debs = "files",
)
+load(
+ "//debian:opencv_armhf.bzl",
+ opencv_armhf_debs = "files",
+)
load("//debian:packages.bzl", "generate_repositories_for_debs")
generate_repositories_for_debs(python_debs)
@@ -76,6 +80,8 @@
generate_repositories_for_debs(python_gtk_debs)
+generate_repositories_for_debs(opencv_armhf_debs)
+
http_archive(
name = "python_repo",
build_file = "@//debian:python.BUILD",
@@ -144,6 +150,17 @@
url = "http://frc971.org/Build-Dependencies/gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabihf.tar.xz",
)
+# The main partition from https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-09-30/2019-09-26-raspbian-buster-lite.zip.
+# The following folders are removed to make bazel happy with it:
+# usr/share/ca-certificates
+# This copy command to make clang happy: `cp usr/lib/arm-linux-gnueabihf/*.o usr/lib`
+http_archive(
+ name = "armhf_debian_rootfs",
+ build_file = "@//:compilers/armhf_debian_rootfs.BUILD",
+ sha256 = "8c827bdb79615046ee3e13e85664e5d01286ca1721f7169341667a634e599eb6",
+ url = "http://frc971.org/Build-Dependencies/2019-09-26-raspbian-buster-lite_rootfs.tar.bz2",
+)
+
new_git_repository(
name = "python_gflags_repo",
build_file = "@//debian:gflags.BUILD",
@@ -560,3 +577,11 @@
sha256 = "91c98edee0c90a19992792c711dde4a6743af2d6d7e45b5079ec228fdf51ff11",
urls = ["http://www.frc971.org/Build-Dependencies/small_sample_logfile.fbs"],
)
+
+# OpenCV armhf (for raspberry pi)
+http_archive(
+ name = "opencv_armhf",
+ build_file = "@//debian:opencv.BUILD",
+ sha256 = "1dd496ad0947ed6ce5d89cbefcfa55ea15ccb5bf70fa6ad7701c62cf2fcdd657",
+ url = "http://www.frc971.org/Build-Dependencies/opencv_armhf_v3.tar.gz",
+)
diff --git a/aos/controls/polytope.h b/aos/controls/polytope.h
index c63166f..28f011e 100644
--- a/aos/controls/polytope.h
+++ b/aos/controls/polytope.h
@@ -109,13 +109,15 @@
#ifdef __linux__
+
template <int number_of_dimensions>
class HPolytope : public Polytope<number_of_dimensions> {
public:
// Constructs a polytope given the H and k matrices.
- HPolytope(Eigen::Ref<const Eigen::Matrix<double, Eigen::Dynamic,
- number_of_dimensions>> H,
- Eigen::Ref<const Eigen::Matrix<double, Eigen::Dynamic, 1>> k)
+ HPolytope(
+ Eigen::Ref<
+ const Eigen::Matrix<double, Eigen::Dynamic, number_of_dimensions>> H,
+ Eigen::Ref<const Eigen::Matrix<double, Eigen::Dynamic, 1>> k)
: H_(H), k_(k), vertices_(CalculateVertices(H, k)) {}
// This is an initialization function shared across all instantiations of this
@@ -133,6 +135,8 @@
return k_;
}
+ // NOTE: If you are getting bizarre errors that you are tracing back to the
+ // vertex matrix being funky, please check that you correctly called Init().
Eigen::Matrix<double, number_of_dimensions, Eigen::Dynamic> Vertices()
const override {
return vertices_;
diff --git a/aos/dump_rtprio.cc b/aos/dump_rtprio.cc
index 12000f0..5d9a0b4 100644
--- a/aos/dump_rtprio.cc
+++ b/aos/dump_rtprio.cc
@@ -248,7 +248,7 @@
int main() {
::aos::logging::Init();
- ::aos::logging::AddImplementation(
+ ::aos::logging::SetImplementation(
new ::aos::logging::StreamLogImplementation(stdout));
const int pid_max = find_pid_max();
diff --git a/aos/events/logging/log_stats.cc b/aos/events/logging/log_stats.cc
index 9383fdd..2d9604f 100644
--- a/aos/events/logging/log_stats.cc
+++ b/aos/events/logging/log_stats.cc
@@ -79,7 +79,6 @@
if (channel->name()->string_view().find(FLAGS_name) != std::string::npos) {
// Add a record to the stats vector.
channel_stats.push_back({channel});
- it++;
// Lambda to read messages and parse for information
stats_event_loop->MakeRawWatcher(
channel,
@@ -99,6 +98,7 @@
// update the overall logfile statistics
logfile_stats.logfile_length += context.size;
});
+ it++;
// TODO (Stephan): Frequency of messages per second
// - Sliding window
// - Max / Deviation
diff --git a/aos/ipc_lib/ipc_comparison.cc b/aos/ipc_lib/ipc_comparison.cc
index 1553159..cf5581e 100644
--- a/aos/ipc_lib/ipc_comparison.cc
+++ b/aos/ipc_lib/ipc_comparison.cc
@@ -955,7 +955,7 @@
::gflags::ParseCommandLineFlags(&argc, &argv, true);
::aos::InitNRT();
- ::aos::logging::AddImplementation(
+ ::aos::logging::SetImplementation(
new ::aos::logging::StreamLogImplementation(stdout));
return ::aos::Main(argc, argv);
diff --git a/aos/ipc_lib/raw_queue_test.cc b/aos/ipc_lib/raw_queue_test.cc
index 3048e1b..1c02c53 100644
--- a/aos/ipc_lib/raw_queue_test.cc
+++ b/aos/ipc_lib/raw_queue_test.cc
@@ -994,52 +994,52 @@
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
queue->WriteMessage(nullptr, RawQueue::kPeek);
},
".*illegal write option.*");
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
queue->WriteMessage(nullptr, RawQueue::kFromEnd);
},
".*illegal write option.*");
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
queue->WriteMessage(nullptr, RawQueue::kPeek | RawQueue::kFromEnd);
},
".*illegal write option.*");
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
queue->WriteMessage(nullptr, RawQueue::kNonBlock | RawQueue::kBlock);
},
".*invalid write option.*");
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
queue->ReadMessageIndex(
RawQueue::kBlock | RawQueue::kFromEnd | RawQueue::kPeek, nullptr);
},
".*ReadMessageIndex.*is not allowed.*");
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
queue->ReadMessageIndex(RawQueue::kOverride, nullptr);
},
".*illegal read option.*");
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
queue->ReadMessageIndex(RawQueue::kOverride | RawQueue::kBlock,
nullptr);
},
".*illegal read option.*");
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
queue->ReadMessage(RawQueue::kNonBlock | RawQueue::kBlock);
},
".*invalid read option.*");
diff --git a/aos/logging/implementations.cc b/aos/logging/implementations.cc
index 89fc904..cfc14c0 100644
--- a/aos/logging/implementations.cc
+++ b/aos/logging/implementations.cc
@@ -1,16 +1,16 @@
#include "aos/logging/implementations.h"
-#include <stdarg.h>
#include <inttypes.h>
+#include <stdarg.h>
#include <algorithm>
#include <chrono>
+#include "absl/base/call_once.h"
#include "aos/die.h"
+#include "aos/ipc_lib/queue.h"
#include "aos/logging/printf_formats.h"
#include "aos/time/time.h"
-#include "aos/ipc_lib/queue.h"
-#include "absl/base/call_once.h"
namespace aos {
namespace logging {
@@ -23,30 +23,18 @@
// apply here (mostly the parts about being able to use AOS_LOG) because this is
// the root one.
class RootLogImplementation : public LogImplementation {
- public:
- void have_other_implementation() { only_implementation_ = false; }
-
protected:
virtual ::aos::monotonic_clock::time_point monotonic_now() const {
return ::aos::monotonic_clock::now();
}
private:
- void set_next(LogImplementation *) override {
- AOS_LOG(FATAL, "can't have a next logger from here\n");
- }
-
- __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
- void DoLog(log_level level, const char *format, va_list ap) override {
+ __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0))) void DoLog(
+ log_level level, const char *format, va_list ap) override {
LogMessage message;
internal::FillInMessage(level, monotonic_now(), format, ap, &message);
internal::PrintMessage(stderr, message);
- if (!only_implementation_) {
- fputs("root logger got used, see stderr for message\n", stdout);
- }
}
-
- bool only_implementation_ = true;
};
RootLogImplementation *root_implementation = nullptr;
@@ -63,15 +51,13 @@
internal::global_top_implementation.store(implementation);
}
-void NewContext() {
- internal::Context::Delete();
-}
+void NewContext() { internal::Context::Delete(); }
void DoInit() {
SetGlobalImplementation(root_implementation = new RootLogImplementation());
- if (pthread_atfork(NULL /*prepare*/, NULL /*parent*/,
- NewContext /*child*/) != 0) {
+ if (pthread_atfork(NULL /*prepare*/, NULL /*parent*/, NewContext /*child*/) !=
+ 0) {
AOS_LOG(FATAL, "pthread_atfork(NULL, NULL, %p) failed\n", NewContext);
}
}
@@ -142,22 +128,26 @@
internal::PrintMessage(stream_, message);
}
-void AddImplementation(LogImplementation *implementation) {
+void SetImplementation(LogImplementation *implementation, bool update_global) {
internal::Context *context = internal::Context::Get();
- if (implementation->next() != NULL) {
- AOS_LOG(FATAL,
- "%p already has a next implementation, but it's not"
- " being used yet\n",
- implementation);
+ if (implementation == nullptr) {
+ AOS_LOG(FATAL, "SetImplementation got invalid implementation");
}
- LogImplementation *old = context->implementation;
- if (old != NULL) {
- implementation->set_next(old);
+ context->implementation = implementation;
+ if (update_global) {
+ SetGlobalImplementation(implementation);
}
- SetGlobalImplementation(implementation);
- root_implementation->have_other_implementation();
+}
+
+LogImplementation *SwapImplementation(LogImplementation *implementation) {
+ internal::Context *context = internal::Context::Get();
+
+ LogImplementation *old = context->implementation;
+ context->implementation = implementation;
+
+ return old;
}
void Init() {
@@ -165,13 +155,9 @@
absl::call_once(once, DoInit);
}
-void Load() {
- internal::Context::Get();
-}
+void Load() { internal::Context::Get(); }
-void Cleanup() {
- internal::Context::Delete();
-}
+void Cleanup() { internal::Context::Delete(); }
namespace {
@@ -239,14 +225,26 @@
return ::aos::monotonic_clock::now();
}
- __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
- void DoLog(log_level level, const char *format, va_list ap) override {
+ __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0))) void DoLog(
+ log_level level, const char *format, va_list ap) override {
LogMessage *message = GetMessageOrDie();
internal::FillInMessage(level, monotonic_now(), format, ap, message);
Write(message);
}
};
+class CallbackLogImplementation : public HandleMessageLogImplementation {
+ public:
+ CallbackLogImplementation(
+ const ::std::function<void(const LogMessage &)> &callback)
+ : callback_(callback) {}
+
+ private:
+ void HandleMessage(const LogMessage &message) override { callback_(message); }
+
+ ::std::function<void(const LogMessage &)> callback_;
+};
+
} // namespace
RawQueue *GetLoggingQueue() {
@@ -261,7 +259,14 @@
Die("logging: couldn't fetch queue\n");
}
- AddImplementation(new LinuxQueueLogImplementation());
+ SetImplementation(new LinuxQueueLogImplementation());
+}
+
+void RegisterCallbackImplementation(
+ const ::std::function<void(const LogMessage &)> &callback,
+ bool update_global = true) {
+ Init();
+ SetImplementation(new CallbackLogImplementation(callback), update_global);
}
} // namespace logging
diff --git a/aos/logging/implementations.h b/aos/logging/implementations.h
index 27c0472..78980ff 100644
--- a/aos/logging/implementations.h
+++ b/aos/logging/implementations.h
@@ -1,17 +1,17 @@
#ifndef AOS_LOGGING_IMPLEMENTATIONS_H_
#define AOS_LOGGING_IMPLEMENTATIONS_H_
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/types.h>
#include <unistd.h>
-#include <stdint.h>
-#include <limits.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string>
-#include <functional>
#include <atomic>
+#include <functional>
+#include <string>
#include "aos/logging/context.h"
#include "aos/logging/interface.h"
@@ -42,9 +42,7 @@
// Contains all of the information about a given logging call.
struct LogMessage {
- enum class Type : uint8_t {
- kString
- };
+ enum class Type : uint8_t { kString };
int32_t seconds, nseconds;
// message_length is just the length of the actual data (which member depends
@@ -71,8 +69,7 @@
int rows, cols;
size_t string_length;
// The message string and then the serialized matrix.
- char
- data[LOG_MESSAGE_LEN - sizeof(type) - sizeof(rows) - sizeof(cols)];
+ char data[LOG_MESSAGE_LEN - sizeof(type) - sizeof(rows) - sizeof(cols)];
} matrix;
};
};
@@ -87,14 +84,16 @@
// Returns a string representing level or "unknown".
static inline const char *log_str(log_level level) {
-#define DECL_LEVEL(name, value) if (level == name) return #name;
+#define DECL_LEVEL(name, value) \
+ if (level == name) return #name;
DECL_LEVELS;
#undef DECL_LEVEL
return "unknown";
}
// Returns the log level represented by str or LOG_UNKNOWN.
static inline log_level str_log(const char *str) {
-#define DECL_LEVEL(name, value) if (!strcmp(str, #name)) return name;
+#define DECL_LEVEL(name, value) \
+ if (!strcmp(str, #name)) return name;
DECL_LEVELS;
#undef DECL_LEVEL
return LOG_UNKNOWN;
@@ -109,8 +108,8 @@
}
private:
- __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
- void DoLog(log_level level, const char *format, va_list ap) override;
+ __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0))) void DoLog(
+ log_level level, const char *format, va_list ap) override;
virtual void HandleMessage(const LogMessage &message) = 0;
};
@@ -133,7 +132,12 @@
// when needed or by calling Load()).
// The logging system takes ownership of implementation. It will delete it if
// necessary, so it must be created with new.
-void AddImplementation(LogImplementation *implementation);
+void SetImplementation(LogImplementation *implementation,
+ bool update_global = true);
+
+// Updates the log implementation for the current thread, returning the current
+// implementation.
+LogImplementation *SwapImplementation(LogImplementation *implementation);
// Must be called at least once per process/load before anything else is
// called. This function is safe to call multiple times from multiple
@@ -153,12 +157,15 @@
// The caller takes ownership.
RawQueue *GetLoggingQueue();
-// Calls AddImplementation to register the standard linux logging implementation
+// Calls SetImplementation to register the standard linux logging implementation
// which sends the messages through a queue. This implementation relies on
// another process(es) to read the log messages that it puts into the queue.
// This function is usually called by aos::Init*.
void RegisterQueueImplementation();
+void RegisterCallbackImplementation(
+ const ::std::function<void(const LogMessage &)> &callback);
+
// This is where all of the code that is only used by actual LogImplementations
// goes.
namespace internal {
diff --git a/aos/logging/implementations_test.cc b/aos/logging/implementations_test.cc
index d97e165..a7b8b7d 100644
--- a/aos/logging/implementations_test.cc
+++ b/aos/logging/implementations_test.cc
@@ -1,17 +1,17 @@
+#include "aos/logging/implementations.h"
+
#include <inttypes.h>
#include <chrono>
#include <string>
+#include "aos/logging/printf_formats.h"
+#include "aos/time/time.h"
#include "gtest/gtest.h"
-#include "aos/logging/implementations.h"
-#include "aos/time/time.h"
-#include "aos/logging/printf_formats.h"
-
+using ::testing::AssertionFailure;
using ::testing::AssertionResult;
using ::testing::AssertionSuccess;
-using ::testing::AssertionFailure;
namespace aos {
namespace logging {
@@ -51,8 +51,8 @@
protected:
AssertionResult WasAnythingLogged() {
if (log_implementation->used()) {
- return AssertionSuccess() << "read message '" <<
- log_implementation->message().message << "'";
+ return AssertionSuccess() << "read message '"
+ << log_implementation->message().message << "'";
}
return AssertionFailure();
}
@@ -61,9 +61,9 @@
return AssertionFailure() << "nothing was logged";
}
if (log_implementation->message().level != level) {
- return AssertionFailure() << "a message with level " <<
- log_str(log_implementation->message().level) <<
- " was logged instead of " << log_str(level);
+ return AssertionFailure() << "a message with level "
+ << log_str(log_implementation->message().level)
+ << " was logged instead of " << log_str(level);
}
internal::Context *context = internal::Context::Get();
if (log_implementation->message().source != context->source) {
@@ -73,17 +73,16 @@
}
if (log_implementation->message().name_length != context->name_size ||
memcmp(log_implementation->message().name, context->name,
- context->name_size) !=
- 0) {
+ context->name_size) != 0) {
AOS_LOG(FATAL, "got a message from %.*s, but we're %s\n",
static_cast<int>(log_implementation->message().name_length),
log_implementation->message().name, context->name);
}
- if (strstr(log_implementation->message().message, message.c_str())
- == NULL) {
- return AssertionFailure() << "got a message of '" <<
- log_implementation->message().message <<
- "' but expected it to contain '" << message << "'";
+ if (strstr(log_implementation->message().message, message.c_str()) ==
+ NULL) {
+ return AssertionFailure()
+ << "got a message of '" << log_implementation->message().message
+ << "' but expected it to contain '" << message << "'";
}
return AssertionSuccess() << log_implementation->message().message;
@@ -96,14 +95,12 @@
first = false;
Init();
- AddImplementation(log_implementation = new TestLogImplementation());
+ SetImplementation(log_implementation = new TestLogImplementation());
}
log_implementation->reset_used();
}
- void TearDown() override {
- Cleanup();
- }
+ void TearDown() override { Cleanup(); }
static TestLogImplementation *log_implementation;
};
@@ -169,7 +166,7 @@
TEST_F(LoggingTest, Timing) {
// For writing only.
- //static const long kTimingCycles = 5000000;
+ // static const long kTimingCycles = 5000000;
static const long kTimingCycles = 5000;
monotonic_clock::time_point start = monotonic_clock::now();
diff --git a/aos/logging/interface.cc b/aos/logging/interface.cc
index b72f8e1..e6e9203 100644
--- a/aos/logging/interface.cc
+++ b/aos/logging/interface.cc
@@ -4,8 +4,8 @@
#include <stdio.h>
#include <string.h>
-#include <type_traits>
#include <functional>
+#include <type_traits>
#include "aos/die.h"
#include "aos/logging/context.h"
@@ -21,8 +21,8 @@
const int ret = vsnprintf(output, size, format, ap);
typedef ::std::common_type<int, size_t>::type RetType;
if (ret < 0) {
- AOS_PLOG(FATAL, "vsnprintf(%p, %zd, %s, args) failed",
- output, size, format);
+ AOS_PLOG(FATAL, "vsnprintf(%p, %zd, %s, args) failed", output, size,
+ format);
} else if (static_cast<RetType>(ret) >= static_cast<RetType>(size)) {
// Overwrite the '\0' at the end of the existing data and
// copy in the one on the end of continued.
@@ -32,30 +32,22 @@
}
void RunWithCurrentImplementation(
- int levels, ::std::function<void(LogImplementation *)> function) {
+ ::std::function<void(LogImplementation *)> function) {
Context *context = Context::Get();
- LogImplementation *const top_implementation = context->implementation;
- LogImplementation *new_implementation = top_implementation;
- LogImplementation *implementation = NULL;
- for (int i = 0; i < levels; ++i) {
- implementation = new_implementation;
- if (new_implementation == NULL) {
- Die("no logging implementation to use\n");
- }
- new_implementation = new_implementation->next();
+ LogImplementation *const implementation = context->implementation;
+ if (implementation == NULL) {
+ Die("no logging implementation to use\n");
}
- context->implementation = new_implementation;
function(implementation);
- context->implementation = top_implementation;
}
} // namespace internal
using internal::Context;
-void LogImplementation::DoVLog(log_level level, const char *format, va_list ap,
- int levels) {
+void LogImplementation::DoVLog(log_level level, const char *format,
+ va_list ap) {
auto log_impl = [&](LogImplementation *implementation) {
va_list ap1;
va_copy(ap1, ap);
@@ -66,11 +58,11 @@
VDie(format, ap);
}
};
- internal::RunWithCurrentImplementation(levels, ::std::ref(log_impl));
+ internal::RunWithCurrentImplementation(::std::ref(log_impl));
}
void VLog(log_level level, const char *format, va_list ap) {
- LogImplementation::DoVLog(level, format, ap, 1);
+ LogImplementation::DoVLog(level, format, ap);
}
void VCork(int line, const char *function, const char *format, va_list ap) {
@@ -101,9 +93,8 @@
VCork(line, function, format, ap);
- log_do(level, "%s: %d-%d: %s: %s", file,
- context->cork_data.line_min, context->cork_data.line_max, function,
- context->cork_data.message);
+ log_do(level, "%s: %d-%d: %s: %s", file, context->cork_data.line_min,
+ context->cork_data.line_max, function, context->cork_data.message);
context->cork_data.Reset();
}
diff --git a/aos/logging/interface.h b/aos/logging/interface.h
index 92f0b10..3695e40 100644
--- a/aos/logging/interface.h
+++ b/aos/logging/interface.h
@@ -3,8 +3,8 @@
#include <stdarg.h>
-#include <string>
#include <functional>
+#include <string>
#include "aos/logging/logging.h"
#include "aos/macros.h"
@@ -38,24 +38,19 @@
// overriden methods may end up logging through a given implementation's DoLog.
class LogImplementation {
public:
- LogImplementation() : next_(NULL) {}
+ LogImplementation() {}
- // The one that this one's implementation logs to.
- // NULL means that there is no next one.
- LogImplementation *next() { return next_; }
- // Virtual in case a subclass wants to perform checks. There will be a valid
- // logger other than this one available while this is called.
- virtual void set_next(LogImplementation *next) { next_ = next; }
+ virtual ~LogImplementation() {}
virtual bool fill_type_cache() { return true; }
protected:
// Actually logs the given message. Implementations should somehow create a
// LogMessage and then call internal::FillInMessage.
- __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
- virtual void DoLog(log_level level, const char *format, va_list ap) = 0;
- __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 4)))
- void DoLogVariadic(log_level level, const char *format, ...) {
+ __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0))) virtual void DoLog(
+ log_level level, const char *format, va_list ap) = 0;
+ __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 4))) void DoLogVariadic(
+ log_level level, const char *format, ...) {
va_list ap;
va_start(ap, format);
DoLog(level, format, ap);
@@ -66,12 +61,10 @@
// These functions call similar methods on the "current" LogImplementation or
// Die if they can't find one.
// levels is how many LogImplementations to not use off the stack.
- static void DoVLog(log_level, const char *format, va_list ap, int levels)
+ static void DoVLog(log_level, const char *format, va_list ap)
__attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 0)));
friend void VLog(log_level, const char *, va_list);
-
- LogImplementation *next_;
};
namespace internal {
diff --git a/aos/logging/log_displayer.cc b/aos/logging/log_displayer.cc
index d3e5728..fa8fe6b 100644
--- a/aos/logging/log_displayer.cc
+++ b/aos/logging/log_displayer.cc
@@ -154,7 +154,7 @@
int32_t source_pid = -1;
::aos::logging::Init();
- ::aos::logging::AddImplementation(
+ ::aos::logging::SetImplementation(
new ::aos::logging::StreamLogImplementation(stdout));
while (true) {
diff --git a/aos/mutex/mutex_test.cc b/aos/mutex/mutex_test.cc
index 53b47ca..e7bd617 100644
--- a/aos/mutex/mutex_test.cc
+++ b/aos/mutex/mutex_test.cc
@@ -72,7 +72,7 @@
test_mutex_.Unlock();
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
test_mutex_.Unlock();
},
".*multiple unlock.*");
@@ -83,7 +83,7 @@
logging::Init();
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
test_mutex_.Unlock();
},
".*multiple unlock.*");
@@ -93,7 +93,7 @@
TEST_F(MutexDeathTest, RepeatLock) {
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
ASSERT_FALSE(test_mutex_.Lock());
ASSERT_FALSE(test_mutex_.Lock());
},
@@ -297,7 +297,7 @@
});
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
MutexLocker locker(mutex);
},
".*previous owner of mutex [^ ]+ died.*");
diff --git a/aos/network/message_bridge_client_lib.cc b/aos/network/message_bridge_client_lib.cc
index 3652db2..39c3d17 100644
--- a/aos/network/message_bridge_client_lib.cc
+++ b/aos/network/message_bridge_client_lib.cc
@@ -32,6 +32,7 @@
CHECK(config->has_nodes()) << ": Config must have nodes to transfer.";
flatbuffers::FlatBufferBuilder fbb;
+ fbb.ForceDefaults(1);
flatbuffers::Offset<Node> node_offset = CopyFlatBuffer<Node>(my_node, &fbb);
const std::string_view node_name = my_node->name()->string_view();
@@ -106,6 +107,7 @@
aos::FlatbufferDetachedBuffer<aos::logger::MessageHeader>
MakeMessageHeaderReply() {
flatbuffers::FlatBufferBuilder fbb;
+ fbb.ForceDefaults(1);
logger::MessageHeader::Builder message_header_builder(fbb);
message_header_builder.add_channel_index(0);
message_header_builder.add_monotonic_sent_time(0);
@@ -121,6 +123,7 @@
const std::vector<std::string_view> &source_node_names,
const Configuration *configuration) {
flatbuffers::FlatBufferBuilder fbb;
+ fbb.ForceDefaults(1);
std::vector<flatbuffers::Offset<ClientConnection>> connection_offsets;
for (const std::string_view node_name : source_node_names) {
diff --git a/aos/testing/test_logging.cc b/aos/testing/test_logging.cc
index bc60081..1799cda 100644
--- a/aos/testing/test_logging.cc
+++ b/aos/testing/test_logging.cc
@@ -143,7 +143,7 @@
void *DoEnableTestLogging() {
logging::Init();
- logging::AddImplementation(TestLogImplementation::GetInstance());
+ logging::SetImplementation(TestLogImplementation::GetInstance());
::testing::UnitTest::GetInstance()->listeners().Append(
new MyTestEventListener());
diff --git a/aos/transaction/transaction_test.cc b/aos/transaction/transaction_test.cc
index f7551c8..5d1fe90 100644
--- a/aos/transaction/transaction_test.cc
+++ b/aos/transaction/transaction_test.cc
@@ -93,7 +93,7 @@
logging::Init();
EXPECT_DEATH(
{
- logging::AddImplementation(new util::DeathTestLogImplementation());
+ logging::SetImplementation(new util::DeathTestLogImplementation());
for (int i = 0; i < 1000; ++i) {
CreateWork(i);
}
diff --git a/aos/vision/debug/debug_framework.cc b/aos/vision/debug/debug_framework.cc
index 7b3ad76..47e0856 100644
--- a/aos/vision/debug/debug_framework.cc
+++ b/aos/vision/debug/debug_framework.cc
@@ -151,7 +151,7 @@
void DebugFrameworkMain(int argc, char **argv, FilterHarness *filter,
CameraParams camera_params) {
::aos::logging::Init();
- ::aos::logging::AddImplementation(
+ ::aos::logging::SetImplementation(
new ::aos::logging::StreamLogImplementation(stdout));
gtk_init(&argc, &argv);
diff --git a/aos/vision/tools/camera_primer.cc b/aos/vision/tools/camera_primer.cc
index 1ac96fd..e1d5fc5 100644
--- a/aos/vision/tools/camera_primer.cc
+++ b/aos/vision/tools/camera_primer.cc
@@ -27,7 +27,7 @@
// target_sender
int main(int argc, char **argv) {
::aos::logging::Init();
- ::aos::logging::AddImplementation(
+ ::aos::logging::SetImplementation(
new ::aos::logging::StreamLogImplementation(stdout));
aos::vision::CameraParams params;
diff --git a/aos/vision/tools/jpeg_vision_test.cc b/aos/vision/tools/jpeg_vision_test.cc
index 5267041..4ba290c 100644
--- a/aos/vision/tools/jpeg_vision_test.cc
+++ b/aos/vision/tools/jpeg_vision_test.cc
@@ -112,7 +112,7 @@
int main(int argc, char *argv[]) {
::aos::logging::Init();
- ::aos::logging::AddImplementation(
+ ::aos::logging::SetImplementation(
new ::aos::logging::StreamLogImplementation(stdout));
aos::events::EpollLoop loop;
gtk_init(&argc, &argv);
diff --git a/compilers/armhf_debian_rootfs.BUILD b/compilers/armhf_debian_rootfs.BUILD
new file mode 100644
index 0000000..004b82a
--- /dev/null
+++ b/compilers/armhf_debian_rootfs.BUILD
@@ -0,0 +1,15 @@
+filegroup(
+ name = "sysroot_files",
+ srcs = glob(
+ include = [
+ "include/**",
+ "lib/**",
+ "usr/include/**",
+ "usr/lib/**",
+ ],
+ exclude = [
+ "usr/share/**",
+ ],
+ ),
+ visibility = ["//visibility:public"],
+)
diff --git a/compilers/linaro_linux_gcc.BUILD b/compilers/linaro_linux_gcc.BUILD
index aea261d..f2fae98 100644
--- a/compilers/linaro_linux_gcc.BUILD
+++ b/compilers/linaro_linux_gcc.BUILD
@@ -58,14 +58,15 @@
filegroup(
name = "compiler_pieces",
- srcs = glob([
- "arm-linux-gnueabihf/**",
- "libexec/**",
- "lib/gcc/arm-linux-gnueabihf/**",
- "include/**",
- ], exclude=["arm-linux-gnueabihf/libc/usr/include/linux/sctp.h"]) +
- [
- "@org_frc971//third_party/linux:sctp",
+ srcs = glob(
+ include = [
+ "arm-linux-gnueabihf/**",
+ "libexec/**",
+ "lib/gcc/arm-linux-gnueabihf/**",
+ "include/**",
+ ],
+ ) + [
+ "@armhf_debian_rootfs//:sysroot_files",
],
)
diff --git a/debian/BUILD b/debian/BUILD
index 5c9d814..11f9349 100644
--- a/debian/BUILD
+++ b/debian/BUILD
@@ -48,6 +48,10 @@
":python_gtk.bzl",
python_gtk_debs = "files",
)
+load(
+ ":opencv_armhf.bzl",
+ opencv_armhf_debs = "files",
+)
load("//debian:packages.bzl", "download_packages", "generate_deb_tarball")
filegroup(
@@ -282,6 +286,13 @@
files = python_gtk_debs,
)
+# This list was generated with download_packages.py on armhf and then
+# hand-tweaked to get everything it needs.
+generate_deb_tarball(
+ name = "opencv_armhf_v3",
+ files = opencv_armhf_debs,
+)
+
exports_files([
"ssh_wrapper.sh",
])
diff --git a/debian/opencv.BUILD b/debian/opencv.BUILD
new file mode 100644
index 0000000..1915d25
--- /dev/null
+++ b/debian/opencv.BUILD
@@ -0,0 +1,258 @@
+load("@//tools/build_rules:select.bzl", "cpu_select")
+
+cc_library(
+ name = "opencv",
+ srcs = cpu_select({
+ "amd64": [
+ ],
+ "roborio": [
+ ],
+ "armhf": [
+ "usr/lib/arm-linux-gnueabihf/libopencv_core.so.3.2",
+ "usr/lib/arm-linux-gnueabihf/libopencv_features2d.so.3.2",
+ "usr/lib/arm-linux-gnueabihf/libopencv_imgproc.so.3.2",
+ "usr/lib/arm-linux-gnueabihf/libopencv_flann.so.3.2",
+ "usr/lib/arm-linux-gnueabihf/libopencv_highgui.so.3.2",
+ "usr/lib/arm-linux-gnueabihf/libopencv_videoio.so.3.2",
+ "usr/lib/arm-linux-gnueabihf/libopencv_imgcodecs.so.3.2",
+ "usr/lib/arm-linux-gnueabihf/libopencv_ml.so.3.2",
+ "usr/lib/arm-linux-gnueabihf/libtbb.so.2",
+ "usr/lib/arm-linux-gnueabihf/libgtk-3.so.0",
+ "usr/lib/arm-linux-gnueabihf/libgdk-3.so.0",
+ "usr/lib/arm-linux-gnueabihf/libpangocairo-1.0.so.0",
+ "usr/lib/arm-linux-gnueabihf/libpango-1.0.so.0",
+ "usr/lib/arm-linux-gnueabihf/libatk-1.0.so.0",
+ "usr/lib/arm-linux-gnueabihf/libgdcmDICT.so.2.8",
+ "usr/lib/arm-linux-gnueabihf/libgdcmCommon.so.2.8",
+ "usr/lib/arm-linux-gnueabihf/libgdcmIOD.so.2.8",
+ "usr/lib/arm-linux-gnueabihf/libgdcmMSFF.so.2.8",
+ "usr/lib/arm-linux-gnueabihf/libavutil.so.56",
+ "usr/lib/arm-linux-gnueabihf/libswscale.so.5",
+ "usr/lib/arm-linux-gnueabihf/libavresample.so.4",
+ "usr/lib/arm-linux-gnueabihf/libcairo-gobject.so.2",
+ "usr/lib/arm-linux-gnueabihf/libcairo.so.2",
+ "usr/lib/arm-linux-gnueabihf/libgdk_pixbuf-2.0.so.0",
+ "usr/lib/arm-linux-gnueabihf/libgio-2.0.so.0",
+ "usr/lib/arm-linux-gnueabihf/libgobject-2.0.so.0",
+ "usr/lib/arm-linux-gnueabihf/libglib-2.0.so.0",
+ "usr/lib/arm-linux-gnueabihf/libgthread-2.0.so.0",
+ "usr/lib/arm-linux-gnueabihf/libdc1394.so.22",
+ "usr/lib/arm-linux-gnueabihf/libgphoto2.so.6",
+ "usr/lib/arm-linux-gnueabihf/libgphoto2_port.so.12",
+ "usr/lib/arm-linux-gnueabihf/libavcodec.so.58",
+ "usr/lib/arm-linux-gnueabihf/libavformat.so.58",
+ "usr/lib/arm-linux-gnueabihf/libjpeg.so.62",
+ "usr/lib/arm-linux-gnueabihf/libwebp.so.6",
+ "usr/lib/arm-linux-gnueabihf/libpng16.so.16",
+ "usr/lib/arm-linux-gnueabihf/libtiff.so.5",
+ "usr/lib/arm-linux-gnueabihf/libImath-2_2.so.23",
+ "usr/lib/arm-linux-gnueabihf/libIlmImf-2_2.so.23",
+ "usr/lib/arm-linux-gnueabihf/libIex-2_2.so.23",
+ "usr/lib/arm-linux-gnueabihf/libHalf.so.23",
+ "usr/lib/arm-linux-gnueabihf/libIlmThread-2_2.so.23",
+ "usr/lib/libgdal.so.20",
+ "usr/lib/arm-linux-gnueabihf/libgdcmDSED.so.2.8",
+ "usr/lib/arm-linux-gnueabihf/libgmodule-2.0.so.0",
+ "usr/lib/arm-linux-gnueabihf/libX11.so.6",
+ "usr/lib/arm-linux-gnueabihf/libXi.so.6",
+ "usr/lib/arm-linux-gnueabihf/libXcomposite.so.1",
+ "usr/lib/arm-linux-gnueabihf/libXdamage.so.1",
+ "usr/lib/arm-linux-gnueabihf/libXfixes.so.3",
+ "usr/lib/arm-linux-gnueabihf/libatk-bridge-2.0.so.0",
+ "usr/lib/arm-linux-gnueabihf/libxkbcommon.so.0",
+ "usr/lib/arm-linux-gnueabihf/libwayland-cursor.so.0",
+ "usr/lib/arm-linux-gnueabihf/libwayland-egl.so.1",
+ "usr/lib/arm-linux-gnueabihf/libwayland-client.so.0",
+ "usr/lib/arm-linux-gnueabihf/libepoxy.so.0",
+ "usr/lib/arm-linux-gnueabihf/libharfbuzz.so.0",
+ "usr/lib/arm-linux-gnueabihf/libpangoft2-1.0.so.0",
+ "usr/lib/arm-linux-gnueabihf/libfontconfig.so.1",
+ "usr/lib/arm-linux-gnueabihf/libfreetype.so.6",
+ "usr/lib/arm-linux-gnueabihf/libXinerama.so.1",
+ "usr/lib/arm-linux-gnueabihf/libXrandr.so.2",
+ "usr/lib/arm-linux-gnueabihf/libXcursor.so.1",
+ "usr/lib/arm-linux-gnueabihf/libXext.so.6",
+ "usr/lib/arm-linux-gnueabihf/libthai.so.0",
+ "usr/lib/arm-linux-gnueabihf/libfribidi.so.0",
+ "usr/lib/arm-linux-gnueabihf/libcrypto.so.1.1",
+ "lib/arm-linux-gnueabihf/libexpat.so.1",
+ "usr/lib/arm-linux-gnueabihf/libgdcmjpeg8.so.2.8",
+ "usr/lib/arm-linux-gnueabihf/libgdcmjpeg12.so.2.8",
+ "usr/lib/arm-linux-gnueabihf/libgdcmjpeg16.so.2.8",
+ "usr/lib/arm-linux-gnueabihf/libopenjp2.so.7",
+ "usr/lib/arm-linux-gnueabihf/libCharLS.so.2",
+ "lib/arm-linux-gnueabihf/libuuid.so.1",
+ "usr/lib/arm-linux-gnueabihf/libjson-c.so.3",
+ "usr/lib/arm-linux-gnueabihf/libva-drm.so.2",
+ "usr/lib/arm-linux-gnueabihf/libva.so.2",
+ "usr/lib/arm-linux-gnueabihf/libva-x11.so.2",
+ "usr/lib/arm-linux-gnueabihf/libvdpau.so.1",
+ "usr/lib/arm-linux-gnueabihf/libdrm.so.2",
+ "usr/lib/arm-linux-gnueabihf/libpixman-1.so.0",
+ "usr/lib/arm-linux-gnueabihf/libxcb-shm.so.0",
+ "usr/lib/arm-linux-gnueabihf/libxcb.so.1",
+ "usr/lib/arm-linux-gnueabihf/libxcb-render.so.0",
+ "usr/lib/arm-linux-gnueabihf/libXrender.so.1",
+ "lib/arm-linux-gnueabihf/libmount.so.1",
+ "usr/lib/arm-linux-gnueabihf/libffi.so.6",
+ "usr/lib/arm-linux-gnueabihf/libraw1394.so.11",
+ "lib/arm-linux-gnueabihf/libusb-1.0.so.0",
+ "usr/lib/arm-linux-gnueabihf/libltdl.so.7",
+ "usr/lib/arm-linux-gnueabihf/libexif.so.12",
+ "usr/lib/arm-linux-gnueabihf/libswresample.so.3",
+ "usr/lib/arm-linux-gnueabihf/libvpx.so.5",
+ "usr/lib/arm-linux-gnueabihf/libwebpmux.so.3",
+ "opt/vc/lib/libmmal_core.so",
+ "opt/vc/lib/libmmal_util.so",
+ "opt/vc/lib/libmmal_vc_client.so",
+ "opt/vc/lib/libbcm_host.so",
+ "usr/lib/arm-linux-gnueabihf/librsvg-2.so.2",
+ "usr/lib/arm-linux-gnueabihf/libzvbi.so.0",
+ "usr/lib/arm-linux-gnueabihf/libsnappy.so.1",
+ "usr/lib/arm-linux-gnueabihf/libaom.so.0",
+ "usr/lib/arm-linux-gnueabihf/libcodec2.so.0.8.1",
+ "usr/lib/arm-linux-gnueabihf/libgsm.so.1",
+ "usr/lib/arm-linux-gnueabihf/libmp3lame.so.0",
+ "usr/lib/arm-linux-gnueabihf/libopus.so.0",
+ "usr/lib/arm-linux-gnueabihf/libshine.so.3",
+ "usr/lib/arm-linux-gnueabihf/libspeex.so.1",
+ "usr/lib/arm-linux-gnueabihf/libtheoraenc.so.1",
+ "usr/lib/arm-linux-gnueabihf/libtheoradec.so.1",
+ "usr/lib/arm-linux-gnueabihf/libtwolame.so.0",
+ "usr/lib/arm-linux-gnueabihf/libvorbis.so.0",
+ "usr/lib/arm-linux-gnueabihf/libvorbisenc.so.2",
+ "usr/lib/arm-linux-gnueabihf/libwavpack.so.1",
+ "usr/lib/arm-linux-gnueabihf/libx264.so.155",
+ "usr/lib/arm-linux-gnueabihf/libx265.so.165",
+ "usr/lib/arm-linux-gnueabihf/libxvidcore.so.4",
+ "usr/lib/arm-linux-gnueabihf/libxml2.so.2",
+ "usr/lib/arm-linux-gnueabihf/libgme.so.0",
+ "usr/lib/arm-linux-gnueabihf/libopenmpt.so.0",
+ "usr/lib/arm-linux-gnueabihf/libchromaprint.so.1",
+ "usr/lib/arm-linux-gnueabihf/libbluray.so.2",
+ "usr/lib/arm-linux-gnueabihf/libgnutls.so.30",
+ "usr/lib/arm-linux-gnueabihf/libssh-gcrypt.so.4",
+ "usr/lib/arm-linux-gnueabihf/libzstd.so.1",
+ "usr/lib/arm-linux-gnueabihf/libjbig.so.0",
+ "usr/lib/libarmadillo.so.9",
+ "usr/lib/arm-linux-gnueabihf/libproj.so.13",
+ "usr/lib/arm-linux-gnueabihf/libpoppler.so.82",
+ "usr/lib/arm-linux-gnueabihf/libfreexl.so.1",
+ "usr/lib/arm-linux-gnueabihf/libqhull.so.7",
+ "usr/lib/arm-linux-gnueabihf/libgeos_c.so.1",
+ "usr/lib/arm-linux-gnueabihf/libepsilon.so.1",
+ "usr/lib/arm-linux-gnueabihf/libodbc.so.2",
+ "usr/lib/arm-linux-gnueabihf/libodbcinst.so.2",
+ "usr/lib/arm-linux-gnueabihf/libkmlbase.so.1",
+ "usr/lib/arm-linux-gnueabihf/libkmldom.so.1",
+ "usr/lib/arm-linux-gnueabihf/libkmlengine.so.1",
+ "usr/lib/arm-linux-gnueabihf/libkmlxsd.so.1",
+ "usr/lib/arm-linux-gnueabihf/libkmlregionator.so.1",
+ "usr/lib/arm-linux-gnueabihf/libxerces-c-3.2.so",
+ "usr/lib/arm-linux-gnueabihf/libnetcdf.so.13",
+ "usr/lib/arm-linux-gnueabihf/libhdf5_serial_hl.so.100",
+ "usr/lib/arm-linux-gnueabihf/libsz.so.2",
+ "usr/lib/arm-linux-gnueabihf/libhdf5_serial.so.103",
+ "usr/lib/libmfhdfalt.so.0",
+ "usr/lib/libdfalt.so.0",
+ "usr/lib/libogdi.so.3.2",
+ "usr/lib/arm-linux-gnueabihf/libgif.so.7",
+ "usr/lib/arm-linux-gnueabihf/libgeotiff.so.2",
+ "usr/lib/arm-linux-gnueabihf/libpq.so.5",
+ "usr/lib/arm-linux-gnueabihf/libdapclient.so.6",
+ "usr/lib/arm-linux-gnueabihf/libdapserver.so.7",
+ "usr/lib/arm-linux-gnueabihf/libdap.so.25",
+ "usr/lib/arm-linux-gnueabihf/libspatialite.so.7",
+ "usr/lib/arm-linux-gnueabihf/libcurl-gnutls.so.4",
+ "usr/lib/arm-linux-gnueabihf/libfyba.so.0",
+ "usr/lib/arm-linux-gnueabihf/libfygm.so.0",
+ "usr/lib/arm-linux-gnueabihf/libfyut.so.0",
+ "usr/lib/arm-linux-gnueabihf/libmariadb.so.3",
+ "lib/arm-linux-gnueabihf/libdbus-1.so.3",
+ "usr/lib/arm-linux-gnueabihf/libatspi.so.0",
+ "usr/lib/arm-linux-gnueabihf/libgraphite2.so.3",
+ "usr/lib/arm-linux-gnueabihf/libdatrie.so.1",
+ "usr/lib/arm-linux-gnueabihf/libXau.so.6",
+ "usr/lib/arm-linux-gnueabihf/libXdmcp.so.6",
+ "lib/arm-linux-gnueabihf/libblkid.so.1",
+ "lib/arm-linux-gnueabihf/libudev.so.1",
+ "usr/lib/arm-linux-gnueabihf/libsoxr.so.0",
+ "opt/vc/lib/libvcos.so",
+ "opt/vc/lib/libvchiq_arm.so",
+ "opt/vc/lib/libvcsm.so",
+ "usr/lib/arm-linux-gnueabihf/libcroco-0.6.so.3",
+ "usr/lib/arm-linux-gnueabihf/libogg.so.0",
+ "usr/lib/arm-linux-gnueabihf/libicui18n.so.63",
+ "usr/lib/arm-linux-gnueabihf/libicuuc.so.63",
+ "usr/lib/arm-linux-gnueabihf/libicudata.so.63",
+ "usr/lib/arm-linux-gnueabihf/libmpg123.so.0",
+ "usr/lib/arm-linux-gnueabihf/libvorbisfile.so.3",
+ "usr/lib/arm-linux-gnueabihf/libp11-kit.so.0",
+ "usr/lib/arm-linux-gnueabihf/libidn2.so.0",
+ "usr/lib/arm-linux-gnueabihf/libunistring.so.2",
+ "usr/lib/arm-linux-gnueabihf/libtasn1.so.6",
+ "usr/lib/arm-linux-gnueabihf/libnettle.so.6",
+ "usr/lib/arm-linux-gnueabihf/libhogweed.so.4",
+ "usr/lib/arm-linux-gnueabihf/libgmp.so.10",
+ "lib/arm-linux-gnueabihf/libgcrypt.so.20",
+ "usr/lib/arm-linux-gnueabihf/libgssapi_krb5.so.2",
+ "usr/lib/arm-linux-gnueabihf/blas/libblas.so.3",
+ "usr/lib/arm-linux-gnueabihf/lapack/liblapack.so.3",
+ "usr/lib/arm-linux-gnueabihf/libarpack.so.2",
+ "usr/lib/arm-linux-gnueabihf/libsuperlu.so.5",
+ "usr/lib/arm-linux-gnueabihf/libnss3.so",
+ "usr/lib/arm-linux-gnueabihf/libsmime3.so",
+ "usr/lib/arm-linux-gnueabihf/libnspr4.so",
+ "usr/lib/arm-linux-gnueabihf/liblcms2.so.2",
+ "usr/lib/arm-linux-gnueabihf/libgeos-3.7.1.so",
+ "usr/lib/arm-linux-gnueabihf/libpopt.so.0",
+ "usr/lib/arm-linux-gnueabihf/libminizip.so.1",
+ "usr/lib/arm-linux-gnueabihf/liburiparser.so.1",
+ "usr/lib/arm-linux-gnueabihf/libkmlconvenience.so.1",
+ "usr/lib/arm-linux-gnueabihf/libaec.so.0",
+ "usr/lib/arm-linux-gnueabihf/libssl.so.1.1",
+ "usr/lib/arm-linux-gnueabihf/libldap_r-2.4.so.2",
+ "usr/lib/arm-linux-gnueabihf/libsqlite3.so.0",
+ "usr/lib/arm-linux-gnueabihf/libnghttp2.so.14",
+ "usr/lib/arm-linux-gnueabihf/librtmp.so.1",
+ "usr/lib/arm-linux-gnueabihf/libssh2.so.1",
+ "usr/lib/arm-linux-gnueabihf/libpsl.so.5",
+ "usr/lib/arm-linux-gnueabihf/libkrb5.so.3",
+ "usr/lib/arm-linux-gnueabihf/libk5crypto.so.3",
+ "lib/arm-linux-gnueabihf/libcom_err.so.2",
+ "usr/lib/arm-linux-gnueabihf/liblber-2.4.so.2",
+ "lib/arm-linux-gnueabihf/libsystemd.so.0",
+ "usr/lib/arm-linux-gnueabihf/libbsd.so.0",
+ "lib/arm-linux-gnueabihf/libgpg-error.so.0",
+ "usr/lib/arm-linux-gnueabihf/libkrb5support.so.0",
+ "lib/arm-linux-gnueabihf/libkeyutils.so.1",
+ "usr/lib/arm-linux-gnueabihf/libgfortran.so.5",
+ "usr/lib/arm-linux-gnueabihf/libnssutil3.so",
+ "usr/lib/arm-linux-gnueabihf/libplc4.so",
+ "usr/lib/arm-linux-gnueabihf/libplds4.so",
+ "usr/lib/arm-linux-gnueabihf/libsasl2.so.2",
+ "usr/lib/arm-linux-gnueabihf/liblz4.so.1",
+ "lib/arm-linux-gnueabihf/libz.so.1",
+ "usr/lib/arm-linux-gnueabihf/libatomic.so.1",
+ "lib/arm-linux-gnueabihf/libselinux.so.1",
+ "lib/arm-linux-gnueabihf/libpcre.so.3",
+ "lib/arm-linux-gnueabihf/liblzma.so.5",
+ "lib/arm-linux-gnueabihf/libbz2.so.1.0",
+ "usr/lib/arm-linux-gnueabihf/libgomp.so.1",
+ ],
+ "cortex-m": [],
+ }),
+ hdrs = glob([
+ "usr/include/opencv/**",
+ "usr/include/opencv2/**",
+ ]),
+ includes = [
+ "usr/include",
+ ],
+ linkopts = [
+ "-ldl",
+ "-lnsl",
+ "-lresolv",
+ ],
+ visibility = ["//visibility:public"],
+)
diff --git a/debian/opencv_armhf.bzl b/debian/opencv_armhf.bzl
new file mode 100644
index 0000000..d48ee39
--- /dev/null
+++ b/debian/opencv_armhf.bzl
@@ -0,0 +1,380 @@
+files = {
+ "adduser_3.118_all.deb": "bd71dd1ab8dcd6005390708f23741d07f1913877affb7604dfd55f85d009aa2b",
+ "adwaita-icon-theme_3.30.1-1_all.deb": "698b3f0fa337bb36ea4fe072a37a32a1c81875db13042368677490bb087ccb93",
+ "coreutils_8.30-3_armhf.deb": "6a578920fe016ce628065f4c7a2639a6ffc3d52637e4b4f20a46ea76fcc05539",
+ "dconf-gsettings-backend_0.30.1-2_armhf.deb": "61bd02ba2da9e549e245ab2f5152baa2f27ea40fd0b0cde5873c63048feaa708",
+ "dconf-service_0.30.1-2_armhf.deb": "2ddc0eddff21e18afda15379d6414ffea5ea21a10e958c2ddc85625feab5cf70",
+ "fontconfig-config_2.13.1-2_all.deb": "9f5d34ba20eb156ef62d8126866a376be985c6a83fdcfb33f12cd83acac480c2",
+ "fontconfig_2.13.1-2_armhf.deb": "f2d17a9588f37d149e2777bdeb6acbc8bad203b814c8983b34ddee24ce316421",
+ "fonts-dejavu-core_2.37-1_all.deb": "58d21a255606191e6512cca51f32c4480e7a798945cc980623377696acfa3cfc",
+ "fonts-liberation_1.07.4-9_all.deb": "c936aebbfd0af7851399ae5ab08bb01744f5e3381f7678fb87cc77114f95ef53",
+ "gdal-data_2.4.0+dfsg-1_all.deb": "6e0fce32cf2e85ad2539482087d712bf2258d05e1838f3586a17ad2dc6bb7410",
+ "glib-networking-common_2.58.0-2_all.deb": "79831fd09fc96dc5729e8ed360563b05100d6bff70b03f3badf4e0f4759bb7ec",
+ "glib-networking-services_2.58.0-2_armhf.deb": "f901428286b7d10acac92159d6e0b9c3e09691dbe7d5ec4848f962491f0805d6",
+ "glib-networking_2.58.0-2_armhf.deb": "713ec6741147cc75468f8c16cda12185aa5b11ec79cfcc5786790febf1664aaf",
+ "gsettings-desktop-schemas_3.28.1-1_all.deb": "a75aed8781a781c4b819b2d1e952791b123580b1a02a4bb35fdbbba2e3ab8310",
+ "gtk-update-icon-cache_3.24.5-1+rpt2_armhf.deb": "8ed36c27190370354987249416dd4d19545a9e82e6020f271499bf72db067e8b",
+ "hicolor-icon-theme_0.17-2_all.deb": "20304d34b85a734ec1e4830badf3a3a70a5dc5f9c1afc0b2230ecd760c81b5e0",
+ "libaec0_1.0.2-1_armhf.deb": "6a8107a0253577259ccadd5c274664bf7cb7f0d6e67a694d7ff0da7af850a7e9",
+ "libaom0_1.0.0-3_armhf.deb": "eca4cfebdc6f8afcdf141e17097c37c4094da61bb220c5c6fdf7faf2ef9badd6",
+ "libarmadillo9_9.200.7+dfsg-1_armhf.deb": "30e835a8de5c42bcede50b98f10ac2292d2677de12fbb44349b4611cc8803ad8",
+ "libarpack2_3.7.0-2_armhf.deb": "a1a466a360902651a8722539a39521787afe10df067a47b8d6b070e3cdc35b60",
+ "libatk-bridge2.0-0_2.30.0-5_armhf.deb": "7c7900d671e6a04cada9f36162a7a2e411763b19b08a2cd6b81ec9c249d24445",
+ "libatk1.0-0_2.30.0-2_armhf.deb": "c2c32c8784a995894da3b76d9c5e9269f64cb2cf3c28971a1cbede53190605c2",
+ "libatk1.0-data_2.30.0-2_all.deb": "cf0c94611ff2245ae31d12a5a43971eb4ca628f42e93b0e003fd2c4c0de5e533",
+ "libatomic1_8.3.0-6+rpi1_armhf.deb": "f0c29af98f8358dc7d38a25f12a1f82ee8f876336ca459c25c08f42754b03865",
+ "libatspi2.0-0_2.30.0-7_armhf.deb": "05980a3e666d895433b8bd24306d67d2362ead58199253ce2e699f9dc4e8fa5d",
+ "libaudit-common_2.8.4-3_all.deb": "4e51dc247cde083528d410f525c6157b08be8b69511891cf972bc87025311371",
+ "libaudit1_2.8.4-3_armhf.deb": "25378f4115b0c71b352ea91095e85d5ddced7ceb7b46448abb8cb53a0bc02da9",
+ "libavahi-client3_0.7-4+b1_armhf.deb": "8555f041940308d4bb24558d8eed6c506287d95ea151814c9fb5572ef68b9797",
+ "libavahi-common-data_0.7-4+b1_armhf.deb": "064992922f2ff006f0dea327fb5c38e1328fe58e17eb55a6c2ceac4dc531c46d",
+ "libavahi-common3_0.7-4+b1_armhf.deb": "6d40047dc95d3d24c75763288367eb651cac1e93ad167d9c4cae6eb6ffc7fa59",
+ "libavcodec-dev_4.1.4-1+rpt1~deb10u1_armhf.deb": "3dfe147c25d8a852edd763722afc3e46c83a4c87092624af59f89cb8fcde20cc",
+ "libavcodec58_4.1.4-1+rpt1~deb10u1_armhf.deb": "38010fa402aad07d8d68a93f2f9518ba7ac997371e2ef424b8d7d083687a4ad4",
+ "libavformat-dev_4.1.4-1+rpt1~deb10u1_armhf.deb": "1d43679f4c7bd834ded1da3e82d1d09380dc8dcba169b57abdcee931e5fb5d23",
+ "libavformat58_4.1.4-1+rpt1~deb10u1_armhf.deb": "6e61fd1b2c724214def3c50eda0dfcd6ef4982dbf69fa8be33d91c77b25a39e8",
+ "libavresample-dev_4.1.4-1+rpt1~deb10u1_armhf.deb": "f733261644f240dc73c8fbcb85bec57797183df2f83a8a30245b2d8c80a2b8f9",
+ "libavresample4_4.1.4-1+rpt1~deb10u1_armhf.deb": "4d06883a40682cd2348d7bfbb657340bcb23f57bea5151554483ca99704d6d1e",
+ "libavutil-dev_4.1.4-1+rpt1~deb10u1_armhf.deb": "b2d034461daa7e3ab80bcfb5e0975ac243dc16dfe2c1526a3d658cc1f8aaf0b2",
+ "libavutil56_4.1.4-1+rpt1~deb10u1_armhf.deb": "e17b9be1e6ea97fe7ce2bcebc66e4d975501bb3f5408ebbd7b922ad739f22445",
+ "libblas3_3.8.0-2_armhf.deb": "4231b6d249eb60cb13e9fc65e4378bc9e7908407a3b49a6fcdd4e88eb5df9f3d",
+ "libblkid1_2.33.1-0.1_armhf.deb": "92801e35c3dbe24f2cb45d76e0837bc3928ecf2c1016ab07e827097634afa2c0",
+ "libbluray2_1.1.0-1_armhf.deb": "670a11be9d786fa07e472928893f78ba57140cd7caecfb1e396802d3ef8863dd",
+ "libbsd0_0.9.1-2_armhf.deb": "49164a38e2aa95b45e154dafa9974765554bad662c6ee865244a1b115d568b94",
+ "libcairo-gobject2_1.16.0-4+rpt1_armhf.deb": "e3fdc6667bb647e0804cbad1eb369949d7caa8a711592786b158d0bc62c576cf",
+ "libcairo2_1.16.0-4+rpt1_armhf.deb": "1f651a306f87337b4b493ba248a09813a6da8acf60bea8ad3669a06d9d522c9f",
+ "libcap-ng0_0.7.9-2_armhf.deb": "5218a1d5d264620e027391df53c66ddc3cb5715e0aa6065238118fa3515b5e7b",
+ "libcharls2_2.0.0+dfsg-1_armhf.deb": "fa95753cbe407167cf4959f9ac02ac5db804fbaad1aaf5e04fc0bc2839502ee4",
+ "libchromaprint1_1.4.3-3_armhf.deb": "ae8106e0e758a423a89443fd1abb180d5ba3e6b208c93fc4f4a619390331abd1",
+ "libcodec2-0.8.1_0.8.1-2_armhf.deb": "21b065c1587dfa8ca1d8b9cbf0c797c56fa19738b2f697886091305cbdd891e6",
+ "libcolord2_1.4.3-4_armhf.deb": "4eec3912d5e1df92ef8d71a9c72aad2d7cc31c05edde8b583f3ee94c0181fe25",
+ "libcom-err2_1.44.5-1+deb10u2_armhf.deb": "2bc8807d701b7a41f0aed2c6ae869e26424bb66709fa5f217bb93aef8d87dcd6",
+ "libcroco3_0.6.12-3_armhf.deb": "45940fc83e016ab6921a17001125b4fd0743ff37a87d2cf503c97a9b73e50f3b",
+ "libcups2_2.2.10-6+deb10u1_armhf.deb": "f9e40ab35364c65998d4bfb217a1f1db2d1a0520a9c18d089e09b87c444aaa11",
+ "libcurl3-gnutls_7.64.0-4_armhf.deb": "1f52639539ccc0b358c4bac4d4044fe95db30acbaa2d27765c7132632a11047e",
+ "libdap25_3.20.3-1_armhf.deb": "e4a7a8502e233d355eadbcfad793d23a6e2b5dfbfda813aef3b76e91da6178f6",
+ "libdapclient6v5_3.20.3-1_armhf.deb": "beee7cb7642fcfd2d550908ae019a833195eb46ae5e5fac3732ab8208e0626a9",
+ "libdapserver7v5_3.20.3-1_armhf.deb": "cb4b57096e13161c5368db9d2ae868ba377a177a17dbb47503bfc1d022019b6e",
+ "libdatrie1_0.2.12-2_armhf.deb": "8e57fcfce1f6cad89e48332931d3ac3e7d65838ef36108dcb8cb9b8689268704",
+ "libdb5.3_5.3.28+dfsg1-0.5_armhf.deb": "e9bfd3904dfbdab095f24f4e3d2736c1cabd0fc0a13c06239fc795dc3fd394fa",
+ "libdbus-1-3_1.12.16-1_armhf.deb": "8956d26ed5e36da1827b295af1db20c4c3326c2fb6286df0611af1fddadfe148",
+ "libdc1394-22-dev_2.2.5-1_armhf.deb": "e1181d30983e2388f30168a06e347af77f63dadd472d7f10a06c0453c9854492",
+ "libdc1394-22_2.2.5-1_armhf.deb": "dc9d04ccaaf4c9d8e789a81b5eee65f3b7dbc16dedd492106d5494a14cc024f6",
+ "libdconf1_0.30.1-2_armhf.deb": "6ede031759943492bbc180e8d370b68d22279158a73ed692501b0e2347491cde",
+ "libdpkg-perl_1.19.7_all.deb": "1cb272a8168138e9b8334e87cc26388259f232b74667b3a7f3856f227adcc4ba",
+ "libdrm-amdgpu1_2.4.99-1~bpo10~1_armhf.deb": "f432b784cb753da0a763ba3f6bed0f5e74578cc6c1a27de617a27f25ad89391e",
+ "libdrm-common_2.4.99-1~bpo10~1_all.deb": "e48b70787ace4ee4874df9078f28353119af80792c85c76db45aed26a2bbd813",
+ "libdrm-nouveau2_2.4.99-1~bpo10~1_armhf.deb": "11bb0b958997810924afa5eba00dbce4ce5f036409a86b309823c40a32420581",
+ "libdrm-radeon1_2.4.99-1~bpo10~1_armhf.deb": "79d4d288276a852b18e6b02e409c589a6cdca5f9bc712accdc062e60db500b4a",
+ "libdrm2_2.4.99-1~bpo10~1_armhf.deb": "ff95d213633ecaa8450cb9f77b04b34cc5017459c32e42f6ec90138436faafd8",
+ "libedit2_3.1-20181209-1_armhf.deb": "0d35fbdf5952df7a78dbc4776b89361a2fef8006342a94ab9d602483ad3578da",
+ "libelf1_0.176-1.1_armhf.deb": "013c168e64666e33e431701f7b1d683d2234f39caa2d801e389ef69266e88167",
+ "libepoxy0_1.5.3-0.1_armhf.deb": "1c09ff3084a59f3fbb519ca43b3d5d2bd32eb2835ec1b8f5703d02ddfefef2fc",
+ "libepsilon1_0.9.2+dfsg-4_armhf.deb": "22394acdfe3159dbb6a17aca4fa4edc641c1d6f04c5eed09802b10f0cbd24a29",
+ "libevent-2.1-6_2.1.8-stable-4_armhf.deb": "b8bca67f980502877981d8891e751fa0bd879e785c63e2dd25b61ef629442adc",
+ "libevent-core-2.1-6_2.1.8-stable-4_armhf.deb": "24cd3b8e29650bd0e4b4efe6c1d770b1e75df9682c07eb3276fa22eb55276c44",
+ "libevent-pthreads-2.1-6_2.1.8-stable-4_armhf.deb": "cb009ff0d23de8d1de1972b712c210899fd5e4380027d9ac6846d5bb3b7e8c25",
+ "libexif-dev_0.6.21-5.1_armhf.deb": "bc9c03655e49f038b308228d92998677429b63f3aa1e97ef336dbdd0fe6cdbf0",
+ "libexif12_0.6.21-5.1_armhf.deb": "9105590ee18cb2113e8dee17f270ce81d9cdb2199904886278b99c44c661cbfc",
+ "libexpat1_2.2.6-2+deb10u1_armhf.deb": "869f0de1b5548c13e395554f454dcd17398479e12b5b1e7079fd8e5246113365",
+ "libffi6_3.2.1-9_armhf.deb": "dd24f5e9fa15e16c80c8a13869d63f1a1fbef153b63c628d09f9bc4ed513112e",
+ "libfontconfig1_2.13.1-2_armhf.deb": "3c9b6ab7c53742599ba2d43f67181b01b77442c0bd48539466e3a117c555e094",
+ "libfreetype6_2.9.1-3+deb10u1_armhf.deb": "84a520466752a39ac67acd32403fd00b18f41bf5477044e8475d643fdfaefd78",
+ "libfreexl1_1.0.5-3_armhf.deb": "42a5ad5b00b79271a9651cd0fa220e488bc700b691e3e9789b7b0d0c27219a5e",
+ "libfribidi0_1.0.5-3.1+deb10u1_armhf.deb": "c1fd57da1608f48bd699d853f0149e47bb21baa4d7328be5f87fb0f908a5ed54",
+ "libfyba0_4.1.1-6_armhf.deb": "331d150a88b29e2cc16139dc2ba3c1c77ab0fd577be4f2f08de603bbaec0e59b",
+ "libgcrypt20_1.8.4-5_armhf.deb": "19ec0ba3e4d133ade463dedc1ca4f2b37344eab058213cc384ea14488a7272d5",
+ "libgd3_2.2.5-5.2_armhf.deb": "77e8999b903a4b576ae05f3c3776f69a0277a8200857aba6fa3bc8fb290c874c",
+ "libgdal20_2.4.0+dfsg-1+b2_armhf.deb": "7b4f71a576320aecbeadd11dbd507c5a6f7c9c519606bd30efa5e192183112c4",
+ "libgdcm2-dev_2.8.8-9_armhf.deb": "8b27b3ab3e2c265bd92c78aa39bc485f692da499bcf5ed0e2d9ff6b52d5d6eff",
+ "libgdcm2.8_2.8.8-9_armhf.deb": "e07feea0e5724c4ea9ab24af5dae2ba5bc0d3be20d6c9596b09f7067dd037768",
+ "libgdk-pixbuf2.0-0_2.38.1+dfsg-1_armhf.deb": "68dc44a106ef642247847657567890d7f36a4eeed16d2b7d1e7e733a0442a265",
+ "libgdk-pixbuf2.0-common_2.38.1+dfsg-1_all.deb": "1310e3f0258866eb4d0e95f140d5d9025cf6be1e3e2c375f4a426ccc2e78cf68",
+ "libgeos-3.7.1_3.7.1-1_armhf.deb": "2fd2fc54180965df1f3921ced9186de9e97204bc08f05558a48de4fcfcec69e3",
+ "libgeos-c1v5_3.7.1-1_armhf.deb": "6efa1978880f24e97214163972ff29f652ffcb8a2cebff3d17235704e204f57b",
+ "libgeotiff2_1.4.3-1_armhf.deb": "044798114f725f781ec3f2415bdf12bba85c4e762e6a2d93fff0508ab8fa2346",
+ "libgfortran5_8.3.0-6+rpi1_armhf.deb": "a5f5a383d8e617a11316ec335f83ee5bafade9cc7de5c9d83dc79f5c5858f9ad",
+ "libgif7_5.1.4-3_armhf.deb": "b88a0b203bf0f88264dd932ee13a52d28b1e92eb76bfbc7e62a124eae71f9de5",
+ "libgl1-mesa-dri_19.2.0~rc1-1~bpo10+1~rpt3_armhf.deb": "f7291de6f9dfc56a412330f306ae89f809ed7c7d021b7da15347784803a2111f",
+ "libgl1-mesa-glx_19.2.0~rc1-1~bpo10+1~rpt3_armhf.deb": "261e3a9fef4f4f7912c6cf61a09fed47c3c1eeef1d563ae757b879284a0d084e",
+ "libgl1_1.1.0-1_armhf.deb": "7243594e50a2f898a023fc2ec4b17d59e2e71fd415afeafe6dc8af104268c9fe",
+ "libgl2ps1.4_1.4.0+dfsg1-2_armhf.deb": "61aa9ebb7c7205365cf6adb2318b4d8376e30f6dbed9271bdda63135e6d57c37",
+ "libglapi-mesa_19.2.0~rc1-1~bpo10+1~rpt3_armhf.deb": "03ce3b9a80c6eadb3f5dd5ac421c4a45bb6beacb7748f244931343025abd6173",
+ "libglib2.0-0_2.58.3-2+deb10u2_armhf.deb": "6c9edefc08726bc9e63b31e487c022db6b55dd710fe3e022e1a414a17f33328f",
+ "libglu1-mesa_9.0.0-2.1_armhf.deb": "1a3aaf79151e412a4af3316873e8ae5f73a8e78ef7e361b37e49aed186470e91",
+ "libglvnd0_1.1.0-1_armhf.deb": "c449f17f2c86dc60b49161a84414a7c355bd329a49979e4a5ba92e7a1dd37927",
+ "libglx-mesa0_19.2.0~rc1-1~bpo10+1~rpt3_armhf.deb": "787521cf777871c9aa59ddfd563ac428bec27454d91f85248df21d96c559f32f",
+ "libglx0_1.1.0-1_armhf.deb": "c2495916884ddb8d0360fcba429f42463ec03d7935eef24a2f3548b57bb80aa7",
+ "libgme0_0.6.2-1_armhf.deb": "09a4d473e20c1cbd76119c45a42d00fe953ea7a58cda45abaf65897bea82e21d",
+ "libgmp10_6.1.2+dfsg-4_armhf.deb": "ca3cd65e915de80716dd976fd9e6b9588342e39117ec07ac5a00e60bcb1a27df",
+ "libgnutls30_3.6.7-4_armhf.deb": "439dbc35caa9e3baacc7ddf200c60385e69c262c37b20294295c3c2071606812",
+ "libgomp1_8.3.0-6+rpi1_armhf.deb": "243f49f947c8a992ecb8c38a301288661254bc10099d27c98eafd2e05fe88100",
+ "libgpg-error0_1.35-1_armhf.deb": "6549092b313862bf3959fa4a0903a885ff81a777bed2b4925ab85df03588eee2",
+ "libgphoto2-6_2.5.22-3_armhf.deb": "b20dd5e04ecce954151680f4aa35e6f5a2c8c7f09a8bbfc5a769345d99481861",
+ "libgphoto2-dev_2.5.22-3_armhf.deb": "30b98ae9bb8fa42ce16e2231f509bf68c425d1bc81003ef66ed8fda1774fa135",
+ "libgphoto2-port12_2.5.22-3_armhf.deb": "0eae07c8307af1d629d475c9a50570e032941c6ef065b2551684b03dbc0e7c46",
+ "libgraphite2-3_1.3.13-7_armhf.deb": "461cc0fec95f74dae2c031e7c7123774877e8bb4f0341b607d163ee0e58d1186",
+ "libgsm1_1.0.18-2_armhf.deb": "148dd82999418b9d1e70b412b5fe2d2e1d4de7407cc23ec7e2c485a7fd73ef57",
+ "libgssapi-krb5-2_1.17-3_armhf.deb": "63a06b5943840f841aacc34032974f228a3c0023fca05d9b4b6329650390361a",
+ "libgtk-3-0_3.24.5-1+rpt2_armhf.deb": "3ee5f878748e4a6301a631a1fc1e5afad3a0bc07cf5d2485e12511545609732b",
+ "libgtk-3-common_3.24.5-1+rpt2_all.deb": "eb65d4610b98e5927a23ce4f36bfd76e2d53e1303b94c6d2a0c634d8fe4506fd",
+ "libharfbuzz0b_2.3.1-1_armhf.deb": "cb57cfe0e2c3e36a9cdbf032eed11269eeda8ae5c66203fb95c19cc8c2fa1ed0",
+ "libhdf4-0-alt_4.2.13-4+b1_armhf.deb": "df376e0f0413e52cd59ddc937a4c9fde565cc4d5cf56cdc63f9c32c709ac8053",
+ "libhdf5-103_1.10.4+repack-10_armhf.deb": "ebe9eff643cb5e5fb0f78038ee81ae8a7ee29bd2e1d34eeb92452c3c172291ff",
+ "libhdf5-openmpi-103_1.10.4+repack-10_armhf.deb": "eb53ab0db447b08d50f3c8a5d22f8c643f65075ace448efe86d6bea5e194352a",
+ "libhogweed4_3.4.1-1_armhf.deb": "9eafecd38110191e285293a770eb13ef7a291cea2e0ff18cf511c6cf21b947b6",
+ "libhwloc-plugins_1.11.12-3+rpi1_armhf.deb": "5703cbe54214331b879aa8bc07577dc7e4e3c748df6a9c8f89af9e6e6e5cb20d",
+ "libhwloc5_1.11.12-3+rpi1_armhf.deb": "a9c20eeaa0f5abff444a3f12639ccb8554fae05d97cef1840e5de54c7d3c394b",
+ "libibverbs1_22.1-1_armhf.deb": "37aebd2d0c1cffe2b9a8678bbde786ae57b9e04ca8977fce5baa334378e661f7",
+ "libice6_1.0.9-2_armhf.deb": "92374e7e8076ad0062638c7438c886d0c23000b1a8a9b361a057d0625dc20a65",
+ "libicu63_63.1-6_armhf.deb": "94010cc7c8ce2de49ad2dcdf2d70eccb32b890a8d5e9b30ec5ba3ce72f681fdc",
+ "libidn2-0_2.0.5-1_armhf.deb": "4652f117181607de335c7ded31109310934bc40051c6afb7bbdedb9fbbb2b28c",
+ "libilmbase-dev_2.2.1-2_armhf.deb": "bcd411d9f601549cbbb343b672e6ce0be2704c701f2cc6cdbc254cc8a8b61bce",
+ "libilmbase23_2.2.1-2_armhf.deb": "7d8995d3db7cfe4ff6705553d00679682f55cd4021436e7bd2e83bb56d23d8c2",
+ "libjbig-dev_2.1-3.1+b2_armhf.deb": "8324e57714c0e44ed47235ef3510cd4f1acc8b098eb2140b7773935cfdd4a7e6",
+ "libjbig0_2.1-3.1+b2_armhf.deb": "b50783fe5974f648125b6ce2487ba05f99e4f11929f5b75bdc5baa94890a563f",
+ "libjpeg-dev_1.5.2-2_all.deb": "71b42025bdeb9fcc30054b54c84c4306da59466fbd419f46471f15ec54d435aa",
+ "libjpeg62-turbo-dev_1.5.2-2+b1_armhf.deb": "c8b85c158cff2deb164da3e67eba70fa13cfddc40ef7e721eaa4bf0c770f9194",
+ "libjpeg62-turbo_1.5.2-2+b1_armhf.deb": "bc28dbc5b68fe0268aa7692562bb0a39908e1bd0901be1990affd585fec773b3",
+ "libjson-c3_0.12.1+ds-2_armhf.deb": "ca3de6f029fb22f0efb576734f27a97583ebd9b9137b1c7cfd0f6228fae44423",
+ "libjson-glib-1.0-0_1.4.4-2_armhf.deb": "a790c43ed7957d646337df29628b17e812869b1e087a59002f5b1b97a42b400f",
+ "libjson-glib-1.0-common_1.4.4-2_all.deb": "c27dbb0cf9c73e2a09d5c774fb46ecf6d2b634facaf3b37b20a4654d9c549187",
+ "libjsoncpp1_1.7.4-3_armhf.deb": "25674de33c2105228048b9380b71045faf0716e63c3f901f4d9bc67ed4579c8a",
+ "libk5crypto3_1.17-3_armhf.deb": "abcc38ec1ec6f0c84feb2cb14b8a96517957cbcbdc20f6183e7fe3c0e133975c",
+ "libkeyutils1_1.6-6_armhf.deb": "ee0948ea16c2520d5a8612ba74c95c820966ed8dba78334729aef37571161d58",
+ "libkmlbase1_1.3.0-7_armhf.deb": "7ffa17e6e3487fd5745d32416ff82dba541b926b9eaab2e16ac7811a38de2486",
+ "libkmlconvenience1_1.3.0-7_armhf.deb": "4bfcc0187e12a3eef08372c3b8be8205d4eecddaaf4d7467ce29585466bc2365",
+ "libkmldom1_1.3.0-7_armhf.deb": "168b96f0e36b863517afc16ea6a37f00acb20dac80a40ffe2a6039412db0630d",
+ "libkmlengine1_1.3.0-7_armhf.deb": "d1d5df02935b20105d94e9ea8d4d1b186d3592f9197d9bea36d69b2cc2952d80",
+ "libkmlregionator1_1.3.0-7_armhf.deb": "3eba2098651bd33e7a51e7c54f9996ac11f0167c133ce59ddea4415ad7f5cecc",
+ "libkmlxsd1_1.3.0-7_armhf.deb": "820b7705568f69c54b7ac30feb9bc36935aecbbcaac55a801b6675f1bfe1a599",
+ "libkrb5-3_1.17-3_armhf.deb": "eb91711bd2f1606354c27216c89cef3c85d78407902b750ee228018f9134f8a1",
+ "libkrb5support0_1.17-3_armhf.deb": "5b0d26f4a7f8a0991087b917b2a9d93d353c4c9cc18f6a345db45e1c06391564",
+ "liblapack3_3.8.0-2_armhf.deb": "b6b2d62fe5f607efbb383d5b39edffa414a1bdad89cb886a60e0b5ee55c8ecbd",
+ "liblcms2-2_2.9-3_armhf.deb": "6d771698dd7b90af8f53d744775ad0f8a669be7a5ee8bf2c285f7bced0c64822",
+ "libldap-2.4-2_2.4.47+dfsg-3+rpi1+deb10u1_armhf.deb": "b61e759ffe122e843dd2b5117a421fcd344deac94c75b1892e338ab6042ce4a9",
+ "libldap-common_2.4.47+dfsg-3+rpi1+deb10u1_all.deb": "16f2cc9f5faaf9a539697d8adf05c0f460d274d785497aa8027dca6b0e9236d0",
+ "liblept5_1.76.0-1_armhf.deb": "9eb19fa5d74b861bdca63d195e9f23c90f359e6702ab2140df36804d7098f495",
+ "libllvm8_8-3+rpi1_armhf.deb": "2e3a98a357ebccfcc630cdb8a7177ec1561d31c11c5ffaceb5c449a14f817660",
+ "libltdl7_2.4.6-9_armhf.deb": "0109cd8ee5f2216584d21dcbb8b85786d5d38cd3d88fa8602c756088c38ba29a",
+ "liblz4-1_1.8.3-1_armhf.deb": "99661a8b347d55fc0212b8176f691eaee1e13e2ee75aa316c549ac669fe77925",
+ "liblzma-dev_5.2.4-1_armhf.deb": "94c1b419a70af792590eb26582f3ab5fd6908ee0f045ee649c65523503290bd4",
+ "libmariadb3_10.3.17-0+deb10u1_armhf.deb": "d141db7c82826cead85bbc3c8808e9d2148029f87c41b676c425f21cd8397639",
+ "libminizip1_1.1-8+b1_armhf.deb": "7ac58a7fb21b641d00d5485c0068ab4aca024f795ee220eec5ac1501cbfe6b7c",
+ "libmount1_2.33.1-0.1_armhf.deb": "9443056463d7ddedde9bf28e1f2b6486198b68143fa0b7a2688e3edf823d566d",
+ "libmp3lame0_3.100-2+b1_armhf.deb": "1b5334f976afe0a16c0faa29832ff35e6d442beca23062b9f385079a120d4017",
+ "libmpg123-0_1.25.10-2_armhf.deb": "e552789597110f8cc7300ca34578a2e93700db189ee4732c2adce39a339ad617",
+ "libncursesw6_6.1+20181013-2+deb10u2_armhf.deb": "2435c3c7d6f27d907584a36583da629927eec4c2d8e2deff7bc8d814ff2b97b6",
+ "libnetcdf-c++4_4.2-11_armhf.deb": "ddbc876f3a37f78386f7d4611ad9ef095dce27a8dffa95f65a64c10381324d27",
+ "libnetcdf13_4.6.2-1+b1_armhf.deb": "0323f376ec2d0be39683adfdebaba1a0ee062d4387a4b1cd5946b389b6fd0409",
+ "libnettle6_3.4.1-1_armhf.deb": "49010bb7544c086eb20d5330fd1b1bce61bf29f66f0bfe7da5381f1ddcc6abf0",
+ "libnghttp2-14_1.36.0-2+deb10u1_armhf.deb": "3e47c770b48f555decbb31bc38f38b985c8d6009f39f7923c0fc7973bac99348",
+ "libnl-3-200_3.4.0-1_armhf.deb": "61c07f733be04122faa5f86e50138f27b639b10852fa19c5109b63ce7b4f1d8d",
+ "libnl-route-3-200_3.4.0-1_armhf.deb": "3761f4d6c6b255873b5ddf9c615ff9c396f00b212bde9d81cf83a86373316b44",
+ "libnspr4_4.20-1_armhf.deb": "1a5c311c0b2d3de1d53bb8bed8034c475dcd8293319e69f4bea2d765f00c87ee",
+ "libnss3_3.42.1-1+deb10u2_armhf.deb": "bf52021aac6e4c10183f10155fb554286831c75639e766c19c0f4946cde76718",
+ "libodbc1_2.3.6-0.1_armhf.deb": "07ce132f8fc2dab2e11f6988896cfdaf2e865b81da96456f42fde8f5e1e1708f",
+ "libogdi3.2_3.2.1+ds-4_armhf.deb": "f2089377ed36ef36327e8a982ea3fdde736806fd7288be67da19b69a7d1f6bb1",
+ "libogg0_1.3.2-1+b2_armhf.deb": "2518b3214e3c709eb0df6bb71127d1b9e24fc642513f6a8a9e729de98f789d50",
+ "libopencv-calib3d-dev_3.2.0+dfsg-6_armhf.deb": "8c7f3ca52bf148f39483a6e1ed864c36107f5461fed78934b9ae3cecf027e48a",
+ "libopencv-calib3d3.2_3.2.0+dfsg-6_armhf.deb": "a7ce99efec8b00d8db399352a7099ab78153d5aec72fb1f53d3570b6213d1c4c",
+ "libopencv-contrib-dev_3.2.0+dfsg-6_armhf.deb": "b733091fe4bafb84f40b1221af788ec5df7f64108bd15c700575054a9846d1b0",
+ "libopencv-contrib3.2_3.2.0+dfsg-6_armhf.deb": "41ce0e6af765c46d2fbfd9d9b8ecca678537e53ac637dbc28775f26b22b18d49",
+ "libopencv-core-dev_3.2.0+dfsg-6_armhf.deb": "a83d0f59ce1e23cfa2f7c400e669f12b905acbbc9349998b9eab451c78ce91ca",
+ "libopencv-core3.2_3.2.0+dfsg-6_armhf.deb": "d2b7ecda65da3ba6610711dc9ab95f7bc8f90a6dead77ad06f93a082b5ae36f2",
+ "libopencv-dev_3.2.0+dfsg-6_armhf.deb": "aa519c3e572b655f039803117c737bc7c0f0638fbc86ff8989294b5df294a8fb",
+ "libopencv-features2d-dev_3.2.0+dfsg-6_armhf.deb": "b614de275538bcb5a12ed7bc9cf7dc644572b1792cab7f5c821d329fbf05ae54",
+ "libopencv-features2d3.2_3.2.0+dfsg-6_armhf.deb": "2acd7864a39c01528f87b8d34fb5b620004e04cc287200c74ca44e0712a161b2",
+ "libopencv-flann-dev_3.2.0+dfsg-6_armhf.deb": "b81522782181f3d39d48a6b61b3b61fa45388c305ab7952d98fd7b6084314e5d",
+ "libopencv-flann3.2_3.2.0+dfsg-6_armhf.deb": "097da5fec0d3828e7e2de1bd1d38cccf86c3e0f866a94e9ae0f116fe69afdace",
+ "libopencv-highgui-dev_3.2.0+dfsg-6_armhf.deb": "20c31e48c84f7ac8ff74e603aa91453671fe0f13292f5c05370ce7c984eaeb76",
+ "libopencv-highgui3.2_3.2.0+dfsg-6_armhf.deb": "f52232ca0db2aec76bf55605f7268eb3f5969524d0dd4627a5e0c75900655b38",
+ "libopencv-imgcodecs-dev_3.2.0+dfsg-6_armhf.deb": "055d2f33c8b1b20edc0d989a6ff047d0b9eea0347237febbcf27f9380fc1b843",
+ "libopencv-imgcodecs3.2_3.2.0+dfsg-6_armhf.deb": "3a87d0dd4a0d534242394de932526365a9e080f9fe783a1caaaeb72b909762c0",
+ "libopencv-imgproc-dev_3.2.0+dfsg-6_armhf.deb": "0069eb4e75c2133ca12b94f979e5c2ec1c4be31b7ca42e39a90200bbb287f4c8",
+ "libopencv-imgproc3.2_3.2.0+dfsg-6_armhf.deb": "2561604f98264ade28e5ecb31b1e5590fab4c861bb170de41e8533d09dd868c6",
+ "libopencv-ml-dev_3.2.0+dfsg-6_armhf.deb": "f576a5bd460c64914e6091d5229ecf5a021a9541319d5dae472105f2d3c6e3aa",
+ "libopencv-ml3.2_3.2.0+dfsg-6_armhf.deb": "f187fa8c4cb52c982a19c5199b4df4d311bb19a561744e9086a46b4f40de69f9",
+ "libopencv-objdetect-dev_3.2.0+dfsg-6_armhf.deb": "5a1e49091efe0af562cbbc3fcd5035c4770d076503f4266360528b3aacd170ba",
+ "libopencv-objdetect3.2_3.2.0+dfsg-6_armhf.deb": "a908f56acfd787d76ab91bf3e10374c6c34070fe73acf0b58683d15d845bd5ce",
+ "libopencv-photo-dev_3.2.0+dfsg-6_armhf.deb": "6f93654b78007bb54b6294a6294d2ee1b2c8c34f9557f7fb6f51caf8a996680c",
+ "libopencv-photo3.2_3.2.0+dfsg-6_armhf.deb": "2dbb93becd211a9543711c99c32a9f6e7480f554c068a945bd76c20111756207",
+ "libopencv-shape-dev_3.2.0+dfsg-6_armhf.deb": "a56b63c6706af19b3f6e556ee7cac51dd80af48d948f7226bc5d60d4d57dda16",
+ "libopencv-shape3.2_3.2.0+dfsg-6_armhf.deb": "a6906df95067c61b18ebdbe36e30e836752c2a4c1b6a4160b1dc991b347cbe34",
+ "libopencv-stitching-dev_3.2.0+dfsg-6_armhf.deb": "d343a82f4190e0cf10ba72846d01fd38a132f7e22024f8e8ba19171c0a65feab",
+ "libopencv-stitching3.2_3.2.0+dfsg-6_armhf.deb": "e8abf81b53d28ee5e68ae5d6e423a1278e0619b02920efbc247665b5b7bbe497",
+ "libopencv-superres-dev_3.2.0+dfsg-6_armhf.deb": "24511a36a510be5943842931933577334b4e8410ded4be3fe6ad634831b5baba",
+ "libopencv-superres3.2_3.2.0+dfsg-6_armhf.deb": "81e8882fbeeae7d07665c6c07e7885b5f43fdd7d536b7007e298cdeea4acc510",
+ "libopencv-ts-dev_3.2.0+dfsg-6_armhf.deb": "2e9520d3c83ac2ef3af690ff4241c68a8cad067c0cc50d3ec9395ac7d75e29dc",
+ "libopencv-video-dev_3.2.0+dfsg-6_armhf.deb": "c7ae7ced16c7cf6aa1a1647758b0c1cf01e38bf84444dbd3baf568d4328c6f86",
+ "libopencv-video3.2_3.2.0+dfsg-6_armhf.deb": "e6d079903ce88b25558046b4ce94261eafd2fb5de0617e7fcffbbef02521ac59",
+ "libopencv-videoio-dev_3.2.0+dfsg-6_armhf.deb": "f712aa3626fd0efc42240c1b500e05a37f8e05bfab459046a6a1cf2364541127",
+ "libopencv-videoio3.2_3.2.0+dfsg-6_armhf.deb": "ed38ad4aded75bc4b5ee1a2e7acc67fc0a7a0484d9d5fe46e56f5a9edaafeb57",
+ "libopencv-videostab-dev_3.2.0+dfsg-6_armhf.deb": "942519168d7be208736394024612285bacc9c41f66edcce5a33eb86aedae6dfc",
+ "libopencv-videostab3.2_3.2.0+dfsg-6_armhf.deb": "a4dae91092fe9e9e60b2c185d610a15452f7f9df9b9b635e8deaa3b0aa93cbbf",
+ "libopencv-viz-dev_3.2.0+dfsg-6_armhf.deb": "64a9b47eb603860c60fe62f4024b3f23a4df23fe7a0e185090ba730a32ec7fc2",
+ "libopencv-viz3.2_3.2.0+dfsg-6_armhf.deb": "e3a859dc1426c7eddfb181f0e37c8c20bebced557fabf5161de795195c12c9b4",
+ "libopencv3.2-java_3.2.0+dfsg-6_all.deb": "6a177762d8dbe7e2a54cfc03aa523802848e0567ded674314d1919652b07f81b",
+ "libopencv3.2-jni_3.2.0+dfsg-6_armhf.deb": "4fae611a082c059c2344d4f39ad60d3c00c79e243b3e218d6ac5fa5a829c63bb",
+ "libopenexr-dev_2.2.1-4.1_armhf.deb": "fb634227cc4fb67662fd45a8a5e741dd9609a2872a841856cd21c20aa7f4d0e8",
+ "libopenexr23_2.2.1-4.1_armhf.deb": "437f125bc53e5749d32de0625f8aaa4eb3c06df096ce147889cf9bd380876dde",
+ "libopenjp2-7_2.3.0-2_armhf.deb": "0bc6c631f13494dda21f9df8ae87ccd35f7aa3c8945b2ee5014d410633dd7c58",
+ "libopenmpi3_3.1.3-11+rpi1_armhf.deb": "b6d19977698ae4860690574ce43dd947462e41ab96498f6cc557c4a122ad2cb7",
+ "libopenmpt0_0.4.3-1_armhf.deb": "85eb98a60a45992c9345583c5869a124a71e6d9179737bc7ad5597c615b08530",
+ "libopus0_1.3-1_armhf.deb": "69cd56d03aaa51a4d62ad8f98d2ff487ea062bbdfe13e983afcefa99cb0c010e",
+ "libp11-kit0_0.23.15-2_armhf.deb": "56de64f62447b20b4f24f3c1d5cf2036f0971f22e1e820e25ff16b8cf59a7490",
+ "libpam-modules-bin_1.3.1-5+rpt1_armhf.deb": "d10f1ff2fa6e1b486e2d1443793ee86eecaa15db9487f553e659696d4a9c7e01",
+ "libpam-modules_1.3.1-5+rpt1_armhf.deb": "a7294f87afe55e0972ed7bba8269f62226b53824a6e0f25a8348776173be0907",
+ "libpam0g_1.3.1-5+rpt1_armhf.deb": "3f85873f6bda68084c597ccc7ec985cb5406b5335eaf0fd225ecce892d7c24dc",
+ "libpango-1.0-0_1.42.4-7~deb10u1_armhf.deb": "23d2b3f5e3ba20bc858adcd1e1718e1794ab34e7d50050d8af0f22c64d4c2afd",
+ "libpangocairo-1.0-0_1.42.4-7~deb10u1_armhf.deb": "a66aa6ac56c5d0f62d90c3015f2c9d8b6d40bbe00d0e2edc3f7ee14b030ae400",
+ "libpangoft2-1.0-0_1.42.4-7~deb10u1_armhf.deb": "40cd486567b4207f2fe367d704a9ad6224c3e032129df5d6cb625bd3435a3bb8",
+ "libpciaccess0_0.14-1_armhf.deb": "37f01b81f204bfd7ab1ffbd3e4f2ef1355dd0f65167e8081ac3639bf12af912b",
+ "libpixman-1-0_0.36.0-1+rpt1_armhf.deb": "e24b5249c31dcccc246a88df767cc1b05ad47c98d484773f9e18982e1b3c2739",
+ "libpmix2_3.1.2-3_armhf.deb": "dc28717bcaffa242bc81a4e55d37819fdc73d6e204303555cf836f85973ab1e4",
+ "libpng-dev_1.6.36-6_armhf.deb": "91d8e235856389d40018e6a1568cf23c7f22c8a8fb076e9d9515ffec7159a676",
+ "libpng16-16_1.6.36-6_armhf.deb": "e5d547ed5bcc30045e8812602324c41a8e59536bed73d2af0405cbe3b596eb44",
+ "libpoppler82_0.71.0-5_armhf.deb": "78add7ce54ba679fcba6a87545ff99ed4a586c506642982caad8b529f60a6cb6",
+ "libpopt0_1.16-12_armhf.deb": "260b2ba983c6489f86cbfa590316b6e4fa3ba7501bfe9475f00c46fbf3ee76e4",
+ "libpq5_11.5-1+deb10u1_armhf.deb": "6ab0c723546189d39f793a79d7042b2b58d8ee0f349c64e196c29d563122ca68",
+ "libproj13_5.2.0-1_armhf.deb": "01226abbfaf179ce9f19397ee085bced5a29ee89e8af012b817196b8d173a857",
+ "libproxy1v5_0.4.15-5_armhf.deb": "6786d3190e0ab7069b207679d93b9d2f204aeb091aa87cbf0b899902521c7407",
+ "libpsl5_0.20.2-2_armhf.deb": "e4d0c0fc1b232cc3aee36351a474d55e56c45c587edbb4e3b4ce58ef399bdc3e",
+ "libpython2.7-minimal_2.7.16-2+deb10u1_armhf.deb": "e84407a0d58e7dff3adac497db1519dbdeba952a7caabd4f7ea2a14abb0e346d",
+ "libpython2.7-stdlib_2.7.16-2+deb10u1_armhf.deb": "dd2479f925a3da9b605b8dfb5a14ff58642e450252d7d4d99f05ca249c0d0280",
+ "libpython2.7_2.7.16-2+deb10u1_armhf.deb": "d5617bddfb0927d53471aee0ce553f22786fa488725ed09c22c13ffd8d97d884",
+ "libqhull7_2015.2-4_armhf.deb": "498f825e3c31489dc47fb9312110333ebf8bad5f1e1fd850a312fff4694f6a92",
+ "libraspberrypi0_1.20190925+1-1_armhf.deb": "9bd18328b4a040a5da558093e6d458f046372bb278decb28920d21095f7432f7",
+ "libraw1394-11_2.1.2-1+b1_armhf.deb": "e7691347dfdc9096a69068f22a2f88a81f132e1cb0d1619cce89177a79fd02aa",
+ "libraw1394-dev_2.1.2-1+b1_armhf.deb": "23620ea90abf64a75431beb2939a129473fb9de4ab1f6b6fe9a414f85abc7b53",
+ "libreadline7_7.0-5_armhf.deb": "f655bfd17328343631ea6dd3fc7d885184a518fa397881f4d32f2a30b1e8fcb5",
+ "librest-0.7-0_0.8.1-1_armhf.deb": "ac4b777c967ae0f31b6d1ff51c32c8098c9d17e742ebdd2cbaa152b6f375e820",
+ "librsvg2-2_2.44.10-2.1+rpi1_armhf.deb": "9bfade393582432caa8f96868cd2a67b974ff04b9dc94a266e1bf578d14b124b",
+ "librsvg2-common_2.44.10-2.1+rpi1_armhf.deb": "02d96caf56f77643744d9d902c0d413b50224ad1a95757da65ddc2471dbb6cd0",
+ "librtmp1_2.4+20151223.gitfa8646d.1-2_armhf.deb": "c4adf4780f3e19b55fba417a0edc8d0d3b40be6d61c996a23d1a60cc3d1a3980",
+ "libsasl2-2_2.1.27+dfsg-1+b1_armhf.deb": "02b64b1ad87e6ae75095f7cef2b38e7b59888569bed25951830aad2b5aa319e9",
+ "libsasl2-modules-db_2.1.27+dfsg-1+b1_armhf.deb": "c54eee01f398398cb1e8af9c801750f00fbfa0e8c53cba819992e0ac39c4bbcc",
+ "libsemanage-common_2.8-2_all.deb": "fa3c50e11afa9250f823218898084bdefea73c7cd1995ef5ed5e7c12e7b46331",
+ "libsemanage1_2.8-2_armhf.deb": "7f403dccd00375eb91786db9fbea41496833cb9391f78bd6ea1136d83203b325",
+ "libsensors-config_3.5.0-3_all.deb": "a064dbafa1590562e979852aca9802fc10ecfb6fda5403369c903fb38fa9802a",
+ "libsensors5_3.5.0-3_armhf.deb": "695f500a247e8a7762fe044c6fd9081db2e9806818eb4cd0593075de53ad5f5f",
+ "libsepol1_2.8-1_armhf.deb": "9941f76c1d378ed0322cb413e0340455fe812f6b7451cf86a78065b2e5db69ef",
+ "libshine3_3.1.1-2+b1_armhf.deb": "7853acc136660422b7d3423caaf2ed5cb526001bb5064f932dfedf702fb5a35b",
+ "libsm6_1.2.3-1_armhf.deb": "92eccccb771f738c18bec33b38c2bf95a281e216608e91341a7e2dbb1f8703fd",
+ "libsnappy1v5_1.1.7-1_armhf.deb": "8b87dfb35872804edd1fd002383762e593e54e3860123d0089a5b7bb26b8aef9",
+ "libsocket++1_1.12.13-10_armhf.deb": "64af2171d010a98d3cb8ca200ce24738a8fb92ef057f6b4d0c059885bf233531",
+ "libsoup-gnome2.4-1_2.64.2-2_armhf.deb": "f36e6e41e88d1ea5e203fcd1a833ef0198693a2156a6abc4a29baae817746073",
+ "libsoup2.4-1_2.64.2-2_armhf.deb": "6ef422515aa22db398887e4b0efaaeeb980a3e0d27ec1dbe3199a186d6ac19fc",
+ "libsoxr0_0.1.2-3_armhf.deb": "82c3a5098221423a3213cb7754758034e24ff114ca4e8562bf37038efc7e8afd",
+ "libspatialite7_4.3.0a-5+b2_armhf.deb": "26db41b6b1f2fee9a39673e624fe74172cc4a12b4324737dd7c066b2ae205098",
+ "libspeex1_1.2~rc1.2-1+b2_armhf.deb": "a05502ef24e63edcb3410bce0fb654c3d5a8d3129df7cfe60e0e2a330ddbc114",
+ "libsqlite3-0_3.27.2-3_armhf.deb": "09efeaead3ce02fe3b390952a30c2207be518acdcf0210715595c486212dbe53",
+ "libssh-gcrypt-4_0.8.7-1_armhf.deb": "6e8ee452c5c3fede30ee89ab80f95532f63614a76afe3d138213e33986df768b",
+ "libssh2-1_1.8.0-2.1_armhf.deb": "ab4159f8bbd8491349d75231d09bc2fdca61f91756abaa2bac95210cfc21d310",
+ "libssl1.1_1.1.1d-0+deb10u2_armhf.deb": "893e3bfdfa84cfcc48d870a1d26341de408d71cbae0fc74788a9917bb5187910",
+ "libstdc++6_8.3.0-6+rpi1_armhf.deb": "bfc0533cc7d6a4d8adfb62205b39a79ee6df7c2f7c48a1dc6ff15f5af519aed4",
+ "libsuperlu5_5.2.1+dfsg1-4_armhf.deb": "f4d797c904bbedb0ea341bd7667661137004403a86a2a8b3e7d1c2365d08dc35",
+ "libswresample-dev_4.1.4-1+rpt1~deb10u1_armhf.deb": "78691ab4c0df8a0d4810f5388958007463c9e1df9e43b218cd70ef5315688ecd",
+ "libswresample3_4.1.4-1+rpt1~deb10u1_armhf.deb": "4bee948872147a2b53ee073d5816a377c827c1f0f23eeaba1d9422fdf920f815",
+ "libswscale-dev_4.1.4-1+rpt1~deb10u1_armhf.deb": "7d294825bd34e57e3831b524a1454bba2402f8b6361e83f89294f7dcfeccfc63",
+ "libswscale5_4.1.4-1+rpt1~deb10u1_armhf.deb": "07ad95a40cd28eb1dfb537c8bd45b45dfe40c35e7aa6f3ab9784d2e3913c76b6",
+ "libsystemd0_241-7~deb10u2+rpi1_armhf.deb": "b05e56f47b281fd84054f8ed6babdb67467f1d4a32c98d79334821d841988cab",
+ "libsz2_1.0.2-1_armhf.deb": "ce5347b6d722e01899fc49a39073da7a16985ceadcf8238985e8109617a2a11b",
+ "libtasn1-6_4.13-3_armhf.deb": "594f82946858a332bfbe55ddb2b10247a52486b8b183fd818231fef8a70ff682",
+ "libtbb-dev_2018~U6-4_armhf.deb": "ff7b27eae8c89056677a0479667448c0a2d8e20f75ed84862ccc183d9739ae7c",
+ "libtbb2_2018~U6-4_armhf.deb": "4ed379b2c64bdc16b6cf1cff7b0b859c125bfc311ebfa933f17c8f6efb8f65af",
+ "libtcl8.6_8.6.9+dfsg-2_armhf.deb": "b0f0b25f4bdbb95020ed1476fbc9a84e9a22b3d5278c0dd3df4a5963b5daf3f1",
+ "libtesseract4_4.0.0-2_armhf.deb": "1f46f21a995d76aa42c83ea6272876292520d04a51936fbd4752811ea5e73be1",
+ "libthai-data_0.1.28-2_all.deb": "267d6b251f77c17fb1415ac0727675cb978c895cc1c77d7540e7133125614366",
+ "libthai0_0.1.28-2_armhf.deb": "dad127d817507db95d10a5010db28cef882b51567d5fae58da97fc7bed55f7ae",
+ "libtheora0_1.1.1+dfsg.1-15_armhf.deb": "92f9de0685e30d293e113072b429651a6b2f783c23ffdbdc430da851e9f48236",
+ "libtiff-dev_4.0.10-4_armhf.deb": "0119ae4eb3003f5aa842daa83044a56629f36970ddbf3ff27eaea1a556657720",
+ "libtiff5_4.0.10-4_armhf.deb": "93bb72344e7663b74d0d4fe19ac216a8386f235d5bd3e39ecda17f4468c489a8",
+ "libtiffxx5_4.0.10-4_armhf.deb": "7cd65c17d98224aae86c800c82ab5a197906b4a195089e5948ff3f58ba4626c4",
+ "libtinfo6_6.1+20181013-2+deb10u2_armhf.deb": "48f25a4a8c6629126aa77d9665030b83867f520e50cf8317249e22d8ec204963",
+ "libtk8.6_8.6.9-2_armhf.deb": "d15d84339d668d91cc78e66122265fbccbb56f2ab5b37f2792f3112e44b9dded",
+ "libtwolame0_0.3.13-4_armhf.deb": "2fc0bb23e5ba08b77fce5651d9c3b536478eebfd00ff8078633187538b8bdb4a",
+ "libudev1_241-7~deb10u2+rpi1_armhf.deb": "a10d8ac4dc6b4fe4296f6e2df732a3e4e1f53fd10179fe73b8ab28182a6628f8",
+ "libunistring2_0.9.10-1_armhf.deb": "7e9a8046fde4a3471e9f5477bdcecd079e423aff2b916791e0d4a224e5a6c999",
+ "liburiparser1_0.9.1-1_armhf.deb": "ed680831b4a4236a27707cd50d4649fd812876eccf1f1bfec772bb9255f65cba",
+ "libusb-1.0-0_1.0.22-2_armhf.deb": "11df519acc304a52083bbcdf018bc842510fa9f6621ac957c0e3e994dc6a1843",
+ "libuuid1_2.33.1-0.1_armhf.deb": "31dd55f3044d29370d22f956aa86965b085a201f133771aed5a44631bf989791",
+ "libva-drm2_2.4.0-1_armhf.deb": "2475f97e6e91b6c5afb81ffa0ec00e57727ab44fcbc0eb6947d4ae3dabecd397",
+ "libva-x11-2_2.4.0-1_armhf.deb": "96a84184a734f4795ff0553b1ccb31c29641024b2967327c121f46dc794d9dd1",
+ "libva2_2.4.0-1_armhf.deb": "f4a11116c295ff059b74f2aab5b0156b6e5de493595ede9ccdca21dd2a0b6d24",
+ "libvdpau1_1.1.1-10_armhf.deb": "174cc3df89c9cce18253b832f896dfe4189b765d7122f3dfe8efc48d4b9f2528",
+ "libvorbis0a_1.3.6-2_armhf.deb": "10c7ef81708ea3382fa08dd9185d7f633788362e08e9d5e7549604d6c54bc33c",
+ "libvorbisenc2_1.3.6-2_armhf.deb": "5274a1593ea161d8a4511e4f771eaf83234cc40a383857209d8f38637dee2489",
+ "libvorbisfile3_1.3.6-2_armhf.deb": "22803a4d65a855683ce59f4d95663b786a75a35c2fff78574bdcd70d113318b5",
+ "libvpx5_1.7.0-3+deb10u1_armhf.deb": "44339d7f9ee6a467524aca298a71009092680ff17af4c50b654a0e4ea081f12b",
+ "libvtk6.3_6.3.0+dfsg2-2+b6_armhf.deb": "6f0a4ea94d410d4543fa1f3345b0481960bae5969405c177212c179a177ccf15",
+ "libwavpack1_5.1.0-6_armhf.deb": "d5f7a739bd2ec74e224d205ef2dd331ced7044f687636922c0c3da6250af94a0",
+ "libwayland-client0_1.16.0-1_armhf.deb": "384c3b3288e9a1ecd1014cdb62aece060b47383cb564a001a056bb78f66b2c09",
+ "libwayland-cursor0_1.16.0-1_armhf.deb": "384fd0dbcd9760d62348b5426f3d3072e582a99fd83218ac9d4a91d1758fd40c",
+ "libwayland-egl1_1.16.0-1_armhf.deb": "6270413558873bd434d112e789796d6cba5e0d8703ae19903db0234db2c71924",
+ "libwebp6_0.6.1-2_armhf.deb": "979fc61f16f7887e4ad602a7df402ed8f12d461fda376fde31de90873920494f",
+ "libwebpmux3_0.6.1-2_armhf.deb": "6237227b67a31609eeaa20c164028447c8db0f07c6aba29da0c0d08d2f758375",
+ "libx11-6_1.6.7-1_armhf.deb": "40450a640133af52c6ca90c150cbb6ff549d3ad0e81c80f8916bc57f6af5d918",
+ "libx11-data_1.6.7-1_all.deb": "eb9e373fa57bf61fe3a3ecb2e869deb639aab5c7a53c90144ce903da255f7431",
+ "libx11-xcb1_1.6.7-1_armhf.deb": "13085f3f991abfab2fd17176c0cd97c9ade0856cd864cdb1d560451ee903b967",
+ "libx264-155_0.155.2917+git0a84d98-2+rpi1_armhf.deb": "307de7bd1053117095523c7b4cfa3ca3843490a6f10023beb77c7201143691ab",
+ "libx265-165_2.9-4_armhf.deb": "aeb74dbd170aee841a1908444e6d6997c81da92fc532c41f3908595ea86dd090",
+ "libxau6_1.0.8-1+b2_armhf.deb": "1d1c083edfc29fa3a0c7539565357fcf2f90488dee919444a155afee59ca85eb",
+ "libxcb-dri2-0_1.13.1-2_armhf.deb": "dd81a9718fec85632b80fbac71f2b03972c1c588ed570f4a6c26b7de15ba0914",
+ "libxcb-dri3-0_1.13.1-2_armhf.deb": "7760da9fec785977eea7a1dad02601d7db1841ee36bdba1d05ee8dfd5c65a11a",
+ "libxcb-glx0_1.13.1-2_armhf.deb": "d787c79efcad262895de9fa662cf7646448c1c447b4c8603daa5ac2e49d56aaa",
+ "libxcb-present0_1.13.1-2_armhf.deb": "00d64156b4710ff5621fa95c33a95d608fb59c22cb293dee26c0a09e701b80b2",
+ "libxcb-render0_1.13.1-2_armhf.deb": "842d08da35fd84d9c52d189bb412fc238ada6391da803f4e8a3bc8f9dddeded0",
+ "libxcb-shm0_1.13.1-2_armhf.deb": "d6d35c9e57153832d88a521eb22acb19639e80003de7f3d9c834162fe8e4b5da",
+ "libxcb-sync1_1.13.1-2_armhf.deb": "3a150594eb919886708a37a3c4ad13383ad798780db9175632fd442510fc436b",
+ "libxcb1_1.13.1-2_armhf.deb": "9be3930e901f475e377dd0b3fb598d785826699be1e0e4cb1b4c24ed0ad3a46d",
+ "libxcomposite1_0.4.4-2_armhf.deb": "8550a66e62a33368988efbf9c77008e3b030a03a21421a96b595584481b15331",
+ "libxcursor1_1.1.15-2_armhf.deb": "c7ac382c659528b58c053a0c552d5cc9f26aded0caf2e2e3fcd602d978380fe4",
+ "libxdamage1_1.1.4-3+b3_armhf.deb": "51339efb637c4a3bf800ed0e605158e330732cd01c9ff6b8de94f2edc5bc9b29",
+ "libxdmcp6_1.1.2-3_armhf.deb": "c871d428ca79b15b31967a8e2f19507f06c4af10bcc29429a903a175634af6e4",
+ "libxerces-c3.2_3.2.2+debian-1+b1_armhf.deb": "df1a22c853bf85b6e9afa79751860c57280406d8b40a098ac3bc8f66eceb3255",
+ "libxext6_1.3.3-1+b2_armhf.deb": "4cff4cba6aae865ca4d5e72061d51c16c87985de0232751afce0d05909c755cc",
+ "libxfixes3_5.0.3-1_armhf.deb": "92ee46160bc288442c8e8cd7e0eb2a4dd24e69904333f49371b703af8a9e1b94",
+ "libxft2_2.3.2-2_armhf.deb": "502631a6a91f4a8fccbde895aeedcb518a54e11987f97d20866c325b2eeef220",
+ "libxi6_1.7.9-1_armhf.deb": "f03478e7a8bcf4c144e46d416fb01e74352bddb57a737f3ce78da308784f9639",
+ "libxinerama1_1.1.4-2_armhf.deb": "fb715bf6feefd3695dbaf963191673864a8f73976aa3f52f1197a551af66010e",
+ "libxkbcommon0_0.8.2-1_armhf.deb": "6a45884e50e7e7438e58b6c8387dfeed5f571b79cc8a3e9dc373ffcd6f4a76de",
+ "libxml2_2.9.4+dfsg1-7+b3_armhf.deb": "2629f83a6a430149ed091098e25e22884fb163df01a1f1a3a19765bd205b1a8b",
+ "libxpm4_3.5.12-1_armhf.deb": "f1a677cb3ef3b45e2262e326af71d939ff67dcd0fa3c7a6741706836900612fd",
+ "libxrandr2_1.5.1-1_armhf.deb": "5668f1bf32b9c1d3fe13a90ffb0a15aa5b6445029d24d1718865c08b08581d8a",
+ "libxrender1_0.9.10-1_armhf.deb": "82343e14e073be48577ae1c2c5f95886bc2dddf9a1966b77ba76a827a8e62e44",
+ "libxshmfence1_1.3-1_armhf.deb": "4c9c872c366037d4535e2b5749f34bae782e19171efec6eaaf8c14c9f2486225",
+ "libxss1_1.2.3-1_armhf.deb": "8ce41b86c573c234016450b188551001f7c7da606f090d865adde9c326e1cbc1",
+ "libxt6_1.1.5-1+b3_armhf.deb": "20e1bfa25f403a7014bb3c096a2140b5a6b4db0d370b30774965fc23bb7db122",
+ "libxvidcore4_1.3.5-1_armhf.deb": "caf1801fb13ee60bdc12235f5cd4138a5479b3769be598d29e1864dd7ffd5160",
+ "libxxf86vm1_1.1.4-1+b2_armhf.deb": "cbe30a767f4decb6203bc09661e877579a8adff99ccf73459c698ad0de8efce7",
+ "libzstd1_1.3.8+dfsg-3+rpi1_armhf.deb": "250e609240c682a90b85f2d90024acc63bd0b3f586699929246c1a5d4ba0458c",
+ "libzvbi-common_0.2.35-16_all.deb": "5eea3f86857626ce4371a8a70ba9ce89f1abfc47ed033d1de12ebc0c7d1dd3ea",
+ "libzvbi0_0.2.35-16_armhf.deb": "b8e412ce669fde535a3250714eda0a446c6791771bb6360f93f676efa3d6376d",
+ "lsb-base_10.2019051400+rpi1_all.deb": "b3e203037786d00dd83a5fa9412c8395090921d373e914cb166b395ee2aedaa4",
+ "mariadb-common_10.3.17-0+deb10u1_all.deb": "43edeb3274f132675447d7375f39dd324495a430b0cddcf608875c22cbd4e9c3",
+ "mime-support_3.62_all.deb": "776efd686af26fa26325450280e3305463b1faef75d82b383bb00da61893d8ca",
+ "mysql-common_5.8+1.0.5_all.deb": "340c68aaf03b9c4372467a907575b6a7c980c6d31f90f1d6abc6707a0630608a",
+ "ocl-icd-libopencl1_2.2.12-2_armhf.deb": "634dd778eb0a073609a773b4af463999be6c77b7a757b270ba2759d52e28f16d",
+ "odbcinst1debian2_2.3.6-0.1_armhf.deb": "a2fa334961f985d37602f2eb8ec2a69338897a8e0cba6438b55d365e06624f4c",
+ "odbcinst_2.3.6-0.1_armhf.deb": "81f2678332309805a18b7120dca0c0d76e29ba4e67cca1a629c100893d65a19c",
+ "passwd_4.5-1.1_armhf.deb": "beae91f59bddfe2ca8bf99a70131263d120ada1bdee6d1b3bb46cf96093c44b3",
+ "perl_5.28.1-6_armhf.deb": "464d3c3c46d40e18ebb233106d83a1855931b01b02bd761e72217b161e87ec48",
+ "pkg-config_0.29-6_armhf.deb": "cd1b397b846e4a8b815be6a8e1edbf9a3f509b924030a008c07f2fa3ddd20911",
+ "proj-data_5.2.0-1_all.deb": "fa7126aa00742ccf75f0e9867b54ea70f733436b97f600bec39408c5d3c54bd2",
+ "raspberrypi-bootloader_1.20190925+1-1_armhf.deb": "f43da527cde12548ac439ca496305bd8d818e0981d1506adb5dd7dea943f7673",
+ "readline-common_7.0-5_all.deb": "153d8a5ddb04044d10f877a8955d944612ec9035f4c73eec99d85a92c3816712",
+ "sensible-utils_0.0.12_all.deb": "2043859f8bf39a20d075bf52206549f90dcabd66665bb9d6837273494fc6a598",
+ "shared-mime-info_1.10-1_armhf.deb": "9cc1069b361b8c229b4e2afa4c5b7014e0258cca867204f2b9d4735cb7941e68",
+ "ttf-bitstream-vera_1.10-8_all.deb": "328def7f581bf94b3b06d21e641f3e5df9a9b2e84e93b4206bc952fe8e80f38a",
+ "tzdata_2019c-0+deb10u1_all.deb": "59b295b0e669af26d494ed2803eb9011408f768a77395db2573e67c388e8a509",
+ "ucf_3.0038+nmu1_all.deb": "d02a82455faab988a52121f37d97c528a4f967ed75e9398e1d8db571398c12f9",
+ "x11-common_7.7+19_all.deb": "221b2e71e0e98b8cafa4fbc674b3fbe293db031c51d35570a3c8cdfb02a5a155",
+ "xkb-data_2.26-2_all.deb": "17d21564c940dd8d89e0a1b69d6fea0144d057e4698902378f5c83500612b779",
+ "zlib1g-dev_1.2.11.dfsg-1_armhf.deb": "51561e557bd16f56e1e28b276184f0a6d82617afce987fc8d5322369ab0da478",
+ "zlib1g_1.1.2.11.dfsg-1_armhf.deb": "408be89eee242d4836aa0fa5ef1bedeae68f6ddb3b13b792a4df0363b09320c4",
+ "libselinux1_2.8-1+b1_armhf.deb": "cc2fee966330b3d362358434ae60fa08dd7dcec81b606f4ac94ce83dd6097a39",
+ "libpcre3_2.8.39-12_armhf.deb": "394b0ce553f25fe1bcca1ab367ac86e374c30688c213f95c50f62d0c9101a9df",
+ "liblzma5_5.2.4-1_armhf.deb": "825babb4ce905472493d6f26a5ec6dfa055447f3a9f4b3418cec9e0d56681f03",
+ "libbz2-1.0_1.0.6-9.2~deb10u1_armhf.deb": "22840e43aa2b48fb0ebe441d7cef8b33380063f722769fe1382574052e214d0e",
+}
diff --git a/debian/packages.bzl b/debian/packages.bzl
index 8054d1d..ba1f840 100644
--- a/debian/packages.bzl
+++ b/debian/packages.bzl
@@ -55,13 +55,14 @@
)
def _convert_deb_to_target(deb):
- """Converts a debian package filename to a valid bazel target name."""
- target = deb.split("_")[0]
- target = target.replace("-", "_")
- target = target.replace(".", "_")
- target = target.replace(":", "_")
- target = target.replace("+", "x")
- return "deb_%s_repo" % target
+ """Converts a debian package filename to a valid bazel target name."""
+ target = deb
+ target = target.replace('-', '_')
+ target = target.replace('.', '_')
+ target = target.replace(':', '_')
+ target = target.replace('+', 'x')
+ target = target.replace('~', '_')
+ return "deb_%s_repo" % target
def generate_repositories_for_debs(files, base_url = "http://www.frc971.org/Build-Dependencies"):
"""A WORKSPACE helper to add all the deb packages in the dictionary as a repo.
diff --git a/frc971/analysis/plot.py b/frc971/analysis/plot.py
index 124968f..d325bd7 100644
--- a/frc971/analysis/plot.py
+++ b/frc971/analysis/plot.py
@@ -11,6 +11,7 @@
from frc971.analysis.plot_config_pb2 import PlotConfig, Signal
from google.protobuf import text_format
+import numpy as np
import matplotlib
from matplotlib import pyplot as plt
@@ -42,6 +43,39 @@
parsed_json = json.loads(valid_json)
self.data[channel.alias].append((message[0], message[1],
parsed_json))
+ self.calculate_signals()
+
+ def calculate_imu_signals(self):
+ if 'IMU' in self.data:
+ entries = []
+ for entry in self.data['IMU']:
+ accel_x = 'accelerometer_x'
+ accel_y = 'accelerometer_y'
+ accel_z = 'accelerometer_z'
+ msg = entry[2]
+ new_msg = {}
+ if accel_x in msg and accel_y in msg and accel_x in msg:
+ total_acceleration = np.sqrt(
+ msg[accel_x]**2 + msg[accel_y]**2 + msg[accel_z]**2)
+ new_msg['total_acceleration'] = total_acceleration
+ entries.append((entry[0], entry[1], new_msg))
+ if 'CalcIMU' in self.data:
+ raise RuntimeError('CalcIMU is already a member of data.')
+ self.data['CalcIMU'] = entries
+
+ def calculate_signals(self):
+ """Calculate any derived signals for plotting.
+
+ See calculate_imu_signals for an example, but the basic idea is that
+ for any data that is read in from the logfile, we may want to calculate
+ some derived signals--possibly as simple as doing unit conversions,
+ or more complicated version where we do some filtering or the such.
+ The way this will work is that the calculate_* functions will, if the
+ raw data is available, calculate the derived signals and place them into
+ fake "messages" with an alias of "Calc*". E.g., we currently calculate
+ an overall magnitude for the accelerometer readings, which is helpful
+ to understanding how some internal filters work."""
+ self.calculate_imu_signals()
def plot_signal(self, axes: matplotlib.axes.Axes, signal: Signal):
if not signal.channel in self.data:
@@ -53,7 +87,13 @@
monotonic_time.append(entry[0] * 1e-9)
value = entry[2]
for name in field_path:
- value = value[name]
+ # If the value wasn't populated in a given message, fill in
+ # NaN rather than crashing.
+ if name in value:
+ value = value[name]
+ else:
+ value = float("nan")
+ break
# Catch NaNs and convert them to floats.
value = float(value)
signal_data.append(value)
@@ -66,7 +106,8 @@
fig = plt.figure()
num_subplots = len(figure_config.axes)
for ii in range(num_subplots):
- axes = fig.add_subplot(num_subplots, 1, ii + 1, sharex=shared_axis)
+ axes = fig.add_subplot(
+ num_subplots, 1, ii + 1, sharex=shared_axis)
shared_axis = shared_axis or axes
axes_config = figure_config.axes[ii]
for signal in axes_config.signal:
diff --git a/frc971/analysis/plot_configs/drivetrain.pb b/frc971/analysis/plot_configs/drivetrain.pb
index 25d482e..2b15220 100644
--- a/frc971/analysis/plot_configs/drivetrain.pb
+++ b/frc971/analysis/plot_configs/drivetrain.pb
@@ -103,6 +103,10 @@
}
signal {
channel: "Status"
+ field: "trajectory_logging.left_velocity"
+ }
+ signal {
+ channel: "Status"
field: "poly_drive_logging.goal_left_velocity"
}
signal {
@@ -111,6 +115,10 @@
}
signal {
channel: "Status"
+ field: "trajectory_logging.right_velocity"
+ }
+ signal {
+ channel: "Status"
field: "poly_drive_logging.goal_right_velocity"
}
signal {
diff --git a/frc971/analysis/plot_configs/gyro.pb b/frc971/analysis/plot_configs/gyro.pb
index e398a2e..f246835 100644
--- a/frc971/analysis/plot_configs/gyro.pb
+++ b/frc971/analysis/plot_configs/gyro.pb
@@ -22,6 +22,10 @@
}
axes {
signal {
+ channel: "CalcIMU"
+ field: "total_acceleration"
+ }
+ signal {
channel: "IMU"
field: "accelerometer_x"
}
diff --git a/frc971/control_loops/BUILD b/frc971/control_loops/BUILD
index 17613ab..7d3b915 100644
--- a/frc971/control_loops/BUILD
+++ b/frc971/control_loops/BUILD
@@ -142,6 +142,22 @@
],
)
+cc_test(
+ name = "coerce_goal_test",
+ srcs = [
+ "coerce_goal_test.cc",
+ ],
+ linkopts = [
+ "-lm",
+ ],
+ deps = [
+ ":coerce_goal",
+ "//aos/controls:polytope",
+ "//aos/testing:googletest",
+ "@org_tuxfamily_eigen//:eigen",
+ ],
+)
+
# TODO(austin): Select isn't working right. We should be able to remove
# logging conditionally with select and have CPU constraints work correctly.
cc_library(
diff --git a/frc971/control_loops/coerce_goal.cc b/frc971/control_loops/coerce_goal.cc
index 311d882..6fdc70f 100644
--- a/frc971/control_loops/coerce_goal.cc
+++ b/frc971/control_loops/coerce_goal.cc
@@ -1,11 +1,8 @@
#include "frc971/control_loops/coerce_goal.h"
#include "Eigen/Dense"
-
#include "aos/controls/polytope.h"
namespace frc971 {
-namespace control_loops {
-
-} // namespace control_loops
+namespace control_loops {} // namespace control_loops
} // namespace frc971
diff --git a/frc971/control_loops/coerce_goal.h b/frc971/control_loops/coerce_goal.h
index 6e927b0..b682b85 100644
--- a/frc971/control_loops/coerce_goal.h
+++ b/frc971/control_loops/coerce_goal.h
@@ -35,14 +35,34 @@
if (is_inside) *is_inside = true;
return R;
}
+ const Scalar norm_K = K.norm();
Eigen::Matrix<Scalar, 2, 1> parallel_vector;
Eigen::Matrix<Scalar, 2, 1> perpendicular_vector;
- perpendicular_vector = K.transpose().normalized();
+ // Calculate a vector that is perpendicular to the line defined by K * x = w.
+ perpendicular_vector = K.transpose() / norm_K;
+ // Calculate a vector that is parallel to the line defined by K * x = w.
parallel_vector << perpendicular_vector(1, 0), -perpendicular_vector(0, 0);
- Eigen::Matrix<Scalar, 4, 1> projectedh = region.static_H() * parallel_vector;
- Eigen::Matrix<Scalar, 4, 1> projectedk =
- region.static_k() - region.static_H() * perpendicular_vector * w;
+ // Calculate the location along the K x = w line where each boundary of the
+ // polytope would intersect.
+ // I.e., we want to calculate the distance along the K x = w line, as
+ // represented by
+ // parallel_vector * dist + perpendicular_vector * w / norm(K),
+ // such that it intersects with H_i * x = k_i.
+ // This gives us H_i * (parallel * dist + perp * w / norm(K)) = k_i.
+ // dist = (k_i - H_i * perp * w / norm(K)) / (H_i * parallel)
+ // projectedh is the numerator, projectedk is the denominator.
+ // The case where H_i * parallel is zero indicates a scenario where the given
+ // boundary of the polytope is parallel to the line, and so there is no
+ // meaningful value of dist to return.
+ // Note that the sign of projectedh will also indicate whether the distance is
+ // an upper or lower bound. If since valid points satisfy H_i * x < k_i, then
+ // if H_i * parallel is less than zero, then dist will be a lower bound and
+ // if it is greater than zero, then dist will be an upper bound.
+ const Eigen::Matrix<Scalar, 4, 1> projectedh =
+ region.static_H() * parallel_vector;
+ const Eigen::Matrix<Scalar, 4, 1> projectedk =
+ region.static_k() - region.static_H() * perpendicular_vector * w / norm_K;
Scalar min_boundary = ::std::numeric_limits<Scalar>::lowest();
Scalar max_boundary = ::std::numeric_limits<Scalar>::max();
@@ -50,7 +70,7 @@
if (projectedh(i, 0) > 0) {
max_boundary =
::std::min(max_boundary, projectedk(i, 0) / projectedh(i, 0));
- } else {
+ } else if (projectedh(i, 0) != 0) {
min_boundary =
::std::max(min_boundary, projectedk(i, 0) / projectedh(i, 0));
}
@@ -60,11 +80,16 @@
vertices << max_boundary, min_boundary;
if (max_boundary > min_boundary) {
+ // The line goes through the region (if the line just intersects a single
+ // vertex, then we fall through to the next clause), but R is not
+ // inside the region. The returned point will be one of the two points where
+ // the line intersects the edge of the region.
Scalar min_distance_sqr = 0;
Eigen::Matrix<Scalar, 2, 1> closest_point;
for (int i = 0; i < vertices.innerSize(); i++) {
Eigen::Matrix<Scalar, 2, 1> point;
- point = parallel_vector * vertices(0, i) + perpendicular_vector * w;
+ point =
+ parallel_vector * vertices(0, i) + perpendicular_vector * w / norm_K;
const Scalar length = (R - point).squaredNorm();
if (i == 0 || length < min_distance_sqr) {
closest_point = point;
@@ -74,6 +99,8 @@
if (is_inside) *is_inside = true;
return closest_point;
} else {
+ // The line does not pass through the region; identify the vertex closest to
+ // the line.
Eigen::Matrix<Scalar, 2, 4> region_vertices = region.StaticVertices();
#ifdef __linux__
CHECK_GT(reinterpret_cast<ssize_t>(region_vertices.outerSize()), 0);
@@ -83,8 +110,11 @@
Scalar min_distance = INFINITY;
int closest_i = 0;
for (int i = 0; i < region_vertices.outerSize(); i++) {
+ // Calculate the distance of the vertex from the line. The closest vertex
+ // will be the one to return.
const Scalar length = ::std::abs(
- (perpendicular_vector.transpose() * (region_vertices.col(i)))(0, 0));
+ (perpendicular_vector.transpose() * (region_vertices.col(i)))(0, 0) -
+ w);
if (i == 0 || length < min_distance) {
closest_i = i;
min_distance = length;
diff --git a/frc971/control_loops/coerce_goal_test.cc b/frc971/control_loops/coerce_goal_test.cc
new file mode 100644
index 0000000..ae04d6c
--- /dev/null
+++ b/frc971/control_loops/coerce_goal_test.cc
@@ -0,0 +1,217 @@
+#include "frc971/control_loops/coerce_goal.h"
+
+#include <unistd.h>
+
+#include "aos/controls/polytope.h"
+#include "gtest/gtest.h"
+
+namespace frc971 {
+namespace control_loops {
+
+namespace {
+
+aos::controls::HVPolytope<2, 4, 4> MakeBox(double x1_min, double x1_max,
+ double x2_min, double x2_max) {
+ Eigen::Matrix<double, 4, 2> box_H;
+ box_H << /*[[*/ 1.0, 0.0 /*]*/,
+ /*[*/ -1.0, 0.0 /*]*/,
+ /*[*/ 0.0, 1.0 /*]*/,
+ /*[*/ 0.0, -1.0 /*]]*/;
+ Eigen::Matrix<double, 4, 1> box_k;
+ box_k << /*[[*/ x1_max /*]*/,
+ /*[*/ -x1_min /*]*/,
+ /*[*/ x2_max /*]*/,
+ /*[*/ -x2_min /*]]*/;
+ aos::controls::HPolytope<2> t_poly(box_H, box_k);
+ return aos::controls::HVPolytope<2, 4, 4>(t_poly.H(), t_poly.k(),
+ t_poly.Vertices());
+}
+} // namespace
+
+class CoerceGoalTest : public ::testing::Test {
+ public:
+ void SetUp() override { aos::controls::HPolytope<2>::Init(); }
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+};
+
+
+TEST_F(CoerceGoalTest, Inside) {
+ aos::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
+
+ Eigen::Matrix<double, 1, 2> K;
+ K << /*[[*/ 1, -1 /*]]*/;
+
+ Eigen::Matrix<double, 2, 1> R;
+ R << /*[[*/ 1.5, 1.5 /*]]*/;
+
+ Eigen::Matrix<double, 2, 1> output =
+ frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
+
+ EXPECT_EQ(R(0, 0), output(0, 0));
+ EXPECT_EQ(R(1, 0), output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, LineOutside) {
+ aos::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
+
+ // Make a line equivalent to y = -x, which does not pass through the box and
+ // is nearest the box at (1, 1).
+ Eigen::Matrix<double, 1, 2> K;
+ K << 1, 1;
+
+ Eigen::Matrix<double, 2, 1> R;
+ R << /*[[*/ 0.0, 0.0 /*]]*/;
+
+ Eigen::Matrix<double, 2, 1> output =
+ frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
+
+ EXPECT_EQ(1.0, output(0, 0));
+ EXPECT_EQ(1.0, output(1, 0));
+
+ // Test the same line, but on the other side of the box, where the (2, 2)
+ // vertex will be closest.
+ output = frc971::control_loops::CoerceGoal<double>(box, K, 5, R);
+ EXPECT_EQ(2.0, output(0, 0));
+ EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, GoalOutsideLineInsideThroughOrigin) {
+ aos::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
+
+ Eigen::Matrix<double, 1, 2> K;
+ K << 1, -1;
+
+ Eigen::Matrix<double, 2, 1> R;
+ R << 5, 5;
+
+ Eigen::Matrix<double, 2, 1> output =
+ frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
+
+ EXPECT_EQ(2.0, output(0, 0));
+ EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, GoalOutsideLineNotThroughOrigin) {
+ aos::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
+
+ Eigen::Matrix<double, 1, 2> K;
+ K << 1, 1;
+
+ Eigen::Matrix<double, 2, 1> R;
+ R << 0, 3;
+
+ Eigen::Matrix<double, 2, 1> output =
+ frc971::control_loops::CoerceGoal<double>(box, K, 3, R);
+
+ EXPECT_EQ(1.0, output(0, 0));
+ EXPECT_DOUBLE_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, GoalOutsideLineThroughVertex) {
+ aos::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
+
+ Eigen::Matrix<double, 1, 2> K;
+ K << 1, -1;
+
+ Eigen::Matrix<double, 2, 1> R;
+ R << 5, 5;
+
+ Eigen::Matrix<double, 2, 1> output =
+ frc971::control_loops::CoerceGoal<double>(box, K, 1, R);
+
+ EXPECT_EQ(2.0, output(0, 0));
+ EXPECT_EQ(1.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, LineAndGoalOutside) {
+ aos::controls::HVPolytope<2, 4, 4> box = MakeBox(3, 4, 1, 2);
+
+ Eigen::Matrix<double, 1, 2> K;
+ K << 1, -1;
+
+ Eigen::Matrix<double, 2, 1> R;
+ R << 5, 5;
+
+ Eigen::Matrix<double, 2, 1> output =
+ frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
+
+ EXPECT_EQ(3.0, output(0, 0));
+ EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, LineThroughEdgeOfBox) {
+ aos::controls::HVPolytope<2, 4, 4> box = MakeBox(0, 4, 1, 2);
+
+ Eigen::Matrix<double, 1, 2> K;
+ K << -1, 1;
+
+ Eigen::Matrix<double, 2, 1> R;
+ R << 5, 5;
+
+ Eigen::Matrix<double, 2, 1> output =
+ frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
+
+ EXPECT_EQ(2.0, output(0, 0));
+ EXPECT_EQ(2.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, PerpendicularLine) {
+ aos::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
+
+ Eigen::Matrix<double, 1, 2> K;
+ K << 1, 1;
+
+ Eigen::Matrix<double, 2, 1> R;
+ R << 5, 5;
+
+ Eigen::Matrix<double, 2, 1> output =
+ frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
+
+ EXPECT_EQ(1.0, output(0, 0));
+ EXPECT_EQ(1.0, output(1, 0));
+}
+
+TEST_F(CoerceGoalTest, WithinRegion) {
+ const auto upoly = MakeBox(-12.0, 12.0, -12.0, 12.0);
+ Eigen::Matrix<double, 1, 2> k;
+ k << 2, 2;
+
+ Eigen::Matrix<double, 2, 1> goal;
+ goal << -2, 2;
+
+ auto result = CoerceGoal<double>(upoly, k, 0, goal);
+
+ EXPECT_EQ(result(0, 0), goal(0, 0));
+ EXPECT_EQ(result(1, 0), goal(1, 0));
+}
+
+TEST_F(CoerceGoalTest, VerticalLine) {
+ const auto upoly = MakeBox(-12.0, 12.0, -12.0, 12.0);
+ Eigen::Matrix<double, 1, 2> k;
+ k << 2, 0;
+
+ Eigen::Matrix<double, 2, 1> goal;
+ goal << 0, 13;
+
+ auto result = CoerceGoal<double>(upoly, k, 0, goal);
+
+ EXPECT_EQ(result(0, 0), 0);
+ EXPECT_EQ(result(1, 0), 12);
+}
+
+TEST_F(CoerceGoalTest, HorizontalLine) {
+ const auto upoly = MakeBox(-12.0, 12.0, -12.0, 12.0);
+ Eigen::Matrix<double, 1, 2> k;
+ k << 0, 2;
+
+ Eigen::Matrix<double, 2, 1> goal;
+ goal << 13, 2;
+
+ auto result = CoerceGoal<double>(upoly, k, 0, goal);
+
+ EXPECT_EQ(result(0, 0), 12);
+ EXPECT_EQ(result(1, 0), 0);
+}
+
+} // namespace control_loops
+} // namespace frc971
diff --git a/frc971/control_loops/drivetrain/BUILD b/frc971/control_loops/drivetrain/BUILD
index a723d96..6f46965 100644
--- a/frc971/control_loops/drivetrain/BUILD
+++ b/frc971/control_loops/drivetrain/BUILD
@@ -106,7 +106,8 @@
":drivetrain_status_fbs",
":drivetrain_position_fbs",
":localizer_fbs",
- "//frc971/queues:gyro",
+ "//frc971/queues:gyro_fbs",
+ "//frc971/queues:gyro_uid_fbs",
"//frc971/wpilib:imu_fbs",
],
visibility = ["//visibility:public"],
@@ -382,7 +383,7 @@
"//aos/controls:control_loop",
"//aos/util:log_interval",
"//frc971/control_loops:runge_kutta",
- "//frc971/queues:gyro",
+ "//frc971/queues:gyro_fbs",
"//frc971/wpilib:imu_fbs",
],
)
@@ -403,7 +404,7 @@
"//aos/testing:googletest",
"//frc971/control_loops:control_loops_fbs",
"//frc971/control_loops:state_feedback_loop",
- "//frc971/queues:gyro",
+ "//frc971/queues:gyro_fbs",
"//y2016:constants",
"//y2016/control_loops/drivetrain:polydrivetrain_plants",
],
@@ -434,7 +435,7 @@
":drivetrain_test_lib",
"//aos/controls:control_loop_test",
"//aos/testing:googletest",
- "//frc971/queues:gyro",
+ "//frc971/queues:gyro_fbs",
] + cpu_select({
"amd64": [
"//third_party/matplotlib-cpp",
@@ -641,3 +642,31 @@
"arm": [],
}),
)
+
+cc_library(
+ name = "improved_down_estimator",
+ srcs = [
+ "improved_down_estimator.cc",
+ ],
+ hdrs = [
+ "improved_down_estimator.h",
+ ],
+ deps = [
+ "//frc971/control_loops:runge_kutta",
+ "@com_github_google_glog//:glog",
+ "@org_tuxfamily_eigen//:eigen",
+ ],
+)
+
+cc_test(
+ name = "improved_down_estimator_test",
+ srcs = [
+ "improved_down_estimator_test.cc",
+ ],
+ deps = [
+ "//aos/testing:googletest",
+ "//aos/testing:random_seed",
+ "//frc971/control_loops/drivetrain:improved_down_estimator",
+ "@org_tuxfamily_eigen//:eigen",
+ ],
+)
diff --git a/frc971/control_loops/drivetrain/drivetrain_config.json b/frc971/control_loops/drivetrain/drivetrain_config.json
index dc828bb..df64659 100644
--- a/frc971/control_loops/drivetrain/drivetrain_config.json
+++ b/frc971/control_loops/drivetrain/drivetrain_config.json
@@ -13,6 +13,11 @@
},
{
"name": "/drivetrain",
+ "type": "frc971.sensors.Uid",
+ "frequency": 200
+ },
+ {
+ "name": "/drivetrain",
"type": "frc971.control_loops.drivetrain.Goal",
"frequency": 200
},
diff --git a/frc971/control_loops/drivetrain/drivetrain_lib_test.cc b/frc971/control_loops/drivetrain/drivetrain_lib_test.cc
index 3b668dd..a289fed 100644
--- a/frc971/control_loops/drivetrain/drivetrain_lib_test.cc
+++ b/frc971/control_loops/drivetrain/drivetrain_lib_test.cc
@@ -1414,109 +1414,6 @@
EXPECT_EQ(1.0, localizer_.theta());
}
-::aos::controls::HVPolytope<2, 4, 4> MakeBox(double x1_min, double x1_max,
- double x2_min, double x2_max) {
- Eigen::Matrix<double, 4, 2> box_H;
- box_H << /*[[*/ 1.0, 0.0 /*]*/,
- /*[*/ -1.0, 0.0 /*]*/,
- /*[*/ 0.0, 1.0 /*]*/,
- /*[*/ 0.0, -1.0 /*]]*/;
- Eigen::Matrix<double, 4, 1> box_k;
- box_k << /*[[*/ x1_max /*]*/,
- /*[*/ -x1_min /*]*/,
- /*[*/ x2_max /*]*/,
- /*[*/ -x2_min /*]]*/;
- ::aos::controls::HPolytope<2> t_poly(box_H, box_k);
- return ::aos::controls::HVPolytope<2, 4, 4>(t_poly.H(), t_poly.k(),
- t_poly.Vertices());
-}
-
-class CoerceGoalTest : public ::testing::Test {
- public:
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW
-};
-
-// WHOOOHH!
-TEST_F(CoerceGoalTest, Inside) {
- ::aos::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
-
- Eigen::Matrix<double, 1, 2> K;
- K << /*[[*/ 1, -1 /*]]*/;
-
- Eigen::Matrix<double, 2, 1> R;
- R << /*[[*/ 1.5, 1.5 /*]]*/;
-
- Eigen::Matrix<double, 2, 1> output =
- ::frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
-
- EXPECT_EQ(R(0, 0), output(0, 0));
- EXPECT_EQ(R(1, 0), output(1, 0));
-}
-
-TEST_F(CoerceGoalTest, Outside_Inside_Intersect) {
- ::aos::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
-
- Eigen::Matrix<double, 1, 2> K;
- K << 1, -1;
-
- Eigen::Matrix<double, 2, 1> R;
- R << 5, 5;
-
- Eigen::Matrix<double, 2, 1> output =
- ::frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
-
- EXPECT_EQ(2.0, output(0, 0));
- EXPECT_EQ(2.0, output(1, 0));
-}
-
-TEST_F(CoerceGoalTest, Outside_Inside_no_Intersect) {
- ::aos::controls::HVPolytope<2, 4, 4> box = MakeBox(3, 4, 1, 2);
-
- Eigen::Matrix<double, 1, 2> K;
- K << 1, -1;
-
- Eigen::Matrix<double, 2, 1> R;
- R << 5, 5;
-
- Eigen::Matrix<double, 2, 1> output =
- ::frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
-
- EXPECT_EQ(3.0, output(0, 0));
- EXPECT_EQ(2.0, output(1, 0));
-}
-
-TEST_F(CoerceGoalTest, Middle_Of_Edge) {
- ::aos::controls::HVPolytope<2, 4, 4> box = MakeBox(0, 4, 1, 2);
-
- Eigen::Matrix<double, 1, 2> K;
- K << -1, 1;
-
- Eigen::Matrix<double, 2, 1> R;
- R << 5, 5;
-
- Eigen::Matrix<double, 2, 1> output =
- ::frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
-
- EXPECT_EQ(2.0, output(0, 0));
- EXPECT_EQ(2.0, output(1, 0));
-}
-
-TEST_F(CoerceGoalTest, PerpendicularLine) {
- ::aos::controls::HVPolytope<2, 4, 4> box = MakeBox(1, 2, 1, 2);
-
- Eigen::Matrix<double, 1, 2> K;
- K << 1, 1;
-
- Eigen::Matrix<double, 2, 1> R;
- R << 5, 5;
-
- Eigen::Matrix<double, 2, 1> output =
- ::frc971::control_loops::CoerceGoal<double>(box, K, 0, R);
-
- EXPECT_EQ(1.0, output(0, 0));
- EXPECT_EQ(1.0, output(1, 0));
-}
-
// TODO(austin): Make sure the profile reset code when we disable works.
} // namespace testing
diff --git a/frc971/control_loops/drivetrain/improved_down_estimator.cc b/frc971/control_loops/drivetrain/improved_down_estimator.cc
new file mode 100644
index 0000000..40dc8e3
--- /dev/null
+++ b/frc971/control_loops/drivetrain/improved_down_estimator.cc
@@ -0,0 +1,287 @@
+#include "frc971/control_loops/drivetrain/improved_down_estimator.h"
+
+#include "Eigen/Dense"
+#include "Eigen/Geometry"
+
+namespace frc971 {
+namespace control_loops {
+namespace drivetrain {
+
+Eigen::Matrix<double, 4, 1> ToQuaternionFromRotationVector(
+ const Eigen::Matrix<double, 3, 1> &X, const double max_angle_cap) {
+ const double unclipped_angle = X.norm();
+ const double angle_scalar =
+ (unclipped_angle > max_angle_cap) ? max_angle_cap / unclipped_angle : 1.0;
+ const double angle = unclipped_angle * angle_scalar;
+ const double half_angle = angle * 0.5;
+
+ const double half_angle_squared = half_angle * half_angle;
+
+ // sin(x)/x = 1
+ double sinx_x = 1.0;
+
+ // - x^2/3!
+ double value = half_angle_squared / 6.0;
+ sinx_x -= value;
+
+ // + x^4/5!
+ value = value * half_angle_squared / 20.0;
+ sinx_x += value;
+
+ // - x^6/7!
+ value = value * half_angle_squared / (6.0 * 7.0);
+ sinx_x -= value;
+
+ // + x^8/9!
+ value = value * half_angle_squared / (8.0 * 9.0);
+ sinx_x += value;
+
+ // - x^10/11!
+ value = value * half_angle_squared / (10.0 * 11.0);
+ sinx_x -= value;
+
+ // + x^12/13!
+ value = value * half_angle_squared / (12.0 * 13.0);
+ sinx_x += value;
+
+ // - x^14/15!
+ value = value * half_angle_squared / (14.0 * 15.0);
+ sinx_x -= value;
+
+ // + x^16/17!
+ value = value * half_angle_squared / (16.0 * 17.0);
+ sinx_x += value;
+
+ // To plot the residual in matplotlib, run:
+ // import numpy
+ // import scipy
+ // from matplotlib import pyplot
+ // x = numpy.arange(-numpy.pi, numpy.pi, 0.01)
+ // pyplot.plot(x, 1 - x**2 / scipy.misc.factorial(3) +
+ // x**4 / scipy.misc.factorial(5) -
+ // x**6 / scipy.misc.factorial(7) +
+ // x**8 / scipy.misc.factorial(9) -
+ // x ** 10 / scipy.misc.factorial(11) +
+ // x ** 12 / scipy.misc.factorial(13) -
+ // x ** 14 / scipy.misc.factorial(15) +
+ // x ** 16 / scipy.misc.factorial(17) -
+ // numpy.sin(x) / x)
+
+ const double scalar = sinx_x * 0.5;
+
+ Eigen::Matrix<double, 4, 1> result;
+ result.block<3, 1>(0, 0) = X * scalar * angle_scalar;
+ result(3, 0) = std::cos(half_angle);
+ return result;
+}
+
+inline Eigen::Matrix<double, 4, 1> MaybeFlipX(
+ const Eigen::Matrix<double, 4, 1> &X) {
+ if (X(3, 0) < 0.0) {
+ return -X;
+ } else {
+ return X;
+ }
+}
+
+Eigen::Matrix<double, 3, 1> ToRotationVectorFromQuaternion(
+ const Eigen::Matrix<double, 4, 1> &X) {
+ // TODO(austin): Verify we still need it.
+ const Eigen::Matrix<double, 4, 1> corrected_X = MaybeFlipX(X);
+ const double half_angle =
+ std::atan2(corrected_X.block<3, 1>(0, 0).norm(), corrected_X(3, 0));
+
+ const double half_angle_squared = half_angle * half_angle;
+
+ // TODO(austin): We are doing a division at the end of this. Do the taylor
+ // series expansion of x/sin(x) instead to avoid this.
+
+ // sin(x)/x = 1
+ double sinx_x = 1.0;
+
+ // - x^2/3!
+ double value = half_angle_squared / 6.0;
+ sinx_x -= value;
+
+ // + x^4/5!
+ value = value * half_angle_squared / 20.0;
+ sinx_x += value;
+
+ // - x^6/7!
+ value = value * half_angle_squared / (6.0 * 7.0);
+ sinx_x -= value;
+
+ // + x^8/9!
+ value = value * half_angle_squared / (8.0 * 9.0);
+ sinx_x += value;
+
+ // - x^10/11!
+ value = value * half_angle_squared / (10.0 * 11.0);
+ sinx_x -= value;
+
+ // + x^12/13!
+ value = value * half_angle_squared / (12.0 * 13.0);
+ sinx_x += value;
+
+ // - x^14/15!
+ value = value * half_angle_squared / (14.0 * 15.0);
+ sinx_x -= value;
+
+ // + x^16/17!
+ value = value * half_angle_squared / (16.0 * 17.0);
+ sinx_x += value;
+
+ const double scalar = 2.0 / sinx_x;
+
+ return corrected_X.block<3, 1>(0, 0) * scalar;
+}
+
+// States are X_hat_bar (position estimate) and P (Covariance)
+
+void QuaternionUkf::Predict(const Eigen::Matrix<double, 3, 1> &U,
+ const Eigen::Matrix<double, 3, 1> &measurement) {
+ // Compute the sigma points.
+ // Our system is pretty linear. The traditional way of dealing with process
+ // noise is to augment your state vector with the mean of the process noise,
+ // and augment your covariance matrix with the covariance of your process
+ // noise. Sigma points are then computed. These points are then propegated
+ // through the model. This ends up effectively meaning that perturbations
+ // from the unaugmented state with covariance P are propegated through the
+ // model, and points which are at the mean but with perturbations to simulated
+ // process noise are propegated through the system. The covariance is then
+ // calculated from this set of points, and works out to have a covariance of
+ // essentially P + Q.
+ //
+ // Since our noise is just additive, and quaternian rotation preserves
+ // distance, we can add our noise first and it'll be a good representation of
+ // our distance. This will reduce the number of math operations we need to
+ // do. If we break this assumption in the future by adding a nonlinear model
+ // somewhere in this system, we'll have to revisit this assumption.
+
+ // Now, compute the actual sigma points using the columns of S as the
+ // pertubation vectors. The last point is the original mean.
+ const Eigen::Matrix<double, 4, 3 * 2 + 1> X =
+ GenerateSigmaPoints(X_hat_, P_ + Q_);
+
+ // Now, compute Y, the sigma points which have been propegated forwards by the
+ // model.
+ Eigen::Matrix<double, 4, 3 * 2 + 1> Y;
+ for (int i = 0; i < Y.cols(); ++i) {
+ // Y = Transformed sigma points
+ Y.col(i) = A(X.col(i), U);
+ }
+
+ // We now have the sigma points after the model update.
+ // Compute the mean of the transformed sigma point
+ X_hat_ = Eigen::Quaternion<double>(QuaternionMean(Y));
+
+ // And the covariance.
+ Eigen::Matrix<double, 3, 2 * 3 + 1> Wprime;
+ Eigen::Matrix<double, 3, 3> P_prior =
+ ComputeQuaternionCovariance(X_hat_, Y, &Wprime);
+
+ // If the only obvious acceleration is that due to gravity, then accept the
+ // measurement.
+ constexpr double kUseAccelThreshold = 0.1;
+ if (std::abs(measurement.squaredNorm() - 1.0) < kUseAccelThreshold) {
+ P_ = P_prior;
+ return;
+ }
+
+ // TODO(austin): Maybe re-calculate the sigma points here before transforming
+ // them? Otherwise we can't cleanly decouple the model and measurement updates.
+
+ // Apply the measurement transform to all the sigma points to get a
+ // representation of the distribution of the measurement.
+ Eigen::Matrix<double, kNumMeasurements, 3 * 2 + 1> Z;
+ Z_hat_.setZero();
+ for (int i = 0; i < Z.cols(); ++i) {
+ Z.col(i) = H(Y.col(i));
+
+ // Compute the mean in addition.
+ Z_hat_ += Z.col(i) / Z.cols();
+ }
+
+ // Now compute the measurement covariance.
+ Eigen::Matrix<double, 3, 3> P_zz;
+ P_zz.setZero();
+ Eigen::Matrix<double, 3, 2 * 3 + 1> Zprime;
+ for (int i = 0; i < 7; ++i) {
+ // Compute the error vector for each sigma point.
+ Eigen::Matrix<double, 3, 1> Zprimei = Z.col(i) - Z_hat_;
+
+ // Now, compute the contribution of this sigma point to P_zz.
+ P_zz += 1.0 / 12.0 * Zprimei * Zprimei.transpose();
+ // Save the error for the cross-correlation matrix.
+ Zprime.col(i) = Zprimei;
+ }
+
+ // Compute the measurement error and innovation uncertanty.
+ const Eigen::Matrix<double, kNumMeasurements, kNumMeasurements> P_vv =
+ P_zz + R_;
+
+ // Now compute the cross correlation matrix P_xz.
+ Eigen::Matrix<double, 3, 3> P_xz;
+ P_xz.setZero();
+ for (int i = 0; i < 7; ++i) {
+ // Now, compute the contribution of this sigma point to P_prior.
+ P_xz += 1.0 / 12.0 * Wprime.col(i) * Zprime.col(i).transpose();
+ }
+
+ // Compute the kalman gain.
+ const Eigen::Matrix<double, 3, kNumMeasurements> K =
+ P_xz * P_vv.inverse();
+
+ // Update X_hat and the covariance P
+ X_hat_ = X_hat_ * Eigen::Quaternion<double>(ToQuaternionFromRotationVector(
+ K * (measurement - Z_hat_)));
+ P_ = P_prior - K * P_vv * K.transpose();
+}
+
+Eigen::Matrix<double, 3, 3> ComputeQuaternionCovariance(
+ const Eigen::Quaternion<double> &mean,
+ const Eigen::Matrix<double, 4, 7> &points,
+ Eigen::Matrix<double, 3, 7> *residual) {
+ Eigen::Matrix<double, 3, 3> P_prior;
+ P_prior.setZero();
+
+ for (int i = 0; i < 7; ++i) {
+ // Compute the error vector for each sigma point.
+ Eigen::Matrix<double, 3, 1> Wprimei = ToRotationVectorFromQuaternion(
+ Eigen::Quaternion<double>(mean).conjugate() *
+ Eigen::Quaternion<double>(points.col(i)));
+ // Now, compute the contribution of this sigma point to P_prior.
+ P_prior += 1.0 / 6.0 * (Wprimei * Wprimei.transpose());
+ // Save the error for the cross-correlation matrix.
+ residual->col(i) = Wprimei;
+ }
+ return P_prior / 2.0;
+}
+
+Eigen::Matrix<double, 4, 3 * 2 + 1> GenerateSigmaPoints(
+ const Eigen::Quaternion<double> &mean,
+ const Eigen::Matrix<double, 3, 3> &covariance) {
+ // Take the matrix square root.
+ Eigen::Matrix<double, 3, 3> S = covariance.llt().matrixL();
+
+ S *= std::sqrt(2.0 * 3.0);
+ // TODO(austin): Make sure the sigma points aren't outside +- PI/2.0.
+ // Otherwise they wrap on themselves and we get a mess.
+
+ // Now, compute the actual sigma points using the columns of S as the
+ // pertubation vectors. The last point is the original mean.
+ Eigen::Matrix<double, 4, 3 * 2 + 1> X;
+ for (int i = 0; i < 3; ++i) {
+ Eigen::Quaternion<double> perturbation(
+ ToQuaternionFromRotationVector(S.col(i), M_PI_2));
+
+ X.col(i * 2) = (mean * perturbation).coeffs();
+ X.col(i * 2 + 1) = (mean * perturbation.conjugate()).coeffs();
+ }
+ X.col(6) = mean.coeffs();
+ return X;
+}
+
+} // namespace drivetrain
+} // namespace control_loops
+} // namespace frc971
diff --git a/frc971/control_loops/drivetrain/improved_down_estimator.h b/frc971/control_loops/drivetrain/improved_down_estimator.h
new file mode 100644
index 0000000..2b47f9e
--- /dev/null
+++ b/frc971/control_loops/drivetrain/improved_down_estimator.h
@@ -0,0 +1,219 @@
+#ifndef FRC971_CONTROL_LOOPS_DRIVETRAIN_IMPROVED_DOWN_ESTIMATOR_H_
+#define FRC971_CONTROL_LOOPS_DRIVETRAIN_IMPROVED_DOWN_ESTIMATOR_H_
+
+#include "Eigen/Dense"
+#include "Eigen/Geometry"
+
+#include "frc971/control_loops/runge_kutta.h"
+#include "glog/logging.h"
+
+namespace frc971 {
+namespace control_loops {
+namespace drivetrain {
+
+// Function to compute the quaternion average of a bunch of quaternions. Each
+// column in the input matrix is a quaternion (optionally scaled by it's
+// weight).
+template <int SM>
+Eigen::Matrix<double, 4, 1> QuaternionMean(
+ Eigen::Matrix<double, 4, SM> input) {
+ // Algorithm to compute the average of a bunch of quaternions:
+ // http://www.acsu.buffalo.edu/~johnc/ave_quat07.pdf
+
+ Eigen::Matrix<double, 4, 4> m = input * input.transpose();
+
+ Eigen::EigenSolver<Eigen::Matrix<double, 4, 4>> solver;
+ solver.compute(m);
+
+ Eigen::EigenSolver<Eigen::Matrix<double, 4, 4>>::EigenvectorsType
+ eigenvectors = solver.eigenvectors();
+ Eigen::EigenSolver<Eigen::Matrix<double, 4, 4>>::EigenvalueType eigenvalues =
+ solver.eigenvalues();
+
+ int max_index = 0;
+ double max_eigenvalue = 0.0;
+ for (int i = 0; i < 4; ++i) {
+ const double eigenvalue = std::abs(eigenvalues(i, 0));
+ if (eigenvalue > max_eigenvalue) {
+ max_eigenvalue = eigenvalue;
+ max_index = i;
+ }
+ }
+
+ // Assume that there shouldn't be any imaginary components to the eigenvector.
+ // I can't prove this is true, but everyone else seems to assume it...
+ // TODO(james): Handle this more rigorously.
+ for (int i = 0; i < 4; ++i) {
+ CHECK_LT(eigenvectors(i, max_index).imag(), 1e-4)
+ << eigenvectors(i, max_index);
+ }
+ return eigenvectors.col(max_index).real().normalized();
+}
+
+// Converts from a quaternion to a rotation vector, where the rotation vector's
+// direction represents the axis to rotate around and its magnitude represents
+// the number of radians to rotate.
+Eigen::Matrix<double, 3, 1> ToRotationVectorFromQuaternion(
+ const Eigen::Matrix<double, 4, 1> &X);
+
+inline Eigen::Matrix<double, 3, 1> ToRotationVectorFromQuaternion(
+ const Eigen::Quaternion<double> &X) {
+ return ToRotationVectorFromQuaternion(X.coeffs());
+};
+
+// Converts from a rotation vector to a quaternion. If you supply max_angle_cap,
+// then the rotation vector's magnitude will be clipped to be no more than
+// max_angle_cap before being converted to a quaternion.
+Eigen::Matrix<double, 4, 1> ToQuaternionFromRotationVector(
+ const Eigen::Matrix<double, 3, 1> &X,
+ const double max_angle_cap = std::numeric_limits<double>::infinity());
+
+// Generates the sigma points to use in the UKF given the current estimate and
+// covariance.
+Eigen::Matrix<double, 4, 3 * 2 + 1> GenerateSigmaPoints(
+ const Eigen::Quaternion<double> &mean,
+ const Eigen::Matrix<double, 3, 3> &covariance);
+
+// Computes the covariance of the noise given the mean and the transformed sigma
+// points. The residual corresponds with the W' variable from the original
+// paper.
+Eigen::Matrix<double, 3, 3> ComputeQuaternionCovariance(
+ const Eigen::Quaternion<double> &mean,
+ const Eigen::Matrix<double, 4, 7> &points,
+ Eigen::Matrix<double, 3, 7> *residual);
+
+// This class provides a quaternion-based Kalman filter for estimating
+// orientation using a 3-axis gyro and 3-axis accelerometer. It does leave open
+// the option of overridding the system process model and the function used to
+// calculate the expected measurement (which is relevant if, e.g., the IMU is
+// not mounted horizontally in the robot).
+class QuaternionUkf {
+ public:
+ // The state is just a quaternion representing the current robot orientaiton.
+ // The zero/identity quaternion (1, 0, 0, 0) implies that the robot is
+ // position flat on the ground with a heading of zero (which, in our normal
+ // field coordinates, means pointed straight away from our driver's station
+ // wall).
+ constexpr static int kNumStates = 4;
+ // Inputs to the system--we use the (x, y, z) gyro measurements as the inputs
+ // to the system.
+ constexpr static int kNumInputs = 3;
+ // Measurements to use for correcting the estimated system state. These
+ // correspond to (x, y, z) measurements from the accelerometer.
+ constexpr static int kNumMeasurements = 3;
+ QuaternionUkf() {
+ // TODO(james): Tune the process/measurement noises.
+ R_.setIdentity();
+ R_ /= 100.0;
+
+ Q_.setIdentity();
+ Q_ /= 10000.0;
+
+ // Assume that the robot starts flat on the ground pointed straight forward.
+ X_hat_ = Eigen::Quaternion<double>(1.0, 0.0, 0.0, 0.0);
+
+ // TODO(james): Determine an appropriate starting noise estimate. Probably
+ // not too critical.
+ P_.setIdentity();
+ P_ /= 1000.0;
+ }
+
+ // Handles updating the state of the UKF, given the gyro and accelerometer
+ // measurements.
+ void Predict(const Eigen::Matrix<double, kNumInputs, 1> &U,
+ const Eigen::Matrix<double, 3, 1> &measurement);
+
+ // Returns the updated state for X after one time step, given the current
+ // state and gyro measurements.
+ virtual Eigen::Matrix<double, 4, 1> A(
+ const Eigen::Matrix<double, 4, 1> &X,
+ const Eigen::Matrix<double, kNumInputs, 1> &U) const = 0;
+
+ // Returns the current expected accelerometer measurements given the current
+ // state.
+ virtual Eigen::Matrix<double, 3, 1> H(
+ const Eigen::Matrix<double, 4, 1> &X) const = 0;
+
+ // Returns the current estimate of the robot's orientation. Note that this
+ // filter does not have anything other than the gyro with which to estimate
+ // the robot's yaw heading, and so it may need to be corrected for by upstream
+ // filters.
+ const Eigen::Quaternion<double> &X_hat() const { return X_hat_; }
+
+ Eigen::Matrix<double, 3, 1> Z_hat() const { return Z_hat_; };
+
+ private:
+ // Measurement Noise (Uncertainty)
+ Eigen::Matrix<double, kNumInputs, kNumInputs> R_;
+ // Model noise. Note that both this and P are 3 x 3 matrices, despite the
+ // state having 4 dimensions.
+ Eigen::Matrix<double, 3, 3> Q_;
+ // Current estimate covariance.
+ Eigen::Matrix<double, 3, 3> P_;
+
+ // Current state estimate.
+ Eigen::Quaternion<double> X_hat_;
+
+ // Current expected accelerometer measurement.
+ Eigen::Matrix<double, 3, 1> Z_hat_;
+};
+
+class DrivetrainUkf : public QuaternionUkf {
+ public:
+ constexpr static double kDt = 0.00505;
+
+ // UKF for http://kodlab.seas.upenn.edu/uploads/Arun/UKFpaper.pdf
+ // Reference in case the link is dead:
+ // Kraft, Edgar. "A quaternion-based unscented Kalman filter for orientation
+ // tracking." In Proceedings of the Sixth International Conference of
+ // Information Fusion, vol. 1, pp. 47-54. 2003.
+
+ // A good reference for quaternions is available at
+ // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/
+ //
+ // A good reference for angular velocity vectors with quaternions is at
+ // http://www.euclideanspace.com/physics/kinematics/angularvelocity/
+
+ // Creates a rotational velocity vector to be integrated.
+ //
+ // omega is the rotational velocity vector in body coordinates.
+ // q is a matrix with the compononents of the quaternion in it.
+ //
+ // Returns dq / dt
+ static Eigen::Vector4d QuaternionDerivative(Eigen::Vector3d omega,
+ const Eigen::Vector4d &q_matrix) {
+ Eigen::Quaternion<double> q(q_matrix);
+
+ Eigen::Quaternion<double> omega_q;
+ omega_q.w() = 0.0;
+ omega_q.vec() = 0.5 * (q * omega);
+
+ Eigen::Quaternion<double> deriv = omega_q * q;
+ return deriv.coeffs();
+ }
+
+ // Moves the robot by the provided rotation vector (U).
+ Eigen::Matrix<double, kNumStates, 1> A(
+ const Eigen::Matrix<double, kNumStates, 1> &X,
+ const Eigen::Matrix<double, kNumInputs, 1> &U) const override {
+ return RungeKutta(
+ std::bind(&QuaternionDerivative, U, std::placeholders::_1), X, kDt);
+ }
+
+ // Returns the expected accelerometer measurement (which is just going to be
+ // 1g downwards).
+ Eigen::Matrix<double, kNumMeasurements, 1> H(
+ const Eigen::Matrix<double, kNumStates, 1> &X) const override {
+ // TODO(austin): Figure out how to compute what the sensors *should* read.
+ Eigen::Quaternion<double> Xquat(X);
+ Eigen::Matrix<double, 3, 1> gprime =
+ Xquat * Eigen::Matrix<double, 3, 1>(0.0, 0.0, -1.0);
+ return gprime;
+ }
+};
+
+} // namespace drivetrain
+} // namespace control_loops
+} // namespace frc971
+
+#endif // FRC971_CONTROL_LOOPS_DRIVETRAIN_IMPROVED_DOWN_ESTIMATOR_H_
diff --git a/frc971/control_loops/drivetrain/improved_down_estimator_test.cc b/frc971/control_loops/drivetrain/improved_down_estimator_test.cc
new file mode 100644
index 0000000..db7eeee
--- /dev/null
+++ b/frc971/control_loops/drivetrain/improved_down_estimator_test.cc
@@ -0,0 +1,280 @@
+#include "frc971/control_loops/runge_kutta.h"
+
+#include <Eigen/Geometry>
+#include <random>
+
+#include "aos/testing/random_seed.h"
+#include "frc971/control_loops/drivetrain/improved_down_estimator.h"
+#include "glog/logging.h"
+#include "gtest/gtest.h"
+
+namespace frc971 {
+namespace control_loops {
+namespace testing {
+
+// Do a known transformation to see if quaternion integration is working
+// correctly.
+TEST(RungeKuttaTest, QuaternionIntegral) {
+ Eigen::Vector3d ux = Eigen::Vector3d::UnitX();
+ Eigen::Vector3d uy = Eigen::Vector3d::UnitY();
+ Eigen::Vector3d uz = Eigen::Vector3d::UnitZ();
+
+ Eigen::Quaternion<double> q(
+ Eigen::AngleAxis<double>(0.5 * M_PI, Eigen::Vector3d::UnitY()));
+
+ Eigen::Quaternion<double> q0(
+ Eigen::AngleAxis<double>(0, Eigen::Vector3d::UnitY()));
+
+ auto qux = q * ux;
+
+ VLOG(1) << "Q is w: " << q.w() << " vec: " << q.vec();
+ VLOG(1) << "ux is " << ux;
+ VLOG(1) << "qux is " << qux;
+
+ // Start by rotating around the X world vector for pi/2
+ Eigen::Quaternion<double> integral1(
+ RungeKutta(std::bind(&drivetrain::DrivetrainUkf::QuaternionDerivative, ux,
+ std::placeholders::_1),
+ q0.coeffs(), 0.5 * M_PI));
+
+ VLOG(1) << "integral1 * uz => " << integral1 * uz;
+
+ // Then rotate around the Y world vector for pi/2
+ Eigen::Quaternion<double> integral2(
+ RungeKutta(std::bind(&drivetrain::DrivetrainUkf::QuaternionDerivative, uy,
+ std::placeholders::_1),
+ integral1.normalized().coeffs(), 0.5 * M_PI));
+
+ VLOG(1) << "integral2 * uz => " << integral2 * uz;
+
+ // Then rotate around the X world vector for -pi/2
+ Eigen::Quaternion<double> integral3(
+ RungeKutta(std::bind(&drivetrain::DrivetrainUkf::QuaternionDerivative,
+ -ux, std::placeholders::_1),
+ integral2.normalized().coeffs(), 0.5 * M_PI));
+
+ integral3.normalize();
+
+ VLOG(1) << "Integral is w: " << integral1.w() << " vec: " << integral1.vec()
+ << " norm " << integral1.norm();
+
+ VLOG(1) << "Integral is w: " << integral3.w() << " vec: " << integral3.vec()
+ << " norm " << integral3.norm();
+
+ VLOG(1) << "ux => " << integral3 * ux;
+ EXPECT_NEAR(0.0, (uy - integral3 * ux).norm(), 5e-2);
+}
+
+TEST(RungeKuttaTest, Ukf) {
+ drivetrain::DrivetrainUkf dtukf;
+ Eigen::Vector3d ux = Eigen::Vector3d::UnitX();
+ Eigen::Matrix<double, 3, 1> measurement;
+ measurement.setZero();
+ dtukf.Predict(ux, measurement);
+}
+
+// Tests that small perturbations around a couple quaternions averaged out
+// return the original quaternion.
+TEST(RungeKuttaTest, QuaternionMean) {
+ Eigen::Matrix<double, 4, 7> vectors;
+ vectors.col(0) << 0, 0, 0, 1;
+ for (int i = 0; i < 3; ++i) {
+ Eigen::Matrix<double, 4, 1> perturbation;
+ perturbation.setZero();
+ perturbation(i, 0) = 0.1;
+
+ vectors.col(i * 2 + 1) = vectors.col(0) + perturbation;
+ vectors.col(i * 2 + 2) = vectors.col(0) - perturbation;
+ }
+
+ for (int i = 0; i < 7; ++i) {
+ vectors.col(i).normalize();
+ }
+
+ Eigen::Matrix<double, 4, 1> mean = drivetrain::QuaternionMean(vectors);
+
+ for (int i = 0; i < 4; ++i) {
+ EXPECT_NEAR(mean(i, 0), vectors(i, 0), 0.001) << ": Failed on index " << i;
+ }
+}
+
+// Tests that computing sigma points, and then computing the mean and covariance
+// returns the original answer.
+TEST(RungeKuttaTest, SigmaPoints) {
+ const Eigen::Quaternion<double> mean(
+ Eigen::AngleAxis<double>(M_PI / 2.0, Eigen::Vector3d::UnitX()));
+
+ Eigen::Matrix<double, 3, 3> covariance;
+ covariance << 0.4, -0.1, 0.2, -0.1, 0.6, 0.0, 0.2, 0.0, 0.5;
+ covariance *= 0.1;
+
+ const Eigen::Matrix<double, 4, 3 * 2 + 1> vectors =
+ drivetrain::GenerateSigmaPoints(mean, covariance);
+
+ const Eigen::Matrix<double, 4, 1> calculated_mean =
+ drivetrain::QuaternionMean(vectors);
+
+ VLOG(1) << "actual mean: " << mean.coeffs();
+ VLOG(1) << "calculated mean: " << calculated_mean;
+
+ Eigen::Matrix<double, 3, 3 * 2 + 1> Wprime;
+ Eigen::Matrix<double, 3, 3> calculated_covariance =
+ drivetrain::ComputeQuaternionCovariance(
+ Eigen::Quaternion<double>(calculated_mean), vectors, &Wprime);
+
+ EXPECT_NEAR(1.0,
+ (mean.conjugate().coeffs() * calculated_mean.transpose()).norm(),
+ 1e-4);
+
+ EXPECT_NEAR(0.0, (calculated_covariance - covariance).norm(), 1e-8);
+}
+
+// Tests that computing sigma points with a large covariance that will precisely
+// wrap, that we do clip the perturbations.
+TEST(RungeKuttaTest, ClippedSigmaPoints) {
+ const Eigen::Quaternion<double> mean(
+ Eigen::AngleAxis<double>(M_PI / 2.0, Eigen::Vector3d::UnitX()));
+
+ Eigen::Matrix<double, 3, 3> covariance;
+ covariance << 0.4, -0.1, 0.2, -0.1, 0.6, 0.0, 0.2, 0.0, 0.5;
+ covariance *= 100.0;
+
+ const Eigen::Matrix<double, 4, 3 * 2 + 1> vectors =
+ drivetrain::GenerateSigmaPoints(mean, covariance);
+
+ const Eigen::Matrix<double, 4, 1> calculated_mean =
+ drivetrain::QuaternionMean(vectors);
+
+ Eigen::Matrix<double, 3, 3 * 2 + 1> Wprime;
+ Eigen::Matrix<double, 3, 3> calculated_covariance =
+ drivetrain::ComputeQuaternionCovariance(
+ Eigen::Quaternion<double>(calculated_mean), vectors, &Wprime);
+
+ EXPECT_NEAR(1.0,
+ (mean.conjugate().coeffs() * calculated_mean.transpose()).norm(),
+ 1e-4);
+
+ const double calculated_covariance_norm = calculated_covariance.norm();
+ const double covariance_norm = covariance.norm();
+ EXPECT_LT(calculated_covariance_norm, covariance_norm / 2.0)
+ << "Calculated covariance should be much smaller than the original "
+ "covariance.";
+}
+
+// Tests that ToRotationVectorFromQuaternion works for a 0 rotation.
+TEST(RungeKuttaTest, ToRotationVectorFromQuaternionAtZero) {
+ Eigen::Matrix<double, 3, 1> vector =
+ drivetrain::ToRotationVectorFromQuaternion(
+ Eigen::Quaternion<double>(
+ Eigen::AngleAxis<double>(0.0, Eigen::Vector3d::UnitX()))
+ .coeffs());
+
+ EXPECT_NEAR(0.0, (vector - Eigen::Vector3d::Zero()).norm(), 1e-4);
+}
+
+// Tests that ToRotationVectorFromQuaternion works for a real rotation.
+TEST(RungeKuttaTest, ToRotationVectorFromQuaternion) {
+ Eigen::Matrix<double, 3, 1> vector =
+ drivetrain::ToRotationVectorFromQuaternion(
+ Eigen::Quaternion<double>(
+ Eigen::AngleAxis<double>(M_PI * 0.5, Eigen::Vector3d::UnitX()))
+ .coeffs());
+
+ EXPECT_NEAR(0.0, (vector - Eigen::Vector3d::UnitX() * M_PI * 0.5).norm(),
+ 1e-4);
+}
+
+// Tests that ToRotationVectorFromQuaternion works for a solution with negative
+// coefficients.
+TEST(RungeKuttaTest, ToRotationVectorFromQuaternionNegative) {
+ Eigen::Matrix<double, 3, 1> vector =
+ drivetrain::ToRotationVectorFromQuaternion(
+ Eigen::Quaternion<double>(
+ -Eigen::Quaternion<double>(
+ Eigen::AngleAxis<double>(M_PI * 0.5,
+ Eigen::Vector3d::UnitX()))
+ .coeffs())
+ .coeffs());
+
+ EXPECT_NEAR(0.0, (vector - Eigen::Vector3d::UnitX() * M_PI * 0.5).norm(),
+ 1e-4);
+}
+
+// Tests that ToQuaternionFromRotationVector works for a 0 rotation.
+TEST(RungeKuttaTest, ToQuaternionFromRotationVectorAtZero) {
+ Eigen::Matrix<double, 4, 1> quaternion =
+ drivetrain::ToQuaternionFromRotationVector(Eigen::Vector3d::Zero());
+
+ EXPECT_NEAR(0.0, (quaternion -
+ Eigen::Quaternion<double>(
+ Eigen::AngleAxis<double>(0.0, Eigen::Vector3d::UnitX()))
+ .coeffs()).norm(),
+ 1e-4);
+}
+
+// Tests that ToQuaternionFromRotationVector works for a real rotation.
+TEST(RungeKuttaTest, ToQuaternionFromRotationVector) {
+ Eigen::Matrix<double, 4, 1> quaternion =
+ drivetrain::ToQuaternionFromRotationVector(Eigen::Vector3d::UnitX() *
+ M_PI * 0.5);
+
+ EXPECT_NEAR(0.0, (quaternion -
+ Eigen::Quaternion<double>(
+ Eigen::AngleAxis<double>(
+ M_PI * 0.5, Eigen::Vector3d::UnitX())).coeffs())
+
+ .norm(),
+ 1e-4);
+}
+
+// Tests that ToQuaternionFromRotationVector correctly clips a rotation vector
+// that is too large in magnitude.
+TEST(RungeKuttaTest, ToQuaternionFromLargeRotationVector) {
+ const double kMaxAngle = 2.0;
+ const Eigen::Vector3d rotation_vector =
+ Eigen::Vector3d::UnitX() * kMaxAngle * 2.0;
+ const Eigen::Matrix<double, 3, 1> clipped_vector =
+ drivetrain::ToRotationVectorFromQuaternion(
+ drivetrain::ToQuaternionFromRotationVector(rotation_vector,
+ kMaxAngle));
+
+ EXPECT_NEAR(0.0, (rotation_vector / 2.0 - clipped_vector).norm(), 1e-4);
+}
+
+// Tests that ToQuaternionFromRotationVector and ToRotationVectorFromQuaternion
+// works for random rotations.
+TEST(RungeKuttaTest, RandomQuaternions) {
+ std::mt19937 generator(aos::testing::RandomSeed());
+ std::uniform_real_distribution<double> random_scalar(-1.0, 1.0);
+
+ for (int i = 0; i < 1000; ++i) {
+ Eigen::Matrix<double, 3, 1> axis;
+ axis << random_scalar(generator), random_scalar(generator),
+ random_scalar(generator);
+ EXPECT_GE(axis.norm(), 1e-6);
+ axis.normalize();
+
+ const double angle = random_scalar(generator) * M_PI;
+
+ Eigen::Matrix<double, 4, 1> quaternion =
+ drivetrain::ToQuaternionFromRotationVector(axis * angle);
+
+ Eigen::Quaternion<double> answer(Eigen::AngleAxis<double>(angle, axis));
+
+ EXPECT_NEAR(quaternion(3, 0), std::cos(angle / 2.0), 1e-8);
+ EXPECT_NEAR(answer.w(), std::cos(angle / 2.0), 1e-8);
+
+ EXPECT_NEAR(1.0, (answer.coeffs() * quaternion.transpose()).norm(), 1e-6);
+
+ const Eigen::Matrix<double, 3, 1> recalculated_axis =
+ drivetrain::ToRotationVectorFromQuaternion(quaternion);
+
+ EXPECT_NEAR(std::abs(angle), recalculated_axis.norm(), 1e-8);
+
+ EXPECT_NEAR(0.0, (axis * angle - recalculated_axis).norm(), 1e-8);
+ }
+}
+
+} // namespace testing
+} // namespace control_loops
+} // namespace frc971
diff --git a/frc971/control_loops/python/control_loop.py b/frc971/control_loops/python/control_loop.py
index 8bd70fe..919968e 100644
--- a/frc971/control_loops/python/control_loop.py
+++ b/frc971/control_loops/python/control_loop.py
@@ -661,3 +661,27 @@
self.Kt = 1.0 / self.Kv
# Stall Torque in N m
self.stall_torque = self.Kt * self.stall_current
+
+
+class Falcon(object):
+ """Class representing the VexPro Falcon 500 motor.
+
+ All numbers based on data from
+ https://www.vexrobotics.com/vexpro/falcon-500."""
+
+ def __init__(self):
+ # Stall Torque in N m
+ self.stall_torque = 4.69
+ # Stall Current in Amps
+ self.stall_current = 257.0
+ # Free Speed in rad / sec
+ self.free_speed = 6380.0 / 60.0 * 2.0 * numpy.pi
+ # Free Current in Amps
+ self.free_current = 1.5
+ # Resistance of the motor, divided by 2 to account for the 2 motors
+ self.resistance = 12.0 / self.stall_current
+ # Motor velocity constant
+ self.Kv = (self.free_speed /
+ (12.0 - self.resistance * self.free_current))
+ # Torque constant
+ self.Kt = self.stall_torque / self.stall_current
diff --git a/frc971/queues/BUILD b/frc971/queues/BUILD
index e440638..4005092 100644
--- a/frc971/queues/BUILD
+++ b/frc971/queues/BUILD
@@ -3,9 +3,17 @@
load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
flatbuffer_cc_library(
- name = "gyro",
+ name = "gyro_fbs",
srcs = [
"gyro.fbs",
],
gen_reflections = 1,
)
+
+flatbuffer_cc_library(
+ name = "gyro_uid_fbs",
+ srcs = [
+ "gyro_uid.fbs",
+ ],
+ gen_reflections = 1,
+)
diff --git a/frc971/queues/gyro.fbs b/frc971/queues/gyro.fbs
index 8a76678..a6dce45 100644
--- a/frc971/queues/gyro.fbs
+++ b/frc971/queues/gyro.fbs
@@ -10,9 +10,4 @@
velocity:double;
}
-// Published on "/drivetrain"
-table Uid {
- uid:uint;
-}
-
root_type GyroReading;
diff --git a/frc971/queues/gyro_uid.fbs b/frc971/queues/gyro_uid.fbs
new file mode 100644
index 0000000..05934bf
--- /dev/null
+++ b/frc971/queues/gyro_uid.fbs
@@ -0,0 +1,8 @@
+namespace frc971.sensors;
+
+// Published on "/drivetrain"
+table Uid {
+ uid:uint;
+}
+
+root_type Uid;
diff --git a/frc971/wpilib/BUILD b/frc971/wpilib/BUILD
index 18a1775..bcdd2ce 100644
--- a/frc971/wpilib/BUILD
+++ b/frc971/wpilib/BUILD
@@ -117,7 +117,8 @@
"//aos/robot_state:robot_state_fbs",
"//aos/time",
"//aos/util:phased_loop",
- "//frc971/queues:gyro",
+ "//frc971/queues:gyro_fbs",
+ "//frc971/queues:gyro_uid_fbs",
"//frc971/zeroing:averager",
],
)
diff --git a/frc971/wpilib/gyro_sender.cc b/frc971/wpilib/gyro_sender.cc
index 4f88f9e..e7273ee 100644
--- a/frc971/wpilib/gyro_sender.cc
+++ b/frc971/wpilib/gyro_sender.cc
@@ -14,6 +14,7 @@
#include "aos/time/time.h"
#include "frc971/queues/gyro_generated.h"
+#include "frc971/queues/gyro_uid_generated.h"
#include "frc971/zeroing/averager.h"
namespace frc971 {
diff --git a/frc971/wpilib/gyro_sender.h b/frc971/wpilib/gyro_sender.h
index 8125598..a0048fb 100644
--- a/frc971/wpilib/gyro_sender.h
+++ b/frc971/wpilib/gyro_sender.h
@@ -9,6 +9,7 @@
#include "aos/events/shm_event_loop.h"
#include "aos/robot_state/robot_state_generated.h"
#include "frc971/queues/gyro_generated.h"
+#include "frc971/queues/gyro_uid_generated.h"
#include "frc971/wpilib/gyro_interface.h"
#include "frc971/zeroing/averager.h"
diff --git a/frc971/zeroing/BUILD b/frc971/zeroing/BUILD
index fe95bdc..b066dea 100644
--- a/frc971/zeroing/BUILD
+++ b/frc971/zeroing/BUILD
@@ -73,3 +73,14 @@
"//aos/testing:googletest",
],
)
+
+cc_test(
+ name = "unwrap_test",
+ srcs = [
+ "unwrap_test.cc",
+ ],
+ deps = [
+ ":wrap",
+ "//aos/testing:googletest",
+ ],
+)
diff --git a/y2018/control_loops/superstructure/intake/unwrap_test.cc b/frc971/zeroing/unwrap_test.cc
similarity index 89%
rename from y2018/control_loops/superstructure/intake/unwrap_test.cc
rename to frc971/zeroing/unwrap_test.cc
index 6211846..d1e6db9 100644
--- a/y2018/control_loops/superstructure/intake/unwrap_test.cc
+++ b/frc971/zeroing/unwrap_test.cc
@@ -1,10 +1,8 @@
+#include "frc971/zeroing/wrap.h"
#include "gtest/gtest.h"
-#include "y2018/control_loops/superstructure/intake/sensor_unwrap.h"
-namespace y2018 {
-namespace control_loops {
-namespace superstructure {
-namespace intake {
+namespace frc971 {
+namespace zeroing {
namespace testing {
TEST(SensorTest, UnwrapOnce) {
@@ -65,7 +63,5 @@
}
} // namespace testing
-} // namespace intake
-} // namespace superstructure
-} // namespace control_loops
-} // namespace y2018
+} // namespace zeroing
+} // namespace frc971
diff --git a/frc971/zeroing/wrap.cc b/frc971/zeroing/wrap.cc
index 593ac97..1a0504f 100644
--- a/frc971/zeroing/wrap.cc
+++ b/frc971/zeroing/wrap.cc
@@ -5,6 +5,57 @@
namespace frc971 {
namespace zeroing {
+UnwrapSensor::UnwrapSensor(double sensor_offset, double sensor_range)
+ : sensor_offset_(sensor_offset), sensor_range_(sensor_range) {
+ Reset();
+}
+
+double UnwrapSensor::Unwrap(double current_sensor_value) {
+ // First time the function is called it will use that value to initialize the
+ // wrap calculation. This catches cases where the offset and first value
+ // difference triggers an unwanted wrap at the first calculation.
+ if (uninitialized_ == true) {
+ uninitialized_ = false;
+ } else {
+ // Calculates the lower sensor value and set the max sensor range
+ // If offset is not 0, this will correct the zeroing offset
+ const double sensor_min_value = sensor_offset_;
+ const double sensor_max_value = sensor_range_ + sensor_min_value;
+
+ // Check if provided sensor value is within the range. This to prevent the
+ // function to get out of sync. Will not throw an error, but continue and
+ // return the value + wrapped factor and not process this value.
+ if (current_sensor_value < sensor_min_value ||
+ current_sensor_value > sensor_max_value) {
+ return current_sensor_value + (sensor_range_ * wrap_count_);
+ }
+
+ // Calculate the positive or negative movement
+ const double sensor_move = current_sensor_value - sensor_last_value_;
+
+ // Function assumes that a movement of more then 1/2 of the range
+ // indicates that we wrapped, instead of moved very fast.
+ if (std::abs(sensor_move) > (sensor_range_ / 2)) {
+ if (sensor_move >= 0) {
+ // sensor moved past the sensor_min_value
+ wrap_count_ -= 1;
+ } else {
+ // sensor moved past the sensor_max_value
+ wrap_count_ += 1;
+ }
+ }
+ }
+ sensor_last_value_ = current_sensor_value;
+ // return the unwrapped sensor value
+ return current_sensor_value + (sensor_range_ * wrap_count_);
+}
+
+void UnwrapSensor::Reset() {
+ wrap_count_ = 0;
+ sensor_last_value_ = sensor_offset_;
+ uninitialized_ = true;
+}
+
float Wrap(float nearest, float value, float period) {
return remainderf(value - nearest, period) + nearest;
}
diff --git a/frc971/zeroing/wrap.h b/frc971/zeroing/wrap.h
index 976e605..f96b9fb 100644
--- a/frc971/zeroing/wrap.h
+++ b/frc971/zeroing/wrap.h
@@ -4,6 +4,40 @@
namespace frc971 {
namespace zeroing {
+// UnwrapSensor takes in a sensor value from a sensor that loops in a certain
+// interval. ex(the sensor moves from 0 to 10 and back to 0 while moving the
+// same direction) By checking for big gaps in sensor readings it assumes you
+// have wrapped either back or forwards and handles accordingly. It returns the
+// overall sensor value.
+
+class UnwrapSensor {
+ public:
+ // The sensor_offset (+ or -) present the sensor value that is 'zero'
+ // The sensor_range presents the absolute value of the sensor range from 0 to
+ // sensor_range. This will be adjusted using the sensor_offset
+ UnwrapSensor(double sensor_offset, double sensor_range);
+
+ // Takes a wrapped sensor value and unwraps it to give you its total position.
+ double Unwrap(double current_sensor_value);
+
+ void Reset();
+
+ int sensor_wrapped() const { return wrap_count_; }
+
+ private:
+ const double sensor_offset_, sensor_range_;
+
+ // The last value given from set_position, starts at offset
+ double sensor_last_value_ = sensor_offset_;
+
+ // Log if sensor is in wrapped state in either direction
+ int wrap_count_ = 0;
+
+ // function waits for first call with a value to set sensor_last_value_. Will
+ // start to calculate the spring unwrap at the second function call.
+ bool uninitialized_ = true;
+};
+
// Returns a modified value which has been wrapped such that it is +- period/2
// away from nearest.
double Wrap(double nearest, double value, double period);
diff --git a/third_party/linux/BUILD b/third_party/linux/BUILD
deleted file mode 100644
index 007b913..0000000
--- a/third_party/linux/BUILD
+++ /dev/null
@@ -1,10 +0,0 @@
-licenses(["notice"])
-
-package(default_visibility = ["//visibility:public"])
-
-filegroup(
- name = "sctp",
- srcs = [
- "sctp.h",
- ],
-)
diff --git a/third_party/linux/sctp.h b/third_party/linux/sctp.h
deleted file mode 100644
index bd82046..0000000
--- a/third_party/linux/sctp.h
+++ /dev/null
@@ -1,1105 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-/* SCTP kernel implementation
- * (C) Copyright IBM Corp. 2001, 2004
- * Copyright (c) 1999-2000 Cisco, Inc.
- * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2002 Intel Corp.
- *
- * This file is part of the SCTP kernel implementation
- *
- * This header represents the structures and constants needed to support
- * the SCTP Extension to the Sockets API.
- *
- * This SCTP implementation is free software;
- * you can redistribute it and/or modify it under the terms of
- * the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This SCTP implementation is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * ************************
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU CC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Please send any bug reports or fixes you make to the
- * email address(es):
- * lksctp developers <linux-sctp@vger.kernel.org>
- *
- * Or submit a bug report through the following website:
- * http://www.sf.net/projects/lksctp
- *
- * Written or modified by:
- * La Monte H.P. Yarroll <piggy@acm.org>
- * R. Stewart <randall@sctp.chicago.il.us>
- * K. Morneau <kmorneau@cisco.com>
- * Q. Xie <qxie1@email.mot.com>
- * Karl Knutson <karl@athena.chicago.il.us>
- * Jon Grimm <jgrimm@us.ibm.com>
- * Daisy Chang <daisyc@us.ibm.com>
- * Ryan Layer <rmlayer@us.ibm.com>
- * Ardelle Fan <ardelle.fan@intel.com>
- * Sridhar Samudrala <sri@us.ibm.com>
- * Inaky Perez-Gonzalez <inaky.gonzalez@intel.com>
- * Vlad Yasevich <vladislav.yasevich@hp.com>
- *
- * Any bugs reported given to us we will try to fix... any fixes shared will
- * be incorporated into the next SCTP release.
- */
-
-#ifndef _SCTP_H
-#define _SCTP_H
-
-#include <linux/types.h>
-#include <linux/socket.h>
-
-typedef __s32 sctp_assoc_t;
-
-/* The following symbols come from the Sockets API Extensions for
- * SCTP <draft-ietf-tsvwg-sctpsocket-07.txt>.
- */
-#define SCTP_RTOINFO 0
-#define SCTP_ASSOCINFO 1
-#define SCTP_INITMSG 2
-#define SCTP_NODELAY 3 /* Get/set nodelay option. */
-#define SCTP_AUTOCLOSE 4
-#define SCTP_SET_PEER_PRIMARY_ADDR 5
-#define SCTP_PRIMARY_ADDR 6
-#define SCTP_ADAPTATION_LAYER 7
-#define SCTP_DISABLE_FRAGMENTS 8
-#define SCTP_PEER_ADDR_PARAMS 9
-#define SCTP_DEFAULT_SEND_PARAM 10
-#define SCTP_EVENTS 11
-#define SCTP_I_WANT_MAPPED_V4_ADDR 12 /* Turn on/off mapped v4 addresses */
-#define SCTP_MAXSEG 13 /* Get/set maximum fragment. */
-#define SCTP_STATUS 14
-#define SCTP_GET_PEER_ADDR_INFO 15
-#define SCTP_DELAYED_ACK_TIME 16
-#define SCTP_DELAYED_ACK SCTP_DELAYED_ACK_TIME
-#define SCTP_DELAYED_SACK SCTP_DELAYED_ACK_TIME
-#define SCTP_CONTEXT 17
-#define SCTP_FRAGMENT_INTERLEAVE 18
-#define SCTP_PARTIAL_DELIVERY_POINT 19 /* Set/Get partial delivery point */
-#define SCTP_MAX_BURST 20 /* Set/Get max burst */
-#define SCTP_AUTH_CHUNK 21 /* Set only: add a chunk type to authenticate */
-#define SCTP_HMAC_IDENT 22
-#define SCTP_AUTH_KEY 23
-#define SCTP_AUTH_ACTIVE_KEY 24
-#define SCTP_AUTH_DELETE_KEY 25
-#define SCTP_PEER_AUTH_CHUNKS 26 /* Read only */
-#define SCTP_LOCAL_AUTH_CHUNKS 27 /* Read only */
-#define SCTP_GET_ASSOC_NUMBER 28 /* Read only */
-#define SCTP_GET_ASSOC_ID_LIST 29 /* Read only */
-#define SCTP_AUTO_ASCONF 30
-#define SCTP_PEER_ADDR_THLDS 31
-#define SCTP_RECVRCVINFO 32
-#define SCTP_RECVNXTINFO 33
-#define SCTP_DEFAULT_SNDINFO 34
-
-/* Internal Socket Options. Some of the sctp library functions are
- * implemented using these socket options.
- */
-#define SCTP_SOCKOPT_BINDX_ADD 100 /* BINDX requests for adding addrs */
-#define SCTP_SOCKOPT_BINDX_REM 101 /* BINDX requests for removing addrs. */
-#define SCTP_SOCKOPT_PEELOFF 102 /* peel off association. */
-/* Options 104-106 are deprecated and removed. Do not use this space */
-#define SCTP_SOCKOPT_CONNECTX_OLD 107 /* CONNECTX old requests. */
-#define SCTP_GET_PEER_ADDRS 108 /* Get all peer address. */
-#define SCTP_GET_LOCAL_ADDRS 109 /* Get all local address. */
-#define SCTP_SOCKOPT_CONNECTX 110 /* CONNECTX requests. */
-#define SCTP_SOCKOPT_CONNECTX3 111 /* CONNECTX requests (updated) */
-#define SCTP_GET_ASSOC_STATS 112 /* Read only */
-#define SCTP_PR_SUPPORTED 113
-#define SCTP_DEFAULT_PRINFO 114
-#define SCTP_PR_ASSOC_STATUS 115
-#define SCTP_PR_STREAM_STATUS 116
-#define SCTP_RECONFIG_SUPPORTED 117
-#define SCTP_ENABLE_STREAM_RESET 118
-#define SCTP_RESET_STREAMS 119
-#define SCTP_RESET_ASSOC 120
-#define SCTP_ADD_STREAMS 121
-#define SCTP_SOCKOPT_PEELOFF_FLAGS 122
-#define SCTP_STREAM_SCHEDULER 123
-#define SCTP_STREAM_SCHEDULER_VALUE 124
-
-/* PR-SCTP policies */
-#define SCTP_PR_SCTP_NONE 0x0000
-#define SCTP_PR_SCTP_TTL 0x0010
-#define SCTP_PR_SCTP_RTX 0x0020
-#define SCTP_PR_SCTP_PRIO 0x0030
-#define SCTP_PR_SCTP_MAX SCTP_PR_SCTP_PRIO
-#define SCTP_PR_SCTP_MASK 0x0030
-
-#define __SCTP_PR_INDEX(x) ((x >> 4) - 1)
-#define SCTP_PR_INDEX(x) __SCTP_PR_INDEX(SCTP_PR_SCTP_ ## x)
-
-#define SCTP_PR_POLICY(x) ((x) & SCTP_PR_SCTP_MASK)
-#define SCTP_PR_SET_POLICY(flags, x) \
- do { \
- flags &= ~SCTP_PR_SCTP_MASK; \
- flags |= x; \
- } while (0)
-
-#define SCTP_PR_TTL_ENABLED(x) (SCTP_PR_POLICY(x) == SCTP_PR_SCTP_TTL)
-#define SCTP_PR_RTX_ENABLED(x) (SCTP_PR_POLICY(x) == SCTP_PR_SCTP_RTX)
-#define SCTP_PR_PRIO_ENABLED(x) (SCTP_PR_POLICY(x) == SCTP_PR_SCTP_PRIO)
-
-/* For enable stream reset */
-#define SCTP_ENABLE_RESET_STREAM_REQ 0x01
-#define SCTP_ENABLE_RESET_ASSOC_REQ 0x02
-#define SCTP_ENABLE_CHANGE_ASSOC_REQ 0x04
-#define SCTP_ENABLE_STRRESET_MASK 0x07
-
-#define SCTP_STREAM_RESET_INCOMING 0x01
-#define SCTP_STREAM_RESET_OUTGOING 0x02
-
-/* These are bit fields for msghdr->msg_flags. See section 5.1. */
-/* On user space Linux, these live in <bits/socket.h> as an enum. */
-enum sctp_msg_flags {
- MSG_NOTIFICATION = 0x8000,
-#define MSG_NOTIFICATION MSG_NOTIFICATION
-};
-
-/* 5.3.1 SCTP Initiation Structure (SCTP_INIT)
- *
- * This cmsghdr structure provides information for initializing new
- * SCTP associations with sendmsg(). The SCTP_INITMSG socket option
- * uses this same data structure. This structure is not used for
- * recvmsg().
- *
- * cmsg_level cmsg_type cmsg_data[]
- * ------------ ------------ ----------------------
- * IPPROTO_SCTP SCTP_INIT struct sctp_initmsg
- */
-struct sctp_initmsg {
- __u16 sinit_num_ostreams;
- __u16 sinit_max_instreams;
- __u16 sinit_max_attempts;
- __u16 sinit_max_init_timeo;
-};
-
-/* 5.3.2 SCTP Header Information Structure (SCTP_SNDRCV)
- *
- * This cmsghdr structure specifies SCTP options for sendmsg() and
- * describes SCTP header information about a received message through
- * recvmsg().
- *
- * cmsg_level cmsg_type cmsg_data[]
- * ------------ ------------ ----------------------
- * IPPROTO_SCTP SCTP_SNDRCV struct sctp_sndrcvinfo
- */
-struct sctp_sndrcvinfo {
- __u16 sinfo_stream;
- __u16 sinfo_ssn;
- __u16 sinfo_flags;
- __u32 sinfo_ppid;
- __u32 sinfo_context;
- __u32 sinfo_timetolive;
- __u32 sinfo_tsn;
- __u32 sinfo_cumtsn;
- sctp_assoc_t sinfo_assoc_id;
-};
-
-/* 5.3.4 SCTP Send Information Structure (SCTP_SNDINFO)
- *
- * This cmsghdr structure specifies SCTP options for sendmsg().
- *
- * cmsg_level cmsg_type cmsg_data[]
- * ------------ ------------ -------------------
- * IPPROTO_SCTP SCTP_SNDINFO struct sctp_sndinfo
- */
-struct sctp_sndinfo {
- __u16 snd_sid;
- __u16 snd_flags;
- __u32 snd_ppid;
- __u32 snd_context;
- sctp_assoc_t snd_assoc_id;
-};
-
-/* 5.3.5 SCTP Receive Information Structure (SCTP_RCVINFO)
- *
- * This cmsghdr structure describes SCTP receive information
- * about a received message through recvmsg().
- *
- * cmsg_level cmsg_type cmsg_data[]
- * ------------ ------------ -------------------
- * IPPROTO_SCTP SCTP_RCVINFO struct sctp_rcvinfo
- */
-struct sctp_rcvinfo {
- __u16 rcv_sid;
- __u16 rcv_ssn;
- __u16 rcv_flags;
- __u32 rcv_ppid;
- __u32 rcv_tsn;
- __u32 rcv_cumtsn;
- __u32 rcv_context;
- sctp_assoc_t rcv_assoc_id;
-};
-
-/* 5.3.6 SCTP Next Receive Information Structure (SCTP_NXTINFO)
- *
- * This cmsghdr structure describes SCTP receive information
- * of the next message that will be delivered through recvmsg()
- * if this information is already available when delivering
- * the current message.
- *
- * cmsg_level cmsg_type cmsg_data[]
- * ------------ ------------ -------------------
- * IPPROTO_SCTP SCTP_NXTINFO struct sctp_nxtinfo
- */
-struct sctp_nxtinfo {
- __u16 nxt_sid;
- __u16 nxt_flags;
- __u32 nxt_ppid;
- __u32 nxt_length;
- sctp_assoc_t nxt_assoc_id;
-};
-
-/*
- * sinfo_flags: 16 bits (unsigned integer)
- *
- * This field may contain any of the following flags and is composed of
- * a bitwise OR of these values.
- */
-enum sctp_sinfo_flags {
- SCTP_UNORDERED = (1 << 0), /* Send/receive message unordered. */
- SCTP_ADDR_OVER = (1 << 1), /* Override the primary destination. */
- SCTP_ABORT = (1 << 2), /* Send an ABORT message to the peer. */
- SCTP_SACK_IMMEDIATELY = (1 << 3), /* SACK should be sent without delay. */
- SCTP_NOTIFICATION = MSG_NOTIFICATION, /* Next message is not user msg but notification. */
- SCTP_EOF = MSG_FIN, /* Initiate graceful shutdown process. */
-};
-
-typedef union {
- __u8 raw;
- struct sctp_initmsg init;
- struct sctp_sndrcvinfo sndrcv;
-} sctp_cmsg_data_t;
-
-/* These are cmsg_types. */
-typedef enum sctp_cmsg_type {
- SCTP_INIT, /* 5.2.1 SCTP Initiation Structure */
-#define SCTP_INIT SCTP_INIT
- SCTP_SNDRCV, /* 5.2.2 SCTP Header Information Structure */
-#define SCTP_SNDRCV SCTP_SNDRCV
- SCTP_SNDINFO, /* 5.3.4 SCTP Send Information Structure */
-#define SCTP_SNDINFO SCTP_SNDINFO
- SCTP_RCVINFO, /* 5.3.5 SCTP Receive Information Structure */
-#define SCTP_RCVINFO SCTP_RCVINFO
- SCTP_NXTINFO, /* 5.3.6 SCTP Next Receive Information Structure */
-#define SCTP_NXTINFO SCTP_NXTINFO
-} sctp_cmsg_t;
-
-/*
- * 5.3.1.1 SCTP_ASSOC_CHANGE
- *
- * Communication notifications inform the ULP that an SCTP association
- * has either begun or ended. The identifier for a new association is
- * provided by this notificaion. The notification information has the
- * following format:
- *
- */
-struct sctp_assoc_change {
- __u16 sac_type;
- __u16 sac_flags;
- __u32 sac_length;
- __u16 sac_state;
- __u16 sac_error;
- __u16 sac_outbound_streams;
- __u16 sac_inbound_streams;
- sctp_assoc_t sac_assoc_id;
- __u8 sac_info[0];
-};
-
-/*
- * sac_state: 32 bits (signed integer)
- *
- * This field holds one of a number of values that communicate the
- * event that happened to the association. They include:
- *
- * Note: The following state names deviate from the API draft as
- * the names clash too easily with other kernel symbols.
- */
-enum sctp_sac_state {
- SCTP_COMM_UP,
- SCTP_COMM_LOST,
- SCTP_RESTART,
- SCTP_SHUTDOWN_COMP,
- SCTP_CANT_STR_ASSOC,
-};
-
-/*
- * 5.3.1.2 SCTP_PEER_ADDR_CHANGE
- *
- * When a destination address on a multi-homed peer encounters a change
- * an interface details event is sent. The information has the
- * following structure:
- */
-struct sctp_paddr_change {
- __u16 spc_type;
- __u16 spc_flags;
- __u32 spc_length;
- struct sockaddr_storage spc_aaddr;
- int spc_state;
- int spc_error;
- sctp_assoc_t spc_assoc_id;
-} __attribute__((packed, aligned(4)));
-
-/*
- * spc_state: 32 bits (signed integer)
- *
- * This field holds one of a number of values that communicate the
- * event that happened to the address. They include:
- */
-enum sctp_spc_state {
- SCTP_ADDR_AVAILABLE,
- SCTP_ADDR_UNREACHABLE,
- SCTP_ADDR_REMOVED,
- SCTP_ADDR_ADDED,
- SCTP_ADDR_MADE_PRIM,
- SCTP_ADDR_CONFIRMED,
-};
-
-
-/*
- * 5.3.1.3 SCTP_REMOTE_ERROR
- *
- * A remote peer may send an Operational Error message to its peer.
- * This message indicates a variety of error conditions on an
- * association. The entire error TLV as it appears on the wire is
- * included in a SCTP_REMOTE_ERROR event. Please refer to the SCTP
- * specification [SCTP] and any extensions for a list of possible
- * error formats. SCTP error TLVs have the format:
- */
-struct sctp_remote_error {
- __u16 sre_type;
- __u16 sre_flags;
- __u32 sre_length;
- __be16 sre_error;
- sctp_assoc_t sre_assoc_id;
- __u8 sre_data[0];
-};
-
-
-/*
- * 5.3.1.4 SCTP_SEND_FAILED
- *
- * If SCTP cannot deliver a message it may return the message as a
- * notification.
- */
-struct sctp_send_failed {
- __u16 ssf_type;
- __u16 ssf_flags;
- __u32 ssf_length;
- __u32 ssf_error;
- struct sctp_sndrcvinfo ssf_info;
- sctp_assoc_t ssf_assoc_id;
- __u8 ssf_data[0];
-};
-
-/*
- * ssf_flags: 16 bits (unsigned integer)
- *
- * The flag value will take one of the following values
- *
- * SCTP_DATA_UNSENT - Indicates that the data was never put on
- * the wire.
- *
- * SCTP_DATA_SENT - Indicates that the data was put on the wire.
- * Note that this does not necessarily mean that the
- * data was (or was not) successfully delivered.
- */
-enum sctp_ssf_flags {
- SCTP_DATA_UNSENT,
- SCTP_DATA_SENT,
-};
-
-/*
- * 5.3.1.5 SCTP_SHUTDOWN_EVENT
- *
- * When a peer sends a SHUTDOWN, SCTP delivers this notification to
- * inform the application that it should cease sending data.
- */
-struct sctp_shutdown_event {
- __u16 sse_type;
- __u16 sse_flags;
- __u32 sse_length;
- sctp_assoc_t sse_assoc_id;
-};
-
-/*
- * 5.3.1.6 SCTP_ADAPTATION_INDICATION
- *
- * When a peer sends a Adaptation Layer Indication parameter , SCTP
- * delivers this notification to inform the application
- * that of the peers requested adaptation layer.
- */
-struct sctp_adaptation_event {
- __u16 sai_type;
- __u16 sai_flags;
- __u32 sai_length;
- __u32 sai_adaptation_ind;
- sctp_assoc_t sai_assoc_id;
-};
-
-/*
- * 5.3.1.7 SCTP_PARTIAL_DELIVERY_EVENT
- *
- * When a receiver is engaged in a partial delivery of a
- * message this notification will be used to indicate
- * various events.
- */
-struct sctp_pdapi_event {
- __u16 pdapi_type;
- __u16 pdapi_flags;
- __u32 pdapi_length;
- __u32 pdapi_indication;
- sctp_assoc_t pdapi_assoc_id;
-};
-
-enum { SCTP_PARTIAL_DELIVERY_ABORTED=0, };
-
-/*
- * 5.3.1.8. SCTP_AUTHENTICATION_EVENT
- *
- * When a receiver is using authentication this message will provide
- * notifications regarding new keys being made active as well as errors.
- */
-struct sctp_authkey_event {
- __u16 auth_type;
- __u16 auth_flags;
- __u32 auth_length;
- __u16 auth_keynumber;
- __u16 auth_altkeynumber;
- __u32 auth_indication;
- sctp_assoc_t auth_assoc_id;
-};
-
-enum { SCTP_AUTH_NEWKEY = 0, };
-
-/*
- * 6.1.9. SCTP_SENDER_DRY_EVENT
- *
- * When the SCTP stack has no more user data to send or retransmit, this
- * notification is given to the user. Also, at the time when a user app
- * subscribes to this event, if there is no data to be sent or
- * retransmit, the stack will immediately send up this notification.
- */
-struct sctp_sender_dry_event {
- __u16 sender_dry_type;
- __u16 sender_dry_flags;
- __u32 sender_dry_length;
- sctp_assoc_t sender_dry_assoc_id;
-};
-
-#define SCTP_STREAM_RESET_INCOMING_SSN 0x0001
-#define SCTP_STREAM_RESET_OUTGOING_SSN 0x0002
-#define SCTP_STREAM_RESET_DENIED 0x0004
-#define SCTP_STREAM_RESET_FAILED 0x0008
-struct sctp_stream_reset_event {
- __u16 strreset_type;
- __u16 strreset_flags;
- __u32 strreset_length;
- sctp_assoc_t strreset_assoc_id;
- __u16 strreset_stream_list[];
-};
-
-#define SCTP_ASSOC_RESET_DENIED 0x0004
-#define SCTP_ASSOC_RESET_FAILED 0x0008
-struct sctp_assoc_reset_event {
- __u16 assocreset_type;
- __u16 assocreset_flags;
- __u32 assocreset_length;
- sctp_assoc_t assocreset_assoc_id;
- __u32 assocreset_local_tsn;
- __u32 assocreset_remote_tsn;
-};
-
-#define SCTP_ASSOC_CHANGE_DENIED 0x0004
-#define SCTP_ASSOC_CHANGE_FAILED 0x0008
-#define SCTP_STREAM_CHANGE_DENIED SCTP_ASSOC_CHANGE_DENIED
-#define SCTP_STREAM_CHANGE_FAILED SCTP_ASSOC_CHANGE_FAILED
-struct sctp_stream_change_event {
- __u16 strchange_type;
- __u16 strchange_flags;
- __u32 strchange_length;
- sctp_assoc_t strchange_assoc_id;
- __u16 strchange_instrms;
- __u16 strchange_outstrms;
-};
-
-/*
- * Described in Section 7.3
- * Ancillary Data and Notification Interest Options
- */
-struct sctp_event_subscribe {
- __u8 sctp_data_io_event;
- __u8 sctp_association_event;
- __u8 sctp_address_event;
- __u8 sctp_send_failure_event;
- __u8 sctp_peer_error_event;
- __u8 sctp_shutdown_event;
- __u8 sctp_partial_delivery_event;
- __u8 sctp_adaptation_layer_event;
- __u8 sctp_authentication_event;
- __u8 sctp_sender_dry_event;
- __u8 sctp_stream_reset_event;
- __u8 sctp_assoc_reset_event;
- __u8 sctp_stream_change_event;
-};
-
-/*
- * 5.3.1 SCTP Notification Structure
- *
- * The notification structure is defined as the union of all
- * notification types.
- *
- */
-union sctp_notification {
- struct {
- __u16 sn_type; /* Notification type. */
- __u16 sn_flags;
- __u32 sn_length;
- } sn_header;
- struct sctp_assoc_change sn_assoc_change;
- struct sctp_paddr_change sn_paddr_change;
- struct sctp_remote_error sn_remote_error;
- struct sctp_send_failed sn_send_failed;
- struct sctp_shutdown_event sn_shutdown_event;
- struct sctp_adaptation_event sn_adaptation_event;
- struct sctp_pdapi_event sn_pdapi_event;
- struct sctp_authkey_event sn_authkey_event;
- struct sctp_sender_dry_event sn_sender_dry_event;
- struct sctp_stream_reset_event sn_strreset_event;
- struct sctp_assoc_reset_event sn_assocreset_event;
- struct sctp_stream_change_event sn_strchange_event;
-};
-
-/* Section 5.3.1
- * All standard values for sn_type flags are greater than 2^15.
- * Values from 2^15 and down are reserved.
- */
-
-enum sctp_sn_type {
- SCTP_SN_TYPE_BASE = (1<<15),
- SCTP_ASSOC_CHANGE,
-#define SCTP_ASSOC_CHANGE SCTP_ASSOC_CHANGE
- SCTP_PEER_ADDR_CHANGE,
-#define SCTP_PEER_ADDR_CHANGE SCTP_PEER_ADDR_CHANGE
- SCTP_SEND_FAILED,
-#define SCTP_SEND_FAILED SCTP_SEND_FAILED
- SCTP_REMOTE_ERROR,
-#define SCTP_REMOTE_ERROR SCTP_REMOTE_ERROR
- SCTP_SHUTDOWN_EVENT,
-#define SCTP_SHUTDOWN_EVENT SCTP_SHUTDOWN_EVENT
- SCTP_PARTIAL_DELIVERY_EVENT,
-#define SCTP_PARTIAL_DELIVERY_EVENT SCTP_PARTIAL_DELIVERY_EVENT
- SCTP_ADAPTATION_INDICATION,
-#define SCTP_ADAPTATION_INDICATION SCTP_ADAPTATION_INDICATION
- SCTP_AUTHENTICATION_EVENT,
-#define SCTP_AUTHENTICATION_INDICATION SCTP_AUTHENTICATION_EVENT
- SCTP_SENDER_DRY_EVENT,
-#define SCTP_SENDER_DRY_EVENT SCTP_SENDER_DRY_EVENT
- SCTP_STREAM_RESET_EVENT,
-#define SCTP_STREAM_RESET_EVENT SCTP_STREAM_RESET_EVENT
- SCTP_ASSOC_RESET_EVENT,
-#define SCTP_ASSOC_RESET_EVENT SCTP_ASSOC_RESET_EVENT
- SCTP_STREAM_CHANGE_EVENT,
-#define SCTP_STREAM_CHANGE_EVENT SCTP_STREAM_CHANGE_EVENT
-};
-
-/* Notification error codes used to fill up the error fields in some
- * notifications.
- * SCTP_PEER_ADDRESS_CHAGE : spc_error
- * SCTP_ASSOC_CHANGE : sac_error
- * These names should be potentially included in the draft 04 of the SCTP
- * sockets API specification.
- */
-typedef enum sctp_sn_error {
- SCTP_FAILED_THRESHOLD,
- SCTP_RECEIVED_SACK,
- SCTP_HEARTBEAT_SUCCESS,
- SCTP_RESPONSE_TO_USER_REQ,
- SCTP_INTERNAL_ERROR,
- SCTP_SHUTDOWN_GUARD_EXPIRES,
- SCTP_PEER_FAULTY,
-} sctp_sn_error_t;
-
-/*
- * 7.1.1 Retransmission Timeout Parameters (SCTP_RTOINFO)
- *
- * The protocol parameters used to initialize and bound retransmission
- * timeout (RTO) are tunable. See [SCTP] for more information on how
- * these parameters are used in RTO calculation.
- */
-struct sctp_rtoinfo {
- sctp_assoc_t srto_assoc_id;
- __u32 srto_initial;
- __u32 srto_max;
- __u32 srto_min;
-};
-
-/*
- * 7.1.2 Association Parameters (SCTP_ASSOCINFO)
- *
- * This option is used to both examine and set various association and
- * endpoint parameters.
- */
-struct sctp_assocparams {
- sctp_assoc_t sasoc_assoc_id;
- __u16 sasoc_asocmaxrxt;
- __u16 sasoc_number_peer_destinations;
- __u32 sasoc_peer_rwnd;
- __u32 sasoc_local_rwnd;
- __u32 sasoc_cookie_life;
-};
-
-/*
- * 7.1.9 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR)
- *
- * Requests that the peer mark the enclosed address as the association
- * primary. The enclosed address must be one of the association's
- * locally bound addresses. The following structure is used to make a
- * set primary request:
- */
-struct sctp_setpeerprim {
- sctp_assoc_t sspp_assoc_id;
- struct sockaddr_storage sspp_addr;
-} __attribute__((packed, aligned(4)));
-
-/*
- * 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
- *
- * Requests that the local SCTP stack use the enclosed peer address as
- * the association primary. The enclosed address must be one of the
- * association peer's addresses. The following structure is used to
- * make a set peer primary request:
- */
-struct sctp_prim {
- sctp_assoc_t ssp_assoc_id;
- struct sockaddr_storage ssp_addr;
-} __attribute__((packed, aligned(4)));
-
-/* For backward compatibility use, define the old name too */
-#define sctp_setprim sctp_prim
-
-/*
- * 7.1.11 Set Adaptation Layer Indicator (SCTP_ADAPTATION_LAYER)
- *
- * Requests that the local endpoint set the specified Adaptation Layer
- * Indication parameter for all future INIT and INIT-ACK exchanges.
- */
-struct sctp_setadaptation {
- __u32 ssb_adaptation_ind;
-};
-
-/*
- * 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS)
- *
- * Applications can enable or disable heartbeats for any peer address
- * of an association, modify an address's heartbeat interval, force a
- * heartbeat to be sent immediately, and adjust the address's maximum
- * number of retransmissions sent before an address is considered
- * unreachable. The following structure is used to access and modify an
- * address's parameters:
- */
-enum sctp_spp_flags {
- SPP_HB_ENABLE = 1<<0, /*Enable heartbeats*/
- SPP_HB_DISABLE = 1<<1, /*Disable heartbeats*/
- SPP_HB = SPP_HB_ENABLE | SPP_HB_DISABLE,
- SPP_HB_DEMAND = 1<<2, /*Send heartbeat immediately*/
- SPP_PMTUD_ENABLE = 1<<3, /*Enable PMTU discovery*/
- SPP_PMTUD_DISABLE = 1<<4, /*Disable PMTU discovery*/
- SPP_PMTUD = SPP_PMTUD_ENABLE | SPP_PMTUD_DISABLE,
- SPP_SACKDELAY_ENABLE = 1<<5, /*Enable SACK*/
- SPP_SACKDELAY_DISABLE = 1<<6, /*Disable SACK*/
- SPP_SACKDELAY = SPP_SACKDELAY_ENABLE | SPP_SACKDELAY_DISABLE,
- SPP_HB_TIME_IS_ZERO = 1<<7, /* Set HB delay to 0 */
-};
-
-struct sctp_paddrparams {
- sctp_assoc_t spp_assoc_id;
- struct sockaddr_storage spp_address;
- __u32 spp_hbinterval;
- __u16 spp_pathmaxrxt;
- __u32 spp_pathmtu;
- __u32 spp_sackdelay;
- __u32 spp_flags;
-} __attribute__((packed, aligned(4)));
-
-/*
- * 7.1.18. Add a chunk that must be authenticated (SCTP_AUTH_CHUNK)
- *
- * This set option adds a chunk type that the user is requesting to be
- * received only in an authenticated way. Changes to the list of chunks
- * will only effect future associations on the socket.
- */
-struct sctp_authchunk {
- __u8 sauth_chunk;
-};
-
-/*
- * 7.1.19. Get or set the list of supported HMAC Identifiers (SCTP_HMAC_IDENT)
- *
- * This option gets or sets the list of HMAC algorithms that the local
- * endpoint requires the peer to use.
- */
-/* This here is only used by user space as is. It might not be a good idea
- * to export/reveal the whole structure with reserved fields etc.
- */
-enum {
- SCTP_AUTH_HMAC_ID_SHA1 = 1,
- SCTP_AUTH_HMAC_ID_SHA256 = 3,
-};
-
-struct sctp_hmacalgo {
- __u32 shmac_num_idents;
- __u16 shmac_idents[];
-};
-
-/* Sadly, user and kernel space have different names for
- * this structure member, so this is to not break anything.
- */
-#define shmac_number_of_idents shmac_num_idents
-
-/*
- * 7.1.20. Set a shared key (SCTP_AUTH_KEY)
- *
- * This option will set a shared secret key which is used to build an
- * association shared key.
- */
-struct sctp_authkey {
- sctp_assoc_t sca_assoc_id;
- __u16 sca_keynumber;
- __u16 sca_keylength;
- __u8 sca_key[];
-};
-
-/*
- * 7.1.21. Get or set the active shared key (SCTP_AUTH_ACTIVE_KEY)
- *
- * This option will get or set the active shared key to be used to build
- * the association shared key.
- */
-
-struct sctp_authkeyid {
- sctp_assoc_t scact_assoc_id;
- __u16 scact_keynumber;
-};
-
-
-/*
- * 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK)
- *
- * This option will effect the way delayed acks are performed. This
- * option allows you to get or set the delayed ack time, in
- * milliseconds. It also allows changing the delayed ack frequency.
- * Changing the frequency to 1 disables the delayed sack algorithm. If
- * the assoc_id is 0, then this sets or gets the endpoints default
- * values. If the assoc_id field is non-zero, then the set or get
- * effects the specified association for the one to many model (the
- * assoc_id field is ignored by the one to one model). Note that if
- * sack_delay or sack_freq are 0 when setting this option, then the
- * current values will remain unchanged.
- */
-struct sctp_sack_info {
- sctp_assoc_t sack_assoc_id;
- uint32_t sack_delay;
- uint32_t sack_freq;
-};
-
-struct sctp_assoc_value {
- sctp_assoc_t assoc_id;
- uint32_t assoc_value;
-};
-
-struct sctp_stream_value {
- sctp_assoc_t assoc_id;
- uint16_t stream_id;
- uint16_t stream_value;
-};
-
-/*
- * 7.2.2 Peer Address Information
- *
- * Applications can retrieve information about a specific peer address
- * of an association, including its reachability state, congestion
- * window, and retransmission timer values. This information is
- * read-only. The following structure is used to access this
- * information:
- */
-struct sctp_paddrinfo {
- sctp_assoc_t spinfo_assoc_id;
- struct sockaddr_storage spinfo_address;
- __s32 spinfo_state;
- __u32 spinfo_cwnd;
- __u32 spinfo_srtt;
- __u32 spinfo_rto;
- __u32 spinfo_mtu;
-} __attribute__((packed, aligned(4)));
-
-/* Peer addresses's state. */
-/* UNKNOWN: Peer address passed by the upper layer in sendmsg or connect[x]
- * calls.
- * UNCONFIRMED: Peer address received in INIT/INIT-ACK address parameters.
- * Not yet confirmed by a heartbeat and not available for data
- * transfers.
- * ACTIVE : Peer address confirmed, active and available for data transfers.
- * INACTIVE: Peer address inactive and not available for data transfers.
- */
-enum sctp_spinfo_state {
- SCTP_INACTIVE,
- SCTP_PF,
- SCTP_ACTIVE,
- SCTP_UNCONFIRMED,
- SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */
-};
-
-/*
- * 7.2.1 Association Status (SCTP_STATUS)
- *
- * Applications can retrieve current status information about an
- * association, including association state, peer receiver window size,
- * number of unacked data chunks, and number of data chunks pending
- * receipt. This information is read-only. The following structure is
- * used to access this information:
- */
-struct sctp_status {
- sctp_assoc_t sstat_assoc_id;
- __s32 sstat_state;
- __u32 sstat_rwnd;
- __u16 sstat_unackdata;
- __u16 sstat_penddata;
- __u16 sstat_instrms;
- __u16 sstat_outstrms;
- __u32 sstat_fragmentation_point;
- struct sctp_paddrinfo sstat_primary;
-};
-
-/*
- * 7.2.3. Get the list of chunks the peer requires to be authenticated
- * (SCTP_PEER_AUTH_CHUNKS)
- *
- * This option gets a list of chunks for a specified association that
- * the peer requires to be received authenticated only.
- */
-struct sctp_authchunks {
- sctp_assoc_t gauth_assoc_id;
- __u32 gauth_number_of_chunks;
- uint8_t gauth_chunks[];
-};
-
-/* The broken spelling has been released already in lksctp-tools header,
- * so don't break anyone, now that it's fixed.
- */
-#define guth_number_of_chunks gauth_number_of_chunks
-
-/* Association states. */
-enum sctp_sstat_state {
- SCTP_EMPTY = 0,
- SCTP_CLOSED = 1,
- SCTP_COOKIE_WAIT = 2,
- SCTP_COOKIE_ECHOED = 3,
- SCTP_ESTABLISHED = 4,
- SCTP_SHUTDOWN_PENDING = 5,
- SCTP_SHUTDOWN_SENT = 6,
- SCTP_SHUTDOWN_RECEIVED = 7,
- SCTP_SHUTDOWN_ACK_SENT = 8,
-};
-
-/*
- * 8.2.6. Get the Current Identifiers of Associations
- * (SCTP_GET_ASSOC_ID_LIST)
- *
- * This option gets the current list of SCTP association identifiers of
- * the SCTP associations handled by a one-to-many style socket.
- */
-struct sctp_assoc_ids {
- __u32 gaids_number_of_ids;
- sctp_assoc_t gaids_assoc_id[];
-};
-
-/*
- * 8.3, 8.5 get all peer/local addresses in an association.
- * This parameter struct is used by SCTP_GET_PEER_ADDRS and
- * SCTP_GET_LOCAL_ADDRS socket options used internally to implement
- * sctp_getpaddrs() and sctp_getladdrs() API.
- */
-struct sctp_getaddrs_old {
- sctp_assoc_t assoc_id;
- int addr_num;
- struct sockaddr *addrs;
-};
-
-struct sctp_getaddrs {
- sctp_assoc_t assoc_id; /*input*/
- __u32 addr_num; /*output*/
- __u8 addrs[0]; /*output, variable size*/
-};
-
-/* A socket user request obtained via SCTP_GET_ASSOC_STATS that retrieves
- * association stats. All stats are counts except sas_maxrto and
- * sas_obs_rto_ipaddr. maxrto is the max observed rto + transport since
- * the last call. Will return 0 when RTO was not update since last call
- */
-struct sctp_assoc_stats {
- sctp_assoc_t sas_assoc_id; /* Input */
- /* Transport of observed max RTO */
- struct sockaddr_storage sas_obs_rto_ipaddr;
- __u64 sas_maxrto; /* Maximum Observed RTO for period */
- __u64 sas_isacks; /* SACKs received */
- __u64 sas_osacks; /* SACKs sent */
- __u64 sas_opackets; /* Packets sent */
- __u64 sas_ipackets; /* Packets received */
- __u64 sas_rtxchunks; /* Retransmitted Chunks */
- __u64 sas_outofseqtsns;/* TSN received > next expected */
- __u64 sas_idupchunks; /* Dups received (ordered+unordered) */
- __u64 sas_gapcnt; /* Gap Acknowledgements Received */
- __u64 sas_ouodchunks; /* Unordered data chunks sent */
- __u64 sas_iuodchunks; /* Unordered data chunks received */
- __u64 sas_oodchunks; /* Ordered data chunks sent */
- __u64 sas_iodchunks; /* Ordered data chunks received */
- __u64 sas_octrlchunks; /* Control chunks sent */
- __u64 sas_ictrlchunks; /* Control chunks received */
-};
-
-/*
- * 8.1 sctp_bindx()
- *
- * The flags parameter is formed from the bitwise OR of zero or more of the
- * following currently defined flags:
- */
-#define SCTP_BINDX_ADD_ADDR 0x01
-#define SCTP_BINDX_REM_ADDR 0x02
-
-/* This is the structure that is passed as an argument(optval) to
- * getsockopt(SCTP_SOCKOPT_PEELOFF).
- */
-typedef struct {
- sctp_assoc_t associd;
- int sd;
-} sctp_peeloff_arg_t;
-
-typedef struct {
- sctp_peeloff_arg_t p_arg;
- unsigned flags;
-} sctp_peeloff_flags_arg_t;
-
-/*
- * Peer Address Thresholds socket option
- */
-struct sctp_paddrthlds {
- sctp_assoc_t spt_assoc_id;
- struct sockaddr_storage spt_address;
- __u16 spt_pathmaxrxt;
- __u16 spt_pathpfthld;
-};
-
-/*
- * Socket Option for Getting the Association/Stream-Specific PR-SCTP Status
- */
-struct sctp_prstatus {
- sctp_assoc_t sprstat_assoc_id;
- __u16 sprstat_sid;
- __u16 sprstat_policy;
- __u64 sprstat_abandoned_unsent;
- __u64 sprstat_abandoned_sent;
-};
-
-struct sctp_default_prinfo {
- sctp_assoc_t pr_assoc_id;
- __u32 pr_value;
- __u16 pr_policy;
-};
-
-struct sctp_info {
- __u32 sctpi_tag;
- __u32 sctpi_state;
- __u32 sctpi_rwnd;
- __u16 sctpi_unackdata;
- __u16 sctpi_penddata;
- __u16 sctpi_instrms;
- __u16 sctpi_outstrms;
- __u32 sctpi_fragmentation_point;
- __u32 sctpi_inqueue;
- __u32 sctpi_outqueue;
- __u32 sctpi_overall_error;
- __u32 sctpi_max_burst;
- __u32 sctpi_maxseg;
- __u32 sctpi_peer_rwnd;
- __u32 sctpi_peer_tag;
- __u8 sctpi_peer_capable;
- __u8 sctpi_peer_sack;
- __u16 __reserved1;
-
- /* assoc status info */
- __u64 sctpi_isacks;
- __u64 sctpi_osacks;
- __u64 sctpi_opackets;
- __u64 sctpi_ipackets;
- __u64 sctpi_rtxchunks;
- __u64 sctpi_outofseqtsns;
- __u64 sctpi_idupchunks;
- __u64 sctpi_gapcnt;
- __u64 sctpi_ouodchunks;
- __u64 sctpi_iuodchunks;
- __u64 sctpi_oodchunks;
- __u64 sctpi_iodchunks;
- __u64 sctpi_octrlchunks;
- __u64 sctpi_ictrlchunks;
-
- /* primary transport info */
- struct sockaddr_storage sctpi_p_address;
- __s32 sctpi_p_state;
- __u32 sctpi_p_cwnd;
- __u32 sctpi_p_srtt;
- __u32 sctpi_p_rto;
- __u32 sctpi_p_hbinterval;
- __u32 sctpi_p_pathmaxrxt;
- __u32 sctpi_p_sackdelay;
- __u32 sctpi_p_sackfreq;
- __u32 sctpi_p_ssthresh;
- __u32 sctpi_p_partial_bytes_acked;
- __u32 sctpi_p_flight_size;
- __u16 sctpi_p_error;
- __u16 __reserved2;
-
- /* sctp sock info */
- __u32 sctpi_s_autoclose;
- __u32 sctpi_s_adaptation_ind;
- __u32 sctpi_s_pd_point;
- __u8 sctpi_s_nodelay;
- __u8 sctpi_s_disable_fragments;
- __u8 sctpi_s_v4mapped;
- __u8 sctpi_s_frag_interleave;
- __u32 sctpi_s_type;
- __u32 __reserved3;
-};
-
-struct sctp_reset_streams {
- sctp_assoc_t srs_assoc_id;
- uint16_t srs_flags;
- uint16_t srs_number_streams; /* 0 == ALL */
- uint16_t srs_stream_list[]; /* list if srs_num_streams is not 0 */
-};
-
-struct sctp_add_streams {
- sctp_assoc_t sas_assoc_id;
- uint16_t sas_instrms;
- uint16_t sas_outstrms;
-};
-
-/* SCTP Stream schedulers */
-enum sctp_sched_type {
- SCTP_SS_FCFS,
- SCTP_SS_DEFAULT = SCTP_SS_FCFS,
- SCTP_SS_PRIO,
- SCTP_SS_RR,
- SCTP_SS_MAX = SCTP_SS_RR
-};
-
-#endif /* _SCTP_H */
diff --git a/tools/cpp/CROSSTOOL b/tools/cpp/CROSSTOOL
index 20f47e3..c15eddf 100644
--- a/tools/cpp/CROSSTOOL
+++ b/tools/cpp/CROSSTOOL
@@ -914,7 +914,7 @@
needsPic: true
compiler_flag: "-target"
compiler_flag: "armv7a-arm-linux-gnueabif"
- compiler_flag: "--sysroot=external/linaro_linux_gcc_repo/arm-linux-gnueabihf/libc"
+ compiler_flag: "--sysroot=external/armhf_debian_rootfs"
compiler_flag: "-mfloat-abi=hard"
compiler_flag: "-mfpu=vfpv3-d16"
compiler_flag: "-nostdinc"
@@ -931,7 +931,9 @@
compiler_flag: "-isystem"
compiler_flag: "external/linaro_linux_gcc_repo/include/c++/7.4.1"
compiler_flag: "-isystem"
- compiler_flag: "external/linaro_linux_gcc_repo/arm-linux-gnueabihf/libc/usr/include"
+ compiler_flag: "external/armhf_debian_rootfs/usr/include"
+ compiler_flag: "-isystem"
+ compiler_flag: "external/armhf_debian_rootfs/usr/include/arm-linux-gnueabihf"
compiler_flag: "-isystem"
compiler_flag: "external/org_frc971/third_party"
compiler_flag: "-D__STDC_FORMAT_MACROS"
@@ -960,12 +962,14 @@
compiler_flag: "-ggdb3"
linker_flag: "-target"
linker_flag: "armv7a-arm-linux-gnueabif"
- linker_flag: "--sysroot=external/linaro_linux_gcc_repo/arm-linux-gnueabihf/libc"
+ linker_flag: "--sysroot=external/armhf_debian_rootfs"
linker_flag: "-lstdc++"
linker_flag: "-Ltools/cpp/linaro_linux_gcc/clang_more_libs"
- linker_flag: "-Lexternal/linaro_linux_gcc_repo/arm-linux-gnueabihf/lib"
- linker_flag: "-Lexternal/linaro_linux_gcc_repo/arm-linux-gnueabihf/libc/lib"
- linker_flag: "-Lexternal/linaro_linux_gcc_repo/arm-linux-gnueabihf/libc/usr/lib"
+ linker_flag: "-Lexternal/armhf_debian_rootfs/usr/lib/gcc/arm-linux-gnueabihf/8"
+ linker_flag: "-Lexternal/armhf_debian_rootfs/lib/arm-linux-gnueabihf"
+ linker_flag: "-Lexternal/armhf_debian_rootfs/usr/lib/arm-linux-gnueabihf"
+ linker_flag: "-Lexternal/armhf_debian_rootfs/lib"
+ linker_flag: "-Lexternal/armhf_debian_rootfs/usr/lib"
linker_flag: "-Lexternal/linaro_linux_gcc_repo/lib/gcc/arm-linux-gnueabihf/7.4.1"
linker_flag: "-Bexternal/linaro_linux_gcc_repo/lib/gcc/arm-linux-gnueabihf/7.4.1"
linker_flag: "-Bexternal/linaro_linux_gcc_repo/arm-linux-gnueabihf/bin"
@@ -990,12 +994,8 @@
mode: DYNAMIC
}
cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//include)%"
- cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/libc/usr/include)%"
- cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/libc/usr/lib/include)%"
- cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/libc/lib/gcc/arm-linux-gnueabihf/7.4.1/include-fixed)%"
+ cxx_builtin_include_directory: "%package(@armhf_debian_rootfs//usr/include)%"
cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//include)%/c++/7.4.1"
- cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/libc/lib/gcc/arm-linux-gnueabihf/7.4.1/include)%"
- cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/libc/lib/gcc/arm-linux-gnueabihf/7.4.1/include-fixed)%"
cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//lib/gcc/arm-linux-gnueabihf/7.4.1/include)%"
cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//lib/gcc/arm-linux-gnueabihf/7.4.1/include-fixed)%"
cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/include)%/c++/7.4.1"
diff --git a/tools/cpp/linaro_linux_gcc/BUILD b/tools/cpp/linaro_linux_gcc/BUILD
index b5ea5a5..7b7f3e5 100644
--- a/tools/cpp/linaro_linux_gcc/BUILD
+++ b/tools/cpp/linaro_linux_gcc/BUILD
@@ -1,13 +1,5 @@
package(default_visibility = ["//tools/cpp:__pkg__"])
-cc_library(
- name = "libpthread",
- srcs = [
- "clang_more_libs/libpthread.so",
- ],
- visibility = ["//visibility:public"],
-)
-
filegroup(
name = "gcc",
srcs = [
diff --git a/tools/cpp/linaro_linux_gcc/clang_more_libs/libpthread.so b/tools/cpp/linaro_linux_gcc/clang_more_libs/libpthread.so
deleted file mode 100644
index 71f034f..0000000
--- a/tools/cpp/linaro_linux_gcc/clang_more_libs/libpthread.so
+++ /dev/null
@@ -1,5 +0,0 @@
-/* GNU ld script
- Use the shared library, but some functions are only in
- the static library, so try that secondarily. */
-OUTPUT_FORMAT(elf32-littlearm)
-GROUP ( libpthread.so.0 libpthread_nonshared.a )
diff --git a/tools/cpp/static_crosstool.pb b/tools/cpp/static_crosstool.pb
index 8552dff..7261677 100644
--- a/tools/cpp/static_crosstool.pb
+++ b/tools/cpp/static_crosstool.pb
@@ -939,7 +939,7 @@
compiler_flag: "-target"
compiler_flag: "armv7a-arm-linux-gnueabif"
- compiler_flag: "--sysroot=external/linaro_linux_gcc_repo/arm-linux-gnueabihf/libc"
+ compiler_flag: "--sysroot=external/armhf_debian_rootfs"
compiler_flag: "-mfloat-abi=hard"
compiler_flag: "-mfpu=vfpv3-d16"
@@ -957,27 +957,29 @@
compiler_flag: "-isystem"
compiler_flag: "external/linaro_linux_gcc_repo/include/c++/7.4.1"
compiler_flag: "-isystem"
- compiler_flag: "external/linaro_linux_gcc_repo/arm-linux-gnueabihf/libc/usr/include"
+ compiler_flag: "external/armhf_debian_rootfs/usr/include"
+ compiler_flag: "-isystem"
+ compiler_flag: "external/armhf_debian_rootfs/usr/include/arm-linux-gnueabihf"
+ compiler_flag: "-isystem"
+ compiler_flag: "external/org_frc971/third_party"
cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//include)%"
- cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/libc/usr/include)%"
- cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/libc/usr/lib/include)%"
- cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/libc/lib/gcc/arm-linux-gnueabihf/7.4.1/include-fixed)%"
+ cxx_builtin_include_directory: "%package(@armhf_debian_rootfs//usr/include)%"
cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//include)%/c++/7.4.1"
- cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/libc/lib/gcc/arm-linux-gnueabihf/7.4.1/include)%"
- cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/libc/lib/gcc/arm-linux-gnueabihf/7.4.1/include-fixed)%"
cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//lib/gcc/arm-linux-gnueabihf/7.4.1/include)%"
cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//lib/gcc/arm-linux-gnueabihf/7.4.1/include-fixed)%"
cxx_builtin_include_directory: "%package(@linaro_linux_gcc_repo//arm-linux-gnueabihf/include)%/c++/7.4.1"
linker_flag: "-target"
linker_flag: "armv7a-arm-linux-gnueabif"
- linker_flag: "--sysroot=external/linaro_linux_gcc_repo/arm-linux-gnueabihf/libc"
+ linker_flag: "--sysroot=external/armhf_debian_rootfs"
linker_flag: "-lstdc++"
linker_flag: "-Ltools/cpp/linaro_linux_gcc/clang_more_libs"
- linker_flag: "-Lexternal/linaro_linux_gcc_repo/arm-linux-gnueabihf/lib"
- linker_flag: "-Lexternal/linaro_linux_gcc_repo/arm-linux-gnueabihf/libc/lib"
- linker_flag: "-Lexternal/linaro_linux_gcc_repo/arm-linux-gnueabihf/libc/usr/lib"
+ linker_flag: "-Lexternal/armhf_debian_rootfs/usr/lib/gcc/arm-linux-gnueabihf/8"
+ linker_flag: "-Lexternal/armhf_debian_rootfs/lib/arm-linux-gnueabihf"
+ linker_flag: "-Lexternal/armhf_debian_rootfs/usr/lib/arm-linux-gnueabihf"
+ linker_flag: "-Lexternal/armhf_debian_rootfs/lib"
+ linker_flag: "-Lexternal/armhf_debian_rootfs/usr/lib"
linker_flag: "-Lexternal/linaro_linux_gcc_repo/lib/gcc/arm-linux-gnueabihf/7.4.1"
linker_flag: "-Bexternal/linaro_linux_gcc_repo/lib/gcc/arm-linux-gnueabihf/7.4.1"
linker_flag: "-Bexternal/linaro_linux_gcc_repo/arm-linux-gnueabihf/bin"
diff --git a/y2014/BUILD b/y2014/BUILD
index b2617da..6ff529a 100644
--- a/y2014/BUILD
+++ b/y2014/BUILD
@@ -36,7 +36,7 @@
"//aos/util:log_interval",
"//frc971/autonomous:auto_fbs",
"//frc971/control_loops/drivetrain:drivetrain_status_fbs",
- "//frc971/queues:gyro",
+ "//frc971/queues:gyro_fbs",
"//y2014/actors:shoot_action_lib",
"//y2014/control_loops/claw:claw_goal_fbs",
"//y2014/control_loops/claw:claw_status_fbs",
diff --git a/y2016/BUILD b/y2016/BUILD
index 520dd4b..a96ea5a 100644
--- a/y2016/BUILD
+++ b/y2016/BUILD
@@ -38,7 +38,7 @@
"//frc971/autonomous:auto_fbs",
"//frc971/control_loops/drivetrain:drivetrain_goal_fbs",
"//frc971/control_loops/drivetrain:drivetrain_status_fbs",
- "//frc971/queues:gyro",
+ "//frc971/queues:gyro_fbs",
"//y2016/actors:autonomous_action_lib",
"//y2016/actors:superstructure_action_lib",
"//y2016/actors:vision_align_action_lib",
@@ -51,6 +51,9 @@
)
robot_downloader(
+ data = [
+ ":config.json",
+ ],
dirs = [
"//y2016/dashboard:www_files",
],
@@ -81,12 +84,17 @@
"//y2016/control_loops/superstructure:superstructure_position_fbs",
"//y2016/control_loops/superstructure:superstructure_status_fbs",
"//y2016/queues:ball_detector_fbs",
- "//y2017/vision:vision_fbs",
+ "//y2016/vision:vision_fbs",
+ "//y2019/control_loops/drivetrain:target_selector_fbs",
+ "//y2016/actors:vision_align_action_fbs",
+ "//y2016/actors:superstructure_action_fbs",
],
visibility = ["//visibility:public"],
deps = [
"//aos/robot_state:config",
+ "//frc971/autonomous:config",
"//frc971/control_loops/drivetrain:config",
+ "//frc971/wpilib:config",
],
)
diff --git a/y2016/actors/autonomous_actor.cc b/y2016/actors/autonomous_actor.cc
index a665c28..0b11bdd 100644
--- a/y2016/actors/autonomous_actor.cc
+++ b/y2016/actors/autonomous_actor.cc
@@ -64,7 +64,7 @@
actors::VisionAlignActor::MakeFactory(event_loop)),
vision_status_fetcher_(
event_loop->MakeFetcher<::y2016::vision::VisionStatus>(
- "/superstructure")),
+ "/vision")),
ball_detector_fetcher_(
event_loop->MakeFetcher<::y2016::sensors::BallDetector>(
"/superstructure")),
diff --git a/y2016/actors/vision_align_actor.cc b/y2016/actors/vision_align_actor.cc
index ae05c70..1761a72 100644
--- a/y2016/actors/vision_align_actor.cc
+++ b/y2016/actors/vision_align_actor.cc
@@ -24,7 +24,7 @@
event_loop, "/vision_align_action"),
vision_status_fetcher_(
event_loop->MakeFetcher<::y2016::vision::VisionStatus>(
- "/superstructure")),
+ "/vision")),
drivetrain_goal_sender_(
event_loop->MakeSender<::frc971::control_loops::drivetrain::Goal>(
"/drivetrain")) {}
diff --git a/y2016/dashboard/dashboard.cc b/y2016/dashboard/dashboard.cc
index 8aec0de..3361e96 100644
--- a/y2016/dashboard/dashboard.cc
+++ b/y2016/dashboard/dashboard.cc
@@ -53,13 +53,13 @@
: event_loop_(event_loop),
vision_status_fetcher_(
event_loop->MakeFetcher<::y2016::vision::VisionStatus>(
- "/superstructure")),
+ "/vision")),
ball_detector_fetcher_(
event_loop->MakeFetcher<::y2016::sensors::BallDetector>(
"/superstructure")),
autonomous_mode_fetcher_(
event_loop->MakeFetcher<::frc971::autonomous::AutonomousMode>(
- "/aos")),
+ "/autonomous")),
superstructure_status_fetcher_(
event_loop
->MakeFetcher<::y2016::control_loops::superstructure::Status>(
diff --git a/y2016/vision/target_receiver.cc b/y2016/vision/target_receiver.cc
index e9a2e1d..93ec131 100644
--- a/y2016/vision/target_receiver.cc
+++ b/y2016/vision/target_receiver.cc
@@ -305,7 +305,7 @@
::aos::ShmEventLoop event_loop(&config.message());
::aos::Sender<::y2016::vision::VisionStatus> vision_status_sender =
- event_loop.MakeSender<::y2016::vision::VisionStatus>("/superstructure");
+ event_loop.MakeSender<::y2016::vision::VisionStatus>("/vision");
StereoGeometry stereo(constants::GetValues().vision_name);
AOS_LOG(INFO, "calibration: %s\n",
diff --git a/y2016/vision/target_sender.cc b/y2016/vision/target_sender.cc
index 3e29085..41da462 100644
--- a/y2016/vision/target_sender.cc
+++ b/y2016/vision/target_sender.cc
@@ -226,7 +226,7 @@
using namespace y2016::vision;
StereoGeometry stereo("./stereo_rig.calib");
::aos::logging::Init();
- ::aos::logging::AddImplementation(
+ ::aos::logging::SetImplementation(
new ::aos::logging::StreamLogImplementation(stdout));
std::thread cam0([stereo]() {
RunCamera(0, GetCameraParams(stereo.calibration()),
diff --git a/y2016/wpilib_interface.cc b/y2016/wpilib_interface.cc
index dc828f3..5c2fcd6 100644
--- a/y2016/wpilib_interface.cc
+++ b/y2016/wpilib_interface.cc
@@ -153,7 +153,7 @@
"/superstructure")),
auto_mode_sender_(
event_loop->MakeSender<::frc971::autonomous::AutonomousMode>(
- "/aos")),
+ "/autonomous")),
shooter_position_sender_(
event_loop->MakeSender<shooter::Position>("/shooter")),
superstructure_position_sender_(
diff --git a/y2016/y2016.json b/y2016/y2016.json
index eb8ecd5..9ad4f20 100644
--- a/y2016/y2016.json
+++ b/y2016/y2016.json
@@ -45,10 +45,45 @@
"name": "/superstructure",
"type": "y2016.sensors.BallDetector",
"frequency": 200
+ },
+ {
+ "name": "/vision",
+ "type": "y2016.vision.VisionStatus",
+ "frequency": 200
+ },
+ {
+ "name": "/superstructure_action",
+ "type": "aos.common.actions.Status"
+ },
+ {
+ "name": "/vision_align_action",
+ "type": "aos.common.actions.Status"
+ },
+ {
+ "name": "/autonomous",
+ "type": "aos.common.actions.Status"
+ },
+ {
+ "name": "/autonomous",
+ "type": "frc971.autonomous.Goal"
+ },
+ {
+ "name": "/drivetrain",
+ "type": "y2019.control_loops.drivetrain.TargetSelectorHint"
+ },
+ {
+ "name": "/vision_align_action",
+ "type": "y2016.actors.vision_align_action.Goal"
+ },
+ {
+ "name": "/superstructure_action",
+ "type": "y2016.actors.superstructure_action.Goal"
}
],
"imports": [
"../aos/robot_state/robot_state_config.json",
- "../frc971/control_loops/drivetrain/drivetrain_config.json"
+ "../frc971/control_loops/drivetrain/drivetrain_config.json",
+ "../frc971/autonomous/autonomous_config.json",
+ "../frc971/wpilib/wpilib_config.json"
]
}
diff --git a/y2017/vision/target_sender.cc b/y2017/vision/target_sender.cc
index 261c397..88655c7 100644
--- a/y2017/vision/target_sender.cc
+++ b/y2017/vision/target_sender.cc
@@ -220,7 +220,7 @@
using namespace y2017::vision;
::aos::logging::Init();
- ::aos::logging::AddImplementation(
+ ::aos::logging::SetImplementation(
new ::aos::logging::StreamLogImplementation(stdout));
VisionConfig cfg;
if (ReadConfiguration("ConfigFile.pb.ascii", &cfg)) {
diff --git a/y2018/control_loops/superstructure/intake/BUILD b/y2018/control_loops/superstructure/intake/BUILD
index ea44c7a..dde7c63 100644
--- a/y2018/control_loops/superstructure/intake/BUILD
+++ b/y2018/control_loops/superstructure/intake/BUILD
@@ -39,7 +39,6 @@
visibility = ["//visibility:public"],
deps = [
":intake_plants",
- ":sensor_unwrap",
"//aos:math",
"//aos/controls:control_loop",
"//frc971/control_loops:control_loops_fbs",
@@ -50,25 +49,3 @@
"//y2018/control_loops/superstructure:superstructure_status_fbs",
],
)
-
-cc_library(
- name = "sensor_unwrap",
- srcs = [
- "sensor_unwrap.cc",
- ],
- hdrs = [
- "sensor_unwrap.h",
- ],
- visibility = ["//visibility:public"],
-)
-
-cc_test(
- name = "unwrap_test",
- srcs = [
- "unwrap_test.cc",
- ],
- deps = [
- ":sensor_unwrap",
- "//aos/testing:googletest",
- ],
-)
diff --git a/y2018/control_loops/superstructure/intake/intake.h b/y2018/control_loops/superstructure/intake/intake.h
index ac4f971..e064c0e 100644
--- a/y2018/control_loops/superstructure/intake/intake.h
+++ b/y2018/control_loops/superstructure/intake/intake.h
@@ -5,11 +5,11 @@
#include "aos/commonmath.h"
#include "aos/controls/control_loop.h"
+#include "frc971/zeroing/wrap.h"
#include "frc971/zeroing/zeroing.h"
#include "y2018/constants.h"
#include "y2018/control_loops/superstructure/intake/intake_delayed_plant.h"
#include "y2018/control_loops/superstructure/intake/intake_plant.h"
-#include "y2018/control_loops/superstructure/intake/sensor_unwrap.h"
#include "y2018/control_loops/superstructure/superstructure_output_generated.h"
#include "y2018/control_loops/superstructure/superstructure_position_generated.h"
#include "y2018/control_loops/superstructure/superstructure_status_generated.h"
@@ -121,7 +121,8 @@
return ::y2018::constants::Values::kIntakeSpringRatio() * (2 * M_PI);
}
- UnwrapSensor spring_unwrap_{spring_offset_, spring_range()};
+ ::frc971::zeroing::UnwrapSensor spring_unwrap_{spring_offset_,
+ spring_range()};
State state_ = State::UNINITIALIZED;
diff --git a/y2018/control_loops/superstructure/intake/sensor_unwrap.cc b/y2018/control_loops/superstructure/intake/sensor_unwrap.cc
deleted file mode 100644
index c7d2a03..0000000
--- a/y2018/control_loops/superstructure/intake/sensor_unwrap.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-#include "y2018/control_loops/superstructure/intake/sensor_unwrap.h"
-
-#include <cmath>
-
-namespace y2018 {
-namespace control_loops {
-namespace superstructure {
-namespace intake {
-
-UnwrapSensor::UnwrapSensor(double sensor_offset, double sensor_range)
- : sensor_offset_(sensor_offset), sensor_range_(sensor_range) {
- Reset();
-}
-
-double UnwrapSensor::Unwrap(double current_sensor_value) {
- // First time the function is called it will use that value to initialize the
- // wrap calculation. This catches cases where the offset and first value
- // difference triggers an unwanted wrap at the first calculation.
- if (uninitialized_ == true) {
- uninitialized_ = false;
- } else {
- // Calculates the lower sensor value and set the max sensor range
- // If offset is not 0, this will correct the zeroing offset
- const double sensor_min_value = sensor_offset_;
- const double sensor_max_value = sensor_range_ + sensor_min_value;
-
- // Check if provided sensor value is within the range. This to prevent the
- // function to get out of sync. Will not throw an error, but continue and
- // return the value + wrapped factor and not process this value.
- if (current_sensor_value < sensor_min_value ||
- current_sensor_value > sensor_max_value) {
- return current_sensor_value + (sensor_range_ * wrap_count_);
- }
-
- // Calculate the positive or negative movement
- const double sensor_move = current_sensor_value - sensor_last_value_;
-
- // Function assumes that a movement of more then 1/2 of the range
- // indicates that we wrapped, instead of moved very fast.
- if (std::abs(sensor_move) > (sensor_range_ / 2)) {
- if (sensor_move >= 0) {
- // sensor moved past the sensor_min_value
- wrap_count_ -= 1;
- } else {
- // sensor moved past the sensor_max_value
- wrap_count_ += 1;
- }
- }
- }
- sensor_last_value_ = current_sensor_value;
- // return the unwrapped sensor value
- return current_sensor_value + (sensor_range_ * wrap_count_);
-}
-
-void UnwrapSensor::Reset() {
- wrap_count_ = 0;
- sensor_last_value_ = sensor_offset_;
- uninitialized_ = true;
-}
-
-} // namespace intake
-} // namespace superstructure
-} // namespace control_loops
-} // namespace y2018
diff --git a/y2018/control_loops/superstructure/intake/sensor_unwrap.h b/y2018/control_loops/superstructure/intake/sensor_unwrap.h
deleted file mode 100644
index ccb1b52..0000000
--- a/y2018/control_loops/superstructure/intake/sensor_unwrap.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef Y2018_CONTROL_LOOPS_SUPERSTRUCTURE_INTAKE_SENSOR_UNWRAP_H_
-#define Y2018_CONTROL_LOOPS_SUPERSTRUCTURE_INTAKE_SENSOR_UNWRAP_H_
-
-namespace y2018 {
-namespace control_loops {
-namespace superstructure {
-namespace intake {
-
-// UnwrapSensor takes in a sensor value from a sensor that loops in a certain
-// interval. ex(the sensor moves from 0 to 10 and back to 0 while moving the
-// same direction) By checking for big gaps in sensor readings it assumes you
-// have wrapped either back or forwards and handles accordingly. It returns the
-// overall sensor value.
-
-class UnwrapSensor {
- public:
- // The sensor_offset (+ or -) present the sensor value that is 'zero'
- // The sensor_range presents the absolute value of the sensor range from 0 to
- // sensor_range. This will be adjusted using the sensor_offset
- UnwrapSensor(double sensor_offset, double sensor_range);
-
- // Takes a wrapped sensor value and unwraps it to give you its total position.
- double Unwrap(double current_sensor_value);
-
- void Reset();
-
- int sensor_wrapped() const { return wrap_count_; }
-
- private:
- const double sensor_offset_, sensor_range_;
-
- // The last value given from set_position, starts at offset
- double sensor_last_value_ = sensor_offset_;
-
- // Log if sensor is in wrapped state in either direction
- int wrap_count_ = 0;
-
- // function waits for first call with a value to set sensor_last_value_. Will
- // start to calculate the spring unwrap at the second function call.
- bool uninitialized_ = true;
-};
-
-} // namespace intake
-} // namespace superstructure
-} // namespace control_loops
-} // namespace y2018
-
-#endif // Y2018_CONTROL_LOOPS_SUPERSTRUCTURE_INTAKE_SENSOR_UNWRAP_H_
diff --git a/y2018/vision/image_streamer.cc b/y2018/vision/image_streamer.cc
index b0c1f86..fa5f4b5 100644
--- a/y2018/vision/image_streamer.cc
+++ b/y2018/vision/image_streamer.cc
@@ -289,7 +289,7 @@
int main(int argc, char ** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, false);
::aos::logging::Init();
- ::aos::logging::AddImplementation(
+ ::aos::logging::SetImplementation(
new ::aos::logging::StreamLogImplementation(stderr));
TCPServer<MjpegDataSocket> tcp_server_(80);
diff --git a/y2019/image_streamer/image_streamer.cc b/y2019/image_streamer/image_streamer.cc
index 30bea8f..6f8027c 100644
--- a/y2019/image_streamer/image_streamer.cc
+++ b/y2019/image_streamer/image_streamer.cc
@@ -308,7 +308,7 @@
int main(int argc, char **argv) {
gflags::ParseCommandLineFlags(&argc, &argv, false);
::aos::logging::Init();
- ::aos::logging::AddImplementation(
+ ::aos::logging::SetImplementation(
new ::aos::logging::StreamLogImplementation(stderr));
TCPServer<MjpegDataSocket> tcp_server_(80);
aos::vision::CameraParams params0;
diff --git a/y2019/vision/debug_serial.cc b/y2019/vision/debug_serial.cc
index 857f20f..c707d1f 100644
--- a/y2019/vision/debug_serial.cc
+++ b/y2019/vision/debug_serial.cc
@@ -24,7 +24,7 @@
using namespace frc971::jevois;
// gflags::ParseCommandLineFlags(&argc, &argv, false);
::aos::logging::Init();
- ::aos::logging::AddImplementation(
+ ::aos::logging::SetImplementation(
new ::aos::logging::StreamLogImplementation(stderr));
int flags = fcntl(0, F_GETFL, 0);
diff --git a/y2019/vision/global_calibration.cc b/y2019/vision/global_calibration.cc
index e2c4490..52a6e52 100644
--- a/y2019/vision/global_calibration.cc
+++ b/y2019/vision/global_calibration.cc
@@ -103,7 +103,7 @@
};
::aos::logging::Init();
- ::aos::logging::AddImplementation(
+ ::aos::logging::SetImplementation(
new ::aos::logging::StreamLogImplementation(stderr));
TargetFinder target_finder;
diff --git a/y2020/BUILD b/y2020/BUILD
new file mode 100644
index 0000000..17d3020
--- /dev/null
+++ b/y2020/BUILD
@@ -0,0 +1,125 @@
+load("//frc971:downloader.bzl", "robot_downloader")
+load("//aos:config.bzl", "aos_config")
+load("@com_google_protobuf//:protobuf.bzl", "cc_proto_library")
+load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
+
+robot_downloader(
+ data = [
+ ":config.json",
+ ],
+ start_binaries = [
+ ":joystick_reader",
+ ":wpilib_interface",
+ "//y2020/control_loops/drivetrain:drivetrain",
+ "//y2020/control_loops/superstructure:superstructure",
+ "//y2020/actors:binaries",
+ ],
+)
+
+cc_library(
+ name = "constants",
+ srcs = [
+ "constants.cc",
+ ],
+ hdrs = [
+ "constants.h",
+ ],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//aos/logging",
+ "//aos/mutex",
+ "//aos/network:team_number",
+ "//frc971:constants",
+ "//frc971/control_loops:pose",
+ "//frc971/control_loops:static_zeroing_single_dof_profiled_subsystem",
+ "//y2020/control_loops/drivetrain:polydrivetrain_plants",
+ "@com_google_absl//absl/base",
+ ],
+)
+
+cc_binary(
+ name = "wpilib_interface",
+ srcs = [
+ "wpilib_interface.cc",
+ ],
+ restricted_to = ["//tools:roborio"],
+ deps = [
+ ":constants",
+ "//aos:init",
+ "//aos:make_unique",
+ "//aos:math",
+ "//aos/controls:control_loop",
+ "//aos/events:shm_event_loop",
+ "//aos/logging",
+ "//aos/robot_state:robot_state_fbs",
+ "//aos/stl_mutex",
+ "//aos/time",
+ "//aos/util:log_interval",
+ "//aos/util:phased_loop",
+ "//aos/util:wrapping_counter",
+ "//frc971/autonomous:auto_mode_fbs",
+ "//frc971/control_loops:control_loops_fbs",
+ "//frc971/control_loops/drivetrain:drivetrain_position_fbs",
+ "//frc971/wpilib:ADIS16448",
+ "//frc971/wpilib:buffered_pcm",
+ "//frc971/wpilib:drivetrain_writer",
+ "//frc971/wpilib:encoder_and_potentiometer",
+ "//frc971/wpilib:interrupt_edge_counting",
+ "//frc971/wpilib:joystick_sender",
+ "//frc971/wpilib:logging_fbs",
+ "//frc971/wpilib:loop_output_handler",
+ "//frc971/wpilib:pdp_fetcher",
+ "//frc971/wpilib:sensor_reader",
+ "//frc971/wpilib:wpilib_interface",
+ "//frc971/wpilib:wpilib_robot_base",
+ "//third_party:phoenix",
+ "//third_party:wpilib",
+ "//y2020/control_loops/superstructure:superstructure_output_fbs",
+ "//y2020/control_loops/superstructure:superstructure_position_fbs",
+ ],
+)
+
+cc_binary(
+ name = "joystick_reader",
+ srcs = [
+ ":joystick_reader.cc",
+ ],
+ deps = [
+ "//aos:init",
+ "//aos/actions:action_lib",
+ "//aos/input:action_joystick_input",
+ "//aos/input:drivetrain_input",
+ "//aos/input:joystick_input",
+ "//aos/logging",
+ "//frc971/autonomous:auto_fbs",
+ "//frc971/autonomous:base_autonomous_actor",
+ "//frc971/control_loops:profiled_subsystem_fbs",
+ "//y2020/control_loops/drivetrain:drivetrain_base",
+ "//y2020/control_loops/superstructure:superstructure_goal_fbs",
+ "//y2020/control_loops/superstructure:superstructure_status_fbs",
+ ],
+)
+
+aos_config(
+ name = "config",
+ src = "y2020.json",
+ flatbuffers = [
+ "//y2020/control_loops/superstructure:superstructure_goal_fbs",
+ "//y2020/control_loops/superstructure:superstructure_output_fbs",
+ "//y2020/control_loops/superstructure:superstructure_position_fbs",
+ "//y2020/control_loops/superstructure:superstructure_status_fbs",
+ ],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//aos/robot_state:config",
+ "//frc971/autonomous:config",
+ "//frc971/control_loops/drivetrain:config",
+ "//frc971/wpilib:config",
+ ],
+)
+
+py_library(
+ name = "python_init",
+ srcs = ["__init__.py"],
+ visibility = ["//visibility:public"],
+)
diff --git a/y2020/__init__.py b/y2020/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/y2020/__init__.py
diff --git a/y2020/actors/BUILD b/y2020/actors/BUILD
new file mode 100644
index 0000000..668c502
--- /dev/null
+++ b/y2020/actors/BUILD
@@ -0,0 +1,53 @@
+filegroup(
+ name = "binaries.stripped",
+ srcs = [
+ ":autonomous_action.stripped",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+filegroup(
+ name = "binaries",
+ srcs = [
+ ":autonomous_action",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+cc_library(
+ name = "autonomous_action_lib",
+ srcs = [
+ "auto_splines.cc",
+ "autonomous_actor.cc",
+ ],
+ hdrs = [
+ "auto_splines.h",
+ "autonomous_actor.h",
+ ],
+ deps = [
+ "//aos/events:event_loop",
+ "//aos/logging",
+ "//aos/util:phased_loop",
+ "//frc971/autonomous:base_autonomous_actor",
+ "//frc971/control_loops:control_loops_fbs",
+ "//frc971/control_loops:profiled_subsystem_fbs",
+ "//frc971/control_loops/drivetrain:drivetrain_config",
+ "//frc971/control_loops/drivetrain:localizer_fbs",
+ "//y2020/control_loops/drivetrain:drivetrain_base",
+ "//y2020/control_loops/superstructure:superstructure_goal_fbs",
+ "//y2020/control_loops/superstructure:superstructure_status_fbs",
+ ],
+)
+
+cc_binary(
+ name = "autonomous_action",
+ srcs = [
+ "autonomous_actor_main.cc",
+ ],
+ deps = [
+ ":autonomous_action_lib",
+ "//aos:init",
+ "//aos/events:shm_event_loop",
+ "//frc971/autonomous:auto_fbs",
+ ],
+)
diff --git a/y2020/actors/auto_splines.cc b/y2020/actors/auto_splines.cc
new file mode 100644
index 0000000..86eed14
--- /dev/null
+++ b/y2020/actors/auto_splines.cc
@@ -0,0 +1,103 @@
+#include "y2020/actors/auto_splines.h"
+
+#include "frc971/control_loops/control_loops_generated.h"
+
+namespace y2020 {
+namespace actors {
+
+void MaybeFlipSpline(
+ aos::Sender<frc971::control_loops::drivetrain::Goal>::Builder *builder,
+ flatbuffers::Offset<flatbuffers::Vector<float>> spline_y_offset,
+ bool is_left) {
+ flatbuffers::Vector<float> *spline_y =
+ GetMutableTemporaryPointer(*builder->fbb(), spline_y_offset);
+
+ if (!is_left) {
+ for (size_t i = 0; i < spline_y->size(); i++) {
+ spline_y->Mutate(i, -spline_y->Get(i));
+ }
+ }
+}
+
+flatbuffers::Offset<frc971::MultiSpline> AutonomousSplines::BasicSSpline(
+ aos::Sender<frc971::control_loops::drivetrain::Goal>::Builder *builder) {
+ flatbuffers::Offset<frc971::Constraint> longitudinal_constraint_offset;
+ flatbuffers::Offset<frc971::Constraint> lateral_constraint_offset;
+ flatbuffers::Offset<frc971::Constraint> voltage_constraint_offset;
+
+ {
+ frc971::Constraint::Builder longitudinal_constraint_builder =
+ builder->MakeBuilder<frc971::Constraint>();
+ longitudinal_constraint_builder.add_constraint_type(
+ frc971::ConstraintType::LONGITUDINAL_ACCELERATION);
+ longitudinal_constraint_builder.add_value(1.0);
+ longitudinal_constraint_offset = longitudinal_constraint_builder.Finish();
+ }
+
+ {
+ frc971::Constraint::Builder lateral_constraint_builder =
+ builder->MakeBuilder<frc971::Constraint>();
+ lateral_constraint_builder.add_constraint_type(
+ frc971::ConstraintType::LATERAL_ACCELERATION);
+ lateral_constraint_builder.add_value(1.0);
+ lateral_constraint_offset = lateral_constraint_builder.Finish();
+ }
+
+ {
+ frc971::Constraint::Builder voltage_constraint_builder =
+ builder->MakeBuilder<frc971::Constraint>();
+ voltage_constraint_builder.add_constraint_type(
+ frc971::ConstraintType::VOLTAGE);
+ voltage_constraint_builder.add_value(6.0);
+ voltage_constraint_offset = voltage_constraint_builder.Finish();
+ }
+
+ flatbuffers::Offset<
+ flatbuffers::Vector<flatbuffers::Offset<frc971::Constraint>>>
+ constraints_offset =
+ builder->fbb()->CreateVector<flatbuffers::Offset<frc971::Constraint>>(
+ {longitudinal_constraint_offset, lateral_constraint_offset,
+ voltage_constraint_offset});
+
+ const float startx = 0.4;
+ const float starty = 3.4;
+ flatbuffers::Offset<flatbuffers::Vector<float>> spline_x_offset =
+ builder->fbb()->CreateVector<float>({0.0f + startx, 0.6f + startx,
+ 0.6f + startx, 0.4f + startx,
+ 0.4f + startx, 1.0f + startx});
+ flatbuffers::Offset<flatbuffers::Vector<float>> spline_y_offset =
+ builder->fbb()->CreateVector<float>({starty - 0.0f, starty - 0.0f,
+ starty - 0.3f, starty - 0.7f,
+ starty - 1.0f, starty - 1.0f});
+
+ frc971::MultiSpline::Builder multispline_builder =
+ builder->MakeBuilder<frc971::MultiSpline>();
+
+ multispline_builder.add_spline_count(1);
+ multispline_builder.add_constraints(constraints_offset);
+ multispline_builder.add_spline_x(spline_x_offset);
+ multispline_builder.add_spline_y(spline_y_offset);
+
+ return multispline_builder.Finish();
+}
+
+flatbuffers::Offset<frc971::MultiSpline> AutonomousSplines::StraightLine(
+ aos::Sender<frc971::control_loops::drivetrain::Goal>::Builder *builder) {
+ flatbuffers::Offset<flatbuffers::Vector<float>> spline_x_offset =
+ builder->fbb()->CreateVector<float>(
+ {-12.3, -11.9, -11.5, -11.1, -10.6, -10.0});
+ flatbuffers::Offset<flatbuffers::Vector<float>> spline_y_offset =
+ builder->fbb()->CreateVector<float>({1.25, 1.25, 1.25, 1.25, 1.25, 1.25});
+
+ frc971::MultiSpline::Builder multispline_builder =
+ builder->MakeBuilder<frc971::MultiSpline>();
+
+ multispline_builder.add_spline_count(1);
+ multispline_builder.add_spline_x(spline_x_offset);
+ multispline_builder.add_spline_y(spline_y_offset);
+
+ return multispline_builder.Finish();
+}
+
+} // namespace actors
+} // namespace y2020
diff --git a/y2020/actors/auto_splines.h b/y2020/actors/auto_splines.h
new file mode 100644
index 0000000..471b7b9
--- /dev/null
+++ b/y2020/actors/auto_splines.h
@@ -0,0 +1,28 @@
+#ifndef y2020_ACTORS_AUTO_SPLINES_H_
+#define y2020_ACTORS_AUTO_SPLINES_H_
+
+#include "aos/events/event_loop.h"
+#include "frc971/control_loops/control_loops_generated.h"
+#include "frc971/control_loops/drivetrain/drivetrain_goal_generated.h"
+/*
+
+ The cooridinate system for the autonomous splines is the same as the spline
+ python generator and drivetrain spline systems.
+
+*/
+
+namespace y2020 {
+namespace actors {
+
+class AutonomousSplines {
+ public:
+ static flatbuffers::Offset<frc971::MultiSpline> BasicSSpline(
+ aos::Sender<frc971::control_loops::drivetrain::Goal>::Builder *builder);
+ static flatbuffers::Offset<frc971::MultiSpline> StraightLine(
+ aos::Sender<frc971::control_loops::drivetrain::Goal>::Builder *builder);
+};
+
+} // namespace actors
+} // namespace y2020
+
+#endif // y2020_ACTORS_AUTO_SPLINES_H_
diff --git a/y2020/actors/autonomous_actor.cc b/y2020/actors/autonomous_actor.cc
new file mode 100644
index 0000000..d015c65
--- /dev/null
+++ b/y2020/actors/autonomous_actor.cc
@@ -0,0 +1,38 @@
+#include "y2020/actors/autonomous_actor.h"
+
+#include <inttypes.h>
+
+#include <chrono>
+#include <cmath>
+
+#include "aos/logging/logging.h"
+#include "frc971/control_loops/drivetrain/localizer_generated.h"
+#include "y2020/control_loops/drivetrain/drivetrain_base.h"
+
+namespace y2020 {
+namespace actors {
+
+using ::aos::monotonic_clock;
+using ::frc971::ProfileParametersT;
+using frc971::control_loops::drivetrain::LocalizerControl;
+namespace chrono = ::std::chrono;
+
+AutonomousActor::AutonomousActor(::aos::EventLoop *event_loop)
+ : frc971::autonomous::BaseAutonomousActor(
+ event_loop, control_loops::drivetrain::GetDrivetrainConfig()) {}
+
+void AutonomousActor::Reset() {
+ InitializeEncoders();
+ ResetDrivetrain();
+}
+
+bool AutonomousActor::RunAction(
+ const ::frc971::autonomous::AutonomousActionParams *params) {
+ Reset();
+
+ AOS_LOG(INFO, "Params are %d\n", params->mode());
+ return true;
+}
+
+} // namespace actors
+} // namespace y2020
diff --git a/y2020/actors/autonomous_actor.h b/y2020/actors/autonomous_actor.h
new file mode 100644
index 0000000..3bfa610
--- /dev/null
+++ b/y2020/actors/autonomous_actor.h
@@ -0,0 +1,27 @@
+#ifndef y2020_ACTORS_AUTONOMOUS_ACTOR_H_
+#define y2020_ACTORS_AUTONOMOUS_ACTOR_H_
+
+#include "aos/actions/actions.h"
+#include "aos/actions/actor.h"
+#include "frc971/autonomous/base_autonomous_actor.h"
+#include "frc971/control_loops/control_loops_generated.h"
+#include "frc971/control_loops/drivetrain/drivetrain_config.h"
+
+namespace y2020 {
+namespace actors {
+
+class AutonomousActor : public ::frc971::autonomous::BaseAutonomousActor {
+ public:
+ explicit AutonomousActor(::aos::EventLoop *event_loop);
+
+ bool RunAction(
+ const ::frc971::autonomous::AutonomousActionParams *params) override;
+
+ private:
+ void Reset();
+};
+
+} // namespace actors
+} // namespace y2020
+
+#endif // y2020_ACTORS_AUTONOMOUS_ACTOR_H_
diff --git a/y2020/actors/autonomous_actor_main.cc b/y2020/actors/autonomous_actor_main.cc
new file mode 100644
index 0000000..99563ee
--- /dev/null
+++ b/y2020/actors/autonomous_actor_main.cc
@@ -0,0 +1,20 @@
+#include <stdio.h>
+
+#include "aos/events/shm_event_loop.h"
+#include "aos/init.h"
+#include "y2020/actors/autonomous_actor.h"
+
+int main(int /*argc*/, char * /*argv*/ []) {
+ ::aos::Init(-1);
+
+ aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+ aos::configuration::ReadConfig("config.json");
+
+ ::aos::ShmEventLoop event_loop(&config.message());
+ ::y2020::actors::AutonomousActor autonomous(&event_loop);
+
+ event_loop.Run();
+
+ ::aos::Cleanup();
+ return 0;
+}
diff --git a/y2020/constants.cc b/y2020/constants.cc
new file mode 100644
index 0000000..70876c3
--- /dev/null
+++ b/y2020/constants.cc
@@ -0,0 +1,84 @@
+#include "y2020/constants.h"
+
+#include <inttypes.h>
+
+#include <map>
+
+#if __has_feature(address_sanitizer)
+#include "sanitizer/lsan_interface.h"
+#endif
+
+#include "absl/base/call_once.h"
+#include "aos/logging/logging.h"
+#include "aos/mutex/mutex.h"
+#include "aos/network/team_number.h"
+
+namespace y2020 {
+namespace constants {
+
+const int Values::kZeroingSampleSize;
+
+namespace {
+
+const uint16_t kCompTeamNumber = 971;
+const uint16_t kPracticeTeamNumber = 9971;
+const uint16_t kCodingRobotTeamNumber = 7971;
+
+const Values *DoGetValuesForTeam(uint16_t team) {
+ Values *const r = new Values();
+
+ switch (team) {
+ // A set of constants for tests.
+ case 1:
+ break;
+
+ case kCompTeamNumber:
+ break;
+
+ case kPracticeTeamNumber:
+ break;
+
+ case kCodingRobotTeamNumber:
+ break;
+
+ default:
+ AOS_LOG(FATAL, "unknown team #%" PRIu16 "\n", team);
+ }
+
+ return r;
+}
+
+void DoGetValues(const Values **result) {
+ uint16_t team = ::aos::network::GetTeamNumber();
+ AOS_LOG(INFO, "creating a Constants for team %" PRIu16 "\n", team);
+ *result = DoGetValuesForTeam(team);
+}
+
+} // namespace
+
+const Values &GetValues() {
+ static absl::once_flag once;
+ static const Values *result;
+ absl::call_once(once, DoGetValues, &result);
+ return *result;
+}
+
+const Values &GetValuesForTeam(uint16_t team_number) {
+ static ::aos::Mutex mutex;
+ ::aos::MutexLocker locker(&mutex);
+
+ // IMPORTANT: This declaration has to stay after the mutex is locked to avoid
+ // race conditions.
+ static ::std::map<uint16_t, const Values *> values;
+
+ if (values.count(team_number) == 0) {
+ values[team_number] = DoGetValuesForTeam(team_number);
+#if __has_feature(address_sanitizer)
+ __lsan_ignore_object(values[team_number]);
+#endif
+ }
+ return *values[team_number];
+}
+
+} // namespace constants
+} // namespace y2020
diff --git a/y2020/constants.h b/y2020/constants.h
new file mode 100644
index 0000000..2e915f9
--- /dev/null
+++ b/y2020/constants.h
@@ -0,0 +1,44 @@
+#ifndef y2020_CONSTANTS_H_
+#define y2020_CONSTANTS_H_
+
+#include <math.h>
+#include <stdint.h>
+
+#include <array>
+
+#include "frc971/constants.h"
+#include "frc971/control_loops/pose.h"
+#include "frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h"
+#include "y2020/control_loops/drivetrain/drivetrain_dog_motor_plant.h"
+
+namespace y2020 {
+namespace constants {
+
+struct Values {
+ static const int kZeroingSampleSize = 200;
+
+ static constexpr double kDrivetrainCyclesPerRevolution() { return 512.0; }
+ static constexpr double kDrivetrainEncoderCountsPerRevolution() {
+ return kDrivetrainCyclesPerRevolution() * 4;
+ }
+ static constexpr double kDrivetrainEncoderRatio() { return (24.0 / 52.0); }
+ static constexpr double kMaxDrivetrainEncoderPulsesPerSecond() {
+ return control_loops::drivetrain::kFreeSpeed / (2.0 * M_PI) *
+ control_loops::drivetrain::kHighOutputRatio /
+ constants::Values::kDrivetrainEncoderRatio() *
+ kDrivetrainEncoderCountsPerRevolution();
+ }
+};
+
+// Creates (once) a Values instance for ::aos::network::GetTeamNumber() and
+// returns a reference to it.
+const Values &GetValues();
+
+// Creates Values instances for each team number it is called with and returns
+// them.
+const Values &GetValuesForTeam(uint16_t team_number);
+
+} // namespace constants
+} // namespace y2020
+
+#endif // y2020_CONSTANTS_H_
diff --git a/y2020/control_loops/BUILD b/y2020/control_loops/BUILD
new file mode 100644
index 0000000..c0aa1ee
--- /dev/null
+++ b/y2020/control_loops/BUILD
@@ -0,0 +1,6 @@
+py_library(
+ name = "python_init",
+ srcs = ["__init__.py"],
+ visibility = ["//visibility:public"],
+ deps = ["//y2020:python_init"],
+)
diff --git a/y2020/control_loops/__init__.py b/y2020/control_loops/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/y2020/control_loops/__init__.py
diff --git a/y2020/control_loops/drivetrain/BUILD b/y2020/control_loops/drivetrain/BUILD
new file mode 100644
index 0000000..d03c1b9
--- /dev/null
+++ b/y2020/control_loops/drivetrain/BUILD
@@ -0,0 +1,83 @@
+load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
+load("//tools/build_rules:select.bzl", "compiler_select", "cpu_select")
+
+genrule(
+ name = "genrule_drivetrain",
+ outs = [
+ "drivetrain_dog_motor_plant.h",
+ "drivetrain_dog_motor_plant.cc",
+ "kalman_drivetrain_motor_plant.h",
+ "kalman_drivetrain_motor_plant.cc",
+ ],
+ cmd = "$(location //y2020/control_loops/python:drivetrain) $(OUTS)",
+ tools = [
+ "//y2020/control_loops/python:drivetrain",
+ ],
+)
+
+genrule(
+ name = "genrule_polydrivetrain",
+ outs = [
+ "polydrivetrain_dog_motor_plant.h",
+ "polydrivetrain_dog_motor_plant.cc",
+ "polydrivetrain_cim_plant.h",
+ "polydrivetrain_cim_plant.cc",
+ "hybrid_velocity_drivetrain.h",
+ "hybrid_velocity_drivetrain.cc",
+ ],
+ cmd = "$(location //y2020/control_loops/python:polydrivetrain) $(OUTS)",
+ tools = [
+ "//y2020/control_loops/python: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",
+ ],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//frc971/control_loops:hybrid_state_feedback_loop",
+ "//frc971/control_loops:state_feedback_loop",
+ ],
+)
+
+cc_library(
+ name = "drivetrain_base",
+ srcs = [
+ "drivetrain_base.cc",
+ ],
+ hdrs = [
+ "drivetrain_base.h",
+ ],
+ visibility = ["//visibility:public"],
+ deps = [
+ ":polydrivetrain_plants",
+ "//frc971:shifter_hall_effect",
+ "//frc971/control_loops/drivetrain:drivetrain_config",
+ ],
+)
+
+cc_binary(
+ name = "drivetrain",
+ srcs = [
+ "drivetrain_main.cc",
+ ],
+ visibility = ["//visibility:public"],
+ deps = [
+ ":drivetrain_base",
+ "//aos:init",
+ "//aos/events:shm_event_loop",
+ "//frc971/control_loops/drivetrain:drivetrain_lib",
+ ],
+)
diff --git a/y2020/control_loops/drivetrain/drivetrain_base.cc b/y2020/control_loops/drivetrain/drivetrain_base.cc
new file mode 100644
index 0000000..c3597f5
--- /dev/null
+++ b/y2020/control_loops/drivetrain/drivetrain_base.cc
@@ -0,0 +1,63 @@
+#include "y2020/control_loops/drivetrain/drivetrain_base.h"
+
+#include <chrono>
+
+#include "frc971/control_loops/drivetrain/drivetrain_config.h"
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "y2020/control_loops/drivetrain/drivetrain_dog_motor_plant.h"
+#include "y2020/control_loops/drivetrain/hybrid_velocity_drivetrain.h"
+#include "y2020/control_loops/drivetrain/kalman_drivetrain_motor_plant.h"
+#include "y2020/control_loops/drivetrain/polydrivetrain_dog_motor_plant.h"
+
+using ::frc971::control_loops::drivetrain::DrivetrainConfig;
+
+namespace chrono = ::std::chrono;
+
+namespace y2020 {
+namespace control_loops {
+namespace drivetrain {
+
+using ::frc971::constants::ShifterHallEffect;
+
+const ShifterHallEffect kThreeStateDriveShifter{0.0, 0.0, 0.25, 0.75};
+
+const DrivetrainConfig<double> &GetDrivetrainConfig() {
+ static DrivetrainConfig<double> kDrivetrainConfig{
+ ::frc971::control_loops::drivetrain::ShifterType::SIMPLE_SHIFTER,
+ ::frc971::control_loops::drivetrain::LoopType::CLOSED_LOOP,
+ ::frc971::control_loops::drivetrain::GyroType::IMU_Z_GYRO,
+ ::frc971::control_loops::drivetrain::IMUType::IMU_FLIPPED_X,
+
+ drivetrain::MakeDrivetrainLoop,
+ drivetrain::MakeVelocityDrivetrainLoop,
+ drivetrain::MakeKFDrivetrainLoop,
+ drivetrain::MakeHybridVelocityDrivetrainLoop,
+
+ chrono::duration_cast<chrono::nanoseconds>(
+ chrono::duration<double>(drivetrain::kDt)),
+ drivetrain::kRobotRadius,
+ drivetrain::kWheelRadius,
+ drivetrain::kV,
+
+ drivetrain::kHighGearRatio,
+ drivetrain::kLowGearRatio,
+ drivetrain::kJ,
+ drivetrain::kMass,
+ kThreeStateDriveShifter,
+ kThreeStateDriveShifter,
+ true /* default_high_gear */,
+ 0 /* down_offset if using constants use
+ constants::GetValues().down_error */
+ ,
+ 0.7 /* wheel_non_linearity */,
+ 1.2 /* quickturn_wheel_multiplier */,
+ 1.2 /* wheel_multiplier */,
+ true /*pistol_grip_shift_enables_line_follow*/,
+ };
+
+ return kDrivetrainConfig;
+};
+
+} // namespace drivetrain
+} // namespace control_loops
+} // namespace y2020
diff --git a/y2020/control_loops/drivetrain/drivetrain_base.h b/y2020/control_loops/drivetrain/drivetrain_base.h
new file mode 100644
index 0000000..c220088
--- /dev/null
+++ b/y2020/control_loops/drivetrain/drivetrain_base.h
@@ -0,0 +1,17 @@
+#ifndef y2020_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_BASE_H_
+#define y2020_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_BASE_H_
+
+#include "frc971/control_loops/drivetrain/drivetrain_config.h"
+
+namespace y2020 {
+namespace control_loops {
+namespace drivetrain {
+
+const ::frc971::control_loops::drivetrain::DrivetrainConfig<double>
+ &GetDrivetrainConfig();
+
+} // namespace drivetrain
+} // namespace control_loops
+} // namespace y2020
+
+#endif // y2020_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_BASE_H_
diff --git a/y2020/control_loops/drivetrain/drivetrain_main.cc b/y2020/control_loops/drivetrain/drivetrain_main.cc
new file mode 100644
index 0000000..66b9cc7
--- /dev/null
+++ b/y2020/control_loops/drivetrain/drivetrain_main.cc
@@ -0,0 +1,25 @@
+#include "aos/events/shm_event_loop.h"
+#include "aos/init.h"
+#include "frc971/control_loops/drivetrain/drivetrain.h"
+#include "y2020/control_loops/drivetrain/drivetrain_base.h"
+
+using ::frc971::control_loops::drivetrain::DrivetrainLoop;
+
+int main() {
+ ::aos::InitNRT(true);
+
+ aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+ aos::configuration::ReadConfig("config.json");
+
+ ::aos::ShmEventLoop event_loop(&config.message());
+ ::frc971::control_loops::drivetrain::DeadReckonEkf localizer(
+ &event_loop, ::y2020::control_loops::drivetrain::GetDrivetrainConfig());
+ DrivetrainLoop drivetrain(
+ ::y2020::control_loops::drivetrain::GetDrivetrainConfig(), &event_loop,
+ &localizer);
+
+ event_loop.Run();
+
+ ::aos::Cleanup();
+ return 0;
+}
diff --git a/y2020/control_loops/python/BUILD b/y2020/control_loops/python/BUILD
new file mode 100644
index 0000000..edc72f5
--- /dev/null
+++ b/y2020/control_loops/python/BUILD
@@ -0,0 +1,57 @@
+package(default_visibility = ["//y2020:__subpackages__"])
+
+py_binary(
+ name = "drivetrain",
+ srcs = [
+ "drivetrain.py",
+ ],
+ legacy_create_init = False,
+ restricted_to = ["//tools:k8"],
+ deps = [
+ ":python_init",
+ "//external:python-gflags",
+ "//external:python-glog",
+ "//frc971/control_loops/python:drivetrain",
+ ],
+)
+
+py_binary(
+ name = "polydrivetrain",
+ srcs = [
+ "drivetrain.py",
+ "polydrivetrain.py",
+ ],
+ legacy_create_init = False,
+ restricted_to = ["//tools:k8"],
+ deps = [
+ ":python_init",
+ "//external:python-gflags",
+ "//external:python-glog",
+ "//frc971/control_loops/python:polydrivetrain",
+ ],
+)
+
+py_library(
+ name = "polydrivetrain_lib",
+ srcs = [
+ "drivetrain.py",
+ "polydrivetrain.py",
+ ],
+ restricted_to = ["//tools:k8"],
+ visibility = ["//visibility:public"],
+ deps = [
+ ":python_init",
+ "//external:python-gflags",
+ "//external:python-glog",
+ "//frc971/control_loops/python:controls",
+ "//frc971/control_loops/python:drivetrain",
+ "//frc971/control_loops/python:polydrivetrain",
+ ],
+)
+
+py_library(
+ name = "python_init",
+ srcs = ["__init__.py"],
+ visibility = ["//visibility:public"],
+ deps = ["//y2020/control_loops:python_init"],
+)
diff --git a/y2020/control_loops/python/__init__.py b/y2020/control_loops/python/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/y2020/control_loops/python/__init__.py
diff --git a/y2020/control_loops/python/drivetrain.py b/y2020/control_loops/python/drivetrain.py
new file mode 100644
index 0000000..54745dd
--- /dev/null
+++ b/y2020/control_loops/python/drivetrain.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+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.')
+
+kDrivetrain = drivetrain.DrivetrainParams(
+ J=1.5,
+ mass=38.5,
+ robot_radius=0.45 / 2.0,
+ wheel_radius=4.0 * 0.0254 / 2.0,
+ G=9.0 / 52.0,
+ q_pos=0.14,
+ q_vel=1.30,
+ efficiency=0.80,
+ 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) != 5:
+ print "Expected .h file name and .cc file name"
+ else:
+ # Write the generated constants out to a file.
+ drivetrain.WriteDrivetrain(argv[1:3], argv[3:5], 'y2020', kDrivetrain)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/y2020/control_loops/python/polydrivetrain.py b/y2020/control_loops/python/polydrivetrain.py
new file mode 100644
index 0000000..6481af1
--- /dev/null
+++ b/y2020/control_loops/python/polydrivetrain.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+
+import sys
+from y2020.control_loops.python 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) != 7:
+ glog.fatal('Expected .h file name and .cc file name')
+ else:
+ polydrivetrain.WritePolyDrivetrain(argv[1:3], argv[3:5], argv[5:7], 'y2020',
+ drivetrain.kDrivetrain)
+
+if __name__ == '__main__':
+ argv = FLAGS(sys.argv)
+ glog.init()
+ sys.exit(main(argv))
diff --git a/y2020/control_loops/superstructure/BUILD b/y2020/control_loops/superstructure/BUILD
new file mode 100644
index 0000000..533a369
--- /dev/null
+++ b/y2020/control_loops/superstructure/BUILD
@@ -0,0 +1,78 @@
+package(default_visibility = ["//visibility:public"])
+
+load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
+
+flatbuffer_cc_library(
+ name = "superstructure_goal_fbs",
+ srcs = [
+ "superstructure_goal.fbs",
+ ],
+ gen_reflections = 1,
+ includes = [
+ "//frc971/control_loops:control_loops_fbs_includes",
+ "//frc971/control_loops:profiled_subsystem_fbs_includes",
+ ],
+)
+
+flatbuffer_cc_library(
+ name = "superstructure_output_fbs",
+ srcs = [
+ "superstructure_output.fbs",
+ ],
+ gen_reflections = 1,
+)
+
+flatbuffer_cc_library(
+ name = "superstructure_status_fbs",
+ srcs = [
+ "superstructure_status.fbs",
+ ],
+ gen_reflections = 1,
+ includes = [
+ "//frc971/control_loops:control_loops_fbs_includes",
+ "//frc971/control_loops:profiled_subsystem_fbs_includes",
+ ],
+)
+
+flatbuffer_cc_library(
+ name = "superstructure_position_fbs",
+ srcs = [
+ "superstructure_position.fbs",
+ ],
+ gen_reflections = 1,
+ includes = [
+ "//frc971/control_loops:control_loops_fbs_includes",
+ "//frc971/control_loops:profiled_subsystem_fbs_includes",
+ ],
+)
+
+cc_library(
+ name = "superstructure_lib",
+ srcs = [
+ "superstructure.cc",
+ ],
+ hdrs = [
+ "superstructure.h",
+ ],
+ deps = [
+ ":superstructure_goal_fbs",
+ ":superstructure_output_fbs",
+ ":superstructure_position_fbs",
+ ":superstructure_status_fbs",
+ "//aos/controls:control_loop",
+ "//aos/events:event_loop",
+ "//y2020:constants",
+ ],
+)
+
+cc_binary(
+ name = "superstructure",
+ srcs = [
+ "superstructure_main.cc",
+ ],
+ deps = [
+ ":superstructure_lib",
+ "//aos:init",
+ "//aos/events:shm_event_loop",
+ ],
+)
diff --git a/y2020/control_loops/superstructure/superstructure.cc b/y2020/control_loops/superstructure/superstructure.cc
new file mode 100644
index 0000000..a3978a4
--- /dev/null
+++ b/y2020/control_loops/superstructure/superstructure.cc
@@ -0,0 +1,43 @@
+#include "y2020/control_loops/superstructure/superstructure.h"
+
+#include "aos/events/event_loop.h"
+
+namespace y2020 {
+namespace control_loops {
+namespace superstructure {
+
+using frc971::control_loops::AbsoluteEncoderProfiledJointStatus;
+using frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus;
+
+Superstructure::Superstructure(::aos::EventLoop *event_loop,
+ const ::std::string &name)
+ : aos::controls::ControlLoop<Goal, Position, Status, Output>(event_loop,
+ name) {
+ event_loop->SetRuntimeRealtimePriority(30);
+}
+
+void Superstructure::RunIteration(const Goal * /*unsafe_goal*/,
+ const Position * /*position*/,
+ aos::Sender<Output>::Builder *output,
+ aos::Sender<Status>::Builder *status) {
+ if (WasReset()) {
+ AOS_LOG(ERROR, "WPILib reset, restarting\n");
+ }
+
+
+ if (output != nullptr) {
+ OutputT output_struct;
+ output->Send(Output::Pack(*output->fbb(), &output_struct));
+ }
+
+ Status::Builder status_builder = status->MakeBuilder<Status>();
+
+ status_builder.add_zeroed(true);
+ status_builder.add_estopped(false);
+
+ status->Send(status_builder.Finish());
+}
+
+} // namespace control_loops
+} // namespace y2020
+} // namespace y2020
diff --git a/y2020/control_loops/superstructure/superstructure.h b/y2020/control_loops/superstructure/superstructure.h
new file mode 100644
index 0000000..9aaca8e
--- /dev/null
+++ b/y2020/control_loops/superstructure/superstructure.h
@@ -0,0 +1,35 @@
+#ifndef y2020_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_H_
+#define y2020_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_H_
+
+#include "aos/controls/control_loop.h"
+#include "aos/events/event_loop.h"
+#include "y2020/constants.h"
+#include "y2020/control_loops/superstructure/superstructure_goal_generated.h"
+#include "y2020/control_loops/superstructure/superstructure_output_generated.h"
+#include "y2020/control_loops/superstructure/superstructure_position_generated.h"
+#include "y2020/control_loops/superstructure/superstructure_status_generated.h"
+
+namespace y2020 {
+namespace control_loops {
+namespace superstructure {
+
+class Superstructure
+ : public ::aos::controls::ControlLoop<Goal, Position, Status, Output> {
+ public:
+ explicit Superstructure(::aos::EventLoop *event_loop,
+ const ::std::string &name = "/superstructure");
+
+ protected:
+ virtual void RunIteration(const Goal *unsafe_goal, const Position *position,
+ aos::Sender<Output>::Builder *output,
+ aos::Sender<Status>::Builder *status) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Superstructure);
+};
+
+} // namespace superstructure
+} // namespace control_loops
+} // namespace y2020
+
+#endif // y2020_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_H_
diff --git a/y2020/control_loops/superstructure/superstructure_goal.fbs b/y2020/control_loops/superstructure/superstructure_goal.fbs
new file mode 100644
index 0000000..8a38b95
--- /dev/null
+++ b/y2020/control_loops/superstructure/superstructure_goal.fbs
@@ -0,0 +1,9 @@
+include "frc971/control_loops/profiled_subsystem.fbs";
+
+namespace y2020.control_loops.superstructure;
+
+table Goal {
+
+}
+
+root_type Goal;
diff --git a/y2020/control_loops/superstructure/superstructure_main.cc b/y2020/control_loops/superstructure/superstructure_main.cc
new file mode 100644
index 0000000..101a0c7
--- /dev/null
+++ b/y2020/control_loops/superstructure/superstructure_main.cc
@@ -0,0 +1,20 @@
+#include "y2020/control_loops/superstructure/superstructure.h"
+
+#include "aos/events/shm_event_loop.h"
+#include "aos/init.h"
+
+int main(int /*argc*/, char * /*argv*/ []) {
+ ::aos::InitNRT(true);
+
+ aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+ aos::configuration::ReadConfig("config.json");
+
+ ::aos::ShmEventLoop event_loop(&config.message());
+ ::y2020::control_loops::superstructure::Superstructure superstructure(
+ &event_loop);
+
+ event_loop.Run();
+
+ ::aos::Cleanup();
+ return 0;
+}
diff --git a/y2020/control_loops/superstructure/superstructure_output.fbs b/y2020/control_loops/superstructure/superstructure_output.fbs
new file mode 100644
index 0000000..3682db6
--- /dev/null
+++ b/y2020/control_loops/superstructure/superstructure_output.fbs
@@ -0,0 +1,7 @@
+namespace y2020.control_loops.superstructure;
+
+table Output {
+
+}
+
+root_type Output;
diff --git a/y2020/control_loops/superstructure/superstructure_position.fbs b/y2020/control_loops/superstructure/superstructure_position.fbs
new file mode 100644
index 0000000..c4b0a9a
--- /dev/null
+++ b/y2020/control_loops/superstructure/superstructure_position.fbs
@@ -0,0 +1,9 @@
+include "frc971/control_loops/control_loops.fbs";
+
+namespace y2020.control_loops.superstructure;
+
+table Position {
+
+}
+
+root_type Position;
diff --git a/y2020/control_loops/superstructure/superstructure_status.fbs b/y2020/control_loops/superstructure/superstructure_status.fbs
new file mode 100644
index 0000000..d0e9266
--- /dev/null
+++ b/y2020/control_loops/superstructure/superstructure_status.fbs
@@ -0,0 +1,15 @@
+include "frc971/control_loops/control_loops.fbs";
+include "frc971/control_loops/profiled_subsystem.fbs";
+
+namespace y2020.control_loops.superstructure;
+
+table Status {
+ // All subsystems know their location.
+ zeroed:bool;
+
+ // If true, we have aborted. This is the or of all subsystem estops.
+ estopped:bool;
+
+}
+
+root_type Status;
diff --git a/y2020/joystick_reader.cc b/y2020/joystick_reader.cc
new file mode 100644
index 0000000..105506e
--- /dev/null
+++ b/y2020/joystick_reader.cc
@@ -0,0 +1,79 @@
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "aos/actions/actions.h"
+#include "aos/init.h"
+#include "aos/input/action_joystick_input.h"
+#include "aos/input/driver_station_data.h"
+#include "aos/input/drivetrain_input.h"
+#include "aos/input/joystick_input.h"
+#include "aos/logging/logging.h"
+#include "aos/network/team_number.h"
+#include "aos/util/log_interval.h"
+#include "frc971/autonomous/base_autonomous_actor.h"
+#include "y2020/control_loops/drivetrain/drivetrain_base.h"
+#include "y2020/control_loops/superstructure/superstructure_goal_generated.h"
+#include "y2020/control_loops/superstructure/superstructure_status_generated.h"
+
+using aos::input::driver_station::ButtonLocation;
+using aos::input::driver_station::ControlBit;
+using aos::input::driver_station::JoystickAxis;
+using aos::input::driver_station::POVLocation;
+
+namespace y2020 {
+namespace input {
+namespace joysticks {
+
+namespace superstructure = y2020::control_loops::superstructure;
+
+class Reader : public ::aos::input::ActionJoystickInput {
+ public:
+ Reader(::aos::EventLoop *event_loop)
+ : ::aos::input::ActionJoystickInput(
+ event_loop,
+ ::y2020::control_loops::drivetrain::GetDrivetrainConfig(),
+ ::aos::input::DrivetrainInputReader::InputType::kPistol, {}),
+ superstructure_goal_sender_(
+ event_loop->MakeSender<superstructure::Goal>("/superstructure")),
+ superstructure_status_fetcher_(
+ event_loop->MakeFetcher<superstructure::Status>(
+ "/superstructure")) {}
+
+ void AutoEnded() override {
+ AOS_LOG(INFO, "Auto ended, assuming disc and have piece\n");
+ }
+
+ void HandleTeleop(
+ const ::aos::input::driver_station::Data & /*data*/) override {
+ superstructure_status_fetcher_.Fetch();
+ if (!superstructure_status_fetcher_.get()) {
+ AOS_LOG(ERROR, "Got no superstructure status message.\n");
+ return;
+ }
+ }
+
+ private:
+ ::aos::Sender<superstructure::Goal> superstructure_goal_sender_;
+
+ ::aos::Fetcher<superstructure::Status> superstructure_status_fetcher_;
+};
+
+} // namespace joysticks
+} // namespace input
+} // namespace y2020
+
+int main() {
+ ::aos::InitNRT(true);
+
+ aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+ aos::configuration::ReadConfig("config.json");
+
+ ::aos::ShmEventLoop event_loop(&config.message());
+ ::y2020::input::joysticks::Reader reader(&event_loop);
+
+ event_loop.Run();
+
+ ::aos::Cleanup();
+}
diff --git a/y2020/wpilib_interface.cc b/y2020/wpilib_interface.cc
new file mode 100644
index 0000000..4968c9f
--- /dev/null
+++ b/y2020/wpilib_interface.cc
@@ -0,0 +1,248 @@
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <array>
+#include <chrono>
+#include <cmath>
+#include <functional>
+#include <mutex>
+#include <thread>
+
+#include "ctre/phoenix/CANifier.h"
+#include "frc971/wpilib/ahal/AnalogInput.h"
+#include "frc971/wpilib/ahal/Counter.h"
+#include "frc971/wpilib/ahal/DigitalGlitchFilter.h"
+#include "frc971/wpilib/ahal/DriverStation.h"
+#include "frc971/wpilib/ahal/Encoder.h"
+#include "frc971/wpilib/ahal/VictorSP.h"
+#undef ERROR
+
+#include "aos/commonmath.h"
+#include "aos/events/event_loop.h"
+#include "aos/events/shm_event_loop.h"
+#include "aos/init.h"
+#include "aos/logging/logging.h"
+#include "aos/make_unique.h"
+#include "aos/realtime.h"
+#include "aos/robot_state/robot_state_generated.h"
+#include "aos/time/time.h"
+#include "aos/util/log_interval.h"
+#include "aos/util/phased_loop.h"
+#include "aos/util/wrapping_counter.h"
+#include "ctre/phoenix/motorcontrol/can/TalonSRX.h"
+#include "frc971/autonomous/auto_mode_generated.h"
+#include "frc971/control_loops/drivetrain/drivetrain_position_generated.h"
+#include "frc971/wpilib/ADIS16448.h"
+#include "frc971/wpilib/buffered_pcm.h"
+#include "frc971/wpilib/buffered_solenoid.h"
+#include "frc971/wpilib/dma.h"
+#include "frc971/wpilib/drivetrain_writer.h"
+#include "frc971/wpilib/encoder_and_potentiometer.h"
+#include "frc971/wpilib/joystick_sender.h"
+#include "frc971/wpilib/logging_generated.h"
+#include "frc971/wpilib/loop_output_handler.h"
+#include "frc971/wpilib/pdp_fetcher.h"
+#include "frc971/wpilib/sensor_reader.h"
+#include "frc971/wpilib/wpilib_robot_base.h"
+#include "y2020/constants.h"
+#include "y2020/control_loops/superstructure/superstructure_output_generated.h"
+#include "y2020/control_loops/superstructure/superstructure_position_generated.h"
+
+using ::aos::monotonic_clock;
+using ::y2020::constants::Values;
+namespace superstructure = ::y2020::control_loops::superstructure;
+namespace chrono = ::std::chrono;
+using aos::make_unique;
+
+namespace y2020 {
+namespace wpilib {
+namespace {
+
+constexpr double kMaxBringupPower = 12.0;
+
+// TODO(Brian): Fix the interpretation of the result of GetRaw here and in the
+// DMA stuff and then removing the * 2.0 in *_translate.
+// The low bit is direction.
+
+// TODO(brian): Use ::std::max instead once we have C++14 so that can be
+// constexpr.
+template <typename T>
+constexpr T max(T a, T b) {
+ return (a > b) ? a : b;
+}
+
+template <typename T, typename... Rest>
+constexpr T max(T a, T b, T c, Rest... rest) {
+ return max(max(a, b), c, rest...);
+}
+
+double drivetrain_translate(int32_t in) {
+ return ((static_cast<double>(in) /
+ Values::kDrivetrainEncoderCountsPerRevolution()) *
+ (2.0 * M_PI)) *
+ Values::kDrivetrainEncoderRatio() *
+ control_loops::drivetrain::kWheelRadius;
+}
+
+double drivetrain_velocity_translate(double in) {
+ return (((1.0 / in) / Values::kDrivetrainCyclesPerRevolution()) *
+ (2.0 * M_PI)) *
+ Values::kDrivetrainEncoderRatio() *
+ control_loops::drivetrain::kWheelRadius;
+}
+
+constexpr double kMaxFastEncoderPulsesPerSecond =
+ Values::kMaxDrivetrainEncoderPulsesPerSecond();
+static_assert(kMaxFastEncoderPulsesPerSecond <= 1300000,
+ "fast encoders are too fast");
+constexpr double kMaxMediumEncoderPulsesPerSecond = kMaxFastEncoderPulsesPerSecond;
+
+static_assert(kMaxMediumEncoderPulsesPerSecond <= 400000,
+ "medium encoders are too fast");
+
+} // namespace
+
+// Class to send position messages with sensor readings to our loops.
+class SensorReader : public ::frc971::wpilib::SensorReader {
+ public:
+ SensorReader(::aos::ShmEventLoop *event_loop)
+ : ::frc971::wpilib::SensorReader(event_loop),
+ auto_mode_sender_(
+ event_loop->MakeSender<::frc971::autonomous::AutonomousMode>(
+ "/autonomous")),
+ superstructure_position_sender_(
+ event_loop->MakeSender<superstructure::Position>(
+ "/superstructure")),
+ drivetrain_position_sender_(
+ event_loop
+ ->MakeSender<::frc971::control_loops::drivetrain::Position>(
+ "/drivetrain")) {
+ // Set to filter out anything shorter than 1/4 of the minimum pulse width
+ // we should ever see.
+ UpdateFastEncoderFilterHz(kMaxFastEncoderPulsesPerSecond);
+ UpdateMediumEncoderFilterHz(kMaxMediumEncoderPulsesPerSecond);
+ }
+
+ // Auto mode switches.
+ void set_autonomous_mode(int i, ::std::unique_ptr<frc::DigitalInput> sensor) {
+ autonomous_modes_.at(i) = ::std::move(sensor);
+ }
+
+ void RunIteration() override {
+ {
+ auto builder = drivetrain_position_sender_.MakeBuilder();
+ frc971::control_loops::drivetrain::Position::Builder drivetrain_builder =
+ builder.MakeBuilder<frc971::control_loops::drivetrain::Position>();
+ drivetrain_builder.add_left_encoder(
+ drivetrain_translate(drivetrain_left_encoder_->GetRaw()));
+ drivetrain_builder.add_left_speed(
+ drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod()));
+
+ drivetrain_builder.add_right_encoder(
+ -drivetrain_translate(drivetrain_right_encoder_->GetRaw()));
+ drivetrain_builder.add_right_speed(-drivetrain_velocity_translate(
+ drivetrain_right_encoder_->GetPeriod()));
+
+ builder.Send(drivetrain_builder.Finish());
+ }
+
+ {
+ auto builder = superstructure_position_sender_.MakeBuilder();
+ superstructure::Position::Builder position_builder =
+ builder.MakeBuilder<superstructure::Position>();
+ builder.Send(position_builder.Finish());
+ }
+
+ {
+ auto builder = auto_mode_sender_.MakeBuilder();
+
+ uint32_t mode = 0;
+ for (size_t i = 0; i < autonomous_modes_.size(); ++i) {
+ if (autonomous_modes_[i] && autonomous_modes_[i]->Get()) {
+ mode |= 1 << i;
+ }
+ }
+
+ auto auto_mode_builder =
+ builder.MakeBuilder<frc971::autonomous::AutonomousMode>();
+
+ auto_mode_builder.add_mode(mode);
+
+ builder.Send(auto_mode_builder.Finish());
+ }
+ }
+
+ private:
+ ::aos::Sender<::frc971::autonomous::AutonomousMode> auto_mode_sender_;
+ ::aos::Sender<superstructure::Position> superstructure_position_sender_;
+ ::aos::Sender<::frc971::control_loops::drivetrain::Position>
+ drivetrain_position_sender_;
+
+ ::std::array<::std::unique_ptr<frc::DigitalInput>, 2> autonomous_modes_;
+};
+
+class SuperstructureWriter
+ : public ::frc971::wpilib::LoopOutputHandler<superstructure::Output> {
+ public:
+ SuperstructureWriter(::aos::EventLoop *event_loop)
+ : ::frc971::wpilib::LoopOutputHandler<superstructure::Output>(
+ event_loop, "/superstructure") {}
+
+ private:
+ void Write(const superstructure::Output & /*output*/) override {}
+
+ void Stop() override { AOS_LOG(WARNING, "Superstructure output too old.\n"); }
+};
+
+class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
+ public:
+ ::std::unique_ptr<frc::Encoder> make_encoder(int index) {
+ return make_unique<frc::Encoder>(10 + index * 2, 11 + index * 2, false,
+ frc::Encoder::k4X);
+ }
+
+ void Run() override {
+ aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+ aos::configuration::ReadConfig("config.json");
+
+ // Thread 1.
+ ::aos::ShmEventLoop joystick_sender_event_loop(&config.message());
+ ::frc971::wpilib::JoystickSender joystick_sender(
+ &joystick_sender_event_loop);
+ AddLoop(&joystick_sender_event_loop);
+
+ // Thread 2.
+ ::aos::ShmEventLoop pdp_fetcher_event_loop(&config.message());
+ ::frc971::wpilib::PDPFetcher pdp_fetcher(&pdp_fetcher_event_loop);
+ AddLoop(&pdp_fetcher_event_loop);
+
+ // Thread 3.
+ ::aos::ShmEventLoop sensor_reader_event_loop(&config.message());
+ SensorReader sensor_reader(&sensor_reader_event_loop);
+ sensor_reader.set_drivetrain_left_encoder(make_encoder(0));
+ sensor_reader.set_drivetrain_right_encoder(make_encoder(1));
+
+ AddLoop(&sensor_reader_event_loop);
+
+ // Thread 4.
+ ::aos::ShmEventLoop output_event_loop(&config.message());
+ ::frc971::wpilib::DrivetrainWriter drivetrain_writer(&output_event_loop);
+ drivetrain_writer.set_left_controller0(
+ ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(0)), true);
+ drivetrain_writer.set_right_controller0(
+ ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(1)), false);
+
+ SuperstructureWriter superstructure_writer(&output_event_loop);
+
+ AddLoop(&output_event_loop);
+
+ RunLoops();
+ }
+};
+
+} // namespace wpilib
+} // namespace y2020
+
+AOS_ROBOT_CLASS(::y2020::wpilib::WPILibRobot);
diff --git a/y2020/y2020.json b/y2020/y2020.json
new file mode 100644
index 0000000..411e3ff
--- /dev/null
+++ b/y2020/y2020.json
@@ -0,0 +1,36 @@
+{
+ "channels":
+ [
+ {
+ "name": "/superstructure",
+ "type": "y2020.control_loops.superstructure.Goal",
+ "frequency": 200
+ },
+ {
+ "name": "/superstructure",
+ "type": "y2020.control_loops.superstructure.Status",
+ "frequency": 200
+ },
+ {
+ "name": "/superstructure",
+ "type": "y2020.control_loops.superstructure.Output",
+ "frequency": 200
+ },
+ {
+ "name": "/superstructure",
+ "type": "y2020.control_loops.superstructure.Position",
+ "frequency": 200
+ }
+ ],
+ "applications": [
+ {
+ "name": "drivetrain"
+ }
+ ],
+ "imports": [
+ "../aos/robot_state/robot_state_config.json",
+ "../frc971/control_loops/drivetrain/drivetrain_config.json",
+ "../frc971/autonomous/autonomous_config.json",
+ "../frc971/wpilib/wpilib_config.json"
+ ]
+}