How-To: Building a good Auton without Odometry or GPS

Is odometry too hard, and require too many sensors? Is GPS too pricey, annoying, and not even present during non-skills matches? What are your tools for programming a good autonomous without these?

Turning? Inertial meter based pid for turning. You can even set your left or right wheels to zero while executing to turn and translate.

Driving Straight? Combine the inertial based turning pid, with a regular PD control function for your drive motors to reach their destination while helping maintain a heading.

Checking your position? When your robot is at 0, 90, 180, or 260 degrees, an optical distance sensor will help give you your coordinates.

Run into something, or need to know if you are playing an auton tug of war? Use the inertia.collision or motor.current or velocity functions to know if you are going the speed you should be going.

Picking up an object? Use the vision sensor to write a drive straight PID, replacing your inertial meter with the horizontal object position of your vision sensor, so that the colored object stays centered in the camera while you drive towards it.
…Then use a line reader or distance sensor to make sure you grabbed the object. Pretty easy coding here.

Furthermore, if objects are placed well, you can use trig+inertial meter when you grab an object to calculate your position.

Also, use voltage, not velocity when telling the motors to spin.

It is always good to know your tools.


I haven’t heard this before. What is the reason for this?


The motor has its own internal PID to set the velocity, so if you’re running a PID yourself, you’ll have 2 PIDs running over each other. Voltage gives you more immediate and precise control over the motor’s speed


Lots of mention of the inertial sensor (and distance sensor) in this post. Sensors often provide “noisy” values; in the real-world, a stationary robot asking its inertial sensor for heading may not get the same value back consecutively (even over a short interval). Filtering sensor values (even something as basic as taking the MEDIAN [1] can be helpful) can help smooth out the stream of values coming directly from the sensor.

Another thing to talk about with sensors is what their sampling rate is. I wish the Vex Website would list those values in the sensor specifications. As it is, I think the only way to find them is to search through VexForum for @jpearman posts. I believe the general rule of thumb for V5 sensors is 20ms, though I believe some sensors can be read more frequently (I thought I recall reading the GPS can be read every 3 or 5 ms). @DRow - would it be possible for Vex to update sensor listings with these values?

[1] Median often acts as a better filter than AVERAGE since a value wildly different than other recent values can cause the AVERAGE filter to spike. For example, a stream of (1, 100, 2) would report a median of 2 but an average of 34


I’m not sure how useful that would be, there’s more involved than just the base sensor update rate including the fact that user programs can change the sensor update rate for some sensors if required.

I’ll try and make a post giving a few more details later this week.


Though if you know that much trig, you have most of the necessary knowledge to do odometry.


If things like a PID are to complex, time based coding isnt really good but you can somewhat immitate a PID using steps of speed in increasing and decreasing order.


Note: I was a lazy programmer in competition which was why my autonomous’s never really worked in matches. I knew how to build a good auton but never had the motivation until after graduation and after vex competitions.

If you do not know odometry or do not wish to use a GPS, the greatest solution is to combine motion profiling with PID for the drivetrain. This system is so good that, if tuned correctly, you can have a good autonomous by merely using this system with the internal encoders on the motors themselves as compared to external encoder tracking wheels and you will have relatively consistent results (Proof 365X during Turning Point making skills robin with nothing but motion profiling on IME’s).

As for the other components on the robot, I am unsure as to how well the new rotation tracker or potentiometer is. But in a scenario where the potentiometer is accurate at tracking even at high speeds (as compared to the old crappy red potentiometer), I would suggest a PID algorithm whenever trying to hold an arbitrary angle or position, and a regular P loop for hard stops (with the desired position slightly beyond the hardstop).

TL;DR: For arms and lifts, usually P loops are good for positions that have hard-stops and PID is good for arbitrary positions. Motion Profiling + PID is one of the best control movement algorithms for the drivetrain.


I feel as though students should avoid using sketchy shortcuts, and instead reach out for help to do things

There is nothing wrong with asking for help. And if who you ask has the information and is being stubborn, don’t feel empathetic to pester them until they open up and provide you a response. You will realize you have to do this frequently in life, especially in college.


I will say that a large percentage of teams can have a strong 15 second autonomous using VexCode V5 Blocks and a Drivetrain with an inertial sensor. The built in PID does pretty well if you don’t spin your wheels.

Navigation becomes more complicated the longer the robot drives (IE: Programming Skills). A 3% error over several feet can make a big difference. Using odometry with extra wheels under the chassis and/or creating your own PID method, since the weight and power if each robot is different, will greatly improve accuracy. While this is most likely the best practice for advanced teams, I think that GPS will take over and be the standard in the next few seasons.


If you’re too lazy to do pid you can make the auton slower


Motion profiling is fully open-loop, so it doesn’t need any sensor input. Saying that you are using “motion profiling on IME’s” is inherently incorrect.

