Setup
This section will guide you through the setup of the project. Voyager is a library that is meant to be as simple as possible to install and use. The following steps will guide you through the setup of the project.
Step 1: Setup your preferred choice of localization of your robot.
Voyager supports an abstracted form of localization: AbstractOdometry
.
Voyager does infact come with a built in 3 wheel odometry system, but you can also create your own odometry system by extending the AbstractOdometry
class.
It is highly recommeneded to use your own odometry system as it will be more accurate and reliable than the built in one.
The built in one has barely been tested and is not recommended for use in a competition.
Example: PinPointOdometry
public class PinpointOdometry extends AbstractOdometry {
private GoBildaPinpointDriver driver; //GobildaPinpointDriver is a driver for the GoBilda odometry system that has already been tuned.
public PinpointOdometry(HardwareMap hardwareMap) {
driver = hardwareMap.get(GoBildaPinpointDriver.class, "odo");
}
//This is where you will update the position of the robot.
@Override
public PointXYZ getRawPosition() {
Pose2D pose = driver.getPosition(); //Reason I store as a pose instead of doing it in one line is because the driver may return different position per call.
return new PointXYZ(pose.getX(DistanceUnit.INCH), pose.getY(DistanceUnit.INCH), pose.getHeading(AngleUnit.DEGREES));
}
}
Step 2: Setup your preferred choice of drive system.
Voyager supports an abstracted form of a drive system: AbstractDrive
.
However, there are also built in drive systems that you can use such as MecanumDrive
, TankDrive
, and SwerveDrive
.
For this example we will be using the MecanumDrive
. To first use the MecanumDrive
you will need to create a MecanumDrive
object and pass in your motors.
For simplicity, AbstractMotors
will do the job but it is highly recommended you create your own class to interface with your motors.
public class PathfinderRobot {
private DcMotor dcMotorFrontRight;
private DcMotor dcMotorFrontLeft;
private DcMotor dcMotorBackRight;
private DcMotor dcMotorBackLeft;
private Motor motorFrontRight;
private Motor motorFrontLeft;
private Motor motorBackRight;
private Motor motorBackLeft;
private Drive drive;
public void init(HardwareMap map) {
dcMotorFrontRight = map.get(DcMotor.class, "fr");
dcMotorFrontLeft = map.get(DcMotor.class, "fl");
dcMotorBackRight = map.get(DcMotor.class, "br");
dcMotorBackLeft = map.get(DcMotor.class, "bl");
dcMotorBackLeft.setDirection(DcMotor.Direction.REVERSE);
dcMotorFrontLeft.setDirection(DcMotor.Direction.REVERSE);
motorFrontRight = new AbstractMotor(
dcMotorFrontRight::setPower,
dcMotorFrontRight::getPower
);
motorFrontLeft = new AbstractMotor(
dcMotorFrontLeft::setPower,
dcMotorFrontLeft::getPower
);
motorBackRight = new AbstractMotor(
dcMotorBackRight::setPower,
dcMotorBackRight::getPower
);
motorBackLeft = new AbstractMotor(
dcMotorBackLeft::setPower,
dcMotorBackLeft::getPower
);
drive = new MecanumDrive(
motorFrontRight,
motorFrontLeft,
motorBackRight,
motorBackLeft
);
}
}
Step 3: Add your odometry, create a Robot, and finally initialize Voyager.
The Voyager class requires you to pass in a Robot
object and a FollowerGenerator
object.
The Robot
object requires a Drive
object and an Odometry
object.
The FollowerGenerator
object requires a Controller
object.
For your controller, it is recommended you tune the coefficient to fit your needs.
For this example, we will be using the GenericTurnController
with a coefficient of 0.05.
You can also use a more advanced PID controller, and in fact it is recommended you do so.
public class VoyagerRobot {
...
private Odometry odometry;
private Robot robot;
private Voyager voyager;
//Tune your constant to fit your needs.
private static final Controller turnController = new GenericTurnController(0.05);
private static final FollowerGenerator followerGenerator = new GenericFollowerGenerator(turnController);
public void init(HardwareMap map) {
...
odometry = new PinpointOdometry(map);
robot = new Robot(drive, odometry);
voyager = new Voyager(robot, followerGenerator);
}
public Voyager voyager() {return this.voyager;}
}
Step 4: Use Voyager!
All you have to do now is instantiate your robot object by passing in a hardwaremap. Then you can use the voyager object to control your robot.
VoyagerRobot robot = new VoyagerRobot(hardwareMap);
robot.voyager().doSomething();