void FieldPainter::drawPostAbs (const AbsCoord &post, QColor colour) { save(); translate(post.x(), post.y()); setPen("white"); setBrush(colour); drawEllipse (QPoint(0, 0), 80, 80); restore(); }
void MultiGaussianDistribution::addSymmetricMode(std::vector<SimpleGaussian*> &distribution) { AbsCoord ballPos = distribution.front()->getBallPosition(); double fromCentre = sqrt(ballPos.x()*ballPos.x() + ballPos.y()*ballPos.y()); // If the ball is close to the centre then a symmetric mode will be too close to the original mode // and hence provide spurious matches potentially. if (fromCentre >= 1300.0) { // TODO: make this a constant in the ConstantsProvider SimpleGaussian *symmetric = distribution.front()->createSymmetricGaussian(); distribution.push_back(symmetric); } }
void FieldPainter::drawBallPosAbs(const AbsCoord &ball, QColor colour) { save(); QPoint newBall = QPoint(ball.x(), ball.y()); QPen absPen(colour); setPen(absPen); setBrush(QBrush(colour)); drawEllipse(newBall, 40, 40); restore(); drawAbsCovEllipse(ball, absPen); }
void FieldPainter::drawPlayerNumber (const AbsCoord &pos, int num) { save(); translate(pos.x() - 50, pos.y() - 400); scale(1,-1); setPen("white"); setBrush(QColor("white")); QFont font; font.setPixelSize(200); setFont(font); drawText(0, 0, QString::number(num)); restore(); }
void FieldPainter::translateRR(const RRCoord &rr, const AbsCoord &robot) { translate(robot.x(), robot.y()); rotate((const float)RAD2DEG(robot.theta())); rotate((const float)RAD2DEG(rr.heading())); translate(rr.distance(), 0); /* rotate((const float)RAD2DEG(-robot.theta())); rotate((const float)RAD2DEG(-rr.heading())); */ if (!isnan(rr.orientation())) { rotate(RAD2DEG(-rr.orientation())); } }
// draw absolute position covariance ellipse void FieldPainter::drawAbsCovEllipse(const AbsCoord &pos, QPen variancePen) { variancePen.setWidth(20); Eigen::VectorXf eigenvalues = pos.var.block<2, 2>(0,0).marked<Eigen::SelfAdjoint>().eigenvalues(); int r_major_axis = sqrt(MAX(eigenvalues[0], eigenvalues[1])); int r_minor_axis = sqrt(MIN(eigenvalues[0], eigenvalues[1])); float theta = atan2(2*pos.var(0,1), pos.var(0,0)-pos.var(1,1))/2.0; save(); translate(pos.x(), pos.y()); rotate(RAD2DEG(theta)); QRect varRect(-r_major_axis, -r_minor_axis, r_major_axis*2, r_minor_axis*2); setPen(variancePen); setBrush(QBrush(Qt::NoBrush)); drawEllipse(varRect); restore(); }
void FieldPainter::drawBallPosRRC(const AbsCoord &ballPos, const AbsCoord &ballVel, bool moving, const AbsCoord &robot) { save(); translate(robot.x(), robot.y()); rotate(RAD2DEG(robot.theta())); QPoint newBall = QPoint(ballPos.x(), ballPos.y()); QPoint nextBall = QPoint(ballPos.x() + ballVel.x(), ballPos.y() + ballVel.y()); setPen(QPen(QColor(255, 0, 0))); setBrush(QBrush(QColor(255, 0, 0))); drawEllipse(newBall, 40, 40); if (moving) drawLine(newBall, nextBall); restore(); drawRRCovEllipse(ballPos, robot); }
void FieldPainter::drawRobotAbs (const AbsCoord &pos, QColor colour, bool ellipse, QColor varColour) { static const int robot_radius = 120; QRect roboRect(-robot_radius,-robot_radius,robot_radius*2,robot_radius*2); QPen variancePen(varColour); variancePen.setWidth(20); // draw pacman save(); translate(pos.x(), pos.y()); setPen("black"); int fov; if (pos.var(2,2) > 0) { fov = MIN(160, RAD2DEG(sqrt(pos.var(2,2)))); } else { fov = 0; } setBrush(QBrush(colour)); rotate((RAD2DEG(pos.theta())-(fov/2))); drawPie(roboRect, 0, (360-fov)*16); restore(); /* Converting covariance matrix to ellipse representation * Eigenvalues of the matrix are the major and minor axis lengths * Eigenvectors are the vectors from the center along the axes (should be perpendicular) */ if (ellipse) { Eigen::VectorXf eigenvalues = pos.var.block<2, 2>(0,0).marked<Eigen::SelfAdjoint>().eigenvalues(); int r_major_axis = MAX(sqrt(MAX(eigenvalues[0], eigenvalues[1])), robot_radius); int r_minor_axis = MAX(sqrt(MIN(eigenvalues[0], eigenvalues[1])), robot_radius); float theta = atan2(2*pos.var(0,1), pos.var(0,0)-pos.var(1,1))/2.0; // draw position covariance ellipse save(); translate(pos.x(), pos.y()); rotate(RAD2DEG(theta)); QRect varRect(-r_major_axis, -r_minor_axis, r_major_axis*2, r_minor_axis*2); setPen(variancePen); setBrush(QBrush(Qt::NoBrush)); drawEllipse(varRect); restore(); } }
void FieldPainter::drawFeatureAbs (const AbsCoord &pos, const FieldFeatureInfo::Type &type) { save(); translate(pos.x(), pos.y()); rotate(RAD2DEG(pos.theta())); setPen(Qt::NoPen); setBrush(QBrush("red")); QPen p; switch (type) { case FieldFeatureInfo::fCorner: save(); rotate(RAD2DEG(M_PI_4)); drawRect(-25, -25, 300, 50); restore(); save(); rotate(RAD2DEG(-M_PI_4)); drawRect(-25, -25, 300, 50); restore(); break; case FieldFeatureInfo::fTJunction: drawRect(-25, -300, 50, 600); drawRect(0, -25, 300, 50); case FieldFeatureInfo::fPenaltySpot: break; case FieldFeatureInfo::fCentreCircle: save(); setPen("red"); p = pen(); p.setWidth(50); setPen(p); setBrush(Qt::NoBrush); drawEllipse (QPoint(0, 0), 600, 600); restore(); break; case FieldFeatureInfo::fLine: break; default: break; } restore(); }
void MultiGaussianDistribution::startOfPlayReset(void) { // All other modes other than the best mode that are in the opponent half are zeroed out. for (unsigned i = 1; i < modes.size(); i++) { if (modes[i]->getRobotPose().x() > 0.0) { modes[i]->setWeight(0.0); } } AbsCoord robotPose = modes.front()->getRobotPose(); // If we are way inside the opponent half or we are just inside the opponent half and think we // are facing our own goal, then we are symmetrically flipped. NOTE: we dont want to blindly // zero out all modes that are in the opposing half because it is possible that we are // actually in our own half but due to noise the state estimation places us just over the // halfway line. This is quite possible for robots standing near the halfway line. if (robotPose.x() > 1000.0 || (robotPose.x() > 0.0 && fabs(robotPose.theta()) > M_PI/2.0)) { SimpleGaussian *flippedMode = modes.front()->createSymmetricGaussian(); modes.front()->setWeight(0.0); modes.push_back(flippedMode); } fixupDistribution(); }
void VariableView::redraw(NaoData *naoData) { Frame frame = naoData->getCurrentFrame(); Blackboard *blackboard = (frame.blackboard); if(!blackboard) return; // struct RobotPos wrapperPos[4]; // readArray(localisation, robot, wrapperPos); AbsCoord pos = readFrom(localisation, robotPos); stringstream spos; uint32_t ballLostCount = readFrom(localisation, ballLostCount); AbsCoord ballPos = readFrom(localisation, ballPos); AbsCoord ballVelRRC = readFrom(localisation, ballVelRRC); spos << " Robot @ (" << pos.x() << ", " << pos.y() << ")" << endl; spos << "Heading: " << pos.theta() << " (" << RAD2DEG(pos.theta()) << " deg)" << endl; spos << "Variance: " << pos.var(0,0) << ", " << pos.var(1,1) << ", " << pos.var(2,2) << endl; spos << "ballLostCount: " << ballLostCount << endl; spos << "ball pos; x:" << ballPos.x() << ", y:" << ballPos.y() << endl; spos << "ball var; xx:" << ballPos.var(0,0) << ", xy:" << ballPos.var(0,1) << endl; spos << " yx:" << ballPos.var(1,0) << ", yy:" << ballPos.var(1,1) << endl; spos << "ball vel rrc; x':" << ballVelRRC.x() << ", y':" << ballVelRRC.y() << endl; spos << "ball vel rrc var; x'x':" << ballVelRRC.var(0,0) << ", x'y':" << ballVelRRC.var(0,1) << endl; spos << " y'x':" << ballVelRRC.var(1,0) << ", y'y':" << ballVelRRC.var(1,1) << endl; localisationRobotPos->setText(0, spos.str().c_str()); updateVision(naoData); updateBehaviour(naoData); stringstream steam; steam << "gamecontroller.team_red = " << readFrom(gameController, team_red) << endl; gameControllerTeam->setText(0, steam.str().c_str()); }
SPLStandardMessage(const int &playerNum, const int &teamNum, const int &fallen, const AbsCoord &robotPos, const AbsCoord &walking, const AbsCoord &shooting, const int &ballAge, const AbsCoord &ballPosition, const AbsCoord &ballVelocity, const int8_t intention, const BroadcastData &broadcast) : playerNum(playerNum), teamNum(teamNum), fallen(fallen), ballAge(ballAge), intention(intention), averageWalkSpeed(200), maxKickDistance(8000), currentPositionConfidence(50), currentSideConfidence(50) { const char* init = SPL_STANDARD_MESSAGE_STRUCT_HEADER; for(unsigned int i = 0; i < sizeof(header); ++i) header[i] = init[i]; version = SPL_STANDARD_MESSAGE_STRUCT_VERSION; pose[0] = robotPos.x(); pose[1] = robotPos.y(); pose[2] = robotPos.theta(); walkingTo[0] = walking.x(); walkingTo[1] = walking.y(); shootingTo[0] = shooting.x(); shootingTo[1] = shooting.y(); AbsCoord ballPosRR = ballPosition.convertToRobotRelativeCartesian(robotPos); ball[0] = ballPosRR.x(); ball[1] = ballPosRR.y(); ballVel[0] = ballVelocity.x(); ballVel[1] = ballVelocity.y(); for(int i = 0; i < SPL_STANDARD_MESSAGE_MAX_NUM_OF_PLAYERS; ++i) suggestion[i] = 0; // Everything else we need goes into the "data" section numOfDataBytes = sizeof(broadcast); memcpy(data, &broadcast, numOfDataBytes); }
void LocalisationAdapter::writeResultToBlackboard(void) { AbsCoord robotPos = L->getRobotPose(); AbsCoord ballPosition = L->getBallPosition(); RRCoord ballPosRR = ballPosition.convertToRobotRelative(robotPos); AbsCoord ballPosRRC = ballPosition.convertToRobotRelativeCartesian(robotPos); AbsCoord ballVelocity = L->getBallVelocity(); double robotPosUncertainty = L->getRobotPosUncertainty(); double robotHeadingUncertainty = L->getRobotHeadingUncertainty(); double ballPosUncertainty = L->getBallPosUncertainty(); double ballVelEigenvalue = L->getBallVelocityUncertainty(); AbsCoord nextBall(ballPosition.x() + ballVelocity.x(), ballPosition.y() + ballVelocity.y(), 0.0f); AbsCoord nextBallRRC = nextBall.convertToRobotRelativeCartesian(robotPos); AbsCoord ballVelRRC(nextBallRRC.x() - ballPosRRC.x(), nextBallRRC.y() - ballPosRRC.y(), 0.0f); Pose pose = readFrom(motion, pose); XYZ_Coord ballNeckRelative = pose.robotRelativeToNeckCoord(ballPosRR, BALL_RADIUS); uint32_t ballLostCount = L->getBallLostCount(); SharedLocalisationUpdateBundle sharedLocalisationBundle = L->getSharedUpdateData(); acquireLock(serialization); writeTo(localisation, robotPos, robotPos); writeTo(localisation, ballLostCount, ballLostCount); writeTo(localisation, ballPos, ballPosition); writeTo(localisation, ballPosRR, ballPosRR); writeTo(localisation, ballPosRRC, ballPosRRC); writeTo(localisation, ballVelRRC, ballVelRRC); writeTo(localisation, ballVel, ballVelocity); writeTo(localisation, robotPosUncertainty, robotPosUncertainty); writeTo(localisation, robotHeadingUncertainty, robotHeadingUncertainty); writeTo(localisation, ballPosUncertainty, ballPosUncertainty); writeTo(localisation, ballVelEigenvalue, ballVelEigenvalue); writeTo(localisation, teamBall, TeamBallInfo()); // TODO: make this a different value? writeTo(localisation, ballNeckRelative, ballNeckRelative); writeTo(localisation, sharedLocalisationBundle, sharedLocalisationBundle); writeTo(localisation, havePendingOutgoingSharedBundle, true); writeTo(localisation, havePendingIncomingSharedBundle, std::vector<bool>(5, false)); writeTo(localisation, robotObstacles, robotFilter->filteredRobots); releaseLock(serialization); }
/*----------------------------------------------------------------------------- * Motion thread tick function *---------------------------------------------------------------------------*/ void MotionAdapter::tick() { Timer t; // Get the motion request from behaviours int behaviourReadBuf = readFrom(behaviour, readBuf); ActionCommand::All request = readFrom(behaviour, request[behaviourReadBuf]).actions; // Get sensor information from kinematics SensorValues sensors; if(request.body.actionType == Body::MOTION_CALIBRATE){ // raw sensor values are sent to offnao for calibration // these values are straight forward copy paste into pos files sensors = nakedTouch->getSensors(kinematics); sensors.sensors[Sensors::InertialSensor_AngleX] = -RAD2DEG(sensors.sensors[Sensors::InertialSensor_AngleX]); sensors.sensors[Sensors::InertialSensor_AngleY] = -RAD2DEG(sensors.sensors[Sensors::InertialSensor_AngleY]); sensors.sensors[Sensors::InertialSensor_GyrX] = -sensors.sensors[Sensors::InertialSensor_GyrX]; sensors.sensors[Sensors::InertialSensor_GyrY] = -sensors.sensors[Sensors::InertialSensor_GyrY]; } else { sensors = touch->getSensors(kinematics); } // For kinematics, give it the lagged sensorValues with the most recent lean angles (because they already // have a lag in them) unless it's the very first one otherwise it will propagate nans everywhere SensorValues sensorsLagged; if (sensorBuffer.size() > 0) { sensorsLagged = sensorBuffer.back(); } else { sensorsLagged = sensors; } sensorsLagged.sensors[Sensors::InertialSensor_AngleX] = sensors.sensors[Sensors::InertialSensor_AngleX]; sensorsLagged.sensors[Sensors::InertialSensor_AngleY] = sensors.sensors[Sensors::InertialSensor_AngleY]; kinematics.setSensorValues(sensorsLagged); kinematics.parameters = readFrom(kinematics, parameters); // Calculate the Denavit-Hartenberg chain kinematics.updateDHChain(); writeTo(motion, pose, kinematics.getPose()); bool standing = touch->getStanding(); ButtonPresses buttons = touch->getButtons(); llog(VERBOSE) << "touch->getSensors took " << t.elapsed_ms() << "ms" << std::endl; t.restart(); // Keep a running time for standing if (standing) { uptime = 0.0f; } else { uptime += 0.01f; } writeTo(motion, uptime, uptime); // Sensors are lagged so it correctly synchronises with vision sensorBuffer.insert(sensorBuffer.begin(), sensors); writeTo(motion, sensors, sensors); //Lagged); writeTo(kinematics, sensorsLagged, sensorsLagged); // std::cout << "live = " << sensors.joints.angles[Joints::HeadYaw] // << " delayed = " << sensorsLagged.joints.angles[Joints::HeadYaw] // << std::endl; if (sensorBuffer.size() > SENSOR_LAG) { sensorBuffer.pop_back(); } // sonar recorder gets and update and returns the next sonar request request.sonar = sonarRecorder.update(sensors.sonar); writeTo(motion, sonarWindow, sonarRecorder.sonarWindow); if (isIncapacitated(request.body.actionType)) { uptime = 0.0f; } buttons |= readFrom(motion, buttons); writeTo(motion, buttons, buttons); llog(VERBOSE) << "writeTo / readFrom took " << t.elapsed_ms() << "ms" << std::endl; t.restart(); if (standing) { generator->reset(); request.body = ActionCommand::Body::INITIAL; odometry.clear(); } // Get the position of the ball in robot relative cartesian coordinates AbsCoord robotPose = readFrom(localisation, robotPos); AbsCoord ballAbs = readFrom(localisation, ballPos); AbsCoord ball = ballAbs.convertToRobotRelativeCartesian(robotPose); // Update the body model bodyModel.kinematics = &kinematics; bodyModel.update(&odometry, sensors); // Get the joints requested by whichever generator we're using JointValues joints = generator->makeJoints(&request, &odometry, sensors, bodyModel, ball.x(), ball.y()); // Save the body model Center of Mass writeTo(motion, com, bodyModel.getCoM()); writeTo(motion, active, request); // Odometry is lagged by walk's estimations, and it also correctly synchronises with vision writeTo(motion, odometry, Odometry(odometry)); // Save the pendulum model writeTo(motion, pendulumModel, bodyModel.getPendulumModel()); llog(VERBOSE) << "generator->makeJoints took " << t.elapsed_ms() << "ms" << std::endl; t.restart(); // Actuate joints as requested. effector->actuate(joints, request.leds, request.sonar); llog(VERBOSE) << "effector->actuate took " << t.elapsed_ms() << "ms" << std::endl; }
void ICPFieldView::redraw(Blackboard *blackboard, const AbsCoord &robotPos, int icpResult, const AbsCoord &icpObs, const AbsCoord &ballRRC, const AbsCoord &teamBall) { *renderPixmap = imagePixmap; FieldPainter painter(renderPixmap); AbsCoord anchor; if (icpResult >= ICP_LOCALISED){ anchor = icpObs; } else { anchor = robotPos; } /* Draw features with absolute coordinates */ if (!isnan(robotPos.theta()) && !isnan(robotPos.x()) && !isnan(robotPos.y())) { /* Draw the team ball */ if (!isnan(teamBall.x()) && !isnan(teamBall.y())){ painter.drawBallPosAbs(teamBall, QColor(255, 0, 255)); } /* Draw our position */ painter.drawRobotAbs(robotPos, "#ffee00", true, "black"); // pacman yellow, black variance if (icpResult >= ICP_LOCALISED) { /* Draw icp's chosen/closest observation on top of the others */ if (!isnan(icpObs.theta()) && !isnan(icpObs.x()) && !isnan(icpObs.y())) { painter.drawRobotAbs(icpObs, "blue", true, "blue"); } } } /* Draw features with robot-relative coordinates */ if ((!isnan(anchor.theta()) && !isnan(anchor.x()) && !isnan(anchor.y()))) { /* Posts */ std::vector<PostInfo> posts = readFrom(vision, posts); std::vector<PostInfo>::iterator post_i; for (post_i = posts.begin (); post_i < posts.end (); ++ post_i) { painter.drawPostRR(*post_i, anchor); } /* Ball */ AbsCoord bVel; if (!isnan(ballRRC.x()) && !isnan(ballRRC.y())){ painter.drawBallPosRRC(ballRRC, bVel, false, anchor); } /* Field Lines RR */ std::vector<FieldFeatureInfo> features = readFrom(vision,fieldFeatures); std::vector<FieldFeatureInfo>::iterator feature_i; for (feature_i = features.begin (); feature_i < features.end (); ++ feature_i) { painter.drawFeatureRR(*feature_i, anchor); } /* RRCoord fieldPoints[MAX_FIELD_LINE_POINTS]; readArray(vision, fieldLinePoints, fieldPoints); for (uint16_t i = 0; i < MAX_FIELD_LINE_POINTS; i++) { std::cout << "point with d = " << fieldPoints[i].distance() << " and h = " << fieldPoints[i].heading() << std::endl; CentreCircleInfo c = CentreCircleInfo(); FieldFeatureInfo f = FieldFeatureInfo(fieldPoints[i], c); painter.drawFeatureRR(f, anchor); } */ } /* Draw ICP lines */ //static std::vector<LineInfo> allFieldLines; // in decreasing order of length std::vector<LineInfo>::const_iterator line = ICP::getAllFieldLines().begin(); for (; line != ICP::getAllFieldLines().end(); ++line) { painter.drawFieldLine(*line); } setPixmap (*renderPixmap); return; }