cgse 2024.7.0__py3-none-any.whl → 2025.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- README.md +27 -0
- bump.py +85 -0
- cgse-2025.0.2.dist-info/METADATA +38 -0
- cgse-2025.0.2.dist-info/RECORD +5 -0
- {cgse-2024.7.0.dist-info → cgse-2025.0.2.dist-info}/WHEEL +1 -2
- cgse-2024.7.0.dist-info/COPYING +0 -674
- cgse-2024.7.0.dist-info/COPYING.LESSER +0 -165
- cgse-2024.7.0.dist-info/METADATA +0 -144
- cgse-2024.7.0.dist-info/RECORD +0 -660
- cgse-2024.7.0.dist-info/entry_points.txt +0 -75
- cgse-2024.7.0.dist-info/top_level.txt +0 -2
- egse/__init__.py +0 -12
- egse/__main__.py +0 -32
- egse/aeu/aeu.py +0 -5238
- egse/aeu/aeu_awg.yaml +0 -265
- egse/aeu/aeu_crio.yaml +0 -273
- egse/aeu/aeu_cs.py +0 -627
- egse/aeu/aeu_devif.py +0 -321
- egse/aeu/aeu_main_ui.py +0 -903
- egse/aeu/aeu_metrics.py +0 -131
- egse/aeu/aeu_protocol.py +0 -463
- egse/aeu/aeu_psu.yaml +0 -204
- egse/aeu/aeu_ui.py +0 -873
- egse/aeu/arbdata/FccdRead.arb +0 -2
- egse/aeu/arbdata/FccdRead_min_points.arb +0 -2
- egse/aeu/arbdata/HeaterSync_FccdRead.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead25.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead31_25.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead37_50.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead43_75.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead50.arb +0 -2
- egse/aeu/arbdata/Heater_FccdRead_min_points.arb +0 -2
- egse/aeu/arbdata/ccdRead25.arb +0 -2
- egse/aeu/arbdata/ccdRead25_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead31_25.arb +0 -2
- egse/aeu/arbdata/ccdRead31_25_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead37_50.arb +0 -2
- egse/aeu/arbdata/ccdRead37_50_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead43_75.arb +0 -2
- egse/aeu/arbdata/ccdRead43_75_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead50.arb +0 -2
- egse/aeu/arbdata/ccdRead50_150ms.arb +0 -2
- egse/alert/__init__.py +0 -1049
- egse/alert/alertman.yaml +0 -37
- egse/alert/alertman_cs.py +0 -233
- egse/alert/alertman_ui.py +0 -600
- egse/alert/gsm/beaglebone.py +0 -138
- egse/alert/gsm/beaglebone.yaml +0 -51
- egse/alert/gsm/beaglebone_cs.py +0 -108
- egse/alert/gsm/beaglebone_devif.py +0 -122
- egse/alert/gsm/beaglebone_protocol.py +0 -46
- egse/bits.py +0 -318
- egse/camera.py +0 -44
- egse/collimator/__init__.py +0 -0
- egse/collimator/fcul/__init__.py +0 -0
- egse/collimator/fcul/ogse.py +0 -1077
- egse/collimator/fcul/ogse.yaml +0 -14
- egse/collimator/fcul/ogse_cs.py +0 -154
- egse/collimator/fcul/ogse_devif.py +0 -358
- egse/collimator/fcul/ogse_protocol.py +0 -132
- egse/collimator/fcul/ogse_sim.py +0 -431
- egse/collimator/fcul/ogse_ui.py +0 -1108
- egse/command.py +0 -699
- egse/config.py +0 -410
- egse/confman/__init__.py +0 -1058
- egse/confman/confman.yaml +0 -70
- egse/confman/confman_cs.py +0 -240
- egse/confman/confman_ui.py +0 -381
- egse/confman/setup_ui.py +0 -565
- egse/control.py +0 -632
- egse/coordinates/__init__.py +0 -534
- egse/coordinates/avoidance.py +0 -100
- egse/coordinates/cslmodel.py +0 -127
- egse/coordinates/laser_tracker_to_dict.py +0 -122
- egse/coordinates/point.py +0 -707
- egse/coordinates/pyplot.py +0 -194
- egse/coordinates/referenceFrame.py +0 -1279
- egse/coordinates/refmodel.py +0 -737
- egse/coordinates/rotationMatrix.py +0 -85
- egse/coordinates/transform3d_addon.py +0 -419
- egse/csl/__init__.py +0 -50
- egse/csl/commanding.py +0 -78
- egse/csl/icons/hexapod-connected-selected.svg +0 -30
- egse/csl/icons/hexapod-connected.svg +0 -30
- egse/csl/icons/hexapod-homing-selected.svg +0 -68
- egse/csl/icons/hexapod-homing.svg +0 -68
- egse/csl/icons/hexapod-retract-selected.svg +0 -56
- egse/csl/icons/hexapod-retract.svg +0 -51
- egse/csl/icons/hexapod-zero-selected.svg +0 -56
- egse/csl/icons/hexapod-zero.svg +0 -56
- egse/csl/icons/logo-puna.svg +0 -92
- egse/csl/icons/stop.svg +0 -1
- egse/csl/initialisation.py +0 -102
- egse/csl/mech_pos_settings.yaml +0 -18
- egse/das.py +0 -1240
- egse/das.yaml +0 -7
- egse/data/conf/SETUP_CSL_00000_170620_150000.yaml +0 -5
- egse/data/conf/SETUP_CSL_00001_170620_151010.yaml +0 -69
- egse/data/conf/SETUP_CSL_00002_170620_151020.yaml +0 -69
- egse/data/conf/SETUP_CSL_00003_170620_151030.yaml +0 -69
- egse/data/conf/SETUP_CSL_00004_170620_151040.yaml +0 -69
- egse/data/conf/SETUP_CSL_00005_170620_151050.yaml +0 -69
- egse/data/conf/SETUP_CSL_00006_170620_151060.yaml +0 -69
- egse/data/conf/SETUP_CSL_00007_170620_151070.yaml +0 -69
- egse/data/conf/SETUP_CSL_00008_170620_151080.yaml +0 -75
- egse/data/conf/SETUP_CSL_00010_210308_083016.yaml +0 -138
- egse/data/conf/SETUP_INTA_00000_170620_150000.yaml +0 -4
- egse/data/conf/SETUP_SRON_00000_170620_150000.yaml +0 -4
- egse/decorators.py +0 -514
- egse/device.py +0 -269
- egse/dpu/__init__.py +0 -2698
- egse/dpu/ccd_ui.py +0 -514
- egse/dpu/dpu.py +0 -783
- egse/dpu/dpu.yaml +0 -153
- egse/dpu/dpu_cs.py +0 -272
- egse/dpu/dpu_ui.py +0 -671
- egse/dpu/fitsgen.py +0 -2096
- egse/dpu/fitsgen_ui.py +0 -399
- egse/dpu/hdf5_model.py +0 -332
- egse/dpu/hdf5_ui.py +0 -277
- egse/dpu/hdf5_viewer.py +0 -506
- egse/dpu/hk_ui.py +0 -468
- egse/dpu_commands.py +0 -81
- egse/dsi/__init__.py +0 -33
- egse/dsi/_libesl.py +0 -232
- egse/dsi/constants.py +0 -296
- egse/dsi/esl.py +0 -630
- egse/dsi/rmap.py +0 -444
- egse/dsi/rmapci.py +0 -39
- egse/dsi/spw.py +0 -335
- egse/dsi/spw_state.py +0 -29
- egse/dummy.py +0 -318
- egse/dyndummy.py +0 -179
- egse/env.py +0 -278
- egse/exceptions.py +0 -88
- egse/fdir/__init__.py +0 -26
- egse/fdir/fdir_manager.py +0 -85
- egse/fdir/fdir_manager.yaml +0 -37
- egse/fdir/fdir_manager_controller.py +0 -136
- egse/fdir/fdir_manager_cs.py +0 -164
- egse/fdir/fdir_manager_interface.py +0 -15
- egse/fdir/fdir_remote.py +0 -73
- egse/fdir/fdir_remote.yaml +0 -30
- egse/fdir/fdir_remote_controller.py +0 -30
- egse/fdir/fdir_remote_cs.py +0 -94
- egse/fdir/fdir_remote_interface.py +0 -9
- egse/fdir/fdir_remote_popup.py +0 -26
- egse/fee/__init__.py +0 -106
- egse/fee/f_fee_register.yaml +0 -43
- egse/fee/feesim.py +0 -914
- egse/fee/n_fee_hk.py +0 -768
- egse/fee/nfee.py +0 -188
- egse/filterwheel/__init__.py +0 -4
- egse/filterwheel/eksma/__init__.py +0 -49
- egse/filterwheel/eksma/fw8smc4.py +0 -657
- egse/filterwheel/eksma/fw8smc4.yaml +0 -121
- egse/filterwheel/eksma/fw8smc4_cs.py +0 -144
- egse/filterwheel/eksma/fw8smc4_devif.py +0 -473
- egse/filterwheel/eksma/fw8smc4_protocol.py +0 -82
- egse/filterwheel/eksma/fw8smc4_ui.py +0 -940
- egse/filterwheel/eksma/fw8smc5.py +0 -115
- egse/filterwheel/eksma/fw8smc5.yaml +0 -105
- egse/filterwheel/eksma/fw8smc5_controller.py +0 -307
- egse/filterwheel/eksma/fw8smc5_cs.py +0 -141
- egse/filterwheel/eksma/fw8smc5_interface.py +0 -65
- egse/filterwheel/eksma/fw8smc5_simulator.py +0 -29
- egse/filterwheel/eksma/fw8smc5_ui.py +0 -1065
- egse/filterwheel/eksma/testpythonfw.py +0 -215
- egse/fov/__init__.py +0 -65
- egse/fov/fov_hk.py +0 -710
- egse/fov/fov_ui.py +0 -859
- egse/fov/fov_ui_controller.py +0 -140
- egse/fov/fov_ui_model.py +0 -200
- egse/fov/fov_ui_view.py +0 -345
- egse/gimbal/__init__.py +0 -32
- egse/gimbal/symetrie/__init__.py +0 -26
- egse/gimbal/symetrie/alpha.py +0 -586
- egse/gimbal/symetrie/generic_gimbal_ui.py +0 -1521
- egse/gimbal/symetrie/gimbal.py +0 -877
- egse/gimbal/symetrie/gimbal.yaml +0 -168
- egse/gimbal/symetrie/gimbal_cs.py +0 -183
- egse/gimbal/symetrie/gimbal_protocol.py +0 -138
- egse/gimbal/symetrie/gimbal_ui.py +0 -361
- egse/gimbal/symetrie/pmac.py +0 -1006
- egse/gimbal/symetrie/pmac_regex.py +0 -83
- egse/graph.py +0 -132
- egse/gui/__init__.py +0 -47
- egse/gui/buttons.py +0 -378
- egse/gui/focalplane.py +0 -1285
- egse/gui/formatter.py +0 -10
- egse/gui/led.py +0 -162
- egse/gui/limitswitch.py +0 -143
- egse/gui/mechanisms.py +0 -587
- egse/gui/states.py +0 -148
- egse/gui/stripchart.py +0 -729
- egse/gui/styles.qss +0 -48
- egse/gui/switch.py +0 -112
- egse/h5.py +0 -274
- egse/help/__init__.py +0 -0
- egse/help/help_ui.py +0 -126
- egse/hexapod/__init__.py +0 -32
- egse/hexapod/symetrie/__init__.py +0 -137
- egse/hexapod/symetrie/alpha.py +0 -874
- egse/hexapod/symetrie/dynalpha.py +0 -1387
- egse/hexapod/symetrie/hexapod_ui.py +0 -1516
- egse/hexapod/symetrie/pmac.py +0 -1010
- egse/hexapod/symetrie/pmac_regex.py +0 -83
- egse/hexapod/symetrie/puna.py +0 -1167
- egse/hexapod/symetrie/puna.yaml +0 -193
- egse/hexapod/symetrie/puna_cs.py +0 -195
- egse/hexapod/symetrie/puna_protocol.py +0 -134
- egse/hexapod/symetrie/puna_ui.py +0 -433
- egse/hexapod/symetrie/punaplus.py +0 -107
- egse/hexapod/symetrie/zonda.py +0 -872
- egse/hexapod/symetrie/zonda.yaml +0 -337
- egse/hexapod/symetrie/zonda_cs.py +0 -172
- egse/hexapod/symetrie/zonda_devif.py +0 -414
- egse/hexapod/symetrie/zonda_protocol.py +0 -123
- egse/hexapod/symetrie/zonda_ui.py +0 -449
- egse/hk.py +0 -791
- egse/icons/aeu-cs-start.svg +0 -117
- egse/icons/aeu-cs-stop.svg +0 -118
- egse/icons/aeu-cs.svg +0 -107
- egse/icons/aeu_cs-started.svg +0 -112
- egse/icons/aeu_cs-stopped.svg +0 -112
- egse/icons/aeu_cs.svg +0 -55
- egse/icons/alert.svg +0 -1
- egse/icons/arrow-double-left.png +0 -0
- egse/icons/arrow-double-right.png +0 -0
- egse/icons/arrow-up.svg +0 -11
- egse/icons/backward.svg +0 -1
- egse/icons/busy.svg +0 -1
- egse/icons/cleaning.svg +0 -115
- egse/icons/color-scheme.svg +0 -1
- egse/icons/cs-connected-alert.svg +0 -91
- egse/icons/cs-connected-disabled.svg +0 -43
- egse/icons/cs-connected.svg +0 -89
- egse/icons/cs-not-connected.svg +0 -44
- egse/icons/double-left-arrow.svg +0 -1
- egse/icons/double-right-arrow.svg +0 -1
- egse/icons/erase-disabled.svg +0 -19
- egse/icons/erase.svg +0 -59
- egse/icons/fitsgen-start.svg +0 -47
- egse/icons/fitsgen-stop.svg +0 -48
- egse/icons/fitsgen.svg +0 -1
- egse/icons/forward.svg +0 -1
- egse/icons/fov-hk-start.svg +0 -33
- egse/icons/fov-hk-stop.svg +0 -37
- egse/icons/fov-hk.svg +0 -1
- egse/icons/front-desk.svg +0 -1
- egse/icons/home-actioned.svg +0 -15
- egse/icons/home-disabled.svg +0 -15
- egse/icons/home.svg +0 -13
- egse/icons/info.svg +0 -1
- egse/icons/invalid.png +0 -0
- egse/icons/led-green.svg +0 -20
- egse/icons/led-grey.svg +0 -20
- egse/icons/led-orange.svg +0 -20
- egse/icons/led-red.svg +0 -20
- egse/icons/led-square-green.svg +0 -134
- egse/icons/led-square-grey.svg +0 -134
- egse/icons/led-square-orange.svg +0 -134
- egse/icons/led-square-red.svg +0 -134
- egse/icons/limit-switch-all-green.svg +0 -115
- egse/icons/limit-switch-all-red.svg +0 -117
- egse/icons/limit-switch-el+.svg +0 -116
- egse/icons/limit-switch-el-.svg +0 -117
- egse/icons/location-marker.svg +0 -1
- egse/icons/logo-dpu.svg +0 -48
- egse/icons/logo-gimbal.svg +0 -112
- egse/icons/logo-huber.svg +0 -23
- egse/icons/logo-ogse.svg +0 -31
- egse/icons/logo-puna.svg +0 -92
- egse/icons/logo-tcs.svg +0 -29
- egse/icons/logo-zonda.svg +0 -66
- egse/icons/maximize.svg +0 -1
- egse/icons/meter.svg +0 -1
- egse/icons/more.svg +0 -45
- egse/icons/n-fee-hk-start.svg +0 -24
- egse/icons/n-fee-hk-stop.svg +0 -25
- egse/icons/n-fee-hk.svg +0 -83
- egse/icons/observing-off.svg +0 -46
- egse/icons/observing-on.svg +0 -46
- egse/icons/open-document-hdf5.png +0 -0
- egse/icons/open-document-hdf5.svg +0 -21
- egse/icons/ops-mode.svg +0 -1
- egse/icons/play-green.svg +0 -17
- egse/icons/plugged-disabled.svg +0 -27
- egse/icons/plugged.svg +0 -21
- egse/icons/pm_ui.svg +0 -1
- egse/icons/power-button-green.svg +0 -27
- egse/icons/power-button-red.svg +0 -27
- egse/icons/power-button.svg +0 -27
- egse/icons/radar.svg +0 -1
- egse/icons/radioactive.svg +0 -2
- egse/icons/reload.svg +0 -1
- egse/icons/remote-control-off.svg +0 -28
- egse/icons/remote-control-on.svg +0 -28
- egse/icons/repeat-blue.svg +0 -15
- egse/icons/repeat.svg +0 -1
- egse/icons/settings.svg +0 -1
- egse/icons/shrink.svg +0 -1
- egse/icons/shutter.svg +0 -1
- egse/icons/sign-off.svg +0 -1
- egse/icons/sign-on.svg +0 -1
- egse/icons/sim-mode.svg +0 -1
- egse/icons/small-buttons-go.svg +0 -20
- egse/icons/small-buttons-minus.svg +0 -51
- egse/icons/small-buttons-plus.svg +0 -51
- egse/icons/sponge.svg +0 -220
- egse/icons/start-button-disabled.svg +0 -84
- egse/icons/start-button.svg +0 -50
- egse/icons/stop-button-disabled.svg +0 -84
- egse/icons/stop-button.svg +0 -50
- egse/icons/stop-red.svg +0 -17
- egse/icons/stop.svg +0 -1
- egse/icons/switch-disabled-square.svg +0 -87
- egse/icons/switch-disabled.svg +0 -15
- egse/icons/switch-off-square.svg +0 -87
- egse/icons/switch-off.svg +0 -72
- egse/icons/switch-on-square.svg +0 -87
- egse/icons/switch-on.svg +0 -61
- egse/icons/temperature-control.svg +0 -44
- egse/icons/th_ui_logo.svg +0 -1
- egse/icons/unplugged.svg +0 -23
- egse/icons/unvalid.png +0 -0
- egse/icons/user-interface.svg +0 -1
- egse/icons/vacuum.svg +0 -1
- egse/icons/valid.png +0 -0
- egse/icons/zoom-to-pixel-dark.svg +0 -64
- egse/icons/zoom-to-pixel-white.svg +0 -36
- egse/images/big-rotation-stage.png +0 -0
- egse/images/connected-100.png +0 -0
- egse/images/cross.svg +0 -6
- egse/images/disconnected-100.png +0 -0
- egse/images/gui-icon.png +0 -0
- egse/images/home.svg +0 -6
- egse/images/info-icon.png +0 -0
- egse/images/led-black.svg +0 -89
- egse/images/led-green.svg +0 -85
- egse/images/led-orange.svg +0 -85
- egse/images/led-red.svg +0 -85
- egse/images/load-icon.png +0 -0
- egse/images/load-setup.png +0 -0
- egse/images/load.png +0 -0
- egse/images/pause.png +0 -0
- egse/images/play-button.svg +0 -8
- egse/images/play.png +0 -0
- egse/images/process-status.png +0 -0
- egse/images/restart.png +0 -0
- egse/images/search.png +0 -0
- egse/images/sma.png +0 -0
- egse/images/start.png +0 -0
- egse/images/stop-button.svg +0 -8
- egse/images/stop.png +0 -0
- egse/images/switch-off.svg +0 -48
- egse/images/switch-on.svg +0 -48
- egse/images/undo.png +0 -0
- egse/images/update-button.svg +0 -11
- egse/imageviewer/exposureselection.py +0 -475
- egse/imageviewer/imageviewer.py +0 -198
- egse/imageviewer/matchfocalplane.py +0 -179
- egse/imageviewer/subfieldposition.py +0 -133
- egse/lampcontrol/__init__.py +0 -4
- egse/lampcontrol/beaglebone/beaglebone.py +0 -178
- egse/lampcontrol/beaglebone/beaglebone.yaml +0 -62
- egse/lampcontrol/beaglebone/beaglebone_cs.py +0 -106
- egse/lampcontrol/beaglebone/beaglebone_devif.py +0 -150
- egse/lampcontrol/beaglebone/beaglebone_protocol.py +0 -73
- egse/lampcontrol/energetiq/__init__.py +0 -22
- egse/lampcontrol/energetiq/eq99.yaml +0 -98
- egse/lampcontrol/energetiq/lampEQ99.py +0 -283
- egse/lampcontrol/energetiq/lampEQ99_cs.py +0 -128
- egse/lampcontrol/energetiq/lampEQ99_devif.py +0 -158
- egse/lampcontrol/energetiq/lampEQ99_encode_decode_errors.py +0 -73
- egse/lampcontrol/energetiq/lampEQ99_protocol.py +0 -71
- egse/lampcontrol/energetiq/lampEQ99_ui.py +0 -465
- egse/lib/CentOS-7/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/CentOS-8/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/CentOS-8/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/Debian/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/Debian/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/Debian/libetherspacelink_v35_21.dylib +0 -0
- egse/lib/Linux/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/Linux/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/Ubuntu-20/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/Ubuntu-20/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/gssw/python3-gssw_2.2.3+31f63c9f-1_all.deb +0 -0
- egse/lib/ximc/__pycache__/pyximc.cpython-38 2.pyc +0 -0
- egse/lib/ximc/__pycache__/pyximc.cpython-38.pyc +0 -0
- egse/lib/ximc/libximc.framework/Frameworks/libbindy.dylib +0 -0
- egse/lib/ximc/libximc.framework/Frameworks/libxiwrapper.dylib +0 -0
- egse/lib/ximc/libximc.framework/Headers/ximc.h +0 -5510
- egse/lib/ximc/libximc.framework/Resources/Info.plist +0 -42
- egse/lib/ximc/libximc.framework/Resources/keyfile.sqlite +0 -0
- egse/lib/ximc/libximc.framework/libbindy.so +0 -0
- egse/lib/ximc/libximc.framework/libximc +0 -0
- egse/lib/ximc/libximc.framework/libximc.so +0 -0
- egse/lib/ximc/libximc.framework/libximc.so.7.0.0 +0 -0
- egse/lib/ximc/libximc.framework/libxiwrapper.so +0 -0
- egse/lib/ximc/pyximc.py +0 -922
- egse/listener.py +0 -179
- egse/logger/__init__.py +0 -243
- egse/logger/log_cs.py +0 -321
- egse/metrics.py +0 -102
- egse/mixin.py +0 -464
- egse/monitoring.py +0 -95
- egse/ni/alarms/__init__.py +0 -26
- egse/ni/alarms/cdaq9375.py +0 -300
- egse/ni/alarms/cdaq9375.yaml +0 -89
- egse/ni/alarms/cdaq9375_cs.py +0 -130
- egse/ni/alarms/cdaq9375_devif.py +0 -183
- egse/ni/alarms/cdaq9375_protocol.py +0 -48
- egse/obs_inspection.py +0 -165
- egse/observer.py +0 -41
- egse/obsid.py +0 -163
- egse/powermeter/__init__.py +0 -0
- egse/powermeter/ni/__init__.py +0 -38
- egse/powermeter/ni/cdaq9184.py +0 -224
- egse/powermeter/ni/cdaq9184.yaml +0 -73
- egse/powermeter/ni/cdaq9184_cs.py +0 -130
- egse/powermeter/ni/cdaq9184_devif.py +0 -201
- egse/powermeter/ni/cdaq9184_protocol.py +0 -48
- egse/powermeter/ni/cdaq9184_ui.py +0 -544
- egse/powermeter/thorlabs/__init__.py +0 -25
- egse/powermeter/thorlabs/pm100a.py +0 -380
- egse/powermeter/thorlabs/pm100a.yaml +0 -132
- egse/powermeter/thorlabs/pm100a_cs.py +0 -136
- egse/powermeter/thorlabs/pm100a_devif.py +0 -127
- egse/powermeter/thorlabs/pm100a_protocol.py +0 -80
- egse/powermeter/thorlabs/pm100a_ui.py +0 -725
- egse/process.py +0 -451
- egse/procman/__init__.py +0 -834
- egse/procman/cannot_start_process_popup.py +0 -43
- egse/procman/procman.yaml +0 -49
- egse/procman/procman_cs.py +0 -201
- egse/procman/procman_ui.py +0 -2081
- egse/protocol.py +0 -605
- egse/proxy.py +0 -531
- egse/randomwalk.py +0 -140
- egse/reg.py +0 -585
- egse/reload.py +0 -122
- egse/reprocess.py +0 -693
- egse/resource.py +0 -333
- egse/rmap.py +0 -406
- egse/rst.py +0 -135
- egse/search.py +0 -182
- egse/serialdevice.py +0 -190
- egse/services.py +0 -247
- egse/services.yaml +0 -68
- egse/settings.py +0 -379
- egse/settings.yaml +0 -980
- egse/setup.py +0 -1181
- egse/shutter/__init__.py +0 -0
- egse/shutter/thorlabs/__init__.py +0 -19
- egse/shutter/thorlabs/ksc101.py +0 -205
- egse/shutter/thorlabs/ksc101.yaml +0 -105
- egse/shutter/thorlabs/ksc101_cs.py +0 -136
- egse/shutter/thorlabs/ksc101_devif.py +0 -201
- egse/shutter/thorlabs/ksc101_protocol.py +0 -71
- egse/shutter/thorlabs/ksc101_ui.py +0 -548
- egse/shutter/thorlabs/sc10.py +0 -82
- egse/shutter/thorlabs/sc10.yaml +0 -52
- egse/shutter/thorlabs/sc10_controller.py +0 -81
- egse/shutter/thorlabs/sc10_cs.py +0 -108
- egse/shutter/thorlabs/sc10_interface.py +0 -25
- egse/shutter/thorlabs/sc10_simulator.py +0 -30
- egse/simulator.py +0 -41
- egse/slack.py +0 -61
- egse/socketdevice.py +0 -218
- egse/sockets.py +0 -218
- egse/spw.py +0 -1401
- egse/stages/__init__.py +0 -12
- egse/stages/aerotech/ensemble.py +0 -245
- egse/stages/aerotech/ensemble.yaml +0 -205
- egse/stages/aerotech/ensemble_controller.py +0 -275
- egse/stages/aerotech/ensemble_cs.py +0 -110
- egse/stages/aerotech/ensemble_interface.py +0 -132
- egse/stages/aerotech/ensemble_parameters.py +0 -433
- egse/stages/aerotech/ensemble_simulator.py +0 -27
- egse/stages/aerotech/mgse_sim.py +0 -188
- egse/stages/arun/smd3.py +0 -110
- egse/stages/arun/smd3.yaml +0 -68
- egse/stages/arun/smd3_controller.py +0 -470
- egse/stages/arun/smd3_cs.py +0 -112
- egse/stages/arun/smd3_interface.py +0 -53
- egse/stages/arun/smd3_simulator.py +0 -27
- egse/stages/arun/smd3_stop.py +0 -16
- egse/stages/huber/__init__.py +0 -49
- egse/stages/huber/smc9300.py +0 -920
- egse/stages/huber/smc9300.yaml +0 -63
- egse/stages/huber/smc9300_cs.py +0 -178
- egse/stages/huber/smc9300_devif.py +0 -345
- egse/stages/huber/smc9300_protocol.py +0 -113
- egse/stages/huber/smc9300_sim.py +0 -547
- egse/stages/huber/smc9300_ui.py +0 -973
- egse/state.py +0 -173
- egse/statemachine.py +0 -274
- egse/storage/__init__.py +0 -1067
- egse/storage/persistence.py +0 -2295
- egse/storage/storage.yaml +0 -79
- egse/storage/storage_cs.py +0 -231
- egse/styles/dark.qss +0 -343
- egse/styles/default.qss +0 -48
- egse/synoptics/__init__.py +0 -417
- egse/synoptics/syn.yaml +0 -9
- egse/synoptics/syn_cs.py +0 -195
- egse/system.py +0 -1611
- egse/tcs/__init__.py +0 -14
- egse/tcs/tcs.py +0 -879
- egse/tcs/tcs.yaml +0 -14
- egse/tcs/tcs_cs.py +0 -202
- egse/tcs/tcs_devif.py +0 -292
- egse/tcs/tcs_protocol.py +0 -180
- egse/tcs/tcs_sim.py +0 -177
- egse/tcs/tcs_ui.py +0 -543
- egse/tdms.py +0 -171
- egse/tempcontrol/__init__.py +0 -23
- egse/tempcontrol/agilent/agilent34970.py +0 -109
- egse/tempcontrol/agilent/agilent34970.yaml +0 -44
- egse/tempcontrol/agilent/agilent34970_cs.py +0 -114
- egse/tempcontrol/agilent/agilent34970_devif.py +0 -182
- egse/tempcontrol/agilent/agilent34970_protocol.py +0 -96
- egse/tempcontrol/agilent/agilent34972.py +0 -111
- egse/tempcontrol/agilent/agilent34972.yaml +0 -44
- egse/tempcontrol/agilent/agilent34972_cs.py +0 -115
- egse/tempcontrol/agilent/agilent34972_devif.py +0 -189
- egse/tempcontrol/agilent/agilent34972_protocol.py +0 -98
- egse/tempcontrol/beaglebone/beaglebone.py +0 -341
- egse/tempcontrol/beaglebone/beaglebone.yaml +0 -110
- egse/tempcontrol/beaglebone/beaglebone_cs.py +0 -117
- egse/tempcontrol/beaglebone/beaglebone_protocol.py +0 -134
- egse/tempcontrol/beaglebone/beaglebone_ui.py +0 -674
- egse/tempcontrol/digalox/digalox.py +0 -115
- egse/tempcontrol/digalox/digalox.yaml +0 -36
- egse/tempcontrol/digalox/digalox_cs.py +0 -108
- egse/tempcontrol/digalox/digalox_protocol.py +0 -56
- egse/tempcontrol/keithley/__init__.py +0 -33
- egse/tempcontrol/keithley/daq6510.py +0 -662
- egse/tempcontrol/keithley/daq6510.yaml +0 -105
- egse/tempcontrol/keithley/daq6510_cs.py +0 -163
- egse/tempcontrol/keithley/daq6510_devif.py +0 -343
- egse/tempcontrol/keithley/daq6510_protocol.py +0 -79
- egse/tempcontrol/keithley/daq6510_sim.py +0 -186
- egse/tempcontrol/lakeshore/__init__.py +0 -33
- egse/tempcontrol/lakeshore/lsci.py +0 -361
- egse/tempcontrol/lakeshore/lsci.yaml +0 -162
- egse/tempcontrol/lakeshore/lsci_cs.py +0 -174
- egse/tempcontrol/lakeshore/lsci_devif.py +0 -292
- egse/tempcontrol/lakeshore/lsci_protocol.py +0 -76
- egse/tempcontrol/lakeshore/lsci_ui.py +0 -387
- egse/tempcontrol/ni/__init__.py +0 -0
- egse/tempcontrol/spid/spid.py +0 -109
- egse/tempcontrol/spid/spid.yaml +0 -81
- egse/tempcontrol/spid/spid_controller.py +0 -279
- egse/tempcontrol/spid/spid_cs.py +0 -136
- egse/tempcontrol/spid/spid_protocol.py +0 -107
- egse/tempcontrol/spid/spid_ui.py +0 -723
- egse/tempcontrol/srs/__init__.py +0 -22
- egse/tempcontrol/srs/ptc10.py +0 -867
- egse/tempcontrol/srs/ptc10.yaml +0 -227
- egse/tempcontrol/srs/ptc10_cs.py +0 -128
- egse/tempcontrol/srs/ptc10_devif.py +0 -116
- egse/tempcontrol/srs/ptc10_protocol.py +0 -39
- egse/tempcontrol/srs/ptc10_ui.py +0 -906
- egse/ups/apc/apc.py +0 -236
- egse/ups/apc/apc.yaml +0 -45
- egse/ups/apc/apc_cs.py +0 -101
- egse/ups/apc/apc_protocol.py +0 -125
- egse/user.yaml +0 -7
- egse/vacuum/beaglebone/beaglebone.py +0 -149
- egse/vacuum/beaglebone/beaglebone.yaml +0 -44
- egse/vacuum/beaglebone/beaglebone_cs.py +0 -108
- egse/vacuum/beaglebone/beaglebone_devif.py +0 -159
- egse/vacuum/beaglebone/beaglebone_protocol.py +0 -192
- egse/vacuum/beaglebone/beaglebone_ui.py +0 -638
- egse/vacuum/instrutech/igm402.py +0 -91
- egse/vacuum/instrutech/igm402.yaml +0 -90
- egse/vacuum/instrutech/igm402_controller.py +0 -124
- egse/vacuum/instrutech/igm402_cs.py +0 -108
- egse/vacuum/instrutech/igm402_interface.py +0 -49
- egse/vacuum/instrutech/igm402_simulator.py +0 -36
- egse/vacuum/keller/kellerBus.py +0 -256
- egse/vacuum/keller/leo3.py +0 -100
- egse/vacuum/keller/leo3.yaml +0 -38
- egse/vacuum/keller/leo3_controller.py +0 -81
- egse/vacuum/keller/leo3_cs.py +0 -101
- egse/vacuum/keller/leo3_interface.py +0 -33
- egse/vacuum/mks/evision.py +0 -86
- egse/vacuum/mks/evision.yaml +0 -75
- egse/vacuum/mks/evision_cs.py +0 -101
- egse/vacuum/mks/evision_devif.py +0 -313
- egse/vacuum/mks/evision_interface.py +0 -60
- egse/vacuum/mks/evision_simulator.py +0 -24
- egse/vacuum/mks/evision_ui.py +0 -701
- egse/vacuum/pfeiffer/acp40.py +0 -87
- egse/vacuum/pfeiffer/acp40.yaml +0 -60
- egse/vacuum/pfeiffer/acp40_controller.py +0 -117
- egse/vacuum/pfeiffer/acp40_cs.py +0 -109
- egse/vacuum/pfeiffer/acp40_interface.py +0 -40
- egse/vacuum/pfeiffer/acp40_simulator.py +0 -37
- egse/vacuum/pfeiffer/tc400.py +0 -87
- egse/vacuum/pfeiffer/tc400.yaml +0 -83
- egse/vacuum/pfeiffer/tc400_controller.py +0 -136
- egse/vacuum/pfeiffer/tc400_cs.py +0 -109
- egse/vacuum/pfeiffer/tc400_interface.py +0 -70
- egse/vacuum/pfeiffer/tc400_simulator.py +0 -35
- egse/vacuum/pfeiffer/tpg261.py +0 -80
- egse/vacuum/pfeiffer/tpg261.yaml +0 -66
- egse/vacuum/pfeiffer/tpg261_controller.py +0 -150
- egse/vacuum/pfeiffer/tpg261_cs.py +0 -109
- egse/vacuum/pfeiffer/tpg261_interface.py +0 -59
- egse/vacuum/pfeiffer/tpg261_simulator.py +0 -23
- egse/version.py +0 -174
- egse/visitedpositions.py +0 -398
- egse/windowing.py +0 -213
- egse/zmq/__init__.py +0 -28
- egse/zmq/spw.py +0 -160
- egse/zmq_ser.py +0 -41
- scripts/alerts/cold.yaml +0 -278
- scripts/alerts/example_alerts.yaml +0 -54
- scripts/alerts/transition.yaml +0 -14
- scripts/alerts/warm.yaml +0 -49
- scripts/analyse_n_fee_hk_data.py +0 -52
- scripts/check_hdf5_files.py +0 -192
- scripts/check_register_sync.py +0 -47
- scripts/check_tcs_calib_coef.py +0 -90
- scripts/correct_ccd_cold_temperature_cal.py +0 -157
- scripts/create_hdf5_report.py +0 -293
- scripts/csl_model.py +0 -420
- scripts/csl_restore_setup.py +0 -229
- scripts/export-grafana-dashboards.py +0 -49
- scripts/fdir/cs_recovery/fdir_cs_recovery.py +0 -54
- scripts/fdir/fdir_table.yaml +0 -70
- scripts/fdir/fdir_test_recovery.py +0 -10
- scripts/fdir/hw_recovery/fdir_agilent_hw_recovery.py +0 -73
- scripts/fdir/limit_recovery/fdir_agilent_limit.py +0 -61
- scripts/fdir/limit_recovery/fdir_bb_heater_limit.py +0 -59
- scripts/fdir/limit_recovery/fdir_ensemble_limit.py +0 -33
- scripts/fdir/limit_recovery/fdir_pressure_limit_recovery.py +0 -71
- scripts/fix_csv.py +0 -80
- scripts/ias/correct_ccd_temp_cal_elfique.py +0 -43
- scripts/ias/correct_ccd_temp_cal_floreffe.py +0 -43
- scripts/ias/correct_trp_swap_achel.py +0 -199
- scripts/inta/correct_ccd_temp_cal_duvel.py +0 -43
- scripts/inta/correct_ccd_temp_cal_gueuze.py +0 -43
- scripts/n_fee_supply_voltage_calculation.py +0 -92
- scripts/playground.py +0 -30
- scripts/print_hdf5_hk_data.py +0 -68
- scripts/print_register_map.py +0 -43
- scripts/remove_lines_between_matches.py +0 -188
- scripts/sron/commanding/control_heaters.py +0 -44
- scripts/sron/commanding/pumpdown.py +0 -46
- scripts/sron/commanding/set_pid_setpoint.py +0 -19
- scripts/sron/commanding/shutdown_bbb_heaters.py +0 -10
- scripts/sron/commanding/shutdown_pumps.py +0 -33
- scripts/sron/correct_mgse_coordinates_brigand_chimay.py +0 -272
- scripts/sron/correct_trp_swap_brigand.py +0 -204
- scripts/sron/gimbal_conversions.py +0 -75
- scripts/sron/tm_gen/tm_gen_agilent.py +0 -37
- scripts/sron/tm_gen/tm_gen_heaters.py +0 -4
- scripts/sron/tm_gen/tm_gen_spid.py +0 -13
- scripts/update_operational_cgse.py +0 -268
- scripts/update_operational_cgse_old.py +0 -273
egse/stages/huber/smc9300.py
DELETED
|
@@ -1,920 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This module defines the device classes to be used to connect to and control the HUBER Stages.
|
|
3
|
-
"""
|
|
4
|
-
from __future__ import annotations
|
|
5
|
-
|
|
6
|
-
import logging
|
|
7
|
-
import textwrap
|
|
8
|
-
from typing import Tuple
|
|
9
|
-
|
|
10
|
-
import rich
|
|
11
|
-
import time
|
|
12
|
-
|
|
13
|
-
from egse.control import Failure
|
|
14
|
-
from egse.device import DeviceConnectionError
|
|
15
|
-
from egse.device import DeviceConnectionState
|
|
16
|
-
from egse.device import DeviceInterface
|
|
17
|
-
from egse.mixin import DynamicCommandMixin
|
|
18
|
-
from egse.mixin import add_cr_lf
|
|
19
|
-
from egse.mixin import dynamic_command
|
|
20
|
-
from egse.proxy import DynamicProxy
|
|
21
|
-
from egse.settings import Settings
|
|
22
|
-
from egse.setup import load_setup
|
|
23
|
-
from egse.stages.huber.smc9300_devif import HuberError
|
|
24
|
-
from egse.stages.huber.smc9300_devif import HuberSMC9300EthernetInterface
|
|
25
|
-
from egse.zmq_ser import connect_address
|
|
26
|
-
|
|
27
|
-
# Explicitly set the module name instead of __name__. When module is executed instead of imported
|
|
28
|
-
# __name__ will result in __main__ and no logging to zmq will be done.
|
|
29
|
-
|
|
30
|
-
MODULE_LOGGER = logging.getLogger("egse.stages.huber.smc9300")
|
|
31
|
-
|
|
32
|
-
HC_SETTINGS = Settings.load("Huber Controller")
|
|
33
|
-
CTRL_SETTINGS = Settings.load("Huber Control Server")
|
|
34
|
-
DEVICE_SETTINGS = Settings.load(filename="smc9300.yaml")
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def print_state(state: int) -> None:
|
|
38
|
-
"""Prints the state of the axis."""
|
|
39
|
-
|
|
40
|
-
rich.print(
|
|
41
|
-
textwrap.dedent(
|
|
42
|
-
f"""\
|
|
43
|
-
axis ready: {bool(state & 1)}
|
|
44
|
-
reference position installed: {bool(state & 2)}
|
|
45
|
-
end/limit switch EL- active: {bool(state & 4)}
|
|
46
|
-
end/limit switch EL+ active: {bool(state & 8)}
|
|
47
|
-
program execution in progress: {bool(state & 64)}
|
|
48
|
-
controller ready: {bool(state & 128)}
|
|
49
|
-
oscillation in progress: {bool(state & 256)}
|
|
50
|
-
oscillation positioning error: {bool(state & 512)}
|
|
51
|
-
encoder reference installed: {bool(state & 1024)}
|
|
52
|
-
axis error: {bool(state & 16384)}
|
|
53
|
-
"""
|
|
54
|
-
)
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def untangle_status(status: str) -> dict:
|
|
59
|
-
"""Returns a dictionary with all the values from the status string."""
|
|
60
|
-
|
|
61
|
-
try:
|
|
62
|
-
|
|
63
|
-
axis, errn, errm, pos, epos, el, ref, eref, rdy, osc, prog, *_ = status.split(":")
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
"axis": int(axis), # the axis id
|
|
67
|
-
"err_no": int(errn), # error number
|
|
68
|
-
"err_msg": errm, # error message
|
|
69
|
-
"pos": float(pos), # position
|
|
70
|
-
"epos": float(epos), # encode position
|
|
71
|
-
"elimit": int(el), # end/limit status
|
|
72
|
-
"ref": int(ref), # reference status
|
|
73
|
-
"eref": int(eref), # encoder reference status
|
|
74
|
-
"ctrl": int(rdy), # controller ready
|
|
75
|
-
"osc": int(osc), # oscillation status
|
|
76
|
-
"prog": int(prog), # program running
|
|
77
|
-
}
|
|
78
|
-
except ValueError as exc:
|
|
79
|
-
raise ValueError(
|
|
80
|
-
textwrap.dedent(
|
|
81
|
-
f"""\
|
|
82
|
-
Could not disentangle the status from SMC9300, response from the device can not be parsed.
|
|
83
|
-
The expected format is "axis:err_no:err_msg:pos:epos:elimit:ref:eref:ctrl:osc:prog", where
|
|
84
|
-
`err_msg` is a string, `pos` and `epos` are floats and the others are of type int.
|
|
85
|
-
{status=}
|
|
86
|
-
"""
|
|
87
|
-
)
|
|
88
|
-
) from exc
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def decode_response(response: bytes) -> str:
|
|
92
|
-
"""Decodes the bytes object and strips off the newline."""
|
|
93
|
-
|
|
94
|
-
# MODULE_LOGGER.debug(f"response -> {response}")
|
|
95
|
-
|
|
96
|
-
return response.decode().rstrip()
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def decode_info(response: bytes) -> str:
|
|
100
|
-
response = decode_response(response).split("\r\n")
|
|
101
|
-
|
|
102
|
-
return "\n".join(response)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def decode_get_state(response: bytes) -> int:
|
|
106
|
-
"""Decodes the response from the get state command and strips off the newline."""
|
|
107
|
-
|
|
108
|
-
# The response argument has the following format: '<axis>:<state>;'
|
|
109
|
-
# where <axis> is 1, 2, or 3 and we need the <state>, so we to
|
|
110
|
-
# cut e.g. '1:' and ';' if <axis> is 1.
|
|
111
|
-
|
|
112
|
-
response = decode_response(response)
|
|
113
|
-
return int(response[2:-1])
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def decode_get_parameter(response: bytes) -> Tuple[str, int, str]:
|
|
117
|
-
"""
|
|
118
|
-
Decodes the response from a request for a parameter value. The response contains
|
|
119
|
-
the parameter name, the axis, and the value.
|
|
120
|
-
|
|
121
|
-
Returns:
|
|
122
|
-
A tuple of (`<parameter name: str>`, `<axis: int>`, `<value: str>`)
|
|
123
|
-
"""
|
|
124
|
-
response = decode_response(response)
|
|
125
|
-
name, value = response.split(":")
|
|
126
|
-
axis = name[-1]
|
|
127
|
-
name = name[:-1]
|
|
128
|
-
return name, int(axis), value
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
def decode_get_error(response: bytes) -> Tuple[str]:
|
|
132
|
-
"""Decodes the response from the get error command and strips off the newline."""
|
|
133
|
-
|
|
134
|
-
response = decode_response(response)
|
|
135
|
-
|
|
136
|
-
# The response string looks like '<axis>:<errno> <errmsg>' where <axis> is the axis number,
|
|
137
|
-
# <errno> is the error number and <errmsg> is the error message.
|
|
138
|
-
|
|
139
|
-
response = response[2:]
|
|
140
|
-
|
|
141
|
-
error = response.split(maxsplit=1)
|
|
142
|
-
|
|
143
|
-
if len(error) == 1 and error[0] == '0':
|
|
144
|
-
error.append("no error")
|
|
145
|
-
|
|
146
|
-
return tuple(error)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
def decode_axis_float(response: bytes) -> float:
|
|
150
|
-
"""Decodes the response of type `<axis>:<float>;` and strips off the newline."""
|
|
151
|
-
|
|
152
|
-
response = decode_response(response)
|
|
153
|
-
|
|
154
|
-
return float(response[2:-1])
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
def decode_axis_int(response: bytes) -> int:
|
|
158
|
-
"""Decodes the response of type `<axis>:<int>;` and strips off the newline."""
|
|
159
|
-
|
|
160
|
-
response = decode_response(response)
|
|
161
|
-
|
|
162
|
-
return int(response[2:-1])
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
def decode_get_configuration(response: bytes) -> dict | Failure:
|
|
166
|
-
"""Decodes the response from the controller on the request for the configuration parameters.
|
|
167
|
-
|
|
168
|
-
Returns:
|
|
169
|
-
A dictionary with parameter names and their values.
|
|
170
|
-
"""
|
|
171
|
-
all_conf = decode_response(response).split("\r\n")
|
|
172
|
-
|
|
173
|
-
# Every item in the all_conf list has the format '<var><axis>:<value>' where <var> is the
|
|
174
|
-
# name of the configuration variable, <axis> is the axis number and <value> is the current
|
|
175
|
-
# value for the configuration variable. A comment line starts with a '#' character.
|
|
176
|
-
|
|
177
|
-
all_conf = [item.split(":") for item in all_conf if not item.startswith("#")]
|
|
178
|
-
|
|
179
|
-
# Turn this list of lists into a dictionary and remove the <axis> from the variable names
|
|
180
|
-
|
|
181
|
-
return {key[:-1]: value for key, value in all_conf}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
def process_cmd_string(command: str) -> str:
|
|
185
|
-
"""Prepares the command string for sending to the controller.
|
|
186
|
-
A carriage return and newline is appended to the command."""
|
|
187
|
-
|
|
188
|
-
# MODULE_LOGGER.debug(f"process_command() = {command}")
|
|
189
|
-
|
|
190
|
-
return add_cr_lf(command)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
class HuberSMC9300Interface(DeviceInterface):
|
|
194
|
-
"""
|
|
195
|
-
Interface definition for the Controller, Simulator and Proxy classes for this device.
|
|
196
|
-
"""
|
|
197
|
-
|
|
198
|
-
def __init__(self):
|
|
199
|
-
|
|
200
|
-
super().__init__()
|
|
201
|
-
|
|
202
|
-
setup = load_setup()
|
|
203
|
-
self.avoidance = setup.gse.stages.big_rotation_stage.avoidance
|
|
204
|
-
self.hardstop = setup.gse.stages.big_rotation_stage.hardstop
|
|
205
|
-
|
|
206
|
-
@dynamic_command(
|
|
207
|
-
cmd_type="query", cmd_string="?",
|
|
208
|
-
process_cmd_string=process_cmd_string,
|
|
209
|
-
process_response=decode_info)
|
|
210
|
-
def info(self) -> str:
|
|
211
|
-
"""
|
|
212
|
-
Retrieve basic information about the Huber Stages and the Controller.
|
|
213
|
-
The returned string contains multiple lines seperated by a newline (`\n`).
|
|
214
|
-
"""
|
|
215
|
-
raise NotImplementedError
|
|
216
|
-
|
|
217
|
-
@dynamic_command(
|
|
218
|
-
cmd_type="query", cmd_string="?conf${axis}",
|
|
219
|
-
process_cmd_string=process_cmd_string,
|
|
220
|
-
process_response=decode_get_configuration)
|
|
221
|
-
def get_configuration(self, axis) -> dict | Failure:
|
|
222
|
-
"""
|
|
223
|
-
Returns the configuration parameters for the given axis.
|
|
224
|
-
|
|
225
|
-
Returns:
|
|
226
|
-
A dictionary with configuration parameter names and their values.
|
|
227
|
-
"""
|
|
228
|
-
raise NotImplementedError
|
|
229
|
-
|
|
230
|
-
def get_conf_value(self, axis, name):
|
|
231
|
-
"""
|
|
232
|
-
Returns the value of the requested configuration parameter.
|
|
233
|
-
|
|
234
|
-
Returns:
|
|
235
|
-
A string containing the value of the requested parameter. The returned object is
|
|
236
|
-
always a string and needs to be converted to int or float by the caller if needed.
|
|
237
|
-
"""
|
|
238
|
-
conf = self.get_configuration(axis)
|
|
239
|
-
return conf[name] if name in conf else None
|
|
240
|
-
|
|
241
|
-
@dynamic_command(
|
|
242
|
-
cmd_type="query", cmd_string="?v",
|
|
243
|
-
process_cmd_string=process_cmd_string,
|
|
244
|
-
process_response=decode_response)
|
|
245
|
-
def get_version(self):
|
|
246
|
-
"""
|
|
247
|
-
Returns the version information about the current control program on the HUBER controller.
|
|
248
|
-
"""
|
|
249
|
-
raise NotImplementedError
|
|
250
|
-
|
|
251
|
-
def goto(self, axis: int, position: float, wait: bool = True) -> int:
|
|
252
|
-
"""
|
|
253
|
-
Moves the stage to the given absolute position. For the big rotation stage, the movement is done
|
|
254
|
-
relative to the current position and the avoidance range and hard stop from the Setup are taken
|
|
255
|
-
into account.
|
|
256
|
-
|
|
257
|
-
A positive angle moves the rotation stage counter clockwise.
|
|
258
|
-
|
|
259
|
-
Args:
|
|
260
|
-
axis (int): the integer identifier of one of the axis controlled by the SMC
|
|
261
|
-
position (float): when the given axis is a rotation stage, the position is given
|
|
262
|
-
in degrees [deg], for a translation stage, the position is given
|
|
263
|
-
in millimeter [mm].
|
|
264
|
-
wait (bool): Only return when the device is in position [default=True]
|
|
265
|
-
|
|
266
|
-
Returns:
|
|
267
|
-
Zero (0) is returned unless a limit switch was hit, in which case +1 is returned when the LIMIT+ switch
|
|
268
|
-
was hit, and -1 is returned when the LIMIT- switch was hit.
|
|
269
|
-
"""
|
|
270
|
-
|
|
271
|
-
# For the big rotation stage use the workaround to avoid continuous movement in the same
|
|
272
|
-
# direction, and to avoid the limit switch.
|
|
273
|
-
|
|
274
|
-
if axis == HC_SETTINGS.BIG_ROTATION_STAGE:
|
|
275
|
-
current = self.get_current_position(axis)
|
|
276
|
-
movement = calculate_relative_movement(current, position, avoidance=self.avoidance, hardstop=self.hardstop)
|
|
277
|
-
self.move_direct(axis, movement)
|
|
278
|
-
else:
|
|
279
|
-
self.goto_direct(axis, position)
|
|
280
|
-
|
|
281
|
-
if wait:
|
|
282
|
-
return self.wait_until_axis_ready(axis)
|
|
283
|
-
|
|
284
|
-
return 0
|
|
285
|
-
|
|
286
|
-
@dynamic_command(
|
|
287
|
-
cmd_type="write", cmd_string="goto${axis}:${position}",
|
|
288
|
-
process_cmd_string=process_cmd_string)
|
|
289
|
-
def goto_direct(self, axis: int, position: float) -> None:
|
|
290
|
-
"""
|
|
291
|
-
Moves the stage to the given absolute position. No position checking nor conversion is done.
|
|
292
|
-
|
|
293
|
-
A positive angle moves the rotation stage counter clockwise.
|
|
294
|
-
|
|
295
|
-
Args:
|
|
296
|
-
axis (int): the integer identifier of one of the axis controlled by the SMC
|
|
297
|
-
position (float): when the given axis is a rotation stage, the position is given
|
|
298
|
-
in degrees [deg], for a translation stage, the position is given
|
|
299
|
-
in millimeter [mm].
|
|
300
|
-
"""
|
|
301
|
-
raise NotImplementedError
|
|
302
|
-
|
|
303
|
-
def move(self, axis: int, distance: float, wait: bool = True) -> int:
|
|
304
|
-
"""
|
|
305
|
-
Moves the stage relative to the current position in the given distance.
|
|
306
|
-
|
|
307
|
-
A positive angle moves the rotation stage counterclockwise.
|
|
308
|
-
|
|
309
|
-
Args:
|
|
310
|
-
axis: the integer identifier of one of the axis controlled by the SMC
|
|
311
|
-
distance: when the given axis is a rotation stage, the distance is given
|
|
312
|
-
in degrees [deg], for a translation stage, the distance is given
|
|
313
|
-
in millimeter [mm].
|
|
314
|
-
wait (bool): Only return when the device is in position [default=True]
|
|
315
|
-
|
|
316
|
-
Returns:
|
|
317
|
-
Zero (0) is returned unless a limit switch was hit, in which case +1 is returned when the LIMIT+ switch
|
|
318
|
-
was hit, and -1 is returned when the LIMIT- switch was hit.
|
|
319
|
-
"""
|
|
320
|
-
self.move_direct(axis, distance)
|
|
321
|
-
if wait:
|
|
322
|
-
return self.wait_until_axis_ready(axis)
|
|
323
|
-
return 0
|
|
324
|
-
|
|
325
|
-
@dynamic_command(
|
|
326
|
-
cmd_type="write", cmd_string="move${axis}:${distance}",
|
|
327
|
-
process_cmd_string=process_cmd_string,
|
|
328
|
-
)
|
|
329
|
-
def move_direct(self, axis: int, distance: float) -> None:
|
|
330
|
-
"""
|
|
331
|
-
Moves the stage relative to the current position in the given distance.
|
|
332
|
-
|
|
333
|
-
A positive angle moves the rotation stage counterclockwise.
|
|
334
|
-
|
|
335
|
-
Args:
|
|
336
|
-
axis: the integer identifier of one of the axis controlled by the SMC
|
|
337
|
-
distance: when the given axis is a rotation stage, the distance is given
|
|
338
|
-
in degrees [deg], for a translation stage, the distance is given
|
|
339
|
-
in millimeter [mm].
|
|
340
|
-
"""
|
|
341
|
-
raise NotImplementedError
|
|
342
|
-
|
|
343
|
-
@dynamic_command(
|
|
344
|
-
cmd_type="write", cmd_string="home${axis}:he;hm${pos}",
|
|
345
|
-
process_cmd_string=process_cmd_string,
|
|
346
|
-
)
|
|
347
|
-
def home_forward_direction(self, axis: int, pos: float = 0):
|
|
348
|
-
"""
|
|
349
|
-
Execute a home position search procedure for the given axis. This function will search in
|
|
350
|
-
forward direction for the encoder ECZ (index) signal and set the position to `pos`.
|
|
351
|
-
|
|
352
|
-
Args:
|
|
353
|
-
axis: the integer identifier of one of the axis controlled by the SMC, this
|
|
354
|
-
should be '3' for the translation stage (the other axes have an absolute encoder).
|
|
355
|
-
pos: after the home is found, set the position to `pos`.
|
|
356
|
-
|
|
357
|
-
"""
|
|
358
|
-
raise NotImplementedError
|
|
359
|
-
|
|
360
|
-
@dynamic_command(
|
|
361
|
-
cmd_type="write", cmd_string="home${axis}:he;hr${pos}",
|
|
362
|
-
process_cmd_string=process_cmd_string,
|
|
363
|
-
)
|
|
364
|
-
def home_reverse_direction(self, axis: int, pos: float = 0):
|
|
365
|
-
"""
|
|
366
|
-
Execute a home position search procedure for the given axis. This function will search in
|
|
367
|
-
reverse direction for the encoder ECZ (index) signal and set the position to `pos`.
|
|
368
|
-
|
|
369
|
-
Args:
|
|
370
|
-
axis: the integer identifier of one of the axis controlled by the SMC, this
|
|
371
|
-
should be '3' for the translation stage (the other axes have an absolute encoder).
|
|
372
|
-
pos: after the home is found, set the position to `pos`.
|
|
373
|
-
|
|
374
|
-
"""
|
|
375
|
-
raise NotImplementedError
|
|
376
|
-
|
|
377
|
-
@dynamic_command(
|
|
378
|
-
cmd_type="write", cmd_string="ffast${axis}:${speed}",
|
|
379
|
-
process_cmd_string=process_cmd_string)
|
|
380
|
-
def set_slew_speed(self, axis, speed):
|
|
381
|
-
"""
|
|
382
|
-
Configures the maximum slew speed used for the execution of manual
|
|
383
|
-
positioning commands. The maximum speed depends on the motor type,
|
|
384
|
-
driver type and positioning hardware properties.
|
|
385
|
-
|
|
386
|
-
For axis=1 (big rotation stage) the slew speed is given in 1e-4 deg/s, i.e. a slew_speed of
|
|
387
|
-
15_000 results in an actual speed of 1.5deg/s.
|
|
388
|
-
|
|
389
|
-
Manual positioning commands are i.e. ``fast``, ``move``, ``goto``, or
|
|
390
|
-
the use of the direction keys.
|
|
391
|
-
"""
|
|
392
|
-
raise NotImplementedError
|
|
393
|
-
|
|
394
|
-
def get_slew_speed(self, axis) -> int:
|
|
395
|
-
"""
|
|
396
|
-
Returns the maximum slew speed used for the execution of manual
|
|
397
|
-
positioning commands. The maximum speed depends on the motor type,
|
|
398
|
-
driver type and positioning hardware properties.
|
|
399
|
-
"""
|
|
400
|
-
return int(self.get_parameter(axis, "ffast")[-1])
|
|
401
|
-
|
|
402
|
-
@dynamic_command(
|
|
403
|
-
cmd_type="write", cmd_string="edev${axis}:${value}",
|
|
404
|
-
process_cmd_string=process_cmd_string)
|
|
405
|
-
def set_edev(self, axis, value):
|
|
406
|
-
"""
|
|
407
|
-
Configure the maximum allowed deviation between actual position
|
|
408
|
-
and commanded target position for closed-loop positioning. this
|
|
409
|
-
value must not be less than the resolution of the used encoder.
|
|
410
|
-
|
|
411
|
-
This command cannot be executed during positioning or program execution.
|
|
412
|
-
"""
|
|
413
|
-
raise NotImplementedError
|
|
414
|
-
|
|
415
|
-
def get_edev(self, axis) -> float:
|
|
416
|
-
"""
|
|
417
|
-
Returns the maximum allowed deviation between actual position
|
|
418
|
-
and commanded target position for closed-loop positioning.
|
|
419
|
-
"""
|
|
420
|
-
return float(self.get_parameter(axis, "edev")[-1])
|
|
421
|
-
|
|
422
|
-
@dynamic_command(
|
|
423
|
-
cmd_type="write", cmd_string="edir${axis}:${value}",
|
|
424
|
-
process_cmd_string=process_cmd_string)
|
|
425
|
-
def set_edir(self, axis, value):
|
|
426
|
-
"""
|
|
427
|
-
Configure the encoder rotation sense. For the case the controller returns the encoder
|
|
428
|
-
position information with the wrong sign, use this command to change it correspondingly.
|
|
429
|
-
|
|
430
|
-
This command cannot be executed during positioning or program execution.
|
|
431
|
-
"""
|
|
432
|
-
raise NotImplementedError
|
|
433
|
-
|
|
434
|
-
def get_edir(self, axis) -> int:
|
|
435
|
-
"""
|
|
436
|
-
Returns the encoder rotation sense: 0 is normal, 1 is inverted.
|
|
437
|
-
"""
|
|
438
|
-
return int(self.get_parameter(axis, "edir")[-1])
|
|
439
|
-
|
|
440
|
-
def is_in_position(self, axis) -> bool:
|
|
441
|
-
"""
|
|
442
|
-
Returns True if the mechanism is in position and not moving.
|
|
443
|
-
"""
|
|
444
|
-
|
|
445
|
-
# The sleep of 0.5s here is empirically determined because tests failed randomly
|
|
446
|
-
# because the position was apparently not completely reached. We also noticed an
|
|
447
|
-
# oscilation when arriving at a certain position. A diagnostic test revealed that
|
|
448
|
-
# the status sometimes changes bit 0 and bit 7 indicating the axis/controller
|
|
449
|
-
# ready before the mechanism actually reached the setpoint. We need about
|
|
450
|
-
# 0.2s before the actual value is reached, 0.5 seconds is a safe wait time.
|
|
451
|
-
|
|
452
|
-
time.sleep(0.5)
|
|
453
|
-
|
|
454
|
-
state = self.get_state(axis)
|
|
455
|
-
|
|
456
|
-
return state & 0b10000001 == 0b10000001
|
|
457
|
-
|
|
458
|
-
@dynamic_command(
|
|
459
|
-
cmd_type="query", cmd_string="?p${axis}",
|
|
460
|
-
process_cmd_string=process_cmd_string,
|
|
461
|
-
process_response=decode_axis_float)
|
|
462
|
-
def get_current_position(self, axis) -> float:
|
|
463
|
-
"""
|
|
464
|
-
Returns the current position for this axis as a float. The position is
|
|
465
|
-
given in degrees for rotation stages and in mm for translation stages.
|
|
466
|
-
"""
|
|
467
|
-
raise NotImplementedError
|
|
468
|
-
|
|
469
|
-
@dynamic_command(
|
|
470
|
-
cmd_type="query", cmd_string="?e${axis}",
|
|
471
|
-
process_cmd_string=process_cmd_string,
|
|
472
|
-
process_response=decode_axis_float)
|
|
473
|
-
def get_current_encoder_position(self, axis) -> float:
|
|
474
|
-
"""
|
|
475
|
-
Returns the current encoder position for this axis as a float. The position
|
|
476
|
-
is given in degrees for rotation stages and in mm for translation stages.
|
|
477
|
-
"""
|
|
478
|
-
raise NotImplementedError
|
|
479
|
-
|
|
480
|
-
@dynamic_command(
|
|
481
|
-
cmd_type="query", cmd_string="?ec${axis}",
|
|
482
|
-
process_cmd_string=process_cmd_string,
|
|
483
|
-
process_response=decode_axis_int)
|
|
484
|
-
def get_current_encoder_counter_value(self, axis) -> int:
|
|
485
|
-
"""
|
|
486
|
-
Returns the current encoder counter value for this axis as an int.
|
|
487
|
-
"""
|
|
488
|
-
raise NotImplementedError
|
|
489
|
-
|
|
490
|
-
@dynamic_command(
|
|
491
|
-
cmd_type="query", cmd_string="?err${axis}",
|
|
492
|
-
process_cmd_string=process_cmd_string,
|
|
493
|
-
process_response=decode_get_error)
|
|
494
|
-
def get_error(self, axis) -> Tuple[str]:
|
|
495
|
-
"""
|
|
496
|
-
Returns the last occurred error and corresponding error message for the given axis.
|
|
497
|
-
"""
|
|
498
|
-
raise NotImplementedError
|
|
499
|
-
|
|
500
|
-
@dynamic_command(
|
|
501
|
-
cmd_type="query", cmd_string="?${name}${axis}",
|
|
502
|
-
process_cmd_string=process_cmd_string,
|
|
503
|
-
process_response=decode_get_parameter)
|
|
504
|
-
def get_parameter(self, axis, name) -> Tuple[str, int, str]:
|
|
505
|
-
"""
|
|
506
|
-
Queries the device for the current value of the given parameter and the given axis.
|
|
507
|
-
|
|
508
|
-
Returns:
|
|
509
|
-
A tuple containing the parameter name (str), axis (int), and the value (str).
|
|
510
|
-
"""
|
|
511
|
-
raise NotImplementedError
|
|
512
|
-
|
|
513
|
-
@dynamic_command(
|
|
514
|
-
cmd_type="write", cmd_string="cerr${axis}",
|
|
515
|
-
process_cmd_string=process_cmd_string)
|
|
516
|
-
def clear_error(self, axis):
|
|
517
|
-
"""
|
|
518
|
-
Reset the last occurred error and clear the error message.
|
|
519
|
-
"""
|
|
520
|
-
raise NotImplementedError
|
|
521
|
-
|
|
522
|
-
@dynamic_command(
|
|
523
|
-
cmd_type="write", cmd_string="quit",
|
|
524
|
-
process_cmd_string=process_cmd_string)
|
|
525
|
-
def quit(self) -> None:
|
|
526
|
-
"""
|
|
527
|
-
Immediately stop any positioning process.
|
|
528
|
-
|
|
529
|
-
The controller decelerates with the configured deceleration ramp.
|
|
530
|
-
In contrast to an emergency stop caused by limit switch events,
|
|
531
|
-
the position information remains valid in this case.
|
|
532
|
-
"""
|
|
533
|
-
raise NotImplementedError
|
|
534
|
-
|
|
535
|
-
@dynamic_command(cmd_type="write", cmd_string="update", process_cmd_string=process_cmd_string)
|
|
536
|
-
def save_configuration(self):
|
|
537
|
-
"""Saves the current configuration permanently. The settings will be reloaded automatically
|
|
538
|
-
the next time the controller starts."""
|
|
539
|
-
raise NotImplementedError
|
|
540
|
-
|
|
541
|
-
@dynamic_command(cmd_type="write", cmd_string="reset", process_cmd_string=process_cmd_string)
|
|
542
|
-
def reset(self):
|
|
543
|
-
"""Resets the controller back to power-on state. When you previously saved the configuration,
|
|
544
|
-
those values will be reloaded automatically, otherwise the default configuration will be loaded."""
|
|
545
|
-
raise NotImplementedError
|
|
546
|
-
|
|
547
|
-
@dynamic_command(
|
|
548
|
-
cmd_type="query", cmd_string="?s${axis}",
|
|
549
|
-
process_cmd_string=process_cmd_string,
|
|
550
|
-
process_response=decode_get_state)
|
|
551
|
-
def get_state(self, axis) -> int:
|
|
552
|
-
"""Query of the current operating state of the controller."""
|
|
553
|
-
raise NotImplementedError
|
|
554
|
-
|
|
555
|
-
@dynamic_command(
|
|
556
|
-
cmd_type="query", cmd_string="?status${axis}",
|
|
557
|
-
process_cmd_string=process_cmd_string,
|
|
558
|
-
process_response=decode_response)
|
|
559
|
-
def get_status(self, axis) -> str:
|
|
560
|
-
"""
|
|
561
|
-
Returns the status of the given axis. The status contains the following information:
|
|
562
|
-
|
|
563
|
-
* axis: the axis number
|
|
564
|
-
* err_no: the error number
|
|
565
|
-
* err_msg: the error message if there is an error
|
|
566
|
-
* pos: the current position
|
|
567
|
-
* epos: the encoder position
|
|
568
|
-
* elimit: end/limit status
|
|
569
|
-
* ref: reference status
|
|
570
|
-
* eref: encoder reference status
|
|
571
|
-
* ctrl: is controller ready?
|
|
572
|
-
* osc: status oscillation
|
|
573
|
-
* pro: is program running?
|
|
574
|
-
|
|
575
|
-
The status response can be untangled as follows:
|
|
576
|
-
|
|
577
|
-
>>> dev = HuberSMC9300Proxy()
|
|
578
|
-
>>> untangle_status(dev.get_status(axis=1))
|
|
579
|
-
|
|
580
|
-
"""
|
|
581
|
-
raise NotImplementedError
|
|
582
|
-
|
|
583
|
-
@dynamic_command(
|
|
584
|
-
cmd_type="write", cmd_string="zero${axis}",
|
|
585
|
-
process_cmd_string=process_cmd_string)
|
|
586
|
-
def zero(self, axis) -> None:
|
|
587
|
-
"""
|
|
588
|
-
Set the current position of the axis to zero (0.00). If a reference position
|
|
589
|
-
offset value is configured (see the configuration command `rofs`) the current
|
|
590
|
-
position is set to that reference offset value.
|
|
591
|
-
|
|
592
|
-
If you want to retain this zero position, you will have to also call the
|
|
593
|
-
'save_configuration()' command. Otherwise the zero position will be lost
|
|
594
|
-
after a reset or a power cycle.
|
|
595
|
-
"""
|
|
596
|
-
raise NotImplementedError
|
|
597
|
-
|
|
598
|
-
def wait_until_axis_ready(self, axis: int) -> int:
|
|
599
|
-
"""
|
|
600
|
-
Send the given axis a state query and wait for the response.
|
|
601
|
-
|
|
602
|
-
This function will return only when one of the following states has been reached:
|
|
603
|
-
|
|
604
|
-
* The LIMIT- switch was activated
|
|
605
|
-
* The LIMIT+ switch was activated
|
|
606
|
-
* The end position was reached, axis ready (bit 0) & controller ready (bit 7)
|
|
607
|
-
|
|
608
|
-
Returns:
|
|
609
|
-
|
|
610
|
-
* 0: on success, i.e. position is reached
|
|
611
|
-
* +1: when LIMIT+ switch is reached
|
|
612
|
-
* -1: when LIMIT- switch is reached
|
|
613
|
-
"""
|
|
614
|
-
|
|
615
|
-
# MODULE_LOGGER.debug(f"Wait until axis {axis} is ready...")
|
|
616
|
-
|
|
617
|
-
while True:
|
|
618
|
-
|
|
619
|
-
time.sleep(0.5)
|
|
620
|
-
|
|
621
|
-
state = self.get_state(axis)
|
|
622
|
-
|
|
623
|
-
# MODULE_LOGGER.debug(f"state for axis {axis}: {beautify_binary(state)} ({state})")
|
|
624
|
-
|
|
625
|
-
if state & 4 == 4:
|
|
626
|
-
MODULE_LOGGER.warning("LIMIT- active!")
|
|
627
|
-
rv = -1
|
|
628
|
-
break
|
|
629
|
-
|
|
630
|
-
if state & 8 == 8:
|
|
631
|
-
MODULE_LOGGER.warning("LIMIT+ active!")
|
|
632
|
-
rv = +1
|
|
633
|
-
break
|
|
634
|
-
|
|
635
|
-
if state & 512 == 512:
|
|
636
|
-
MODULE_LOGGER.error("oscillation positioning error (encoder)")
|
|
637
|
-
|
|
638
|
-
if state & 129 == 129:
|
|
639
|
-
# exit loop when position is reached,
|
|
640
|
-
# state bit 0 and bit 7 indicate 'axis ready' AND 'controller ready',
|
|
641
|
-
# i.e. all axes stopped
|
|
642
|
-
rv = 0
|
|
643
|
-
break
|
|
644
|
-
|
|
645
|
-
if state & 16384: # 0b100_0000_0000_0000
|
|
646
|
-
response = self.get_error(axis)
|
|
647
|
-
MODULE_LOGGER.error(f"ERROR on axis {axis}: {response}")
|
|
648
|
-
self.clear_error(axis)
|
|
649
|
-
|
|
650
|
-
# The sleep of 0.5s here is empirically determined because tests failed randomly
|
|
651
|
-
# because the position was apparently not completely reached. We also noticed an
|
|
652
|
-
# oscillation when arriving at a certain position. A diagnostic test revealed that
|
|
653
|
-
# the state sometimes changes bit 0 and bit 7 indicating the axis/controller
|
|
654
|
-
# ready before the mechanism actually reached the setpoint. We need about
|
|
655
|
-
# 0.2s before the actual value is reached, 0.5 seconds is a safe wait time.
|
|
656
|
-
|
|
657
|
-
time.sleep(0.5)
|
|
658
|
-
|
|
659
|
-
return rv
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
class HuberSMC9300Controller(HuberSMC9300Interface, DynamicCommandMixin):
|
|
663
|
-
"""
|
|
664
|
-
The HuberSmC9300Controller class is used to directly communicate with the HUBER SMC9300
|
|
665
|
-
Controller through an Ethernet interface.
|
|
666
|
-
"""
|
|
667
|
-
|
|
668
|
-
def __init__(self, hostname=HC_SETTINGS.HOSTNAME, port=HC_SETTINGS.PORT):
|
|
669
|
-
"""
|
|
670
|
-
Opens a TCP/IP socket connection with the HUBER SMC9300 Hardware Controller.
|
|
671
|
-
|
|
672
|
-
Args:
|
|
673
|
-
hostname (str): the IP address or fully qualified hostname of the HUBER hardware
|
|
674
|
-
controller. The default is defined in the ``settings.yaml`` configuration file.
|
|
675
|
-
|
|
676
|
-
port (int): the IP port number to connect to, by default set in the `settings.yaml`
|
|
677
|
-
configuration file.
|
|
678
|
-
|
|
679
|
-
"""
|
|
680
|
-
super().__init__()
|
|
681
|
-
|
|
682
|
-
MODULE_LOGGER.info(
|
|
683
|
-
f"Initializing Huber SMC9300 Controller with hostname={hostname} on port={port}")
|
|
684
|
-
|
|
685
|
-
self.transport = self.huber = HuberSMC9300EthernetInterface(hostname, port)
|
|
686
|
-
|
|
687
|
-
self._number_of_axes = HC_SETTINGS.NUMBER_OF_AXES
|
|
688
|
-
|
|
689
|
-
def connect(self):
|
|
690
|
-
try:
|
|
691
|
-
self.huber.connect()
|
|
692
|
-
|
|
693
|
-
# set the speed of each of the stages to the default speed from the Settings.
|
|
694
|
-
|
|
695
|
-
for stage in 1, 2, 3:
|
|
696
|
-
default_speed = HC_SETTINGS.DEFAULT_SPEED[stage - 1]
|
|
697
|
-
self.set_slew_speed(stage, default_speed)
|
|
698
|
-
|
|
699
|
-
except HuberError as exc:
|
|
700
|
-
MODULE_LOGGER.warning(f"HuberError caught: Couldn't establish connection ({exc})")
|
|
701
|
-
raise ConnectionError("Couldn't establish a connection with the HUBER Stage.") from exc
|
|
702
|
-
|
|
703
|
-
self.notify_observers(DeviceConnectionState.DEVICE_CONNECTED)
|
|
704
|
-
|
|
705
|
-
def disconnect(self):
|
|
706
|
-
try:
|
|
707
|
-
# Clear the error for each of the axis before disconnecting
|
|
708
|
-
for axis in range(1, self._number_of_axes + 1):
|
|
709
|
-
self.clear_error(axis)
|
|
710
|
-
self.huber.disconnect()
|
|
711
|
-
except DeviceConnectionError as exc:
|
|
712
|
-
raise ConnectionError("Couldn't disconnect from HUBER Controller.") from exc
|
|
713
|
-
|
|
714
|
-
self.notify_observers(DeviceConnectionState.DEVICE_NOT_CONNECTED)
|
|
715
|
-
|
|
716
|
-
def reconnect(self):
|
|
717
|
-
if self.is_connected():
|
|
718
|
-
self.disconnect()
|
|
719
|
-
self.connect()
|
|
720
|
-
|
|
721
|
-
def is_connected(self):
|
|
722
|
-
"""Check if the HUBER Stages Controller is connected. """
|
|
723
|
-
return self.huber.is_connected()
|
|
724
|
-
|
|
725
|
-
def is_simulator(self):
|
|
726
|
-
return "simulator: true" in self.info()
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
class HuberSMC9300Simulator(HuberSMC9300Interface):
|
|
730
|
-
"""
|
|
731
|
-
The class simulates the HUBER Stages.
|
|
732
|
-
"""
|
|
733
|
-
|
|
734
|
-
def __init__(self):
|
|
735
|
-
super().__init__()
|
|
736
|
-
MODULE_LOGGER.critical(
|
|
737
|
-
textwrap.dedent(
|
|
738
|
-
"""\
|
|
739
|
-
The HuberSMC9300Simulator class is deprecated in favor of the smc9300_sim process.
|
|
740
|
-
Start the SMC9300 simulator in a separate terminal with the command:
|
|
741
|
-
|
|
742
|
-
smc9300_sim start
|
|
743
|
-
|
|
744
|
-
then restart the SCM9300 Control Server:
|
|
745
|
-
|
|
746
|
-
smc9300_cs start
|
|
747
|
-
|
|
748
|
-
Make sure the local_settings.yaml file contains the correct HOSTNAME
|
|
749
|
-
and PORT for accessing the simulator process.
|
|
750
|
-
"""
|
|
751
|
-
)
|
|
752
|
-
)
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
REQUEST_TIMEOUT = 10_000 # 10 seconds
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
class HuberSMC9300Proxy(DynamicProxy, HuberSMC9300Interface):
|
|
759
|
-
"""
|
|
760
|
-
The HuberProxy class is used to connect to the Huber SMC9300 control server and send commands
|
|
761
|
-
to the HUBER Hardware Controller remotely.
|
|
762
|
-
"""
|
|
763
|
-
|
|
764
|
-
def __init__(
|
|
765
|
-
self,
|
|
766
|
-
protocol=CTRL_SETTINGS.PROTOCOL,
|
|
767
|
-
hostname=CTRL_SETTINGS.HOSTNAME,
|
|
768
|
-
port=CTRL_SETTINGS.COMMANDING_PORT,
|
|
769
|
-
timeout=REQUEST_TIMEOUT
|
|
770
|
-
):
|
|
771
|
-
"""
|
|
772
|
-
Args:
|
|
773
|
-
protocol: the transport protocol
|
|
774
|
-
[default is taken from settings file]
|
|
775
|
-
hostname: location of the control server (IP address)
|
|
776
|
-
[default is taken from settings file]
|
|
777
|
-
port: TCP port on which the control server is listening for commands
|
|
778
|
-
[default is taken from settings file]
|
|
779
|
-
timeout: time out on the response from the control server [milliseconds]
|
|
780
|
-
"""
|
|
781
|
-
|
|
782
|
-
DynamicProxy.__init__(self, connect_address(protocol, hostname, port), timeout=timeout) # explicit calls without super
|
|
783
|
-
HuberSMC9300Interface.__init__(self)
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
def calculate_relative_movement(current, setpoint, hardstop=None, avoidance=None):
|
|
787
|
-
"""
|
|
788
|
-
This function calculates the relative movement from the current position to the given setpoint.
|
|
789
|
-
It defines the direction and the size of the movement based on the current position,
|
|
790
|
-
the setpoint, the hardstop position and the avoidance angle.
|
|
791
|
-
|
|
792
|
-
The function strives to always return the smallest possible angle in order to minimize the
|
|
793
|
-
duration of the movement.
|
|
794
|
-
|
|
795
|
-
The target position (setpoint) can not fall in the range [hardstop - avoidance,
|
|
796
|
-
hardstop + avoidance]. There is no check on the current position, it is assumed not to be in
|
|
797
|
-
the avoidance range.
|
|
798
|
-
|
|
799
|
-
If hardstop or avoidance are not given, they are loaded from the setup.
|
|
800
|
-
|
|
801
|
-
Args:
|
|
802
|
-
current (float): the current position of the rotation stage
|
|
803
|
-
setpoint (float): the target position of the rotation stage
|
|
804
|
-
hardstop (float): the location of the hardstop
|
|
805
|
-
avoidance (float): angle of avoidance
|
|
806
|
-
setup: Setup
|
|
807
|
-
Returns:
|
|
808
|
-
The angle to move relative from current position to setpoint.
|
|
809
|
-
Raises:
|
|
810
|
-
A ValueError when the setpoint falls inside the avoidance range, i.e.
|
|
811
|
-
[-180 + avoidance, +180 - avoidance].
|
|
812
|
-
"""
|
|
813
|
-
|
|
814
|
-
if not avoidance or not hardstop:
|
|
815
|
-
setup = load_setup()
|
|
816
|
-
|
|
817
|
-
avoidance = avoidance or setup.gse.stages.big_rotation_stage.avoidance
|
|
818
|
-
hardstop = hardstop or setup.gse.stages.big_rotation_stage.hardstop
|
|
819
|
-
|
|
820
|
-
# avoidance = avoidance if avoidance is not None else setup.gse.stages.big_rotation_stage.avoidance
|
|
821
|
-
# hardstop = hardstop if hardstop is not None else setup.gse.stages.big_rotation_stage.hardstop
|
|
822
|
-
|
|
823
|
-
# MODULE_LOGGER.debug(f"@entry: {current=}, {setpoint=}, {hardstop=}, {avoidance=}")
|
|
824
|
-
|
|
825
|
-
# Bring the current and the setpoint between 0 and 360 (non-inclusive)
|
|
826
|
-
|
|
827
|
-
current %= 360
|
|
828
|
-
setpoint %= 360
|
|
829
|
-
|
|
830
|
-
# MODULE_LOGGER.debug(f"After % 360: {current=}, {setpoint=}")
|
|
831
|
-
|
|
832
|
-
# Check if the setpoint falls in the avoidance range
|
|
833
|
-
|
|
834
|
-
if hardstop - avoidance < setpoint < hardstop + avoidance:
|
|
835
|
-
print(f"{hardstop - avoidance} < {setpoint} < {hardstop + avoidance}")
|
|
836
|
-
raise ValueError(
|
|
837
|
-
f"setpoint argument shall NOT be between {hardstop - avoidance} and "
|
|
838
|
-
f"{hardstop + avoidance}, given value {setpoint = }")
|
|
839
|
-
|
|
840
|
-
# Find the smallest angle between the current and the setpoint
|
|
841
|
-
|
|
842
|
-
movement = min(abs(current - setpoint), abs(360 + current - setpoint))
|
|
843
|
-
direction = +1 if current + movement == setpoint else -1
|
|
844
|
-
|
|
845
|
-
target = current + direction * movement
|
|
846
|
-
|
|
847
|
-
# MODULE_LOGGER.debug(
|
|
848
|
-
# f"Smallest movement: {current=}, {setpoint=}, {target=:.2f}, "
|
|
849
|
-
# f"{movement=:.2f}, {direction=}"
|
|
850
|
-
# )
|
|
851
|
-
|
|
852
|
-
# Check if we will pass over 180º and invert direction if true.
|
|
853
|
-
|
|
854
|
-
if (current < target and current < hardstop < target) or \
|
|
855
|
-
(current > target and target < hardstop < current):
|
|
856
|
-
movement = 360 - movement
|
|
857
|
-
direction *= -1
|
|
858
|
-
|
|
859
|
-
# target = current + direction * movement
|
|
860
|
-
# MODULE_LOGGER.debug(
|
|
861
|
-
# f"corrected: {current=}, {setpoint=}, {target=:.2f}, {movement=:.2f}, {direction=}"
|
|
862
|
-
# )
|
|
863
|
-
|
|
864
|
-
return direction * movement
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
if __name__ == "__main__":
|
|
868
|
-
from rich import print
|
|
869
|
-
|
|
870
|
-
huber = HuberSMC9300Controller()
|
|
871
|
-
|
|
872
|
-
# The .connect() method takes 1.5s because it also configures the slew speed of all the axes
|
|
873
|
-
|
|
874
|
-
huber.connect()
|
|
875
|
-
|
|
876
|
-
print(f"{huber.info()=}")
|
|
877
|
-
print(f"{huber.get_version()=}")
|
|
878
|
-
print(f"{huber.get_error(axis=1)=}")
|
|
879
|
-
print(f"{huber.get_error(axis=2)=}")
|
|
880
|
-
print(f"{huber.get_error(axis=3)=}")
|
|
881
|
-
print(f"{huber.get_state(axis=1)=}")
|
|
882
|
-
print(f"{huber.get_state(axis=2)=}")
|
|
883
|
-
print(f"{huber.get_state(axis=3)=}")
|
|
884
|
-
print(f"{huber.get_status(axis=1)=}")
|
|
885
|
-
print(f"{huber.get_status(axis=2)=}")
|
|
886
|
-
print(f"{huber.get_status(axis=3)=}")
|
|
887
|
-
print(f"{huber.get_configuration(axis=1)=}")
|
|
888
|
-
print(f"{huber.get_configuration(axis=2)=}")
|
|
889
|
-
print(f"{huber.get_configuration(axis=3)=}")
|
|
890
|
-
print(f"{huber.get_conf_value(axis=1, name='gnum')=}")
|
|
891
|
-
print(f"{huber.get_slew_speed(axis=1)=}")
|
|
892
|
-
print(f"{huber.get_slew_speed(axis=2)=}")
|
|
893
|
-
print(f"{huber.get_slew_speed(axis=3)=}")
|
|
894
|
-
print(f"{huber.is_in_position(axis=1)=}")
|
|
895
|
-
print(f"{huber.is_in_position(axis=2)=}")
|
|
896
|
-
print(f"{huber.is_in_position(axis=3)=}")
|
|
897
|
-
print(f"{huber.get_current_position(axis=1)=}")
|
|
898
|
-
print(f"{huber.get_current_position(axis=2)=}")
|
|
899
|
-
print(f"{huber.get_current_position(axis=3)=}")
|
|
900
|
-
print(f"{huber.get_current_encoder_position(axis=1)=}")
|
|
901
|
-
print(f"{huber.get_current_encoder_position(axis=2)=}")
|
|
902
|
-
print(f"{huber.get_current_encoder_position(axis=3)=}")
|
|
903
|
-
print(f"{huber.get_current_encoder_counter_value(axis=1)=}")
|
|
904
|
-
print(f"{huber.get_current_encoder_counter_value(axis=2)=}")
|
|
905
|
-
print(f"{huber.get_current_encoder_counter_value(axis=3)=}")
|
|
906
|
-
|
|
907
|
-
for axis_ in range(1, 4):
|
|
908
|
-
print(f"{huber.get_parameter(axis=axis_, name='ffast')=}")
|
|
909
|
-
print(f"{huber.get_parameter(axis=axis_, name='frun')=}")
|
|
910
|
-
print(f"{huber.get_parameter(axis=axis_, name='rofs')=}")
|
|
911
|
-
print(f"{huber.get_parameter(axis=axis_, name='erofs')=}")
|
|
912
|
-
|
|
913
|
-
print(f"{huber.get_parameter(axis=axis_, name='ecl')=}")
|
|
914
|
-
print(f"{huber.get_parameter(axis=axis_, name='edev')=}")
|
|
915
|
-
print(f"{huber.get_parameter(axis=axis_, name='edir')=}")
|
|
916
|
-
print(f"{huber.get_parameter(axis=axis_, name='eres')=}")
|
|
917
|
-
|
|
918
|
-
huber.clear_error(axis=axis_)
|
|
919
|
-
|
|
920
|
-
huber.disconnect()
|