hopsan icon indicating copy to clipboard operation
hopsan copied to clipboard

Labview export doesnt support subsystems

Open yuvalk1 opened this issue 3 years ago • 4 comments

Exporting to labview/sit doesnt include the subsystem components in the generated code, and hopsanrt-wrapper.h has no support for adding components in subsystems, connecting components in subsystems, setting parameters in subsystems and adding system ports..

yuvalk1 avatar Aug 07 '22 09:08 yuvalk1

I have made some changes to hopsanrt-wrapper.h and the generated file that seems to be working, at least for level 1 subsystems. I believe it could be easily modified to support nested subsystems.

added functions to hopsanrt-wrapper.h:

void addComponentToSubSystem(string systemName, string name, string type)
{
    hopsan::ComponentSystem* system = spCoreComponentSystem->getSubComponentSystem(systemName.c_str());
    hopsan::Component* pCoreComponent;
    pCoreComponent = gHopsanCore.createComponent(type.c_str());
    system->addComponent(pCoreComponent);
    pCoreComponent->setName(name.c_str());
    sComponentNames.push_back(name);
}
void addSubSystemPort(string systemName, string portName) {
    hopsan::ComponentSystem* system = spCoreComponentSystem->getSubComponentSystem(systemName.c_str());
    system->addSystemPort(portName.c_str());
    //spCoreComponentSystem->
}
bool connectInSubSystem(string systemName, string comp1, string port1, string comp2, string port2)
{
    hopsan::ComponentSystem* system = spCoreComponentSystem->getSubComponentSystem(systemName.c_str());
    return system->connect(comp1.c_str(), port1.c_str(), comp2.c_str(), port2.c_str());
}
void setParameterInSubSystem(string subSystemName, string compname, string parname, double value)
{
    std::stringstream ss;
    ss << value;
    hopsan::ComponentSystem* system = spCoreComponentSystem->getSubComponentSystem(subSystemName.c_str());
    system->getSubComponentOrThisIfSysPort(compname.c_str())->setParameterValue(parname.c_str(), ss.str().c_str());

}

A modified USER_Initialize function with a single subsystem that works with the wrapper above:

long USER_Initialize() 
{
    createSystem(1e-3);

    addComponent("C_type_Voltage_Source", "ElectricUsource");
    addComponent("Input_Interface_Component", "SignalInputInterface");
    addComponent("Output_Interface_Component", "SignalOutputInterface");
    addComponent("Q_type_Ground", "ElectricGround");
    addComponent("Subsystem", "Subsystem");


    addComponentToSubSystem("Subsystem", "Current_Sensor", "ElectricIsensor");
    addComponentToSubSystem("Subsystem", "Q_Type_Inductance", "ElectricInductance");

    addSubSystemPort("Subsystem", "SystemPort");
    addSubSystemPort("Subsystem", "SystemPort_1");
    addSubSystemPort("Subsystem", "SystemPort_2");

    connectInSubSystem("Subsystem", "Current_Sensor", "Pel1", "Q_Type_Inductance", "Pel2");
    connectInSubSystem("Subsystem", "Current_Sensor", "Piout", "SystemPort_1", "SystemPort_1");
    connectInSubSystem("Subsystem", "Q_Type_Inductance", "Pel1", "SystemPort", "SystemPort");
    connectInSubSystem("Subsystem", "Q_Type_Inductance", "Pel2", "SystemPort_2", "SystemPort_2");

    connect("C_type_Voltage_Source", "Pel1", "Subsystem", "SystemPort");
    connect("Output_Interface_Component", "in", "Subsystem", "SystemPort_1");
    connect("Q_type_Ground", "Pel1", "Subsystem", "SystemPort_2");

    

    setParameter("C_type_Voltage_Source", "Pel1#Voltage", 0);
    setParameter("C_type_Voltage_Source", "Pel1#Current", 0);
    setParameter("C_type_Voltage_Source", "Pel1#WaveVariable", 0);
    setParameter("C_type_Voltage_Source", "Pel1#CharImpedance", 0);
    setParameter("C_type_Voltage_Source", "uin#Value", 1200);
    setParameter("Output_Interface_Component", "in#Value", 0);
    setParameter("Q_type_Ground", "Pel1#Voltage", 0);
    setParameter("Q_type_Ground", "Pel1#Current", 0);
    setParameter("Q_type_Ground", "Pel1#WaveVariable", 0);
    setParameter("Q_type_Ground", "Pel1#CharImpedance", 0);

    setParameterInSubSystem("Subsystem", "Current_Sensor", "Pel1#Voltage", 0);
    setParameterInSubSystem("Subsystem", "Current_Sensor", "Pel1#Current", 0);
    setParameterInSubSystem("Subsystem", "Current_Sensor", "Pel1#WaveVariable", 0);
    setParameterInSubSystem("Subsystem", "Current_Sensor", "Pel1#CharImpedance", 0);
    setParameterInSubSystem("Subsystem", "Q_Type_Inductance", "Induct#Value", 0.1);

    initSystem();
    rtSignal.Time = 0;

    return NI_OK;
}

yuvalk1 avatar Aug 07 '22 09:08 yuvalk1

Confirmed. I like your suggestions, but I think we should keep the number of functions to a minimum. The best solution is probably to add an optional subsystem argument at the end in addComponent():

addComponent("C_type_Voltage_Source", "ElectricUsource");
addComponent("Input_Interface_Component", "SignalInputInterface");
addComponent("Output_Interface_Component", "SignalOutputInterface");
addComponent("Q_type_Ground", "ElectricGround");
addComponent("Subsystem", "Subsystem");
addComponent("Subsystem", "Current_Sensor", "ElectricIsensor", "Subsystem");
addComponentToSubSystem("Subsystem", "Q_Type_Inductance", "ElectricInductance", "Subsystem");

The last argument could then support multiple level of subsystems with a separator character, e.g. "Subsystem1|Subsystem2|Subsystem3". The same principle should work for connect() and setParameter(). We still also need to add the addSubSystemPort() I think.

robbr48 avatar Aug 11 '22 12:08 robbr48

@robbr48 Do you still have access to Labview to test and implement this?

peterNordin avatar Aug 16 '22 20:08 peterNordin

Not on my computer, but I believe it is still installed in some computer in the lab. A better solution might be to harmonize this code with the one used for FMI or S-functions. It still requires testing for all targets though.

robbr48 avatar Aug 17 '22 06:08 robbr48