Go to Post FIRST doesn't graduate you from HS ... your performance in class (your grades) do. - Franchesca [more]
Home
Go Back   Chief Delphi > Technical > Programming
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Closed Thread
 
Thread Tools Rate Thread Display Modes
  #1   Spotlight this post!  
Unread 27-05-2013, 15:18
apples000's Avatar
apples000 apples000 is offline
Registered User
no team
 
Join Date: Mar 2012
Rookie Year: 2012
Location: United States
Posts: 222
apples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant future
Java Swerve Drive Math Inconsistencies

Our team is working on putting a cRIO onto one of our old swerve bots from the past. We're writing the swerve software in Java and we came up with our own equation that gives us rotation and x/y control of the robot. However, when testing, we've found that it gave a different result than Ether's swerve spreadsheet. We figured that he was right, so we put his equations into the program and we still got the same incorrect results as we did the first time. The answer we get is close, but it is usually off by 20%. Right now we get three different answers when we run our code on the robot, on our computer, and in Ether's spreadsheet, but I can't find the difference. Does anybody know what causes these inconsistencies between platforms/applications, and how to stop them from happening?

Here is our java code for the robot, and attached is an application we made that gets very close, but wrong answers for the swerve calculation.

Code:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


import com.sun.squawk.util.MathUtils;
import edu.wpi.first.wpilibj.DoubleSolenoid;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.PIDController;
import edu.wpi.first.wpilibj.PIDOutput;
import edu.wpi.first.wpilibj.PIDSource;
import edu.wpi.first.wpilibj.SpeedController;
import edu.wpi.first.wpilibj.Victor;
import edu.wpi.first.wpilibj.command.Subsystem;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;


/**
 *
 * 
 */
public class Drive extends Subsystem {
    //declare the steering pods and shifter valve

    private Pod frontLeft, frontRight, rearLeft, rearRight;
    private DoubleSolenoid shift;

    public Drive() {
        //set up the steering pods with the correct sensors and controllers
        shift = new DoubleSolenoid(RobotMap.Solenoid.DRIVE_SHIFT_HIGH, RobotMap.Solenoid.DRIVE_SHIFT_LOW);
        frontLeft = new Pod(RobotMap.PWM.DRIVE_FRONT_LEFT,
                RobotMap.PWM.DRIVE_FRONT_LEFT_STEERING,
                RobotMap.DIO.DRIVE_FRONT_LEFT_ENC_A,
                RobotMap.DIO.DRIVE_FRONT_LEFT_ENC_B, 1);
        frontRight = new Pod(RobotMap.PWM.DRIVE_FRONT_RIGHT,
                RobotMap.PWM.DRIVE_FRONT_RIGHT_STEERING,
                RobotMap.DIO.DRIVE_FRONT_RIGHT_ENC_A,
                RobotMap.DIO.DRIVE_FRONT_RIGHT_ENC_B, 2);
        rearLeft = new Pod(RobotMap.PWM.DRIVE_REAR_LEFT,
                RobotMap.PWM.DRIVE_REAR_LEFT_STEERING,
                RobotMap.DIO.DRIVE_REAR_LEFT_ENC_A,
                RobotMap.DIO.DRIVE_REAR_LEFT_ENC_B, 3);
        rearRight = new Pod(RobotMap.PWM.DRIVE_REAR_RIGHT,
                RobotMap.PWM.DRIVE_REAR_RIGHT_STEERING,
                RobotMap.DIO.DRIVE_REAR_RIGHT_ENC_A,
                RobotMap.DIO.DRIVE_REAR_RIGHT_ENC_B, 4);
    }

    public void teleopDrive() {
        //get values from joysticks
        double x, y, rotate;
        boolean isLowGear, isHighGear;
        x = CommandBase.oi.stick1.getRawAxis(RobotMap.Control.DRIVE_CONTROLLER_AXIS_1);
        y = -CommandBase.oi.stick1.getRawAxis(RobotMap.Control.DRIVE_CONTROLLER_AXIS_2);
        rotate = CommandBase.oi.stick2.getRawAxis(RobotMap.Control.DRIVE_CONTROLLER_AXIS_1);
        isLowGear = CommandBase.oi.stick1.getRawButton(RobotMap.Control.DRIVE_CONTROLLER_SHIFT_LOW);
        isHighGear = CommandBase.oi.stick1.getRawButton(RobotMap.Control.DRIVE_CONTROLLER_SHIFT_HIGH);
        //calculate angle/speed setpoints using 28 by 38 inch robot 
        double L = 28, W = 38;
        double R = Math.sqrt((L * L) + (W * W));
        double A = x - rotate * (L / R);
        double B = x + rotate * (L / R);
        double C = y - rotate * (W / R);
        double D = y + rotate * (W / R);
        //find wheel speeds
        double frontRightWheelSpeed = Math.sqrt((B * B) + (C * C));
        double frontLeftWheelSpeed = Math.sqrt((B * B) + (D * D));
        double rearLeftWheelSpeed = Math.sqrt((A * A) + (D * D));
        double rearRightWheelSpeed = Math.sqrt((A * A) + (C * C));
        //normalize wheel speeds
        double max = frontRightWheelSpeed;
        if (frontLeftWheelSpeed > max) {
            max = frontLeftWheelSpeed;
        }
        if (rearLeftWheelSpeed > max) {
            max = rearLeftWheelSpeed;
        }
        if (rearRightWheelSpeed > max) {
            max = rearRightWheelSpeed;
        }
        frontRightWheelSpeed /= max;
        frontLeftWheelSpeed /= max;
        rearLeftWheelSpeed /= max;
        rearRightWheelSpeed /= max;
        //find steering angles
        double frontRightSteeringAngle = MathUtils.atan2(B, C)*180/Math.PI;
        double frontLeftSteeringAngle = MathUtils.atan2(B, D)*180/Math.PI;
        double rearLeftSteeringAngle = MathUtils.atan2(A, D)*180/Math.PI;
        double rearRightSteeringAngle = MathUtils.atan2(A, C)*180/Math.PI;
        //set shifter
        if(isLowGear){
            shift.set(DoubleSolenoid.Value.kForward);
        }
        if(isHighGear){
            shift.set(DoubleSolenoid.Value.kReverse);
        }
        //set pods
        frontRight.setSteeringAngle(frontRightSteeringAngle);
        frontRight.setWheelSpeed(frontRightWheelSpeed);
        frontLeft.setSteeringAngle(frontLeftSteeringAngle);
        frontLeft.setWheelSpeed(frontLeftWheelSpeed);
        rearLeft.setSteeringAngle(rearLeftSteeringAngle);
        rearLeft.setWheelSpeed(rearLeftWheelSpeed);
        rearRight.setSteeringAngle(rearRightSteeringAngle);
        rearRight.setWheelSpeed(rearRightWheelSpeed);

    }

