Python robotics challenges for university
84 Python programming challenges, in the order the course teaches them. Each one opens in the simulator with a starting program, and it is marked the moment you press Run: the robot either does the job or you are told what is missing.
U1. The robot as a system
- A loop that runs at 10 Hz clock() gives the seconds since the program started. Read it before the loop and after it, and divide the difference by how many times round you went. Lesson U1.1
- How fast is this robot? It takes about a quarter of a second to reach full speed, so ignore the beginning. Either read flow() several times and average, or time a known distance with position(). Lesson U1.2
- How far out is the dead reckoning? Drive at least a metre and a bit, with a turn or two in it. At the end read both odometry() and position() and work out the distance between the two points. Lesson U1.3
- Hold the heading on a slow loop This robot pulls to one side. Correct with the rotation term of drive(), in proportion to the heading error. A slower loop needs a gentler gain, or it will swing about. Lesson U1.4
- Plot the error plot(name, value) once per loop, next to where you work the value out. Two names, two lines. Lesson U1.5
- The step response Ask for full speed from a standing start, and read flow() every tenth of a second into a list. The settled speed is the average of the last few; the time constant is… Lesson U1.6
- The data sheet Four measurements, one after another, each one a short drive and a read. Work up from a small command in steps to find where the robot first moves. Keep the whole run… Lesson U1.7
U2. Kinematics and frames
- Which frame is which? The robot starts facing along the world's x axis. Drive forward for a few seconds. In the body frame that is forward; in the world frame it is x. Read flow() for one… Lesson U2.1
- Rotate a vector A robot at heading 60 measures (0, 10) in its own frame: ten centimetres straight ahead. World x is vx*cos(h) + vy*sin(h); world y is -vx*sin(h) + vy*cos(h). The angle… Lesson U2.2
- Crab into the zone The zone is to the robot's right, and it must arrive facing the same way it started. drive(fwd, lat, rot) takes a sideways term, and right() is the blocking version of… Lesson U2.3
- Predict where it stops Work out the body velocity you are about to ask for, rotate it into the world with the heading you are at, multiply by how long you will drive, and print that before… Lesson U2.4
- North while facing east The robot faces east and must travel north without turning. Decide the world velocity you want, rotate it into the body frame with the current heading, and scale each… Lesson U2.5
- Go to a point The target is at world (140, 150) and the robot starts at (60, 60) facing the wrong way. position() is relative to the start, so the target is 80 across and 90 up from… Lesson U2.6
- A square while spinning Four corners of a square in world coordinates, and the robot rotates the whole way round. Every tick, work out the world vector to the next corner, rotate it into the… Lesson U2.7
U3. Odometry and drift
- Integrate a velocity Drive straight and read flow() every tenth of a second. Each reading is a speed in cm/s, so it contributes speed times the length of the step. Add them up as you go. Lesson U3.1
- Your own odometry Keep x, y and h as your own variables and update them every tick, including while turning. Blocking calls like turn_right(angle=90) run the world without running your… Lesson U3.2
- Measure the gyro bias Stand still and read imu()[1] many times. The average of enough readings is the bias; the spread around it is the noise. Sixty readings is plenty and takes six seconds. Lesson U3.3
- A calibrated lap Stand still for a few seconds first and average the gyro. Subtract that bias from every turn rate afterwards. The tolerance here is tighter than the uncalibrated task,… Lesson U3.4
- A fix from a tag Tag 7 sits on the far wall, 165 cm up the mat from where the robot starts. Dead reckon towards it, and when the camera reads it, the fourth number in the tag is how far… Lesson U3.5
- An error budget A rough budget is enough: a heading error of e degrees over a run of d centimetres puts you about d times e in radians off to one side, and the scale error adds a few… Lesson U3.6
- The long lap Two metres of driving, then home on your own estimate: steer towards (0, 0) in your estimated frame with the inverse kinematics from U2. If the estimate is good you… Lesson U3.7
U4. Noise and filtering
- Measure the noise Stand still and read distance() a hundred times, a tenth of a second apart. The mean is the sum over the count; sigma is the square root of the mean squared difference… Lesson U4.1
- Average it down Aim for 1 cm at two sigma, 0.5 cm at one: work out n, then take that many, a tenth of a second apart. Lesson U4.2
- A low pass filter filtered = alpha * new + (1 - alpha) * filtered, once per tick. Plot both lines while the robot drives towards the wall, and watch the filtered line follow the raw one… Lesson U4.3
- Throw out the wrong ones Another robot shuttles across between you and the wall. While it is in the beam the sensor measures it, not the wall: two readings far too short. Stop 35 cm from the… Lesson U4.4
- Measure the lag Drive steadily at the wall so the distance falls in a straight line, then compare the two signals: the filtered one reaches any given value later. The theory says the… Lesson U4.5
- Tune the filter Run the same still robot through three or four filters at once, each with a different alpha, and measure the spread of each filtered signal. The smallest spread wins… Lesson U4.6
- Hold the gap The wall's near face is 150 cm up the mat, so 25 cm from it is y = 125, which is 65 cm from where the robot starts. Filter the depth reading, control on the filtered… Lesson U4.7
U5. Feedback control
- Close the loop The wall's face is 150 cm up the mat and the robot starts at 60, so 20 cm from the wall is 70 cm of travel. Error is where you want to be minus where you are; drive in… Lesson U5.1
- Find a gain that works Too little gain and it stops short: once the command falls under 15 percent the drive does nothing. More gain gets it closer; far too much and it shuffles back and… Lesson U5.2
- Damp the overshoot This robot is carrying a load, so it takes about three times as long to speed up and slow down. With P alone it either creeps in too slowly or swings past, whatever the… Lesson U5.3
- No offset left 25 cm from the wall is y = 65 from the start, and the tolerance is 3 cm, which proportional control at a gentle gain will not manage: below about 15 percent this drive… Lesson U5.4
- Find the ultimate gain Run the same loop several times, each at a higher gain, and watch the error. Steady oscillation that neither grows nor dies is the ultimate gain. The period is the time… Lesson U5.5
- Anti-windup The command is pinned at its limit for most of the way in, and an unprotected integral keeps growing the whole time, so the robot arrives with far more push than it… Lesson U5.6
- Park it Three errors at once: x, y and heading. Run a proportional controller on each, put the two translation terms through the inverse kinematics from U2, and add the heading… Lesson U5.7
U6. State estimation
- A complementary filter Integrate imu()[1] for a heading that is smooth but drifts, and read imu()[0] for one that is noisy but does not. mine = 0.98 * (mine + rate * dt) + 0.02 * fused, every… Lesson U6.1
- Predict, then correct Predict with the flow sensor: estimate += flow()[1] * dt. Correct with the wall: the robot started 110 cm from the wall's face, so the depth reading says you have… Lesson U6.2
- A Kalman filter in one dimension Carry a variance p as well as the estimate. Predict: p += Q. Correct: k = p / (p + R), then estimate += k * (measured - estimate), then p = (1 - k) * p. R is the… Lesson U6.3
- Tune Q and R R is measurable: stand still, take a hundred readings, and square the standard deviation. Q is a statement about how much the state can change between ticks that your… Lesson U6.4
- The shape of the uncertainty Grow two numbers as the robot drives: the along-track uncertainty by the scale error times the distance travelled each tick, and the across-track by the distance times… Lesson U6.5
- Fuse a tag fix Tag 4 is 165 cm up the mat from the start. Predict with flow and grow the variance every tick; when the tag is in view, correct with 165 minus its distance, using R for… Lesson U6.6
- Navigate on the estimate The target's centre is 105 across and 105 up from the start, and nothing about it is visible to the robot. Tag 9 is straight up the mat from the start, and what it… Lesson U6.7
U7. Localisation
- Which places are possible? The mat is 200 by 200 and the robot faces along +y, so the wall ahead is at y = 200 and the reading tells you y and nothing about x. Step a grid of candidate positions… Lesson U7.1
- A thousand guesses Scatter the particles evenly over the whole mat with random.uniform(0, 200) for x and y. The standard deviation of a uniform spread over a width w is w over the square… Lesson U7.2
- Move the cloud Start every particle at zero. Each tick, move every one of them by the measured flow, plus a small random amount of its own. The cloud tracks the robot and slowly… Lesson U7.3
- Weigh the guesses Each particle predicts what the sensor would read if the robot were there: 200 minus its y. Weight it by exp(-(predicted - measured)^2 / (2*sigma^2)), normalise the… Lesson U7.4
- Resample Low variance resampling: one random start, then step through the cumulative weights in equal strides. Every particle comes out with weight 1/N, so the effective sample… Lesson U7.5
- Monte Carlo localisation Particles spread over the mat, moved by the flow sensor and weighted by the depth reading against each particle's predicted distance to the far wall. Resample when the… Lesson U7.6
- The kidnapped robot The robot wakes up somewhere on the mat and does not know where. The depth sensor only measures the wall it is pointing at, so one cloud can only find one axis:… Lesson U7.7
U8. Mapping
- Which cell did that reading land in? The robot stands at (100, 50) on the mat facing straight up it, so the thing it can see ahead is at y = 50 plus the reading. A cell index is a coordinate divided by the… Lesson U8.1
- One ray, two statements Step out along the ray in steps smaller than a cell, keeping the cells you land in, and stop one cell short of the reading. The cell at the reading itself is the… Lesson U8.2
- Adding up the evidence Each hit adds 0.85 to the cell's log odds and each pass-through subtracts 0.4, and the total is held between -10 and +10. Turning a log odds back into a probability is… Lesson U8.3
- Build a grid while you drive The robot starts at (100, 40) on the mat. Each tick, take the pose, turn every scan() pair into a world direction, and run the inverse sensor model along it. Plot how… Lesson U8.4
- Predict a reading from the map Build a small map standing still, then march a ray out of it from a pose the robot is not at yet: one step at a time until a cell is occupied, and the distance you have… Lesson U8.5
- What have I not seen? Turn on the spot for a good while, integrating every scan into the grid. A cell is unknown while its log odds is near zero; a frontier cell is a free one with an… Lesson U8.6
- Map the mat The robot starts at (100, 25) facing up the mat and there is a wall across it with one way through. Turn on the spot to fill in the grid, move to a second viewpoint and… Lesson U8.7
U9. Planning
- Grow the obstacle, shrink the robot The chassis radius is about 3.5 cm, so grow the block by 6 cm on every side and then treat the robot as a single point. A lane at x runs straight up the mat from y = 30… Lesson U9.1
- Breadth first across the mat Build the 40 by 40 grid described on the page, mark a cell blocked when its centre is inside a wall grown by 8 cm or within 8 cm of the mat edge, then run breadth first… Lesson U9.2
- The cheapest way across Same grid, eight neighbours. Entering a cell costs the length of the step in centimetres, times three if that cell's centre is closer than 20 cm to a wall. A priority… Lesson U9.3
- The same answer, less work Run both searches over the same grid with plain step costs (5 cm straight, 5 root 2 diagonal) and count the expansions of each. A* is Dijkstra with the queue ordered by… Lesson U9.4
- Slide round the block Every tick, work out a velocity rather than a route: a pull towards (170, 160) and a push away from the nearest point of the block and of each mat edge, added together,… Lesson U9.5
- Grow a tree into the free space Start the tree at (30, 30). Each round, pick a random point on the mat (and now and then the goal itself), find the nearest node, step about 12 cm from it towards the… Lesson U9.6
- Plan a route and drive it Plan first and print the length, then drive. Inflate by more than the chassis radius, because the robot follows a plan approximately, and shorten the grid path by… Lesson U9.7
U10. Following a trajectory
- Put a clock on a path The path is the four waypoints joined by straight lines, and its length is the sum of the legs. The trajectory is the same geometry with a rule for where you are at… Lesson U10.1
- A trapezoidal profile Reaching the cruise speed takes v/a seconds and covers v squared over 2a. If two of those fit inside the distance there is a flat top in the middle; if they do not, the… Lesson U10.2
- Drive the cross-track error to zero The taped line runs from (60, 30) to (60, 170) and the robot starts 25 cm to the right of it. Build a unit vector along the path and one at right angles to it, split… Lesson U10.3
- Chase the look-ahead point Project the robot onto the path to get the arc length it has reached, then take the point that much plus the look-ahead further along, and steer the velocity vector at… Lesson U10.4
- How far behind a ramp Run the same ramp twice: once commanding only the gain times the error, once adding the reference's own speed through the kinematics before the correction. Average the… Lesson U10.5
- How far behind the plan Build a trapezoid to 80 cm at 12 cm/s/s and 14 cm/s, start a clock, and follow it with the reference speed fed forward and a correction on top. Keep the largest… Lesson U10.6
- Drive the route The tape runs (30, 30), (30, 150), (120, 150), (120, 60), (170, 60), and the crate sits beside the middle of it. Follow the path with a look-ahead point, slow down… Lesson U10.7
U11. Vision
- Turn a pixel into a bearing The detector gives you a column in the picture and a range. The column is an angle: the camera is 320 pixels wide across 120 degrees, and the relation between a pixel… Lesson U11.1
- Measure the focal length Four tags are stuck on the mat at positions the task tells you, and the robot is at a position it tells you too, facing along +y. So you know the true bearing of every… Lesson U11.2
- Range from apparent size Both balls are 8 cm across. A sphere of radius r at range d covers 2*r*f/d pixels, with f the focal length you measured in U11.2, so the range falls out of the width of… Lesson U11.3
- Fix your position from two tags Tag 20 is at (40, 160) on the mat and tag 21 at (150, 140). Each one gives a range and a bearing, and a bearing is measured from the robot's nose, so a position worked… Lesson U11.4
- Threshold a picture Take a 64 by 48 picture and count, twice. First with the test a beginner writes, red above some level, and express the answer as a percentage of the whole picture,… Lesson U11.5
- Servo on the pixels Two errors, both in pixels, and neither converted to metres. The horizontal one is the blob's centre against 160 and it drives rotation. The other is the blob's width… Lesson U11.6
- Find the one that is green Three balls, all 6 cm across, all the same size and shape to a depth sensor. Survey first: the camera runs one detector at a time, so set each colour in turn, give it a… Lesson U11.7
U12. Learning, and the capstone
- The data sheet is not your robot The data sheet says 20 cm/s at command 100, so command 60 for 4 seconds should be 48 cm. Drive it, measure what happened with the lab's camera, and divide. That ratio… Lesson U12.1
- Fit the drive Sweep the command, and at each one let the robot settle before reading flow(). Run each command forwards and then backwards so the robot stays where it started, and… Lesson U12.2
- Choose the model by held-out error Collect a speed at each of the fourteen commands, six for training and eight for testing, and never let the test eight touch the fit. Fit a straight line and a degree 5… Lesson U12.3
- Learn the offset that drives it straight This robot slides sideways whenever it drives forward. The policy is one number, a lateral command held on all the time, and its score is how far the robot slid during… Lesson U12.4
- Two scores, two winners Try commands 55, 70, 85 and 100, each for four seconds from the same starting line, driving back between trials so every trial is fair. Score each one twice: how far it… Lesson U12.5
- Tune it, then stress it The robot should end up in the green band, 30 cm from the wall. Tune the reading at which it starts braking, by trials: drive at the wall, stop, measure the gap you… Lesson U12.6
- Capstone: cross the barrier and park The robot starts at (30, 25) on a 200 by 200 mat, facing up it. A barrier runs across at y = 100 with a gap between x = 115 and x = 170, and the target is the far left… Lesson U12.7
Questions
Are these Python challenges free?
Yes. Every challenge runs in the browser with nothing to install.
How are the challenges checked?
The simulator runs your program and checks what the robot did and what it printed against the challenge's goals. If something is missing it says what, so you can fix it and run it again.
Are there solutions?
There is no answer to copy. Each challenge has a Stuck? button that tells you what to work out next, and the lesson it comes from teaches everything the challenge needs.
What order should I do them in?
Top to bottom. They follow the course, so each section only needs what the sections before it taught.