{"id":870,"date":"2014-12-07T21:14:30","date_gmt":"2014-12-08T02:14:30","guid":{"rendered":"http:\/\/fll-freak.com\/blog\/?p=870"},"modified":"2025-04-21T00:54:35","modified_gmt":"2025-04-21T04:54:35","slug":"complimentary-filter","status":"publish","type":"post","link":"https:\/\/fll-freak.com\/blog\/?p=870","title":{"rendered":"Complimentary filter"},"content":{"rendered":"<p>I have been struggling with how to fuse all the data into one cohesive mess. In the case of heading I have several source. I have a magnetometer, the heading from GPS,\u00a0the integrated value from the gyro, and if I can manage it, the solar compass.<\/p>\n<p>They each have strengths and weaknesses. The magnetometer is great as long as the car is not moving, the servos moving, or it sitting on a man hole cover.<\/p>\n<p>The GPS is great as long as the robot is moving a a reasonable speed and has a good lock.<\/p>\n<p>The gyro has no ability to determine north, but for short periods of time can keep track of changes in heading.<\/p>\n<p>The solar compass is fantastic as long as we have the sun and it is not too high in the sky.<\/p>\n<p>So what is a poor robot to do? One solution is to use a Kalman filter to merge the data. But the math is complex and you need\u00a0 mathematical model of your system to make best use of it. Now I have the habit of picking at everyone I know for knowledge (and even those I do not know). This has lead me to the complimentary filter.<\/p>\n<p>The complimentary filter is nothing more than a weighted average. Rather than each heading having equal weight when taking an average, you assign each a unique weight. The more likely that the value is right the higher the weight you give it.<\/p>\n<p>So how do you assign weights? The literature would have you use the parameter&#8217;s covariance. This is the inverse of the standard deviation. A parameter you have confidently measured would have a larger covariance than one you are not so sure about. There are lots of mathematical ways to determine covariance given sample sets of numbers. But in my case, I will take\u00a0 simpler way out.<\/p>\n<p>My weights will be the inverse of the expected accuracy of the system. Here are the cases:<\/p>\n<p>GPS: Zero if velocity is under 2 meters\/second, else it ramps up to 3 degrees at 6 m\/s or above.<\/p>\n<p>Magentometer: 5 degrees if motor is off, 180 degrees if on<\/p>\n<p>SUNDAR: Based on the error it reports based on the signal to noise ratio<\/p>\n<p>IMU: Starts with the accuracy of the device that last reset its heading. The accuracy then decreases by 90 degrees per minute before it gets reset by the best azimuth device.<\/p>\n<p>My heading now becomes the weighted average using the equation:<\/p>\n<p>heading = (h1*W1 + h2*W2 + h3*W3 + h4*W4)\/(W1+W2+W3+W4)<\/p>\n<p>The problem is this does not work for headings. To see why assume two equally weighted sensors providing the headings of 350 and 10 degrees. The average would be (350*1 + 10*1)\/(1+1) or 180 degrees! Oops; wrong direction! We really should have gotten 0 or 360 degrees.<\/p>\n<p>So how does one average headings? A future post will address that.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have been struggling with how to fuse all the data into one cohesive mess. In the case of heading I have several source. I have a magnetometer, the heading from GPS,\u00a0the integrated value from the gyro, and if I &hellip; <a href=\"https:\/\/fll-freak.com\/blog\/?p=870\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-870","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/fll-freak.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/870","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fll-freak.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fll-freak.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fll-freak.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fll-freak.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=870"}],"version-history":[{"count":2,"href":"https:\/\/fll-freak.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/870\/revisions"}],"predecessor-version":[{"id":889,"href":"https:\/\/fll-freak.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/870\/revisions\/889"}],"wp:attachment":[{"href":"https:\/\/fll-freak.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=870"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fll-freak.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=870"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fll-freak.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=870"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}