    private class Pod implements PIDOutput, PIDSource {

        private Encoder steeringEnc;
        private SpeedController drive;
        private SpeedController steer;
        private PIDController pid;

        public Pod(int drivePWM, int steeringPWM, int steeringEncA,
                int steeringEncB, int podNumber) {
            steeringEnc = new Encoder(steeringEncA, steeringEncB);
            steeringEnc.setDistancePerPulse(RobotMap.Constants.STEERING_ENC_REVOLUTIONS_PER_PULSE);
            drive = new Victor(drivePWM);
            steer = new Victor(steeringPWM);
            pid = new PIDController(RobotMap.Constants.STEERING_PID_P,
                    RobotMap.Constants.STEERING_PID_I,
                    RobotMap.Constants.STEERING_PID_D, this, this);
            SmartDashboard.putData("Steering Pod " + podNumber, pid);
            pid.setInputRange(-180, 180);
            pid.setContinuous(true);
            pid.enable();

        }

        public void pidWrite(double output) {
            steer.set(output);
        }

        public double pidGet() {
            return steeringEnc.getDistance();
        }

        public void setSteeringAngle(double angle) {
            pid.setSetpoint(angle);
        }

        public void setWheelSpeed(double speed) {
            drive.set(speed);
        }
    }

    public void initDefaultCommand() {
    }
}
Attached Files
File Type: zip swerve.zip (6.9 KB, 241 views)
  #2   Spotlight this post!  
Unread 28-05-2013, 08:48
Jon Stratis's Avatar
Jon Stratis Jon Stratis is offline
Electrical/Programming Mentor
FRC #2177 (The Robettes)
Team Role: Mentor
 
Join Date: Feb 2007
Rookie Year: 2006
Location: Minnesota
Posts: 3,753
Jon Stratis has a reputation beyond reputeJon Stratis has a reputation beyond reputeJon Stratis has a reputation beyond reputeJon Stratis has a reputation beyond reputeJon Stratis has a reputation beyond reputeJon Stratis has a reputation beyond reputeJon Stratis has a reputation beyond reputeJon Stratis has a reputation beyond reputeJon Stratis has a reputation beyond reputeJon Stratis has a reputation beyond reputeJon Stratis has a reputation beyond repute
Re: Java Swerve Drive Math Inconsistencies

Try printing out the values of every variable at each step, each of the different ways you're trying it. Then you can compare them and see where the error is being introduced.

A double does not have infinite precision... I wonder if the issue is just a rounding one when you run out of space in the variable.
__________________
2007 - Present: Mentor, 2177 The Robettes
LRI: North Star 2012-2016; Lake Superior 2013-2014; MN State Tournament 2013-2014, 2016; Galileo 2016; Iowa 2017
2015: North Star Regional Volunteer of the Year
2016: Lake Superior WFFA
  #3   Spotlight this post!  
Unread 28-05-2013, 10:33
Ether's Avatar
Ether Ether is offline
systems engineer (retired)
no team
 
Join Date: Nov 2009
Rookie Year: 1969
Location: US
Posts: 8,077
Ether has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond repute
Re: Java Swerve Drive Math Inconsistencies


Is there a reason you left out the "if(max>1)" part of the normalization?

Code:
if(max>1){ws1/=max; ws2/=max; ws3/=max; ws4/=max;}
  #4   Spotlight this post!  
Unread 28-05-2013, 14:56
apples000's Avatar
apples000 apples000 is offline
Registered User
no team
 
Join Date: Mar 2012
Rookie Year: 2012
Location: United States
Posts: 222
apples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant futureapples000 has a brilliant future
Re: Java Swerve Drive Math Inconsistencies

Quote:
Originally Posted by Ether View Post

Is there a reason you left out the "if(max>1)" part of the normalization?

Code:
if(max>1){ws1/=max; ws2/=max; ws3/=max; ws4/=max;}
Yup, that was the problem. Now it works great. The difference between the swerve calculator program and Ether's spreadsheet and the cRIO is < 0.01, so I'm happy. It also explains why the swerve calculator sometimes comes up with a solution that has a wheel speed > 1.
Closed Thread


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -5. The time now is 03:08.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi