학부연구생

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

Beige00 2024. 3. 13. 15:48

이전 포스팅에 기록했던 곳에서 교수님과 상의 몇가지 아이디어가 추가되었지만, 우선 큰 골자를 디자인하겠다.

 

1. 시뮬레이션 상황 구현 준비

우선 Wireless Mesh Network, Mobile Adhoc Network, SDN, Centralized Dynamic Routing을 가정하겠다.

따라서 가정 시나리오는 다음과 같다.

SDN controller는 각 node에 대한 정보를 알고있고, 이를 이용해 routing을 해준다.

그리고 GW에 연결이 가능한 노드들이 GateWay 노드가 되게 된다.

또한 각 노드의 성능의 차이를 주어야 노드 간의 level이 발생하게 되므로 노드들의 성능도 랜덤하게 주어야할 것 같다.

크게 나눠보면

Adhoc node에서의 라우팅 요청 -> SDN Controller에서 학습된 route 제공 -> 데이터 전송 의 과정이 될 것이다.

당장 내가 구현이 가능한 부분은 Adhoc node 상황을 만들어 Trace source들을 구하는 것이다. (SDN Controller의 구현 생략)

 

그러면 내가 구해야하는 데이터로는 어떤 것이 있을까?

우선 링크 품질, 주변 노드 갯수, 노드의 이동성, 에너지 수준을 수집하는 것을 목표로 구현해야겠다.


2. 구현 시작

우선 특수한 경우에만 작동할 알고리즘을 디자인 할 것이 아니다.

따라서 최대한 포괄적인 경우를 맞출 것이다. 그러나, 각 노드별로 랜덤하게 성능에 차이를 주어 다양한 결과를 뽑아내야할 것 같다.

 

랜덤한 주기든 일정한 주기든 일단 tracing 함수를 주기적으로 스케쥴링할 생각이며, 각 Objective 마다 수집할 계획은 다음과 같다.

 

- 주변 노드 갯수

1. MobilityHelper를 통해 설정된 모든 노드의 현재 위치 정보를 가져온다.

2. 각 노드간의 유클리드 거리를 계산한다.

3. 신호 범위 내의 노드를 판별.

 

- 노드의 이동성

1. 각 노드의 MobilityModel에 접근해서 노드의 속도를 계산.

 

- 에너지 수준

1. 각 노드에 에너지 모델을 설정해준다.(BasicEnergySource 활용 예정)

2. Remaining energy를 가져온다.

 

- 링크 품질

1. YansWifiPhy 모델의 RxPower 파위를 기록하여 신호 강도의 추정치로 사용 가능.


=> 여기서 생각한건데, 처음에는 링크 유효 기간이 중요하다고 생각했다.

왜냐하면, "주변 노드 갯수" 인자가 늘어날 시, 무조건 좋은 노드라고 생각될 수 있지만, 노드의 전송범위 경계에서 들어갔다 나갔다를 반복하는 경우, 주변 노드 갯수가 펌핑되는 현상이 발생 가능하기 때문이다.

그러나 ns3에서 LET(LinkExpirationTime)을 측정하는 방법을 생각해보니, 노드의 현재 위치와 속도를 파악하고, 상대적 속도를 계산해서 LET를 "추정"하는 방법 밖에 없었다.

따라서, LET를 objective로 쓰기에는 무리가 있다고 판단했다.

그렇다면, 이웃 노드의 속도와 거리가 클 시 LET가 짧을 것으로 판단할 수 있지 않을까?

그러면 objective를 이웃 노드간의 거리 합, 주변 노드의 갯수, 각 이웃 노드들의 상대 속도 값(멀어질시 + 가까워 질시 -)을 가공해서 수치화를 시키면 어떨까?

그러면 LET 추정치와 비슷한 값을 뽑아낼 수 있고, 이 값과 remaining energy를 사용하여 classification을 하는 것이다.

 

결론적으로 내 아이디어가 맞아떨어지면 나는 노드들의 위치 정보, 이동성 정보를 수집해야하고, 이를 가공하여 이웃 노드간의 거리 합, 주변 노드의 갯수, 각 이웃 노드들의 상대 속도 값 들을 구해낼 수 있을 것이다.

