summaryrefslogtreecommitdiff
path: root/ImuCalcs.mdwn
blob: 4301db7be93fd440254108c057c72f5825df2a0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
## <a name="IMU Calculations Page"></a> IMU Calculations Page

----

**General Outline:**

We'd like to functionalize the IMU calculation code so that:

- You don't have to worry about how we call the routine
- You don't have to bother with the strange data flow in our system (CAN messages, etc.).
- Your calculation routine is more modular and doesn't depend on the implementation of the IMU.

This means we want to be able to call your routine like a function everytime we get an inertial data packet from the IMU. The call would look something like:

<font>(Xpos,Ypos,Zpos,Roll,Pitch,Yaw) = IMUCalc (Xacc,Yacc,Zacc,Rollrate,Pitchrate,Yawrate);</font>

Your routine - IMUCalc or whatever you'd like to call it - uses the inertial data to calculate position and attitude and then returns that data.

<font> Right this makes sense actually I've created a struct called INS\_Data\_Type: </font>

      //INS Data Type
    struct INS_Data_Type{
       double pos_X;
       double pos_Y;
       double pos_Z;

       double vel_X;
       double vel_Y;
       double vel_Z;

       double Roll;
       double Pitch;
       double Yaw;
    } INS_Data,Init_Data;

_Excellent. We'll use that._

----

**Calibration Issues:**

For the September launch, our sensors will need to be slope and offset adjusted for each sample.

<font> For this I assume you mean normalized, i.e. corrected for misalignment? Misalignment errors are a factor, however are secondary to getting things working. Once the software runs, we can perform correction rotations to compensate for misalignment etc.</font>

_Sorry that wasn't clear. I meant calibrate the data coming in via scaling it and offsetting the raw sensor data. Don't worry about this - we're going to handle all of the "preprocessing" on the raw data so that all you get is the inertial data._

In the future, we'll have a routine where we use a local averaging method on a multi-megabyte calinration data set to get a best estimate of the actual inertial state... but that's _after_ the 9/29 launch, unfortunately.

In order to keep the IMU calculations independent of the calibration/scaling/adjustment methods we use, I think we should keep those routines out of the inertial calculation and hand you a "cleaned-up" data set: This means giving you accelerometer values in g's and the gyro data in rad/sec.

<font>Either way works for me, just let me know. It may be easier for you to send me data in g's and in rad/s or deg/s (let me know rads or degs?)</font>

_Right now we're planning on giving you linear acceleration in m/s^2 and rotational velocity in rad/s._

I assume, until otherwise told, that we should be using double precision floating point numbers.

<font> yes double precision. That's what, 64-bits? that should be plenty, although a long double can be used if necesary (I doubt it).</font>

_I don't think 64bits is lowering our standards any ;)_

----

**Sampling Rate Issues:**

Our sampling rates are:

<table border=1 cellpadding=0 cellspacing=0>
  <tr>
    <td> X,Y,Z Accelerometers </td>
    <td> 2.5Ksps </td>
  </tr>
  <tr>
    <td> Roll, Pitch and Yaw rate gyros </td>
    <td> 833sps(2.5ksps/3) </td>
  </tr>
</table>

That means for every 1 gyro data packet we'll receive 3 accelerometer data packets. What I suggest we do is to "zero order hold" the gyro data - basically, we'll just copy the gyro data twice more so that your routine gets all 6 sensors at 2.5ksps... it's just that the gyro data will only change every third sample.

Does this make sense, given your routine? Or what would be better?

<font> The easiest thing here is for you to call my routine once you have six samples for each of the sensors. The numerical methods I have developed are based on a 5th order polynomial approximation, therefore six samples. Your current sampling rate is just astronomical as compared to our processing power. </font>

_Actually, we may have way to much processing power on board - See the processor specs below. Hmmm. I don't understand what you're fitting, but I'll bug you about detauls of your routine later._

<font> I reccommend taking every nth sample (until you have six for each sensor), where n is some value that gives a sampling rate that can be processed. Once the "buffer" of six samples for each sensors is full with new data, you call one "round" of my INS calc program. This will update the flight data and reset the buffer. </font>

_Ok, you got it. We'll collect 6 "samples" of the inertial data and pass it to your routine. I use quotes because we'll average the incoming raw data samples to get down to a reasonable update rate - see below._

----

**LPFing the Input Data or Undersampling the Output Data:**

We don't need a fast rate on the position data. We're thinking that 2Hz would be ok, 10Hz would be great, and 100Hz would rock but 2.5kHz is way overboard and will swamp the processor. So how should we handle this? Two immediate options are:

- We could digitally low pass filter the IMU data and then call your routine at the rate we want, like 10Hz.
- If you're doing the IMU routines like I think you might be doing them, you'll collect the data in an integrator and only do the position calculation after n samples. In that case, as long as n &gt;= 10, we'll just go with the rate you return data to us.

What works better for you?

<font> The first method is best because it allows you to change your update rate and really makes my routines just a workhorse. Again, I think the "buffer" method, where you fill a buffer (at whatever rate you want) and then call my routine when the buffer is full. Keep in mind also that the numerical methods here assume that samples are evenly spaced. Of course methods do exist for unevenly spaced samples, but are better suited for approximating a known function, rather than what we are doing here (at least this is my opinion). </font>

_We sample the accelerometers at 2.5KHz (400us) and the gyros at 1/3 that rate at 833Hz (1.2ms). In order to get a reasonable update rate, we're going to average the incoming accelerometer data in clumps of 3 points, which means we'll have raw data packets at 833Hz (1.2ms) at that point. We'll then calibrate them and collect 6 of these packets and pass them to your routine, thus calling your routine at 2.5KHz/3/6 = 138.89Hz (7.2ms). We'll try this rate first, and futz with it when as we have to._

<font> If you want to take the approach of separating the attitude calculation from the position/velocity calculation that's fine; I'll just give you two separate routines to call. This would yield DIFFERENT resolutions for the two. In my work I kept their resolutions the same. I.e. each "round" I updated the attitude and position/velocity. </font>

_Let's keep the inertial calcs as one routine; we'll pass you both types of data at once._

<font> As an aside, and without knowing how much else you're actually running on this processor, I don't think it will be difficult to achieve 100 Hz. I got about 94 Hz out of my 40MHz (8-bit, fixed point!) PIC18. </font>

-What are the processor specs?

_We're using an 133MHz AMD 586 processor (w/FPU) with 64MB SDRAM and a 128MB FLASH disk - it should give us at least 10MFlops. It's called the "Elan" microcontroller and it's basically a PC on a chip. Checkout the [[FlightComputer]] page for more information. We're using Debian Linux, with a real time kernel patch called "RTLinux" for the real time stuff. I think we're going to have plenty of processing power, but we'll see: being conservative about processing power is always a good thing._

----

**Libraries, Code, etc.:**

Write everything in ANSI C and try and use only standard libraries like stdio.h and math.h. Since you're only doing the calcs, you won't need all of the strange and twisted (sorry Jamey ;) interprocess communication calls - hopefully this will make it very easy and very fast to code.

----

**Coordinate Frames** How do you want to define the Body and Reference/Navigation frames? For now, and for simplicity, I suggest the following:

**Reference Frame **

<table border=1 cellpadding=0 cellspacing=0>
  <tr>
    <td> Axis </td>
    <td> Direction </td>
  </tr>
  <tr>
    <td> Positive Z </td>
    <td> Up, Perpendicular to the tangent plane of Earth&#39;s Surface and the point of launch </td>
  </tr>
  <tr>
    <td> Positive X </td>
    <td> East, but along a plane tangent to Earth&#39;s Surface </td>
  </tr>
  <tr>
    <td> Positive Y </td>
    <td> North, but along a plane tangent to Earth&#39;s Surface </td>
  </tr>
</table>

** Body Frame ** This is a bit more flexible and dependant on your INS configuration and mounting

<table border=1 cellpadding=0 cellspacing=0>
  <tr>
    <td> Positive Z </td>
    <td> Out of the nose cone </td>
  </tr>
  <tr>
    <td> Positive X/Y </td>
    <td> Pick a side (doesn&#39;t matter at all) </td>
  </tr>
</table>

Either way, I need to know how the group wants to define these in order to perform the appropriate rotations.

_Whoops! I forgot to upload our coordinate system. It's very close to your's: essentiall the same for the rocket but a little different for our reference frame. Check out the [[InertialMeasurementUnit]] page for the coordinate system information._

[[coordinates.PDF]] (Rotation Matrices) <br />

- [[INS.c]]: IMU Calculation C code

- [[numerical.pdf]]: Numerical Methods