This vehicle combines the basic line following mechanism (two independent treads and a light sensor) with the addition of a lifting arm. The arm has two sensors - a touch sensor to detect when the lift arm has bumped into something, and an angle sensor to determine the position of the lift arm.
There are lots of different ways to program it. You can have it follow a line, emptying any garbage cans it encounters en route. Alternatively, it can follow the line until the first garbage can, lift this can slightly off the ground, then turn around and return with the garbage can itself.

Here's a closeup of the lifting mechanism. I use a worm gear driving a 24t gear followed by a 8t to 24t gear reduction. The resulting arm has enormous torque. The light sensor can also be seen to the left of the gear mechanism, and the angle sensor is visible at the far right. The angle sensor can measure 1/16 of a rotation. Since it is measuring the non-reduced drive shaft, the resulting resolution is about 3 tick per degree.

Here's a closeup of the touch sensor mounted at the front of the lift arm. Nothing unusual here.

A typical garbage can...

The garbage truck in action...

/* garbage.nqc
* written by Dave Baum for NQC 2.0
*/
#define EYE SENSOR_1
#define BUMP SENSOR_2
#define ANGLE SENSOR_3
#define RIGHT OUT_A
#define LIFT OUT_B
#define LEFT OUT_C
#define NORMAL_SPEED 6
#define TURN_SPEED 2
#define DELAY 20
#define CUTOFF 55
#define STOP 48
#define INITIAL_TIME 2
int direction, time, eye;
task main()
{
/* setup sensors */
SetSensor(EYE, SENSOR_LIGHT);
SetSensor(BUMP, SENSOR_TOUCH);
SetSensor(ANGLE, SENSOR_ROTATION);
/* initialize vars for line following */
direction = 1;
time = INITIAL_TIME;
/* follow line until we hit something */
follow();
PlaySound(5);
/* pickup the garbage bin */
collect();
}
sub collect()
{
/* lift garbage bin and dump into truck */
OnFwd(LIFT);
until(ANGLE <-300);
Off(LIFT);
Wait(100);
OnRev(LIFT);
until(ANGLE >-2);
Off(LIFT);
}
sub follow()
{
/* follow a line until the touch sensor hits something */
On(LEFT+RIGHT);
while(true)
{
if (BUMP == 1) break;
eye = EYE;
if (eye >= CUTOFF) continue;
{
ClearTimer(0);
if (direction == 1)
{
SetPower(RIGHT+LEFT, TURN_SPEED);
Fwd(RIGHT);
Rev(LEFT);
}
else
{
SetPower(RIGHT+LEFT, TURN_SPEED);
Fwd(LEFT);
Rev(RIGHT);
}
while(true)
{
if (EYE < CUTOFF)
{
time = INITIAL_TIME;
break;
}
if (Timer(0) > time)
{
direction *= -1;
time *= 2;
break;
}
}
SetPower(RIGHT+LEFT, NORMAL_SPEED);
Fwd(RIGHT+LEFT);
}
}
Off(RIGHT+LEFT);
}