turtlebot:adventures:sensing101_forwarderror
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| turtlebot:adventures:sensing101_forwarderror [2015/10/06 23:26] – pvela | turtlebot:adventures:sensing101_forwarderror [2024/08/20 21:38] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 41: | Line 41: | ||
| If your goal here is to go to a static Turtlebot pose, then you should have some kind of stop-control condition that checks to see if the two errors are too small to bother fixing. | If your goal here is to go to a static Turtlebot pose, then you should have some kind of stop-control condition that checks to see if the two errors are too small to bother fixing. | ||
| + | |||
| + | ==== Generating the Desired End Pose ==== | ||
| + | |||
| + | Alright, the above is all fine and good, but the bigger question is: how do I create the desired pose signal to begin with? It actually works in the opposite way as computing the error. | ||
| + | \begin{equation} | ||
| + | \Delta g = g_{curr}^{-1} g_{des}. | ||
| + | \end{equation} | ||
| + | Now, let's rearrange it to solve for $g_{des}$, | ||
| + | \begin{equation} | ||
| + | g_{des} = g_{curr} \Delta g. | ||
| + | \end{equation} | ||
| + | Ha! This final equation is exactly what you want to do. Take the current position, as measured prior to actually performing any feedback, and left-multiply by the desired movement of the Turtlebot. | ||
| + | \begin{equation} | ||
| + | \Delta g_{forward} = \left[ \begin{matrix} 1 & \Delta x + 0j \\ 0 & 1 \end{matrix} \right] | ||
| + | \quad \text{and} \quad | ||
| + | \Delta g_{turn} = \left[ \begin{matrix} e^{j \Delta \theta} & 0 \\ 0 & 1 \end{matrix} \right], | ||
| + | \end{equation} | ||
| + | where $\Delta x$ is the distance to drive forward and $\Delta \theta$ is the angle (in radians most likely) to turn. In future instantiations, | ||
| + | |||
| + | This desired end pose will then be fixed until the proper terminating condition is achieved (e.g., the error is small enough to be negligible). | ||
| + | ==== Complex Matrices in Python ==== | ||
| + | |||
| + | OK, so you are thinking " | ||
| + | < | ||
| + | > import numpy | ||
| + | > import cmath | ||
| + | </ | ||
| + | After that you will be happy because then complex matrices will be supported. Let's build the simplest such matrix, which is the identity matrix of $SE(2)$. | ||
| + | < | ||
| + | > r = cmath.rect(1, | ||
| + | > t = complex(0, | ||
| + | > g = numpy.mat([[r, | ||
| + | > g | ||
| + | </ | ||
| + | If I am not mistaken, you should now have the identity matrix! | ||
| + | < | ||
| + | > r = cmath.rect(1, | ||
| + | > t = complex(5, | ||
| + | > g = numpy.mat([[r, | ||
| + | > g | ||
| + | </ | ||
| + | I recommend using '' | ||
| + | Taking the inverse you should see that the top left part of the matrix gets conjugated: | ||
| + | < | ||
| + | > gInverse = numpy.linalg.inv(g) | ||
| + | > gInverse | ||
| + | </ | ||
| + | If you can get the above working, then that's pretty much all you will need. Matrix multiplication should work how you think it does: | ||
| + | < | ||
| + | > gErr = gCurrInv * gDes | ||
| + | </ | ||
| + | or maybe even | ||
| + | < | ||
| + | > gErr = numpy.linalg.inv(gCurr) * gDes | ||
| + | </ | ||
| + | There is actually a computationally faster way of doing it that exploits the fact that $r$ is a rotation, but that's for another day, or maybe even for you to explore on your own. | ||
| --------- | --------- | ||
| ;#; | ;#; | ||
| [[Turtlebot: | [[Turtlebot: | ||
| ;#; | ;#; | ||
turtlebot/adventures/sensing101_forwarderror.1444188418.txt.gz · Last modified: 2024/08/20 21:38 (external edit)
