Eigen library for linear algebra / Teensy 3.1 / Help needed

Status
Not open for further replies.
Paul, is it possible to get a fix for that problem in the near future?

For the bug preventing error messages from printing, yes, that's a very high priority. In fact, I'm going to work on this this weekend or early next week.

For the Eigen library, maybe, but I really don't have time to dig into that huge code base right now.
 
In the meantime (or if it takes longer to fix the IDE), why not try another IDE? There are many possibilities, and - compared to the arduino IDE - I think you would enjoy most of them. THey will also give you more control over what is compiled, and I think that is the important point: you won't need all of Eigen's functionality, and it might be a good idea to only add what you need.
 
... a few of these no detail errors popped up and were swatted by Paul as 1.6.0 and 1.6.1 and the new compiler with 1.21 came online. If not for the "stop the compiler from committing suicide" I'd expect this to be just another case. From what I saw in the thread links it is commonly compiled with the gcc family being used, so that comment may have been written for it.
 
Success! I'm running ubuntu 14.04, arduino-1.0.6 installed in $HOME/builds/arduino/arduino-1.0.6, teensyduino 1.21 (release version). I didn't exactly follow the instructions at http://forum.arduino.cc/index.php?topic=144446.msg1089371#msg1089371. Here's what I did:
  • Downloaded Eigen313.zip to arduino-1.0.6/libraries
  • unzipped at that location, resulting in arduino-1.0.6/libraries/Eigen313 (not to the SAM subdirectoy!)
  • Added the library to arduino: Sketch->Import Library->Add Library->arduino-1.0.6/libraries/Eigen313 (not the zip, I added the directory)
  • Created a new sketch
  • Imported Eigen313 from the library menu
  • Added sketch code from the link above
  • Compiled/linked, uploaded to a Teensy LC and got correct output
I have not altered my arduino IDE, teensyduino 1.21, or the Eigen code from the link above (neither lib nor sketch) in any way. I have also tested simply pasting the code without importing the library from the menu, and that worked as well.

Output:
Code:
nrow: 6
ncol: 6

0.112775, 0.048292, -0.313197, -0.067979, 0.238543, 0.096648, 
-0.002733, -0.177437, 1.128801, 0.750399, -1.283369, -0.084223, 
0.645584, 0.189010, -1.758835, -1.095649, 2.438091, 0.718835, 
-0.613756, -0.359208, 2.150181, 1.179505, -2.575186, -0.930255, 
0.504729, 0.085257, -0.751615, -0.277679, 1.106807, 0.128982, 
-0.107398, 0.104756, 0.108780, 0.094344, -0.231374, 0.222546,
 
Last edited:
Using a more recent version of Eigen, and taking a closer look at that zip from the arduino forum thread:

Eigen313.zip is a subset of the full Eigen code, namely just the Eigen subdirectory. It also includes a library header for arduino to find, Eigen313.h:
Code:
// Credits:   @rpavlik for writing this header.
// Note:  "Importantly, it includes a header to both indicate to the Arduino IDE
//         that this library should be used, and set up the preprocessor environment
//         so the ample #define lines in the Arduino and AVR libraries don't wreak havoc with Eigen.

// Disable debug asserts.
#define EIGEN_NO_DEBUG 1

// Hint to number of registers
#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS 16

#ifdef A0
# define NEED_A0_RESTORED A0
# undef A0
#endif
#ifdef A1
# define NEED_A1_RESTORED A1
# undef A1
#endif
#ifdef B0
# define NEED_B0_RESTORED B0
# undef B0
#endif
#ifdef B1
# define NEED_B1_RESTORED B1
# undef B1
#endif

namespace std {
	struct nothrow_t;
}


// Include main EIGEN Core header
#include <Core>


#ifdef NEED_A0_RESTORED
# define A0 NEED_A0_RESTORED
# undef NEED_A0_RESTORED
#endif
#ifdef NEED_A1_RESTORED
# define A1 NEED_A1_RESTORED
# undef NEED_A1_RESTORED
#endif
#ifdef NEED_B0_RESTORED
# define B0 NEED_B0_RESTORED
# undef NEED_B0_RESTORED
#endif
#ifdef NEED_B1_RESTORED
# define B1 NEED_B1_RESTORED
# undef NEED_B1_RESTORED
#endif
Looking through that I can spot no magic at all, so why not use this as a starting point for using Eigen-3.2.4? Here's how:
  • Download Eigen-3.2.4 and unzip to a location of your choice, I'll call that directory "eigen".
  • Create arduino-1.0.6/libraries/Eigen324
  • Copy the contents of eigen/Eigen to arduino-1.0.6/libraries/Eigen324, you should now see a file arduino-1.0.6/libraries/Eigen324/Eigen (no file type suffix)
  • Copy Eigen313/Eigen313.h to Eigen324/Eigen324.h, no content changes are needed
  • Add library directory to arduino

