Coverage for examples/controller/pid_with_simulator.py: 79%

39 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2025-10-30 13:39 +0000

1"""A typical example for how to use the AgentLib, requiring only the basic dependencies. 

2 

3This example will teach you about: 

41. Pre-implemented Modules: Simulator, PID, local communicator 

52. How to write a simple dependency free model 

63. How to use the alias of variables to facilitate communication between agents 

74. How to run agents without the LocalMAS utility 

85. How to log and plot the state of an agent using the agentlogger 

9 

10""" 

11 

12import logging 

13from typing import List 

14 

15import agentlib as ag 

16 

17 

18class HeatedRoomConfig(ag.ModelConfig): 

19 inputs: List[ag.ModelInput] = [ 

20 ag.ModelInput(name="heating_power_in_watt", value=100) 

21 ] 

22 states: List[ag.ModelState] = [ 

23 ag.ModelState(name="temperature_in_celsius", value=20) 

24 ] 

25 parameters: List[ag.ModelParameter] = [ 

26 ag.ModelParameter(name="heat_loss_in_watt", value=150), 

27 ag.ModelParameter(name="thermal_capacity_zone", value=100_000), 

28 ] 

29 

30 

31class HeatedRoom(ag.Model): 

32 config: HeatedRoomConfig 

33 

34 def initialize(self, **kwargs): 

35 pass 

36 

37 def do_step(self, *, t_start, t_sample): 

38 t = self.get("temperature_in_celsius").value 

39 power = self.get("heating_power_in_watt").value 

40 loss = self.get("heat_loss_in_watt").value 

41 capacity = self.get("thermal_capacity_zone").value 

42 t = t + ((power - loss) / capacity) * t_sample 

43 self.set("temperature_in_celsius", t) 

44 

45 

46pid_agent_config = { 

47 "id": "PID", 

48 "modules": [ 

49 { 

50 "module_id": "myPid", 

51 "type": "pid", 

52 "setpoint": 21, 

53 "Kp": 1000, 

54 "Ti": 10, 

55 "lb": 0, 

56 "ub": 500, 

57 "input": {"name": "u", "value": 0, "alias": "room_temp"}, 

58 "output": { 

59 "name": "y", 

60 "value": 0, 

61 "alias": "heating_power", 

62 "shared": True, 

63 }, 

64 }, 

65 {"module_id": "myLogger", "type": "AgentLogger"}, 

66 {"module_id": "myComm", "type": "local", "subscriptions": ["Process"]}, 

67 ], 

68} 

69 

70process_agent_config = { 

71 "id": "Process", 

72 "modules": [ 

73 { 

74 "module_id": "sim", 

75 "type": "simulator", 

76 "model": {"type": {"file": __file__, "class_name": "HeatedRoom"}}, 

77 "t_sample": 10, 

78 "inputs": [ 

79 {"name": "heating_power_in_watt", "value": 0, "alias": "heating_power"} 

80 ], 

81 "states": [ 

82 { 

83 "name": "temperature_in_celsius", 

84 "value": 21, 

85 "shared": True, 

86 "alias": "room_temp", 

87 } 

88 ], 

89 }, 

90 {"module_id": "myLogger", "type": "AgentLogger"}, 

91 {"module_id": "myComm", "type": "local", "subscriptions": ["PID"]}, 

92 ], 

93} 

94 

95 

96def run_example(with_plots=True, log_level=logging.INFO): 

97 # Set the log-level 

98 logging.basicConfig(level=log_level) 

99 

100 env_config = {"rt": False, "factor": 0.01, "clock": True, "t_sample": 60} 

101 env = ag.Environment(config=env_config) 

102 pid_agent = ag.Agent(config=pid_agent_config, env=env) 

103 process_agent = ag.Agent(config=process_agent_config, env=env) 

104 env.run(until=1000) 

105 

106 results = process_agent.get_results() 

107 res = results["myLogger"] 

108 if with_plots: 

109 import matplotlib.pyplot as plt 

110 

111 fig, ax = plt.subplots(2, 1) 

112 res["room_temp"].plot(ax=ax[0], label="$T_{room}$") 

113 ax[0].axhline(21, label="$T_{room, set}$", linestyle="--", color="black") 

114 res["heating_power"].plot(ax=ax[1], label="$\dot{Q}_{heat}$") 

115 ax[0].legend() 

116 ax[1].legend() 

117 plt.show() 

118 return {"PID_1": results} 

119 

120 

121if __name__ == "__main__": 

122 run_example(log_level="INFO")