2010-07-29 6 views
12

Estoy tratando de escribir un método que interpola de 0 a x (posición de un objeto en una dimensión) en el tiempo usando aceleración al comienzo y desaceleración al final (suavizar/facilitar) con las únicas restricciones que se proporciona el tiempo total, así como la duración de la aceleración y deceleración. el movimiento debe replicar el efecto de inercia y estoy considerando un Hermite curve para las porciones no lineales.Matemáticas: Facilitar la entrada, facilitar un desplazamiento usando la curva de Hermite con restricción de tiempo

double Interpolate(
    double timeToAccel, double timeCruising, double timeToDecel, 
    double finalPosition, 
    double currentTime) 
{ 
    //... 
} 

¿Alguien me puede indicar una parte del código que hace eso? No sé cómo integrar la curva de Hermite, por lo tanto, no sé cuánto moveré en la porción de aceleración o en la porción de desaceleración y, a su vez, no puedo determinar cuál será la velocidad en el lineal. parte.

Gracias.

Some reference para ilustrar mi pregunta.

Edición:

velocidades
  • de inicio y fin son nulos, y el tiempo actual también es parte de los parámetros en el método, he actualizado la firma.
  • básicamente la idea es imaginar un movimiento a velocidad constante en una distancia d, esto da una duración total. Luego agregamos las fases de aceleración y desaceleración, manteniendo la misma duración, por lo tanto, tenemos una nueva velocidad de crucero desconocida para determinar (porque movemos menos en las fases de Hermite que en las fases lineales que han reemplazado). Tal vez la cantidad de movimiento perdido en las fases de Hermite, en comparación con un movimiento lineal de la misma duración es la relación entre el área superior e inferior en las curvas, solo una idea de un no experto.

Editar: Roman y Bob10 han proporcionado soluciones de trabajo completas. Implementé el código de Roman. ¡Gracias a ambos, muchachos! Aprecio su apoyo perfecto y sus soluciones detalladas, me salvó largas búsquedas y ensayos.

+0

son las velocidades de punto final a cero? –

+1

Sí Victor, lo son. – 742

Respuesta

22

En primer lugar, vamos a hacer una función de Hermite spline cúbica:

/* 
    t - in interval <0..1> 
    p0 - Start position 
    p1 - End position 
    m0 - Start tangent 
    m1 - End tangent 
*/ 
double CubicHermite(double t, double p0, double p1, double m0, double m1) { 
    t2 = t*t; 
    t3 = t2*t; 
    return (2*t3 - 3*t2 + 1)*p0 + (t3-2*t2+t)*m0 + (-2*t3+3*t2)*p1 + (t3-t2)*m1; 
} 

Ahora su tarea es calcular el P0, P1, M0 y M1, tanto para la facilidad y la facilidad en porciones. Añadamos unas pocas variables para hacer los cálculos un poco más fácil de escribir:

double Interpolate(
    double timeToAccel, double timeCruising, double timeToDecel, 
    double finalPosition, 
    double currentTime) { 

    double t1 = timeToAccel; 
    double t2 = timeCruising; 
    double t3 = timeToDecel; 
    double x = finalPosition; 
    double t = currentTime; 

Tenemos que especificar dónde debe ser el objeto cuando se deja de acelerar y decelerar comienza. Puede especificarlos como quiera y seguir produciendo un movimiento suave, sin embargo, nos gustaría una solución un tanto "natural".

Supongamos que la velocidad de crucero es v. Durante el crusing, el objeto recorre la distancia x2 = v * t2. Ahora, cuando el objeto acelera de 0 a velocidad v, recorre la distancia x1 = v * t1/2. Lo mismo para la deceleración x3 = v * t3/2.Poner todo junto:

x1 + x2 + x3 = x

v * t1/2 + v * t2 + v * t3/2 = x

Desde que podemos calcular nuestra velocidad y las distancias :

double v = x/(t1/2 + t2 + t3/2); 
    double x1 = v * t1/2; 
    double x2 = v * t2; 
    double x3 = v * t3/2; 

Y ahora que lo sabemos todo, acabamos de comer en nuestra interpolador de Hermite spline cúbica

if(t <= t1) { 
     // Acceleration 
     return CubicHermite(t/t1, 0, x1, 0, v*t1); 
    } else if(t <= t1+t2) { 
     // Cruising 
     return x1 + x2 * (t-t1)/t2; 
    } else { 
     // Deceleration 
     return CubicHermite((t-t1-t2)/t3, x1+x2, x, v*t3, 0); 
    } 
} 

Probé esto en Excel, aquí está el código VBA equivalente para jugar. Hay algunas divisiones por cero para condiciones de contorno, dejo solución a esto como un ejercicio para el lector


Public Function CubicHermite(t As Double, p0 As Double, p1 As Double, _ 
m0 As Double, m1 As Double) As Double 
    t2 = t * t 
    t3 = t2 * t 
    CubicHermite = (2 * t3 - 3 * t2 + 1) * p0 + _ 
(t3 - 2 * t2 + t) * m0 + (-2 * t3 + 3 * t2) * p1 + (t3 - t2) * m1 
End Function 