Sketch to test:
Code:
// Example By: RandomVibe
// Eigen Doc: http://eigen.tuxfamily.org/dox/
// Quick Reference: http://eigen.tuxfamily.org/dox/QuickRefPage.html

#include <Eigen324.h>     // Calls main Eigen matrix class library
#include <LU>             // Calls inverse, determinant, LU decomp., etc.
using namespace Eigen;    // Eigen related statement; simplifies syntax for declaration of matrices

void print_mtxf(const Eigen::MatrixXf& K);


void setup() {

    Serial.begin(9600);
    while(!Serial.available());
    while(Serial.available())
    {
      Serial.read();
    }
    
    
    // DECLARE MATRICES 
    //--------------------
    MatrixXf Pp(6,6);   // Produces 6x6 float matrix class
    MatrixXf H(6,6);    // Note: without "using namespace Eigen", declaration would be: Eigen::MatrixXf H(6,6);
    MatrixXf R(6,6);  
    MatrixXf X(6,6);  
    MatrixXf K(6,6);  
    MatrixXf Z(6,6);  

    // INPUT MATRICES (so-called comma-initialize syntax)
    //---------------------------------------------------------
    Pp << 0.3252,  0.3192,  1.0933, -0.0068, -1.0891, -1.4916,
         -0.7549,  0.3129,  1.1093,  1.5326,  0.0326, -0.7423,
          1.3703, -0.8649, -0.8637, -0.7697,  0.5525, -1.0616,
         -1.7115, -0.0301,  0.0774,  0.3714,  1.1006,  2.3505,
         -0.1022, -0.1649, -1.2141, -0.2256,  1.5442, -0.6156,
         -0.2414,  0.6277, -1.1135,  1.1174,  0.0859,  0.7481 ;

    H << 0.8147, 0.2785, 0.9572, 0.7922, 0.6787, 0.7060,
         0.9058, 0.5469, 0.4854, 0.9595, 0.7577, 0.0318,
         0.1270, 0.9575, 0.8003, 0.6557, 0.7431, 0.2769,
         0.9134, 0.9649, 0.1419, 0.0357, 0.3922, 0.0462,
         0.6324, 0.1576, 0.4218, 0.8491, 0.6555, 0.0971,
         0.0975, 0.9706, 0.9157, 0.9340, 0.1712, 0.8235;

    R << 0.3252,  0.3192,  1.0933, -0.0068, -1.0891, -1.4916,
        -0.7549,  0.3129,  1.1093,  1.5326,  0.0326, -0.7423,
         1.3703, -0.8649, -0.8637, -0.7697,  0.5525, -1.0616,
        -1.7115, -0.0301,  0.0774,  0.3714,  1.1006,  2.3505,
        -0.1022, -0.1649, -1.2141, -0.2256,  1.5442, -0.6156,
        -0.2414,  0.6277, -1.1135,  1.1174,  0.0859,  0.7481;


    // Kalman Gain Example; Matlab form:  K = Pp * H' * inv(H * Pp * H' + R)
    //-----------------------------------
    X  = H * Pp * H.transpose() + R;    
    K  = Pp * H.transpose() * X.inverse();   


    // Print Result
    //----------------------------
     print_mtxf(K);      // Print Matrix Result (passed by reference)
    
}




void loop() {
  // put your main code here, to run repeatedly: 
  
}




// PRINT MATRIX (float type)
// By: randomvibe
//-----------------------------
void print_mtxf(const Eigen::MatrixXf& X)  
{
    int i, j, nrow, ncol;
    
    nrow = X.rows();
    ncol = X.cols();

    Serial.print("nrow: "); Serial.println(nrow);
    Serial.print("ncol: "); Serial.println(ncol);       
    Serial.println();
    
    for (i=0; i<nrow; i++)
    {
        for (j=0; j<ncol; j++)
        {
            Serial.print(X(i,j), 6);   // print 6 decimal places
            Serial.print(", ");
        }
        Serial.println();
    }
    Serial.println();
}
Output:
Code:
nrow: 6
ncol: 6

0.112775, 0.048292, -0.313197, -0.067979, 0.238543, 0.096648, 
-0.002733, -0.177437, 1.128801, 0.750399, -1.283369, -0.084223, 
0.645584, 0.189010, -1.758835, -1.095649, 2.438091, 0.718835, 
-0.613756, -0.359208, 2.150181, 1.179505, -2.575186, -0.930255, 
0.504729, 0.085257, -0.751615, -0.277679, 1.106807, 0.128982, 
-0.107398, 0.104756, 0.108780, 0.094344, -0.231374, 0.222546,
 
No objections? Has anyone else tried this? I have the feeling that I'm the only one who simply had luck and got this to work without to much hassle
 
Tried this on Windows 7 x64 with Arduino 1.0.6 and Teensyduino 1.21. There are still the error messages when compiling. Now I try to install Ubuntu as a virtual machine; maybe that the Eigen library will compile then. But it would still be great to be able to use the Eigen library when Arduino & Teensyduino are installed on a Windows machine.
 
@cristoph: Like I reported earlier (post #10 and #14), I can get it to compile in 1.6.1. I essentially did the same thing you did. I also reported that I was able to compile 3.2.4. I used the same trick with copying the header files.
 
Could trace it down for 1.0.6 to a call to an abort function. Adding a custom abort to the sketch helps.
Code:
void abort() {
        while(1);
}
Still trying to find where it should be linked and from what library (newlib?).

Edit: probably related to src/Core/util/Macros.h in the Eigen library. We probably need more defines?
 
Last edited:
I'm investigating this problem today. It's very strange that it builds properly on Linux but fails so badly on Windows.

I hope to have answers or at least a detailed explanation soon....
 
I'm not sure I followed all the steps to get to a working solution and only tried it as an exercise to see what came of the 'secret error details' - I'm not looking for it to work any time soon on Windows.
 
Is there a chance to get the Eigen library compiling on Windows? I should code matrix math next week, and the Eigen library would be a great help...
 
As a workaround did you try the custom abort function I mentioned in a previous post? You could even put a Serial.println("aborting"); in there.
In principle you should not hit the abort function. Don't know what happens if your matrix gets too big, or is singular when inverting. The library might throw?

Edit: post #35
 
Last edited:
Just got the idea from the std::vector thread.
It might be related to throwing.
The -fno-exceptions option replaces all throw() calls with a call to abort().
Maybe this option is handled differently on windows?
 
kpc, the workaround with the custom abort function work with Arduino 1.0.6 an Teesyduino 1.20. The other versions do not compile. I will try to get my code working with the custom function workaround.

Paul, I tried Linux, but couldn't install it on my mac where I have Windows installed. And on OSX I couldn't compile it either.
 
This compiled fine for me on Windows Vista, basically using the steps outlined in #30
- Teensy 3.1
- Arduino 1.6.3
- TeensyD 122 beta 3
- latest version of gcc (4.9-2015-q1-update) from launchpad : https://launchpad.net/gcc-arm-embedded

I did need to change the test code above slightly to use
Code:
#include <Eigen/LU>
instead of
Code:
#include <LU>
Also, I needed to change Eigen324.h at line 35 to read
Code:
#include <Eigen/Core>

Output is exactly the same as described above. I did not need to mess with compiler options, etc.

Hope this helps,
Matt
 
Last edited:
mconsidine, tried to copy what you did. I am using Windows 7 x64 and a Teensy 3.1. First I installed Arduino 1.6.3, and then Teensyduino 1.22, and finally gcc (4.9-2015-q1-update). But it looks like there needs some configuration to be done of gcc (4.9-2015-q1-update), but I don't know what and how.

When following the steps of your post outlined in #46 then I get the following error message:
Code:
In file included from Eigen324_Sample_Script.ino:5:0:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Eigen324/Eigen324.h:35:22: fatal error: Eigen/Core: No such file or directory
#include <Eigen/Core>
^
compilation terminated.
Error compiling.
 
Indeed, getting the compiler from launchpad shouldn't be necessary. teensyduino comes with gcc and compiled libraries.
 
@christoph - yes, I realize that getting the compiler from launchpad may not be necessary. I noted though that the latest versions have optimizations for Cortex M4 and I was hoping that would improve compilations for speed, such as -O2 (vs -Os). (By the way, thanks for the explorad link!)

@Paraglider - I'll go through in more detail here what I did, acknowledging christoph's point that getting code from launchpad may not be necessary. Since I had already done that for other reasons, though, I thought it important to point out. (And thanks to Frank B for pointing out the steps to accomplish the toolchain update.)

- I am running on Windows Vista (64bit, technically) and am using Arduino IDE 1.6.3 and TeensyDuino 1.22 at this point. (As well as the gcc 4.9.3 toolchain).
- At the moment I have not changed any options in boards.txt (found in my case at Program Files (x86)/Arduino/hardware/teensy/avr)
- My Sketchbook location (from File -> Preferences in the Arduino IDE) is C:\Users\Matt\Documents\Arduino
- Within that Sketchbook location are various projects as well as a "libraries" folder. It was within this libraries folder that I placed a folder "Eigen324"
- "Eigen324" contains one folder and one file. The folder is the "Eigen" subfolder extracted from the compressed file mentioned above. The file is "Eigen324.h"
- Using Notepad++ I edited line 35 on Eigen324.h to read #include <Eigen/Core>
- I created a new Sketch called Eigen_test based on the code above. I needed to change the seoncd line to refer to the Eigen folder. Here is the code
Code:
// Example By: RandomVibe
// Eigen Doc: http://eigen.tuxfamily.org/dox/
// Quick Reference: http://eigen.tuxfamily.org/dox/QuickRefPage.html

#include <Eigen324.h>     // Calls main Eigen matrix class library
#include <Eigen/LU>             // Calls inverse, determinant, LU decomp., etc.
using namespace Eigen;    // Eigen related statement; simplifies syntax for declaration of matrices

void print_mtxf(const Eigen::MatrixXf& K);


void setup() {

    Serial.begin(9600);
    while(!Serial.available());
    while(Serial.available())
    {
      Serial.read();
    }
    
    
    // DECLARE MATRICES 
    //--------------------
    MatrixXf Pp(6,6);   // Produces 6x6 float matrix class
    MatrixXf H(6,6);    // Note: without "using namespace Eigen", declaration would be: Eigen::MatrixXf H(6,6);
    MatrixXf R(6,6);  
    MatrixXf X(6,6);  
    MatrixXf K(6,6);  
    MatrixXf Z(6,6);  

    // INPUT MATRICES (so-called comma-initialize syntax)
    //---------------------------------------------------------
    Pp << 0.3252,  0.3192,  1.0933, -0.0068, -1.0891, -1.4916,
         -0.7549,  0.3129,  1.1093,  1.5326,  0.0326, -0.7423,
          1.3703, -0.8649, -0.8637, -0.7697,  0.5525, -1.0616,
         -1.7115, -0.0301,  0.0774,  0.3714,  1.1006,  2.3505,
         -0.1022, -0.1649, -1.2141, -0.2256,  1.5442, -0.6156,
         -0.2414,  0.6277, -1.1135,  1.1174,  0.0859,  0.7481 ;

    H << 0.8147, 0.2785, 0.9572, 0.7922, 0.6787, 0.7060,
         0.9058, 0.5469, 0.4854, 0.9595, 0.7577, 0.0318,
         0.1270, 0.9575, 0.8003, 0.6557, 0.7431, 0.2769,
         0.9134, 0.9649, 0.1419, 0.0357, 0.3922, 0.0462,
         0.6324, 0.1576, 0.4218, 0.8491, 0.6555, 0.0971,
         0.0975, 0.9706, 0.9157, 0.9340, 0.1712, 0.8235;

    R << 0.3252,  0.3192,  1.0933, -0.0068, -1.0891, -1.4916,
        -0.7549,  0.3129,  1.1093,  1.5326,  0.0326, -0.7423,
         1.3703, -0.8649, -0.8637, -0.7697,  0.5525, -1.0616,
        -1.7115, -0.0301,  0.0774,  0.3714,  1.1006,  2.3505,
        -0.1022, -0.1649, -1.2141, -0.2256,  1.5442, -0.6156,
        -0.2414,  0.6277, -1.1135,  1.1174,  0.0859,  0.7481;


    // Kalman Gain Example; Matlab form:  K = Pp * H' * inv(H * Pp * H' + R)
    //-----------------------------------
    X  = H * Pp * H.transpose() + R;    
    K  = Pp * H.transpose() * X.inverse();   


    // Print Result
    //----------------------------
     print_mtxf(K);      // Print Matrix Result (passed by reference)
    
}




void loop() {
  // put your main code here, to run repeatedly: 
  
}




// PRINT MATRIX (float type)
// By: randomvibe
//-----------------------------
void print_mtxf(const Eigen::MatrixXf& X)  
{
    int i, j, nrow, ncol;
    
    nrow = X.rows();
    ncol = X.cols();

    Serial.print("nrow: "); Serial.println(nrow);
    Serial.print("ncol: "); Serial.println(ncol);       
    Serial.println();
    
    for (i=0; i<nrow; i++)
    {
        for (j=0; j<ncol; j++)
        {
            Serial.print(X(i,j), 6);   // print 6 decimal places
            Serial.print(", ");
        }
        Serial.println();
    }
    Serial.println();
}

Here is a screenshot of the compilation results
Eigin_clip.jpg

Hope this helps. If not, please ask questions.
Matt

PS For anyone interested, my project is to try to create a pointing-model based set of digital setting circles for a telescope. So I need to be able to read encoders, deal with Bluetooth and WiFi communications and a lot of matrix math. If by some miracle someone has already gone down this path, I'd be interested in hearing about it.
 
@mconsidine, thanks for your detailed tutorial. Eigen compiles now on Arduino 1.6.3 and Teensyduino 1.22 without any problem on my Windows 7 x64 computer. Like this it's very easy to do matrix math on Teensy 3.1.

@Paul, what about the idea to integrate the Eigen library into the next release of Teensyduino?
 
Status
Not open for further replies.
Back
Top