학부연구생

문제 해결을 위한 시뮬레이션 제작 및 Tracing source 추출-3

Beige00 2024. 3. 17. 01:56

이전에 작성한 코드로 구할 수 있었던 Attribute들은 서술하지 않음.

 

* Queue Length

1. OnOff의 Qos Level을 AC_BE로 세팅

2. 각 노드의 AC_BE Queue 길이를 검사.

 

* Node Score(Node Strength)

1. LET 배열을 전부 -1로 초기화

2. 이웃한 노드일 시, 주변 노드 수를 1 증가 시키고 다음을 수행.

2-1. 가까워 질 시, 해당 노드와의 LET를 -10으로 저장.

2-2. 멀어질 시, 해당 노드와의 LET를 식에 따라 계산

3. LET가 -1일 경우 이웃 노드가 아니고, -10일 경우 구한 LET 중 최대값에 1.5를 곱한 수를 Total에 더해준다. 그 외의 경우 그냥 LET 값을 Total에 더해준다.

4. 0.7*TotalLET  + 0.3*주변노드 수

 

* node Speed

1. 노드의 x속도, y속도 절대값을 더한 값이다.

 

#include <sstream>
#include <fstream>
#include <ns3/network-module.h>
#include <ns3/core-module.h>
#include <ns3/applications-module.h>
#include <ns3/mobility-module.h>
#include <ns3/internet-module.h>
#include <ns3/yans-wifi-helper.h>
#include "ns3/energy-module.h"
#include "ns3/wifi-radio-energy-model-helper.h"
#include "ns3/device-energy-model.h"
#include "ns3/olsr-helper.h"
#include "ns3/wifi-mac-queue.h"
#include "ns3/adhoc-wifi-mac.h"
#include <cmath>
#include <vector>
#include <string>

using namespace ns3;

std::vector<std::vector<std::string>> Data;

#define TxRange 350
#define TotalTime 100
#define nodeNum 50

void 
makeCsvFile(const std::string& filename, const std::vector<std::vector<std::string>>& data){
    std::ofstream file1(filename);
    for(const auto& row : data){
        for(auto it = row.begin(); it!=row.end(); ++it){
            file1<<*it;
            if(next(it)!=row.end()){
                file1<<",";
            }
        }
        file1<<std::endl;
    }
    file1.close();
}

Vector 
Normalize(const Vector& velocity){
    double magnitude = std::sqrt(velocity.x * velocity.x + velocity.y * velocity.y + velocity.z * velocity.z);
    // 크기가 0인 벡터는 정규화할 수 없으므로, 원본 벡터를 반환
    if (magnitude == 0)
    {
        return velocity;
    }
    return ns3::Vector(velocity.x / magnitude, velocity.y / magnitude, velocity.z / magnitude);
}

double distance(double x1, double y1, double x2, double y2){
    return sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
}

double CalculateRelativeSpeed(double vAx, double vAy, double vBx, double vBy) {
    // 상대 속도 벡터의 각 성분을 계산
    double relativeVx = vBx - vAx;
    double relativeVy = vBy - vAy;

    return sqrt(pow(relativeVx, 2) + pow(relativeVy, 2));
}

