Tech Toolbox
  • Please Visit https://ftc-tech-toolbox.vercel.app/ for the new tech toolbox!!
    • Introduction
    • Choosing an IDE
    • Creating an OpMode
    • Motors and Encoders
    • Servos
    • Gamepad Controls
    • Drive Systems
    • Lynx Modules
    • Telemetry
    • Wireless Download
    • The Sleep Command
  • Please Visit the New Link
    • Tank Drive / Skid Steer (Part 1)
    • Mecanum Drive (Part 1)
    • Turrets
    • Linear Slides
    • Kicker
    • Active Intake / Sweepers
    • Flywheels / Shooters
  • Please Visit the new Link
    • Base Class (Step 1)
    • Module Classes (Step 2)
    • OpMode Classes (Step 3)
  • This domain is now depreciated and is no longer updated!
  • This domain is now depreciated and is no longer updated!
    • What is Localization?
    • General Odometry Logic
    • Tank (No Deadwheels)
    • Mecanum (No Deadwheels)
    • Deadwheel Odometry (Mecanum and Tank)
    • VSLAM
  • This domain is now depreciated and is no longer updated!
    • What is Control Theory?
    • Custom PID Loops
    • Essential Control Theory Concepts
    • Resources for Learning Advanced Control Theory
  • This domain is now depreciated and is no longer updated! Please visit this domain for the new TT!
    • Introduction
    • Mecanum Drive (Part 2)
    • Tank Drive (Part 2)
    • Introduction to Pure Pursuit
    • Pure Pursuit: Mecanum
    • Pure Pursuit: Tank
    • Advanced Pure Pursuit
    • Guided Vector Fields
    • Autonomous Movement Libraries
  • Sensors
    • IMU
    • Color Sensors
      • Advanced Sensing Code
    • Distance Sensors
    • Touch Sensor
  • Computer Vision
    • Setting up Camera/Intro to Computer Vision Tools
      • Intro to OpenCV
      • Vuforia
    • Streaming Frames
    • Color Thresholding
    • April Tags
    • Linear Regression
    • Machine Learning Toolchain
    • Object Distance Estimation
    • Object Tracking / Driving to an Object
    • Computer Vision Simulators
  • Simulators
    • Beta8397 Simulator
    • VRS
  • Cool Codebases
Powered by GitBook
On this page
  1. This domain is now depreciated and is no longer updated!

Mecanum (No Deadwheels)

PreviousTank (No Deadwheels)NextDeadwheel Odometry (Mecanum and Tank)

Last updated 1 year ago

Notes:

  • This method is derived from the following paper:

  • All angle calculations are done in radians.

  • Note that the only manually calibrated value you will need is the number of ticks your encoder reads after the robot travels an inch.

    • An easy way of calculating this value is by slowly driving your robot forward by 1 foot and diving your motor's encoder reading by 12.

  • After conducting testing, we found that replacing the angle calculated through odometry with the angle calculated through the IMU significantly improves accuracy. Consequently, the implementation will solely rely on the IMU angle.

    • Nevertheless, you can refer to equation 24 in the aforementioned paper to determine the methodology for deriving the angle based on drive encoder velocities.

This specific odometry technique involves using encoders attached to the drive motors of our robot to capture the individual velocities of the drive motors. We then input these values into the kinematic model of a mecanum robot, which consists of a set of equations that provide the overall velocities of the robot. By applying basic physics principles, we continuously accumulate these velocities over time to determine the position of the robot.

The step-by-step mathematical process is outlined below:

Firstly we will attain the individual velocities of our drive motors:

fLeftMotor.retMotorEx().getVelocity() // repeat for the other four motors

We will represent these velocities mathematically as follows:

  • w1w_1 w1​: Front left motor velocity

  • w2w_2w2​: Front right motor velocity

  • w3w_3w3​: Back left motor velocity

  • w4w_4w4​: Back right motor velocity

  • rrr: wheel radius

We will then plug these velocities into the equations provided by the paper. Note that the derivation for these equations is rather extensive. As a result, we will be skipping over them. However, we encourage you to read through the paper to learn where these equations come from.

