state on dilsc as of 2022-10-03
vector field, but no new state machine yet
This commit is contained in:
95
secop_psi/dilsc.py
Normal file
95
secop_psi/dilsc.py
Normal file
@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# *****************************************************************************
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# Module authors:
|
||||
# Markus Zolliker <markus.zolliker@psi.ch>
|
||||
# *****************************************************************************
|
||||
"""vector field"""
|
||||
|
||||
import math
|
||||
from secop.core import Drivable, Done, BUSY, IDLE, ERROR, Parameter, TupleOf, ArrayOf, FloatRange
|
||||
from secop.errors import BadValueError
|
||||
from secop_psi.vector import Vector
|
||||
from secop.states import HasStates, Retry
|
||||
|
||||
|
||||
DECREASE = 1
|
||||
INCREASE = 2
|
||||
|
||||
|
||||
class VectorField(HasStates, Vector, Drivable):
|
||||
sphere_radius = Parameter('max. spehere', datatype=FloatRange(0, 0.7, unit='T'), readonly=True, default=0.6)
|
||||
cylinders = Parameter('allowed cylinders (list of radius and height)',
|
||||
datatype=ArrayOf(TupleOf(FloatRange(0, 0.6, unit='T'), FloatRange(0, 5.2, unit='T')), 1, 9),
|
||||
readonly=True, default=((0.23, 5.2), (0.45, 0.8)))
|
||||
|
||||
def initModule(self):
|
||||
super().initModule()
|
||||
# override check_limits of the components with a check for restrictions on the vector
|
||||
for idx, component in enumerate(self.components):
|
||||
|
||||
def outer_check(target, vector=self, i=idx, inner_check=component.check_limits):
|
||||
inner_check(target)
|
||||
if vector:
|
||||
value = [c.value - math.copysign(c.tolerance, c.value)
|
||||
for c in vector.components]
|
||||
value[i] = target
|
||||
vector.check_limits(value)
|
||||
|
||||
component.check_limits = outer_check
|
||||
|
||||
def merge_status(self):
|
||||
return self.status
|
||||
|
||||
def check_limits(self, value):
|
||||
"""check if value is within one of the safe shapes"""
|
||||
if sum((v ** 2 for v in value)) <= self.sphere_radius ** 2:
|
||||
return
|
||||
for r, h in self.cylinders:
|
||||
if sum(v ** 2 for v in value[0:2]) <= r ** 2 and abs(value[2]) <= h:
|
||||
return
|
||||
raise BadValueError('vector %s does not fit in any limiting shape' % repr(value))
|
||||
|
||||
def write_target(self, value):
|
||||
"""initiate target change"""
|
||||
# check limits first
|
||||
for target, component in zip(value, self.components):
|
||||
# check against limits of individual components
|
||||
component.check_limits(target, vector=None) # no outer check here!
|
||||
self.check_limits(value)
|
||||
for target, component in zip(value, self.components):
|
||||
if target * component.value < 0:
|
||||
# change sign: drive to zero first
|
||||
target = 0
|
||||
if abs(target) > abs(component.value):
|
||||
target = component.value
|
||||
component.write_target(target)
|
||||
self.start_state(self.ramp_down, target=value)
|
||||
return value
|
||||
|
||||
def ramp_down(self, state):
|
||||
for target, component in zip(state.target, self.components):
|
||||
if component.isDriving():
|
||||
return Retry()
|
||||
for target, component in zip(state.target, self.components):
|
||||
component.write_target(target)
|
||||
return self.final_ramp
|
||||
|
||||
def final_ramp(self, state):
|
||||
for component in self.components:
|
||||
if component.isDriving():
|
||||
return Retry()
|
||||
return self.final_status()
|
Reference in New Issue
Block a user