Embedded Motion Control 2017 Group 9

From Control Systems Technology Group
Jump to navigation Jump to search

Group Members

Name: Student id:
Mian Wei 1035075
Zhihao Wu 1041226
Petrus Teguh Handoko X
Bo Deng X
Bo Cong X
Jian Wen Kok X
Nico Huebel Tutor


Initial Design

The initial design for the maze challenge is elaborated below. It includes the requirements, functions, components, schematic of program structure, specifications and interfaces to define the working of PICO. The file for the initial design is included here: File:Assignment-for-week1.pdf

Requirements

➢ PICO drives autonomously through maze
➢ Being able to take a turn without touching a wall
➢ Being able to detect a turn or branching corridors
➢ Avoiding collisions with obstacles (including the walls)
➢ Driving straight and rotating smoothly
➢ PICO should not stand still for 30 seconds
➢ Avoid getting trapped in a loop of the maze
➢ Being able to recognize the door

Functions

Functionsg9.jpeg

Components

drive control
‐Holonomic base (omni‐wheels)
‐Pan‐tilt unit for head

detection ‐170◦ wide‐angle camer
‐Laser Range Finder (LRF)
‐Wheel encoders (odometry)
‐Asus Xtion Depth sensor

world model
computer
‐Intel I7
‐Ubuntu 14.04

Specifications

- maximum translational speed of 0.5 m/s
‐ maximum rotational speed of 1.2 rad/s
‐ Door template: length of 0.5 ‐ 1.5m and with side walls of approximately 30cm, see figure below
‐ LRF accuracy and range unknown
‐ odometer accuracy unknown

Doortempg9.jpeg

Interfaces

The odometer and LRF generates data for mapping the environment.

The algorithm sets nodes on the junction as a setpoint for navigation, plans the route and put the actuators to work accordingly.

The odometer and LRF keeps on keeping track of the environment and the software recognizes obstructions, dead ends that might be doors and junction.

Corridor Challenge

Design

At first, PICO moves forward with a modified potential field.
When it detects the junction, the potential field goes off and stops when it is in the middle of the junction.
PICO then rotates 90 degree and moves forward.
When PICO detects that it is inside the junction, the potential field goes on and finishes the challenge.

Result

The corridor challenge failed

In the first trial PICO moved straight forward without potential field.
When it detects the junction it stopped and rotated 90 degrees in the wrong direction.
This inevitably resulted into crashing into the walls.

The second trial PICO did not detect the junction and drove straight forward, this was the latest program.

Evaluation

The first trial used our old program that has proven itself as seen in the video below. Unfortunately we did not push the correct version to PICO.
Corridor test.gif

The second trial used our latest program. Potential field is added because there exists a chance that PICO would run into the walls without it.
The new program works in the simulation, it has been tested in the real setting and we had problems with the odometer to correctly make the turning.
The program had to run without debugging in the real setting. Later on, a bug was found in the junction detection.

Maze Challenge

Design

Architecture

Architecture.jpeg

Main Flow

