Switch to python3 and scipy from slycot

Turns out we need python3 matplotlib to make scipy work well enough to
place the poles correctly for our systems.  Rather than do it piecemeal,
do it all at once.

This includes a python opencv upgrade too to support the new python, and
a matplotlib upgrade.

Change-Id: Ic7517b5ebbfdca9cc90ae6a61d86b474f2f21b29
diff --git a/frc971/control_loops/python/libcdd.py b/frc971/control_loops/python/libcdd.py
index b46d908..72d5833 100644
--- a/frc971/control_loops/python/libcdd.py
+++ b/frc971/control_loops/python/libcdd.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 """Wrapper around libcdd, a polytope manipulation library."""
 
@@ -8,24 +8,16 @@
 import os
 import sys
 
-# Wrapper around PyFile_AsFile so that we can print out the error messages.
-# Set the arg type and return types of the function call.
-class FILE(ctypes.Structure):
-  pass
-
-ctypes.pythonapi.PyFile_AsFile.argtypes = [ctypes.py_object]
-ctypes.pythonapi.PyFile_AsFile.restype = ctypes.POINTER(FILE)
-
 # Load and init libcdd.  libcdd is a C library that implements algorithm to
 # manipulate half space and vertex representations of polytopes.
 # Unfortunately, the library was compiled with C++ even though it has a lot of C
 # code in it, so all the symbol names are mangled.  Ug.
 libcdd = None
 for path in os.environ.get('PYTHONPATH').split(':'):
-  try:
-    libcdd = ctypes.cdll.LoadLibrary(os.path.join(path, 'third_party/cddlib/_cddlib.so'))
-  except OSError, e:
-    pass
+    try:
+        libcdd = ctypes.cdll.LoadLibrary(os.path.join(path, 'third_party/cddlib/_cddlib.so'))
+    except OSError:
+        pass
 
 assert libcdd is not None, 'Failed to find _cddlib.so'
 
@@ -41,21 +33,21 @@
 
 # Forward declaration for the polyhedra data structure.
 class dd_polyhedradata(ctypes.Structure):
-  pass
+    pass
 
 
 # Definition of dd_matrixdata
 class dd_matrixdata(ctypes.Structure):
-  _fields_ = [
-      ("rowsize", ctypes.c_long),
-      ("linset", ctypes.POINTER(ctypes.c_ulong)),
-      ("colsize", ctypes.c_long),
-      ("representation", ctypes.c_int),
-      ("numbtype", ctypes.c_int),
-      ("matrix", ctypes.POINTER(ctypes.POINTER(mytype))),
-      ("objective", ctypes.c_int),
-      ("rowvec", ctypes.POINTER(mytype)),
-  ]
+    _fields_ = [
+        ("rowsize", ctypes.c_long),
+        ("linset", ctypes.POINTER(ctypes.c_ulong)),
+        ("colsize", ctypes.c_long),
+        ("representation", ctypes.c_int),
+        ("numbtype", ctypes.c_int),
+        ("matrix", ctypes.POINTER(ctypes.POINTER(mytype))),
+        ("objective", ctypes.c_int),
+        ("rowvec", ctypes.POINTER(mytype)),
+    ]
 
 # Define the input and output types for a bunch of libcdd functions.
 libcdd.dd_CreateMatrix.restype = ctypes.POINTER(dd_matrixdata)
@@ -95,40 +87,40 @@
 
 
 def dd_CreateMatrix(rows, cols):
-  return libcdd.dd_CreateMatrix(ctypes.c_long(rows), ctypes.c_long(cols))
+    return libcdd.dd_CreateMatrix(ctypes.c_long(rows), ctypes.c_long(cols))
 
 
 def dd_set_d(mytype_address, double_value):
-  libcdd.ddd_set_d(mytype_address, ctypes.c_double(double_value))
+    libcdd.ddd_set_d(mytype_address, ctypes.c_double(double_value))
 
 
 def dd_CopyGenerators(polyhedraptr):
-  return libcdd.dd_CopyGenerators(polyhedraptr)
+    return libcdd.dd_CopyGenerators(polyhedraptr)
 
 
 def dd_get_d(mytype_address):
-  return libcdd.ddd_get_d(mytype_address)
+    return libcdd.ddd_get_d(mytype_address)
 
 
 def dd_FreeMatrix(matrixptr):
-  libcdd.dd_FreeMatrix(matrixptr)
+    libcdd.dd_FreeMatrix(matrixptr)
 
 
 def dd_FreePolyhedra(polyhedraptr):
-  libcdd.dd_FreePolyhedra(polyhedraptr)
+    libcdd.dd_FreePolyhedra(polyhedraptr)
 
 
 def dd_DDMatrix2Poly(matrixptr):
-  error = ctypes.c_int()
-  polyhedraptr = libcdd.dd_DDMatrix2Poly(matrixptr, ctypes.byref(error))
+    error = ctypes.c_int()
+    polyhedraptr = libcdd.dd_DDMatrix2Poly(matrixptr, ctypes.byref(error))
 
-  # Return None on error.
-  # The error values are enums, so they aren't exposed.
-  if error.value != DD_NO_ERRORS:
-    # Dump out the errors to stderr
-    libcdd.dd_WriteErrorMessages(
-        ctypes.pythonapi.PyFile_AsFile(ctypes.py_object(sys.stdout)),
-        error)
-    dd_FreePolyhedra(polyhedraptr)
-    return None
-  return polyhedraptr
+    # Return None on error.
+    # The error values are enums, so they aren't exposed.
+    if error.value != DD_NO_ERRORS:
+        # TODO(austin): Dump out the errors to stderr
+        #libcdd.dd_WriteErrorMessages(
+        #    ctypes.pythonapi.PyFile_AsFile(ctypes.py_object(sys.stdout)),
+        #    error)
+        dd_FreePolyhedra(polyhedraptr)
+        return None
+    return polyhedraptr