Hello I am a rookie programmer and I am struggling! Does anyone know how to set the constant rate of acceleration for mecanum drive!!! Any help will be appreciated! THANKS :yikes:
More context and detail please.
When you have all wheels going forward or reverse, the rate of acceleration for mecanum is calculated essentially the same as that of traction wheels as long as you don’t lose traction and “spin out”. The maximum rate of acceleration (at low speeds) is going to be equal to the coefficient of friction in rolling motion times gravity. For most of the FRC mecanum wheels is going to be about 0.7 * 32 fps/sec, or 22 fps/sec. Because of the way mecanums interact with the floor, the maximum strafing acceleration is a bit lower than forward, and on a 45 degree bias, it will be off about 30%. Curiously, the fastest “acceleration” you can manage with mecanums is to spin; all of the wheels engage with the floor just as well as they ever do, all at the same time.
Hi guys, thanks for your help; I understand how the rate of acceleration is derived with physics but I want to know how to limit the Volts/sec on our Mecanum drive motor controllers. We are using CANTalons, we’re programming in Java–Command-Based, and we have implemented the setVoltageRampRate() method. That works pretty well to prevent the robot from zooming to a really high speed or stopping abruptly (which would cause totes to fall!) but the problem is driving is much tougher as drivers have to account for the time it takes for the robot to decelerate, making our positioning senses go out of whack.
Is there a way to program the mecanum drive so we can set a fixed low rate of acceleration without losing accurate drive position control? So we researched PID loops and such but since we have never implemented them before we wanted to know if this would solve our issue (I think it would?) and if so, how exactly… Do we have to create a new PID subsystem and somehow connect that to our motor controls?
Thank you! Any help will be greatly appreciated
Perhaps you can call the setVoltageRampRate() function every time you change the target voltage – to a lower value when increasing speed and to a somewhat higher rate when reducing speed.
It sounds like you should use an integrated motion unit like the NAV6 or NAVX, or use encoders on you wheels (and derive acceleration from them). You could then run a control loop (not sure what exactly it should be- maybe Take-back-half?) to keep your acceleration constant, up to top speed (where power produced by the motor(s) is equal to the power consumed by friction).
You can possibly do some tweaking with the voltage ramping, but even then, that’s just voltage, not acceleration. Your acceleration will be a function of input voltage, losses due to friction, (possibly traction), mass of vehicle, and current speed (because brushed motors produce linearly less torque as their speed rises).
This is a problem I’ve actually never seen tackled before, and one which we might look into using the nav6 board…
Many teams will impose a ramp on the joystick command input to limit the change in velocity (a.k.a acceleration) command. Some of the speed controllers can also do this for an individual wheel (which will mess up the mecanum kinematics). Yet another way is to use the accelerometer built into the roboRIO and reduce the command value if the acceleration is getting too close to the “spin out” speed. The accelerometer is probably better suited to detecting that you already spun out and therefor maybe the least useful option.
I would recommend imposing a software ramp on the joystick command even if you implement some other control method. It also helps to limit peak motor current - especially if the driver is going full velocity forward and throw the robot into full reverse - which will often pop a breaker.
Based on the various requests for this capability (which by the way hasn’t really been assessed for accuracy yet), what follows is a snippet of code which is an extension to the nav6’s IMUAdvanced class to calculate displacement. Your feedback is welcomed, if there’s enough interest we’ll create a separate thread on this topic, where the method and the results from the investigation can be gathered and reviewed:
private float last_velocity] = new float[2];
private float displacement] = new float[2];
/**
* Zeros the displacement integration variables. Invoke this at the moment when
* integration begins.
* @return none.
*/
public void resetDisplacement() {
for ( int i = 0; i < 2; i++ ) {
last_velocity* = 0.0f;
displacement* = 0.0f;
}
}
/**
* Each time new linear acceleration samples are received, this function should be invoked.
* This function transforms acceleration in G to meters/sec^2, then converts this value to
* Velocity in meters/sec (based upon velocity in the previous sample). Finally, this value
* is converted to displacement in meters, and integrated.
* @return none.
*/
private void updateDisplacement( float accel_x_g, float accel_y_g, int update_rate_hz ) {
float accel_g] = new float[2];
float accel_m_s2] = new float[2];
float curr_velocity_m_s] = new float[2];
float sample_time = (1.0f / update_rate_hz);
accel_g[0] = accel_x_g;
accel_g[1] = accel_y_g;
for ( int i = 0; i < 2; i++ ) {
accel_m_s2* = accel_g* * 9.8f;
curr_velocity_m_s* = last_velocity* * (accel_m_s2* * sample_time);
last_velocity* = curr_velocity_m_s*;
displacement* = displacement* + (curr_velocity_m_s* * sample_time);
}
}
/**
* Returns the displacement (in meters) of the X axis since resetDisplacement()
* was invoked.
* @return none.
*/
private float getDisplacementX() {
return displacement[0];
}
/**
* Returns the displacement (in meters) of the Y axis since resetDisplacement()
* was invoked.
* @return none.
*/
private float getDisplacementY() {
return displacement[1];
}
Yes! This is what we did for the simplest solution, and it’s working wonderfully! I might also try to limit the joystick-set correlation to acceleration.