If my understanding is correct, you are talking about using motion profile for the initial parts of the code, and then switching to PID in the end. In this case, combining motion profiling with PID in the end kind of defeats the purpose of using motion profiling in the first place. The reason of using open-loop control algorithms in the first place it to have its consistent, smooth starting and settling. This is an advantage compared to closed-loop (ex. PID) controllers because in VEX, noisy sensors can cause disturbances within each run ; the results can be unpredictable / oscillate and have different settling positions each time. So essentially, you are trying to use motion profile for consistent, smooth settling, and then switch to the more violent and unpredictable PID in order to settle.

Also, there really isn’t too much of a reason to switch to PID in order to reduce error as well. If you have a good velocity controller tuned out, motion profiling will be more (if not as) accurate than traditional PIDs, and be extremely more precise. My chassis control using motion profiling never surpasses 0.25" of error per movement, and rerunning the same movement is basically yields the same result (<0.01" stddev).


I didn’t know the term until I googled it with a bit of time. You are correct in that simple technical error as I shortened what I said by mistake, but overall…

I do not believe you understood what I was saying. When I was meaning PID + Motion Profiling, I was referring to what is called a Profiled PID. Usually, profiled PID’s are motion profiled path with a PID speed algorithm to properly follow the path with immense accuracy and precision.

More information can be explained here:


Using motion profiling + PID velocity control is indeed a great way to achieve consistent and accurate movements. There are actually methods which can further improve the accuracy of the velocity control, mainly by adding what is called “feedforward terms”.

Since motion profile outputs goal velocity and acceleration and , you can use these values to “predict” what your target voltage should be to achieve the velocity. For example, for DC Motors, velocity is almost linear to the amount of voltage applied. Similarly, if you want your robot to accelerate, you would want more voltage applied.

Instead of relying on the feedback to control all the velocity (which can oscillate and cause disturbance), you are able to make feedforward to the bulk of the work, and make feedback only correct for minor corrections, allowing for higher accuracy.

The general equation of this velocity control is as follows, where kV, kA, kP are the gains for velocity, acceleration and proportion. You can also add a proportion feedback for velocity and a separate gain for deceleration for more accuracy as well.

double voltage = targetVel * kV + targetAccel * kA + (targetPos - actualPos) * kP

More information can be explained here:


While this thread is a few days old and I may be saying something repeated, I would like to share my 2 cents.

First off, the simplest way to not use GPS or anything funky, a tracking wheel is the best option. While it may be jank, it will work 80-90% of the time, and requires no money.

Secondly, a good autonomous should not be defined by the sensors you use. You can spend some time coding a bot that runs forward, picks up a yellow goal and brings it back with ease, and not using a sensor. While using the tracking wheel, Inertial, or GPS may make the job easier, they come with cash, time spent coding, and time figuring it out.

The Inertial sensor is a great way to be used on a 2D plane, working and going up the “See-Saws” is rough, but it works (If you calibrate it properly). A lot of teams will complain about inertial being hard to use, but me an ametur programmer and my friend got it working in just a few minutes. This “hardness” is due to VEX’s lack of documentation on the sensor, and we had to figure it out on our own.

As for GPS, we took the plunge and bought one. It takes a while to set up properly with having to use trig for headings, and degrees. But will work like a charm afterwards, working in every scenario we have put it through. A worthwhile investment if you ask me.

Many times, “jankness” or ineffectiveness of sensors may be user error, not setting it up properly, and that’s not your fault. VEX is not the best when it comes to teaching how to set things up, and most of the time, the Forums is the best place. Hopefully this helps

TL;DR - Sensor not that complex when working right. Choose the best option for your team.


So… how is there documentation when there’s a whole Knowledge Base article on the sensor?

Using the V5 Inertial Sensor – STEM Library (


How would I go about doing the driving straight PD with inertial?

2 pids that sum their output to the motors.
Translation PID uses the average position of the two drive motor groups as the sensor value.
Rotation PID uses the inertial meter as the sensor value.
You will want to limit the maximal translational pid output to -12 V<output<12 V to make sure you are not trying to apply the turning pid values (which will be small) to a MASSIVE translational output value.

In general though, limiting the output is always a healthy thing to do.

Tune the translational pid completely before tuning the translational pid.


How would I utilize both PIDS to be running at the same time?

This is what I have so far, this is not PID but I think it should still work.

double avgDrive() {
  return (fabs(leftMotorFront.getPosition(degrees)) +
          fabs(leftMotorBack.getPosition(degrees)) +
          fabs(rightMotorFront.getPosition(degrees)) +
void translate(int distance, int vel) {
  leftMotorFront.setPosition(0, degrees);
  leftMotorBack.setPosition(0, degrees);
  rightMotorFront.setPosition(0, degrees);
  rightMotorBack.setPosition(0, degrees);

  double error;
  double output;
  double kP = 1.5;
  double heading = Inertial9.rotation;

  while (avgDrive() < distance) {
    error = heading - Inertial9.rotation(); //5 
    output = error * kP; // 7.5

    LeftDrive.spin(forward, vel - output, percentUnits::pct);
    RightDrive.spin(forward, vel + output, percentUnits::pct);