... | @@ -119,9 +119,9 @@ The robot was still moving very slowly, so we changed the motor powers in the tu |
... | @@ -119,9 +119,9 @@ The robot was still moving very slowly, so we changed the motor powers in the tu |
|
|
|
|
|
#### Experimenting with faster initial ramp climb
|
|
#### Experimenting with faster initial ramp climb
|
|
|
|
|
|
We wanted to find a faster method for climbing the first ramp than using the old LineFollower program. As described, we initially disabled line following and instead used the program **FullDowney.java **[5] which simply makes the robot drive forward with full speed. We did this to see if, by positioning it correctly, we could get the robot to go straight up and not drive off the ramp.
|
|
We wanted to find a faster method for climbing the first ramp than using the old LineFollower program. As described, we initially disabled line following and instead used the program **_FullDowney.java_**[5] which simply makes the robot drive forward with full speed. We did this to see if, by positioning it correctly, we could get the robot to go straight up and not drive off the ramp.
|
|
|
|
|
|
The robot performed very poorly, often making a sudden turn off the track. After taking a closer look, we ended up replacing the left motor, a lego-stick-thing [TODO Ida: "change slightly bent sticky-thing to not bent sticky-thing" - tror at “sticky” = pinde-agtig, ikke klistret], and the support wheel. This seemed to improve the robot’s driving slightly, but did not fix the issues with seemingly random turns completely. We gave up on trying to get the robot to go straight without sensor input and went on to experimenting with the gyro sensor.
|
|
The robot performed very poorly, often making a sudden turn off the track. After taking a closer look, we ended up replacing the left motor, a LEGO-stick-thing, and the support wheel. This seemed to improve the robot’s driving slightly, but did not fix the issues with seemingly random turns completely. We gave up on trying to get the robot to go straight without sensor input and went on to experimenting with the gyro sensor.
|
|
|
|
|
|
### Experimenting with the gyro sensor
|
|
### Experimenting with the gyro sensor
|
|
|
|
|
... | @@ -193,7 +193,7 @@ As described previously, Nicolai and Emil worked on each their implementation of |
... | @@ -193,7 +193,7 @@ As described previously, Nicolai and Emil worked on each their implementation of |
|
|
|
|
|
The goal of this implementation was to use PID control to very accurately follow the black line, in order to use the resulting reliable entrance angle of the Y-sections and black borders on the platforms to guide the robot. As such, **_GodBot.java_** [10] was made.
|
|
The goal of this implementation was to use PID control to very accurately follow the black line, in order to use the resulting reliable entrance angle of the Y-sections and black borders on the platforms to guide the robot. As such, **_GodBot.java_** [10] was made.
|
|
|
|
|
|
In an attempt to improve our line follower we wanted to make several changes. First off, we started calibrating the two light sensors for seperate black/white light values using the **_BlackWhiteSensor.java_** [11] program, in order to guard ourselves against potential small differences in values read by two difference sensors. Then a basic controller utilizing both light sensors properly was implemented by calculating the *error* value for both light sensors, *leftError* and *rightError* (Black-White threshold subtracted from light reading), multiplying left*Error* value by -1, and then adding it to *rightError* for a combined *turn* value. Inverting one sensors error was to ensure that the two sensors were working together to correct toward the center of the black line, as they would be placed so each sensor was attempting to stay on one of the black tapes borders (left sensor on the left border, and right sensor on the right border obviously). This combined *turn *value was then used by subtracting it from the robot’s left motor’s power, and adding it to the right motor’s power.
|
|
In an attempt to improve our line follower we wanted to make several changes. First off, we started calibrating the two light sensors for separate black/white light values using the **_BlackWhiteSensor.java_** [11] program, in order to guard ourselves against potential small differences in values read by two difference sensors. Then a basic controller utilizing both light sensors properly was implemented by calculating the *error* value for both light sensors, *leftError* and *rightError* (Black-White threshold subtracted from light reading), multiplying left*Error* value by -1, and then adding it to *rightError* for a combined *turn* value. Inverting one sensors error was to ensure that the two sensors were working together to correct toward the center of the black line, as they would be placed so each sensor was attempting to stay on one of the black tapes borders (left sensor on the left border, and right sensor on the right border obviously). This combined *turn *value was then used by subtracting it from the robot’s left motor’s power, and adding it to the right motor’s power.
|
|
|
|
|
|
Running this program with a *targetPower* = 70 followed the line for the most part, but reacted far too violently to the line, causing big oscillations. It occurred to us that even though we didn’t implement P, I or D variables in the controller, the current program is basically a P controller with P = 2, since we are getting error values from two sensors and adding them together for doubled the effect on motor power. We solved this by simply dividing the *leftError + rightError* by 2 before adding to the motor’s power. This resulted in a robot that follows the line decently, although still oscillating a fair bit. We reduced the *targetPower* to 60, resulting in a *very* slow robot, but one that follows the line more steadily. As speed isn’t our top priority at the moment, we decided this was fine for an initial attempt at getting all the way to the top and back down.
|
|
Running this program with a *targetPower* = 70 followed the line for the most part, but reacted far too violently to the line, causing big oscillations. It occurred to us that even though we didn’t implement P, I or D variables in the controller, the current program is basically a P controller with P = 2, since we are getting error values from two sensors and adding them together for doubled the effect on motor power. We solved this by simply dividing the *leftError + rightError* by 2 before adding to the motor’s power. This resulted in a robot that follows the line decently, although still oscillating a fair bit. We reduced the *targetPower* to 60, resulting in a *very* slow robot, but one that follows the line more steadily. As speed isn’t our top priority at the moment, we decided this was fine for an initial attempt at getting all the way to the top and back down.
|
|
|
|
|
... | @@ -279,11 +279,11 @@ The robot may have had trouble getting safely up the ramps using this approach, |
... | @@ -279,11 +279,11 @@ The robot may have had trouble getting safely up the ramps using this approach, |
|
|
|
|
|
#### Combining line following ramp climbing with piloted platform turns
|
|
#### Combining line following ramp climbing with piloted platform turns
|
|
|
|
|
|
Initially, we included code from **_GodBot.java_** [10] in a copy of **_SimplePilot.java _**[16], **_PilotedCarLineFollower.java _**[17], to drive the robot up the ramp instead of using pilot.forward(). In the API for DifferentialPilot [TODO ref. til [http://www.lejos.org/nxt/nxj/api/lejos/robotics/navigation/DifferentialPilot.html](http://www.lejos.org/nxt/nxj/api/lejos/robotics/navigation/DifferentialPilot.html)] it is stated that the results of other objects making calls to the motors when DifferentialPilot is in use are unpredictable. We had trouble figuring out how to separate line following control from the differential pilot’s control, to be able to switch between them. Our first attempt was to instantiate the DifferentialPilot within the if-statement that captures the case where the robot reads black on both sensors, so that it would only try to run in this isolated case and would be terminated upon exit from the if-statement’s scope. The robot had no trouble getting up the first ramp using line following and individual control of the motors, and it performed the turn on the first platforms - but after this, when exiting the if-statement, the robot started randomly turning and racing around. We spent several hours trying out different approaches to getting the differential pilot to work along with the GodBot line following, but did not succeed.
|
|
Initially, we included code from **_GodBot.java_** [10] in a copy of **_SimplePilot.java _** [16], **_PilotedCarLineFollower.java _** [17], to drive the robot up the ramp instead of using pilot.forward(). In the API for DifferentialPilot [TODO ref. til [http://www.lejos.org/nxt/nxj/api/lejos/robotics/navigation/DifferentialPilot.html](http://www.lejos.org/nxt/nxj/api/lejos/robotics/navigation/DifferentialPilot.html)] it is stated that the results of other objects making calls to the motors when DifferentialPilot is in use are unpredictable. We had trouble figuring out how to separate line following control from the differential pilot’s control, to be able to switch between them. Our first attempt was to instantiate the DifferentialPilot within the if-statement that captures the case where the robot reads black on both sensors, so that it would only try to run in this isolated case and would be terminated upon exit from the if-statement’s scope. The robot had no trouble getting up the first ramp using line following and individual control of the motors, and it performed the turn on the first platforms - but after this, when exiting the if-statement, the robot started randomly turning and racing around. We spent several hours trying out different approaches to getting the differential pilot to work along with the GodBot line following, but did not succeed.
|
|
|
|
|
|
##### DifferentialPilot line following
|
|
##### DifferentialPilot line following
|
|
|
|
|
|
Deciding to take a break from attempting the combined approach, we resorted to implementing line following using the DifferentialPilot’s arc-method, in the class **_Piloted_****_LineFollower_****_.java _**[18] [TODO pretty?]. It proved difficult to properly steer the robot according to divergence in the black/white readings of the sensors. Though this was perhaps most likely due to a limited overview of how to utilize our error measurements in the arguments to **_arc()_** and/or increasing tiredness and frustration levels, we temporarily gave up on creating a satisfactory implementation. Instead, we began an implementation using a switcher to switch between behaviors implemented in an interface. This is described in the section below. After some debate regarding this solution (to be found in the section below), we continued the attempt at implementing line following using DifferentialPilot. We experimented with different parameters for **_arc()_** and introduced a turn utilizing **_rotateRight()_** to turn until aligned with the bottom bar of the Y on the platform in order to let the robot more easily find its way back on track after making a platform turn. We also performed other minor additions. We managed to get the robot to the second platform, successfully performing the intermediate turn operation on the first platform (see Video 7). At some point, however, the robot began failing in detecting the black end line - perhaps due to poor lighting in the later hours of the day, perhaps due to the sensors being raised as they were sometimes scraping on the track, and perhaps simply due to low battery. As black sensing was still working for the other two ongoing implementations, we decided to leave the DifferentialPilot at this.
|
|
Deciding to take a break from attempting the combined approach, we resorted to implementing line following using the DifferentialPilot’s arc-method, in the class **_PilotedLineFollower.java _**[18] [TODO pretty?]. It proved difficult to properly steer the robot according to divergence in the black/white readings of the sensors. Though this was perhaps most likely due to a limited overview of how to utilize our error measurements in the arguments to **_arc()_** and/or increasing tiredness and frustration levels, we temporarily gave up on creating a satisfactory implementation. Instead, we began an implementation using a switcher to switch between behaviors implemented in an interface. This is described in the section below. After some debate regarding this solution (to be found in the section below), we continued the attempt at implementing line following using DifferentialPilot. We experimented with different parameters for **_arc()_** and introduced a turn utilizing **_rotateRight()_** to turn until aligned with the bottom bar of the Y on the platform in order to let the robot more easily find its way back on track after making a platform turn. We also performed other minor additions. We managed to get the robot to the second platform, successfully performing the intermediate turn operation on the first platform (see Video 7). At some point, however, the robot began failing in detecting the black end line - perhaps due to poor lighting in the later hours of the day, perhaps due to the sensors being raised as they were sometimes scraping on the track, and perhaps simply due to low battery. As black sensing was still working for the other two ongoing implementations, we decided to leave the DifferentialPilot at this.
|
|
|
|
|
|
[TODO: Fix to markdown video format]
|
|
[TODO: Fix to markdown video format]
|
|
|
|
|
... | @@ -297,7 +297,7 @@ We constructed an architecture with a class, **_Switcher.java_** [19] with a fie |
... | @@ -297,7 +297,7 @@ We constructed an architecture with a class, **_Switcher.java_** [19] with a fie |
|
|
|
|
|
##### Using a bumper
|
|
##### Using a bumper
|
|
|
|
|
|
An implementation similar to **_SimplePilot.java_** [16], that used a touch sensor to detect when the robot hit the wall by the track *and then* making the second 90 degree turn, was also made (**_PilotWithBumper.java _**[23]), but was never tested. To test it, we would have to refit the robot with a touch sensor, preferably with a bumper to ensure that collision with the wall would be detected no matter the angle of the robot. Since the difference to using SimplePilot seemed minor and we figured that this version would take longer to complete the track due to having to wait until hitting the wall and then backing up, we decided to postpone refitting with a touch sensor until we might see an actual gain in using one. We never got to this point. A benefit we might have seen would be the possibility of letting the robot use the bumper to align with the wall, by waiting a little before stopping upon impact, thus enabling it to enter the next ramp perpendicularly after making the 90 degree turn following collision.
|
|
An implementation similar to **_SimplePilot.java_** [16], that used a touch sensor to detect when the robot hit the wall by the track *and then* making the second 90 degree turn, was also made (**_PilotWithBumper.java_**[23]), but was never tested. To test it, we would have to refit the robot with a touch sensor, preferably with a bumper to ensure that collision with the wall would be detected no matter the angle of the robot. Since the difference to using SimplePilot seemed minor and we figured that this version would take longer to complete the track due to having to wait until hitting the wall and then backing up, we decided to postpone refitting with a touch sensor until we might see an actual gain in using one. We never got to this point. A benefit we might have seen would be the possibility of letting the robot use the bumper to align with the wall, by waiting a little before stopping upon impact, thus enabling it to enter the next ramp perpendicularly after making the 90 degree turn following collision.
|
|
|
|
|
|
### Discussion of alternative approaches
|
|
### Discussion of alternative approaches
|
|
|
|
|
... | @@ -313,9 +313,9 @@ We ended up having to work for more than the two days originally planned. We wor |
... | @@ -313,9 +313,9 @@ We ended up having to work for more than the two days originally planned. We wor |
|
|
|
|
|
At the 5th of April we decided to split the group into working with two different approaches to a PID line follower, and another using the DifferentialPilot. One PID follower focused on very precise line following for predictable light sensor readings when encountering the Y-sections to trigger the turns on the platforms, whereas the other used a simple idea of which side of the line the robot was on, whilst using the tacho counter to handle the turns on the platform.
|
|
At the 5th of April we decided to split the group into working with two different approaches to a PID line follower, and another using the DifferentialPilot. One PID follower focused on very precise line following for predictable light sensor readings when encountering the Y-sections to trigger the turns on the platforms, whereas the other used a simple idea of which side of the line the robot was on, whilst using the tacho counter to handle the turns on the platform.
|
|
|
|
|
|
The precision line follower, **_PIDGod.java _**[13], had a lot of success getting to the top of the platform, and once we raised the light sensors were able to drive down as well, but the problems caused by the raised sensors reading black from being too far off the ground when driving onto the platforms while driving up the track, meant we were never able to get a reliable reaction to all of our desired turning triggers, and could never get it to drive up and down in a singular build and program.
|
|
The precision line follower, **_PIDGod.java_** [13], had a lot of success getting to the top of the platform, and once we raised the light sensors were able to drive down as well, but the problems caused by the raised sensors reading black from being too far off the ground when driving onto the platforms while driving up the track, meant we were never able to get a reliable reaction to all of our desired turning triggers, and could never get it to drive up and down in a singular build and program.
|
|
|
|
|
|
The other PID line follower approach, **_OldPIDTest.java_**, wasn’t very consistent in reaching the top, but did it a lot faster. It was intended to be a simple solution, but it became obvious that the implementation could also easily become complex. At times it performed consistently, but it could also be very unstable. It wasn’t entirely clear which factors affected the performance, but it seemed like especially battery and the resulting motor power would affect both the tacho counter and linefollowing. The low level of ambient light also seemed to affect our light readings when attempting to drive down. With a few very good results and a relatively simple implementation, it definitely shows promise and serves as a fine proof-of-concept of what we initially attempted to achieve.
|
|
The other PID line follower approach, **_OldPIDTest.java_** [14], wasn’t very consistent in reaching the top, but did it a lot faster. It was intended to be a simple solution, but it became obvious that the implementation could also easily become complex. At times it performed consistently, but it could also be very unstable. It wasn’t entirely clear which factors affected the performance, but it seemed like especially battery and the resulting motor power would affect both the tacho counter and linefollowing. The low level of ambient light also seemed to affect our light readings when attempting to drive down. With a few very good results and a relatively simple implementation, it definitely shows promise and serves as a fine proof-of-concept of what we initially attempted to achieve.
|
|
|
|
|
|
Our attempt to use the **_DifferentialPilot_** class was illustrative of the inconsistencies that the real world brings into robot programming; although **_DifferentialPilot_** is very effective at controlling the robot’s movements precisely, the simple approach in **_SimplePilot.java_** [16] is not enough to make a functioning hill-climbing robot as external factors bring the robot off a perfectly straight course. The work on **_PilotedLineFollower.java_** [18], which adds line following to SimplePilot, showed promise, but due to time constraints we chose to opt out of our experiments with it before having implemented a fully functional up-down robot.
|
|
Our attempt to use the **_DifferentialPilot_** class was illustrative of the inconsistencies that the real world brings into robot programming; although **_DifferentialPilot_** is very effective at controlling the robot’s movements precisely, the simple approach in **_SimplePilot.java_** [16] is not enough to make a functioning hill-climbing robot as external factors bring the robot off a perfectly straight course. The work on **_PilotedLineFollower.java_** [18], which adds line following to SimplePilot, showed promise, but due to time constraints we chose to opt out of our experiments with it before having implemented a fully functional up-down robot.
|
|
|
|
|
... | | ... | |