started adding support for logging matrices and used it
diff --git a/aos/common/logging/logging.gyp b/aos/common/logging/logging.gyp
index e230e47..0139784 100644
--- a/aos/common/logging/logging.gyp
+++ b/aos/common/logging/logging.gyp
@@ -24,6 +24,26 @@
       ],
       'export_dependent_settings': [
         '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:die',
+      ],
+    },
+    {
+      'target_name': 'matrix_logging',
+      'type': 'static_library',
+      'sources': [
+        'matrix_logging.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:die',
+        '<(AOS)/common/common.gyp:queue_types',
+        '<(EXTERNALS):eigen',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/common/common.gyp:die',
+        '<(AOS)/common/common.gyp:queue_types',
+        '<(EXTERNALS):eigen',
       ],
     },
   ],
diff --git a/aos/common/logging/logging_impl.h b/aos/common/logging/logging_impl.h
index 3d5b387..11b28b0 100644
--- a/aos/common/logging/logging_impl.h
+++ b/aos/common/logging/logging_impl.h
@@ -42,7 +42,7 @@
 // The struct that the code uses for making logging calls.
 struct LogMessage {
   enum class Type : uint8_t {
-    kString, kStruct,
+    kString, kStruct, kMatrix
   };
 
   int32_t seconds, nseconds;
@@ -63,6 +63,13 @@
       // The message string and then the serialized structure.
       char serialized[LOG_MESSAGE_LEN - sizeof(type) - sizeof(string_length)];
     } structure;
+    struct {
+      // The type ID of the element type.
+      uint32_t type;
+      int rows, columns;
+      char
+          data[LOG_MESSAGE_LEN - sizeof(type) - sizeof(rows) - sizeof(columns)];
+    } matrix;
   };
 };
 static_assert(shm_ok<LogMessage>::value, "it's going in a queue");
@@ -102,9 +109,12 @@
 void LogNext(log_level level, const char *format, ...)
   __attribute__((format(LOG_PRINTF_FORMAT_TYPE, 2, 3)));
 
-// Will take a structure and log it.
+// Takes a structure and log it.
 template <class T>
 void DoLogStruct(log_level, const ::std::string &, const T &);
+// Takes a matrix and logs it.
+template <class T>
+void DoLogMatrix(log_level, const ::std::string &, const T &);
 
 // Represents a system that can actually take log messages and do something
 // useful with them.
@@ -144,6 +154,12 @@
   virtual void LogStruct(log_level level, const ::std::string &message,
                          size_t size, const MessageType *type,
                          const ::std::function<size_t(char *)> &serialize);
+  // Similiar to LogStruct, except for matrixes.
+  // type_id is the type of the elements of the matrix.
+  // data points to rows*cols*type_id.Size() bytes of data in row-major order.
+  virtual void LogMatrix(log_level level, const ::std::string &message,
+                         uint32_t type_id, int rows, int cols,
+                         const void *data);
 
   // These functions call similar methods on the "current" LogImplementation or
   // Die if they can't find one.
@@ -154,12 +170,17 @@
                           size_t size, const MessageType *type,
                           const ::std::function<size_t(char *)> &serialize,
                           int levels);
+  static void DoLogMatrix(log_level level, const ::std::string &message,
+                          uint32_t type_id, int rows, int cols,
+                          const void *data);
 
   // Friends so that they can access the static Do* functions.
   friend void VLog(log_level, const char *, va_list);
   friend void LogNext(log_level, const char *, ...);
   template <class T>
   friend void DoLogStruct(log_level, const ::std::string &, const T &);
+  template <class T>
+  friend void DoLogMatrix(log_level, const ::std::string &, const T &);
 
   LogImplementation *next_;
 };
