Gabriel de Biasi
Gabriel de Biasi

Reputation: 13

How to properly use "moduleDisplayString" in Veins 4.4?

I have used Veins 4.4 and the simulations are executed normally.

However, I would like to change the appearance of vehicles in graphic mode. By analyzing the code, I noticed that the "moduleDisplayString" parameter is used to do this, but even using OMNeT's default DisplayString values I always get a mapping error.

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

Error message:

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

Has anyone been able to use this parameter correctly?

Upvotes: 1

Views: 214

Answers (1)

Michele Segata
Michele Segata

Reputation: 116

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

Upvotes: 3

Related Questions