ns3-gym入门(一):代码结构和简单例子

ns3-gym真的好难学,网上可以参考的例子也太少了,如果有用这个做路由的麻烦联系我交流一下吧,太痛苦了

一、安装
之前的文章已经提到过了,这里不赘述了

二、运行简单的例子

用两个终端的方式运行感觉更加直观,但是仍然有些坑:

  1. Terminal 1:最好用sudo模式,可能是哪里的权限不够,反正我只用waf指令时好时坏,也是挺神奇的,这里实际上是在运行/contrib/opengym/examples/目录下,"opengym"文件夹里的"sim.cc",在后续更复杂的例子里,其实ns3环境是配置在"mygym.cc"里面的,最终通过头文件"mygym.h"被"sim.cc"调用
  2. Terminal 2:Ubuntu 20.04自带的protobuf版本相对低了一点,直接运行会报错,所以在运行时先设置环境变量PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python。这里是执行/contrib/opengym/examples/目录下,"opengym"文件夹对应的test.py
# Terminal 1
cd ~/ns-allinone-3.35/ns-3.35
sudo ./waf --run "opengym"

# Terminal 2
cd ~/ns-allinone-3.35/ns-3.35/contrib/opengym/examples/opengym/
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python ./test.py --start=0

三、例子代码详解
        整体的代码结构图如下,摘自对应的论文。这里的接口主要用的是ZMQ Socket通信,另一个ns3-ai用的是共享内存的方法,据说会比ns3-gym快100倍,但是资料也不多,有时间再试一下

1.基本的接口
        python端:

import gym
import ns3gym
import MyAgent
from ns3gym import ns3env

#env = gym.make('ns3-v0')  <--- causes some errors with the new OpenAI Gym framework, please use ns3env.Ns3Env()
env = ns3env.Ns3Env()
obs = env.reset()
agent = MyAgent.Agent()

while True:
  action = agent.get_action(obs)
  obs, reward, done, info = env.step(action)

  if done:
    break
env.close()

        ns3端:

Ptr<OpenGymSpace> GetObservationSpace();
Ptr<OpenGymSpace> GetActionSpace();
Ptr<OpenGymDataContainer> GetObservation();
float GetReward();
bool GetGameOver();
std::string GetExtraInfo();
bool ExecuteActions(Ptr<OpenGymDataContainer> action);

2.Example1:"opengym"详解
        这个需要sim.cc和test.py对照着来看,懒得打字了,我直接把关键的函数、属性、两个端口的交互画在纸上了:

        首先初始化环境会有一个observation(step0),然后每一轮按照action-obs+reward+done+info的方式迭代(step++),迭代是否结束是sim.cc里面的done布尔值决定的。
        obs收集到的状态是在(low, high)范围内生成的5个随机数,reward是每次迭代+1(我后来改成了reward=action),action是在离散空间下的[0,1,2,3,4],agent通过sample随机选择动作。
        这里还需要对相应的数据类型有一些了解:

        我稍微改动了一下代码,让每一轮迭代更清晰了一些。
        python端:

        ns3端:

PS. 这里和普通的gym环境不太一样:在sim.cc里定义的各个空间函数属性不能改,这个应该是定义在如下的接口回调函数里了,要实现什么功能在对应的函数内部改动就行

  // OpenGym Env
  Ptr<OpenGymInterface> openGym = CreateObject<OpenGymInterface> (openGymPort);
  openGym->SetGetActionSpaceCb( MakeCallback (&MyGetActionSpace) );
  openGym->SetGetObservationSpaceCb( MakeCallback (&MyGetObservationSpace) );
  openGym->SetGetGameOverCb( MakeCallback (&MyGetGameOver) );
  openGym->SetGetObservationCb( MakeCallback (&MyGetObservation) );
  openGym->SetGetRewardCb( MakeCallback (&MyGetReward) );
  openGym->SetGetExtraInfoCb( MakeCallback (&MyGetExtraInfo) );
  openGym->SetExecuteActionsCb( MakeCallback (&MyExecuteActions) );
  Simulator::Schedule (Seconds(0.0), &ScheduleNextStateRead, envStepTime, openGym);

3.Example2:"opengym-2"详解

        运行指令和之前一毛一样,只需要需修改代码路径,还是最好开两个终端(有时候ns3会突然发疯报错,我什么代码都没改它也报错。。。这个时候多半是终端卡住了,新建终端,先重新编译再输入指令就行)

sudo ./waf configure --enable-test --enable-examples
sudo ./waf build

# Terminal 1
cd ~/ns-allinone-3.35/ns-3.35
sudo ./waf --run "opengym-2"

# Terminal 2
cd ~/ns-allinone-3.35/ns-3.35/contrib/opengym/examples/opengym-2/
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python ./test.py --start=0

        这个比较特别的是把ns3仿真环境单独写成了mygym.cc,再在sim.cc里面通过头文件mygym.h进行引用,其实具体的obs\reward\action定义都和"opengym"差不多,只是用到了更丰富的数据类型。后面如果要用到比较复杂的ns3环境的话,估计也会这样写更方便调试。
sim.cc(不再具体创建环境了,只是定义一些宏观的参数):

  // OpenGym Env
  Ptr<OpenGymInterface> openGymInterface = CreateObject<OpenGymInterface> (openGymPort);
  Ptr<MyGymEnv> myGymEnv = CreateObject<MyGymEnv> (Seconds(envStepTime));
  myGymEnv->SetOpenGymInterface(openGymInterface);

mygym.h(创建一个自定义的 Gym 环境类,该类继承自OpenGymEnv):

class MyGymEnv : public OpenGymEnv
{
public:
  MyGymEnv ();
  MyGymEnv (Time stepTime);
  virtual ~MyGymEnv ();
  static TypeId GetTypeId (void);
  virtual void DoDispose ();

  Ptr<OpenGymSpace> GetActionSpace();
  Ptr<OpenGymSpace> GetObservationSpace();
  bool GetGameOver();
  Ptr<OpenGymDataContainer> GetObservation();
  float GetReward();
  std::string GetExtraInfo();
  bool ExecuteActions(Ptr<OpenGymDataContainer> action);

private:
  void ScheduleNextStateRead();

  Time m_interval;
};

mygym.cc(对应mygym.h分别进行定义,这里只把和"opengym/sim.cc"不一样的地方贴出来了,后面依然是对各个要素空间的定义,用到了tuple\dict两种数据类型):

MyGymEnv::MyGymEnv ()
{
  NS_LOG_FUNCTION (this);
  m_interval = Seconds(0.1);

  Simulator::Schedule (Seconds(0.0), &MyGymEnv::ScheduleNextStateRead, this);
}

MyGymEnv::MyGymEnv (Time stepTime)
{
  NS_LOG_FUNCTION (this);
  m_interval = stepTime;

  Simulator::Schedule (Seconds(0.0), &MyGymEnv::ScheduleNextStateRead, this);
}

void
MyGymEnv::ScheduleNextStateRead ()
{
  NS_LOG_FUNCTION (this);
  Simulator::Schedule (m_interval, &MyGymEnv::ScheduleNextStateRead, this);
  Notify();
}

MyGymEnv::~MyGymEnv ()
{
  NS_LOG_FUNCTION (this);
}

TypeId
MyGymEnv::GetTypeId (void)
{
  static TypeId tid = TypeId ("MyGymEnv")
    .SetParent<OpenGymEnv> ()
    .SetGroupName ("OpenGym")
    .AddConstructor<MyGymEnv> ()
  ;
  return tid;
}

void
MyGymEnv::DoDispose ()
{
  NS_LOG_FUNCTION (this);
}

这两个简单的例子其实重在展示基础的交互过程和丰富的数据类型,并没有涉及到强化学习的内核,比如说reward如何基于state(obs)和action定义,action又是怎么作用于state的,要与具体的网络环境耦合还需要更深层次的探索

### 配置使用ns-3ns-3-gym在VSCode中的网络仿真 #### 安装依赖项 为了确保能够在VSCode中顺利运行ns-3以及ns-3-gym,需要先安装系列必要的软件包。这包括但不限于CMake、Python3及其pip工具等基础构建组件。 对于Ubuntu 20.04而言,可以通过如下命令来完成这些前置条件的部署: ```bash sudo apt update && sudo apt install -y build-essential cmake python3-dev python3-pip git libboost-all-dev autoconf automake bison flex g++ gcc libffi-dev libgmp-dev libmpc-dev libmpfr-dev libtool make pkg-config texinfo zlib1g-dev qtbase5-dev libcwiid-dev wiimote-tools ``` 接着利用`pip3`安装额外所需的Python库文件,特别是针对ns-3-gym的支持部分: ```bash pip3 install gym numpy matplotlib pybind11==2.6.2 ``` #### 下载并编译ns-3源码 获取最新的ns-3版本(此处假设为v3.34),解压后进入对应目录执行编译操作。考虑到后续可能涉及到频繁修改测试的需求,建议采用调试模式(Debug)来进行编译工作以便于排查错误信息。 ```bash git clone https://github.com/nsnam/ns-3-dev.git ns-3.34 cd ns-3.34 ./waf configure --build-profile=debug ./waf ``` #### 整合ns-3-gym模块至ns-3项目内 下载ns-3-gym仓库,并将其放置到ns-3项目的顶层路径下作为子模块管理;随后按照官方文档指示调整配置参数使得两者能够协同运作[^1]。 ```bash git submodule add https://github.com/tkn-tub/ns3-gym.git src/gym-api ./waf clean ./waf configure --with-gym-api=./src/gym-api/ ./waf ``` #### 设置VSCode开发环境 打开Visual Studio Code编辑器,在目标工程根目录创建`.vscode/launch.json`用于定义启动选项,同时编写相应的任务脚本(`tasks.json`)辅助日常编码流程自动化处理。下面给出了组基本样例供参考: **launch.json** ```json { "version": "0.2.0", "configurations": [ { "name": "(gdb) Launch", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/build/debug/${fileBasenameNoExtension}", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": true, "MIMode": "gdb", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true } ], "preLaunchTask": "compile" } ] } ``` **tasks.json** ```json { "version": "2.0.0", "tasks": [ { "label": "compile", "command": "./waf", "group": { "kind": "build", "isDefault": true }, "detail": "Compile the project using waf.", "problemMatcher": ["$gcc"], "presentation": { "echo": true, "reveal": "always", "focus": false, "panel": "shared" } } ] } ``` 通过上述步骤即可实现在VSCode环境下对ns-3ns-3-gym的有效支持,方便开发者开展基于强化学习算法驱动下的无线通信场景模拟实验研究工作[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值