https://cstwiki.wtb.tue.nl/api.php?action=feedcontributions&user=S149491&feedformat=atomControl Systems Technology Group - User contributions [en]2024-03-28T12:00:03ZUser contributionsMediaWiki 1.39.5https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=79822Embedded Motion Control 2019 Group 42019-06-21T14:42:53Z<p>S149491: </p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019. The course Embedded Motion Control is about the design and implementation of software into autonomous robots. Application of the acquired knowledge is done to real-life robotics tasks and tested with robot PICO.<br />
<br />
Additional recommendations that were pointed out during the lectures are:<br />
* Perceive the world from the point of view of the robot<br />
* Semantic knowledge of the environment is essential<br />
* Incorporate what information is needed at which moment and how often it should be updated, with an eye out for computational power.<br />
<br />
The statement above of the needed information at which moment is the main focus of our project. For example, planning is not important if you already know where you have to go and if you are not moving you do not have to avoid walls.<br />
<br />
Because of this, PICO is chosen as the center of the universe and the map is changed to fit the location of PICO, instead of fixing a map point. Hence, PICO is the center of reasoning of all parts of the program. This year’s challenge is to move through a Hospital in order to visit a number of cabinets. The approach and solutions that are found are explained in the sections below.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the execution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
For the escaperoom challenge a specific strategy is determined. After initialization, PICO starts rotating and simultaneously scanning the room to find the door. In case no door is found after a full rotation, PICO determines the far-most corner and moves in this direction with half the distance measured. After this, PICO repeats this sequence. In case a door is found, PICO moves to a position 50cm in front of the door and faces the exit. A second scan verifies the location of PICO with respect to the door and corrects its position if necessary. After this, the end of the hallway is determined and PICO moves towards this point. After the goal is reached, PICO says it has reached its goal and shuts down. A schematic representation of the strategy is given below. <br />
<br />
[[File:Strategy_escaperoom2.jpg|600px]]<br />
<br />
Out of the plan a finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
</gallery><br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO starts looking for a door, the LRF data is first preprocessed into walls by a ''split and merge'' algorithm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visible door is determined.<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First, for every measured point the location in cartesian coordinates is calculated, using PICO as the center point. After this, PICO takes the leftmost and rightmost LRF-measurements and formulates the hypothesis that they are two points on a single wall. Then, the two points are used to calculate the expected middle point. Consequently, this point is compared to the real LRF-data measurement in the middle of the two points. Two checks are executed to verify the wall:<br />
<br />
* The absolute distance between the expected point and real point is sufficiently small<br />
* The length of the wall does not exceed the size of a door, to ensure no doors are overlooked <br />
<br />
On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdivided into walls, or splitting is no longer possible because a wall consists of only two points. Remaining is a large number of small wall sections, some of which actually belong together. Wall sections are merged they share an endpoint and their relative angle is small (the ''merge'').<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base of the perception software in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|First step: Expected point is far away from real LRF-point; splitting wall.<br />
File:Split_merge2.png|Second step: Expected point is closer to the real LRF-point, but not sufficiently close; splitting again.<br />
File:Split_merge3.png|Third step: Expected point coincides with the real LRF-point and the two points are sufficiently close; wall found.<br />
</gallery><br />
<br />
==== Corner recognition ====<br />
<br />
In corner recognition as used in the escaperoom competition, three types of corners are distinguished: Inside (shallow), outside (wide) and endpoint corners. The first two are defined as a shared endpoint of two walls, where the walls have a certain angle respectively to each other. An endpoint corner is defined as the end of a wall at which no other wall is detected (i.e. a jump in LRF-data is measured at the end of a wall). <br />
Also corner detection has proven to be very effective and has played a major role throughout the project. All different corners type are shown in the image below. These are <span style="color:green">inside corner</span>, <span style="color:red">outside corner</span>, <span style="color:orange">virtual "flat" corner</span> and <span style="color:grey">endpoint corners</span>.<br />
<br />
[[File:Cornerrecog2.png|100px|left|frame|All types of corners and doors.]]<br clear=all><br />
<br />
==== Door detection ====<br />
By clearly distinguishing types of corners, doors can be found by looking at specific combinations of corner types. Three types of doors are possible:<br />
*Door at the middle of a wall<br />
*Door in a corner<br />
*Door at end of hallway<br />
Depending on the point of view, these doors consist of different combinations of corner-types. For instance, the door at the middle of a wall can consist of two corners of type "outside" or one "outside" corner and one "endpoint" corner. Additional checks are used to confirm the door. The width must be within the expected margins and the relative angle with respect to adjacent walls.<br />
<br />
In the above figure it is already seen that a door in a corner is found and a door at the end of a hallway is found. Below you can see the example that a door is in the middle of a wall and that is is recognised while turning PICO<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|100px|Animation of the exit detection flow]]<br clear=all><br />
<br />
=== Escape Room - Testing ===<br />
In real life PICO behaves different than in the simulations. A couple of things needed testing in order to stay on track of the global planning of the project.<br />
The main goal of every test date is given together with it's result in the end.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
<b>Goal:</b> Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
<b>Result:</b> PICO moves in the correct direction, but the signal to the motors seems to be too low. <br />
Suspected problem: smooth acceleration, which is implemented to prevent slip and shocky movement, should be less smooth.<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
<b>Goal:</b> Test improved smooth acceleration profile. Also test some parameter tweaks such as the emergency distance.<br />
<br />
<b>Result:</b> Changed smooth acceleration profile helps a bit, but PICO still does not move to the desired location (moves less than expected). Suspected problem: PICO does not move by using odometry data. This should be implemented before the escaperoom challenge. UPDATE: movement on odometry data could not be implemented before the challenge day, because of the time. Therefore, a final check is implemented when PICO thinks it is in front of the door. Essentially, this contains an additional scan to find a door and a movements towards the desired location in front of the door.<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
<b>Goal:</b> Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
<br />
<b>Result:</b> Odometry still needs small tweaks, but the emergency stop works fine now. We don't take into account that there is an offset in the odometry frame, so a reset in this is needed.<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The designed algorithm worked perfectly and very quick. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that odometry had not been implemented, the distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement that needed to be done is the usage of odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, the laser data should be used more frequently, updating plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
[[File:Pico_EscapeRoom_Group4.gif]]<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge it is crucial to be able to localize accurately. With the RRT relying on the location of PICO on the map, the idea is to update the localization every time the robot needs to make a new path. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. If PICO may run into trouble of any kind, either the (dynamic) obstacle avoidance or the state machine compensates for this. In this case, the robot goes to a 're-planning' state, where it also updates the location again. In this way it is never a problem if the accuracy of the localization is a bit off. The procedure of elaborated below.<br />
<br />
==== Point matching ====<br />
PICO is localized as follows:<br />
<br />
Before the final challenge, in order for PICO to localize, the corners of the map are given the type 'outside' and 'inside' by hand. When the program is started, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
In an alternative localization procedure than described above, the door finding and cabinet finding algorithm can be used. This algorithm comes from the exit recognition that was used for the escaperoom challenge and worked very well. In the hospital challenge, doors are recognised in the same manner as the exit was detected in the escaperoom. Cabinets are defined as a set of corners with certain properties: corner distance and corner type. This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked much faster than the other localization algorithm, as hardly any calculation is required. However, this option is heavily based on the geometry of the starting area, and is therefore not very generic.<br />
<br />
Another alternative that is considered is the use of a particle filter for localization. This is a well known type of localization and some examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. Particle filters are not used in the design, because it would be much of an 'overkill', since the starting area is known and the rooms have enough points of recognition (think of distances and corner kinds etc). Therefore it is chosen to localize with an in our opinion more elegant algorithm where less computational effort is required.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the genericity. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. In each iteration of the RRT-algorithm a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similiar to the splitting algorithm used to find walls in LRF data. In the first step, the splitting algorithm tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
With the two improvements to the random tree path planner implemented, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, it consists of an array of points. An extra orientation is added to these points in order to let PICO orient itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanner2.gif|frame|left|300px|Pathplanner using a RRT algorithm with path optimizer.]]<br clear=all><br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also reflected in the [[#Hospital Challenge - Finite state machine|finite state machine]]. In global movement PICO follows the path created by the path planner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 cm in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), which is an entry of the list of cabinets that should be visited. A counter is used to keep track of the number of cabinets that are already visited. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y,theta) which define the path. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is within a certain range of the target path position, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the endpoint is much smaller to ensure PICO reaches his final position. During the goalMove state, two special situations can occur: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map, or is trying to avoid an obstacle, which has driven him into a corner. PICO will then scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to a local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors and corners, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. This step is also used to update the position on the map based on the LRF data and the cabinet PICO is looking at. If the cabinet is not found, PICO starts rotating and searches for cabinets again, until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and deadlock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. Its primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows. First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
The image below on the left shows how the obstacle avoidance works in a simulation enviroment. PICO is only aware of the wall in front of him at the starting position and plans a path to a location 4 meters in front of him. He succesfully avoids all small obstacles in the adjoining room. The second image displays a test done on PICO. Again he is only aware of the first wall in front of him and succesfully avoids the obstacles on his path.<br />
<br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:dynobsavoid.gif |frame|Dynamic obstacle avoidance simulation.]]<br />
<br />
| [[File:dynobsavoid_mov.gif|frame|Dynamicd obstacle avoidance test.]]<br />
<br />
|}<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognizing unexpected obstacles and adding them to the map, obstacles that have been added to the map and are no longer present in the environment should automatically be removed.<br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visible will be defined as two separate obstacles.<br />
<br />
Next, the obstacles that are defined multiple times (overlapping lines) are merged and obstacles that are recognized as being on the JSON map are removed. In this procedure, obstacles are interpreted as lines. The algorithm looks at the relative angle between lines, the perpendicular distance from one line to the other and checks whether the lines overlap. If all hold, a new obstacle is defined as a combination of these lines. The two initial obstacles are removed. The same checks are executed to filter any walls from the obstacles.<br />
<br />
With the updated version of the map, the path planning is now able to re-plan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether their corners should be within vision range and the view on the obstacle is not obstructed. This is done by checking if a line between the corner and PICO is crossed by a line of data from the LRF scan. If not the obstacles should be visible. As this function is used before adding new obstacles, an obstacle in sight which is still in place will be added to the map again.<br />
<br />
This way paths that were obstructed before will be accessible by the robot again when the obstacles as well as wrongly detected obstacles are removed. The image below shows an example of how PICO is able to plan around an obstacle found. In this case a door which seems to be open in the map, is actually closed. PICO made a path from cabinet 2 to 0. When following the path an obstacle (the closed door) is detected, added to the map and planned a new route. As the localization at this point was not fully correct, the obstacle is placed on the map with a slight offset.<br />
<br />
[[File:staticobstacleavoid.gif|left|frame|250px|Static obstacle recognition and replanning.]]<br clear=all><br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality.<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
<b>Goal:</b><br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
<br />
<b>Result:</b><br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03), PICO Test 6 (2019-06-05) and PICO Test 7 (2019-06-11) ====<br />
These tests were mainly on testing a lot of small things and problems that occured while testing.<br />
<br />
<b>Goals:</b><br />
*Test the localization algorithm and the dynamic obstacle avoidance.<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
<b>Results:</b><br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Simulation ===<br />
<br />
To show how the final program works, a full simulation is done on the competition hospital map. During this simulation PICO is told to visit cabinets 0, 1 and 3. The complete program is used as described above. Note that the GIF is played at 1.7x speed with 5 FPS due to the limited available file size. A full video of this simulation can be found in [[:File:Group4_FinalChallengeSimulation.zip|ZIP attached]]. <br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:finalsim2.gif |frame|Hospital challenge simulation]]<br />
<br />
| [[File:finalviz2.gif|frame|Hospital challenge visualization]]<br />
<br />
|}<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. Within these two trials we had the chance to show our skills to a bigger audience and to the organization of the course. The localization problem was known but hopes were to show as much of our built functionality as possible.<br />
<br />
The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position.<br />
<br />
The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be too inaccurate to use in this hospital challenge. PICO stranded next to a door where he had to replan his route. Here PICO could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
[[File:Hospitalmovie.gif|frame|left|Group 4 hospital challenge.]]<br clear=all><br />
<br />
== Conclusion ==<br />
The Embedded Motion Control course of 2019 proved to be a challenging assignment but was received with lots of enthusiasm. It is not often you get a chance to just play around with a robot like this. Besides the requirements set by the course, additional goals were set by ourselves as deducted from the lectures accompanying the course. These included semantic knowledge of the environment, selective use of information, a world view as perceived by the robot and to avoid using a grids.<br />
<br />
=== Escape Room challenge ===<br />
The first requirement was already fulfilled to a large extend by class definition of walls, corners, doors and later cabinets. The split and merge algorithm allowed the recognition of these semantic concepts in the LRF data in an accurate yet efficient manner. Rather than mapping out the entire area, the algorithm looked for a door and next for the end of hallway, fulfilling the second and third goal by only making use of information needed to fulfill the task at hand and defining the door and end of hallway positions as seen by the robot. The effectiveness of these concepts was clearly visible during the escape room challenge as the door was found immediately as it entered PICO’s field of view. The task of the driving towards known target however was underestimated and PICO was unable to reach the exit.<br />
<br />
=== Hospital challenge ===<br />
For the hospital challenge, driving on odometry was successfully implemented and reinforced with a powerful ‘dynamic obstacle avoidance’. Speeds were adjusted when getting close to obstacles while adding repelling forces to PICO from any obstacles around it.<br />
<br />
The fourth goal mainly played a role when coming up with a path planning algorithm. The solution for grid-less path planning was found in a RRT algorithm, which was extended with a small bias to make it converge faster and our own split and merge algorithm to generate a smoother trajectory. The addition of static object detection and updating provided the option to find alternative routes in case the way was blocked, forming a strong combination with the path planning algorithm.<br />
The whole system was controlled by a strong and extensive finite state machine. Yet through the smart use of loops it remained relatively compact while at the same time adding to its robustness.<br />
<br />
The only weak point in the system was the localization, which was neither strong enough to always determine its location regardless of its position, nor had the ability to use priory acquired knowledge to update it. The localization was built keeping in mind the use of semantic concepts and to make PICO the center of the world, but this proved to be too hard for the time given. This caused us to fail the final competition.<br />
<br />
Due to the lack of proper localization, the competition has not shown the full potential of the result of this project. Yet we are convinced that there are some very powerful tools among the created software of which we would be happy to see them reappear in the upcoming years. Hence, in the end group 4 is happy with the progress that was made within the project. We thank the organization of this course for this opportunity and help with the assignment.<br />
<br />
== Recommendations ==<br />
The implementation of localization was unsuccessful in the project. The use of semantic concepts as recognizable features however had lots of potential, given more time to implement it. The algorithm would fail however when multiple rooms show the same features, in which case it could be combined with the option to have multiple hypothesis on its current location. Yet many good alternatives present themselves.<br />
<br />
Also a lot of wasted hours were spend on the endless conversion of coordinates from PICO’s view to the map and back, because they worked in different coordinate systems. Our recommendation would be to from the start convert these to work in the same system. This will not only save on computation time, but will mainly help understanding the systems and reduce the chance on errors.<br />
<br />
== Code ==<br />
The following snippets give a good representation of how the software for this project was structured, and how it did what it was supposed to do.<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/144 Overall functionality]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/148 State changes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/147 Effect of state on functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/145 Methods in classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/146 Dynamic obstacle avoidance]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/149 Velocity planning]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/150 Complex classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/151 Functions within functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/152 Splitting of the RRT path]<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 10 (2019-06-12)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190620.pdf#filelinks Meeting 11 (2019-06-20)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=79821Embedded Motion Control 2019 Group 42019-06-21T14:42:20Z<p>S149491: </p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019. The course Embedded Motion Control is about the design and implementation of software into autonomous robots. Application of the acquired knowledge is done to real-life robotics tasks and tested with robot PICO.<br />
<br />
Additional recommendations that were pointed out during the lectures are:<br />
• Perceive the world from the point of view of the robot<br />
• Semantic knowledge of the environment is essential<br />
• Incorporate what information is needed at which moment and how often it should be updated, with an eye out for computational power.<br />
<br />
The statement above of the needed information at which moment is the main focus of our project. For example, planning is not important if you already know where you have to go and if you are not moving you do not have to avoid walls.<br />
<br />
Because of this, PICO is chosen as the center of the universe and the map is changed to fit the location of PICO, instead of fixing a map point. Hence, PICO is the center of reasoning of all parts of the program. This year’s challenge is to move through a Hospital in order to visit a number of cabinets. The approach and solutions that are found are explained in the sections below.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the execution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
For the escaperoom challenge a specific strategy is determined. After initialization, PICO starts rotating and simultaneously scanning the room to find the door. In case no door is found after a full rotation, PICO determines the far-most corner and moves in this direction with half the distance measured. After this, PICO repeats this sequence. In case a door is found, PICO moves to a position 50cm in front of the door and faces the exit. A second scan verifies the location of PICO with respect to the door and corrects its position if necessary. After this, the end of the hallway is determined and PICO moves towards this point. After the goal is reached, PICO says it has reached its goal and shuts down. A schematic representation of the strategy is given below. <br />
<br />
[[File:Strategy_escaperoom2.jpg|600px]]<br />
<br />
Out of the plan a finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
</gallery><br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO starts looking for a door, the LRF data is first preprocessed into walls by a ''split and merge'' algorithm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visible door is determined.<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First, for every measured point the location in cartesian coordinates is calculated, using PICO as the center point. After this, PICO takes the leftmost and rightmost LRF-measurements and formulates the hypothesis that they are two points on a single wall. Then, the two points are used to calculate the expected middle point. Consequently, this point is compared to the real LRF-data measurement in the middle of the two points. Two checks are executed to verify the wall:<br />
<br />
* The absolute distance between the expected point and real point is sufficiently small<br />
* The length of the wall does not exceed the size of a door, to ensure no doors are overlooked <br />
<br />
On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdivided into walls, or splitting is no longer possible because a wall consists of only two points. Remaining is a large number of small wall sections, some of which actually belong together. Wall sections are merged they share an endpoint and their relative angle is small (the ''merge'').<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base of the perception software in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|First step: Expected point is far away from real LRF-point; splitting wall.<br />
File:Split_merge2.png|Second step: Expected point is closer to the real LRF-point, but not sufficiently close; splitting again.<br />
File:Split_merge3.png|Third step: Expected point coincides with the real LRF-point and the two points are sufficiently close; wall found.<br />
</gallery><br />
<br />
==== Corner recognition ====<br />
<br />
In corner recognition as used in the escaperoom competition, three types of corners are distinguished: Inside (shallow), outside (wide) and endpoint corners. The first two are defined as a shared endpoint of two walls, where the walls have a certain angle respectively to each other. An endpoint corner is defined as the end of a wall at which no other wall is detected (i.e. a jump in LRF-data is measured at the end of a wall). <br />
Also corner detection has proven to be very effective and has played a major role throughout the project. All different corners type are shown in the image below. These are <span style="color:green">inside corner</span>, <span style="color:red">outside corner</span>, <span style="color:orange">virtual "flat" corner</span> and <span style="color:grey">endpoint corners</span>.<br />
<br />
[[File:Cornerrecog2.png|100px|left|frame|All types of corners and doors.]]<br clear=all><br />
<br />
==== Door detection ====<br />
By clearly distinguishing types of corners, doors can be found by looking at specific combinations of corner types. Three types of doors are possible:<br />
*Door at the middle of a wall<br />
*Door in a corner<br />
*Door at end of hallway<br />
Depending on the point of view, these doors consist of different combinations of corner-types. For instance, the door at the middle of a wall can consist of two corners of type "outside" or one "outside" corner and one "endpoint" corner. Additional checks are used to confirm the door. The width must be within the expected margins and the relative angle with respect to adjacent walls.<br />
<br />
In the above figure it is already seen that a door in a corner is found and a door at the end of a hallway is found. Below you can see the example that a door is in the middle of a wall and that is is recognised while turning PICO<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|100px|Animation of the exit detection flow]]<br clear=all><br />
<br />
=== Escape Room - Testing ===<br />
In real life PICO behaves different than in the simulations. A couple of things needed testing in order to stay on track of the global planning of the project.<br />
The main goal of every test date is given together with it's result in the end.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
<b>Goal:</b> Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
<b>Result:</b> PICO moves in the correct direction, but the signal to the motors seems to be too low. <br />
Suspected problem: smooth acceleration, which is implemented to prevent slip and shocky movement, should be less smooth.<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
<b>Goal:</b> Test improved smooth acceleration profile. Also test some parameter tweaks such as the emergency distance.<br />
<br />
<b>Result:</b> Changed smooth acceleration profile helps a bit, but PICO still does not move to the desired location (moves less than expected). Suspected problem: PICO does not move by using odometry data. This should be implemented before the escaperoom challenge. UPDATE: movement on odometry data could not be implemented before the challenge day, because of the time. Therefore, a final check is implemented when PICO thinks it is in front of the door. Essentially, this contains an additional scan to find a door and a movements towards the desired location in front of the door.<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
<b>Goal:</b> Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
<br />
<b>Result:</b> Odometry still needs small tweaks, but the emergency stop works fine now. We don't take into account that there is an offset in the odometry frame, so a reset in this is needed.<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The designed algorithm worked perfectly and very quick. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that odometry had not been implemented, the distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement that needed to be done is the usage of odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, the laser data should be used more frequently, updating plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
[[File:Pico_EscapeRoom_Group4.gif]]<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge it is crucial to be able to localize accurately. With the RRT relying on the location of PICO on the map, the idea is to update the localization every time the robot needs to make a new path. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. If PICO may run into trouble of any kind, either the (dynamic) obstacle avoidance or the state machine compensates for this. In this case, the robot goes to a 're-planning' state, where it also updates the location again. In this way it is never a problem if the accuracy of the localization is a bit off. The procedure of elaborated below.<br />
<br />
==== Point matching ====<br />
PICO is localized as follows:<br />
<br />
Before the final challenge, in order for PICO to localize, the corners of the map are given the type 'outside' and 'inside' by hand. When the program is started, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
In an alternative localization procedure than described above, the door finding and cabinet finding algorithm can be used. This algorithm comes from the exit recognition that was used for the escaperoom challenge and worked very well. In the hospital challenge, doors are recognised in the same manner as the exit was detected in the escaperoom. Cabinets are defined as a set of corners with certain properties: corner distance and corner type. This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked much faster than the other localization algorithm, as hardly any calculation is required. However, this option is heavily based on the geometry of the starting area, and is therefore not very generic.<br />
<br />
Another alternative that is considered is the use of a particle filter for localization. This is a well known type of localization and some examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. Particle filters are not used in the design, because it would be much of an 'overkill', since the starting area is known and the rooms have enough points of recognition (think of distances and corner kinds etc). Therefore it is chosen to localize with an in our opinion more elegant algorithm where less computational effort is required.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the genericity. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. In each iteration of the RRT-algorithm a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similiar to the splitting algorithm used to find walls in LRF data. In the first step, the splitting algorithm tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
With the two improvements to the random tree path planner implemented, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, it consists of an array of points. An extra orientation is added to these points in order to let PICO orient itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanner2.gif|frame|left|300px|Pathplanner using a RRT algorithm with path optimizer.]]<br clear=all><br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also reflected in the [[#Hospital Challenge - Finite state machine|finite state machine]]. In global movement PICO follows the path created by the path planner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 cm in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), which is an entry of the list of cabinets that should be visited. A counter is used to keep track of the number of cabinets that are already visited. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y,theta) which define the path. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is within a certain range of the target path position, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the endpoint is much smaller to ensure PICO reaches his final position. During the goalMove state, two special situations can occur: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map, or is trying to avoid an obstacle, which has driven him into a corner. PICO will then scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to a local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors and corners, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. This step is also used to update the position on the map based on the LRF data and the cabinet PICO is looking at. If the cabinet is not found, PICO starts rotating and searches for cabinets again, until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and deadlock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. Its primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows. First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
The image below on the left shows how the obstacle avoidance works in a simulation enviroment. PICO is only aware of the wall in front of him at the starting position and plans a path to a location 4 meters in front of him. He succesfully avoids all small obstacles in the adjoining room. The second image displays a test done on PICO. Again he is only aware of the first wall in front of him and succesfully avoids the obstacles on his path.<br />
<br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:dynobsavoid.gif |frame|Dynamic obstacle avoidance simulation.]]<br />
<br />
| [[File:dynobsavoid_mov.gif|frame|Dynamicd obstacle avoidance test.]]<br />
<br />
|}<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognizing unexpected obstacles and adding them to the map, obstacles that have been added to the map and are no longer present in the environment should automatically be removed.<br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visible will be defined as two separate obstacles.<br />
<br />
Next, the obstacles that are defined multiple times (overlapping lines) are merged and obstacles that are recognized as being on the JSON map are removed. In this procedure, obstacles are interpreted as lines. The algorithm looks at the relative angle between lines, the perpendicular distance from one line to the other and checks whether the lines overlap. If all hold, a new obstacle is defined as a combination of these lines. The two initial obstacles are removed. The same checks are executed to filter any walls from the obstacles.<br />
<br />
With the updated version of the map, the path planning is now able to re-plan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether their corners should be within vision range and the view on the obstacle is not obstructed. This is done by checking if a line between the corner and PICO is crossed by a line of data from the LRF scan. If not the obstacles should be visible. As this function is used before adding new obstacles, an obstacle in sight which is still in place will be added to the map again.<br />
<br />
This way paths that were obstructed before will be accessible by the robot again when the obstacles as well as wrongly detected obstacles are removed. The image below shows an example of how PICO is able to plan around an obstacle found. In this case a door which seems to be open in the map, is actually closed. PICO made a path from cabinet 2 to 0. When following the path an obstacle (the closed door) is detected, added to the map and planned a new route. As the localization at this point was not fully correct, the obstacle is placed on the map with a slight offset.<br />
<br />
[[File:staticobstacleavoid.gif|left|frame|250px|Static obstacle recognition and replanning.]]<br clear=all><br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality.<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
<b>Goal:</b><br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
<br />
<b>Result:</b><br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03), PICO Test 6 (2019-06-05) and PICO Test 7 (2019-06-11) ====<br />
These tests were mainly on testing a lot of small things and problems that occured while testing.<br />
<br />
<b>Goals:</b><br />
*Test the localization algorithm and the dynamic obstacle avoidance.<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
<b>Results:</b><br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Simulation ===<br />
<br />
To show how the final program works, a full simulation is done on the competition hospital map. During this simulation PICO is told to visit cabinets 0, 1 and 3. The complete program is used as described above. Note that the GIF is played at 1.7x speed with 5 FPS due to the limited available file size. A full video of this simulation can be found in [[:File:Group4_FinalChallengeSimulation.zip|ZIP attached]]. <br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:finalsim2.gif |frame|Hospital challenge simulation]]<br />
<br />
| [[File:finalviz2.gif|frame|Hospital challenge visualization]]<br />
<br />
|}<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. Within these two trials we had the chance to show our skills to a bigger audience and to the organization of the course. The localization problem was known but hopes were to show as much of our built functionality as possible.<br />
<br />
The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position.<br />
<br />
The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be too inaccurate to use in this hospital challenge. PICO stranded next to a door where he had to replan his route. Here PICO could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
[[File:Hospitalmovie.gif|frame|left|Group 4 hospital challenge.]]<br clear=all><br />
<br />
== Conclusion ==<br />
The Embedded Motion Control course of 2019 proved to be a challenging assignment but was received with lots of enthusiasm. It is not often you get a chance to just play around with a robot like this. Besides the requirements set by the course, additional goals were set by ourselves as deducted from the lectures accompanying the course. These included semantic knowledge of the environment, selective use of information, a world view as perceived by the robot and to avoid using a grids.<br />
<br />
=== Escape Room challenge ===<br />
The first requirement was already fulfilled to a large extend by class definition of walls, corners, doors and later cabinets. The split and merge algorithm allowed the recognition of these semantic concepts in the LRF data in an accurate yet efficient manner. Rather than mapping out the entire area, the algorithm looked for a door and next for the end of hallway, fulfilling the second and third goal by only making use of information needed to fulfill the task at hand and defining the door and end of hallway positions as seen by the robot. The effectiveness of these concepts was clearly visible during the escape room challenge as the door was found immediately as it entered PICO’s field of view. The task of the driving towards known target however was underestimated and PICO was unable to reach the exit.<br />
<br />
=== Hospital challenge ===<br />
For the hospital challenge, driving on odometry was successfully implemented and reinforced with a powerful ‘dynamic obstacle avoidance’. Speeds were adjusted when getting close to obstacles while adding repelling forces to PICO from any obstacles around it.<br />
<br />
The fourth goal mainly played a role when coming up with a path planning algorithm. The solution for grid-less path planning was found in a RRT algorithm, which was extended with a small bias to make it converge faster and our own split and merge algorithm to generate a smoother trajectory. The addition of static object detection and updating provided the option to find alternative routes in case the way was blocked, forming a strong combination with the path planning algorithm.<br />
The whole system was controlled by a strong and extensive finite state machine. Yet through the smart use of loops it remained relatively compact while at the same time adding to its robustness.<br />
<br />
The only weak point in the system was the localization, which was neither strong enough to always determine its location regardless of its position, nor had the ability to use priory acquired knowledge to update it. The localization was built keeping in mind the use of semantic concepts and to make PICO the center of the world, but this proved to be too hard for the time given. This caused us to fail the final competition.<br />
<br />
Due to the lack of proper localization, the competition has not shown the full potential of the result of this project. Yet we are convinced that there are some very powerful tools among the created software of which we would be happy to see them reappear in the upcoming years. Hence, in the end group 4 is happy with the progress that was made within the project. We thank the organization of this course for this opportunity and help with the assignment.<br />
<br />
== Recommendations ==<br />
The implementation of localization was unsuccessful in the project. The use of semantic concepts as recognizable features however had lots of potential, given more time to implement it. The algorithm would fail however when multiple rooms show the same features, in which case it could be combined with the option to have multiple hypothesis on its current location. Yet many good alternatives present themselves.<br />
<br />
Also a lot of wasted hours were spend on the endless conversion of coordinates from PICO’s view to the map and back, because they worked in different coordinate systems. Our recommendation would be to from the start convert these to work in the same system. This will not only save on computation time, but will mainly help understanding the systems and reduce the chance on errors.<br />
<br />
== Code ==<br />
The following snippets give a good representation of how the software for this project was structured, and how it did what it was supposed to do.<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/144 Overall functionality]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/148 State changes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/147 Effect of state on functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/145 Methods in classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/146 Dynamic obstacle avoidance]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/149 Velocity planning]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/150 Complex classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/151 Functions within functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/152 Splitting of the RRT path]<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 10 (2019-06-12)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190620.pdf#filelinks Meeting 11 (2019-06-20)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=79803Embedded Motion Control 2019 Group 42019-06-21T14:21:04Z<p>S149491: /* Hospital Challenge - Competition */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019. The course Embedded Motion Control is about software design and implementation into autonomous robots. Application of the acquired knowledge is done to real-life robotics tasks and tested with robot PICO.<br />
<br />
During lectures it is explained that the point of view of the robot is essential. Semantic knowledge of the environment is essential. Which information is needed at which moment, and when are things less important in terms of computational power.<br />
<br />
The statement above of the needed information at which moment is the main focus of our project. For example, planning is not important if you already know where you have to go and if you are not moving you do not have to avoid walls. Because of this, it is chosen to change the location of the map towards the location of PICO and not the other way around. PICO is the center of reasoning of all parts of the program.<br />
This year’s challenge is to move through a Hospital in order to visit a number of cabinets. The approach and solutions that are found are explained in the upcoming sections.<br />
<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the execution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
For the escaperoom challenge a specific strategy is determined. After initialization, PICO starts rotating and simultaneously scanning the room to find the door. In case no door is found after a full rotation, PICO determines the far-most corner and moves in this direction with half the distance measured. After this, PICO repeats this sequence. In case a door is found, PICO moves to a position 50cm in front of the door and faces the exit. A second scan verifies the location of PICO with respect to the door and corrects its position if necessary. After this, the end of the hallway is determined and PICO moves towards this point. After the goal is reached, PICO says it has reached its goal and shuts down. A schematic representation of the strategy is given below. <br />
<br />
[[File:Strategy_escaperoom2.jpg|600px]]<br />
<br />
Out of the plan a finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
</gallery><br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO starts looking for a door, the LRF data is first preprocessed into walls by a ''split and merge'' algorithm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visible door is determined.<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First, for every measured point the location in cartesian coordinates is calculated, using PICO as the center point. After this, PICO takes the leftmost and rightmost LRF-measurements and formulates the hypothesis that they are two points on a single wall. Then, the two points are used to calculate the expected middle point. Consequently, this point is compared to the real LRF-data measurement in the middle of the two points. Two checks are executed to verify the wall:<br />
<br />
* The absolute distance between the expected point and real point is sufficiently small<br />
* The length of the wall does not exceed the size of a door, to ensure no doors are overlooked <br />
<br />
On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdivided into walls, or splitting is no longer possible because a wall consists of only two points. Remaining is a large number of small wall sections, some of which actually belong together. Wall sections are merged they share an endpoint and their relative angle is small (the ''merge'').<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base of the perception software in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|First step: Expected point is far away from real LRF-point; splitting wall.<br />
File:Split_merge2.png|Second step: Expected point is closer to the real LRF-point, but not sufficiently close; splitting again.<br />
File:Split_merge3.png|Third step: Expected point coincides with the real LRF-point and the two points are sufficiently close; wall found.<br />
</gallery><br />
<br />
==== Corner recognition ====<br />
<br />
In corner recognition as used in the escaperoom competition, three types of corners are distinguished: Inside (shallow), outside (wide) and endpoint corners. The first two are defined as a shared endpoint of two walls, where the walls have a certain angle respectively to each other. An endpoint corner is defined as the end of a wall at which no other wall is detected (i.e. a jump in LRF-data is measured at the end of a wall). <br />
Also corner detection has proven to be very effective and has played a major role throughout the project. All different corners type are shown in the image below. These are <span style="color:green">inside corner</span>, <span style="color:red">outside corner</span>, <span style="color:orange">virtual "flat" corner</span> and <span style="color:grey">endpoint corners</span>.<br />
<br />
[[File:Cornerrecog2.png|100px|left|frame|All types of corners and doors.]]<br clear=all><br />
<br />
==== Door detection ====<br />
By clearly distinguishing types of corners, doors can be found by looking at specific combinations of corner types. Three types of doors are possible:<br />
*Door at the middle of a wall<br />
*Door in a corner<br />
*Door at end of hallway<br />
Depending on the point of view, these doors consist of different combinations of corner-types. For instance, the door at the middle of a wall can consist of two corners of type "outside" or one "outside" corner and one "endpoint" corner. Additional checks are used to confirm the door. The width must be within the expected margins and the relative angle with respect to adjacent walls.<br />
<br />
In the above figure it is already seen that a door in a corner is found and a door at the end of a hallway is found. Below you can see the example that a door is in the middle of a wall and that is is recognised while turning PICO<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|100px|Animation of the exit detection flow]]<br clear=all><br />
<br />
=== Escape Room - Testing ===<br />
In real life PICO behaves different than in the simulations. A couple of things needed testing in order to stay on track of the global planning of the project.<br />
The main goal of every test date is given together with it's result in the end.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
<b>Goal:</b> Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
<b>Result:</b> PICO moves in the correct direction, but the signal to the motors seems to be too low. <br />
Suspected problem: smooth acceleration, which is implemented to prevent slip and shocky movement, should be less smooth.<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
<b>Goal:</b> Test improved smooth acceleration profile. Also test some parameter tweaks such as the emergency distance.<br />
<br />
<b>Result:</b> Changed smooth acceleration profile helps a bit, but PICO still does not move to the desired location (moves less than expected). Suspected problem: PICO does not move by using odometry data. This should be implemented before the escaperoom challenge. UPDATE: movement on odometry data could not be implemented before the challenge day, because of the time. Therefore, a final check is implemented when PICO thinks it is in front of the door. Essentially, this contains an additional scan to find a door and a movements towards the desired location in front of the door.<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
<b>Goal:</b> Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
<br />
<b>Result:</b> Odometry still needs small tweaks, but the emergency stop works fine now. We don't take into account that there is an offset in the odometry frame, so a reset in this is needed.<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The designed algorithm worked perfectly and very quick. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that odometry had not been implemented, the distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement that needed to be done is the usage of odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, the laser data should be used more frequently, updating plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
[[File:Pico_EscapeRoom_Group4.gif]]<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge it is crucial to be able to localize accurately. With the RRT relying on the location of PICO on the map, the idea is to update the localization every time the robot needs to make a new path. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. If PICO may run into trouble of any kind, either the (dynamic) obstacle avoidance or the state machine compensates for this. In this case, the robot goes to a 're-planning' state, where it also updates the location again. In this way it is never a problem if the accuracy of the localization is a bit off. The procedure of elaborated below.<br />
<br />
==== Point matching ====<br />
PICO is localized as follows:<br />
<br />
Before the final challenge, in order for PICO to localize, the corners of the map are given the type 'outside' and 'inside' by hand. When the program is started, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
In an alternative localization procedure than described above, the door finding and cabinet finding algorithm can be used. This algorithm comes from the exit recognition that was used for the escaperoom challenge and worked very well. In the hospital challenge, doors are recognised in the same manner as the exit was detected in the escaperoom. Cabinets are defined as a set of corners with certain properties: corner distance and corner type. This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked much faster than the other localization algorithm, as hardly any calculation is required. However, this option is heavily based on the geometry of the starting area, and is therefore not very generic.<br />
<br />
Another alternative that is considered is the use of a particle filter for localization. This is a well known type of localization and some examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. Particle filters are not used in the design, because it would be much of an 'overkill', since the starting area is known and the rooms have enough points of recognition (think of distances and corner kinds etc). Therefore it is chosen to localize with an in our opinion more elegant algorithm where less computational effort is required.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the genericity. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. In each iteration of the RRT-algorithm a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similiar to the splitting algorithm used to find walls in LRF data. In the first step, the splitting algorithm tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
With the two improvements to the random tree path planner implemented, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, it consists of an array of points. An extra orientation is added to these points in order to let PICO orient itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanner2.gif|frame|left|300px|Pathplanner using a RRT algorithm with path optimizer.]]<br clear=all><br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also reflected in the [[#Hospital Challenge - Finite state machine|finite state machine]]. In global movement PICO follows the path created by the path planner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 cm in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), which is an entry of the list of cabinets that should be visited. A counter is used to keep track of the number of cabinets that are already visited. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y,theta) which define the path. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is within a certain range of the target path position, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the endpoint is much smaller to ensure PICO reaches his final position. During the goalMove state, two special situations can occur: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map, or is trying to avoid an obstacle, which has driven him into a corner. PICO will then scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to a local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors and corners, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. This step is also used to update the position on the map based on the LRF data and the cabinet PICO is looking at. If the cabinet is not found, PICO starts rotating and searches for cabinets again, until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and deadlock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. Its primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows. First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
The image below on the left shows how the obstacle avoidance works in a simulation enviroment. PICO is only aware of the wall in front of him at the starting position and plans a path to a location 4 meters in front of him. He succesfully avoids all small obstacles in the adjoining room. The second image displays a test done on PICO. Again he is only aware of the first wall in front of him and succesfully avoids the obstacles on his path.<br />
<br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:dynobsavoid.gif |frame|Dynamic obstacle avoidance simulation.]]<br />
<br />
| [[File:dynobsavoid_mov.gif|frame|Dynamicd obstacle avoidance test.]]<br />
<br />
|}<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognizing unexpected obstacles and adding them to the map, obstacles that have been added to the map and are no longer present in the environment should automatically be removed.<br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visible will be defined as two separate obstacles.<br />
<br />
Next, the obstacles that are defined multiple times (overlapping lines) are merged and obstacles that are recognized as being on the JSON map are removed. In this procedure, obstacles are interpreted as lines. The algorithm looks at the relative angle between lines, the perpendicular distance from one line to the other and checks whether the lines overlap. If all hold, a new obstacle is defined as a combination of these lines. The two initial obstacles are removed. The same checks are executed to filter any walls from the obstacles.<br />
<br />
With the updated version of the map, the path planning is now able to re-plan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether their corners should be within vision range and the view on the obstacle is not obstructed. This is done by checking if a line between the corner and PICO is crossed by a line of data from the LRF scan. If not the obstacles should be visible. As this function is used before adding new obstacles, an obstacle in sight which is still in place will be added to the map again.<br />
<br />
This way paths that were obstructed before will be accessible by the robot again when the obstacles as well as wrongly detected obstacles are removed. The image below shows an example of how PICO is able to plan around an obstacle found. In this case a door which seems to be open in the map, is actually closed. PICO made a path from cabinet 2 to 0. When following the path an obstacle (the closed door) is detected, added to the map and planned a new route. As the localization at this point was not fully correct, the obstacle is placed on the map with a slight offset.<br />
<br />
[[File:staticobstacleavoid.gif|left|frame|250px|Static obstacle recognition and replanning.]]<br clear=all><br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality.<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
<b>Goal:</b><br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
<br />
<b>Result:</b><br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03), PICO Test 6 (2019-06-05) and PICO Test 7 (2019-06-11) ====<br />
These tests were mainly on testing a lot of small things and problems that occured while testing.<br />
<br />
<b>Goals:</b><br />
*Test the localization algorithm and the dynamic obstacle avoidance.<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
<b>Results:</b><br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Simulation ===<br />
<br />
To show how the final program works, a full simulation is done on the competition hospital map. During this simulation PICO is told to visit cabinets 0, 1 and 3. The complete program is used as described above. Note that the GIF is played at 1.7x speed with 5 FPS due to the limited available file size. A full video of this simulation can be found in [[:File:Group4_FinalChallengeSimulation.zip|ZIP attached]]. <br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:finalsim2.gif |frame|Hospital challenge simulation]]<br />
<br />
| [[File:finalviz2.gif|frame|Hospital challenge visualization]]<br />
<br />
|}<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. Within these two trials we had the chance to show our skills to a bigger audience and to the organization of the course. The localization problem was known but hopes were to show as much of our built functionality as possible.<br />
<br />
The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position.<br />
<br />
The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be too inaccurate to use in this hospital challenge. PICO stranded next to a door where he had to replan his route. Here PICO could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
[[File:Hospitalmovie.gif|frame|left|Group 4 hospital challenge.]]<br clear=all><br />
<br />
== Conclusion ==<br />
The Embedded Motion Control course of 2019 proved to be a challenging assignment but was received with lots of enthusiasm. It is not often you get a chance to just play around with a robot like this. Besides the requirements set by the course, additional goals were set by ourselves as deducted from the lectures accompanying the course. These included semantic knowledge of the environment, selective use of information, a world view as perceived by the robot and to avoid using a grids.<br />
<br />
=== Escape Room challenge ===<br />
The first requirement was already fulfilled to a large extend by class definition of walls, corners, doors and later cabinets. The split and merge algorithm allowed the recognition of these semantic concepts in the LRF data in an accurate yet efficient manner. Rather than mapping out the entire area, the algorithm looked for a door and next for the end of hallway, fulfilling the second and third goal by only making use of information needed to fulfill the task at hand and defining the door and end of hallway positions as seen by the robot. The effectiveness of these concepts was clearly visible during the escape room challenge as the door was found immediately as it entered PICO’s field of view. The task of the driving towards known target however was underestimated and PICO was unable to reach the exit.<br />
<br />
=== Hospital challenge ===<br />
For the hospital challenge, driving on odometry was successfully implemented and reinforced with a powerful ‘dynamic obstacle avoidance’. Speeds were adjusted when getting close to obstacles while adding repelling forces to PICO from any obstacles around it.<br />
<br />
The fourth goal mainly played a role when coming up with a path planning algorithm. The solution for grid-less path planning was found in a RRT algorithm, which was extended with a small bias to make it converge faster and our own split and merge algorithm to generate a smoother trajectory. The addition of static object detection and updating provided the option to find alternative routes in case the way was blocked, forming a strong combination with the path planning algorithm.<br />
The whole system was controlled by a strong and extensive finite state machine. Yet through the smart use of loops it remained relatively compact while at the same time adding to its robustness.<br />
<br />
The only weak point in the system was the localization, which was neither strong enough to always determine its location regardless of its position, nor had the ability to use priory acquired knowledge to update it. The localization was built keeping in mind the use of semantic concepts and to make PICO the center of the world, but this proved to be too hard for the time given. This caused us to fail the final competition.<br />
<br />
Due to the lack of proper localization, the competition has not shown the full potential of the result of this project. Yet we are convinced that there are some very powerful tools among the created software of which we would be happy to see them reappear in the upcoming years. Hence, in the end group 4 is happy with the progress that was made within the project. We thank the organization of this course for this opportunity and help with the assignment.<br />
<br />
== Recommendations ==<br />
The implementation of localization was unsuccessful in the project. The use of semantic concepts as recognizable features however had lots of potential, given more time to implement it. The algorithm would fail however when multiple rooms show the same features, in which case it could be combined with the option to have multiple hypothesis on its current location. Yet many good alternatives present themselves.<br />
<br />
Also a lot of wasted hours were spend on the endless conversion of coordinates from PICO’s view to the map and back, because they worked in different coordinate systems. Our recommendation would be to from the start convert these to work in the same system. This will not only save on computation time, but will mainly help understanding the systems and reduce the chance on errors.<br />
<br />
== Code ==<br />
The following snippets give a good representation of how the software for this project was structured, and how it did what it was supposed to do.<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/144 Overall functionality]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/148 State changes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/147 Effect of state on functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/145 Methods in classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/146 Dynamic obstacle avoidance]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/149 Velocity planning]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/150 Complex classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/151 Functions within functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/152 Splitting of the RRT path]<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 10 (2019-06-12)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190620.pdf#filelinks Meeting 11 (2019-06-20)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=79801Embedded Motion Control 2019 Group 42019-06-21T14:19:35Z<p>S149491: /* Escape Room - Competition */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019. The course Embedded Motion Control is about software design and implementation into autonomous robots. Application of the acquired knowledge is done to real-life robotics tasks and tested with robot PICO.<br />
<br />
During lectures it is explained that the point of view of the robot is essential. Semantic knowledge of the environment is essential. Which information is needed at which moment, and when are things less important in terms of computational power.<br />
<br />
The statement above of the needed information at which moment is the main focus of our project. For example, planning is not important if you already know where you have to go and if you are not moving you do not have to avoid walls. Because of this, it is chosen to change the location of the map towards the location of PICO and not the other way around. PICO is the center of reasoning of all parts of the program.<br />
This year’s challenge is to move through a Hospital in order to visit a number of cabinets. The approach and solutions that are found are explained in the upcoming sections.<br />
<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the execution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
For the escaperoom challenge a specific strategy is determined. After initialization, PICO starts rotating and simultaneously scanning the room to find the door. In case no door is found after a full rotation, PICO determines the far-most corner and moves in this direction with half the distance measured. After this, PICO repeats this sequence. In case a door is found, PICO moves to a position 50cm in front of the door and faces the exit. A second scan verifies the location of PICO with respect to the door and corrects its position if necessary. After this, the end of the hallway is determined and PICO moves towards this point. After the goal is reached, PICO says it has reached its goal and shuts down. A schematic representation of the strategy is given below. <br />
<br />
[[File:Strategy_escaperoom2.jpg|600px]]<br />
<br />
Out of the plan a finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
</gallery><br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO starts looking for a door, the LRF data is first preprocessed into walls by a ''split and merge'' algorithm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visible door is determined.<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First, for every measured point the location in cartesian coordinates is calculated, using PICO as the center point. After this, PICO takes the leftmost and rightmost LRF-measurements and formulates the hypothesis that they are two points on a single wall. Then, the two points are used to calculate the expected middle point. Consequently, this point is compared to the real LRF-data measurement in the middle of the two points. Two checks are executed to verify the wall:<br />
<br />
* The absolute distance between the expected point and real point is sufficiently small<br />
* The length of the wall does not exceed the size of a door, to ensure no doors are overlooked <br />
<br />
On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdivided into walls, or splitting is no longer possible because a wall consists of only two points. Remaining is a large number of small wall sections, some of which actually belong together. Wall sections are merged they share an endpoint and their relative angle is small (the ''merge'').<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base of the perception software in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|First step: Expected point is far away from real LRF-point; splitting wall.<br />
File:Split_merge2.png|Second step: Expected point is closer to the real LRF-point, but not sufficiently close; splitting again.<br />
File:Split_merge3.png|Third step: Expected point coincides with the real LRF-point and the two points are sufficiently close; wall found.<br />
</gallery><br />
<br />
==== Corner recognition ====<br />
<br />
In corner recognition as used in the escaperoom competition, three types of corners are distinguished: Inside (shallow), outside (wide) and endpoint corners. The first two are defined as a shared endpoint of two walls, where the walls have a certain angle respectively to each other. An endpoint corner is defined as the end of a wall at which no other wall is detected (i.e. a jump in LRF-data is measured at the end of a wall). <br />
Also corner detection has proven to be very effective and has played a major role throughout the project. All different corners type are shown in the image below. These are <span style="color:green">inside corner</span>, <span style="color:red">outside corner</span>, <span style="color:orange">virtual "flat" corner</span> and <span style="color:grey">endpoint corners</span>.<br />
<br />
[[File:Cornerrecog2.png|100px|left|frame|All types of corners and doors.]]<br clear=all><br />
<br />
==== Door detection ====<br />
By clearly distinguishing types of corners, doors can be found by looking at specific combinations of corner types. Three types of doors are possible:<br />
*Door at the middle of a wall<br />
*Door in a corner<br />
*Door at end of hallway<br />
Depending on the point of view, these doors consist of different combinations of corner-types. For instance, the door at the middle of a wall can consist of two corners of type "outside" or one "outside" corner and one "endpoint" corner. Additional checks are used to confirm the door. The width must be within the expected margins and the relative angle with respect to adjacent walls.<br />
<br />
In the above figure it is already seen that a door in a corner is found and a door at the end of a hallway is found. Below you can see the example that a door is in the middle of a wall and that is is recognised while turning PICO<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|100px|Animation of the exit detection flow]]<br clear=all><br />
<br />
=== Escape Room - Testing ===<br />
In real life PICO behaves different than in the simulations. A couple of things needed testing in order to stay on track of the global planning of the project.<br />
The main goal of every test date is given together with it's result in the end.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
<b>Goal:</b> Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
<b>Result:</b> PICO moves in the correct direction, but the signal to the motors seems to be too low. <br />
Suspected problem: smooth acceleration, which is implemented to prevent slip and shocky movement, should be less smooth.<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
<b>Goal:</b> Test improved smooth acceleration profile. Also test some parameter tweaks such as the emergency distance.<br />
<br />
<b>Result:</b> Changed smooth acceleration profile helps a bit, but PICO still does not move to the desired location (moves less than expected). Suspected problem: PICO does not move by using odometry data. This should be implemented before the escaperoom challenge. UPDATE: movement on odometry data could not be implemented before the challenge day, because of the time. Therefore, a final check is implemented when PICO thinks it is in front of the door. Essentially, this contains an additional scan to find a door and a movements towards the desired location in front of the door.<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
<b>Goal:</b> Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
<br />
<b>Result:</b> Odometry still needs small tweaks, but the emergency stop works fine now. We don't take into account that there is an offset in the odometry frame, so a reset in this is needed.<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The designed algorithm worked perfectly and very quick. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that odometry had not been implemented, the distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement that needed to be done is the usage of odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, the laser data should be used more frequently, updating plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
[[File:Pico_EscapeRoom_Group4.gif]]<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge it is crucial to be able to localize accurately. With the RRT relying on the location of PICO on the map, the idea is to update the localization every time the robot needs to make a new path. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. If PICO may run into trouble of any kind, either the (dynamic) obstacle avoidance or the state machine compensates for this. In this case, the robot goes to a 're-planning' state, where it also updates the location again. In this way it is never a problem if the accuracy of the localization is a bit off. The procedure of elaborated below.<br />
<br />
==== Point matching ====<br />
PICO is localized as follows:<br />
<br />
Before the final challenge, in order for PICO to localize, the corners of the map are given the type 'outside' and 'inside' by hand. When the program is started, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
In an alternative localization procedure than described above, the door finding and cabinet finding algorithm can be used. This algorithm comes from the exit recognition that was used for the escaperoom challenge and worked very well. In the hospital challenge, doors are recognised in the same manner as the exit was detected in the escaperoom. Cabinets are defined as a set of corners with certain properties: corner distance and corner type. This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked much faster than the other localization algorithm, as hardly any calculation is required. However, this option is heavily based on the geometry of the starting area, and is therefore not very generic.<br />
<br />
Another alternative that is considered is the use of a particle filter for localization. This is a well known type of localization and some examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. Particle filters are not used in the design, because it would be much of an 'overkill', since the starting area is known and the rooms have enough points of recognition (think of distances and corner kinds etc). Therefore it is chosen to localize with an in our opinion more elegant algorithm where less computational effort is required.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the genericity. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. In each iteration of the RRT-algorithm a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similiar to the splitting algorithm used to find walls in LRF data. In the first step, the splitting algorithm tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
With the two improvements to the random tree path planner implemented, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, it consists of an array of points. An extra orientation is added to these points in order to let PICO orient itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanner2.gif|frame|left|300px|Pathplanner using a RRT algorithm with path optimizer.]]<br clear=all><br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also reflected in the [[#Hospital Challenge - Finite state machine|finite state machine]]. In global movement PICO follows the path created by the path planner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 cm in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), which is an entry of the list of cabinets that should be visited. A counter is used to keep track of the number of cabinets that are already visited. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y,theta) which define the path. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is within a certain range of the target path position, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the endpoint is much smaller to ensure PICO reaches his final position. During the goalMove state, two special situations can occur: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map, or is trying to avoid an obstacle, which has driven him into a corner. PICO will then scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to a local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors and corners, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. This step is also used to update the position on the map based on the LRF data and the cabinet PICO is looking at. If the cabinet is not found, PICO starts rotating and searches for cabinets again, until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and deadlock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. Its primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows. First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
The image below on the left shows how the obstacle avoidance works in a simulation enviroment. PICO is only aware of the wall in front of him at the starting position and plans a path to a location 4 meters in front of him. He succesfully avoids all small obstacles in the adjoining room. The second image displays a test done on PICO. Again he is only aware of the first wall in front of him and succesfully avoids the obstacles on his path.<br />
<br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:dynobsavoid.gif |frame|Dynamic obstacle avoidance simulation.]]<br />
<br />
| [[File:dynobsavoid_mov.gif|frame|Dynamicd obstacle avoidance test.]]<br />
<br />
|}<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognizing unexpected obstacles and adding them to the map, obstacles that have been added to the map and are no longer present in the environment should automatically be removed.<br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visible will be defined as two separate obstacles.<br />
<br />
Next, the obstacles that are defined multiple times (overlapping lines) are merged and obstacles that are recognized as being on the JSON map are removed. In this procedure, obstacles are interpreted as lines. The algorithm looks at the relative angle between lines, the perpendicular distance from one line to the other and checks whether the lines overlap. If all hold, a new obstacle is defined as a combination of these lines. The two initial obstacles are removed. The same checks are executed to filter any walls from the obstacles.<br />
<br />
With the updated version of the map, the path planning is now able to re-plan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether their corners should be within vision range and the view on the obstacle is not obstructed. This is done by checking if a line between the corner and PICO is crossed by a line of data from the LRF scan. If not the obstacles should be visible. As this function is used before adding new obstacles, an obstacle in sight which is still in place will be added to the map again.<br />
<br />
This way paths that were obstructed before will be accessible by the robot again when the obstacles as well as wrongly detected obstacles are removed. The image below shows an example of how PICO is able to plan around an obstacle found. In this case a door which seems to be open in the map, is actually closed. PICO made a path from cabinet 2 to 0. When following the path an obstacle (the closed door) is detected, added to the map and planned a new route. As the localization at this point was not fully correct, the obstacle is placed on the map with a slight offset.<br />
<br />
[[File:staticobstacleavoid.gif|left|frame|250px|Static obstacle recognition and replanning.]]<br clear=all><br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality.<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
<b>Goal:</b><br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
<br />
<b>Result:</b><br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03), PICO Test 6 (2019-06-05) and PICO Test 7 (2019-06-11) ====<br />
These tests were mainly on testing a lot of small things and problems that occured while testing.<br />
<br />
<b>Goals:</b><br />
*Test the localization algorithm and the dynamic obstacle avoidance.<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
<b>Results:</b><br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Simulation ===<br />
<br />
To show how the final program works, a full simulation is done on the competition hospital map. During this simulation PICO is told to visit cabinets 0, 1 and 3. The complete program is used as described above. Note that the GIF is played at 1.7x speed with 5 FPS due to the limited available file size. A full video of this simulation can be found in [[:File:Group4_FinalChallengeSimulation.zip|ZIP attached]]. <br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:finalsim2.gif |frame|Hospital challenge simulation]]<br />
<br />
| [[File:finalviz2.gif|frame|Hospital challenge visualization]]<br />
<br />
|}<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. Within these two trials we had the chance to show our skills to a bigger audience and to the organization of the course. We were aware of the localization problem and hoped that we could show as much of our built functionality as possible.<br />
<br />
The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position.<br />
<br />
The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be too inaccurate to use in this hospital challenge. PICO stranded next to a door where he had to replan his route. Here PICO could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
[[File:Hospitalmovie.gif|frame|left|Group 4 hospital challenge.]]<br clear=all><br />
<br />
== Conclusion ==<br />
The Embedded Motion Control course of 2019 proved to be a challenging assignment but was received with lots of enthusiasm. It is not often you get a chance to just play around with a robot like this. Besides the requirements set by the course, additional goals were set by ourselves as deducted from the lectures accompanying the course. These included semantic knowledge of the environment, selective use of information, a world view as perceived by the robot and to avoid using a grids.<br />
<br />
=== Escape Room challenge ===<br />
The first requirement was already fulfilled to a large extend by class definition of walls, corners, doors and later cabinets. The split and merge algorithm allowed the recognition of these semantic concepts in the LRF data in an accurate yet efficient manner. Rather than mapping out the entire area, the algorithm looked for a door and next for the end of hallway, fulfilling the second and third goal by only making use of information needed to fulfill the task at hand and defining the door and end of hallway positions as seen by the robot. The effectiveness of these concepts was clearly visible during the escape room challenge as the door was found immediately as it entered PICO’s field of view. The task of the driving towards known target however was underestimated and PICO was unable to reach the exit.<br />
<br />
=== Hospital challenge ===<br />
For the hospital challenge, driving on odometry was successfully implemented and reinforced with a powerful ‘dynamic obstacle avoidance’. Speeds were adjusted when getting close to obstacles while adding repelling forces to PICO from any obstacles around it.<br />
<br />
The fourth goal mainly played a role when coming up with a path planning algorithm. The solution for grid-less path planning was found in a RRT algorithm, which was extended with a small bias to make it converge faster and our own split and merge algorithm to generate a smoother trajectory. The addition of static object detection and updating provided the option to find alternative routes in case the way was blocked, forming a strong combination with the path planning algorithm.<br />
The whole system was controlled by a strong and extensive finite state machine. Yet through the smart use of loops it remained relatively compact while at the same time adding to its robustness.<br />
<br />
The only weak point in the system was the localization, which was neither strong enough to always determine its location regardless of its position, nor had the ability to use priory acquired knowledge to update it. The localization was built keeping in mind the use of semantic concepts and to make PICO the center of the world, but this proved to be too hard for the time given. This caused us to fail the final competition.<br />
<br />
Due to the lack of proper localization, the competition has not shown the full potential of the result of this project. Yet we are convinced that there are some very powerful tools among the created software of which we would be happy to see them reappear in the upcoming years. Hence, in the end group 4 is happy with the progress that was made within the project. We thank the organization of this course for this opportunity and help with the assignment.<br />
<br />
== Recommendations ==<br />
The implementation of localization was unsuccessful in the project. The use of semantic concepts as recognizable features however had lots of potential, given more time to implement it. The algorithm would fail however when multiple rooms show the same features, in which case it could be combined with the option to have multiple hypothesis on its current location. Yet many good alternatives present themselves.<br />
<br />
Also a lot of wasted hours were spend on the endless conversion of coordinates from PICO’s view to the map and back, because they worked in different coordinate systems. Our recommendation would be to from the start convert these to work in the same system. This will not only save on computation time, but will mainly help understanding the systems and reduce the chance on errors.<br />
<br />
== Code ==<br />
The following snippets give a good representation of how the software for this project was structured, and how it did what it was supposed to do.<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/144 Overall functionality]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/148 State changes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/147 Effect of state on functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/145 Methods in classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/146 Dynamic obstacle avoidance]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/149 Velocity planning]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/150 Complex classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/151 Functions within functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/152 Splitting of the RRT path]<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 10 (2019-06-12)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190620.pdf#filelinks Meeting 11 (2019-06-20)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=79672Embedded Motion Control 2019 Group 42019-06-21T12:44:09Z<p>S149491: /* Detect missing obstacles */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019. The course Embedded Motion Control is about software design and implementation into autonomous robots. Application of the acquired knowledge is done to real-life robotics tasks and tested with robot PICO.<br />
<br />
During lectures it is explained that the point of view of the robot is essential. Semantic knowledge of the environment is essential. Which information is needed at which moment, and when are things less important in terms of computational power.<br />
<br />
The statement above of the needed information at which moment is the main focus of our project. For example, planning is not important if you already know where you have to go and if you are not moving you do not have to avoid walls. Because of this, it is chosen to change the location of the map towards the location of PICO and not the other way around. PICO is the center of reasoning of all parts of the program.<br />
This year’s challenge is to move through a Hospital in order to visit a number of cabinets. The approach and solutions that are found are explained in the upcoming sections.<br />
<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the execution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
For the escaperoom challenge a specific strategy is determined. After initialization, PICO starts rotating and simultaneously scanning the room to find the door. In case no door is found after a full rotation, PICO determines the far-most corner and moves in this direction with half the distance measured. After this, PICO repeats this sequence. In case a door is found, PICO moves to a position 50cm in front of the door and faces the exit. A second scan verifies the location of PICO with respect to the door and corrects its position if necessary. After this, the end of the hallway is determined and PICO moves towards this point. After the goal is reached, PICO says it has reached its goal and shuts down. A schematic representation of the strategy is given below. <br />
<br />
[[File:Strategy_escaperoom2.jpg|600px]]<br />
<br />
Out of the plan a finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
</gallery><br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO starts looking for a door, the LRF data is first preprocessed into walls by a ''split and merge'' algorithm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visible door is determined.<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First, for every measured point the location in cartesian coordinates is calculated, using PICO as the center point. After this, PICO takes the leftmost and rightmost LRF-measurements and formulates the hypothesis that they are two points on a single wall. Then, the two points are used to calculate the expected middle point. Consequently, this point is compared to the real LRF-data measurement in the middle of the two points. Two checks are executed to verify the wall:<br />
<br />
* The absolute distance between the expected point and real point is sufficiently small<br />
* The length of the wall does not exceed the size of a door, to ensure no doors are overlooked <br />
<br />
On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdivided into walls, or splitting is no longer possible because a wall consists of only two points. Remaining is a large number of small wall sections, some of which actually belong together. Wall sections are merged they share an endpoint and their relative angle is small (the ''merge'').<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base of the perception software in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|First step: Expected point is far away from real LRF-point; splitting wall.<br />
File:Split_merge2.png|Second step: Expected point is closer to the real LRF-point, but not sufficiently close; splitting again.<br />
File:Split_merge3.png|Third step: Expected point coincides with the real LRF-point and the two points are sufficiently close; wall found.<br />
</gallery><br />
<br />
==== Corner recognition ====<br />
<br />
In corner recognition as used in the escaperoom competition, three types of corners are distinguished: Inside (shallow), outside (wide) and endpoint corners. The first two are defined as a shared endpoint of two walls, where the walls have a certain angle respectively to each other. An endpoint corner is defined as the end of a wall at which no other wall is detected (i.e. a jump in LRF-data is measured at the end of a wall). <br />
Also corner detection has proven to be very effective and has played a major role throughout the project. All different corners type are shown in the image below. These are <span style="color:green">inside corner</span>, <span style="color:red">outside corner</span>, <span style="color:orange">virtual "flat" corner</span> and <span style="color:grey">endpoint corners</span>.<br />
<br />
[[File:Cornerrecog2.png|100px|left|frame|All types of corners and doors.]]<br clear=all><br />
<br />
==== Door detection ====<br />
By clearly distinguishing types of corners, doors can be found by looking at specific combinations of corner types. Three types of doors are possible:<br />
*Door at the middle of a wall<br />
*Door in a corner<br />
*Door at end of hallway<br />
Depending on the point of view, these doors consist of different combinations of corner-types. For instance, the door at the middle of a wall can consist of two corners of type "outside" or one "outside" corner and one "endpoint" corner. Additional checks are used to confirm the door. The width must be within the expected margins and the relative angle with respect to adjacent walls.<br />
<br />
In the above figure it is already seen that a door in a corner is found and a door at the end of a hallway is found. Below you can see the example that a door is in the middle of a wall and that is is recognised while turning PICO<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|100px|Animation of the exit detection flow]]<br clear=all><br />
<br />
=== Escape Room - Testing ===<br />
In real life PICO behaves different than in the simulations. A couple of things needed testing in order to stay on track of the global planning of the project.<br />
The main goal of every test date is given together with it's result in the end.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
<b>Goal:</b> Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
<b>Result:</b> PICO moves in the correct direction, but the signal to the motors seems to be too low. <br />
Suspected problem: smooth acceleration, which is implemented to prevent slip and shocky movement, should be less smooth.<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
<b>Goal:</b> Test improved smooth acceleration profile. Also test some parameter tweaks such as the emergency distance.<br />
<br />
<b>Result:</b> Changed smooth acceleration profile helps a bit, but PICO still does not move to the desired location (moves less than expected). Suspected problem: PICO does not move by using odometry data. This should be implemented before the escaperoom challenge. UPDATE: movement on odometry data could not be implemented before the challenge day, because of the time. Therefore, a final check is implemented when PICO thinks it is in front of the door. Essentially, this contains an additional scan to find a door and a movements towards the desired location in front of the door.<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
<b>Goal:</b> Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
<br />
<b>Result:</b> Odometry still needs small tweaks, but the emergency stop works fine now. We don't take into account that there is an offset in the odometry frame, so a reset in this is needed.<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
[[File:Pico_EscapeRoom_Group4.gif]]<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge it is crucial to be able to localize accurately. With the RRT relying on the location of PICO on the map, the idea is to update the localization every time the robot needs to make a new path. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. If PICO may run into trouble of any kind, either the (dynamic) obstacle avoidance or the state machine compensates for this. In this case, the robot goes to a 're-planning' state, where it also updates the location again. In this way it is never a problem if the accuracy of the localization is a bit off. The procedure of elaborated below.<br />
<br />
==== Point matching ====<br />
PICO is localized as follows:<br />
<br />
Before the final challenge, in order for PICO to localize, the corners of the map are given the type 'outside' and 'inside' by hand. When the program is started, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
In an alternative localization procedure than described above, the door finding and cabinet finding algorithm can be used. This algorithm comes from the exit recognition that was used for the escaperoom challenge and worked very well. In the hospital challenge, doors are recognised in the same manner as the exit was detected in the escaperoom. Cabinets are defined as a set of corners with certain properties: corner distance and corner type. This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked much faster than the other localization algorithm, as hardly any calculation is required. However, this option is heavily based on the geometry of the starting area, and is therefore not very generic.<br />
<br />
Another alternative that is considered is the use of a particle filter for localization. This is a well known type of localization and some examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. Particle filters are not used in the design, because it would be much of an 'overkill', since the starting area is known and the rooms have enough points of recognition (think of distances and corner kinds etc). Therefore it is chosen to localize with an in our opinion more elegant algorithm where less computational effort is required.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the genericity. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. In each iteration of the RRT-algorithm a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similiar to the splitting algorithm used to find walls in LRF data. In the first step, the splitting algorithm tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
With the two improvements to the random tree path planner implemented, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, it consists of an array of points. An extra orientation is added to these points in order to let PICO orient itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanner2.gif|frame|left|300px|Pathplanner using a RRT algorithm with path optimizer.]]<br clear=all><br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also reflected in the [[#Hospital Challenge - Finite state machine|finite state machine]]. In global movement PICO follows the path created by the path planner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 cm in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), which is an entry of the list of cabinets that should be visited. A counter is used to keep track of the number of cabinets that are already visited. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y,theta) which define the path. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is within a certain range of the target path position, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the endpoint is much smaller to ensure PICO reaches his final position. During the goalMove state, two special situations can occur: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map, or is trying to avoid an obstacle, which has driven him into a corner. PICO will then scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to a local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors and corners, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. This step is also used to update the position on the map based on the LRF data and the cabinet PICO is looking at. If the cabinet is not found, PICO starts rotating and searches for cabinets again, until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and deadlock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. Its primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows. First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
The image below on the left shows how the obstacle avoidance works in a simulation enviroment. PICO is only aware of the wall in front of him at the starting position and plans a path to a location 4 meters in front of him. He succesfully avoids all small obstacles in the adjoining room. The second image displays a test done on PICO. Again he is only aware of the first wall in front of him and succesfully avoids the obstacles on his path.<br />
<br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:dynobsavoid.gif |frame|Dynamic obstacle avoidance simulation.]]<br />
<br />
| [[File:dynobsavoid_mov.gif|frame|Dynamicd obstacle avoidance test.]]<br />
<br />
|}<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognizing unexpected obstacles and adding them to the map, obstacles that have been added to the map and are no longer present in the environment should automatically be removed.<br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visible will be defined as two separate obstacles.<br />
<br />
Next, the obstacles that are defined multiple times (overlapping lines) are merged and obstacles that are recognized as being on the JSON map are removed. In this procedure, obstacles are interpreted as lines. The algorithm looks at the relative angle between lines, the perpendicular distance from one line to the other and checks whether the lines overlap. If all hold, a new obstacle is defined as a combination of these lines. The two initial obstacles are removed. The same checks are executed to filter any walls from the obstacles.<br />
<br />
With the updated version of the map, the path planning is now able to re-plan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether their corners should be within vision range and the view on the obstacle is not obstructed. This is done by checking if a line between the corner and PICO is crossed by a line of data from the LRF scan. If not the obstacles should be visible. As this function is used before adding new obstacles, an obstacle in sight which is still in place will be added to the map again.<br />
<br />
This way paths that were obstructed before will be accessible by the robot again when the obstacles as well as wrongly detected obstacles are removed. The image below shows an example of how PICO is able to plan around an obstacle found. In this case a door which seems to be open in the map, is actually closed. PICO made a path from cabinet 2 to 0. When following the path an obstacle (the closed door) is detected, added to the map and planned a new route. As the localization at this point was not fully correct, the obstacle is placed on the map with a slight offset.<br />
<br />
[[File:staticobstacleavoid.gif|left|frame|250px|Static obstacle recognition and replanning.]]<br clear=all><br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality.<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
<b>Goal:</b><br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
<br />
<b>Result:</b><br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03), PICO Test 6 (2019-06-05) and PICO Test 7 (2019-06-11) ====<br />
These tests were mainly on testing a lot of small things and problems that occured while testing.<br />
<br />
<b>Goals:</b><br />
*Test the localization algorithm and the dynamic obstacle avoidance.<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
<b>Results:</b><br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Simulation ===<br />
<br />
To show how the final program works, a full simulation is done on the competition hospital map. During this simulation PICO is told to visit cabinets 0, 1 and 3. The complete program is used as described above. Note that the GIF is played at 1.7x speed with 5 FPS due to the limited available file size. A full video of this simulation can be found in [[:File:Group4_FinalChallengeSimulation.zip|ZIP attached]]. <br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:finalsim2.gif |frame|Hospital challenge simulation]]<br />
<br />
| [[File:finalviz2.gif|frame|Hospital challenge visualization]]<br />
<br />
|}<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. Within these two trials we had the chance to show our skills to a bigger audience and to the organization of the course. We were aware of the localization problem and hoped that we could show as much of our built functionality as possible.<br />
<br />
The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position.<br />
<br />
The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be too inaccurate to use in this hospital challenge. PICO stranded next to a door where he had to replan his route. Here PICO could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
[[File:Hospitalmovie.gif|frame|left|Group 4 hospital challenge.]]<br clear=all><br />
<br />
== Conclusion ==<br />
The Embedded Motion Control course of 2019 proved to be a challenging assignment but was received with lots of enthusiasm. It is not often you get a chance to just play around with a robot like this. Besides the requirements set by the course, additional goals were set by ourselves as deducted from the lectures accompanying the course. These included semantic knowledge of the environment, selective use of information, a world view as perceived by the robot and to avoid using a grids.<br />
<br />
=== Escape Room challenge ===<br />
The first requirement was already fulfilled to a large extend by class definition of walls, corners, doors and later cabinets. The split and merge algorithm allowed the recognition of these semantic concepts in the LRF data in an accurate yet efficient manner. Rather than mapping out the entire area, the algorithm looked for a door and next for the end of hallway, fulfilling the second and third goal by only making use of information needed to fulfill the task at hand and defining the door and end of hallway positions as seen by the robot. The effectiveness of these concepts was clearly visible during the escape room challenge as the door was found immediately as it entered PICO’s field of view. The task of the driving towards known target however was underestimated and PICO was unable to reach the exit.<br />
<br />
=== Hospital challenge ===<br />
For the hospital challenge, driving on odometry was successfully implemented and reinforced with a powerful ‘dynamic obstacle avoidance’. Speeds were adjusted when getting close to obstacles while adding repelling forces to PICO from any obstacles around it.<br />
<br />
The fourth goal mainly played a role when coming up with a path planning algorithm. The solution for grid-less path planning was found in a RRT algorithm, which was extended with a small bias to make it converge faster and our own split and merge algorithm to generate a smoother trajectory. The addition of static object detection and updating provided the option to find alternative routes in case the way was blocked, forming a strong combination with the path planning algorithm.<br />
The whole system was controlled by a strong and extensive finite state machine. Yet through the smart use of loops it remained relatively compact while at the same time adding to its robustness.<br />
<br />
The only weak point in the system was the localization, which was neither strong enough to always determine its location regardless of its position, nor had the ability to use priory acquired knowledge to update it. The localization was built keeping in mind the use of semantic concepts and to make PICO the center of the world, but this proved to be too hard for the time given. This caused us to fail the final competition.<br />
<br />
Due to the lack of proper localization, the competition has not shown the full potential of the result of this project. Yet we are convinced that there are some very powerful tools among the created software of which we would be happy to see them reappear in the upcoming years. Hence, in the end group 4 is happy with the progress that was made within the project. We thank the organization of this course for this opportunity and help with the assignment.<br />
<br />
== Recommendations ==<br />
The implementation of localization was unsuccessful in the project. The use of semantic concepts as recognizable features however had lots of potential, given more time to implement it. The algorithm would fail however when multiple rooms show the same features, in which case it could be combined with the option to have multiple hypothesis on its current location. Yet many good alternatives present themselves.<br />
<br />
Also a lot of wasted hours were spend on the endless conversion of coordinates from PICO’s view to the map and back, because they worked in different coordinate systems. Our recommendation would be to from the start convert these to work in the same system. This will not only save on computation time, but will mainly help understanding the systems and reduce the chance on errors.<br />
<br />
== Code ==<br />
The following snippets give a good representation of how the software for this project was structured, and how it did what it was supposed to do.<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/144 Overall functionality]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/148 State changes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/147 Effect of state on functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/145 Methods in classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/146 Dynamic obstacle avoidance]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/149 Velocity planning]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/150 Complex classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/151 Functions within functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/152 Splitting of the RRT path]<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 10 (2019-06-12)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190620.pdf#filelinks Meeting 11 (2019-06-20)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=79667Embedded Motion Control 2019 Group 42019-06-21T12:36:58Z<p>S149491: /* Detect new obstacles */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019. The course Embedded Motion Control is about software design and implementation into autonomous robots. Application of the acquired knowledge is done to real-life robotics tasks and tested with robot PICO.<br />
<br />
During lectures it is explained that the point of view of the robot is essential. Semantic knowledge of the environment is essential. Which information is needed at which moment, and when are things less important in terms of computational power.<br />
<br />
The statement above of the needed information at which moment is the main focus of our project. For example, planning is not important if you already know where you have to go and if you are not moving you do not have to avoid walls. Because of this, it is chosen to change the location of the map towards the location of PICO and not the other way around. PICO is the center of reasoning of all parts of the program.<br />
This year’s challenge is to move through a Hospital in order to visit a number of cabinets. The approach and solutions that are found are explained in the upcoming sections.<br />
<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the execution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
For the escaperoom challenge a specific strategy is determined. After initialization, PICO starts rotating and simultaneously scanning the room to find the door. In case no door is found after a full rotation, PICO determines the far-most corner and moves in this direction with half the distance measured. After this, PICO repeats this sequence. In case a door is found, PICO moves to a position 50cm in front of the door and faces the exit. A second scan verifies the location of PICO with respect to the door and corrects its position if necessary. After this, the end of the hallway is determined and PICO moves towards this point. After the goal is reached, PICO says it has reached its goal and shuts down. A schematic representation of the strategy is given below. <br />
<br />
[[File:Strategy_escaperoom2.jpg|600px]]<br />
<br />
Out of the plan a finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
</gallery><br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO starts looking for a door, the LRF data is first preprocessed into walls by a ''split and merge'' algorithm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visible door is determined.<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First, for every measured point the location in cartesian coordinates is calculated, using PICO as the center point. After this, PICO takes the leftmost and rightmost LRF-measurements and formulates the hypothesis that they are two points on a single wall. Then, the two points are used to calculate the expected middle point. Consequently, this point is compared to the real LRF-data measurement in the middle of the two points. Two checks are executed to verify the wall:<br />
<br />
* The absolute distance between the expected point and real point is sufficiently small<br />
* The length of the wall does not exceed the size of a door, to ensure no doors are overlooked <br />
<br />
On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdivided into walls, or splitting is no longer possible because a wall consists of only two points. Remaining is a large number of small wall sections, some of which actually belong together. Wall sections are merged they share an endpoint and their relative angle is small (the ''merge'').<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base of the perception software in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|First step: Expected point is far away from real LRF-point; splitting wall.<br />
File:Split_merge2.png|Second step: Expected point is closer to the real LRF-point, but not sufficiently close; splitting again.<br />
File:Split_merge3.png|Third step: Expected point coincides with the real LRF-point and the two points are sufficiently close; wall found.<br />
</gallery><br />
<br />
==== Corner recognition ====<br />
<br />
In corner recognition as used in the escaperoom competition, three types of corners are distinguished: Inside (shallow), outside (wide) and endpoint corners. The first two are defined as a shared endpoint of two walls, where the walls have a certain angle respectively to each other. An endpoint corner is defined as the end of a wall at which no other wall is detected (i.e. a jump in LRF-data is measured at the end of a wall). <br />
Also corner detection has proven to be very effective and has played a major role throughout the project. All different corners type are shown in the image below. These are <span style="color:green">inside corner</span>, <span style="color:red">outside corner</span>, <span style="color:orange">virtual "flat" corner</span> and <span style="color:grey">endpoint corners</span>.<br />
<br />
[[File:Cornerrecog2.png|100px|left|frame|All types of corners and doors.]]<br clear=all><br />
<br />
==== Door detection ====<br />
By clearly distinguishing types of corners, doors can be found by looking at specific combinations of corner types. Three types of doors are possible:<br />
*Door at the middle of a wall<br />
*Door in a corner<br />
*Door at end of hallway<br />
Depending on the point of view, these doors consist of different combinations of corner-types. For instance, the door at the middle of a wall can consist of two corners of type "outside" or one "outside" corner and one "endpoint" corner. Additional checks are used to confirm the door. The width must be within the expected margins and the relative angle with respect to adjacent walls.<br />
<br />
In the above figure it is already seen that a door in a corner is found and a door at the end of a hallway is found. Below you can see the example that a door is in the middle of a wall and that is is recognised while turning PICO<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|100px|Animation of the exit detection flow]]<br clear=all><br />
<br />
=== Escape Room - Testing ===<br />
In real life PICO behaves different than in the simulations. A couple of things needed testing in order to stay on track of the global planning of the project.<br />
The main goal of every test date is given together with it's result in the end.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
<b>Goal:</b> Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
<b>Result:</b> PICO moves in the correct direction, but the signal to the motors seems to be too low. <br />
Suspected problem: smooth acceleration, which is implemented to prevent slip and shocky movement, should be less smooth.<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
<b>Goal:</b> Test improved smooth acceleration profile. Also test some parameter tweaks such as the emergency distance.<br />
<br />
<b>Result:</b> Changed smooth acceleration profile helps a bit, but PICO still does not move to the desired location (moves less than expected). Suspected problem: PICO does not move by using odometry data. This should be implemented before the escaperoom challenge. UPDATE: movement on odometry data could not be implemented before the challenge day, because of the time. Therefore, a final check is implemented when PICO thinks it is in front of the door. Essentially, this contains an additional scan to find a door and a movements towards the desired location in front of the door.<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
<b>Goal:</b> Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
<br />
<b>Result:</b> Odometry still needs small tweaks, but the emergency stop works fine now. We don't take into account that there is an offset in the odometry frame, so a reset in this is needed.<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
[[File:Pico_EscapeRoom_Group4.gif]]<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge it is crucial to be able to localize accurately. With the RRT relying on the location of PICO on the map, the idea is to update the localization every time the robot needs to make a new path. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. If PICO may run into trouble of any kind, either the (dynamic) obstacle avoidance or the state machine compensates for this. In this case, the robot goes to a 're-planning' state, where it also updates the location again. In this way it is never a problem if the accuracy of the localization is a bit off. The procedure of elaborated below.<br />
<br />
==== Point matching ====<br />
PICO is localized as follows:<br />
<br />
Before the final challenge, in order for PICO to localize, the corners of the map are given the type 'outside' and 'inside' by hand. When the program is started, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
In an alternative localization procedure than described above, the door finding and cabinet finding algorithm can be used. This algorithm comes from the exit recognition that was used for the escaperoom challenge and worked very well. In the hospital challenge, doors are recognised in the same manner as the exit was detected in the escaperoom. Cabinets are defined as a set of corners with certain properties: corner distance and corner type. This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked much faster than the other localization algorithm, as hardly any calculation is required. However, this option is heavily based on the geometry of the starting area, and is therefore not very generic.<br />
<br />
Another alternative that is considered is the use of a particle filter for localization. This is a well known type of localization and some examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. Particle filters are not used in the design, because it would be much of an 'overkill', since the starting area is known and the rooms have enough points of recognition (think of distances and corner kinds etc). Therefore it is chosen to localize with an in our opinion more elegant algorithm where less computational effort is required.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the genericity. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. In each iteration of the RRT-algorithm a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similiar to the splitting algorithm used to find walls in LRF data. In the first step, the splitting algorithm tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
With the two improvements to the random tree path planner implemented, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, it consists of an array of points. An extra orientation is added to these points in order to let PICO orient itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanner2.gif|frame|left|300px|Pathplanner using a RRT algorithm with path optimizer.]]<br clear=all><br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also reflected in the [[#Hospital Challenge - Finite state machine|finite state machine]]. In global movement PICO follows the path created by the path planner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 cm in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), which is an entry of the list of cabinets that should be visited. A counter is used to keep track of the number of cabinets that are already visited. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y,theta) which define the path. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is within a certain range of the target path position, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the endpoint is much smaller to ensure PICO reaches his final position. During the goalMove state, two special situations can occur: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map, or is trying to avoid an obstacle, which has driven him into a corner. PICO will then scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to a local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors and corners, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. This step is also used to update the position on the map based on the LRF data and the cabinet PICO is looking at. If the cabinet is not found, PICO starts rotating and searches for cabinets again, until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and deadlock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. Its primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows. First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
The image below on the left shows how the obstacle avoidance works in a simulation enviroment. PICO is only aware of the wall in front of him at the starting position and plans a path to a location 4 meters in front of him. He succesfully avoids all small obstacles in the adjoining room. The second image displays a test done on PICO. Again he is only aware of the first wall in front of him and succesfully avoids the obstacles on his path.<br />
<br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:dynobsavoid.gif |frame|Dynamic obstacle avoidance simulation.]]<br />
<br />
| [[File:dynobsavoid_mov.gif|frame|Dynamicd obstacle avoidance test.]]<br />
<br />
|}<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognizing unexpected obstacles and adding them to the map, obstacles that have been added to the map and are no longer present in the environment should automatically be removed.<br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visible will be defined as two separate obstacles.<br />
<br />
Next, the obstacles that are defined multiple times (overlapping lines) are merged and obstacles that are recognized as being on the JSON map are removed. In this procedure, obstacles are interpreted as lines. The algorithm looks at the relative angle between lines, the perpendicular distance from one line to the other and checks whether the lines overlap. If all hold, a new obstacle is defined as a combination of these lines. The two initial obstacles are removed. The same checks are executed to filter any walls from the obstacles.<br />
<br />
With the updated version of the map, the path planning is now able to re-plan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether they should be within vision range. It checks for all previously found obstacles, if the corners are visible. This is done by checking if a line between a corner and PICO is crossed by a line of data from the LRF scan. If not the obstacles should be visible. As this function is used before adding new obstacles, an obstacle in sight which is still in place will be added to the map again.<br />
<br />
This way paths that were obstructed before will be accessable by the robot again when the obstacles as well as wrongly detected obstacles are removed. The image below shows an example of how PICO is able to plan around an obstacle found. In this case a door which seems to be open in the map, is actually closed. PICO made a path from cabinet 2 to 0. When following the path an obstacle (the closed door) is detected, added to the map and planned a new route. As the localization at this point was not fully correct, the obstacle is placed on the map with a slight offset.<br />
<br />
[[File:staticobstacleavoid.gif|left|frame|250px|Static obstacle recognition and replanning.]]<br clear=all><br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality.<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
<b>Goal:</b><br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
<br />
<b>Result:</b><br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03), PICO Test 6 (2019-06-05) and PICO Test 7 (2019-06-11) ====<br />
These tests were mainly on testing a lot of small things and problems that occured while testing.<br />
<br />
<b>Goals:</b><br />
*Test the localization algorithm and the dynamic obstacle avoidance.<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
<b>Results:</b><br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Simulation ===<br />
<br />
To show how the final program works, a full simulation is done on the competition hospital map. During this simulation PICO is told to visit cabinets 0, 1 and 3. The complete program is used as described above. Note that the GIF is played at 1.7x speed with 5 FPS due to the limited available file size. A full video of this simulation can be found in [[:File:Group4_FinalChallengeSimulation.zip|ZIP attached]]. <br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:finalsim2.gif |frame|Hospital challenge simulation]]<br />
<br />
| [[File:finalviz2.gif|frame|Hospital challenge visualization]]<br />
<br />
|}<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. Within these two trials we had the chance to show our skills to a bigger audience and to the organization of the course. We were aware of the localization problem and hoped that we could show as much of our built functionality as possible.<br />
<br />
The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position.<br />
<br />
The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be too inaccurate to use in this hospital challenge. PICO stranded next to a door where he had to replan his route. Here PICO could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
[[File:Hospitalmovie.gif|frame|left|Group 4 hospital challenge.]]<br clear=all><br />
<br />
== Conclusion ==<br />
The Embedded Motion Control course of 2019 proved to be a challenging assignment but was received with lots of enthusiasm. It is not often you get a chance to just play around with a robot like this. Besides the requirements set by the course, additional goals were set by ourselves as deducted from the lectures accompanying the course. These included semantic knowledge of the environment, selective use of information, a world view as perceived by the robot and to avoid using a grids.<br />
<br />
=== Escape Room challenge ===<br />
The first requirement was already fulfilled to a large extend by class definition of walls, corners, doors and later cabinets. The split and merge algorithm allowed the recognition of these semantic concepts in the LRF data in an accurate yet efficient manner. Rather than mapping out the entire area, the algorithm looked for a door and next for the end of hallway, fulfilling the second and third goal by only making use of information needed to fulfill the task at hand and defining the door and end of hallway positions as seen by the robot. The effectiveness of these concepts was clearly visible during the escape room challenge as the door was found immediately as it entered PICO’s field of view. The task of the driving towards known target however was underestimated and PICO was unable to reach the exit.<br />
<br />
=== Hospital challenge ===<br />
For the hospital challenge, driving on odometry was successfully implemented and reinforced with a powerful ‘dynamic obstacle avoidance’. Speeds were adjusted when getting close to obstacles while adding repelling forces to PICO from any obstacles around it.<br />
<br />
The fourth goal mainly played a role when coming up with a path planning algorithm. The solution for grid-less path planning was found in a RRT algorithm, which was extended with a small bias to make it converge faster and our own split and merge algorithm to generate a smoother trajectory. The addition of static object detection and updating provided the option to find alternative routes in case the way was blocked, forming a strong combination with the path planning algorithm.<br />
The whole system was controlled by a strong and extensive finite state machine. Yet through the smart use of loops it remained relatively compact while at the same time adding to its robustness.<br />
<br />
The only weak point in the system was the localization, which was neither strong enough to always determine its location regardless of its position, nor had the ability to use priory acquired knowledge to update it. The localization was built keeping in mind the use of semantic concepts and to make PICO the center of the world, but this proved to be too hard for the time given. This caused us to fail the final competition.<br />
<br />
Due to the lack of proper localization, the competition has not shown the full potential of the result of this project. Yet we are convinced that there are some very powerful tools among the created software of which we would be happy to see them reappear in the upcoming years. Hence, in the end group 4 is happy with the progress that was made within the project. We thank the organization of this course for this opportunity and help with the assignment.<br />
<br />
== Recommendations ==<br />
The implementation of localization was unsuccessful in the project. The use of semantic concepts as recognizable features however had lots of potential, given more time to implement it. The algorithm would fail however when multiple rooms show the same features, in which case it could be combined with the option to have multiple hypothesis on its current location. Yet many good alternatives present themselves.<br />
<br />
Also a lot of wasted hours were spend on the endless conversion of coordinates from PICO’s view to the map and back, because they worked in different coordinate systems. Our recommendation would be to from the start convert these to work in the same system. This will not only save on computation time, but will mainly help understanding the systems and reduce the chance on errors.<br />
<br />
== Code ==<br />
The following snippets give a good representation of how the software for this project was structured, and how it did what it was supposed to do.<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/144 Overall functionality]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/148 State changes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/147 Effect of state on functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/145 Methods in classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/146 Dynamic obstacle avoidance]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/149 Velocity planning]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/150 Complex classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/151 Functions within functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/152 Splitting of the RRT path]<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 10 (2019-06-12)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190620.pdf#filelinks Meeting 11 (2019-06-20)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=79597Embedded Motion Control 2019 Group 42019-06-21T11:43:54Z<p>S149491: /* Conclusion */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019. The course Embedded Motion Control is about software design and implementation into autonomous robots. Application of the acquired knowledge is done to real-life robotics tasks and tested with robot PICO.<br />
<br />
During lectures it is explained that the point of view of the robot is essential. Semantic knowledge of the environment is essential. Which information is needed at which moment, and when are things less important in terms of computational power.<br />
<br />
The statement above of the needed information at which moment is the main focus of our project. For example, planning is not important if you already know where you have to go and if you are not moving you do not have to avoid walls. Because of this, it is chosen to change the location of the map towards the location of PICO and not the other way around. PICO is the center of reasoning of all parts of the program.<br />
This year’s challenge is to move through a Hospital in order to visit a number of cabinets. The approach and solutions that are found are explained in the upcoming sections.<br />
<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the execution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
For the escaperoom challenge a specific strategy is determined. After initialization, PICO starts rotating and simultaneously scanning the room to find the door. In case no door is found after a full rotation, PICO determines the far-most corner and moves in this direction with half the distance measured. After this, PICO repeats this sequence. In case a door is found, PICO moves to a position 50cm in front of the door and faces the exit. A second scan verifies the location of PICO with respect to the door and corrects its position if necessary. After this, the end of the hallway is determined and PICO moves towards this point. After the goal is reached, PICO says it has reached its goal and shuts down. A schematic representation of the strategy is given below. <br />
<br />
[[File:Strategy_escaperoom2.jpg|600px]]<br />
<br />
Out of the plan a finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
</gallery><br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO starts looking for a door, the LRF data is first preprocessed into walls by a ''split and merge'' algorithm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visible door is determined.<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First, for every measured point the location in cartesian coordinates is calculated, using PICO as the center point. After this, PICO takes the leftmost and rightmost LRF-measurements and formulates the hypothesis that they are two points on a single wall. Then, the two points are used to calculate the expected middle point. Consequently, this point is compared to the real LRF-data measurement in the middle of the two points. Two checks are executed to verify the wall:<br />
<br />
* The absolute distance between the expected point and real point is sufficiently small<br />
* The length of the wall does not exceed the size of a door, to ensure no doors are overlooked <br />
<br />
On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdivided into walls, or splitting is no longer possible because a wall consists of only two points. Remaining is a large number of small wall sections, some of which actually belong together. Wall sections are merged they share an endpoint and their relative angle is small (the ''merge'').<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base of the perception software in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|First step: Expected point is far away from real LRF-point; splitting wall.<br />
File:Split_merge2.png|Second step: Expected point is closer to the real LRF-point, but not sufficiently close; splitting again.<br />
File:Split_merge3.png|Third step: Expected point coincides with the real LRF-point and the two points are sufficiently close; wall found.<br />
</gallery><br />
<br />
==== Corner recognition ====<br />
<br />
In corner recognition as used in the escaperoom competition, three types of corners are distinguished: Inside (shallow), outside (wide) and endpoint corners. The first two are defined as a shared endpoint of two walls, where the walls have a certain angle respectively to each other. An endpoint corner is defined as the end of a wall at which no other wall is detected (i.e. a jump in LRF-data is measured at the end of a wall). <br />
Also corner detection has proven to be very effective and has played a major role throughout the project. All different corners type are shown in the image below. These are <span style="color:green">inside corner</span>, <span style="color:red">outside corner</span>, <span style="color:orange">virtual "flat" corner</span> and <span style="color:grey">endpoint corners</span>.<br />
<br />
[[File:Cornerrecog2.png|100px|left|frame|All types of corners and doors.]]<br clear=all><br />
<br />
==== Door detection ====<br />
By clearly distinguishing types of corners, doors can be found by looking at specific combinations of corner types. Three types of doors are possible:<br />
*Door at the middle of a wall<br />
*Door in a corner<br />
*Door at end of hallway<br />
Depending on the point of view, these doors consist of different combinations of corner-types. For instance, the door at the middle of a wall can consist of two corners of type "outside" or one "outside" corner and one "endpoint" corner. Additional checks are used to confirm the door. The width must be within the expected margins and the relative angle with respect to adjacent walls.<br />
<br />
In the above figure it is already seen that a door in a corner is found and a door at the end of a hallway is found. Below you can see the example that a door is in the middle of a wall and that is is recognised while turning PICO<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|100px|Animation of the exit detection flow]]<br clear=all><br />
<br />
=== Escape Room - Testing ===<br />
In real life PICO behaves different than in the simulations. A couple of things needed testing in order to stay on track of the global planning of the project.<br />
The main goal of every test date is given together with it's result in the end.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
<b>Goal:</b> Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
<b>Result:</b> PICO moves in the correct direction, but the signal to the motors seems to be too low. <br />
Suspected problem: smooth acceleration, which is implemented to prevent slip and shocky movement, should be less smooth.<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
<b>Goal:</b> Test improved smooth acceleration profile. Also test some parameter tweaks such as the emergency distance.<br />
<br />
<b>Result:</b> Changed smooth acceleration profile helps a bit, but PICO still does not move to the desired location (moves less than expected). Suspected problem: PICO does not move by using odometry data. This should be implemented before the escaperoom challenge. UPDATE: movement on odometry data could not be implemented before the challenge day, because of the time. Therefore, a final check is implemented when PICO thinks it is in front of the door. Essentially, this contains an additional scan to find a door and a movements towards the desired location in front of the door.<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
<b>Goal:</b> Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
<br />
<b>Result:</b> Odometry still needs small tweaks, but the emergency stop works fine now. We don't take into account that there is an offset in the odometry frame, so a reset in this is needed.<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
[[File:Pico_EscapeRoom_Group4.gif]]<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge it is crucial to be able to localize accurately. With the RRT relying on the location of PICO on the map, the idea is to update the localization every time the robot needs to make a new path. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. If PICO may run into trouble of any kind, either the (dynamic) obstacle avoidance or the state machine compensates for this. In this case, the robot goes to a 're-planning' state, where it also updates the location again. In this way it is never a problem if the accuracy of the localization is a bit off. The procedure of elaborated below.<br />
<br />
==== Point matching ====<br />
PICO is localized as follows:<br />
<br />
Before the final challenge, in order for PICO to localize, the corners of the map are given the type 'outside' and 'inside' by hand. When the program is started, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
In an alternative localization procedure than described above, the door finding and cabinet finding algorithm can be used. This algorithm comes from the exit recognition that was used for the escaperoom challenge and worked very well. In the hospital challenge, doors are recognised in the same manner as the exit was detected in the escaperoom. Cabinets are defined as a set of corners with certain properties: corner distance and corner type. This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked much faster than the other localization algorithm, as hardly any calculation is required. However, this option is heavily based on the geometry of the starting area, and is therefore not very generic.<br />
<br />
Another alternative that is considered is the use of a particle filter for localization. This is a well known type of localization and some examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. Particle filters are not used in the design, because it would be much of an 'overkill', since the starting area is known and the rooms have enough points of recognition (think of distances and corner kinds etc). Therefore it is chosen to localize with an in our opinion more elegant algorithm where less computational effort is required.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the genericity. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. In each iteration of the RRT-algorithm a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similiar to the splitting algorithm used to find walls in LRF data. In the first step, the splitting algorithm tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
With the two improvements to the random tree path planner implemented, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, it consists of an array of points. An extra orientation is added to these points in order to let PICO orient itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanner2.gif|frame|left|300px|Pathplanner using a RRT algorithm with path optimizer.]]<br clear=all><br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and dead-lock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. It's primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows. First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
The image below on the left shows how the obstacle avoidance works in a simulation enviroment. PICO is only aware of the wall in front of him at the starting position and plans a path to a location 4 meters in front of him. He succesfully avoids all small obstacles in the adjoining room. The second image displays a test done on PICO. Again he is only aware of the first wall in front of him and succesfully avoids the obstacles on his path.<br />
<br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:dynobsavoid.gif |frame|Dynamic obstacle avoidance simulation.]]<br />
<br />
| [[File:dynobsavoid_mov.gif|frame|Dynamicd obstacle avoidance test.]]<br />
<br />
|}<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognition, also the missing of previously found obstacles must be detected. <br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visable will be defined as two separate obstacles. Next double defined obstacles (overlapping lines) are merged and obstacles that are recognized as walls are removed.<br />
<br />
The detection of double defined obstacles happens in three steps in which obstacles are seen as lines. First the relative angle between the lines is calculated. When two parallel lines are found the perpendicular distance from one line to the other is calculated. When this distance falls within the limits, a check is executed to see if the lines overlap. If also the third check is satisfied, a new obstacle is defined as the two endpoints of these lines that are the furthest appart (e.g. start point of line 1 and end point of line 2). The two initial obstacles are removed.<br />
<br />
The same checks are executed to filter any walls from the obstacles. Obstacles are compared to walls and when all three checks are satisfied for some wall the obstacle is removed.<br />
<br />
With the updated version of the map, the path planning is now able to replan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether they should be within vision range. It checks for all previously found obstacles, if the corners are visible. This is done by checking if a line between a corner and PICO is crossed by a line of data from the LRF scan. If not the obstacles should be visible. As this function is used before adding new obstacles, an obstacle in sight which is still in place will be added to the map again.<br />
<br />
This way paths that were obstructed before will be accessable by the robot again when the obstacles as well as wrongly detected obstacles are removed. The image below shows an example of how PICO is able to plan around an obstacle found. In this case a door which seems to be open in the map, is actually closed. PICO made a path from cabinet 2 to 0. When following the path an obstacle (the closed door) is detected, added to the map and planned a new route. As the localization at this point was not fully correct, the obstacle is placed on the map with a slight offset.<br />
<br />
[[File:staticobstacleavoid.gif|left|frame|250px|Static obstacle recognition and replanning.]]<br clear=all><br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality.<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
<b>Goal:</b><br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
<br />
<b>Result:</b><br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03), PICO Test 6 (2019-06-05) and PICO Test 7 (2019-06-11) ====<br />
These tests were mainly on testing a lot of small things and problems that occured while testing.<br />
<br />
<b>Goals:</b><br />
*Test the localization algorithm and the dynamic obstacle avoidance.<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
<b>Results:</b><br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Simulation ===<br />
<br />
To show how the final program works, a full simulation is done on the competition hospital map. During this simulation PICO is told to visit cabinets 0, 1 and 3. The complete program is used as described above. Note that the GIF is played at 1.7x speed with 5 FPS due to the limited available file size. A full video of this simulation can be found in [[:File:Group4_FinalChallengeSimulation.zip|ZIP attached]]. <br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:finalsim2.gif |frame|Hospital challenge simulation]]<br />
<br />
| [[File:finalviz2.gif|frame|Hospital challenge visualization]]<br />
<br />
|}<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. Within these two trials we had the chance to show our skills to a bigger audience and to the organization of the course. We were aware of the localization problem and hoped that we could show as much of our built functionality as possible.<br />
<br />
The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position.<br />
<br />
The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be too inaccurate to use in this hospital challenge. PICO stranded next to a door where he had to replan his route. Here PICO could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
[[File:Hospitalmovie.gif|frame|left|Group 4 hospital challenge.]]<br clear=all><br />
<br />
== Conclusion ==<br />
The Embedded Motion Control course of 2019 proved to be a challenging assignment but was received with lots of enthusiasm. It is not often you get a chance to just play around with a robot like this. Besides the requirements set by the course, additional goals were set by ourselves as deducted from the lectures accompanying the course. These included semantic knowledge of the environment, selective use of information, a world view as perceived by the robot and to avoid using a grids.<br />
<br />
=== Escape Room challenge ===<br />
The first requirement was already fulfilled to a large extend by class definition of walls, corners, doors and later cabinets. The split and merge algorithm allowed the recognition of these semantic concepts in the LRF data in an accurate yet efficient manner. Rather than mapping out the entire area, the algorithm looked for a door and next for the end of hallway, fulfilling the second and third goal by only making use of information needed to fulfill the task at hand and defining the door and end of hallway positions as seen by the robot. The effectiveness of these concepts was clearly visible during the escape room challenge as the door was found immediately as it entered PICO’s field of view. The task of the driving towards known target however was underestimated and PICO was unable to reach the exit.<br />
<br />
=== Hospital challenge ===<br />
For the hospital challenge, driving on odometry was successfully implemented and reinforced with a powerful ‘dynamic obstacle avoidance’. Speeds were adjusted when getting close to obstacles while adding repelling forces to PICO from any obstacles around it.<br />
<br />
The fourth goal mainly played a role when coming up with a path planning algorithm. The solution for grid-less path planning was found in a RRT algorithm, which was extended with a small bias to make it converge faster and our own split and merge algorithm to generate a smoother trajectory. The addition of static object detection and updating provided the option to find alternative routes in case the way was blocked, forming a strong combination with the path planning algorithm.<br />
The whole system was controlled by a strong and extensive finite state machine. Yet through the smart use of loops it remained relatively compact while at the same time adding to its robustness.<br />
<br />
The only weak point in the system was the localization, which was neither strong enough to always determine its location regardless of its position, nor had the ability to use priory acquired knowledge to update it. The localization was built keeping in mind the use of semantic concepts and to make PICO the center of the world, but this proved to be too hard for the time given. This caused us to fail the final competition.<br />
<br />
Due to the lack of proper localization, the competition has not shown the full potential of the result of this project. Yet we are convinced that there are some very powerful tools among the created software of which we would be happy to see them reappear in the upcoming years. Hence, in the end group 4 is happy with the progress that was made within the project. We thank the organization of this course for this opportunity and help with the assignment.<br />
<br />
== Recommendations ==<br />
The implementation of localization was unsuccessful in the project. The use of semantic concepts as recognizable features however had lots of potential, given more time to implement it. The algorithm would fail however when multiple rooms show the same features, in which case it could be combined with the option to have multiple hypothesis on its current location. Yet many good alternatives present themselves.<br />
<br />
Also a lot of wasted hours were spend on the endless conversion of coordinates from PICO’s view to the map and back, because they worked in different coordinate systems. Our recommendation would be to from the start convert these to work in the same system. This will not only save on computation time, but will mainly help understanding the systems and reduce the chance on errors.<br />
<br />
== Code ==<br />
The following snippets give a good representation of how the software for this project was structured, and how it did what it was supposed to do.<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/144 Overall functionality]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/148 State changes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/147 Effect of state on functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/145 Methods in classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/146 Dynamic obstacle avoidance]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/149 Velocity planning]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/150 Complex classes]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/151 Functions within functions]<br />
*[https://gitlab.tue.nl/EMC2019/group4/snippets/152 Splitting of the RRT path]<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 10 (2019-06-12)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190620.pdf#filelinks Meeting 11 (2019-06-20)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78973Embedded Motion Control 2019 Group 42019-06-20T14:06:46Z<p>S149491: /* Minutes */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019. The course Embedded Motion Control is about software design and implementation into autonomous robots. Application of the acquired knowledge is done to real-life robotics tasks and tested with robot PICO.<br />
<br />
During lectures it is explained that the point of view of the robot is essential. Semantic knowledge of the environment is essential. Which information is needed at which moment, and when are things less important in terms of computational power.<br />
<br />
The statement above of the needed information at which moment is the main focus of our project. For example, planning is not important if you already know where you have to go and if you are not moving you do not have to avoid walls. Because of this, it is chosen to change the location of the map towards the location of PICO and not the other way around. PICO is the center of reasoning of all parts of the program.<br />
This year’s challenge is to move through a Hospital in order to visit a number of cabinets. The approach and solutions that are found are explained in the upcoming sections.<br />
<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the execution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
For the escaperoom challenge a specific strategy is determined. After initialization, PICO starts rotating and simultaneously scanning the room to find the door. In case no door is found after a full rotation, PICO determines the far-most corner and moves in this direction with half the distance measured. After this, PICO repeats this sequence. In case a door is found, PICO moves to a position 50cm in front of the door and faces the exit. A second scan verifies the location of PICO with respect to the door and corrects its position if necessary. After this, the end of the hallway is determined and PICO moves towards this point. After the goal is reached, PICO says it has reached its goal and shuts down. A schematic representation of the strategy is given below. <br />
<br />
[[File:Strategy_escaperoom2.jpg|800px]]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO starts looking for a door, the LRF data is first preprocessed into walls by a ''split and merge'' algorithm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visible door is determined.<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First, for every measured point the location in cartesian coordinates is calculated, using PICO as the center point. After this, PICO takes the leftmost and rightmost LRF-measurements and formulates the hypothesis that they are two points on a single wall. Then, the two points are used to calculate the expected middle point. Consequently, this point is compared to the real LRF-data measurement in the middle of the two points. Two checks are executed to verify the wall:<br />
<br />
* The absolute distance between the expected point and real point is sufficiently small<br />
* The length of the wall does not exceed the size of a door, to ensure no doors are overlooked <br />
<br />
On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdivided into walls, or splitting is no longer possible because a wall consists of only two points. Remaining is a large number of small wall sections, some of which actually belong together. Wall sections are merged they share an endpoint and their relative angle is small (the ''merge'').<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base of the perception software in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|First step: Expected point is far away from real LRF-point; splitting wall.<br />
File:Split_merge2.png|Second step: Expected point is closer to the real LRF-point, but not sufficiently close; splitting again.<br />
File:Split_merge3.png|Third step: Expected point coincides with the real LRF-point and the two points are sufficiently close; wall found.<br />
</gallery><br />
<br />
==== Corner recognition ====<br />
In corner recognition as used in the escaperoom competition, three types of corners are distinguished: Inside (shallow), outside (wide) and endpoint corners. The first two are defined as a shared endpoint of two walls, where the walls have a certain angle respectively to each other. An endpoint corner is defined as the end of a wall at which no other wall is detected (i.e. a jump in LRF-data is measured at the end of a wall). <br />
Also corner detection has proven to be very effective and has played a major role throughout the project.<br />
<br />
SCREENSHOT OR GIF WITH DIFFERENT TYPES OF CORNERS (INSIDE+OUTSIDE+ENDPOINT)<br />
<br />
==== Door detection ====<br />
By clearly distinguishing types of corners, doors can be found by looking at specific combinations of corner types. Three types of doors are possible:<br />
*Door at the middle of a wall<br />
*Door in a corner<br />
*Door at end of hallway<br />
Depending on the point of view, these doors consist of different combinations of corner-types. For instance, the door at the middle of a wall can consist of two corners of type "outside" or one "outside" corner and one "endpoint" corner. Different situations are shown below. <br />
<br />
SCREENSHOTS OR GIFS WITH:<br />
DOOR AT SIDE OF ROOM FROM DIFFERENT POINTS OF VIEW<br />
DOOR AT MIDDLE OF ROOM FROM DIFFERENT POINTS OF VIEW<br />
<br />
Additional checks are used to confirm the door. The width must be within the expected margins and the relative angle with respect to adjacent walls.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|100px|Animation of the exit detection flow]]<br clear=all><br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
PICO moves in the correct direction, but the signal to the motors seems to be too low. Suspected problem: smooth acceleration, which is implemented to prevent slip and shocky movement, should be less smooth.<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Test improved smooth acceleration profile. Also test some parameter tweaks.<br />
<br />
===== Result =====<br />
Changed smooth acceleration profile helps a bit, but PICO still does not move to the desired location (moves less than expected). Suspected problem: PICO does not move by using odometry data. This should be implemented before the escaperoom challenge. UPDATE: movement on odometry data could not be implemented before the challenge day, because of the time. Therefore, a final check is implemented when PICO thinks it is in front of the door. Essentially, this contains an additional scan to find a door and a movements towards the desired location in front of the door.<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
First of all the cabinet and door recognition. This strategy comes from the exit recognition that was used for the escape room challenge. Doors are recognised with the same exit strategy als the exits are found in the escape room. Cabinets are defined by a set of corners within a certain region of each other, combined with the kind of corner ('inside' or 'outside'). This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked as good as the other localization algorithm which is given above.<br />
<br />
We also looked at a particle filter for localization. This is a well known type of localization and a couple of examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. It was thought that this way was overkill for this challenge, because the starting area was known and the rooms have enough points of recognition (think of distances and corner kinds etc) to localize in other ways with less computational effort.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and dead-lock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. It's primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognition, also the missing of previously found obstacles must be detected. <br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visable will be defined as two separate obstacles. Next double defined obstacles (overlapping lines) are merged and obstacles that are recognized as walls are removed.<br />
<br />
The detection of double defined obstacles happens in three steps in which obstacles are seen as lines. First the relative angle between the lines is calculated. When two parallel lines are found the perpendicular distance from one line to the other is calculated. When this distance falls within the limits, a check is executed to see if the lines overlap. If also the third check is satisfied, a new obstacle is defined as the two endpoints of these lines that are the furthest appart (e.g. start point of line 1 and end point of line 2). The two initial obstacles are removed.<br />
<br />
The same checks are executed to filter any walls from the obstacles. Obstacles are compared to walls and when all three checks are satisfied for some wall the obstacle is removed.<br />
<br />
With the updated version of the map, the path planning is now able to replan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether they should be within vision range. It checks this by searching for walls, cabinets or other obstacles that are in between PICO and the currently looked at obstacle. If there are none, the distance of the obstacle is compared to the distance measured in the LRF data. If the LRF data vastly exceeds the distance to the obstacle, the obstacle is removed.<br />
<br />
This way paths that were obstructed before will be accessable by the robot again when the obstacles as well as wrongly detected obstacles are removed.<br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
===== Result =====<br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
Test the localization algorithm and the dynamic obstacle avoidance.<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
The following points should be tested in this attempt:<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
===== Result =====<br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Simulation ===<br />
<br />
To show how the final program works, a full simulation is done on the competition hospital map. During this simulation PICO is told to visit cabinets 0, 1 and 3. The complete program is used as described above. Note that the GIF is played at 1.7x speed with 5 FPS due to the limited available file size. A full video of this simulation can be found in [[:File:Group4_FinalChallengeSimulation.zip|ZIP attached]]. <br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:finalChallenge_reduced.gif |660px|Hospital challenge simulation]]<br />
<br />
| [[File:finalChallenge_vizReduced.gif|600px|Hospital challenge visualization]]<br />
<br />
|}<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. Within these two trials we had the chance to show our skills to a bigger audience and to the organization of the course. We were aware of the localization problem and hoped that we could show as much of our built functionality as possible.<br />
<br />
The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position. <br />
<br />
The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be too inaccurate to use in this hospital challenge. PICO stranded next to a door where he could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
== Conclusion ==<br />
The Embedded Motion Control course of 2019 was a challenging assignment with a couple of difficulties to solve. The <br />
localization, and path planning were the most difficult to solve.<br />
<br />
The solutions that are found for the path planning (the RRT) worked out perfectly.<br />
<br />
In the end, group 4 is happy with the progress that was made within the project. Unfortunately the final challenge didn't represent the results that came forward. <br />
<br />
We thank the organization of this course for this opportunity and help with the assignment.<br />
<br />
== Code ==<br />
Snippets suggested by Bram:<br />
*Main to show loop around the different sections of the code<br />
*A couple of classes how we defined e.a. doors/walls etc<br />
*Perception?<br />
*Methods in LRFData or OdomData, used for updating and resetting<br />
*Obstacle avoidance function ''avoid()''<br />
*Example of FSM implementation, such as control.cpp lines 20-26<br />
*Implementation of ''trajectory()'', ''avoid()'', ''slow()'', in control.cpp lines 57-68<br />
*Functionality of monitor.cpp, like lines 75-80<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 10 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78968Embedded Motion Control 2019 Group 42019-06-20T14:02:55Z<p>S149491: /* Hospital Challenge - Competition */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019. The course Embedded Motion Control is about software design and implementation into autonomous robots. Application of the acquired knowledge is done to real-life robotics tasks and tested with robot PICO.<br />
<br />
During lectures it is explained that the point of view of the robot is essential. Semantic knowledge of the environment is essential. Which information is needed at which moment, and when are things less important in terms of computational power.<br />
<br />
The statement above of the needed information at which moment is the main focus of our project. For example, planning is not important if you already know where you have to go and if you are not moving you do not have to avoid walls. Because of this, it is chosen to change the location of the map towards the location of PICO and not the other way around. PICO is the center of reasoning of all parts of the program.<br />
This year’s challenge is to move through a Hospital in order to visit a number of cabinets. The approach and solutions that are found are explained in the upcoming sections.<br />
<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the execution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
For the escaperoom challenge a specific strategy is determined. After initialization, PICO starts rotating and simultaneously scanning the room to find the door. In case no door is found after a full rotation, PICO determines the far-most corner and moves in this direction with half the distance measured. After this, PICO repeats this sequence. In case a door is found, PICO moves to a position 50cm in front of the door and faces the exit. A second scan verifies the location of PICO with respect to the door and corrects its position if necessary. After this, the end of the hallway is determined and PICO moves towards this point. After the goal is reached, PICO says it has reached its goal and shuts down. A schematic representation of the strategy is given below. <br />
<br />
[[File:Strategy_escaperoom2.jpg|800px]]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO starts looking for a door, the LRF data is first preprocessed into walls by a ''split and merge'' algorithm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visible door is determined.<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First, for every measured point the location in cartesian coordinates is calculated, using PICO as the center point. After this, PICO takes the leftmost and rightmost LRF-measurements and formulates the hypothesis that they are two points on a single wall. Then, the two points are used to calculate the expected middle point. Consequently, this point is compared to the real LRF-data measurement in the middle of the two points. Two checks are executed to verify the wall:<br />
<br />
* The absolute distance between the expected point and real point is sufficiently small<br />
* The length of the wall does not exceed the size of a door, to ensure no doors are overlooked <br />
<br />
On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdivided into walls, or splitting is no longer possible because a wall consists of only two points. Remaining is a large number of small wall sections, some of which actually belong together. Wall sections are merged they share an endpoint and their relative angle is small (the ''merge'').<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base of the perception software in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|First step: Expected point is far away from real LRF-point; splitting wall.<br />
File:Split_merge2.png|Second step: Expected point is closer to the real LRF-point, but not sufficiently close; splitting again.<br />
File:Split_merge3.png|Third step: Expected point coincides with the real LRF-point and the two points are sufficiently close; wall found.<br />
</gallery><br />
<br />
==== Corner recognition ====<br />
In corner recognition as used in the escaperoom competition, three types of corners are distinguished: Inside (shallow), outside (wide) and endpoint corners. The first two are defined as a shared endpoint of two walls, where the walls have a certain angle respectively to each other. An endpoint corner is defined as the end of a wall at which no other wall is detected (i.e. a jump in LRF-data is measured at the end of a wall). <br />
Also corner detection has proven to be very effective and has played a major role throughout the project.<br />
<br />
SCREENSHOT OR GIF WITH DIFFERENT TYPES OF CORNERS (INSIDE+OUTSIDE+ENDPOINT)<br />
<br />
==== Door detection ====<br />
By clearly distinguishing types of corners, doors can be found by looking at specific combinations of corner types. Three types of doors are possible:<br />
*Door at the middle of a wall<br />
*Door in a corner<br />
*Door at end of hallway<br />
Depending on the point of view, these doors consist of different combinations of corner-types. For instance, the door at the middle of a wall can consist of two corners of type "outside" or one "outside" corner and one "endpoint" corner. Different situations are shown below. <br />
<br />
SCREENSHOTS OR GIFS WITH:<br />
DOOR AT SIDE OF ROOM FROM DIFFERENT POINTS OF VIEW<br />
DOOR AT MIDDLE OF ROOM FROM DIFFERENT POINTS OF VIEW<br />
<br />
Additional checks are used to confirm the door. The width must be within the expected margins and the relative angle with respect to adjacent walls.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|100px|Animation of the exit detection flow]]<br clear=all><br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
PICO moves in the correct direction, but the signal to the motors seems to be too low. Suspected problem: smooth acceleration, which is implemented to prevent slip and shocky movement, should be less smooth.<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Test improved smooth acceleration profile. Also test some parameter tweaks.<br />
<br />
===== Result =====<br />
Changed smooth acceleration profile helps a bit, but PICO still does not move to the desired location (moves less than expected). Suspected problem: PICO does not move by using odometry data. This should be implemented before the escaperoom challenge. UPDATE: movement on odometry data could not be implemented before the challenge day, because of the time. Therefore, a final check is implemented when PICO thinks it is in front of the door. Essentially, this contains an additional scan to find a door and a movements towards the desired location in front of the door.<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
First of all the cabinet and door recognition. This strategy comes from the exit recognition that was used for the escape room challenge. Doors are recognised with the same exit strategy als the exits are found in the escape room. Cabinets are defined by a set of corners within a certain region of each other, combined with the kind of corner ('inside' or 'outside'). This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked as good as the other localization algorithm which is given above.<br />
<br />
We also looked at a particle filter for localization. This is a well known type of localization and a couple of examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. It was thought that this way was overkill for this challenge, because the starting area was known and the rooms have enough points of recognition (think of distances and corner kinds etc) to localize in other ways with less computational effort.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and dead-lock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. It's primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognition, also the missing of previously found obstacles must be detected. <br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visable will be defined as two separate obstacles. Next double defined obstacles (overlapping lines) are merged and obstacles that are recognized as walls are removed.<br />
<br />
The detection of double defined obstacles happens in three steps in which obstacles are seen as lines. First the relative angle between the lines is calculated. When two parallel lines are found the perpendicular distance from one line to the other is calculated. When this distance falls within the limits, a check is executed to see if the lines overlap. If also the third check is satisfied, a new obstacle is defined as the two endpoints of these lines that are the furthest appart (e.g. start point of line 1 and end point of line 2). The two initial obstacles are removed.<br />
<br />
The same checks are executed to filter any walls from the obstacles. Obstacles are compared to walls and when all three checks are satisfied for some wall the obstacle is removed.<br />
<br />
With the updated version of the map, the path planning is now able to replan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether they should be within vision range. It checks this by searching for walls, cabinets or other obstacles that are in between PICO and the currently looked at obstacle. If there are none, the distance of the obstacle is compared to the distance measured in the LRF data. If the LRF data vastly exceeds the distance to the obstacle, the obstacle is removed.<br />
<br />
This way paths that were obstructed before will be accessable by the robot again when the obstacles as well as wrongly detected obstacles are removed.<br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
===== Result =====<br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
Test the localization algorithm and the dynamic obstacle avoidance.<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
The following points should be tested in this attempt:<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
===== Result =====<br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Simulation ===<br />
<br />
To show how the final program works, a full simulation is done on the competition hospital map. During this simulation PICO is told to visit cabinets 0, 1 and 3. The complete program is used as described above. Note that the GIF is played at 1.7x speed with 5 FPS due to the limited available file size. A full video of this simulation can be found in [[:File:Group4_FinalChallengeSimulation.zip|ZIP attached]]. <br />
<br />
{|style="margin: 0 auto;"<br />
<br />
| [[File:finalChallenge_reduced.gif |660px|Hospital challenge simulation]]<br />
<br />
| [[File:finalChallenge_vizReduced.gif|600px|Hospital challenge visualization]]<br />
<br />
|}<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. Within these two trials we had the chance to show our skills to a bigger audience and to the organization of the course. We were aware of the localization problem and hoped that we could show as much of our built functionality as possible.<br />
<br />
The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position. <br />
<br />
The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be too inaccurate to use in this hospital challenge. PICO stranded next to a door where he could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
== Conclusion ==<br />
The Embedded Motion Control course of 2019 was a challenging assignment with a couple of difficulties to solve. The <br />
localization, and path planning were the most difficult to solve.<br />
<br />
The solutions that are found for the path planning (the RRT) worked out perfectly.<br />
<br />
In the end, group 4 is happy with the progress that was made within the project. Unfortunately the final challenge didn't represent the results that came forward. <br />
<br />
We thank the organization of this course for this opportunity and help with the assignment.<br />
<br />
== Code ==<br />
Snippets suggested by Bram:<br />
*Main to show loop around the different sections of the code<br />
*A couple of classes how we defined e.a. doors/walls etc<br />
*Methods in LRFData or OdomData, used for updating and resetting<br />
*Obstacle avoidance function ''avoid()''<br />
*Example of FSM implementation, such as control.cpp lines 20-26<br />
*Implementation of ''trajectory()'', ''avoid()'', ''slow()'', in control.cpp lines 57-68<br />
*Functionality of monitor.cpp, like lines 75-80<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 9 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78743Embedded Motion Control 2019 Group 42019-06-20T10:14:00Z<p>S149491: /* Door detection */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the excecution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
The initial strategy that is formulated is as follows:<br />
<br />
[[File:Strategy_escaperoom.png|400px]]<br />
<br />
This plan is updated to gain more insights and control over the different situations that can happen.<br />
<br />
[PLAATJE]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO ... the LRF data is first preprocessed into walls by a ''split and merge'' algorihtm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visable door is determined.<br />
<br />
DON'T EDIT, I'M WORKING ON THIS :D<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First for every measured point the location in carthesian coordinates is calculated, using PICO as the center point. Next the algorithm tries to fit a single wall through the entire LRF data. Two checks are executed to verify the wall. First the position of the middle point of the wall is matched with the position of the middle point in the LRF data. Secondly the lenght of the wall may not exceed the size of a door, to ensure no doors are accidentally closed. On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdiveded into walls, or splitting is no longer possible because a wall consists of only two points.<br />
<br />
Because the split is executed at the middle point of each assumed wall, it is unlikely to split walls on corners only. Hence, remaining is a large number of small wall sections, some of which actually belong together. Two wall sections are merged they share an endpoint and their relative angle is small.<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base the entire software is build upon also in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|Example first step<br />
File:Split_merge2.png|Example second step<br />
File:Split_merge3.png|Example third step<br />
</gallery><br />
<br />
==== Corner recognition ====<br />
In corner recognition as used in the escaperoom competition, three types of corners are distinguished: Inside (shallow), outside (wide) and endpoint corners. The first two are defined as a shared endpoint of two walls, where the walls have a certain angle respectively to each other. An endpoint corner is defined as the closest of two consequtive LRF points, between which a large difference in range is measured, hence they can not be part of the same wall. The distinction in points enables the distiction between room corners, door corners and end of hallway corners.<br />
<br />
Also corner detection has proven to be very effective and also has played a large role until the end of the project.<br />
<br />
==== Door detection ====<br />
With the distiction in corners, door can consist of various combinations of corners. The recognition of the most commonly found door is visualised below. This door is recognized by two outside corners. Additional checks are executed to confirm the door length falls within the margins and the door itself is an extension of a wall. A door can also consist of an outside and an endpoint corner when seen slightly more from an angle, or two endpoint corners making it an end-of-hallway door.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|300px|Animation of the exit detection flow]]<br clear=all><br />
<br />
A different type of door however occurs when a wall is placed on some distance, perpendicular to another wall (see figure). In this case there is only one corner from which the door can be recognized.<br />
[PROBABLY NEEDS FIGURE, OR EVEN GIF TO PROVE IT WORKS]<br />
<br />
At last, the center point of the exit is calculated together with a point in front of this center point. This point in front is sent to the movement part of the PICO.<br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Use a more advanced algorithm to detect and move.<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
First of all the cabinet and door recognition. This strategy comes from the exit recognition that was used for the escape room challenge. Doors are recognised with the same exit strategy als the exits are found in the escape room. Cabinets are defined by a set of corners within a certain region of each other, combined with the kind of corner ('inside' or 'outside'). This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked as good as the other localization algorithm which is given above.<br />
<br />
We also looked at a particle filter for localization. This is a well known type of localization and a couple of examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. It was thought that this way was overkill for this challenge, because the starting area was known and the rooms have enough points of recognition (think of distances and corner kinds etc) to localize in other ways with less computational effort.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and dead-lock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. It's primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognition, also the missing of previously found obstacles must be detected. <br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visable will be defined as two separate obstacles. Next double defined obstacles (overlapping lines) are merged and obstacles that are recognized as walls are removed.<br />
<br />
The detection of double defined obstacles happens in three steps in which obstacles are seen as lines. First the relative angle between the lines is calculated. When two parallel lines are found the perpendicular distance from one line to the other is calculated. When this distance falls within the limits, a check is executed to see if the lines overlap. If also the third check is satisfied, a new obstacle is defined as the two endpoints of these lines that are the furthest appart (e.g. start point of line 1 and end point of line 2). The two initial obstacles are removed.<br />
<br />
The same checks are executed to filter any walls from the obstacles. Obstacles are compared to walls and when all three checks are satisfied for some wall the obstacle is removed.<br />
<br />
With the updated version of the map, the path planning is now able to replan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether they should be within vision range. It checks this by searching for walls, cabinets or other obstacles that are in between PICO and the currently looked at obstacle. If there are none, the distance of the obstacle is compared to the distance measured in the LRF data. If the LRF data vastly exceeds the distance to the obstacle, the obstacle is removed.<br />
<br />
This way paths that were obstructed before will be accessable by the robot again when the obstacles as well as wrongly detected obstacles are removed.<br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
===== Result =====<br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
Test the localization algorithm and the dynamic obstacle avoidance.<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
The following points should be tested in this attempt:<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
===== Result =====<br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position. The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be to inaccurate to use in this hospital challenge. PICO stranded next to a door where he could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
== Conclusion ==<br />
<br />
== Code ==<br />
Snippets suggested by Bram:<br />
*Methods in LRFData or OdomData, used for updating and resetting<br />
*Obstacle avoidance function ''avoid()''<br />
*Example of FSM implementation, such as control.cpp lines 20-26<br />
*Implementation of ''trajectory()'', ''avoid()'', ''slow()'', in control.cpp lines 57-68<br />
*Functionality of monitor.cpp, like lines 75-80<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 9 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78739Embedded Motion Control 2019 Group 42019-06-20T10:04:30Z<p>S149491: /* Corner recognition */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the excecution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
The initial strategy that is formulated is as follows:<br />
<br />
[[File:Strategy_escaperoom.png|400px]]<br />
<br />
This plan is updated to gain more insights and control over the different situations that can happen.<br />
<br />
[PLAATJE]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO ... the LRF data is first preprocessed into walls by a ''split and merge'' algorihtm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visable door is determined.<br />
<br />
DON'T EDIT, I'M WORKING ON THIS :D<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First for every measured point the location in carthesian coordinates is calculated, using PICO as the center point. Next the algorithm tries to fit a single wall through the entire LRF data. Two checks are executed to verify the wall. First the position of the middle point of the wall is matched with the position of the middle point in the LRF data. Secondly the lenght of the wall may not exceed the size of a door, to ensure no doors are accidentally closed. On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdiveded into walls, or splitting is no longer possible because a wall consists of only two points.<br />
<br />
Because the split is executed at the middle point of each assumed wall, it is unlikely to split walls on corners only. Hence, remaining is a large number of small wall sections, some of which actually belong together. Two wall sections are merged they share an endpoint and their relative angle is small.<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base the entire software is build upon also in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|Example first step<br />
File:Split_merge2.png|Example second step<br />
File:Split_merge3.png|Example third step<br />
</gallery><br />
<br />
==== Corner recognition ====<br />
In corner recognition as used in the escaperoom competition, three types of corners are distinguished: Inside (shallow), outside (wide) and endpoint corners. The first two are defined as a shared endpoint of two walls, where the walls have a certain angle respectively to each other. An endpoint corner is defined as the closest of two consequtive LRF points, between which a large difference in range is measured, hence they can not be part of the same wall. The distinction in points enables the distiction between room corners, door corners and end of hallway corners.<br />
<br />
Also corner detection has proven to be very effective and also has played a large role until the end of the project.<br />
<br />
==== Door detection ====<br />
With the distiction in corners, also various 'types' of doors can be destinguished. The most commonly found door is <br />
<br />
Then the corners are recognized. The 2 different kind of corners are recognized and from the right kind of corners the exit is generated. This is visualised below.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|300px|Animation of the exit detection flow]]<br clear=all><br />
<br />
At last, the center point of the exit is calculated together with a point in front of this center point. This point in front is sent to the movement part of the PICO.<br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Use a more advanced algorithm to detect and move.<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
First of all the cabinet and door recognition. This strategy comes from the exit recognition that was used for the escape room challenge. Doors are recognised with the same exit strategy als the exits are found in the escape room. Cabinets are defined by a set of corners within a certain region of each other, combined with the kind of corner ('inside' or 'outside'). This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked as good as the other localization algorithm which is given above.<br />
<br />
We also looked at a particle filter for localization. This is a well known type of localization and a couple of examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. It was thought that this way was overkill for this challenge, because the starting area was known and the rooms have enough points of recognition (think of distances and corner kinds etc) to localize in other ways with less computational effort.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and dead-lock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. It's primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognition, also the missing of previously found obstacles must be detected. <br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visable will be defined as two separate obstacles. Next double defined obstacles (overlapping lines) are merged and obstacles that are recognized as walls are removed.<br />
<br />
The detection of double defined obstacles happens in three steps in which obstacles are seen as lines. First the relative angle between the lines is calculated. When two parallel lines are found the perpendicular distance from one line to the other is calculated. When this distance falls within the limits, a check is executed to see if the lines overlap. If also the third check is satisfied, a new obstacle is defined as the two endpoints of these lines that are the furthest appart (e.g. start point of line 1 and end point of line 2). The two initial obstacles are removed.<br />
<br />
The same checks are executed to filter any walls from the obstacles. Obstacles are compared to walls and when all three checks are satisfied for some wall the obstacle is removed.<br />
<br />
With the updated version of the map, the path planning is now able to replan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether they should be within vision range. It checks this by searching for walls, cabinets or other obstacles that are in between PICO and the currently looked at obstacle. If there are none, the distance of the obstacle is compared to the distance measured in the LRF data. If the LRF data vastly exceeds the distance to the obstacle, the obstacle is removed.<br />
<br />
This way paths that were obstructed before will be accessable by the robot again when the obstacles as well as wrongly detected obstacles are removed.<br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
===== Result =====<br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
Test the localization algorithm and the dynamic obstacle avoidance.<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
The following points should be tested in this attempt:<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
===== Result =====<br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position. The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be to inaccurate to use in this hospital challenge. PICO stranded next to a door where he could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
== Conclusion ==<br />
<br />
== Code ==<br />
Snippets suggested by Bram:<br />
*Methods in LRFData or OdomData, used for updating and resetting<br />
*Obstacle avoidance function ''avoid()''<br />
*Example of FSM implementation, such as control.cpp lines 20-26<br />
*Implementation of ''trajectory()'', ''avoid()'', ''slow()'', in control.cpp lines 57-68<br />
*Functionality of monitor.cpp, like lines 75-80<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 9 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78725Embedded Motion Control 2019 Group 42019-06-20T09:51:39Z<p>S149491: /* Split and merge method */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the excecution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
The initial strategy that is formulated is as follows:<br />
<br />
[[File:Strategy_escaperoom.png|400px]]<br />
<br />
This plan is updated to gain more insights and control over the different situations that can happen.<br />
<br />
[PLAATJE]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO ... the LRF data is first preprocessed into walls by a ''split and merge'' algorihtm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visable door is determined.<br />
<br />
DON'T EDIT, I'M WORKING ON THIS :D<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First for every measured point the location in carthesian coordinates is calculated, using PICO as the center point. Next the algorithm tries to fit a single wall through the entire LRF data. Two checks are executed to verify the wall. First the position of the middle point of the wall is matched with the position of the middle point in the LRF data. Secondly the lenght of the wall may not exceed the size of a door, to ensure no doors are accidentally closed. On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdiveded into walls, or splitting is no longer possible because a wall consists of only two points.<br />
<br />
Because the split is executed at the middle point of each assumed wall, it is unlikely to split walls on corners only. Hence, remaining is a large number of small wall sections, some of which actually belong together. Two wall sections are merged they share an endpoint and their relative angle is small.<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base the entire software is build upon also in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|Example first step<br />
File:Split_merge2.png|Example second step<br />
File:Split_merge3.png|Example third step<br />
</gallery><br />
<br />
==== Corner recognition ====<br />
<br />
Then the corners are recognized. The 2 different kind of corners are recognized and from the right kind of corners the exit is generated. This is visualised below.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|300px|Animation of the exit detection flow]]<br clear=all><br />
<br />
At last, the center point of the exit is calculated together with a point in front of this center point. This point in front is sent to the movement part of the PICO.<br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Use a more advanced algorithm to detect and move.<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
First of all the cabinet and door recognition. This strategy comes from the exit recognition that was used for the escape room challenge. Doors are recognised with the same exit strategy als the exits are found in the escape room. Cabinets are defined by a set of corners within a certain region of each other, combined with the kind of corner ('inside' or 'outside'). This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked as good as the other localization algorithm which is given above.<br />
<br />
We also looked at a particle filter for localization. This is a well known type of localization and a couple of examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. It was thought that this way was overkill for this challenge, because the starting area was known and the rooms have enough points of recognition (think of distances and corner kinds etc) to localize in other ways with less computational effort.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and dead-lock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. It's primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognition, also the missing of previously found obstacles must be detected. <br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visable will be defined as two separate obstacles. Next double defined obstacles (overlapping lines) are merged and obstacles that are recognized as walls are removed.<br />
<br />
The detection of double defined obstacles happens in three steps in which obstacles are seen as lines. First the relative angle between the lines is calculated. When two parallel lines are found the perpendicular distance from one line to the other is calculated. When this distance falls within the limits, a check is executed to see if the lines overlap. If also the third check is satisfied, a new obstacle is defined as the two endpoints of these lines that are the furthest appart (e.g. start point of line 1 and end point of line 2). The two initial obstacles are removed.<br />
<br />
The same checks are executed to filter any walls from the obstacles. Obstacles are compared to walls and when all three checks are satisfied for some wall the obstacle is removed.<br />
<br />
With the updated version of the map, the path planning is now able to replan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether they should be within vision range. It checks this by searching for walls, cabinets or other obstacles that are in between PICO and the currently looked at obstacle. If there are none, the distance of the obstacle is compared to the distance measured in the LRF data. If the LRF data vastly exceeds the distance to the obstacle, the obstacle is removed.<br />
<br />
This way paths that were obstructed before will be accessable by the robot again when the obstacles as well as wrongly detected obstacles are removed.<br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
===== Result =====<br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
Test the localization algorithm and the dynamic obstacle avoidance.<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
The following points should be tested in this attempt:<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
===== Result =====<br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position. The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be to inaccurate to use in this hospital challenge. PICO stranded next to a door where he could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
== Conclusion ==<br />
<br />
== Code ==<br />
Snippets suggested by Bram:<br />
*Methods in LRFData or OdomData, used for updating and resetting<br />
*Obstacle avoidance function ''avoid()''<br />
*Example of FSM implementation, such as control.cpp lines 20-26<br />
*Implementation of ''trajectory()'', ''avoid()'', ''slow()'', in control.cpp lines 57-68<br />
*Functionality of monitor.cpp, like lines 75-80<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 9 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78723Embedded Motion Control 2019 Group 42019-06-20T09:50:52Z<p>S149491: /* Split and merge method */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the excecution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
The initial strategy that is formulated is as follows:<br />
<br />
[[File:Strategy_escaperoom.png|400px]]<br />
<br />
This plan is updated to gain more insights and control over the different situations that can happen.<br />
<br />
[PLAATJE]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO ... the LRF data is first preprocessed into walls by a ''split and merge'' algorihtm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visable door is determined.<br />
<br />
DON'T EDIT, I'M WORKING ON THIS :D<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First for every measured point the location in carthesian coordinates is calculated, using PICO as the center point. Next the algorithm tries to fit a single wall through the entire LRF data. Two checks are executed to verify the wall. First the position of the middle point of the wall is matched with the position of the middle point in the LRF data. Secondly the lenght of the wall may not exceed the size of a door, to ensure no doors are accidentally closed. On a double succes the wall is confirmed. On a fail the wall is split into two separate walls on this middle point (the ''split''). The process is then repeated on these two walls until all points are subdiveded into walls, or splitting is no longer possible because a wall consists of only two points.<br />
<br />
Because the split is executed at the middle point of each assumed wall, it is unlikely to split walls on corners only. Hence, remaining is a large number of small wall sections, some of which actually belong together. Two wall sections are merged they share an endpoint and their relative angle is small.<br />
<br />
The ''split and merge'' algorithm has proven to be very effective and has continued to be the base the entire software is build upon also in the Hospital challenge.<br />
<br />
<gallery><br />
File:Split_merge1.png|Example first step<br />
File:Split_merge2.png|Example second step<br />
File:Split_merge3.png|Example third step<br />
</gallery><br />
<br />
Then the corners are recognized. The 2 different kind of corners are recognized and from the right kind of corners the exit is generated. This is visualised below.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|300px|Animation of the exit detection flow]]<br clear=all><br />
<br />
At last, the center point of the exit is calculated together with a point in front of this center point. This point in front is sent to the movement part of the PICO.<br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Use a more advanced algorithm to detect and move.<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
First of all the cabinet and door recognition. This strategy comes from the exit recognition that was used for the escape room challenge. Doors are recognised with the same exit strategy als the exits are found in the escape room. Cabinets are defined by a set of corners within a certain region of each other, combined with the kind of corner ('inside' or 'outside'). This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked as good as the other localization algorithm which is given above.<br />
<br />
We also looked at a particle filter for localization. This is a well known type of localization and a couple of examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. It was thought that this way was overkill for this challenge, because the starting area was known and the rooms have enough points of recognition (think of distances and corner kinds etc) to localize in other ways with less computational effort.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and dead-lock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. It's primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognition, also the missing of previously found obstacles must be detected. <br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visable will be defined as two separate obstacles. Next double defined obstacles (overlapping lines) are merged and obstacles that are recognized as walls are removed.<br />
<br />
The detection of double defined obstacles happens in three steps in which obstacles are seen as lines. First the relative angle between the lines is calculated. When two parallel lines are found the perpendicular distance from one line to the other is calculated. When this distance falls within the limits, a check is executed to see if the lines overlap. If also the third check is satisfied, a new obstacle is defined as the two endpoints of these lines that are the furthest appart (e.g. start point of line 1 and end point of line 2). The two initial obstacles are removed.<br />
<br />
The same checks are executed to filter any walls from the obstacles. Obstacles are compared to walls and when all three checks are satisfied for some wall the obstacle is removed.<br />
<br />
With the updated version of the map, the path planning is now able to replan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether they should be within vision range. It checks this by searching for walls, cabinets or other obstacles that are in between PICO and the currently looked at obstacle. If there are none, the distance of the obstacle is compared to the distance measured in the LRF data. If the LRF data vastly exceeds the distance to the obstacle, the obstacle is removed.<br />
<br />
This way paths that were obstructed before will be accessable by the robot again when the obstacles as well as wrongly detected obstacles are removed.<br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
===== Result =====<br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
Test the localization algorithm and the dynamic obstacle avoidance.<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
The following points should be tested in this attempt:<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
===== Result =====<br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position. The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be to inaccurate to use in this hospital challenge. PICO stranded next to a door where he could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
== Conclusion ==<br />
<br />
== Code ==<br />
Snippets suggested by Bram:<br />
*Methods in LRFData or OdomData, used for updating and resetting<br />
*Obstacle avoidance function ''avoid()''<br />
*Example of FSM implementation, such as control.cpp lines 20-26<br />
*Implementation of ''trajectory()'', ''avoid()'', ''slow()'', in control.cpp lines 57-68<br />
*Functionality of monitor.cpp, like lines 75-80<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 9 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78703Embedded Motion Control 2019 Group 42019-06-20T09:31:57Z<p>S149491: /* Split and merge method */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the excecution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
The initial strategy that is formulated is as follows:<br />
<br />
[[File:Strategy_escaperoom.png|400px]]<br />
<br />
This plan is updated to gain more insights and control over the different situations that can happen.<br />
<br />
[PLAATJE]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO ... the LRF data is first preprocessed into walls by a ''split and merge'' algorihtm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visable door is determined.<br />
<br />
DON'T EDIT, I'M WORKING ON THIS :D<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data. A wall is defined as a starting and an end point, a length and an index.<br />
<br />
First for every measured point the location in carthesian coordinates is calculated, using PICO as the center point. Next the algorithm tries to fit a single wall through the entire LRF data. A check is executed to see whether the position of the middle point of this wall matches the position of the middle point in the LRF data. On a succes the wall is confirmed. On a fail the wall is split into two separate walls, hence the ''split'', on this middle point. The process is then repeated on these two walls until splitting is no longer necessary.<br />
<br />
<br />
<br />
Firstly walls are created from the lrf data. Next, these small walls are merged into large walls. <br />
For this, the 'split and merge' method is used as shown below.<br />
<br />
<gallery><br />
File:Split_merge1.png|Example first step<br />
File:Split_merge2.png|Example second step<br />
File:Split_merge3.png|Example third step<br />
</gallery><br />
<br />
Then the corners are recognized. The 2 different kind of corners are recognized and from the right kind of corners the exit is generated. This is visualised below.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|300px|Animation of the exit detection flow]]<br clear=all><br />
<br />
At last, the center point of the exit is calculated together with a point in front of this center point. This point in front is sent to the movement part of the PICO.<br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Use a more advanced algorithm to detect and move.<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
First of all the cabinet and door recognition. This strategy comes from the exit recognition that was used for the escape room challenge. Doors are recognised with the same exit strategy als the exits are found in the escape room. Cabinets are defined by a set of corners within a certain region of each other, combined with the kind of corner ('inside' or 'outside'). This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked as good as the other localization algorithm which is given above.<br />
<br />
We also looked at a particle filter for localization. This is a well known type of localization and a couple of examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. It was thought that this way was overkill for this challenge, because the starting area was known and the rooms have enough points of recognition (think of distances and corner kinds etc) to localize in other ways with less computational effort.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and dead-lock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. It's primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognition, also the missing of previously found obstacles must be detected. <br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visable will be defined as two separate obstacles. Next double defined obstacles (overlapping lines) are merged and obstacles that are recognized as walls are removed.<br />
<br />
The detection of double defined obstacles happens in three steps in which obstacles are seen as lines. First the relative angle between the lines is calculated. When two parallel lines are found the perpendicular distance from one line to the other is calculated. When this distance falls within the limits, a check is executed to see if the lines overlap. If also the third check is satisfied, a new obstacle is defined as the two endpoints of these lines that are the furthest appart (e.g. start point of line 1 and end point of line 2). The two initial obstacles are removed.<br />
<br />
The same checks are executed to filter any walls from the obstacles. Obstacles are compared to walls and when all three checks are satisfied for some wall the obstacle is removed.<br />
<br />
With the updated version of the map, the path planning is now able to replan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether they should be within vision range. It checks this by searching for walls, cabinets or other obstacles that are in between PICO and the currently looked at obstacle. If there are none, the distance of the obstacle is compared to the distance measured in the LRF data. If the LRF data vastly exceeds the distance to the obstacle, the obstacle is removed.<br />
<br />
This way paths that were obstructed before will be accessable by the robot again when the obstacles as well as wrongly detected obstacles are removed.<br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
===== Result =====<br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
Test the localization algorithm and the dynamic obstacle avoidance.<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
The following points should be tested in this attempt:<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
===== Result =====<br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position. The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be to inaccurate to use in this hospital challenge. PICO stranded next to a door where he could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
== Conclusion ==<br />
<br />
== Code ==<br />
Snippets suggested by Bram:<br />
*Methods in LRFData or OdomData, used for updating and resetting<br />
*Obstacle avoidance function ''avoid()''<br />
*Example of FSM implementation, such as control.cpp lines 20-26<br />
*Implementation of ''trajectory()'', ''avoid()'', ''slow()'', in control.cpp lines 57-68<br />
*Functionality of monitor.cpp, like lines 75-80<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 9 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78686Embedded Motion Control 2019 Group 42019-06-20T09:19:13Z<p>S149491: /* Escape Room - Exit recognition */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the excecution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
The initial strategy that is formulated is as follows:<br />
<br />
[[File:Strategy_escaperoom.png|400px]]<br />
<br />
This plan is updated to gain more insights and control over the different situations that can happen.<br />
<br />
[PLAATJE]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Before PICO ... the LRF data is first preprocessed into walls by a ''split and merge'' algorihtm. Using these walls and the angle they have relative to each other, corners are found. Then, by looking at the different types of corners present in PICO's view, the location of any visable door is determined.<br />
<br />
DON'T EDIT, I'M WORKING ON THIS :D<br />
<br />
==== Split and merge method ====<br />
The split and merge algorithm takes care of detecting walls in the LRF data.<br />
<br />
Firstly walls are created from the lrf data. Next, these small walls are merged into large walls. <br />
For this, the 'split and merge' method is used as shown below.<br />
<br />
<gallery><br />
File:Split_merge1.png|Example first step<br />
File:Split_merge2.png|Example second step<br />
File:Split_merge3.png|Example third step<br />
</gallery><br />
<br />
Then the corners are recognized. The 2 different kind of corners are recognized and from the right kind of corners the exit is generated. This is visualised below.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|300px|Animation of the exit detection flow]]<br clear=all><br />
<br />
At last, the center point of the exit is calculated together with a point in front of this center point. This point in front is sent to the movement part of the PICO.<br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Use a more advanced algorithm to detect and move.<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map. A visualisation of this is given in the following figure:<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
[[File:Localization.gif|left|thumb|600px|Localization together with simulation when moving]]<br clear=all><br />
<br />
==== Alternatives ====<br />
First of all the cabinet and door recognition. This strategy comes from the exit recognition that was used for the escape room challenge. Doors are recognised with the same exit strategy als the exits are found in the escape room. Cabinets are defined by a set of corners within a certain region of each other, combined with the kind of corner ('inside' or 'outside'). This way, the location of PICO can be determined by using the distances of the LRF corners. This alternative worked as good as the other localization algorithm which is given above.<br />
<br />
We also looked at a particle filter for localization. This is a well known type of localization and a couple of examples can be found online. The accuracy of a particle filter improves over time, because more samples are used. It was thought that this way was overkill for this challenge, because the starting area was known and the rooms have enough points of recognition (think of distances and corner kinds etc) to localize in other ways with less computational effort.<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and dead-lock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. It's primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognition, also the missing of previously found obstacles must be detected. <br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visable will be defined as two separate obstacles. Next double defined obstacles (overlapping lines) are merged and obstacles that are recognized as walls are removed.<br />
<br />
The detection of double defined obstacles happens in three steps in which obstacles are seen as lines. First the relative angle between the lines is calculated. When two parallel lines are found the perpendicular distance from one line to the other is calculated. When this distance falls within the limits, a check is executed to see if the lines overlap. If also the third check is satisfied, a new obstacle is defined as the two endpoints of these lines that are the furthest appart (e.g. start point of line 1 and end point of line 2). The two initial obstacles are removed.<br />
<br />
The same checks are executed to filter any walls from the obstacles. Obstacles are compared to walls and when all three checks are satisfied for some wall the obstacle is removed.<br />
<br />
With the updated version of the map, the path planning is now able to replan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether they should be within vision range. It checks this by searching for walls, cabinets or other obstacles that are in between PICO and the currently looked at obstacle. If there are none, the distance of the obstacle is compared to the distance measured in the LRF data. If the LRF data vastly exceeds the distance to the obstacle, the obstacle is removed.<br />
<br />
This way paths that were obstructed before will be accessable by the robot again when the obstacles as well as wrongly detected obstacles are removed.<br />
<br />
=== Hospital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
Setup of test area: two rooms, with matching .json and sim map (similar to items provided on Wiki).<br />
*Main priority: Localization<br />
*Plan to two cabinets, first far away, second back in start area, move to both<br />
*Initialization to RRT planning.<br />
*Dynamic obstacle avoidance<br />
**Create a test case, just drive straight ahead and place an object in PICO's way<br />
===== Result =====<br />
*Pico drives backwards due to no odometry reset<br />
*Program crashes at wall merging (probably due to array size in recursive function)<br />
**Turn all arrays into vectors so issues like this can never occur.<br />
*Wall avoidance trough door is too tight. Keeps repositioning in door, does not drive trough.<br />
*Program stops after emergency, does not plan again.<br />
**Update FSM flow, create functionality for replanning.<br />
*Pico plans a path trough walls because it drives on lrf data only<br />
**Enable planning on JSON map.<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
Test the localization algorithm and the dynamic obstacle avoidance.<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
The following points should be tested in this attempt:<br />
*Robustness of localization algorithm<br />
**Should work in any orientation, and should not determine incorrect location.<br />
*Robustness of dynamic obstacle avoidance<br />
**PICO should be able to move through doors without stopping or jittering.<br />
**PICO should be able to move through hallways without stopping or jittering.<br />
**PICO should be able to avoid moving objects.<br />
*Functionality of static obstacle avoidance<br />
**Recognize when an issue has occurred<br />
**Plan a new path around the obstacle<br />
<br />
===== Result =====<br />
*PICO sometimes drives backwards, even though this was supposed to have been solved.<br />
**ODOM.reset() was not called after initialization, has been added to the software now.<br />
*PICO does not yet plan using the JSON map, only on the LRF map.<br />
**Enable this in RRT planning function.<br />
*Bram’s avoidance algorithm works better right now, and we will continue working with this.<br />
**Marcel’s algorithm requires at least too much tuning, and perhaps has more issues.<br />
*PICO moves correctly through hallways.<br />
*PICO moves correctly through doors.<br />
*PICO sometimes hits walls directly ahead.<br />
**Try finetuning the avoidance parameters in that direction.<br />
*PICO returns to 0 after movements.<br />
**Update map and reset odometry after movement.<br />
**Update map accurately when in front of cabinet.<br />
*It is unclear whether PICO always orients itself correctly in front of the cabinet.<br />
**Atan2 definitions need to be checked, rotations might get flipped.<br />
*Is the localization accurate enough?<br />
**Tolerances present in both RRT path and in next point selection, might make PICO drive through walls.<br />
*Visualization doesn’t work during movement.<br />
**The room and location on map could be updated more frequently<br />
*Orientation-dependent emergency might be interesting.<br />
**PICO is wider than long.<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
*Localization in test does only work iff pico finds 4 corners. If more or less corners are found, translation matrix went to inf.<br />
<br />
=== Hospital Challenge - Competition ===<br />
The hospital challenge consisted of two trials. The first trial was not a succes. The initial localization of PICO was to place itself outside the hospital map. Therefore the pathplanner could not find a path to the first required cabinet and PICO remained standing still on its starting position. The second trial worked out a lot better. The initial localization was correct and PICO was able to plan a path to the first cabinet. When following the path PICO did not update the localization (continous localization was not finished) and therefore only relied on its odometry data. This proved to be to inaccurate to use in this hospital challenge. PICO stranded next to a door where he could not localize itself again correctly and therefore could not plan a new path to its destination.<br />
<br />
== Conclusion ==<br />
<br />
== Code ==<br />
Snippets suggested by Bram:<br />
*Methods in LRFData or OdomData, used for updating and resetting<br />
*Obstacle avoidance function ''avoid()''<br />
*Example of FSM implementation, such as control.cpp lines 20-26<br />
*Implementation of ''trajectory()'', ''avoid()'', ''slow()'', in control.cpp lines 57-68<br />
*Functionality of monitor.cpp, like lines 75-80<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 9 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78282Embedded Motion Control 2019 Group 42019-06-19T11:41:01Z<p>S149491: /* Hospital Challenge - Obstacle avoidance */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the excecution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
The initial strategy that is formulated is as follows:<br />
<br />
[[File:Strategy_escaperoom.png|400px]]<br />
<br />
This plan is updated to gain more insights and control over the different situations that can happen.<br />
<br />
[PLAATJE]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Firstly walls are created from the lrf data. Next, these small walls are merged into large walls. <br />
For this, the 'split and merge' method is used as shown below.<br />
<br />
<gallery><br />
File:Split_merge1.png|Example first step<br />
File:Split_merge2.png|Example second step<br />
File:Split_merge3.png|Example third step<br />
</gallery><br />
<br />
Then the corners are recognized. The 2 different kind of corners are recognized and from the right kind of corners the exit is generated. This is visualised below.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|300px|Animation of the exit detection flow]]<br clear=all><br />
<br />
At last, the center point of the exit is calculated together with a point in front of this center point. This point in front is sent to the movement part of the PICO.<br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Use a more advanced algorithm to detect and move.<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map.<br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
==== Alternatives ====<br />
* Cabinet and Door recognition<br />
* Particle filter<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
In order to have PICO move through the hospital safely and fast and yet prevent live- and dead-lock situations, two layers of obstacle avoidance were implemented. The first layer, the ''dynamic obstacle avoidance'', has as primary function to exert repeling forces on PICO pushing it away from obstacles while driving. The second layer, the ''static obstacle avoidance'', becomes active when the chosen trajectory can no longer be followed, even with the help of the ''dynamic obstacle avoidance''. It's primary function is to recognize these objects and add them to the map to enable the planning of a path around it.<br />
<br />
==== Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labelled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
==== Static obstacle avoidance ====<br />
The recognition of obstacles which cannot be avoided by repelling forces alone and do require PICO to stop and plan a new route, has been labelled ''static obstacle avoidance''. Next to recognition, also the missing of previously found obstacles must be detected. <br />
<br />
===== Detect new obstacles =====<br />
A situation in which ''dynamic obstacle avoidance'' is no longer sufficient is communicated through the event ''objectFound'' setting the state to ''goalObject''. The ''static obstacle avoidance'' then adds any found walls (lines) found in the LRF data to the map as if they were obstacles. E.g. a box of which two sides are visable will be defined as two separate obstacles. Next double defined obstacles (overlapping lines) are merged and obstacles that are recognized as walls are removed.<br />
<br />
The detection of double defined obstacles happens in three steps in which obstacles are seen as lines. First the relative angle between the lines is calculated. When two parallel lines are found the perpendicular distance from one line to the other is calculated. When this distance falls within the limits, a check is executed to see if the lines overlap. If also the third check is satisfied, a new obstacle is defined as the two endpoints of these lines that are the furthest appart (e.g. start point of line 1 and end point of line 2). The two initial obstacles are removed.<br />
<br />
The same checks are executed to filter any walls from the obstacles. Obstacles are compared to walls and when all three checks are satisfied for some wall the obstacle is removed.<br />
<br />
With the updated version of the map, the path planning is now able to replan the route towards its target, now taking into account the detected obstacles.<br />
<br />
===== Detect missing obstacles =====<br />
To have a robust system, not only should it have the possibility to add obstacles, but it should be able remove them when they are no longer present. As part of the ''static obstacle avoidance'', the function ''removeObstacle'' takes care of this.<br />
<br />
The function loops over all obstacles found previously and checks whether they should be within vision range. It checks this by searching for walls, cabinets or other obstacles that are in between PICO and the currently looked at obstacle. If there are none, the distance of the obstacle is compared to the distance measured in the LRF data. If the LRF data vastly exceeds the distance to the obstacle, the obstacle is removed.<br />
<br />
This way paths that were obstructed before will be accessable by the robot again when the obstacles as well as wrongly detected obstacles are removed.<br />
<br />
=== Hostpital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
=== Hospital Challenge - Competition ===<br />
<br />
<br />
== Conclusion ==<br />
<br />
== Code ==<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 9 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78233Embedded Motion Control 2019 Group 42019-06-19T10:15:45Z<p>S149491: /* Hospital Challenge - Local movement */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the excecution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
The initial strategy that is formulated is as follows:<br />
<br />
[[File:Strategy_escaperoom.png|400px]]<br />
<br />
This plan is updated to gain more insights and control over the different situations that can happen.<br />
<br />
[PLAATJE]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Firstly walls are created from the lrf data. Next, these small walls are merged into large walls. <br />
For this, the 'split and merge' method is used as shown below.<br />
<br />
<gallery><br />
File:Split_merge1.png|Example first step<br />
File:Split_merge2.png|Example second step<br />
File:Split_merge3.png|Example third step<br />
</gallery><br />
<br />
Then the corners are recognized. The 2 different kind of corners are recognized and from the right kind of corners the exit is generated. This is visualised below.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|300px|Animation of the exit detection flow]]<br clear=all><br />
<br />
At last, the center point of the exit is calculated together with a point in front of this center point. This point in front is sent to the movement part of the PICO.<br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Use a more advanced algorithm to detect and move.<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map.<br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
==== Alternatives ====<br />
* Cabinet and Door recognition<br />
* Particle filter<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: First, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
<br />
==== Hospital Challenge - Static obstacle avoidance ====<br />
<br />
<br />
==== Hospital Challenge - Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labeled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
=== Hostpital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
=== Hospital Challenge - Competition ===<br />
<br />
<br />
== Conclusion ==<br />
<br />
== Code ==<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 9 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78232Embedded Motion Control 2019 Group 42019-06-19T10:15:22Z<p>S149491: /* Hospital Challenge - Local movement */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the excecution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
The initial strategy that is formulated is as follows:<br />
<br />
[[File:Strategy_escaperoom.png|400px]]<br />
<br />
This plan is updated to gain more insights and control over the different situations that can happen.<br />
<br />
[PLAATJE]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Firstly walls are created from the lrf data. Next, these small walls are merged into large walls. <br />
For this, the 'split and merge' method is used as shown below.<br />
<br />
<gallery><br />
File:Split_merge1.png|Example first step<br />
File:Split_merge2.png|Example second step<br />
File:Split_merge3.png|Example third step<br />
</gallery><br />
<br />
Then the corners are recognized. The 2 different kind of corners are recognized and from the right kind of corners the exit is generated. This is visualised below.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|300px|Animation of the exit detection flow]]<br clear=all><br />
<br />
At last, the center point of the exit is calculated together with a point in front of this center point. This point in front is sent to the movement part of the PICO.<br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Use a more advanced algorithm to detect and move.<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map.<br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
==== Alternatives ====<br />
* Cabinet and Door recognition<br />
* Particle filter<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: first, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
<br />
==== Hospital Challenge - Static obstacle avoidance ====<br />
<br />
<br />
==== Hospital Challenge - Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labeled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
=== Hostpital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
=== Hospital Challenge - Competition ===<br />
<br />
<br />
== Conclusion ==<br />
<br />
== Code ==<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 9 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78225Embedded Motion Control 2019 Group 42019-06-19T10:09:37Z<p>S149491: /* RRT path splitting */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the excecution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
The initial strategy that is formulated is as follows:<br />
<br />
[[File:Strategy_escaperoom.png|400px]]<br />
<br />
This plan is updated to gain more insights and control over the different situations that can happen.<br />
<br />
[PLAATJE]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Firstly walls are created from the lrf data. Next, these small walls are merged into large walls. <br />
For this, the 'split and merge' method is used as shown below.<br />
<br />
<gallery><br />
File:Split_merge1.png|Example first step<br />
File:Split_merge2.png|Example second step<br />
File:Split_merge3.png|Example third step<br />
</gallery><br />
<br />
Then the corners are recognized. The 2 different kind of corners are recognized and from the right kind of corners the exit is generated. This is visualised below.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|300px|Animation of the exit detection flow]]<br clear=all><br />
<br />
At last, the center point of the exit is calculated together with a point in front of this center point. This point in front is sent to the movement part of the PICO.<br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Use a more advanced algorithm to detect and move.<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map.<br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
==== Alternatives ====<br />
* Cabinet and Door recognition<br />
* Particle filter<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if they can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: firstly, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
<br />
==== Hospital Challenge - Static obstacle avoidance ====<br />
<br />
<br />
==== Hospital Challenge - Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labeled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
=== Hostpital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
=== Hospital Challenge - Competition ===<br />
<br />
<br />
== Conclusion ==<br />
<br />
== Code ==<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 9 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=Embedded_Motion_Control_2019_Group_4&diff=78209Embedded Motion Control 2019 Group 42019-06-19T09:54:47Z<p>S149491: /* Point matching */</p>
<hr />
<div>This is the CSTWiki page for group 4 of Embedded Motion Control 2019.<br />
<br />
== Group members ==<br />
{|<br />
|Marcel Bosselaar<br />
|0906127<br />
|-<br />
|Ruben Sommer<br />
|0910856<br />
|-<br />
|Jeroen Setz<br />
|0843356<br />
|-<br />
|Bram Grolleman<br />
|0757428<br />
|-<br />
|Martijn Tibboel<br />
|0909136<br />
|}<br />
<br />
== Deliverables ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Design_Document_Embedded_Motion_Control.pdf#filelinks Design Document]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group04_Interim.pdf#filelinks Interim presentation]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_Final.pdf#filelinks Final presentation]<br />
<br />
== Escape Room ==<br />
The following ideas are used for the excecution of the Escape room.<br />
<br />
=== Escape Room - Plan ===<br />
The initial strategy that is formulated is as follows:<br />
<br />
[[File:Strategy_escaperoom.png|400px]]<br />
<br />
This plan is updated to gain more insights and control over the different situations that can happen.<br />
<br />
[PLAATJE]<br />
<br />
=== Escape Room - Exit recognition ===<br />
Firstly walls are created from the lrf data. Next, these small walls are merged into large walls. <br />
For this, the 'split and merge' method is used as shown below.<br />
<br />
<gallery><br />
File:Split_merge1.png|Example first step<br />
File:Split_merge2.png|Example second step<br />
File:Split_merge3.png|Example third step<br />
</gallery><br />
<br />
Then the corners are recognized. The 2 different kind of corners are recognized and from the right kind of corners the exit is generated. This is visualised below.<br />
<br />
[[File:Ezgif.com-video-to-gif.gif|left|frame|300px|Animation of the exit detection flow]]<br clear=all><br />
<br />
At last, the center point of the exit is calculated together with a point in front of this center point. This point in front is sent to the movement part of the PICO.<br />
<br />
=== Escape Room - Finite state machine ===<br />
A finite state machine is introduced in order to maintain control over what is happening at all times.<br />
<br />
<br />
After the challenge, an alternative FSM was thought of that reduces the number of states required and vastly improves accuracy.<br />
<br />
<gallery><br />
File:4SC020_group4_FSM_escapeRoom.png|Diagram of the finite state machine used in the escape room competition.<br />
File:4SC020_group4_FSM_escapeRoom_circular.png|Diagram of an improved FSM, thought of after the competition.<br />
</gallery><br />
<br />
=== Escape Room - Testing ===<br />
The following testing dates have been set. Also the goal of each testing date is put behind in order to stay on track of the global planning of the project.<br />
<br />
==== PICO Test 1 (2019-05-08) ====<br />
===== Goal =====<br />
Have PICO detect the exit, and perform simple motion towards it.<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 2 (2019-05-13) ====<br />
===== Goal =====<br />
Use a more advanced algorithm to detect and move.<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 3 (2019-05-16) ====<br />
===== Goal =====<br />
Test improvements done based on competition results. If available, test ideas that were previously generated but would only be useful for the final competition.<br />
===== Result =====<br />
<br />
=== Escape Room - Competition ===<br />
In the escape room competition, we were potentially the team that had the highest high and the lowest low. <br />
<br />
The algorithm we had designed worked perfectly and very quickly. The door was found as soon as it came into view, and PICO decided to move toward the correct location in front of the door. The door was then immediately found again, and PICO's position in front of the door was made more accurate. Then, the exit of the hallway was detected immediately, and PICO drove towards its end goal.<br />
<br />
However, due to the fact that we had not managed to implement the odometry into PICO, distances traveled were around 30% too short, meaning PICO stopped well before the detected end of the exit hallway. In addition, telling PICO to drive straight didn't actually make it drive straight, making it graze the wall.<br />
<br />
The first improvement we will need to make is the odometry, as we're confident PICO would have exited the room within 30 seconds if it actually was were it thought it was. Secondly, we should use the laser data more frequently, and create new plans during movement to keep things moving in the right direction. Improving the finite state machine to use fewer states and being more circular might also be a good addition.<br />
<br />
== Hospital Challenge ==<br />
The following section explains the different functions build and used in the hospital challenge.<br />
<br />
=== Hospital Challenge - Software architecture ===<br />
The figure below gives an overview of the elements present in our software, with some of the most important functions these elements run, the data present in them, and the data sent around between them.<br />
<br />
[[File:4SC020-Group4-SoftwareArchitecture.png|left|thumb|600px|Overview of the software architecture]]<br clear=all><br />
<br />
The control over which function is allowed to use what data comes from the definition of the functions. Each function gets access to certain variables that are relevant for their functioning.<br />
<br />
Standard access is read-only, so the function basically creates a local variable that can be accessed by elements within the function.<br />
<br />
Data that should be altered, represented by the arrows returning into the world model, is fed into the function with write permissions.<br />
<br />
=== Hospital Challenge - Finite state machine ===<br />
Due to the hospital challenge requiring different functionality from the escape room challenge, a new finite state machine was developed, visible below.<br />
<br />
[[File:4SC020-Group4-FSM hospital horizontal.png|left|thumb|600px|Diagram of the finite state machine used in the hospital challenge]]<br clear=all><br />
<br />
==== Explanation ====<br />
<br />
In this state machine, there is once again an initialization state, called ''init''. Once PICO has been initialized, which is checked by grabbing LRF and odometry data and seeing whether it is correct, the event ''initialized'' occurs, and the state is set to ''initMap''.<br />
<br />
With the initialization of the state ''initMap'', the localization flow has been started. This flow works by using the ''initMap'' state to have PICO gather LRF data, until such a time that the desired data has been collected. Once this happens, the ''initFit'' state is used to attempt to fit this data to the map, and orient the map correctly with regard to PICO. Should a fit prove impossible, the state ''initRepos'' will become active, in which PICO will attempt to reposition itself in a different location, and try to map and fit itself again.<br />
<br />
Once PICO has localized itself, the state will switch to ''goalSelect'', leaving PICO in the global movement flow. Here, PICO will select the cabinet it should travel to from the array created by user input in the ''goalSelect'' state. Once this has been done, the ''goalPlan'' state will use our [[#Hospital_Challenge_-_Path_planning|rapidly-expanding random tree algorithm]] to generate a path to the selected cabinet.<br />
<br />
The ''goalMove'' state handles the actual movement along the generated path to the cabinet, as well as [[#Hospital_Challenge_-_Dynamic_obstacle_avoidance|dynamic obstacle avoidance]]. From this state, two escapes are possible. The first and most important is the ''goalAvoid'' state, triggered by the ''goalEmergency'' event. As the event implies, this state is designed for avoiding an emergency, and should only occur when an object suddenly comes too close to PICO, as the dynamic obstacle avoidance should keep PICO from reaching the emergency state during normal operation. The ''goalAvoid'' state then reorients PICO to a safe location, and the ''goalPlan'' state becomes active again.<br />
<br />
Should PICO get stuck in the ''goalMove'' state and not be able to reach its target, the ''objectFound'' event is triggered, setting PICO to the ''goalObject'' state. In this state, PICO will add the unexpected object to the map, and once this is done the ''goalPlan'' state will become active again, and will plan a path around the new object that was added to the map.<br />
<br />
The end of the global movement flow is signified when PICO has reached a point of half a meter in front of the cabinet. From this point forward, PICO will use its LRF sensor to enable precise local movement. The first state in this flow is ''cabFind'', in which PICO will attempt to recognize a cabinet from its LRF data. Once this cabinet has been found, PICO will move towards it in the ''cabMove'' state, once again with an emergency avoid state.<br />
<br />
When PICO has reached the desired position in front of the cabinet, the ''cabStop'' state will become active, in which PICO will pause in front of the cabinet and exclaim what is happening. Then, in preparation for movement to the next cabinet, the ''cabTurn'' state turns PICO around by 180 degrees, so he's looking away from the cabinet, and the global movement flow is once again initiated when the event ''cabTurned'' is thrown.<br />
<br />
Global and local movement will keep occurring just as long as there are more cabinets in the array of supplied cabinets, when the event ''goalReached'' occurs. This event leads to the ''done'' state, signalling PICO to say goodbye and terminate the program.<br />
<br />
==== Implementation ====<br />
The state machine as described above has been implemented in the software as an ''enum'' type variable for the events and for the states. This type of variable can only have the values of the states/events, declared in its generation.<br />
<br />
The monitor function is the only function that can alter the states, and it will do so based on the events generated by the other functions. For instance, when the event ''goalSelected'' is thrown, by way of the variable ''E'' having value ''goalSelected'', the monitor will change the state to ''goalPlan'', by way of changing variable ''FSM'' to ''goalPlan''.<br />
<br />
The perception, planning, and control functions will then display different behavior depending on what the value of ''FSM'' is. This is achieved by creating multiple successive ''if''-loops that describe the behavior in a certain state or states.<br />
<br />
==== Conclusion ====<br />
With the finite state machine as described above, we have developed a usable way of controlling PICO's discrete behavior. Due to multiple loops in the state flow we believe to have kept the states to a sufficiently low number, while still having very clear states for very clear behavior. The implementation is susceptible to errors, as the events are not coupled to the state PICO is currently in, but with the use of the figure no programming errors have occurred.<br />
<br />
=== Hospital Challenge - Localization ===<br />
For the hospital challenge localization is key to achieve goals. If everything works but you don't know where you are it is going to be a mess. The idea is to update the localization every time the robot needs to make a new path with the path planning. In between two setpoints of the path, the odometry is used to know the current location and this is assumed to be 'good enough'. When something goes wrong and it is not enough, the state machine compensates, because the robot goes to a 're-planning' state, where it also updates the location again. This way it is never a problem if the accuracy of the localization is a bit off.<br />
<br />
[[File:4SC020-Group40LocalizationFlow.png|left|thumb|600px|Diagram of the localization flow theorized for the hospital challenge]]<br clear=all><br />
<br />
<br />
==== Point matching ====<br />
The idea that is used for localizing PICO's location is as follows. <br />
<br />
When PICO is being initialized, a calculation is done over the map information. All corners are specified with the right corner type 'inside' or 'outside' corner, which is also done for the LRF data as explained in the escape room challenge. For all corners of the map is the distance between the point and all other points calculated for use in the future.<br />
<br />
Within the localization script a loop is made through all corners of the map and all corners that are specified in the LRF data. A point of the LRF data is checked if it has the same kind of corner as the map point. If that is true, another point of both data sets is checked if this has the same kind. When this holds, a distance is calculated between the points of the LRF and then checked if this distance is near the distance that it should be compared to the map. (which is stored in the beginning) Summarizing, this means that a wall with 2 points of the LRF data is checked if it is suits to be fitted to a wall of the map.<br />
<br />
Next, this is done for another three walls, while aborting if one of the statements does not hold. This reduces the amount of possibilities of the best fit and the possible fits are stored in an array. After this, the script uses the stored fits to calculate a location of PICO in the map with the given distances from the LRF corners that are fitted in the fits. The different that come forward are analysed on the amount of occurances and unfeasible locations (outside the map for example) are removed from the possibilities.<br />
<br />
From the locations that are found a mean location is calculated together with the guess (from the odometry data) where PICO possible could to obtain the final location of PICO. Accordingly to the location of PICO the map is translated and rotated in order to fit the map over the LRF data. This way the planning can be done easier, because it is assured that PICO is at the origin of the plot.<br />
<br />
A problem occured while making this way of localizing. The localization had a lot of 'unwanted' locations, so that is why the above filters were added. This solved the problem, but still a offset remained within the localization. Later on it appeared to be a problem within the shifting of the map, because we were using multiple coordinate system which made reasoning pretty hard. In the beginning we thought it was the uncertainty of the found points that gave this offset, that is why we also looked at other localization options. Which in the end, turned out to have the same problem.<br />
<br />
==== Alternatives ====<br />
* Cabinet and Door recognition<br />
* Particle filter<br />
<br />
=== Hospital Challenge - Path planning ===<br />
<br />
Path planning is defined here as finding a way from point A to B based on a known map while avoiding obstacles on this map. In general there are four different approaches to path planning for mobile robotics:<br />
;Cell decomposition<br />
:Divide the map into a grid and define obstacles as cells which can not be used for movement. Then an algorithm as A* or Dijkstra can be used to find the (optimal) path from A to B.<br />
;Potential fields<br />
:A map is converted to a potential field map in which obstacles have high values and free space low. This way a path from A to B can be created which follows the lowest potentials.<br />
;Sampling based<br />
:A sampling based algorithm finds points in the free space of a map and tries to connect them. Then a path is found from A to B following these points. Examples are a Rapidely-expanding Random Tree (RRT) or a probabilistic roadmap.<br />
<br />
The requirement set for a path planning algorithm was to avoid a grid (to prevent scalability issues and limited cell resolution) and potential fields (as followed from the Do's and Don'ts lecture). Therefore one candidate remained: sampling based. The choice was made to use a RRT algorithm as is seemed easier to implement compared to a probabilistic roadmap. The benefit of using such a path planning algorithm is the generality. It does not need any predefined points, cells or possible paths. It can find a path on any given map with obstacles.<br />
<br />
==== Rapidly-expanding Random Tree algorithm ====<br />
A RRT algorithm starts with a root node. In this case the initial position of PICO. Each iteration a random point is created in the space of the map. The closest node of the tree to the random point is chosen to extend the tree in the direction of the random point. The connection of the newly placed node will be checked for validity (i.e. not colliding with obstacles on the map). This way the random tree will eventually span the complete free space. The algorithm terminates if the goal point B is reached with the tree. An open-source [https://github.com/mpdmanash/rrt-star-dubins-sim existing algorithm] is used which creates a basic random tree. This is modified to work with our software. Two (major) additions are done to the existing algorithm. <br />
<br />
[[File:RRTexample.gif]]<br />
<br />
===== RRT end point bias =====<br />
To ensure a quick convergence of the tree towards the end goal (point B), an endpoint bias is used. This means that every few iterations the algorithm does not use a random point is space but the end goal. This way the tree will be extended in the direction of the goal. This proved to achieve a much faster algorithm which required a lot less iterations to find a path. The end point bias may to be too large (i.e. take every other random point as the end point) as the algorithm can get trapped in corners between obstacles.<br />
<br />
===== RRT path splitting =====<br />
A drawback of the RRT algorithm is that it will find a path which is generally not optimal. To optimize the found path, a splitting algorithm is used similliar to the splitting algorithm used to find walls in LRF data. It first tries to connect the start and end point of the path to see if it can be connected with a straight line without colliding with obstacles. If this fails, the check is done using the middle point of the path. This is done recursively to optimize the path. In the worst case scenario the original path will be retrieved again. The RRT splitting method showed to create nice straight lines between all points on the path, this still does not create an optimal path, but an optimized version of the original found path.<br />
<br />
===== Resulting pathplanner =====<br />
Using the two discussed additions to the random tree path planner, the final result is shown below. A path is created based on the obstacles (walls and cabinets) in the JSON file of the hospital challenge from initial position to cabinet 0. First a random path is found, in which the influence of the endpoint bias is clearly visible. Afterwards the path is approximated by straight lines using the path splitting algorithm. This results in points which can actually be followed smoothly by PICO. The path is shown not to cross any obstacles. Obstacle lines are slightly extended to prevent pico from driving too close to wall corners. This could be improved by blowing up obstacles instead of just extending them. When the path is created, is consists of an array of points. An extra orientation is added to these points in order to let PICO orientate itself in the direction in which it will drive to the next point.<br />
(Note: The image visualization is not the actual speed of the pathplanning algorithm, this could be much faster or slower depending on the map.)<br />
<br />
[[File:pathplanningResult.gif]]<br />
<br />
=== Hospital Challenge - Movement ===<br />
The movement of PICO from a start position to a cabinet is divided into two parts; global and local movement. This is also shown in the visualization of the [[#Hospital Challenge - Finite state machine|finite state machine]]. The global movement is defined as following the path created by the pathplanner. This results in a path to a location which is 0.5 meter in front of the cabinet. Once this location is reached, PICO switches to the local movement flow. This basically means it has to find the cabinet and drive to the required distance of approximately 20 centimeter in front of the cabinet.<br />
<br />
==== Hospital Challenge - Global movement ====<br />
The global movement flow is visualized in the [[#Hospital Challenge - Finite state machine|finite state machine]] diagram. It starts with selecting a goal (State = goalSelect), this is done based on the list of cabinets that should be visited. A counter is used which keeps track of how many cabinets are already visited and the next one is selected as goal. If all cabinets are already visited, the program is shut down.<br />
Once the goal is selected, a path to this goal is planned using the [[#Hospital Challenge - Path planning|RRT pathplanner]] (State = goalPlan). <br />
<br />
Once the global path is created, PICO has an array containing positions (x,y) and an orientation which should be reached. The trajectory() function in the control section sets the velocities needed to reach the next point in the path. Once PICO is at a distance of 0.5 meter of the point in the path, the next point is selected to drive to (State = goalMove). This prevents PICO from stopping in between points and ensures he moves smoothly along the path. Once PICO is driving to the final point of the path, the required distance to the point is much smaller to ensure it actually reaches his final position. During the goalMove state, two situations can apear: Emergency or Stuck. The emergency state requires PICO to stop and plan its path again. The Stuck situation appears when PICO does not move significantly for a certain amount of time. This means PICO has probably encountered an obstacle in its path which was not on the map. PICO will scan the room and add obstacles in sight to the map. Then the state is set to goalPlan again. The obstacles found in its path will be taken into account when planning a new path. When the final location is reached, PICO will switch to the local movement flow.<br />
<br />
==== Hospital Challenge - Local movement ====<br />
As stated in previous section, after PICO has reached its destination determined by the RRT, PICO switches to local movement flow. In this flow, PICO moves towards the cabinet based on LRF-data. This is done in a few steps: firstly, PICO scans the room. In this step LRF-data is updated and the algorithm is started which finds walls, doors, corners etc, which results in an updated world model. Secondly, PICO searches for corners in the world model with certain requirements (distance to PICO, distance between corners and corners of type "outside") to find the front wall of the near cabinet. If this step might fail, PICO starts rotating and executes this step again until the cabinet is found. Thirdly, PICO moves to the desired position in front of the cabinet on odometry data.<br />
<br />
=== Hospital Challenge - Obstacle avoidance ===<br />
<br />
==== Hospital Challenge - Static obstacle avoidance ====<br />
<br />
<br />
==== Hospital Challenge - Dynamic obstacle avoidance ====<br />
The avoidance of obstacles during driving, and which does not require PICO to stop and plan a new route, has been labeled ''dynamic obstacle avoidance''.<br />
<br />
Two different algorithms were developed, with a similar thought behind them. The first was to look at the nearest point to PICO, and push PICO away from this point. The biggest issue with this method was that PICO will jitter immensely when moving through narrow hallways or similar features. In order to solve this, a second algorithm was developed. This second algorithm has a similar functionality, but it looks at all points that lie within a certain safety range, and pushes PICO away from them simultaneously. Different strengths of the repulsion are defined in ''x'' and ''y''-directions, allowing finetuning of the avoidance behavior.<br />
<br />
GIF?!<br />
<br />
Implementation of the dynamic obstacle avoidance has been done as follows:<br />
<br />
First, the ''trajectory'' function determines the velocities required to move to the next point in the path, including initial acceleration and final deceleration. These velocities are entered into the ''avoid'' function, which uses the data from the LRF readings to push PICO away from any objects that are too close for comfort by altering the velocities that were input. Finally, the ''slow'' function slows PICO down when too close to objects, to ensure PICO can stop quickly when emergency situations might occur, and to scale the velocities down to the maximum when the ''avoid'' function has been too aggressive in its avoidance.<br />
<br />
=== Hostpital Challenge - Testing ===<br />
The following tests were planned and performed for hospital functionality<br />
<br />
==== PICO Test 4 (2019-05-29) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
<br />
==== PICO Test 5 (2019-06-03) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
The software was not ready for testing, so the test was cancelled at the last minute.<br />
<br />
<br />
==== PICO Test 6 (2019-06-05) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
<br />
<br />
==== PICO Test 7 (2019-06-11) ====<br />
===== Goal =====<br />
<br />
===== Result =====<br />
<br />
=== Hospital Challenge - Competition ===<br />
<br />
<br />
== Conclusion ==<br />
<br />
== Code ==<br />
<br />
== Minutes ==<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_1.pdf#filelinks Meeting 1 (2019-04-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_2.pdf#filelinks Meeting 2 (2019-05-06)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_3.pdf#filelinks Meeting 3 (2019-05-08)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:Meeting_4.pdf#filelinks Meeting 4 (2019-05-13)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190520.pdf#filelinks Meeting 5 (2019-05-20)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190527.pdf#filelinks Meeting 6 (2019-05-27)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190529.pdf#filelinks Meeting 7 (2019-05-29)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190603.pdf#filelinks Meeting 8 (2019-06-03)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190605.pdf#filelinks Meeting 9 (2019-06-05)]<br />
*[http://cstwiki.wtb.tue.nl/index.php?title=File:4SC020_Group4_mom_20190612.pdf#filelinks Meeting 9 (2019-06-12)]<br />
<br />
== Tips & tricks ==<br />
[https://stackoverflow.com/questions/48147356/install-qt-on-ubuntu Install Qt]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_log_martijn&diff=25881PRE2015 3 Groep2 log martijn2016-04-03T17:45:26Z<p>S149491: /* Week 7 */</p>
<hr />
<div>== Week 1 ==<br />
*Meeting after lecture<br />
*Background research about drones for deciding on topic<br />
<br />
It was clear we wanted to do something with drones. Options for topics were:<br />
*Drones filming in a football match<br />
*Drones delivering packages at home<br />
*Drones chasing a fugitive like a police helicopter<br />
<br />
== Week 2 ==<br />
*Meeting<br />
*Rules for drones (see 'Legalisation' under 'week 2')<br />
*Presentation (preparation, I was supposed to present as well but got ill and also lost my voice)<br />
<br />
== Week 3 ==<br />
*Meeting<br />
*First look into other projects at home<br />
*Wednesday entire morning researching the drone. What do we have and how does fly? Also what software is available? (also see Problems)<br />
*Redefining Research<br />
*Research Personal Space by E. Torta --> See Research, week 3 (together with Jeroen)<br />
<br />
Problems:<br />
This week we together looked at the drone together and tried to make it fly. Also we looked at the feedback we got after out last presentation regarding our project. One of these feedback points was about other groups of previous years that had done projects with similar subjects.<br />
<br />
One project however seemed to look like a little too much like the plans we had in mind, forcing us to adjust the aim of our project. They were using the same drone, the same software to fly it and even thought of the same method for verification of the customer (NFC tag). We had two choices, either continue where the other group left off or research a different aspect of the subject. Considering we have only 2 people from ICT, 1 electrical engineer and 3 people from WTB with little programming experience, choosing the first option seemed unwise.<br />
<br />
Thus we moved our focus to the part of flying the drone as in finding a good landing spot. Also we decided to research the approaching of people by drones, since no research we were able to find did look at that for drones yet.<br />
<br />
== Week 4 ==<br />
*Working on Approaching Users<br />
*Working on Drone specifications<br />
*Performing experiment 1<br />
**Being a test subject<br />
**Taking measurements<br />
<br />
== Week 5 ==<br />
*Discussing the progression of the project<br />
**Discussing how the test setup of the autonomous landing research will look like<br />
*Second experiment<br />
**Doing the experiment<br />
**Processing the results of the experiment<br />
*Extending information that is coming in the report<br />
**Rewrite Chapter about the Users<br />
<br />
== Week 6 ==<br />
*Performing the experiments with new test subjects<br />
*Extending the description of the experiments<br />
*Rewriting State of the Art to new project aim<br />
<br />
== Week 7 ==<br />
*Revising general layout of the report<br />
*Working on report<br />
<br />
== Week 8 ==<br />
*Finishing report<br />
*Preparations for the discussion of results in the chapter 'approach'<br />
<br />
Problems:<br />
My other project demanded a lot of a time for the deadline approached and we were not on scheme. Due to this a was not able do the same amount as previous weeks.</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_log_martijn&diff=25659PRE2015 3 Groep2 log martijn2016-03-28T18:42:52Z<p>S149491: /* Week 7 */</p>
<hr />
<div>== Week 1 ==<br />
*Meeting after lecture<br />
*Background research about drones for deciding on topic<br />
<br />
It was clear we wanted to do something with drones. Options for topics were:<br />
*Drones filming in a football match<br />
*Drones delivering packages at home<br />
*Drones chasing a fugitive like a police helicopter<br />
<br />
== Week 2 ==<br />
*Meeting<br />
*Rules for drones (see 'Legalisation' under 'week 2')<br />
*Presentation (preparation, I was supposed to present as well but got ill and also lost my voice)<br />
<br />
== Week 3 ==<br />
*Meeting<br />
*First look into other projects at home<br />
*Wednesday entire morning researching the drone. What do we have and how does fly? Also what software is available? (also see Problems)<br />
*Redefining Research<br />
*Research Personal Space by E. Torta --> See Research, week 3 (together with Jeroen)<br />
<br />
Problems:<br />
This week we together looked at the drone together and tried to make it fly. Also we looked at the feedback we got after out last presentation regarding our project. One of these feedback points was about other groups of previous years that had done projects with similar subjects.<br />
<br />
One project however seemed to look like a little too much like the plans we had in mind, forcing us to adjust the aim of our project. They were using the same drone, the same software to fly it and even thought of the same method for verification of the customer (NFC tag). We had two choices, either continue where the other group left off or research a different aspect of the subject. Considering we have only 2 people from ICT, 1 electrical engineer and 3 people from WTB with little programming experience, choosing the first option seemed unwise.<br />
<br />
Thus we moved our focus to the part of flying the drone as in finding a good landing spot. Also we decided to research the approaching of people by drones, since no research we were able to find did look at that for drones yet.<br />
<br />
== Week 4 ==<br />
*Working on Approaching Users<br />
*Working on Drone specifications<br />
*Performing experiment 1<br />
**Being a test subject<br />
**Taking measurements<br />
<br />
== Week 5 ==<br />
*Discussing the progression of the project<br />
**Discussing how the test setup of the autonomous landing research will look like<br />
*Second experiment<br />
**Doing the experiment<br />
**Processing the results of the experiment<br />
*Extending information that is coming in the report<br />
**Rewrite Chapter about the Users<br />
<br />
== Week 6 ==<br />
*Performing the experiments with new test subjects<br />
*Extending the description of the experiments<br />
*Rewriting State of the Art to new project aim<br />
<br />
== Week 7 ==<br />
*Revising general layout of the report<br />
*Working on report</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_log_martijn&diff=25571PRE2015 3 Groep2 log martijn2016-03-21T12:35:17Z<p>S149491: /* Week 6 */</p>
<hr />
<div>== Week 1 ==<br />
*Meeting after lecture<br />
*Background research about drones for deciding on topic<br />
<br />
It was clear we wanted to do something with drones. Options for topics were:<br />
*Drones filming in a football match<br />
*Drones delivering packages at home<br />
*Drones chasing a fugitive like a police helicopter<br />
<br />
== Week 2 ==<br />
*Meeting<br />
*Rules for drones (see 'Legalisation' under 'week 2')<br />
*Presentation (preparation, I was supposed to present as well but got ill and also lost my voice)<br />
<br />
== Week 3 ==<br />
*Meeting<br />
*First look into other projects at home<br />
*Wednesday entire morning researching the drone. What do we have and how does fly? Also what software is available? (also see Problems)<br />
*Redefining Research<br />
*Research Personal Space by E. Torta --> See Research, week 3 (together with Jeroen)<br />
<br />
Problems:<br />
This week we together looked at the drone together and tried to make it fly. Also we looked at the feedback we got after out last presentation regarding our project. One of these feedback points was about other groups of previous years that had done projects with similar subjects.<br />
<br />
One project however seemed to look like a little too much like the plans we had in mind, forcing us to adjust the aim of our project. They were using the same drone, the same software to fly it and even thought of the same method for verification of the customer (NFC tag). We had two choices, either continue where the other group left off or research a different aspect of the subject. Considering we have only 2 people from ICT, 1 electrical engineer and 3 people from WTB with little programming experience, choosing the first option seemed unwise.<br />
<br />
Thus we moved our focus to the part of flying the drone as in finding a good landing spot. Also we decided to research the approaching of people by drones, since no research we were able to find did look at that for drones yet.<br />
<br />
== Week 4 ==<br />
*Working on Approaching Users<br />
*Working on Drone specifications<br />
*Performing experiment 1<br />
**Being a test subject<br />
**Taking measurements<br />
<br />
== Week 5 ==<br />
*Discussing the progression of the project<br />
**Discussing how the test setup of the autonomous landing research will look like<br />
*Second experiment<br />
**Doing the experiment<br />
**Processing the results of the experiment<br />
*Extending information that is coming in the report<br />
**Rewrite Chapter about the Users<br />
<br />
== Week 6 ==<br />
*Performing the experiments with new test subjects<br />
*Extending the description of the experiments<br />
*Rewriting State of the Art to new project aim<br />
<br />
== Week 7 ==<br />
*Revising general layout of the report</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_log_martijn&diff=25570PRE2015 3 Groep2 log martijn2016-03-21T12:34:59Z<p>S149491: /* Week 6 */</p>
<hr />
<div>== Week 1 ==<br />
*Meeting after lecture<br />
*Background research about drones for deciding on topic<br />
<br />
It was clear we wanted to do something with drones. Options for topics were:<br />
*Drones filming in a football match<br />
*Drones delivering packages at home<br />
*Drones chasing a fugitive like a police helicopter<br />
<br />
== Week 2 ==<br />
*Meeting<br />
*Rules for drones (see 'Legalisation' under 'week 2')<br />
*Presentation (preparation, I was supposed to present as well but got ill and also lost my voice)<br />
<br />
== Week 3 ==<br />
*Meeting<br />
*First look into other projects at home<br />
*Wednesday entire morning researching the drone. What do we have and how does fly? Also what software is available? (also see Problems)<br />
*Redefining Research<br />
*Research Personal Space by E. Torta --> See Research, week 3 (together with Jeroen)<br />
<br />
Problems:<br />
This week we together looked at the drone together and tried to make it fly. Also we looked at the feedback we got after out last presentation regarding our project. One of these feedback points was about other groups of previous years that had done projects with similar subjects.<br />
<br />
One project however seemed to look like a little too much like the plans we had in mind, forcing us to adjust the aim of our project. They were using the same drone, the same software to fly it and even thought of the same method for verification of the customer (NFC tag). We had two choices, either continue where the other group left off or research a different aspect of the subject. Considering we have only 2 people from ICT, 1 electrical engineer and 3 people from WTB with little programming experience, choosing the first option seemed unwise.<br />
<br />
Thus we moved our focus to the part of flying the drone as in finding a good landing spot. Also we decided to research the approaching of people by drones, since no research we were able to find did look at that for drones yet.<br />
<br />
== Week 4 ==<br />
*Working on Approaching Users<br />
*Working on Drone specifications<br />
*Performing experiment 1<br />
**Being a test subject<br />
**Taking measurements<br />
<br />
== Week 5 ==<br />
*Discussing the progression of the project<br />
**Discussing how the test setup of the autonomous landing research will look like<br />
*Second experiment<br />
**Doing the experiment<br />
**Processing the results of the experiment<br />
*Extending information that is coming in the report<br />
**Rewrite Chapter about the Users<br />
<br />
== Week 6 ==<br />
*Performing the experiments with new test subjects.<br />
*Extending the description of the experiments<br />
*Rewriting State of the Art to new project aim.<br />
<br />
== Week 7 ==<br />
*Revising general layout of the report</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_log_martijn&diff=25519PRE2015 3 Groep2 log martijn2016-03-20T14:40:38Z<p>S149491: /* Week 5 */</p>
<hr />
<div>== Week 1 ==<br />
*Meeting after lecture<br />
*Background research about drones for deciding on topic<br />
<br />
It was clear we wanted to do something with drones. Options for topics were:<br />
*Drones filming in a football match<br />
*Drones delivering packages at home<br />
*Drones chasing a fugitive like a police helicopter<br />
<br />
== Week 2 ==<br />
*Meeting<br />
*Rules for drones (see 'Legalisation' under 'week 2')<br />
*Presentation (preparation, I was supposed to present as well but got ill and also lost my voice)<br />
<br />
== Week 3 ==<br />
*Meeting<br />
*First look into other projects at home<br />
*Wednesday entire morning researching the drone. What do we have and how does fly? Also what software is available? (also see Problems)<br />
*Redefining Research<br />
*Research Personal Space by E. Torta --> See Research, week 3 (together with Jeroen)<br />
<br />
Problems:<br />
This week we together looked at the drone together and tried to make it fly. Also we looked at the feedback we got after out last presentation regarding our project. One of these feedback points was about other groups of previous years that had done projects with similar subjects.<br />
<br />
One project however seemed to look like a little too much like the plans we had in mind, forcing us to adjust the aim of our project. They were using the same drone, the same software to fly it and even thought of the same method for verification of the customer (NFC tag). We had two choices, either continue where the other group left off or research a different aspect of the subject. Considering we have only 2 people from ICT, 1 electrical engineer and 3 people from WTB with little programming experience, choosing the first option seemed unwise.<br />
<br />
Thus we moved our focus to the part of flying the drone as in finding a good landing spot. Also we decided to research the approaching of people by drones, since no research we were able to find did look at that for drones yet.<br />
<br />
== Week 4 ==<br />
*Working on Approaching Users<br />
*Working on Drone specifications<br />
*Performing experiment 1<br />
**Being a test subject<br />
**Taking measurements<br />
<br />
== Week 5 ==<br />
*Discussing the progression of the project<br />
**Discussing how the test setup of the autonomous landing research will look like<br />
*Second experiment<br />
**Doing the experiment<br />
**Processing the results of the experiment<br />
*Extending information that is coming in the report<br />
**Rewrite Chapter about the Users<br />
<br />
== Week 6 ==<br />
*Performing the experiments with new test subjects.<br />
*Extending the description of the experiments<br />
*Rewriting State of the Art to new project aim.</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25518PRE2015 3 Groep2 week62016-03-20T14:35:55Z<p>S149491: /* Can and cannot */</p>
<hr />
<div>= Further testing =<br />
NOTE: Experiments in random order.<br />
<br />
<br />
Due to limited battery time, a small adjustment has been made to the experiment to increase productivity. Instead of testing with only one test subject at the time, two people will be standing next to each other as the drone approaches them. Because of the accuracy of the drone, which is about 0.5 meter, both test subjects should feel as they are being approached by the drone. The test subjects have approved it and indicate that because the full focus is on the drone, it does not influence the results. Afterwards both test subjects are questioned separately so their opinions will not influence each other.<br />
<br />
== Experiment 2 ==<br />
<br />
=== Results A ===<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results B ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results C ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
== Analyzing results ==<br />
=== Test group ===<br />
During the experiment it wasn't possible to to the experiment on a diverse test group. As a result the conclusion of the experiment will only be valid for Dutch males, aged between 20 and 22 years and who have a technical background. If their is more time and people available who don't fall into this region, preferably females, these will be added to the results. No other test subjects will be added if these people can't be found and the results, and so the conclusion, will be based on a heavily biased test group.<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 1: A bar graph of the three ways of approaching vs. the rating. The error bars show the two-tailed 95% coincidence interval.]]<br />
<br />
=== T-test ===<br />
A T-test gives the possibility to decide if an hypotheses needs to be rejected or not <ref>Diez, D.M. Barr, C.D. Çetinkaya-Rundel, M. (2012) OpenIntro Statistics. Second Edition</ref>. The hypothese in this case are the values: 'Very bad' (1), 'Bad' (2), 'Neutral' (3), 'Good' (4) and 'Very Good' (5). A t-test will be conducted of all the hypotheses value of the different approach routes.<br />
<br />
To determine how likely a rating will occur during a specific approach, a p-value will also be computed. This value stand for the probability that an user will rate the experience a certain way. <br />
<br />
Shown in the table bellow are the p-values of the different ways of approaching. Values which are rejected by the t-test (one-tailed 95% coincidence interval, α = 0.05) are marked with an 'X'. <br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Rating<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Vertical<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | At an angle<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Horizontal<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,3739<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
|- valign="top"<br />
|}<br />
<br />
== State of the Art ==<br />
Being at the brink of being introduced, drone delivery still encounters many problems. Most of these problems are not in autonomous flying however, but mainly in the implementation of these technologies. The first companies are already using less urban areas as their test-grounds. The concept is working, but remains unreliable. The drones still have the tendency to crash into objects and the endless list of unexpected events that can possibly happen ask for a high reaction speed. Also the limited battery lifetime appears to pose problems. Below Amazon's Prime Air is described, as the leader in the current developments, followed by more general current developments and points that still are being researched on.<br />
<br />
=== Amazon Prime Air ===<br />
The leader in the current developments is the Amazon Prime Air concept from Amazon.<ref>Amazon (2016). [http://www.amazon.com/b?node=8037720011 “Amazon Prime air”]</ref> Unfortunately the drones are not ready to be embedded in society, but successful flights already have been made. One of the drones they are using is small plane that has the possibility of vertical takeoff. Flying the drone as a plane increases the speed and range of the drone, resulting in a delivery time of 30 minutes or less and a range of 24 kilometers. As the drone approaches its destination, a message is send to notify the customer that the package is arriving. The drone recognizes its destination by a big 'A' that is placed on the ground. Before lowering itself, the landing area first is scanned for obstacles. After the landing, a small valve is opened releasing the package. A second drone that is being developed is a quad-copter. This drone has a range of about 14 miles and can carry packages of about 2.5 kg. This may not seem much, be around 80% of the packages delivered by Amazon falls within this weight margin, making the likelihood of this technology being introduced in the recent future rather high. Hopes are to be able to make us of this technology around 2020.<ref>Amazon (2015), [https://www.youtube.com/watch?v=MXo_d6tNWuY Amazon Prime Air]</ref><ref>The Daily Conversation (December 2013) [https://www.youtube.com/watch?v=f2kfl4j42ac Amazon Prime Air]</ref><br />
<br />
Also Google <ref>Bradshaw, Tim (Aug 2014), [http://search.proquest.com.dianus.libr.tue.nl/docview/1565890256?pq-origsite=summon “Google tests drone deliveries in Australia”] </ref> and Walmart <ref>Kulkarni, Nitish (Oct 2015), [http://techcrunch.com/2015/10/26/walmart-drone-delivery/ “Walmart Is Looking To Get Into The Drone Delivery Game”]</ref> are joining the competition to get the first working delivery drones ready. These three competitors all want to be the first company that can use the drones, which means that a lot of research (and money) is involved. The problem those companies are working on is the reliability of the drones.<br />
<br />
=== Can and cannot ===<br />
Autonomous flying is not the main problem of technology anymore, some companies already want to carry out their autonomous drone in the near future.<ref>Qualcomm (Jan 2016),[http://allcompanies.website/2016/01/01/qualcomm-video-pronkt-drone-vliegen-in-autonome-modus/ “Qualcomm Video Pronkt Drone Vliegen in Autonome Modus”]</ref> Those companies however, are using less urban areas for testing but will not hold in busier areas. Drones need to be more reliable, they still have a tendency to crash and run into objects. Some experiments, for example from MIT, are getting better at avoiding object autonomously <ref>Conner-Simons, Adam (Oct 2015), [http://www.csail.mit.edu/drone_flies_through_forest_at_30_mph “Self-flying drone dips, darts and dives through trees at 30mph”]</ref>, but this problem is still big because of unexpected events that asks the drone to react very quick. How for example to cope with moving objects like people, animals (an enthusiastic dog for example) or flying objects (a football for example). Simply stuffing the drones with numberless sensors would drive up the price drastically, hopes are to be able to develop smart software that only uses few and or cheaper sensors to make the drones more attractive on the market.<br />
<br />
A second problem is the limited battery-life of the drones. Increasing the size of the battery would reduce the loading capacity, but a small battery again will drastically decrease the range of the drone. This would require many distribution centers, which on their turn need to be supplied as well. An alternative however is given by ###, proposing to have the battery replaced without landing.<ref>Fujii, K., Higuchi, K., Rekimoto, J. (2013), [http://ieeexplore.ieee.org.dianus.libr.tue.nl/xpls/abs_all.jsp?arnumber=6726212 “Endless Flyer: A Continuous Flying Drone with Automatic Battery Replacement”]</ref><br />
<br />
Another problem with delivery drones these days is the ‘problem of the last meters’. These last problems aren’t so much about the technology, since most of it already exists, but how to implement all these technologies to make it actually work. These problems are for example: how do we deliver packages in (high) apartment buildings and how do people (and animals) react to these kind of deliveries <ref>Frankel, Todd C. (2016), [https://www.washingtonpost.com/business/economy/biggest-obstacle-for-delivery-drones-isnt-the-technology-its-you-and-me/2016/01/06/e4cae052-aa81-11e5-9b92-dea7cd4b1a4d_story.html “Biggest obstacle for delivery drones isn’t the technology: It’s you and me"]. The Washington Post</ref>. The article from the Washington Post gives a great start to start asking questions which aren’t technical, but more to the side of users. What do we want as society? Areas where relatively less research is done, compared to the more technical side. This however is exactly what this project about, making a next step in the development of user-friendly or rather user-centered drones.<br />
<br />
= First version report =<br />
[[Media:First_version_report_group_2_quarter_3_2015-2016.pdf]]<br />
<br />
= References =<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25517PRE2015 3 Groep2 week62016-03-20T14:12:30Z<p>S149491: /* State of the Art */</p>
<hr />
<div>= Further testing =<br />
NOTE: Experiments in random order.<br />
<br />
<br />
Due to limited battery time, a small adjustment has been made to the experiment to increase productivity. Instead of testing with only one test subject at the time, two people will be standing next to each other as the drone approaches them. Because of the accuracy of the drone, which is about 0.5 meter, both test subjects should feel as they are being approached by the drone. The test subjects have approved it and indicate that because the full focus is on the drone, it does not influence the results. Afterwards both test subjects are questioned separately so their opinions will not influence each other.<br />
<br />
== Experiment 2 ==<br />
<br />
=== Results A ===<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results B ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results C ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
== Analyzing results ==<br />
=== Test group ===<br />
During the experiment it wasn't possible to to the experiment on a diverse test group. As a result the conclusion of the experiment will only be valid for Dutch males, aged between 20 and 22 years and who have a technical background. If their is more time and people available who don't fall into this region, preferably females, these will be added to the results. No other test subjects will be added if these people can't be found and the results, and so the conclusion, will be based on a heavily biased test group.<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 1: A bar graph of the three ways of approaching vs. the rating. The error bars show the two-tailed 95% coincidence interval.]]<br />
<br />
=== T-test ===<br />
A T-test gives the possibility to decide if an hypotheses needs to be rejected or not <ref>Diez, D.M. Barr, C.D. Çetinkaya-Rundel, M. (2012) OpenIntro Statistics. Second Edition</ref>. The hypothese in this case are the values: 'Very bad' (1), 'Bad' (2), 'Neutral' (3), 'Good' (4) and 'Very Good' (5). A t-test will be conducted of all the hypotheses value of the different approach routes.<br />
<br />
To determine how likely a rating will occur during a specific approach, a p-value will also be computed. This value stand for the probability that an user will rate the experience a certain way. <br />
<br />
Shown in the table bellow are the p-values of the different ways of approaching. Values which are rejected by the t-test (one-tailed 95% coincidence interval, α = 0.05) are marked with an 'X'. <br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Rating<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Vertical<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | At an angle<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Horizontal<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,3739<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
|- valign="top"<br />
|}<br />
<br />
== State of the Art ==<br />
Being at the brink of being introduced, drone delivery still encounters many problems. Most of these problems are not in autonomous flying however, but mainly in the implementation of these technologies. The first companies are already using less urban areas as their test-grounds. The concept is working, but remains unreliable. The drones still have the tendency to crash into objects and the endless list of unexpected events that can possibly happen ask for a high reaction speed. Also the limited battery lifetime appears to pose problems. Below Amazon's Prime Air is described, as the leader in the current developments, followed by more general current developments and points that still are being researched on.<br />
<br />
=== Amazon Prime Air ===<br />
The leader in the current developments is the Amazon Prime Air concept from Amazon.<ref>Amazon (2016). [http://www.amazon.com/b?node=8037720011 “Amazon Prime air”]</ref> Unfortunately the drones are not ready to be embedded in society, but successful flights already have been made. One of the drones they are using is small plane that has the possibility of vertical takeoff. Flying the drone as a plane increases the speed and range of the drone, resulting in a delivery time of 30 minutes or less and a range of 24 kilometers. As the drone approaches its destination, a message is send to notify the customer that the package is arriving. The drone recognizes its destination by a big 'A' that is placed on the ground. Before lowering itself, the landing area first is scanned for obstacles. After the landing, a small valve is opened releasing the package. A second drone that is being developed is a quad-copter. This drone has a range of about 14 miles and can carry packages of about 2.5 kg. This may not seem much, be around 80% of the packages delivered by Amazon falls within this weight margin, making the likelihood of this technology being introduced in the recent future rather high. Hopes are to be able to make us of this technology around 2020.<ref>Amazon (2015), [https://www.youtube.com/watch?v=MXo_d6tNWuY Amazon Prime Air]</ref><ref>The Daily Conversation (December 2013) [https://www.youtube.com/watch?v=f2kfl4j42ac Amazon Prime Air]</ref><br />
<br />
Also Google <ref>Bradshaw, Tim (Aug 2014), [http://search.proquest.com.dianus.libr.tue.nl/docview/1565890256?pq-origsite=summon “Google tests drone deliveries in Australia”] </ref> and Walmart <ref>Kulkarni, Nitish (Oct 2015), [http://techcrunch.com/2015/10/26/walmart-drone-delivery/ “Walmart Is Looking To Get Into The Drone Delivery Game”]</ref> are joining the competition to get the first working delivery drones ready. These three competitors all want to be the first company that can use the drones, which means that a lot of research (and money) is involved. The problem those companies are working on is the reliability of the drones.<br />
<br />
=== Can and cannot ===<br />
They say that autonomous flying is not the main problem of technology anymore, some companies already want to carry out their autonomous drone in the near future <ref>Qualcomm (Jan 2016),[http://allcompanies.website/2016/01/01/qualcomm-video-pronkt-drone-vliegen-in-autonome-modus/ “Qualcomm Video Pronkt Drone Vliegen in Autonome Modus”]</ref>. Those companies however, are using less urban areas (our second case) for testing and we are curious about how their drones are going to hold in our first case. Drones need to be more reliable, they still have a tendency to crash and run into objects. Some experiments, for example from MIT, are getting better at avoiding object autonomously <ref>Conner-Simons, Adam (Oct 2015), [http://www.csail.mit.edu/drone_flies_through_forest_at_30_mph “Self-flying drone dips, darts and dives through trees at 30mph”]</ref>, but this problem is still big because of unexpected events that asks the drone to react very quick.<br />
<br />
The problem with the battery-life as given above can, for example, be fixed (maybe until there are better batteries) by changing the battery of the delivery drone in the air <ref>Fujii, K., Higuchi, K., Rekimoto, J. (2013), [http://ieeexplore.ieee.org.dianus.libr.tue.nl/xpls/abs_all.jsp?arnumber=6726212 “Endless Flyer: A Continuous Flying Drone with Automatic Battery Replacement”]</ref>.<br />
<br />
Another problem with delivery drones these days is the ‘problem of the last meters’. These last problems aren’t so much about the technology, since most of it already exists, but how to implement all these technologies to make it actually work. These problems are for example: how do we deliver packages in (high) apartment buildings and how do people (and animals) react to these kind of deliveries <ref>Frankel, Todd C. (2016), [https://www.washingtonpost.com/business/economy/biggest-obstacle-for-delivery-drones-isnt-the-technology-its-you-and-me/2016/01/06/e4cae052-aa81-11e5-9b92-dea7cd4b1a4d_story.html “Biggest obstacle for delivery drones isn’t the technology: It’s you and me"]. The Washington Post</ref>. The article from the Washington Post gives a great start to start asking questions which aren’t technical, but more to the side of users. What do we want as society?<br />
<br />
= First version report =<br />
[[Media:First_version_report_group_2_quarter_3_2015-2016.pdf]]<br />
<br />
= References =<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25513PRE2015 3 Groep2 week62016-03-20T13:39:34Z<p>S149491: /* State of the Art */</p>
<hr />
<div>= Further testing =<br />
NOTE: Experiments in random order.<br />
<br />
<br />
Due to limited battery time, a small adjustment has been made to the experiment to increase productivity. Instead of testing with only one test subject at the time, two people will be standing next to each other as the drone approaches them. Because of the accuracy of the drone, which is about 0.5 meter, both test subjects should feel as they are being approached by the drone. The test subjects have approved it and indicate that because the full focus is on the drone, it does not influence the results. Afterwards both test subjects are questioned separately so their opinions will not influence each other.<br />
<br />
== Experiment 2 ==<br />
<br />
=== Results A ===<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results B ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results C ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
== Analyzing results ==<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 1: A bar graph of the three ways of approaching vs. the rating. The error bars show the two-tailed 95% coincidence interval.]]<br />
=== T-test ===<br />
A T-test gives the possibility to decide if an hypotheses needs to be rejected or not <ref>Diez, D.M. Barr, C.D. Çetinkaya-Rundel, M. (2012) OpenIntro Statistics. Second Edition</ref>. The hypothese in this case are the values: 'Very bad' (1), 'Bad' (2), 'Neutral' (3), 'Good' (4) and 'Very Good' (5). A t-test will be conducted of all the hypotheses value of the different approach routes.<br />
<br />
To determine how likely a rating will occur during a specific approach, a p-value will also be computed. This value stand for the probability that an user will rate the experience a certain way. <br />
<br />
Shown in the table bellow are the p-values of the different ways of approaching. Values which are rejected by the t-test (one-tailed 95% coincidence interval, α = 0.05) are marked with an 'X'. <br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Rating<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Vertical<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | At an angle<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Horizontal<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,3739<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
|- valign="top"<br />
|}<br />
<br />
== State of the Art ==<br />
Being at the brink of being introduced, drone delivery still encounters many problems. Most of these problems are not in autonomous flying however, but mainly in the implementation of these technologies. The first companies are already using less urban areas as their test-grounds. The concept is working, but remains unreliable. The drones still have the tendency to crash into objects and the endless list of unexpected events that can possibly happen ask for a high reaction speed. Also the limited battery lifetime appears to pose problems. Below the pioneers and their progress so far is described.<br />
<br />
The leader in the current developments is the Amazon Prime Air concept from Amazon.<ref>Amazon (2016). [http://www.amazon.com/b?node=8037720011 “Amazon Prime air”]</ref> Unfortunately the drones are not ready to be embedded in society, but successful flights already have been made. One of the drones they are using is small plane that has the possibility of vertical takeoff. Flying the drone as a plane increases the speed and range of the drone, resulting in a delivery time of 30 minutes or less and a range of 24 kilometers. As the drone approaches its destination, a message is send to notify the customer that the package is arriving. The drone recognizes its destination by a big 'A' that is placed on the ground. Before lowering itself, the landing area first is scanned for obstacles. After the landing, a small valve is opened releasing the package. A second drone that is being developed is a quad-copter. This drone has a range of about 14 miles and can carry packages of about 2.5 kg. This may not seem much, be around 80% of the packages delivered by Amazon falls within this weight margin, making the likelihood of this technology being introduced in the recent future rather high. Hopes are to be able to make us of this technology around 2020.<ref>Amazon (2015), [https://www.youtube.com/watch?v=MXo_d6tNWuY Amazon Prime Air]</ref><ref>The Daily Conversation (December 2013) [https://www.youtube.com/watch?v=f2kfl4j42ac Amazon Prime Air]</ref><br />
<br />
= First version report =<br />
[[Media:First_version_report_group_2_quarter_3_2015-2016.pdf]]<br />
<br />
= References =<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25512PRE2015 3 Groep2 week62016-03-20T13:38:02Z<p>S149491: /* State of the Art */</p>
<hr />
<div>= Further testing =<br />
NOTE: Experiments in random order.<br />
<br />
<br />
Due to limited battery time, a small adjustment has been made to the experiment to increase productivity. Instead of testing with only one test subject at the time, two people will be standing next to each other as the drone approaches them. Because of the accuracy of the drone, which is about 0.5 meter, both test subjects should feel as they are being approached by the drone. The test subjects have approved it and indicate that because the full focus is on the drone, it does not influence the results. Afterwards both test subjects are questioned separately so their opinions will not influence each other.<br />
<br />
== Experiment 2 ==<br />
<br />
=== Results A ===<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results B ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results C ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
== Analyzing results ==<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 1: A bar graph of the three ways of approaching vs. the rating. The error bars show the two-tailed 95% coincidence interval.]]<br />
=== T-test ===<br />
A T-test gives the possibility to decide if an hypotheses needs to be rejected or not <ref>Diez, D.M. Barr, C.D. Çetinkaya-Rundel, M. (2012) OpenIntro Statistics. Second Edition</ref>. The hypothese in this case are the values: 'Very bad' (1), 'Bad' (2), 'Neutral' (3), 'Good' (4) and 'Very Good' (5). A t-test will be conducted of all the hypotheses value of the different approach routes.<br />
<br />
To determine how likely a rating will occur during a specific approach, a p-value will also be computed. This value stand for the probability that an user will rate the experience a certain way. <br />
<br />
Shown in the table bellow are the p-values of the different ways of approaching. Values which are rejected by the t-test (one-tailed 95% coincidence interval, α = 0.05) are marked with an 'X'. <br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Rating<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Vertical<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | At an angle<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Horizontal<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,3739<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
|- valign="top"<br />
|}<br />
<br />
== State of the Art ==<br />
Being at the brink of being introduced, drone delivery still encounters many problems. Most of these problems are not in autonomous flying however, but mainly in the implementation of these technologies. The first companies are already using less urban areas as their test-grounds. The concept is working, but remains unreliable. The drones still have the tendency to crash into objects and the endless list of unexpected events that can possibly happen ask for a high reaction speed. Also the limited battery lifetime appears to pose problems. Below the pioneers and their progress so far is described.<br />
<br />
The leader in the current developments is the Amazon Prime Air concept from Amazon.<ref>Amazon (2016). [http://www.amazon.com/b?node=8037720011 “Amazon Prime air”]</ref> Unfortunately this is still a concept, but successful flights already have been made. One of the drones they are using is small plane that has the possibility of vertical takeoff. Flying the drone as a plane increases the speed and range of the drone, resulting in a delivery time of 30 minutes or less and a range of 24 kilometers. As the drone approaches its destination, a message is send to notify the customer that the package is arriving. The drone recognizes its destination by a big 'A' that is placed on the ground. Before lowering itself, the landing area first is scanned for obstacles. After the landing, a small valve is opened releasing the package. A second drone that is being developed is a quad-copter. This drone has a range of about 14 miles and can carry packages of about 2.5 kg. This may not seem much, be around 80% of the packages delivered by Amazon falls within this weight margin, making the likelihood of this technology being introduced in the recent future rather high. Hopes are to be able to make us of this technology around 2020.<ref>Amazon (2015), [https://www.youtube.com/watch?v=MXo_d6tNWuY Amazon Prime Air]</ref><ref>The Daily Conversation (December 2013) [https://www.youtube.com/watch?v=f2kfl4j42ac Amazon Prime Air]</ref><br />
<br />
= First version report =<br />
[[Media:First_version_report_group_2_quarter_3_2015-2016.pdf]]<br />
<br />
= References =<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25511PRE2015 3 Groep2 week62016-03-20T13:36:12Z<p>S149491: /* State of the Art */</p>
<hr />
<div>= Further testing =<br />
NOTE: Experiments in random order.<br />
<br />
<br />
Due to limited battery time, a small adjustment has been made to the experiment to increase productivity. Instead of testing with only one test subject at the time, two people will be standing next to each other as the drone approaches them. Because of the accuracy of the drone, which is about 0.5 meter, both test subjects should feel as they are being approached by the drone. The test subjects have approved it and indicate that because the full focus is on the drone, it does not influence the results. Afterwards both test subjects are questioned separately so their opinions will not influence each other.<br />
<br />
== Experiment 2 ==<br />
<br />
=== Results A ===<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results B ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results C ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
== Analyzing results ==<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 1: A bar graph of the three ways of approaching vs. the rating. The error bars show the two-tailed 95% coincidence interval.]]<br />
=== T-test ===<br />
A T-test gives the possibility to decide if an hypotheses needs to be rejected or not <ref>Diez, D.M. Barr, C.D. Çetinkaya-Rundel, M. (2012) OpenIntro Statistics. Second Edition</ref>. The hypothese in this case are the values: 'Very bad' (1), 'Bad' (2), 'Neutral' (3), 'Good' (4) and 'Very Good' (5). A t-test will be conducted of all the hypotheses value of the different approach routes.<br />
<br />
To determine how likely a rating will occur during a specific approach, a p-value will also be computed. This value stand for the probability that an user will rate the experience a certain way. <br />
<br />
Shown in the table bellow are the p-values of the different ways of approaching. Values which are rejected by the t-test (one-tailed 95% coincidence interval, α = 0.05) are marked with an 'X'. <br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Rating<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Vertical<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | At an angle<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Horizontal<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,3739<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
|- valign="top"<br />
|}<br />
<br />
== State of the Art ==<br />
Being at the brink of being introduced, drone delivery still encounters many problems. Most of these problems are not in autonomous flying however, but mainly in the implementation of these technologies. The first companies are already using less urban areas as their test-grounds. The concept is working, but remains unreliable. The drones still have the tendency to crash into objects and the endless list of unexpected events that can possibly happen ask for a high reaction speed. Also the limited battery lifetime appears to pose problems. Below the pioneers and their progress so far is described.<br />
<br />
The leader in the current developments is the Amazon Prime Air concept from Amazon.<ref>Amazon (2016). [http://www.amazon.com/b?node=8037720011 “Amazon Prime air”]</ref> Unfortunately this is still a concept, but successful flights already have been made. One of the drones they are using is small plane that has the possibility of vertical takeoff. Flying the drone as a plane increases the speed and range of the drone, resulting in a delivery time of 30 minutes or less and a range of 24 kilometers. As the drone approaches its destination, a message is send to notify the customer that the package is arriving. The drone recognizes its destination by a big 'A' that is placed on the ground. Before lowering itself, the landing area first is scanned for obstacles. After the landing, a small valve is opened releasing the package. A second drone that is being developed is a quad-copter. This drone has a range of about 14 miles and can carry packages of about 2.5 kg. This may not seem much, be around 80% of the packages delivered by Amazon falls within this weight margin, making the likelihood of this technology being introduced in the recent future rather high. Hopes are to be able to make us of this technology around 2020.<ref>Amazon, [https://www.youtube.com/watch?v=MXo_d6tNWuY Amazon Prime Air]</ref><ref>The Daily Conversation [https://www.youtube.com/watch?v=f2kfl4j42ac Amazon Prime Air]</ref><br />
<br />
= First version report =<br />
[[Media:First_version_report_group_2_quarter_3_2015-2016.pdf]]<br />
<br />
= References =<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week1&diff=25510PRE2015 3 Groep2 week12016-03-20T13:35:59Z<p>S149491: /* Legislature */</p>
<hr />
<div>{{DISPLAYTITLE:Week 1 - The idea}}<br />
<br />
== The idea and State of the Art ==<br />
Drones can take goods that are ordered from the storage to somebodies house. The delivery is quick and orders can be handled a lot faster. This way, delivery companies can handle more orders at a higher rate. But people also get the items they have ordered really quick, which helps the satisfaction. We will distinguish two cases, in the first case drones that are used in urban areas, need to be navigated by a drone pilot, for safety reasons, since autonomous flying is not yet that advanced to safely navigate through crowded urban areas. The second case is where drones can potentially fly autonomously in rural areas or less urban areas. In both cases the drone can autonomously execute the landing when a landing zone is insight that is not obstructed.<br />
<br />
They say that autonomous flying is not the main problem of technology anymore, some companies already want to carry out their autonomous drone in the near future <ref>Qualcomm (Jan 2016),[http://allcompanies.website/2016/01/01/qualcomm-video-pronkt-drone-vliegen-in-autonome-modus/ “Qualcomm Video Pronkt Drone Vliegen in Autonome Modus”]</ref>. Those companies however, are using less urban areas (our second case) for testing and we are curious about how their drones are going to hold in our first case. Drones need to be more reliable, they still have a tendency to crash and run into objects. Some experiments, for example from MIT, are getting better at avoiding object autonomously <ref>Conner-Simons, Adam (Oct 2015), [http://www.csail.mit.edu/drone_flies_through_forest_at_30_mph “Self-flying drone dips, darts and dives through trees at 30mph”]</ref>, but this problem is still big because of unexpected events that asks the drone to react very quick. Energy consumption could also be a problem <ref>Stolaroff, K. (2014), “The Need for a Life Cycle Assessment of Drone-Based Commercial Package Delivery”.</ref>. For long flights the drones need large batteries, but bigger batteries also means less space for cargo. <br />
<br />
Another problem with delivery drones these days is the ‘problem of the last meters’. These last problems aren’t so much about the technology, since most of it already exists, but how to implement all these technologies to make it actually work. These problems are for example: how do we deliver packages in (high) apartment buildings and how do people (and animals) react to these kind of deliveries <ref>Frankel, Todd C. (2016), [https://www.washingtonpost.com/business/economy/biggest-obstacle-for-delivery-drones-isnt-the-technology-its-you-and-me/2016/01/06/e4cae052-aa81-11e5-9b92-dea7cd4b1a4d_story.html “Biggest obstacle for delivery drones isn’t the technology: It’s you and me"]. The Washington Post</ref>. The article from the Washington Post gives a great start to start asking questions which aren’t technical, but more to the side of users. What do we want as society?<br />
<br />
The problem with the battery-life as given above can, for example, be fixed (maybe until there are better batteries) by changing the battery of the delivery drone in the air <ref>Fujii, K., Higuchi, K., Rekimoto, J. (2013), [http://ieeexplore.ieee.org.dianus.libr.tue.nl/xpls/abs_all.jsp?arnumber=6726212 “Endless Flyer: A Continuous Flying Drone with Automatic Battery Replacement”]</ref>. The concept Amazon Prime Air is the best example of the given idea <ref>Amazon (2016). [http://www.amazon.com/b?node=8037720011 “Amazon Prime air”]</ref>, which is (unfortunately) still a concept and not working yet. Also Google <ref>Bradshaw, Tim (Aug 2014), [http://search.proquest.com.dianus.libr.tue.nl/docview/1565890256?pq-origsite=summon “Google tests drone deliveries in Australia”] </ref> and Walmart <ref>Kulkarni, Nitish (Oct 2015), [http://techcrunch.com/2015/10/26/walmart-drone-delivery/ “Walmart Is Looking To Get Into The Drone Delivery Game”]</ref> are joining the competition to get the first working delivery drones ready. These three competitors all want to be the first company that can use the drones, which means that a lot of research (and money) is involved. The problem those companies are working on is the reliability of the drones.<br />
<br />
Our idea is to look at drones and find out what the best human interaction is when they want to land. Do the buyers have to put an big A in their garden? How does this work if you live on the 3rd floor? What if the neighbors also bought a package that is due at the same time? Maybe we don’t need the pilots, but we can let the buyers fly their own package the last meters? Are the buyers home at the time the package arrives? all those questions together, what can we expect from buyers and how are we going to interact with them to let the landing go smooth?<br />
<br />
== USE/Impact → who is benefiting? ==<br />
=== Primary user ===<br />
*Consumers, people who order online<br />
*Drone pilots<br />
<br />
=== Secondary users ===<br />
*Companies and shopkeepers<br />
*Drone developers<br />
*Drone manufacturers<br />
*Legislature<br />
<br />
=== Tertiary users ===<br />
*Mechanics<br />
*Safety instances (in case of accidents)<br />
*People walking/using the streets<br />
*Other airspace users<br />
<br />
== Needs of those users ==<br />
=== Consumers ===<br />
The consumers demand fast, trustworthy and safe delivery of their packages. Note that fast delivery is not necessarily a need, more than a wish or desire. Also no discrete value can be given to what is considered as fast delivery. Trustworthy delivery means the guarantee that the package is delivered withing the agreed time limit without huge delays or high chance of cancellation.<br />
<br />
Safe delivery covers several parts. First the guarantee that the package arrives without being damaged during its trip. Second comes the guarantee that the package is not stole on the way. Last comes the demand that no damage is done by the drone to any property of the consumer during the landing.<br />
<br />
=== Drone pilots ===<br />
Pilots that will navigate the drones, will need adequate training and specialization to be able to safely navigate these drones through public airspace, especially in urban environments. A training facility is therefore needed and an organization that supplies drone pilot licenses will be needed. In areas with few tall buildings, autonomous drones might be used.<br />
<br />
=== Companies and shopkeepers ===<br />
Companies and shopkeepers will be the ones providing the service of drone delivery. Therefor they will take a large portion of the responsibility for the drones. Their needs will lay in reliability of the drones as well as flexibility. With flexibility, in this case, being able to fly long distances or multiple flights after each other without (long) charging is meant.<br />
Another important need for companies is for the drones to be cheap, or at least affordable. A right balance between price and quality must be found. Also for they are to provide the service to the consumers, consumers needs automatically become needs for companies and shopkeepers as well.<br />
<br />
=== Drone developers and manufacturers ===<br />
Of course with the increasing use of drones, companies will be able to make money with it. Also new developments will be stimulated. For companies producing drones the ease of producing will be an important need as well as the expense of separate parts. These parts need to be modular in order to customize the drone to fit its environment to optimize flying conditions. Furthermore, when parts become interchangeable, drones can be quickly repaired and upgraded without altering the core parts for future use. <br />
<br />
=== Legislature ===<br />
New legislation must be designated that describes in which environments drones are allowed to navigate autonomously and in which areas it is unsafe to do this. Also a consensus about safe flying altitudes for drones must be established. Rules and requirements for a drone pilot license need to determined. During flights where drones are operating autonomously, liability becomes an important obstacle since it is not clear who should take responsibility in an accident. <br />
<br />
Generally, taking full responsibility as the drone producer can be seen as a generous gesture towards customers and will also push the development of autonomous vehicles onto the main audience. Other autonomous machine producers have already done so: “Volvo, Google and Mercedes have now all said that they will accept full liability if their self-driving vehicles cause a collision”.<ref>S.Elmer, Autoguide (Oct 2015), [http://www.autoguide.com/auto-news/2015/10/volvo-google-and-mercedes-to-accept-responsibility-in-self-driving-car-collisions.html “Volvo, Google and Mercedes to Accept Responsibility in Self-Driving Car Collisions”]<br />
</ref><br />
<br />
=== Mechanics ===<br />
Easy to repair or preform maintenance as well as safety doing so, due the fact that the drone parts are produced in a modular fashion. This makes it also cheap and environment friendly since it produces less waste as you only need to throw away the broken part instead of the whole package.<br />
<br />
=== Safety instances ===<br />
A need or wish for safety instances it to have the drones to be able to fly without accidents, for their priority is to provide a safe living environment. And in case of an accident, which will unfortunately be inevitable, the damage must be minimal.<br />
<br />
=== People walking/using the streets ===<br />
The main need for these people concerning drone delivery is to be able to walk the streets safely without the fear or risk of an accident.<br />
Other airspace users<br />
<br />
Tight regulation of the airspace to keep the accidents to a minimum or preventive mechanisms to avoid them. Drones should only be allowed to fly at certain safe altitudes that do not interfere with air crafts and helicopters, moreover drones should not be allowed to fly next to locations like airports, since that can result in a dangerous situation that can lead to crashes with commercial airliners.<br />
<br />
== Scenario ==<br />
Eindhoven University of Technology (TU/e) is planning to start a centralized shop to save some money. In this shop product for educational use, i.e. lecture notes, college blocks and pencils, can be bought by the students and employees. It is also possible to print out reports and let them be bound. It will also be possible to borrow electronical devices, i.e. projectors, presenters and measuring equipment. The regulations and prices of this new shop will be the same as it is today in the local shops and borrow points.<br />
<br />
The direction of the university is only afraid that some student and employees will complain, since all the local shops and borrow points will disappear. It is decided that the location of this shop will be in the MetaForum, this location is in the center of the campus and is easy to find. The board also has another idea: delivery by drone. To make even the laziest student and employees happy, your package will be delivered to your office and, if you live in Eindhoven, to your front door. All free of charge of course. The delivery time on campus will be at the most 5 minutes and in the rest of the city 20 minutes.<br />
<br />
In a real world situation apartment complexes are seen as the buildings on campus. Suburban areas, i.e. houses with gardens, are seen as the rest of the delivery location in Eindhoven.<br />
<br />
The costumer is able to follow his/her package on the website or the app of the shop. Here the costumer can find the location of the package and how long it will take before it arrives. If the user can’t be on the place of delivery at the given delivery time, the user can change the delivery location. When the drone with the package hasn’t left the MetaForum it’s also possible to put the delivery on hold. The package will then be delivered when the costumer says it can be on the delivery location on the given time.<br />
<br />
From the start the new system has been quite popular. The students and staff of the TU/e have not jet experienced difficulties using the system. The management is even trying to expand the service to the cafeteria. Also other universities have shown interested in using this system at their own universities.<br />
<br />
== References ==<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25509PRE2015 3 Groep2 week62016-03-20T13:30:06Z<p>S149491: /* State of the Art */</p>
<hr />
<div>= Further testing =<br />
NOTE: Experiments in random order.<br />
<br />
<br />
Due to limited battery time, a small adjustment has been made to the experiment to increase productivity. Instead of testing with only one test subject at the time, two people will be standing next to each other as the drone approaches them. Because of the accuracy of the drone, which is about 0.5 meter, both test subjects should feel as they are being approached by the drone. The test subjects have approved it and indicate that because the full focus is on the drone, it does not influence the results. Afterwards both test subjects are questioned separately so their opinions will not influence each other.<br />
<br />
== Experiment 2 ==<br />
<br />
=== Results A ===<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results B ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results C ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
== Analyzing results ==<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 1: A bar graph of the three ways of approaching vs. the rating. The error bars show the two-tailed 95% coincidence interval.]]<br />
=== T-test ===<br />
A T-test gives the possibility to decide if an hypotheses needs to be rejected or not <ref>Diez, D.M. Barr, C.D. Çetinkaya-Rundel, M. (2012) OpenIntro Statistics. Second Edition</ref>. The hypothese in this case are the values: 'Very bad' (1), 'Bad' (2), 'Neutral' (3), 'Good' (4) and 'Very Good' (5). A t-test will be conducted of all the hypotheses value of the different approach routes.<br />
<br />
To determine how likely a rating will occur during a specific approach, a p-value will also be computed. This value stand for the probability that an user will rate the experience a certain way. <br />
<br />
Shown in the table bellow are the p-values of the different ways of approaching. Values which are rejected by the t-test (one-tailed 95% coincidence interval, α = 0.05) are marked with an 'X'. <br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Rating<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Vertical<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | At an angle<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Horizontal<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,3739<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
|- valign="top"<br />
|}<br />
<br />
== State of the Art ==<br />
Being at the brink of being introduced, drone delivery still encounters many problems. Most of these problems are not in autonomous flying however, but mainly in the implementation of these technologies. The first companies are already using less urban areas as their test-grounds. The concept is working, but remains unreliable. The drones still have the tendency to crash into objects and the endless list of unexpected events that can possibly happen ask for a high reaction speed. Also the limited battery lifetime appears to pose problems. Below the pioneers and their progress so far is described.<br />
<br />
The leader in the current developments is the Amazon Prime Air concept from Amazon.<ref>Amazon (2016). [http://www.amazon.com/b?node=8037720011 “Amazon Prime air”]</ref> Unfortunately this is still a concept, but successful flights already have been made. The drone they are using is small plane that has the possibility of vertical takeoff. Flying the drone as a plane increases the speed and range of the drone, resulting in a delivery time of 30 minutes or less and a range of 24 kilometers. As the drone approaches its destination, a message is send to notify the customer that the package is arriving. The drone recognizes its destination by a big 'A' that is placed on the ground. Before lowering itself, the landing area first is scanned for obstacles. After the landing, a small valve is opened releasing the package. Hopes are to be able to make us of this technology around 2020.<ref>Amazon, [https://www.youtube.com/watch?v=MXo_d6tNWuY Amazon Prime Air]</ref><ref>The Daily Conversation [https://www.youtube.com/watch?v=f2kfl4j42ac Amazon Prime Air]</ref><br />
<br />
= First version report =<br />
[[Media:First_version_report_group_2_quarter_3_2015-2016.pdf]]<br />
<br />
= References =<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25508PRE2015 3 Groep2 week62016-03-20T13:28:57Z<p>S149491: /* State of the Art */</p>
<hr />
<div>= Further testing =<br />
NOTE: Experiments in random order.<br />
<br />
<br />
Due to limited battery time, a small adjustment has been made to the experiment to increase productivity. Instead of testing with only one test subject at the time, two people will be standing next to each other as the drone approaches them. Because of the accuracy of the drone, which is about 0.5 meter, both test subjects should feel as they are being approached by the drone. The test subjects have approved it and indicate that because the full focus is on the drone, it does not influence the results. Afterwards both test subjects are questioned separately so their opinions will not influence each other.<br />
<br />
== Experiment 2 ==<br />
<br />
=== Results A ===<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results B ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results C ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
== Analyzing results ==<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 1: A bar graph of the three ways of approaching vs. the rating. The error bars show the two-tailed 95% coincidence interval.]]<br />
=== T-test ===<br />
A T-test gives the possibility to decide if an hypotheses needs to be rejected or not <ref>Diez, D.M. Barr, C.D. Çetinkaya-Rundel, M. (2012) OpenIntro Statistics. Second Edition</ref>. The hypothese in this case are the values: 'Very bad' (1), 'Bad' (2), 'Neutral' (3), 'Good' (4) and 'Very Good' (5). A t-test will be conducted of all the hypotheses value of the different approach routes.<br />
<br />
To determine how likely a rating will occur during a specific approach, a p-value will also be computed. This value stand for the probability that an user will rate the experience a certain way. <br />
<br />
Shown in the table bellow are the p-values of the different ways of approaching. Values which are rejected by the t-test (one-tailed 95% coincidence interval, α = 0.05) are marked with an 'X'. <br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Rating<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Vertical<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | At an angle<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Horizontal<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,3739<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
|- valign="top"<br />
|}<br />
<br />
== State of the Art ==<br />
Being at the brink of being introduced, drone delivery still encounters many problems. Most of these problems are not in autonomous flying however, but mainly in the implementation of these technologies. The first companies are already using less urban areas as their test-grounds. The concept is working, but remains unreliable. The drones still have the tendency to crash into objects and the endless list of unexpected events that can possibly happen ask for a high reaction speed. Also the limited battery lifetime appears to pose problems. Below the pioneers and their progress so far is described.<br />
<br />
The leader in the current developments is the Amazon Prime Air concept from Amazon.<ref>Amazon (2016). [http://www.amazon.com/b?node=8037720011 “Amazon Prime air”]</ref> Unfortunately this is still a concept, but the hopes are high. The drone they are using is small plane that has the possibility of vertical takeoff. Flying the drone as a plane increases the speed and range of the drone, resulting in a delivery time of 30 minutes or less and a range of 24 kilometers. As the drone approaches its destination, a message is send to notify the customer that the package is arriving. The drone recognizes its destination by a big 'A' that is placed on the ground. Before lowering itself, the landing area first is scanned for obstacles. After the landing, a small valve is opened releasing the package. Hopes are to be able to make us of this technology around 2020.<ref>Amazon, [https://www.youtube.com/watch?v=MXo_d6tNWuY Amazon Prime Air]</ref><ref>The Daily Conversation [https://www.youtube.com/watch?v=f2kfl4j42ac Amazon Prime Air]</ref><br />
<br />
= First version report =<br />
[[Media:First_version_report_group_2_quarter_3_2015-2016.pdf]]<br />
<br />
= References =<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25507PRE2015 3 Groep2 week62016-03-20T13:27:53Z<p>S149491: /* State of the Art */</p>
<hr />
<div>= Further testing =<br />
NOTE: Experiments in random order.<br />
<br />
<br />
Due to limited battery time, a small adjustment has been made to the experiment to increase productivity. Instead of testing with only one test subject at the time, two people will be standing next to each other as the drone approaches them. Because of the accuracy of the drone, which is about 0.5 meter, both test subjects should feel as they are being approached by the drone. The test subjects have approved it and indicate that because the full focus is on the drone, it does not influence the results. Afterwards both test subjects are questioned separately so their opinions will not influence each other.<br />
<br />
== Experiment 2 ==<br />
<br />
=== Results A ===<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results B ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results C ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
== Analyzing results ==<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 1: A bar graph of the three ways of approaching vs. the rating. The error bars show the two-tailed 95% coincidence interval.]]<br />
=== T-test ===<br />
A T-test gives the possibility to decide if an hypotheses needs to be rejected or not <ref>Diez, D.M. Barr, C.D. Çetinkaya-Rundel, M. (2012) OpenIntro Statistics. Second Edition</ref>. The hypothese in this case are the values: 'Very bad' (1), 'Bad' (2), 'Neutral' (3), 'Good' (4) and 'Very Good' (5). A t-test will be conducted of all the hypotheses value of the different approach routes.<br />
<br />
To determine how likely a rating will occur during a specific approach, a p-value will also be computed. This value stand for the probability that an user will rate the experience a certain way. <br />
<br />
Shown in the table bellow are the p-values of the different ways of approaching. Values which are rejected by the t-test (one-tailed 95% coincidence interval, α = 0.05) are marked with an 'X'. <br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Rating<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Vertical<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | At an angle<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Horizontal<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,3739<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
|- valign="top"<br />
|}<br />
<br />
== State of the Art ==<br />
Being at the brink of being introduced, drone delivery still encounters many problems. Most of these problems are not in autonomous flying however, but mainly in the implementation of these technologies. The first companies are already using less urban areas as their test-grounds. The concept is working, but remains unreliable. The drones still have the tendency to crash into objects and the endless list of unexpected events that can possibly happen ask for a high reaction speed. Also the limited battery lifetime appears to pose problems. Below the pioneers and their progress so far is described.<br />
<br />
The leader in the current developments is the Amazon Prime Air concept from Amazon.<ref>Amazon (2016). [http://www.amazon.com/b?node=8037720011 “Amazon Prime air”]</ref> Unfortunately this is still a concept, but the hopes are high. The drone they are using is small plane that has the possibility of vertical takeoff. Flying the drone as a plane increases the speed and range of the drone, resulting in a delivery time of 30 minutes or less and a range of 24 kilometers. As the drone approaches its destination, a message is send to notify the customer that the package is arriving. The drone recognizes its destination by a big 'A' that is placed on the ground. Before lowering itself, the landing area first is scanned for obstacles. After the landing, a small valve is opened releasing the package. Hopes are to be able to make us of this technology around 2020.<ref>The Daily Conversation [https://www.youtube.com/watch?v=f2kfl4j42ac Amazon Prime Air]</ref><br />
<br />
= First version report =<br />
[[Media:First_version_report_group_2_quarter_3_2015-2016.pdf]]<br />
<br />
= References =<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week1&diff=25506PRE2015 3 Groep2 week12016-03-20T12:36:11Z<p>S149491: /* The idea and State of the Art */</p>
<hr />
<div>{{DISPLAYTITLE:Week 1 - The idea}}<br />
<br />
== The idea and State of the Art ==<br />
Drones can take goods that are ordered from the storage to somebodies house. The delivery is quick and orders can be handled a lot faster. This way, delivery companies can handle more orders at a higher rate. But people also get the items they have ordered really quick, which helps the satisfaction. We will distinguish two cases, in the first case drones that are used in urban areas, need to be navigated by a drone pilot, for safety reasons, since autonomous flying is not yet that advanced to safely navigate through crowded urban areas. The second case is where drones can potentially fly autonomously in rural areas or less urban areas. In both cases the drone can autonomously execute the landing when a landing zone is insight that is not obstructed.<br />
<br />
They say that autonomous flying is not the main problem of technology anymore, some companies already want to carry out their autonomous drone in the near future <ref>Qualcomm (Jan 2016),[http://allcompanies.website/2016/01/01/qualcomm-video-pronkt-drone-vliegen-in-autonome-modus/ “Qualcomm Video Pronkt Drone Vliegen in Autonome Modus”]</ref>. Those companies however, are using less urban areas (our second case) for testing and we are curious about how their drones are going to hold in our first case. Drones need to be more reliable, they still have a tendency to crash and run into objects. Some experiments, for example from MIT, are getting better at avoiding object autonomously <ref>Conner-Simons, Adam (Oct 2015), [http://www.csail.mit.edu/drone_flies_through_forest_at_30_mph “Self-flying drone dips, darts and dives through trees at 30mph”]</ref>, but this problem is still big because of unexpected events that asks the drone to react very quick. Energy consumption could also be a problem <ref>Stolaroff, K. (2014), “The Need for a Life Cycle Assessment of Drone-Based Commercial Package Delivery”.</ref>. For long flights the drones need large batteries, but bigger batteries also means less space for cargo. <br />
<br />
Another problem with delivery drones these days is the ‘problem of the last meters’. These last problems aren’t so much about the technology, since most of it already exists, but how to implement all these technologies to make it actually work. These problems are for example: how do we deliver packages in (high) apartment buildings and how do people (and animals) react to these kind of deliveries <ref>Frankel, Todd C. (2016), [https://www.washingtonpost.com/business/economy/biggest-obstacle-for-delivery-drones-isnt-the-technology-its-you-and-me/2016/01/06/e4cae052-aa81-11e5-9b92-dea7cd4b1a4d_story.html “Biggest obstacle for delivery drones isn’t the technology: It’s you and me"]. The Washington Post</ref>. The article from the Washington Post gives a great start to start asking questions which aren’t technical, but more to the side of users. What do we want as society?<br />
<br />
The problem with the battery-life as given above can, for example, be fixed (maybe until there are better batteries) by changing the battery of the delivery drone in the air <ref>Fujii, K., Higuchi, K., Rekimoto, J. (2013), [http://ieeexplore.ieee.org.dianus.libr.tue.nl/xpls/abs_all.jsp?arnumber=6726212 “Endless Flyer: A Continuous Flying Drone with Automatic Battery Replacement”]</ref>. The concept Amazon Prime Air is the best example of the given idea <ref>Amazon (2016). [http://www.amazon.com/b?node=8037720011 “Amazon Prime air”]</ref>, which is (unfortunately) still a concept and not working yet. Also Google <ref>Bradshaw, Tim (Aug 2014), [http://search.proquest.com.dianus.libr.tue.nl/docview/1565890256?pq-origsite=summon “Google tests drone deliveries in Australia”] </ref> and Walmart <ref>Kulkarni, Nitish (Oct 2015), [http://techcrunch.com/2015/10/26/walmart-drone-delivery/ “Walmart Is Looking To Get Into The Drone Delivery Game”]</ref> are joining the competition to get the first working delivery drones ready. These three competitors all want to be the first company that can use the drones, which means that a lot of research (and money) is involved. The problem those companies are working on is the reliability of the drones.<br />
<br />
Our idea is to look at drones and find out what the best human interaction is when they want to land. Do the buyers have to put an big A in their garden? How does this work if you live on the 3rd floor? What if the neighbors also bought a package that is due at the same time? Maybe we don’t need the pilots, but we can let the buyers fly their own package the last meters? Are the buyers home at the time the package arrives? all those questions together, what can we expect from buyers and how are we going to interact with them to let the landing go smooth?<br />
<br />
== USE/Impact → who is benefiting? ==<br />
=== Primary user ===<br />
*Consumers, people who order online<br />
*Drone pilots<br />
<br />
=== Secondary users ===<br />
*Companies and shopkeepers<br />
*Drone developers<br />
*Drone manufacturers<br />
*Legislature<br />
<br />
=== Tertiary users ===<br />
*Mechanics<br />
*Safety instances (in case of accidents)<br />
*People walking/using the streets<br />
*Other airspace users<br />
<br />
== Needs of those users ==<br />
=== Consumers ===<br />
The consumers demand fast, trustworthy and safe delivery of their packages. Note that fast delivery is not necessarily a need, more than a wish or desire. Also no discrete value can be given to what is considered as fast delivery. Trustworthy delivery means the guarantee that the package is delivered withing the agreed time limit without huge delays or high chance of cancellation.<br />
<br />
Safe delivery covers several parts. First the guarantee that the package arrives without being damaged during its trip. Second comes the guarantee that the package is not stole on the way. Last comes the demand that no damage is done by the drone to any property of the consumer during the landing.<br />
<br />
=== Drone pilots ===<br />
Pilots that will navigate the drones, will need adequate training and specialization to be able to safely navigate these drones through public airspace, especially in urban environments. A training facility is therefore needed and an organization that supplies drone pilot licenses will be needed. In areas with few tall buildings, autonomous drones might be used.<br />
<br />
=== Companies and shopkeepers ===<br />
Companies and shopkeepers will be the ones providing the service of drone delivery. Therefor they will take a large portion of the responsibility for the drones. Their needs will lay in reliability of the drones as well as flexibility. With flexibility, in this case, being able to fly long distances or multiple flights after each other without (long) charging is meant.<br />
Another important need for companies is for the drones to be cheap, or at least affordable. A right balance between price and quality must be found. Also for they are to provide the service to the consumers, consumers needs automatically become needs for companies and shopkeepers as well.<br />
<br />
=== Drone developers and manufacturers ===<br />
Of course with the increasing use of drones, companies will be able to make money with it. Also new developments will be stimulated. For companies producing drones the ease of producing will be an important need as well as the expense of separate parts. These parts need to be modular in order to customize the drone to fit its environment to optimize flying conditions. Furthermore, when parts become interchangeable, drones can be quickly repaired and upgraded without altering the core parts for future use. <br />
<br />
=== Legislature ===<br />
New legislation must be designated that describes in which environments drones are allowed to navigate autonomously and in which areas it is unsafe to do this. Also a consensus about safe flying altitudes for drones must be established. Rules and requirements for a drone pilot license need to determined. During flights where drones are operating autonomously, liability becomes an important obstacle since it is not clear who should take responsibility in an accident. <br />
<br />
Generally, taking full responsibility as the drone producer can be seen as a generous gesture towards customers and will also push the development of autonomous vehicles onto the main audience. Other autonomous machine producers have already done so: “Volvo, Google and Mercedes have now all said that they will accept full liability if their self-driving vehicles cause a collision”<ref>S.Elmer, Autoguide (Oct 2015), [http://www.autoguide.com/auto-news/2015/10/volvo-google-and-mercedes-to-accept-responsibility-in-self-driving-car-collisions.html “Volvo, Google and Mercedes to Accept Responsibility in Self-Driving Car Collisions”]<br />
</ref>.<br />
<br />
=== Mechanics ===<br />
Easy to repair or preform maintenance as well as safety doing so, due the fact that the drone parts are produced in a modular fashion. This makes it also cheap and environment friendly since it produces less waste as you only need to throw away the broken part instead of the whole package.<br />
<br />
=== Safety instances ===<br />
A need or wish for safety instances it to have the drones to be able to fly without accidents, for their priority is to provide a safe living environment. And in case of an accident, which will unfortunately be inevitable, the damage must be minimal.<br />
<br />
=== People walking/using the streets ===<br />
The main need for these people concerning drone delivery is to be able to walk the streets safely without the fear or risk of an accident.<br />
Other airspace users<br />
<br />
Tight regulation of the airspace to keep the accidents to a minimum or preventive mechanisms to avoid them. Drones should only be allowed to fly at certain safe altitudes that do not interfere with air crafts and helicopters, moreover drones should not be allowed to fly next to locations like airports, since that can result in a dangerous situation that can lead to crashes with commercial airliners.<br />
<br />
== Scenario ==<br />
Eindhoven University of Technology (TU/e) is planning to start a centralized shop to save some money. In this shop product for educational use, i.e. lecture notes, college blocks and pencils, can be bought by the students and employees. It is also possible to print out reports and let them be bound. It will also be possible to borrow electronical devices, i.e. projectors, presenters and measuring equipment. The regulations and prices of this new shop will be the same as it is today in the local shops and borrow points.<br />
<br />
The direction of the university is only afraid that some student and employees will complain, since all the local shops and borrow points will disappear. It is decided that the location of this shop will be in the MetaForum, this location is in the center of the campus and is easy to find. The board also has another idea: delivery by drone. To make even the laziest student and employees happy, your package will be delivered to your office and, if you live in Eindhoven, to your front door. All free of charge of course. The delivery time on campus will be at the most 5 minutes and in the rest of the city 20 minutes.<br />
<br />
In a real world situation apartment complexes are seen as the buildings on campus. Suburban areas, i.e. houses with gardens, are seen as the rest of the delivery location in Eindhoven.<br />
<br />
The costumer is able to follow his/her package on the website or the app of the shop. Here the costumer can find the location of the package and how long it will take before it arrives. If the user can’t be on the place of delivery at the given delivery time, the user can change the delivery location. When the drone with the package hasn’t left the MetaForum it’s also possible to put the delivery on hold. The package will then be delivered when the costumer says it can be on the delivery location on the given time.<br />
<br />
From the start the new system has been quite popular. The students and staff of the TU/e have not jet experienced difficulties using the system. The management is even trying to expand the service to the cafeteria. Also other universities have shown interested in using this system at their own universities.<br />
<br />
== References ==<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25505PRE2015 3 Groep2 week62016-03-20T12:32:34Z<p>S149491: /* First version report */</p>
<hr />
<div>= Further testing =<br />
NOTE: Experiments in random order.<br />
<br />
<br />
Due to limited battery time, a small adjustment has been made to the experiment to increase productivity. Instead of testing with only one test subject at the time, two people will be standing next to each other as the drone approaches them. Because of the accuracy of the drone, which is about 0.5 meter, both test subjects should feel as they are being approached by the drone. The test subjects have approved it and indicate that because the full focus is on the drone, it does not influence the results. Afterwards both test subjects are questioned separately so their opinions will not influence each other.<br />
<br />
== Experiment 2 ==<br />
<br />
=== Results A ===<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results B ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results C ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
== Analyzing results ==<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 1: A bar graph of the three ways of approaching vs. the rating. The error bars show the two-tailed 95% coincidence interval.]]<br />
=== T-test ===<br />
A T-test gives the possibility to decide if an hypotheses needs to be rejected or not <ref>Diez, D.M. Barr, C.D. Çetinkaya-Rundel, M. (2012) OpenIntro Statistics. Second Edition</ref>. The hypothese in this case are the values: 'Very bad' (1), 'Bad' (2), 'Neutral' (3), 'Good' (4) and 'Very Good' (5). A t-test will be conducted of all the hypotheses value of the different approach routes.<br />
<br />
To determine how likely a rating will occur during a specific approach, a p-value will also be computed. This value stand for the probability that an user will rate the experience a certain way. <br />
<br />
Shown in the table bellow are the p-values of the different ways of approaching. Values which are rejected by the t-test (one-tailed 95% coincidence interval, α = 0.05) are marked with an 'X'. <br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Rating<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Vertical<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | At an angle<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Horizontal<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,3739<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
|- valign="top"<br />
|}<br />
<br />
== State of the Art ==<br />
<br />
<br />
= First version report =<br />
[[Media:First_version_report_group_2_quarter_3_2015-2016.pdf]]<br />
<br />
= References =<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25504PRE2015 3 Groep2 week62016-03-20T12:32:14Z<p>S149491: /* State of the Art */</p>
<hr />
<div>= Further testing =<br />
NOTE: Experiments in random order.<br />
<br />
<br />
Due to limited battery time, a small adjustment has been made to the experiment to increase productivity. Instead of testing with only one test subject at the time, two people will be standing next to each other as the drone approaches them. Because of the accuracy of the drone, which is about 0.5 meter, both test subjects should feel as they are being approached by the drone. The test subjects have approved it and indicate that because the full focus is on the drone, it does not influence the results. Afterwards both test subjects are questioned separately so their opinions will not influence each other.<br />
<br />
== Experiment 2 ==<br />
<br />
=== Results A ===<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results B ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results C ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
== Analyzing results ==<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 1: A bar graph of the three ways of approaching vs. the rating. The error bars show the two-tailed 95% coincidence interval.]]<br />
=== T-test ===<br />
A T-test gives the possibility to decide if an hypotheses needs to be rejected or not <ref>Diez, D.M. Barr, C.D. Çetinkaya-Rundel, M. (2012) OpenIntro Statistics. Second Edition</ref>. The hypothese in this case are the values: 'Very bad' (1), 'Bad' (2), 'Neutral' (3), 'Good' (4) and 'Very Good' (5). A t-test will be conducted of all the hypotheses value of the different approach routes.<br />
<br />
To determine how likely a rating will occur during a specific approach, a p-value will also be computed. This value stand for the probability that an user will rate the experience a certain way. <br />
<br />
Shown in the table bellow are the p-values of the different ways of approaching. Values which are rejected by the t-test (one-tailed 95% coincidence interval, α = 0.05) are marked with an 'X'. <br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Rating<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Vertical<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | At an angle<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Horizontal<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,3739<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
|- valign="top"<br />
|}<br />
<br />
= First version report =<br />
[[Media:First_version_report_group_2_quarter_3_2015-2016.pdf]]<br />
<br />
= References =<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25503PRE2015 3 Groep2 week62016-03-20T12:31:55Z<p>S149491: /* First version report */</p>
<hr />
<div>= Further testing =<br />
NOTE: Experiments in random order.<br />
<br />
<br />
Due to limited battery time, a small adjustment has been made to the experiment to increase productivity. Instead of testing with only one test subject at the time, two people will be standing next to each other as the drone approaches them. Because of the accuracy of the drone, which is about 0.5 meter, both test subjects should feel as they are being approached by the drone. The test subjects have approved it and indicate that because the full focus is on the drone, it does not influence the results. Afterwards both test subjects are questioned separately so their opinions will not influence each other.<br />
<br />
== Experiment 2 ==<br />
<br />
=== Results A ===<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results B ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
=== Results C ===<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
== Analyzing results ==<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 1: A bar graph of the three ways of approaching vs. the rating. The error bars show the two-tailed 95% coincidence interval.]]<br />
=== T-test ===<br />
A T-test gives the possibility to decide if an hypotheses needs to be rejected or not <ref>Diez, D.M. Barr, C.D. Çetinkaya-Rundel, M. (2012) OpenIntro Statistics. Second Edition</ref>. The hypothese in this case are the values: 'Very bad' (1), 'Bad' (2), 'Neutral' (3), 'Good' (4) and 'Very Good' (5). A t-test will be conducted of all the hypotheses value of the different approach routes.<br />
<br />
To determine how likely a rating will occur during a specific approach, a p-value will also be computed. This value stand for the probability that an user will rate the experience a certain way. <br />
<br />
Shown in the table bellow are the p-values of the different ways of approaching. Values which are rejected by the t-test (one-tailed 95% coincidence interval, α = 0.05) are marked with an 'X'. <br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Rating<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Vertical<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | At an angle<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Horizontal<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,30456<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,3739<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,47662<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0,051606<br />
|- valign="top"<br />
|}<br />
<br />
= First version report =<br />
[[Media:First_version_report_group_2_quarter_3_2015-2016.pdf]]<br />
<br />
== State of the Art ==<br />
<br />
= References =<br />
<references/></div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25361PRE2015 3 Groep2 week62016-03-14T10:54:26Z<p>S149491: /* Further Testing */</p>
<hr />
<div>== Further testing ==<br />
NOTE: Experiments in random order.<br />
<br />
<br />
Due to limited battery time, a small adjustment has been made to the experiment to increase productivity. Instead of testing with only one test subject at the time, two people will be standing next to each other as the drone approaches them. Because of the accuracy of the drone, which is about 0.5 meter, both test subjects should feel as they are being approached by the drone. The test subjects have approved it and indicate that because the full focus is on the drone, it does not influence the results. Afterwards both test subjects are questioned separately so their opinions will not influence each other.<br />
<br />
=== Experiment 2 ===<br />
<br />
==== Results A ====<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
==== Results B ====<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
==== Results C ====<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 3: A bar graph of the three ways of approaching]]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25356PRE2015 3 Groep2 week62016-03-14T10:41:43Z<p>S149491: /* Further Testing */</p>
<hr />
<div>== Further Testing ==<br />
<br />
=== Experiment 2 ===<br />
<br />
==== Results A ====<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
==== Results B ====<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
==== Results C ====<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 3: A bar graph of the three ways of approaching]]</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25355PRE2015 3 Groep2 week62016-03-14T10:40:54Z<p>S149491: /* Results */</p>
<hr />
<div>== Further Testing ==<br />
<br />
=== Experiment 2 ===<br />
<br />
==== Results A ====<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 3: A bar graph of the three ways of approaching]]<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
==== Results B ====<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 3: A bar graph of the three ways of approaching]]<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
==== Results C ====<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 3: A bar graph of the three ways of approaching]]<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
|}</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25354PRE2015 3 Groep2 week62016-03-14T10:36:40Z<p>S149491: /* Results */</p>
<hr />
<div>== Further Testing ==<br />
<br />
=== Experiment 2 ===<br />
<br />
==== Results ====<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 3: A bar graph of the three ways of approaching]]<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" |<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|- valign="top" <br />
|}</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25353PRE2015 3 Groep2 week62016-03-14T10:34:42Z<p>S149491: /* Results */</p>
<hr />
<div>== Further Testing ==<br />
<br />
=== Experiment 2 ===<br />
<br />
==== Results ====<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 3: A bar graph of the three ways of approaching]]<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|- valign="top" <br />
|}</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25352PRE2015 3 Groep2 week62016-03-14T10:34:20Z<p>S149491: /* Results */</p>
<hr />
<div>== Further Testing ==<br />
<br />
=== Experiment 2 ===<br />
<br />
==== Results ====<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 3: A bar graph of the three ways of approaching]]<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|- valign="top" <br />
|}</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6&diff=25351PRE2015 3 Groep2 week62016-03-14T10:32:31Z<p>S149491: Created page with '== Further Testing == === Experiment 2 === ==== Results ==== Figure 3: A bar graph of the three ways of approaching {| class="wiki…'</p>
<hr />
<div>== Further Testing ==<br />
<br />
=== Experiment 2 ===<br />
<br />
==== Results ====<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 3: A bar graph of the three ways of approaching]]<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top"</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2&diff=25350PRE2015 3 Groep22016-03-14T10:31:43Z<p>S149491: /* Project Progress */</p>
<hr />
<div>{{DISPLAYTITLE:Delivery Drones}}<br />
<br />
Drones are becoming more and more accepted in our society. The market for consumer drones has never been bigger, so is the interested of the big companies in these technologies. An sector which shows great interest is the online retail sector. These companies could use drones to delivery there packages to the costumer in minutes instead of days. These drones will fly, most of the time, autonomously. Many of the problems with these kind of deliveries have been solved. The results are that drones can now reach a certain GPS-coordinated without major problems. The only problem that is still there is the problem of the so called 'last meters'. The moment where the drone needs to land and is going to interacted with the untrained costumer. There are two problems which need to be solved first before the package can be handed over to the costumer: the drone needs to find a safe landing spot and what is the best way to approach the costumer.<br />
<br />
The first problem, landing the drone safely, is the last problem with regards to autonomous flying. Nowadays companies, Amazon for example, are relying on the costumer to chose a safe landing spot. But to make drone delivery as easy for the costumer as possible, the drone needs to do this all on its own.<br />
<br />
The second problem is concerned with the experience of the costumer during the last phase of the delivery. If the costumer feels threatened by the drone during landing and take off, the chance will be lowered for choosing drone delivery the next time the costumer orders something. So if approaching the costumer and the landing distance can be determined where the costumer still feels safe the market for drone delivery will really take off.<br />
<br />
== Group Members ==<br />
{|<br />
|-<br />
! Student<br />
! Student number<br />
! <br />
|-<br />
| Stevie van der Loo<br />
| 0813076<br />
| [http://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_log_stevie Logbook]<br />
|-<br />
| Elbert van de Put<br />
| 0897289<br />
| [http://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_log_elbert Logbook]<br />
|-<br />
| Jeroen Setz<br />
| 0843356<br />
| [http://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_log_jeroen Logbook]<br />
|-<br />
| Martijn Tibboel<br />
| 0909136 <br />
| [http://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_log_martijn Logbook]<br />
|-<br />
| Maarten Vlaswinkel<br />
| 0899061<br />
| [http://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_log_maarten Logbook]<br />
|-<br />
| Mert Zararsiz<br />
| 0865084<br />
| [http://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_log_mertz Logbook]<br />
|}<br />
<br />
== Project Progress ==<br />
[http://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week1 Week 1: The idea]<br />
<br />
[http://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week2 Week 2: Specifying the idea]<br />
<br />
[http://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week3 Week 3: Redefining focus and deliverables and starting research]<br />
<br />
[http://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week4 Week 4: Experiments and mapping]<br />
<br />
[http://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week5 Week 5: Experiments and autonomous landing]<br />
<br />
[http://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week6 Week 6: Mapping and more experiments]<br />
<br />
== Project Planning ==<br />
<br />
=== Week 2 ===<br />
*Laws for drones → Martijn<br />
*Planning → Jeroen<br />
*Presentation on Monday → Martijn, Elbert, Jeroen<br />
*Explaining focus and new scenario → Jeroen<br />
*Start Navigation → Maarten, Elbert<br />
*Start Verification → Mert, Stevie<br />
*If anyone is done, they can help extending navigation or verification<br />
<br />
=== Week 3 ===<br />
*Redefining focus<br />
*Background information landing and approach<br />
*Background information altitude meter<br />
*Controller drone<br />
<br />
=== Week 4 ''(start test and experiment-phase)'' ===<br />
*Flying with drone and testing altitude meter<br />
*Starting approach experiment<br />
<br />
=== Week 5 ''(test and experiment-phase)'' ===<br />
*Start autonomous landing implementing<br />
*Approach experiment<br />
<br />
=== Week 6 ''(test and experiment-phase)'' ===<br />
*Autonomous landing implementing <br />
*Finishing approach experiment<br />
*Documentation<br />
<br />
=== Week 7 ''(finishing test and experiment-phase)'' ===<br />
*Finishing practice + documentation<br />
*Final report<br />
<br />
=== Week 8 ===<br />
*Finishing Report</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week5&diff=25269PRE2015 3 Groep2 week52016-03-13T14:15:03Z<p>S149491: /* USE */</p>
<hr />
<div>== Approaching Users ==<br />
=== Experiment 1: Landing distance ===<br />
[[File:Opstelling.jpg|thumbnail|upright=2.5|Figure 1: Picture of the first experiment for determining the landing distance. Strips on the ground are giving the distance per 0.5m.]]<br />
The variable landing distance is about the distance that users are still comfortable with the drone around. The optimal distance that users like and the nearest distance that people are comfortable with drones around are determined with an experiment. The subject (an user) stands on a given spot (l=0). The distances 0.5, 1, 1.5…7 meters are marked with masking tape (distance to test subject) on the ground. The drone will start at a distance of 7 meters (= l<sub>start</sub>) as seen in figure 1. The drone will approach the person at a steady speed of approximately v = 1 m/s. It does so at a height of h = 1 meter. Whenever the test subject feels like the current distance between him and the drone is the most comfortable distance to land, the test subject will give off a sign and the drone will be given the order to land (l<sub>end</sub>). The subject will redo the test to determine the nearest distance where he or she feels comfortable. Those distances are measured and rounded per 0.25m. The results are seen below.<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Optimal distance (m)<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Nearest distance (m)<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.25<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.0<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.75<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.75<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.5<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.0<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.25<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.75<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.0<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.75<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 6<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.75<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.5<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 7<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3.5<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.0<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 8<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3.5<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.75<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 9<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.75<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.5<br />
|}<br />
<br />
<br />
The mean value of the optimal distance is 2.47m with an standard deviation of 0.67. The nearest distance has a mean of 1.00m with an standard deviation of 0.53. These means give the landing distance from this experiment, the optimal landing distance is 2.5m with a nearest landing distance of 1.0m. The drone should be programmed to keep these distances as first option and starting point of the landing procedure.<br />
<br />
==== Points of improvement ====<br />
Though the experiment came with a clear conclusion, with a few outliners, some variables that might influence the results have not been touched upon. The experiment above gives a general idea for a distance to keep from the users, but does for instance not distinguish between different users. These differences may for example concern:<br />
<br />
*Age<br />
*Sex<br />
*Experience (with drones)<br />
*Length of the user<br />
*And even general (in)security or character of the user<br />
<br />
But also the drone itself can have influence on results:<br />
<br />
*Approaching speed<br />
*Size of the drone<br />
*Appearance of the drone<br />
*Noise<br />
*Wind generated<br />
<br />
Further research will have to point out to what extend these factors play a role in approaching users with drones.<br />
<br />
=== Experiment 2: Way of approach ===<br />
[[File:FlightPathCombined.png|thumbnail|upright=2.5|Figure 2: Schematic representation of the experiment setup. Situation A, displayed in red. Situation B, displayed in green. Situation C, displayed in blue.]]<br />
It's not only interesting to look at the best landing distance, but also at the way the drone approaches the user. For this, a distinction is made between three different situations. For a description of these situation see the list below and figure 2. In all these situations the test person is positioned at l = 0m. The drone starts at a distance l<sub>start</sub> and height h<sub>start</sub>.<br />
<br />
;Situation A<br />
:The drone flies horizontally to a certain distance l<sub>end</sub> then the drone lands vertically.<br />
;Situation B<br />
:The drone flies diagonally, at an angle α, to a certain point at distance l<sub>end</sub> and height h<sub>end</sub>. Then the drone lands vertically.<br />
;Situation C<br />
:The drones lowers itself vertically to a certain height h<sub>end</sub>. It then flies horizontally to a certain distance l<sub>end</sub> before it lands vertically on the ground.<br />
<br />
For the distance l<sub>start</sub> a distance of 8m is chosen. The ending distance l<sub>end</sub> is chosen according to the results of experiment 1 at roughly 2.5 meters.<br />
<br />
<br />
After each test variation the test person is asked to rate the experience with the values very bad/bad/neutral/good/very good.<br />
<br />
==== Point of improvement ====<br />
During the experiment some notes ware mate about the quality of the experiment.<br />
*The drone has been flown manually, so the same ways of approaching are different with each test subject<br />
*The test group only exists of males<br />
*The test group only involves three people, so the result aren't trustworthy<br />
<br />
==== Results ====<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 3: A bar graph of the three ways of approaching]]<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
As can be seen from figure 3 the best way of approaching the user is while flying at an angle. Flying horizontally to the user seems better at first, but since the error is bigger than it is at approaching at an angle it's safer to use this way of approaching. Keep in mind that their where only three test subjects used, the results aren't trustworthy and more test subjects have to be used to give a trustworthy conclusion.<br />
<br />
Something that is clear is that the user prefers an approach at which the drone is under the eye level at close distances. A possible explanation for this is that when the drone is under eye level the user has to look down. Looking down unto the drone gives people the feeling that their more dominant, i.e. in control of the situation. Looking upwards, when the drone tries to land vertical for example, gives the opposite feeling, that the drone is in control. In a situation where the user isn't into control it can be wise to at least give the user the feeling their into control.<br />
<br />
During the experiment the landing distance of 2,5 meters is chosen, but maybe the way of approach differs at different landing distance. Do find this out their will also be looked at the likability of approaches with a landing distance of 1,5 and 3,5 meters.<br />
<br />
== Autonomous landing ==<br />
=== Test setup ===<br />
A major problem during the autonomous landing phase is that the drone needs to know where it is on the map it is creating. It's not wise to assume that the drone flies at a constant speed, since it doesn't. Doing so would create an error which can result in complete disaster. <br />
<br />
Since the test setup has been moved inside, the situation created won't be realistic, but very controllable. Determining the location of the drone will be done with markers placed on the ground or objects which the drone can detected with its down facing camera. These markers will be placed 50cm from its neighboring marker.<br />
<br />
In the first situation the system will be developed in a two dimensional world. Their will be height differences and the drone can be front- and backwards. No movement to the left or right will be possible. If the drone succeeds to land in such a randomized environment their will be looked at the second situation.<br />
<br />
In the second situation a third dimension will be added, the left and right movement. This will be a more realistic environment, but far from the environment a drone will encounter in a real world scenario.<br />
<br />
In both the situations their will only be objects the drone can detected from the height it uses to scan the environment. Since the markers are used to determine the location of the drone, they will be placed on a level surface. This could be an object or the ground. Their will also be enough space to land the drone in a user friendly way.<br />
<br />
== USE ==<br />
In designing a technique it is not merely about finding a technical working system that solves the problem. User preference play a big role in the success or failure of such a technique. The first question appears: What are the user preferences concerning this system? Two user preferences that will be tested for are: The distance to keep between the user and the drone, also the optimal distance for landing. And the way of approaching the user. These experiments will be further explained in the chapter 4 Research. Below the question of 'Who is this user and what are his or her preferences?' is answered.<br />
<br />
=== Users ===<br />
Users can be categorized into three different categories. Primary users are the users that the technique is aimed at, the main people to interact with. In the case of the delivery drone these are the people that will have their package handed over by the drone:<br />
<br />
Primary user:<br />
*Consumers, people who order online<br />
<br />
Secondary users are the people who also will be making use of the technique, but have less direct contact with the drone than the primary users. Some secondary users of the delivery drone are listed below.<br />
<br />
Secondary users:<br />
*Companies and shopkeepers<br />
*Drone developers<br />
*Drone manufacturers<br />
<br />
The last group of users are the tertiary users. This group often contains the users that are only incidentally confronted with the technique, people working in the same environment or people who perform maintenance on the drones for example:<br />
<br />
Tertiary users:<br />
*Mechanics<br />
*Safety instances (in case of accidents)<br />
*People walking/using the streets<br />
*Other airspace users<br />
*Government instances (new laws)<br />
<br />
=== User needs ===<br />
The main focus of the project will be interaction with the drones of the primary users. Therefor an in depth analysis of these users and their needs is needed. Other users however may play a part in this project as well, so for some their needs will be illustrated briefly as well.<br />
<br />
General primary user needs for drone delivery are fast, trustworthy and safe delivery of their packages. Note that no discrete values can be given to what is fast, trustworthy or safe delivery. In the scope of the project these needs however are slightly different. Safety still remains a priority, the user should in no way be exposed to risky and or dangerous situation regarding the drone. Since the flight of the drone to the address is assumed to be no problem, fast delivery falls a little more to the background. Trustworthy delivery remains an user need, but its meaning changes with the context. Here trustworthy delivery is not so much about not damaging or losing the package on the way, but rather about a being able to find a location to land no matter the environment. Last an extra user desire comes within focus, the comfortability of the delivery. This involves the drone's behavior towards the user which should not only be safe, but also feel safe and comfortable.<br />
<br />
Companies and shopkeepers will be the ones providing the service of drone delivery. Therefor they will take a large portion of the responsibility for the drones. Their needs will lay in reliability of the drones.<br />
Another important need for companies is for the drones to be cheap, or at least affordable. A right balance between price and quality must be found. Also for they are to provide the service to the consumers, consumers needs automatically become needs for companies and shopkeepers as well.<br />
<br />
Of course with the increasing use of drones, developers and drone-producingcompanies will be able to make money with it. Also new developments will be stimulated. For companies producing drones, the ease of producing will be an important need as well as the expense of separate parts.<br />
<br />
Generally, taking full responsibility as the drone producer can be seen as a generous gesture towards customers and will also push the development of autonomous vehicles onto the main audience. Other autonomous machine producers have already done so: "Volvo, Google and Mercedes have now all said that they will accept full liability if their self-driving vehicles cause a collision".<br />
<br />
The primary need for mechanics is that the drones are easy to repair or preform maintenance on, as well as safety doing.<br />
<br />
A need or wish for safety instances it to have the drones to be able to fly without accidents, for their priority is to provide a safe living environment. And in case of an accident, which will unfortunately be inevitable, the damage must be minimal.<br />
<br />
For people walking/using the streets the main need concerning drone delivery is to be able to walk the streets safely without the fear or risk of an accident.</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week5&diff=25268PRE2015 3 Groep2 week52016-03-13T14:09:25Z<p>S149491: /* Autonomous landing */</p>
<hr />
<div>== Approaching Users ==<br />
=== Experiment 1: Landing distance ===<br />
[[File:Opstelling.jpg|thumbnail|upright=2.5|Figure 1: Picture of the first experiment for determining the landing distance. Strips on the ground are giving the distance per 0.5m.]]<br />
The variable landing distance is about the distance that users are still comfortable with the drone around. The optimal distance that users like and the nearest distance that people are comfortable with drones around are determined with an experiment. The subject (an user) stands on a given spot (l=0). The distances 0.5, 1, 1.5…7 meters are marked with masking tape (distance to test subject) on the ground. The drone will start at a distance of 7 meters (= l<sub>start</sub>) as seen in figure 1. The drone will approach the person at a steady speed of approximately v = 1 m/s. It does so at a height of h = 1 meter. Whenever the test subject feels like the current distance between him and the drone is the most comfortable distance to land, the test subject will give off a sign and the drone will be given the order to land (l<sub>end</sub>). The subject will redo the test to determine the nearest distance where he or she feels comfortable. Those distances are measured and rounded per 0.25m. The results are seen below.<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Optimal distance (m)<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Nearest distance (m)<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.25<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.0<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.75<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.75<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.5<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.0<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.25<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.75<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.0<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.75<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 6<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.75<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.5<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 7<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3.5<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.0<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 8<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3.5<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.75<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 9<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.75<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.5<br />
|}<br />
<br />
<br />
The mean value of the optimal distance is 2.47m with an standard deviation of 0.67. The nearest distance has a mean of 1.00m with an standard deviation of 0.53. These means give the landing distance from this experiment, the optimal landing distance is 2.5m with a nearest landing distance of 1.0m. The drone should be programmed to keep these distances as first option and starting point of the landing procedure.<br />
<br />
==== Points of improvement ====<br />
Though the experiment came with a clear conclusion, with a few outliners, some variables that might influence the results have not been touched upon. The experiment above gives a general idea for a distance to keep from the users, but does for instance not distinguish between different users. These differences may for example concern:<br />
<br />
*Age<br />
*Sex<br />
*Experience (with drones)<br />
*Length of the user<br />
*And even general (in)security or character of the user<br />
<br />
But also the drone itself can have influence on results:<br />
<br />
*Approaching speed<br />
*Size of the drone<br />
*Appearance of the drone<br />
*Noise<br />
*Wind generated<br />
<br />
Further research will have to point out to what extend these factors play a role in approaching users with drones.<br />
<br />
=== Experiment 2: Way of approach ===<br />
[[File:FlightPathCombined.png|thumbnail|upright=2.5|Figure 2: Schematic representation of the experiment setup. Situation A, displayed in red. Situation B, displayed in green. Situation C, displayed in blue.]]<br />
It's not only interesting to look at the best landing distance, but also at the way the drone approaches the user. For this, a distinction is made between three different situations. For a description of these situation see the list below and figure 2. In all these situations the test person is positioned at l = 0m. The drone starts at a distance l<sub>start</sub> and height h<sub>start</sub>.<br />
<br />
;Situation A<br />
:The drone flies horizontally to a certain distance l<sub>end</sub> then the drone lands vertically.<br />
;Situation B<br />
:The drone flies diagonally, at an angle α, to a certain point at distance l<sub>end</sub> and height h<sub>end</sub>. Then the drone lands vertically.<br />
;Situation C<br />
:The drones lowers itself vertically to a certain height h<sub>end</sub>. It then flies horizontally to a certain distance l<sub>end</sub> before it lands vertically on the ground.<br />
<br />
For the distance l<sub>start</sub> a distance of 8m is chosen. The ending distance l<sub>end</sub> is chosen according to the results of experiment 1 at roughly 2.5 meters.<br />
<br />
<br />
After each test variation the test person is asked to rate the experience with the values very bad/bad/neutral/good/very good.<br />
<br />
==== Point of improvement ====<br />
During the experiment some notes ware mate about the quality of the experiment.<br />
*The drone has been flown manually, so the same ways of approaching are different with each test subject<br />
*The test group only exists of males<br />
*The test group only involves three people, so the result aren't trustworthy<br />
<br />
==== Results ====<br />
<br />
[[file:approach.png||thumbnail|upright=2.5|Figure 3: A bar graph of the three ways of approaching]]<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
As can be seen from figure 3 the best way of approaching the user is while flying at an angle. Flying horizontally to the user seems better at first, but since the error is bigger than it is at approaching at an angle it's safer to use this way of approaching. Keep in mind that their where only three test subjects used, the results aren't trustworthy and more test subjects have to be used to give a trustworthy conclusion.<br />
<br />
Something that is clear is that the user prefers an approach at which the drone is under the eye level at close distances. A possible explanation for this is that when the drone is under eye level the user has to look down. Looking down unto the drone gives people the feeling that their more dominant, i.e. in control of the situation. Looking upwards, when the drone tries to land vertical for example, gives the opposite feeling, that the drone is in control. In a situation where the user isn't into control it can be wise to at least give the user the feeling their into control.<br />
<br />
During the experiment the landing distance of 2,5 meters is chosen, but maybe the way of approach differs at different landing distance. Do find this out their will also be looked at the likability of approaches with a landing distance of 1,5 and 3,5 meters.<br />
<br />
== Autonomous landing ==<br />
=== Test setup ===<br />
A major problem during the autonomous landing phase is that the drone needs to know where it is on the map it is creating. It's not wise to assume that the drone flies at a constant speed, since it doesn't. Doing so would create an error which can result in complete disaster. <br />
<br />
Since the test setup has been moved inside, the situation created won't be realistic, but very controllable. Determining the location of the drone will be done with markers placed on the ground or objects which the drone can detected with its down facing camera. These markers will be placed 50cm from its neighboring marker.<br />
<br />
In the first situation the system will be developed in a two dimensional world. Their will be height differences and the drone can be front- and backwards. No movement to the left or right will be possible. If the drone succeeds to land in such a randomized environment their will be looked at the second situation.<br />
<br />
In the second situation a third dimension will be added, the left and right movement. This will be a more realistic environment, but far from the environment a drone will encounter in a real world scenario.<br />
<br />
In both the situations their will only be objects the drone can detected from the height it uses to scan the environment. Since the markers are used to determine the location of the drone, they will be placed on a level surface. This could be an object or the ground. Their will also be enough space to land the drone in a user friendly way.<br />
<br />
== USE ==<br />
In designing a technique it is not merely about finding a technical working system that solves the problem. User preference play a big role in the succes or failure of such a technique. The first question appears: What are the user preferences concerning this system? Two user preferences that will be tested for are: The distance to keep between the user and the drone, also the optimal distance for landing. And the way of approaching the user. These experiments will be further explained in the chapter 4 Research. Below the question of 'Who is this user and what are his or her preferences?' is answered.<br />
<br />
=== Users ===<br />
Users can be categorized into three different catechories. Primary users are the users that the technique is aimed at, the main people to interact with. In the case of the delivery drone these are the people that will have their package handed over by the drone:<br />
<br />
Primary user:<br />
*Consumers, people who order online<br />
<br />
Secondary users are the people who also will be making use of the technique, but have less direct contact with the drone than the primary users. Some secondary users of the delivery drone are listed below.<br />
<br />
Secondary users:<br />
*Companies and shopkeepers<br />
*Drone developers<br />
*Drone manufacturers<br />
<br />
The last group of users are the tertiary users. This group often contains the users that are only incidentally contronted with the technique, people working in the same environment or people who perform maintenance on the drones for example:<br />
<br />
Tertiary users:<br />
*Mechanics<br />
*Safety instances (in case of accidents)<br />
*People walking/using the streets<br />
*Other airspace users<br />
*Government instances (new laws)<br />
<br />
=== User needs ===<br />
The main focus of the project will be interaction with the drones of the primary users. Therefor an indepth analysis of these users and their needs is needed. Other users however may play a part in this project as well, so for some their needs will be illustrated briefly as well.<br />
<br />
General primary user needs for drone delivery are fast, thrustworthy and safe delivery of their packages. Note that no discrete values can be given to what is fast, thrustworthy or safe delivery. In the scope of the project these needs however are slightly different. Safety still remains a priority, the user should in no way be exposed to risky and or dangerous situation regarding the drone. Since the flight of the drone to the adress is assumed to be no problem, fast delivery falls a little more to the background. Thrustworthy delivery remains an user need, but its meaning changes with the context. Here thrustworthy delivery is not so much about not damaging or losing the package on the way, but rather about a being able to find a location to land no matter the environment. Last an extra user desire comes within focus, the comfortability of the delivery. This involves the drone's behaviour towards the user which should not only be safe, but also feel safe and comfortable.<br />
<br />
Companies and shopkeepers will be the ones providing the service of drone delivery. Therefor they will take a large portion of the responsibility for the drones. Their needs will lay in reliability of the drones.<br />
Another important need for companies is for the drones to be cheap, or at least affordable. A right balance between price and quality must be found. Also for they are to provide the service to the consumers, consumers needs automatically become needs for companies and shopkeepers as well.<br />
<br />
Of course with the increasing use of drones, developers and drone-producingcompanies will be able to make money with it. Also new developments will be stimulated. For companies producing drones, the ease of producing will be an important need as well as the expense of separate parts.<br />
<br />
Generally, taking full responsibility as the drone producer can be seen as a generous gesture towards customers and will also push the development of autonomous vehicles onto the main audience. Other autonomous machine producers have already done so: "Volvo, Google and Mercedes have now all said that they will accept full liability if their self-driving vehicles cause a collision" \cite{onl:elmer}.<br />
<br />
The primary need for mechanics is that the drones are easy to repair or preform maintenance on, as well as safety doing.<br />
<br />
A need or wish for safety instances it to have the drones to be able to fly without accidents, for their priority is to provide a safe living environment. And in case of an accident, which will unfortunately be inevitable, the damage must be minimal.<br />
<br />
For people walking/using the streets the main need concerning drone delivery is to be able to walk the streets safely without the fear or risk of an accident.</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_log_martijn&diff=25267PRE2015 3 Groep2 log martijn2016-03-13T14:05:41Z<p>S149491: /* Week 4 */</p>
<hr />
<div>== Week 1 ==<br />
*Meeting after lecture<br />
*Background research about drones for deciding on topic<br />
<br />
It was clear we wanted to do something with drones. Options for topics were:<br />
*Drones filming in a football match<br />
*Drones delivering packages at home<br />
*Drones chasing a fugitive like a police helicopter<br />
<br />
== Week 2 ==<br />
*Meeting<br />
*Rules for drones (see 'Legalisation' under 'week 2')<br />
*Presentation (preparation, I was supposed to present as well but got ill and also lost my voice)<br />
<br />
== Week 3 ==<br />
*Meeting<br />
*First look into other projects at home<br />
*Wednesday entire morning researching the drone. What do we have and how does fly? Also what software is available? (also see Problems)<br />
*Redefining Research<br />
*Research Personal Space by E. Torta --> See Research, week 3 (together with Jeroen)<br />
<br />
Problems:<br />
This week we together looked at the drone together and tried to make it fly. Also we looked at the feedback we got after out last presentation regarding our project. One of these feedback points was about other groups of previous years that had done projects with similar subjects.<br />
<br />
One project however seemed to look like a little too much like the plans we had in mind, forcing us to adjust the aim of our project. They were using the same drone, the same software to fly it and even thought of the same method for verification of the customer (NFC tag). We had two choices, either continue where the other group left off or research a different aspect of the subject. Considering we have only 2 people from ICT, 1 electrical engineer and 3 people from WTB with little programming experience, choosing the first option seemed unwise.<br />
<br />
Thus we moved our focus to the part of flying the drone as in finding a good landing spot. Also we decided to research the approaching of people by drones, since no research we were able to find did look at that for drones yet.<br />
<br />
== Week 4 ==<br />
*Working on Approaching Users<br />
*Working on Drone specifications<br />
*Performing experiment 1<br />
**Being a test subject<br />
**Taking measurements<br />
<br />
== Week 5 ==<br />
*Discussing the progression of the project<br />
**Discussing how the test setup of the autonomous landing research will look like<br />
*Second experiment<br />
**Doing the experiment<br />
**Processing the results of the experiment<br />
*Extending information that is coming in the report<br />
**Rewrite Chapter about the Users</div>S149491https://cstwiki.wtb.tue.nl/index.php?title=PRE2015_3_Groep2_week5&diff=25132PRE2015 3 Groep2 week52016-03-09T09:31:38Z<p>S149491: /* Test setup */</p>
<hr />
<div>== Approaching Users ==<br />
=== Experiment 1: Landing distance ===<br />
[[File:Opstelling.jpg|thumbnail|upright=2.5|Figure 1: Picture of the first experiment for determining the landing distance. Strips on the ground are giving the distance per 0.5m.]]<br />
The variable landing distance is about the distance that users are still comfortable with the drone around. The optimal distance that users like and the nearest distance that people are comfortable with drones around are determined with an experiment. The subject (an user) stands on a given spot (l=0). The distances 0.5, 1, 1.5…7 meters are marked with masking tape (distance to test subject) on the ground. The drone will start at a distance of 7 meters (= l<sub>start</sub>) as seen in figure 1. The drone will approach the person at a steady speed of approximately v = 1 m/s. It does so at a height of h = 1 meter. Whenever the test subject feels like the current distance between him and the drone is the most comfortable distance to land, the test subject will give off a sign and the drone will be given the order to land (l<sub>end</sub>). The subject will redo the test to determine the nearest distance where he or she feels comfortable. Those distances are measured and rounded per 0.25m. The results are seen below.<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Optimal distance (m)<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Nearest distance (m)<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.25<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.0<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.75<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.75<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.5<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.0<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 4<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.25<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.75<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 5<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.0<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.75<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 6<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.75<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.5<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 7<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3.5<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2.0<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 8<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3.5<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.75<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 9<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1.75<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 0.5<br />
|}<br />
<br />
<br />
The mean value of the optimal distance is 2.47m with an standard deviation of 0.67. The nearest distance has a mean of 1.00m with an standard deviation of 0.53. These means give the landing distance from this experiment, the optimal landing distance is 2.5m with a nearest landing distance of 1.0m. The drone should be programmed to keep these distances as first option and starting point of the landing procedure.<br />
<br />
==== Points of improvement ====<br />
Though the experiment came with a clear conclusion, with a few outliners, some variables that might influence the results have not been touched upon. The experiment above gives a general idea for a distance to keep from the users, but does for instance not distinguish between different users. These differences may for example concern:<br />
<br />
*Age<br />
*Sex<br />
*Experience (with drones)<br />
*Length of the user<br />
*And even general (in)security or character of the user<br />
<br />
But also the drone itself can have influence on results:<br />
<br />
*Approaching speed<br />
*Size of the drone<br />
*Appearance of the drone<br />
*Noise<br />
*Wind generated<br />
<br />
Further research will have to point out to what extend these factors play a role in approaching users with drones.<br />
<br />
=== Experiment 2: Way of approach ===<br />
[[File:FlightPathCombined.png|thumbnail|upright=2.5|Figure 2: Schematic representation of the experiment setup. Situation A, displayed in red. Situation B, displayed in green. Situation C, displayed in blue.]]<br />
It's not only interesting to look at the best landing distance, but also at the way the drone approaches the user. For this, a distinction is made between three different situations. For a description of these situation see the list below and figure 2. In all these situations the test person is positioned at l = 0m. The drone starts at a distance l<sub>start</sub> and height h<sub>start</sub>.<br />
<br />
;Situation A<br />
:The drone flies horizontally to a certain distance l<sub>end</sub> then the drone lands vertically.<br />
;Situation B<br />
:The drone flies diagonally, at an angle α, to a certain point at distance l<sub>end</sub> and height h<sub>end</sub>. Then the drone lands vertically.<br />
;Situation C<br />
:The drones lowers itself vertically to a certain height h<sub>end</sub>. It then flies horizontally to a certain distance l<sub>end</sub> before it lands vertically on the ground.<br />
<br />
For the distance l<sub>start</sub> a distance of 8m is chosen. The ending distance l<sub>end</sub> is chosen according to the results of experiment 1 at roughly 2.5 meters.<br />
<br />
<br />
After each test variation the test person is asked to rate the experience with the values very bad/bad/neutral/good/very good.<br />
<br />
{| class="wikitable" style="border: 1px solid black; border-collapse:collapse;" cellpadding="5"<br />
|- valign="top"<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Experiment<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Bad<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Neutral<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Good<br />
! style="border-right: 1px solid black; border-bottom: 1px solid black;" | Very good<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 1C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 2C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3A<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3B<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | 3C<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | X<br />
| style="border-right: 1px solid black; border-bottom: 1px solid black;" | <br />
|- valign="top" <br />
|}<br />
<br />
== Autonomous landing ==<br />
=== Test setup ===<br />
A major problem during the autonomous landing phase is that the drone needs to know where it is on the map it is creating. It's not wise to assume that the drone flies at a constant speed, since it doesn't. Doing so would create an error which can result in complete disaster. <br />
<br />
Since the test setup has been moved inside, the situation created won't be realistic, but very controllable. Determining the location of the drone will be done with markers placed on the ground or objects which the drone can detected with its down facing camera. These markers will be placed 50cm from its neighboring marker.<br />
<br />
In the first situation the system will be developed in a two dimensional world. Their will be height differences and the drone can be front- and backwards. No movement to the left or right will be possible. If the drone succeeds to land in such a randomized environment their will be looked at the second situation.<br />
<br />
In the second situation a third dimension will be added, the left and right movement. This will be a more realistic environment, but far from the environment a drone will encounter in a real world scenario.<br />
<br />
In both the situations their will only be objects the drone can detected from the height it uses to scan the environment. Since the markers are used to determine the location of the drone, they will be placed on a level surface. This could be an object or the ground. Their will also be enough space to land the drone in a user friendly way.</div>S149491