int32_t KobukiMobileController::GetPosition(OPRoS::MobilePositionData &position) { double x, y, radian; getOdometry(x, y, radian); position.x = x; position.y = y; position.theta = radian * 180.0 / M_PI; return API_SUCCESS; }
const bool RobotAction::rotation(const double& swingRange) { MessageFreqMgr requestOdo; sendMessageFreq(requestOdo); Sleep(sizeof(requestOdo)); this->buzyWaitForMgr(500); OdometryMgr curPos; getOdometry(curPos); this->getCurrentTime(); /* Prepare subgoal message */ SubgoalMgr goal; goal.x = curPos.x; goal.y = curPos.y; goal.theta = curPos.theta + swingRange * 2.0; // Multiple 2 to speed up the rotation /* Send subgoal message */ sendSubgoal(goal); Sleep(sizeof(goal) + 2000); // Turn to the another direction goal.theta = curPos.theta + swingRange * -2.0; sendSubgoal(goal); Sleep(sizeof(goal) + 4000); /* Turn back */ goal.theta = curPos.theta + swingRange * 2.0; // To speed up the turn back sendSubgoal(goal); Sleep(sizeof(goal) + 2000); goal.theta = curPos.theta; sendSubgoal(goal); naviExecuting = true; Sleep(sizeof(goal)); while (this->executingTime() <= timeout) { if (naviExecuting == false) return true; Sleep(50); } // Timeout cout << "> WARNING: Action, Rotation, timeout" << endl; return false; }
/** * @brief RobotThread::RobotThread */ RobotThread::RobotThread() { // necessary to send this type over qued connections qRegisterMetaType< QVector<double> >("QVector<double>"); qRegisterMetaType< QList<Obstacle> >("QList<Obstacle>"); qRegisterMetaType< QList< QPair<double,double> > >("QList< QPair<double,double> >"); // fuer path planning -> path realizer qRegisterMetaType< PathPlotData >("PathPlotData"); qRegisterMetaType< FilterParams >("FilterParams"); qRegisterMetaType< CameraParams >("CameraParams"); qRegisterMetaType< PIDParams >("PIDParams"); qRegisterMetaType< PIDPlotData >("PIDPlotData"); qRegisterMetaType< cv::Mat >("cv::Mat"); qRegisterMetaType< QString >("QString"); //Log qRegisterMetaType< LaserPlotData > ("LaserPlotData"); qRegisterMetaType< Position > ("Position"); qRegisterMetaType< TeamColor >("TeamColor"); qRegisterMetaType< CamColor >("CamColor"); qDebug() << "INIT 'RobotThread'"; //initialize Objects for Actors and Sensory actorLowLevel = new ActorLowLevel(); actorHighLevel = new ActorHighLevel(); sensorHighLevel = new SensorHighLevel(); sensorLowLevel = new SensorLowLevel(); pathPlanner = new PathPlanning(); gameEngine = new GameEngine(); cam = new Cam(); // moving objects to different threads sensorLowLevel->moveToThread(&threadRobotLowLevel); sensorHighLevel->moveToThread(&threadSensorHighLevel); actorLowLevel->moveToThread(&threadRobotLowLevel); actorHighLevel->moveToThread(&threadActorHighLevel); pathPlanner->moveToThread(&threadPathPlanner); gameEngine->moveToThread(&threadGameEngine); cam->moveToThread(&threadCam); // Name the threads (helpful for debugging) threadRobotLowLevel.setObjectName("Robot Low Level Thread"); threadSensorHighLevel.setObjectName("High Level Sensor Thread"); threadPathRealizer.setObjectName("Path Realizer Thread"); threadPathPlanner.setObjectName("Path Planner Thread"); threadGameEngine.setObjectName("Game Engine Thread"); threadCam.setObjectName("Cam Thread"); // *********************************************************************** // DELETE LATER connect(&threadRobotLowLevel, SIGNAL(finished()), sensorLowLevel, SLOT(deleteLater())); connect(&threadSensorHighLevel, SIGNAL(finished()), sensorHighLevel, SLOT(deleteLater())); connect(&threadRobotLowLevel, SIGNAL(finished()), actorLowLevel, SLOT(deleteLater())); connect(&threadActorHighLevel, SIGNAL(finished()), actorHighLevel, SLOT(deleteLater())); connect(&threadPathPlanner, SIGNAL(finished()), pathPlanner, SLOT(deleteLater())); connect(&threadCam, SIGNAL(finished()), cam, SLOT(deleteLater())); connect(&threadGameEngine, SIGNAL(finished()), gameEngine, SLOT(deleteLater())); // *********************************************************************** // SIGNALS FROM GUI // start Orientation connect(mainWindow,SIGNAL(signalStartOrientation(bool)), sensorHighLevel, SLOT(slotStartDetection(bool))); // remote controle over GUI connect(mainWindow,SIGNAL(robotRemoteControllUpdate(double,double)), actorLowLevel,SLOT(setRobotRemoteControllParams(double,double))); // remote Odometry update connect(mainWindow,SIGNAL(updateRemoteOdometry(Position)), actorLowLevel, SLOT(setOdometry(Position))); // Cam Display // Camera Parameters in GUI have changed, send to Cam class connect(mainWindow, SIGNAL(signalChangeCamParams(CameraParams)), cam, SLOT(slotSetCameraParams(CameraParams))); // Set Median Filter connect(mainWindow, SIGNAL(signalChangeFilterParams(FilterParams)), sensorHighLevel, SLOT(slotSetFilterParams(FilterParams))); // PID Tab connect(mainWindow, SIGNAL(signalChangePIDParams(PIDParams)), actorHighLevel, SLOT(slotChangePIDParams(PIDParams))); // *********************************************************************** // SIGNALS TO GUI // Sensor Display // Display the sensor data in GUI connect(sensorLowLevel, SIGNAL(signalLaserPlotRaw(LaserPlotData)), // raw data mainWindow, SLOT(slotLaserDisplay(LaserPlotData))); connect(sensorHighLevel, SIGNAL(signalSendLaserData(LaserPlotData)), // filtered data mainWindow, SLOT(slotLaserDisplay(LaserPlotData))); // Path Display // Display potential map and raw waypoints connect(pathPlanner, SIGNAL(pathDisplay(PathPlotData)), mainWindow, SLOT(updatePathDisplay(PathPlotData))); // Display calculated spline connect(actorHighLevel, SIGNAL(signalSplinePlot(PathPlotData)), mainWindow, SLOT(updatePathDisplay(PathPlotData))); // Display PID Plot connect(actorHighLevel, SIGNAL(signalPIDPlot(PIDPlotData)), mainWindow, SLOT(slotPIDPlot(PIDPlotData))); // Cam grabbed a frame, display in GUI connect(cam, SIGNAL(signalDisplayFrame(cv::Mat)), mainWindow, SLOT(slotDisplayFrame(cv::Mat))); // *********************************************************************** // emergency detected/received connect(sensorHighLevel,SIGNAL(signalEmergencyStopEnabled(bool)), // emergency stop durch kollisionsvermeidung actorLowLevel,SLOT(slotEmergencyStopEnabled(bool))); connect(gameEngine, SIGNAL(signalEmergencyStopEnabled(bool)), // stopMovement() von Referee actorLowLevel, SLOT(slotEmergencyStopEnabled(bool))); //send turn command from high sensor to low level actor connect(sensorHighLevel,SIGNAL(signalSendRobotControlParams(double,double)), actorLowLevel,SLOT(setRobotControllParams(double,double))); // controle command from High Level Aktor connect(actorHighLevel,SIGNAL(signalSendRobotControlParams(double,double)), actorLowLevel,SLOT(setRobotControllParams(double,double))); // Get waypoints from path planning into the path realizer connect(pathPlanner, SIGNAL(sendUpdatedWaypoints(QList< QPair<double,double> >)), actorHighLevel, SLOT(slotUpdateWaypoints(QList< QPair<double,double> >))); // SENSOR DATA TO HIGH LEVEL SENSOR connect(sensorLowLevel,SIGNAL(laserDataReady(QVector<double>)), sensorHighLevel, SLOT(getLaserData(QVector<double>))); connect(sensorLowLevel,SIGNAL(sonarDataReady(QVector<double>)), sensorHighLevel, SLOT(getSonarData(QVector<double>))); // start color detection from sensor connect(sensorHighLevel, SIGNAL(signalStartColorDetection()), cam, SLOT(slotStartColorDetection())); // color succesfully detected connect(cam, SIGNAL(signalColorDetected(CamColor)), sensorHighLevel, SLOT(slotColorDetected(CamColor))); // *********************************************************************** // update Odometry connect(sensorLowLevel,SIGNAL(updateOdometry()), actorLowLevel, SLOT(getOdometry())); connect(sensorHighLevel, SIGNAL(sendOdometryData(Position)), actorLowLevel, SLOT(setOdometry(Position))); // *********************************************************************** // Signals from GameEngine connect(gameEngine,SIGNAL(signalStartDetection(bool)), sensorHighLevel, SLOT(slotStartDetection(bool))); // Signals to GameEngine connect(sensorHighLevel, SIGNAL(signalSendTeamColor(CamColor)), gameEngine, SLOT(slotDetectionFinished(CamColor))); // starting the eventloop of all threads threadRobotLowLevel.start(); threadSensorHighLevel.start(); threadPathRealizer.start(); threadPathPlanner.start(); threadCam.start(); threadGameEngine.start(); // Starte Game Engine State Machine gameEngine->start(); // Start the PathPlanning "loop" /// \todo: Das ist erstmal nur zum Debuggen drinnen. // Spaeter darf die Pfadplanung nur bei beginn der Spielphase aus der GameEngine heraus angestossen werden QMetaObject::invokeMethod(pathPlanner, "planPath"); }
const bool RobotAction::movingToAroundOfHuman(const int& speed, const float& distance, const double& angle2FrontOfHuman) { this->turnFaceToHuman(); Sleep(1000); /* Request current robot pose */ MessageFreqMgr requestOdo; sendMessageFreq(requestOdo); Sleep(sizeof(requestOdo)); this->buzyWaitForMgr(250); OdometryMgr curPos; getOdometry(curPos); /* Request current human pose */ PerceptionMgr legRequest; legRequest.sensing = legDetection; sendPerception(legRequest); Sleep(sizeof(legDetection)); this->buzyWaitForMgr(250); PeopleMgr targetPos; getPeople(targetPos); /* Request body direction */ PerceptionHAEMgr requestBody; requestBody.sensing = bodyDirectionCont; sendPerceptionHAE(requestBody); Sleep(sizeof(requestBody)); this->buzyWaitForMgr(250); HAEMgr receivedBodyDir; getHAE(receivedBodyDir); /* Prepare subgoal message */ // Find the possible candidate of the target, the nearest one double possibleCandidateX = 0.0, possibleCandidateY = 0.0; if (targetPos.count == 0) { cout << "> WARNING: No Human Candidate!" << endl; return 1; } else if(targetPos.count > 1) { /* Find the person who is nearest to the robot */ float minX = 0.0, minY = 0.0, squaredDistance = 0.0, minSquaredDistance = 999999.0; for (int i = 0; i < targetPos.count; i++) { squaredDistance = pow(targetPos.x[i],2) + pow(targetPos.y[i],2); if (squaredDistance <= minSquaredDistance) { minSquaredDistance = squaredDistance; minX = targetPos.x[i]; minY = targetPos.y[i]; } } possibleCandidateX = minX / 100.0; possibleCandidateY = minY / 100.0; } double dist_robot2human = sqrt(pow(possibleCandidateX / 100.0, 2) + pow(possibleCandidateY / 100.0, 2)); double theta_BD = (-1 * receivedBodyDir.body_direction_cont); double theta_robotHeading = atan2(possibleCandidateY, possibleCandidateX) * 180 / M_PI; /* Coordinate Transformation */ CoordTrans coordinateTrans; // From human coordinate (B) to robot coordinate (R) double X_g_H = distance * cos(angle2FrontOfHuman / 180 * M_PI), Y_g_H = distance * sin(angle2FrontOfHuman / 180 * M_PI), theta_g_H = 180.0 + angle2FrontOfHuman; double X_g_R = 0.0, Y_g_R = 0.0, theta_g_R = 0.0; coordinateTrans.trans2D(X_g_H, Y_g_H, theta_g_H, dist_robot2human * cos(theta_BD / 180 * M_PI), dist_robot2human * sin(theta_BD / 180 * M_PI), 180.0 + theta_BD - theta_robotHeading, X_g_R, Y_g_R, theta_g_R); // From robot coordinate to world coordinate (W) double X_g_W = 0.0, Y_g_W = 0.0, theta_g_W = 0.0; coordinateTrans.trans2D(X_g_R, Y_g_R, theta_g_R, curPos.x - 0.0, curPos.y - 0.0, -1 * curPos.theta, X_g_W, Y_g_W, theta_g_W); /* For visualization, used for debug */ // Transform the centor point of human //double X_c_H = 0.0, Y_c_H = 0.0, Y_c_R, Y_c_W, X_c_R, X_c_W; //coordinateTrans.trans2D(X_c_H, Y_c_H, theta_g_H, // dist_robot2human * cos(theta_BD / 180 * M_PI), dist_robot2human * sin(theta_BD / 180 * M_PI), 180.0 + theta_BD - theta_robotHeading, // X_c_R, Y_c_R, theta_g_R); //coordinateTrans.trans2D(X_c_R, Y_c_R, theta_g_R, // curPos.x - 0.0, curPos.y - 0.0, -1 * curPos.theta, // X_c_W, Y_c_W, theta_g_W); //int imgX_g = 0, imgY_g = 0, imgX_c = 0, imgY_c = 0; //coordinateTrans.plane2Img(X_g_W, Y_g_W, imgX_g, imgY_g); //coordinateTrans.plane2Img(X_c_W, Y_c_W, imgX_c, imgY_c); //coordinateTrans.insertPoint(imgX_g, imgY_g); //coordinateTrans.insertPoint(imgX_c, imgY_c); //coordinateTrans.drawPoint(); SubgoalMgr goal; goal.theta = theta_g_W; goal.x = X_g_W; goal.y = Y_g_W; /* Print information for debug */ cout << "BodyDirection: " << receivedBodyDir.body_direction_cont << endl; cout << "X_Goal: " << goal.x << ", Y_Goal: " << goal.y << ", Theta_Goal: " << goal.theta << endl; /* Send subgoal message */ sendSubgoal(goal); naviExecuting = true; Sleep(sizeof(goal) + 500); this->getCurrentTime(); this->turningFace(0); Result_Navi resultNaviStatus; getResultNavi(resultNaviStatus); while (this->executingTime() <= timeout) { if (naviExecuting == false || resultNaviStatus.current_status == FINISHED) return true; getResultNavi(resultNaviStatus); Sleep(50); } // Timeout cout << "> WARNING: Action, MovingToFrontOfHuman, timeout" << endl; naviExecuting = false; return false; }
const bool RobotAction::forwardApproach(const int& speed, const double& distance) { this->turningFace(0); /* Request current robot pose */ MessageFreqMgr requestOdo; sendMessageFreq(requestOdo); Sleep(sizeof(requestOdo)); this->buzyWaitForMgr(500); OdometryMgr curPos; getOdometry(curPos); /* Request current human pose */ PerceptionMgr legRequest; legRequest.sensing = legDetection; sendPerception(legRequest); Sleep(sizeof(legDetection)); this->buzyWaitForMgr(500); PeopleMgr targetPos; getPeople(targetPos); /* Prepare subgoal message */ if (targetPos.count == 0) { cout << "> WARNING: No Human!" << endl; return 1; } else if(targetPos.count > 1) { /* Find the person who is nearest to the robot */ float minX = 0.0, minY = 0.0, squaredDistance = 0.0, minSquaredDistance = 999999.0; for (int i = 0; i < targetPos.count; i++) { squaredDistance = pow(targetPos.x[i],2) + pow(targetPos.y[i],2); if (squaredDistance <= minSquaredDistance) { minSquaredDistance = squaredDistance; minX = targetPos.x[i]; minY = targetPos.y[i]; } } targetPos.x[0] = minX; targetPos.y[0] = minY; } double dX = (targetPos.x[0] / 100.0) - curPos.x; double dY = (targetPos.y[0] / 100.0) - curPos.y; if (sqrt(pow(dX, 2) + pow(dY, 2)) < 1.5) { cout << "> WARNING: Too close to human!" << endl; return false; } SubgoalMgr goal; goal.theta = atan2(dY, dX) * 180 / M_PI; goal.x = curPos.x + distance * cos(goal.theta / 180 * M_PI); goal.y = curPos.y + distance * sin(goal.theta / 180 * M_PI); cout << "Xr: " << curPos.x << ", Yr: " << curPos.y << endl; cout << "Xh: " << targetPos.x[0] << ", Yh: " << targetPos.y[0] << endl; cout << "Xg: " << goal.x << ", Yg: " << goal.y << endl; /* Send subgoal message */ sendSubgoal(goal); naviExecuting = true; Sleep(sizeof(goal) + 500); this->getCurrentTime(); Result_Navi resultNaviStatus; getResultNavi(resultNaviStatus); while (this->executingTime() <= timeout) { if (naviExecuting == false || resultNaviStatus.current_status == FINISHED) return true; getResultNavi(resultNaviStatus); Sleep(50); } // Timeout cout << "> WARNING: Action, ForwardApproach, timeout" << endl; naviExecuting = false; return false; }