-
Notifications
You must be signed in to change notification settings - Fork 0
/
AnsysScriptDataConnector.py
317 lines (229 loc) · 9.09 KB
/
AnsysScriptDataConnector.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
#Used to connect to Ansys
import random
import socket
import struct
import time
import sys
import platform
#Used to load the model and launch the simualtion
import os
from pyaedt import TwinBuilder
from pyaedt import generate_unique_project_name
#Used by Bonsai
import logging
import time
import threading
import mathutils
from typing import NamedTuple, Dict, Any
from datetime import datetime
import queue
#import imageio
#from skimage.transform import rescale, resize, downscale_local_mean
#import cv2
from microsoft_bonsai_api.simulator.client import BonsaiClient, BonsaiClientConfig
from microsoft_bonsai_api.simulator.generated.models import SimulatorInterface, SimulatorState, SimulatorSessionResponse
# Define host and port where the DataConnector socket is listening
host = '127.0.0.1'
port = int(5010)
comm_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
comm_socket.settimeout(10)
#Set logging
#log = logging.getLogger("ansys_simulator")
log = logging.getLogger()
log.setLevel(logging.INFO)
#Set Bonsai
workspace = os.getenv("SIM_WORKSPACE")
accesskey = os.getenv("SIM_ACCESS_KEY")
print('workspace is: ', workspace)
config_client = BonsaiClientConfig()
client = BonsaiClient(config_client)
registration_info = SimulatorInterface(
name="Ansys",
timeout=60,
simulator_context=config_client.simulator_context,
description=None,
)
registered_session: SimulatorSessionResponse = client.session.create(workspace_name=config_client.workspace, body=registration_info)
print(f"Registered simulator. {registered_session.session_id}")
#>>> platform.system()
#Linux Darwin(MacOS) Windows
if platform.system() == 'Linux':
log.info("Using Linux path")
SAVE_DIR = '/home/nicolas/Workspace/ml/logs/Ansys' #Ubuntu
elif platform.system() == 'Darwin':
log.info("Using MacOS path")
SAVE_DIR = '/Users/nicolas/Workspace/ml/logs/Ansys' #MacOS
else:
log.info("Using Windows path")
SAVE_DIR = 'C:/Users/nmaquaire/Workspace/ml/logs/Ansys' #Windows
#Global parameters
run_thread = True
class SimulatorModel:
def __init__(self, q_2ansys, q_2bonsai ):
global host, port, comm_socket
self.q_2ansys = q_2ansys
self.q_2bonsai = q_2bonsai
def reset(self, config) -> Dict[str, Any]:
# Raise the Ansys timeout
log.info("\n\nSleep to timeout TR")
time.sleep(6)
# Put message in q_2ansys to ask Ansys to reset
log.info("\nq_2ansys - Put Reset_Ansys")
msg2Ansys = ('Relaunch', 'Relaunch Analyze TR')
self.q_2ansys.put(msg2Ansys)
self.q_2ansys.join()
# Get message from q_2bonsai to set returned states
#log.info("q_2bonsai - Get Reset_Bonsai")
#msgFromAnsys = self.q_2bonsai.get()
#log.info(f'{"msgFromAnsys is: {} ".format(msgFromAnsys)}')
log.info("Set new states")
states = [2.2, 0, 0]
#self.q_2bonsai.task_done()
# Wait for TR to initialize
log.info("\n\nSleep to let TR launch")
time.sleep(3)
# Connects to the socket
log.info("\n\nConnects to the socket")
try:
comm_socket.connect((host, port))
except ConnectionRefusedError:
print('Could not find socket to connect. Make sure the simulation is in the Initialize state, and that the localhost and port number are correct')
sys.exit(-1)
# return states
returned_dict = self._gym_to_state(states, 0.0, False)
return returned_dict
def step(self, action) -> Dict[str, Any]:
log.info(f'{"step with action: {} ".format(action)}')
# Put message in q_2ansys to ask Ansys to do a step
log.info("\n\nStep_Ansys")
step_reward = 0
done = False
truncated = False
info = {}
val1, val2, val3 = random.random(), random.random(), random.random()
print('Step - Sent to Twin Builder: {},{},{}'.format(val1, val2, val3))
# Data sent through the socket needs to be in binary format
# '!dd' format indicates that 2 double-values will be packed
# into binary form using network byte order
packet = struct.pack('!ddd', val1, val2, val3)
# data.encode()
#packet = struct.pack('!dd', val1)
try:
comm_socket.sendall(packet)
# '24' indicates that three 8-byte values will return from the simulatiom
packet = comm_socket.recv(24)
except ConnectionAbortedError as e:
print('Data socket connection lost. Shutting down...')
sys.exit(-1)
sim_data = struct.unpack('!ddd', packet)
print('Received from Twin Builder: {}'.format(sim_data))
new_state = [sim_data[0], sim_data[1], sim_data[2]]
print('Step new_state', new_state)
#step_reward = dataAnsys['step_reward']
#done = dataAnsys['done']
returned_dict = self._gym_to_state(new_state, step_reward, done)
return returned_dict
def _gym_to_state(self, new_state, step_reward, done ):
dict_state = {
"fromDataConnector1": float(new_state[0]),
"fromDataConnector2": float(new_state[1]),
"fromDataConnector3": float(new_state[2]),
"_gym_reward": float(step_reward),
"_gym_terminal": float(done)
}
return dict_state
def thread_simulate(q_2ansys, q_2bonsai):
global run_thread
sequence_id = 1
sim_model = SimulatorModel(q_2ansys, q_2bonsai)
sim_model_state = { 'sim_halted': False }
#Wait for Ansys to start Analyze
time.sleep(1)
'''
try:
config = {'h':2.2}
print('Reset')
_ = sim_model.reset(config)
time.sleep(1)
print('Step0')
sim_model.step(0)
time.sleep(1)
print('Step1')
sim_model.step(0)
time.sleep(1)
print('Step2')
sim_model.step(0)
time.sleep(1)
'''
try:
while run_thread:
sim_state = SimulatorState(sequence_id=sequence_id, state=sim_model_state, halted=sim_model_state.get('sim_halted', False))
if sequence_id % 100 == 0: print('sim_state:', sim_state)
event = client.session.advance(
workspace_name=config_client.workspace,
session_id=registered_session.session_id,
body=sim_state,
)
sequence_id = event.sequence_id
if event.type == "Idle":
time.sleep(event.idle.callback_time)
elif event.type == "EpisodeStart":
sim_model_state = sim_model.reset(event.episode_start.config)
elif event.type == "EpisodeStep":
sim_model_state = sim_model.step(event.episode_step.action)
elif event.type == "EpisodeFinish":
sim_model_state = { 'sim_halted': False }
elif event.type == "Unregister":
log.info(f'{"Simulator Session unregistered by platform because {} ".format(event.unregister.details)}')
return
except BaseException as err:
client.session.delete(workspace_name=config_client.workspace, session_id=registered_session.session_id)
log.info(f'{"Unregistered simulator because {} ".format(err)}')
def _initScene(tb):
try:
tb.close_project(save_project=False)
tb.load_project('C:/Users/nmaquaire/Workspace/Ansys/Projects/PumpingSystem.aedt', design_name='PumpingDesign')
except BaseException as err:
print('Error loading the Twin Builder project...')
if __name__ == '__main__':
now = datetime.utcnow().strftime("%Y%m%d%H%M%S")
# Instantiate the Queue object to manage all actions on BPY
q_2ansys = queue.Queue()
q_2bonsai = queue.Queue()
simulation_samples_index = 0
truncated = False
done =False
episode_reward = 0
# prepare Twin Builder
desktop_version = "2022.2"
non_graphical = os.getenv("PYAEDT_NON_GRAPHICAL", "False").lower() in ("true", "1", "t")
new_thread = True
log.info("Twin Builder starting")
tb = TwinBuilder(specified_version=desktop_version, non_graphical=False, new_desktop_session=new_thread)
_initScene(tb)
#Start connection with Bonsai
log.info("Thread simulate starting")
threadSimulate = threading.Thread(target=thread_simulate, args=(q_2ansys,q_2bonsai,))
threadSimulate.start()
tb.analyze_setup('TR')
try:
while run_thread:
if q_2ansys.empty() is False:
log.info("\n\nq_2ansys - Get msgFromBonsai")
msgFromBonsai = q_2ansys.get()
log.info(f'{"q_2ansys - msgFromBonsai is: {} ".format(msgFromBonsai)}')
if msgFromBonsai[0] == 'Relaunch':
log.info("Relaunch TR")
q_2ansys.task_done()
tb.analyze_setup('TR')
except KeyboardInterrupt:
run_thread = False
comm_socket.close()
tb.release_desktop()
print('Process interupted')
exit()
raise
run_thread = False
tb.release_desktop()
comm_socket.close()
exit()