System Characterization and Online Mass Property Identification of the SPHERES Formation Flight Testbed By Dustin S. Berkovitz SUBMITTED TO THE DEPARTMENT OF AERONAUTICS AND ASTRONAUTICS IN PARTIAL FULFILLMENT OF THE REQUIREMENTS FOR THE DEGREE OF MASTER OF SCIENCE IN AERONAUTICS AND ASTRONAUTICS AT THE MASSACHUSSETS INSTITUTE OF TECHNOLOGY FEBRUARY 2008 ©2008 Massachusetts Institute of Technology. All rights reserved. Signature of Author: Department of Aeronautics and Astronautics / September 4, 2007 Certified by: David W. Miller Professor Thesis Supgryisor Accepted by: I3avid.)Dahnmofal Associate Professor, Department of Aeronautics and Kstronautics Chairman, Graduate Committee .. _8" MASACHUSETM-tNSTITUT OF TECHNOLOGY MAR 2 5 2008 LIB.RARIES ARCHNES System Characterization and Online Mass Property Identification of the SPHERES Formation Flight Testbed By Dustin S. Berkovitz Submitted to the Department of Aeronautics and Astronautics on September 4, 2007, in partial fulfillment of the requirements for the degree of Master of Science in Aeronautics and Astronautics Abstract The National Aeronautics and Space Administration (NASA) and other entities in the aerospace industry have recently been considering distributed architectures for many space applications, such as space-based interferometry. Whether the craft in such a system are structurally connected or flown in tight formation, distribution allows for higher redundancy in case of failures as well as reducing the minimum payload footprint for launch. Designed to fly in precise formation, the SPHERES satellites rely on accurate system characteristics such as thruster strength and vehicle mass and inertia. The SPHERES testbed is described and the applications for formation flight are presented. Mass properties of the SPHERES satellites are examined because of their impact on control determination, with comparison between CAD model estimates and empirically determined values. The sensor and actuator suite, essential for closed-loop control, are also identified and characterized. A recursive least squares algorithm for determining mass properties in real time is explained and implemented both offline and online with results from test flights aboard NASA's KC-135 micro-gravity aircraft (Reduced Gravity Airplane, RGA). Thesis Supervisor: David W. Miller Title: Professor Acknowledgments The mass property identification algorithm discussed in this thesis is derived and formulated by Edward Wilson, Chris Lages, and Robert Mah of NASA Ames Research Center. Some data and results using the AMES implementation of the algorithm are included and referenced. I'd like to thank my friends and family, my parents and Katie Shirley for supporting me through this lengthy process. I also am grateful to my graduate advisor, David Miller, for putting up with me for the past 6 years. Also, thanks to my lab mates in the Space Systems Lab for making work fun; especially Alvar Saenz-Otero and Simon Nolet for reviewing this thesis on their own time. Contents A bstract ............................................. List of Figures ............... ................... ..... 9 ........................... ... ................................ 12 List of Tables ................................................................. Nomenclature ................... Chapter 1 .... ......................... 1,2 SPHERES Hardware Overview......................... ......... 1.2. I Inertial Sensors .......... 1.2.2 Propulsion System ........ 1.2.3 Ultrasound-based Positioning System .................. 15 ................. 17 ............. ....... ...................... 17 ............................. 1.3 Current Programs ...................................... ................ 18 .................. 18 ............................19 1.4 System Characterization Motivation ..................... SPHERES Mass Properties .............. 2.1 Mass Properties Overview ...... 13 ................................. 15 Introduction ................ 1.1 SPHERES Background ........................................................ ........ Chapter 2 3 ........... 21 ....................... 24 ........................................... 24 ......................... 26 2.2 Measuring Center of Mass ............................ 2.2.1 CoM Error Sources ............. .............. ................ 2.3 M easuring M oment of Inertia .................................. 27 ............... 27 ...... .......................28 2.3.1 Torsional Pendulum Modeling ........................ 2.3.2 Test Procedure ..... 2.3.3 Products of Inertia .............. 2.3.4 Results .................................. 2.3.5 Alternate Method for Measuring Inertia ..................................... 34 2.3.6 Inertia Measurement Error Analysis ....... 2.3.7 Empirical Mass Properties Conclusion ............... Chapter 3 ..................... ...... ....... ................. ............. 32 ............. ............................. 33 ..... ................ 35 ............ 42 .... ................. 44 Thruster Characterization ................. ............ 44 3.1 Propulsion System Overview ............................... .......... ....................................... 45 3.2 Propulsion Hardware .............. 3.3 Pulse-width Modulation Scheme .............. ............ 47 .................... 3.4 Propulsion Limitations ...................................................... .......... 51 51 3.5 Measuring Nominal Thrust Vector ..................................... 3.6 Thrust Latency ............................... 3.7 Multiple Thruster Pressure Drop ............. ..................... .............. 3.8 Sensor Characterization ........................................... Chapter 4 32 ........ 53 .............. 56 58 Mass Property Identification ............. ................................... 61 4.1 Online M ass Property Identification .................................................... 61 4.2 Theory and Equations .............. ........................................ 4.3 KC-135 Micro-gravity Testing..................... 6 ............ 63 .................. 65 4.4 Algorithm Development ........................................ ........ .......... 69 4.4.1 Gyro Filtering and Interpolation .................. 4.4.2 Angular Acceleration Estimation.............................71 4.4.3 Mass Property Identification ....... 4.4.4 C Code Implementation ................. ........ Chapter 5 .... ... Conclusion ................................. 5.1 Thesis Summary ........................... ...... ,.... ............... 86 Tuning Fork Gyroscopes................... ..... A.2 Modeling Rate Sensing ................. .............. 93 ................................ 93 ..... ........................ 94 ... ..................... 96 Fuel Slosh .............................................. B. 1 Propellant Properties .................................. . ........................ 99 .......................99 ................. B.3 Modeling Fuel Slosh ................................................. B.4 Modeling Input .................. 89 . A.3 Application to SPHERES ...................... B.2 Fuel Slosh on SPHERES ............. 87 ......................................... . 84 ...................... 84 ............................................ A. Background Physics ................... Appendix B .................... 79 . Bibliography ........................ Appendix A ....... ........................... 76 ........................... 5.2 Conclusions .............................................. 5.3 Future Work ...................... ..............70 100 101 ............... ............... 103 B .5 Resu lts ....................................................................................... 104 Appendix C SPHERES Satellite Properties ................ ... ............... 107 C. 1 CoM Offset .............................................. ................... 107 C.2 M oment of Inertia................... ................................................... 108 C.3 Thrust Strengths ................... ................ C.4 Thrust Directions ...... ......................... Appendix D MATLAB Code .......... .................... ............ ............ ........ ...................... 108 109 110 D. 1 Mass Property ID Code .................................................... 110 D.2 Interpolation Scheme ................................................... D.3 Gyro Filter ...................................... D.4 Angular Acceleration Estimator ....... ... 113 ........ .................. ........... 114 .............. 115 D.5 Batch Mass Property ID ...................................... 117 D.6 Recursive Mass Property ID ......... 119 Appendix E C Code ............... ............................... .......................... . ....... E.1 Mass Property ID Code ................................. E.2 Angular Acceleration Kalman Filter ................. E.3 Mass ID - low level . ............. .................. 126 ................126 .............141 ........................................... 146 List of Figures 1.1 SPHERES Flight Satellite 1.2 Ultrasound Beacon 1.3 Standard Feedback Control Representation 2.1 SPHERES Satellite Hanging in a Torsional Pendulum 2.2 Model of One String of the Torsional Pendulum 2.3 Equal Arc-lengths Assumption 2.4 X-Gyro Data from SPHERE SN 2 on the Torsional Pendulum 3.1 Solenoid Valve Thruster 2 3.2 PWM Mixer Code Block Diagram 3.3 Thrust Correction for Simultaneous Firings 3.4 SPHERES Body Axes 3.5 Thrust Latency in Solenoid Valve 3.6 Applied Impulse From Difference in Thruster Latency 3.7 Sample of 6ms Solenoid Delay 3.8 System Pressure Propagation Test Setup 3.9 Pressure Change Propagation Data 3.10 Inertial Measurement Unit Specifications 3.11 Filtered 338 Hz Gyro Noise 3.12 FFT of Gyro Ringing 4.1 Ideal Maneuvers for Inertia and CoM Identification 4.2 Three-Axis Gyro Data From RGA Test 4.3 Concatenated RGA Gyro Data 4.4 AMES/Intellization Mass Property RGA Results [Wilson, 2003] 4.5 Filtered Gyro Data Standard Deviation 4.6 Kalman Filter Process 4.7 Angular Acceleration Estimation Comparison 4.8 Estimation Routine Variances 4.9 Sample Ixx Convergence 4.10 MATLAB vs. Visual C Acceleration Estimation Results 4.11 Visual C vs. Online Embedded C Mass ID Results 4.12 Z-Axis Gyro Data From Online Mass ID Test 4.13 Online Mass Property Estimate Convergence A. 1 Tuning Fork Gyro A.2 Gyro Sensing Model A.3 12 Hz Gyro Noise A.4 38 Hz Gyro Noise B. 1 Observed Fuel Slosh in Gyro Data B.2 Linearized Fuel Slosh Model B.3 Simplified Fuel Slosh Model B.4 Fuel Slosh Model Input B.5 Model Output List of Tables 2.1 Measured CM Offset vs. CAD Values 2.2 Measured Moment of Inertia vs. CAD Values 2.3 Nonlinear Spring Constant Values 3.1 Thruster Dependencies [Chen, 2002] 3.2 Thruster Locations w.r.t. Geometric Center (GC) 3.3 Thruster Strength and Direction for SPHERE SN 2 4.1 RGA Mass Property Results 4.2 Standard Deviations for Line-fits of Varying Order B.1 Worst-case Effect of Fuel Slosh on Mass Properties C.1 CoM Offset C.2 Moment of Inertia C.3 Thrust Strengths C.4 Thrust Directions Nomenclature DSP Digital Signal Processor ISS International Space Station MIT Massachusetts Institute of Technology NASA National Aeronautics and Space Administration PWM Pulse-width Modulation SPHERES Synchronized Position Hold, Engage, Reorient, Experimental Satellites SSL Space Systems Laboratory CM/CoM Center of Mass GC Geometric Center DOF Degrees of Freedom CAD Computer-aided Design C02 Carbon Dioxide ID Identification (as in "Mass Property Identification") (R)LS (Recursive) Least Squares IMU Inertial Measurement Unit KC NASA's micro-gravity aircraft, KC-135 KF Kalman Filter P Estimate error covariance Q Process error covariance R Measurement error covariance I Moment of inertia g Damping ratio K Spring constant b Damping coefficient E Young's modulus o" Stress (Hooke's Law); standard deviation Pseudo-inverse operator 0, c, a Angular acceleration i Estimate of true value, x Chapter 1 Introduction 1.1 SPHERES Background SPHERES (Synchronized Position-Hold, Engage, Reorient Experimental Satellites) is a high fidelity test-bed designed to help develop and mature algorithms for formation flight and autonomous docking. The test-bed includes three satellites with full six degrees of freedom (6-DOF) control authority and a relative and absolute positioning system. SPHERES is meant to be a low risk platform for testing experimental spacecraft navigation [10, 15, 16]. The SPHERES program began as an undergraduate design course in the Department of Aeronautics and Astronautics at the Massachusetts Institute of Technology (MIT). Juniors and seniors were asked to design and build a platform for testing formation flight algorithms over a span of three academic terms. Because of the growing interest in formation flying satellites in the aerospace industry, many interested parties such as the Defense Advanced Research Projects Agency (DARPA), National Aeronautics and Space Administration (NASA), and Lockheed Martin invested in SPHERES as a graduate research program. The SPHERES satellites were redesigned and rebuilt with the intention of operating for an extended period of time aboard the International Space Station (ISS). They have been tested extensively at the MIT Space System Laboratory's (SSL) float table (2D configuration) and in micro-gravity aboard NASA's Reduced Gravity Airplane (RGA). Three SPHERES satellites and accompanying test equipment were launched to ISS throughout 2006. Figure 1.1 SPHERES Flight Satellite This thesis first presents an overview of the SPHERES testbed hardware, including the satellites themselves as well as the ultrasonic positioning system equipment. Next, it presents the offline and online characterization of key system parameters of the SPHERES testbed. First, mass properties of the SPHERES satellites are examined, with comparison between CAD model estimates and empirically determined values (Chapter 2). Next, experiments performed to characterize the SPHERES satellite's propulsion system and sensor suite are detailed (Chapter 3). Finally, online mass property identification algorithm is introduced and compared with previous results (Chapter 4). 1.2 SPHERES Hardware Overview The SPHERES hardware was designed and built collaboratively by the MIT Space Systems Laboratory and Payload Systems Inc. There are five identical satellites in operation (two for ground testing at MIT, three for experiments aboard the ISS). Each SPHERES satellite has an aluminum truss-work skeleton that provides mounting points for the avionics, propulsion system, and sensors. A color-coded, translucent plastic shell protects this equipment and helps provide easy identification. The subsystems relevant to this thesis are described below. Other subsystems include the CPU and signal processing, power, communications, and the control laptop with the GUI, but will not be introduced here. Refer to [13, 16] for more information. 1.2.1 Inertial Sensors Each SPHERES satellite has six inertial sensors, three accelerometers and three gyroscopes. The three Honeywell accelerometers are mounted in three orthogonal axes in the body frame. They are designed to measure a fine resolution of linear acceleration produced by the onboard thrusters. While this is ideal in micro-gravity, accelerometer data is unreliable at the 2D MIT facility (the accelerometers are saturated by the presence of gravity when the satellite is tilted by more than one degree). Similarly, three gyroscopes are mounted on each axis to provide angular rate information. 1.2.2 Propulsion System SPHERES satellites accelerate using a cold-gas propulsion system (carbon dioxide, CO2). The multi-phase C02 is stored at 860 psi in a tank located in the middle of the satellite. The gas is regulated to 35 psi and fed through an expansion capacitor to the 12 solenoid-actuated valve thrusters. When a command to fire is sent through the Digital Signal Processor (DSP) to the firing circuit, the corresponding thruster solenoid is actuated, allowing the pressurized CO2 to escape and provide thrust. The 12 thrusters can be commanded either ON or OFF (no intermediate settings or throttle) and are controlled via pulse-width modulation (PWM). They are located around the satellite so as to provide full, uncoupled control in 6 Degrees of Freedom (6-DOF). 1.2.3 Ultrasound-based Positioning System Most space systems have some way to measure absolute position (e.g., star-trackers or GPS). A localized system involving ultrasonics was developed for SPHERES in order to operate inside the ISS. Given a priori knowledge of the pre-programmed delays in the beacons, the DSP computes the time-of-flight of the ultrasound pings, which travel at the speed of sound. The time-of-flight is used by an Extended Kalman Filter (EKF) to estimate absolute translational and angular position and velocity. Figure 1.2 Ultrasound Beacon Each SPHERES satellite is equipped with its own onboard beacon to allow for satelliteto-satellite relative ranging and bearing angles (more accurate for close proximity maneuvers). 1.3 Current Programs SPHERES is designed as a flexible platform for testing autonomous spacecraft algorithms, specifically targeting rendezvous and proximity operations (RPO) and formation flight. Related ideas include such topics as servicing spacecraft [14], spacetethers [6], formation flying interferometers [11] and space-network topology [19]. The SPHERES project offers an opportunity to do research in this area as a low cost, low risk, and high fidelity hardware simulation. By operating inside the ISS, the SPHERES testbed exploits the micro-gravity environment to represent the dynamics of docking missions while protecting itself from getting lost in space when real or simulated failures occur. Space-based interferometry is an especially interesting topic because of the consistent demand for higher resolution pictures in space. In order to get better quality images from orbiting telescopes like Hubble, the diameter of the primary mirror would have to grow in size. However, a telescope with a larger mirror would not fit in any launch vehicle available today. Rather than designing and building a launch vehicle with a higher payload volume, interferometry can be used to get comparable quality images using multiple smaller telescopes arranged in a precise pattern. Spacecraft autonomy is a very powerful concept. Without the need for human assistance, satellites can operate efficiently for longer lifetimes in orbit. Fault Detection Isolation and Recovery (FDIR) is a big step towards fully autonomous spacecraft [20]. Systems with FDIR can detect failures in their components and adjust accordingly to fulfill their primary objectives. A more specific example of this applied to SPHERES is thruster FDIR. Using the firing commands given by the software and the measured dynamics from the onboard sensors, an FDIR algorithm can isolate thruster failures and alter future firing commands with this failure taken into account. Another, more basic fundamental of autonomy is estimation. The more accurate the information is in the state vector, the better the control performance can be. The goal in autonomous estimation is to identify relevant system parameters online (especially changing ones like fuel mass). A mass property identification algorithm has been developed for testing on the SPHERES testbed [21]. It has the ability to give a continually updating estimate of the Center of Mass (CoM) and Moment of Inertia by using thruster commands and gyroscope data. These estimated values then impact how commanded forces and torques are manifested as thruster ON/OFF times. This wide variety of research topics is the focus of the SPHERES project. Many algorithms have gone through multiple levels of iteration, with offline testing in MATLAB and other computational tools, and online testing on the SPHERES satellites at the 2D testbed at MIT as well as several flights on NASA's RGA micro-gravity "laboratory" and aboard the ISS. 1.4 System Characterization Motivation It is an inevitable consequence of the manufacturing process that misalignments, asymmetries, and other minor flaws are created that affect the performance of any assembly. Though all SPHERES satellites are meant to be identical, there are slight inconsistencies that cause each to behave differently. Correcting or accounting for these errors can be addressed in multiple ways, including but not limited to using stochastic values or designing controllers to compensate for sensor noise or uncertainty in specific parameters of the plant model. Regardless of which methods are employed, the underlying truth holds that the more that is known about the system, the easier it will be to control and improve performance. Efficient use of consumables (pressurized gas and batteries) is a universally important issue for space applications, and is crucial for extending the life of SPHERES as test-bed aboard the ISS, as well as countless other space vehicles. The first part of our strategy for improving system performance is to make SPHERES behave the best possible in open loop. This is accomplished by fully characterizing the propulsion system (Actuator) and the vehicle itself (Plant). This system characterization is used to calibrate and tune the control software and allow the SPHERES satellite to perform open loop maneuvers, like flying straight, with better accuracy. However, there is only so much we can accomplish with characterization and calibration while SPHERES is on the ground. Some system parameters like CoM and Inertia will change as fuel is depleted (or in cases of other satellites, when components are deployed or jettisoned or docking with another spacecraft has occurred). Online estimation of these parameters can extend mission lifetime by allowing more accurate maneuvers and by using the on-board fuel more efficiently. An online mass property identification algorithm developed at the NASA AMES Research Center [Lages, Wilson, Mah] [21] has been implemented for use on SPHERES to identify CoM and Inertia. In addition, the Inertial Measurement Units (Sensor) used to close the loop are examined. Figure 1.3 depicts a standard control-loop representation with the feedback as a dashed line to signify an open loop system. The input to the control software is in the form of desired state (position, attitude, velocity and angular rates). This is transformed to body forces and torques and then passed through a "mixer" to get thruster ON/OFF times for each of the 12 thrusters. The thrusters apply forces and moments on the plant and the inertial sensors measure angular rates and linear acceleration. .... .... ... .... ... .... ... .... .... ... .... ... .... ... .... ... S0 X ! : ... ... . Controller 0 --0 . .. .. . .. .. . .. .. . .. .. . .. .. .. . .. .. 4,-- aI . .. .. . .. .. Output I Jr Figure 1.3 Standard Control-Loop Representation We use this representation as a model for the organization of the SPHERES System Characterization in Chapters 2 and 3. The Plant, Sensors, and Actuators are fixed (already built/purchased), so our only form of correction is in the control software. After presenting predicted and empirically measured values for key system parameters, online mass property identification is introduced and compared with previous results (Chapter 4). Chapter 2 SPHERES Mass Properties 2.1 Mass Properties Overview Modem spacecraft are designed using computer-aided design tools such as ProEngineer and Solidworks. Many CNC workshop machines can replicate parts directly from imported CAD files. This allows for a high level of fidelity between the conceived design and the ultimate product. However accurate the machine, there are bound to be inconsistencies between "identical" pieces. CAD estimated values for mass properties could be unreliable because of this assumption. Also, some parts (like electronics boards) are modeled crudely and thus do not truly represent their effect on mass, CoM, and Inertia of the assembled satellite. Still other errors can arise from hollow components that are approximated as solid objects. The most important error source from CAD drawings is assembly of components. Most of the time, fixation devices (screws, rivets, bolts, nuts, soldering joints, etc.) are not modeled in a CAD drawing, and the assembled parts are assumed to be perfectly assembled, when in fact we know that there is always clearance in a bolt hole and the bolt is likely not to be centered in the hole. These error sources, along with discrepancies introduced from the manufacture and assembly processes, indicate that there is plenty of room for improvement in the accuracy of our mass property estimates. Table 2.1 shows the discrepancy between predicted (CAD modeling) and measured CoM offset of one the SPHERES satellites. I CAD Model Measured 0.49 -1.24 3.98 0.37 -1.52 3.32 0.48 -1.19 1.08 0.82 -0.99 1.07 Table 2.1 Measured CM Offset vs. CAD Values These tests were repeated for all five SPHERES satellites with a full C02 tank (Wet) and an empty tank (Dry). How the gas settles and sloshes does have an impact on CoM and Inertia but will not be discussed in detail here (refer to Appendix B). 2.2 Measuring Center of Mass (CoM) To get a more reliable estimate of the SPHERES satellite mass properties (Plant parameters), a test stand was built that holds a SPHERES satellite rigid, while keeping its center of geometry in a very precise, known location (Figure 2.1). The stand consists of an aluminum plate with various mounting points and four rectangular posts that allow access to screw into the frame of the SPHERES satellite. A SPHERES satellite can be mounted along any primary axis to this stand. It was designed to attach to the top of a 6DOF load cell (for measuring thruster strengths and CoM) and to a torsional pendulum harness (for measuring moment of inertia). The primary function of the load cell is to measure forces and torques applied to it. Before each CoM test, the signals from all six channels (corresponding to each DOF) were recorded using a SigLab Data Acquisition System. These measurements were averaged and saved as bias estimates. The same was done with the empty test stand. By positioning the center of geometry of the SPHERES satellite directly over the center of the load cell, we can determine the torque applied by the CoM offset of the satellite alone (removing the other recorded biases). From the two horizontal moments applied on the load cell, we get the CoM offset in two axes. For the 3 rd coordinate, the SPHERES satellite is rotated so it's mounted on its side and the moments are measured again. 2.2.1 CoM Error Sources When measuring offsets on the order of millimeters, any slight misalignment will drown out the true value. The test stand was meticulously designed and each test carefully performed, but errors on that scale of magnitude are difficult to avoid completely. The four screws that secure the test stand to the load cell are M4x.7 (Metric screws, 4.0mm in diameter, 0.7 threads per mm). The through-holes on the test plate were made with the recommended clearance of 4.5mm, leaving 0.5mm of play. With CoM values ranging from 0-3mm, this is a significant source of error. By assuming the error bias is close to zero mean, averaging over many tests: can provide reasonable estimates. 2.3 Measuring Moment of Inertia The principal moments of inertia were measured using a trifilar torsional pendulum. An aluminum mounting plate supports a satellite while hanging by three strings from another plate bolted to the ceiling. A specially modified outer shell was used to allow a SPHERES satellite to be mounted in six different orientations. The two aluminum plates were designed to allow leveling in both horizontal axes. The top plate is mounted in two locations to a metal rail secured to the ceiling. By adjusting these two mounting points, the top plate can be leveled along the axis perpendicular to the rail. To level the other horizontal axis, there are two thumbscrews that can be torqued into the ceiling, raising or lowering either side of the plate. The three 8 ft. long strands of fishing line are tied to steel bolts screwed into the ceiling-mounted plate. They are threaded through a fine hole drilled through the length of each bolt to minimize lateral strain on the strings. The opposite end of each string is tied to aluminum mounting adapters. Similar to the steel bolts at the top, the strings are threaded through a small hole in the center of the adapter. The bottom of the adapter is threaded with a standard %-20 thread, which is used to secure it to the bottom plate where the SPHERES satellite is mounted, as shown in Figure 2.1. The threaded adapter also allows for independent leveling of the bottom plate, which is important for inertia tests. Three mounting points, though coupled, can still allow the leveling of both horizontal axes. Figure 2.1 SPHERES Satellite Hanging in a Torsional 2.3.1 Torsional Pendulum Modeling The motion of a trifilar torsional pendulum is a nonlinear problem because the strings restrict each other's movement and are therefore coupled. This causes the test object to lift slightly as the pendulum oscillates. The test equipment and conditions were designed to minimize the effect of these phenomena on the measured inertia (long strings of >8 ft; string length >> mounting plate radius; small oscillations of <200 amplitude). In order to determine the equations of motion, a simplified conceptual model will be used. Figure 2.2 is a force diagram representation of one of the three suspension strings modeled as a simple pendulum in 2-D. Force equilibrium along the axes parallel and normal to the string: YF = T -mg cos 0= 0 (2.1) SF 1 = mg sin 0 = fm0 y T m9 Figure 2.2 Model of One String of the Torsional Pendulum Solving for T: T = mg cos b (assumes even distribution of weight between the three strings). Since the string is attached to a plate with negligible vertical mobility, Fx is assumed to be the torque applied to the mounting plate. xFx =Tsin = mgcosOsinO (2.2) From the rotational equations of motion: rxF = 1M, where r is the radius of the circle defined by the three string mounting points, I is the rotational inertia of the entire rotating assembly, and 0 is the angle through which the mounting plate has turned. Substituting for F and including a damping term gives: -mgr cos 0 sin 0 - !; = MI (2.3) Since the strings are so long and the angle that the pendulum rotates through is so small, the arcs of the two angles 0 and 0 are approximated as equal: O==Or. approximation is shown in Figure 2.3: These arc-lengths assumed equivalent Figure 2.3 Equal Arc-lengths Assumption ' r This This produces a non-linear damped harmonic oscillator: 1 ++g0+mgrcos r0 sin( ) =0 (2.4) The type of string used was a long, thin monofilament line with very small energy dissipation (assumed massless). Also, energy loss to drag from the ambient air is small due to the circular profile of the satellite and the low angular velocities. For these reasons, the damping term was considered negligible. Inputs will be of the form of an initial displacement 40 from the pendulum's equilibrium point such that 0= 00cos ( . Substituting for 0,and solving for I: I= mgr "o62COS( C) cos( 0 cos(C) (. sin r90 cos(C) ) (2.5) (t 1 As was mentioned earlier, this test is designed to run for small values of 0 = 0ocos a . Using small angle approximations for sine and cosine (~ << 1 and r9 O<<1), Equation (2.5) becomes: m gr I = mg I0 For this particular setup, the values are: m - mass = 7.172kg g - 9.8m s2 r -radius = 0.146 1m I -length - 2.47m I0 -baselnertia= 0.0448kgm2 o- frequency (2,6) 2.3.2 Test Procedure The test: object is weighed before every experiment. After weighing, it is secured on the mounting plate, then the plate is leveled using a dual axis high precision level. The last pre-test procedure is measuring the length of the strings. Finally, an oscillation is initiated by turning the pendulum through a slight angle and releasing, being careful not to impart any translational motion. Using Equation (2.6), it is possible to determine the inertia of the object about that axis by measuring the frequency of oscillation. Inertia measurements with only the test stand were performed to remove the bias of the stand. 2.3.3 Products of Inertia This method was helpful to determine the primary moments of inertia, but not the offaxis terms. It is possible to use the same experimental setup to find the off-axis terms using Mohr's Circle [3]. The Principal Axes of an object are defined as the axes around which the products of inertia are zero. If a test object were mounted so that it could be incrementally rotated around the x-axis, and inertia estimates were taken for many different combinations of axes in the Y-Z plane, the resulting values would be sinusoidal. The maximum and minimum values of this sinusoid (in 3-D) correspond to the Principal Axes. If the object were rotated through an angle B in the Y-Z plane, the measured inertia is related to the product of inertia by Equation (2.7). IBrz = Iz sin 2 B+ Iy, cos 2 B-IPz sin2B (2.7) The minimum number of measurements necessary to determine products of inertia is six; assuming three orthogonal axes are used for a basis. One measurement about X, Y, and Z is needed as well as one each about axes 45 degrees between the X-Y, Y-Z, and Z-X axes. Unfortunately this: method requires more mounting configurations than are available on the current test stand, and so the products of inertia were not measured empirically. Since the SPHERES satellites are designed to be symmetric, the off-axis terms are a couple orders of magnitude below the primary inertias (according to the CAD predictions and online mass property results) and thus much more prone to mounting errors and mathematical assumptions. 2.3.4 Results Table (2.2) shows sample inertia data for one satellite, comparing CAD predictions to empirically measured values. As seen in the table, they are similar but vary by nontrivial amounts. The discrepancy is expected because of the inherent inaccuracy of CAD predictions for heterogeneous objects. The error analysis described in Section 2.3.6 and the results from the online mass property identification algorithm verify that the empirical values are better candidates for measures of truth. I Measured CAD Model 2.30 2.19 2.57 2.45 10.5% 2.42 2.31 2.25 2.15 7.6% 2.14 2.13 2.03 2.03 5.4% 0.01 0.01 n/a n/a n/a -0.03 -0.03 n/a n/a n/a -0 -0 n/a n/a n/a Table 2.2 Measured Moment of Inertia vs. CAD Values 2.3.5 Alternate Method for Measuring Inertia An alternate method for measuring inertia was attempted. The strategy is to approximate the entire torsional pendulum as a torsional spring with spring constant K. r =10 =K-O 9= A sin(ot) I= (2.8) K The procedure in this case is to measure K by testing an object of known inertia and use that K value for all future tests. It turns out however that this is an over-simplification of the torsional spring since, when compared to Equation (2.6), K depends on m and m which is not constant: K= mngr 2 (2.9) If the spring were linear, it would exhibit strain displacement proportional to applied stress and K would be constant. behavior. Table 2.3 shows data supporting this nonlinear The first row includes data from a torsional pendulum test with just the mounting plate. The second row is from a test with a SPHERES satellite mounted (inertia values are validated from CAD models and online estimation). 0.0448 0.0674 2.286 2.933 0.2341 0.5802 Table 2.3 Nonlinear Spring Constant Values The estimates for off-axis terms of inertia have come from running an offline version of AMES/Intellizations's gyro-based mass property identification algorithm [21]. Gyroscope data collected in micro-gravity on the RGA provided the necessary information to determine off axis inertias. The algorithm itself is discussed in full detail in Chapter 4. 2.3.6 Inertia Measurement Error Analysis The moment of inertia characterization is vulnerable to many error sources ranging from the background math and physics to the test implementation and execution. Mathematical Approximation (equal arc lengths, small angle, no damping) To properly reduce Equation (2.4), the arc lengths Of and Or are assumed equal. This is a slightly less "risky" assumption than using small angle approximations for 0 and (b. Since 0 is the larger angle, it has the highest potential for error under the small angle assumption. Showing that the small angle assumption for 0 is negligible will then prove the equal arc-lengths assumption negligible as well. As part of the test procedure, the maximum value of 0 is 20 degrees (0.349 rad). The length of the arc defined by 0 is rO = 0.025499m. 2r sin - The length of the chord that approximates this arc is = 0.025467m, which is an error of 0.000259m (0.5%). Inertia varies linearly with this error, so none of the angle assumptions will affect inertia by more than 0.5%. The equations used also assume that the damping is negligible. The damping ratio can be determined by examining the rate of descent of the oscillation amplitude. I ; = 2 •ln(at1 (2.10) The percent error in measured inertia is equal to 100;2 [3]. The data in Figure 2.4 was taken for the X-axis inertia of SPHERE SN 2. SN 2 lxx Measurement Data 2400 2300 2200 .4 4 2100 .4. 2000 4* 4 1900 ,i. 1800 1 7n 0 o I I 500 1000 Update Number (50 Hz) 1500 Figure 2.4 X-Gyro Data From SPHERES SN 2 on the Torsional Pendulum Over these 13 oscillations, the amplitude dropped from 306 to 299 counts: n=13 a0 =306 a = 299 S26In 30 (2.11) 99) = 2.833e error = 100ý 2 = 8.0267e-6% There would need to be much more severe damping to have a noticeable impact on inertia measurement. Mounting error and string load distribution There are a number of reasons why the axis of rotation might not coincide with the CoM of the test object. Among them are mounting error, offset between the geometric center and the CoM, and string load distribution. The transformation for inertia about parallel axes is used to characterize the effect of this misalignment: I B = I + mrA, (2.12) According to the "Mass Properties Measurement Handbook" [Boynton, Wiener] [3], offsets around 1% of the radius of gyration are negligible, which is 1.461mm. The most obvious source of misalignment is mounting error. The mounting plate and test stand were: designed in CAD and machined to 0.001 in tolerances (0.254 mm) to hold a SPHERES satellite securely in the middle of the three strings. Another possibility is that the CoM of the satellite is not at the center of geometry. Most CoM measurements have fallen in the range of 0-3 mm and are on the order of negligible errors. A third source comes from the load distribution in the strings. If the tension in the strings is not equal the axis of gyration will not be centered, imitating a CoM offset error. This is why care is taken before each test to level the mounting plate. Having one comer of the mounting plate lower than the others would tilt the measurement axis and could change the pendulum's equilibrium point. Such errors would cause the inertia to vary by md 2 (Equation 2.12) where d is the distance between the CoM and the axis of gyration. A conservative estimate of 1 cm for d results in an inertia error of SI = 0.000717kg .m 2 (1.025%). Elasticity in the string The inertia measurement equation is a function of the length of the strings holding the test plate. Since the strings are stretching and contracting through these oscillations, this length is not truly a constant. The string used was nylon fishing line with a Young's Modulus of approximately 3 GPa. A nominal value for load would be 23.52 N m 1 (7.2kgx9.8 -- x-, assuming equal load on all three strings). Using a diameter of 2mm, s 3 the cross-sectional area of the string is 3.14e-6m2 . From Hooke's law: E= E = 0.002496 (2.13) 1 According to Equation (2.6), inertia varies with string length as -. In the range of values of e used for these tests, the relationship is close to linear (-1% change in £ leads to -1% change in I). For example, using a nominal string length of 2.6m, S&= 0.0065m. This translates into a change of I equal to SI =0.000175kg.m2 , or a 0.7% error. As shown earlier, the strain in the strings does not vary linearly with the applied stress, making Hooke's law invalid. However, since the error due to string stretching is so small, the effect of this linear approximation is negligible. Measurement Error (weight, string length, oscillation period) The period was measured by using a stopwatch to time 10, 20, and 50 oscillations. The time at each of these checkpoints is used to estimate the period and data is averaged. The measured time on the stopwatch (T)is related to w by the number of oscillations. For a test over 20 oscillations: 2r 40" ST= -;=T 20 (2.14) 2 I= 1600n . T • (2.15) Using nominal values for m and £, I changes by I = 0.0007696kg. m2 (1.194%) with a measurement error of ST = 0.25s. This error source was addressed by collecting data from tests as long as 50 periods as well as averaging over 10-20 tests per SPHERES satellite, per axis, and per wet/dry configuration. Inertia sensitivity to changes in mass would be less than sensitivity to time errors since inertia varies linearly with mass. Sensitivity to changes in string length was discussed earlier, with respect to string elasticity. Orthogonal Rotational/Translational Motion If the SPHERES satellite is rotating or translating in any direction outside of the desired axis (vertical rotation), more complicated equations of motion would be needed to accurately describe this behavior. The equations of motion used assume no translational movement, and care was taken during the experiment to minimize the amount of this motion. Because of the coupling in a trifilar torsional pendulum, a CoM misalignment causes sideways motion. The energy in the translational oscillation is not included in the rotation frequency (and therefore not observable in inertia measurements), and the nonlinearity of the pendulum is amplified. Consider that the torsional pendulum acts as a simple harmonic oscillator in both degrees of freedom of interest: A) a disc of mass m and radius r that oscillates about its center (amplitude of 0=20') B) a mass m on a string of length f that swings at very small amplitude (0.01m) causing unwanted side-to-side motion The total energy of a simple harmonic oscillator is: 1 E= K.A2 (2.16) 2 where K is the spring constant and A is the oscillation amplitude. 1 In Case A, E A = -K AA A where 2A 2 A IcoA= (2.17) AA = r For a circular disk, I = mr 2. From Equation (2.6), 2 ac ingr it 2 Substituting into Equation (2.16) yields: EA 1 In Case B, E, =~KA where 2 2 202 (2.18) KB = mfLoW K'~ A, = O.Olmeter For a simple pendulum, co2 = g = r (2.19) Substituting into Equation (2.16) yields: 1 mg(2 SMg (0.01)2 2f (2.20) Assuming a translational amplitude of 1cm ( A = 0.01) and a rotational amplitude of 20' ( A = 0.349 rad), E A = 0.037005J E, = 0.001423J (2.21) SI = 0.002799kg -nm2 This constitutes an inertia error of 3.845%. Alternatively, if A, = 0.005 the inertia error is 0.961%. 2.3.7 Empirical Mass Properties Conclusion There are two goals for empirically measuring SPHERES satellite mass properties. The first is simply to collect accurate information about the vehicle so that the controller can be as efficient as possible. The obvious advantage to this is more precise maneuvering and better fuel efficiency. This plant characterization continues in Chapter 3 with an indepth characterization of the CO 2 thrusters. The second goal is to establish a truth measure for the online mass property identification described in Chapter 4. From section 2.3.6, almost all the error sources in inertia calculation are around or below 1%. Adding them together as a worst-case scenario still amounts to <5% error. Because of this, the empirical inertia values serve as adequate truth measures for online mass ID. However, because of the small magnitude of CM offset, it would not be surprising to see deviations on the order of the values themselves, despite how meticulously the mount was created and the tests were performed. While averaging over several tests can help to remove some of the error bias, the CM measurements are not exceedingly reliable as truth measures. Chapter 3 Thruster Characterization 3.1 Propulsion System Overview SPHERES satellites maneuver using twelve ON/OFF solenoid valve thrusters that provide%independent control in three axes of rotation and three axes of translation. The fuel used is cold gas (C02) and is stored in mixed liquid/gaseous phase in a tank at the center of the satellite. Since it is multiphase C02, the pressure inside the gas tank remains constant at 860 psi until all the liquid evaporates. Directly downstream of the tank is a variable pressure regulator calibrated to provide 35 psi C02 when the regulator is completely opened. After the regulator is a small gas capacitor that allows any liquid CO2 to expand before reaching the plastic tubing and the thrusters themselves. The capacitor also helps maintain constant pressure downstream when thrusters are opened. The C02 is then fed through a series of manifolds and tube branches to supply all 12 thrusters with gas. 3.2 Propulsion Hardware The fuel tank was placed near the center of the satellite along the Z-axis to minimize the error induced by fuel depletion and slosh on the CoM and moment of inertia. While the fuel is mixed phase, the pressure inside the tank remains constant at 860 psi. Once all the liquid has expanded into gas (occurs with -28g of C02 remaining), the tank pressure begins to drop as more C02 is expelled. Since this only occurs when the tank is almost empty, we can assume a constant pressure supply for almost all tests. The gas capacitor serves two purposes: allowing solid and liquid C02 to expand to gaseous form and to provide a small buffer for changes, in supply pressure or demand on the regulator. Through continuous firing, the regulator will start to get cold. When this happens, its more likely that liquid C02 will make it into the piping past the regulator, which can damage the tubes and thrusters or produce off-nominal behavior. This has been seen even with a warm regulator when the tank is upside-down in 1-g and in microgravity. Also, there is a time constant associated with the regulator's ability to react to changes in demand for C02, which occurs whenever a thruster is commanded on. As gas is expelled through that thruster, the pressure drop propagates up the system back to the regulator, which opens wider to maintain a constant 35 psi. compensate for this delay since it acts a small reservoir of fuel. The capacitor helps Figure 3.1 Solenoid Valve Thruster 2 As per the control model representation in Figure 1.3, the thrusters (Actuators) are the most important part of the propulsion system to characterize. The thrust exerted by the solenoid valve thrusters depends on a number of things. A summary of applied thrust dependencies obtained by [Chen, 2002] [5] is listed in Table 3.1. Always set to 35 psi (regulator modified with slip ring to "bottom out" at 35 psi) Measured with an in-line contour projector Solenoid variation negligible. System Pressure Nozzle Area Solenoid Mechanics # Open Thrusters Temperature Firing Duration Thrust varies linearly with # of open thrusters (R2=0.9955) Negligible Negligible - slightly positive slope in thrust profile (<5% change after 70 sec) Table 3.1 Thrust Dependencies [Chen, 2002] [5] The location of each thruster was taken from the engineering CAD model used to build the SPHERES satellites. Table 3.2 has the nominal positions of each thruster in centimeters relative to the geometric center of the vehicle: -5.16 -5.16 0.00 0.00 9.65 -9.65 -5.16 0.00 -9.65 -9.65 -5.16 0.00 -9.65 -5.16 0.00 0.00 -9.65 -5.16 0.0 -. 65 -5.65 5.16 0.00 -9.65 9.65 5.16 0.00 -9.65 5.6 0.00 0.00 9.65 5.16 0.00 -9.65 5.16 Table 3.2 Thruster Locations wrt Geometric Center (GC) 3.3 Pulse-Width Modulation Scheme In most of the control schemes run on SPHERES, the outputs of controllers are forces and torques. For variable-force thrusters and reaction wheels this is a fairly straightforward command. However, since the SPHERES thrusters are binary, a PulseWidth Modulation (PWM) scheme is used [10]. This is accomplished using a mixing matrix to transform forces and torques to thruster ON/OFF times. Figure 3.2 describes the mixer process end-to-end. Controller Command Mixing Matrix (MMT )- M* =M Resolve Opposing Thrust Resolve Negative Values Scale by Maximum xT Dead Zone Pulse Centering Ii Multiple Thruster Correction .I Check TON >0 TOFF < T Schedule Propulsion Interrupt Srigure 3.L WIVwI MViixer •ole block Diagram The mixing matrix that transforms the command vector into thruster ON/OFF times is constructed using the calibrated force vectors for each thruster. First, the top half of a 6 by 12 matrix is populated with the three force vector components from each thruster. On the bottom half, instead of force there is the cross product of force and location, leaving a vector of torques for each thruster. F2 ... F-2y F1z F F2g --. F12Z MM=MT Next, the pseudo inverse of this matrix is obtained: =M (2.1) When a command vector is multiplied by the matrix MA, the result is a vector of length 12 of commanded forces normalized by each thruster's nominal force (i.e. a "2" means the controller wants that thruster to fire twice as hard as it actually can). Since SPHERES uses pulse width modulation, these numbers are actually fractions of the control period rather than fractions of the desired force. If any of these values is greater than 1, then they are all scaled down so that the net direction of the commanded firing will remain the same. If all values are below 1,then net impulse can be conserved as well. The next step is to take the vector of thrust durations and center all the pulses about the middle of the control period. The algorithm then accounts for multiple-thruster pressure drop by starting with the thruster with the smallest pulse and calculating how much impulse is lost on that thruster and extending the pulse accordingly (using the linear relationship between number of open valves and drop in thrust [5]). From here, the algorithm works outwards, finishing with the longest pulse. Ideally, this would be an iterative process, but for now our mixer does this just once. The final step is to implement a deadband of 10 ms (minimum time needed for thrusters to open) and round up pulse durations that are very close to the entire period. Figure 3.3 shows a simple example of how the commanded firing durations of two thrusters are altered to account for strength differences and the drop in system pressure when multiple valves are open. Since the thrusters are pulse-width modulated, the firing duration of the thruster with strength F 1 is shortened and then the pulses are centered so that there is no residual torque applied. The total area would be kept constant as well to have the same applied impulse. Corrected Thrust command is pulse Uncorrected c Thri .cqf width mnrli ilat•• F2 F2 - hnrf~n F pulse to account for higher thrust and multiple thruster pressure drop ,F Thrust F2 t Figure 3.3 Thrust Correction for Simultaneous Firings t 3.4 Propulsion Limitations There are a couple of limitations that complicate the SPHERES PWM system. The solenoid actuators have a mechanical limitation that requires a 10ms opening transient. This means that 10ms is the minimum impulse bit for thruster commands. Also, because of how fast the propulsion software interrupt runs, the resolution with which a thruster can be turned off is 1 ms. Lastly, thrusters cannot be on during any ultrasound measurement period since they can be misinterpreted as ultrasound signals used in the position and attitude determination system. This requires scheduling between global position updates and command periods. 3.5 Measuring Nominal Thrust Vector Nominal forces from the thrusters are key parameters for SPHERES system characterization. Each thruster was turned on and off for one second while testing on the load cell. The measured forces and torques over time in each axis were collected with a SigLab data acquisition system and processed with MATLAB scripts to filter out teststand vibrations, change coordinate frames, and decouple forces and moments. Force components were averaged over the one-second pulse to create a nominal vector of applied force in all three axes for each thruster. From this, the resultant thrust magnitude and direction were determined. This characterized both the nominal thrust of each solenoid valve as well as its misalignment with the satellite body axes. These nominal values were averaged over 200-500 tests per SPHERES satellite. The same 6 DOF load cell and test stand used to measure the Center of Mass was used to measure nominal thrust strengths. A test program was written to cycle through all 12 thrusters in order and loaded onto a SPHERES satellite beforehand. This vehicle, with a full tank and batteries, was mounted upright on the test stand with the regulator knob pointing up. The power was turned on, the-1ropulsion system was pressurized and data collection on SigLab begun right before the "start test" command was initiated from the ground station laptop. Each test was run 5-10 times for repeatability. _IV. +Z Af Y Figure 3.4 SPHERES Body Axes Because of the geometry of the SPHERES satellite and the test stand, the two thrusters pointing down would not register correctly on the load cell. This is because the force from those thrusters is cancelled by itself since it reacts against the test stand. Therefore, like with the CoM tests, the satellite was rotated 90 degrees and the tests performed again to get the last two thruster strengths. Since the load cell is 6 DOF, the output data included forces and torques in three axes, so the misalignment of the mounted thrusters could be examined. Table 3.3 shows sample thrust strength and direction numbers for SPHERE SN 2. These tests were conducted on all five of the flight satellites. As expected, these thrust strength 2 numbers are reasonably correlated with nozzle area (R = 0.42). "Dx," "Dy," and "Dz" form the components of a unit vector in the direction of force for a given thruster. As the chart shows, most thrusters have a unit vector direction aligned to at least 0.996 along the principal body axes. 0.134 0.004 0.998 -0.022 0.025 0.130 0.002 0.999 -0.001 -0.025 0.122 0.006 0.059 0.996 0.032 0.130 0.004 -0.018 0.999 0.004 0.114 0.005 0.011 0.034 0.999 0.124 0.006 -0.022 -0.012 0.999 0.134 0.004 -0.999 -0.008 0.044 0.130 0.003 -0.998 -0.009 -0.037 0.128 0.006 0.042 -0.999 0.009 0.132 0.005 -0.019 -1.000 0.004 0.126 0.006 0.004 0.060 -0.998 0.110 0.005 I -0.002 -0.030 -0.999 Table 3.3 Thruster Strength and Direction for SPHERE SN 2 3.6 Thruster Latency Each solenoid has a latency of about 6 ms. If we assume that thruster firings will be much longer than 6 ms (say 1-2 orders of magnitude), then the difference in delay I between thrusters should not be a concern. Some tests were conducted on the prototype SPHERES satellite to get an idea for this "relative" delay between thrusters. For example, two thrusters in the same direction were commanded to fire and the produced torque was measured on a load cell. Figures 3.6 shows some samples of the torque data from the load cell. The horizontal axis is in seconds. Every two seconds both parallel thrusters were commanded to fire for one second. The first maneuver at t = 0 seconds had Thruster A firing 3 ms before Thruster B. Two seconds later, Thruster A fired 2 ms before Thruster B, and so on. The middle maneuver at t = 6 seconds is when both thrusters fired simultaneously. By looking for the shortest impulse in the first figure (Z-moment) or the intercept in the second figure (X-moment), the relative delay appears to be less than 1 ms. V / - 20V - Signal to solenoid 5V io F t Id 1Oms i / \' T FO I I Applied force t I 54 t Figure 3.5 Thrust Latency in Solenoid Valve Figure 3.6 Applied Impulse From Difference in Thruster Latency The flight SPHERES satellites have access to accelerometer data at 1 kHz, which can be used to get a better idea of the absolute delays for each solenoid. Figure 3.7 shows an example of solenoid delay on the order of 6ms. TMr.DdY I Figure 3.7 Sample of 6ms Solenoid Delay The possibility of using the JR3 load cell to measure the solenoid delays of the flight SPHERES thrusters was explored. The JR3 has a bandwidth of 8 kHz and in order to resolve a 6ms delay in thruster actuation, an effective bandwidth of 2 kHz is desired (20 counts over a 10ms period). When a mass is placed on top of the load cell, q drops: ofg= = Vm (2.2) The stiffness of the load cell to forces in the X and Y directions is c = 18x10 3 in English units. With a typical SPHERES satellite weight of 7.7 lb, the bandwidth of the entire system is approximately 48 Hz. The response time of the combined SPHERES and JR3 system will drown out the solenoid latency. 3.7 Multiple Thruster Pressure Drop Since the capacitor is not infinite in size, the supply pressure coming out of the regulator is not constant, but dependent on the flow rate. As such, the more thrusters that are open at a time, the lower the pressure is at each nozzle. The lower supply pressure results in a lower produced thrust. The first SPHERES mixer assumed constant thrust, while newer iterations, including one described in [Blanc-Pacques '05] [1] compensate for the thrust reduction, resulting in more accurate open (and closed) loop control. This new thruster mixer was developed using the previous thruster characterizations. Tests to see this effect were carried out on a mock propulsion system, pictured in Figure 3.8. This setup includes all the components of the propulsion systems on the flight SPHERES arrayed on a plywood board [5]. P1 P4 Thruster 1 Figure 3.8 System Pressure Propagation Test Setup Pressure transducers were placed at 4 locations in the system to measure the propagation of pressure loads. Figure 3.9 shows the thrust commands and the corresponding pressure from the four transducers. From this test, it appears that the reduction in thrust is not very dependent on how close the thrusters are in the tubing tree. The effect of the gas capacitor can be seen here where the upstream pressure does not change much with increased pressure demand. System Pressure Thruster Configuration LJ.H .U.LUKL r:i · · *·'"·' 0; ' '··--.·!-.··"·~-;:· • 5 ~·-~····I·--`'·"- • rWn -o . N•n I .. ,r,* o 10 20 30 time (s) 40 50 6o - 10 ............ " 20 30 Figure 3.9 Pressure Change Propagation Data 40 time (s) F -upstream P S P downstream i70 60 50 P4 -downstream 3.8 Sensor Characterization Having adequately examined the Plant (SPHERES satellite) and actuators (propulsion system and thrusters), all that remains is to look at the sensors (inertial gyroscopes and accelerometers) to complete our system characterization. The two inertial sensors are the BEI Gyrochip II tuning-fork gyroscope and the Honeywell Q-Flex 750 accelerometer. There are three of each on the flight SPHERES, providing telemetry for all axes. While the accelerometers are mentioned here for completeness, they are not used to close the loop, and so are irrelevant to the topics in this thesis. The specifications for these sensors are summarized in Figure 3.10. Max Update Rate Range 1000 Hz +25.6 mg Max Update Rate 1000 Hz Range +83 deg/s Resolution 12.5 [tg/count Resolution 0.0407 deg/s/count Bandwidth 300 Hz Bandwidth 300 Hz Noise (0 to 10 Hz) < 7 tg rms Noise (10 to 500 Hz) < 70 pg rms Noise (0 to 100 Hz) < 0.05 deg/s/(Hz)1/2 Figure 3.10 Inertial Measurement Unit Specifications · In order to take full advantage of these sensors in closed-loop control, it is beneficial to examine the noise characteristics. In addition to the noise listed under the manufacturer's specification, there also appears to be a high frequency ringing associated with the gyroscope when thrusters are opened or closed. As a tuning fork gyro, the Gyrochip II vibrates one set of tines at a "drive frequency." The other set of tines (the "pickup fork") oscillate at a sense or "pickup frequency" only when the gyro is rotating (Coriolisinduced torque) [17]. The difference between these frequencies is known as the "deltaF" of the gyro, which in our case is about 338 Hz. This phenomenon is explained in more detail in Appendix A. When this frequency is excited, say by the small impulse of opening/closing a solenoid valve, there is a decaying oscillation of 338 Hz in the gyro data. Since this noise is tonal, it can be filtered out fairly easily with a notch filter. Figure 3.11 shows gyro data where this high frequency noise is especially apparent. Since this data is sampled at 1 kHz and the noise in question is about 338 Hz, the effect of only having three samples per period is apparent (Nyquist requires >2). Figure 3.12 shows a Fast Fourier Transform of gyro data sampled at 1 kHz to isolate this noise peak. 25D 1...... Fii Figure 3.11 Filtered 338 Hz Gyro Noise A couple key characteristics of these sensors are the biases and scale factors used to convert from counts to rad/sec and m/s 2. The biases and scale factors of each gyroscope were computed with the help of a rate table, while the biases and scale factors for the accelerometers were taken from manufacturer specifications. These values are stored in flash memory on the corresponding satellites and are automatically used when IMU readings are converted. FFT of signal with Ts = 0.001. DC :comrn ponent:(0.00038837) is not shown, 0.5 0.45 0.4 0.35 0.3 0•.25 p 0.2 E 0.15 0.1 0.05 O 0 1 50 100" A, 150 200 250 300 frequency [Hz] 350 400 450 500 Figure 3.12 FFT of Gyro Ringing With gyro-specific scale factors and biases and online filtering of the 338 Hz noise, the gyro output is very accurate, which is important for closed-loop control and for the online mass property identification algorithm. Chapter 4 Mass Property Identification 4.1 Online Mass Property Identification Thruster values and relevant sensor calibration information remains the same over normal operation, but mass properties of the SPHERES satellites change as fuel is depleted. While previously measured empirical values for CoM and Inertia provide a good start for control algorithms using these values, having them update online is preferred for more accurate control performance. The mass-property algorithm and equations ((4.1) through (4.8)) are taken from "On-line, gyro-based, mass-property identification for thruster-controlled spacecraft using recursive least squares," [Wilson, Lages, Mah] [21]. The general approach to online mass ID is to use gyro information about rotational rate to estimate angular acceleration and system characterization information (especially about the thrusters) to estimate applied torque. With this information, Euler's dynamical equation is used to find inertia assuming a center of mass offset, or find the moment arm (hence center of mass offset) assuming a value for inertia. The center of mass offsets can be identified with better accuracy with pure translations along a single axis since the unbalanced effect of these offsets is much easier to see when the range of the gyro data is small. The two major error contributors in flying along a straight path (pure translation) are the thrust strength variation (which we've characterized) and the center of mass offset. While identifying center of mass, the difference in torques provided by parallel thrusters is the "signal" that provides the algorithm with the necessary information to identify CoM. If there are rotational maneuvers occurring, this signal is easily lost in much higher magnitude "noise" of largescale rotations. On the other hand, pure rotations about a single axis, provide the best data for estimating the inertia matrix elements. The inertia associated with that axis depends on the estimated angular acceleration during the maneuver, which is most accurate during pure rotations since the effect of nonzero center of mass offset in the gyro data is minimized. Figure 4.1 shows a representation of these two scenarios. z = moment x Jorce = la ' =J F I T.i. 1 r Lfj p _ mome moment Figure 4.1 Ideal Maneuvers for Inertia and CoM Identification 4.2 Theory and Equations The first step in formulating the equations behind the mass ID algorithm is to take Euler's dynamical equation, and write it in a form that allows least squares (LS) analysis, with gyro data as our measured quantity and with CM offset and inertia as our unknowns. In the following equations, L is the thruster locations measured from the CoM, D is the nominal thrust directions (unit vector), F is the nominal thrust, B is the blowdown effect from decaying thrust, and Tis a binary on/off value for each thruster. (o= I1 ' (' - @ICo) (3.1) ) (3.2) S= thrusters + Zdisturb = (L x D F + zitub Fk = B(Fom +Fbias + (3.3) adom,k )Tk The algorithm is equipped to handle disturbance torques, random variability in the thrusters and blowdown, although for our purposes at this stage, these quantities are considered negligible. Equations (4.1), (4.2), and (4.3) are combined to give: Co = I' ((LxD)B(Fom +F + Fbi' ,ndom,k Tk + diturb - OX(I O)) (3.4) The next step is converting this Equation (4.4) into the standard least squares form, Ax - b. For the center of mass identification, there are a few more definitions: C is the true center of mass and A is the CoM offset. C = Cnom +A L=Lom -A[1 (3.5) . . . 1] (3.6) Refer to [Wilson, Lages, Mah] [21] for more detailed derivations. The final least squares form is: Ak =I-1 0 -c3 2 C3 0 -C1 -- C 2 C1 0 1 x k bk = +-1 1(cox(+I))-I-' (LnomxD)FnomTk A2 A3 Center of Mass LS Formula ck - DFnoT (3.7) k The vector of center of mass offsets fits well into the standard least squares form. However, the inertia matrix is a symmetric 3x3 matrix with 6 independent terms and needs a special transformation to conform to Ax _ b. Also, the inverse of the inertia matrix is identified because of the form of the equations of motion: a, Ak =0 0 0 a2 a3 0 I a2 0 a1 0 0 a1 a2 I-I2 33 -0 0 a3 a3 x= bk k 12 ak = (L xD ) FomTk S(LD)F) -o 1131 - I I3nInertia LS Formula (3.8) For Equations (4.8) and (4.9), the inverse inertia matrix and center of mass offsets are identified by using the standard batch LS solution, = (ATA) -1ATb. This is acceptable for "off-line" data processing for computing mass property estimates. For on-line estimation, a recursive algorithm is used, incorporating the covariance and state update equations: Qk+ -1 +=Tk-IAk+1 = Xk + Qk+lAIZR+l 4.3 Ak-I [bk+-Ak+lk-] (3.9) (3.10) RGA Micro-gravity Testing From February 5-7, 2002, the SPHERES team conducted tests aboard NASA's RGA. Mass property identification tests were run to help with development of the algorithm as well as to provide good, independent estimates of inertia and center of mass offsets for each of the flight units. Two types of tests were performed to help identify the mass properties of each SPHERES satellite. One set of tests was composed of 12 different maneuvers: pure rotations and pure translations in each axis in both directions (2 x (3+3) = 12). Essentially, pairs of thrusters were turned on for one second to produce pure rotations/translations in both the negative and positive directions. The IMU data was sampled at 100 Hz, which was the most data that could pass through the communications system in real time. The other set of tests had seven maneuvers, which involved turning on one thruster at a time for one second each (maneuvers 1-6 each tested 2 different thrusters). These tests had a sampling rate of 1 kHz and required a period of about 30 seconds to download the IMU data afterwards. The last maneuver in this set of tests was created with the intention of testing the robustness of the mass ID algorithm. It consisted of a series of firings of duration varying from 0.01-0.02 seconds. Some firings included orthogonal thrusters to excite motion around multiple axes. Figure 4.2 shows some sample filtered gyro data taken during a test on the RGA. The plot on the left shows a pure rotation in the Y-axis and then an equal and opposite rotation. This data is ideal for identifying Iyy, Ixy, and lyz. The plot on the right is from a pure translation test along the +Y-axis. As is expected, the angular rate values do not change much over the course of the two firings. This data is ideal for identifying the center of mass offset along the x-axis. Assuming we know the thruster misalignments, the nonzero change in angular rate in the figure is purely due to CoM offset and is easily observable. It is this information the algorithm uses to identify CoM offset. .. ... . " ............• ........... ........... .. * . ... . I-... ... .. .............. ........... .. . ··. ·... .......... ... ...... .... I i; ··· ·-I----· .......... . .......... , ··. .................... r-·- ; -,;···;·~1I·-;I······ ......... . Y"o - ma ma m "o 0 ........... ............. .................. ........... s o s o 0 10 Figure 4.2 Three-Axis Gyro Data From RGA Test Every data file collected during the RGA flights was analyzed and catalogued. Each SPHERES satellite ran from 2-8 successful iterations of each maneuver type (translations and rotations in x, y, and z), totaling in 15-40 micro-gravity tests for each SPHERES satellite. Continuous, undisturbed data was extracted from as many tests as possible and run through the offline MATLAB implementation of the mass property identification algorithm. Mass property estimates for each SPHERES satellite were separated and averaged to produce nominal values. These results are shown in Table 4.1. As expected, the values are similar across all the satellites. 0.967 0.0284 -2.68 -0.0000837 0.0268 0.55 0.000014 -0.00029 -0.33 0.02795 -0.23 0.000108 0.0238 0.737 0.000157 0.0000123 3.517 0.0260 0.771 -0.0000082 0.0229 -1.87 0.000149 -0.000221 Table 4.1 RGA Mass Property Results 0.0236 0.0204 0.0208 All the usable data was also concatenated to test the convergence of the mass property estimates over long tests. Figure 4.3 shows an example of all the Z-axis rotation data (measured by the gyro along the X-axis) for one SPHERES satellite and the corresponding angular acceleration estimate. SPHERE SN 1 performed 5 Z-axis rotation maneuvers (5 seconds each) and 3 "combo" maneuvers that excited all axes, totaling 34 seconds of usable concatenated data. Gyro Data '"^ Angular Ac celeraion Estimate ^" --... ... .... ... .. ---- ... --- -- -4 0.4 3O2 S I I 2500 IL II Ii II I II II 1 1 I I 0.2 2600 ..... .... ... .. ..... ...... .. "..... . ... .... .. .. .. ... ..... ... .. ..... . ... .. .. .. ..... 1600 ... ................ .... .................. .......... * * oomaoy - . I z g"yro I J LA 2 22 --L - , , -0.4 0 70.6 n00 .e 222 2.4 2.6 time (ms) 268 3 3.2 34 1.8, 2.4 x 10 2.86 time (ms) 2.8 3 3.2 3.4 x 10 Figure 4.3 Concatenated RGA Gyro Data NASA Ames/Intellization also conducted some tests with SPHERES aboard the RGA. As with the tests above, raw IMU data was collected and post-processed using a MATLAB version of their mass property identification algorithm [20]. The green lines in Figure 4.4 indicate when the RGA pulled out of its freefall. Data telemetry collection was paused during these periods using real-time commands from the control laptop. This pause/resume feature was implemented to keep the data stream free of disturbances caused by the satellite bumping the wall or being handled by the test operators. On the thirtieth parabola, a known mass was attached to one side of the vehicle. By adding a measured proof mass with a precisely known mass, CoM, and inertia, it was possible to determine if the mass property identification algorithm was accurate in measuring changes in these parameters. Around the fiftieth parabola, a near empty tank of C02 was used to replace the current tank. This tank had been depleted to the point that all the liquid C02 inside had expanded to gas form. Since the pressure inside the tank is no longer constant as gas is expelled, the resulting force from the thrusters is no longer constant as well. - IDeadinertia X10 1 p 2.s .5- ID~ed dolt&C . A1 4'C Is. 1! i5, -0.5- 1 pI0010ro a. -.. -'5--- between parabolas 500d ~c.5.. -2.3- ~ ~ o4~ -0.55'. ----0 ~20 10 F" It dolt.c S.- -3- )3z 7 k~ S-1.5 dltaC. deltacy -3.5ý $ 30 -4 40 50 Ime [sconds] 60 70 0 10 20 30 40 50 tm e [econds) o 70 80 Figure 4.4 AMES/Intellization Mass Property RGA Results [Wilson, 2003] [20] The RGA testing provided high-fidelity data for post-processing. The mass property identification algorithm was validated offline by estimating mass properties similar to empirically measured values. The NASA Ames tests succeeded in identifying known changes in mass properties from the addition of a proof mass. 4.4 Algorithm Development The first few iterations of the mass property ID code were developed in MATLAB using a batch least squares approach described in "On-line gyro-based mass-property •( identification for thruster-controlled spacecraft using recursive least squares" [21] to post-process data. Later revisions included simulated recursive LS convergence, varying methods for estimating di,offline C code that used mock data, and finally an online realtime version that ran on the SPHERES Embedded C++ operating system. The first hurdle to clear when implementing the mass-property identification algorithm was to characterize the key system parameters, which is what most of the preceding chapters are dedicated to outlining. Once the thrust strengths, directions, and moment arms were identified and nominal mass properties were determined, the only missing piece was how to estimate ;)from the onboard gyroscopes. The crucial part of this problem was that 6)is the measurement vector for the RLS mass property equations, and its variance must be small enough to make the inertia and CoM estimates meaningful. Also, differentiation is an inherently noisy process, where a simple difference can raise noise by a factor of1 (1,000 at 1 kHz). This is why careful attention was paid to both At the noise of wo and noise created by the process of estimating (0. 4.4.1 Gyro Filtering and Interpolation As explained in Section 3.8 and in greater detail in Appendix A, the SPHERES gyroscopes have a non-trivial noise component at 338 Hz. Raw gyro data is always sent through a low pass-filter, either online before it is sent across the communications channel or during post processing in MATLAB (Figure 3.11 shows unfiltered gyro data). In the latter case, a zero-phase forward-backward filter with two poles at 50 Hz is used. Even before the rate data is filtered, it is sent through an interpolator to account for lost data points due to dropped telemetry packets (not an issue for online testing). This makes the signal even smoother and allows a uniform sample rate assumption for the filter. This filter was chosen because it sufficiently reduced the noise (approximately -20DB) without softening the corners in ) where rate: changes occur, and because it produced acceptable values for the variance of gyro data. Figure 4.5 shows a sample of filtered rate data collected during one of SPHERES micro-gravity RGA tests. This test consisted of two one-second long torques (equal and opposite) around the X-axis. Also shown are the post-filter calculated values for R0, the standard deviation of the gyro signals. Fietarg X -GyFQ D0*taSN 1) 'i i .. ,. .. ): : ~36 i· i 2000 rr :· i, r-;·~···:l.·····;·-. 1900 i· i ·;r·-r·..,.,.--·.·1·-·)··-~::···i··1 : i·; ·L·····-··'.'6"'.'l"Z : ·li 6 :· :· * i rl 1700 : i: i r i i1600 •.m · · ·.· ;·······.- j i : .... t~t.~-TI · · · ~i·?t;·.-jli :: :i 1 *·· :: i S. 600 . 1000500... 2W :2500 30003500 Updnte Pointrms) 9.5661e -7 =0 0 0 2.7365e -7 0 0 4000 0 0 rad s 2.3044e- 7 Figure 4.5 Filtered Gyro Data Standard Deviation 4.4.2 Angular Acceleration Estimation A number of different candidate filters were considered for estimating b. Finite differences are very light on computation, but produce unacceptable noise levels in the output. First order line-fits are suggested [Wilson, Lages, Mah, 2002] [21], and many of these were used and analyzed. The window of a line-fit determines how many data points to take into account for each estimate of 6, which is equal to the filter order for discrete filters. Two different line-fits are compared in Table 4.2, a non-overlapping linefit and an overlapping ("sliding") line-fit, for varying window sizes. Both of these linefits are "centered" (the 6) estimate is centered around an odd number of Co values) and are therefore acausal and unusable in real-time. A backward line-fit that only operates on previous values should be used for online estimation. Table 4.2 Standard Deviations for Line-fits of Varying Order Sliding line-fits of high order clearly provide the lowest variance estimates, but not low enough. Using these variance values for the measurement vector in the mass-property identification algorithm led to uncertainties in inertia and CoM on the order of the values themselves. The approach that is currently implemented to estimate 6is a discrete Kalman Filter. The propagation and measurement update equations are derived from: k+l= kXk + Wk(3.11) Zk = Hkxk +vk I In Equation (4.11), x is the estimate of the true value x, wk is the process noise from propagating x, 0 is the propagation matrix, z is the measurement, v is the measurement noise, and k is the update number. Figure 4.6 shows the form of the general Kalman Filter equations as they were implemented in code. 6ýý Measurement update +H Rk Hk = (Pk' Kk Xk 7 P kHIRk k = Xk +Kk (zk -Hk k kXk- I 41,ý ii - Update number - (superscript) indicates "a priori" knowledge - Covariance matrix of estimate error - Matrix relating measurement and state vector - Measurement error covariance matrix - Kalman gain - Estimate vector - Measurement vector - Propagation matrix - Process noise covariance matrix Figure 4.6 Kalman Filter Process Assuming constant thrust and no energy loss due to drag, dc is a constant during any given thruster firing configuration. By using a Kalman Filter to identify a constant [18], all the previous information during a given thruster firing is used to determine that constant. Each successive measurement update increases the confidence in this value, leading to very low values of variance. Since the estimate vector is a constant and the derivative of the measurement vector: 0=1 Qk=4Ewk R Rk 1 (3.12) E[VkVk.] = Hk =tk This Kalman Filter has been shown to converge well for initial conditions Xj =0 and (PO- = 0 as well as for more accurate starting guesses. This technique allows the variance: of angular acceleration to decrease to a level that gives reasonable convergence values for the mass properties. configuration changes, the Kalman Filter resets. Whenever the firing The initial estimate of angular acceleration for the Kalman Filter is set to: a number calculated using nominal thrust and inertia, and the covariance of the initial estimate is reset to a very conservative value. The gyro data in Figure 4.5 was sent through the oh Kalman Filter as well as line-fits of varying order for comparison. Figure 4.7 shows plotted angular acceleration for a nonoverlapping line-fit and a sliding line-fit (both of order 15) and the Kalman Filter. Angular Acceleration Estimation -1overapping 1.9 2 2.1 22 2.3 Not2.4-verlppin 2. 5 4 x 10 -1 1.9 2 2.1 2.2 2.3 1.9 2 21 22 Time (ms) 2.3 2.4 2 X104 Kalman Filter 2.4 25 4 X 10 Figure 4.7 Angular Acceleration Estimation Comparison The trade-off between the Kalman Filter and the line-fits is that the KF estimate can be fairly uncertain at the start of each new firing, whereas its variance becomes much smaller after a few updates. The KF estimate variance at the end of this data set is 5.4508e- rad/s4 . Figure 4.8 shows the variance profiles for each estimation method. Using the Kalman Filter over the line-fits led to much better convergence of mass properties. Innr• Omega Dot Variance Comparison (U U) U C (U Update Point(ms) Figure 4.8 Estimation Routine Variances 4.4.3 Mass Property Identification At this point, the thrust characteristics and nominal mass properties are known, the gyro data has been interpolated and filtered, and an co estimate with low covariance has been calculated. xk+A= (A The MATLAB code performs a batch LS over all the data using A)- A'b to give an estimate of inertia and CoM. Then the calculation is done recursively to show the convergence of the mass property estimates. Depending on the length of the test, the initial guesses for the recursive estimator are provided by a batch LS of the first two firings. This initial batch calculation is to help avoid a poorly conditioned estimate covariance matrix. Many of the test maneuvers consist of single axis translation or rotation since they are the easiest way to make specific mass properties observable. Unfortunately, this means that little to no information about the other values in the estimate vector is being provided, so the difference in the covariance values is very large. An ill-conditioned matrix is extremely prone to digitization error, especially when inverted. Another procedure for avoiding this problem is that the MATLAB code can scale down the Recursive Least Squares RLS equations, (4.7) and (4.8), depending on which axes have been excited. For example, a moment about the X-axis will only exist if thruster 5, 6, 11, or 12 is fired. If only these thrusters are fired, I~, I , and I7 are unobservable. If running the mass property algorithm on this data merely leads to radical values of those inertias, this is not a problem, but if it causes matrix inversion errors from a high condition number, it will pollute the value being measured, I:. If those inertias are assumed 0, Equation (4.8) reduces to: Ax a, 02 a2 3 0 a, 0 1I-= 0 0 a, I =b (3.13) Though this eliminates the poorly conditioned Q problem, it is impractical for tests with maneuvers about multiple axes. This would require dynamically changing sizes for all the vectors and matrices, which is difficult and inefficient to implement. Of course, if there are different maneuvers about multiple axes, Q will be well-conditioned and the full order equations are ideal. Using the pseudo-inverse instead ('pinv' command in MATLAB) will usually be able to force a solution regardless of poor conditioning, but I the resulting values can still be distorted. In the actual algorithm, the first two firings are used for a batch estimate. Chances are enough axes are excited to avoid these issues, and subsequent updates occur with each new measurement. Once an initial estimate with reasonable covariance has been provided, the RLS equations can calculate the convergence of the estimated inertia and CoM. The final value of the recursion should equal the total batch results since the two processes are mathematically equivalent. Figure 4.9 shows an example of I, convergence. bxxRecursive Estimate 0.1 iI * l • II I I I I I I II II II I I I 0.08 r --I - ----- - -- 1 ------ - 0.06 E I S0.04 - I 1i I - , I 0.02 i 1......... ........ I .... . I Il I I I I I II ............ II I I I e Ij I II I 0 0 1000 2000 3000 4000 5000 6000 update # 7000 8000 9000 10000 Figure 4.9 Sample Ixx Convergence The green and red lines are la boundaries based on the estimate error covariance. The regions where the a envelope closes rapidly are during rotations induced about the Xaxis, when I, is most observable. Similarly, the areas where the confidence envelope is flat correspond to times when the SPHERES satellite is free-floating or firing about orthogonal axes, which provides very little information that can be used to improve confidence in the I, estimate. 4.4.4 C Code Implementation Once a fully operational offline mass, property identification algorithm was functional, the next goal was to transport it to the SPHERES operating system for online use, which would allow the satellite control routines to take advantage of mass properties updated in real-time. This process was made easier by separating the task into two parts, each with its own complications. Porting the mass ID algorithm from MATLAB to C Code required thinking about memory allocation (local stacks, static and volatile variables). Also, computation in C is handled differently than MATLAB, especially with matrix inversion, matrix multiplication, and indexing. Once the code is functional in C, the language barrier is crossed, but changing the code to work on a real-time DSP is nontrivial. The various threads of the SPHERES flight code operate on prioritized periodic interrupts, which require careful scheduling of processor time. Thread scheduling places constraints on when a piece of code can retrieve its inputs, when it can make its calculations, and when it can send data over the communications channel. Another important issue that doesn't exist in the offline implementation is limitations on processor power and communication bandwidth. Inverting a 300x300 matrix at 1 kHz or sending every RLS variable over the wireless channel is not feasible. The first step was writing the basic functions in Visual Studio C++. These functions were tested by taking previously collected telemetry data and writing them to a text file in MATLAB. The C Code would read these files as inputs, calculate mass property estimates, and write the output to other text files, which would be read by MATLAB scripts and compared to the outputs of the original software. Figure 4.10 compares angular acceleration from the MATLAB and offline C Code. The error is probably due to the different precisions of matrix inversion processes. Since both still converge to the same value, the initial error is assumed negligible. 0.56 0.54 '664 -- . - . Angular Acceleration Estimate I I - --- -4-_--- I. . . . - - 11 ,II*. II I - MATLAB - 0.52 aos, -. 048 0.481 .t . II 1 I II 0.42 ~~ . .~ . . - -- -- -- I 1|j 1,9 --- - 1.95 -- I I -• . - TI T---------1-------I --. - I II -I 0.44 0.4 - -----II --- ---c I I ~--'-iI I i -. . - ,-I . . . .- :-- I I 2 time (ms) I I 2.06 -- - - I I 2.1 x 10 Figure 4.10 MATLAB vs. Visual C Acceleration Estimation Results After validating the functionality of the C code algorithm, tests were conducted using the system clock to try to simulate real-time conditions. The highest frequency interrupt on the SPHERES DSP is the propulsion interrupt at 1 kHz. This defines the minimum thruster command and the maximum rate at which the sensors can be sampled. From an estimation accuracy standpoint, it is desirable to operate at the maximum update frequency. However, running the ID algorithm at 1 kHz caused problems with processor time, so the algorithm was changed to trigger off the less frequent interrupts. For more specific information on the online C Code implementation, refer to Appendix E. Figures 4.11 shows test results from the online mass ID algorithm. Gyro data was also downloaded and fed into the offline C version to compare outputs. IntersInertia (Izz)- Sphere Online Inversnertia(Izz)- VisualStudio Ju I I I I I I I I I I I I - - - I - -I- -I- -I--;: '+----i- I I I 1I I I I I I I r-.....r-- I I I. II I- I I -I L~l 0 0 10 I -- I 20 I T. I I I I I I I I I I I I I·---_-. 30 I 1I I.-.-~....~..~. 1 I I I I - I I 40 50 update # I I i I I I 7-II I ---- i -I i I1 60. 70 I I I 80 nl 0 90 10 I I 20 I I ~ ..-I I I I 11 ~ ~ I I I I I II I I I ~ I I I 30 40 I I I I I. I 50 • II I I II II I I I I 80 I I I 70 80 90 update # Figure 4.11 Visual Cvs. Online Embedded CMass ID Results Figure 4.12 shows the Z-axis gyro data for a maneuver designed to test the full functionality of the online mass ID code. The test included 4 pure rotations about Z designed to identify I, followed by four pure translations designed to identify XCM. 81 Z-Gyro Data 08 , -0.4 - 0.64 --0.46 - •+I -- - I 0.28 L ---I - I -"-____I l l -/ 4.6 4.8 -2Figure 4.12 4.6 4.8 axisCM -0.8offset 5 Z-Axis l 5.2 5.4 Gyro 5 Data 5.2 - I I I L - I I 58 6 -- -- ii n 56 From , Online 5.4 5.6 time (ms) 5.8 l 62 Mass 6 6.4 ID l 6.2 Test z esmate 6.4 4 X 10 Figure 4.12 Z-Axis Gyro Data From Online Mass ID Test The resulting RLS estimates are plotted in Figures 4.13. Izz esbtmate X-axis CM offset II I .I 1 I -0.2 -- -0.48 - -- -- S + I ---- t -t I I --- I I -- III----4I II I I -- - I o -- T . I . .1--. . . . 4II --- SI -1.2 • 0 0.05 4- 0.04 I I .I.. - . I - I. --I - ----- -- *I I 0.0 0.06 ------ I - I I T-1 I . I I - -- I I I 4 I I I 20 40 60 80 100 update# . . -T - I I 4. 7- I1 . I 4 I -I I - 4 I I I I I 120 140 160 -- 0.02 180 0 4-- 20 ----- -----4 40 1I -- --III- I---- 60 - T- Ir 4- - 80 - i - I -r -- I I ----- 100 120 140 - --II4-- - -- [. . 160 180 update# Figure 4.13 Online Mass Property Estimate Convergence As expected, the inertia estimate converges quickly during the pure rotations while the CoM offset jumps wildly. During the pure translations, the inertia covariance does not improve, but the CoM offset converges quickly. The primary goal of this test was to show that the online algorithm converged to the same value as the offline MATLAB code, which it did. The actual estimated mass properties are incorrect, probably because of drag on the air-table or gas escaping from the air-bearing in a non-uniform way. The online algorithm in real-time C has been shown to be equivalent to the offline C++ version as well as the offline MATLAB version, which from RGA tests was shown to estimate mass properties correctly. Chapter 5 Conclusion 5.1 Thesis Summary The first chapter introduces SPHERES as a low risk, high fidelity platform for developing algorithms for autonomous spacecraft. The various components of SPHERES hardware are examined. The motivation behind creating SPHERES to test autonomous rendezvous, docking, and formation flight is explained and related to current projects and areas of active research in the field of aerospace. Also, the motivation behind system characterization as a candidate algorithm on SPHERES is provided. Results of empirical tests to establish a truth measure more reliable than CAD estimates by obtaining the mass properties of the SPHERES satellites are presented. The test procedure and error sources for CoM measurements are briefly outlined. Since moment of inertia isn't measured directly like CoM, a model is introduced to approximate a torsional pendulum. Equations and assumptions are presented and results are shown and compared to CAD values. Error sources for inertia measurement are analyzed in detail and the procedure behind measuring products of inertia is explained. Empirical measurements are proven to be more reliable than CAD predictions. Having characterized the SPHERES satellite itself (Plant), the thrusters (Actuators) and gyroscopes (Sensors) are analyzed. The hardware associated with the propulsion system and sensors is detailed as well as the thruster locations and thrust dependencies. The PWM routine is explained in detail, including a block diagram of the mixer code. The test setup for measuring thruster strengths and directions is outlined and results are displayed. Different measures of thruster latency are presented and the difference in delay deemed negligible. Data depicting the multiple thruster pressure drop phenomenon is shown and observations made. The sensor specifications are reviewed and the noise characteristics of the gyroscopes are characterized. Finally, a mass property identification algorithm [21] is introduced to improve mass estimates on line, thereby allowing even finer control than offline estimates. The theory and equations behind the algorithm are presented, and results from micro-gravity experiments on the RGA are presented. The development of the mass property ID algorithm from an offline batch LS in MATLAB to an online recursive LS in real-time C is described. This included a discussion of gyro filtering, a comparison of multiple candidate algorithms for finding angular acceleration, and a description of the Kalman Filter that was chosen. The transformation from MATLAB to C++ to Embedded realtime C is explained, with data comparisons between the different versions provided. 5.2 Conclusions Offline characterization can be used to improve control performance for autonomous spacecraft. Having accurate knowledge of important system parameters can lead to more efficient maneuvers. While characterizing mass properties "offline" is helpful, online estimation offers another level of fine control because of shifting parameters like fuel mass. This is even more helpful for drastic changes in mass properties caused by deploying extendable parts or docking with other vehicles. The CoM tests performed do serve a purpose, but two non-trivial error sources exist: the play in the mount for the load cell and the effect of the liquid fuel. The 0.5mm play in the mounting configuration is unavoidable with the available manufacturing tolerances. While the fuel mass shouldn't affect CoM measurements while statically mounted to the load cell, it can change the CoM by a factor of 1 or more when in motion. The inertia measurements proved more robust, as all the error sources were resolved to around 1% or less of the measured value. Ideally, the absolute thruster latency would be known so that the controller and mass ID algorithm could account for the "lost" impulse. Knowing only that the delays are similar does still help with centering pulses in the PWM routine. The results from the multiple thruster pressure drop tests can help in future characterization. Since the effect seems to be independent of thruster location, a simple model should suffice. The gyro-based mass property identification algorithm was validated against CAD and empirical values with test data taken aboard the RGA. A Kalman Filter estimator for angular acceleration was proven to be the best routine. The mass ID algorithm was proven to function in an online implementation, allowing for real-time controller adjustments. Future missions can use this technology to continually update plant models and allow for tighter control. Not only could they benefit from being able to track changing mass properties due to fuel depletion and other dynamic effects, but algorithms like these can also help compensate for poorly measured or rough system parameters. Better plant knowledge and tighter control can have effects as minor as marginally improving fuel efficiency and as major as saving a mission from failure, and has applicability to any and all space vehicles. 5.3 Future Work Recommendations for future work are as follows: * Integrate accelerometers into the mass property identification algorithm either as a way to check thruster strengths or to estimate mass change from fuel depletion. Since the accelerometers are not at the CoM, there also might be redundant information about the angular rate that could be fused with gyro data. * Perform online mass ID tests with 2 SPHERES satellites docked. Both vehicles could provide independent estimates using their own gyros. Care would have to be taken to ensure there is no plume impingement and that both satellites are aware of all thruster commands. * Restrict mass property ID to favorable maneuvers. This might be accomplished by assigning a signal-to-noise ratio threshold for CoM and inertia estimation, dependent on the commanded thruster profile. This could include a dynamically changing A matrix to minimize any singularity distortions. * Account for fuel slosh in the algorithm. While deemed mostly negligible, it may be possible to excite a mode along the long dimension of the fuel tank, causing a greater disturbance. Including a model of how the fuel slosh should affect gyro readings as a function of how much fuel mass remains could improve results. Bibliography [1] Blanc-Paques, P., "Thruster Calibration for the SPHERES Spacecraft Formation Flight Testbed," Master's Thesis, MIT, 2005 [2] Bloomberg, J.J., Layne, C.S., McDonald, P.V., Peters, B.T., Huebner, W.P., Reschke, M.F., Berthoz, A., Glasauer, S., Newman, D.J. and D.K. Jackson, "Effects of Space Flight on Locomotor Control," in Extended Duration Orbiter Medical Project, Final Report 1989-1995, NASA SP-1999-534, NASA Johnson Space Center, 1999. [3] Boynton, R.; Wiener, K. "Mass properties measurement handbook - part 3". SA WE, Wichita, 1998 [4] Brown, R.G., and Hwang, P.Y., "Introduction to Random Signals and Applied Kalman Filtering," 1997. [5] Chen, A., "Propulsion System Characterization for the SPHERES Formation Flight and Docking Testbed," Master's Thesis, MIT, 2000. [6] Chung, S-J, Kong, E. M., Miller, D., "Dynamics and Control of Tethered Formation Flight Spacecraft Using the SPHERE Testbed." 2005 AIAA Guidance, Navigation and Control Conference, San Francisco, CA, August 2005. [7] Dahleh, M., Dahleh, M., and Verghese G., Lectures on Dynamic Systems and Control, 2002. [8] "Demonstration of Autonomous Rendezvous Technology www.nasa.gov/centers/marshall/news/backgrounds/factsheets.htm, [9] (DART)", September 2004 Enright, J., et al., "The SPHERES Guest Scientist Program: Collaborative Science on the ISS," IEEE Aerospace Conference, Big Sky, Montana, 2004 [10] Hilstad, M., "A Multi-Vehicle Testbed and Interface Framework for the Development and Verification of Separated Spacecraft Control Algorithms," Master's Thesis, MIT, 2002. [11] Kong, E. M., Hilstad, M., Nolet, S., Miller, D., "Development and verification of algorithms for spacecraft formation flight using the SPHERES testbed: application to TPF," SPIE Astronomical Telescope Conference 2004, Glasgow, Scotland, June 2004 [12] Kong, E.M., Saenz-Otero, A., Nolet, S., Berkovitz, D., Miller, D., "SPHERES as a Formation Flight Algorithm Development and Validation Testbed: Current Progress and Beyond." 2 nd International Symposium on Formation Flying Missions & Technologies, Washington, DC, September 2004 [13] Miller, David W., et al, SPHERES Critical Design Review, February 2002 [14] Nolet, S., Kong, E., Miller, D., "Design of an algorithm for autonomous docking with a freely tumbling target." SPIE Defense and Security Symposium 2005, Vol. 5799-16, Orlando, FL, March 2005 [15] Saenz-Otero, "The SPHERES Satellite Formation Flight Testbed: Design and Initial Control", Master's Thesis, MIT, 2000 [16] Saenz-Otero, A., Miller, D., "The SPHERES ISS Laboratory for Rendezvous and Formation Flight," 5 th InternationalESA Conference on Guidance,Navigation and ControlSystems, Frascati, Italy, October 2002 [17] Shkel, A., "Type I and Type II Micromachined Vibratory Gyros," IEEE, 2006 [18] Strang, G., "Introduction to Applied Mathematics," 1986. [19] Tillerson M., Breger L., and How J. P., "Distributed Coordination and Control of Formation Flying Spacecraft," IEEEAmericanControl Conference, June 2003 [20] Wilson, E., et al., "Motion-based System Identification and Fault Detection and Isolation Technologies for Thruster Controlled Spacecraft," JANNAF 3 rd Modeling and Simulation Joint Subcommittee Meeting, Colorado Springs, CO, December 2003 [21] Wilson, E., Lages, C., and Mah, R., "On-line gyro- based mass-property identification for thruster-controlled spacecraft using recursive least squares." 4 5 th IEEE InternationalMidwest Symposium on Circuits and Systems, Tulsa, Oklahoma, Aug 2002. [22] Wu, M., Lectures in "MEMS Physics and Design," UCLA Electrical Engineering course. Appendix A Tuning-Fork Gyroscopes A. 1 Background Physics The angular rate sensors used in SPHERES are BEI GyroChip II vibrating quartz tuningfork gyroscopes. They operate by taking advantage of the Coriolis force, measuring its effect with piezoelectric elements, and using that to determine rotation rate. The Coriolis force acts on rotating objects that are translating in a direction orthogonal to their spin. F, = 2mvxQl (A.1) Tuning-fork gyros like the GyroChip II drive one set of tines to wobble in a direction radially outward from the spin axis. When the gyro spins about this axis, the Coriolis force acts on the driven tines. Since these are always driven in opposite directions, the effect of the Coriolis force is an oscillating torque applied to the rest of the tuning fork. This causes the other set of tines to wobble in a direction orthogonal to both the drive axis and the spin axis. Figure A. 1 summarizes this process. Figure A.1 Tuning Fork Gyro This out-of-plane motion can be picked up by optics or, in the case of the GyroChip II, piezoelectric sensing. The sensed oscillation is then amplified and demodulated withreference to the drive signal to produce the output voltage, which is proportional to the angular rate. A.2 Modeling Rate Sensing A simplified model of tuning fork tines is two proof masses suspended by springs and dashpots, as shown in Figure A.2. The spring resistances in the x-axis and y-axis are kx and ky respectively, and the damping coefficients are bx and by. The simplified equations of motions can be described as: Ali = -bxi-kxx+M(Q2x+ 2x + 2y)+ Fx AM/ = -byj -kyy +M((2y - (A.2) 202i - Ox)+ F, Figure A.2 Gyro Sensing Model 1 The Q term is assumed to be 0 since we're considering small angular accelerations. The 2' term is also assumed negligible with respect to the other larger terms. F, = 0 since the drive force is along the x-axis only. MA.= -byj -kyy- 2MDvk (A.3) As a damped second order system, this can be expressed in terms of natural frequencies and damping ratios (which are assumed equal for both axes): j + 2;ao,,) +Wy + 22k0= 0 (A.4) The position of the proof masses on the x-axis is assumed to be +xo +a sin(odt), where x0 is the rest position and cod is the drive frequency. The velocity of the masses along the x-axis is: x = ac cos(odlt) (A.5) Assuming that the drive frequency and natural frequency are equivalent, the equation of motion along the y-axis becomes: j + 2g.cwy + ouy + 22cawo cos(ot) = 0 The solution to this second ordinary differential equation (ODE) is sin(ao)t). The constants a, Wc, and ; are known or calibrated and y is sensed, y = -- which allows solving for Q2. deflection, A.3 order (A.6) Q = a If the gyroscope measures just the amplitude of the y- y. Application to SPHERES In this simplified model, the drive frequency and sense frequency are exactly the same but in practice, this is rarely the case. The natural frequency of a vibrating structure gyroscope is a function of its geometry and mass distribution. Even if it were possible to match both the drive and sense frequency to the natural frequency, the sensing elements are often highly sensitive to temperature. Small changes in temperature can move the resonant peaks of the drive and sense tines of the tuning fork far enough away to drastically affect signal-to-noise ratio (SNR). These gyroscopes are typically tuned so that they are driven at their natural frequency, but usually need force feedback to ensure consistent amplitude oscillation along the drive axis. Figure A.3 is an FFT of gyroscope data sampled at 50 Hz from a test on MIT's float table. n r1 .. ls6 061 a 'UMS 1.'r ian .L (iSM a ~ · ------------- - --- · ·- -i-----·- · -- :--··;--·-- is Figure A.3 12 Hz Gyro Noise Originally, this 11.45 Hz noise was assumed to be vibration from the building propagating through the float table. During more recent tests aboard the RGA where the sampling rate was 100 Hz, a 38.33 Hz noise signal was observed instead (shown in Figure A.4). After later sampling the gyro at 1 kHz and also performing an FFT of the analog signal directly from the gyro output pins, it was determined that these noise spikes were merely aliasing of noise at 338 Hz. alB2 r f Xi a' UM rj ," a I .e s r' a r *r " *i rt1 acvis I * r·~= " i~~ r .* vr s h" 0 "% 9 ""lril+ `4 ~·i " i ° "* r tli i r· * * r ?. · n 1 ' r Figure A.4 38 Hz Gyro Noise From contacting the manufacturer, it was determined that this noise at 338 Hz was a result of a difference between the drive and sense frequencies of the gyro. As explained above, this means that the input and output resonances are different, causing the difference between the frequencies to pass through the demodulation as noise. Since this noise is very frequency-specific, filtering it out has been trivial. 98 Appendix B Fuel Slosh Analysis B. 1 Propellant Properties The propellant used to maneuver the SPHERES satellites is gaseous C02. When stored in the onboard tank, it is in a mixed-phase state with liquid and gas at 860 psi (vapor pressure of C02) and at room temperature. The volume containing the propellant remains constant, and the temperature is assumed constant as well (there is no external heat source, only the ambient air around the tank). As gaseous C02 is expelled from the tank, some of the liquid vaporizes to reestablish phase equilibrium. Nominal fuel mass for a "full" tank is 172g. The C02 exists in dual-phase until approximately 28g remains in the tank. After this point, the tank pressure starts to drop as more gas is expelled. Since the supply pressure changes significantly during this period, the regulator is unable to maintain a stable system pressure of 35 psi downstream and the resultant force provided by the thrusters is unreliable. Because of this, navigation experiments are usually concluded at or shortly after this point. This means that a high percentage of SPHERES tests are conducted with liquid-phase C02 present in the fuel tank, and are subject to the effects of fuel slosh. B.2 Fuel Slosh on SPHERES Fuel slosh has been shown to have a negligible effect on online mass property estimation for SPHERES when compared to other noise sources such as thruster variability and gyro ringing. Tests conducted by NASA AMES/Intellization produced these values for CM with a full tank (maximum slosh) and a near empty tank (no slosh): CM (empty) = [-0.000015665375 -0.000821387572 0.003081773236] CM (full) = [-0.000054495248 -0.000810686405 0.000244119942 ] Figure B.1 is an example of gyro data gathered during a 3 DOF SPHERES test on the float table at MIT that exhibits some evidence of fuel slosh. From the figure, the amplitude of the disturbance is greater and the frequency smaller when the SPHERES satellite is rotating slower. The angular rate of the satellite is directly proportional to the applied rotational impulse: I r = Jo). Hence, for this model we treat the applied rotational impulse as the input and the resulting sinusoidal disturbance as the output. 100 I Filtered Z-axis Gyro .. 0.2 - 01 Fi . "ue ... iO.u .... ..... :3 -0.6 . . ......... ..... ... : ....... .. ...... ................ . . ........... ..... • time [sec] Figure B.I Observed Fuel Slosh in Gyro Data B.3 Modeling Fuel Slosh Fuel slosh is known to be a non-linear phenomenon, but for the purposes of understanding it and recognizing its effect, a simplified linear model will suffice. Figure B.2 depicts a simple representation of fuel slosh: a solid mass M connected to each side of the tank by a spring and a dashpot, constrained to one DOF. Figure B.2 Linearized Fuel Slosh Model 101 Since the mirror image sides do not add any mathematical significance, the model will be further simplified to: X Figure B,3 Simplified Fuel Slosh Model The linear motion of this mass will represent the sloshing of liquid C02, which in turn affects the angular velocity of the satellite. This system acts as a damped harmonic oscillator, which satisfies the second order differential equation: b k 2+x + - x = u(t) MM where u(t) is the driving force. The states in this system are X = Sk M b .+I u(t) M 102 (B.1) ]so (B.2) oi] Y=[1 J (B.3) This is a state-space representation with A, B, C, and D defined as: 0 A= 1 k b B=M[ B= 0 [01 C=[1 0] (B.4) D=0 A value of 0.05kg was used for M, while k and b were manipulated so the output disturbance resembled the plotted gyro data (k=0.3, b=0.001). For this analysis, just the shape of the output is important, not the numerical scale. These values lead to a system transfer function of: H(s)= 2 s2 1 +0.02s+6 (B.5) which is a complex pair of poles at -0.01 + 2.45i. B.4 Modeling Input Now with the model characterized, the next step is to see its response to a rotational impulse input, modeled as a unit height rectangle impulse (Figure B.4). 103 Rotational Impulse Input 2 sec 4 sec .... .................................. ....... ..... .... 038 0.6 .. .. ... .... .... 0.4 0.2 0 ' -" 0 1000 1500 sec/100 2000 2500 3000 Figure B.4 Fuel Slosh Model Input In order to do this, the fuel slosh transfer function must be discretized. Because of the expected input, a zero-order hold method was used for discretization, along with a sample time of 0.01. H(z)= B.5 4.999e-' z + 4.999e - 5 z2 -1.999z +0.9998 Results Figure B.5 shows the responses to input impulses of width 2 sec and 4 sec. 104 CB.6) Fuel Slosh Impulse Response 0 S00 1000 1500 sec/l00 2000 2500 3000 Figure B.5 Model Output As expected, the amplitude of the response increases with the width of the input impulse. However, unlike the sample fuel slosh data the output frequency remains unchanged, which is to be expected from an LTI model (the mass M will always oscillate at the natural frequency of the complex pair of poles). The discrepancy is most likely caused by the true nonlinearity of the system. According to the Department of Transportation guidelines for the safe packaging of liquid C02, no more than 68% of the tank may be filled with liquid. The worst-case scenario for fuel slosh affecting CoM and Inertia would be a full tank (172 g) with all the liquid C02 at the bottom of the tank (Z-axis has highest moment arm potential for fuel). Under these conditions, CoM values are highly unreliable (200%-1600% change). The CoM change in the X and Y-axes is on the order of typical values while the change in the 105 Z-axis is over 5 times as large. Inertia is less affected, with the worst-case percentage difference being 4.5% around the X or Y-axis. Table B.1 Worst-case Effects of Fuel Slosh on Mass Properties 106 Appendix C SPHERES Satellite Properties C.1 CoM Offset CoM offset in mm (from batch LS of mass property ID). or is about 0.08 in X and Y, 0.4 in Z. 0.5125 0.4549 -1.2502 -1.241 2.9484 0.8691 -1.2069 2.74191 0.63431 -1.6191 3.5379 0.7879 -1.3827 0.108 0.8115 -1.2044 -0.0985 0.5767 -1.6296 0.6975 0.7303 2.4472 0.4621 -1.3613 3.1517 -1.3824 -0.3932 0.4045 -1.3294 0.3113 107 C.2 Moment of Inertia Inertia in kg-m^2 (from batch LS of mass property ID). a is about 0.002. 0.0275 0.024517 0.0242 0.0235 0.021529 0.0214 0.0194 0.0212 0.020309 -8.4E-05 0.000108 -8.2E-06 0.000014 0.000157 0.000149 0.00029 1.23E-05 -0.00022 C.3 0.023 0.0242 0.0242 0.021529 0.0212 0.0214 0.0001 -0.00022 -0.0003 0 0 0.0001 Thrust Strengths U.1UbS U.UU;3U U.1Ubb U.UUbU U.11 b U.UU44 U.1111 U.UUb3 0.1302 0.0023 0.1117 0.0018 0.1096 0.0031 0.1120 0.0023 0.1108 0.0032 0.1221 0.0063 0.1131 0.0090 0.1164 0.0097 0.1195 0.0098 0.1108 0.0080 0.1299 0.0042 0.1120 0.0070 0.1097 0.0057 0.1149 0.0074 0.1142 0.0049 0.1139 0.0047 0.1120 0.0025 0.1060 0.0097 0.1224 0.0026 0.1123 0.0075 0.1244 0.0056 0.1116 0.0025 0.1048 0.0070 0.1204 0.0014 0.1105 0.0050 0.1335 0.0040 0.1117 0.0043 0.1051 0.0050 0.1228 0.0075 0.1160 0.0060 0.1302 0.0027 0.1151 0.0053 0.1128 0.0055 0.1191 0.0071 0.1130 0.0047 0.1284 0.0059 0.1170 0.0078 0.1184 0.0083 0.1220 0.0089 0.1135 0.0066 0.1316 0.0051 0.1137 0.0064 0.1160 0.0059 0.1194 0.0074 0.1138 0.0047 0.1256 0.0056 0.1058 0.0022 0.1089 0.0093 0.1225 0.0023 0.1068 0.0073 0.1095 0.0050 0.1113 0.0026 0.1041 0.0072 0.1127 0.0021 0.1079 0.0063 U.133b U.UU44 108 C.4 Thrust Directions 0.9982 0.9985 0.0014 0.0017 -0.0221 -0.0008 0.0471 0.0255 0.0249 -0.0248 0.0214 0.0438 0.0589 -0.0176 0.0330 0.0128 0.9961 0.9994 0.0044 0.0002 0.0324 0.0036 0.0506 0.0268 0.9988 0.9995 0.0009 0.0005 -0.0061 -0.0086 0.0299 0.0293 0.0356 -0.0018 0.0156 0.0095 0.0126 -0.0209 -0.0011 -0.0076 -0.9996 -0.9989 0.0391 -0.0292 0.0085 -0.0046 0.0278 0.0126 0.0168 0.0067 0.0003 0.0005 0.0040 0.0055 0.0064 0.0052 0.9994 0.9995 0.0244 -0.0278 0.0162 0.0374 -0.9989 -0.9992 0.0598 0.0075 0.0005 0.0002 0.0178 0.0087 0.0096 0.0059 0.0003 0.0004 0.0085 0.0090 0.0104 -0.0149 0.9994 0.9995 0.0137 -0.0166 0.0219 0.0239 -0.9981 -0.9999 0.0106 0.0119 0.0009 0.0002 0.0153 00227 00102 00117 00005 00001 0.9996 0.9986 0.0004 0.0009 -0.0091 -0.0247 0.0164 0.0152 0.0171 -0.0405 0.0166 0.0187 0.0100 -0.0393 0.0084 0.0252 0.0119 0.0243 0.9995 0.9988 -0.0087 0.0006 0.0003 0.0320 0.0009 0.0125 0.9992 0.0189 0.0228 0.0009 0.9990 0.0010 -0.0331 0.0227 0.0196 0.0123 0.0107 -0.0224 -0.9986 -0.9984 0.0418 -0.0194 0.0041 -0.0018 0.0075 0.0101 0.0010 0.0014 0.0107 0.0124 0.0069 0.0070 0.0337 -0.0121 -0.0077 -0.0095 -0.9990 -0.9997 0.0603 -0.0297 0.0224 0.0224 0.0249 0.0365 0.0005 0.0002 0.0070 0.0218 0.9991 0.9994 0.0445 -0.0367 0.0088 0.0044 -0.9981 -0.9994 0.0010 0.0005 0.0179 0.0225 00060 0_0085 0_0004 00009 -0.0166 -0.9988 -0.9983 0.0078 -0.0310 0.0204 0.0010 0.0012 0.0411 0.0283 -0.0835 0.0134 0.0162 -0.9990 -0.9990 0.0309 0.0116 0.0124 0.0009 0.0011 0.9957 0.0067 -0.0353 -0.0158 -0.0003 0.0033 0.0463 0.0428 0.0086 0.0181 0.9983 0.0264 -0.0455 -0.0128 -0.0136 -0.9996 -0.9988 0.0005 0.0209 0.0184 0.0272 0.0176 0.0005 0.0009 -0.0351 0.9992 0.9985 0.0264 -0.0660 0.0020 0.0149 0.0132 0.0012 0.0008 0.0156 0.0114 0.0093 0.0102 -0.0451 0.0085 -0.0212 0.9991 0.9975 0.0092 -0.0408 0.0032 0.0244 0.0108 0.0009 0.0005 0.0264 0.0224 -0.0258 0.0083 0.0132 0.0259 0.0426 -0.0462 0.0743 0.0381 -0.9961 -0.9979 0.0092 0.0024 0.0023 -0.0448 -0.0279 0.0231 0.0273 0.0233 0.0109 0.0090 -0.9995 -0.9986 0.0159 -0.0335 0.0005 0.0009 0.0236 0.0281 -0.0114 0.0079 -0.9992 -0.9988 0.0098 0.0122 0.0007 0.0007 0.9988 0.9987 0.0229 -0.0669 -0.0219 -0.0036 -0.9992 -0.9991 0.0090 -0.0450 -0.0108 0.0136 0.0005 0.0003 0.0120 0.0051 0.0223 0.0136 0.0003 0.0007 0.0385 0.0281 0.0070 0.0103 -0.0108 -0.0276 0.9993 0.9975 0.0272 -0.0662 0.0101 0.0110 -0.9989 -0.9985 0.0352 -0.0334 0.0100 0.0075 0.0003 0.0006 0.0086 0.0047 0.0258 0.0130 0.0010 0.0013 0.0265 0.0189 0.0452 -0.0406 -0.0202 -0.0225 0.9991 0.9977 0.0003 -0.0255 -0.0250 -0.0089 -0.9990 -0.9991 0.0136 0.0064 0.0214 0.0086 0.0007 0.0003 0.0303 0.0296 0.0087 0.0089 0.0011 0.0006 109 Appendix D MATLAB Code D. 1 Mass Property ID code (massidkcl.m) This is the high-level function call for the mass property ID algorithm. function [cm l, Il] = massidkcl(start,finish); load('kc test.mat); disp('Initializing...'); % SYSTEM PARAMETERS- Initialize system parametersdepending on which SPHERE was used. % ------------------------------------------------------------------------------ ifSph Fnom = [0.13364, 0.13023, 0.12209, 0.12994, 0.11388, 0.12436, 0.13351, 0.13018, 0.1284, 0.13159, 0.12563, 0.10954]; D = [ 0.99824, 0.99853, 0.05895, -0.00176, 0.01074, -0.02244, -0.99856, -0.99845, 0.04179, -0.01939, 0.00412, -0.00184;... -0.02206, -0.00082, 0.99608, 0.99944, 0.03370, -0.01207, -0.00774, -0.00946, 0.99902, -0.99971, 0.06026, -0.02973;... 110 0.02491, -0.02481, 0.03236, 0.00365, 0.99913, 0.99941, 0.04447, -0.03675, 0.00876, 0.00438, -0.99814, -0.99936]; Lnom = 0.01 .* [-5.16, -5.16, 9.65, -9.65, 0, 0, 5.16, 5.16, 9.65, -9.65, 0, 0;... 0, 0, -5.16, -5.16, 9.65, -9.65, 0, 0, 5.16, 5.16, 9.65, -9.65;... 9.65, -9.65, 0, 0, -5.16, -5.16, 9.65, -9.65, 0, 0, 5.16, 5.16];%m 9%I_nom = 0. 0335;% kg.mA2, for 2-D table experiments Inom = [0.0229, 0.0000965, -0.000293; 0.0000965, 0.0242, -0.0000311; -0.000293, 0.0000311, 0.0214]; cm_nom = [0;0;0]; bias = [2055; 2079; 2051]; elseifSph == 2 Fnom = [0.11808, 0.11868, 0.11885, 0.11984, 0.11590, 0.11830, 0.11843, 0.12168, 0.11953, 0.11874, 0.11630, 0.11917]; %CalibratedPressureGauge D = [0.99880, 0.99951, 0.01260, -0.02093, -0.00105, -0.00764, -0.99962, -0.99890, 0.03911, -0.02922, 0.00846, -0.00464;... -0.00614, -0.00857, 0.99944, 0.99953, 0.02440, -0.02778, 0.01615, 0.03738, 0.99894, -0.99921, 0.05980, 0.00753;... 0.03561, -0.00181, 0.01040, -0.01492, 0.99941, 0.99953, 0.01372,-0.01662, 0.02191, 0.02388, -0.99812, -0.99991]; Lnom - 0.01 .*[-5.16, -5.16, 9.65, -9.65, 0, 0, 5.16, 5.16, 9.65, -9.65, 0, 0;... 0, 0, -5.16, -5.16, 9.65, -9.65, 0, 0, 5.16, 5.16, 9.65, -9.65;... 9.65, -9.65, 0, 0, -5.16, -5.16, 9.65, -9.65, 0, 0, 5.16, 5.16];% m %I_nom = 0. 0335;% kg.mA2, for table experiments I nom = [0.0229, 0.0000965, -0.000293; 0.0000965, 0.0242, -0.0000311; -0.000293, 0.0000311, 0.0214]; cm_nom = [0;0;0]; bias = [2077; 2070; 2058]; elseifSph == 3 Fnom = [0.10648965825739, 0.10958074078082, 0.11639991410096, 0.10972026118392, 0.10595235083091, 0.10476246795815, 0.10506642798593, 0.11278450399743, 0.11835632534687, 0.11600639008945, 0.10888722593497, 0.10413145765793]; D = [0.99824, 0.99833, 0.00140, -0.00010, -0.00308, -0.00958, -0.99861, -0.99757, 0.02145, -0.04382, -0.00456, 0.00586;... 0.01498, -0.01245, 0.99974, 0.99962, 0.04179, -0.02819, 0.02828, 0.02149, 0.99934, -0.99886, 0.04434, -0.02649;... 0.03182, -0.04666, -0.00102, 0.00158, 0.99907, 0.99953, 0.04307, -0.05952,0.01566, 0.01221, -0.99897, -0.99946]; 111 Lnom = 0.01 .*[-5.16, -5.16, 9.65, -9.65, 0, 0, 5.16, 5.16, 9.65, -9.65, 0, 0;... 0, 0,-5.16, -5.16, 9.65, -9.65, 0, 0,5.16, 5.16, 9.65, -9.65;... 9.65, -9.65, 0, 0, -5.16, -5.16, 9.65, -9.65, 0, 0, 5.16, 5.16];% m % Inom = 0.0335; % kg.mA2, for table experiments I nom = [0.0229, 0.0000965, -0.000293; 0.0000965, 0.0242, -0.0000311; -0.000293, 0.0000311, 0.0214]; cm nom = [O;0;0]; bias = [2055; 2061; 2053]; end; % % TESTPARAMETERS % % ---------------------------------------- ----------------------------- rate raw = gyro; % Convert rate %conversion = 1713.14;% m V/(rad/s) conversion = 1412. 79; % counts/(rad/s) for n = 1:length(rate_raw) rate(:, n) = (rate raw(:,n) - bias) ./ conversion;% rad/s end; % Interpolate missing telemetryfrom droppedcomm packets disp('Interpolatemissing data.... ); [time, rate, accel, thrusters] = int(time, rate, accel,thrusters); % Findbeginnings/endsoffirings indtemp =find(diff(thrusters)); window = 1; if mod(length(indtemp),2) == 1 indtemp = [indtemp' length(thrusters)]; end; % T is the binary version of "thrusters" T= de2bi(thrusters,12); % Filter interpolatedgyro signal disp('Filtergyro readings....) rate = gyrofiltvar(rate,time, 50, 2); % updateind is a vector with the indices of all the updates (i.e. which time points actually have an associatedw dot estimate) updateind=find(thrusters); L = Lnom - cm nom *ones(1,12); 112 disp('EstimateAngular Acceleration....); wdotkalman %%%%%%%%%%%%%%%%%%%%%% % Batch Least Squares % 0%%%%%%%%%%°1%% %%%%%%% disp('BatchLS.... ); batchLS; % Batch Results: cm] = cm(:,end) HI = I_mat{end) %%%%%%%%%%%%%%%%%%%%%%%%%% % Recursive Least Squares % %%%%%%%%%%%%%%%%%%%%%%%%%%%% disp('RecursiveLS....'); recursiveLS; %%%%%%%%%%%%% % Plots % %%%%%%%%%%%%% %%OMITTED%% D.2 Interpolation Scheme (int.m) This file is the first called by massid_kc.m. It fills in the missing data gaps with a linear interpolation. function [inttime, intgyro, intaccel,intthrusters]= int(time, gyro, accel, thrusters); b =find(diff(time) == 0); dt = floor(mean(diff(time(1:50)))); forj = J:length(b) index = length(b) -j + 1; time(b(index)+1) = []; gyro(,b(index)+1) = []; accel(.',b(index)+1) = []; thrusters(b(index)+1) = []; 113 end; x = time; a =find(diff(time) - I *dt); for i = 1:3 y = gyro(i,:); xi = []; forj = 1:length(a) xi = [xi time(a(J))+1*dt :dt: time(a)(j+l)-l]; end; yi = interpl(x, y, xi, 'linear"); A = [[xxi]' [yyi']; B = sortrows(A,1); intgyro(i,.) = B(:, 2)'; end; inttime = B(:,1)'; y = thrusters; yi = interpl(x,y, xi, 'nearest); C = [[xxi]'[y yi']; D = sortrows(C,1); intthrusters = D(-,2); intaccel = accel; D.3 Gyro Filter (gyrofiltvar.m) This file is called by massid_kcl.m to filter the gyros after missing data points are interpolated. functionfiltered_data= gyrofiltvar(gyro,time, freq, ord) freq = freq*2*pi; 114 s =tf('s'); filter cont = freqAord/(s+freq)^ord; dt = (time(2)-time(1))/l000; filter_disc = c2d(ftltercont,dt ,'tustin); filter struct = get(filter disc); b =filterstruct.num{1}; a =filter struct.den{1}; filtered_data(],.) =filtfilt(b, a, gyro(1,:)); filtered_data(2,.) = fltfilt(b, a, gyro(2,:)); filtered data(3,:) = filtfilt(b, a, gyro(3, )); D.4 Angular Acceleration Estimator (wdotkalman.m) This script is called after interpolating and filtering to start the Kalman Filter for angular acceleration estimation. dt = floor(mean(diff(time(1:50))))/1000; % Kalman FilterInitializations phi = 1; Fk = (Fnom-sum(T(updateind(1),:))*0.0106). * T(updateind(1),:); x minus{1} = inv(I nom) *cross(L,D)*Fk'; P inv_ minus{1} = 2*eye(3,3); Q = zeros(3,3); H{1} = diag(zeros(1,3)); R = le-7 * [9.5661 0; 0 2.7365 0; 0 0 2.3044]; bias] = rate(:,updateind(1) - 1); ifdt < 5/1000 updateind(1:10)= []; %bias] = mean(rate(:,1:updateind(1)-10),2); end; % StartKalman Filter j=1 *dt, k=l; while k< length(updateind) 115 H{k) = diag(fjjj])*1; G =find(T(updateind(k),:)); P inv{k} = Pinvminusfk} + H{k}'*inv(R)*H{k}; P{k} = ivPinv(Pinv{k); {k}k = Pk} *H{k} '*inv(R) ; xfk} = x minusfk} + Kk} *(rate(:,updateind(k))-biasl - H{k} *x minus k}); xminus k+1} = phi*xfk}; P_minusk+1} = phi*P{k} *phi'+ Q; P invminusfk+1} = inv(P minus{k+1}); if -(thrusters(updateind(k+1)) == thrusters(updateind(k))) Fk = (Fnom-sum(T(updateind(k+1),)) *0.0106) . * T(updateind(k+ ),), j = 0; xminus lk+ 1) = inv(I nom) *cross(L,D)*Fk'; P inv minus k+1} = 2*eye(3,3); bias] = rate(., updateind(k+1) - 1); ifdt < 5/1000 updateind(k+ :k+11) = [] end; end; j=j+]*dt; k=k+l; end; % Extract angularaccelerationand associatedstandarddeviation for i = 1:length(x) acc(.,i) = x{i}; acc xvar(i) = P{i}(1,1) ; acc_yvar(i) = P{i}(2,2); acczvar(i) = P{i}(3,3); acc_Sigmax(i) = sqrt(acc xvar(i)); accSigmay(i) = sqrt(accyvar(i)); acc Sigmaz(i) = sqrt(acc zvar(i)); R acc{i} = diag(diag(P{i})); end; anew = zeros(3, length(time)); for i = 1:length(x) anew (.,updateind(i)) = x{i}; end; 116 % Clear local variablessince this is a script, not afunction clearH G x accxvar accyvar acczvar acc_Sigmay acc_Sigmaz P inyvminus Pinv P D.5 Batch Mass Property ID (batchLS.m) This script called after angular acceleration has been calculated. % estI holds information about which axes have been excited. This allows simplification ofLS equations ifnecessaryfor well-conditionedQ cc=]; estI = zeros(1,3); for bb=l:ength(updateind) if thrusters(updateind(bb))> 0 if (T(updateind(bb),5) T(updateind(bb),6) T(updateind(bb),l) I T(updateind(bb),12)) estI(1,1) = 1; end; if(T(updateind(bb),1) T(updateind(bb),2) T(updateind(bb),7) T(updateind(bb),8)) estI(1,2) = 1; end; if (T(updateind(bb),3) T(updateind(bb),4) T(updateind(bb),9) T(updateind(bb),10)) estI(1, 3) = 1; end; Fk = (Fnom-sum(T(updateind(bb),:))*0.0106) .* T(updateind(bb),:); Ck = D*Fk'; Ak = cross(L,D) *Fk'; estldec = bi2de(estI) All switch statements are uncommented if we are using estI to simplify equations. switch estIdec case bi2de([1 0 0]) Al(cc:cc+2,.) =inv(I nom) *[ 0 -Ck(3);... Ck(3) 0 ;... -Ck(2) Ck(])]; bl(cc:cc+2,.) = anew(:,updateind(bb))- inv(I nom) *cross(Lnom,D)*Fk'; 117 0/o 0/o A2(cc:cc+2,.) = [Ak(1) Ak(2) Ak(3) ;... o Ak(1) 0 o o Ak(1)], ;... b2(cc:cc+2,:) = anew(:,updateind(bb)); case bi2de([0 10]) Al (cc:cc+2,.) = inv(I nom) *[-Ck(3) Ck(2);... o -Ck(]);... Ck (1)0 ]; 0/o bl(cc:cc+2,:) = anew(:, updateind(bb)) - inv(I nonm) *cross(Lnom,D)*Fk'; A2(cc:cc+2,:) = [0 Ak(2) 0 Ak(2) Ak(1) Ak(3) ;... O 0 Ak(2)]; 0/o 0/6 b2(cc:cc+2,:) = anew(:,updateind(bb)); case bi2de([O 0 1]) A (cc:cc+2,.) = inv(I nom) *[ 0 Ck(2);... Ck(3) -Ck(1);... 0/6 -Ck(2) 0 ], bl(cc:cc+2,:) = anew (:, updateind(bb)) - inv(I non) *cross(Lnom,D)*Fk'; A2(cc:cc+2,:) = [0 Ak(3) 0 O 0 Ak(3) ;... 0/o Ak(3) Ak(1) Ak(2)]; 9~o b2(cc:cc+2,:) = anew(:, updateind(bb)); 9/o case bi2de([1 1 0]) Al(cc:cc+2,) = inv(J nom)*[ 0 -Ck(3) Ck(2);... Ck(3) 0 -Ck(1);... -Ck(2) Ck(1) 0 ]; 0/o 0/o 0/o bl (cc:cc+2,:) = anew(:,updateind(bb)) - inv(I nom) *cross(Lnom,D)*Fk; A2(cc:cc+2,:) = [Ak(1) 0 Ak(2) Ak(3) 0 ;... o Ak(2) Ak(1) 0 o o0 0 Ak(3) ;... Ak(l) Ak(2)]; b2(cc:cc+2,.) = anew(:,updateind(bb)); case bi2de([1 0 1]) Al(cc:cc+2,:) = inv(I nom)*[ 0 -Ck(3) Ck(2);... Ck(3) 0 -Ck(l);... -Ck(2) Ck(1) 0 1; 00 0/0 0/o 0/6 b](cc:cc+2,:) = anew(:, updateind(bb)) - inv(Inom) *cross(Lnom,D)*Fk'; A2(cc:cc+ 2,:) = [Ak(1) 0 Ak(2) Ak(3) 0 ;... 0 0 Ak(1) 0 Ak(3) ;... 0 Ak(3) 0 Ak(1) Ak(2)]; b2(cc:cc+2,.) = anew(:,updateind(bb)); case bi2de([0 1 1rJ7 -) 00 Al(cc:cc+2,:) inv(I nom) *[ 0 -Ck(3) Ck(2);... Ck(3) 0 -Ck(1);... 0/o 0/o -Ck(2) Ck(1) 0 ]; bl(cc:cc+2,.) anew(:, updateind(bb)) - inv(Inom) *cross(Lnom,D)*Fk'; A2(cc:cc+2,:) S[0 0 Ak(2) Ak(3) O ;... 118 Ak(2) 0 Ak(1) 0 Ak(3) ;... 0 Ak(3) 0 Ak(1) Ak(2)]; % % b2(cc:cc+2,:) = anew(:,updateind(bb)); case bi2de([l 1])% FULL ORDER CASE Al(cc:cc+2,:) = inv(I nom) *[ 0 -Ck(3) Ck(2);... % % Ck(3) 0 -Ck(l);... -Ck(2) Ck(J) 0 ]; bl(cc:cc+2,:) = anew(:,updateind(bb)) - inv(I nom) *cross(Lnom,D)*Fk'; A2(cc:cc+2,.) = [Ak(1) 0 0 Ak(2) Ak(3) 0 ;... o Ak(2) 0 Ak(1) 0 Ak(3) ;... o %o % % % 0 Ak(3) 0 Ak(1) Ak(2)]; b2(cc:cc+2,:) = anew(:,updateind(bb)); case bi2de([0 0 0]) disp('Error) keyboard; end cc=cc+3; % ID Estimatesindexed with thrusteron time (*NO* gaps between thrusterfirings) ifbb = length(updateind)% Only taking batch after all datais included cm(:,(cc-J)/3) = inv(AI'*A1) *Al'*bl; I inv(.;,(cc-1)/3) = inv(A2 '*A22) *A2'*b2; I_inv_mat (cc-1) 3} = [linv(1,(cc-1)/3) I inv(4, (cc-1)/3) I_inv(5, (cc-1)/3);... I_inv(4, (cc-1)/3) I inv(2, (cc-1)/3) l_inv(6,(cc-1)/3);... I inv(5, (cc-1)/3) I inv(6,(cc-1)/3) I_inv(3, (cc-1)/3)]; Imat{(cc-1)/3} end, end; end; D.6 = inv(Iinvmat{(cc-1)/3}); Recursive Mass Property ID (recursiveLS.m) This is the last script call executed from massidkc.m and it is where the recursive equations are exercised. 119 % Batch overfirst twofirings cc 1; % used to index rows ofA and b count = 1; % how far we've gotten through our w dot updates stop_batch = indtemp(3)+1; % thruster values change 4 times over two firings! L = Lnom - cm nom *ones(1,12); estI = zeros(1,3); Rbatch = []; while time(updateind(count)) < time(stop batch -floor(window/2)-1) if (T(updateind(count),5) T(updateind(count),6) T(updateind(count),11) T(updateind(count),12)) estI(1, 1) = 1; end; if (T(updateind(count),1) T(updateind(count),2) T(updateind(count),7) T(updateind(count),8)) estI(1,2) = 1; end; if (T(updateind(count),3) I T(updateind(count),4) T(updateind(count),9) T(updateind(count),10)) estI(1,3) = 1; end; Fk = (Fnom-sum(T(updateind(count),.))*0. 0106) .* T(updateind(count),.); % This takes into account thrust drop with multiple thrustersopen Ckrls = D*Fk'; Akrls = cross(L,D)*Fk'; estIdec = bi2de(estl); switch estIdec case bi2de([1 0 0]) Alrls(cc:cc+2,:) = inv(I nom) *[ 0 -Ckrls(3) ;... Ckrls(3) 0 -Ckrls(2) Ckrls(1)]; blrls(cc:cc+2,:)= anew (:,updateind(count)) - inv(I_nom) *cross(Lnom,D)*Fk'; A2rls(cc:cc+2,:) =[Akrls(1) Akrls(2) Akrls(3) ;... 0 Akrls(1) 0 ;... 0 0 Akrls(1)]; b2rls(cc:cc+2,:) = anew (, updateind(count)); case bi2de([O 1 0]) A lrls(cc:cc+2,.) inv(I nom) *[-Ckrls(3)Ckrls(2);... o -Ckrls(1);... Ckrls(1) 0 ]; blrls(cc:cc+2,.:) anew(:, updateind(count)) - inv(Inom) *cross(Lnom,D)*Fk'; Akrls(2) 0 A2rls(cc:cc+2,:) [0 Akrls(2) Akrls(1) Akrls(3) ;... 120 0 0 Akrls(2)]; b2rls(cc:cc+2,:) = anew(:,updateind(count)); case bi2de([0 Orl) Alrls(cc:cc+2,.) = inv(I nom) *[ 0 Ckrls(2);... Ckrls(3) -Ckrls(l);... -Ckrls(2) 0 ]; blrls(cc:cc+2,.) = anew (., updateind(count))- inv(I nom) *cross(Lnom,D)*Fk'; A2rls(cc:cc+2,.) = [0 Akrls(3) 0 0 0 Akrls(3) ;... Akrls(3) Akrls(1) Akrls(2)]; b2rls(cc:cc+2,. - anew(-, updateind(count)); case bi2de([1 1 0]) Alrls(cc:cc+2,.) - inv(I nom) *[ 0 -Ckrls(3) Ckrls(2);... Ckrls(3) 0 -Ckrls(]);... -Ckrls(2) Ckrls(i) 0 ]; blrls(cc:cc+ -2, ) = anew (:, updateind(count))- inv(I nom) *cross(Lnom,D)*Fk', A2rls(cc:cc-+2,.) [Akrls(1) 0 Akrls(2) Akrls(3) 0 ;... 0 Akrls(2) Akrls(1) 0 Akrls(3) ;... O 0 0 Akrlsrl) Akrls(2)]; b2rls(cc:cc+2,:) = anew(., updateind(count)); case bi2de([1 0 1]) A lrls(cc:cc-+2,.) = inv(I nor) *[ 0 -Ckrls(3) Ckrls(2);... Ckrls(3) 0 -Ckrls(1);... -Ckrls(2) Ckrls() 0 ]; blrls(cc:cc+2,.:) anew(., updateind(count)) - inv(I nom) *cross(Lnonm,D)*Fk'; A2rls(cc:cc-+2,) = [Akrls(1) 0 Akrls(2) Akrls(3) 0 0 0 Akrls(1) 0 Akrls(3) ;... o Akrls(3) 0 Akrls(1) Akrls(2)]; b2rls(cc:cc+2,:) = anew(:,updateind(count)); case bi2de([0 A lrls(cc:cc-+2,.') = inv(I nom) *[0 -Ckrls(3) Ckrls(2);... Ckrls(3) 0 -Ckrls(J);... -Ckrls(2) Ckrls(l) 0 ]; blrls(cc:cc- 2,:) = anew (.,updateind(count)) - inv(I nom) *cross(Lnom,D) *Fk'; A2rls(cc:cc-+2,.) = [0 0 Akrls(2) Akrls(3) 0 Akrls(2) 0 Akrls(l) 0 Akrls(3) ;... 0 Akrls(3) 0 Akrls(1) Akrls(2)]; b2rls(cc:cc+2,:) = anew(:, updateind(count)); case bi2de([] 1 1]) Alrls(cc:cc+2,.) =inv(I nom) *[ 0 -Ckrls(3) Ckrls(2);... Ckrls(3) 0 -Ckrls(1);... -Ckrls(2) Ckrls(1) 0 ]; blrls(cc:cc+2,:) anew (:,updateind(count))- inv( non) *cross(Lnom,D)*Fk'; A2rls(cc:cc+2,:) S[Akrls(1) 0 0 Akrls(2) Akrls(3) 0 0 Akrls(2) 0 Akrls(1) 0 Akrls(3) ;... 0 0 Akrls(3) 0 Akrls(1) Akrls(2)]; 121 b2rls(cc:cc+2,:)= anew(:,updateind(count)); % case bi2de([O 0 0]) % % disp('Error) keyboard; end; % cc=cc+3; Rbatch = diag([diag(R_batch);diag(Racc{count})]); count = count + 1, end; temp = (count); % Remember how far we got through w dot updates...we want to start our recursive where our batch left off % Initialstate/covarianceestimates: cm rls(:,l) = inv(A rls'*A rls) *Alrls'*blrls; Qcm inv{1} = Airls' * (inv(R batch)) * A rls; I inv rls(:,1)= inv(A2rls'*A2rls) *A2rls'*b2rls; QI inv{1} = (A2rls' * (inv(R batch)) * A2rls); clear A Irls A2rls blrls b2rls; k=2; % k=l is our batch estimate, recursive starts with k=2 for bb=temp:length(updateind)-1 if (T(updateind(bb),5) T(updateind(bb),6) T(updateind(bb),11) T(updateind(bb),12)) estI(1, 1) = 1; end; if (T(updateind(bb),1) T(updateind(bb),2) T(updateind(bb), 7) T(updateind(bb),8)) estI(1,2) = 1; end; if(T(updateind(bb),3) T(updateind(bb),4) T(updateind(bb),9) I T(updateind(bb),10)) estI(1,3) = 1; end; Fk = (Fnom-sum(T(updateind(bb),:))*0.010 6) . * T(updateind(bb),.); Ckrls = D*Fk'; Akrls = cross(L,D)*Fk',; estldec = bi2de(estl); % switch estldec % case bi2de([i 0 0]) % A Irls = inv(I nom) *[ 0 % Ckrls(3) 0 -Ckrls(3) ;. ;... -Ckrls(2) Ckrls(i)]; 122 .. % % % % % % bbrls = anew (:,updateind(bb))- inv(I nom) *cross(Lnom,D)*Fk'; A2rls = [Akrls(1) Akrls(2) Akrls(3) ;... 0 0 Akrls(1) 0 0 Akrls(1)]; b2rls = anew(:,updateind(bb)); case bi2de([0 1 0]) % Alrls = inv(I_nom) *[-Ckrls(3)Ckrls(2);... % % % 0 -Ckrls(1);... Ckrls(1) 0 ]; birls = anew(:,updateind(bb))- inv(I nom) *cross(Lnom,D)*Fk'; % % A2rls = [0 Akrls(2) 0 Akrls(2) Akrls(1) Akrls(3) ;... % % % % % 0 0 Akrls(2)]; b2rls = anew(.,updateind(bb)); case bi2de([O 0 1]) Alrls = inv(I nom) *[ 0 Ckrls(2);... Ckrls(3) -Ckrls(1);... % -Ckrls(2) 0 % % % % % % birls = anew(:,updateind(bb))- inv(Inom) *cross(Lnom,D)*Fk'; A2rls = [0 Akrls(3) 0 0 0 Akrls(3) ;... Akrls(3) Akrls(1) Akrls(2)]; b2rls = anew(:,updateind(bb)); case bi2de([1 1 0]) % A Irls - inv(I nom) *[ 0 % Ckrls(3) 0 % % % ]; -Ckrls(3) Ckrls(2);... -Ckrls(1);... -Ckrls(2) Ckrls(1) 0 % 0 Akrls(2) Akrls(1) 0 % 0 0 % ]; blrls = anew(:,updateind(bb))- inv(I nom) *cross(Lnom,D)*Fk'; A2rls = [Akrls(1) 0 Akrls(2) Akrls(3) 0 0 Akrls(3) ;... Akrls(1) Akrls(2)]; b2rls = anew(:,updateind(bb)); % % case bi2de([1 0 1]) A rls inv(Inon) *[ 0 % Ckrls(3) 0 % -Ckrls(3) Ckrls(2);... -Ckrls(1);... -Ckrls(2) Ckrls(1) 0 ]; % bIrls = anew(:,updateind(bb))- inv(I nom) *cross(Lnom,D)*Fk'; % A2rls - [Akrls(1) 0 % % % % % % % % 0 0 Alkrls(2) Akrls(3) 0 Akrls(1) 0 Alkrls(3) ;... 0 Akrls(3) 0 Akrls(1) Akrls(2)]; b2rls = anew(.',updateind(bb)); case bi2de([0 1 ]) Alrls = inv(I nom)*[ 0 -Ckrls(3) Ckrls(2);... Ckrls(3) 0 -Ckrls(1);... -Ckrls(2) Ckrls(1) 0 ]; birls = anew(:,updateind(bb))- inv(I nom) *cross(Lnom,D)*Fk'; 123 A2rls = [0 % % % % Akrls(2) Akrls(3) 0 0 Akrls(2) 0 % Akrls(1) 0 Akrls(3) ;... Akrls(1) Akrls(2)]; Akr/s(3) 0 0 anew(:,updateind(bb)); b2rls = case bi2de([1 1 1]) -Ckrls(3) Ckrls(2);... Alrls = inv(I nom) *[ 0 Ckrls(3) 0 -Ckrls(1);... -Ckrls(2) Ckrls(]) 0 ]; blrls = anew(:,updateind(bb)) - inv(I nom) *cross(Lnom,D)*Fk'; 0 A2rls = [Akrls(1) 0 0 Akrls(2) Akrls(3) 0 Akrls(2) 0 o 0 Akrls(3) ;... Akrls(1) 0 Akrls(3) 0 Akrls(1) Akrls(2)]; b2rls = anew(:,updateind(bb)); % case bi2de([O 0 0]) % disp('Error') % % keyboard; end; % State/Covarianceupdate: Qcminvk} = Qcm inv{k-1} + Alrls' * (inv(R acc{temp-2+k})) *Alrls; cm rls(:,k) = cm rls(:,k-1) + inv(Qcm inv{k}) * Alrls' * (inv(R acc{temp-2+k})) * (birls - Alrls * cm rls(:,k-1)); QI inv'k}= QI inv{k-1} + A2rls' * (inv(R acc{temp-2+k})) * A2rls; Iinvrls(.,k) = I inv r/s(:,k-1) + inv(nv(QI invk) * A2rls' * (inv(R acc{temp-2+k})) * (b2rls - A2rls * Iinmvrls(:,k-1)); k=k+l; end; % %oPutinverse inertiaestimate into matrixform and invert it. for i = i:size(I invrls,2) I inv mat rlsi} = [I inv rls(1,i)I inv rls(4,i) I inv rls(5,i);... I_ inv rls(4,i) I inv rls(2,i) I inv rls(6,i);... I inv rls(5,i) I inv rls(6,i) I inv rls(3,i)]; I_mat rls{i} = inv(I inv mat rs{i}); end; % Get varaince/stdev of lxx, Iyy, Izz over time forj = i:length(QIinv) QIxx(j) = 1/(QI inv/j}(1,1)); Sigmaxx() = sqrt(Qlxx()); Ixx rlso) = I mat rls{i}(1,1); Qlyyo) = 1(QI invo{}(2,2)); Sigmayyo) = sqrt(QIyyo)); Iyy rls(j) = I mat rls{} (2,2); 124 QIzzo) 1/(QI invoj}(3,3)); Sigmazz() = sqrt(QIzz()); Izz ris) = Imat rls{j(3,3); end; 125 Appendix E C Code E.1 Mass Property ID code (massid/gsp.c) This is the highest layer of the online mass ID code. /* Templatefile ofgsp.c */ #include <std.h> #include <clk.h> #include <sys.h> #include <stdlib.h> #include <string.h> //#include "gsp.h" #include "gsp internal.h" #include "prop.h" #include "pads.h" #include "comm.h" #include "commands.h" #include "gsp task.h" #include "spheresconstants.h" #include "system.h" #include "control.h" 126 #include "pads correct.h" #include "comm datacomm.h" #include "housekeeping.h" #include "control internal.h" #include "est ang acc.h" #include "mass id.h" #include "gsutil standard maneuvers.h" #include "mix simple.h" #include "mix simple_correct.h" #include "math matrix.h" #include "math LTIFilter.h" #include "spheres types. h" #include "utilserial_printfh" //1kHz sampling declarations #define SHORTS PERSAMPLE #define FLOATS PER SAMPLE #define SAMPLES PER SECOND #define TESTDURATION (8) (4) (1000) (5) staticfloat *sample_buffer=NULL; staticfloat *current buffer = NULL; staticfloat *BufferPos= NULL; //static unsigned int sample_bufsize =sizeof(unsignedshort) * SHORTS PER SAMPLE * SAMPLES PER SECOND * TEST DURATION; static unsigned int sample_bufsize =sizeof(float) * FLOATS PER SAMPLE * SAMPLES PER SECOND * TEST DURATION, static defaultrfm fpayloadpkt; //omega dot KF declarations staticfloat startgyro[3]= {0.0•]; staticfloat current_gyro[3] = 0.0f}; staticfloat gsp omega dot[3], gsp omega dot minus[3], lastomega dot[3], gsp R acc[3], last Racc[3]; int k, p; unsignedint test started = 1; unsigned shortpast thrust, new thrust; int down count = -1; //mass id declarations unsigned int numfirings = 0; static mass ID input batch one = {0.O], batch two = {O.O], recursive one = {0.0; static mass ID output batchresult= {0.O], propagate = {0.O; int rls init - 1; 127 // gyrofilter declarations staticfloat U_gyro[3] = {0. Of}; //debug declarations unsigned int data num; dbgfloat_packetDebugVec; //dbgushort_packetDebugVec; // control declarations unsigned int current cycle void gspPadslnertial(IMUsample *accel,IMU sample *gyro,unsigned int numsamples) //1 00 Hz sampling declarations static int is second sample = 0; int data start = 0; int i; padsCountsConvertGyros(gyro[0],current_gyro); /* //100 Hz data sampling if (is second sample) data start = 8; else data start = 0; //Fill in the IMU data ((unsignedshort *)pkt)[data start] sysGetSpheresTime() & Oxffff" for (i=O0;i<3;i++) ((unsignedshort *) pkt)[data start + 1 + i] = accel[O][i]; for (i=0;i<3;i++) ((unsigned short *)pkt)[datastart+ 4 +i] = gyro[O][i]; 128 ((unsignedshort *)pkt)[data start + 7] = propGetCurrentTrustersO; if(is_second_sample) I commSendPacket(COAMM CHANNEL_STL, GROUND,sysIdentityGetO,COMM CMD_IMU DATA, pkt, 0); is_second sample = 0; print int(1); e else I}* is second sample = 1; void gspPadsGlobal(unsignedint beacon, beacon_measurement matrix measurements) void gspldentitySetO // The unique logical identity of this sphere: / SPHERE1, SPHERE2, SPHERE3, SPHERE4, or SPHERES. sysIdentitySet(SPHERE1); void gspInitProgram() //Basic Initialization- These settings can be changedas neededfor each experiment padslnitializeFPGA(5); 129 //Set up comm TDMframes -- These are sphere-specific /Set up comm TDMframes -- These are sphere-specific commTdmaStandardlnit(COMAvM CHANNEL STS, sysIdentityGetO, 1); commTdmaStandardlnit(COMM CHANNEL STL, sysldentityGetO, 1); //Enable both communications channels comm TdmaEnable(COMM CHANNEL STS); commTdmaEnable(COMM CHANNEL STL); //Allocate a single sample's worth of internalstorage padsInertialAllocateBuffers(1); //Sample andprocess inertialsensors at 10Hz padslnertialPeriodSet(10, 10); //Advanced Initialization- These settings should not need adjustmentfor early experiments //Turn on 1Hz background telemetry commBackgroundPointerDefaultO); /Set up flow controlfor data transfers ctrlBypassEnable(1); datacommTokenSetup(O, 18,8); // kHz sampling init // sample buffer = (unsignedshort *) calloc(sample_bufsize,1); sample buffer =(float *) calloc(sample bufsize, 1); } void gsplnitTest(unsignedint testnumber) { //Turn off spheres beacon padsBeaconNumberSet(O); test started = 1; for (k= O;k<3;k++) { gsp omega dot minus[k] =0.Of gsp_omegadot[k] = O.Of" start_gyro[k] = current gyro[k]; past thrust = propGetCurrentThrusterso; 130 switch (test number) case 1: case 2: //mass idpreset rotation //firingstraight,correctfor induced acceleration //Firstset the controlfrequency ctrlPeriodSet(1000); //setup the datastackpointer current buffer = sample buffer; memset(gsp_omega dot, 0, sizeof(gsp_omega dot)); memset(gsp_omega dot minus, 0, sizeof(gsp_omega_dot_minus)); memset(gsp R_acc, 0, sizeof(gsp R_acc)); memset(propagate.CM offset, 0, sizeof(propagate.CM offset)); memset(propagate.CM offsetcov, 0, sizeof(propagate.CM_offset cov)); memset(propagate.Inv_Inertia,0, sizeof(propagate.Inv_Inertia)); memset(propagate.Inv_Inertia_cov, 0, sizeof(propagate.InvInertiacov)); memset(batch result.CMoffset, 0, sizeof(batch result.CM offset)); memset(batch result.CMoffset_cov, 0, sizeof(hatch_result.CMoffsetcov)); memset(batchresult.Inv Inertia,0, sizeof(batch result.Inv_Inertia)); memset(batch result.Inv Inertia cov, 0, sizeof(batch_result.InvInertia cov)); memset(batchone.:omega, 0, sizeof(batch_one.omega)); memset(batch one.omega_dot, 0, sizeof(batch_one.omega dot)); memset(batch one.Racc, 0, sizeof(batchone.Racc)); batch one.thrust = 0; memset(batch_two.omega, 0, sizeof(batchtwo.omega)); memset(batch two.omega_dot, 0, sizeof(batch two.omeg a dot)); memset(batch two.R_acc, 0, sizeof(batch two.R_acc)) ; batch two.thrust = 0; memset(recursive_one.omega, 0, sizeof(recursive_one.omega)); memset(recursive_one.omega dot, 0, sizeof(recursiveone.omega dot)); memset(recursive_one.R_acc, 0, sizeof(recursive one.Racc)); recursive one.thrust = 0; mass_ID InitO; break; case 3: //download 1 kHz data ctrlPeriodSet(50); break; default: current buffer = NULL; 131 } BufferPos = current buffer; } void gsplnitTask() I taskTriggerMaskSet(PADS INERTIALTRIG); void gspTaskRun(unsigned int gsp_task trigger,unsigned int extra data) { // kHz sampling variables float cur time; unsigned int testnum; //FilteringVariables float xinput; constfloatAcoeff_gyro[3] = {1.Of 0. 6498f 0. 1056f}; constfloat Bcoeff_ gyro[3] = {0.5975f 0.6498f 0.5081f•; // Test 3 is data transfer test num = ctrlTestNumGetO; if(test num == 3) { return; } // Start off test resettingKF if (test started) reset KF((float *) current gyro, (float *) gsp omega dot minus); test started = 0; new thrust = propGetCurrentThrustersO; x input = current_gyro[2];//TEMP!!, justfiltering z gyro for now if (new thrust != 0) //If thruster(s)is on pstthrust)/If thruster(s)just turned on st if (new_thrust= { down count = 1; //=lfor 132 1 kHz numJfirings++; down count--; if (down count -= 0) //If 10 ms haspassed to avoid transient for (k-0;k<3;k++) startgyro[k] = current gyro[k]; reset KF((float *) start gyro, (float *)gsp_omega dot minus); } for (k=0;k<3;k++)//Maybe memcopy or atomic memcopy (forall vector copies)? last omegadot[k] = gsp_omega dotk]J; last R acc[k] - gsp_R acc[k]; // We're past transient,update KF and run mass ID if (down_count <= 0) { update KF((float *) currentgyro,(float*) gsp omega dot, (float *) gsp omega dot minus, (float *) gspR acc); if(numirings > = 3) for (k=0;k<3;k++) recursive_one.omega_dot[k]= gsp omega_dot[k]; recursive one.omega[k] = current_gyro[k]; recursive one.R acc[k] = gsp R acc[k]; } recursive one.thrust = new thrust; if (rls init == 1) rls init = 0; propagate = mass ID_RLS(batch result, recursive one); } else 133 propagate= mass ID RLS(propagate, recursive one); } else //Thrusters are off { memset(gspomega dot,O,sizeof(gsp omega dot)); if (newthrust ! pastthrust) //Thruster(s)just turned off switch (num_firings)//Need datafrom two differentfirings to start of mass id I- case 0: break, case 1: for (k=0O;k<3;k++) batchone.omega dot[k] = last omega_dot[k]; batch one.omega[k] = current gyro[k]; batch one.R acc[k]= last R acc[k]; } batch_one.thrust = past thrust; break; case 2: for (k=0O;k<3;k++) { batchtwo.omegadot[k] = lastomega dot[k]; batch two.omega[k] = current gyro[k]; batch two.R acc[k] last R acc[k]; batch two. thrust = past thrust; batch result = mass ID Batch(batch one, batch two); break; default: break; 134 I past_thrust = new thrust; //Range check. Make sure that we don't recordtoo many samples. if (current buffer) if ((BufferPos - current buffer) < (SHORTS PER SAMPLE * SAMPLES PER SECOND * TESTDURATION * sizeof(short))) /* if ((BufferPos - currentbuffer) < (sample bufsize >> 2)) //Fill in the valuesfor this sample cur time = (float)sysGetSpheresTime 0; BufferPos[O] = 7.Of BufferPos[l] = cur time; // // BufferPos[2] = last omega dot[2]; BufferPos[2] = x input; BufferPos[3] = gsp_omega dot minus[2]; BufferPos[3] = current_gyro[2]; BufferPos[4] = gyro[O][O]; BufferPos[5] = gyro[O][1]; BufferPos[6] = gyro[O][2]; BufferPos[7] = propGetCurrentThrustersO; BufferPos += FLOATS PER SAMPLE; }*/ data num++; if (data num >= 20) data num = 0; void gspControl(unsignedint test number, unsignedint test_time, unsigned int maneuvernumber,unsigned int maneuver time) //FastlMUvariables static unsigned int started flag = staticfloat *buffer_pos; static unsigned int last length = 0; 135 // Controlvariablesfor mixer const unsignedint minpulse = 20; staticfloat defaultState[13] = {O.f O0.0O O0.0f 0.0f 0.of o. f o0.Of; O0.0f O.0f 0.f 0.Of, 0.Of 1.Of float command[6] = 0. Of 0.2f 0. Of 0. Of 0.Of 0. Of; float correcttorque[3]; proptimefiring times; memset(firing_times.on time, 0, sizeof(firing times.on_time)); memset(firing times.off time, 0, sizeof(firing times.off time)); switch (test number) { case 1: started flag = 0; lastlength = (sample_bufsize >> 2); switch (maneuver number) { case O.: case 1: DoStandardManeuver(1,1000); ctrlManeuverNumSet(2); break; case 2: DoStandardManeuver(12,1000); ctrlManeuverNumSet(3); break; case 3: DoStandardMvfaneuver(1,1000); ctrlManeuverNumSet(4); break; case 4: DoStandardManeuver(13,1000); ctrlManeuverNumSet(5); break; case 5: DoStandardManeuver(1,1000); ctrlManeuverNumSet(6); break; case 6: DoStandardManeuver(13,1000); ctrlManeuverNumSet(7); break; case 7: 136 DoStandardfManeuver(1,1000); ctrlManeuverNumSet(8); break; case 8: DoStandardManeuver(12,1000); ctrlManeuverNumSet(9); break; case 9: DoStandardManeuver(1,1000); ctrlManeuverNumnSet(10); break; case 10: DoStandardManeuver(4,1000); ctrlManeuverNumnSet(11); break; case 11: DoStandardManeuver(1,1000); ctrlManeuverNumSet(12); break; case 12: DoStandardManeuver(5,1000); ctrlManeuverNumSet(13); break; case 13: DoStandardManeuver(1,1000); ctrlManeuverNumSet(14); break; case 14: DoStandardlMvaneuver(5,1000); ctrlManeuverNumnSet(15); break; case 15: DoStandardManeuver(1,1000); ctrlManeuverNumSet(16); break; case 16: DoStandard2 aneuver(4,1000); ctrlManeuverNumnSet(17); break; case 17: DoStandardManeuver(1,1000); ctrlManeuverNumSet(22); break; case 18: DoStandardManeuver(12,1000); ctrlManeuverNumSet(19); 137 break; case 19: DoStandardManeuver(1,1000); ctrlManeuverNumSet(20); break; case 20: DoStandardManeuver(13,1000); ctrlManeuverNumSet(21); break; case 21: DoStandardManeuver(1,1000); ctrlManeuverNumSet(22); break; /* case 0: case 1: DoStandardManeuver(1,2000); ctrlManeuverNumSet(2); break; case 2: firing times.on time[2] = 0; firing times.off time[2] = 2000; ctrlManeuverNumSet(3); break; case 3: DoStandardManeuver(1,2000); ctrlManeuverNumSet(4); break; case 4: firing_times.on time[3] = 0; firing times.off time[3] = 2000; ctrlManeuverNumSet(5); break; case 5: DoStandardManeuver(1,2000); ctrlManeuverNumSet(6); break; case 6: firing times.on time[9] = 0; firing times.off time[9] = 2000; ctrlManeuverNumSet(7); break; case 7: DoStandardManeuver(1,2000); ctrlManeuverNumSet(8); break; case 8: 138 firing times.on time[9] = 0; firing times.off time[9] = 2000; ctrlManeuverNumSet(9); break; case 9: DoStandardManeuver(1,2000); ctrlManeuverNumSet(10); break; case 10: firing times.on time[21 = 0; firing times.off time[2] = 2000; ctrlManeuverNumSet(11); break; case 11: DoStandardManeuver(1,2000); ctrlManeuverNumSet(22); break; case 12: firing times.on time[3] = 0; firing_times.off time[3] = 2000; ctrlManeuverNumSet(13); break; case 13: DoStandardManeuver(1,2000); ctrlManeuverNumSet(22); break; */ case 22: ctrlTestTerminate(TEST RESULT NORMAL); break; default: break; } //propSetThrusterTimes(&firing times); break; case 2: startedflag = 0; last length = (samplebufsize >> 2); currentcycle++; if(current cycle == 2) { ctrlMixSimple(command,min pulse, defaultState); if(current cycle 4) 4= { 139 mathMatVecMult((float *) correct torque, (float **) J nom, (float *) last omega dot, 3, 3); for (k=3;k<5;k++) { command[k] = command[k] - correct torque[k-3]; } ctrlMixSimpleCorrect(command,minpulse, defaultState); } if (current cycle > 5) { ctrlTestTerminate(TEST RESULT NORMAL); } break; case 3: /Send the data buffer over the comm if (!startedflag) { startedflag = 1; bufferpos = samplebuffer; } else //copy the datafrom the sample buffer into apacket, two samples at a time memcpy(pkt, buffer_pos,sizeof(default rfmn_ payload)); // increment memory pointer by two samples (16 shorts) bufferpos += 8; //put the packet in the STL queue commSendPacket(COMM CHANNEL STS, GROUND,sysldentityGetO,COMMAI CMD DBG FLOA T,(unsignedchar *)pkt,0); // once all data is sent, stop transmissions if ((bufferpos-samplebuffer) >= last length) startedflag = 0; ctrlTestTerminate(TEST RESULT NORMAL); break; default: break; I 140 E.2 Angular Acceleration Kalman Filter (est_angacc.c) #include "est angacc.h" #include <math.h> #include "spheres constants.h" #include "system.h" #include "control.h" #include "comm.h" #include <assert.h> #include "math lubksb.h" #include "math ludcmp.h" #include '"prop.h" #include "math matrix.h" #include "commands.h" #include '"ads.h" #include <string.h> #include "util serialprintfh" //#include "mass id constants.h" //Declarations constfloat dt = 0.Ol1/ float I nom[3][3] = { 0.0229f 0.0000965f -0.000293f}, {0.0000965f 0.0242f -0.0000311f}, [-0.000293f -0.0000311f 0.0214f }, }; constfloat I inv[3][3] = {43.6765f -0.1734f 0.5977f}, {-0.1734f 41.3231f 0.0577f}, {0.5977f 0.0577f 46.7372f}, }; constfloatF nom[l2] = {0.12579f 0.13153f 0.13530f 0.13568f 0.12788f 0.12956f 0.12096f 0.13180f 0.13593f 0.14065f 0.12774f 0.12620]j; static int part index[3] = {0}; staticfloat even odd; staticfloat Pinv minus[3][3] = [0.Of}; constfloat R inv[3][3] = 141 {7.2307e4f0.f, 0.0f }, {0. Of 1.5119e4f 0.f }, {O.Of O0.0 3.1776e4ji, ,. unsigned int updatenum; staticfloat bias[3] = {0. OJ•; staticfloat hf3] = {0. Of}; staticfloat P[3][3] = {0. Qf; staticfloat P inv[3][33] = {0. O•; int i,j; //Functions void reset KF(float start_rate[3],float *omega dot minus) unsigned short thruster quant; staticfloat Fk[12] = 0. Of}; constfloat L cross D[3][12] = { {0.002128790f -0.000079130f, -0.001669776f -0.000188340f 0.098154965f -0.097065877f 0.000746910f -0.000912890f 0.000452016f 0.000226008f -0.099429926f 0.097972308jf, {0.097615516f -0.097638341f -0.003122740f 0.000352225f 0.000554184f 0.001157904/ -0.098655692f 0.098246725f -0.000845340f 0.000422670f 0.000212592f -0.000094944f}, {0.001138296f 0.000042312f 0.099163540f -0.096536776f 0.00103641Of, -0.002165460f -0.000399384f -0.000488136f -0.098561794f 0.097472539f -0.000397580f -0.000177560fl, }; staticfloat ind torque[3] = {0. Ot; unsigned short thrusters; i/Fudgednumber update num = 0; thruster quant = 0; thrusters = propGetCurrentThrustersO; for (i=0;i<12;i++) thruster quant = thruster quant + ((thrusters>>i)& OxOOO1); } for (i=0;i<12;i++) if (thrusters& (1<<i)) 142 Fk[i] = (F nom[i] - (thruster_quant- 1)*0 0106J); else Fk[i] = O.Of, //To get L-cross_D, DO THIS:// /* for (i=O;i<12;i++) L_cross D[O][i] = L[fi] *D[2][i]- L[2][i]*D[1][i]; L_crossD[1][i]=L[2][i *D[O][i]-L[O[i]*D[2]i]; Lcross D[2][i] =L[O][i]*D[]][i]- L[ffi]*D[O][i]; } */ //OR USE CONST:// memse t(part index,0,sizeof(part index)); memset(omega_dotminus,O,sizeof(omega dot minus)); mathMatVecMult(ind_torque, (float **) Lcross_D, Fk, 3, 12); //To get omega dot minus, DO THIS:!/ /* for (i=0;i<3;i++) for (=0;j<3j+ +) Itemp[ijy] = Inom[ilj]; ludcmp((float **) I_temp, 3, (int *)partindex,&even_odd); lubksb((float **) I_temp, 3, (int *)partindex, ind_torque); 143 for (i=0;i<3;i++) { omega_dot_minus[i] = ind_torque[i]; }*I IIIIIIIIIIII IIGR THIS.il IIIIIIIIIIII n1athMatVecMult(omega_dot_minus, (float **) I_inv, ind_torque, 3, 3); for (i=O;i<3;i++) { for (j=0,j<3,j++) { } P_inv_minus[i][i] = 10. Of; } for (i=0;i<3;i+ +) { bias[i] = start_rate[i],' } } void update_KF(float current_rate[3], float *omega_dot, float *omega_dot_minus, float *R_acc) { IIUpdate KF Variables static float H[3][3] = {O.Oj}; static float P_inv_temp[3][3] = {O. OJ}; static float Mat_Tempi [3][3] = {O. OJ}; static float Mat_ Temp2[3] [3] = {O. OJ}; static float K[3][3] = {O. OJ}; static float ang_vel[3] = {O. OJ}; static float Vec_Tempi[3] = {O.Oj}; static float Vec_Temp2[3] = {O.Oj}; static float Vec_ TeJnp3 [3] = {O. OJ}; static float Vec_Temp4[3] = {O.Oj}; IIProp Variables float phi = i. Of; 144 update_num+ +; for (i=O;i<3;i++) { for (j=0,j<3,j+ +) { H [i} [j] = o. Of; } H[i][i] = update_nunl*dt; } mathMatTransposeMatMult((float **)Mat_Tempi, (float**) H, (float **) R_inv, 3, 3, 3); mathMatMatMult((float **) Mat_Temp2, (float **) Mat_Tempi, (float **) H, 3, 3,3); mathMatAdd((float **) P_inv, (float **) P_inv_minus, (float **) Mat_Temp 2, 3, 3); for (i=O;i<3;i+ +) { for (j=0,j<3,j+ +) { } } ludcmp((float**) P_inv_temp, 3,(int*) part_index, &even_odd); for (i=O;i<3;i++) { for (j=0,j<3,j++) h[j] = O.Oj; h[i} = i.Of; lubksb((float**) P_inv_temp, 3, (int*) part_index, h); for (j=O;j<3,j+ +) P[j][i] = h[j]; R acc[i] = P[i}[i}; } mathMatMatMult((float **) K, (float **) P, (float **) Mat_Tempi, 3, 3, 3); mathMatVecMult((float *) Vee_Tempi, (float **) H, (float *) amega_dot_minus, 3,3); mathVecAdd((float *) Vec_Temp2, (float *) bias, (float *) Vec_Tempi, 3); 145 for (i=O;i<3;i+ +) Temp2[i]j; Vec_Temp2[i] = -Vec_ math VecAdd((float *) Vec Temp3, (float*) current rate, (float *) VecTemp2, mathMatVecMult((float *) VecTemp4, (float **) K, (float *) VecTemp3, 3, 3); mathVecAdd((float *) omega_dot, (float *) omega dot minus, (float *) Vec_Temp4, 3); //PropagateStep for (i=O;i<3;i+ +) for (j=O;j<3j++) P inv_ minus[il[fl =-P inv[i][j]; for (i=O;i<3;i++) omega dot minus[i] = phi *omega_dot[i]; void prop KF(float *omega dot,float *omegamdot minus) //PropagateKF Variables E.3 Mass ID - low level (mass_id.c) #include <string.h> #include "mass id.h" #include "math matrix.h" #include "mass id constants.h" 146 #include "math lubksb.h" #include "math ludcmp.h" #include "comm.h" :#include "commands.h" #include "spheresconstants.h" #include "system.h" #include "spheres types.h" #include "util_serialprintfh" dbg float packet DebugVecl, DebugVec2,DebugVec3; float L[3][12] = {0.0Of; float cm nom[3] = (0.O); unsignedint count, index; float Ck[6], Ak[6]; float C[3][3] = {0.O}; float A1[6][3] = (0. O},A2[6][6 = .Ojf; float Bl[6] = (.Of}, B2[6] = {0.Of}; static int part indexl[3] = {0}); static int partindex2[6] = {0}; staticfloat even_odd; staticfloat h1[3] = {0.O•; staticfloat h2[6] = {0.OJ}; int m,n; void mass ID InitO { for (m=0;m<3;m++) for (n=O;n<12;n++) { L[m][n] = L_nom[m][n] - cm_nom[m]; } memset(Al,0,sizeof(A1)); memset(A2, 0, sizeof(A2)); } mass ID output massID Batch(mass ID input batch_one, mass_ID input batch two) f float Al _top[3][3] = {0.0]), Al_bot[3][3] = {0.0/}; 147 floatA2 top[3][6] = [0.O}, A2_bot[3][6] = [0.}; float Bl top[3] = [0.0f}, Bl_bot[3] = {0.0}, B2_top[3] = {0.0}, B2_bot[3] = {o.o0.; float MatTempl[3][3] = {0. Of, Mat_Temp2[3][3] = [0.0f); float Mat Temp3[3][6] = [0. 03]; floatMat Temp4[6][6] = [0. 01f, Mat Temp5[6][6] = {0. Ofj; float Mat_Temp6[6][6] = [0. 0O}; float R_batch[6][6] = 0.0f}; float Al_temp[3][6] = [0. O1; mass_IDoutputbatchresult; // Get LS Equations get_LS_equations(baions(batch_one,(float **)Al_top, (float **) A2 _top, (float*) Bl_top, (float *) B2_top); get_LS_equationsations(batch_two,(float **)Al_bot, (float **)A2 bot, (float *) Bl_bot, (float *) B2_bot); // Combine Matrices for (m=0;m<3;m++) for (n=0;n<3;n++) Al[m][n] = Al_top[m]n]; for (n=O;n<6;n++) A2[m][n] = A 2_top[m][n]; Bl[m] = Bltop[m]; B2[m] = B2_top[m]; I for (m=3;m<6;m++) for (n=0;n<3;n++) A l[m][n] = A l_bot[m-3][n]; for (n=0;n<6;n++) A2[m][n] = A2_bot[m-3][n]; Bl[m] = Bl_bot[m-3]; B2[m] = B2_bot[m-3]; } 148 for (m=O;m<3;m++) for (n=O;n<6;n++) Al temp[m][n] = Al[n][m]; I I //Perform batch memset(Mat_Templ, 0, sizeof(Mat Templ)); // CM offset mathMatMatMult((float **)Mat_ Templ, (float **) Al_temp, (float **)Al, 3, 6, 3); ludcmp((float**) Mat Templ, 3, (int*)part indexl, &evenodd); for (m=0O;m<3;m++) for (n=O;n<3;n++) { hl[n] = 0.Of, h1/m] = .Of lubksb((float* *)Mat_Templ, for (n=0;n<3;n++) 3, (int*) part index], hl); { Mat_Temp2[n][m] = hl[n]; mathMatMatTransposeMult((float**)Mat Temp3, (float **) Mat Temp2, (float **)A, 3, 3, 6); mathMatVecMult(batch result.CM offset, (float **)Mat Temp3, (float*) B, 3, mathMatTransposeMatMult((float**)Mat Temp4, (float **) A2, (float **)A2, 6, 6, 6); ludcmp((float**) Mat Temp4, 6, (int*)part_index2, &evenodd); for (m=0;m<6;m++) for (n=O;n<6;n++) h2[n] = 0.Of h2[m] = 1.Of0 149 lubksb((float**) MatTemp4, 6, (int*) part index2, h2); for (n=O;n<6;n++) Mat_Temp5[n][m] = h2[n]; mathMatMatTransposeMult((float**)MatTemp6, (float**) Mat Temp5, (float *)A2, 6, 6, 6); 6); mathMatVecMult(batch result.InvInertia,(float **)Mat Temp6, (float *) B2, 6, //Covariances memset(R batch, 0, sizeof(R batch)); for (m=0;m<3;m++) I Rbatch[m][m] = batch one.Racc[m]; Rbatch[m+3][m+3]= batch_two.R_acc[m]; ludcmp((float**)R batch, 6,(int*) part _index2, &even odd); for (m=0;m<6;m++) for (n=O;n<6;n++) h2[n] = o. Of0 h2[m] = 1.Of0 lubksb((float**) R batch, 6, (int*) part index2, h2); for (n=0;n<6;n++) Mat Temp5[n][m] = h2[n]; mathMatTransposeMatMult((float**)Mat_Temp3, (float **) A , (float ** Mat Temp5, 6, 3, 6); mathMatMatMult((float **) batch_result.CMoffsetcov, (float **)Mat_Temp3, (float **)A1, 3, 6, 3); mathMatTransposeMatMult((float**) Mat Temp4, (float**)A2, (float **) Mat Temp5, 6, 6, 6); mathMatMatMult((float **) batch_result.InvInertia_cov,(float**) Mat Temp4, (float **)A2, 6, 6, 6); 150 return batch result; } massID output mass ID RLS(mass ID output minus, mass ID input recursive one) float A lrls[3][3]= {O. OJ}; float A2rls[3][6] = 0. Of}; float B rls[3] = {O. Of}; float B2rls[3] = {0. O}; float Qcm[3][3] = o0.0 }; float Qcm_inv[3][3] = {0.0f3; float Qcm_inv minus[3][3] = 0.0o}; float QI[6][6] = {0. 0]o; float QI inv[6][6] = {0. Of; float QIinv2[6][6] = {0.0]]; staticfloat QI inv3[6][6] = 0.0f} ; float QInmv minus[6][6] = {0. o}; float R[3][3] = 0.Of}; float Mat float Mat float Mat float Mat float Mat float Mat Temp][3][3] = {0. Ofl; Temp2[3][3] = {0. Of}; Temp3[3][3] = {0. Of; Temp4[6][3] = {0. Of; Temp5[6][6] = {0. O; Temp6[6][3] = {0. OP; float VecTempl[3] = {O.0Of; float Vec Temp2[3] = {0. P0; float VecTemp3[3] = {0. Oj; float Vec Temp4[6] = 0. Of; int s, t; static mass ID outputpropagate; get LSequations(recursive one, (float**) A rls, (float **) A2rls, (float *) Brls, (float *) B2rls); memset(R, 0, sizeof(R)); for (s=O;s<3;s++) R[s][s] = recursive one.R acc[s]; ludcmp((float**) R, 3,(int*)part-indexl, &evenodd); for (s=0;s<3;s++) 151 for (t=O;t<3;t++) hl[t] = O.Of, hl[s] = i.Of; lubksb((float* *) R, 3, (int*) part index], hl); for (t=0O;t<3;t++) Mat Templ[t][s] = hl[t]; I I memcpy(Qcm_invy minus, minus.CMoffset_cov, sizeof(minus.CM offsetcov)); memcpy(QI inv_minus, minus.Inv_nertia_cov,sizeof(minus.Inv_Inertia_cov)); mathMatTransposeMatMult((float**)Mat_Temp2, (float **)A lrls, (float **) Mat Templ, 3, 3, 3); mathMatMatMult((float * *)MatTemp3, (float **)Mat Temp2, (float **)Alrls, 3, 3, 3); mathMatAdd((float **) Qcm_inv, :(float **) Qcm invminus, (float **) Mat Temp3, 3, 3); for (s=0;s<3;s+ +) for(t=O;t<3;t++) { propagate.CM offset cov[s][t] = Qcminv[s]ft]; ludcmp((float**) Qcm_inv, 3,f(int*) part index], &even_odd); for (s=O;s<3;s++) { for (t=O;t<3;t++) { hl[t] = O.Of, hi[s] = i.Of, lubksb((float**) Qcm inv, 3, (int*)part indexl, hl); for (t=O;t<3;t++) Qcm[t][s] = hl[t]; 152 mathMatTransposeMatMult((float**)Mat Temp4, (float **)A2rls, (float ** Mat Templ, 3, 6, 3); mathMatMatMult((float **) Mat Temp5, (float **)Mat Temp4, (float **) A2rls, 6, 3, 6); mathMatAdd((float * *)QIinv,(float **) QI_inv_minus, (float **)Mat Temp5, 6, 6); for (s=O;s<6;s++) { for(t =0;t<6;t++) { propagate.Inv_lnertiacov[s][t] = QLinv[s][t]; QIinv2[s][t] = QLinv[s][t]; QIinv3[s][t] = Qlinv[s][t]; I I ludcmp((float* *) QI mv, 6, (int*)part index2, &even_odd); for (s=O;s<6;s++) for (t=O;t<6;t++) h2[t] = O.Of, I h2[s] =1.Oflubksb((float**) QIinv, 6, (int*) part_index2, h2); for (t=O;t<6;t++) { QI[t][s] = h2[t]; mathMatVecMult((float *) Vec Templ, (float **) Alrls, (float*) minus.CM offset, 3, 3); for (s=O;s<3;s++) Vec_ Temp2[s] = Brls[s]- Vec_ Templ[s]; mathMatMatMult((float **)Mat Temp3, (float**) Qcm, (float **) Mat Temp2, 3, 3, 3); mathMatVecMult((float *) Vec Temp3, (float **)MatTemp3, (float *) Vec_Temp2, 3, 3); mathVecAdd((float *)propagate.CMoffset, (float *) minus.CM_offset, (float *) VecTemp3, 3); 153 mathMatVecMult((float *) Vec_ Templ, (float **)A2rls, (float *) minus.Inv_Inertia, 3, 6); for (s= 0;s<3;s++) Vec_Temp2[s] = B2rls[s] - VecTempl[s]; mathMatMatMult((float **) Mat Temp6, (float **) QI, (float **) Mat Temp4, 6, 6, 3); mathMatVecMult((float *) Vec _Temp4, (float **)MatTemp6, (float *) VecTemp2, 6, 3); mathVecAdd((float *)propagate.InvyInertia,(float*) minus.Inv Inertia, (float *) VecTemp4, 6); returnpropagate; I void get LS equations(mass ID input measurement,float **al, float **a2, float *bl, float *b2) unsignedshort thruster_quant; staticfloat Fk[12] = 0.O}; constfloat L_cross_D_Default[3][12]= { (0.002128790f -0.000079130f -0.001669776f -0.000188340f 0.098154965f -0.097065877f 0.000746910f -0.000912890f 0.000452016f 0.000226008f -0.099429926f 0.097972308f}, (0.097615516f -0.097638341f -0.003122740f 0.000352225f 0.000554184f 0.001157904f -0.098655692f 0.098246725f -0.000845340f 0.000422670f 0.000212592f -0.000094944f], (0.001138296f 0.000042312f 0.099163540f -0.096536776f 0.001036410f -0.002165460f -0.000399384f -0.000488136f -0.098561794f 0.097472539f -0.000397580f -0.000177560fj, ,; unsigned short thrusters;//Fudged number constfloat I inv[3][3] = {43.6765f -0.1734f 0.5977j], (-0.1734f 41.3231f 0.0577jf, {0.5977f 0.0577f 46.7372f}, float alpha[3]; float VecTemp[3] = (0.Of}; thruster_quant = 0; thrusters = measurement.thrust; memcpy(alpha,measurement.omega_dot,sizeof(measurement.omega dot)); 154 for (n=0;n<12;n++) thrusterquant= thruster quant + ((thrusters>>n)& OxO001); for (n=O;n<12;n++) { if (thrusters& (1<<n)) { Fk[n] = (F mag Default[n] - (thrusterquant- 1) *0. 0106f); // TEMP use ofFmag_Default } else { Fk[n] = 0. Of } } // Create CM offset RLS equations mathMatVecMult(Ck, (float **) D Default, (float *) Fk, 3, 12); // TEMP use of D Default mathMatVecMult(Ak, (float **) L_cross D Default, (float *)Fk, 3, 12); / TEMP use ofLcross D Default...needto take Cg into account mathSkewSymmetric (Ck, (float *) C); mathMatMatatMult((float**) a, (float **) Iinv, (float**) C, 3, 3, 3); mathMatVecMult((float *) VecTemp, (float **) I_inv, (float *)Ak, 3, 3); // TEMP Ak uses L not Lnom +) for (n=0;n<3;n+ bl[n] = alpha[n]- VecTemp[n]; // Create Inverse InertiaRLS equations ((float *)a2)[0*6+0]= Ak[O]; ((float *)a2)[1*6+1] = Ak[1]; ((float *)a2)[2*6+2] = Ak[2]; ((float *)a2)[0*6+3]= Ak[1]; ((float *)a2)[0*6+4] = Ak[2]; ((float *)a2)[1*6+ 3] = Ak[0]; ((float *)a2)[1*6+5] = Ak[2]; ((float *)a2)[2*6+4] = Ak[O]; ((float *)a2)[2*6+5] = Ak[1]; 0;n<3;n++) for (n=O b2[n] = alpha[n]; 155