pickleCopyMbs.py

You can view and download this file on Github: pickleCopyMbs.py

  1#%%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2# This is an EXUDYN example
  3#
  4# Details:  Two rigid bodies, where the first body moves on a straight rail (fixed on ground) and the second is mounted with a revolute joint on the first body;
  5#           the particular reason for this test example is the copying of the model as well as load save;
  6#           shows reading and writing mbs with dictionaries and export by HDF5 files
  7#
  8# Author:   Johannes Gerstmayr
  9# Date:     2024-10-13
 10#
 11# Copyright:This file is part of Exudyn. Exudyn is free software. You can redistribute it and/or modify it under the terms of the Exudyn license. See 'LICENSE.txt' for more details.
 12#
 13#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 14
 15import exudyn as exu
 16from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities
 17import numpy as np
 18import exudyn.graphics as graphics
 19from math import sin, cos
 20import copy 
 21
 22testIsActive = exu.sys.get('testIsActive', False)
 23
 24
 25SC = exu.SystemContainer()
 26mbs = SC.AddSystem()
 27
 28
 29#%%+++++++++++++++++++++++++++++++++++
 30L = 0.5
 31w = 0.05
 32ground = mbs.CreateGround(graphicsDataList=[graphics.CheckerBoard(point=[0,0,-0.1*L], size=10)])
 33
 34b0size = [0.5*L,L,0.2*L]
 35p0 = np.array([0.5,1,0])
 36b0 = mbs.CreateRigidBody(referencePosition=p0,
 37                         initialVelocity=[0,1,0],
 38                         inertia=InertiaCuboid(500, b0size),
 39                         graphicsDataList=[graphics.Brick(size=b0size,
 40                                                          color=graphics.color.dodgerblue)])
 41b1size=[w,L,w]
 42p1 = p0 + [0,0.5*L,0.5*b0size[2]+w]
 43b1 = mbs.CreateRigidBody(referencePosition=p1,
 44                         initialVelocity=[0,1,0],
 45                         initialAngularVelocity=[0,0,4*pi],
 46                         inertia=InertiaCuboid(1000, b1size),
 47                         graphicsDataList=[graphics.Brick(size=b1size,
 48                                                          color=graphics.color.red)])
 49
 50mbs.CreateRevoluteJoint(itemNumbers=[b0,b1],
 51                        position=p1-[0,0.5*L,0.5*w], 
 52                        axis = [0,0,1],
 53                        axisRadius=0.5*w, axisLength=2.2*w)
 54
 55mbs.CreatePrismaticJoint(itemNumbers=[ground,b0],
 56                         position=p0, 
 57                         axis = [0,1,0],
 58                         axisRadius=0.5*w, axisLength=5*L)
 59
 60# UFtorque = 0
 61def UFtorque(mbs, t, loadVector):
 62    f = np.heaviside(t - 1,1)
 63    return [0,0,-f*2*cos(pi*2*t)]
 64
 65load = mbs.CreateTorque(itemNumber=b1, loadVector=[0,0,0],
 66                        loadVectorUserFunction=UFtorque)
 67
 68sPos = mbs.AddSensor(SensorBody(bodyNumber=b0, storeInternal=True, 
 69                                outputVariableType=exu.OutputVariableType.Position))
 70
 71
 72#del mbs
 73
 74#%%+++++++++++++++++++++++++++++++++++
 75#use dictionaries and pickle to load/save MBS
 76import pickle
 77
 78mbsDict = mbs.GetDictionary()
 79
 80#save MUST be done before solving, as solver structures and settings cannot be saved!
 81#erase variables and system variables as they may contain some solver stuff (if solved once)
 82#  that should not / can not be pickled
 83mbsDict['variables'] = {} 
 84mbsDict['systemVariables'] = {}
 85
 86#save mbs data (could also use dill); the files are output of the test, so they go into
 87#exudyn.config.outputDirectory, which the test suite sets per model (#2418)
 88import os
 89from exudyn.basicUtilities import OutputFilePath
 90pickleFileName = OutputFilePath('solution/mbs.pkl', 'pickleCopyMbs')
 91hdf5FileName = OutputFilePath('solution/mbs.h5', 'pickleCopyMbs')
 92os.makedirs(os.path.dirname(pickleFileName), exist_ok=True)
 93
 94with open(pickleFileName, 'wb') as f:
 95    pickle.dump(mbsDict, f) #, pickle.HIGHEST_PROTOCOL)
 96
 97#load mbs data
 98with open(pickleFileName, 'rb') as f:
 99    mbsCopy = pickle.load(f)
100
101SC = exu.SystemContainer()
102mbs2 = SC.AddSystem()
103mbs2.SetDictionary(mbsDict)
104
105#+++++++++++++++++++++++
106
107hasH5py = False
108try:
109    import h5py
110    hasH5py = True
111except ImportError:
112    exu.Print('h5py not available; skipping HDF5 test')
113    
114if hasH5py:
115    from exudyn.advancedUtilities import SaveDictToHDF5, LoadDictFromHDF5
116    #use HDF5 load / save may not work for all cases, as some types are not implemented
117    #save MUST be done before solving, as solver structures and settings cannot be saved!
118    mbsDict = mbs.GetDictionary()
119    mbsDict['variables'] = {} 
120    mbsDict['systemVariables'] = {}
121    SaveDictToHDF5(hdf5FileName, mbsDict) #problems with Python functions as sub-dicts
122    mbsCopy2 = LoadDictFromHDF5(hdf5FileName, globals())
123    # print('loaded_data:\n', mbsCopy2)
124    
125    SC = exu.SystemContainer()
126    mbs2 = SC.AddSystem()
127    mbs2.SetDictionary(mbsCopy)
128
129#%%+++++++++++++++++++++++++++++++++++
130#ALTERNATIVE: work with copy of mbs:
131#we have to create a new Systemcontainer:
132#mbs2 = copy.copy(mbs) #alternative way to directly copy
133# SC = exu.SystemContainer()
134# SC.AppendSystem(mbs2)
135
136mbs2.Assemble()
137
138#check mbs2:
139#print(mbs2)
140
141simulationSettings = exu.SimulationSettings() #takes currently set values or default values
142
143tEnd = 1
144h = 1e-3
145simulationSettings.timeIntegration.numberOfSteps = int(tEnd/h)
146simulationSettings.timeIntegration.endTime = tEnd
147simulationSettings.timeIntegration.verboseMode = 1
148# simulationSettings.timeIntegration.realtime.active = True
149
150simulationSettings.timeIntegration.newton.useModifiedNewton = True
151simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 0.6 #0.6 works well 
152# simulationSettings.show.computationTime = True
153
154simulationSettings.solution.file.information = "rigid body tests"
155SC.visualizationSettings.nodes.defaultSize = 0.05
156SC.visualizationSettings.openGL.multiSampling = 4
157SC.visualizationSettings.openGL.lineWidth = 2
158SC.visualizationSettings.view0.window.renderWindowSize = [2000,1600]
159
160if not testIsActive:
161    SC.renderer.Start()
162    SC.renderer.DoIdleTasks()
163
164mbs2.SolveDynamic(simulationSettings)
165
166if not testIsActive:
167    SC.renderer.DoIdleTasks()
168    SC.renderer.Stop() #safely close rendering window!
169
170
171#+++++++++++++++++++++++++++++++++++++++++++++
172uTotal = 0.1 * sum(mbs2.GetSensorValues(sPos)) #sPos is still the correct index
173exu.Print('uTotal=',uTotal)
174
175exu.sys['testResult'] = uTotal
176#+++++++++++++++++++++++++++++++++++++++++++++