The code programmed for maze solving is a flag-based one, which decide whether to run the corresponding blocks or not according to the flags set for indicating different cases. These flag are set when the “Detection & Decision Block” has detected the corresponding cases;when the movement corresponding to a particular case is completed,they will be reset. These flags are the base of logic of the whole program.
As demonstrated on Figure1, the structure of Main Loop consists of four blocks: “Detection & Decision Block”,”Door Movement Block”, “Junction Movement Block” and “Normal Movement Block”.
Initialization function will run for one time at the moment when the robot is turned on. Then we come to looping part, which is the main part of the main function and executed at a frequency of 20HZ.
The first block to be executed in loop structure is “Detection & Decision Block”. “Detection & Decision Block” is responsible for junction detection, door detection ,open space detection and making movement decision. In this block, robot detects the existence of the door first and return “possible_door_flag”. This flag indicates the existence and the direction of the door with respect to the robot. When “possible_door_flag” is nonzero, robot will skip “junction detection” sub-block and directly execute “Door Movement Block” because the information of junction existence is no more important if the door of existence is found already. Otherwise, “Detection & Decision Block” will execute sub-block for junction checking.
“junction_flag”, which indicate the existence of the junction around the robot, will be returned by “Junction Detection” sub-block and an array named as “junction_direction” with three elements will be return at the mean time. If “junction_flag” is nonzero, which indicate the existence of junction, “Decision” sub-block will be executed to make the decision of the next corridor the robot is going to move to. If not, “Decision” sub-block will be blocked and the robot will take default movement mold——“Normal Move Forward”. Except for junction-detection, “Junction Detection” sub-block is responsible for “Open Space Detection” in the meanwhile. We will illustrate it in detail when introduce the mathematic model for open-space-detection the corresponding movement.
One more point added, “Detection & Decision Block” can only be executed when both “junction_falg” and “possible_door_flag” are zero. i.e. , the “Detection & Decision Block” will not be executed anymore without any other blocks to help it to clean the flag set in the last time junction or door was detected. This condition is added to avoid the disturbance of error movement order. When the robot is executing actions, the position and orientation of the robot w.r.t. the maze is changing, data collected by laser scanner is not reliable for making decision. We block the “Detection and Decision Block” until the last issued command is implemented completely and “junction_falg” , “possible_door_flag” are reset.
When the execution of first block complete, “Junction Movement Block”, “Door Movement Block” and “Normal Move Forward Block” will executed according to the movement command issued by “Detection & Decision Block”. “Normal Move Forward Block” controls default forward movement. When neither junction nor door is detected, the movement of the robot is controlled by this block to move with potential field protection. But it will be substituted by “Junction Movement Block” or “Door Movement Block” when special case detected.
Structure of Main Loop

Detection


Door Detection


There are two conditions of door, front door and side door.

  • Front door detection method

Detecting the distance of three ranges, the range is defined by angle θ=48°, and detection radius φf.
We consider the front door as a dead end, hence the detection is to check whether there is a dead end or not. If the average distance in the three detect ranges all smaller than φf, that means there is a dead end and return possible_door_flag=2 (means there is a front door).

Frontdoor.PNGSidedoor.PNG

  • Side door detection method

Using the left and right side detect ranges to detect the side door, considering the given restrictions the depth of door template is around 0.3m and the corridor width is from 0.5m to 1.5m, we use an annulus range with limitation φA=0.7m and φB=1.3m to define the possible door condition (the red shadow in Figure). To avoid the robot trap by the side door detection loop, we consider front data about 45° should smaller than φC=1m (the yellow line in Figure).
For example, considering the right door in the Figure, first check whether two edge laser data.212 and data.2(±24°) are in the red shadow (in Figure), and the data of front 45°(laser data.303) smaller than φC. If the first condition satisfied then check the second condition: all the other data between scan data.212 and data.2, if 75% data satisfied the length condition (in the red shadow), that means there is a right side door, and return possible_door_flag=1, (for the left door possible_door_flag=3 ).

Junction Detection


In the following picture, it is clear that three laser bundles in forward direction, left direction and right direction are selected to detect the junction. In order to find junction in perfect way, the detection radius and detection angle need to be well calculated. The detection angle is set to be 24° since the maximum detection range is ±114°.

As a result, the boundaries of three laser bundles are:

  • Left bundle: +114° and +66°
  • Forward bundle: +24° and −24°
  • Right bundle: −114° and −66°

The width of the corridor is between 0.5m to 1.5m. In order to detect the widthest corridor, the following equation need to be satisfied:

Equ2.png


Also the width of a junction should be bigger than PICO's width, so:

Equ1.png

These two equations will make sure the pico can find junction in the widthest corridor and also could go through the junction in open loop. Finally, the detection radius is set to be 0.85.

Junction.PNG


To find the junction, both boundaries in one laser bundle needs to have longer distance than the detection radius. After that, to increase the robustness of the detection, all the distance of the laser line inside the laser bundle will be measured, if 80% laser line has longer distance than the detection radius, PICO will consider there is a junction.

Two flag are used to describe the exist and feature of junctions: the junction flag and the direction flag.

Junction flag:

  • Junction flag is used to describe the exist of junctions
    • 0: no junction or only forward junction
    • 1: existence of left or right junction

Direction flag:

  • Direction flag D[3] is an array, and each number represent a direction
    • D[0]=true: right direction available
    • D[1]=true: forward direction available
    • D[2]=true: left direction available

If junction flag becomes 1, the decision block will be triggered and decide a direction to move based on the direction flag.