void 
TracingParameter(EnergySourceContainer e, NetDeviceContainer n){
    double nodeX[nodeNum];
    double nodeY[nodeNum];
    double spdX[nodeNum];
    double spdY[nodeNum];
    double TL[nodeNum];
    double remainEn[nodeNum];
    double NS[nodeNum];

    uint32_t QL[nodeNum];
    
    //각 노드들의 데이터 긁어오기, 0=PacketSinkApp, 1=OnOffApp
    for(int i=0; i<nodeNum; i++){
        //node들의 에너지 잔량,속도, 방향, 위치 정보 수집(Node x, Node y)
        Ptr<Node> node = n.Get(i)->GetNode();
        Ptr<MobilityModel> mobility = node->GetObject<MobilityModel>();
        Ptr<BasicEnergySource> enPtr = DynamicCast<BasicEnergySource>(e.Get(i));
        ApplicationContainer app = node->GetApplication(0);
        Ptr<PacketSink> psink = StaticCast<PacketSink>(app.Get(0));

        Vector pos = mobility->GetPosition();
        Vector velocity = mobility->GetVelocity();

        PointerValue ptr;
        n.Get(i)->GetAttribute("Mac",ptr);
        Ptr<AdhocWifiMac> mac = ptr.Get<AdhocWifiMac>();
        Ptr<WifiMacQueue> queue = mac->GetTxopQueue(AC_BE);
        
        nodeX[i] = pos.x;
        nodeY[i] = pos.y;
        remainEn[i] = enPtr->GetRemainingEnergy();
        spdX[i] = velocity.x;
        spdY[i] = velocity.y;
        TL[i] = ((psink->GetTotalRx()*8)/(1e6*Simulator::Now().GetSeconds()));
        QL[i] = queue->GetNPackets();
    }
    
    //Node Strength 계산
    for(int i=0; i<nodeNum; i++){

        int NNodeNum = 0;
        double LETMax = -200000;
        double TotalLET = 0;
        double LET[nodeNum];
        std::fill(LET,LET+nodeNum,-1);

        for(int j=0; j<nodeNum; j++){
            //처리해줘야할 노드만 처리
            if(i==j) continue;
            double dis = distance(nodeX[i],nodeY[i],nodeX[j],nodeY[j]);
            if(dis<=TxRange){
                NNodeNum++;
                if((spdX[i]*spdX[j]+spdY[i]*spdY[j])>=0){
                    LET[j]=-10;
                }//가까워짐
                else{
                    LET[j] = dis / (CalculateRelativeSpeed(spdX[i],spdY[i],spdX[j],spdY[j]));
                    if(LETMax<LET[j]) LETMax = LET[j];
                }
            }
        }//이 시점에서 모든 node i 에 대한 LET 정보 갱신 완료.
        
        for(int j=0; j<nodeNum; j++){
            if(LET[j] == -1) continue;
            if(LET[j]==-10) TotalLET += (LETMax*1.5);
            else TotalLET += LET[j];
        }

        NS[i] = 0.7*TotalLET + 0.3*NNodeNum;
    }


    //Write Info
    for(int i=0; i<nodeNum; i++){
        //Second, nodeid, energy, TP, NodeScore, QueueLen, Speed
        Data.push_back({std::to_string(Simulator::Now().GetSeconds()),
        std::to_string(i),
        std::to_string(remainEn[i]),
        std::to_string(TL[i]),
        std::to_string(NS[i]),
        std::to_string(QL[i]),
        std::to_string(abs(spdX[i])+abs(spdY[i]))
        });
    }
     
    std::cout<<Simulator::Now().GetSeconds()<<std::endl;
    Simulator::Schedule(Seconds(1),&TracingParameter,e,n);
}

