Shop OBEX P1 Docs P2 Docs Learn Events
Propeller 9-DOF Experimenter board – LIMITED QUANTY - Page 4 — Parallax Forums

Propeller 9-DOF Experimenter board – LIMITED QUANTY

1246

Comments

  • Heater.Heater. Posts: 21,230
    edited 2014-09-27 01:21
    Dave,
    I connected a serial link between the HoverFly and a Prop Demo Board, and I got the Visualizer working earlier this morning.
    In case you missed my comment in the above TL;DR post this is cool, well done. I have to get a Prop and VGA screen together now...
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2014-09-27 06:08
    @Heater
    I can appreciate that you have enjoyed learning how to get your IMU to the Esprino board and then into JavaScript in Chrome on your PC. And that this has been a really useful demonstration of what quaternions are about, and that you have discovered they are supported in mainstream software. I am even glad that I was able to turn you into the Madjwick/Quaternion maven that you appear to have become. (It is a lot of fun to convert your disinterest into enthusiam.)

    Okay, when I mentioned RS-232 -- what I really should have said was asynchronous 8 bit serial as opposed to synchronous 8 bit serial communications. Generally is is USB that does it these days, not RS232 and not RS422/485.

    You will have to forgive me for expecting that somehow, somewhere a Parallax product might be included in this project. I have just presumed that is is good form to do so as they host the forums. Forgive me for being so crass. I will just muddle along in my own directions.

    I was just getting deja vu of a 3-D printer project that we had earlier this year in which I tried rather dismally to migrate Arduino code to a Propeller 1. I seem to be suffering traumatic flash-backs.
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-09-27 06:16
    Here's the PropViz program and the modified DCM program called "Main HoverFlyGimbal - PropViz". PropViz runs on a board that supports VGA, such as the Propeller Demo Board, which is what I am using. The DCM "Main HoverFlyGimbal - PropViz" program runs on the HoverFly board. The serial link requires two wires between the HoverFly and the other Prop board -- one for ground and one for transmit from the HoverFly to the VGA Prop.

    The rotation matrix is sent from the HoverFly in 8 bytes plus a CR. The VGA Prop looks for the CR, and then stores the 8 bytes for the rotation matrix. It then uses the YZ columns from the rotation matrix for the 2D projection on the VGA screen. Each byte that is received is interpreted as a signed integer with a range of -128 to 127.

    I found that I had to read out the rotation matrix in a ZXY order because the DCM code stores it that way. The X and Y values seem to work OK on PropViz, but the Z axis rotates in the opposite direction. That still needs to be fixed.
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2014-09-27 06:24
    @Dave
    Absolutely wonderful.. an all Propeller solution with VGA support. I guess that will assuage Heater's fears that the Propeller might not be enough one way or another.

    Both you and Heater do run circles around what I seem to get done.
  • PublisonPublison Posts: 12,366
    edited 2014-09-27 06:54
    Dave Hein wrote: »
    The HoverFly has large mounting holes that accept rubber grommets. Does anyone know of a good source for getting the rubber grommets?

    I found this one at McMastercarr on this page. Good news is is a perfect fit according to my digital calipers. Bad news, pack of 25. Group buy? That would satisfy six people at about 2 bucks a board, (plus shipping). I'll order if a few people show the want.
  • Heater.Heater. Posts: 21,230
    edited 2014-09-27 07:01
    Loopy,
    It is a lot of fun to convert your disinterest into enthusiam.
    Yep. Much appreciated. Thank you.

    The thing about serial streams is that we don't think RS232 or RS485 or USB or any other hardware transport. What we are talking about is streams of bytes carried in whatever way possible. This concept is fundamental to Unix, for example, where everything is a file and files are just bytes. And we character devices that send a receive byte streams no matter what the hardware is. And we have pipes and sockets etc.

    Things get a bit weird in the JS world and web technologies because JS originally knew only numbers and those numbers were 64 bit floats. You can use those as ints or bytes but it's a pain and JS had no concept of byte stream IO.

    This has changed recently with addition of typed arrays to JS which can be used to handle bytes, words etc for for use with opengl graphics, serial ports etc.
    You will have to forgive me for expecting that somehow, somewhere a Parallax product might be included in this project.
    Ah, good point.

    I have excuses....currently I don't have any accelerometers, gyros, magnetometers that I can attach to a Propeller. That will come with time. I have just put the order in for a FreeIMU board that will for sure be attached to a Propeller.
    I was just getting deja vu of a 3-D printer project that we had earlier this year in which I tried rather dismally to migrate Arduino code to a Propeller 1. I seem to be suffering traumatic flash-backs.
    Yeah, what happened to that project?

    It's a worry. Madgwick might be just too big and slow for the Prop. At some point I'll try compiling it with propgcc and seeing how it runs on my GadgetGanster board.

    Still, there is the DCC solution available.
  • Heater.Heater. Posts: 21,230
    edited 2014-09-27 07:03
    Dave,

    Great stuff.

    Need more Propellers around here.
  • Heater.Heater. Posts: 21,230
    edited 2014-09-27 08:35
    dgately,

    And any one who might be interested. I just pushed a new magwick.js with a new improved serial ASCII stream parser.

    It understands now undertsand accel, gyro, magnetometer and barometer data in messages like this:

    {"a": [10, 14, -22], "g": [30, 10, 32], "m": [4, 8, 11], "b": 0}

    All on one line. Spaces are optional. Just set the values of g, m and b to 0 if you don't have them (Actually b is not used anyway)

    I have to think about how to put some user interface on this for port and other parameter setting.

    Anyone have any suggestions?

    https://github.com/ZiCog/madgwick.js
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-09-27 12:57
    Publison wrote: »
    I found this one at McMastercarr on this page. Good news is is a perfect fit according to my digital calipers. Bad news, pack of 25. Group buy? That would satisfy six people at about 2 bucks a board, (plus shipping). I'll order if a few people show the want.
    I'm in for 4, and maybe a few more depending on how many people get into the group buy.
  • PublisonPublison Posts: 12,366
    edited 2014-09-27 13:00
    Dave Hein wrote: »
    I'm in for 4, and maybe a few more depending on how many people get into the group buy.

    Ordering the grommets on Monday Anybody else? Loppy seems to have gotten his already. If Heater needs some, I can send.
  • Heater.Heater. Posts: 21,230
    edited 2014-09-27 13:10
    Thanks for the offer Publison but I shall decline. I'm far away from actually building any serious mechanical stuff here.
  • dgatelydgately Posts: 1,630
    edited 2014-09-27 14:37
    Heater. wrote: »
    dgately,

    And any one who might be interested. I just pushed a new magwick.js with a new improved serial ASCII stream parser.

    It understands now undertsand accel, gyro, magnetometer and barometer data in messages like this:

    {"a": [10, 14, -22], "g": [30, 10, 32], "m": [4, 8, 11], "b": 0}

    All on one line. Spaces are optional. Just set the values of g, m and b to 0 if you don't have them (Actually b is not used anyway)


    https://github.com/ZiCog/madgwick.js

    I get the following (line 310 of scene.js):
    TypeErrorimuData.a.jpg


    imuData is defined in serial.js as: "var imuData;"


    What's a quick fix for this?

    Thanks,
    dgately
    1024 x 211 - 25K
  • Heater.Heater. Posts: 21,230
    edited 2014-09-27 14:53
    Hmmm...not sure.

    The data coming out of my Espruino board looks like this when I cat it directly from the serial device /dev/ttyACM0
    {"a":[3,-3,51],"g":[0,0,0],"m":[0,0,0],"b":0}
    >        
    {"a":[3,-3,51],"g":[0,0,0],"m":[0,0,0],"b":0}
    >        
    {"a":[3,-3,51],"g":[0,0,0],"m":[0,0,0],"b":0}
    >        
    .....
    
    Those lines with ">" are just junk because I'm just blasting the data out of the console of the Espruino which then puts the command prompt after it. Those lines get filtered out because the JSON parser fails on them.

    Ah, wait a minute. If I yank out my Espruino USB connection I get that same error. So basically it looks like you have no data coming in at all, or perhaps the format is not quite right.

    I just pushed a change that constructs imuData with all the correct elements like so:
    var imuData = {a: [0, 0, 0], g: [0, 0, 0], m: [0, 0, 0], b: 0};
    
    So now that error should not come out in the absence of data.
  • Heater.Heater. Posts: 21,230
    edited 2014-09-27 15:08
    It occurs to me that is another JS oddity.

    var x;

    Creates a variable called "x". So "x" is defined to exist at least. But it's type and value are still undefined.

    So then:

    y = x.a;

    Produces the error: "TypeError: Cannot read property 'a' of undefined" which is a bit confusing at first sight.

    Contrast to trying to using a non-existent object:

    y.a

    Produces the error: "ReferenceError: y is not defined".

    Thing is "undefined" does not mean the thing does not exist. "undefined" is actually a value that an existing thing can have!
  • dgatelydgately Posts: 1,630
    edited 2014-09-27 16:28
    Heater. wrote: »
    Ah, wait a minute. If I yank out my Espruino USB connection I get that same error. So basically it looks like you have no data coming in at all, or perhaps the format is not quite right.

    I just pushed a change that constructs imuData with all the correct elements like so:
    var imuData = {a: [0, 0, 0], g: [0, 0, 0], m: [0, 0, 0], b: 0};
    
    So now that error should not come out in the absence of data.

    Thanks Heater... OK, I'm getting somewhere now!

    I modified my code a little from printing print("%c%c",0x0d,0x0a); to print("\n%c",0x0a); and suddenly, I get it to work at some level (odd, those should provide the same output...). The display does not settle-down unless I'm moving the Hoverfly 9DOF around then, it settles into a more stable display with movements that reflect my turning the device around x,y, & z axis... Once I stop moving the device around or put it down, the displayed cube gets spiny around one axis.

    Here's the C code, running on the board to send the stream of data:
    [INDENT]print("{\"a\":[%d,%d,%d],",SensorDriver_Getaccx(),SensorDriver_Getaccy(),SensorDriver_Getaccz());
    print("\"g\":[%d,%d,%d],",SensorDriver_Getgyrox(),SensorDriver_Getgyroy(),SensorDriver_Getgyroz());
    print("\"m\":[%d,%d,%d]",SensorDriver_Getmagx(),SensorDriver_Getmagy(),SensorDriver_Getmagz());
    print(",\"b\":0}");
    print("\n%c",0x0a);[/INDENT]
    

    Guess I'll just need to average-out the sensor data and then send it to the stream.

    Here's a screen display showing the whole thing in-action. This is with the sensor device sitting on a fairly soft (too filter-out table movement), flat surface. Of course, the screenshot makes the box look stable but it's actually spinning around one axis...

    Magwick&9DOF.jpg


    dgately
    1024 x 640 - 129K
  • Heater.Heater. Posts: 21,230
    edited 2014-09-27 16:41
    dgatley,

    Excellent. Almost there by the sound of it.

    "spiny around one axis" sounds familiar. I don't have a gyro so I set all my g's to zero. At some point I inadvertently set some value to one g or another and that had the brick spinning around like crazy.

    Are your gyro readings signed? Or are they all positive with an offset?

    I'm tired, I have to sleep on this.
  • dgatelydgately Posts: 1,630
    edited 2014-09-27 22:43
    Heater. wrote: »

    Are your gyro readings signed? Or are they all positive with an offset?
    Signed values from the gyro... I'll fiddle with the gyro values a bit and see what comes of it!

    EDIT
    I set gyro values to always stream x0, y0, z0 and I get a stable output. In this zipped video, I am turning the sensor around one axis, then another.

    9DOPF-Minus-Gyro.mov.zip

    Now, how to employ the gyro values?

    dgately
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2014-09-27 23:12
    High vibration dampening grommets... a very nice find. But I think I am good with what I have on hand. By the time these might arrive in Taiwan, I fear that they would be about $1 USD each.
  • Heater.Heater. Posts: 21,230
    edited 2014-09-28 04:31
    dgately,

    I just had a little play with this. If I get my Esprunio to send accel from my actual accelerometer and a "fake" value of 5 for the z component of the gyro then the brick does indeed rotate around the Z axis. Works for x and y components as well.

    Like so:

    {"a":[3,-2,51],"g":[0,0,5],"m":[0,0,0],"b":0}

    So I'm at a bit of a loss as to what to advise.

    You could try putting a "console.log(myString);" in serial.js to see what is actually arriving.
  • LtechLtech Posts: 380
    edited 2014-09-28 10:44
    i just found some interesting link, do not know who make this.
    It is a try to maVlink ground station qgroundcontrol
    Take a look, cordic , quaternion for propeller ....

    https://github.com/mattmccrink/UAV-Parallax-Propeller
  • Heater.Heater. Posts: 21,230
    edited 2014-09-28 13:14
    Ltech,

    Wow, someone has been doing a lot of work there. Who is that ?
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-09-28 19:41
    I did a little more tweaking on the PropViz code and the DCM code that talks to it. In the PropViz program, I had the X axis pointing in the wrong direction, so I flipped the signs on the X row of the rotate matrix to correct this. I also changed the axis markers drawn on the screen from "I, II and III" to "X, Y and Z".

    In the DCM program I fiddled with the signs applied to the raw gyro values so that the rotation looks correct on PropViz. I also created a TransmitThread method that runs in its own cog so the update rate is independent of the transmit rate. The update rate is back to 200 Hz, while the transmit thread runs at 10 Hz. The transmit thread sends the matrix to the PropViz Prop, and also prints out the matrix scaled by 100 to the standard serial port on pins 31 and 30.

    The DCM program works correctly when doing independent X, Y or Z rotations away from, and back to zero. However, more complex rotations don't seem to work correctly. The DCM program always applies the rotation along the original XYZ axes rather than along the rotated XYZ axes. I'll have to read up on how this is done, or maybe I can derive the appropriate equations myself if I think about it long enough.
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-09-29 07:16
    After I posted HoverFly006 last night I realized that the perception of the direction of the X axis (and actually all 3 axes) depends on how the brain interprets the stick diagram. If you perceive the intersection of the 3 axes as looking at the corner of a cube from the outside you see the axes in a different direction than if you perceive it as looking from the inside of the cube. So I removed the negation of the X axis in PropViz, and changed the sign bits on the Gyro program to all be negative to make the rotations of the HoverFly card match the PropViz display.

    I think the reason for the need to negate the Gyro values is because PropViz is actually showing the rotation of the coordinate system rather than the rotation of the object within the original coordinate system. I also had to negate one of the accelerometer values to make everything consistent. The fact that the DCM program uses a ZXY coordinate ordering from the gyro/acc chips makes things a bit confusing. I'll probably generate a version of the DCM program where the XYZ coordinates match to make it easier to understand -- at least it will make it easier for me to understand it.

    In this version I also changed the formatting of the rotation matrix in the debug output to make it look cleaner.
  • JasonDorieJasonDorie Posts: 1,930
    edited 2014-09-29 13:57
    To change what you're displaying (as in, whether you're showing object in world space, or world space rotated into the object frame) just transpose the matrix (swap rows for columns).

    A pure rotation matrix is inverted by transposing it, so it's trivial to flip between a version that rotates things into that space, or out of that space.
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-09-30 05:33
    Jason, thanks for the suggestion about using the transposed rotation matrix. I'll give that a try.

    BTW, I think I found a problem in the DCM code, where rotations are always performed around the original XYZ axes instead of the rotated axes. The RotateRefToTempMatrix combines the Gyro's rotation values with the Ref matrix to produce a new rotation matrix. It essentially implements the expression R' = R*G. G is a rotation matrix consisting of unity values on the diagonal and the gyro values on the off-diagonal positions. The G matrix isn't explicitly generated in the code, but it would look like this:
     --           --
    |  1   -Rz   Ry |
    |  Rz   1   -Rx |
    | -Ry   Rx   1  |
     --           --
    
    The expression R*G applies the gyro rotation to the coordinate system first, and then applies the original rotation matrix. The correct expression should be R' = G*R, where the original rotation matrix is applied first, and then the gyro rotation is applied to the rotated space. I coded this up, and it performs the rotations correctly now.

    The drift compensation using the accelerometer tended to mask the rotation problem because the axes would be re-aligned with gravity over time. However, if the drift compensation is disabled it is clear the rotations were being done around original XYZ axes.
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-09-30 11:16
    It looks like the fix for the Gyro rotations messes up the drift compensation that uses the accelerometer. The problem is that the drift compensation was added to the gyro values, but these are no longer aligned with the original reference frame, and are aligned with the board instead. So I think the matrix equation will now look like R' = G*R*A, where A is a rotation matrix based on the difference between the current rotation matrix and the values from the accelerometer. I'll give it a try tonight when I get home to see if that works.
  • JasonDorieJasonDorie Posts: 1,930
    edited 2014-09-30 12:20
    Dave - I assume you're looking at the C# version, not the Prop version? I'll have a look. The RefMatrix *should* be stored in transposed form, that is, representing the world orientation relative to the Propeller. That way, the gyro rotations and accelerometer adjustments are all happening in the correct space. If the RefMatrix were stored as the body relative to the world, then you're right, those rotations would be incorrect.

    Edit: Ok, you're talking about the Prop code. I've turned off the reference correction in mine, and it tracks as I expect, so I'm not sure how to explain what you're seeing. If you tip the board 90 degrees forward, then tilt 90 degrees sideways, and so on, and eventually get back to level, the cube tracks the board as expected. Is this not what you're seeing?

    The PropDCM code uses X/Y/Z coordinates that are "standard 3D", where X is right, Y is up, Z is forward. This is normally how 3D cartesian space is represented. Gyro / accel data tends to make Z the vertical axis, which confuses me, so I flip the Y & Z data coming from the sensors before feeding them through the DCM code.

    I'm looking at the code, and it does seem like it's working in spite of itself... It's possible that my matrix multiply code is doing the transposition... I'll keep poking at it.
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-09-30 12:44
    No, I'm looking at the Spin Prop version. I don't do C#. I read the original paper on DCM, and I think I understand it pretty well now. What I see in the Spin Prop version is that I can make a series of rotations that should bring me back to the original orientation, and the rotation matrix ends up being something other than the identity matrix. The accelerometer adjustment will eventually bring it back to the identity matrix over time.

    As an example, rotate 90 degrees around X, 90 degrees around Z, -90 degrees around Y and then -90 degrees around Z. This should bring everything back to the starting point, but the rotation matrix ends up at a different orientation. With the changes I made I get back to the starting point.

    EDIT: I'll try your original Prop program again just to make sure I didn't break something with the my changes. The test is to disable the accelerometer adjustment, do the four 90-degree rotations that I described, and the rotation matrix should return back to the identity matrix.
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2014-10-01 01:22
    Just wanted to say "Hello" and cheer everyone on.
    I have been following all this, but also been deep into reading the maths for all that is involved. I've learned quite a bit of useful info, but don't want to distract the thread.

    Madjwick's solution has a long history that starts with using Calculus for linear regressions instead of the usual approach via the Gradient Descent linear regression algorithm. That and the use of a partial derivative matrix (Jacobian) are at the heart of better sensor fusion. But once one starts looking into these topics, there are many other uses for the same topics in computing -- hence I am busy being distracted by the exploration of possibilities.

    http://spin.atomicobject.com/2014/06/24/gradient-descent-linear-regression/
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-10-01 07:05
    Jason, I tried the original code you posted, and it does work correctly. Sorry for saying that there was a problem with it. The difference in the coordinate system used in your program and the coordinate system used in the chips is a bit confusing for me. The changes that I made to your code must have caused things to not work correctly.

    I see the advantage to using the transposed rotation matrix instead of the normal rotation matrix. Using the board's orientation as the frame of reference, and rotating the world axes does simplify the drift compensation. I'll continue to look at the way I was doing it just to complete my understanding of how that works. However, I'll go back to your method after that since it is more efficient.

    I will continue to use the board's XYZ ordering since that makes more sense to me. When working with 3D coordinate systems I normally use the Z axis to mean up. I know that 2D coordinates are always drawn with the Y axis up, and when extended to 3D the Z axis points outward. So either way works. Now I need to go back to my old textbooks and see how the 3D axes were represented. My memory may be incorrect on that. It's only been 45 years since I was first exposed to this stuff in high school math and physics. :)
Sign In or Register to comment.