Door Open Detection

We use the similar way to detect if door is opened after 5 second. The forwad direction laser bundle has been used. If both boundaries have longer distance and more than 75% laser line inside the laser bundle is longer than detection radius, PICO will consider door has opened.

Decision Block

Decision Block is consisted of two sub-blocks. One of the sub-blocks is “Corridor Decision Block” and the other block is “Open Space Decision Block”. These two block account for decision in corridor and open-space respectively. The switch between two decision sub-block is based on the value of “openspace_flag”, which indicate the existence of the open space.
As demonstrated in “Figure2 Flow-Chart of Decision block”, when “Decision Block” is executed, program will be navigated to different sub-blocks. Navigating variables are given by “junction_detection” block. According to the internal logic of the “junction_detection” block, “junction_flag” and “openspace_flag” cannot be true at the same time, which ensures that “Decision” block cannot execute “Corridor Decision Block” and “Open Space Decision Block” in same round.
The detailed decision logic will be interpreted below:
“Decision Block” is called after “Detection Block”(junction_detection & door_check) has been executed with the information which indicated the existence of door、junction and open space provided. The value of junction_flag ,openspace_falg and openspace_decision_flag are checked.
  • When junction_flag is true, which indicates that junction is found and the absence of open space due to the mutual exclusiveness between junction indicator and open space indicator, Decision Block will be navigated to “Corridor Decision Block”. Arbitrary choice between available corridor directions will be made in “Corridor Decision Block” .
  • If it is open space detected, “Open Space Decision Block” will be executed, difference priorities are given to different choice. “turning left” is given the highest priority, so the availability of the corridor at right side of the robot will be check first, and then the check on the availability of corridor at forward direction follows and the last direction to check is right side. With this check order, the robot can implement the goal of moving along the left wall in open space. The difference between two sub-blocks in “Open Space Decision Block” is that they adopt different move-forward mode. When “Openspace_flag==true &&Openspace_decision_flag==true” holds, the robot is moving within the open space or just enter the open space. Under these two circumstance, the moving forward movement controlled in a close loop way to avoid bumping the wall . when “openspace_flag==false && openspace_decision_flag=true?” hold, the robot is gonna to encounter with the exit of the open space. Because of lead detection on open space, the indicator of open space has been reset. To ensure that the robot can move to the middle line of the exit before making the next decision, valuable openspace_decision_flag is declared. With this valuable distinguishing the last forward movement before leaving the open space with other forward movements in the open space, last forward movement is an open loop controlled one navigating the robot to move forward by 0.5 meters. “Protection Block” is executed all the time, which protects the robot from bumping in open loop procedures .
Flow Chart of Decision Block
There are three cases that robot may encounter in open space:
Case1:As figure “openspace_case1” show, the first case that robot encountered in open space. In this case, laser beam at right, left and front side has detected the available corridors at the corresponding directions. While another two laser beams at front right and front left direction for open space detection will reset junction_flag when their detection has proved the existence of the open space. Openspace flag and openspace_decision_flag will be set at this moment. Movement control will switch to open space mode. According to the priority of different direction choice, the robot will take turning left as first choice and turn to left side.
openspace_case1
Case2:Then the robot comes to the second case illustrated in “openspace_case2”. Because the front right laser beam keeps reporting the existence of the open space on right side, open space indicator stay at 1. The priority of direction choice make “Forward movement” be the movement choice. Decision block executes “Open Space Decision Block” and the condition “Openspace_flag==true &&Openspace_decision_flag==true” holds, forward movement is controlled in close loop way.
openspace_case2
Case3:The third case following is illustrated in figure “openspace_case3”, laser beam for open space detection are blocked by the wall in front of the robot and thus openspace_flag is reset. While valuable openspace_decision_flag stay at 1 and this variable can only be reset by the second sub-block of “Open Space Decision Block”. Now, condition that “openspace_flag==false && openspace_decision_flag=true” holds and second sub-block of “Open Space Decision Block” is executed. With the priority of the choices, forward movement is selected again. However, this time forward movement is controlled by open loop block and the robot will move forward by 0.5 meter if it is not stopped by protection block.
openspace_case3

Movement

Door Movement


Door_movement function

