rosaria/Legacy/Aria/javaExamples/actionExample.java

274 lines
8.7 KiB
Java
Raw Permalink Normal View History

2021-12-16 15:07:59 +01:00
/*
example program demonstrating how to make and use new actions.
This example program creates two new actions, Go and Turn. Go will drive the robot forward safely,
while Turn will avoid obstacles detected by the sonar by turning.
This program also adds a predefined
action from Aria which tries to recover from stalls (hit something and
can't move forward) by backing and turning.
Each of these actions have the normal constructor and destructor, note that
the constructors use constructor chaining to create their ArAction part
correctly. Each action then also implements the essential virtual method,
fire(). This fire function is called by the action resolver, and
returns values that, in combination with other actions' desired behavior,
determine the driving commands sent to the robot.
Also note that each of these actions override the setRobot function; these
implementations obtain the sonar device from the robot in addition to doing the
needed caching of the robot pointer. This is what you should do if you
care about the presence or absence of a particular sensor. If you don't
care about any particular sensor you could just use one of the checkRangeDevice...
methods in ArRobot (there are four of them).
Also note that these are very naive actions, they are simply an example
of how to use actions.
See the @ref actions Actions section of the Aria reference manual overview for more details about actions.
Note that actions must take a small amount of time to execute, to avoid
delaying the robot synchronization cycle.
*/
import com.mobilerobots.Aria.*;
/**
* Example Action class that drives the robot forward, but stops if obstacles are
* detected by sonar.
*/
class ExampleGoAction extends ArAction
{
// constructor, sets myMaxSpeed and myStopDistance
public ExampleGoAction(double maxSpeed, double stopDistance)
{
super("Go");
myMaxSpeed = maxSpeed;
myStopDistance = stopDistance;
myDesired = new ArActionDesired();
}
/**
This fire is the whole point of the action.
currentDesired is the combined desired action from other actions
previously processed by the action resolver. In this case, we're
not interested in that, we will set our desired
forward velocity in the myDesired member, and return it.
*/
public ArActionDesired fire(ArActionDesired currentDesired)
{
double speed;
// reset the actionDesired (must be done), to clear
// its previous values.
myDesired.reset();
// get the range of the sonar
double robotRadius = 400;
double range = mySonar.currentReadingPolar(-70, 70) - robotRadius;
// if the range is greater than the stop distance, find some speed to go
if (range > myStopDistance)
{
// just an arbitrary speed based on the range
speed = range * .3;
// if that speed is greater than our max, cap it
if (speed > myMaxSpeed)
speed = myMaxSpeed;
// now set the velocity
myDesired.setVel(speed);
}
// the range was less than the stop distance, so request stop
else
{
myDesired.setVel(0);
}
// return the actionDesired to the resolver to make our request
return myDesired;
}
/**
Override ArAction.setRobot() to get the sonar device from the robot, or deactivate this action if it is missing.
You must also call ArAction.setRobot() to properly store
the ArRobot pointer in the ArAction base class.
*/
public void setRobot(ArRobot robot)
{
setActionRobot(robot);
mySonar = robot.findRangeDevice("sonar");
}
// the sonar device object obtained from the robot by setRobot()
protected ArRangeDevice mySonar;
/** Our current desired action: fire() modifies this object and returns
to the action resolver a pointer to this object.
This object is kept as a class member so that it persists after fire()
returns (otherwise fire() would have to create a new object each invocation,
but would never be able to delete that object).
*/
protected ArActionDesired myDesired;
protected double myMaxSpeed;
protected double myStopDistance;
}
/** Example action class that turns the robot away from obstacles detected by the
* sonar. Used by actionExample.java. */
class ExampleTurnAction extends ArAction
{
public ExampleTurnAction(double turnThreshold, double turnAmount)
{
super("Turn");
myTurnThreshold = turnThreshold;
myTurnAmount = turnAmount;
myTurning = 0;
myDesired = new ArActionDesired();
}
/**
This is the guts of the Turn action.
*/
public ArActionDesired fire(ArActionDesired currentDesired)
{
double leftRange, rightRange;
// reset the actionDesired (must be done)
myDesired.reset();
double robotRadius = 400;
// Get the left readings and right readings off of the sonar
leftRange = (mySonar.currentReadingPolar(0, 100) - robotRadius);
rightRange = (mySonar.currentReadingPolar(-100, 0) - robotRadius);
// if neither left nor right range is within the turn threshold,
// reset the turning variable and don't turn
if (leftRange > myTurnThreshold && rightRange > myTurnThreshold)
{
myTurning = 0;
myDesired.setDeltaHeading(0);
}
// if we're already turning some direction, keep turning that direction
else if (myTurning != 0)
{
myDesired.setDeltaHeading(myTurnAmount * myTurning);
}
// if we're not turning already, but need to, and left is closer, turn right
// and set the turning variable so we turn the same direction for as long as
// we need to
else if (leftRange < rightRange)
{
myTurning = -1;
myDesired.setDeltaHeading(myTurnAmount * myTurning);
}
// if we're not turning already, but need to, and right is closer, turn left
// and set the turning variable so we turn the same direction for as long as
// we need to
else
{
myTurning = 1;
myDesired.setDeltaHeading(myTurnAmount * myTurning);
}
return myDesired;
}
/**
Calls the ArAction.setRobot() method to store the robot object (all setRobot overloaded functions must do this),
finds the sonar device from the robot.
*/
public void setRobot(ArRobot robot)
{
setActionRobot(robot);
mySonar = robot.findRangeDevice("sonar");
}
// this is to hold the sonar device form the robot
protected ArRangeDevice mySonar;
// what the action wants to do; used by the action resover after fire()
protected ArActionDesired myDesired;
// distance at which to start turning
protected double myTurnThreshold;
// amount to turn when turning is needed
protected double myTurnAmount;
// remember which turn direction we requested, to help keep turns smooth
protected int myTurning; // -1 == left, 1 == right, 0 == none
}
public class actionExample {
/* Try to load the Aria and ArNetworking wrapper libraries when the
* program starts:
*/
static {
try {
System.loadLibrary("AriaJava");
} catch(UnsatisfiedLinkError e) {
System.err.println("Native code library libAriaJava failed to load. Make sure that its directory is in your library path. See javaExamples/README.txt and the chapter on Dynamic Linking Problems in the SWIG Java Documentation (http://www.swig.org) for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
Aria.init();
ArSimpleConnector conn = new ArSimpleConnector(argv);
ArRobot robot = new ArRobot();
ArSonarDevice sonar = new ArSonarDevice();
// Create instances of the actions defined above, plus ArActionStallRecover,
ExampleGoAction go = new ExampleGoAction(500, 350);
ExampleTurnAction turn = new ExampleTurnAction(400, 10);
// a predefined action from Aria.
ArActionStallRecover recover = new ArActionStallRecover();
// Parse all command-line arguments
if(!Aria.parseArgs())
{
Aria.logOptions();
System.exit(1);
}
// Connect to the robot
if(!conn.connectRobot(robot))
{
ArLog.log(ArLog.LogLevel.Terse, "actionExample: Could not connect to robot! Exiting.");
System.exit(2);
}
// Add the range device to the robot. You should add all the range
// devices and such before you add actions
robot.addRangeDevice(sonar);
// Add our actions in order. The second argument is the priority,
// with higher priority actions going first, and possibly pre-empting lower
// priority actions.
robot.addAction(recover, 60);
robot.addAction(turn, 50);
robot.addAction(go, 40);
// Enable the motors, disable amigobot sounds
robot.enableMotors();
// Run the robot processing cycle.
// 'true' means to return if it loses connection,
// after which we exit the program.
robot.run(true);
Aria.exit(0);
}
}