Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Custom NS3 scheduler

166 views
Skip to first unread message

Mohamed Mohsen

unread,
Aug 7, 2024, 9:00:40 AM8/7/24
to 5G-LENA-users
So at the moment, I am working on an NS3 scheduler that I am basing on the PF Nr scheduler provided with the module. A key part of what I am doing is that I am trying to obtain metrics such as m_potentialTputDl to use as my observation space for RL integration using the NS3-GYM gym module.

(A snippet of a place holder code) 


static double GetPotentialThroughputDl(const NrMacSchedulerNs3::UePtrAndBufferReq& lue,
const NrMacSchedulerNs3::UePtrAndBufferReq& rue)
{
auto luePtr = dynamic_cast<NrMacSchedulerUeInfoA3C2*>(lue.first.get());

double x = std::pow(luePtr->m_potentialTputDl, luePtr->m_alpha) /
std::max(1E-9, luePtr->m_avgTputDl);
return (x);
}


But I always run into basically the same error whenever I try to call this function to retrieve the return (See below)

(One method to retrieve the function)
double XLEUM=NrMacSchedulerUeInfoA3C2::GetPotentialThroughputDl;

(And then the error I run into)
error: cannot convert ‘double (*)(const UePtrAndBufferReq&, const UePtrAndBufferReq&)’ {aka ‘double (*)(const std::pair<std::shared_ptr<ns3::NrMacSchedulerUeInfo>, unsigned int>&, const std::pair<std::shared_ptr<ns3::NrMacSchedulerUeInfo>, unsigned int>&)’} to ‘double’ in initialization
  128 | static double XLEUM=NrMacSchedulerUeInfoA3C2::GetPotentialThroughputDl;
      |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
      |                                               |
      |                                               double (*)(const UePtrAndBufferReq&, const UePtrAndBufferReq&) {aka double (*)(const std::pair<std::shared_ptr<ns3::NrMacSchedulerUeInfo>, unsigned int>&, const std::pair<std::shared_ptr<ns3::NrMacSchedulerUeInfo>, unsigned int>&)}

Is that an issue with the way I am trying to access the function? is that an issue with how I called it? any guidance is highly appreciated.

Gabriel Ferreira

unread,
Aug 7, 2024, 10:50:07 AM8/7/24
to 5G-LENA-users
There is an error there, and the error description describes it.
type    variable   assignment operator                        function
v                  v       v                                                           v
double XLEUM=NrMacSchedulerUeInfoA3C2::GetPotentialThroughputDl;

First thing, you are trying to assign a function by value (copying the function) into a variable of type double, which is very wrong.
The compiler knows that you probably meant, and transformed it into a function pointer with the same signature of your function.

Second thing, the function signature is `double (*)(const UePtrAndBufferReq&, const UePtrAndBufferReq&)`, not a double.
You could do

double(*XLEUM)(const UePtrAndBufferReq&, const UePtrAndBufferReq&) = &NrMacSchedulerUeInfoA3C2::GetPotentialThroughputDl;

Now the point function XLEUM contains the address of the function to be called. However, this is only valid for static functions, not member functions.

The C++ way to handle this is

auto XLEUM = std::bind_front(&NrMacSchedulerUeInfoA3C2::GetPotentialThroughputDl, this/respective UeInfoA3C2 object)

Now you have the XLEUM function which matches the  `double(*XLEUM)(const UePtrAndBufferReq&, const UePtrAndBufferReq&)` signature.

Mohamed Mohsen

unread,
Aug 8, 2024, 7:19:33 AM8/8/24
to 5G-LENA-users
Thanks for the response 

 Using std::bind_front allowed me to bind the original function see code bellow
auto XLEUM = std::bind_front(&NrMacSchedulerUeInfoA3C2::GetPotentialThroughputDl);


but now the issue is that I am trying to use that value of the return as part of my observation space (NS3-GYM module) of my RL algorithm and when I try to do that it basically returns the same error 

Ptr<OpenGymDataContainer>

MyGymEnv::GetObservation()

{

auto XLEUM = std::bind_front(&NrMacSchedulerUeInfoA3C2::GetPotentialThroughputDl);



uint32_t numValues = 6;

std::vector<uint32_t> shape = {numValues,};

Ptr<OpenGymBoxContainer<double> > box2 = CreateObject<OpenGymBoxContainer<double> >(shape);



(Error)

/home/kotymmm/ns-3-dev/scratch/Mohsen01BWP/mygym.cc: In member function ‘virtual ns3::Ptr<ns3::OpenGymDataContainer> ns3::MyGymEnv::GetObservation()’:
/home/kotymmm/ns-3-dev/scratch/Mohsen01BWP/mygym.cc:190:18: error: cannot convert ‘std::_Bind_front<double (*)(const std::pair<std::shared_ptr<ns3::NrMacSchedulerUeInfo>, unsigned int>&, const std::pair<std::shared_ptr<ns3::NrMacSchedulerUeInfo>, unsigned int>&)>’ to ‘double’
  190 |   box2->AddValue(XLEUM);
      |                  ^~~~~
      |                  |
      |                  std::_Bind_front<double (*)(const std::pair<std::shared_ptr<ns3::NrMacSchedulerUeInfo>, unsigned int>&, const std::pair<std::shared_ptr<ns3::NrMacSchedulerUeInfo>, unsigned int>&)>

I know that the error is coming from the type of the box itself but I am unsure if there is a way to use the function as it is now.. perhaps as a tuple?  Or is it a mistake in the way I am defining the std::bind_front ?

Kent Huns

unread,
Aug 8, 2024, 10:40:58 AM8/8/24
to 5G-LENA-users
The object structure of LENA is complex and C++ syntax is difficult, so you should sort out the basics before debugging.
Even if you could write this function correctly, there remains the problem where it can be called correctly.
And we don't know in which source file you want to put it.

I hope the following flow will give you a hint.
"NrMacSchedulerNs3::UePtrAndBufferReq& " is the type of "ue" in nr-mac-scheduler-ofdma.cc, 
and "ue" is a element of "activeDl" in nr-mac-scheduler-ns3.cc.

1. nr-mac-scheduler-ns3.cc
NrMacSchedulerNs3::DoScheduleDlData(...  const ActiveUeMap& activeDl, ...) const
    BeamSymbolMap symPerBeam = AssignDLRBG(symAvail, activeDl);
                        ↓
2. nr-mac-scheduler-ofdma.cc
NrMacSchedulerOfdma::AssignDLRBG(uint32_t symAvail, const ActiveUeMap& activeDl) const
    for (const auto& el : activeDl)
    {
std::vector<UePtrAndBufferReq> ueVector;
        for (const auto& ue : GetUeVector(el))
        {
            ueVector.emplace_back(ue);
        }
        for (auto& ue : ueVector)
        {
            BeforeDlSched(ue, FTResources(rbgAssignable * beamSym, beamSym));
                        ↓
3. nr-mac-scheduler-ofdma-pf.cc
NrMacSchedulerOfdmaPF::BeforeDlSched(const UePtrAndBufferReq& ue,
                                     const FTResources& assignableInIteration) const
{
    auto uePtr = std::dynamic_pointer_cast<NrMacSchedulerUeInfoPF>(ue.first);
    uePtr->CalculatePotentialTPutDl(assignableInIteration, m_dlAmc);
                        ↓
4. nr-mac-scheduler-ue-info-pf.cc

NrMacSchedulerUeInfoPF::CalculatePotentialTPutDl(const NrMacSchedulerNs3::FTResources& assignableInIteration,const Ptr<const NrAmc>& amc)
{
    uint32_t rbsAssignable = assignableInIteration.m_rbg * GetNumRbPerRbg();
    m_potentialTputDl = amc->CalculateTbSize(m_dlMcs, m_dlRank, rbsAssignable);
    m_potentialTputDl /= assignableInIteration.m_sym;

Mohamed Mohsen

unread,
Aug 8, 2024, 12:39:40 PM8/8/24
to 5G-LENA-users
Thank you for your response. I think this flow will make it easier to get through this but I do have one more question.

Where is the structure/code where the lue, and rue (Left ue and right ue) are defined? 

doesn't this 
double lA3C2Metric = std::pow(luePtr->m_potentialTputDl, luePtr->m_alpha) /
std::max(1E-9, luePtr->m_avgTputDl);
mean that there is a hypothetical left ue and right ue m_potentialTputDl value somewhere? and subsequently a left ue and rue m_avgTputDl? 

and if so couldn't they be accessed? as values (I assume double  since this code is from the PF ue-info.h file)

and again I thank you for the guidance.   

Kent Huns

unread,
Aug 8, 2024, 10:55:38 PM8/8/24
to 5g-len...@googlegroups.com
Sorry, I didn't send my answer to all members. 

On Fri, Aug 9, 2024 at 2:44 AM Kent Huns <kent.sa...@gmail.com> wrote:
  >> Where is the structure/code where the lue, and rue (Left ue and right ue) are defined? 
Unfortunately, they are NOT explicitly defined.  They are implicitly defined and used in std::sort(list.start, list.end, ComparisonFunction)
Here, sorted ueVector means the order of PFpriority.
 
The output of "ConparisonFunction" must be bool.
So if you want to get PFmetric directly, perhaps you should add "GetPFmetric(ue)" in nr-mac-scheduler-ofdma-pf.cc & nr-mac-scheduler-ue-info-pf.h

To be honest, I don't like std::sort() because this makes the sorting algorithm inflexible.(Complex scheduler requires many input parameters and uses various criteria.)

nr-mac-scheduler-ofdma.cc
NrMacSchedulerOfdma::AssignDLRBG(uint32_t symAvail, const ActiveUeMap& activeDl) const
        for (auto& ue : ueVector)
        {
            BeforeDlSched(ue, FTResources(rbgAssignable * beamSym, beamSym));
        }
        while (resources > 0)
        {
            GetFirst GetUe;
            std::sort(ueVector.begin(), ueVector.end(), GetUeCompareDlFn());
      ↓
nr-mac-scheduler-ofdma-pf.cc
NrMacSchedulerOfdmaPF::GetUeCompareDlFn() const
{
    return NrMacSchedulerUeInfoPF::CompareUeWeightsDl;
}
      ↓
nr-mac-scheduler-ue-info-pf.h
    static bool CompareUeWeightsDl(const NrMacSchedulerNs3::UePtrAndBufferReq& lue,
                                   const NrMacSchedulerNs3::UePtrAndBufferReq& rue)
    {
        auto luePtr = dynamic_cast<NrMacSchedulerUeInfoPF*>(lue.first.get());
        auto ruePtr = dynamic_cast<NrMacSchedulerUeInfoPF*>(rue.first.get());

        double lPfMetric = std::pow(luePtr->m_potentialTputDl, luePtr->m_alpha) /
                           std::max(1E-9, luePtr->m_avgTputDl);
        double rPfMetric = std::pow(ruePtr->m_potentialTputDl, ruePtr->m_alpha) /
                           std::max(1E-9, ruePtr->m_avgTputDl);

        return (lPfMetric > rPfMetric);
    }
--
You received this message because you are subscribed to the Google Groups "5G-LENA-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to 5g-lena-user...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/5g-lena-users/8a6d2bcc-863b-451e-b051-7c451c4e1f7en%40googlegroups.com.

Mohamed Mohsen

unread,
Aug 30, 2024, 1:36:30 PM8/30/24
to 5G-LENA-users
So I have been working nonstop on this project and I found a method to successfully send my action space data to the UE-info.H file from my RL algorithm ( Kindly See below)

mygym.cc
/*
Execute received actions
*/
bool MyGymEnv::ExecuteActions(Ptr<OpenGymDataContainer> action)
{
Ptr<OpenGymBoxContainer<uint32_t> > box = DynamicCast<OpenGymBoxContainer<uint32_t> >(action);
actionValue1 = box->GetValue(0);
actionValue2 = box->GetValue(1);

//NS_LOG_UNCOND("MyExecuteActions: " << action);
NS_LOG_UNCOND("---Action Value 1: " << actionValue1);
NS_LOG_UNCOND("---Action Value 2: " << actionValue2);

NrMacSchedulerUeInfoA3C2::m_actionValue1 = box->GetValue(0);
NrMacSchedulerUeInfoA3C2::m_actionValue2 = box->GetValue(2);

return true;

}


nr-mac-scheduler-ue-info.h
double NrMacSchedulerUeInfoA3C2::m_actionValue1;
double NrMacSchedulerUeInfoA3C2::m_actionValue2;
static bool CompareUeWeightsDl(const NrMacSchedulerNs3::UePtrAndBufferReq& lue,
const NrMacSchedulerNs3::UePtrAndBufferReq& rue)
{
//auto luePtr = dynamic_cast<NrMacSchedulerUeInfoA3C2*>(lue.first.get());
//auto ruePtr = dynamic_cast<NrMacSchedulerUeInfoA3C2*>(rue.first.get());

//double lA3CMetric = std::max(1E-9, m_actionValue1) ;
double lA3CMetric = m_actionValue1;
double rA3CMetric = m_actionValue2;

return (lA3CMetric > rA3CMetric);
}



but I am still struggling to achieve the opposite. To send data from any of the 5G-Lena based scripts (PFofdma and Ue-info)  and using a similar method to what I have used for the action space does not seem to update correctly (resulting in the same output every cycle) 

mygym.cc
float
MyGymEnv::GetReward()
{


static double reward;

reward =NrMacSchedulerUeInfoA3C2::valDL;



return (reward);
}

nr-mac-scheduler-ue-info-A3C2.cc
double NrMacSchedulerUeInfoA3C2::valDL;
void
NrMacSchedulerUeInfoA3C2::UpdateUlA3C2Metric(const NrMacSchedulerNs3::FTResources& totAssigned,
double timeWindow,
const Ptr<const NrAmc>& amc)
{
NS_LOG_FUNCTION(this);

NrMacSchedulerUeInfo::UpdateUlMetric(amc);

m_currTputUl = static_cast<double>(m_ulTbSize) / (totAssigned.m_sym);
m_avgTputUl = ((1.0 - (1.0 / static_cast<double>(timeWindow))) * m_lastAvgTputUl) +
((1.0 / timeWindow) * m_currTputUl);
valDL =((1.0 - (1.0 / static_cast<double>(timeWindow))) * m_lastAvgTputUl) +
((1.0 / timeWindow) * m_currTputUl);


NS_LOG_DEBUG("Update UL A3C2 Metric for UE "
<< m_rnti << " UL TBS: " << m_ulTbSize << " Updated currTputUl " << m_currTputUl
<< " avgTputUl " << m_avgTputUl << " over n. of syms: " << +totAssigned.m_sym
<< ", last Avg TH Ul " << m_lastAvgTputUl << " total sym assigned "
<< static_cast<uint32_t>(totAssigned.m_sym)
<< " updated UL metric: " << m_potentialTputUl / std::max(1E-9, m_avgTputUl));
}

I have even tried using the get this method along with a dynamic cast method but all lead to the same issue of an output that does not update along with the program. Any ideas or questions are very welcome! 












Kent Huns

unread,
Aug 31, 2024, 12:46:49 PM8/31/24
to 5G-LENA-users
I think the simplest way would be to copy "NrMacSchedulerOfdmaPF" and modify it to your "NrMacSchedulerOfdmaA3C2".
                                                                         ("NrMacSchedulerUeInfoPF")                                     ("NrMacSchedulerUeInfoA3C2")

And if you made new class, you must define its TypeId and set it in scenario file.
For example, you can see below sentence in nr/example/cttc-3gpp-indoor-calibration.cc.
Here, multiplexing type and scheduler algorithm are set and connected to corresponding source.
    nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerTdmaRR"));
    // nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerOfdmaPF"));
    // nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerOfdmaA3C2"));
nr-mac-scheduler-ofdma-pf.cc
namespace ns3
{

NS_LOG_COMPONENT_DEFINE("NrMacSchedulerOfdmaPF");
NS_OBJECT_ENSURE_REGISTERED(NrMacSchedulerOfdmaPF);

TypeId
NrMacSchedulerOfdmaPF::GetTypeId()
{
    static TypeId tid =
        TypeId("ns3::NrMacSchedulerOfdmaPF")
            .SetParent<NrMacSchedulerOfdmaRR>()
            .AddConstructor<NrMacSchedulerOfdmaPF>()

Mohamed Mohsen

unread,
Sep 2, 2024, 8:43:21 AM9/2/24
to 5G-LENA-users
once again thanks a lot for the reply!

I have actually done that and created my own NrMacSchedulerOfdmaA3C2 and NrMacSchedulerOfdmaA3C(for testing) to begin all this, but after reading your response I decided to try my best to write my NS3gym code in the same NrMacSchedulerOfdmaA3C2.cc script (join them into one class with two parent classes), but unfortunately that opens a whole new can of worms of ambiguity errors as both the OpenGymEnv and the NrMacScheduler classes inherit from the Object class and, simply going in to make that inheritance virtual in one or both of those parent classes brings in their own issues.

At this point, I don't know what the alternative is. Is there really no way to pass values like m_lastAvgTputDl from the ue-info script in run time to another class?

Kent Huns

unread,
Sep 3, 2024, 11:52:38 PM9/3/24
to 5G-LENA-users
Your goal is almost there but the problem seems to be OOP in C++ rather than 5G-LENA.
I don't know how you set up OpenGymEnv in detail, so I can only give you the basics. (I'm not C++ expert)

Sorry if you already checked.
1. Update CMakeLists.txt if you create new (.h/.cc) file.
2. Create setter/getter functions to access private members in other classes. You can see them everywhere in ns-3/5G-LENA.

Mohamed Mohsen

unread,
Sep 17, 2024, 10:57:53 AM9/17/24
to 5G-LENA-users
Good news!
as it stands using this approach
//Action space
double NrMacSchedulerUeInfoA3C2::m_actionValue1;
double NrMacSchedulerUeInfoA3C2::m_actionValue2;

//DL
double NrMacSchedulerUeInfoA3C2::potentialDl;
double NrMacSchedulerUeInfoA3C2::currentDl;
double NrMacSchedulerUeInfoA3C2::avgTputDl;



//UL
double NrMacSchedulerUeInfoA3C2::potentialUl;
double NrMacSchedulerUeInfoA3C2::currentUl;
double NrMacSchedulerUeInfoA3C2::avgTputUl;

//QS Smoke dev room
double NrMacSchedulerUeInfoA3C2::Smoke;

NrMacSchedulerUeInfoA3C2::UpdateDlA3C2Metric(const NrMacSchedulerNs3::FTResources& totAssigned,
double timeWindow,
const Ptr<const NrAmc>& amc)
{
NS_LOG_FUNCTION(this);

NrMacSchedulerUeInfo::UpdateDlMetric(amc);
uint32_t tbSize = 0;
for (const auto& it : m_dlTbSize)
{
tbSize += it;
NrMacSchedulerUeInfoA3C2::Smoke = tbSize;
}
m_currTputDl = static_cast<double>(tbSize) / (totAssigned.m_sym);
NrMacSchedulerUeInfoA3C2::currentDl = m_currTputDl;
m_avgTputDl = ((1.0 - (1.0 / static_cast<double>(timeWindow))) * m_lastAvgTputDl) +
((1.0 / timeWindow) * m_currTputDl);
NrMacSchedulerUeInfoA3C2::avgTputDl = m_avgTputDl;
NS_LOG_DEBUG("Update DL A3C2 Metric for UE "
<< m_rnti << " DL TBS: " << tbSize << " Updated currTputDl " << m_currTputDl
<< " avgTputDl " << m_avgTputDl << " over n. of syms: " << +totAssigned.m_sym
<< ", last Avg TH Dl " << m_lastAvgTputDl << " total sym assigned "
<< static_cast<uint32_t>(totAssigned.m_sym)
<< " updated DL metric: " << m_potentialTputDl / std::max(1E-9, m_avgTputDl));
}




I have succeeded at obtaining the three throughput values (For DL) and plugging them into my implementation of A2C and A3C reinforcement learning algorithms using NS3-GYM
and even returning my action space values here, effectively meaning my RL algorithm is in charge of Qos flow scheduling.
static bool CompareUeWeightsDl(const NrMacSchedulerNs3::UePtrAndBufferReq& lue,
const NrMacSchedulerNs3::UePtrAndBufferReq& rue)
{
//auto ruePtr = dynamic_cast<NrMacSchedulerUeInfoA3C2*>(rue.first.get());

//double lA3CMetric = std::max(1E-9, m_actionValue1) ;
double lA3CMetric = m_actionValue1;
double rA3CMetric = m_actionValue2;

return (lA3CMetric < rA3CMetric);
}


but now I have run into a different hiccup in trying to obtain values pertaining to QoS as the same issue that most of those values like the delayBudgetFacto, are defined and declared in header files see bellow
static double CalculateDelayBudgetFactor(uint64_t pdb, uint16_t hol)
{
double denominator = hol >= pdb ? 0.1 : static_cast<double>(pdb) - static_cast<double>(hol);
double delayBudgetFactor = static_cast<double>(pdb) / denominator;

return delayBudgetFactor;
}

so my question is how can I create a method to obtain values like the delayBudgetFactor for each UE and access it from another script?
any ideas or past experiences in trying to obtain UE related metrics from the header files of the schedulers is highly appreciated. If something is not clear please feel free to ask and I will try to clarify.

Katerina Koutlia

unread,
Sep 18, 2024, 5:47:49 AM9/18/24
to 5G-LENA-users
Try to have it as a UE-related info in the NrMacSchedulerUeInfo class. You can even create Get/Set functions to store and retrieve the value easily.

BR,
Kat

Kent Huns

unread,
Sep 19, 2024, 8:19:57 AM9/19/24
to 5G-LENA-users
Hi Mohamed,

>>how can I create a method to obtain values like the delayBudgetFactor for each UE and access it from another script?
I'm not sure you would like to adjust "a parameter with different value for each UE" or "delayBudgetFactor itself".
Katerina answered about the former. And the original source is very good example. luePtr->m_potentialTputDl means left side UE's m_potentialTputDl.
nr-mac-scheduler-ue-info-pf.h
    static bool CompareUeWeightsDl(const NrMacSchedulerNs3::UePtrAndBufferReq& lue,
                                   const NrMacSchedulerNs3::UePtrAndBufferReq& rue)
    {
        auto luePtr = dynamic_cast<NrMacSchedulerUeInfoPF*>(lue.first.get());
        auto ruePtr = dynamic_cast<NrMacSchedulerUeInfoPF*>(rue.first.get());

        double lPfMetric = std::pow(luePtr->m_potentialTputDl, luePtr->m_alpha) /
                           std::max(1E-9, luePtr->m_avgTputDl);
        double rPfMetric = std::pow(ruePtr->m_potentialTputDl, ruePtr->m_alpha) /
                           std::max(1E-9, ruePtr->m_avgTputDl);

        return (lPfMetric > rPfMetric);
    }

On the other hand, delayBudgetFactor is not as simple as above.
static_cast<double>(pdb) are defined in src/lte/model/eps-bearer.cc and their value are strictly 3GPP compliant. They shouldn't be changed.
If you don't care about the difference of eps-bearer type, pdb will be a constant since the same bearer type is set for all UEs as (implicit) input parameter.
  cf)  src/lte/model/eps-bearer.h,  src/lte/model/eps-bearer.cc ,  https://en.wikipedia.org/wiki/QoS_Class_Identifier

Katerina Koutlia

unread,
Sep 19, 2024, 9:17:33 AM9/19/24
to Kent Huns, 5G-LENA-users
Hi Kent,

If I understood correctly, (correct me if I am wrong), he just wants to send the calculated Delay Budget Factor to ns3-gym, not change the value.
If Kent is right, then yes, you can get the PDB (packet delay budget) from the eps-bearer.

BR,
Kat    

--
You received this message because you are subscribed to the Google Groups "5G-LENA-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to 5g-lena-user...@googlegroups.com.

Mohamed Mohsen

unread,
Sep 19, 2024, 10:34:02 AM9/19/24
to 5G-LENA-users
Hi Kent & Katerina

First of all again thank you both for taking the time to respond.

Yes my intention here is just to send the calculated Delay Budget Factor to ns3-gym, and I... sort of did that? (Kindly see bellow)

From the NrMacSchedulerLcQos.cc script
double NrMacSchedulerLcQos::getHOL;
double NrMacSchedulerLcQos::getPDB;



std::vector<NrMacSchedulerLcAlgorithm::Assignation>
NrMacSchedulerLcQos::AssignBytesToDlLC(const std::unordered_map<uint8_t, LCGPtr>& ueLCG,
uint32_t tbs,
Time slotPeriod) const
{
NS_LOG_FUNCTION(this);
GetFirst GetLCGID;
GetSecond GetLCG;

std::vector<NrMacSchedulerLcAlgorithm::Assignation> ret;

NS_LOG_INFO("To distribute: " << tbs << " bytes over " << ueLCG.size() << " LCG"
<< " in Qos manner");

uint32_t bytesLeftToBeAssigned = tbs;
uint32_t bytesAssigned = 0;
uint64_t sumErabGueanteedBitRate = 0;

std::vector<std::pair<uint8_t, uint8_t>>
gbrActiveLCs; // vector that stores the LCG ID and the LC ID of the gbr active LCs
std::vector<std::pair<uint8_t, uint8_t>>
restActiveLCs; // vector that stores the LCG ID and the LC ID of the rest active LCs

std::vector<std::pair<uint8_t, uint32_t>>
AssignedBytesToGbrLCsList; // vector that stores the LC ID with the bytes assigned for the
// case of GBR LCs

for (const auto& lcg : ueLCG)
{
std::vector<uint8_t> ueActiveLCs = GetLCG(lcg)->GetActiveLCIds();
for (const auto lcId : ueActiveLCs)
{
std::unique_ptr<NrMacSchedulerLC>& LCPtr = lcg.second->GetLC(lcId);
// Access the PDB and HOL values
double pdb = LCPtr->m_delayBudget.GetMilliSeconds();
double hol = LCPtr->m_rlcTransmissionQueueHolDelay;
NrMacSchedulerLcQos::getHOL = hol;
NrMacSchedulerLcQos::getPDB = pdb;



Then in my mygym.cc

/*
Collect observations
*/
Ptr<OpenGymDataContainer>
MyGymEnv::GetObservation()
{

uint32_t numValues = 4;

std::vector<uint32_t> shape = {numValues,};
Ptr<OpenGymBoxContainer<double>> box2 = CreateObject<OpenGymBoxContainer<double>>(shape);

double denominator = NrMacSchedulerLcQos::getHOL >= NrMacSchedulerLcQos::getPDB ? 0.1 : static_cast<double>(NrMacSchedulerLcQos::getPDB) - static_cast<double>( NrMacSchedulerLcQos::getHOL);
double delayBudgetFactor = static_cast<double>(NrMacSchedulerLcQos::getPDB) / denominator;


box2->AddValue(delayBudgetFactor);



If its unclear what I did there is yoink head of the line delay and pdb from the Lc.cc script and just calculated the delay budget in my mygym.cc script (And I am finally getting it to spit numbers out) but I suspect there is something wrong with my method as for one the numbers seem.. odd? lots of 1s and 1.XXXXX and this method of mine does not use the more standard approach I am seeing in Lena with an LUE and an RUE.

If you have further advice on whether or not this approach is valid or not. Or if you just simply have more knowledge to share.
going forward from this is to use this same method to obtain other values like the Weight and CQI etc...

Best Wishes
MMF
Reply all
Reply to author
Forward
0 new messages