diff --git a/aos/common/logging/matrix_logging-tmpl.h b/aos/common/logging/matrix_logging-tmpl.h
new file mode 100644
index 0000000..8d18f67
--- /dev/null
+++ b/aos/common/logging/matrix_logging-tmpl.h
@@ -0,0 +1,18 @@
+#include "aos/common/logging/logging_impl.h"
+
+#include <functional>
+
+#include "aos/queue_primitives.h"
+
+namespace aos {
+namespace logging {
+
+template <class T>
+void DoLogMatrix(log_level level, const ::std::string &message,
+                 const T &matrix) {
+  LogImplementation::DoLogMatrix(level, message, TypeID<typename T::Scalar>::id,
+                                 matrix.rows(), matrix.cols(), matrix.data());
+}
+
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/common/logging/matrix_logging.cc b/aos/common/logging/matrix_logging.cc
new file mode 100644
index 0000000..cd30509
--- /dev/null
+++ b/aos/common/logging/matrix_logging.cc
@@ -0,0 +1 @@
+#include "aos/common/logging/matrix_logging.h"
diff --git a/aos/common/logging/matrix_logging.h b/aos/common/logging/matrix_logging.h
new file mode 100644
index 0000000..6efaa06
--- /dev/null
+++ b/aos/common/logging/matrix_logging.h
@@ -0,0 +1,36 @@
+#ifndef AOS_COMMON_LOGGING_MATRIX_LOGGING_H_
+#define AOS_COMMON_LOGGING_MATRIX_LOGGING_H_
+
+#include <string>
+
+#include "Eigen/Dense"
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/die.h"
+
+namespace aos {
+namespace logging {
+
+// Logs the contents of a matrix and a constant string.
+// matrix must be an instance of an Eigen matrix (or something similar).
+#define LOG_MATRIX(level, message, matrix)                          \
+  do {                                                              \
+    static const ::std::string kAosLoggingMessage(                  \
+        LOG_SOURCENAME ": " STRINGIFY(__LINE__) ": " message);      \
+    ::aos::logging::DoLogMatrix(level, kAosLoggingMessage, matrix); \
+    /* so that GCC knows that it won't return */                    \
+    if (level == FATAL) {                                           \
+      ::aos::Die("DoLogStruct(FATAL) fell through!!!!!\n");         \
+    }                                                               \
+  } while (false)
+
+template <class T>
+void DoLogMatrix(log_level level, const ::std::string &message,
+                 const T &matrix);
+
+}  // namespace logging
+}  // namespace aos
+
+#include "aos/common/logging/matrix_logging-tmpl.h"
+
+#endif  // AOS_COMMON_LOGGING_MATRIX_LOGGING_H_
diff --git a/aos/common/logging/queue_logging.cc b/aos/common/logging/queue_logging.cc
index eefb4ac..021da7c 100644
--- a/aos/common/logging/queue_logging.cc
+++ b/aos/common/logging/queue_logging.cc
@@ -1,6 +1,6 @@
-#include "aos/common/logging/logging_impl.h"
+#include "aos/common/logging/queue_logging.h"
 
-#include "aos/common/die.h"
+#include "aos/common/logging/logging_impl.h"
 #include "aos/common/queue_types.h"
 
 namespace aos {
diff --git a/aos/common/logging/queue_logging.h b/aos/common/logging/queue_logging.h
index 191d4c7..ff0167a 100644
--- a/aos/common/logging/queue_logging.h
+++ b/aos/common/logging/queue_logging.h
@@ -7,10 +7,13 @@
 #include <string>
 
 #include "aos/common/logging/logging.h"
+#include "aos/common/die.h"
 
 namespace aos {
 namespace logging {
 
+// Logs the contents of a structure (or Queue message) and a constant string.
+// structure must be an instance of one of the generated queue types.
 #define LOG_STRUCT(level, message, structure)                          \
   do {                                                                 \
     static const ::std::string kAosLoggingMessage(                     \
@@ -18,9 +21,7 @@
     ::aos::logging::DoLogStruct(level, kAosLoggingMessage, structure); \
     /* so that GCC knows that it won't return */                       \
     if (level == FATAL) {                                              \
-      fprintf(stderr, "DoLogStruct(FATAL) fell through!!!!!\n");       \
-      printf("see stderr\n");                                          \
-      abort();                                                         \
+      ::aos::Die("DoLogStruct(FATAL) fell through!!!!!\n");            \
     }                                                                  \
   } while (false)