Acceleration Curve java help

Hey does anyone know how to program an acceleration curve for cim motors??

What are you trying to accomplish?
If you really want to control/limit acceleration, you can set up a PIDController using the motor speed(s) as the system input and the acceleration (from the RoboRIO’s built-in accelerometer, for example) as the system output.

As GeeTwo asked, what is the problem you are trying to solve?

If you are simply wanting to prevent driver “jackrabbit” starts and stops so the totes won’t fall off the stack you are carrying, a simple solution would be to add a slew rate limiter to your joystick commands.

I’m assuming you want something like this.


double magnitude = Math.pow(2,(driveStick.getMagnitude())-1; 
chassis.mecanumDrive_Polar(magnitude, driveStick.getDirectionDegrees(), driveStick.getRotationDirection());

this should make a pretty decent magnitude:acceleration ratio.

It is an exponential function that increases the speed of the robot when reaching the upper bounds.

You can just edit this so that it works with your drive and controls. Or, if you post the code I will do it for you.

Since the OP has not responded to requests to clarify the nature of the problem he is interested in solving, you might want to qualify your suggestion with an explanation of what problem it is intended to solve… lest he take your suggestion and apply it to a problem different from what you inferred.

You might also caution that your suggestion maps the domain -1…+1 to the range 0.769…1.3

Yeah, I wasn’t thinking. I fixed that. Also, the domain is [0,1] because you cannot have a negative magnitude. But, that assumes that he is using mecanum drive. If not, another solution will be needed.


Joystick stick1, stick2;
double stick1val,stick2val;

stick1val = Math.pow(stick1.getX(),3);
stick2val = Math.pow(stick2.getY(),3);

chassis.tankDrive(stick1val, stick2val);

That would let you take input with a domain of -1,1] and use it with tank drive.

We are trying to fix the automatic jump the robot gets as soon as you move the joysticks.

Can you show us your code right now? Otherwise, tell me the type of drive you are using.

Tank Drive:


Joystick stick1, stick2;
double stick1val,stick2val;

stick1val = Math.pow(stick1.getX(),3);
stick2val = Math.pow(stick2.getY(),3);

chassis.tankDrive(stick1val, stick2val);

Mecanum Drive:


double magnitude = Math.pow(driveStick.getMagnitude(),3); 
chassis.mecanumDrive_Polar(magnitude, driveStick.getDirectionDegrees(), driveStick.getRotationDirection());

Then the slew limiter Ether suggested is probably your best solution:

This is our regular code

package org.usfirst.frc.team4640.robot;

import edu.wpi.first.wpilibj.CameraServer;
import edu.wpi.first.wpilibj.SampleRobot;
import edu.wpi.first.wpilibj.RobotDrive;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.Timer;

public class Robot extends SampleRobot {
RobotDrive myRobot; // class that handles basic drive operations
Joystick leftStick; // set to ID 1 in DriverStation
Joystick rightStick; // set to ID 2 in DriverStation
CameraServer server;

public Robot() {
    myRobot = new RobotDrive(0, 1);
    myRobot.setExpiration(0.1);
    leftStick = new Joystick(0);
    rightStick = new Joystick(1);
    server = CameraServer.getInstance();
    server.setQuality(50);
    //the camera name (ex "cam0") can be found through the roborio web interface
    server.startAutomaticCapture("cam0");
        
}


/**
 * Runs the motors with tank steering.
 */
public void operatorControl() {
    myRobot.setSafetyEnabled(true);
    while (isOperatorControl() && isEnabled()) {
    	myRobot.tankDrive(leftStick, rightStick);
        Timer.delay(0.005);		// wait for a motor update time
       
       
        }
    
    }
}


package org.usfirst.frc.team4640.robot;


import edu.wpi.first.wpilibj.CameraServer;
import edu.wpi.first.wpilibj.SampleRobot;
import edu.wpi.first.wpilibj.RobotDrive;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.Timer;



public class Robot extends SampleRobot {
    RobotDrive myRobot;  // class that handles basic drive operations
    Joystick leftStick = new Joystick(0);  // set to ID 0 in DriverStation
    Joystick rightStick = new Joystick(1); // set to ID 1 in DriverStation
    CameraServer server;
    double leftStickVal,rightStickVal;
    
    public Robot() {
        myRobot = new RobotDrive(0, 1);
        myRobot.setExpiration(0.1);
        leftStick = new Joystick(0);
        rightStick = new Joystick(1);
        server = CameraServer.getInstance();
        server.setQuality(50);
        //the camera name (ex "cam0") can be found through the roborio web interface
        server.startAutomaticCapture("cam0");
            
    }

    
    /**
     * Runs the motors with tank steering.
     */
    public void operatorControl() {
        myRobot.setSafetyEnabled(true);
        while (isOperatorControl() && isEnabled()) {

                leftStickVal = Math.pow(leftStick.getY(),3);
                rightStickVal= Math.pow(rightStick.getY(),3);
 
        	myRobot.tankDrive(leftStickVal, rightStickVal);
            Timer.delay(0.005);		// wait for a motor update time
           
           
            }
        
        }
    }

Use this code exactly and your problem should be solved.

For those trying to learn from this thread, the non-whitespace differences between the intitial (21:04) and updated (21:27) code are:

# diff -w initial.txt updated.txt
14,15c14,15
< Joystick leftStick; // set to ID 1 in DriverStation
< Joystick rightStick; // set to ID 2 in DriverStation
---
>     Joystick leftStick = new Joystick(0);  // set to ID 0 in DriverStation
>     Joystick rightStick = new Joystick(1); // set to ID 1 in DriverStation
16a17
>     double leftStickVal,rightStickVal;
37c38,42
< myRobot.tankDrive(leftStick, rightStick);
---
>
>                 leftStickVal = Math.pow(leftStick.getY(),3);
>                 rightStickVal= Math.pow(rightStick.getY(),3);
>
>               myRobot.tankDrive(leftStickVal, rightStickVal);

How about using Talon.setVoltageRampRate()? The only downside is it would also slow down deceleration, and I think it only works on CANTalons.

I wanted Can Motor controllers but we ended up using regular one. I was going to use the setVoltageRampRate function, because we are top heavy, but I had to create something else. The acceleration curve by Math.pow(val, x) wasn’t good enough for us, where x is an int. Why? because if the joystick slips, we don’t want the robot to rapidly accelerate. So, what I do is that I read the “ReachVal” from the joystick, then, read the “CurrentVal” from what I set to the CIMs (CurrentVal is initialized to 0). Then, I take the difference, divide that by 7500 (trial and error lead me to this constant), add that to “CurrentVal”, in my drive thread. This results in a smooth drive and we don’t topple over even though we are quite top heavy.

Hope that helps!

^^Here’s the code for the above:

*
*change = joystickAxis - limitedJoystickAxis;
if (change>limit) change = limit;
else if (change<-limit) change = -limit;
limitedJoystickAxis += change;

Exactly.