Public Function Interpolate(t1 As Double, t2 As Double, t3 As Double, _ 
x As Double, t As Double) As Double 
    Dim x1 As Double, x2 As Double, x3 As Double 

    v = x/(t1/2 + t2 + t3/2) 
    x1 = v * t1/2 
    x2 = v * t2 
    x3 = v * t3/2 

    If (t <= t1) Then 
     Interpolate = CubicHermite(t/t1, 0, x1, 0, v*t1) 
    ElseIf t <= t1 + t2 Then 
     Interpolate = x1 + x2 * (t - t1)/t2 
    Else 
     Interpolate = CubicHermite((t-t1-t2)/t3, x1+x2, x, v*t3, 0) 
    End If 
End Function 
+0

romano, gracias. Correcto, el problema es cómo determinar la cantidad de movimiento en la porción lineal, para obtener la velocidad de crucero, y a su vez estamos de vuelta en la fase de aceleración y su velocidad final (la recíproca para la fase de desaceleración). Todo parece estar enclavado. Mi suposición es que necesitamos integrar las curvas y luego resolver una ecuación donde el resultado es todo el tiempo del movimiento. Pero estoy lejos de ser un matemático, así que puedo estar equivocado. Busqué con fuerza en la red, pero hasta ahora no hay pistas para seguir. – 742

+0

@Roman, creo que puede haber un error aquí. Usó x = v * t/2, pero esto se usa generalmente para la aceleración constante, y está usando una ecuación cúbica que no coincide con este criterio. Me interesaría ver si el resultado de este programa es consistente con las suposiciones de entrada. – tom10

+0

Muchas gracias de nuevo. No entiendo cómo determinar las tangentes para la curva en la función Interpolar. Leí una teoría difícil de entender (para mí) donde puedo ver m0 = c y m1 = 3a + 2b + c, pero no puedo entender cuál es la interpretación visual de los parámetros de las tangentes. ¿Esa es la pendiente en los puntos de inicio y final? Esperaba que ambas pendientes fueran iguales a 0 (horizontal). ¿O son horiz, y el valor es más bien la longitud de los vectores? Necesito esto para gestionar los valores de tangente en caso de que no se utilicen una o dos de las fases (aceleración, crucero, desaceleración) (duración = 0). Thks. – 742

8

Esto es sencillo usando aceleración constante normal. Entonces la pregunta es a qué velocidad (v) necesita acelerar para completar el viaje en el tiempo correcto, y esto le indicará la aceleración que necesita para alcanzar esa velocidad.

Si el tiempo total es T_T y el tiempo de aceleración es t_a, entonces usted tiene la distancia recorrida como los dos acelerar y decelerar partes, y la parte de velocidad constante:

x = 2*(a*t_a*t_a/2) + v*(t_t-2*t_a) 

Esto puede ser resuelto por la aceleración por sustituía en v = a * t_a, para encontrar

a = x/(t_a*(t_t - t_a)) 

Aquí hay un código Python que usa y traza el resultado de estas ecuaciones, que muestra tanto el uso de las ecuaciones y lo que el resultado es idéntico:

from pylab import * 

t_a, t_t, D = 3., 10., 1. # input values 

a = D/(t_a*(t_t - t_a)) 
segments = (t_a, a), (t_t-2*t_a, 0.), (t_a, -a) # durations and accelerations for each segment 

t0, x0, v0 = 0.0, 0.0, 0.0 #initial values for the segment 
tdata, xdata = [], [] 
for t_segment, a in segments: # loop over the three segments 
    times = arange(0, t_segment, .01) 
    x = x0 + v0*times + .5*a*times*times 
    xdata.append(x) 
    tdata.append(times+t0) 
    x0 = x[-1] # the last x calculated in the segment above 
    v0 += a*t_segment 
    t0 += t_segment 

plot(tdata[0], xdata[0], 'r', tdata[1], xdata[1], 'r', tdata[2], xdata[2], 'r') 
xlabel("time") 
ylabel("position") 
show() 

alt text http://i26.tinypic.com/34sqzpi.png

+0

Hola Tom, muchas gracias. Si obtuve la idea correctamente, se supone que la aceleración de las curvas de aceleración y desaceleración es una constante, y porque esto es una constante, todo se resolverá al determinarlo (y a su vez v) Sin embargo, no estoy seguro de que Hermite curva son parte del conjunto de curvas con segunda derivada constante. Me parece que esto estaría bien solo para una parábola (una vez más: tengo habilidades muy limitadas). Si estoy equivocado, y Hermite es realmente parte de esas curvas, ¿podría decirme amablemente cómo convertir la aceleración calculada anteriormente en parámetros de Hermite? Gracias. – 742

+1

Correcto, esta es una facilidad suave para facilitar la salida, pero no una curva de Hermite. En general, con soluciones polinómicas, lo mejor es elegir la curva de orden más baja que resuelva el problema. Puedo imaginar una razón por la que uno podría querer otras curvas, pero su problema no está especificado para una curva de Hermite, así que supuse que realmente no quería una. – tom10

+0

Creo que el movimiento podría ser más suave si usa multinomios de orden superior. Lo que propones llevaría a una curva con derivada discontinua de segundo orden. –

Cuestiones relacionadas