LEGO Chase Demo

Version 26 (Edward Getz, 10/08/2015 10:43 am)

1 1 Edward Getz
h1. LEGO Chase Demo
2 1 Edward Getz
3 7 Edward Getz
This page describes how to make a LEGO robot that chases things, like a ball.  It's the same robot and program that's used in the "Pixy LEGO video":https://www.youtube.com/watch?v=HZ_0qk7Yd7A.  This robot and program is a good launching point for other projects, and it's a good introduction to PID control, which is used throughout robotics and engineering in general.
4 1 Edward Getz
5 1 Edward Getz
h2. *Building the robot*
6 1 Edward Getz
7 2 Edward Getz
The robot we're going to build can be found in Laurens Valk's book "LEGO Mindstorms EV3 Discovery Book":http://robotsquare.com/books/ev3discovery.  The robot is called the Explor3r and it uses only parts that are available in the retail Mindstorms EV3 kit.  
8 1 Edward Getz
9 7 Edward Getz
# Assemble Explor3r through step 11. "Click here for instructions on how to build Explor3r":http://robotsquare.com/2015/10/06/explor3r-building-instructions/."  That is, stop short of mounting the IR Sensor (step 12).  Instead of the IR Sensor, we'll be mounting Pixy.  If you are using an NXT brick, your instructions will be very similar.  
10 4 Edward Getz
# Locate these LEGO parts and your LEGO-mounted Pixy. (There are instructions on how to mount Pixy to LEGO "here":/projects/cmucam5/wiki/Mounting_Pixy_with_LEGO.)   
11 3 Edward Getz
!{width: 40%}http://i74.photobucket.com/albums/i241/cmucam/IMG_4994_zpsds83y5lm.jpg!
12 3 Edward Getz
 
13 3 Edward Getz
# 
14 1 Edward Getz
!{width: 40%}http://i74.photobucket.com/albums/i241/cmucam/IMG_4996_zps8njal9ea.jpg!
15 4 Edward Getz
 
16 6 Edward Getz
# 
17 4 Edward Getz
!{width: 40%}http://i74.photobucket.com/albums/i241/cmucam/IMG_4998_zpsj2rbmhch.jpg!
18 4 Edward Getz
 
19 6 Edward Getz
# 
20 5 Edward Getz
!{width: 40%}http://i74.photobucket.com/albums/i241/cmucam/IMG_5000_zps63ambtvg.jpg!
21 5 Edward Getz
 
22 5 Edward Getz
# 
23 5 Edward Getz
!{width: 40%}http://i74.photobucket.com/albums/i241/cmucam/IMG_5007_zps5956q7xb.jpg!
24 5 Edward Getz
 
25 5 Edward Getz
# Attach Pixy as shown.
26 5 Edward Getz
!{width: 40%}http://i74.photobucket.com/albums/i241/cmucam/IMG_5008_zpsvosebvsq.jpg!
27 1 Edward Getz
 
28 22 Edward Getz
# Connect the Pixy cable. Plug one end of the cable into Pixy and the other end into port 1 of your brick.  You're done with assembly!
29 1 Edward Getz
!{width: 40%}http://i74.photobucket.com/albums/i241/cmucam/chase_ev3_zpsdnasr5hx.jpg!
30 7 Edward Getz
31 9 Edward Getz
h2. *Teach Pixy an object*
32 9 Edward Getz
33 9 Edward Getz
Go ahead and [[teach Pixy an object 2|teach Pixy an object]].  You might try using the button press method.  Using the button press method doesn't require that you hook up a USB cable to Pixy and run PixyMon, so it's much more convenient!  
34 9 Edward Getz
35 7 Edward Getz
h2. *Load Chase example*
36 8 Edward Getz
37 7 Edward Getz
# Turn on your LEGO brick if you haven't done so, and hook up a USB cable between your computer and your LEGO brick.
38 7 Edward Getz
# From the LEGO Mindstorms EV3 Software, go to the *File* menu and select *Open Project*.  
39 7 Edward Getz
!http://i74.photobucket.com/albums/i241/cmucam/Image%20036_zpsxk0kqscq.png!
40 7 Edward Getz
 
