如何在 Veins 4.4 中正确使用 "moduleDisplayString"?

How to properly use "moduleDisplayString" in Veins 4.4?

我用过Veins 4.4,模拟运行正常

但是,我想在图形模式下更改车辆的外观。通过分析代码,我注意到 "moduleDisplayString" 参数用于执行此操作,但即使使用 OMNeT 的默认 DisplayString 值,我也总是会遇到映射错误。

[...]
*.manager.moduleType = "sdvn.nodes.Car"
*.manager.moduleName = "vehicle"
*.manager.moduleDisplayString = "i=misc/sun;is=vs"
[...]

错误信息:

invalid syntax for mapping "i=misc/sun;is=vs" for parameter "moduleDisplayString"

有没有人能正确使用这个参数?

这实际上是一个错误。在最新版本中,Veins 得到了扩展,可以为不同的 SUMO 车辆类型实例化不同的模块类型。例如你可以使用

*.manager.moduleType = "vtypeauto=Car vtypehuman=HumanCar"
*.manager.moduleName = "vtypeauto=node vtypehuman=human"

Car.ned模块实例化SUMO vtype vtypeauto并在配置中用node引用它(例如,*.node[*].mobility.z = 1.895),同时实例化vtype vtypehumanHumanCar.ned 模块并允许您使用 human.

配置它

错误是由语法引起的,因为此功能使用 = 符号在键和值对之间进行拆分。 moduleDisplayString 参数也是如此,因此解析器不起作用。

我准备了一个补丁,其中可以使用单引号 (') 来保护显示字符串。在您的具体情况下,您的配置变为

*.manager.moduleDisplayString = "'i=misc/sun;is=vs'"

所以解析器知道如何正确读取参数。我也试过这个配置

*.manager.moduleType = "vtypeauto=Car vtypehuman=HumanCar"
*.manager.moduleName = "vtypeauto=node vtypehuman=human"
*.manager.moduleDisplayString = "vtypeauto='i=misc/sun;is=vs' vtypehuman='i=abstract/penguin'"

这是结果

您可以看到一种车辆的太阳图像和另一种车辆的企鹅图像。正如您正确指出的那样,Veins 目前显示一个框来突出显示汽车。这很可能很快就会被删除,或者用更好的图标进行更改(例如,实际的汽车图标)。

我会准备一个补丁,它应该很快会在 Veins 的 github 存储库上在线发布。同时,我将代码片段复制粘贴到这里,这样您就可以继续工作而无需等待正式发布。您需要做的是在 TraCIScenarioManager.cpp.

中的函数 TraCIScenarioManager::parseMappings 之前添加以下函数
std::vector<std::string> getMapping(std::string el) {

    //search for string protection characters '
    char protection = '\'';
    size_t first = el.find(protection);
    size_t second;
    size_t eq;
    std::string type, value;
    std::vector<std::string> mapping;

    if (first == std::string::npos) {
        //there's no string protection, simply split by '='
        cStringTokenizer stk(el.c_str(), "=");
        mapping = stk.asVector();
    }
    else {
        //if there's string protection, we need to find a matching delimiter
        second = el.find(protection, first + 1);
        //ensure that a matching delimiter exists, and that it is at the end
        if (second == std::string::npos || second != el.size() - 1)
            throw cRuntimeError("invalid syntax for mapping \"%s\"", el.c_str());

        //take the value of the mapping as the text within the quotes
        value = el.substr(first + 1, second - first - 1);

        if (first == 0) {
            //if the string starts with a quote, there's only the value
            mapping.push_back(value);
        }
        else {
            //search for the equal sign
            eq = el.find('=');
            //this must be the character before the quote
            if (eq == std::string::npos || eq != first - 1) {
                throw cRuntimeError("invalid syntax for mapping \"%s\"", el.c_str());
            }
            else {
                type = el.substr(0, eq);
            }
            mapping.push_back(type);
            mapping.push_back(value);
        }
    }
    return mapping;
}

然后在TraCIScenarioManager::parseMappings函数里面改下面两行

cStringTokenizer typeMappingTz(typeMapping.c_str(), "=");
std::vector<std::string> mapping = typeMappingTz.asVector();

std::vector<std::string> mapping = getMapping(typeMapping);