Libsumo

Libsumo#

与正在运行的仿真进行交互的主要方式是 TraCI,它提供了完全的灵活性,可以进行跨平台、跨语言和网络化交互,其中 sumo 充当服务器。一个主要的缺点是由于协议和套接字通信带来的通信开销。为了实现更高效的耦合而无需套接字通信,TraCI API 以 C++ 库的形式提供,具有以下特性:

  • 基于静态函数的 C++ 接口,以及一些用于结果的简单包装类,可以直接链接到客户端代码
  • 函数签名与 TraCI 类似
  • 为 Java 和 Python 提供预构建的语言绑定(使用 SWIG
  • 通过 SWIG 支持其他编程语言

限制#

以下内容目前不工作(或与 TraCI Python 客户端的工作方式不同):

  • 在 Windows 上无法与 sumo-gui 一起运行,在其他平台上仍处于高度实验阶段
  • 需要额外参数的订阅(除了 vehicle.getLeader
  • 更严格的类型检查
    • TraCI 客户端有时接受任何可迭代对象,而 Libsumo 需要列表
    • TraCI 客户端可能接受任何对象,而 Libsumo 需要布尔值
    • TraCI 在需要字符串时会自动将每个参数转换为字符串,而 Libsumo 不会
  • 无法使用 traci.init 或 traci.connect(始终需要使用 traci.start / libsumo.start)
  • 使用 traci 时,每个 TraCIException 都会在 stderr 上生成一条消息,而 Libsumo 不会生成此消息
  • libsumo 本身不能用于将多个客户端连接到仿真(尽管可以将普通的 TraCI 客户端连接到 libsumo 实例)
  • 运行 libsumo 的并行实例需要 python 中的 multiprocessing 模块

为了避免 GUI 和多客户端支持方面的限制,您也可以使用 libtraci。这是一个 C++ traci 客户端库,与 libsumo 完全 API 兼容。

构建和安装#

二进制 Windows 发行版已经包含了为 C++ 和 Java 预编译好的 libsumo。对于 Python,您可以通过 pip install libsumo 安装它。对于 C#,提供了生成的源文件。只有当您的平台或语言不受支持时,才需要按照以下步骤操作。

目前需要安装 cmake 和 swig 以及 Python 的开发包(如果需要 Java,则也需要 Java 的开发包),对于 Windows,请参见 Windows CMake。您需要在 Windows 下(重新)编译 sumo,遵循上述说明,在 Linux 下请参见 Installing/Linux_Build(如果您之前在没有 swig 的情况下构建过,可能只需再次调用 cmake 和 make 即可)。 对于 Python 绑定,您将获得一个 libsumo.py 和一个 _libsumo.so(在 Windows 上为 .pyd)。如果您将它们放在 Python 路径上的某个位置,您应该能够按照下面的描述使用它们。 如果您想启用实验性的 C# 支持,请确保在您的 cmake 配置中设置了 ENABLE_CS_BINDINGS

Note

确保将 "/your/path/to/sumo/tools" 添加到 PYTHONPATH 环境变量中。

使用 libsumo#

如果您想使用(实验性的)GUI,那么您需要在启动命令中使用 sumo-gui 代替 sumo,或者定义环境变量 LIBSUMO_GUI

Python#

确保您已安装 libsumo (pip install libsumo)。

import libsumo
libsumo.start(["sumo", "-c", "test.sumocfg"])
libsumo.simulationStep()

现有的 traci 脚本可以通过调用以下代码来重用(受限于上述限制):

import libsumo as traci

如果您有很多脚本,也可以将环境变量 LIBSUMO_AS_TRACI 设置为非空值,这将触发如上所述的导入。

C++#

请注意额外的 #define 用于启用 GUI 代码,如果您不使用或无法使用 GUI(Windows),则不需要此行。

示例代码 (test.cpp)#

该示例假设您在当前工作目录中有命名的 sumocfg 文件,并且 SUMO 的 bin 目录包含在 PATH 环境变量中。否则,您需要提供完整的文件路径。

#include <iostream>
#define HAVE_LIBSUMOGUI  // 如果您在 Windows 上或自己编译了没有 GUI 的 libsumo,则应删除此行
#include <libsumo/libsumo.h>

using namespace libsumo;

int main(int argc, char* argv[]) {
    Simulation::start({"sumo", "-c", "test.sumocfg"});
    for (int i = 0; i < 5; i++) {
        Simulation::step();
    }
    Simulation::close();
}

在 Linux 上编译(确保已设置 SUMO_HOME 并已构建 sumo)#

g++ -o test -std=c++11 -I$SUMO_HOME/src test.cpp -L$SUMO_HOME/bin -lsumocpp

在 Linux 上运行#

LD_LIBRARY_PATH=$SUMO_HOME/bin ./test

Java#

在 Windows 上,强烈建议至少使用 OpenJDK 21.0.5(适用于 libsumo 1.22.0 或更高版本)。早期版本会出现无法解释的崩溃。

您可能希望使用可用的 Maven 包

示例代码 (Test.java)#

import org.eclipse.sumo.libsumo.Simulation;
import org.eclipse.sumo.libsumo.StringVector;

public class Test {
    public static void main(String[] args) {
        Simulation.preloadLibraries();
        Simulation.start(new StringVector(new String[] {"sumo", "-c", "test.sumocfg"}));
        for (int i = 0; i < 5; i++) {
            Simulation.step();
        }
        Simulation.close();
    }
}

请注意,从 SUMO 1.16.0 开始,在 Windows 上似乎需要预加载一些库,参见 https://github.com/eclipse-sumo/sumo/issues/12605。 从 SUMO 1.24.0 开始,这已封装在一个单独的便捷调用 Simulation.preloadLibraries() 中。

在 Linux 上编译(确保已设置 SUMO_HOME 并已构建 sumo)#

javac -cp $SUMO_HOME/bin/libsumo-1.25.0-SNAPSHOT.jar Test.java

在 Linux 上运行#

java -Djava.library.path=$SUMO_HOME/bin -cp $SUMO_HOME/bin/libsumo-1.25.0-SNAPSHOT.jar:. Test

转换订阅结果#

请注意,在 Java 中转换订阅结果并非易事。您必须使用 cast 函数,如下所示。如果转换不成功,它不会抛出异常,而是返回一个空指针。

TraCIResults ssRes = Simulation.getSubscriptionResults();
for (Map.Entry<Integer, TraCIResult> entry : ssRes.entrySet()) {
    TraCIResult sR = entry.getValue();
    TraCIStringList vehIDs = TraCIStringList.cast(sR);
    for (String vehID : vehIDs.getValue()) {
        System.out.println("Subscription Departed vehicles: " + vehID);
    }
}

Matlab#

请安装 Python 包。然后,您可以在 Matlab 脚本中使用所有命令,就像在 Python 中一样,只需添加 py. 前缀。

py.libsumo.start(["sumo", "-c", "test.sumocfg"])
py.libsumo.simulationStep()

C#

示例代码 (Program.cs)#

确保您已将 swig 生成的 C# 绑定添加到您的解决方案中,以及编译好的 libsumocs.dll(如果您的 Sumo 安装文件夹中不存在)。

using Eclipse.Sumo.Libsumo;

internal class Program
{
    static void Main(String[] args) {
        Simulation.start(new StringVector(new String[] {"sumo", "-c", "test.sumocfg"}));
        for (int i = 0; i < 5; i++) {
            Simulation.step();
        }
        Simulation.close();
    }
}