Embedded Motion Control 2015 Group 9: Difference between revisions
(29 intermediate revisions by 2 users not shown) | |||
Line 45: | Line 45: | ||
= Objective = | = Objective = | ||
The main objective of the course is to design and implement an embedded motion system and apply | The main objective of the course is to design and implement an embedded motion system and apply it to an autonomous robot. | ||
At the end of the course, there is a maze challenge in which the robot | At the end of the course, there is a maze challenge in which the robot has to find the way out as quickly as possible. | ||
= Robot = | = Robot = | ||
For implementing and testing the software design, robot named PICO is used. There are mainly two inputs | For implementing and testing the software design, a robot named PICO is used. There are mainly two inputs to the PICO robot. | ||
They are (1) odometry data which is received from the wheels and (2) laser data from the range finder. | They are (1) odometry data which is received from the wheels and (2) laser data from the range finder. | ||
Line 72: | Line 72: | ||
decisions required to be made by the robot. | decisions required to be made by the robot. | ||
=== Requirements and specifications === | === Requirements and specifications === | ||
# Data structure depends on applied control/path finding algorithm. | |||
# Data has to be dynamically allocated. | |||
# Data should be dynamically available for the system architecture. | |||
# Appropriate system elements must not corrupt, which means, that the synchronization between reading and writing data is required. | |||
# It should be able to read and manipulate required flags in the robot architecture. | |||
# It should have a priority scheduling architecture for making decisions in real time within specific time constraints. | |||
# It should handle the memory safely without corruption of data or data overflow. | |||
=== Components === | === Components === | ||
The components required to perform this function effectively, are a read only code memory, and a | The components required to perform this function effectively, are a read only code memory, and a | ||
RAM(Random Access Memory). | RAM (Random Access Memory). | ||
== Function: Route mapping == | == Function: Route mapping == | ||
Line 150: | Line 151: | ||
=== Working === | === Working === | ||
1 Centring | |||
* The robot uses to laser data which are perpendicular to the wall to obtained to distance on each side to the wall. | * The robot uses to laser data which are perpendicular to the wall to obtained to distance on each side to the wall. | ||
* Further the difference in distance value between the two sides (error) is calculated. | * Further the difference in distance value between the two sides (error) is calculated. | ||
* If the difference is up to a certain threshold value no input or action is taken. How if the error is greater an input is taken in the opposite direction to correct the error. A PID controller is used for centring. | * If the difference is up to a certain threshold value no input or action is taken. How if the error is greater an input is taken in the opposite direction to correct the error. A PID controller is used for centring. | ||
2 Cornering | |||
* First the laser range data is scanned for potential corners. The condition used for corner detection is that if there is suddenly change (above certain threshold) in the laser data, that point is marked as a potential corner. | * First the laser range data is scanned for potential corners. The condition used for corner detection is that if there is suddenly change (above certain threshold) in the laser data, that point is marked as a potential corner. | ||
* Once all the available corners are identified, it is stored in the mapping. | * Once all the available corners are identified, it is stored in the mapping. | ||
Line 217: | Line 218: | ||
Components that are used by this function are the memory and laser position sensor. | Components that are used by this function are the memory and laser position sensor. | ||
= | = Software system architecture = | ||
[[File:structure.jpg]] | [[File:structure.jpg]] | ||
The system was designed in a structured way based on classes. The figure above shows the system architecture with which the entire coding is made. | |||
This was done to mainly satisfy- | |||
# The composition pattern | # The composition pattern | ||
# High level code readability | # High level code readability | ||
= Corridor Challenge = | = Corridor Challenge = | ||
http://youtu.be/wFrfn02jlCg | http://youtu.be/wFrfn02jlCg | ||
As seen in the video, PICO completed the corridor challenge very smoothly although it was a bit slow. This was because we were short of time for testing our software at higher speeds. The robot remained almost at the exact centre of the corridor throughout the challenge and this was because of the nicely tuned PI controller that was implemented. This meant that our motion task was indeed running satisfactorily. | |||
= Testing PICO = | = Testing PICO = | ||
The PICO is tested for a designed maze prepared by the team.The video below shows the working of PICO in the maze. | The PICO is tested for a designed maze prepared by the team.The video below shows the working of PICO in the maze. Video link - http://youtu.be/-LjT004KEN0 | ||
http://youtu.be/-LjT004KEN0 | |||
Here the PICO is tested for the door detection as it is the major task or objective to complete the maze. | Here the PICO is tested for the door detection as it is the major task or objective to complete the maze. | ||
; Turn around (If no door is detected): For the Maze challenge, PICO is supposed to detect door which would be located in a dead end. So, the software was designed in such a way that, when the PICO detects a dead end, it sends a signal for the door detection (which could be heard as calling bell sound in the video) and waits for 10 seconds. If the door doesn't open, PICO turns around and performs other functions. Video link - http://youtu.be/NASDGkWwzRA | |||
http://youtu.be/ | ; Perform actions (If door is detected): PICO does the following function when the door is detected. The door detection can be seen in the video as PICO sends a signal and waits for 5 seconds and if the door gets opened, PICO moves forward and performs the necessary action. Video link - http://youtu.be/wty2N2sWevY | ||
= Maze Challenge = | |||
[[File:Maze-photo.jpg|1024 px]] | |||
;Trial 1-: As seen in the above photo of the maze, there was a 4-way intersection in the beginning, for which our code was not adequately tested and tuned. As expected, it did not work, and the robot hit the wall while cornering. | |||
;Trial 2-: For this trial, we placed the robot at a different starting point so that it does not have to go through the same intersection. Yet, the robot failed to turn properly while it detected the right turn towards the door. We think this is because while testing, we had ensured that the maze had longer corridors so that the robot can find the center of the corridor and turn along the arc connecting the center of the two corridors. However, in the actual maze, the corridor lengths were substantially smaller and therefore, the robot had to turn much before the center of the corridor it was supposed to turn into. | |||
= Some of the code we're proud of = | = Some of the code we're proud of = | ||
Line 277: | Line 279: | ||
For the decision making, we made use of a simple switch case statement with the priorities left>straight>right>back depending on the kind of intersection the robot is located at. | For the decision making, we made use of a simple switch case statement with the priorities left>straight>right>back depending on the kind of intersection the robot is located at. | ||
< | <pre style="white-space:pre-wrap; width:90%;"> | ||
switch(mon->nodeType){ | switch(mon->nodeType) | ||
{ | |||
case straightOnly: | case straightOnly: | ||
driveStraight(); | driveStraight(); | ||
Line 306: | Line 309: | ||
driveStraight(); | driveStraight(); | ||
std::cout<<"error:node type="<< mon->nodeType<<std::endl; | std::cout<<"error:node type="<< mon->nodeType<<std::endl; | ||
}</ | } | ||
</pre> | |||
= | We also found an interesting way to maintain a list of nodes that the robot has travelled, using the "list" package library. The code for updating the list is as follows- | ||
<pre style="white-space:pre-wrap; width:90%;"> | |||
if(!CheckForRepeatedNodes()) //if present node is not a repeated node | |||
{ //Add new node to list and increment the id and update the previous x and y co-ordinates of the node | |||
NodeList.push_front(node(curr_id,mon->nodeType,curr_decision,1,curr_x,curr_y)); | |||
prev_x = curr_x; | |||
prev_y = curr_y; | |||
curr_id++; | |||
} | |||
</pre> | |||
while the function <code>CheckForRepeatedNodes()</code> is as follows- | |||
<pre style="white-space:pre-wrap; width:90%;"> | |||
bool CheckForRepeatedNodes() //this function checks for repeated nodes based on a tolerance of 0.2m and returns false for unique nodes | |||
{ | |||
std::list<node>::iterator index_x = std::find_if(NodeList.begin(),NodeList.end(),std::bind2nd(isNodex(), curr_x)); | |||
if(index_x == NodeList.end()) | |||
{ | |||
return false; | |||
} | |||
else | |||
{ | |||
std::list<node>::iterator index_y = std::find_if(NodeList.begin(),NodeList.end(),std::bind2nd(isNodey(), curr_y)); | |||
if(index_y == NodeList.end()) | |||
{ | |||
return false; | |||
} | |||
else | |||
{ | |||
return true; | |||
} | |||
} | |||
} | |||
</pre> | |||
= | = Key insights learnt from the course = | ||
*The separation of modules using 5'C' concerns helps in providing an organized structure to the code which aids in localizing bugs and debugging. It also ensures satisfactory treatment of essential components of the code facilitating individual testing of code pieces. | |||
*Explicit planning is essential to the success of the project- A clear quantification of the options and resources (both time and personnel) available helps in taking sound project decisions for the timely and successful completion. | |||
*Learning – The project has been a great learning curve with major focus areas on importance of structuring in C++, hands-on experience with coding, 5'C' patterns- concerns and decoupled structure in coding, etc. | |||
*Testing - The project, in earnest, demonstrates testing as a critical part of software development. It has been a great learning experience to see the different behavior observed using a particular piece of code in real life and simulation. | |||
*The project gives a basic insight into 'Embedded Software Design Chronology and Planning' as well as design analysis, implementation and testing. | |||
*The team explored a lot of options for mobile robot control algorithms including various form of SLAM and other possible topological mapping algorithms. The team also got acquainted with the problem of localization and mapping in robotics and understands the basic drawbacks and advantages of different algorithms. | |||
*The project was a first hand experience for most of the students in the group with an actual functional robot - PICO and came to know about robot characteristics and programming possibilities. | |||
*One of the essential learning from the project was the importance of minimization of hard coded contents in the code to increase portability and ease of understanding and manipulation. The so-called 'MAGIC NUMBERS' should be avoided but in quite a few cases are a necessary evil. Hence handling of these numbers and providing enough details about their existence is key to understanding and debugging codes. | |||
*The team feels one of the main insights from the project was - Big difference between SIMULATION and REALITY. |
Latest revision as of 21:36, 26 June 2015
Group Members
Name | Student nr | |
---|---|---|
Prasanth Muralidharan | 0926106 | p.muralidharan@student.tue.nl |
Arkadiusz Kamrowski | 0921901 | a.l.kamrowski@student.tue.nl |
Marcin Turemka | 0921893 | m.turemka@student.tue.nl |
Kartik Mundaragi Shivakumar | 0926061 | k.mundaragi.shivakumar@student.tue.nl |
Manikandan Manjaparai Sundaram | 0926898 | m.manjaparai.sundaram@student.tue.nl |
Anurodh Mishra | 0927142 | a.mishra@student.tue.nl |
Dennie Craane | 0834726 | d.w.h.craane@student.tue.nl |
Sujit Sharan | 0924962 | s.sharan@student.tue.nl |
Anshuman Singh | 0927466 | a.singh@student.tue.nl |
Objective
The main objective of the course is to design and implement an embedded motion system and apply it to an autonomous robot. At the end of the course, there is a maze challenge in which the robot has to find the way out as quickly as possible.
Robot
For implementing and testing the software design, a robot named PICO is used. There are mainly two inputs to the PICO robot. They are (1) odometry data which is received from the wheels and (2) laser data from the range finder.
Design
To reach the objective, the robot will have to fulfil a set of functions or tasks, for which it will need certain skill sets. In order to judge whether the found solution fulfils the functions, a set of requirements and necessary components are needed to meet the specifications. The functions and underlying skills can be portrayed in graphical overview resulting from brainstorming as shown in the above figure.
For each function, requirements can be set along with additional information about the required components and specifications. The resulting skill sets and robot lower layer abilities needed are derived from the combination of the functions and components.
Function: Memory Handling
As seen in the figure above, this function is mainly involved in handling the on-board memory modules for all the computations and logical decisions required to be made by the robot.
Requirements and specifications
- Data structure depends on applied control/path finding algorithm.
- Data has to be dynamically allocated.
- Data should be dynamically available for the system architecture.
- Appropriate system elements must not corrupt, which means, that the synchronization between reading and writing data is required.
- It should be able to read and manipulate required flags in the robot architecture.
- It should have a priority scheduling architecture for making decisions in real time within specific time constraints.
- It should handle the memory safely without corruption of data or data overflow.
Components
The components required to perform this function effectively, are a read only code memory, and a RAM (Random Access Memory).
Function: Route mapping
As an example of the approach used, the presented figure depicts the route mapping function as a nested CP which denotes how the functional entities can be designed with CP as the building block at various levels of hierarchy. The main function consists of two sub-functions which have a similar construction to one another. Each of the functional entities operates under its own context which helps in separating the 5C concerns. The ‘connections’ show the exchange of data which in this case is with the memory handling function which depicts the communication aspect with other functional entities.
The function route mapping has the following subcomponents:
Path Planning
- Open corridors first (saving doors encountered in memory): The first step is to scan all the open paths/corridors keeping track of the doors encountered. The doors act as the nodes for the subsequent stage.
- Basic decision algorithm (like left-front-right-down, longest distance, etc.) A basic decision algorithm is required to make the exploration of corridors with branching possible. The base decision algorithm can be a rule of thumb or a more reasoned approach.
- Returning to last saved junction. Encountering a dead end or a loop the robot should return to the last saved checkpoint/junction and continue on the basis of the decision algorithm selected.
- Graphical dynamic programming algorithm - The best possible algorithm with the shortest time is found to be the graphical dynamic algorithm and this would be used to solve the problem for optimal path for the maze.
Path Storage
Path information storage – (co-ordinate system and graphical DP)
- In order to store the path information a co-ordinate system can be used which helps in the recognition of loops existing in the system. Moreover distance travelled and location of doors can be easily stored with this. However standardization of unit distance as per the movement of the robot (taking into consideration the error in its distance measuring system) is necessary.
Requirement
In order to successfully accomplish the above mentioned function, certain requirements (qualitative in nature for now), needs to be fulfilled. These are:
- Differentiation between open branches and doors in a corridor is required for exploration in an organized manner.
- A nomenclature for the storage of information needs to be agreed upon for ease of understanding and traceability.
Components
- Memory
- Elements (not clearly defined at this level) for conversion of information from robot skill set to suitable parameters like distance travelled, orientation and location w.r.t. a reference.
- C++ code
- An algorithm for path planning
Working
Route map is very important in the maze challenge because the robot should not go to the same junction or corridor which was taken before. So the route map or world map is made of nodes which is used to store the data relevant to the robot for completing the maze. There are some key components used while making the nodes. The nodes acts as a major communicating factor for communication with other function to base their decisions. An identifier was used for storing the information. Depending upon the operation of the robot (turns,exit,door detection), nodes were categorized. The most important task is positioning the robot in the global coordinate when dealing with loops and dead ends.This was also done using the laser positioning system.
The nodes were defined in the code as a separate class with organized structure to ensure ease of access to information.
Function: Maneuvering
- From the figure above, the 5C principle is clearly understandable in this function. The Monitor senses all the data and condition and sends it to the coordinator. The coordinator receives the data process all possible skills available. Then the scheduler takes the decision and the configurator configures the robot parameters and executes the skill which was decided.
Sub-functions
- Use information from the algorithm and environment to adequately move the robot into the desired position using the abilities from the ROS.
- Maintain a safe velocity and position in respect to the obstacle in the environment, this is to ensure the safety of the robot.
- Optimize movements to reduce time needed.
Requirements
- It must maintain a safe distance with the wall whenever it moves.
- It should move at a constant speed, with which it’s still capable of detecting the door opening.
- The robot mustreverse in the case a wall has been hit.
- If it reaches a dead end it should turn around and return to the last decision location and send a command to the algorithm to recalculate the path.
- If the robot is unable to find a path it might move in backward direction along the same path, so that it has better chance of detecting the doors.
Components
- The robot lower level abilities
- Wheels
- Motors
- Memory
Working
1 Centring
- The robot uses to laser data which are perpendicular to the wall to obtained to distance on each side to the wall.
- Further the difference in distance value between the two sides (error) is calculated.
- If the difference is up to a certain threshold value no input or action is taken. How if the error is greater an input is taken in the opposite direction to correct the error. A PID controller is used for centring.
2 Cornering
- First the laser range data is scanned for potential corners. The condition used for corner detection is that if there is suddenly change (above certain threshold) in the laser data, that point is marked as a potential corner.
- Once all the available corners are identified, it is stored in the mapping.
- Later the based on the decision making algorithm the selected decision is executed. The robot is moved to the centre of the corner and makes a 90 degree turn and moves forward in that direction.
Function: Environment awareness
From the figure, it can be seen that the skills are listed in the composition pattern, further these skills in themselves are composition patterns. The skills consist of a set of computations that uses the input from the sensors and gives output regarding the environment ( obstacles, doors, position) to other functions that further process this information. Some skills are shared across the different functionality (e.g. reading data from the sensors and reading/writing of the memory).
The high level function environment awareness consists of tasks:
- Wall following
- Opening interpretation
- Position detection
- Wall detection:
1.The skills and related robot abilities needed to perform this task can be described as:
- Get distance to obstacle from laser sensor for all degrees
- Decide for what degrees an obstacle is present and where not (opening)
- Save obtained information into memory
2.The 5C pattern to perform this task:
- Monitors observes the obstacle distance, based on this the coordinator decides the behaviour of the functionality. For example if the monitor detects a turn or a straight the coordinator configures to take the appropriate action.
- Opening interpretation:
1.The skills and related robot abilities needed to perform this task can be described as:
- Get opening locations from the memory
- Use previous information from the memory to detect ‘new’ openings
- Decide if opening is an exit, door or another branch
- Save information into the memory
2.The 5C pattern to perform this task:
- Sensor data will also detect abrupt stops of the corridor. These openings should be interpreted to be another branch, a door or possibly the exit. This information is also passed to the other functions that can decide which way to go.
- Position Detection
1.The skills and related robot abilities needed to perform this task can be described as:
- Get distance to obstacle from laser sensor for all degrees
- Get old position from memory
- Compare new distance to old distance and determine distance traveled
- Determine new position relative to starting point
- Save position into memory
2.The 5C pattern to perform this task:
- The position on the map is determined using the sensors of the vehicle relative to the starting position. Also data is processed to determine the local positioning in the corridor. This position info is stored in the memory, where other functions, like route mapping, can use it.
Requirements and specifications
This function should fulfil a set of requirements in order to test if the function is performed correctly. Part of the requirements will be quantitative, however, due to the early stage in the project most requirements are kept qualitative for now.
- The function must differentiate between solid obstacles (wall) and an opening (door).
- Obtained information must be stored in a memory unit accessible by other tasks.
- The memory should be polled with a suitable frequency in order to prevent flooding.
- Detection of obstacles should have a relatively high frequency, due changes in the path (doors)
- Determining global positioning should have a relatively low frequency, due to slow movement speed.
- Upon detection of a door, other tasks should be notified.
Components
Components that are used by this function are the memory and laser position sensor.
Software system architecture
The system was designed in a structured way based on classes. The figure above shows the system architecture with which the entire coding is made. This was done to mainly satisfy-
- The composition pattern
- High level code readability
Corridor Challenge
As seen in the video, PICO completed the corridor challenge very smoothly although it was a bit slow. This was because we were short of time for testing our software at higher speeds. The robot remained almost at the exact centre of the corridor throughout the challenge and this was because of the nicely tuned PI controller that was implemented. This meant that our motion task was indeed running satisfactorily.
Testing PICO
The PICO is tested for a designed maze prepared by the team.The video below shows the working of PICO in the maze. Video link - http://youtu.be/-LjT004KEN0
Here the PICO is tested for the door detection as it is the major task or objective to complete the maze.
- Turn around (If no door is detected)
- For the Maze challenge, PICO is supposed to detect door which would be located in a dead end. So, the software was designed in such a way that, when the PICO detects a dead end, it sends a signal for the door detection (which could be heard as calling bell sound in the video) and waits for 10 seconds. If the door doesn't open, PICO turns around and performs other functions. Video link - http://youtu.be/NASDGkWwzRA
- Perform actions (If door is detected)
- PICO does the following function when the door is detected. The door detection can be seen in the video as PICO sends a signal and waits for 5 seconds and if the door gets opened, PICO moves forward and performs the necessary action. Video link - http://youtu.be/wty2N2sWevY
Maze Challenge
- Trial 1-
- As seen in the above photo of the maze, there was a 4-way intersection in the beginning, for which our code was not adequately tested and tuned. As expected, it did not work, and the robot hit the wall while cornering.
- Trial 2-
- For this trial, we placed the robot at a different starting point so that it does not have to go through the same intersection. Yet, the robot failed to turn properly while it detected the right turn towards the door. We think this is because while testing, we had ensured that the maze had longer corridors so that the robot can find the center of the corridor and turn along the arc connecting the center of the two corridors. However, in the actual maze, the corridor lengths were substantially smaller and therefore, the robot had to turn much before the center of the corridor it was supposed to turn into.
Some of the code we're proud of
We are generally proud of the structure of our main loop which just calls the different functions like monitor(), Coordinate(), etc sequentially. This makes the scheduling of functions easy to understand and easy to debug.
while(com.ok())
{
com.Communicate();
mon.monitor();
ccs.Coordinate();
logg.log();
r.sleep();
}
Another piece of code that we found very useful was the usage of enum{}
to make the conditional statements more user-friendly. An example is the following, in which we create an enum for the decisions taken by the robot-
enum decisions
{
goStraight,
turnLeft,
turnRight,
turnBack,
openDoor,
stop
};
For the decision making, we made use of a simple switch case statement with the priorities left>straight>right>back depending on the kind of intersection the robot is located at.
switch(mon->nodeType) { case straightOnly: driveStraight(); break; case straightLeft: turnLeft(); break; case straightRight: driveStraight(); break; case crossing: turnLeft(); break; case rightTurn: turnRight(); break; case leftTurn: turnLeft(); break; case tSection: turnLeft(); break; case deadEnd: turnBack(); break; default: driveStraight(); std::cout<<"error:node type="<< mon->nodeType<<std::endl; }
We also found an interesting way to maintain a list of nodes that the robot has travelled, using the "list" package library. The code for updating the list is as follows-
if(!CheckForRepeatedNodes()) //if present node is not a repeated node { //Add new node to list and increment the id and update the previous x and y co-ordinates of the node NodeList.push_front(node(curr_id,mon->nodeType,curr_decision,1,curr_x,curr_y)); prev_x = curr_x; prev_y = curr_y; curr_id++; }
while the function CheckForRepeatedNodes()
is as follows-
bool CheckForRepeatedNodes() //this function checks for repeated nodes based on a tolerance of 0.2m and returns false for unique nodes { std::list<node>::iterator index_x = std::find_if(NodeList.begin(),NodeList.end(),std::bind2nd(isNodex(), curr_x)); if(index_x == NodeList.end()) { return false; } else { std::list<node>::iterator index_y = std::find_if(NodeList.begin(),NodeList.end(),std::bind2nd(isNodey(), curr_y)); if(index_y == NodeList.end()) { return false; } else { return true; } } }
Key insights learnt from the course
- The separation of modules using 5'C' concerns helps in providing an organized structure to the code which aids in localizing bugs and debugging. It also ensures satisfactory treatment of essential components of the code facilitating individual testing of code pieces.
- Explicit planning is essential to the success of the project- A clear quantification of the options and resources (both time and personnel) available helps in taking sound project decisions for the timely and successful completion.
- Learning – The project has been a great learning curve with major focus areas on importance of structuring in C++, hands-on experience with coding, 5'C' patterns- concerns and decoupled structure in coding, etc.
- Testing - The project, in earnest, demonstrates testing as a critical part of software development. It has been a great learning experience to see the different behavior observed using a particular piece of code in real life and simulation.
- The project gives a basic insight into 'Embedded Software Design Chronology and Planning' as well as design analysis, implementation and testing.
- The team explored a lot of options for mobile robot control algorithms including various form of SLAM and other possible topological mapping algorithms. The team also got acquainted with the problem of localization and mapping in robotics and understands the basic drawbacks and advantages of different algorithms.
- The project was a first hand experience for most of the students in the group with an actual functional robot - PICO and came to know about robot characteristics and programming possibilities.
- One of the essential learning from the project was the importance of minimization of hard coded contents in the code to increase portability and ease of understanding and manipulation. The so-called 'MAGIC NUMBERS' should be avoided but in quite a few cases are a necessary evil. Hence handling of these numbers and providing enough details about their existence is key to understanding and debugging codes.
- The team feels one of the main insights from the project was - Big difference between SIMULATION and REALITY.