This post is about a robot, which wanders in a limited area. In this project, we have marked an oval shaped area with a black line. We calibrate the robot with white and black values by making a manual movements on the surface. We then take the threshold (average of black and white values) and expect the robot to turn, when it reaches the threshold. That's the reason, the robot turns 90 degrees, when it reaches half way through the black line. The robot continues the behavior of making turns after finding a black line and keeps itself within the oval. A small clip showing the behavior of robot is shared below. You can also find the LeJOS program, which simulates this behavior, shared below.
In this LeJOS program, we have a single class called LtdWanderer. In its main method, this class initializes the large regulated motors on port B and C. It also initializes the two sensors color sensor and gyro sensor attached to port S4 and S2. The color sensor is initialized in Red mode and gyro sensor in Angle mode. The program then stores the calibrated values of light intensity reflected from the black and white surface. The LeJOS API returns the light intensities in the range 0 to 1. We have multiplied them by 100 and calculated the average light intensity of black and white for further programming logic.
The default behavior of the robot is to keep moving forward with a speed of 180 degrees per second. While moving, it also fetches the samples from the color sensor continuously. The robot checks if the light intensity is greater than average light intensity. If yes, the robot is free to wander further because it is on a white surface. However, when the light intensity goes below the average light intensity, the robot concludes that it is on the black boundary, and it make a left turn to be within its limits.
NOTE: With each turn the LimitAngle variable increases its value by 90 degrees. We ideally should have reset the sensor and measure the angle each time the robot makes a turn, to check if it is equal to 90 degrees. However, we found that the reset function did not work as we were expecting. The angle measured by the Gyro sensor kept on increasing as and when the robot takes a turn. Hence the purpose of the LimitAngle variable. With the LimitAngle variable, we are checking whether the difference between previous turn angle and the current turn angle is equal to 90 degrees. We then stop the robot from making a turn and let it go straight and wander.
The robot wanders infinitely until ESCAPE button is pressed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import lejos.hardware.Button; | |
import lejos.hardware.Sound; | |
import lejos.hardware.lcd.LCD; | |
import lejos.hardware.motor.EV3LargeRegulatedMotor; | |
import lejos.hardware.port.MotorPort; | |
import lejos.hardware.port.SensorPort; | |
import lejos.hardware.sensor.EV3ColorSensor; | |
import lejos.hardware.sensor.EV3GyroSensor; | |
import lejos.hardware.sensor.SensorMode; | |
import lejos.robotics.SampleProvider; | |
import lejos.utility.Delay; | |
public class LtdWanderer { | |
public static void main(String[] args) { | |
int LimitAngle = 90; | |
EV3LargeRegulatedMotor BMotor = new EV3LargeRegulatedMotor(MotorPort.B); | |
EV3LargeRegulatedMotor CMotor = new EV3LargeRegulatedMotor(MotorPort.C); | |
EV3ColorSensor light = new EV3ColorSensor(SensorPort.S4); | |
float[] color = new float[1]; | |
EV3GyroSensor gyro = new EV3GyroSensor(SensorPort.S2); | |
float[] gyrosample = new float[1]; | |
SampleProvider gyromode = gyro.getAngleMode(); | |
Sound.twoBeeps(); | |
LCD.drawString("white", 0, 0); | |
Button.ESCAPE.waitForPressAndRelease(); | |
float[] sampleWhite = new float[1]; | |
SensorMode mode = light.getRedMode(); | |
mode.fetchSample(sampleWhite, 0); | |
LCD.drawInt(new Float(sampleWhite[0] * 100).intValue(), 2, 2); | |
Delay.msDelay(1000); | |
Sound.twoBeeps(); | |
LCD.drawString("Black", 4, 4); | |
Button.ESCAPE.waitForPressAndRelease(); | |
float[] sampleBlack = new float[1]; | |
mode.fetchSample(sampleBlack, 0); | |
LCD.drawInt(new Float(sampleBlack[0] * 100).intValue(), 6, 6); | |
Delay.msDelay(5000); | |
LCD.clear(); | |
float avgLight = (sampleBlack[0] * 100 + sampleWhite[0] * 100) / 2; | |
while (Button.ESCAPE.isUp()) { | |
mode.fetchSample(color, 0); | |
LCD.drawInt(new Float(color[0] * 100).intValue(), 2, 2); | |
LCD.drawInt(new Float(avgLight).intValue(), 6, 6); | |
BMotor.setSpeed(180); | |
CMotor.setSpeed(180); | |
BMotor.forward(); | |
CMotor.forward(); | |
if (avgLight > (color[0] * 100)) { | |
gyromode.fetchSample(gyrosample, 0); | |
while (Math.abs(gyrosample[0]) < LimitAngle | |
&& Button.ESCAPE.isUp()) { | |
gyromode.fetchSample(gyrosample, 0); | |
LCD.clear(); | |
LCD.drawInt( | |
Math.abs((new Float(gyrosample[0]).intValue())), 4, | |
4); | |
BMotor.backward(); | |
CMotor.forward(); | |
} | |
if (gyrosample[0] >= 90) { | |
// gyro.reset(); | |
// gyro.getAngleMode(); | |
LimitAngle = LimitAngle + 90; | |
} | |
} | |
} | |
} | |
} | |
No comments:
Post a Comment