First commit. Started working with the subsumption API.
This commit is contained in:
6
.classpath
Normal file
6
.classpath
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.lejos.nxt.ldt.LEJOS_LIBRARY_CONTAINER/nxt"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
*~
|
||||
*.class
|
||||
bin/
|
||||
*.nxd
|
||||
*.nxj
|
23
.project
Normal file
23
.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>RyABI</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.lejos.nxt.ldt.leJOSBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.lejos.nxt.ldt.leJOSNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
22
LICENSE
Normal file
22
LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2016, Miguel Angel Astor Romero
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
7
README.org
Normal file
7
README.org
Normal file
@@ -0,0 +1,7 @@
|
||||
* RyABI
|
||||
|
||||
** Abstract
|
||||
RyABI (/Robótica y Aprendizaje Bio-Inspirado/ - Robotics and Bio-Inspired Learning) is a control program for LEGO Mindstorms NXT using the LeJOS NXJ
|
||||
firmware. It is developed as part of the homonimous course being taught at the Computer Sciences School of the UCV.
|
||||
|
||||
Future verions of this README file will include a technical report on the development of the project.
|
43
src/ve/ucv/ciens/cicore/icaro/ryabi/RyABI.java
Normal file
43
src/ve/ucv/ciens/cicore/icaro/ryabi/RyABI.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package ve.ucv.ciens.cicore.icaro.ryabi;
|
||||
|
||||
import lejos.nxt.Button;
|
||||
import lejos.nxt.LightSensor;
|
||||
import lejos.nxt.SensorPort;
|
||||
import lejos.nxt.TouchSensor;
|
||||
import lejos.nxt.UltrasonicSensor;
|
||||
import lejos.nxt.addon.CompassHTSensor;
|
||||
import lejos.robotics.subsumption.Arbitrator;
|
||||
import lejos.robotics.subsumption.Behavior;
|
||||
import ve.ucv.ciens.cicore.icaro.ryabi.behaviors.SensorCalibrationBehavior;
|
||||
import ve.ucv.ciens.cicore.icaro.ryabi.utils.QuitButtonListener;
|
||||
|
||||
public class RyABI {
|
||||
private static final float WHEEL_RADIUS = 56.0f;
|
||||
private static final float TRACK_WIDTH = 155.0f;
|
||||
|
||||
private static UltrasonicSensor sonar;
|
||||
private static TouchSensor touch;
|
||||
private static CompassHTSensor compass;
|
||||
private static LightSensor light;
|
||||
private static Behavior[] behaviors;
|
||||
private static Arbitrator arbitrator;
|
||||
|
||||
public static void main(String[] args) {
|
||||
/* Create the sensors. */
|
||||
sonar = new UltrasonicSensor(SensorPort.S1);
|
||||
touch = new TouchSensor(SensorPort.S2);
|
||||
compass = new CompassHTSensor(SensorPort.S3);
|
||||
light = new LightSensor(SensorPort.S4);
|
||||
|
||||
/* Register escape button for forced exit. */
|
||||
Button.ESCAPE.addButtonListener(new QuitButtonListener());
|
||||
|
||||
/* Create the behaviors. */
|
||||
behaviors = new Behavior[1];
|
||||
behaviors[0] = new SensorCalibrationBehavior(sonar, touch, light, compass, WHEEL_RADIUS, TRACK_WIDTH);
|
||||
|
||||
/* Start the program. */
|
||||
arbitrator = new Arbitrator(behaviors, true);
|
||||
arbitrator.start();
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package ve.ucv.ciens.cicore.icaro.ryabi.behaviors;
|
||||
|
||||
import lejos.nxt.LightSensor;
|
||||
import lejos.nxt.TouchSensor;
|
||||
import lejos.nxt.UltrasonicSensor;
|
||||
import lejos.nxt.addon.CompassHTSensor;
|
||||
import lejos.robotics.subsumption.Behavior;
|
||||
|
||||
public abstract class BaseBehavior implements Behavior {
|
||||
protected UltrasonicSensor sonar;
|
||||
protected TouchSensor touch;
|
||||
protected CompassHTSensor compass;
|
||||
protected LightSensor light;
|
||||
|
||||
public BaseBehavior(UltrasonicSensor sonar, TouchSensor touch, LightSensor light, CompassHTSensor compass) {
|
||||
this.sonar = sonar;
|
||||
this.touch = touch;
|
||||
this.compass = compass;
|
||||
this.light = light;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract boolean takeControl();
|
||||
|
||||
@Override
|
||||
public abstract void action();
|
||||
|
||||
@Override
|
||||
public abstract void suppress();
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
package ve.ucv.ciens.cicore.icaro.ryabi.behaviors;
|
||||
|
||||
import lejos.nxt.LightSensor;
|
||||
import lejos.nxt.Motor;
|
||||
import lejos.nxt.TouchSensor;
|
||||
import lejos.nxt.UltrasonicSensor;
|
||||
import lejos.nxt.addon.CompassHTSensor;
|
||||
import lejos.robotics.navigation.ArcRotateMoveController;
|
||||
import lejos.robotics.navigation.CompassPilot;
|
||||
import lejos.robotics.objectdetection.RangeFeatureDetector;
|
||||
import lejos.robotics.objectdetection.TouchFeatureDetector;
|
||||
import ve.ucv.ciens.cicore.icaro.ryabi.detectors.FeatureDetectionListener;
|
||||
import ve.ucv.ciens.cicore.icaro.ryabi.detectors.LightFeatureDetector;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class GetToBorderBehavior extends BaseBehavior {
|
||||
private ArcRotateMoveController pilot;
|
||||
private RangeFeatureDetector rangeDetector;
|
||||
private TouchFeatureDetector touchDetector;
|
||||
private LightFeatureDetector lightDetector;
|
||||
private FeatureDetectionListener featureListener;
|
||||
|
||||
public GetToBorderBehavior(UltrasonicSensor sonar, TouchSensor touch, LightSensor light, CompassHTSensor compass) {
|
||||
super(sonar, touch, light, compass);
|
||||
|
||||
pilot = new CompassPilot(compass, 56f, 155f, Motor.A, Motor.C);
|
||||
|
||||
rangeDetector = new RangeFeatureDetector(sonar, 20, 200);
|
||||
touchDetector = new TouchFeatureDetector(touch);
|
||||
lightDetector = new LightFeatureDetector(light);
|
||||
|
||||
rangeDetector.enableDetection(true);
|
||||
touchDetector.enableDetection(true);
|
||||
lightDetector.enableDetection(true);
|
||||
|
||||
featureListener = new FeatureDetectionListener(pilot, compass);
|
||||
rangeDetector.addListener(featureListener);
|
||||
touchDetector.addListener(featureListener);
|
||||
lightDetector.addListener(featureListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean takeControl() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void action() {
|
||||
rangeDetector.enableDetection(true);
|
||||
touchDetector.enableDetection(true);
|
||||
lightDetector.enableDetection(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suppress() {
|
||||
rangeDetector.enableDetection(false);
|
||||
touchDetector.enableDetection(false);
|
||||
lightDetector.enableDetection(false);
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
package ve.ucv.ciens.cicore.icaro.ryabi.behaviors;
|
||||
|
||||
import lejos.nxt.Button;
|
||||
import lejos.nxt.LightSensor;
|
||||
import lejos.nxt.Motor;
|
||||
import lejos.nxt.TouchSensor;
|
||||
import lejos.nxt.UltrasonicSensor;
|
||||
import lejos.nxt.addon.CompassHTSensor;
|
||||
import lejos.robotics.navigation.DifferentialPilot;
|
||||
|
||||
public class SensorCalibrationBehavior extends BaseBehavior {
|
||||
private boolean sensorsCalibrated;
|
||||
private float wheelRadius;
|
||||
private float trackWidth;
|
||||
|
||||
public SensorCalibrationBehavior(UltrasonicSensor sonar, TouchSensor touch, LightSensor light, CompassHTSensor compass, float wheelRadius, float trackWidth) {
|
||||
super(sonar, touch, light, compass);
|
||||
sensorsCalibrated = false;
|
||||
this.wheelRadius = wheelRadius;
|
||||
this.trackWidth = trackWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean takeControl() {
|
||||
return !sensorsCalibrated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void action() {
|
||||
System.out.println("Calib. compass");
|
||||
DifferentialPilot p = new DifferentialPilot(wheelRadius, trackWidth, Motor.A, Motor.C);
|
||||
p.setRotateSpeed(25);
|
||||
compass.startCalibration();
|
||||
p.rotate(720, false);
|
||||
compass.stopCalibration();
|
||||
|
||||
System.out.println("Calib. light s.");
|
||||
light.setFloodlight(true);
|
||||
System.out.println("Point at dark\nand press ENTER");
|
||||
Button.ENTER.waitForPress();
|
||||
light.calibrateLow();
|
||||
System.out.println("Point at light\nand press ENTER");
|
||||
Button.ENTER.waitForPress();
|
||||
light.calibrateHigh();
|
||||
|
||||
sensorsCalibrated = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suppress() { }
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
package ve.ucv.ciens.cicore.icaro.ryabi.detectors;
|
||||
|
||||
import lejos.nxt.Sound;
|
||||
import lejos.nxt.addon.CompassHTSensor;
|
||||
import lejos.robotics.navigation.ArcRotateMoveController;
|
||||
import lejos.robotics.objectdetection.Feature;
|
||||
import lejos.robotics.objectdetection.FeatureDetector;
|
||||
import lejos.robotics.objectdetection.FeatureListener;
|
||||
import lejos.robotics.objectdetection.RangeFeatureDetector;
|
||||
import lejos.robotics.objectdetection.TouchFeatureDetector;
|
||||
|
||||
public class FeatureDetectionListener implements FeatureListener {
|
||||
private ArcRotateMoveController pilot;
|
||||
private CompassHTSensor compass;
|
||||
|
||||
public FeatureDetectionListener(ArcRotateMoveController pilot, CompassHTSensor compass) {
|
||||
this.pilot = pilot;
|
||||
this.compass = compass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void featureDetected(Feature feature, FeatureDetector detector) {
|
||||
if(detector instanceof TouchFeatureDetector) {
|
||||
|
||||
|
||||
} else if(detector instanceof LightFeatureDetector) {
|
||||
// TODO: Add light sensor handling here.
|
||||
|
||||
}else if(detector instanceof RangeFeatureDetector) {
|
||||
// TODO: Add sonar handling here.
|
||||
Sound.beep();
|
||||
|
||||
detector.enableDetection(false);
|
||||
pilot.stop();
|
||||
pilot.travel(-100);
|
||||
rotate90();
|
||||
pilot.forward();
|
||||
detector.enableDetection(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void rotate90() {
|
||||
float cMeasure;
|
||||
|
||||
compass.resetCartesianZero();
|
||||
|
||||
pilot.setRotateSpeed(25);
|
||||
pilot.rotate(3000, true);
|
||||
|
||||
cMeasure = 360.0f;
|
||||
try { Thread.sleep(200); } catch (InterruptedException e) { }
|
||||
while(cMeasure > 285.0f) {
|
||||
cMeasure = compass.getDegreesCartesian();
|
||||
}
|
||||
pilot.stop();
|
||||
}
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
package ve.ucv.ciens.cicore.icaro.ryabi.detectors;
|
||||
|
||||
import lejos.geom.Point;
|
||||
import lejos.nxt.LightSensor;
|
||||
import lejos.robotics.RangeReading;
|
||||
import lejos.robotics.objectdetection.Feature;
|
||||
import lejos.robotics.objectdetection.FeatureDetectorAdapter;
|
||||
import lejos.robotics.objectdetection.RangeFeature;
|
||||
|
||||
public class LightFeatureDetector extends FeatureDetectorAdapter {
|
||||
private static final int DELAY = 50;
|
||||
|
||||
private LightSensor lightSensor;
|
||||
private int threshold;
|
||||
private boolean invert;
|
||||
private float angle = 0;
|
||||
private float range = 0;
|
||||
|
||||
public LightFeatureDetector(LightSensor lightSensor) {
|
||||
this(lightSensor, 50, false, 0, 0);
|
||||
}
|
||||
|
||||
public LightFeatureDetector(LightSensor lightSensor, int threshold) {
|
||||
this(lightSensor, threshold, false, 0, 0);
|
||||
}
|
||||
|
||||
public LightFeatureDetector(LightSensor lightSensor, boolean invert) {
|
||||
this(lightSensor, 50, invert, 0, 0);
|
||||
}
|
||||
|
||||
public LightFeatureDetector(LightSensor lightSensor, double xOffset, double yOffset) {
|
||||
this(lightSensor, 50, false, xOffset, yOffset);
|
||||
}
|
||||
|
||||
public LightFeatureDetector(LightSensor lightSensor, int threshold, double xOffset, double yOffset) {
|
||||
this(lightSensor, threshold, false, xOffset, yOffset);
|
||||
}
|
||||
|
||||
public LightFeatureDetector(LightSensor lightSensor, boolean invert, double xOffset, double yOffset) {
|
||||
this(lightSensor, 50, invert, xOffset, yOffset);
|
||||
}
|
||||
|
||||
public LightFeatureDetector(LightSensor lightSensor, int threshold, boolean invert, double xOffset, double yOffset) {
|
||||
super(DELAY);
|
||||
this.lightSensor = lightSensor;
|
||||
this.threshold = threshold;
|
||||
this.invert = invert;
|
||||
|
||||
// Calculate angle a distance of bumper from center:
|
||||
Point robot_center = new Point(0, 0);
|
||||
Point bumper_p = new Point((float)xOffset, (float)yOffset);
|
||||
range = (float)robot_center.distance(xOffset, yOffset);
|
||||
angle = robot_center.angleTo(bumper_p) - 90;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Feature scan() {
|
||||
RangeFeature rf = null;
|
||||
if(lightSensor.getLightValue() <= threshold) {
|
||||
RangeReading rr = new RangeReading(angle, range);
|
||||
rf = new RangeFeature(rr);
|
||||
}
|
||||
return rf;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notifyListeners(Feature feature) {
|
||||
super.notifyListeners(feature);
|
||||
|
||||
if(invert) {
|
||||
while(lightSensor.getLightValue() >= threshold);
|
||||
} else {
|
||||
while(lightSensor.getLightValue() <= threshold);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package ve.ucv.ciens.cicore.icaro.ryabi.threads;
|
||||
|
||||
import lejos.nxt.LCD;
|
||||
import lejos.nxt.addon.CompassHTSensor;
|
||||
|
||||
public class CompassThread extends Thread {
|
||||
CompassHTSensor compass;
|
||||
boolean done;
|
||||
|
||||
public CompassThread(CompassHTSensor compass) {
|
||||
this.compass = compass;
|
||||
done = false;
|
||||
}
|
||||
|
||||
public synchronized void end() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while(!done) {
|
||||
LCD.clear();
|
||||
System.out.println("C (DEG): " + compass.getDegrees());
|
||||
System.out.println("C (CRT): " + compass.getDegreesCartesian());
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch(InterruptedException i) { }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
package ve.ucv.ciens.cicore.icaro.ryabi.utils;
|
||||
|
||||
import lejos.nxt.Button;
|
||||
import lejos.nxt.ButtonListener;
|
||||
|
||||
public class QuitButtonListener implements ButtonListener {
|
||||
TimeCounter counter;
|
||||
|
||||
@Override
|
||||
public void buttonPressed(Button b) {
|
||||
counter = new TimeCounter();
|
||||
counter.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buttonReleased(Button b) {
|
||||
if(counter != null) {
|
||||
counter.finish();
|
||||
counter = null;
|
||||
}
|
||||
}
|
||||
|
||||
class TimeCounter extends Thread {
|
||||
private boolean done;
|
||||
private long timeMilisBefore;
|
||||
|
||||
public TimeCounter() {
|
||||
done = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long timeMilisNow;
|
||||
|
||||
timeMilisBefore = System.currentTimeMillis();
|
||||
while(!done) {
|
||||
try { Thread.sleep(100); } catch (InterruptedException e) { }
|
||||
timeMilisNow = System.currentTimeMillis();
|
||||
|
||||
if(timeMilisNow - timeMilisBefore > 3000)
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void finish() {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user