Advanced usage of the package

This short example points out the interfaces of the StableRLS class.

[1]:
# this contains the environment class
import stablerls.gymFMU as gymFMU
# this will read our config file
import stablerls.configreader as cfg_reader

import gymnasium as gym
import numpy as np
import logging
[2]:
class my_env(gymFMU.StableRLS):
    def get_action_space(self):
        """My custom action space"""
        # derive the shape of this space from the FMU we can also define it on our own
        # we can do the same for the "get_observation_space" but have to derive the
        # shape from self.fmu.ouput
        high = np.arange(len(self.fmu.input)).astype(np.float32)
        high[:] = np.inf
        low = high[:] * 0
        return gym.spaces.Box(low, high)

    def reset_(self, seed=None):
        """My custom reset function called during each reset"""
        # normally we get the first observation by calling
        # self._next_observation(steps=1)
        # in this case we will define it hard coded and dont set all inputs to zero,
        # which is the default behavior
        first_observation = 5
        return first_observation

    def obs_processing(self, observation):
        """If we dont want to train the agent with all observations, we can modify them"""
        return 2

    def FMU_external_input(self):
        """We can set specific inputs of the FMU independent of the agent"""
        self.fmu.fmu.setReal([self.fmu.input[0].valueReference], [4])

    def export_results(self):
        """This function is not called by default but allows access to save the internal results"""
        pass

For simplicity we already included the compiled FMU models for Linux and Windows. However, if you own Matlab you can compile the *.slx models on your own. If you want to compile the model you can keep the default FMU_path in the config file. Otherwise please change it to 00-Simulink_Windows.fmu or 00-Simulink_Linux.fmu depending on your operating system.

[3]:
# First of all we have to read the config file
config = cfg_reader.configreader('00-config.cfg')

# if we want to we can compile the simulink model.
# Matlab and Matlab Engine for python is required!
if False:
    import stablerls.createFMU as createFMU
    createFMU.createFMU(config,'SimulinkExample00.slx')

The FMU is available now and we run our custom class

[4]:
# create instance of the model
env = my_env(config)

# default reset call bevor the simulation starts now returns 5
obs = env.reset()
print('We can see our first observation:', obs)

# we wont change the action
action = np.array([1,2,3,4])

terminated = False
truncated = False
# Now we always observe 2 as specified
while not (terminated or truncated):
    observation, reward, terminated, truncated, info  = env.step(action)
    print(f'Action: {action}\nObservation: {observation}\nReward: {reward}\n')
    action = action * 2

env.close()
We can see our first observation: 5
Action: [1 2 3 4]
Observation: 2
Reward: 1

Action: [2 4 6 8]
Observation: 2
Reward: 1

Action: [ 4  8 12 16]
Observation: 2
Reward: 1

We can also see that the first action is now always equal to 4 and therefore independent of the agents actions.

[5]:
env.inputs
[5]:
array([[ 4.,  2.,  3.,  4.],
       [ 4.,  4.,  6.,  8.],
       [ 4.,  8., 12., 16.]])
[ ]: