Mobile Robot Control 2020 Group 1: Difference between revisions
Line 129: | Line 129: | ||
== Design architecture == | == Design architecture == | ||
== Strategy == | |||
The purpose of the strategy class is to compute and return the path that PICO needs to take in order to complete its tasks. There are eight functions in this class: findPath, isValid, isGoal, isDest, calcHeuristic, makePath createWPs and crossObject. | |||
findPath is one of the two core functions on which this class is built. This function takes as input the position of PICO and the target point that PICO needs to reach and it outputs a vector of target points. It also takes a Boolean as an input indicating if the path can go diagonal. This was mainly used for debugging purposes. | |||
The findPath function uses the world grid stored in the world model to compute the shortest path to its destination using an A* algorithm. The A* algorithm is very similar to Dijkstra’s algorithm, however, A* uses a heuristic to estimate the total cost of a given node instead of only the cost to reach a certain node. More information of Dijkstra’s or the A*algorithm can be found here [https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm, https://en.wikipedia.org/wiki/A*_search_algorithm] | |||
https://www.youtube.com/watch?v=g024lzsknDo comparison speed between A* and dijkstra? | |||
The isValid function evaluates if a certain node in the grid is marked as a reachable node or not and the isGoal and isDest functions both check if a given node is the final destination or not. The reason for two separate function has to do with the input arguments for both. The isGoal function takes in the x,y coordinates of both the position of PICO and the target and is ran at the start of the algorithm to check if PICO is already on its destination. The isDest function takes in the x,y coordinates of the target and a custom datatype named pathNode. This function is run within the A* algorithm to check if an evaluated node is already the destination or if it needs to continue running. | |||
The A* algorithm also needs the calcHeuristic function which estimates the remaining cost to reach its destination by computing the distance between the node being evaluated and the target node. | |||
After the A* algorithm reached the destination, the makePath function runs backwards from the target node to node representing PICO’s position using the saved parent nodes. This returns a vector of nodes representing the shortest path. | |||
After the shortest path is found, a string pulling algorithm is used to reduce the size of the shortest path vector. This is done in the createWPs function. Here, the path is evaluated on which nodes can reach each other in a straight line without crossing an unreachable node, which is done using the crossObject function. Everytime a node cannot be reached from the starting node, the node before it is stored and then used as the new node from where we start evaluating the remaining nodes. | |||
The figure below shows the entire process of the strategy class. (left to right: worldgrid, A* path, Waypoints) | |||
== Components == | == Components == | ||
=== Localization === | |||
=== Perception === | |||
The main goal of the perception component is to translate the real world data into data which can be used for the simulation. The real world data consists of the LRF-data and the odometry data. Perception uses this data to localize PICO, detect obstacles and to measure the distance to objects around PICO. | |||
==== Localization ==== | |||
=== Path planning === | === Path planning === | ||
=== Movement === | === Movement === | ||
The purpose of the movement class is to compute and send reference velocities to PICO’s actuators. The class consists out of five functions: driveToRef, driveOmniDirection, rotate, stop and allignCabinet. | |||
driveToRef takes as input PICO’s position, a given target point, the potential field vector and a Boolean stating whether or not the target is a cabinet. It outputs a Boolean stating if the target position is reached (true) or not (false). This function is the core of the movement class. It first computes the direction in which PICO is intended to move by adding the potential field vector to the target vector. It then uses a proportional controller to compute the reference velocities in all directions. These reference velocities are then used as a function input for driveOmniDirection. The Boolean stating if the target is the cabinet node was required in order to get closer to the cabinet. For all targets the minimum distance to the target before returning the Boolean stating the target was reached was set higher than for the final target. This was done since if PICO was pushed away from a target due to the potential field it would continue to the next target (if possible) instead of trying to perfectely reach the target. However, for the last target denoting the cabinet position it is important that this target is reached with greater precision. | |||
driveOmniDirection is used to send the reference velocities to PICO’s actuators using the sendBaseReference function. The reason for pulling this function out of the drive to ref function is that with this extra method, other classes could also use it to move PICO in order to accomplish smaller tasks, for example rotate PICO during localization. The rotate and stop functions accomplish the same effect, however, the number of inputs change, the rotate function only takes an angular velocity and the stop function does not have an input. | |||
allignCabinet takes as an input the ID of the target cabinet and the position of PICO and it returns a Boolean indicating if PICO is aligned to the cabinet (true) or not (false). This function is required since the objective states that when PICO has reached a cabinet he needs to face it. The reference orientation for every cabinet is harcoded in a vector and a proportional controller is used to align with this reference (in the same manner as for the driveToRef function). | |||
=== Monitoring === | === Monitoring === | ||
The monitor class serves as a safety net in case PICO shows undesired behavior. Initially the monitoring checked multiple cases. First of all, if an object was too close to PICO a flag would be given. The object would be in PICO’s safe space which is a circle around PICO with a certain radius. Furthermore, if the potential field vector became too large, also a flag would be given. The idea was that if the potential field vector became too large, PICO should not be able to pass an object. Lastly, if something was placed on the desired location of PICO, also a flag would be given. There was initially thought that in this case the path of PICO could not be continued. However, since the desired locations of PICO is reached by means of waypoints, the waypoints could be changed in order to reach the desired location. | The monitor class serves as a safety net in case PICO shows undesired behavior. Initially the monitoring checked multiple cases. First of all, if an object was too close to PICO a flag would be given. The object would be in PICO’s safe space which is a circle around PICO with a certain radius. Furthermore, if the potential field vector became too large, also a flag would be given. The idea was that if the potential field vector became too large, PICO should not be able to pass an object. Lastly, if something was placed on the desired location of PICO, also a flag would be given. There was initially thought that in this case the path of PICO could not be continued. However, since the desired locations of PICO is reached by means of waypoints, the waypoints could be changed in order to reach the desired location. | ||
Line 140: | Line 173: | ||
The first two flags were not used because the parameters of the potential field are chosen in such a way that these flags would not become true. A snipped of the c++ code of the monitor class is showed in this link... | The first two flags were not used because the parameters of the potential field are chosen in such a way that these flags would not become true. A snipped of the c++ code of the monitor class is showed in this link... | ||
=== Visualization === | === Visualization === | ||
Revision as of 09:18, 18 June 2020
Group Members
Name | Student Number | |
---|---|---|
1 | T.J.M. Snijders | 1017557 |
2 | B.P.J. Reijnen | 0988918 |
3 | J.H.B. de Zwart | 1020347 |
4 | S.C.M. Mennen | 1004332 |
5 | A.C.C.E. Vissers | 0914776 |
6 | B. Godschalk | 1265172 |
Introduction
This Wiki-page reports the progress made by Group 1 towards completion of the Escape Room Challenge and Hospital Challenge. The goal of the Escape Room Challenge is to escape a rectangular room as fast as possible without bumping into walls. The goal of the Hospital Challenge is to deliver medicines from one cabinet to another as fast as possible and without bumping into static and dynamic objects.
Logs
Meeting | Date | Time | Chairman | Secretary | Summary | Download |
---|---|---|---|---|---|---|
1 | 24-04-2020 | 15.00 | - | - | Introduction | |
2 | 28-04-2020 | 15.00 | - | T.J.M. Snijders | Introduction to tutor, discussed contents of Design Document | Notes |
3 | 01-05-2020 | 14.00 | B. Godschalk | S.C.M. Mennen | Discussed software architecture | Notes |
4 | 03-05-2020 | 14.00 | - | - | Discussed strategy for Escape Room Challenge | |
5 | 05-05-2020 | 14.00 | - | - | Discussed Escape Room Challenge software structure | |
6 | 08-05-2020 | 15.00 | S.C.M. Mennen | B.P.J. Reijnen | Notes | |
7 | 11-05-2020 | 14.00 | - | - | Decided that the current solution for the escape room challenge is sufficient | |
8 | 12-05-2020 | 14.00 | - | - | Last meeting before Escaperoom Challenge | |
9 | 15-05-2020 | 14.00 | B.P.J. Reijnen | J.H.B. de Zwart | Start architecture and flow chart for Hospital Challenge | |
10 | 19-05-2020 | 14.00 | - | - | Decided upon Hosptial Challenge strategy | |
11 | 22-05-2020 | 14.00 | A.C.C.E. Vissers | J.H.B. de Zwart | Continue in same groups on specific parts | |
12 | 26-05-2020 | 14.00 | - | - | ||
13 | 29-05-2020 | 14.00 | J.H.B. de Zwart | T.J.M. Snijders | Discussion about presentation and Hospital Challenge | |
14 | 02-06-2020 | 14.00 | - | - | ||
15 | 05-06-2020 | 14.00 | T.J.M. Snijders | B. Godschalk | Continue with separate parts, more testing required | |
16 | 09-06-2020 | 14.00 | - | - | Last preparation for Hospital Challenge | |
17 | 12-06-2020 | 13.00 | - | - | Division of tasks for Wiki page |
Design document
In order to get a good overview of the assignment a design document was composed which can be found here. This document describes the requirements, the software architecture which consists of the functions, components and interfaces and at last the system specifications. This document provides a guideline to succesfully complete the assignment.
Escape Room Challenge
Strategy
To create a solid strategy a number of options have been outlined. Two solid versions were considered; wall following and a gap scan version. After confirming that the gap scan version can, if correctly implemented, be a lot faster than following the wall, the gap scan version is used in the escape room challenge since the goal of the escape room challenge is to escape as fast as possible. On the right the strategy flow has been mapped in a flow chart, which starts at 'Inactive' and ends at 'Move forwards' until the PICO (simulation) is stopped.
The first step that will be executed is the 'Initialize' step. This step will be used to clear and set all variable values to the default state from which it will continue to the '360° scan'. In this scan all Laser Range Finder measurements will be mapped into wall objects. When walls do not connect a gap occurs which can be a possible exit or a faulty measurement.
The next step 'Gap?' is checking if the gaps found can be considered as a exit. If no gaps meet the specifications of a gap, the next step will be 'Move to better scan position' and PICO will redo the previous steps. If a gap meets the specifications the next step is 'Path planning', which will be executed to calculate the best possible way to the exit. When the path is set the following step will be 'Move to gap'.
The final step will be 'Center?' which will center the robot in the corridor of the exit to prevent that incorrect alignment with the exit will result in a crash with the walls.
Parallel to this flow PICO will continuously keep track of objects with the laser range finder. Whenever a object is detected in a specific range of the robot a flag will be thrown. This flag can be used to update the path planning, which will prevent crashes when the robot is heading in the wrong direction.
Functions
To perform the strategy described above, the following functions are used.
Finding walls and gaps
To differentiate between the walls and the exit a least squares regression line algorithm has been written. The Laser Range Finder (LRF) data points are fed into this algorithm and gives all the walls in the field of view (VOF) of the LRF. By connecting the walls together it can be possible that a gap occurs, which will be saved into the global reference frame. To collect the data the robot starts with a 360 degree VOF rotation, while doing so collecting all gaps. When the scan stops, all the collected gaps are checked based on some criteria to see if it is a exit and if it is the best exit possible and, if needed, fixed (straightened based on the adjacent walls).
Path planning
Potential field corridor
When PICCO drives in the corridor, PICCO starts to monitor the left and right wall to center itself between the walls of the corridor while moving towards the finish line.
Simulation
With the used strategy and the created functions, the simulation is showed in the created gif of emc-sim. The heightmap used for this simulation is shown below.
When the scan can not find any gaps in the walls, PICO will move 1 meter to the furthest point measured in the scan and performs a new scan. If, for any reason, PICO tends to walk into a wall, the robot will move backwards and starts a new scan. This is showed in the gif below.
Escape Room Challenge results
Immediately in the first attempt a record set of 55 seconds was set! After some doubt from the jury, whether a second attempt was necessary (since the robot did behave a bit strange outside of the corridor) the first attempt was declared valid. However, the moving behaviour was partly confusing since PICO decided to align himself with the reference angle using the largest rotation. In the end group 1 is proud of the result. The result can be seen in the gif on the right.
As can be seen in the scanning, the robot rotates in a smooth counterclockwise rotation in which the gap detection algorithm detects the exit. After validation of the gap, a pre-target and target are placed in relation to the detected gap location. However, the movement towards it went wrong. Normally, the motion component of the software calculates the smallest rotation between the angle of PICO and the pre-target & target of the gap. During the development and validation of the written software in the simulator, this component worked as expected. However, during the challenge it emerged that the calculation did not work when comparing positive and negative angles. As a result, the calculation showed that a positive angle had to turn into the negative direction in order to reach its target. Because of this problem PICO started to rotate 270 degrees to the right instead of 90 degrees to the left. This problem came up 2 times, both after the 360 degrees scan and after reaching the pretarget.
After the challenge we looked at this problem and applied a possible solution. If the simulation would be performed again with the right rotations the simulation time could be reduced to 25 seconds which would have resulted in a 2nd place during the challenge, instead of our 4th place that we were placed this time.
In summary, every software component worked fine without failing completely. However, after a bug fix in the motion component, everything works optimally without any known errors. Since the software is built via Agile, the wall detection and motion software can be taken to the hospital challenge and made usable with some additions without starting from scratch again. The used heightmap in the live stream Escape Room Challenge can be found below.
Hospital Challenge
Design architecture
Strategy
The purpose of the strategy class is to compute and return the path that PICO needs to take in order to complete its tasks. There are eight functions in this class: findPath, isValid, isGoal, isDest, calcHeuristic, makePath createWPs and crossObject.
findPath is one of the two core functions on which this class is built. This function takes as input the position of PICO and the target point that PICO needs to reach and it outputs a vector of target points. It also takes a Boolean as an input indicating if the path can go diagonal. This was mainly used for debugging purposes.
The findPath function uses the world grid stored in the world model to compute the shortest path to its destination using an A* algorithm. The A* algorithm is very similar to Dijkstra’s algorithm, however, A* uses a heuristic to estimate the total cost of a given node instead of only the cost to reach a certain node. More information of Dijkstra’s or the A*algorithm can be found here https://en.wikipedia.org/wiki/A*_search_algorithm
https://www.youtube.com/watch?v=g024lzsknDo comparison speed between A* and dijkstra?
The isValid function evaluates if a certain node in the grid is marked as a reachable node or not and the isGoal and isDest functions both check if a given node is the final destination or not. The reason for two separate function has to do with the input arguments for both. The isGoal function takes in the x,y coordinates of both the position of PICO and the target and is ran at the start of the algorithm to check if PICO is already on its destination. The isDest function takes in the x,y coordinates of the target and a custom datatype named pathNode. This function is run within the A* algorithm to check if an evaluated node is already the destination or if it needs to continue running.
The A* algorithm also needs the calcHeuristic function which estimates the remaining cost to reach its destination by computing the distance between the node being evaluated and the target node.
After the A* algorithm reached the destination, the makePath function runs backwards from the target node to node representing PICO’s position using the saved parent nodes. This returns a vector of nodes representing the shortest path.
After the shortest path is found, a string pulling algorithm is used to reduce the size of the shortest path vector. This is done in the createWPs function. Here, the path is evaluated on which nodes can reach each other in a straight line without crossing an unreachable node, which is done using the crossObject function. Everytime a node cannot be reached from the starting node, the node before it is stored and then used as the new node from where we start evaluating the remaining nodes.
The figure below shows the entire process of the strategy class. (left to right: worldgrid, A* path, Waypoints)
Components
Perception
The main goal of the perception component is to translate the real world data into data which can be used for the simulation. The real world data consists of the LRF-data and the odometry data. Perception uses this data to localize PICO, detect obstacles and to measure the distance to objects around PICO.
Localization
Path planning
Movement
The purpose of the movement class is to compute and send reference velocities to PICO’s actuators. The class consists out of five functions: driveToRef, driveOmniDirection, rotate, stop and allignCabinet.
driveToRef takes as input PICO’s position, a given target point, the potential field vector and a Boolean stating whether or not the target is a cabinet. It outputs a Boolean stating if the target position is reached (true) or not (false). This function is the core of the movement class. It first computes the direction in which PICO is intended to move by adding the potential field vector to the target vector. It then uses a proportional controller to compute the reference velocities in all directions. These reference velocities are then used as a function input for driveOmniDirection. The Boolean stating if the target is the cabinet node was required in order to get closer to the cabinet. For all targets the minimum distance to the target before returning the Boolean stating the target was reached was set higher than for the final target. This was done since if PICO was pushed away from a target due to the potential field it would continue to the next target (if possible) instead of trying to perfectely reach the target. However, for the last target denoting the cabinet position it is important that this target is reached with greater precision.
driveOmniDirection is used to send the reference velocities to PICO’s actuators using the sendBaseReference function. The reason for pulling this function out of the drive to ref function is that with this extra method, other classes could also use it to move PICO in order to accomplish smaller tasks, for example rotate PICO during localization. The rotate and stop functions accomplish the same effect, however, the number of inputs change, the rotate function only takes an angular velocity and the stop function does not have an input.
allignCabinet takes as an input the ID of the target cabinet and the position of PICO and it returns a Boolean indicating if PICO is aligned to the cabinet (true) or not (false). This function is required since the objective states that when PICO has reached a cabinet he needs to face it. The reference orientation for every cabinet is harcoded in a vector and a proportional controller is used to align with this reference (in the same manner as for the driveToRef function).
Monitoring
The monitor class serves as a safety net in case PICO shows undesired behavior. Initially the monitoring checked multiple cases. First of all, if an object was too close to PICO a flag would be given. The object would be in PICO’s safe space which is a circle around PICO with a certain radius. Furthermore, if the potential field vector became too large, also a flag would be given. The idea was that if the potential field vector became too large, PICO should not be able to pass an object. Lastly, if something was placed on the desired location of PICO, also a flag would be given. There was initially thought that in this case the path of PICO could not be continued. However, since the desired locations of PICO is reached by means of waypoints, the waypoints could be changed in order to reach the desired location.
Eventually, only the following flag is used in the hospital challenge. The grid that is used consists of nodes which are accessible or not. A node is not accessible if an object is located on it. If a node that is used in the A* path planning coincides with an inaccessible node, a flag will be given. Because all relevant obstacles were acknowledged by the grid, PICO creates a new path when his previous path is blocked by an obstacle.
The first two flags were not used because the parameters of the potential field are chosen in such a way that these flags would not become true. A snipped of the c++ code of the monitor class is showed in this link...