Skip to content

Instantly share code, notes, and snippets.

@amotta
Created November 28, 2013 21:14
Show Gist options
  • Save amotta/7698177 to your computer and use it in GitHub Desktop.
Save amotta/7698177 to your computer and use it in GitHub Desktop.
fran new wall_follower.cpp
#include <ros/ros.h>
#include <theia_services/MotionCommand.h>
#include <theia_services/object.h>
#include "control_logic/info.h"
#include <core_sensors/ir.h>
#include <theia_services/brain_wall.h>
#include <theia_services/stop.h>
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// VARIABLE DEFINITIONS
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////
const float PI = 3.1415926f;
//IR distance thresholds
double front_max = 20.0;
double front_min = 6.0;
double side_max = 20.0;
double side_min = 4.0;
double side_ref = 4.0;
double cross_thres1=10;
double cross_thres2=10;
int last_turn = 0; //0 - null, 1 - left, 2 - right
int last_direction = 0; //0 - null, 1 - left, 2 - right, 3 - forward
double range_exc = 20.0;
double info_heading_ref = 0;
double drive_mode = 0;
double forward_standard = 22.0;
double forward_medium = 32.0;
double forward_extended = 37.0;
const int hist_size = 100;
const int ir_size = 8;
const int median_size = 3;
// info stuff
char info_heading='E';
int info_wall=0;
ros::Publisher info_pub;
ros::Publisher stop_pub;
double ir[ir_size] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
double ir_raw[ir_size][median_size];
typedef struct history_struct{
int driving_mode; //0:None 1:FWD 2:ROTATE 3:FOLLOW_W
double driving_parameters; //None || Angle || Wall
}driving_history;
driving_history history[hist_size];
int flag_turning = 0;
int flag_avoid = 0;
int flag_object = 0;
int object_in_front = 0;
bool active=false;
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// MISC FUNCTIONS
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
* median: median filter the IR values
* */
double median(double ir[median_size]){ // Simple median_size-value median filter. median_size should be odd
double temp, ir_temp[median_size];
for(int i=0; i < median_size; i++)
ir_temp[i]=ir[i];
for(int i=0; i < median_size; i++){
for(int j=i+1; j<median_size; j++){
if(ir[i]>ir[j]){
temp=ir_temp[i];
ir_temp[i]=ir_temp[j];
ir_temp[j]=temp;
}
}
}
return ir_temp[(median_size-1)/2];
}
/*
* readIrData: updates the IR values obtained from the core, then filtering.
* */
void readIrData(core_sensors::ir::ConstPtr ir_msg){
//Shifting IR values to the immediate right cell
for(int i=0; i<ir_size; i++){
for(int j=0; j<2;j++){
ir_raw[i][j+1]=ir_raw[i][j];
}
}
//Filter
for(int i=0; i<ir_size; i++){
ir_raw[i][0]=ir_msg->dist[i];
ir[i]=median(ir_raw[i]);
}
}
/*
* readObjectData: updates the IR values obtained from the core, then filtering.
* */
void readObjectData(theia_services::object::ConstPtr msg){
theia_services::stop stop_msg;
if(!flag_object){
stop_msg.stop=1;
stop_pub.publish(stop_msg);
object_in_front = msg -> object;
if (object_in_front){
flag_object = 1;
}
}
}
/*
* initialize_ir_raw: initialize the IR values by assigning every cell to zero
**/
void initialize_ir_raw(void){
for(int i=0; i<ir_size; i++){
for(int j=0; j<3; j++){
ir_raw[i][j]=0;
}
}
return;
}
/*
* turn_TYPE: possible turning options
**/
void turn_left() {
history[0].driving_mode=2;
history[0].driving_parameters=PI/2;
return;
}
void change_heading(char delta_heading){
switch(info_heading){
case 'E':
if(delta_heading=='R')
info_heading='S';
else
info_heading='N';
break;
case 'N':
if(delta_heading=='R')
info_heading='E';
else
info_heading='W';
break;
case 'W':
if(delta_heading=='R')
info_heading='N';
else
info_heading='S';
break;
case 'S':
if(delta_heading=='R')
info_heading='W';
else
info_heading='E';
break;
}
}
void turn_right() {
history[0].driving_mode=2;
history[0].driving_parameters=-PI/2;
info_wall=-1;
return;
}
double turn_random() {
int random_var = 0;
int driving_var = 1;
random_var=rand()%10; // random_var = {1, 10}
double d_param = 0;
info_wall=-1;
if (random_var > 5){
d_param=PI/2;
change_heading('L');
}else{
d_param=-PI/2;
change_heading('R');
}
return d_param;
}
/**
* turn_TYPE: possible turning options
**/
void go_forward() {
info_heading_ref = 0;
drive_mode = 3;
last_direction = 3;
return;
}
/**
* initialize_history: initialize the history by assuming we have driving forward for infinite time
**/
void initialize_history(void){
int i;
for (i=0; i < hist_size; i++){
history[i].driving_mode=1;
history[i].driving_parameters=forward_standard;
}
return;
}
/**
* shift_history: updates the history by shifting to the right all the cells in the vector
**/
void shift_history(void){
int i;
for (i=hist_size; i>0; i--){
history[i]=history[i-1];
}
//We are going to move forward if an error is detected. Instead of initializing to 1
history[0].driving_mode=1;
history[0].driving_parameters=forward_standard;
return;
}
/*
* object_in_range: Checks from sensor camera if there is an object in front
**/
int object_in_range(void){
if(object_in_front){
return 1;
}else{
return 0;
}
}
/*
* wall_in_range: Checks for a nearby wall for a given threshold, thres. Side: 1 - Left, 2 - Right, 3 - front, 4- crossed
**/
int wall_in_range(int side, double thres){
switch(side){
case 1:
if((ir[2] < thres) && (ir[3] < thres)){
return 1;
}else{
return 0;
}
break;
case 2:
if((ir[4] < thres) && (ir[5] < thres)){
return 1;
}else{
return 0;
}
break;
case 3:
if((ir[0] < thres) || (ir[1] < thres)){
return 1;
}else{
return 0;
}
break;
case 4:
if((ir[6] < cross_thres1 || ir[7] < cross_thres2) && ir[0] > front_max && ir[1] > front_max){
return 1;
}else{
return 0;
}
default:
return 1;
}
}
/**
* closest_wall: returns the closest one of both walls
* wall = 1 (left); wall = 2 (right);
**/
int closest_wall(void){
double closest_wall_left = 0.0;
double closest_wall_right = 0.0;
if ( !wall_in_range(1, side_max) && wall_in_range(2, side_max)){
return 2;
}
else if ( wall_in_range(1, side_max) && !wall_in_range(2, side_max)){
return 1;
}
else if ( wall_in_range(1, side_max) && wall_in_range(2, side_max)){
if(ir[2] < ir[3]) // check for closest wall on left side
closest_wall_left=ir[2];
else
closest_wall_left=ir[3];
if(ir[4] < ir[5]) // check for closest wall on right side
closest_wall_right=ir[4];
else
closest_wall_right=ir[5];
if(closest_wall_left < closest_wall_right){ // check for closest wall
return 1;
}else{
return 2;
}
}else {
//No wall in range ( !wall_in_range(1, side_max) && !wall_in_range(2, side_max))
ROS_INFO("Error closest_wall = -1");
return -1;
}
}
/**
* closest_frontal_wall: returns the closest frontal wall with the cross sensors
* wall = 1 (left); wall = 2 (right);
**/
/*int closest_frontal_wall(void){
double closest_wall_left = 0.0;
double closest_wall_right = 0.0;
if (!wall_in_range(3, front_min) ){
return 2;
}
//No wall in range ( !wall_in_range(1, side_max) && !wall_in_range(2, side_max))
ROS_INFO("Error closest_wall = -1");
return -1;
}
}*/
/*
* last_wall_followed: search last wall followed. Looks if history.driving_mode == 3 (FOLLOW_W)
* It will be called just when 2 walls are seen on the sides. Then we have to decide which wall to follow.
* Special case: No previous history
*/
int last_wall_followed(void){
for (int i=1; i < hist_size; i++){
// history[0] should not be accessed!; history[1] should have the last command!
if (history[i].driving_mode == 3)
{
//history[0].driving_mode = 3;
//history[0].driving_parameters = history[i].driving_parameters; //Keep the last wall followed
return (int) history[i].driving_parameters;
}else{
//Default: Empty driving history
}
}
//If there is no last_wall_followed
//ROS_INFO("last_wall_followed(void): There is no last_wall_followed in history. Return closest wall()");
return closest_wall();
}
/*
* consecutive_rotations: search in history number of consecutive rotations and then UPDATES the value of history[0].
* It will be called just when a wall is seen in front and we hace two options to choose.Then we have to decide where to rotate
*/
int * consecutive_rotations(void){
int rotations=0;
int direction=0;
int i=0;
int * return_vec=0;
return_vec = new int[2];
for (i=1; i<hist_size; i++){
// history[0] should not be accessed!; history[1] should have the last command!
if (history[i].driving_mode == 2){
if (direction==1){
if(history[i].driving_parameters>0)
rotations++;
else
break;
}else if(!direction){
if(history[i].driving_parameters>0){
direction=1;
}else{
direction=2;
}
return_vec[1]=i;
rotations++;
}else if(direction==2){
if(history[i].driving_parameters<0)
rotations++;
else
break;
}
}
if(rotations==3)
break;
}
return_vec[0]=rotations;
return return_vec;
}
/**
*
* rotate2_(not_)last_rotation: returns the direction of the last rotation (or the opposite) based on the history vector and the previous rotation
*
**/
double rotate2_last_rotation(int history_idx){
if(history[history_idx].driving_parameters==PI/2){
change_heading('L');
return PI/2;
}else if(history[history_idx].driving_parameters==-PI/2){
change_heading('R');
return -PI/2;
}else {
//No previous rotations found in history vector
switch(last_wall_followed()){
case 1:
change_heading('L');
return PI/2;
break;
case 2:
change_heading('R');
return -PI/2;
break;
default:
//No wall following detected in the past. No wall to follow. Misbehave by turning randomly.
ROS_INFO("ERROR history[1].driving_parameters = %.2f",history[1].driving_parameters);
return turn_random();
}
}
}
double rotate2_not_last_rotation(int history_idx){
if(history[history_idx].driving_parameters==PI/2){
change_heading('R');
return -PI/2;
}else if(history[history_idx].driving_parameters==-PI/2){
change_heading('L');
return PI/2;
}else {
//No previous rotations found in history vector
switch(last_wall_followed()){
case 1:
change_heading('R');
return -PI/2;
break;
case 2:
change_heading('L');
return PI/2;
break;
default:
//No wall following detected in the past. No wall to follow. Misbehave by turning randomly.
ROS_INFO("ERROR history[1].driving_parameters = %.2f",history[1].driving_parameters);
return turn_random();
break;
}
}
}
/**
*
* rotate2_(not_)last_wall: returns the direction of the last wall (or the opposite) based on the history vector and the previous rotation
*
**/
double rotate2_last_wall(){
if(last_wall_followed()==1){
change_heading('L');
return PI/2;
}else if(last_wall_followed()==2){
change_heading('R');
return -PI/2;
}else{
//No wall following detected in the past. No wall to follow. Misbehave by turning randomly.
ROS_INFO("RANDOM following last_wall_followed() = %d",last_wall_followed());
return turn_random();
}
}
double rotate2_not_last_wall(){
if(last_wall_followed()==1){
change_heading('R');
return -PI/2;
}else if(last_wall_followed()==2){
change_heading('L');
return PI/2;
}else{
//No wall following detected in the past. No wall to follow. Misbehave by turning randomly.
ROS_INFO("RANDOM following last_wall_followed() = %d",last_wall_followed());
return turn_random();
}
}
void publish_info(){
control_logic::info msg;
msg.info_heading=info_heading;
msg.info_wall=info_wall;
info_pub.publish(msg);
}
int give_info_wall(int resB, double resparameter)
{
switch(resB){
case 1:
return 3;
break;
case 2:
return -1;
break;
case 3:
return resparameter;
break;
default:
ROS_INFO("ERROR res.B = %d",resB);
return -1;
break;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// WALL FOLLOWING SECTION
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
* think: will update &res after a given &req
* */
bool think(theia_services::MotionCommand::Request &req, theia_services::MotionCommand::Response &res){
int history_idx = 0, *rot_count=0;
bool turn=true;
if(ir[0]==0 && ir[1]==0 && ir[2]==0 && ir[3]==0 && ir[4]==0 && ir[5]==0 && ir[6]==0 && ir[7]==0){
res.B=0;
return true;
}
if(!active){ // motion will have to ask somewhere else
res.B=0;
initialize_history();
return true;
}
info_wall=0;
//ros::Duration refresh(0.1);
//refresh.sleep(); // wait a bit before sending new orders
//Get empty space in history vector
shift_history();
///////////////////////////////////////////////////
//CASE 0: I am not seeing walls
///////////////////////////////////////////////////
if ( !wall_in_range(1, side_max) && !wall_in_range(2, side_max) && (!wall_in_range(3, front_min)) ){ // && !wall_in_range(4,cross_thres1) && !wall_in_range(4,cross_thres2))
if(!flag_turning){
if(history[1].driving_mode == 1){
//Going forward trying to find a wall
//Might want to go infinite distance
history[0].driving_mode = 1;
history[0].driving_parameters = forward_standard;
flag_turning=0;
}
else if(history[1].driving_mode == 2){
/*We rotated because we saw a wall in the front and after rotated
we stopped seeing it. We want now to go around it. FWD... then ROTATE*/
history[0].driving_mode = 1;
history[0].driving_parameters = forward_standard;
flag_turning=1;
}
else if(history[1].driving_mode == 3){
//I was following a wall and I lost it
history[0].driving_mode = 1;
history[0].driving_parameters = forward_standard;
flag_turning=1;
}else{
//COMING FROM NOWHERE
if(history[1].driving_mode==0){
ROS_INFO("Coming from nowhere");
history[0].driving_mode = 3;
history[0].driving_parameters = closest_wall(); //Follow the closest wall
flag_turning = 0;
}else{
ROS_INFO("Case 0a: Impossible case flag_turning=0 and coming driving_mode = %d", history[1].driving_mode);
}
}
}else{
// flag_turning = 1
//Same code as in the case of at least 1 wall when I am detecting the wall I was not following
if(history[1].driving_mode == 1){
if(history[1].driving_parameters==forward_standard){
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_last_wall();
}else if(history[1].driving_parameters==forward_medium){
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_last_rotation(2);
}else if(history[1].driving_parameters==forward_extended){
ROS_INFO("Case 0b: I did not find a wall to follow\nImpossible case history[1].driving_parameters = %.2f",history[1].driving_parameters);
}else{
ROS_INFO("Case 0b: Error: history[1].driving_parameters = %.2f",history[1].driving_parameters);
}
}
else if(history[1].driving_mode == 2){
history[0].driving_mode = 1;
if(history[2].driving_parameters==forward_standard){
history[0].driving_parameters = forward_medium;
}else{
history[0].driving_parameters = forward_extended;
flag_turning = 0;
}
}else if(history[1].driving_mode == 3){
ROS_INFO("Case 0b: Impossible case flag_turning=1 and coming driving_mode = %d", history[1].driving_mode);
}else{
ROS_INFO("Case 0b: Impossible case flag_turning=1 and coming driving_mode = %d", history[1].driving_mode);
}
}
///////////////////////////////////////////////////
//CASE 1: If I am seeing at least one wall AND there is no wall very close at the front
///////////////////////////////////////////////////
}else if (((wall_in_range(1, side_max) || wall_in_range(2, side_max)) ) && (!wall_in_range(3, front_min)) ){
// flag_turning = 0
if (!flag_turning){
if(history[1].driving_mode == 1){
//Follow the wall if I am not turning around
history[0].driving_mode = 3;
history[0].driving_parameters = last_wall_followed();
//Previous instruction correcting bug in the defined
/*history[0].driving_parameters = closest_wall();
info_wall=closest_wall();*/
//END Previous instruction
flag_turning=0;
}else if(history[1].driving_mode == 2){
//We might be in a corner after rotation
history[0].driving_mode = 3;
history[0].driving_parameters = last_wall_followed();
flag_turning=0;
}else if(history[1].driving_mode == 3){
//I was following a wall and I lost it. Start to turn around
history[0].driving_mode = 1;
history[0].driving_parameters = forward_standard;
flag_turning=1;
}else{
//COMING FROM NOWHERE
ROS_INFO("Case 1a: Impossible case flag_turning=0 and coming driving_mode = %d", history[1].driving_mode);
history[0].driving_mode = 3;
history[0].driving_parameters = closest_wall();
flag_turning = 0;
}
}else{
// flag_turning = 1
if (wall_in_range(last_wall_followed(), side_max)){
//Then it means that I am seeing the wall I was following before I started turning
history[0].driving_mode = 3;
history[0].driving_parameters=last_wall_followed();
flag_turning = 0;
}else{
if(history[1].driving_mode == 1){
if(history[1].driving_parameters==forward_standard){
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_last_wall();
}else if(history[1].driving_parameters==forward_medium){
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_last_rotation(2);
}else if(history[1].driving_parameters==forward_extended){
ROS_INFO("Case 1b: I did not find a wall to follow\nImpossible case history[1].driving_parameters = %.2f",history[1].driving_parameters);
}else{
ROS_INFO("Case 1b: Error: history[1].driving_parameters = %.2f",history[1].driving_parameters);
}
}
else if(history[1].driving_mode == 2){
history[0].driving_mode = 1;
if(history[2].driving_parameters==forward_standard){
history[0].driving_parameters = forward_medium;
}else{
history[0].driving_parameters = forward_extended;
flag_turning = 0;
}
}else if(history[1].driving_mode == 3){
ROS_INFO("Case 1b: Impossible case flag_turning=1 and coming driving_mode = %d", history[1].driving_mode);
}else{
ROS_INFO("Case 1b: Impossible case flag_turning=1 and coming driving_mode = %d", history[1].driving_mode);
}
}
}
///////////////////////////////////////////////////
//CASE 2: If I am seeing at least one wall to the side AND there is a wall very close at the front or crossed
///////////////////////////////////////////////////
}else if (((wall_in_range(1, side_max) || wall_in_range(2, side_max)) ) && ((wall_in_range(3, front_min)))){
// flag_turning = 0
if (!flag_turning){
if(history[1].driving_mode == 1){
//e.g. when we finished turning mode and we face a wall
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_not_last_rotation(2);
}else if(history[1].driving_mode == 2){
//e.g. when we rotate in an internal corner in a narrow path
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_last_rotation(1);
}else if(history[1].driving_mode == 3){
//Internal corner
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_not_last_wall();
}else{
ROS_INFO("Case 2a: Impossible case flag_turning=0 and coming driving_mode = %d", history[1].driving_mode);
}
}
// flag_turning = 1
else{
if (wall_in_range(last_wall_followed(), side_max)){
//Then it means that I am seeing the wall I following before I started turning
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_not_last_wall();
flag_turning = 0;
}
else{
if(history[1].driving_mode == 1){
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_last_wall();
flag_turning = 0;
}else if(history[1].driving_mode == 2){
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_last_wall();
flag_turning = 0;
}else if(history[1].driving_mode == 3){
ROS_INFO("Case 2b: Impossible case flag_turning=1 and coming driving_mode = %d", history[1].driving_mode);
}else{
ROS_INFO("Case 2b: Impossible case flag_turning=1 and coming driving_mode = %d", history[1].driving_mode);
}
}
}
///////////////////////////////////////////////////
//CASE 3: If I am seeing no walls to the side AND there is a wall very close at the front
///////////////////////////////////////////////////
}else if (((!wall_in_range(1, side_max) && !wall_in_range(2, side_max)) ) && ((wall_in_range(3, front_min)) )){ // || (wall_in_range(4,cross_thres1) || wall_in_range(4,cross_thres2))
rot_count=consecutive_rotations();
// flag_turning = 0
if (!flag_turning){
if(history[1].driving_mode == 1){
if(rot_count[0]==3){
history[0].driving_mode = 2;
history[0].driving_parameters = -history[rot_count[1]].driving_parameters; //Change the sign of rotation
if(history[rot_count[1]].driving_parameters==PI/2)
change_heading('R');
else
change_heading('L');
}else{
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_last_wall();
}
}else if(history[1].driving_mode == 2){
//e.g., Turning in a corner in a narrow path
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_last_wall();
}else if(history[1].driving_mode == 3){
ROS_INFO("Case 3a: Error flag_turning has to be 1");
}else{
ROS_INFO("Case 3a: Impossible case flag_turning=0 and coming driving_mode = %d", history[1].driving_mode);
}
}
// flag_turning = 1
else{
if(history[1].driving_mode == 1){
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_last_wall();
}else if(history[1].driving_mode == 2){
//e.g., Trying to access a very narrow gap when turning, and there is no space in front to go FWD
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_not_last_rotation(1);
}else if(history[1].driving_mode == 3){
ROS_INFO("Case 3: ERROR I cannot be in history[1].driving_mode = %d and flag=1",history[1].driving_mode);
}else{
ROS_INFO("Case 3: Impossible case flag_turning=1 and coming driving_mode = %d", history[1].driving_mode);
}
}
delete [] rot_count;
}
///////////////////////////////////////////////////
//CASE default: No defined case
///////////////////////////////////////////////////
else {
ROS_INFO("\nI am not in any case =(");
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// FIX
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if ( (wall_in_range(4,cross_thres1)) || (wall_in_range(4,cross_thres2)) || flag_avoid ){
//If we have the flag_avoid then we can to avoid the pointy wall
if (!wall_in_range(3, front_min) && !flag_avoid ){
//The detected wall is pointy avoid it
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_not_last_wall();
flag_avoid = 1;
}else if(!wall_in_range(3, front_min) && flag_avoid){
//After rotation we want it to go forward and start the rotation behavior
history[0].driving_mode = 1;
history[0].driving_parameters=forward_standard;
flag_avoid = 0;
flag_turning = 1;
}else if( wall_in_range(3, front_min) ){
//Do nothing
}
}
//By doing this we give more importance to the object. If we find an object and a pointy wall, then we ignore the pointy wall
//Check this assumption later
if ( (wall_in_range(4,cross_thres1)) || (wall_in_range(4,cross_thres2)) || flag_object ){
//If we have the flag_object then we can to avoid the object
if (!wall_in_range(3, front_min) && flag_object ){
//We have detected an object
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_not_last_wall();
flag_object = 0;
}else if(!wall_in_range(3, front_min) && !flag_object){
//After rotation we want it to go forward and start the rotation behavior
history[0].driving_mode = 1;
history[0].driving_parameters=forward_standard;
flag_object = 0;
flag_turning = 1;
}else if( wall_in_range(3, front_min) ){
//Do nothing
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////// FIX
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* if( !wall_in_range(3, front_min) || flag_avoid || flag_object){
//There is an evil wall at front
if(!flag_avoid){
if ( (wall_in_range(4,cross_thres1)) || (wall_in_range(4,cross_thres2)) ){
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_not_last_wall();
flag_avoid = 1;
}
}else{
//(flag_avoid)
//If we are avoiding and object then we shouldn't see that object anymore
if ( (wall_in_range(4,cross_thres1)) || (wall_in_range(4,cross_thres2)) ){
//If we see a new object in the front while avoiding, then we sort of begin to avoid
if(history[1].driving_mode == 1 || history[1].driving_mode == 2){
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_not_last_wall();
flag_avoid = 1;
flag_object = 0;
}
}else if(history[1].driving_mode == 2 && flag_avoid){
flag_turning = 1;
flag_avoid=0;
history[0].driving_mode = 1;
history[0].driving_parameters=forward_standard;
}else if(flag_object!=0){
if(flag_object==1){
history[0].driving_mode = 2;
history[0].driving_parameters=rotate2_not_last_wall();
flag_object=2;
}else if (flag_object==2){
flag_turning = 1;
flag_object = 0;
history[0].driving_mode = 1;
history[0].driving_parameters=forward_standard;
}
}
}
}*/
///////////////////////////////////////////////////
///////////////////////////////////////////////////
//Finished cases. Debug
///////////////////////////////////////////////////
///////////////////////////////////////////////////
ROS_INFO("Last wall: %d",last_wall_followed());
ROS_INFO("Turn flag: %d",flag_turning);
printf("\n");
switch(history[0].driving_mode){
case 1:
ROS_INFO("GO FORWARD");
break;
case 2:
ROS_INFO("TURN %.2f",history[0].driving_parameters);
break;
case 3:
ROS_INFO("FOLLOW WALL: %.0f",history[0].driving_parameters);
break;
default:
//If an error is detected then the default behaviour is going forward as initialization and shifting function suggest
history[0].driving_mode=1;
history[0].driving_parameters=forward_standard;
ROS_INFO("ERROR!! OMG! ERROR!! \n history[0].driving_parameters == -1");
break;
}
//getchar();
res.B = history[0].driving_mode;
res.parameter = history[0].driving_parameters;
info_wall = give_info_wall(res.B, res.parameter);
publish_info();
//loop_rate.sleep();
//ros::spinOnce();
//Update in history vector
return true;
}
bool status(theia_services::brain_wall::Request &req, theia_services::brain_wall::Response &res){
active=req.active;
info_heading=req.heading;
res.ok=true;
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// MAIN() SECTION
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////
int main(int argc, char ** argv){
ros::init(argc, argv, "wall_follower");
ros::NodeHandle n;
ros::Rate loop_rate(10);
ros::ServiceServer motion_command = n.advertiseService("/wall_follower/motion_command", think); //Set up service server in this node
ros::ServiceServer orders = n.advertiseService("/wall_follower/instructions", status);
ros::Subscriber ir_data = n.subscribe("/core_sensors_ir/ir", 1, readIrData);
//ros::Subscriber camera_data = n.subscribe("/core_sensors_ir/ir", 1, readCameraData);
ros::Subscriber object_subs = n.subscribe<theia_services::object>("/control_logic/object",1,readObjectData);
stop_pub = n.advertise<theia_services::stop>("/control_motion/stop",1);
info_pub = n.advertise<control_logic::info>("/control_logic/info",1);
initialize_history();
initialize_ir_raw();
while(ros::ok()){
loop_rate.sleep();
ros::spinOnce();
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment