0

I am currently writing a ROS 2 node to pass values from a PLC through ROS to a visualization:

PLC System --> ROS --> Visualization

Since ROS should only pass on the data, I want to be able to configure the interface here with as little effort as possible. The idea, which can be implemented best with ROS, would be a config-file(.msg file), in which the designation of the variables and their type is entered. Everything else is then derived from this. The problem I inevitably run into with this: In ROS data are passed on over so-called messages. These messages are defined via structs and are automatically generated from my config-file. To assign values to the variables from the struct, I don't want to address every single one hardcoded in the program, but rather iterate through the struct using the known names.

TLNR: Can variables be addressed with variable variable names?

I know that the whole thing sounds a bit confusing. I hope the following example will clarify what I mean:

#include <vector>
#include <string>

struct MsgFile
{
    int someVariable;
    int someOtherVariable;
};

using namespace std;

class Example
{
public:
    vector<string> variableNames{"someVariable", "someOtherVariable"};
    MsgFile message;

    void WriteVariables()
    {
        for (auto const &varName : variableNames)
        {
            message."varName" = 0;  //<-- pseudo code of what I'm thinking of     
        }
    }
};

Regards Tillman

Tillman
  • 7
  • 1
  • 1
    Did you consider using [Lua](http://lua.org/) in your robot? Or [GNU guile](https://www.gnu.org/software/guile/) ? Or writing your [GCC plugin](https://gcc.gnu.org/onlinedocs/gccint/Plugins.html)? Or *generating* some C++ code? See also [this draft report](http://starynkevitch.net/Basile/bismon-doc.pdf) and [DECODER](http://decoder-project.eu/) – Basile Starynkevitch Feb 05 '21 at 10:56

2 Answers2

2

You cannot use variable names like that. There are no variable names at runtime. If you want a mapping between names (strings) and variables, you need to add that yourself.

If your "variables" are of same type, eg int, you can use a map:

#include <vector>
#include <string>
#include <unordered_map>    

using MsgFile = std::unordered_map<std::string,int>;


struct Example {
    std::vector<std::string> variableNames{"someVariable", "someOtherVariable"};
    MsgFile message;

    void WriteVariables() {
        for (auto const &varName : variableNames) {
            message[varName] = 0;  // add an entry { varName, 0 } to the map
                                   // (or updates then entry for key==varName when it already existed)
        }
    }
};

If you only need the string representation to access it (but not for printing etc) you can consider to use an enum as key instead. At least I'd define some constants like const std::string some_variable{"some_variable"}, to avoid typos going unnoticed (perhaps the variableNames is supposed to be const (and static?)).

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • Thanks for the answer. Since I am ultimately bound by ROS to the Struct, I guess I will have to hardcode the part. – Tillman Feb 05 '21 at 10:58
  • @Tillman you say they are generated from a config file, cant you generate them as maps? In your code (and in mine) the mapping between names and variables is done in `Example` but it could be done in `MsgFile` as well – 463035818_is_not_an_ai Feb 05 '21 at 10:59
1

As far as I know there is no standard way to do this, I would choose another way to store the data ( I mean not in struct ), but if you are adamant here is an answered question: Get list of C structure members

Bandi
  • 66
  • 4
  • 1
    Thanks for the answer. Since I am ultimately bound by ROS to the Struct, I guess I will have to hardcode the part – Tillman Feb 05 '21 at 10:58