int 
main(int argc, char* argv[]){


    std::ofstream file("NetInfo.txt");

    Data.push_back({"Second","NodeID","RemainingEnergy",
    "TP","NodeScore","QueueLength","Speed"});
    
    NodeContainer AdhocNodes;
    AdhocNodes.Create(nodeNum);

    NetDeviceContainer AdhocDevices;

    MobilityHelper mobility;
    ObjectFactory points;
    points.SetTypeId("ns3::RandomRectanglePositionAllocator");
    points.Set("X",StringValue("ns3::UniformRandomVariable[Min=0.0|Max=1000.0]"));
    points.Set("Y",StringValue("ns3::UniformRandomVariable[Min=0.0|Max=1000.0]"));
    Ptr<PositionAllocator> waypos = points.Create() -> GetObject<PositionAllocator>();

    mobility.SetMobilityModel("ns3::RandomWaypointMobilityModel",
    "Speed",StringValue("ns3::UniformRandomVariable[Min=0.0|Max=20.0]"),
    "Pause",StringValue("ns3::UniformRandomVariable[Min=0.0|Max=0.5]"),
    "PositionAllocator",PointerValue(waypos));

    mobility.SetPositionAllocator("ns3::RandomRectanglePositionAllocator",
    "X",StringValue("ns3::UniformRandomVariable[Min=0|Max=1000]"),
    "Y",StringValue("ns3::UniformRandomVariable[Min=0|Max=1000]"));

    mobility.Install(AdhocNodes);
    //속도 pause time 방향 범위 내 랜덤.

    WifiHelper wifi;
    wifi.SetStandard(WIFI_STANDARD_80211ac);
    YansWifiPhyHelper phy;
    YansWifiChannelHelper channel;
    WifiMacHelper mac;
    mac.SetType("ns3::AdhocWifiMac");
    phy.SetErrorRateModel("ns3::YansErrorRateModel");
    channel.SetPropagationDelay("ns3::ConstantSpeedPropagationDelayModel");
    wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager");
    channel.AddPropagationLoss("ns3::RangePropagationLossModel","MaxRange",DoubleValue(TxRange));
    phy.SetChannel(channel.Create());
    AdhocDevices.Add(wifi.Install(phy,mac,AdhocNodes));

    InternetStackHelper internet;
    OlsrHelper olsr;
    internet.SetRoutingHelper(olsr);
    internet.Install(AdhocNodes);
    Ipv4AddressHelper ipv4;
    ipv4.SetBase("10.1.1.0","255.255.255.0");
    Ipv4InterfaceContainer ipv4Interface = ipv4.Assign(AdhocDevices);

    uint64_t port = 9;
    ApplicationContainer sink_app;

    PacketSinkHelper packetSink("ns3::UdpSocketFactory",InetSocketAddress(Ipv4Address::GetAny(),port));
    sink_app=packetSink.Install(AdhocNodes);
    sink_app.Start(Seconds(1.0));
    sink_app.Stop(Seconds(TotalTime));

    Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable>();
    Ptr<UniformRandomVariable> y = CreateObject<UniformRandomVariable>();
    x->SetAttribute("Min",DoubleValue(0));
    x->SetAttribute("Max",DoubleValue(30));
    for(int i=0; i<nodeNum; i++){
        for(int j=0; j<nodeNum; j++){
            if(i==j) continue;
            InetSocketAddress sinkSocket (ipv4Interface.GetAddress(j),port);
            sinkSocket.SetTos(0x70);
            OnOffHelper onoff("ns3::UdpSocketFactory",sinkSocket);
            onoff.SetAttribute("StartTime",TimeValue(Seconds(x->GetInteger())));
            onoff.SetAttribute("StopTime",TimeValue(Seconds(TotalTime-2)));
            onoff.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); // 전송 지속 시간
            onoff.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); // 전송 중단 시간
            onoff.SetAttribute("DataRate", DataRateValue(DataRate("54Mbps"))); // 데이터 전송률
            onoff.SetAttribute("PacketSize",UintegerValue(2048));
            onoff.Install(AdhocNodes.Get(i));
        }
    }


    BasicEnergySourceHelper basicSourceHelper;
    EnergySourceContainer sources;
    DeviceEnergyModelContainer energyDevices;
    x->SetAttribute("Min",DoubleValue(1000));
    x->SetAttribute("Max",DoubleValue(3000));
    for(int i=0; i<nodeNum; i++){
        basicSourceHelper.Set("BasicEnergySourceInitialEnergyJ",ns3::DoubleValue(x->GetValue()));
        sources.Add(basicSourceHelper.Install(AdhocNodes.Get(i)));
    }//초기 에너지량 랜덤성 부여
    ns3::WifiRadioEnergyModelHelper radioHelper;
   
    file<<"Tx,Rx Energy"<<std::endl;
    x->SetAttribute("Min",DoubleValue(0.02));
    x->SetAttribute("Max",DoubleValue(0.04));
    for(int i=0; i<nodeNum; i++){
        double snd = x->GetValue();
        double rcv = x->GetValue();
        radioHelper.Set("TxCurrentA",ns3::DoubleValue(snd));//전송 전류 0.017A
        radioHelper.Set("RxCurrentA",ns3::DoubleValue(rcv));
        file<<i<<": "<<snd<<", "<<rcv<<std::endl;
        energyDevices.Add(radioHelper.Install(AdhocDevices.Get(i),sources.Get(i)));
    }
    Simulator::Schedule(Seconds(1),&TracingParameter,sources,AdhocDevices);
    Simulator::Stop(Seconds(TotalTime));
    
    file<<"Inital Energy"<<std::endl;
    for(int i=0; i<nodeNum; i++){
        file<<i<<": "<<sources.Get(i)->GetRemainingEnergy()<<std::endl;
    }

    Simulator::Run();
    Simulator::Destroy();
    makeCsvFile("Result.csv",Data);
    file.close();
}

 

구현 코드이다. 해당 결과 csv를 DT에 넣어 Feature Selection을 하겠다.