I’m trying - and so far failing - to do what should surely be a very simple thing. This isn’t a new situation… especially on unix.
I have a single C file with just two functions. I have a matching H file. I want to make them into a dynamic library that I can call via FFI. This really shouldn’t be rocket science stuff!
So far I can a) compile the C file (well duh) b) link it as a shared library c) install it in /usr/local/lib (next to another library that I can use from FFI already, so I know the path gets looked at) d) set the permissions to match the working library e) use from a simple C program to prove it works
However, all I get from squeak is an error that the external module is not found. I’ll take a look with a debug vm but I’d be very happy to hear that I’m forgetting some trivial flag or incantation that can short-circuit the ‘fun’ of using gdb.
Here is the code and makefile - https://copy.com/DGDbpJM4wnHQrDUG
What I’ve been doing to build & try is make clean make sudo install -m 0755 libmadgwickIMU..s0.1 /usr/local/lib/libmadgwickIMU.so.1 sudo ln -sf /usr/local/lib/libmadgwickIMU.so.1 /usr/local/lib/libmadwickIMU.so sudo ldconfig gcc -Wall -o testing testing.c -lmadwickIMU ./testing
‘testing’ seem to do the right thing. Going into squeak (cog/spur/pi) and trying a method like - invSqrt: floatval #<cdecl: float ‘invSqrt’ (float) module: ‘madgwickIMU’> ^self externalCallFailed - just gives me the not found module error.
I’ve restarted squeak after building the lib, I’ve opened a new terminal after building the lib (just in case there’s some stupid path-exporting nonsense I don’t understand etc) and I’ve made sure to smile only on the left side. What on earth am I forgetting?
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful Latin Phrases:- Braccae illae virides cum subucula rosea et tunica Caledonia-quam elenganter concinnatur! = Those green pants go so well with that pink shirt and the plaid jacket!
Hmm. Maybe try creating the class method:
moduleName ^'madgwickIMU'
(assuming you haven't already).
-cbc
On Wed, Sep 9, 2015 at 11:17 AM, tim Rowledge tim@rowledge.org wrote:
I’m trying - and so far failing - to do what should surely be a very simple thing. This isn’t a new situation… especially on unix.
I have a single C file with just two functions. I have a matching H file. I want to make them into a dynamic library that I can call via FFI. This really shouldn’t be rocket science stuff!
So far I can a) compile the C file (well duh) b) link it as a shared library c) install it in /usr/local/lib (next to another library that I can use from FFI already, so I know the path gets looked at) d) set the permissions to match the working library e) use from a simple C program to prove it works
However, all I get from squeak is an error that the external module is not found. I’ll take a look with a debug vm but I’d be very happy to hear that I’m forgetting some trivial flag or incantation that can short-circuit the ‘fun’ of using gdb.
Here is the code and makefile - https://copy.com/DGDbpJM4wnHQrDUG
What I’ve been doing to build & try is make clean make sudo install -m 0755 libmadgwickIMU..s0.1 /usr/local/lib/libmadgwickIMU.so.1 sudo ln -sf /usr/local/lib/libmadgwickIMU.so.1 /usr/local/lib/libmadwickIMU.so sudo ldconfig gcc -Wall -o testing testing.c -lmadwickIMU ./testing
‘testing’ seem to do the right thing. Going into squeak (cog/spur/pi) and trying a method like - invSqrt: floatval #<cdecl: float ‘invSqrt’ (float) module: ‘madgwickIMU’> ^self externalCallFailed
- just gives me the not found module error.
I’ve restarted squeak after building the lib, I’ve opened a new terminal after building the lib (just in case there’s some stupid path-exporting nonsense I don’t understand etc) and I’ve made sure to smile only on the left side. What on earth am I forgetting?
tim
tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful Latin Phrases:- Braccae illae virides cum subucula rosea et tunica Caledonia-quam elenganter concinnatur! = Those green pants go so well with that pink shirt and the plaid jacket!
On 09-09-2015, at 11:33 AM, Chris Cunningham cunningham.cb@gmail.com wrote:
Hmm. Maybe try creating the class method:
moduleName ^'madgwickIMU'
(assuming you haven't already).
Ah, but that would be for a plugin, whereas this is a simple C library. Or *should* be, if I got it right.
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: XER: Exclusive ERror
On Wed, Sep 9, 2015 at 11:40 AM, tim Rowledge tim@rowledge.org wrote:
On 09-09-2015, at 11:33 AM, Chris Cunningham cunningham.cb@gmail.com wrote:
Hmm. Maybe try creating the class method:
moduleName ^'madgwickIMU'
(assuming you haven't already).
Ah, but that would be for a plugin, whereas this is a simple C library. Or *should* be, if I got it right.
ok. Does FFI know to prepend the lib and postpend the .so in Unix for
you? I'm curious.
-cbc
tim
tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: XER: Exclusive ERror
On 09-09-2015, at 11:44 AM, Chris Cunningham cunningham.cb@gmail.com wrote:
ok. Does FFI know to prepend the lib and postpend the .so in Unix for you? I'm curious.
Well, it does for other libraries; for example calling libwiringPi.so you use #<cdecl: void ‘foo’ (int) module: ‘wiringPi’>
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: SNARF: System Normalize And Reset Flags
How do you start squeak ? Is there a squeak shell script that may modify the library lookup path?
you could try to start squeak with LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH squeak
2015-09-09 20:55 GMT+02:00 tim Rowledge tim@rowledge.org:
On 09-09-2015, at 11:44 AM, Chris Cunningham cunningham.cb@gmail.com wrote:
ok. Does FFI know to prepend the lib and postpend the .so in Unix for
you? I'm curious.
Well, it does for other libraries; for example calling libwiringPi.so you use #<cdecl: void ‘foo’ (int) module: ‘wiringPi’>
tim
tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: SNARF: System Normalize And Reset Flags
On 09-09-2015, at 12:26 PM, Nicolai Hess nicolaihess@web.de wrote:
How do you start squeak ? Is there a squeak shell script that may modify the library lookup path?
you could try to start squeak with LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH squeak
OK, tried that to no avail; but the wiringPi library in the same directory works :-) What fun, eh?
ldconfig -p | grep mad shows ‘libmadgwickIMU.so (libc6,hard-float) => /usr/local/lib.libmadgwickIMU.so
Into the joys of gdb right now, just starting to (attempt to) load the lib. I wonder if it’ll be friendly?
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim In the long run, every program becomes rococco, and then rubble.
I think you may have typed "W" one to many times in this Makefile and you're adding them where they don't belong. I detect a rogue W in the name madgwick.
@$(CC) -shared -Wl,-soname,libmadgwickIMU.so -o lib--------->w<---------madgwickIMU.so.$(VERSION) -lm $(OBJ)
Also, when I compile on this Ubuntu 15.04 I get an error. [1]
FWIW, Chris
[1]
$ make [Compile] MadgwickAHRS.c MadgwickAHRS.c: In function ‘invSqrt’: MadgwickAHRS.c:218:2: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] long i = *(long*)&y; ^ MadgwickAHRS.c:220:2: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] y = *(float*)&i; ^ [Link (Dynamic)]
On Wed, Sep 9, 2015 at 2:55 PM, tim Rowledge tim@rowledge.org wrote:
On 09-09-2015, at 11:44 AM, Chris Cunningham cunningham.cb@gmail.com wrote:
ok. Does FFI know to prepend the lib and postpend the .so in Unix for
you? I'm curious.
Well, it does for other libraries; for example calling libwiringPi.so you use #<cdecl: void ‘foo’ (int) module: ‘wiringPi’>
tim
tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: SNARF: System Normalize And Reset Flags
On 09-09-2015, at 12:55 PM, Chris Cunnington brasspen@gmail.com wrote:
I think you may have typed "W" one to many times in this Makefile and you're adding them where they don't belong. I detect a rogue W in the name madgwick.
Ah, just for a moment there I thought you’d spotted the dumb mistake. But I was ‘correcting’ that in the install stuff and fixing the makefile etc resulted in exactly the same result. Sigh.
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim It is easier to change the specification to fit the program than vice versa.
On Sep 9, 2015, at 12:17, tim Rowledge tim@rowledge.org wrote:
sudo install -m 0755 libmadgwickIMU..s0.1 /usr/local/lib/libmadgwickIMU.so.1 sudo ln -sf /usr/local/lib/libmadgwickIMU.so.1 /usr/local/lib/libmadwickIMU.so
^ Is there a reason for the madwick instead of madgwick?
Ken
On Sep 9, 2015, at 12:17, tim Rowledge tim@rowledge.org wrote:
I’m trying - and so far failing - to do what should surely be a very simple thing. This isn’t a new situation… especially on unix.
I have a single C file with just two functions. I have a matching H file. I want to make them into a dynamic library that I can call via FFI. This really shouldn’t be rocket science stuff!
So far I can a) compile the C file (well duh) b) link it as a shared library c) install it in /usr/local/lib (next to another library that I can use from FFI already, so I know the path gets looked at) d) set the permissions to match the working library e) use from a simple C program to prove it works
However, all I get from squeak is an error that the external module is not found. I’ll take a look with a debug vm but I’d be very happy to hear that I’m forgetting some trivial flag or incantation that can short-circuit the ‘fun’ of using gdb.
Here is the code and makefile - https://copy.com/DGDbpJM4wnHQrDUG
What I’ve been doing to build & try is make clean make sudo install -m 0755 libmadgwickIMU..s0.1 /usr/local/lib/libmadgwickIMU.so.1 sudo ln -sf /usr/local/lib/libmadgwickIMU.so.1 /usr/local/lib/libmadwickIMU.so sudo ldconfig gcc -Wall -o testing testing.c -lmadwickIMU ./testing
‘testing’ seem to do the right thing. Going into squeak (cog/spur/pi) and trying a method like - invSqrt: floatval #<cdecl: float ‘invSqrt’ (float) module: ‘madgwickIMU’> ^self externalCallFailed
- just gives me the not found module error.
I’ve restarted squeak after building the lib, I’ve opened a new terminal after building the lib (just in case there’s some stupid path-exporting nonsense I don’t understand etc) and I’ve made sure to smile only on the left side. What on earth am I forgetting?
tim
tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful Latin Phrases:- Braccae illae virides cum subucula rosea et tunica Caledonia-quam elenganter concinnatur! = Those green pants go so well with that pink shirt and the plaid jacket!
On 09-09-2015, at 2:07 PM, Ken G. Brown kbrown@mac.com wrote:
On Sep 9, 2015, at 12:17, tim Rowledge tim@rowledge.org wrote:
sudo install -m 0755 libmadgwickIMU..s0.1 /usr/local/lib/libmadgwickIMU.so.1 sudo ln -sf /usr/local/lib/libmadgwickIMU.so.1 /usr/local/lib/libmadwickIMU.so
^
Is there a reason for the madwick instead of madgwick?
Sigh; yes, a stupid typo when writing the email. Not in the ‘actual’ commandline. Now I’m running dbg through loading te wiringpi library that it *does* find ok, to see where it thinks it finds it. This is getting really a bit daft.
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim The substance "Hey Y'all, watch this!" is known by the state of California to be hazardous to your health.
So after too much annoyance I finally found the stupid problem. It’s an object lesson in ‘stupid things OSs do to people’.
I’m sure somebody somewhere thought it was a good idea to scatter libraries around the place and then make it possible for applications to not know about all of them. The result is that you end up with shell scripts that try to work out what the library paths are and set environment variables and/or pass arguments along, often to yet another script. Eventually you get to some code in the application that has to look up something involving all this cruft and just have to hope it was all done reasonably well.
And of course, no two *nix versions actually agree on what the paths should be. What a concept!
Thus my situation today; a library lives in /usr/local/lib and I naively make another library and sit it next to that. After all, the first library works ok, right? No problem. But the damn scripts don’t actually do anything with this path, as I discovered after a tedious pair of debugging runs when the *working* library didn’t work. I happened upon looking at all the places where the module loading code seemed to peek. And lo! A link from one such place to the %$^ing /usr/local/lib/libwiringPi.so file. Sigh. Make a link for my new library and it actually loads. Mind you, it returns a Character instead of a Float, so something else is happening now.
I still can’t work out how that link got there. I still can’t work out how the ldconfig cache-thingy doesn’t let the library load. I still can’t work out why RISC OS isn’t the normal OS. Thanks for the assorted suggestions!
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Ready to check in at the HaHa Hilton.
On Wed, Sep 09, 2015 at 11:17:08AM -0700, tim Rowledge wrote:
I?m trying - and so far failing - to do what should surely be a very simple thing. This isn?t a new situation? especially on unix.
I have a single C file with just two functions. I have a matching H file. I want to make them into a dynamic library that I can call via FFI. This really shouldn?t be rocket science stuff!
<OT> I assume there is some good reason that you would not do an end run around all that rocket science and just write a plugin? After all, you are the person who wrote the excellent early papers on how to extend the VM with plugins, and most of what little I know of VMs came from reading your early work on the topic.
I would hate to be the one to deny a masochist his private pleasures, but really, why not not just do it the easy way? </OT>
Dave
http://sdmeta.gforge.inria.fr/FreeBooks/CollectiveNBlueBook/greenberg.pdf
Write it in Smalltalk:
#reverseInPlaceFrom:to:
| temp | 0 to: to - from // 2 do: [:index | temp ← self at: from + index. self at: from + index put: (self at: to-index). self at: to-index put: temp]
Re-write it as Slang:
#primReverseFromto
self export: true. self var: #rcvr declareC: 'int *rcvr'. to ← interpreterProxy stackIntegerValue: 0. from ← interpreterProxy stackIntegerValue: 1. rcvrOop ← interpreterProxy stackObjectValue: 2. rcvr ← self cCoerce: (interpreterProxy firstIndexableField: rcvrOop) to: 'int *'. interpreterProxy success: (from >= 1 and: [from+1 <= to]). interpreterProxy success: (to <= (interpreterProxy stSizeOf: rcvrOop)). interpreterProxy failed ifTrue: [^nil]. rcvr ← rcvr - 1. "adjust for 1-based indexing." 0 to: to-from/2 do: [:index | t ← rcvr at: from + index. rcvr at: from + index put: (rcvr at: to-index). rcvr at: to-index put: t]. interpreterProxy pop: 3 thenPush: rcvrOop
Or subclass the long lost TestCodeGenerator to do it for you!
Chris
For those of you watching at home, the article above has the HelloWorld of plugins. Igor changed is slightly for a lecture in 2011 to make a plugin called TheUniversalAnswer. It returns 42.
#answerSeventeen
self export: true. interpreterProxy pop: 1 thenPush: (interpreterProxy integerObjectOf: 17)
All you need now is a compiling rig with two VMs and two images. The VM you start your VMMaker image with. The VM you compile from the VMMaker source you just generated. And the pristine target image you start with the VM you just compiled to prove it works.
Your spiral into plugin compiling madness starts with this handy script:
http://lists.squeakfoundation.org/pipermail/squeak-dev/2012-October/166038.h...
On 2015-09-09 9:53 PM, David T. Lewis wrote:
On Wed, Sep 09, 2015 at 11:17:08AM -0700, tim Rowledge wrote:
I?m trying - and so far failing - to do what should surely be a very simple thing. This isn?t a new situation? especially on unix.
I have a single C file with just two functions. I have a matching H file. I want to make them into a dynamic library that I can call via FFI. This really shouldn?t be rocket science stuff!
<OT> I assume there is some good reason that you would not do an end run around all that rocket science and just write a plugin? After all, you are the person who wrote the excellent early papers on how to extend the VM with plugins, and most of what little I know of VMs came from reading your early work on the topic.
I would hate to be the one to deny a masochist his private pleasures, but really, why not not just do it the easy way?
</OT>
Dave
On 09-09-2015, at 6:53 PM, David T. Lewis lewis@mail.msen.com wrote:
On Wed, Sep 09, 2015 at 11:17:08AM -0700, tim Rowledge wrote:
I?m trying - and so far failing - to do what should surely be a very simple thing. This isn?t a new situation? especially on unix.
I have a single C file with just two functions. I have a matching H file. I want to make them into a dynamic library that I can call via FFI. This really shouldn?t be rocket science stuff!
<OT> I assume there is some good reason that you would not do an end run around all that rocket science and just write a plugin?
Well I *did* originally point out that there was probably a really stupid mistake in my process and that is pretty much it. In my defence I was in the midst of FFI-ing to multiple external libraries for assorted Pi add-on doohickeys and getting somewhat inured to the idea.
But I think I may re-do it as a plugin today, not least because it seems that the ARM ffi interface has a problem with returning floats; they come back as Character null. I may not be a great IEEE floating point standard expert but that doesn’t seem quite right.
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Useful random insult:- Not enough sense to come in out of the rain.
On Thu, Sep 10, 2015 at 10:29 AM, tim Rowledge tim@rowledge.org wrote:
On 09-09-2015, at 6:53 PM, David T. Lewis lewis@mail.msen.com wrote:
On Wed, Sep 09, 2015 at 11:17:08AM -0700, tim Rowledge wrote:
I?m trying - and so far failing - to do what should surely be a very
simple
thing. This isn?t a new situation? especially on unix.
I have a single C file with just two functions. I have a matching H
file.
I want to make them into a dynamic library that I can call via FFI. This really shouldn?t be rocket science stuff!
<OT> I assume there is some good reason that you would not do an end run around all that rocket science and just write a plugin?
Well I *did* originally point out that there was probably a really stupid mistake in my process and that is pretty much it. In my defence I was in the midst of FFI-ing to multiple external libraries for assorted Pi add-on doohickeys and getting somewhat inured to the idea.
But I think I may re-do it as a plugin today, not least because it seems that the ARM ffi interface has a problem with returning floats; they come back as Character null. I may not be a great IEEE floating point standard expert but that doesn’t seem quite right.
I'm sure this can be fixed. Have you talked to Doug McPherson?
_,,,^..^,,,_ best, Eliot
On 10-09-2015, at 12:33 PM, Eliot Miranda eliot.miranda@gmail.com wrote:
But I think I may re-do it as a plugin today, not least because it seems that the ARM ffi interface has a problem with returning floats; they come back as Character null. I may not be a great IEEE floating point standard expert but that doesn’t seem quite right.
I'm sure this can be fixed. Have you talked to Doug McPherson?
Yup.
And after much head-scratching because I’ve completely forgotten how plugin building works, I finally have a plugin that takes 9 float values, does unspeakable things to them and spits out a four float quaternion answer. On a Pi2 it test at ~ 8 micro-sec per call, which isn’t bad for 270+ floating point operations including 150 divides. The next fun is feeding live IMU data to it and finding away to display something meaningful as a result.
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Strange OpCodes: BOMB: Burn Out Memory Banks
On Thu, Sep 10, 2015 at 06:55:55PM -0700, tim Rowledge wrote:
On 10-09-2015, at 12:33 PM, Eliot Miranda eliot.miranda@gmail.com wrote:
But I think I may re-do it as a plugin today, not least because it seems that the ARM ffi interface has a problem with returning floats; they come back as Character null. I may not be a great IEEE floating point standard expert but that doesn?t seem quite right.
I'm sure this can be fixed. Have you talked to Doug McPherson?
Yup.
And after much head-scratching because I?ve completely forgotten how plugin building works, I finally have a plugin that takes 9 float values, does unspeakable things to them and spits out a four float quaternion answer. On a Pi2 it test at ~ 8 micro-sec per call, which isn?t bad for 270+ floating point operations including 150 divides. The next fun is feeding live IMU data to it and finding away to display something meaningful as a result.
Can you send a copy of your plugin as a fileout, change set, or mcz?
I am expecting that you have one primitive with 9 double precision Float objects as parameters that are coerced to single precision floats and passed as parameters to MadgwickAHRSupdate(), which deposits the results into the q0, q1, q2, and q3 variables, which are coerced back to double precision Float objects and pushed back to the image as the result. Is that right?
Thanks, Dave
On Thu, Sep 10, 2015 at 10:29:24AM -0700, tim Rowledge wrote:
On 09-09-2015, at 6:53 PM, David T. Lewis lewis@mail.msen.com wrote:
On Wed, Sep 09, 2015 at 11:17:08AM -0700, tim Rowledge wrote:
I?m trying - and so far failing - to do what should surely be a very simple thing. This isn?t a new situation? especially on unix.
I have a single C file with just two functions. I have a matching H file. I want to make them into a dynamic library that I can call via FFI. This really shouldn?t be rocket science stuff!
<OT> I assume there is some good reason that you would not do an end run around all that rocket science and just write a plugin?
Well I *did* originally point out that there was probably a really stupid mistake in my process and that is pretty much it. In my defence I was in the midst of FFI-ing to multiple external libraries for assorted Pi add-on doohickeys and getting somewhat inured to the idea.
But I think I may re-do it as a plugin today, not least because it seems that the ARM ffi interface has a problem with returning floats; they come back as Character null. I may not be a great IEEE floating point standard expert but that doesn?t seem quite right.
I don't know what got into me, but I brewed up a nice pot of coffee this morning and ended up with http://squeaksource.com/MadgwickAHRS/
This is a plugin, accessor class, and unit tests that claim to demonstrate that the plugin works.
I used FloatArray for parameter passing, on the theory that users of the plugin may be doing float (not double) arithmetic, so it may be more efficient to pass values in that manner.
It works with 32/64 bit image and host, and the plugin builds without complaint (trunk with Ian's Cmake build) if you put the library source files MadgwickAHRS.c and MadgwickAHRS.h in platforms/Cross/plugins/MadgwickAHRS/
The MadgwickAHRS library is licensed GPL, so it would be best to link the plugin dynamically to e.g. /usr/local/iib/libwmadgwickIMU.so.1 rather than static link to the C code as I have done so far. If there is any interest in the plugin, I'll see if I can figure out the linker magic.
See class MadgwickAHRSTest for examples.
Repository is at http://www.squeaksource.com/MadgwickAHRS
Tim, I added you as developer on the squeaksource.com repository in case you want to make use of this.
Dave
Cool. I'm going to try this out.
Chris On Sep 12, 2015 7:47 PM, "David T. Lewis" lewis@mail.msen.com wrote:
On Thu, Sep 10, 2015 at 10:29:24AM -0700, tim Rowledge wrote:
On 09-09-2015, at 6:53 PM, David T. Lewis lewis@mail.msen.com wrote:
On Wed, Sep 09, 2015 at 11:17:08AM -0700, tim Rowledge wrote:
I?m trying - and so far failing - to do what should surely be a very
simple
thing. This isn?t a new situation? especially on unix.
I have a single C file with just two functions. I have a matching H
file.
I want to make them into a dynamic library that I can call via FFI.
This
really shouldn?t be rocket science stuff!
<OT> I assume there is some good reason that you would not do an end run around all that rocket science and just write a plugin?
Well I *did* originally point out that there was probably a really
stupid mistake in my process and that is pretty much it. In my defence I was in the midst of FFI-ing to multiple external libraries for assorted Pi add-on doohickeys and getting somewhat inured to the idea.
But I think I may re-do it as a plugin today, not least because it seems
that the ARM ffi interface has a problem with returning floats; they come back as Character null. I may not be a great IEEE floating point standard expert but that doesn?t seem quite right.
I don't know what got into me, but I brewed up a nice pot of coffee this morning and ended up with http://squeaksource.com/MadgwickAHRS/
This is a plugin, accessor class, and unit tests that claim to demonstrate that the plugin works.
I used FloatArray for parameter passing, on the theory that users of the plugin may be doing float (not double) arithmetic, so it may be more efficient to pass values in that manner.
It works with 32/64 bit image and host, and the plugin builds without complaint (trunk with Ian's Cmake build) if you put the library source files MadgwickAHRS.c and MadgwickAHRS.h in platforms/Cross/plugins/MadgwickAHRS/
The MadgwickAHRS library is licensed GPL, so it would be best to link the plugin dynamically to e.g. /usr/local/iib/libwmadgwickIMU.so.1 rather than static link to the C code as I have done so far. If there is any interest in the plugin, I'll see if I can figure out the linker magic.
See class MadgwickAHRSTest for examples.
Repository is at http://www.squeaksource.com/MadgwickAHRS
Tim, I added you as developer on the squeaksource.com repository in case you want to make use of this.
Dave
On 12-09-2015, at 6:47 PM, David T. Lewis lewis@mail.msen.com wrote:
I don't know what got into me, but I brewed up a nice pot of coffee this morning and ended up with http://squeaksource.com/MadgwickAHRS/
This is a plugin, accessor class, and unit tests that claim to demonstrate that the plugin works.
I used FloatArray for parameter passing, on the theory that users of the plugin may be doing float (not double) arithmetic, so it may be more efficient to pass values in that manner.
Cool! I did actually write one as well, but I used an array of BoxedFloat64 (or whatever it is) for input and create a 4 element array for the quaternion result. I considered a FloatArray as well but a) I’ve never used one before, so I’m scared of them b) Won’t they be arrays of 64bit float values on a 64-bit image? c) I’m pretty sure I will have to create a bunch of floats when reading the IMU chip anyway, so since I have them, might at well stick’em in an array.
I did consider making the array 13 long so the result could be just appended. Might be worth trying?
The good news is that on a Pi 2 the call as-is costs ~8micro-sec, which considering it apparently uses ~50 +, 60 -, 150 *, 14 / and 5 sqrt floating point calls is quite impressive.
And yes, I suppose we’ll need to keep this as an external plugin to dodge the gnu-stasi. Sigh.
tim -- tim Rowledge; tim@rowledge.org; http://www.rowledge.org/tim Oxymorons: Same difference
On Sat, Sep 12, 2015 at 08:49:50PM -0700, tim Rowledge wrote:
On 12-09-2015, at 6:47 PM, David T. Lewis lewis@mail.msen.com wrote:
I don't know what got into me, but I brewed up a nice pot of coffee this morning and ended up with http://squeaksource.com/MadgwickAHRS/
This is a plugin, accessor class, and unit tests that claim to demonstrate that the plugin works.
I used FloatArray for parameter passing, on the theory that users of the plugin may be doing float (not double) arithmetic, so it may be more efficient to pass values in that manner.
Cool! I did actually write one as well, but I used an array of BoxedFloat64 (or whatever it is) for input and create a 4 element array for the quaternion result. I considered a FloatArray as well but a) I?ve never used one before, so I?m scared of them
Well it's basically the only convenient way to deal with float (as opposed to double) floating point values. In Squeak, a Float is a C double, and AFIK the only thing that directly represents single precision floats is FloatArray. You would be justified in being scared of them, especially if any of this sounds like it makes sense. But it does work and it might be more efficient than arrays of Float (C doubles). Or maybe not, I don't have any way to measure it. But I tried to set things up so that the FloatArray things can be reused to avoid allocations and type conversions, so maybe it will help.
b) Won?t they be arrays of 64bit float values on a 64-bit image?
On the 64 bit V3 image, no. For 64 bit Spur, I am not sure. But by definition I would expect FloatArray to contain single precision float values in any image format, so there is a good chance that it will work on 64 bit Spur also. I did test on 64 bit V3, and that passes the unit tests.
c) I?m pretty sure I will have to create a bunch of floats when reading the IMU chip anyway, so since I have them, might at well stick?em in an array.
I was mainly thinking of matching the parameters to MadgwickAHRSupdate(), which are single precision float. I don't know anything about IMU chips, so I don't have a clue if that is a good fit. And I had to look up "IMU" on Google, so that should give you an idea of my level of expertise.
I did consider making the array 13 long so the result could be just appended. Might be worth trying?
That would work also. I don't think there would be a performance difference either way, so whichever is easier to understand and document is probably good.
The good news is that on a Pi 2 the call as-is costs ~8micro-sec, which considering it apparently uses ~50 +, 60 -, 150 *, 14 / and 5 sqrt floating point calls is quite impressive.
And yes, I suppose we?ll need to keep this as an external plugin to dodge the gnu-stasi. Sigh.
Building external is easy, not an issue. But I think we need to keep the GPL source code out of the platforms/Cross tree to prevent license confusion, so that means linking to an installed library rather than linking the GPL code directly into the plugin. That should not be a problem but I have not actually done it yet.
Dave
Hi,
Am 13.09.2015 um 06:31 schrieb David T. Lewis:
Well it's basically the only convenient way to deal with float (as opposed to double) floating point values. In Squeak, a Float is a C double, and AFIK the only thing that directly represents single precision floats is FloatArray. You would be justified in being scared of them, especially if any of this sounds like it makes sense. But it does work and it might be more efficient than arrays of Float (C doubles). Or maybe not, I don't have any way to measure it. But I tried to set things up so that the FloatArray things can be reused to avoid allocations and type conversions, so maybe it will help.
FloatArray offers a lot of speed up as long as the operations provided by Float array are sufficient. Getting Squeak Floats into and out of Float Array is expensive. This: Time millisecondsToRun: [|array1 array2| array1 := (1.0 to: 10000.0 by: 0.1) asArray. array2 := (10000.0 to: 1.0 by: -0.1) asArray. 1000 timesRepeat: [|result| result := array1 * array2]] 22 seconds is not much slower than using FloatArray Time millisecondsToRun: [|array1 array2| array1 := (1.0 to: 10000.0 by: 0.1) asArray. array2 := (10000.0 to: 1.0 by: -0.1) asArray. 1000 timesRepeat: [|result| result := (array1 asFloatArray * array2 asFloatArray)]] 19 seconds If you change the last line to use more operations supported by FloatArray like: result := (array1 asFloatArray * array2 asFloatArray + 7.0 * 3.0) sum with FloatArrays you get the same speed, without the conversion to FloatArray it takes three times as long.
If you need to use FloatArray>>at: and #at:put very often FloatArrays may get slower than Arrays of Float. So benchmark and benchmark again.
And if your values get small, FloatArray may round them to zero which is bad for division.
I used FloatArray a lot for Audio processing and neural networks but they need to be handled with care. I ended up using both depending on the algorithm.
Cheers,
Herbert
On Sun, Sep 13, 2015 at 01:34:32PM +0200, Herbert K??nig wrote:
Hi,
Am 13.09.2015 um 06:31 schrieb David T. Lewis:
Well it's basically the only convenient way to deal with float (as opposed to double) floating point values. In Squeak, a Float is a C double, and AFIK the only thing that directly represents single precision floats is FloatArray. You would be justified in being scared of them, especially if any of this sounds like it makes sense. But it does work and it might be more efficient than arrays of Float (C doubles). Or maybe not, I don't have any way to measure it. But I tried to set things up so that the FloatArray things can be reused to avoid allocations and type conversions, so maybe it will help.
FloatArray offers a lot of speed up as long as the operations provided by Float array are sufficient. Getting Squeak Floats into and out of Float Array is expensive. This: Time millisecondsToRun: [|array1 array2| array1 := (1.0 to: 10000.0 by: 0.1) asArray. array2 := (10000.0 to: 1.0 by: -0.1) asArray. 1000 timesRepeat: [|result| result := array1 * array2]] 22 seconds is not much slower than using FloatArray Time millisecondsToRun: [|array1 array2| array1 := (1.0 to: 10000.0 by: 0.1) asArray. array2 := (10000.0 to: 1.0 by: -0.1) asArray. 1000 timesRepeat: [|result| result := (array1 asFloatArray * array2 asFloatArray)]] 19 seconds If you change the last line to use more operations supported by FloatArray like: result := (array1 asFloatArray * array2 asFloatArray + 7.0 * 3.0) sum with FloatArrays you get the same speed, without the conversion to FloatArray it takes three times as long.
If you need to use FloatArray>>at: and #at:put very often FloatArrays may get slower than Arrays of Float. So benchmark and benchmark again.
And if your values get small, FloatArray may round them to zero which is bad for division.
I used FloatArray a lot for Audio processing and neural networks but they need to be handled with care. I ended up using both depending on the algorithm.
Herbert,
Thanks, that is good to know. Indeed it might be faster to just use arrays of Float, and it might be worth trying both ways to see which is better.
Dave
Hi Herbert,
On Sun, Sep 13, 2015 at 4:34 AM, Herbert König herbertkoenig@gmx.net wrote:
Hi,
Am 13.09.2015 um 06:31 schrieb David T. Lewis:
Well it's basically the only convenient way to deal with float (as opposed to double) floating point values. In Squeak, a Float is a C double, and AFIK the only thing that directly represents single precision floats is FloatArray. You would be justified in being scared of them, especially if any of this sounds like it makes sense. But it does work and it might be more efficient than arrays of Float (C doubles). Or maybe not, I don't have any way to measure it. But I tried to set things up so that the FloatArray things can be reused to avoid allocations and type conversions, so maybe it will help.
FloatArray offers a lot of speed up as long as the operations provided by Float array are sufficient. Getting Squeak Floats into and out of Float Array is expensive. This: Time millisecondsToRun: [|array1 array2| array1 := (1.0 to: 10000.0 by: 0.1) asArray. array2 := (10000.0 to: 1.0 by: -0.1) asArray. 1000 timesRepeat: [|result| result := array1 * array2]] 22 seconds is not much slower than using FloatArray Time millisecondsToRun: [|array1 array2| array1 := (1.0 to: 10000.0 by: 0.1) asArray. array2 := (10000.0 to: 1.0 by: -0.1) asArray. 1000 timesRepeat: [|result| result := (array1 asFloatArray * array2 asFloatArray)]] 19 seconds If you change the last line to use more operations supported by FloatArray like: result := (array1 asFloatArray * array2 asFloatArray + 7.0 * 3.0) sum with FloatArrays you get the same speed, without the conversion to FloatArray it takes three times as long.
If you need to use FloatArray>>at: and #at:put very often FloatArrays may get slower than Arrays of Float. So benchmark and benchmark again.
That's right. Using FloatArray implies an object allocation on every at:, to construct the (boxed) Float result. 64-bit Spur will change this equation because most of the time the floats fetched will be immediate, instances of SmallFloat64. And indeed they may make it attractive to have a 64-bit float array type.
And if your values get small, FloatArray may round them to zero which is bad for division.
I used FloatArray a lot for Audio processing and neural networks but they need to be handled with care. I ended up using both depending on the algorithm.
Cheers,
Herbert
We might as well have primitives which write their result into an object passed as parameter, or primitives which update the receiver, like the ones provided by KedamaFloatArray. But with SmallFloat64 being on the way, it's not that tempting to write such primitives.
Levente
On Mon, 14 Sep 2015, Eliot Miranda wrote:
Hi Herbert,
On Sun, Sep 13, 2015 at 4:34 AM, Herbert König herbertkoenig@gmx.net wrote: Hi,
Am 13.09.2015 um 06:31 schrieb David T. Lewis: Well it's basically the only convenient way to deal with float (as opposed to double) floating point values. In Squeak, a Float is a C double, and AFIK the only thing that directly represents single precision floats is FloatArray. You would be justified in being scared of them, especially if any of this sounds like it makes sense. But it does work and it might be more efficient than arrays of Float (C doubles). Or maybe not, I don't have any way to measure it. But I tried to set things up so that the FloatArray things can be reused to avoid allocations and type conversions, so maybe it will help. FloatArray offers a lot of speed up as long as the operations provided by Float array are sufficient. Getting Squeak Floats into and out of Float Array is expensive. This: Time millisecondsToRun: [|array1 array2| array1 := (1.0 to: 10000.0 by: 0.1) asArray. array2 := (10000.0 to: 1.0 by: -0.1) asArray. 1000 timesRepeat: [|result| result := array1 * array2]] 22 seconds is not much slower than using FloatArray Time millisecondsToRun: [|array1 array2| array1 := (1.0 to: 10000.0 by: 0.1) asArray. array2 := (10000.0 to: 1.0 by: -0.1) asArray. 1000 timesRepeat: [|result| result := (array1 asFloatArray * array2 asFloatArray)]] 19 seconds If you change the last line to use more operations supported by FloatArray like: result := (array1 asFloatArray * array2 asFloatArray + 7.0 * 3.0) sum with FloatArrays you get the same speed, without the conversion to FloatArray it takes three times as long. If you need to use FloatArray>>at: and #at:put very often FloatArrays may get slower than Arrays of Float. So benchmark and benchmark again.
That's right. Using FloatArray implies an object allocation on every at:, to construct the (boxed) Float result. 64-bit Spur will change this equation because most of the time the floats fetched will be immediate, instances of SmallFloat64. And indeed they may make it attractive to have a 64-bit float array type.
And if your values get small, FloatArray may round them to zero which is bad for division. I used FloatArray a lot for Audio processing and neural networks but they need to be handled with care. I ended up using both depending on the algorithm. Cheers, Herbert
-- _,,,^..^,,,_ best, Eliot
On Mon, Sep 14, 2015 at 11:33:35PM +0200, Levente Uzonyi wrote:
We might as well have primitives which write their result into an object passed as parameter, or primitives which update the receiver, like the ones provided by KedamaFloatArray. But with SmallFloat64 being on the way, it's not that tempting to write such primitives.
Levente
Actually, that is exactly what I did. The caller provides a pre-allocated (and potentially reusable) FloatArray of size 4, and the primitive copies four result values into the array fields. There is no need for allocating Float objects within the primitive, and no need to convert float to double in the primitive. This may or may not be useful depending on how the primitive is used, but it does allow the user an opportunity to optimize both by reusing an existing FloatArray instance for the results, and by allocating new Float object only if and when the elements of that array are actually read and used.
I would expect that FloatArray will still have 32-bit float values in a 64-bit object memory, after all that is what it was designed to do. The need to allocate Float objects and do conversion from single to double floats should go away with 64-bits, so that should be a win. I expect that updates for MadgwickAHRSPlugin should be minimal.
Dave
On Mon, 14 Sep 2015, Eliot Miranda wrote:
Hi Herbert,
On Sun, Sep 13, 2015 at 4:34 AM, Herbert K??nig herbertkoenig@gmx.net wrote: Hi,
Am 13.09.2015 um 06:31 schrieb David T. Lewis: Well it's basically the only convenient way to deal with float (as opposed to double) floating point values. In Squeak, a Float is a C double, and AFIK the only thing that directly represents single precision floats is FloatArray. You would be justified in being scared of them, especially if any of this sounds like it makes sense. But it does work and it might be more efficient than arrays of Float (C doubles). Or maybe not, I don't have any way to measure it. But I tried to set things up so that the FloatArray things can be reused to avoid allocations and type conversions, so maybe it will help. FloatArray offers a lot of speed up as long as the operations provided by Float array are sufficient. Getting Squeak Floats into and out of Float Array is expensive. This: Time millisecondsToRun: ?? ?? [|array1 array2| ?? ?? array1 := (1.0 to: 10000.0 by: 0.1) asArray. ?? ?? array2 := (10000.0 to: 1.0 by: -0.1) asArray. ?? ?? 1000 timesRepeat: [|result| ?? ?? ?? ?? result := array1?? * array2]] 22 seconds is not much slower than using FloatArray Time millisecondsToRun: ?? ?? [|array1 array2| ?? ?? array1 := (1.0 to: 10000.0 by: 0.1) asArray. ?? ?? array2 := (10000.0 to: 1.0 by: -0.1) asArray. ?? ?? 1000 timesRepeat: [|result| ?? ?? ?? ?? result := (array1 asFloatArray * array2 asFloatArray)]] 19 seconds If you change the last line to use more operations supported by FloatArray like: ?? ?? ?? ?? result := (array1 asFloatArray * array2 asFloatArray + 7.0 * 3.0) sum with FloatArrays you get the same speed, without the conversion to FloatArray it takes three times as long. If you need to use FloatArray>>at: and #at:put very often FloatArrays may get slower than Arrays of Float. So benchmark and benchmark again.
That's right.?? Using FloatArray implies an object allocation on every at:, to construct the (boxed) Float result. ??64-bit Spur will change this equation because most of the time the floats fetched will be immediate, instances of SmallFloat64.?? And indeed they may make it attractive to have a 64-bit float array type.
And if your values get small, FloatArray may round them to zero which is bad for division. I used FloatArray a lot for?? Audio processing and neural networks but they need to be handled with care. I ended up using both depending on the algorithm. Cheers, Herbert
-- _,,,^..^,,,_ best,??Eliot
On Sun, Sep 13, 2015 at 9:47 AM, David T. Lewis lewis@mail.msen.com wrote:
On Thu, Sep 10, 2015 at 10:29:24AM -0700, tim Rowledge wrote:
On 09-09-2015, at 6:53 PM, David T. Lewis lewis@mail.msen.com wrote:
On Wed, Sep 09, 2015 at 11:17:08AM -0700, tim Rowledge wrote:
I?m trying - and so far failing - to do what should surely be a very simple thing. This isn?t a new situation? especially on unix.
I have a single C file with just two functions. I have a matching H file. I want to make them into a dynamic library that I can call via FFI. This really shouldn?t be rocket science stuff!
<OT> I assume there is some good reason that you would not do an end run around all that rocket science and just write a plugin?
Well I *did* originally point out that there was probably a really stupid mistake in my process and that is pretty much it. In my defence I was in the midst of FFI-ing to multiple external libraries for assorted Pi add-on doohickeys and getting somewhat inured to the idea.
But I think I may re-do it as a plugin today, not least because it seems that the ARM ffi interface has a problem with returning floats; they come back as Character null. I may not be a great IEEE floating point standard expert but that doesn?t seem quite right.
I don't know what got into me, but I brewed up a nice pot of coffee this morning and ended up with http://squeaksource.com/MadgwickAHRS/
This is a plugin, accessor class, and unit tests that claim to demonstrate that the plugin works.
I used FloatArray for parameter passing, on the theory that users of the plugin may be doing float (not double) arithmetic, so it may be more efficient to pass values in that manner.
It works with 32/64 bit image and host, and the plugin builds without complaint (trunk with Ian's Cmake build) if you put the library source files MadgwickAHRS.c and MadgwickAHRS.h in platforms/Cross/plugins/MadgwickAHRS/
The MadgwickAHRS library is licensed GPL, so it would be best to link the plugin dynamically to e.g. /usr/local/iib/libwmadgwickIMU.so.1 rather than static link to the C code as I have done so far.
Unfortunately the distinction you make between static and dynamic linking is incorrect for GPL code [1][2], and true only for LGPL code.
Now I notice that although [3] indicates the license is GPL, [3] points to original post [4] which was LGPL. A little confusing since neither [3] nor [4] state a license in the C source files. It seems [4] is the same author, so maybe its worth a polite query as to why the license changed from LGPL to GPL.
[1] http://www.gnu.org/licenses/gpl-faq.html#GPLStaticVsDynamic [2] http://www.dwheeler.com/essays/floss-license-slide.html [3] http://www.x-io.co.uk/open-source-imu-and-ahrs-algorithms/ [4] https://code.google.com/p/imumargalgorithm30042010sohm/
cheers -ben
squeak-dev@lists.squeakfoundation.org