We’ll post a variety of articles about robots that we’ve built, tips and tricks that we’ve learnt, and explanations about certain concepts on this page. You’re welcome to use any of this information, and you can also take any of the photos, videos, or text and change it to suit your own needs – all we request is that if possible, please credit us!
I was pretty humbled today, when I was contacted with a question. I wrote quite a long answer, so I thought I’d share a little of what I’ve learnt over the past 7 years of Vex programming with you all.
How do you do a ‘good’ turn?
Well, this is basically the only question when it comes to programming robots. It’s simple to program a robot in a perfect world, however the difficulty comes in when you have real-world factors to deal with. The major factors are:
• Battery power: consecutive runs have diminished battery voltage, resulting in reduced motor power
• Motor/physical inconsistencies: motors are not all built the same, and friction in the robot’s drive trains are generally different also.
In a perfect world, programming robots would be simple. You could, for example, pick any motor you wanted, install it in your robot, go forward for 1 second, then turn off. This would put your robot in the same spot every single time you did it, no matter which motor you chose. That would just be magic, right? Therefore, the major goal is to learn techniques to counteract some of these pesky real-world issues.
First of all, don’t use timed movements. It sounds like a great idea at first, because of its simplicity, but it is literally not worth your time. Sensors are the key here, and in particular, my favourite vex sensor, encoders. Encoders count the number of wheel rotations, allowing you to effectively track where your robot is. Quadrature Encoders, like those used in Vex, have the ability to track the direction of rotation as well as the magnitude. One thing to note about encoders is that they should be placed as close to the wheels as possible, because the further away they are, the more ‘slack’ they will have. Preferably, the encoders will be on the same axle as the wheel, and the wheel’s normal square inserts are replaced with metal inserts used for gears. If you haven’t done this already to your wheels, you really should – it makes a huge difference, in both programming and driver control.
So, the question now becomes, how do I use encoders to turn/drive straight?
1. Translate your units into something easily understandable
Many people skip this stage, and end up spending many hours more than they need to, developing their routine – all because they are attempting to use abstract units. Do not fall into this trap. In this case, the output from the encoders is not any recognised unit, so we will say its output is in “ticks”. It is very easy to visualise measurements in degrees and centimetres (or inches if you prefer), and makes adjustments much easier. To begin setting up your units, turn on the robot and spin around exactly 10 times on the spot, then record the encoder values you got back for each wheel. Absolute these values and take the average, and lets call this value
X. What you are looking for is the number of encoder “ticks” per degree of robot rotation, which is
X/3600, or the number of ticks recorded by the encoders divided by the number of degrees turned. In your code, assign this variable to a constant variable as something like
ticksPerDegree. From here, you can say, “I want to turn 45 degrees”, therefore, “I want my encoders to move 45*ticksPerDegree ticks each”.
You can do this same method again with driving straight as well. Drive forwards 3m and record the ticks required for that distance. Using the same maths you can calculate
ticksPerInch if you prefer).
2. Functions. Functions everywhere.
Functions are building blocks that you create for yourself. If you ever think to yourself, “Hmm, perhaps I should make a function for this”. You might as well do it, you may find it’s more useful than you first thought. As an example, I often use a function called
driveOn(int leftSpeed, int rightSpeed), which simply sets the respective motor speeds. It sounds simple but is really quite useful. It also means that re-using code on new projects is easy. I can copy and paste a ton of code, and then only change the contents of this driveOn function. It will work exactly the way I want. Similarly, what we are looking at creating now is a function which allows us to program, with little care for the real-world factors. To understand how to do this, I will quickly go over a P (Proportional) Controller.
3. P Controller:
When you turn on an oven/hot water tap, it starts cold and warms up over time. No doubt you’ve learnt over the years, that if you turn the hot water on full blast, it warms up faster, when it is at the temperature you want, you can adjust it to the warm temperature you originally wanted. What you are doing here, is being a P controller, you are taking into account how much it needs to warm up, and telling it to ‘overshoot’ your target, then as it gets closer to the target, lowering the amount you overshoot, as it reaches your desired temperature. The same goes for robots, if you want to drive forwards until your encoders reach an average of 1000 ticks, you could drive at max speed till you reach it, then cut your motors. That will cause you robot to overshoot your target, as it will still have forwards momentum when the desired distance is reached. You could drive at the minimum power needed to move your robot, but your autonomous would end before you drove a metre, so clearly, we need to do something more intelligent here.
4. Implementing a (distance) P controller on encoders
What we need to do here is the same as you would do if you were running up to a line, the further away from the line you are, the faster you move – and as you get closer to the line, you slow down so you can stop on it accurately. The equation for this is therefore logically very simple, you want to set the motors to
P*(T-E) where T is the target number of ticks you want, E is the current number of ticks, and P is the proportional constant, such as 0.2. Essentially, what this P variable states, is that for every tick the encoders are off by, increase motor power by this much. Naturally, this won’t work by itself, because the motors need a certain power in order to start moving, and as you get close to your target,
P*(T-E) will give a value lower than this value, therefore, you will need to find the lowest motor values needed to move your robot, both for turning and driving straight, and add the outcome of
P*(T-E) to it – so, as your reach the target value, you will be moving at the minimum speed needed to move – meaning you will be accurate near the end. However, there is the larger issue of driving straight that still plagues your code.
5. Implementing a (wheel difference) P controller on encoders
We have now essentially removed the real-world effect of the battery slowing our drive, as we are working with distance. Now, it’s time to remove the other real-world effect, mechanical differences between the two sides of the drive. This is actually very similar. In a perfect world, we would like the two encoders to have the same value when driving, so, logically, the solution is to fight to keep them at the same value. To do this, we simply use another P controller at the same time as the previous one. This time, we are going to take the difference between the two encoders, and use that. Let’s assume we are driving forward, and both values are going up, we can do set ‘diff’ to leftEnc – rightEnc, which will give us the amount the left wheel is ahead of the right wheel. From there, we can simply subtract
diff*P2 from the left motor, and add diff*P2 to the right motor. Currently, the line of code implementing the function that sets motor speeds could look something like:
driveOn(minSpeed + distPValue - diffPValue, minSpeed + distPValue + diffPValue)
6. Making sure the values work nicely together
If you think about it, when you are going max speed, 127 forwards because of your distance proportion, your
diffPValue may not even have a chance to do anything, therefore, it’s a good idea to ‘cap’ how much these values can actually affect your motors. You may want to limit distPValue in this case, to
120-minSpeed, so that the maximum value
minSpeed + distPValue can be, is 120. This means
diffPValue can take effect all the time.
7. Writing the overall function
So, when everything is said and done, you should now be able to write a function that allows you to negate real-world variables, and drive around easily, using encoders in this case. You may want to increase speed over time, using a timer, or, you may want to use a timer to accelerate up, over the first half-second, it’s really up to you. The beefy bit of code I wrote for the vexU programming skills champion robot used both of these and everything else mentioned here, but nothing else. No Integral and no Derivative (as are used in PID control). Just P, plain and (mostly) simple. The main trouble is using these formulae when turning and moving backwards, but I’ll leave that for you to work out ;)
8. Code smartly
People love to over-complicate code. They love their ternary operators. They love saving bytes of memory by not using variables – which could have descriptive names to make the logic, well, logical. Don’t be this person. Use comments, make simple variables which allow you to code using real-world units. Avoid ternary operations like the plague, write functions for reused code, and use constants/strings to help determine what you want to do, e.g.
autoDrive(LEFT). Encoders are, in my mind, the most reliable sensor. They don’t drift, I’ve never seen one break, they are accurate if you drive correctly and they work in any light. Use them.
Hopefully this gives a little insight into what the world champion code will have looked like, the major drive function (called
autoDrive) was about 89 lines in total, and was:
autoDrive(float dist, int dir, bool flip) (
flip in this case simply reversed left/right, to make blue/red auton easy) and could be called like:
autoDrive(100, FORWARD, false) // Drive forward 1 metre
Good luck for “Nothing But Net”! I’m planning on putting up more tutorials in the coming months, I want to see programming skills be even fiercer.
– Kerey, AURA 2015
This is the video that we entered in this year’s RECF educational video competition (the video was not eligible to win the competition because it exceeded the maximum length).
We use the term “Back Voltage” here rather than “Back EMF” because the video is aimed at an audience that understands what a voltage is but doesn’t necessarily understand the term EMF.
I have put together a document of my impressions and observations of the Asia Pacific competition from a rules perspective. I thought it might be helpful to people to see what some common mistakes were, so that they can avoid them in other competitions.
The rules are full of things you are not allowed to do, so I hope I don’t sound too negative when I say what wasn’t done so well.
Head Referee, Asia-Pacific Robotics Championship 2012
With the release of VEX Sack Attack, many teams have begun to talk about using transmissions on their drivetrains. This is probably the best game ever for a shifting drive; speed is needed due to the large field and race for the easy to access sacks (by the goals), and torque is needed for the inevitable push battle that will happen at the end of the game when fighting over goals. Of course, a traditional drive cannot have both speed and torque unless many motors are used, but it seems difficult to use more than four, maybe six, motors on drive this year, as the sacks are rather heavy, and a 30″ reach will be needed for most robots this year. Of course, strafe will also be useful so that you can defend your troughs easily, and quickly move sacks from you opponents troughs to yours.
What Cameron (TooMuchStategy) from AURA has built to help solve these problems is a drive that switches between traditional tank drive and X holonomic. It uses four 393 motors in the the torque configuration, but this number can be easily increased if you have motors to spare. It uses four pneumatic pistons to shift between X and tank drive. It gets about 8 shifts per tank – we have two tanks on at the moment because we have not yet added pressure regulators; you don’t exactly need 100psi to open up the wheels.
In tank mode, the drive ratio is a bit on the slow side, at 1:1. This is, with four 393’s, rather powerful however, and will usually be enough to win pushing battles. In X mode, the drive ratio is slightly over 1.4 (Squareroot 2) when traveling forwards or straight sideways, and 1:1 when going diagonally – see the “Why is X-Drive Faster” article by Oliver. This makes it highly maneuverable.
As for navigating over or around sacks, in tank mode, driving over sacks is very effective The wheels can easily climb over the sacks. In X mode, sacks can get dragged along with the robot as the wheels try to push them sideways. This system has an advantage over other holonomic systems in that it can switch to tank mode to drive over sacks, then switch back to holonomic mode.
In this article, Oliver explains why x-drives have a higher effective gear ratio than tank drives.
This seems unintuitive to a lot of people, but an X-drive robot has a higher maximum speed* than a tank drive robot with the same gear ratio.
To best understand this, it helps if we consider what happens when the robot drives diagonally.
Figure 1: These two drive bases have identical gearing and an identical number of motors, but drive #1 is X-holonomic and drive #2 is tank.
Drive #1 can move in the y direction by moving only the left and right wheels. The top and bottom wheel rollers will spin freely. In this case, it will travel at the same free speed* as drive #2 would (but with half the power, because it is only using half its motors). Similarly, it can remain stationary in the y direction and move in the x direction at the same free speed as drive #2.
When it does both of these at once, it travels in the x direction at the free speed of a tank drive while also travelling in the y direction at the free speed of a tank drive, so its total free speed is greater than that of a tank drive. The direction it travels in is halfway between the two directions, or towards the front of the robot. For the same reason, an H-drive robot (tank drive with a central strafing wheel) will travel faster if it is driving forward while strafing than if it is simply driving forward. Similarly, in some computer games it is possible to run faster by strafing while running. (http://en.wikipedia.org/wiki/Strafing_%28gaming%29#Straferunning)
The amount that an X-drive is effectively geared up by relative to a tank drive is 1.414, or sqrt(2). This is the ratio of the side length of a square to its diagonal length. The force of the drive is reduced by the same amount because the force in each direction is half that of a tank drive and 1/2 x sqrt(2) = 1/(sqrt(2)). This means that the product of the free speed and the stalling force remains the same so in the ideal case an X-drive is not less powerful than a tank drive, it is just geared differently.
However, an X-drive will usually have greater frictional losses than a tank drive because of friction between the omniwheels and the omniwheel rollers.
* In this article, “maximum speed” and “Free speed” refer to the speed that the robot would travel at if its motors were rotating at their free running speed of 100 rpm. This is sometimes called the ‘theoretical speed’ of the robot, and it depends only on the gear ratio, the size of the wheels and the motor’s rotational free speed. It is different from the actual observed speed of the robot, which will also depend on motor torque, friction and the mass of the robot.
French version / Version française: http://botfatherfr.weebly.com/x-drive.html
Double Cheese was one of the robots that we built for the 2012 Vex Robotics World Championships College Challenge, and played as part of the AURA2 team which placed 11th after qualifications and finished as the quarter-finalists.
Double Cheese gets its name from the wedges on the front of its chassis. These allow it to drive through an isolation zone that is cluttered with lots of objects by forcing those objects upwards. Double Cheese uses an H-drive. Forward motors are four 393s (torque configuration) geared 2:1 for speed on 2.75” wheels. Strafe motors are two 269s geared 1.5:1 for speed on 2.75” wheels. These ratios are equivalent to 1.4:1 and 1:1 on 4” wheels.
The lift is a 6-bar designed to be able to score on all the 30” goals (both sides of the fence) on a college field, meaning it needs to be slightly taller than a high school 6-bar. To help achieve this, the long bar of the 6-bar offset by bolting it to the shoulder gear away from the centre. The 6-bar is also built slightly off parallel so that the ramp is at a lower angle near the bottom of its range and at a steeper angle near the top of its range. The lift is driven by four 269 motors on a 1:7 reduction (torque) with rubber band assistance. Two 269 motors drive 30-tooth sprockets as side rollers, with a 30” ramp for a six-object capacity. Other features include pneumatic drop-down intake rollers for descoring, and rubber band netting to prevent objects becoming stuck on the robot where they would prevent the lift from lowering.
Drive: 4x 393 in torque gearing at 2:1 on 2.75″ wheels and 2x 269s at 1.5:1 on 2.75″ wheels
Lift: 4x 269 at 1:7 Offset 6-bar lift
Intake: 2x 269 side sucker intake (30-tooth sprockets)
Pneumatics: Used on the intake to allow it to drop roughly 90 degrees for descoring top objects
Video of Double Cheese driving around the lab: http://www.youtube.com/watch?v=E0yphqVRWLA
Videos of Double Cheese playing in matches at the World Champs: http://www.youtube.com/playlist?list=PL0B00CF593F9116E9
Dragon was one of the robots that we built for the 2012 Vex Robotics World Championships College Challenge, and played as part of the AURA team which placed 4th after qualifications and finished as the finalists.
Dragon competed in the isolation zone. Dragon is a unique robot that has a backwards six bar in order to get more height and forward reach as it lifts. The backwards six bar also helps the arm not to stick out so far when it is scoring in the 20” goals. Dragon is not ideal for high school competitions because it cannot score 11.5” goals or the far 20” goals, although it can score the 30” interaction goal from isolation. There is a descoring fork on the back of the ramp. Because isolation robots are purely isolated in college, not many motors are needed for pushing power. Dragon can hold up to 6 objects.
Drive: 4×393 4” drive wheels internally speed geared and 2×269 2.75” strafe wheels 24:15 (1.1:1 relative to 4” wheels)
Lift; 4×269 backwards six bar lift geared 1:7
Intake: 2×269 side sucker intake (18T sprockets)
Video of Dragon driving around the lab: http://www.youtube.com/watch?v=-Qd2mQqr6vw
Videos of Dragon playing in matches at the World Champs: http://www.youtube.com/playlist?list=PL0B00CF593F9116E9
Woodpecker was one of the robots that we built for the 2012 Vex Robotics World Championships College Challenge, and played as part of the AURA team which placed 4th after qualifications and finished as the finalists.
Woodpecker was the extension of one of our first interaction robot designs, Carwash. Carwash was designed to be an interaction robot which colour sorted objects in the interaction zone, and passed to the isolation robot. We later realised that it was better to also have the robot scoring in the closest two isolation 30″ goals. For this design, we used what we know works: A very long six bar. Furthermore, we had recently aquirred mecanum wheels, and strafe was a good bonus for this robot as it would be able to easily score both 30″ goals autonomously.
Drive: 8 Motor drive (6x 269, 2 x 393, 1.2 Drive ratio)
Lift: 2 x 393, 1:7
Intake: Side suckers with folding out front ramp, holds 5 – 6 objects.
Scores two closest 30” goals in the isolation zone from the interaction zone in autonomous with 1:7 lift
8 motor drive with strafe, 1.2 drive ratio with mecanum
Video of Woodpecker driving around the lab: http://www.youtube.com/watch?v=sJdOjerj1vY
Videos of Woodpcker playing in matches at the World Champs: http://www.youtube.com/playlist?list=PL0B00CF593F9116E9
Quetzalcoatlus was one of the robots that we built for the 2012 Vex Robotics World Championships College Challenge, and played as part of the AURA2 team which placed 11th after qualifications and finished as a quarter-finalist.
For one of our teams, we wanted our interaction robot to put all the objects from the interaction zone into our isolation zone. Quetzal was the design that we came up with to do this. It uses a 18 inch wide top sucker to pull up to ~10 objects into the robot, then has a rotating, misaligned 4-bar to lift all of them over the wall. This lift is used because it is very efficient, because none of the objects are lifted very far. Even though it only has two 393’s on the lift, it can lift about 9 pounds over its back.
In addition to this, it has two wings that pneumatically unfold, in order to have more capacity. When unfolded, the robot has a width of about ~26 inches.
Drive: 6x 269, 2×393, geared at 2:1 for speed on each side, on 2.75” wheels.
Arm: 2×393 at 1:7. Only needs elastic when lifting very large loads.
Intake: 2×296, 1:2 for torque
Wings: One pneumatic piston each side, allowing individual control.
Sensors: Quetzal has by far the least sensors of any of our college bots, using two shaft encoders, three potentiometers, and three bumpers.
Video of Quetzal driving around the lab: http://www.youtube.com/watch?v=Sw3b8EiXKwI
Videos of Quetzal playing in matches at the World Champs: http://www.youtube.com/playlist?list=PL0B00CF593F9116E9
It’s a CAD-ed version of Java! Java was one of the robots that we built for the Robot World Cup in October 2011, and a lot of teams were interested in the new lift mechanism and how it worked – so we took our time and used Autodesk Inventor to produce a CAD version of the robot too.
It’s a STEP file so should be viewable in any CAD program. It’s only half of the robot (but the other half is symmetrical anyway), not coloured, and no descorer, but hopefully it’ll answer those questions about “how does your 4-bar work?” by letting you see the detail up close.
More information Java itself (with real life photos) is here: