Generación de Trayectoria

La versión 2020 de WPILib contiene clases que ayudan a generar trayectorias. Una trayectoria es una curva suave, con velocidades y aceleraciones en cada punto a lo largo de la curva, conectando dos puntos finales en la cancha. La generación y el seguimiento de trayectorias es increíblemente útil para realizar tareas autónomas. En lugar de una simple rutina autónoma - que implica avanzar, detenerse, girar 90 grados a la derecha, y luego avanzar - el uso de trayectorias permite el movimiento a lo largo de una curva suave. Esto tiene la ventaja de acelerar las rutinas autónomas, creando más tiempo para otras tareas; y cuando se implementa bien, hace que la navegación autónoma sea más precisa y exacta.

Este artículo trata sobre cómo generar una trayectoria. Los próximos artículos de esta serie repasarán cómo seguir realmente la trayectoria generada. Hay algunas cosas que tu robot debe tener antes de sumergirse en el mundo de las trayectorias:

  • Una forma de medir la posición y la velocidad de cada lado del robot. Un codificador es la mejor manera de hacerlo; sin embargo, otras opciones pueden incluir sensores ópticos de flujo, etc.

  • Una forma de medir el ángulo o la velocidad angular del chasis del robot. Un giroscopio es la mejor manera de hacerlo. Aunque la tasa angular puede ser calculada usando las velocidades del codificador, este método NO es recomendado debido al lavado de las ruedas.

Si busca una forma más simple para realizar una navegación autónoma, vea la sección en manejando una distancia.

Splines

Un spline se refiere a un conjunto de curvas que se interpolan entre puntos. Piense en esto como conectar puntos, excepto con las curvas. WPILib apoya dos tipos de splines: cúbico sujetado por la hérmite y quístico sujetado por la hérmite.

  • Hermite clamped cubic: Esta es la opción recomendada para la mayoría de los usuarios. La generación de trayectorias utilizando estas splines implica especificar las coordenadas (x, y) de todos los puntos, y los encabezamientos en los puntos de inicio y final. Los encabezamientos en los waypoints interiores se determinan automáticamente para asegurar una curvatura continua (tasa de cambio de rumbo) en todo momento.

  • Hermite quintic: Esta es una opción más avanzada que requiere que el usuario especifique coordenadas (x, y) y encabezamientos para todos los waypoints. Esto debería utilizarse si no se está satisfecho con las trayectorias que están siendo generadas por las clamped cubic splines o si se desea un control más fino de los encabezamientos en los puntos interiores.

Los splines son usados como una herramienta para generar trayectorias; sin embargo, el propio spline no tiene ninguna información sobre las velocidades y aceleraciones. Por lo tanto, no se recomienda utilizar las clases de spline directamente. Para generar una trayectoria suave con velocidades y aceleraciones, se debe generar una trayectoria.

Creando la configuración de la trayectoria

Se debe crear una configuración para generar una trayectoria. La configuración contiene información sobre las restricciones especiales, la velocidad máxima, la aceleración máxima además de la velocidad inicial y la velocidad final. La configuración también contiene información sobre si la trayectoria debe ser invertida (el robot viaja hacia atrás a lo largo de los puntos de ruta). La clase TrajectoryConfig debe ser usada para construir una configuración. El constructor de esta clase toma dos argumentos, la velocidad máxima y la aceleración máxima. Los otros campos (startVelocity, endVelocity, reversed, constraints) son predeterminados a valores razonables (0, 0, false, {}) cuando se crea el objeto. Si desea modificar los valores de cualquiera de estos campos, puede llamar a los siguientes métodos:

  • setStartVelocity(double startVelocityMetersPerSecond) (Java) / SetStartVelocity(units::meters_per_second_t startVelocity) (C++)

  • setEndVelocity(double endVelocityMetersPerSecond) (Java) / SetEndVelocity(units::meters_per_second_t endVelocity) (C++)

  • setReversed(boolean reversed) (Java) / SetReversed(bool reversed) (C++)

  • addConstraint(TrajectoryConstraint constraint) (Java) / AddConstraint(TrajectoryConstraint constraint) (C++)

