|
Post by Frisbone on Sept 12, 2013 6:07:01 GMT -5
Here is how the code stands in the basic approach to using the AM data. Details are not addressed. Attachments:
|
|
|
Post by Frisbone on Sept 12, 2013 8:15:32 GMT -5
The last step of converting angle to PWM is described here:
Ok, so angles coming in as input are in radians.
Generally speaking we can only achieve a certain angle translation in a sample period as a max rate which is defined by the sensitivity settings of the game and how it interprets the joystick voltage. Voltage translates directly to an angular rate of rotation about an axis.
Ultimately we want to command the PWM to generate a signal between -1.0 and +1.0 (in reality its between 0V dc to 1.6Vdc - with zero being half-way inbetween, but the PWM driver allows you to talk to it in more meaningful terms and translates it). If it is -1.0 that means that we are rotating counter-clockwise at the maximum angular rate. If it is zero that means we are not rotating at all, and +1.0 means max in the clockwise direction.
The reality is that there are three competing limits:
- The limit of how far you can rotate in one period while still being accurately detected by the angle calculation algorithm - this limit is 90 degrees (PI/2) - in either the positive or negative direction.
- The limit of how fast a person can physically rotate a gun in one period in either direction.
- The limit of how fast the view can move in the game according to the sensitivity settings.
So ultimately we want to establish an upper limit in both directions of how far (in radians) you can rotate in one period and then use that as the divisor with your input angle. If it is greater than 1.0 then you know that you have exceeded the games ability to move as quickly as you are moving.
So lets establish a rate in radians per second that is the max joystick rate. Call it JY_RD_MAX.
To figure out how far you can travel in one period you divide JY_RD_MAX by the number of periods in a second to get JY_RD_MAX_PERIOD. Since period (POLLING_RATE) is in microsecods it is 1,000,000 / POLLING_RATE. So in the end the forumula reduces to:
PERC_PCM = <angle this period> / ((<max anglular rate on axis> / 1,000,000.0) * POLLING_RATE)
|
|
|
Post by Frisbone on Sept 12, 2013 8:19:31 GMT -5
When you get a chance, can give me a design review on the pic and the above text? Need a sanity check on this approach. Let me know if I need to explain anything in greater detail.
|
|
|
Post by Frisbone on Sept 12, 2013 16:31:48 GMT -5
Well, one thing I'm seeing with the accelerometer data is that the small noisy bumps aren't balancing out like I expected. Lets say you see a +1 tick in the X direction when you sample (I'm sampling at 12.5Hz which is the same freq I set on the AM itself) it but then you would expect that after that you would see a -1 tick to balance it out (we are dealing with a stationary object) But instead I see it always favor one side/direction and this causes the velocity calculation to keep increasing - forcing by design the point to go further and further outside of the sphere making minute changes in its position be meaningless from an angular perspective.
So this is problem #1 to tackle - why aren't the forces balancing out. I do have the HPF enabled so I'm not seeing gravity in the data as I was expecting - but not sure if it has much or any affect on this phenomena. Its possible that if I increased the sample rate that the problem would lesson - but would it ever go away? I might need a programatic way of ignoring these blips perhaps?
Maybe the sensitivity of this device is too high. Perhaps if I divided by 4 and made the range -128 to +128 instead of -512 to +512, I would see these blips go away.
Do you have any words of wisdom?
|
|
|
Post by Frisbone on Sept 12, 2013 20:02:16 GMT -5
Here is a simple test I ran where I filtered out all of the zeros output before I began moving the gun. I then moved it from the left to the right. The data is close to raw from the gun, its in G (converted data divided by 512 which is the resolution per G for the -4 to +4G range we are configured to detect. The sample rate is 12.5Hz (about 80ms per sample). The total columns I would expect would sum to zero since the gun starts at rest, and then ends at rest (mostly). Its close to true for the Y and Z axis, but the X axis is where all my movement was and its value is non-trivially bigger than zero. This was about 1.5 seconds worth so it would be interesting to see if this error accumulated over time. Attachments:
|
|
|
Post by Frisbone on Sept 13, 2013 8:07:08 GMT -5
I'm starting to think that I was originally on the right track with the design where I wasn't tracking a velocity. Although mathematically it makes sense to do so if you were able to track it at an infinitesimal level - practically you can't and that opens up a big problem.
I'm pretty sure the AM only takes a snapshot of instantaneous acceleration. This means that you miss anything that has happened between your snapshots. The profile gets better and better the higher the sample frequency - but it will never be perfect and capture all of the acceleration changes. For this reason the velocity - if accumulated, will never be zero.
So now I'm thinking that my original idea of going only by changes in acceleration was the right approach. No one can hold that thing perfectly still. Even when I set it down it jitters a bit. If you were to take the average of the last accel and the new accel (as opposed to what I was doing originally, and taking the delta difference) - you could integrate it twice and get average delta distance.
So long as there are always acceleration readings - it should work, its when it is zero (constant velocity) that you would have problems. But the constant velocity issue should be a theoretical thing, not a practical thing.
I modified the code so it accepted an input file of raw data to make it easier to test. We'll see how that works out. Going to change the design to eliminate the velocity tracking and replace it with acceleration averaging and double integration to get delta distance.
|
|
|
Post by Frisbone on Sept 13, 2013 8:19:06 GMT -5
Revised diagram. Attachments:
|
|
|
Post by Frisbone on Sept 15, 2013 15:14:19 GMT -5
I keep going back and forth with this basic approach and think I need some independent input. Part of this might just be I need to brush up on my physics. Give me a review when you get a chance.
Looking at the raw data I see kind of what I expect to see in a straight line test. Sudden acceleration turning into minor fluctuations ending up with sudden deceleration.
The problem is that if you do a double integration during each period on these figures you will get very small numbers compared to the initial numbers and final numbers - yet the change in distance over time should be the same. So it seems like I have to use actual velocity instead of changes in velocity. Don't think you can double-integrate the same figure as I suggested. You can only integrate to get a delta, then accumulate, then integrate again to get delta D. Not sure what I was thinking before. But I'm back where I started with the accuracy problem and the ever growing velocity.
|
|
|
Post by Frisbone on Sept 16, 2013 9:23:04 GMT -5
Found this article. Basically confirms my 2nd approach of tracking velocity and goes into the errors to expect. www.kionix.com/sites/default/files/AN013%20Double%20integration%20Rev%20B.pdfSo at least I can settle out the formula now and then concentrate on managing the resulting errors. Of course the errors they talk about are not related to sampling - they are related to the nature of the device. (sensitivity, voltage bias). A more detailed coverage of errors is here: www.kionix.com/sites/default/files/AN012%20Accelerometer%20Errors.pdfI think what we will need to do is figure out a way to recalibrate periodically. If there were key indicators of when the device was "steady" - we could call that zero velocity and eliminate the accumulation of error. Perhaps something like counting the number of samples where very small acceleration changes occur in all 3 axes. When we fall below that threshold we recalibrate to zero velocity? Tracking position with an AM seems to be very prone to error - but I think the applications that have been targeted are very different than what we are dealing with. We have the advantage of only needing relative movement over short periods of time - so long as we can eliminate accumulated error, it will probably be good enough for our purpose.
|
|
|
Post by Frisbone on Sept 22, 2013 6:49:20 GMT -5
Frustration is setting in and this morning I've decided to take a new angle on this problem. I think my issues has been that there are too many unknowns ranging from characteristics of the input data to uncertainty about how I'm converting it, to questions about my mapping design , to whether or not I have bugs in the design that I have.
So I think what I'm going to do is break the verification down into pieces. I'm going to shunt the entire sampling process and even the conversion and focus on the very end mapping process. I'll use the virtual 3D model to manually manipulate the virtual position of the AM within the sphere in a pre-defined manner (like a square) and modify the code so it accepts input from a file and loops it - then watch it on the monitor. So basically I'm going to make sure the mapping works. If it doesn't - I'll continue to use that same data to debug it. Perhaps I'll move even further up the chain of events to debug further. Once I have it working as I expect I'll move down the chain to where the velocity is converted to position - so the input data will be a series of velocity changes. Then I'll move down to acceleration data. Once that is all working - only then will I start focusing on the data coming out of the AM - and, when I do that - I think what I'll do is export the data out of the gun in real time via TCP/IP and import it into something like LabView - or if that won't work, into my own little test program that essentially plots data. The goal will be to see if you can manipulate the position of a virtual object using the AM movements.
|
|
|
Post by Frisbone on Sept 22, 2013 18:42:01 GMT -5
Took me most of the day but I finally got some code written and partially debugged that moves the virtual position of the accelerometer around from the input values provided in a file (CSV, xyz).
I say partially debugged because it doesn't quite do what I wanted it to. The test file has it moving up, left, down, right about 1 second per leg (12hz). Well, it doesn't seem to convert to a near constant joystick movement rate even though the velocity should be constant (degree of movement is (i think) basically the same for each leg - but a bit hard to tell since its in 3D). However, I had to change the conversion rate ratios by a factor of 10 in order to have the fluctuation in angles register.
It brings up a few of issues:
1) I need to figure out the true max JY rotation rate about each axis (radians per second)
2) Need to figure out if simulating 12Hz at a sampling rate of 12.5Hz is causing any error to propagate in the demo
3) Need to work on getting this to move smoothly in a square - its not really a square, its like a rhombus.
4) I need to determine what the %value to JY rates are in order to determine if there is some breakdown point at which if the frequency is raised too high, that the rate of change in that period is no longer detectable. In that case we might need to track movement at a higher rate than we move the joystick - right now they happen at the same sample frequency.
But it is good progress - I know the algorithm basically works (one bug though for sure, had the X-axis slope calc wrong so the ascension was reversed from what it should have been.
If I increase the sampling frequency to 50Hz without changing the data (expecting the square to complete rotation in about 1 second) the movement is slow and strange. It moves up and to the right like stair steps - pausing. Going to check in the code tonight. Will also post a video when I can.
|
|
|
Post by Frisbone on Sept 23, 2013 19:34:13 GMT -5
The video will be here when complete: youtu.be/nZ7bCCwZJVII determined the rotational speed in COD for each of the sensitivity settings: Setting L/R U/D================ 1 3.2s 4.1s 2 2.3s 2.7s 3 1.8s 2.1s 4 1.4s 1.7s 5 1.2s 1.5s 6 1.0s 1.4s 7 0.88s 1.1s 8 0.80s 0.9s 9 0.71s 0.8s 10 0.64s 0.7s 11 0.57s 0.65s 12 0.48s 0.6s 13 0.41s 0.5s 14 0.37s 0.4s
For L/R (left/right) it is traveling 2 * PI or 360 degrees. For U/D it is traveling between 90 and 180 degrees depending on the view angle - which I'm not sure can be calculated easily. it seems like its probably around 160 degrees if I were to venture a guess. However, its quite clear that the game has the L/R axis much more sensitive than the U/D axis. Looking how the joystick responds its also clear that the voltage to speed conversion is not linear, it seems quadratic. Only way to figure it out for sure is to vary the voltage programmatically and record the timing. The test above was done at full speed. This point is very important because my code has assumed that the conversion is linear and that if we needed to achieve a certain velocity it was a simple linear conversion - now it seems clear that we have some kind of curve and to match up the right velocity we'll need some tricky math. Greg to the rescue?? I think our testing should start out simple and use the lowest sensitivity which is likely to be as nearly linear as possible.
|
|
|
Post by Frisbone on Sept 23, 2013 19:52:28 GMT -5
At the slowest rate (sensitivity setting of 1) the horizontal axis goes 2PI radians in 3.2 seconds which equates to 1.963 radians per second. For the vertical axis the same logic equates to 0.681 radians per second (3 times slower).
I'll plug these in tomorrow and keep my sensitivity at 1 for a while and move on to determining what the voltage to rate steps are - which will tell me if there is ultimately a breakdown frequency of commanding the PWMs.
|
|
|
Post by Frisbone on Sept 24, 2013 11:54:35 GMT -5
I think I need to commit to a slight redesign and I'm seeking comment. It will require one additional input - perhaps you can tell me if we have it after your latest change.
I am now convinced that I need to separate out the process of converting AM input to a virtual position and the process of converting changes in position to an angular directional velocity. The main reason is that the CPU and I2C bandwidth usage for handling the conversion to angular velocity is huge in comparison - and does not contribute to accuracy of following movement of the gun, yet it is obviously a limiting factor in the achieving the highest possible sampling rate.
Knowing that there is a breakdown point where very small changes in angles will result in voltage calculations that will essentially not move the joystick - having the frequency of the two functions be 1 for 1 is not only not ideal, it may simply not work at all. I know that there is a "grace" range around the 1/2 max voltage range (.8V) - which represents "centered" where a little above or below that voltage will keep it centered without movement. Once I create a voltage to turn rate mapping - will have a much better profile of this.
Here is my design change idea. I want to make the AM reading interrupt driven (single interrupt, requiring one addition input pin) and for each interrupt it would simply calculate the new virtual 3D position (not too math heavy - a few multiplies). Then crank the sample rate up as high as 400Hz. Next I'll change the polling in the main program to represent the polling of the current position (stored by the ISR) and would then calculate angular velocity to achieve that new position within that sample period. The frequency/period of the polling would be much slower, perhaps 20Hz or slower depending on test results. This is the process that is more intensive anyway.
Lacking an extra input what I could do is pick frequencies that are multiples of each other. So if the sampling frequency for the AM is 400Hz, then every 20 samples i could kick off the angular conversion and PWM output logic. I don't like this option because it will cause a position reading hiccup every 20 samples - remember, this is not a threaded application so our options are limited.
Let me know your thoughts.
|
|
|
Post by Frisbone on Sept 24, 2013 17:03:56 GMT -5
Ran a voltage-based test from the app and had some interesting results.
+1.0 = 3.4 seconds (full rotation, 360 degrees +0.5 = 4.4 s +0.2 = 2:24.0s +0.15 = 11:44.0s +0.12 - Very Very slow +0.11 - Hardly perceptable +0.10 - Had to wait a while for movement +.094 - End of dead zone -0.15 - End of dead zone -0.5 - 6.2s -1.0 - 3.5 s
What is interesting is that the dead zone is not evenly distributed over the range of voltages we can produce. The number above represents a linear scale between 0 and 1.61V with -1 being zero and +1 being 1.61 and 0 being about .805V. The dead zone on the plus side is smaller than the dead zone on the minus side. This explains why the fairly significant difference at the .5 mark on either side (about a 1.8 second differential) - but it doesn't explain why at +1/-1 it seems to catch up (a 0.1 differential). A very odd looking curve. Only way for me to plot it is to change my speed of movement which I'll do later. going ultra fast might reveal the true dead zone as it seems that you might wait 30 seconds before you see a pixel shift due to very slow rotation.
Another interesting thing that I saw when running this test is that the Y axis in the game shifted over the course of a longish fast moving test (upward) - even though that axis has a stead 0 applied to it. Its as if the movement about the horizontal axis is causing vertical movement. I wonder if this is some kind of physical cross-over voltage - or if its a bug in the game. Either way that could cause of issues down the road if rapid left/right movement causes drift along the up/down axis.
|
|