Skip to main content

Lab 04. Localization (and Project Paper Prototypes)

Today's lab will feature both additions to your robot, and instructions for your first project deliverable, which will be due in two weeks.


Pre-lab​

  • Review the lecture materials on encoders
  • Review the lecture materials on distance sensors
  • Review the project documentation

Lab​

Measuring your robot's position is both one of the most simple and difficult things you can do. This lab is about using sensors to model your robot's position. Recording live data on your robot's position is called telemetry. Figuring out where your robot is on a map is called localization.

A map has many reference points: places that you can measure from. The reference point could be a doorway or a wall. The measurement could be ten paces South from Doorway 1. Localizing yourself would mean finding the doorway on a map, and measuring out ten paces. In the same way that "paces" is a form of measurement full of inaccuracies, robot motion is full of similar errors.

Without external information, robots can only refer to their own sensors for measurement. Using encoders, we can measure how much a wheel has turned. The encoders, as you have seen, have low spatial resolution, which is one source of error. But, there are many other sources of error, such as wheels slipping, or the shape of the tire making the robot wobble.

1. Add encoders to your robot​

Add two encoders to your robot. They should consist of wheel with holes in it, and sensor module that wraps around it. The encoder wheel should go on the other side of your robot's drive wheel (the one that has a tire). You should have two encoders: one for each wheel.

Wire your encoders and test. You can simply use a digitalRead(pin), the same as with a button read. Think through how you will use the digitalRead to determine the encoder speed.

warning

Your encoder has an analog out and a digital out. You can experiment with it, but the digital out is really all you need.

2. Print accurate telemetry to your Serial Monitor​

Once you have the encoder reliably working, print your telemetry to the Serial Monitor. You should design a good enough Serial Monitor print output that you can debug what's wrong with your robot. Format the output nicely and use good delimiting, e.g., always printing a value after a comma.

Optionally, you might want to start streaming this data to your computer using Processing. Although you technically could copy and paste Serial Monitor output, it's going to be annoying pretty quickly.

For example, your Arduino code could look like this:

// ---------------------------
// Pins
// ---------------------------
const int LEFT_ENCODER_PIN = 12;
const int RIGHT_ENCODER_PIN = 13;

// ---------------------------
// Setup
// ---------------------------
void setup() {
pinMode(LEFT_ENCODER_PIN, INPUT_PULLUP);
pinMode(RIGHT_ENCODER_PIN, INPUT_PULLUP);

Serial.begin(9600);

// Optional CSV header
Serial.println("t_ms,left_encoder,right_encoder");
}

// ---------------------------
// Main loop
// ---------------------------
void loop() {
unsigned long t = millis();

// you may want to turn this into a count and then a distance
int leftEncoder =
digitalRead(LEFT_ENCODER_PIN);

// you may want to turn this into a count and then a distance
int rightEncoder =
digitalRead(RIGHT_ENCODER_PIN);


// CSV output
Serial.print(t);
Serial.print(",");

Serial.print(leftEncoder);
Serial.print(",");

Serial.print(rightEncoder);
// Serial.print(",");

Serial.println();

delay(5);
}

And then the Processing.org code could print out a CSV that you can review in Excel or Google Sheets. For example:

import processing.serial.*;

Serial port;
PrintWriter out;

void setup() {
size(600, 300);

// Print available serial ports
println(Serial.list());

// Change this index to match the Arduino.
String portName = Serial.list()[0];

println("Opening: " + portName);

// Create timestamped filename
String fn =
nf(year(), 4) +
nf(month(), 2) +
nf(day(), 2) +
"_" +
nf(hour(), 2) +
nf(minute(), 2) +
nf(second(), 2);

out = createWriter(
"robot_telemetry_" + fn + ".csv"
);

// CSV header
out.println(
"arduino_t_ms,left_encoder,right_encoder"
);

port = new Serial(this, portName, 9600);
port.bufferUntil('\n');

println("Logging started.");

}


// Called whenever a complete line arrives
void serialEvent(Serial p) {
String line = p.readStringUntil('\n');

if (line == null) {
return;
}

line = trim(line);
if (line.length() == 0) {
return;
}

println(line);

// Ignore Arduino header
if (line.startsWith("t_ms")) {
return;
}

String[] parts = split(line, ',');

// We expect exactly four fields
if (parts.length != 3) {
println("Bad row: " + line);
return;
}

// Parse values
int t = int(parts[0]);
int leftEncoder = int(parts[1]);
int rightEncoder = int(parts[2]);

// Save cleaned CSV row
out.println(
t + "," +
leftEncoder + "," +
rightEncoder);

// Immediately write to disk
out.flush();

}


void draw() {
background(240);
fill(0);
textSize(18);

text("Robot telemetry logger", 20, 40);

textSize(14);
text("Press Q to stop and save.", 20, 70);

}


void keyPressed() {

if (key == 'q' || key == 'Q') {
out.flush();
out.close();
port.stop();

println("Log saved.");

exit();
}

}

warning

We do not guarantee that the above code will "just work." These are examplesβ€”you need to design your own logging system.

It is worth spending some time really designing the telemetry and measuring its real-world accuracy. Set up some experiments. For example, you might be tempted to "just" record every tick and the time between ticks, and assume that this will translate directly to wheel distance travelled. And, although the logic makes sense, robots rarely play nicely with logic due to the many errors in the system.

3. Design an Experiment to Determine Your Telemetry Error​

Your encoders will inevitably be inaccurate. Design an experiment to estimate the error of your encoders. Make reference to real-world features, such as the size of the encoder, the size of the wheels, and other objects to make a theoretical analysis of your error. Then, compare that to a real, measured result.

4. Project Paper Prototypes (homework)​

In two weeks, you will demonstrate and hand in your project paper prototypes. In any combination, you will need:

  • Sketches
  • A looks-like prototype
  • A feels-like prototype
  • A works-like prototype
  • A wizard-of-oz workflow
  • A draft annotated Bill of Materials (BOM)

Since you will not have acquired your final electronics yet, your works-like prototype may be human-actuated, and your sensors and logic may be wizard-of-oz. However, your prototype(s) should be as close to your final project as possible without the electronics.

Take some time to review the paper prototypes that your classmates and COGS 300 alumni have made that are sitting on the shelf. Make note of the best practices: which prototypes are merely illustrative vs. could be used for making a clear plan for building something?

The point of this exercise is to not just try something, but to really plan your project. For example, you can say that every pin in the prototype will be a motor, but you cannot say that you will have "some number of motors". You should work out, using your paper prototype(s), the exact number of motors that you will need. Your annotated BOM should be a real drawing of your final product with the parts labeled.

Can your project evolve? Absolutely. We expect it to. This is not your final commitment. However, you should treat this prototype as the real plan. Real enough to base a budget off of it.

If you do not have a project idea yet, now is the time to brainstorm. Your TA will lead a brainstorming session for anyone who does not have their idea yet. You need to leave today with a real idea, ready to make the real plan.