NI Linux Real-Time Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Optris PI Camera Driver

Success (of a kind)!


http://james-green.staff.shef.ac.uk/image_16040053_00094_1439.ppm

is a thermal image of the sofa in my front room shot from my bookcase, a doorway is shown in the middle of frame (not very clear) and a radiator is shown on the right of frame. Taken using sb-RIO, but not using labview, just using some C++ code.

Next job write myself some boilerplate labview to interface with the oprtis driver...

James

0 Kudos
Message 11 of 27
(2,191 Views)

I'd say that's progress! And while it was frustrating and challenging, you certainly learned more by simply forging ahead with minimal input (at least from me). Or that's at least what I tell myself .

If you're looking to plug into a library interface for working with the driver, the biggest issue you may run into would be unusual datatypes that don't map well to NI LabVIEW CLFN argument types. What most people do is write a minimal wrapper to adapt datatypes between LV and the library.

0 Kudos
Message 12 of 27
(2,191 Views)

Actually I'd say your help was invaluable. Many thanks.

No doubt I'll run into more trouble yet.

I can imagin you're busy so don't worry about it too much but if you do have any thoughts on what might be wrong with the package I made, it'd be great to hear them as I'll probably be rolling this out to a few systems in the end, and it would be nice to make it publically available as well.

Cheers,

James

0 Kudos
Message 13 of 27
(2,191 Views)

Hi All, and by all I mean Brad...

I've written a C wrapper for the vendor's C++ library. I've written a minimal C program to test the wrapper. I have the minimal C program running on the target and saving thermal images to /tmp/ I pull them via scp to my laptop and convert to something usable. I have a nice one of my dog sleeping on my side of the sofa while I swear at my laptop in the other room.

In short the wrapper and the camera work on the target, guaranteed. We new the camera worked on the target before, but only via a program written in C++ and using the vendor's C++ library. My minimal C program is actually a manual re-writing of the C++ program more or less line by line (I even wrote a minimal vector library to avoid too much malloc.) of course the C program calls the C wrapper not the vendor's library. The only thing left to do - as far as I can tell - is to write a labview wrapper to cast the types, run the call library block on the C wrapper and derreference the pointers to non-standard types (structs etc.) that return to LV from the wrapper. Also, some callback stuff needs setting up.

But I'm stuck, again!

When I use the call library block in LV it spits error 13 at me. Which is "resource not found". This is different from error 7 "file not found", which is what I get if I point the call library block to a non-existent file. So LV can see the shared library file. If I point LV at the C++ vendors library it gives error 15 which is something about symbols - not supprising really as C++ mangles names during linking and LV only does C style calls.

I have done some digging and found https://decibel.ni.com/content/thread/47187?start=15&tstart=0 which seems similar and is only a month old, and you're the last person to answer on it ;-). The person working in that post is also trying to call an .so via another .so. There is also https://decibel.ni.com/content/message/19511#19511 which is much older and doesn't go nearly as far.

I don't know how to assess the LV program to figure out what's wrong. The only thing I can do so far is look at the minimal C test program I've written and hope that someone at NI can say, "ooo well LV wont like XYZ"...

Looking at the ldd chain for my test program written in C.

     admin@NI-sbRIO-9637-030b4226:~/FirstImgTst/Debug# ldd ./FirstImgTst

             libpthread.so.0 => /lib/libpthread.so.0 (0xb6fa7000)

             libImagerWrapper.so => /usr/local/lib/libImagerWrapper.so (0xb6f95000)

             libudev.so.0 => /lib/libudev.so.0 (0xb6f82000)

             libirimageprocessing.so => /usr/local/lib/libirimageprocessing.so (0xb6f2b000)

             libircore.so => /usr/local/lib/libircore.so (0xb6f0d000)

             libirimager.so => /usr/local/lib/libirimager.so (0xb6ec3000)

             libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb6df7000)

             libm.so.6 => /lib/libm.so.6 (0xb6d84000)

             libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb6d5f000)

             libc.so.6 => /lib/libc.so.6 (0xb6c2b000)

             /lib/ld-linux.so.3 (0xb6fc7000)

             librt.so.1 => /lib/librt.so.1 (0xb6c1c000)

     admin@NI-sbRIO-9637-030b4226:~/FirstImgTst/Debug#

pthread is for -pthreads - a super common threading library for C

libImagerWrapper is my C wrapper library

libudev is the device manager

libirimageprocessing + libircore + libirimager are the libraries provided by Optris (these are armel binaries) repackaged (yes, I can do package management now) so they install properly on NI's Linux.

stdc++ and below etc. are standard stuff and things

files output:

./FirstImgTst: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.14.3, BuildID[sha1]=976a7184dbc82bee71080fb557804417622aeb81, not stripped

The files output is what I would expect to see.

The test program was compiled natively on the target using the standard NI toolchain from the NI packages. Much easier than all that buggering about cross-compiling using eclipse. That said I did use eclipse to write both the wrapper and the test program on my laptop so I don't hate it.

The shared libraries are in /usr/lib and in /usr/local/lib

The libraries are loaded when the RT system boots (I think because of the /usr/local/lib bit). I'm not sure I actually need them loaded at boot but I don't see how it can hurt.

To see what is loading the libraries on the targer I'vr run lsof on both my wrapper library (first) and the vendor's shared library.

# lsof /usr/local/lib/irImageWrapper.so > http://www.iceamplifiers.co.uk/lsofwrapperoutput.txt

# lsof /usr/local/lib/irimager.so > http://www.iceamplifiers.co.uk/lsofoptrisoutput.txt

