Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Implements a robot that coordinates with other using a
- circular region.
- Read Marcolino & Chaimowicz 2009 ICRA paper for more information
- */
- #include "wiseRobot.h"
- #include "../common/regionMethods.cpp"
- #include "../common/commonMethods.cpp"
- //Function to send warnings between robots. In other words, send the control messages
- void WiseRobot::sendWarning()
- {
- double msg[SIZE_MSG];
- if (m_state != I_DONT_CARE && pho() > congestionOkDist)
- {
- if (m_state == GOING)
- msg[MSG_POS_TYPE] = WATCH_OUT;
- else if (m_state == WAIT || m_state == WAIT_A_LOT)
- msg[MSG_POS_TYPE] = STOP;
- msg[MSG_POS_WAYPOINT_X] = destineX;
- msg[MSG_POS_WAYPOINT_Y] = destineY;
- msg[MSG_POS_MY_X] = m_x;
- msg[MSG_POS_MY_Y] = m_y;
- msg[MSG_POS_MY_ID]= (double) m_id;
- if ((msg[MSG_POS_TYPE] == WATCH_OUT && pho() < congestionDangerDist) || msg[MSG_POS_TYPE] == STOP) // I will send a WATCH_OUT only if I am near my waypoint
- {
- connection.sendMsg(msg,SIZE_MSG);
- #ifdef MESSAGESLOG
- for (int i = 0; i < SIZE_MSG; i++){
- messagesLog << msg[i] << " ";
- }
- messagesLog << endl;
- #endif
- }
- }
- }
- //Constructor. pool is the message pool to send and receive msgs
- WiseRobot::WiseRobot(Pool_t *pool):connection(pool){}
- //Initialize all robot data (pose, connection, velocity, etc.)
- void WiseRobot::init(int id, int numRobots, double prob, double region, string path)
- {
- std::ostringstream strs;
- strs << numRobots;
- std::string numRobotsStr = strs.str();
- m_id = id;
- m_name = "robot" + intToStr(id);
- Pose pose = pos->GetPose();
- m_x = pose.x;
- m_y = pose.y;
- m_th = pose.a;
- numIterations = numIterationsReachGoal = 0;
- connection.init_connection(path);
- m_state = GOING;
- pos->SetColor(GOING_COLOR);
- #ifdef GENERAL_LOG
- log.open(("logs/"+numRobotsStr+"/"+m_name).c_str());
- #endif
- m_prob = prob;
- init_position_data();
- init_laser();
- finished = false;
- #ifdef MESSAGESLOG
- messagesLog.open(("messages/"+m_name).c_str());
- #endif
- messageCount = 0;
- inFrontMisses = 0;
- stalls = 0;
- alreadyStalled = false;
- congestionDangerDist = region;
- }
- /*
- Alter the values of waitX and waitY so that
- the robot goes to a a point outside de danger region
- (simbolized by o in the method's name)
- */
- void WiseRobot::goToRegion_o(){
- const double alpha = (PI/180.0)*(90 - ALFA/2);
- const double gama = (PI/180.0)*(90 + ALFA/2);
- const double deltaX = m_x - destineX;
- const double deltaY = m_y - destineY;
- // deltaX = (deltaX == 0)?0.001:deltaX;
- double r = congestionOkDist + 0.01;
- // double A = (deltaY*deltaY)/(deltaX*deltaX) + 1;
- // double x = (m_x < destineX)?
- // destineX - r/sqrt(A) :
- // destineX + r/sqrt(A) ;
- // double y = (m_y < destineY)?
- // destineY - r*sqrt(1-1/A):
- // destineY + r*sqrt(1-1/A);
- double x = destineX + r * (deltaX/hypot(deltaX,deltaY));
- double y = destineY + r * (deltaY/hypot(deltaX,deltaY));
- //if (inRegion_X(x,y)){
- waitX = x;
- waitY = y;
- //}
- /*else{
- waitX = x;
- if ( ((y > destineY) && (x > destineX)) ||
- ((y <= destineY) && (x <= destineX)) )
- {
- waitY = destineY + tan(alpha)*(x-destineX);
- }
- else
- {
- waitY = destineY + tan(gama)*(x-destineX);
- }
- }*/
- }
- //Finish robot, freeing some variables and closing files
- void WiseRobot::finish()
- {
- //cout << "Destroyed " << m_name <<"!" << endl;
- #ifdef GENERAL_LOG
- log.close();
- #endif
- #ifdef MESSAGESLOG
- messagesLog.close();
- cout << m_name << ": message created!" << endl;
- #endif
- }
- //Alter the values of fx and fy, adding repulsion force.
- void WiseRobot::obstaclesRepulsionForces(double &fx, double &fy)
- {
- double Kobs = (m_state != GOING_OUT && m_state != I_DONT_CARE && m_state != GOING)?Ke:Ki; // Weight of the obstacle repulsion forces
- double distance;
- double dx = 0;
- double dy = 0;
- bool found = false;
- double fx_ = 0 ,fy_ = 0;
- const std::vector<meters_t>& scan = laser->GetRanges();
- uint32_t sample_count = scan.size();
- for(uint32_t i = 0; i < sample_count; i++)
- {
- distance = scan[i];
- double influence = INFLUENCE;
- if (distance <= influence)
- {
- dx = distance*cos(m_th + getBearing(i));
- dy = distance*sin(m_th + getBearing(i));
- if (dx < limit && dx >= 0)
- dx = limit;
- if (dx > -limit && dx < 0)
- dx = -limit;
- if (dy < limit && dy >= 0)
- dy = limit;
- if (dy > -limit && dy < 0)
- dy = -limit;
- double _fx = -Kobs*(1.0/distance - 1.0/(influence*2))*(1.0/pow((double)distance,2))*(dx/distance);
- double _fy = -Kobs*(1.0/distance - 1.0/(influence*2))*(1.0/pow((double)distance,2))*(dy/distance);
- fx += _fx;
- fy += _fy;
- fx_ += _fx;
- fy_ += _fy;
- found = true;
- }
- }
- #ifdef DEBUG_FORCES
- fv.setRepulsiveForces(fx_,fy_);
- #endif
- if (messageCount == 0)
- {
- if (found)
- {
- sendWarning();
- }
- }
- messageCount = (messageCount + 1) % MSG_CYCLES;
- }
- //Implements the main loop of robot.
- //Also contain robot controller and
- //probabilistic finite state machine codes
- void WiseRobot::walk(){
- double fx = 0;
- double fy = 0;
- double norm = 0;
- double r;
- double angTarget;
- double linAccel;
- double rotAccel;
- numIterations++;
- //how many times robot stall?
- if (pos->Stalled()){
- if (!alreadyStalled){
- stalls++;
- alreadyStalled = true;
- }
- }
- else{
- alreadyStalled = false;
- }
- Pose pose = pos->GetPose();
- m_x = pose.x;
- m_y = pose.y;
- m_th = pose.a;
- // Test if WAIT robot should change to I_DONT_CARE if pushed inside the Free region. It is NOT in the official results yet
- /*if (pho() < congestionOkDist)
- {
- m_state = I_DONT_CARE;
- pos->SetColor(I_DONT_CARE_COLOR);
- }*/
- //if (pho() < congestionOkDist && (m_state == WAIT || m_state == WAIT_A_LOT))
- // goToRegion_o();
- //if (pho() < waypointDist && (m_state == I_DONT_CARE || m_state == GOING))
- if (pho() < waypointDist)
- {
- finished = true;
- currentWaypoint = 1 + (rand() % NUMBER_OF_WAYPOINTS);
- //if (m_state == I_DONT_CARE){
- m_state = GOING;
- //}
- pos->SetColor(GOING_OUT_COLOR);
- numIterationsReachGoal = numIterations;
- numIterations = 0;
- }
- if (finished && (distance(m_x,m_y,waypoints[0][0],waypoints[0][1]) >= DISTANT_RADIUS)){
- log << numIterations << endl;
- log.close();
- pos->SetColor(END_COLOR);
- finish();
- finished = false;
- connection.finish(m_id,numIterationsReachGoal,numIterations,stalls);
- }
- #ifdef CHECK_DEAD_ROBOTS
- if (numIterations > DEAD_ITERATIONS)
- {
- connection.finish(m_id,numIterations,0,stalls);
- pos->SetColor(END_COLOR);
- finish();
- }
- #endif
- destineX = waypoints[currentWaypoint][0];
- destineY = waypoints[currentWaypoint][1];
- iteration = (iteration + 1) % PROB_CYCLES;
- if (m_state == WAIT && iteration == 0)
- {
- r = ( (double)rand() / ((double)(RAND_MAX)+(double)(1)) );
- if (r < m_prob)
- if (m_state == WAIT){
- m_state = I_DONT_CARE;
- pos->SetColor(I_DONT_CARE_COLOR);
- }
- }
- if (m_state == GOING || m_state == I_DONT_CARE)
- {
- fx = (destineX - m_x);
- fy = (destineY - m_y);
- norm = sqrt(pow(fx,2) + pow(fy,2));
- fx = Ka*fx/norm;
- fy = Ka*fy/norm;
- }
- else if (m_state == WAIT || m_state == WAIT_A_LOT )
- {
- fx = (waitX - m_x);
- fy = (waitY - m_y);
- if (abs(fx) > 0.01 || abs(fy) > 0.01)
- {
- norm = sqrt(pow(fx,2) + pow(fy,2));
- if (pho() < congestionOkDist)
- {
- fx = Ka*fx/norm;
- fy = Ka*fy/norm;
- }
- else
- {
- fx = 0.1*Ka*fx/norm;
- fy = 0.1*Ka*fy/norm;
- }
- }
- /*else{
- fx = fy = 0;
- }*/
- }
- #ifdef DEBUG_FORCES
- fv.setAttractiveForces(fx,fy);
- #endif
- obstaclesRepulsionForces(fx, fy);
- saturation(fx, fy, maxForce);
- #ifdef DEBUG_FORCES
- fv.setResultantForces(fx,fy);
- #endif
- communicate();
- if (fx == 0 && fy == 0) // Change to inequalities?
- angTarget = m_th;
- else
- angTarget = atan2(fy, fx);
- linAccel = Kl*(fx*cos(m_th) + fy*sin(m_th));
- rotAccel = Kr*(angDiff(angTarget, m_th));
- linAccel += -Kdp*linSpeed;
- rotAccel += -Kdp*rotSpeed;
- linSpeed = linSpeed + linAccel*(TIME_STEP);
- rotSpeed = rotSpeed + rotAccel*(TIME_STEP);
- this->pos->SetXSpeed(linSpeed);
- this->pos->SetTurnSpeed(rotSpeed);
- #ifdef GENERAL_LOG
- //log << m_x << " " << m_y << " " << waitX << " " << waitY << " " << destineX << " " << destineY << " " << m_state << endl;
- #endif
- }
- //Receive messages from robots in the proximity and changes state depending on its type
- //and relative position
- void WiseRobot::communicate()
- {
- double ang;
- bool inFront;
- inFront = false;
- double msg[SIZE_MSG];
- //aqui eh que simula a distancia da comunicacao
- bool msgReceived = connection.receiveMsg(m_x,m_y, m_id, msg, SIZE_MSG);
- if (msgReceived && distWaypoint(msg) < sameWaypointOffset && pho() > congestionOkDist )
- {
- if (msg[MSG_POS_TYPE] == WATCH_OUT)
- {
- ang = (180/3.14)*calcAngTarget(m_x, m_y, msg[MSG_POS_MY_X], msg[MSG_POS_MY_Y]);
- if (pho() < congestionDangerDist && m_state == GOING && !(ang < -5 && ang > -175))
- {
- m_state = WAIT;
- pos->SetColor(WAIT_COLOR);
- waitX = m_x;
- waitY = m_y;
- }
- }
- else if (msg[MSG_POS_TYPE] == STOP)
- {
- ang = (180/3.14)*calcAngTarget(m_x, m_y, msg[MSG_POS_MY_X], msg[MSG_POS_MY_Y]);
- if (ang > 45 && ang < 135)
- {
- if (m_state == GOING)
- {
- m_state = WAIT_A_LOT;
- pos->SetColor(WAIT_A_LOT_COLOR);
- waitX = m_x;
- waitY = m_y;
- }
- inFront = true;
- inFrontMisses = 0;
- }
- else if (pho() < congestionDangerDist && m_state == GOING && !(ang < -5 && ang > -175)) // **Conferir se é necessário
- {
- m_state = WAIT;
- pos->SetColor(WAIT_COLOR);
- waitX = m_x;
- waitY = m_y;
- }
- }
- }
- /*if (m_state == WAIT && pho() > congestionDangerDist){
- m_state = WAIT_A_LOT;
- pos->SetColor(WAIT_A_LOT_COLOR);
- }*/
- if (m_state == WAIT_A_LOT && !inFront){
- inFrontMisses++;
- }
- if (inFrontMisses > MAX_MISSES && m_state == WAIT_A_LOT)
- {
- m_state = GOING;
- pos->SetColor(GOING_COLOR);
- inFrontMisses = 0;
- }
- // Missing in previous experiments... :(
- if (m_state == WAIT_A_LOT && pho() <= congestionDangerDist){
- m_state = WAIT;
- pos->SetColor(WAIT_COLOR);
- }
- }
- Pool_t pool;
- //Pointer to a new robot.
- //Every call of this library will create a new robot
- //using this pointer.
- WiseRobot* robot;
- extern "C" int Init(Model *mod, CtrlArgs *args){
- //printf("Vou criar o robo!\n");
- robot = new WiseRobot(&pool);
- vector<string> tokens;
- Tokenize(args->worldfile, tokens);
- robot->pos = (ModelPosition*)mod;
- robot->pos->AddCallback(Model::CB_UPDATE, (model_callback_t)PositionUpdate, robot );
- robot->laser = (ModelRanger*)mod->GetChild( "ranger:1" );
- robot->laser->Subscribe(); // starts the laser updates
- robot->pos->Subscribe(); // starts the position updates
- //printf("Vou criar o robo!\n");
- robot->init(atoi(tokens[1].c_str()), atoi(tokens[2].c_str()), atof(tokens[3].c_str()), atof(tokens[4].c_str()), tokens[5]);
- #ifdef DEBUG_FORCES
- robot->pos->AddVisualizer( &robot->fv, true );
- #endif
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement