File-By-File
Trajectory

Trajectory

A Trajectory specifies to a FollowerExecutor a set of information: the trajectory's next "marker position," the trajectory's current speed, and whether the trajectory has reached its target position. Trajectories are movement-oriented and their completion should correspond with the robot's state. A marker position is a point that Pathfinder will use in determining where to go next. Simple trajectories (such as LinearTrajectory) don't have very complicated uses of speed(PointXYZ) or nextMarker(PointXYZ), but more advanced types of trajectories, such as trajectories based on splines, can use these methods to specify a curve for the robot to follow.

Each Trajectory is executed via a Follower. A follower is responsible for interpreting a trajectory, as well as the robot's current position, to determine how the robot should move. Long story short, Trajectory instances cannot directly control how Pathfinder operates the robot - rather, you'll have to encapsulate each trajectory in an individual follower. These followers are then executed via a FollowerExecutor, which, in turn, are managed via an ExecutorManager.

As of Pathfinder2 v1.1.0, you can also add primitive listeners to a trajectory using the following methods:

  • onStart(Consumer)
  • onFinish(Consumer)
  • withModifiers(Function, Function, Function)
  • addListeners(Consumer, Consumer)

These listeners are relatively ineffective, as the addition of each layer requires the instantiation of a new trajectory. Although this should not pose a performance problem in any cases, it's worth mentioning. These listeners are bound to the trajectory itself and are based on the state of the trajectory; therefore, you do not need to use Pathfinder's listening package in order to use these listeners.

There's a set of default methods that can be used to reproduce an existing Trajectory, but with some modifications. For example, take multiply(double), which multiplies all inputted and outputted values, essentially scaling the trajectory. There's also reflectX(double) and reflectY(double), which allow you to create trajectories that are exact mirrors of each other without having to recreate or recalculate any of the positions.

Methods

nextMarker(PointXYZ current)

Returns the next marker that the robot should attempt to navigate to. This should always be a point along the trajectory. This method may be stateful, meaning its invocation modifies the Trajectory it belongs to.

isDone(PointXYZ current)

Checks if the robot has finished executing this trajectory. This method should return true if the robot has finished executing the trajectory and can move on to the next trajectory or stop. If the robot hasn't finished its trajectory, meaning it should still continue executing it, this method should return false. This method should typically not return false after returning true.

speed(PointXYZ current)

Determines the speed at which the robot should be moving while executing this section of the trajectory. This method should not change the state of the Trajectory it belongs to. In most (if not all) cases, this should return the same output given the same input and should not be dependent on the state of the trajectory.

toMultiSegmentTrajectory(Trajectory... additionalTrajectories)

Converts this trajectory to a MultiSegmentTrajectory, adding all of the provided additional trajectories as segments.

onStart(Consumer<PointXYZ> onStart)

Adds a listener that executes onStart code the very first time the trajectory's nextMarker(PointXYZ) method is called.

onFinish(Consumer<PointXYZ> onFinish)

Adds a listener that executes onFinish code the first time the trajectory's isDone(PointXYZ) method returns true.

addListeners(Consumer<PointXYZ> onStart, Consumer<PointXYZ> onFinish)

Adds listeners to a trajectory by creating a wrapper trajectory and monitoring for certain conditions. onStart is executed once at the beginning, and onFinish is executed once when the trajectory completes.

addListeners(Consumer<PointXYZ> onStart, Consumer<Boolean> onIsDone, Consumer<Double> onSpeed, Consumer<PointXYZ> onFinish)

Adds more comprehensive listeners to a trajectory. onStart is executed once at the beginning, onIsDone is executed every time isDone is called, onSpeed is executed every time speed is called, and onFinish is executed once when the trajectory completes.

withModifiers(Function<PointXYZ, PointXYZ> nextMarkerModifier, Function<Boolean, Boolean> isDoneModifier, Function<Double, Double> speedModifier)

Returns a new Trajectory based on this Trajectory but with modifier functions applied to the inputs and outputs of its nextMarker, isDone, and speed methods.

withTimeLimits(double minimumTimeMs, double maximumTimeMs)

Returns a new Trajectory that wraps this trajectory and enforces time limits. The trajectory will only execute if it has not exceeded maximumTimeMs and will execute for at least minimumTimeMs.

reflectX(double xReflectionAxis)

Returns a new Trajectory that is a reflection of this trajectory over a specified X-axis. This does not modify the original trajectory.

reflectY(double yReflectionAxis)

Returns a new Trajectory that is a reflection of this trajectory over a specified Y-axis. This does not modify the original trajectory.

offset(PointXYZ offset)

Returns a new Trajectory with an applied offset. This shifts all points in the trajectory by the given offset.

getTrajectory(PointXYZ offset, Function<PointXYZ, PointXYZ> nextMarkerFunction, Function<PointXYZ, Boolean> isDoneFunction, Function<PointXYZ, Double> speedFunction, Supplier<String> _toString)

Internal helper method for creating a new Trajectory with applied transformations.

rotateAround(PointXY center, Angle angle)

Returns a new Trajectory that is rotated around a specified center point by a given angle.

shift(PointXY origin, PointXY target)

Returns a new Trajectory that is shifted from an origin point to a target point.

multiply(PointXYZ multiplier)

Returns a new Trajectory where all X, Y, and Z components of its points are multiplied by the corresponding components of the multiplier PointXYZ.

multiplyX(double multiplier)

Returns a new Trajectory where the X components of its points are multiplied by the multiplier.

multiplyY(double multiplier)

Returns a new Trajectory where the Y components of its points are multiplied by the multiplier.

multiplyZ(Angle multiplier)

Returns a new Trajectory where the Z (heading) components of its points are multiplied by the multiplier angle.

multiply(double multiplier)

Returns a new Trajectory where all X, Y, and Z components of its points are multiplied by the multiplier.

multiplyXY(double multiplier)

Returns a new Trajectory where the X and Y components of its points are multiplied by the multiplier.

multiply(double xMultiplier, double yMultiplier, double zMultiplier)

Returns a new Trajectory where the X, Y, and Z components of its points are multiplied by their respective multipliers.

add(double xMultiplier, double yMultiplier, double zMultiplier)

Returns a new Trajectory where the X, Y, and Z components of its points are added by their respective multipliers.

shiftToRobot(PointXYZ origin, PointXYZ target)

Returns a new Trajectory that is shifted and rotated to align with a robot's current position and orientation.

addEndCondition(Supplier<Boolean> isFinished)

Adds a single end condition to the trajectory. The trajectory will be considered done if this condition returns true.

addEndConditions(Iterable<Supplier<Boolean>> conditions)

Adds multiple end conditions to the trajectory. The trajectory will be considered done if any of these conditions return true.

addRequirement(Supplier<Boolean> isStillActive)

Adds a single requirement to the trajectory. The trajectory will be considered done if this requirement returns false.

addRequirements(Iterable<Supplier<Boolean>> requirements)

Adds multiple requirements to the trajectory. The trajectory will be considered done if any of these requirements return false.

toAbstractTrajectory()

Converts this Trajectory into an AbstractTrajectory.

Inner Class: InternalTrajectoryUtils

This is an internal utility class containing static helper methods for creating Function objects that wrap the nextMarker, isDone, and speed methods of a Trajectory. This class exists to avoid cluttering the Trajectory interface with redundant default methods.

nextMarkerFunction(Trajectory trajectory)

Returns a Function that wraps the nextMarker method of the given trajectory.

isDoneFunction(Trajectory trajectory)

Returns a Function that wraps the isDone method of the given trajectory.

speedFunction(Trajectory trajectory)

Returns a Function that wraps the speed method of the given trajectory.