tirsdag den 29. april 2014

Week 10 - Lesson 9


Date:
28/4-2014 (round 1), 29/4-2014 (round 2)

Duration of activity:
10:00 - 15:00 (round 1), 11:30 - 14:00 (round 2)

Group members participating:
Levi, Christina, Benjamin

Goal:
In this lab session we will apply the tacho counter of the NXT motor to keep track of the position and direction af a LEGO car with so called differential drive where two motors are used independtly to move and steer a car as shown in Figure 1.
Figure 1 A car with differential drive that can turn in place [1].


Navigation


We started out with building the basic car, as described in the Mindstorms education manual.
Instead of mounting the thick wheels used in the manual, we used the smaller and thinner solid rubber wheels, so to easier measure radius and circumference of the wheels.






The diameter of the wheels is 4.3 cm and isn’t affected much when the NXT is placed on the car, and the wheels have to support it (thereby possibly being pushed down making them more flat). The track width is measured from the center of the right tire to the center of the left tire, as the documentation describes is should be. This distance is 9.6 cm.


A whiteboard marker was attached to the front of the car. A construction was made so that the marker is pushed towards the board only by gravity, and in a slightly tilted way so that the marker is tilting towards the car. This is important because the car experiences too much resistance from the marker touching the board, if the marker is fixed in a way that ‘pushes’ it to hard against the board.




When using the above measurements for wheel diameter and track width, we got the following pattern drawn on the white board. On the pattern we have marked the starting and ending point with a red marker, as well as drawing lines between the points that the car wants to reach.





The car was supposed to make a turn that would intersect with the first line in a right angle (see picture below), but from the picture it is clear that this is not the case.



We therefore tried adjusting the measurements of the wheels’ diameter to something smaller, because the car doesn’t turn as much as it should, and that we therefore think that the car will turn some more if it ‘thinks’ it has smaller wheels. We changed the diameter to 4.3 cm and got the following result:



We could see that this helped in the degree of rotation and then changed the diameter to 4.1 cm, and got the following result:



We think that we achieve the degree of the rotation of the car to produce a right angle at the intersection as it should, using close to 4.1 cm as the diameter of the wheels.


Experimenting some more with the car’s ability to rotate the correct amount (as Bagnell[2] notes is it’s weakness) along with it’s ability to drive forward the correct distance, we made it go around in a square, that is: going from (0,0) to (20,0) to (20,20) to (0,20) to (0,0).


With the values as the following: diameter = 4.1 cm, track width = 9.7cm, the result was as follows:



We tried experimenting with different values for the diameter and track width (noted on the board for the different produced drawings of the route), and some of them can be seen here:





We were unable, in this round, to find values that produced a fully correct drawn square in regards to the correct degree of turning, so that it ended in the correct place.

We tried changing the wheels to some one that we thought might have a more easily accurately measurable contact surface.


We then got a hint that we could try calibrating the values by driving the car forward and then rotate it 180 degrees, and set the values so that the point where it ended was exactly on the line that it had driven forward on. We experimented with this and found values (using the new wheels) of 5.61 cm for the wheelDiameter and 10.5 cm for the track width, to produce a correct result. A picture of the result when calibrated is shown below:





We then tried to perform a rotation in between the goTo-methods when attempting to draw a square, using the rotateTo-method, because we now were able to turn the car the exact correct amount (at least when turning 180 degrees).
The code for this approach is shown below:




This approach helped a lot, and we were able to produce an (almost) exact square.
The video below shows the robot producing the square.



The picture below not only shows the drawn square by the car, but the coordinates and coordinate system that the car ‘produces’. It also shows how the system interprets arguments for the value of degrees; the angles. We experimented with different ways of rotating the car (like for instance writing -270 instead of 90) and found that the drawn system is how it works.




It is important to notice that the drawing produced is not a representation of the center of the car (center = the center between the wheels), and that the produced drawing therefore is displaced from the actual coordinates of the car. See drawing below.





However, the displacement is relatively the same, so the produced drawing can be used as a ‘displaced coordinate representation’ relatively, to conclude whether or not the car actually turns the correct amount and drives the correct amount forward before turning (because if the center between the wheels moves 10 cm forward, so does the marker placed in front of the car, and if the car turns 90 degrees, so does the marker).


After this worked, we again tried getting the car to work producing a square using only goTo-methods and not the rotateTo-methods in between. Other values were used (5.55 cm for the wheel diameter and 10.62 cm for the track width found by experimenting), and a square was finally produced.
The picture below shows the square produced.





Navigation while avoiding objects

Our approach to make the car move from place to place using the leJOS navigation system while avoiding objects in front ot it, is to attach an ultrasonic sensor to the front of the car, and sense if anything comes within approximately 30 cm of the front of the car.
If it does, we want the car to make a turn in a certain direction and go a bit forward, before beginning to go to the end point again. If something new gets in the way, the car should avoid it in the same manner and continue to try to get to the end point afterwards.


The code for this approach can be seen below, and be found here [3].





Making the car go forward is done by adding 20 to the value of the Y-coordinate, doing nothing to the X-coordinate and then making the car go to this new coordinate set:
robot.goTo(pose.getX(), pose.getY()+20);


We found that it was necessary to clear the path for the Navigator class robot for it to properly go to the new point before attempting to go to the endPoint.

A video that shows the car avoiding objects and getting to its destination is here:



Improved Navigation

In [2] there is a formula that shows how the position and direction are updated during the moves of a mobile robot. In [5], another update formula is used. What is the difference, what is the most accurate? Try to figure out how leJOS updates the position and direction. Can you use [5] to improve that? Or?


We did not complete this task. Unfortunately, mainly because of lack of time.


Conclusion
We completed the first two tasks to a satisfactory degree. Unfortunately, we ran out of time and were unable to get the last task done.

References

  • [1], Java Robotics Tutorials, Enabling Your Robot to Keep Track of its Position. You could also look into Programming Your Robot to Navigate to see how an alternative to the leJOS classes could be implemented.
  • [2], Brian Bagnall, Maximum Lego NXTBuilding Robots with Java Brains, Chapter 12, Localization, p.297 - p.298.

mandag den 7. april 2014

Week 8 - Lesson 7

Date:
3/4-2014(round 1), 7/4-2014(round 2)
Duration of activity:
10:00 - 15:00(round 1), 11:00 - 14:00(round 2)
Group members participating:
Levi, Christina, Benjamin

Goal:
We will use the behaviour control paradigm to implement several observable behaviours on a single NXT that controls a LEGO vehicle with an ultrasonic sensor, a light sensor and two touch sensors.

LEGO vehicle that exhibits a single behaviour

Behaviour of car:

The car drives forward if no obstacles are met. If an obstacle is met, the car stops, and then turns approximately 45 degrees to the right. Immediately after, it drives backwards to original position, and then turns approximately 45 degrees to the left. Looking at the code, we can see that it stores the distance when having turned left and right respectively. If it measures that the right distance is further than the left, it drives backwards again to original position, turns approximately 45 degrees to the right again, and then drives forward. 

Change the program:

Despite the uncertainty of what a "tree" distance is, here is our take.

First of all we need to make sure that if all the three distances measured (frontDistance, leftDistance and rightDistance) are less than the value of stopThreshold, the car sets itself back to the original position after having completed the measurements, as this is not directly in the code provided. When it has done this the car should back up a little and following this, it should spin around on the spot 180 degrees.
The altered code for this behaviour of the car can be found at [1].

A video showing the new behaviour of the car is shown here:

Behaviours as concurrent threads

Describe how the car behaves:

We tried two different environments when testing the car. The first was our TA room where the light is somewhat dim. Afterwards we moved to the entrance area of the TA room where there are windows and thus more sunlight. We did not reset the program between the two settings, so the car did not get new thresholds in the new setting, and thus would act like it was in the first setting.

We tested the triggers by doing different things: when we held a hand close in front of the sonar the LCD displayed ‘Winner 1’ (and executed the ‘avoid’ action) and when nothing was in front of the sonar (at least not in the distance corresponding to the value of 30 - which we found was about a distance of about 30-35 cm) it displayed ‘Winner 2’ if the car was oriented in way that it measured light with a value higher than the value from when the program was started (which is the action ‘follow’).
If the car was oriented in a way that it measured light with a value lower than the value it measured when the program was started and if nothing was in front of the sonar for at least 30-35 cm, the program executed ‘cruise’ and displayed ‘Winner 3’.

