-
Notifications
You must be signed in to change notification settings - Fork 0
Steering offset ukf #84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: rolls
Are you sure you want to change the base?
Conversation
…-Club/robobuggy-software into steering_offset_ukf
…lowup, added auton check to steering offset ukf, started publishing both corrected and raw steering_cmd in controller, corrected wheelbase constants
… update ros_to_bnyahaj.py accordingly
…offset is jumpy in sim
…fset_estimator, introduced steer offset raw and filtered topics, modified launch files to include steer offset configs
… covariance at each update
|
|
||
| # accuracy is the circular error radius (meters) | ||
| # k is the factor that maps between this radius and the Gaussian σ | ||
| k = 0.848867684498 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the rest of the decimal points of this number fully accurate? does it matter much?
I could be wrong, but I looked up some stuff (and assuming this is like a CEP50 based conversation)
It might be worth writing the computation in a comment rather than just using a magic number?
is it the same as k = 1 / sqrt(2 * ln(2))?
https://www.wolframalpha.com/input?i=1+%2F+sqrt%282+*+ln%282%29%29
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw it in constants.py
rb_ws/convert.yaml
Outdated
| @@ -1,4 +1,4 @@ | |||
| output_bags: | |||
| - uri: nand-raceline-mcap | |||
| - uri: rosbag2_2025_11_15-12_47_46_0 | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will revert, but basically a script to convert bags to .mcap (needs bags uri to work) @hpuranik
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove dead code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| offset_variance = self.Sigma[-1, -1] | ||
|
|
||
| # Checks the offset variance is reasonable, corresponds to 6 deg std deviation. | ||
| if offset_variance < 0.1: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make sure we remove magic numbers from our code? It helps with readability and finding bugs.
During our review, we found that this number is actually wrong.
6 degrees standard deviation corresponds to 0.10472 radians, but because this is standard deviation—we need to square the resulting value to find the variance.
The correct constant should be closer to 0.010966
In general:
- Try not to use magic numbers
- If we HAVE to use magic numbers, we should set a standard that we have a comment explaining the formula and the numbers we used to avoid confusion
*similar logic to the k = 0.8 yada yada constant
Also consider moving constants like these into the constants python file.
-vivek
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, what are observed values currently?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do! Current values are rougly 0.05
| self.Q = np.diag([1e-4, 1e-4, 1e-4, 2.4e-1, 1e-6]) # init process covariance values (2.4e-1 for velocity based on 3 x std dev of 0.16) | ||
|
|
||
| # Offset variance extremely high out of caution and proof of convergence | ||
| self.Sigma: np.ndarray = np.diag([1e-4, 1e-4, 1e-2, 1e-2, 5e-2]) # state covariance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does offset covariance usually settle to / hover around? (I believe we only have sim data right now, but let's mock roll and observe and then finalize this init value)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In simulation it hovers around 0.01-0.05, i agree with waiting until mock roll.
the-beast-coder
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some questions about the changes
| self.Q = np.diag([1e-4, 1e-4, 1e-4, 2.4e-1, 1e-6]) # init process covariance values (2.4e-1 for velocity based on 3 x std dev of 0.16) | ||
|
|
||
| # Offset variance extremely high out of caution and proof of convergence | ||
| self.Sigma: np.ndarray = np.diag([1e-4, 1e-4, 1e-2, 1e-2, 5e-2]) # state covariance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where do these values come from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These values are based on the following calculation:
(Rough estimate abt std dev) -> 3x confidence interval -> Variance.
| self.auton_enabled_prev = auton | ||
|
|
||
| @classmethod | ||
| def wrap_angle(cls, angle, limit=np.pi): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does this function do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given an angle, it turns it into [-pi-pi range] (in radians). This ensure's that it's always an accurate angle [-pi, pi]
| offset_variance = self.Sigma[-1, -1] | ||
|
|
||
| # Checks the offset variance is reasonable, corresponds to 6 deg std deviation. | ||
| if offset_variance < 0.1: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if offset variance is more than 0.1? Doesnt that represent some sort of error happening
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the offset variance is greater than 0.1, this means we are very unsure of the offset. If this is the case, we don't want to publish any values because the data is too noisy.
| # measurement vector | ||
| y = [msg.pose.pose.position.x, msg.pose.pose.position.y] | ||
| # extract 2x2 position covariance from the 6x6 pose covariance | ||
| self.R = np.reshape(np.stack((msg.pose.covariance[:2], msg.pose.covariance[6:8]), axis=0), (2, 2)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What changed that made us take this out of the if condition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We noticed a bug in the original implementation, so that the self.R was only set once. Instead, since it's related to the measurement, it can update each time.
|
|
||
| # accuracy is the circular error radius (meters) | ||
| # k is the factor that maps between this radius and the Gaussian σ | ||
| k = 0.848867684498 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw it in constants.py
| self.auton_enabled_prev = auton | ||
|
|
||
| @classmethod | ||
| def wrap_angle(cls, angle, limit=np.pi): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given an angle, it turns it into [-pi-pi range] (in radians). This ensure's that it's always an accurate angle [-pi, pi]
| # measurement vector | ||
| y = [msg.pose.pose.position.x, msg.pose.pose.position.y] | ||
| # extract 2x2 position covariance from the 6x6 pose covariance | ||
| self.R = np.reshape(np.stack((msg.pose.covariance[:2], msg.pose.covariance[6:8]), axis=0), (2, 2)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We noticed a bug in the original implementation, so that the self.R was only set once. Instead, since it's related to the measurement, it can update each time.
| offset_variance = self.Sigma[-1, -1] | ||
|
|
||
| # Checks the offset variance is reasonable, corresponds to 6 deg std deviation. | ||
| if offset_variance < 0.1: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do! Current values are rougly 0.05
| self.Q = np.diag([1e-4, 1e-4, 1e-4, 2.4e-1, 1e-6]) # init process covariance values (2.4e-1 for velocity based on 3 x std dev of 0.16) | ||
|
|
||
| # Offset variance extremely high out of caution and proof of convergence | ||
| self.Sigma: np.ndarray = np.diag([1e-4, 1e-4, 1e-2, 1e-2, 5e-2]) # state covariance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These values are based on the following calculation:
(Rough estimate abt std dev) -> 3x confidence interval -> Variance.
| self.Sigma: np.ndarray = np.diag([1e-4, 1e-4, 1e-2, 1e-2, 1.2e-3]) # state covariance | ||
| self.Q = np.diag([1e-4, 1e-4, 1e-4, 2.4e-1, 1e-6]) # init process covariance values (2.4e-1 for velocity based on 3 x std dev of 0.16) | ||
|
|
||
| # Offset variance extremely high out of caution and proof of convergence |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove comment
rb_ws/convert.yaml
Outdated
| @@ -1,4 +1,4 @@ | |||
| output_bags: | |||
| - uri: nand-raceline-mcap | |||
| - uri: rosbag2_2025_11_15-12_47_46_0 | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will revert, but basically a script to convert bags to .mcap (needs bags uri to work) @hpuranik
Overview
Added a steering offset to the SC UKF. Raw offset is passed into a low pass filter. Filtered offset is added to the command steering angle and passed to Firmware. Simulation allows testing the use, values and variance of the offset.
Linked Issues
#70
Tasks
Testing
We will test the steering offset accuracy during mock rolls in FoxGlove, and then check the offset variance and UKF covariance to try to find a threshold to determine convergence.