hide 2 posts
This commit is contained in:
parent
ad3ee291a0
commit
cafb70eb0a
54
_drafts/2020-01-07-RobotSimGUI.md
Normal file
54
_drafts/2020-01-07-RobotSimGUI.md
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
layout: post
|
||||
title: "Graphical drivebase simulation for FRC robots"
|
||||
description: "Showcasing part of the frc5024 codebase"
|
||||
date: 2020-01-07 22:13:00
|
||||
categories: frc
|
||||
redirect_from:
|
||||
- /post/vcv4101s90/
|
||||
- /vcv4101s90/
|
||||
---
|
||||
|
||||
The 2020 FRC season has kicked off, and the @frc5024 software team is already hard at work developing the software that will power this year's robot. Throughout the season, I'm hoping to showcase cool things we work on.
|
||||
|
||||
Today, I built a little tool to provide a graphical simulation of our robot's drivebase in 2D space. This post will outline how I did it.
|
||||
|
||||
## Robot simulation
|
||||
|
||||
As our code is developed with [WPILib](https://github.com/wpilibsuite/allwpilib), we make use of [HALSIM](https://github.com/wpilibsuite/allwpilib/tree/master/simulation/halsim_gui) to test out code before pushing to real hardware. This tool is great for checking for null pointer exceptions, and ensuring telemetry data is correctly pushed, but has some limitations. Mainly, we use a fair amount of un-supported hardware, and our own robotics library does not integrate with WPILib's "Sendable" system.
|
||||
|
||||
### Faking HAL device support
|
||||
|
||||
To give HALSIM support to our custom devices, we use WPILib's [SimDevice](https://github.com/wpilibsuite/allwpilib/blob/master/hal/src/main/java/edu/wpi/first/hal/SimDevice.java) wrapper. @PeterJohnson explained to me how to do this [in this thread](https://www.chiefdelphi.com/t/ctre-halsim/370106/2?u=ewpratten).
|
||||
|
||||
### Simulating sensors
|
||||
|
||||
For drivebase simulation, we need to simulate two devices. Our [encoders](https://www.usdigital.com/products/encoders/incremental/kit/E4T), and our [gyroscope](https://pdocs.kauailabs.com/navx-mxp/). Neither of these devices have HALSIM support, so I added my own [[1](https://github.com/frc5024/InfiniteRecharge/commit/837e9f571a03917c72b2df83d4e19650bab4ad66)] [[2](https://github.com/frc5024/InfiniteRecharge/commit/78c501a4bbaeee1d05e95a3c1ba07a897bc78a80)].
|
||||
|
||||
Now that the device I/O has been simulated, we need to simulate sensor readings.
|
||||
|
||||
#### Encoders
|
||||
|
||||
Encoder readings can be estimated, assuming we know these properties:
|
||||
|
||||
- Current motor speed (percent output)
|
||||
- Max motor speed (RPM)
|
||||
- Encoder Pulses per Revolution
|
||||
- Gearing ratio between simulated motor and sensor
|
||||
|
||||
Inside a quickly-updating loop, I used this pseudocode to determine the reading for an encoder:
|
||||
```java
|
||||
double current_time = getSeconds();
|
||||
|
||||
double dt = current_time - last_time;
|
||||
last_time = current_time;
|
||||
|
||||
|
||||
double rpm = (getMotorSpeed() * max_rpm) / gearbox_ratio;
|
||||
double revs = (rpm / 60.0) * dt;
|
||||
|
||||
encoder_ticks += (revs * tpr);
|
||||
```
|
||||
|
||||
#### Gyroscope
|
||||
|
89
_drafts/2020-01-14-ZEBRA-Darts.md
Normal file
89
_drafts/2020-01-14-ZEBRA-Darts.md
Normal file
@ -0,0 +1,89 @@
|
||||
---
|
||||
layout: post
|
||||
title: "Interpolating motor control commands from Dart data"
|
||||
description: "And other weird things to do with XY datasets"
|
||||
date: 2020-01-14 20:13:00
|
||||
categories: frc data
|
||||
redirect_from:
|
||||
- /post/eb3v140d/
|
||||
- /eb3v140d/
|
||||
---
|
||||
|
||||
At some FRC events, [ZEBRA Technologies](https://www.zebra.com/us/en.html) places dart trackers for their [MotionWorks](https://www.zebra.com/us/en/solutions/intelligent-edge-solutions/rtls.html) system on robots. They then provide real-time motion tracking data for all bots on the field. I got my hands on a few data archives from various events in 2019 that used the darts. Here is a little post about what I have been able to do with this data.
|
||||
|
||||
## The data
|
||||
For this post, I will be working with data from [Chezy Champs 2019](https://chezychamps.com/). I recived the tracking data in the following CSV format:
|
||||
|
||||
```csv
|
||||
X position (Feet), Y position (Feet), UNIX epoch time (UTC)
|
||||
```
|
||||
|
||||
## Data analysis
|
||||
|
||||
I wrote a little parser that converts the CSV data to pose data. A pose is a vector containing the following field-absolute components:
|
||||
|
||||
```c++
|
||||
struct Pose {
|
||||
double x;
|
||||
double y;
|
||||
double theta;
|
||||
}
|
||||
```
|
||||
|
||||
While we are at it, Ill define a "Transpose", which is like a pose, but relative to other poses, and a "ChassisSpeed" vector:
|
||||
|
||||
```c++
|
||||
struct ChassisSpeed {
|
||||
double left;
|
||||
double right;
|
||||
}
|
||||
|
||||
class Transpose {
|
||||
private:
|
||||
double x;
|
||||
double y;
|
||||
double theta;
|
||||
|
||||
public:
|
||||
ChassisSpeed fromTranspose();
|
||||
}
|
||||
```
|
||||
|
||||
### Converting a difference to a Transpose
|
||||
|
||||
The only data we can directly read from the Dart data is poses over time (all poses have an angle of 0 degrees). To convert these to Transposes, we need to do a little math. Basically, we can take two poses, then calculate their differences:
|
||||
|
||||
```python
|
||||
# Find the differences in coords
|
||||
dx: float = now.x - last.x
|
||||
dy: float = now.y - last.y
|
||||
|
||||
# Calculate a heading from translation
|
||||
theta: float = atan2(dx, dy)
|
||||
```
|
||||
|
||||
Now, with this data, we can build a Transpose out of any pair of data points.
|
||||
|
||||
### Converting a transpose to a ChassisSpeed
|
||||
|
||||
To be completely honest, I originally had no idea what I was going to use this data for, but ended up deciding to try to reconstruct motor data from the position data. This is just a form of [Inverse Kinematics](https://en.wikipedia.org/wiki/Inverse_kinematics).
|
||||
|
||||
To do this, all we need is a little math:
|
||||
|
||||
```java
|
||||
ChassisSpeed fromTranspose(){
|
||||
double delta = TRACK_WIDTH * this.theta / 2 * 1.0469745223;
|
||||
return (new ChassisSpeed(this.x - deltaV, this.x + deltaV);
|
||||
}
|
||||
```
|
||||
|
||||
This will calculate the heading difference between 0,0 and the transpose, then apply that to the X vector as a wheel velocity. `TRACK_WIDTH` is the width of the robot drivebase in inches (I used `25.4` because that is team [254](https://www.thebluealliance.com/team/254)'s track width)
|
||||
|
||||
#### Chassis speeds over time
|
||||
|
||||
Here is a little graph of the calculated chassis speeds over time. (Keeping in mind that inaccuracies in the Dart system cause some "drift")
|
||||
|
||||

|
||||
|
||||
### Extrapolating further
|
||||
|
32
_drafts/Untitled-1
Normal file
32
_drafts/Untitled-1
Normal file
@ -0,0 +1,32 @@
|
||||
00000000
|
||||
01000000
|
||||
00000001
|
||||
10001000
|
||||
00001100
|
||||
00000010
|
||||
|
||||
0x4001880C02
|
||||
|
||||
00000000
|
||||
01000000
|
||||
00000000
|
||||
10000000
|
||||
00000100
|
||||
00000010
|
||||
00000000
|
||||
01001011
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
00000100
|
||||
00001101
|
||||
00000100
|
||||
01110111
|
||||
00000000
|
||||
00000011
|
||||
|
||||
!'gO7"9JQrz!!!!%%0UkT!r
|
0
_includes/advert.html
Normal file
0
_includes/advert.html
Normal file
BIN
assets/images/chassis-speeds.png
Normal file
BIN
assets/images/chassis-speeds.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
Loading…
x
Reference in New Issue
Block a user