41 7 Edward Getz
# Browse to the location where you unzipped the "LEGO blocks and examples" file (which you can download "on this page":/projects/cmucam5/wiki/Latest_release.), and then to the *examples* directory and then either to the *EV3* or *NXT* directory depending on your brick version. Select "chase.ev3" and click on *Open*.
42 9 Edward Getz
# Click on the "track" tab.  You should see a program that looks like this (below). 
43 17 Edward Getz
!{width: 60%}http://i74.photobucket.com/albums/i241/cmucam/Image%20042_zps3bvq1ehm.png!
44 9 Edward Getz
 
45 9 Edward Getz
# Run the program!  Click on the play icon in the lower right corner of your EV3 software window.  If you don't see the play icon, make sure your LEGO brick is powered on, finished booting, and connected to you computer via a USB cable.   
46 9 Edward Getz
!http://i74.photobucket.com/albums/i241/cmucam/Image%20038_zpscvm5bgys.png!
47 9 Edward Getz
 . 
48 9 Edward Getz
# If you are running PixyMon, make sure you are running the "Default program" by clicking on the home icon.
49 9 Edward Getz
!http://i74.photobucket.com/albums/i241/cmucam/Image%20039_zpssap8j5yb.png!
50 9 Edward Getz
 
51 11 Edward Getz
# Move the object that you taught Pixy in front its camera lens.  The track program simply adjusts the angle of the robot so that it always faces your object.  It doesn't chase your object, it just "faces" your object, but it's quick!
52 11 Edward Getz
  
