Nonlinear optimization proof-of-concept

The goal of this page is to prove that the math behind the 3-d magnetic field camera concept for my final project actually works. That is to say, can we use an array of magnetic field sensors to find the position and orientation of a magnet?

Theory

Need to prove that given an array of magnetic field measurements, we can "work backwards" to find the magnetic dipole moment that created them. For now we'll just assume there's a single dipole moment, if that works we'll allow more complicated magnetic sources. The magnetic field at a point \(\vec{r}\) some distance from a magnetic dipole \(\vec{m}\) at the origin is: $$ \vec{B}(\vec{r}) = \frac{\mu_0}{4\pi} \left[ \frac{3 \vec{r}(\vec{m}\cdot\vec{r})}{r^5} - \frac{\vec{m}}{r^3} \right]$$ Given \(N\) magnetic field measurements \(\vec{Bobs}_i\) at locations \(\vec{r}_i\), and a source diple at location \(\vec{r}\), the field at these locations should be: $$ \vec{B}_i = \frac{\mu_0}{4\pi} \left[ \frac{3 (\vec{r}_i - \vec{r})[\vec{m}\cdot(\vec{r}_i - \vec{r})]}{|\vec{r}_i - \vec{r}|^5} - \frac{\vec{m}}{|\vec{r}_i - \vec{r}|^3} \right]$$ Our goal is to find \(\vec{r}\) and \(\vec{m}\) (6 unknowns) to minimize the cost function $$ J(\vec{r},\vec{m}) = \sum_{i=1}^N (\vec{Bobs_i} - \vec{B}_i)^2$$

Python implementation

We implement this in Python using the scipy.optimize library. I've written a test code called scipy_optimize_test.py that demonstrates that scipy.optimize.minimize, using the BFGS method, is able to find the 3-d position and direction of a magnetic dipole, given three or more vector observations of the field some distance away. Which is to say it works: we can use three magnetic field sensors to figure out where a single nearby magnet is, and which direction its north and south poles are. This seems to be very robust to noise and limited data.

Code output

True dipole location:
[0.  0.5 0. ]
True dipole moment:
[1.  0.2 0.4]
Sensor positions:
[[0.  0.  1. ]
 [0.  0.2 1. ]
 [0.2 0.  1. ]]
Noisy sensor field measurements:
[-0.71892588 -0.40225166  0.22562442]
[-0.87653349 -0.42249006  0.48106843]
[-0.52462101 -0.53349802  0.50905385]
Initial guess for dipole location
[-0.52528806 -1.0950005   0.21400471]
Initial guess for dipole moment
[1.51117041 0.4961279  0.47349426]
Optimization terminated successfully.
         Current function value: 0.000203
         Iterations: 172
         Function evaluations: 1421
         Gradient evaluations: 203
Optimized dipole location
[-0.0144755   0.50219301 -0.00484672]
Optimized dipole moment
[1.02772215 0.21357374 0.38935003]

Camera range

How far away will our camera be able to "see" a magnet? As mentioned in the final project components page, it's easy to get a sensor that can sense Earth's field (0.5 gauss), but the camera won't work if we are so far away that the field from a permanent magnet is tough to distinguish from Earth's field, so let's use 1 gauss as our lower sensitivity. The field from a small rare earth magnet can be about 1 Tesla or 10,000 gauss, 1 cm away from the center of the magnet. The field strength from a magnetic dipole drops off as the cube of the inverse distance, so a dipole that's 10,000 gauss at a distance of 1 cm will have a 1 gauss strength at a distance of \((10000)^{1/3} = 20\) cm away from the source. That's closer than I'd hoped, but it's acceptable.