Test fixes
This commit is contained in:
1 parent
9aa4db3b3b
commit
8043785885
6 files changed
+80
-161
No files matched your search
@@ -280,7 +280,7 @@ class aa1AxisPsoDistance(AerotechPsoBase):
|
||||
"""Fire a single PSO event (i.e. manual software trigger)"""
|
||||
# Only trigger if distance was set to invalid
|
||||
# if self.dstDistanceVal.get() == 0:
|
||||
logger.warning(f"[{self.name}] Triggerin...")
|
||||
# logger.warning(f"[{self.name}] Triggerin...")
|
||||
return self.fire(settle_time)
|
||||
|
||||
def arm(self) -> None:
|
||||
|
||||
@@ -33,7 +33,7 @@ program
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Internal parameters - dont use
|
||||
var $axis as axis = ROTY
|
||||
var $axis as axis = {{ scan.rotaxis or 'ROTY' }}
|
||||
var $ii as integer
|
||||
var $axisFaults as integer = 0
|
||||
var $iDdcSafeSpace as integer = 4096
|
||||
|
||||
@@ -20,7 +20,7 @@ program
|
||||
|
||||
|
||||
// Internal
|
||||
var $axis as axis = ROTY
|
||||
var $axis as axis = {{ scan.rotaxis or 'ROTY' }}
|
||||
var $ii as integer
|
||||
var $axisFaults as integer = 0
|
||||
|
||||
|
||||
@@ -7,3 +7,7 @@ from .AerotechAutomation1 import (
|
||||
aa1GlobalVariableBindings,
|
||||
aa1AxisIo,
|
||||
)
|
||||
from .AerotechAutomation1Enums import (
|
||||
DriveDataCaptureInput,
|
||||
DriveDataCaptureTrigger,
|
||||
)
|
||||
@@ -16,7 +16,7 @@ import time
|
||||
import os
|
||||
import jinja2
|
||||
import numpy as np
|
||||
from ophyd import Component, EpicsMotor, EpicsSignal
|
||||
from ophyd import Component, EpicsMotor, EpicsSignal, EpicsSignalRO
|
||||
|
||||
|
||||
from tomcat_bec.devices.aerotech import (
|
||||
@@ -27,21 +27,22 @@ from tomcat_bec.devices.aerotech import (
|
||||
aa1Tasks,
|
||||
aa1AxisDriveDataCollection,
|
||||
aa1AxisPsoDistance,
|
||||
)
|
||||
|
||||
|
||||
from tomcat_bec.devices.aerotech.AerotechAutomation1Enums import (
|
||||
DriveDataCaptureInput,
|
||||
DriveDataCaptureTrigger,
|
||||
)
|
||||
|
||||
os.environ["EPICS_CA_ADDR_LIST"] = "129.129.106.255"
|
||||
|
||||
os.environ["EPICS_CA_ADDR_LIST"] = "129.129.106.255 129.129.99.255"
|
||||
AA1_IOC_NAME = "X02DA-ES1-SMP1"
|
||||
AA1_AXIS_NAME = "ROTY"
|
||||
MOTOR_TOL = 1.0
|
||||
AA1_IOC_AXIS = "ROTY"
|
||||
AA1_DRV_AXIS = "RY"
|
||||
AXIS_VELOCITY = 42
|
||||
AXIS_TRAVEL = 80
|
||||
AXIS_TOL = 1.0
|
||||
|
||||
class AerotechMotor(EpicsMotor):
|
||||
""" EpicsMotor extension with additional PVs"""
|
||||
motor_enable_rbv = Component(EpicsSignalRO, "-EnaAct", kind="omitted", auto_monitor=True)
|
||||
motor_enable = Component(EpicsSignal, ".CNEN", kind="omitted", auto_monitor=True)
|
||||
|
||||
|
||||
@@ -56,7 +57,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
# HIL testing only if there's hardware
|
||||
dev = aa1Controller(AA1_IOC_NAME + ":CTRL:", name="aa1")
|
||||
dev.wait_for_connection()
|
||||
mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="mot")
|
||||
mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_IOC_AXIS, name="mot")
|
||||
mot.wait_for_connection()
|
||||
mot.motor_enable.set(1, settle_time=0.1).wait()
|
||||
cls._isConnected = True
|
||||
@@ -83,7 +84,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
|
||||
print("TASK: Testing the 'run' command (run text with intermediary file)")
|
||||
# Send another empty program
|
||||
filename = "unittesting2.ascript"
|
||||
filename = "test_program.ascript"
|
||||
text = "program\nvar $positions[4] as real = [2, 4, 8, 16]\nend"
|
||||
dev.configure({'script_file': filename, 'script_task': 3, 'script_text': text})
|
||||
dev.arm()
|
||||
@@ -120,21 +121,21 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
|
||||
# # Attempt to run a short motion command using the Execute interface
|
||||
print("TASK: Testing a short motion command")
|
||||
text = """
|
||||
text = f"""
|
||||
var $fDist as real = 90
|
||||
var $fVelo as real = 200
|
||||
var $axis as axis = ROTY
|
||||
var $fVelo as real = 60
|
||||
var $axis as axis = {AA1_DRV_AXIS}
|
||||
Enable($axis)
|
||||
MoveLinear($axis, $fDist, $fVelo)
|
||||
"""
|
||||
dev.configure({'script_task': 3, 'script_text': text})
|
||||
dev.configure({'script_task': 3, 'script_text': text, 'script_file': "test_shortmove.ascript"})
|
||||
dev.arm()
|
||||
t_start = time.time()
|
||||
dev.kickoff()
|
||||
dev.complete().wait()
|
||||
t_end = time.time()
|
||||
t_elapsed = t_end - t_start
|
||||
self.assertTrue( 0 < t_elapsed < 4, f"Motion finished outside of window in: {t_elapsed}")
|
||||
self.assertTrue( 1 < t_elapsed < 4, f"Motion finished outside of window in: {t_elapsed}")
|
||||
dev.unstage()
|
||||
|
||||
print("TASK: Done testing TASK module!")
|
||||
@@ -268,7 +269,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
$iglobal[1]={val_i}
|
||||
$rglobal[1]={val_f}
|
||||
"""
|
||||
tsk.configure({'script_text': text, 'script_task': 4})
|
||||
tsk.configure({'script_text': text, 'script_task': 4, 'script_file': "test_global.ascript"})
|
||||
tsk.arm()
|
||||
tsk.launch()
|
||||
tsk.complete().wait()
|
||||
@@ -285,19 +286,30 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
|
||||
def test_05_axis_motorrecord(self):
|
||||
"""Tests the basic move functionality of the MotorRecord"""
|
||||
mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="x")
|
||||
mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_IOC_AXIS, name="x")
|
||||
mot.wait_for_connection()
|
||||
mot.motor_enable.set(1, settle_time=0.1).wait()
|
||||
mot.velocity.set(200).wait()
|
||||
mot.velocity.set(AXIS_VELOCITY).wait()
|
||||
print("\nMR: Checking the standard EPICS motor record")
|
||||
|
||||
# Test enabling/disabling the axis
|
||||
mot.motor_enable.set(1, settle_time=0.1).wait()
|
||||
time.sleep(1)
|
||||
self.assertTrue(mot.motor_enable_rbv.value, "Motor should be enabled")
|
||||
mot.motor_enable.set(0, settle_time=0.1).wait()
|
||||
time.sleep(1)
|
||||
self.assertFalse(mot.motor_enable_rbv.value, "Motor should be disabled")
|
||||
mot.motor_enable.set(1, settle_time=0.1).wait()
|
||||
time.sleep(1)
|
||||
self.assertTrue(mot.motor_enable_rbv.value, "Motor should be enabled")
|
||||
|
||||
# Four test with absolute moves
|
||||
def move_rel(dist):
|
||||
target = mot.position + dist
|
||||
print(f"Absolute move to {target}, distance: {dist}")
|
||||
mot.move(target, wait=True)
|
||||
self.assertTrue(
|
||||
np.abs(target - mot.position) < MOTOR_TOL,
|
||||
np.abs(target - mot.position) < AXIS_TOL,
|
||||
f"Final position {mot.position} is too far from target {target}",
|
||||
)
|
||||
|
||||
@@ -311,7 +323,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
def test_06_axis_io(self):
|
||||
"""Test axis IO bindings"""
|
||||
# Throws if IOC is not available or PVs are incorrect
|
||||
dev = aa1AxisIo(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":IO:", name="io")
|
||||
dev = aa1AxisIo(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":IO:", name="io")
|
||||
dev.wait_for_connection()
|
||||
|
||||
# Writing random values to analog/digital outputs
|
||||
@@ -338,9 +350,9 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
configuration, state monitoring and readback.
|
||||
"""
|
||||
# Throws if IOC is not available or PVs are incorrect
|
||||
dev = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc")
|
||||
dev = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":DDC:", name="ddc")
|
||||
event = EpicsSignal(
|
||||
AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":PSO:EVENT:SINGLE", put_complete=True
|
||||
AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":PSO:EVENT:SINGLE", put_complete=True
|
||||
)
|
||||
dev.wait_for_connection()
|
||||
event.wait_for_connection()
|
||||
@@ -464,9 +476,9 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
the PSO module and the polled feedback.
|
||||
"""
|
||||
# Throws if IOC is not available or PVs are incorrect
|
||||
pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":PSO:", name="pso1")
|
||||
ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc")
|
||||
mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name=AA1_AXIS_NAME.lower())
|
||||
pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":PSO:", name="pso1")
|
||||
ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":DDC:", name="ddc")
|
||||
mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_IOC_AXIS, name=AA1_IOC_AXIS.lower())
|
||||
mot.wait_for_connection()
|
||||
pso.wait_for_connection()
|
||||
ddc.wait_for_connection()
|
||||
@@ -479,7 +491,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
# Configure steps and move to middle of range
|
||||
pso.configure({"pso_distance": 5, "pso_wavemode": "toggle"})
|
||||
pso.arm()
|
||||
mot.velocity.set(200).wait()
|
||||
mot.velocity.set(AXIS_VELOCITY).wait()
|
||||
mot.move(mot.position + 2.5, wait=True)
|
||||
|
||||
ddc.arm()
|
||||
@@ -527,7 +539,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
pso.disarm()
|
||||
ddc.disarm()
|
||||
|
||||
print("AX:PSO: Checking basic 'pulsed' event generation with DDC (3/5)")
|
||||
print("AX:PSO: Checking basic 'pulsed' event generation with DDC (3/3)")
|
||||
# Configure steps and move to middle of range
|
||||
pso.configure({"pso_distance": 1.8, "pso_wavemode": "pulsed", "pso_n_pulse": 3})
|
||||
pso.arm()
|
||||
@@ -565,9 +577,9 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
and compares them to the expected values.
|
||||
"""
|
||||
# Throws if IOC is not available or PVs are incorrect
|
||||
pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":PSO:", name="pso1")
|
||||
ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc")
|
||||
mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="x")
|
||||
pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":PSO:", name="pso1")
|
||||
ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":DDC:", name="ddc")
|
||||
mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_IOC_AXIS, name="x")
|
||||
mot.wait_for_connection()
|
||||
pso.wait_for_connection()
|
||||
ddc.wait_for_connection()
|
||||
@@ -578,7 +590,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
"\ntest_09_PsoIntegration01: Integration test for vector PSO triggering (advanced)"
|
||||
)
|
||||
|
||||
print("AX:PSO: Testing standard 'enable' style PSO triggering with DDC (1/3)")
|
||||
print("AX:PSO: Testing standard 'enable' style PSO triggering with DDC (1/2)")
|
||||
# This is one line of the Tomcat sequence scan!
|
||||
acc_dist = 0.5 * mot.velocity.value * mot.acceleration.value
|
||||
vec_dist = [acc_dist, 18, 0.01, 18, 0.01, 18, 0.01, 18, 0.01, 18, 0.01, 18]
|
||||
@@ -615,7 +627,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
pso.unstage()
|
||||
ddc.unstage()
|
||||
|
||||
print("AX:PSO: Checking 'individual' style trigger signal with DDC (2/5)")
|
||||
print("AX:PSO: Checking 'individual' style trigger signal with DDC (2/2)")
|
||||
# This is practically golden ratio tomography!
|
||||
acc_dist = 0.5 * mot.velocity.value * mot.acceleration.value
|
||||
vec_dist = [acc_dist]
|
||||
@@ -654,114 +666,16 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
pso.unstage()
|
||||
ddc.unstage()
|
||||
|
||||
# def test_10_AxisPsoWindow1(self):
|
||||
# """ Test basic PSO window mode functionality
|
||||
|
||||
# This module tests basic PSO distance functionality, like events and
|
||||
# waveform generation. The goal is to ensure the basic operation of
|
||||
# the PSO module and the polled feedback.
|
||||
# """
|
||||
# # Throws if IOC is not available or PVs are incorrect
|
||||
# pso = aa1AxisPsoWindow(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":PSO:", name="pso1")
|
||||
# ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc")
|
||||
# mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="x")
|
||||
# mot.wait_for_connection()
|
||||
# pso.wait_for_connection()
|
||||
# ddc.wait_for_connection()
|
||||
# pso.unstage()
|
||||
# ddc.unstage()
|
||||
# mot.unstage()
|
||||
# print("\nAX:PSO: Checking axis PSO in window mode (basic)")
|
||||
|
||||
# print("AX:PSO: Directly checking basic window output (1/3)")
|
||||
# # Configure steps and move to middle of range
|
||||
# pso.configure({'bounds': (5, 13), 'pso_wavemode': "output"})
|
||||
# time.sleep(1)
|
||||
# # Move half a step
|
||||
# mot.move(mot.position + 0.1)
|
||||
# dist = 0.1
|
||||
|
||||
# # Start moving in steps, while checking output
|
||||
# for ii in range(42):
|
||||
# mot.move(mot.position + 0.2)
|
||||
# dist += 0.2
|
||||
# time.sleep(1)
|
||||
# if 5 < dist < 13:
|
||||
# self.assertTrue(pso.output.value == 1,
|
||||
# f"Expected HIGH PSO output inside the window at distance {dist}")
|
||||
# else:
|
||||
# self.assertTrue(pso.output.value == 0,
|
||||
# f"Expected LOW PSO output outside the window at distance {dist}")
|
||||
|
||||
# print("AX:PSO: The next tests fail due to encoder jitter!")
|
||||
# pso.unstage()
|
||||
# return
|
||||
|
||||
# print("AX:PSO: Checking basic window event generation with DDC (2/3)")
|
||||
# # Move to acceleration position
|
||||
# acc_dist = 0.5 * mot.velocity.value * mot.acceleration.value
|
||||
# print(f"Acceleration distance: {acc_dist}")
|
||||
# start_position = mot.position
|
||||
# mot.move(start_position - acc_dist)
|
||||
# # Configure PSO in window mode
|
||||
# cfg = {'bounds': (acc_dist, 30 + acc_dist), 'pso_wavemode': "pulsed", "emode": 'Both'}
|
||||
# dev.configure(cfg)
|
||||
# # Configure the data capture (must be performed in start position)
|
||||
# cfg = {'ntotal': 5*10, 'trigger': DriveDataCaptureTrigger.PsoOutput}
|
||||
# ddc.configure(cfg)
|
||||
# ddc.arm()
|
||||
# npoints_rbv = ddc.nsamples_rbv.value
|
||||
# self.assertEqual(npoints_rbv, 0,
|
||||
# f"DDC.stage should reset the number of DDC points but got: {npoints_rbv}")
|
||||
# # Repeated line scan
|
||||
# for ii in range(10):
|
||||
# dev.arm()
|
||||
# mot.move(start_position + 30 + acc_dist)
|
||||
# dev.unstage()
|
||||
# mot.move(start_position - acc_dist)
|
||||
# time.sleep(0.5)
|
||||
# npoints_rbv = ddc.nsamples_rbv.value
|
||||
# self.assertTrue(np.abs(npoints_rbv - 50) < 1,
|
||||
# f"Expected to record 10 points but got {npoints_rbv}")
|
||||
|
||||
# print("AX:PSO: Checking basic 'toggled' event generation with DDC (3/3)")
|
||||
# print("Test removed as there's some heavy jitter on the PSO output flag")
|
||||
# # Move to acceleration position
|
||||
# acc_dist = 0.5 * mot.velocity.value * mot.acceleration.value
|
||||
# print(f"Acceleration distance: {acc_dist}")
|
||||
# mot.move(mot.position - acc_dist)
|
||||
# # Configure PSO in window mode
|
||||
# cfg = {'bounds': (acc_dist, 30 + acc_dist + 1), 'pso_wavemode': "output"}
|
||||
# dev.configure(cfg)
|
||||
# dev.arm()
|
||||
# # Configure the data capture
|
||||
# cfg = {'ntotal': 10, 'trigger': DriveDataCaptureTrigger.PsoOutput}
|
||||
# ddc.configure(cfg)
|
||||
# ddc.arm()
|
||||
# npoints_rbv = ddc.nsamples_rbv.value
|
||||
# self.assertEqual(npoints_rbv, 0,
|
||||
# f"DDC.stage should reset the number of DDC points but got: {npoints_rbv}")
|
||||
# # Snake scan
|
||||
# for ii in range(10):
|
||||
# if ii % 2 == 0:
|
||||
# mot.move(mot.position + 30 + 2 * acc_dist + 0.1)
|
||||
# else:
|
||||
# mot.move(mot.position - 30 - 2 * acc_dist - 0.1)
|
||||
# time.sleep(0.5)
|
||||
# npoints_rbv = ddc.nsamples_rbv.value
|
||||
# self.assertTrue(np.abs(npoints_rbv - 10) < 1,
|
||||
# f"Expected to record 10 points but got {npoints_rbv}")
|
||||
|
||||
def test_12_StepScan(self):
|
||||
def test_10_StepScan(self):
|
||||
"""Test a simple blusky style step scan (via BEC)
|
||||
|
||||
This module tests manual PSO trigger functionality. The goal is to
|
||||
ensure the basic operation of the PSO module and the polled feedback.
|
||||
"""
|
||||
# Throws if IOC is not available or PVs are incorrect
|
||||
pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":PSO:", name="pso1")
|
||||
ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc")
|
||||
mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="x")
|
||||
pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":PSO:", name="pso1")
|
||||
ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":DDC:", name="ddc")
|
||||
mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_IOC_AXIS, name="x")
|
||||
mot.wait_for_connection()
|
||||
pso.wait_for_connection()
|
||||
ddc.wait_for_connection()
|
||||
@@ -769,7 +683,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
ddc.disarm()
|
||||
mot.unstage()
|
||||
t_start = time.time()
|
||||
print("\ntest_12_StepScan: Simple step scan (via Ophyd)")
|
||||
print("\ntest_10_StepScan: Simple step scan (via Ophyd)")
|
||||
|
||||
pos_start = 112.0
|
||||
scan_range = 180
|
||||
@@ -787,7 +701,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
f"Expected to move to scan start position {pos_start}, now at {mot.position}",
|
||||
)
|
||||
# PSO setup (very large pulse distance)
|
||||
pso.configure(d={"pso_n_pulse": 2, "pso_distance": 99999})
|
||||
pso.configure(d={"pso_n_pulse": 2, "pso_distance": 9999})
|
||||
# DDC setup (trigger at each point plus some extra)
|
||||
cfg = {"num_points_total": 1000 * (scan_steps + 1), "ddc_trigger": DriveDataCaptureTrigger.PsoOutput}
|
||||
ddc.configure(cfg)
|
||||
@@ -800,7 +714,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
for ii in range(len(positions)):
|
||||
mot.move(positions[ii])
|
||||
self.assertTrue(
|
||||
np.abs(mot.position - positions[ii]) < MOTOR_TOL,
|
||||
np.abs(mot.position - positions[ii]) < AXIS_TOL,
|
||||
f"Expected to reach {positions[ii]}, now is at {mot.position} on step {ii}",
|
||||
)
|
||||
pso.trigger()
|
||||
@@ -824,7 +738,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
f"Expected to record {len(positions)} DDC points, got: {npoints_rbv}",
|
||||
)
|
||||
|
||||
def test_13_TomcatSequenceScan(self):
|
||||
def test_11_TomcatSequenceScan(self):
|
||||
"""Test the zig-zag sequence scan from Tomcat (via BEC)
|
||||
|
||||
This module tests basic PSO distance functionality, like events and
|
||||
@@ -832,9 +746,9 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
the PSO module and the polled feedback.
|
||||
"""
|
||||
# Throws if IOC is not available or PVs are incorrect
|
||||
pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":PSO:", name="pso1")
|
||||
ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc")
|
||||
mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="x")
|
||||
pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":PSO:", name="pso1")
|
||||
ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":DDC:", name="ddc")
|
||||
mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_IOC_AXIS, name="x")
|
||||
mot.wait_for_connection()
|
||||
pso.wait_for_connection()
|
||||
ddc.wait_for_connection()
|
||||
@@ -842,7 +756,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
ddc.disarm()
|
||||
mot.unstage()
|
||||
t_start = time.time()
|
||||
print("\ntest_13_TomcatSequenceScan: TOMCAT Sequeence scan (via Ophyd)")
|
||||
print("\ntest_11_TomcatSequenceScan: TOMCAT Sequeence scan (via Ophyd)")
|
||||
|
||||
scan_start = 42.0
|
||||
scan_range = 180
|
||||
@@ -850,14 +764,14 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
scan_type = "PosNeg"
|
||||
|
||||
# Dynamic properties
|
||||
scan_vel = 90
|
||||
scan_vel = AXIS_VELOCITY
|
||||
scan_acc = 500
|
||||
dist_safe = 10.0
|
||||
|
||||
######################################################################
|
||||
print("\tConfigure")
|
||||
# Scan range
|
||||
dist_acc = 0.5 * scan_vel * scan_vel / scan_acc + dist_safe
|
||||
dist_acc = 0.5 * AXIS_VELOCITY * AXIS_VELOCITY / scan_acc + dist_safe
|
||||
if scan_type in ["PosNeg", "Pos"]:
|
||||
pos_start = scan_start - dist_acc
|
||||
pos_end = scan_start + scan_range + dist_acc
|
||||
@@ -868,8 +782,8 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
raise RuntimeError(f"Unexpected ScanType: {scan_type}")
|
||||
|
||||
# Motor setup
|
||||
mot.velocity.set(scan_vel).wait()
|
||||
mot.acceleration.set(scan_vel / scan_acc).wait()
|
||||
mot.velocity.set(AXIS_VELOCITY).wait()
|
||||
mot.acceleration.set(AXIS_VELOCITY / scan_acc).wait()
|
||||
mot.move(pos_start)
|
||||
self.assertTrue(
|
||||
np.abs(mot.position - pos_start) < 1.0,
|
||||
@@ -897,12 +811,12 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
if scan_type in ["Pos", "Neg"]:
|
||||
mot.move(pos_end)
|
||||
self.assertTrue(
|
||||
np.abs(mot.position - pos_end) < MOTOR_TOL,
|
||||
np.abs(mot.position - pos_end) < AXIS_TOL,
|
||||
f"Expected to reach {pos_end}, now is at {mot.position} on iteration {ii}",
|
||||
)
|
||||
mot.move(pos_start)
|
||||
self.assertTrue(
|
||||
np.abs(mot.position - pos_start) < MOTOR_TOL,
|
||||
np.abs(mot.position - pos_start) < AXIS_TOL,
|
||||
f"Expected to rewind to {pos_start}, now at {mot.position} on iteration {ii}",
|
||||
)
|
||||
|
||||
@@ -910,13 +824,13 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
if ii % 2 == 0:
|
||||
mot.move(pos_end, wait=True)
|
||||
self.assertTrue(
|
||||
np.abs(mot.position - pos_end) < MOTOR_TOL,
|
||||
np.abs(mot.position - pos_end) < AXIS_TOL,
|
||||
f"Expected to reach {pos_end}, now at {mot.position} on iteration {ii}",
|
||||
)
|
||||
else:
|
||||
mot.move(pos_start, wait=True)
|
||||
self.assertTrue(
|
||||
np.abs(mot.position - pos_start) < MOTOR_TOL,
|
||||
np.abs(mot.position - pos_start) < AXIS_TOL,
|
||||
f"Expected to reach {pos_start}, now at {mot.position} on iteration {ii}",
|
||||
)
|
||||
|
||||
@@ -946,7 +860,7 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
f"Expected to record {num_repeat} DDC points, but got: {npoints_rbv}",
|
||||
)
|
||||
|
||||
def test_14_JinjaTomcatSequenceScan(self):
|
||||
def test_12_JinjaTomcatSequenceScan(self):
|
||||
""" Run a test sequence scan with template substitution"""
|
||||
# Load the test file
|
||||
path = os.path.dirname(os.path.realpath(__file__))
|
||||
@@ -955,17 +869,18 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
templatetext = f.read()
|
||||
|
||||
scanconfig = {
|
||||
"rotaxis": "RY",
|
||||
"startpos": 42,
|
||||
"scanrange": 180,
|
||||
"nrepeat": 13,
|
||||
"scandir": "NEGPOS",
|
||||
"npoints": 1300,
|
||||
"scanvel": 150,
|
||||
"scanvel": AXIS_VELOCITY,
|
||||
"scanacc": 500,
|
||||
"accdist": 0.5*150*150/500,
|
||||
"accdist": 0.5*AXIS_VELOCITY*AXIS_VELOCITY/500,
|
||||
"psotrigger": "PsoEvent",
|
||||
"psoBoundsPos": [0.5*150*150/500, 180],
|
||||
"psoBoundsNeg": [0.5*150*150/500, 180]
|
||||
"psoBoundsPos": [0.5*AXIS_VELOCITY*AXIS_VELOCITY/500, 180],
|
||||
"psoBoundsNeg": [0.5*AXIS_VELOCITY*AXIS_VELOCITY/500, 180]
|
||||
}
|
||||
tm = jinja2.Template(templatetext)
|
||||
text = tm.render(scan=scanconfig)
|
||||
@@ -974,10 +889,10 @@ class AerotechAutomation1Test(unittest.TestCase):
|
||||
|
||||
# Throws if IOC is not available or PVs are incorrect
|
||||
tsk = aa1Tasks(AA1_IOC_NAME + ":TASK:", name="tsk")
|
||||
ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc")
|
||||
ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":DDC:", name="ddc")
|
||||
tsk.wait_for_connection()
|
||||
ddc.wait_for_connection()
|
||||
print("\nTOMCAT Sequeence scan (via Jinjad AeroScript)")
|
||||
print("\ntest_12_JinjaTomcatSequenceScan: TOMCAT Sequeence scan (via Jinjad AeroScript)")
|
||||
|
||||
# Copy file to controller and run it
|
||||
t_start = time.time()
|
||||
|
||||
@@ -33,7 +33,7 @@ program
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Internal parameters - dont use
|
||||
var $axis as axis = ROTY
|
||||
var $axis as axis = {{ scan.rotaxis or 'ROTY' }}
|
||||
var $ii as integer
|
||||
var $axisFaults as integer = 0
|
||||
var $iDdcSafeSpace as integer = 4096
|
||||
|
||||
Reference in new issue
Block a user