또한 에너지 모델을 사용하여 Remaining Energy를 수집하면 될 것 같다.


#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 <vector>
#include <string>

using namespace ns3;

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

void 
makeCsvFile(const std::string& filename, const std::vector<std::vector<std::string>>& data){
    std::ofstream file(filename);
    for(const auto& row : data){
        for(auto it = row.begin(); it!=row.end(); ++it){
            file<<*it;
            if(next(it)!=row.end()){
                file<<",";
            }
        }
        file<<std::endl;
    }
    file.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);
}

void 
TracingParameter(EnergySourceContainer e, NetDeviceContainer n){
    for(uint32_t i=0; i<n.GetN(); 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));

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

        uint32_t nodeID = node->GetId();
        double nodeX = pos.x;
        double nodeY = pos.y;
        double dirX = Direction.x;
        double dirY = Direction.y;
        double remainEn = enPtr->GetRemainingEnergy();

        //Second, nodeid, energy, posx, posy, dirx,diry
        Data.push_back({std::to_string(Simulator::Now().GetSeconds()),
        std::to_string(nodeID),
        std::to_string(remainEn),
        std::to_string(nodeX),
        std::to_string(nodeY),
        std::to_string(dirX),
        std::to_string(dirY)
        });
    }
    Simulator::Schedule(Seconds(1),&TracingParameter,e,n);
}

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

    Data.push_back({"Second","NodeID","RemainingEnergy",
    "Node position x","Node position y",
    "Node Direction X","Node Direction Y"});
    
    double TotalTime = 2000.0;
    int nodeNum = 50;
    double energys[3] = {10,20,30};
    double transRange[4] = {100,150,200,250};


    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=3.0]"),
    "PositionAllocator",PointerValue(waypos));
    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");
    for(int i=0; i<nodeNum; i++){
        channel.AddPropagationLoss("ns3::RangePropagationLossModel","MaxRange",DoubleValue(transRange[i%4]));
        phy.SetChannel(channel.Create());
        AdhocDevices.Add(wifi.Install(phy,mac,AdhocNodes.Get(i)));
    }

    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,source_app1;

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

    for(int i=nodeNum; i<nodeNum; i++){
        for(int j=0; j<nodeNum; j++){
            if(i==j) continue;
            OnOffHelper onoff("ns3::UdpSocketFactory",InetSocketAddress(ipv4Interface.GetAddress(j), port));
            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(1024)); // 패킷 크기
            source_app1.Add(onoff.Install(AdhocNodes.Get(i)));
        }
    }
    source_app1.Start(Seconds(2.0));
    source_app1.Stop(Seconds(TotalTime));


    BasicEnergySourceHelper basicSourceHelper;
    EnergySourceContainer sources;
    for(int i=0; i<nodeNum; i++){
        basicSourceHelper.Set("BasicEnergySourceInitialEnergyJ",ns3::DoubleValue(energys[i%3]));
        sources.Add(basicSourceHelper.Install(AdhocNodes.Get(i)));
    }//초기 에너지량 랜덤성 부여
    ns3::WifiRadioEnergyModelHelper radioHelper;
    radioHelper.Set("TxCurrentA",ns3::DoubleValue(0.017));//전송 전류 0.017A
    radioHelper.Set("RxCurrentA",ns3::DoubleValue(0.017));
    DeviceEnergyModelContainer energyDevices = radioHelper.Install(AdhocDevices,sources);

    Simulator::Schedule(Seconds(1),&TracingParameter,sources,AdhocDevices);
    Simulator::Stop(Seconds(TotalTime));

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

}

아이디어를 구현한 코드이며 일단은 제대로 csv가 출력되는거 같다. 추후에 제대로 돌아간건지 확인하도록 하겠다.

이게 맞다면, 이제 구한 attribute들을 가공해서 하나의 "노드 링크 품질" 점수로 환산을 해주는 과정만 있음 될 것 같다.