Quote:
Originally Posted by Toa Circuit
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...
|
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:
Code:
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[i] = 0.0f;
displacement[i] = 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[i] = accel_g[i] * 9.8f;
curr_velocity_m_s[i] = last_velocity[i] * (accel_m_s2[i] * sample_time);
last_velocity[i] = curr_velocity_m_s[i];
displacement[i] = displacement[i] + (curr_velocity_m_s[i] * 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];
}