First, we check the calibration flag and rotate finished flag. The default value for those two value are 0. For the initial condition when the calibration flag and the rotate finished flag are both 0, we then check the possible door flag and based on the value of that flag we decide whether we need to turn right, turn left or just go straight. After the turn is executed, we then set the rotate finished flag into 1. For the case when the calibration flag is 0 but the rotate finished flag is 1, we just set the calibration flag to be 1.

For the condition when the calibration flag is 1, we then check the signal sent flag. The signal sent flag indicates whether the open door request has been sent or not. The initial value for this flag is 0. If the signal sent flag is 0 then we execute the “io.sendOpendoorRequest”, set waiting finished flag to be 0 and wait for 5 seconds. After 5 seconds has expired, we then scan whether the door is opened or not the wait finished flag is set to 1.

If the door is opened, then we clear all the door flag and then jump into turn straight in the junction movement function but if not (indicating we detect no door) then we need to make a turn. The turn that we make is based on the where we detect the door before. If we detect the door in the front then we make 180 degrees rotation, if we detect the door in the left then we make 90 degrees rotation to the right and if detect the door in the right then we make 90 degrees rotation to the left. After the rotation is done, the rotate finished flag is set to 1 and then all of the flag related to the door check and movement are cleared.

Door movement.jpeg

Door movement.png

Junction Movement

The Junction Movement function consist of five cases: turnStraight, TurnRight, TurnLeft, protection and movForward.

turnStraight:
PICO shortly moves straight for 0.5m or when counters time[3s] has passed and continues with the moveForward function. The counter is needed to prevent the program go into a loop when PICO is not able to move the distance. The forward movement is protected by 5 laser sectors. When it is too close to the wall or obstruction, the forward movement will move backwards with an speed of -0.2m/s. When the laser beams for the obstruction detection on the sides of PICO detects that it is too close to the wall, the program goes into the state of protection and moves PICO away from the obstruction.

turnRight and turnLeft:
Both cases turnRight and turnLeft rotates 90 degrees to the corresponding direction and measures the rotation with the odometer to determine when to stop. To make sure that the odometer is accurate enough, the rotating speed is set at 0.2 rad/s.

movForward:
After finishing the turnStraight, the code will go into the movForward state. PICO moves straight for 5m or stops when counters time[5s] has passed. This movement is exactly the same as the turnStraight movement except for the distance and countertime.

protection:
When an obstruction is detected in the turnStraight or movForward, PICO then stops and moves sideways to avoid the obstruction.
The protection in the junction_movement.cpp and move_forward.cpp are explained here: protection

The code snippet is included below:
code snippet: junction_movement.cpp

Move Forward

Similarly to the junction_movement.cpp, move_forward.cpp uses three front laser bundles to adjust the speed. The forward speed is either 0.5m/s when the detection allows or -0.2 m/s otherwise. What differs from the junction_movement.cpp is that the forward movement will not stop when it adjusts with the side movement to avoid obstruction. With 6 laser bundles, 3 at both sides, it adjusts the sidewards speed. When it detects a obstruction, it will move sidewards to avoid the obstruction.

code snippet: move_forward.cpp

Mapping

Mapping2.jpeg

Protection

Detection.jpeg
The picture on the left is the front detection for adjusting the forward velocity and on the right picture is the side detection to adjust the sideways velocity. All laser beams takes the average of 15 points.

The code snippet for side protection here:side protection The code snippet for forward protection here:forward protection

Open Space

Result

Evaluation

The problem of complexity:
[Every function and case can be seen as a state --> no]. By adding states we increase the complexity of the system and this can result very easily into undesired behavior as it is observed. PICO can only perform 20 tasks each second and since we are moving at a speed of 0.5 m/s and this combined with the many states the program has, can result into more undesired behavior.
[mention the problems here or in the blocks itself?]
Right now, states are being used to prevent undesired behavior. This way of solving requires the making of repeating states with different conditions which in itself increases the complexity. It is proposed to cut down the number of states and only focus on the key tasks: moving block, detection block, door handling block, maze solving block. To prevent undesired behavior a supervisory controller can be used.

The problem of open loop: where do we have open loop. what problems , how to solve.

The problem of junction detection: use node is more robust--> make lines

Evaluation group9 EMC 2017

Code snippets

Movement

code snippet: move_forward.cpp
code snippet: junction_movement.cpp

Files