00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <GlobalNodeList.h>
00025 #include <PeerInfo.h>
00026 #include <RpcMacros.h>
00027 #include <NeighborCache.h>
00028 #include <GlobalNodeListAccess.h>
00029 #include <Landmark.h>
00030 #include <UnderlayConfigurator.h>
00031 #include <SimpleNodeEntry.h>
00032 #include <SimpleInfo.h>
00033 #include <CoordBasedRoutingAccess.h>
00034 #include <GlobalStatistics.h>
00035
00036 #include <Nps_m.h>
00037
00038 #include <Nps.h>
00039
00040
00041 void Nps::initNps(NeighborCache* neighborCache)
00042 {
00043 this->neighborCache = neighborCache;
00044
00045 npsMaxLayer = neighborCache->par("npsMaxLayer");
00046 npsDimensions = neighborCache->par("npsDimensions");
00047 landmarkTimeout = neighborCache->par("landmarkTimeout");
00048
00049 ownLayer = -1;
00050
00051 receivedCalls = 0;
00052 pendingRequests = 0;
00053 coordCalcRuns = neighborCache->par("npsCoordCalcRuns");
00054
00055 WATCH(ownLayer);
00056 WATCH_VECTOR(ownCoordinates);
00057 WATCH_VECTOR(landmarkSet);
00058
00059 coordBasedRouting = CoordBasedRoutingAccess().get();
00060 globalNodeList = GlobalNodeListAccess().get();
00061
00062 if (neighborCache->getParentModule()->getModuleByRelativePath("tier1")
00063 ->getModuleByRelativePath("landmark") == NULL) {
00064 landmarkTimer = new cMessage("landmarkTimer");
00065 neighborCache->scheduleAt(simTime() + landmarkTimeout, landmarkTimer);
00066 } else {
00067
00068 ownLayer = 0;
00069 }
00070 }
00071
00072 void Nps::handleTimerEvent(cMessage* msg)
00073 {
00074
00075 if (msg == landmarkTimer) {
00076 if (enoughLandmarks()) {
00077 delete msg;
00078
00079 sendCoordRequests();
00080 } else {
00081 neighborCache->scheduleAt(simTime() + landmarkTimeout, msg);
00082 }
00083 }
00084 }
00085
00086 void Nps::handleRpcResponse(BaseResponseMessage* msg,
00087 cPolymorphic* context,
00088 int rpcId, simtime_t rtt)
00089 {
00090
00091 RPC_SWITCH_START( msg );
00092 RPC_ON_RESPONSE( CoordsReq ) {
00093 coordsReqRpcResponse(_CoordsReqResponse, context, rpcId, rtt);
00094 }
00095 #ifdef EXTJOIN_DISCOVERY
00096 RPC_ON_RESPONSE( RttToNode ) {
00097 rttToNodeRpcResponse(_RttToNodeResponse, context, rpcId, rtt);
00098 }
00099 #endif
00100 RPC_SWITCH_END( );
00101
00102 return;
00103 }
00104
00105 void Nps::handleRpcTimeout(BaseCallMessage* msg,
00106 const TransportAddress& dest,
00107 cPolymorphic* context, int rpcId,
00108 const OverlayKey& destKey)
00109 {
00110 RPC_SWITCH_START( msg ) {
00111
00112 RPC_ON_CALL( CoordsReq ) {
00113 if (true) {
00114 #ifdef EXTJOIN_DISCOVERY
00115 if (getPendingRttsReq(dest) == -1) {
00116 RttToNodeCall* call = getNodeMessage(dest);
00117
00118 RttToNodeResponse* rttRes = new RttToNodeResponse("RttToNodeXRes");
00119 rttRes->setPingedNode(dest);
00120 rttRes->setRttToNode(0);
00121 std::vector<double> tempOwnCoords;
00122 tempOwnCoords = getOwnCoordinates();
00123 rttRes->setOwnCoordinatesArraySize(tempOwnCoords.size());
00124 for (uint i = 0; i < tempOwnCoords.size(); i++) {
00125 rttRes->setOwnCoordinates(i, tempOwnCoords[i]);
00126 }
00127 sendRpcResponse(call, rttRes);
00128 deleteNodeMeasurement(dest);
00129 } else {
00130 #endif
00131 updateNodeMeasurement(dest, -1);
00132 #ifdef EXTJOIN_DISCOVERY
00133 }
00134 #endif
00135
00136 } else {
00137 pendingRequests--;
00138
00139 }
00140 }
00141 #ifdef EXTJOIN_DISCOVERY
00142 RPC_ON_CALL( RttToNode ) {
00143 updateNodeMeasurement(dest, -1);
00144 }
00145 #endif
00146 }
00147 RPC_SWITCH_END( )
00148 }
00149
00150
00151 void Nps::coordsReqRpc(CoordsReqCall* msg)
00152 {
00153 receivedCalls++;
00154 CoordsReqResponse* coordRes = new CoordsReqResponse("CoordsReqRes");
00155 coordRes->setLayer(getOwnLayer());
00156 coordRes->setCoordsArraySize(npsDimensions);
00157
00158 if (getOwnLayer() != 0) {
00159 const std::vector<double>& ownCoordinates = getOwnCoordinates();
00160
00161 for (uint i = 0; i < ownCoordinates.size(); i++) {
00162 coordRes->setCoords(i, ownCoordinates[i]);
00163 }
00164 } else {
00165 Landmark* landmark = check_and_cast<Landmark*>(neighborCache->getParentModule()
00166 ->getModuleByRelativePath("tier1.landmark"));
00167 assert(landmark);
00168 const std::vector<double>& ownCoordinates =
00169 landmark->getOwnNpsCoords();
00170
00171 for (uint i = 0; i < ownCoordinates.size(); i++) {
00172 coordRes->setCoords(i, ownCoordinates[i]);
00173 }
00174 }
00175 coordRes->setBitLength(COORDSREQRESPONSE_L(coordRes));
00176 neighborCache->sendRpcResponse(msg, coordRes);
00177 }
00178
00179 #ifdef EXTJOIN_DISCOVERY
00180 void Nps::rttToNodeRpc(RttToNodeCall* msg)
00181 {
00182 incReceivedCalls();
00183 TransportAddress dest = msg->getNodeToPing();
00184
00185 setNodeMessage(dest, msg);
00186 sendCoordsReqCall(dest, -1);
00187 }
00188 #endif
00189
00190 void Nps::coordsReqRpcResponse(CoordsReqResponse* response,
00191 cPolymorphic* context, int rpcId, simtime_t rtt)
00192 {
00193 pendingRequests--;
00194 NodeHandle& srcNode = response->getSrcNode();
00195
00196
00197
00198
00199
00200
00201
00202
00203 std::vector<double> tempCoords;
00204 for (uint i = 0; i < response->getCoordsArraySize(); i++) {
00205 tempCoords.push_back(response->getCoords(i));
00206 }
00207 char tempLayer = response->getLayer();
00208
00209 EV << "[Nps::coordsReqRpcResponse() @ " << neighborCache->thisNode.getAddress()
00210 << " (" << neighborCache->thisNode.getKey().toString(16) << ")]\n received landmark coords: "
00211 << tempCoords[0];
00212 for (uint8_t i = 1; i < npsDimensions; i++) {
00213 EV << ", " << tempCoords[i];
00214 }
00215 EV << endl;
00216
00217 #ifdef EXTJOIN_DISCOVERY
00218 if (doingDiscovery()) {
00219
00220 if ((isEntry(srcNode) && rtt < getNodeRtt(srcNode))
00221 || (isEntry(srcNode) && getNodeRtt(srcNode) < 0) ) {
00222 updateNode(srcNode, rtt, tempCoords, 0);
00223 } else if (!(isEntry(srcNode))) {
00224 updateNode(srcNode, rtt, tempCoords, 0);
00225 } else {
00226 updateNode(srcNode, getNodeRtt(srcNode), tempCoords, 0);
00227 }
00228 setNodeLayer(srcNode, tempLayer);
00229 }
00230 else if (doingNodeMeasurement()) {
00231 if (getPendingRttsReq(srcNode) == -1) {
00232 updateNode(srcNode, rtt, tempCoords, 0);
00233 setNodeLayer(srcNode, tempLayer);
00234 RttToNodeCall* prevCall = getNodeMessage(srcNode);
00235
00236 RttToNodeResponse* rttRes = new RttToNodeResponse("RttToNodeXRes");
00237 rttRes->setPingedNode(srcNode);
00238 rttRes->setRttToNode(rtt);
00239 std::vector<double> tempOwnCoords;
00240 tempOwnCoords = getOwnCoordinates();
00241 rttRes->setOwnCoordinatesArraySize(tempOwnCoords.size());
00242 for (uint i = 0; i < tempOwnCoords.size(); i++) {
00243 rttRes->setOwnCoordinates(i, tempOwnCoords[i]);
00244 }
00245
00246 sendRpcResponse(prevCall, rttRes);
00247 deleteNodeMeasurement(srcNode);
00248 } else {
00249 updateNode(srcNode, rtt, tempCoords, 0);
00250 setNodeLayer(srcNode, tempLayer);
00251 if (checkCoordinates(getOwnCoordinates(), tempCoords, rtt)) {
00252 updateNodeMeasurement(srcNode, -1, 0, 1);
00253 } else {
00254 updateNodeMeasurement(srcNode, -1, 0, 0);
00255 }
00256 }
00257 }
00258 else
00259 #endif
00260 if (pendingRequests == 0) {
00261 neighborCache->updateNode(srcNode, rtt, NodeHandle::UNSPECIFIED_NODE,
00262 tempCoords, 0);
00263 neighborCache->setNodeLayer(srcNode, tempLayer);
00264
00265
00266 std::vector<LandmarkDataEntry> setOfLandmarks;
00267 if (getLandmarkSetSize() < npsDimensions + 1) {
00268 neighborCache->setLandmarkSet(npsDimensions + 1,
00269 npsMaxLayer, &landmarkSet);
00270 }
00271 setOfLandmarks = neighborCache->getLandmarkData(landmarkSet);
00272 assert(setOfLandmarks.size() > 0);
00273
00274
00275
00276 computeOwnCoordinates(setOfLandmarks);
00277 computeOwnLayer(setOfLandmarks);
00278
00279 std::vector<double> coords = getOwnCoordinates();
00280 EV << "[Nps::coordsReqRpcResponse() @ " << neighborCache->thisNode.getAddress()
00281 << " (" << neighborCache->thisNode.getKey().toString(16) << ")]\n setting own coords: "
00282 << coords[0];
00283 for (uint8_t i = 1; i < npsDimensions; i++) {
00284 EV << ", " << coords[i];
00285 }
00286 EV << endl;
00287
00288
00289
00290 ChurnGenerator* lmChurnGen = NULL;
00291 for (uint8_t i = 0; i < neighborCache->underlayConfigurator->getChurnGeneratorNum(); i++) {
00292 ChurnGenerator* searchedGen;
00293 searchedGen = neighborCache->underlayConfigurator->getChurnGenerator(i);
00294 if (searchedGen->getNodeType().overlayType != "oversim.common.cbr.LandmarkModules") {
00295 lmChurnGen = searchedGen;
00296 }
00297 }
00298 SimpleNodeEntry* entry =
00299 dynamic_cast<SimpleInfo*>(globalNodeList->
00300 getPeerInfo(neighborCache->thisNode.getAddress()))->getEntry();
00301
00302 double error = 0;
00303
00304 for (uint8_t i = 1; i < entry->getDim(); i++) {
00305
00306
00307 error += pow(coords[i] - entry->getCoords(i), 2);
00308 }
00309
00310 error = sqrt(error);
00311
00312 neighborCache->globalStatistics
00313 ->addStdDev("NPS: Coordinate difference", error);
00314
00315 neighborCache->neighborCache.clear();
00316 neighborCache->neighborCacheExpireMap.clear();
00317
00318
00319
00320 if (coordBasedRouting) {
00321 int bitsPerDigit = neighborCache->overlay->getBitsPerDigit();
00322 neighborCache->thisNode.setKey(
00323 coordBasedRouting->getNodeId(coords, bitsPerDigit,
00324 OverlayKey::getLength()));
00325
00326 EV << "[Nps::coordsReqRpcResponse() @ " << neighborCache->thisNode.getAddress()
00327 << " (" << neighborCache->thisNode.getKey().toString(16) << ")]"
00328 << "\n -> nodeID ( 2): "
00329 << neighborCache->thisNode.getKey().toString(2)
00330 << "\n -> nodeID (16): "
00331 << neighborCache->thisNode.getKey().toString(16) << endl;
00332
00333 neighborCache->overlay->join(neighborCache->thisNode.getKey());
00334 } else {
00335 neighborCache->overlay->join();
00336 }
00337 } else {
00338 neighborCache->updateNode(srcNode, rtt, NodeHandle::UNSPECIFIED_NODE,
00339 tempCoords, 0);
00340 neighborCache->setNodeLayer(srcNode, tempLayer);
00341 }
00342 }
00343
00344 #ifdef EXTJOIN_DISCOVERY
00345 void Nps::rttToNodeRpcResponse(RttToNodeResponse* response,
00346 cPolymorphic* context, int rpcId, simtime_t rtt)
00347 {
00348 uint dim = coordBasedRouting->getXmlDimensions();
00349 TransportAddress nodeToCheck = response->getPingedNode();
00350 std::vector<double> tempCoords;
00351 tempCoords.resize(dim);
00352 for (uint i = 0; i < dim; i++) {
00353 tempCoords[i] = response->getOwnCoordinates(i);
00354 }
00355 if (checkCoordinates(tempCoords, getNodeCoords(nodeToCheck), response->getRttToNode())) {
00356 updateNodeMeasurement(nodeToCheck, -1, 0, 1);
00357 } else {
00358 updateNodeMeasurement(nodeToCheck, -1, 0, 0);
00359 }
00360 delete context;
00361 }
00362 #endif
00363
00364 void Nps::sendCoordRequests()
00365 {
00366 std::vector <TransportAddress> landmarks;
00367 landmarks = getLandmarks(npsDimensions + 1);
00368
00369
00370
00371
00372
00373
00374 simtime_t timeout = -1;
00375
00376 if (landmarks.size() > 0) {
00377 for (size_t i = 0; i < landmarks.size(); i++) {
00378 const TransportAddress& tolm = landmarks[i];
00379 sendCoordsReqCall(tolm, timeout);
00380 }
00381 neighborCache->setLandmarkSet(npsDimensions + 1, npsMaxLayer,
00382 &landmarkSet);
00383 }
00384 }
00385
00386 void Nps::sendCoordsReqCall(const TransportAddress& dest,
00387 simtime_t timeout)
00388 {
00389 CoordsReqCall* coordReq = new CoordsReqCall("CoordsReq");
00390 coordReq->setBitLength(COORDSREQCALL_L(coordReq));
00391 neighborCache->sendRouteRpcCall(neighborCache->getThisCompType(), dest,
00392 coordReq, NULL, NO_OVERLAY_ROUTING,
00393 timeout, 0, -1, this);
00394 pendingRequests++;
00395 }
00396
00397 void Nps::computeOwnLayer(const std::vector<LandmarkDataEntry>& landmarks)
00398 {
00399 int8_t computedLayer = getOwnLayer();
00400 for (uint i = 0; i < landmarks.size(); i++) {
00401 if (computedLayer <= landmarks[i].layer) {
00402 computedLayer = landmarks[i].layer + 1;
00403 }
00404 }
00405
00406 setOwnLayer(computedLayer);
00407 }
00408
00409 void Nps::setOwnLayer(int8_t layer)
00410 {
00411 ownLayer = layer;
00412
00413
00414 PeerInfo* thisInfo = globalNodeList->getPeerInfo(neighborCache->getThisNode());
00415 thisInfo->setNpsLayer(layer);
00416 if (layer > 0) globalNodeList->refreshEntry(neighborCache->overlay->getThisNode());
00417 if (layer < npsMaxLayer) {
00418 globalNodeList->incLandmarkPeerSize();
00419 globalNodeList->incLandmarkPeerSizePerType(thisInfo->getTypeID());
00420 }
00421 }
00422
00423 #ifdef EXTJOIN_DISCOVERY
00424 bool Nps::checkCoordinates(std::vector<double> coordsOK, std::vector<double> coordsToCheck, simtime_t dist)
00425 {
00426 simtime_t predDist = 0.0;
00427
00428 for (uint i = 0; i < coordsOK.size(); i++) {
00429 predDist += pow(coordsOK[i] - coordsToCheck[i], 2);
00430 }
00431 simtime_t predDistLow = sqrt(SIMTIME_DBL(predDist)) * 2 * (1 - 0.3) / 1000;
00432 simtime_t predDistHigh = sqrt(SIMTIME_DBL(predDist)) * 2 * (1 + 0.3) / 1000;
00433 if (dist > predDistLow && dist < predDistHigh) {
00434 return true;
00435 } else {
00436
00437 return false;
00438 }
00439 }
00440 #endif
00441
00442 void Nps::computeOwnCoordinates(const std::vector<LandmarkDataEntry>& landmarks)
00443 {
00444 CoordCalcFunction coordcalcf(landmarks);
00445
00446 Vec_DP initCoordinates(npsDimensions);
00447 Vec_DP bestCoordinates(npsDimensions);
00448 std::vector<double> computedCoordinatesStdVector(npsDimensions);
00449
00450 double bestval;
00451 double resval;
00452
00453 for (uint runs = 0; runs < coordCalcRuns; runs++) {
00454
00455 for (uint i = 0; i < npsDimensions; i++) {
00456 initCoordinates[i] = uniform(-100, 100);
00457
00458
00459 }
00460
00461
00462 resval = CoordCalcFunction::simplex_min(&coordcalcf, initCoordinates);
00463 if (runs == 0 || (runs > 0 && resval < bestval) ) {
00464 bestval = resval;
00465 bestCoordinates = initCoordinates;
00466 }
00467 }
00468
00469 for (uint i = 0; i < npsDimensions; i++) {
00470 computedCoordinatesStdVector[i] = bestCoordinates[i];
00471 }
00472
00473 setOwnCoordinates(computedCoordinatesStdVector);
00474 }
00475
00476 std::vector<TransportAddress> Nps::getLandmarks(uint8_t howmany)
00477 {
00478 std::vector<TransportAddress> returnPool;
00479
00480 if (howmany > globalNodeList->getLandmarkPeerSize()) {
00481 throw cRuntimeError("Not enough landmarks available in network!");
00482 }
00483
00484 while (returnPool.size() < howmany) {
00485 TransportAddress* lm = globalNodeList->getRandomAliveNode();
00486 PeerInfo* lmInfo = globalNodeList->getPeerInfo(lm->getAddress());
00487 if (lmInfo->getNpsLayer() >= 0 &&
00488 lmInfo->getNpsLayer() < npsMaxLayer) {
00489
00490 bool alreadyin = false;
00491 for (uint8_t i = 0; i < returnPool.size(); i++) {
00492 if (returnPool[i] == *lm)
00493 alreadyin = true;
00494 }
00495 if (alreadyin == false) {
00496 returnPool.push_back(*lm);
00497 }
00498 }
00499 }
00500 return returnPool;
00501 }
00502
00503 bool Nps::enoughLandmarks()
00504 {
00505 return (globalNodeList->getLandmarkPeerSize() > npsDimensions);
00506 }
00507
00508
00509 Prox Nps::getCoordinateBasedProx(const NodeCoordsInfo& info)
00510 {
00511 double dist = 0.0;
00512 uint32_t size = info.coordinates.size();
00513
00514 for (uint32_t i = 0; i < size; i++) {
00515 dist += pow(ownCoordinates[i] - info.coordinates[i], 2);
00516 }
00517 dist = sqrt(dist);
00518
00519 return Prox(dist, 0.0);
00520 }
00521
00522 void Nps::showReceivedCoords()
00523 {
00524 std::cout << neighborCache->thisNode.getAddress() << " is still missing "
00525 << pendingRequests;
00526 std::cout << " responses! Results so far:" << std::endl;
00527 std::vector<LandmarkDataEntry> landmarkData =
00528 neighborCache->getLandmarkData(landmarkSet);
00529 for (uint i = 0; i < landmarkData.size(); i++) {
00530 std::cout << "RTT: " << SIMTIME_DBL(landmarkData[i].rtt)
00531 << " -- Layer: " << (int) landmarkData[i].layer
00532 << " -- Coords: ";
00533 for (uint j = 0; j < landmarkData[i].coordinates.size(); j++) {
00534 std::cout << " " << landmarkData[i].coordinates[j];
00535 }
00536 std::cout << " -- IP: " << landmarkData[i].ip;
00537 std::cout << std::endl;
00538 }
00539 }
00540
00541 void Nps::updateNodeMeasurement(const TransportAddress& node,
00542 uint8_t pending,
00543 uint8_t sent,
00544 uint8_t passed)
00545 {
00546 bool alreadySet = false;
00547 for(uint i = 0; i < nodeMeasurements.size(); i++) {
00548 if (nodeMeasurements[i].measuredNode == node && sent == 0) {
00549 nodeMeasurements[i].rttsPending += pending;
00550 nodeMeasurements[i].rttsSent += sent;
00551 nodeMeasurements[i].coordsPassed += passed;
00552 alreadySet = true;
00553 i = nodeMeasurements.size();
00554 } else if (nodeMeasurements[i].measuredNode == node) {
00555 nodeMeasurements[i].rttsPending = pending;
00556 nodeMeasurements[i].rttsSent = sent;
00557 nodeMeasurements[i].coordsPassed = passed;
00558 alreadySet = true;
00559 i = nodeMeasurements.size();
00560 }
00561 }
00562 if (!alreadySet) {
00563 RttMeasurement newNode;
00564 newNode.measuredNode = node;
00565 newNode.rttsPending = pending;
00566 newNode.rttsSent = sent;
00567 newNode.coordsPassed = passed;
00568 nodeMeasurements.push_back(newNode);
00569 }
00570 }
00571
00572 void Nps::deleteNodeMeasurement(const TransportAddress& node)
00573 {
00574 for(uint i = 0; i < nodeMeasurements.size(); i++) {
00575 if (nodeMeasurements[i].measuredNode == node) {
00576 #ifdef EXTJOIN_DISCOVERY
00577 delete nodeMeasurements[i].message;
00578 #endif
00579 nodeMeasurements.erase(nodeMeasurements.begin()+i);
00580 i--;
00581 }
00582 }
00583 if (nodeMeasurements.size() == 0) {
00584
00585 }
00586 }
00587
00588
00589 double CoordCalcFunction::simplex_min(CoordCalcFunction *functionObject,
00590 Vec_DP& init)
00591 {
00592 double accf = 0.0000001;
00593 double accx = 0.0000001;
00594 uint32_t nmax = 30001;
00595 uint8_t dim = init.size();
00596 Simplex spx(dim);
00597
00598 int ihi;
00599 Vec_DP phi(dim);
00600 double vhi;
00601 double vre;
00602 double vlo, diff;
00603 uint32_t count;
00604
00605
00606 Vec_DP tmp(dim);
00607 spx.functionObject = functionObject;
00608 spx[0] = init;
00609 for (uint8_t i = 0; i < dim; i++) {
00610 tmp[i] = 1;
00611 spx[i+1] = init + tmp;
00612 tmp[i] = 0;
00613 }
00614
00615 Vec_DP debugCoords(dim);
00616
00617 for (count = 1; count <= nmax; count++) {
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628 ihi = spx.high(&vhi);
00629 phi = spx[ihi];
00630 spx.reflect();
00631 vre = functionObject->f(spx[ihi]);
00632 if (vre < functionObject->f(spx[spx.low()])) {
00633 spx[ihi] = phi;
00634 spx.reflect_exp();
00635 vre = functionObject->f(spx[ihi]);
00636 if (vre > functionObject->f(spx[spx.low()])) {
00637 spx[ihi] = phi;
00638 spx.reflect();
00639 }
00640 } else if (vre >= vhi) {
00641 spx[ihi] = phi;
00642 spx.contract();
00643 if (functionObject->f(spx[ihi]) > vhi) {
00644 spx[ihi] = phi;
00645 spx.reduce();
00646 }
00647 }
00648
00649 spx.high(&vhi);
00650 spx.low(&vlo);
00651 diff = vhi - vlo;
00652 if (diff < accf)
00653 if (spx.size() < accx)
00654 break;
00655 }
00656 init = spx[spx.low()];
00657 return vlo;
00658 }
00659
00660 double CoordCalcFunction::f(const Vec_DP& initCoordinates) const
00661 {
00662 double sum = 0;
00663 double rel_diff = 0;
00664
00665 for (uint i = 0; i < landmarks.size(); i++) {
00666
00667 double diff = SIMTIME_DBL(landmarks[i].rtt) / 2 * 1000 -
00668 endnodeDistance(initCoordinates, landmarks[i]);
00669
00670 if (SIMTIME_DBL(landmarks[i].rtt) != 0) {
00671 rel_diff = diff / (SIMTIME_DBL(landmarks[i].rtt) / 2 * 1000);
00672 } else {
00673 opp_error("[CBR] RTT == 0. Node is landmark? This shouldn't happen.");
00674 }
00675 sum += rel_diff * rel_diff;
00676 }
00677 return sum;
00678 }
00679
00680 double CoordCalcFunction::endnodeDistance(const Vec_DP& nodeCoordinates,
00681 LandmarkDataEntry landmark) const
00682 {
00683 double sum_of_squares = 0.0;
00684 for (int i = 0; i < nodeCoordinates.size(); i++) {
00685 sum_of_squares += pow(landmark.coordinates[i] - nodeCoordinates[i], 2);
00686 }
00687 double result = sqrt(sum_of_squares);
00688 return result;
00689 }
00690