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

时间:2017-06-15 16:55:42

标签: c++ simulation omnet++ 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"

有没有人能够正确使用此参数?

1 个答案:

答案 0 :(得分:3)

This is actually a bug. In the latest releases Veins have been extended to enable the possibility of instantiating different module types for different SUMO vehicle types. For example you can use

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

to instantiate the SUMO vtype vtypeauto with the Car.ned module and refer to it in the configuration with node (e.g., *.node[*].mobility.z = 1.895), while instantiating the vtype vtypehuman with the HumanCar.ned module and allowing you to configure it using human.

The bug is due to the syntax, as this feature uses an = sign to split between key and value pairs. The same holds for the moduleDisplayString parameter, so the parser does not work.

I prepared a patch where single quotes (') can be used to protect display strings. In your specific case, your configuration becomes

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

so the parser knows how to properly read the parameter. I tried also this configuration

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

and this is the result

Simulation screenshot

You can see the sun image for one type of vehicle and the penguin for the other. As you correctly pointed out, Veins currently displays a box to highlight the car. This will most probably be removed soon, or changed with a better icon (e.g., an actual car icon).

I will prepare a patch and this should soon be published online on the github repo of Veins. In the meanwhile, I am copy-pasting here the snippet for you, so you can continue working without waiting for the official release. What you have to do is add the following function just before the function TraCIScenarioManager::parseMappings in TraCIScenarioManager.cpp.

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;
}

Then change the following two lines inside the TraCIScenarioManager::parseMappings function

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

with

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