I don't understand the output I'm seeing but the fact that there are so many entries means it's been loaded by something...

For completeness the elf output of my C test program.

# readelf -a ./FirstImgTst >  http://www.iceamplifiers.co.uk/elfoutput.txt

The references to vector in the symbol table in the elf output are the vector implimentation I have in C (there are lots on the internet for lazy programmers - like me - who get tense when they have to malloc) it's not C++ leaking through from elsewhere.

Any thoughts on how I can assess what's going wrong in the LV code? I'm guessing you'll say set up gdb and have it watch the .so when LV calls it. No idea how to do that but while I wait, that's what I'll try.

Many thanks,

James

0 Kudos
Message 14 of 27
(2,191 Views)

Hi James,

If you do an interactive, from-project deploy of an application that references a library through CLFN, it will usually give you additional information as to what's going wrong. What is the configuration of those nodes? It seems that the two .so files have made their way into the ld.so.cache, so CLFNs configured to open "ImageWrapper.*", "imageprocessing.*", etc. should resolve (the CLFN code will prepend "lib" and replace "*" with ".so" and attempt a dlopen() on that, among other variations), which will hit the cache and find them. Did you double-check the function definitions?

Also, regarding your confusion on the output of lsof, the busybox-provided, stripped-down version will only list all files currently opened on the system

(safemode) admin@HerNameIsRIO:~# lsof --help                                   

BusyBox v1.23.1 (2016-06-08 18:05:42 CDT) multi-call binary.                   

                                                                               

Usage: lsof                                                                    

                                                                               

Show all open files 

0 Kudos
Message 15 of 27
(2,191 Views)

Also make sure that you have created a version-less symlink to the major-version symlink that the ld system creates.

0 Kudos
Message 16 of 27
(2,191 Views)

Hi Brad,

Thanks for the speedy reply. This may sound stupid but where would I look for the additional information that you mention?

I can do Help --> Explain error which produces:

Error 13 occurred at an unidentified location

Possible reason(s):

LabVIEW:  Failed to load dynamic library because of missing external symbols or dependencies, or because of an invalid file format.

The code is a single VI. screenshots below of:

Front Panel http://www.iceamplifiers.co.uk/frontpanel.jpg

Block Drg http://www.iceamplifiers.co.uk/blockdiagram.jpg

Call Lib Function Node (Function Tab) http://www.iceamplifiers.co.uk/calllibfunctiontab.jpg

Call Lib Function Node (Parameters Tab return type) http://www.iceamplifiers.co.uk/calllibparamstabreturntype.jpg

Call Lib Function Node (Paraeters Tab Debug) http://www.iceamplifiers.co.uk/calllibprarmsdebugtab.jpg

The prototype of the funtion in the wrapper header is:

#include <stdbool.h>

...

typedef struct IRImager IRImager;

...

IRImager* newIRImager_NoConfig(bool verbosity);

So I'm expecting it to return a pointer to a struct, which I think should be a 32 bit signed intager. It's accepting a bool which I think is signed 8 bit int.

Cheers,

James

0 Kudos
Message 17 of 27
(2,191 Views)

Just got the Duran Duran joke. Nice!

0 Kudos
Message 18 of 27
(2,191 Views)

Hmm, those are some shaky assumptions on the datatypes, especially considering that the IRImager seems to be a C++ class. I think that there needs to be a bit more meat in the actual shim library to help working with underlying library instead of simply passing the  majority of the data to LV to work on it there.

Maybe start with a basic test library that's not doing anything special, test that out first, then start pulling in the library and working from there.

I'm glad you appreciate the bit of humor in the targetname, it keeps me relatively sane

0 Kudos
Message 19 of 27
(2,191 Views)

Hi Brad,

I've got a dummy shared library in C++ and a C wrapper to wrap the dummy library. I'll try to hook it into LV and pass some int around and

then try to pass some pointers to int around and see if I'm still getting problems.

I'd be interested to know what makes you concerned about the assumptions on the memory requirements. Surely a pointer is just a pointer, an address in memory to start looking for some data?

If I re-write the wrapper function from eariler as:

// returns a pointer to a C struct based on the type IRImager defined in the wrapper header.

IRImager* newIRImager_NoConfig(bool verbosity)  {

     // create a C struct from typedef

     IRimager myImager;

    

     // create a pointer to the struct above

     IRImager *pmyImager;

     // memory in bytes needed by the pointer

     printf("\n\n The imager pointer needs %u bytes\n\n", sizeof(pmyImager));

     // return the result of the call to the C++ library

     return new IRImager(verbosity); 

}

re-compile etc. and run my minimal C program, I get:

The imager pointer needs 4 bytes

in the console and the calling of the C++ function IRImager from the vendor's library. Assuming a byte is 8 bits that's one signed 32 bit int. I suppose we should ask on what line is the memory allocated that is pointed to by the pointer ans it's not as far as I can tell not in the original minimal program or in my C version of it. Valgrind doesn't complain that I'm leaking memory or reading from places I shouldn't though.

If I write a C++ proggy to call the IRImager constructor directly in the C++ library (no wrappers, no LV), I can get it to tell me the size of the pointer that points to the instance of the IRImager class by the same method as above and it's 8 ... because I'm on a 64 bit (debian) machine but when I do the same with the C wrappered version on the same machine I still get 8. On a 32 bit machine (the sbRIO) I should get 4 in both cases I think. 

Anyway I'll have a go with a minimal wrappered C++ lib because I have one nearby, and if that doesn't work I'll try just a minimal C library no wrappers.

No doubt you'll hear from me again...

James

0 Kudos
Message 20 of 27
(2,191 Views)