def test_coordinate_system_manager_with_data(copy_arrays, lazy_load): """Test if data attached to a CSM is stored and read correctly.""" csm = tf.CoordinateSystemManager("root", "csm") csm.create_cs("cs_1", "root", coordinates=[1, 1, 1]) csm.create_cs("cs_2", "root", coordinates=[-1, -1, -1]) csm.create_cs("cs_11", "cs_1", coordinates=[1, 1, 1]) data_11 = SpatialData( coordinates=np.array([[1.0, 2.0, 3.0], [3.0, 2.0, 1.0]])) data_2 = SpatialData( coordinates=np.array([ [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [0.0, 1.0, 0.0], ]), triangles=np.array([[0, 1, 2], [0, 2, 3]], dtype="uint32"), ) csm.assign_data(data_11, "data_11", "cs_11") csm.assign_data(data_2, "data_2", "cs_2") tree = {"csm": csm} buffer = write_read_buffer(tree, open_kwargs={ "copy_arrays": copy_arrays, "lazy_load": lazy_load }) csm_buffer = buffer["csm"] for data_name in csm.data_names: sd = csm.get_data(data_name) sd_buffer = csm_buffer.get_data(data_name) assert sd == sd_buffer
def test_coordinate_system_manager_time_dependencies(copy_arrays, lazy_load, csm_time_ref): """Test serialization of time components from CSM and its attached LCS.""" lcs_tdp_1_time_ref = None if csm_time_ref is None: lcs_tdp_1_time_ref = pd.Timestamp("2000-03-17") lcs_tdp_1 = tf.LocalCoordinateSystem( coordinates=[[1, 2, 3], [4, 5, 6]], time=pd.TimedeltaIndex([1, 2], "D"), time_ref=lcs_tdp_1_time_ref, ) lcs_tdp_2 = tf.LocalCoordinateSystem( coordinates=[[3, 7, 3], [9, 5, 8]], time=pd.TimedeltaIndex([1, 2], "D"), time_ref=pd.Timestamp("2000-03-21"), ) csm_root = tf.CoordinateSystemManager("root", "csm_root", csm_time_ref) csm_root.add_cs("cs_1", "root", lcs_tdp_2) csm_sub_1 = tf.CoordinateSystemManager("cs_2", "csm_sub_1", csm_time_ref) csm_sub_1.add_cs("cs_1", "cs_2", lcs_tdp_2) csm_sub_1.add_cs("cs_3", "cs_2", lcs_tdp_1) csm_sub_2 = tf.CoordinateSystemManager("cs_4", "csm_sub_2") csm_sub_2.create_cs("cs_1", "cs_4") csm_root.merge(csm_sub_1) csm_root.merge(csm_sub_2) tree = {"cs_hierarchy": csm_root} data = write_read_buffer(tree, open_kwargs={ "copy_arrays": copy_arrays, "lazy_load": lazy_load }) csm_file = data["cs_hierarchy"] assert csm_root == csm_file
def get_example_coordinate_system_manager(): """Get a consistent CoordinateSystemManager instance for test purposes.""" csm = tf.CoordinateSystemManager("root") csm.create_cs("lcs_01", "root", coordinates=[1, 2, 3]) csm.create_cs( "lcs_02", "root", orientation=WXRotation.from_euler("z", np.pi / 3).as_matrix(), coordinates=[4, -7, 8], ) csm.create_cs( "lcs_03", "lcs_02", orientation=WXRotation.from_euler("y", np.pi / 11), coordinates=[4, -7, 8], ) return csm
def get_coordinate_system_manager_with_subsystems(nested: bool): lcs = [ tf.LocalCoordinateSystem(coordinates=[i, -i, -i]) for i in range(12) ] # create global system csm_global = tf.CoordinateSystemManager("base", "Global System", "2000-06-08") csm_global.add_cs("robot", "base", lcs[0]) csm_global.add_cs("specimen", "base", lcs[1]) # robot system csm_robot = tf.CoordinateSystemManager("robot", "Robot system") csm_robot.add_cs("head", "robot", lcs[2]) # robot head system csm_head = tf.CoordinateSystemManager("head", "Head system") csm_head.add_cs("torch tcp", "head", lcs[3]) csm_head.add_cs("camera tcp", "head", lcs[4], lsc_child_in_parent=False) csm_head.add_cs("scanner 1 tcp", "head", lcs[5]) csm_head.add_cs("scanner 2 tcp", "head", lcs[6]) # scanner system 1 csm_scanner_1 = tf.CoordinateSystemManager("scanner 1", "Scanner 1 system") csm_scanner_1.add_cs("scanner 1 tcp", "scanner 1", lcs[7]) # scanner system 2 csm_scanner_2 = tf.CoordinateSystemManager("scanner 2", "Scanner 2 system") csm_scanner_2.add_cs("scanner 2 tcp", "scanner 2", lcs[8]) # specimen system csm_specimen = tf.CoordinateSystemManager("specimen", "Specimen system") csm_specimen.add_cs("thermocouple 1", "specimen", lcs[9]) csm_specimen.add_cs("thermocouple 2", "specimen", lcs[10]) csm_specimen.add_cs("thermocouple 3", "thermocouple 2", lcs[11]) if nested: csm_head.merge(csm_scanner_1) csm_head.merge(csm_scanner_2) csm_robot.merge(csm_head) csm_global.merge(csm_robot) csm_global.merge(csm_specimen) else: csm_global.merge(csm_specimen) csm_global.merge(csm_robot) csm_global.merge(csm_head) csm_global.merge(csm_scanner_1) csm_global.merge(csm_scanner_2) return csm_global
def single_pass_weld_example( out_file: Optional[Union[str, BytesIO]] = "single_pass_weld_example.asdf", ) -> Optional[tuple[BytesIO, dict]]: """Create ASDF file containing all required fields of the single_pass_weld schema. Parameters ---------- out_file : destination file, if None returns a BytesIO buffer. Returns ------- buff, tree When writing to memory, return the buffer and the tree (as dictionary). """ # Imports import asdf import numpy as np import pandas as pd from asdf.tags.core import Software import weldx.geometry as geo import weldx.measurement as msm # importing the weldx package with prevalent default abbreviations import weldx.transformations as tf from weldx.asdf.util import get_schema_path, write_buffer, write_read_buffer from weldx.constants import META_ATTR, Q_ from weldx.core import MathematicalExpression, TimeSeries from weldx.tags.aws.process.gas_component import GasComponent from weldx.tags.aws.process.shielding_gas_for_procedure import ( ShieldingGasForProcedure, ) from weldx.tags.aws.process.shielding_gas_type import ShieldingGasType from weldx.tags.processes.process import GmawProcess from weldx.transformations.local_cs import LocalCoordinateSystem as lcs from weldx.transformations.rotation import WXRotation from weldx.welding.groove.iso_9692_1 import get_groove from weldx.welding.util import sine # Timestamp reference_timestamp = pd.Timestamp("2020-11-09 12:00:00") # Geometry # groove + trace = geometry groove = get_groove( groove_type="VGroove", workpiece_thickness=Q_(5, "mm"), groove_angle=Q_(50, "deg"), root_face=Q_(1, "mm"), root_gap=Q_(1, "mm"), ) # define the weld seam length in mm seam_length = Q_(300, "mm") # create a linear trace segment a the complete weld seam trace trace_segment = geo.LinearHorizontalTraceSegment(seam_length) trace = geo.Trace(trace_segment) geometry = dict(groove_shape=groove, seam_length=seam_length) base_metal = dict(common_name="S355J2+N", standard="DIN EN 10225-2:2011") workpiece = dict(base_metal=base_metal, geometry=geometry) # Setup the Coordinate System Manager (CSM) # crete a new coordinate system manager with default base coordinate system csm = tf.CoordinateSystemManager("base") # add the workpiece coordinate system csm.add_cs( coordinate_system_name="workpiece", reference_system_name="base", lcs=trace.coordinate_system, ) tcp_start_point = Q_([5.0, 0.0, 2.0], "mm") tcp_end_point = Q_([-5.0, 0.0, 2.0], "mm") + np.append( seam_length, Q_([0, 0], "mm")) v_weld = Q_(10, "mm/s") s_weld = (tcp_end_point - tcp_start_point)[0] # length of the weld t_weld = s_weld / v_weld t_start = pd.Timedelta("0s") t_end = pd.Timedelta(str(t_weld.to_base_units())) rot = WXRotation.from_euler(seq="x", angles=180, degrees=True) coords = [tcp_start_point.magnitude, tcp_end_point.magnitude] tcp_wire = lcs(coordinates=coords, orientation=rot, time=[t_start, t_end]) # add the workpiece coordinate system csm.add_cs( coordinate_system_name="tcp_wire", reference_system_name="workpiece", lcs=tcp_wire, ) tcp_contact = lcs(coordinates=[0, 0, -10]) # add the workpiece coordinate system csm.add_cs( coordinate_system_name="tcp_contact", reference_system_name="tcp_wire", lcs=tcp_contact, ) TCP_reference = csm.get_cs("tcp_contact", "workpiece") # Measurements # time time = pd.timedelta_range(start="0s", end="10s", freq="2s") # current data I_ts = sine(f=Q_(10, "1/s"), amp=Q_(20, "A"), bias=Q_(300, "A")) current_data = TimeSeries(I_ts.interp_time(time).data, time) # voltage data U_ts = sine(f=Q_(10, "1/s"), amp=Q_(3, "V"), bias=Q_(40, "V"), phase=Q_(0.1, "rad")) voltage_data = TimeSeries(U_ts.interp_time(time).data, time) # define current source and transformations src_current = msm.SignalSource( name="Current Sensor", output_signal=msm.Signal(signal_type="analog", units="V", data=None), error=msm.Error(Q_(0.1, "percent")), ) current_AD_transform = msm.SignalTransformation( name="AD conversion current measurement", error=msm.Error(Q_(0.01, "percent")), func=MathematicalExpression( "a * x + b", dict(a=Q_(32768.0 / 10.0, "1/V"), b=Q_(0.0, ""))), type_transformation="AD", ) current_calib_transform = msm.SignalTransformation( name="Calibration current measurement", error=msm.Error(0.0), func=MathematicalExpression( "a * x + b", dict(a=Q_(1000.0 / 32768.0, "A"), b=Q_(0.0, "A"))), ) # define voltage source and transformations src_voltage = msm.SignalSource( name="Voltage Sensor", output_signal=msm.Signal("analog", "V", data=None), error=msm.Error(Q_(0.1, "percent")), ) voltage_AD_transform = msm.SignalTransformation( name="AD conversion voltage measurement", error=msm.Error(Q_(0.01, "percent")), func=MathematicalExpression( "a * x + b", dict(a=Q_(32768.0 / 10.0, "1/V"), b=Q_(0.0, ""))), type_transformation="AD", ) voltage_calib_transform = msm.SignalTransformation( name="Calibration voltage measurement", error=msm.Error(0.0), func=MathematicalExpression( "a * x + b", dict(a=Q_(100.0 / 32768.0, "V"), b=Q_(0.0, "V"))), ) # Define lab equipment HKS_sensor = msm.MeasurementEquipment( name="HKS P1000-S3", sources=[src_current, src_voltage], ) BH_ELM = msm.MeasurementEquipment( name="Beckhoff ELM3002-0000", transformations=[current_AD_transform, voltage_AD_transform], ) twincat_scope = Software(name="Beckhoff TwinCAT ScopeView", version="3.4.3143") setattr(current_calib_transform, META_ATTR, dict(software=twincat_scope)) setattr(voltage_calib_transform, META_ATTR, dict(software=twincat_scope)) # Define current measurement chain welding_current_chain = msm.MeasurementChain.from_equipment( name="welding current measurement chain", equipment=HKS_sensor, source_name="Current Sensor", ) welding_current_chain.add_transformation_from_equipment( equipment=BH_ELM, transformation_name="AD conversion current measurement", ) welding_current_chain.add_transformation( transformation=current_calib_transform, data=current_data, ) # Define voltage measurement chain welding_voltage_chain = msm.MeasurementChain.from_equipment( name="welding voltage measurement chain", equipment=HKS_sensor, source_name="Voltage Sensor", ) welding_voltage_chain.add_transformation_from_equipment( equipment=BH_ELM, transformation_name="AD conversion voltage measurement", ) welding_voltage_chain.add_transformation( transformation=voltage_calib_transform, data=voltage_data, ) # Define measurements welding_current = msm.Measurement( name="welding current measurement", data=[current_data], measurement_chain=welding_current_chain, ) welding_voltage = msm.Measurement( name="welding voltage measurement", data=[voltage_data], measurement_chain=welding_voltage_chain, ) # GMAW Process params_pulse = dict( wire_feedrate=Q_(10.0, "m/min"), pulse_voltage=Q_(40.0, "V"), pulse_duration=Q_(5.0, "ms"), pulse_frequency=Q_(100.0, "Hz"), base_current=Q_(60.0, "A"), ) process_pulse = GmawProcess( "pulse", "CLOOS", "Quinto", params_pulse, tag="CLOOS/pulse", meta={"modulation": "UI"}, ) gas_comp = [ GasComponent("argon", Q_(82, "percent")), GasComponent("carbon dioxide", Q_(18, "percent")), ] gas_type = ShieldingGasType(gas_component=gas_comp, common_name="SG") gas_for_procedure = ShieldingGasForProcedure( use_torch_shielding_gas=True, torch_shielding_gas=gas_type, torch_shielding_gas_flowrate=Q_(20, "l / min"), ) process = dict( welding_process=process_pulse, shielding_gas=gas_for_procedure, weld_speed=TimeSeries(v_weld), welding_wire={"diameter": Q_(1.2, "mm")}, ) # ASDF file tree = dict( reference_timestamp=reference_timestamp, equipment=[HKS_sensor, BH_ELM], measurements=[welding_current, welding_voltage], welding_current=welding_current_chain.get_signal( "Calibration current measurement").data, welding_voltage=welding_voltage_chain.get_signal( "Calibration voltage measurement").data, coordinate_systems=csm, TCP=TCP_reference, workpiece=workpiece, process=process, ) tree[META_ATTR] = {"welder": "A.W. Elder"} model_path = get_schema_path("single_pass_weld-0.1.0.yaml") # pre-validate? write_read_buffer( tree, asdffile_kwargs=dict(custom_schema=str(model_path)), ) if out_file: with asdf.AsdfFile( tree, custom_schema=str(model_path), ) as ff: ff.write_to(out_file, all_array_storage="inline") else: return ( write_buffer( tree, asdffile_kwargs=dict(custom_schema=str(model_path)), write_kwargs=dict(all_array_storage="inline"), ), tree, )