vx(t)=(w1+w2+w3+w4)⋅r4v_x(t) = (w_1+w_2+w_3+w_4)\cdot \frac{r}{4}vx​(t)=(w1​+w2​+w3​+w4​)⋅4r​
double xV = (fLeftMotor.retMotorEx().getVelocity() + fRightMotor.retMotorEx().getVelocity()
            + bLeftMotor.retMotorEx().getVelocity() + bRightMotor.retMotorEx().getVelocity()) * (r/((double)4)));

double yV =  (-fLeftMotor.retMotorEx().getVelocity() + fRightMotor.retMotorEx().getVelocity()
            + bLeftMotor.retMotorEx().getVelocity() - bRightMotor.retMotorEx().getVelocity()) * (r/((double)4)));

These formulas assume that the robot doesn't change in angle. To account for this we must rotate the velocity vectors by the robot's current angle, which is attained from the IMU.

vx′=vxcosθ−vysinβvy′=vxsinθ+vycosθ\begin{split}v_x'=v_xcos \theta - v_ysin \beta \\ v_y'=v_xsin \theta + v_ycos \theta\end{split}vx′​=vx​cosθ−vy​sinβvy′​=vx​sinθ+vy​cosθ​
double nx = (xV*Math.cos(Math.toRadians(getAngle())))-(yV*Math.sin(Math.toRadians(getAngle())));

double nY = (xV*Math.sin(Math.toRadians(getAngle())))+(yV*Math.cos(Math.toRadians(getAngle())));

For those not familiar with integration:

Integration is like adding up small pieces to find the total. Let's say you have a line with a bunch of dots on it. Each dot represents a number. When you integrate, you're adding up all those numbers to find the sum.

For example, imagine you have a line with dots representing the speed of a moving car at different times. By adding up all the speeds at each moment, you can find out how far the car has traveled in total.

Integration helps us find the total when we have lots of small pieces that we want to combine together. It's like counting all the dots on the line to know the whole story.

It is a commonly known concept that integrating velocity over time yields the distance traveled during that timeframe. By keeping track of the elapsed time between function calls and multiplying it by the calculated velocity, we can obtain the distance covered. Accumulating this value into a running sum allows us to determine the current position of the robot.

dx(t)=∫0tvx(t)dtd_x(t) = \int_{0}^{t}v_x(t) dtdx​(t)=∫0t​vx​(t)dt
dy(t)=∫0tvy(t)dtd_y(t) = \int_{0}^{t}v_y(t) dtdy​(t)=∫0t​vy​(t)dt

Note that this value only returns the position in encoder ticks, to convert to inches we must divide the value by our manually calibrated tick-to-inch conversion factor.

double conversionFactor = 162.15; 
curPose.yP+=(yV*(driveTime.seconds()-prevTime))/conversionFactor; // <-- Tick to inch conversion factor
curPose.xP+=(xV*(driveTime.seconds()-prevTime))/conversionFactor;
prevTime = driveTime.seconds();

Implementation

double conversionFactor = 162.15, prevTime = 0;  
ElapsedTime driveTime = new ElapsedTime(); 

    // https://research.ijcaonline.org/volume113/number3/pxc3901586.pdf
public void updatePositionEncoderOdoBackup(){
    // apply mecnaum kinematic model (with wheel velocities [ticks per sec])
   double xV = (fLeftMotor.retMotorEx().getVelocity() + fRightMotor.retMotorEx().getVelocity()
           + bLeftMotor.retMotorEx().getVelocity() + bRightMotor.retMotorEx().getVelocity()) * 0.5;
   
   double yV =  (-fLeftMotor.retMotorEx().getVelocity() + fRightMotor.retMotorEx().getVelocity()
           + bLeftMotor.retMotorEx().getVelocity() - bRightMotor.retMotorEx().getVelocity()) * 0.5;

   // rotate the vector
   double nx = (xV*Math.cos(Math.toRadians(getAngle())))-(yV*Math.sin(Math.toRadians(getAngle())));
   double nY = (xV*Math.sin(Math.toRadians(getAngle())))+(yV*Math.cos(Math.toRadians(getAngle())));
   xV = nx; yV = nY;

   // integrate velocity over time
   curPoseY +=(yV*(driveTime.seconds()-prevTime))/conversionFactor; // <-- Tick to inch conversion factor
   curPoseX +=(xV*(driveTime.seconds()-prevTime))/conversionFactor;
   prevTime = driveTime.seconds();
}

Kinematic Model of a Four Mecanum Wheeled Mobile Robot