Controlling Wheeled Vehicles
A common type of robot is the two wheeled vehicle with independently controlled motors. This design uses differential steering and can turn in place. There are other possible mechanical designs which controlled by other classes. The classes that control vehicles work at several levels of abstraction. At bottom, there are the motors that turn the wheels, controlled by the NXTRegulatedMotor class. The DifferentialPilot class uses the motors to control elementary moves: rotate in place, travel in a straight line, or travel in an arc. At the next level, the Navigator uses a DifferentialPilot to move the robot through a complicated path in a plane. To do navigation, the navigator needs the robot location and the direction it is heading. It uses a OdometeryPoseProvider to keep this information up to date. The relationships among these classes is shown in the in the table.
The flow of control is from the top down: the navigator controls the pilot which controls the motors. But the flow of information is from bottom up. The pilot uses information from the motors to control them. The pose provider uses odometry information from the pilot to update its current estimate of the robot pose. The pose consists of the robot's coordinates (x and y) and its heading angle (the direction it is facing ). The navigator uses this data to calculate the distance and direction to its destination.
The flow of information uses the listener and event model. The pilot registers as a listener to with motors, which inform it when a motor rotation is started or completed. The pose provider registers as a listener with the pilot, which informs it of the start and completion of every movement. This event driven information flow is automatic. In addition to this event driven flow, the navigator can also requests a pose estimate from the pose provider at any time, even while the robot is moving. This chain of listeners is established as the DifferentialPilot and Navigator are constructed.
The DifferentialPilot class controls a vehicle that has two driving
wheels, each with its own motor. It steers the vehicle by
controlling the speed and direction of rotation of its motors. It
is one of several Move Controllers that are based on different
mechanical designs, but the differential steering design is the
Straight line movement
To control the robot moving in a straight line, use:
To control the distance the robot moves, use:
You can cause the robot to begin rotating in place by using
If angle is positive, the robot turns to the left.
The immediateReturn parameter works as in the Motor
methods –allowing the calling thread to do other work while
the rotation task in progress. If another method is called on the
pilot while the rotation is in progress, the rotation will be terminated.
Write a program that uses a DifferentialPilot to trace out a square, using the travel and void rotate(double degrees) methods.
Write a program that traces 2 squares with increasing angle at the corners, then retraces the same path in the opposite direction.. Modify the traceSquare method of program DifferentialPilot 1 so it can trace a square in either direction, and use it in this program. This is stringent test of the accuracy of the wheel diameter and track width constants you use in you pilot.
Traveling in a circular path.
DifferentialPilot can also control the robot to move in a circular path using these methods:
The turnRate parameter determines the radius of the path. A positive value means that center of the circle is to the left of the robot (so the left motor drives the inside wheel). A negative value means the left motor drives the outside wheel. The absolute value is between 0 and 200, and this determines the ratio of inside to outside motor speed. The outside motor runs at the set speed of the robot; the inner motor is slowed down to make the robot turn. At turn rate 0, the speed ratio is 1.0 and the robot travels in a straight line. At turn rate 200, the speed ratio is -1 and the robot turns in place. Turn rate 100 gives speed ratio 0, so the inside motor stops. The formula is: speed ratio = 100 - abs(turnRate).
The angle parameter determines the rotation angle at which the robot stops. If the angle is negative, the robot follows the circular path with the center defined by the turn rate, but it moves backwards.
Write a program that uses the ButtonCounter to enter the turn rate and angle variables, and then calls the steer() method. It does this in a loop so you can try different values of these parameters to control the robot path.Methods that start the robot moving in a circular arc path:
If the radius is positive, center of rotation is on left side of the robot. Methods that complete a circular arc:
Communicating with OdometryPoseProvider
The OdometryPoseProvider keeps track of the robot position and
heading. To do this, it needs to know about every move made by the
DifferetnialPilot. So the pose provider needs to register as a
listener with the pilot by calling the
Other methods for DifferentialPilot
If you need very accurate pilot movement, you might need to use speed and acceleration values less than the defaults.
The CompassPilot is an extension of the DifferentialPilot class. It implements the same methods, but uses a Compass Sensor to ensure that the pilot does not deviate from the correct angle of robot heading.
It needs a HiTechnic or Mindsensors compass sensor plugged in to one of the sensor ports. Its constructors are similar those of DifferentialPilot, but with the additional information of the compass sensor port.
Additional methods in CompassPilot:
Additional methods in CompassPilot:
Write a program that does these steps:
Suggestion: while the robot is moving, nudge it off course and watch it steer back to the correct heading.
The responsibility of this class is to maintain a current estimate
of the robot location and the direction in which it is heading.
robot heading uses Cartesian coordinates, with angles in degrees; 0
degrees is the direction of the positive x axis, 90 degrees is the
positive y axis. The heading and x and y coordinates are stored in a Pose object. The API for Pose is
here. For the OdometryPoseProvider documentation
The only methods you are likely to need to use are:
If you want to know about the inner workings of this class, read
The odometry data is contained in a Move object. The API of this data carrier class is here.
The Navigator class uses a pilot to control the robot movement, and
a PoseProvider to keep track of the robot position. The navigator
follows a route, a sequence of locations. Each location is an instance
of the Waypoint class. The WayPoint API is here.
The route is an instance of the Path class, and the Path API is
here. The route behaves as a first-in-first-queue. When the a way
point is reached, it is removed from the route and the robot goes
to the next one. New way points can be added to the end of the
route at any time. Documentation for the Navigator is here.
Both constructors will register the pose provider as a MoveListener with the pilot.
All the methods (with one exception) in this class are non-blocking, i.e. they return immediatey.
Suppose your robot is in a known location and needs to get to a destination. But there are obstacles in the way. These obstacles are shown on a map. So what route should it follow? This class can find the shortest path to the destination, and produce a route (a collection of WayPoints) that the NavPathController can use. The map this class needs is a LineMap which, as its name suggests, consists of straight lines.The complete documentation for this class is here. Using this class is very simple. The constructor is:
After you constructed the path finder, you can get the route by using either of the route finding methods. They both use a Pose as the starting point, which might be returned returned by the a pose provider, and a WayPoint as the destination. The both will throw the DestinationUnreachableException if no route can be found.
The shortest path, if not a direct line, will have way points at the ends of lines, such as the corners of obstacles on the map. But the physical robot is not a point, so if the center of the robot tries to pass through a corner, there will be a crash. One solution to this difficulty is to enlarge the map obstacles to allow clearance for the robot. However, this may be tedious to by hand, and complex to do with software. A simpler scheme is to extends all the lines on the original map so that a corner now is represented by two points, each some distance from the corner. To make this modification of the map,use the method :
which adds a segment of length delta to each line on the map. The extension delta should probably be at least the track width of the robot, plus an allowance for uncertainties in the robot location.
There are several other path finding classes that use various map representations. See the links to the classes in the pathfinding package here.