Nota

La propiedad «invertida» simplemente representa si el robot está viajando hacia atrás. Si especificas cuatro puntos, a, b, c y d, el robot seguirá viajando en el mismo orden a través de los puntos cuando la bandera «invertida» se ponga en «verdadero». Esto también significa que debe tener en cuenta la dirección del robot cuando proporcione los puntos de ruta. Por ejemplo, si su robot está de cara a la pared de la estación de la alianza y viaja hacia atrás a algún elemento del campo, el waypoint inicial debe tener una rotación de 180 grados.

Generando la trayectoria

El método usado para generar una trayectoria es generateTrajectory(...). Hay cuatro sobrecargas para este método. Dos que usan clamped cubic splines y otras dos que usan quintic splines. Por cada tipo de spline, hay dos formas para construir una trayectoria. Los métodos más sencillos son las sobrecargas que aceptan objetos Pose2d.

Para los clamped cubic splines, este método acepta dos objetos Pose2d, uno para el punto de inicio y otro para el punto final. El método toma un vector de objetos «Translation2d» que representan los puntos de ruta interiores. Los encabezamientos de estos waypoints interiores se determinan automáticamente para asegurar una curvatura continua. Para las curvas quínticas, el método simplemente toma una lista de objetos Pose2d, con cada Pose2d representando un punto y un encabezamiento en la cancha.

La sobrecarga más compleja acepta «vectores de control» para los splines. Este método se utiliza cuando se generan trayectorias con Pathweaver, en las que se puede controlar la magnitud del vector tangente en cada punto. La clase ControlVector consiste de dos arreglos «dobles». Cada arreglo representa una dimensión (x o y), y sus elementos representan las derivadas en ese punto. Por ejemplo, el valor en el elemento 0 de la matriz x representa la coordenada x (0ª derivada), el valor en el elemento 1 representa la 1ª derivada en la dimensión x y así sucesivamente.

Al usarse clamped cubic splines, la longitud de la matriz debe ser 2 (0ª y 1ª derivadas), mientras que cuando se utilizan quintic splines, la longitud del conjunto debe ser 3 (0ª, 1ª y 2ª derivadas). A menos que sepas exactamente lo que estás haciendo, el primer y más simple método es ALTAMENTE recomendado para generar trayectorias manualmente. (es decir, cuando no se utilizan los archivos JSON de Pathweaver).

Aquí hay un ejemplo de cómo generar una trayectoria usando clamped cubic splines para el juego de 2018, FIRST Power Up.

class ExampleTrajectory {
  public void generateTrajectory() {

    // 2018 cross scale auto waypoints.
    var sideStart = new Pose2d(Units.feetToMeters(1.54), Units.feetToMeters(23.23),
        Rotation2d.fromDegrees(-180));
    var crossScale = new Pose2d(Units.feetToMeters(23.7), Units.feetToMeters(6.8),
        Rotation2d.fromDegrees(-160));

    var interiorWaypoints = new ArrayList<Translation2d>();
    interiorWaypoints.add(new Translation2d(Units.feetToMeters(14.54), Units.feetToMeters(23.23)));
    interiorWaypoints.add(new Translation2d(Units.feetToMeters(21.04), Units.feetToMeters(18.23)));

    TrajectoryConfig config = new TrajectoryConfig(Units.feetToMeters(12), Units.feetToMeters(12));
    config.setReversed(true);

    var trajectory = TrajectoryGenerator.generateTrajectory(
        sideStart,
        interiorWaypoints,
        crossScale,
        config);
  }
}

Nota

El código Java utiliza la utility Units , que se añadió a WPILib en 2020 para facilitar las conversiones de unidades.

Nota

Aunque esta generación de trayectorias es de órdenes de magnitud más rápida que la del Pathfinder, se recomienda encarecidamente generar todas las trayectorias al inicio (robotInit) ya que el tiempo de generación no es todavía insignificante. El tiempo de generación suele oscilar entre 10 y 25 ms para cada trayectoria.