53 7 Edward Getz
54 14 Edward Getz
h2. *What's going on in the track program?*
55 12 Edward Getz
56 13 Edward Getz
The track program uses *X centroid* output of the "Pixy block":/projects/cmucam5/wiki/Pixy_LEGO_Block
57 12 Edward Getz
!http://i74.photobucket.com/albums/i241/cmucam/Image%20045_zps7tmkn9xf.png!
58 12 Edward Getz
to adjust the heading of the robot by using a "PID controller":/projects/cmucam5/wiki/PID_LEGO_Block.
59 1 Edward Getz
!http://i74.photobucket.com/albums/i241/cmucam/Image%20046_zpsughyvxkm.png!
60 14 Edward Getz
That is, the *X centroid* output of the Pixy block ranges between 0 and 255, depending on where the detected object is in Pixy's image.  The "center pixel" is therefore 128.  The PID controller tries to move the motors such that the detected object is always centered in the image.  It does this by comparing the *X centroid* value to 128 (the PID controller's *Set Point* input).  
61 14 Edward Getz
62 14 Edward Getz
The *Control Output* of the PID controller is fed directly into the left wheel controller (the *Power Left* input of the Move Tank controller block).  The *Power Right* input is fed the inverted output of the PID controller by subtracting the PID controller's output from 0.  Why are the wheels controlled in opposite directions?  We are interested in controlling only the rotation of the robot, and rotating the robot is achieved by powering the motors in opposite directions at the same power/speed.  It is in this way that the robot "tracks" the object and always faces it.  The program is surprisingly simple!
63 14 Edward Getz
64 15 Edward Getz
There is some additional logic in the program to make sure that if there are no detected objects, the robot doesn't move.  This is done by comparing the *Signature Output* of the Pixy block with 0. If the *Signature Output* is zero, Pixy has not detected an object.  If the *Signature Output* is non-zero, Pixy has detected an object.  The Switch block selects between these two possibilities, and feeds the PID controller output into the motors when an object is detected, and feeds 0 into the motors when no objects are detected.
65 15 Edward Getz
66 16 Edward Getz
h2. *Some notes on adjusting the PID gains*
67 1 Edward Getz
68 23 Edward Getz
The appeal of the PID controller is it's flexibility.  By adjusting the three gain values, one for proportional, one for integral, and one for derivative, lots of different systems can be controlled.  So what's up with the PID values?  How were they chosen?
69 16 Edward Getz
!http://i74.photobucket.com/albums/i241/cmucam/Image%20047_zpswvqehp3l.png!
70 16 Edward Getz
71 16 Edward Getz
These were "tuned" by experimentation.  You can tune the PID loop yourself. In fact, it's a good way to familiarize yourself with PID control.  
72 16 Edward Getz
73 16 Edward Getz
Go ahead and set all of the PID gains to 0.  That is, click on *Proportional* input of the PID block and set the value to 0.  Do the same for the *Integral* and *Derivative* inputs.  Now all of the PID gains are 0.  You can try to run the program now.  And if you guessed that your robot won't move, you're correct!   
74 16 Edward Getz
75 20 Edward Getz
The proportional gain "does most of the work" as they say, so tuning should begin by adjusting this value.  Start with a small value of 0.1 and run the program.  Notice how the robot is now very slow and sluggish.  That is, when trying to track the object (which you're moving around) the robot seems to be trying, but it's heart doesn't seem to be into it.  This is telling you that your proportional gain is too small.  
76 16 Edward Getz
77 20 Edward Getz
Try settnig the proportional gain to 1.0 and run the program.  You might notice that the robot does a shimmy after it faces your object.  In other words you move the object quickly, and the robot responds by turning to face the object, and instead of stopping when it faces your object, it keeps on going.  It overshoots.  In fact, it may overshoot several times before coming to a rest, finally facing your object like it was programmed to do.  This is oscillation, and it's a very common problem.  
78 16 Edward Getz
79 16 Edward Getz
To reduce the oscillation, you need to increase the derivative gain.  Increasing the derivative gain is like adding friction to your system, which may sound like something you should avoid. However, increasing the derivative gain does not adversely affect the efficiency of your system as friction does.  Start by setting the derivative gain to the same value as the proportional gain.  And continue to increase the derivative gain until the oscillation is under control.  
80 16 Edward Getz
81 21 Edward Getz
However, if increasing the derivative gain does not remove the oscillation, the proportional gain may be too high. Try reducing the proportional gain (cutting it in half, say), then setting the derivative gain to zero again, and starting over by increasing the derivative gain until the oscillation is removed. 
82 1 Edward Getz
83 19 Edward Getz
If you're successful in removing the oscillation, you might try your luck by increasing the proportional gain again (not as high as before) and seeing if you can still bring the oscillation under control with derivative gain.  And if you're unsuccessful in removing the oscillation, you can always reduce the proportional gain and try different derivative gains as before.  
84 19 Edward Getz
85 1 Edward Getz
Our goal is to have our robot that tracks the object quickly, but without oscillation.  This is usually the goal, but you may want a robot that oscillates or is sluggish.  It's all up to you!  
86 1 Edward Getz
87 21 Edward Getz
What about the integral gain?  Integral gain is useful when the system has trouble reaching the goal.  Say if our robot tended to get close to facing our object and then stopped, we could try adding a little integral gain.  The integral gain would then make sure that the robot would face the object, eventually.  The integral gain is zero in this example because the the LEGO motors have their own built-in control loops that make sure that we always reach our goal.  
88 17 Edward Getz
89 17 Edward Getz
h2. *Chasing the object*
90 17 Edward Getz
91 17 Edward Getz
Click on the "chase" tab.  You should see a program that looks like this (below).
92 18 Edward Getz
!{width: 60%}http://i74.photobucket.com/albums/i241/cmucam/Image%20048_zps3bi46ssc.png!
93 1 Edward Getz
94 22 Edward Getz
Notice that it's very similar to the track program. In fact, the track program is mostly intact in the top half of the chase program, but there's an additional PID controller in the bottom half of the program.  This PID controller adds the "chase" element.   
95 22 Edward Getz
96 22 Edward Getz
To run the chase program:
97 22 Edward Getz
98 22 Edward Getz
# Make sure you have a fair amount of space for your robot to move around in.
99 22 Edward Getz
# Make sure Pixy can reliably detect/track your object. (Look at Pixy's LED.  Does it glow when the object is present?)  
100 22 Edward Getz
# Tilt Pixy's lens down such that it is looking slightly down at the ground, like in the final assembled picture above.
101 22 Edward Getz
# Place the object that you taught Pixy in front of the robot, but such that Pixy can still see it.  (A ball is perfect for this.)  
102 22 Edward Getz
# Now run the program by clicking on the play icon in the lower right corner of your EV3 software window.
103 22 Edward Getz
104 23 Edward Getz
You should notice that the robot chases the object.  Or more specifically, it will maintain a certain distance from the object.  If the object is farther away, the robot will approach (chase) the object.  If the object is too close, the robot will back up until the correct distance to the object is reestablished.  The program is more complicated than the track program, but not by much!
105 1 Edward Getz
106 23 Edward Getz
h2. *What's going on in the chase program?*
107 23 Edward Getz
108 23 Edward Getz
If you read and understood the section on how the track program works, much of the chase program should make sense.  The main difference is the extra PID controller.  The new controller takes the *Y Centroid* output of the Pixy block and compares it to 150.  Why 150?  The *Y Centroid* output varies between 0 and 199 depending on the position of the detected object in the image.  If the object is higher in the image, the *Y Centroid* value is lower, and if the object is lower in the image, the *Y Centroid* value is higher.  It's backwards in a sense, but many cameras follow this same scheme.  
109 23 Edward Getz
110 23 Edward Getz
Now consider that Pixy is angled slightly such that it is looking downward.  This allows your robot to use a simple distance-measuring technique.  Assuming the object of interest is resting on the ground, if the object is higher in the image, it is farther away from Pixy. If the object is lower in the image, it is closer to Pixy.  In fact, you can estimate the actual distance by performing a simple calculation:  distance = constant * 1/(1 + Y Centroid).  You just need to figure out the value of the constant by doing some simple calibration with a known distance.  Anyway, by choosing the value of 150, we are choosing the lower part of the image, or when the object is relatively close.  You can change this value if you like.  In particular, if you lower the value (to 100, for example), the robot will stop when it is farther away.  If you raise the value (no greater than 199 though!), the robot will stop when it is closer.  
111 23 Edward Getz
112 23 Edward Getz
How is the output of the new PID controller used to control the motors?  The track program was already controlling the motors such that it controlled the rotation of the robot.  The new PID controller must somehow control the translation (forward/backward) motion of the robot.  It does this by using a simple set of equations. 
113 23 Edward Getz
114 23 Edward Getz
<pre>
115 23 Edward Getz
rotation = left_motor - right_motor
116 23 Edward Getz
translation = left_motor + right_motor
117 23 Edward Getz
</pre>
118 23 Edward Getz
119 23 Edward Getz
If you've ever driven a tank, these equations probably make sense.  But we're interested in the "inverted" equations.  We want expressions for the left_wheel and the right_wheel in terms of rotation and translation.  That is, we know how we want our robot to rotate and translate -- these are the outputs of our PID controllers.  Using some algebra, we get the equations below.  
120 23 Edward Getz
121 23 Edward Getz
<pre>
122 23 Edward Getz
right_motor = (translation - rotation)/2
123 23 Edward Getz
left_motor = (rotation + translation)/2
124 23 Edward Getz
</pre> 
125 23 Edward Getz
126 24 Edward Getz
If you look at the program, these equations are implemented in the math blocks that feed the Move Tank block.  The divide-by-two's are missing, but since these are just multiplicative constants (ie multiply by one-half), they end up being taken up in the PID gain values when the gain values are chosen (tuned).    
127 24 Edward Getz
128 24 Edward Getz
h2. *Some notes on the PID block*
129 24 Edward Getz
130 26 Edward Getz
By putting the PID controller in a block, we make things simpler.  It's now very easy to make programs with PID control loops.  In fact, you can use the PID block for other programs that don't use Pixy.  Use the PID block to control your robot's distance to the wall for a wall-following robot.  That is, use the IR sensor in proximity mode as an input to the PID controller.  And feed the output of the PID controller into the steering of your robot.  
131 24 Edward Getz
132 26 Edward Getz
But by making the PID controller a block, we hide the implementation details.  These details are simple though, and can be summarized with some simple expressions. 
133 24 Edward Getz
134 24 Edward Getz
<pre>
135 24 Edward Getz
error = Value_In - Set_Point
136 25 Edward Getz
d_error = error - previous_error                                             // Simple derivative of error
137 25 Edward Getz
i_error = i_error + error                                                    // Simple integral of error
138 25 Edward Getz
previous_error = error                                                       // Remember the error from the previous control cycle
139 25 Edward Getz
Control_Output = Proportional*error + Integral*i_error + Derivative*d_error  // This is "belly of the beast".  Not much of a beast though... :)
140 24 Edward Getz
</pre> 
141 24 Edward Getz
142 25 Edward Getz
Using these expressions, you can try creating your own PID block!
143 24 Edward Getz
144 24 Edward Getz
145 23 Edward Getz
146 23 Edward Getz
147 17 Edward Getz
148 17 Edward Getz
149 7 Edward Getz