The conditions that trigger ‘cruise’ is when there isn’t anything to avoid and when there isn’t any light to follow. When there is light to follow it will follow it (until and unless there is something to avoid) and it won’t start cruising until there isn’t any light to follow anymore.

Triggering conditions:

Avoid: The avoid class acts exactly like the programme ‘AvoidFigure9_3.java’ in the first task
Follow: Here the car drives left and right respectively and measures the light intensity. Then it calculates the delta value, subtracts it from the left motor power, and adds it to the right motor power. This way it will turn towards the brighter side.
Cruise: This class make the car cruise like a gangsta with style!

Add an Escape behaviour

The implementation of the escape behaviour from page 305 of [2] is to check if the two touch sensors bump into anything. If both sensors register that they have touched something it means that the car is being bumped from the front, and the program therefore makes the car drive backwards.
If only the left sensor is bumped, the implementation believes that the car has run into something on the left side of the car, and henceforth turns the car to the right (for a while, the comments for the code says).
Vice versa; if the touch sensor on the right touches something, the car is set to turn to the left.
In this way the robot is able to escape from collisions with obstacles.

First of all we put two touch sensors on the car and attached the two to each other via a ‘bumper’. A picture that shows this is here:


In our implementation of making the car escape from a front bump we start with experimenting with making the car drive backwards for large amount of time in order to get the car to get entirely clear of the wall so that it will not hit it with the bumper when turning to the side to measure the leftDistance and rightDistance.

The code for the programme can be found here [3].

The behaviour can be seen in the video here:

Add a third motor to turn the light sensor

We followed instructions to mount a horizontal motor on the vehicle, and mounted the light sensor on the motor:


In order to reimplement the follow behaviour with the new motor, we utilised LeJOS' NXTRegulatedMotor. This allowed us to turn the motor to specific angles, and thus switch between 45 degrees and -45 degrees from start point.
Here is a video of our implementation in practice:
The altered code can be seen at [4].

The classes SharedCar and Arbiter

In [3] multiple outputs are directed to the same input (that is the function arbitrate()) and the outputs occurring latest in the ordered list of statements have superiority of the earlier ones in the list.
The function arbitrate() is shown below.


As described, the latest output subsume the earlier ones. In the function above, this means that the process for ‘escaping’ overwrites the process for ‘avoiding’ which overwrites the process for ‘following’ that in turn overwrites the process for ‘cruising’. This behaviour makes sure the robot isn’t going to start following light if it has to avoid an object in front of it or if it has hit something.

In the class Arbiter the hierarchy of actions to be performed is implemented. The priority of actions is from the list of car’s in the SharedCar list. The list is run through from the 0th car to the x’th car in the list. In our case this is from the 1st car to the 3rd car.

The code for the Arbiter class is seen below.


If a carCommand from the first car from the list that is checked is different from null, the action of this car is performed. If the carCommand is null, then the carCommand from the next car in the list is checked, and if this is null, the last car’s carCommand from the list is checked. Whenever a car in the list has a carCommand that isn’t null, the for loop that checks all the list’s car’s carCommand’s is broken out of. This means that if the first car in the list has a carCommand different from null, then the other cars carCommand isn’t checked. In this way, the action of the first car in the sharedCar list has priority over the cars further into the list of cars in the sharedCar list.
Establishing the order of prioritisation is done by adding cars to the sharedCar list in the order of decreasing importance, as shown below. 


This order means that the action of an ‘avoiding’ car has superiority over a ‘following’ car which again has superiority over a ‘cruising’ car. In this example the action of an ‘escaping’ car isn’t implemented, but it is prepared to be added to the sharedCar list of cars as the first element (0-indexed), because it has to be prioritised over the action of ‘escaping’.



In [5] there is no need to put the actions in a list in a prioritised order. This implementation is slightly different and makes use of assigned numbers to each action, where a higher number equals higher priority. In his implementation the entire list of enabled processes is searched, and the enabled process with the highest number gets to run.

Conclusion:

Everything went better than expected.

References:

[1] AvoidFigure9_3.java
[2] Jones, Flynn and Seiger
[3] RobotFigure9_9.java
[4] Follow.java
[5] Fred Martin p. 214-218