def prepare_move(self, motion): """ - TODO for multiple move... Args: - <motion> : Emotion motion object. Returns: - Raises: - RuntimeError('The capacitive sensor is not in its right area of function') """ self.sync(self.piezo) self.sync(self.icepap) if self.piezo.controller.name.startswith("mockup"): self.piezo.custom_get_chapi("titi") return # check for power cut self.piezo.CheckPowerCut() tad = self.piezo.Get_TAD() elog.debug("TAD : %s, %s, %s" % (tad, self.TADmax, self.TADmin)) if self.TADmax < tad or tad < self.TADmin: # raise RuntimeError("The capacitive sensor is not in its area of linear function") elog.info(""" ########################################################################## ##### The capacitive sensor is not in its area of linear function ##### ########################################################################## TAD is %s""" % tad)
def send(self, axis, cmd): """ - Adds the 'newline' terminator character : "\\\\n" - Sends command <cmd> to the PI E517 controller. - Channel is defined in <cmd>. - <axis> is passed for debugging purposes. - Returns answer from controller. Args: - <axis> : passed for debugging purposes. - <cmd> : GCS command to send to controller (Channel is already mentionned in <cmd>). Returns: - 1-line answer received from the controller (without "\\\\n" terminator). """ _cmd = cmd + "\n" _t0 = time.time() # PC _ans = "toto" _ans = self.sock.write_readline(_cmd) _duration = time.time() - _t0 if _duration > 0.005: elog.info("PI_E517.py : Received %r from Send %s (duration : %g ms) " % (_ans, _cmd, _duration * 1000)) # Check error code _err = self.sock.write_readline("ERR?\n") if _err != "0": print ":( error read: %s on send(%r)" % (_err, _cmd) return _ans
def _set_closed_loop(self, axis, onoff = True): """ Sets Closed loop status (Servo state) (SVO command) """ axis.closed_loop = onoff self.send_no_ans(axis, "SVO %s %d" % (axis.channel, onoff)) elog.debug("Piezo Servo %r" % onoff) # Only when closing loop: waits to be ON-Target. if onoff: _t0 = time.time() cl_timeout = 2 _ont_state = self._get_on_target_status(axis) elog.info(u'axis {0:s} waiting to be ONTARGET'.format(axis.name)) while((not _ont_state) or (time.time() - _t0) > cl_timeout): time.sleep(0.01) print ".", _ont_state = self._get_on_target_status(axis) if not _ont_state: elog.error('axis {0:s} NOT on-target'.format(axis.name)) raise RuntimeError("Unable to close the loop : not ON-TARGET after %gs :( " % cl_timeout) else: elog.info('axis {0:s} ONT ok after {1:g} s'.format(axis.name, time.time() - _t0)) # Updates emotion setting (internal cached) position. axis._position() # "POS?"
def enable_auto_gate(self, axis, value): if value: # auto gating self.auto_gate_enabled = True elog.info("PI_E517.py : enable_gate %s for axis.channel %s " %(str(value) , axis.channel) ) else: self.auto_gate_enabled = False
def __init__(self, name, config, axes, encoders): Controller.__init__(self, name, config, axes, encoders) self._axis_moves = {} self.factor = 1 # config _target_attribute_name = self.config.get("target_attribute") _gating_ds = self.config.get("gating_ds") try: self.target_attribute = AttributeProxy(_target_attribute_name) except: elog.error("Unable to connect to attrtribute %s " % _target_attribute_name) # External DS to use for gating. # ex: PI-E517 for zap of HPZ. if _gating_ds is not None: self.gating_ds = DeviceProxy(_gating_ds) self.external_gating = True elog.info("external gating True ; gating ds= %s " % _gating_ds) else: # No external gating by default. self.external_gating = False # _pos0 must be in controller unit. self._pos0 = self.target_attribute.read().value * self.factor elog.info("initial position : %g (in ctrl units)" % self._pos0)
def delete_unused_emotion_axes(): """ Removes Emotion axes that are not running. """ # get EmotionAxis (only from current instance). emotion_axis_device_names = get_devices_from_server().get('EmotionAxis') elog.info("Axes: %r" % emotion_axis_device_names)
def test_info(self): log.level(log.INFO) with wrapped_stdout() as stdout: log.info("test") output = stdout.getvalue() self.assertEquals( output, "INFO: test\n")
def initialize(self): """Controller initialization""" tacomaxe_info("initialize() called") # Get controller from emotion config self.taconame = self.config.get("tacodevice") log.info("my taconame is %r"%self.taconame) self.device = MyTacoDevice.TacoDevice(self.taconame)
def move_done_event_received(self, state): if self.auto_gate_enabled: if state is True: elog.info("PI_E517.py : movement is finished") self._set_gate(0) elog.debug("mvt finished, gate set to 0") else: elog.info("PI_E517.py : movement is starting") self._set_gate(1) elog.debug("mvt started, gate set to 1")
def enable_auto_gate(self, axis, value): if value: # auto gating self.auto_gate_enabled = True self.gate_axis = axis elog.info("PI_E517.py : enable_gate " + value + "fro axis.channel " + axis.channel) else: self.auto_gate_enabled = False # To keep external gating possible. self.gate_axis = 1
def delete_emotion_axes(): """ Removes Emotion axis devices from the database. """ db = PyTango.Database() emotion_axis_device_names = get_devices_from_server().get('EmotionAxis') for _axis_device_name in emotion_axis_device_names: elog.info("Deleting existing Emotion axis: %s" % _axis_device_name) db.delete_device(_axis_device_name)
def init_device(self): self.debug_stream("In init_device() of axis") self.get_device_properties(self.get_device_class()) # -v1 self.info_stream("INFO STREAM ON ++++++++++++++++++++++++++") self.warn_stream("WARN STREAM ON ++++++++++++++++++++++++++") self.error_stream("ERROR STREAM ON ++++++++++++++++++++++++++") self.fatal_stream("FATAL STREAM ON ++++++++++++++++++++++++++") # -v3 (-v == -v4) self.debug_stream("DEBUG STREAM ON ++++++++++++++++++++++++++") try: self.axis = TgGevent.get_proxy(emotion.get_axis, self._axis_name) self.kontroler = TgGevent.get_proxy(self.axis.controller) except: elog.error("unable to get kontroller or axis") self.set_status(traceback.format_exc()) self.debug_stream("axis found : %s" % self._axis_name) self.once = False self._init_time = time.time() self._t = time.time() self.attr_Home_position_read = 0.0 self.attr_StepSize_read = 0.0 self.attr_Steps_per_unit_read = 0.0 self.attr_Acceleration_read = 1.0 self.attr_HardLimitLow_read = False self.attr_HardLimitHigh_read = False self.attr_Backlash_read = 0.0 self.attr_Offset_read = 0.0 self.attr_Tolerance_read = 0.0 self.attr_PresetPosition_read = 0.0 """ self.attr_Steps_read = 0 self.attr_Position_read = 0.0 self.attr_Measured_Position_read = 0.0 self.attr_FirstVelocity_read = 0.0 self.attr_Home_side_read = False """ self.attr_trajpar_read = [[0.0]] # To force update of state and status. self.dev_state() # elog.info(" %s" % self.axis.get_info()) elog.info(" Emotion.py Axis " + bcolors.PINK + self._ds_name + bcolors.ENDC + " initialized")
def initialize_axis(self, axis): """ - Reads specific config - Adds specific methods - Switches piezo to ONLINE mode so that axis motion can be caused by move commands. Args: - <axis> Returns: - None """ elog.info("initialize_axis() called for axis %r" % axis.name) self._hw_status = AxisState("READY") """ Documentation uses the word AxisID instead of channel Note: any function used as axis method must accept axis as an argument! Otherwise you will see: TypeError: check_power_cut() takes exactly 1 argument (2 given) """ axis.channel = axis.config.get("channel", int) add_axis_method(axis, self.raw_com, name = "RawCom", types_info = (str, str)) add_axis_method(axis, self.check_power_cut, name = "CheckPowerCut", types_info = (None, None)) add_axis_method(axis, self._get_tns, name = "Get_TNS", types_info = (None, float)) add_axis_method(axis, self._get_tsp, name = "Get_TSP", types_info = (None, float)) add_axis_method(axis, self._get_sva, name = "Get_SVA", types_info = (None, float)) add_axis_method(axis, self._get_vol, name = "Get_VOL", types_info = (None, float)) add_axis_method(axis, self._get_mov, name = "Get_MOV", types_info = (None, float)) add_axis_method(axis, self._get_offset, name = "Get_Offset", types_info = (None, float)) add_axis_method(axis, self._put_offset, name = "Put_Offset", types_info = (float, None)) add_axis_method(axis, self._get_tad, name = "Get_TAD", types_info = (None, float)) add_axis_method(axis, self._get_closed_loop_status, name = "Get_Closed_Loop_Status", types_info = (None, bool)) add_axis_method(axis, self._set_closed_loop, name = "Set_Closed_Loop", types_info = (bool, None)) #add_axis_method(axis, self._get_on_target_status, name = "Get_On_Target_Status", types_info = (None, bool)) add_axis_method(axis, self._get_pos, name = "Get_Pos", types_info = (None, float)) try: axis.paranoia_mode = axis.config.get("paranoia_mode") # check error after each command except KeyError : axis.paranoia_mode = False self._gate_enabled = False # Updates cached value of closed loop status. axis.closed_loop = self._get_closed_loop_status(axis) self.check_power_cut(axis) elog.debug("axis = %r" % axis.name)
def always_executed_hook(self): # here instead of in init_device due to (Py?)Tango bug : # device does not really exist in init_device... (Cyril) if not self.once: try: # Initialises "set values" of attributes. # Position attr = self.get_device_attr().get_attr_by_name("Position") attr.set_write_value(self.axis.position()) # Velocity attr = self.get_device_attr().get_attr_by_name("Velocity") attr.set_write_value(self.axis.velocity()) except: elog.info( "Cannot set one of the attributes write value") finally: self.once = True
def get_info(self, axis): """ Returns a set of useful information about controller. Helpful to tune the device. Args: <axis> : emotion axis Returns: None Raises: ? """ elog.info("PiezoJack: get_info") _info_str = "---------PiezoJack: get_info----------\n" if not self.piezo.controller.name.startswith("mockup"): # elog.info("PiezoJack::get_info: ICEPAP Identifier: " % self.icepap.get_identifier()) # elog.info("PiezoJack::get_info: Piezo Info:" % self.piezo.get_info()) _info_str += "icepap position : %s\n" % self.icepap.position() closed_loop = self.piezo.Get_Closed_Loop_Status() _info_str += "piezo closed loop: %s\n" % closed_loop _info_str += "piezo tns : %s\n" % self.piezo.Get_TNS() _info_str += "piezo offset : %s\n" % self.piezo.Get_Offset() _info_str += "piezo POS? : %s\n" % self.piezo.Get_Pos() _info_str += "piezo instance : %s\n" % self.piezo.name if closed_loop: _info_str += "piezo MOV? : %s\n" % self.piezo.position() self.piezo.Set_Closed_Loop(onoff = False) _info_str += "piezo SVA? : %s\n" % self.piezo.position() self.piezo.Set_Closed_Loop(onoff = True) else: self.piezo.Set_Closed_Loop(onoff = True) _info_str += "piezo MOV? : %s\n" % self.piezo.position() self.piezo.Set_Closed_Loop(onoff = False) _info_str += "piezo SVA? : %s\n" % self.piezo.position() _info_str += "--------------------------------------\n" return _info_str
def calc_from_real(self, positions_dict): log.info("[SLITS] calc_from_real()") log.info("[SLITS]\treal: %s" % positions_dict) calc_dict = dict() slit_type = self.config.get("slit_type", default="both") if slit_type not in ['vertical']: calc_dict.update( { "hoffset": (positions_dict["back"] - positions_dict["front"]) / 2.0, "hgap": positions_dict["back"] + positions_dict["front"] } ) if slit_type not in ['horizontal']: calc_dict.update( { "voffset": (positions_dict["up"] - positions_dict["down"]) / 2.0, "vgap": positions_dict["up"] + positions_dict["down"] } ) log.info("[SLITS]\tcalc: %s" % calc_dict) return calc_dict
def initialize_axis(self, axis): """ - Reads specific config - Adds specific methods """ # can be "X" or "Y" axis.chan_letter = axis.config.get("chan_letter") add_axis_method(axis, self.get_id, types_info=(None, str)) axis.config.config_dict.update({"steps_per_unit": {"value": axis.config.get("steps_per_unit")}}) ini_pos = self.read_position(axis) if ini_pos < 0: elog.info("reseting VSCANNER negative position to 0 !!") _cmd = "V%s 0" % (axis.chan_letter) self.send_no_ans(axis, _cmd) if ini_pos > 10: elog.info("reseting VSCANNER >10-position to 10 !!") _cmd = "V%s 10" % (axis.chan_letter) self.send_no_ans(axis, _cmd)
def send(self, axis, cmd): """ - Adds the 'newline' terminator character : "\\\\n" - Sends command <cmd> to the PI controller. - Channel is defined in <cmd>. - <axis> is passed for debugging purposes. - checks error and in case raises .... what ? - Returns answer from controller. Args: - <axis> : passed for debugging purposes. - <cmd> : GCS command to send to controller (Channel is already mentionned in <cmd>). Returns: - 1-line answer received from the controller (without "\\\\n" terminator). Raises: - """ _cmd = cmd + "\n" #elog.debug("Send %s" % (cmd)) _t0 = time.time() # PC _ans = "toto" _ans = self.sock.write_readline(_cmd) #elog.debug("Answer %s" % (_ans)) _duration = time.time() - _t0 if _duration > 0.05: elog.info("%s Received %s from Send \"%s\" (duration : %g ms) " % (self.cname, repr(_ans), _cmd.rstrip(), _duration * 1000)) # ZARBI : _ans = self.sock.write_readline(_cmd) if axis is not None and axis.paranoia_mode: self.get_error() # should raise exc. return _ans
def move_done_event_received(self, state, sender=None): # <sender> is the axis. elog.info("move_done_event_received(state=%s axis.sender=%s)"%(state, sender.name)) if self.auto_gate_enabled: if state is True: elog.info("PI_E517.py : movement is finished") self.set_gate(sender, 0) elog.debug("mvt finished, gate set to 0") else: elog.info("PI_E517.py : movement is starting") self.set_gate(sender, 1) elog.debug("mvt started, gate set to 1")
def calc_from_real(self, positions_dict): log.info("[SLITS] calc_from_real()") log.info("[SLITS]\treal: %s" % positions_dict) calc_dict = { "hoffset": (positions_dict["back"] - positions_dict["front"]) / 2.0, "hgap": positions_dict["back"] + positions_dict["front"], "voffset": (positions_dict["up"] - positions_dict["down"]) / 2.0, "vgap": positions_dict["up"] + positions_dict["down"] } log.info("[SLITS]\tcalc: %s" % calc_dict) return calc_dict
def calc_to_real(self, axis_tag, positions_dict): if axis_tag in ("hoffset", "hgap"): log.info("[SLITS] calc_to_real()") log.info("[SLITS]\tcalc: %s" % positions_dict) real_dict = { "back": (positions_dict["hgap"] / 2.0) + positions_dict["hoffset"], "front": (positions_dict["hgap"] / 2.0) - positions_dict["hoffset"] } log.info("[SLITS]\treal: %s" % real_dict) return real_dict elif axis_tag in ("voffset", "vgap"): return { "up": (positions_dict["vgap"] / 2.0) + positions_dict["voffset"], "down": (positions_dict["vgap"] / 2.0) - positions_dict["voffset"] }
def _get_tns(self, axis): """Get Normalized Input Signal Value. Loop 10 times to straighten out noise""" accu = 0 for _ in range(10): time.sleep(0.01) _ans = self.send(axis, "TNS? %s" % axis.channel) #elog.debug("TNS? %d : %r" % (axis.channel, _ans)) if _ans != '0': accu += float(_ans[2:]) accu /= 2 elog.debug("TNS? %r" % accu) # during tests with the piezojack, problems with a blocked socket # towards the controller were encountered. Usually, that was # manifesting with 0 TNS readings. If The accumulated value of # TNS is 0, we're pretty sure the connection is broken. # Use self.finalize() to close the socket, it should be reopened # by the next communication attempt. if accu == 0: elog.info("%s##########################################################%s" % (bcolors.GREEN+bcolors.BOLD, bcolors.ENDC)) elog.info("%sPIEZO READ TNS, accu is zero, resetting socket connection!%s" % (bcolors.GREEN+bcolors.BOLD, bcolors.ENDC)) elog.info("%s##########################################################%s" % (bcolors.GREEN+bcolors.BOLD, bcolors.ENDC)) self.finalize() return accu
def tacomaxe_info(msg): """Logging method""" log.info("[TacoMaxe]" + msg)
def main(): try: delete_unused_emotion_axes() except: elog.error( "Cannot delete unused emotion axes.", raise_exception=False) try: py = PyTango.Util(sys.argv) log_param = [param for param in sys.argv if "-v" in param] if log_param: log_param = log_param[0] # print "-vN log flag found len=%d" % len(log_param) if len(log_param) > 2: tango_log_level = int(log_param[2:]) elif len(log_param) > 1: tango_log_level = 4 else: print "Emotion.py - EMOTION ERROR LOG LEVEL" if tango_log_level == 1: elog.level(40) elif tango_log_level == 2: elog.level(30) elif tango_log_level == 3: elog.level(20) else: elog.level(10) else: # by default : show INFO elog.level(20) tango_log_level = 0 print "" elog.info(" ---------------------= EMotion PyTango Device Server =----------------------------") # elog.info("tango log level=%d" % tango_log_level) # elog.debug("Emotion.py debug message") # elog.error("Emotion.py error message", raise_exception=False) # Searches for emotion devices defined in tango database. U = PyTango.Util.instance() db = U.get_database() device_list = get_devices_from_server().get('Emotion') if device_list is not None: _device = device_list[0] elog.info(" Emotion.py - Emotion device : %s" % _device) try: _config_file = db.get_device_property(_device, "config_file")["config_file"][0] except: elog.info(" Emotion.py - 'config_file' property not present ?") _config_file = None first_run = False else: elog.error("[FIRST RUN] New server never started ? -> no database entry...", raise_exception=False) elog.error("[FIRST RUN] NO CUSTOM COMANDS :( ", raise_exception=False) elog.error("[FIRST RUN] Restart DS to havec CUSTOM COMMANDS", raise_exception=False) first_run = True py.add_class(EmotionClass, Emotion) # py.add_class(EmotionAxisClass, EmotionAxis) if not first_run: if _config_file is not None: elog.info(" Emotion.py - config file : " + bcolors.PINK + _config_file + bcolors.ENDC) try: TgGevent.execute(emotion.load_cfg, _config_file) except: elog.error("error (not present or syntax error?) in reading config file : %s" % _config_file, raise_exception=False) sys.excepthook(*sys.exc_info()) sys.exit(-1) else: # Get axis names defined in config file. axis_names = emotion.config.axis_names_list() else: elog.info(" Emotion.py - " + bcolors.PINK + "beacon config" + bcolors.ENDC) # Get axes names from property (= use beacon to get axis objects) emotion.config.BACKEND = "beacon" axis_names = db.get_device_property(_device, "axes")["axes"][0].split() elog.debug("axis names list : %s" % axis_names) for axis_name in axis_names: elog.debug("Emotion.py : _____________ axis %s _____________" % axis_name) try: _axis = TgGevent.get_proxy(emotion.get_axis, axis_name) except ConnectionException: elog.error("beacon_server seems not running") sys.exit(-1) except: print traceback.format_exc() sys.exit(-1) new_axis_class_class = types.ClassType("EmotionAxisClass_%s" % axis_name, (EmotionAxisClass,), {}) new_axis_class = types.ClassType("EmotionAxis_%s" % axis_name, (EmotionAxis,), {}) types_conv_tab = { None: PyTango.DevVoid, str: PyTango.DevString, int: PyTango.DevLong, float: PyTango.DevDouble, bool: PyTango.DevBoolean, "str": PyTango.DevString, "int": PyTango.DevLong, "float": PyTango.DevDouble, "bool": PyTango.DevBoolean, "None": PyTango.DevVoid, "float_array": PyTango.DevVarFloatArray, "double_array": PyTango.DevVarDoubleArray, "long_array": PyTango.DevVarLongArray, "string_array": PyTango.DevVarStringArray } """ CUSTOM COMMANDS """ # Search and adds custom commands. _cmd_list = _axis.custom_methods_list() elog.debug("'%s' custom commands:" % axis_name) new_axis_class_class.cmd_list = dict(EmotionAxisClass.cmd_list) for (fname, (t1, t2)) in _cmd_list: setattr(new_axis_class, fname, getattr(_axis, fname)) tin = types_conv_tab[t1] tout = types_conv_tab[t2] new_axis_class_class.cmd_list.update({fname: [[tin, ""], [tout, ""]]}) elog.debug(" %s (in: %s, %s) (out: %s, %s)" % (fname, t1, tin, t2, tout)) """ SETTINGS AS ATTRIBUTES. """ elog.debug(" Emotion.py : %s : -------------- SETTINGS -----------------" % axis_name) new_axis_class_class.attr_list = dict(EmotionAxisClass.attr_list) for setting_name in _axis.settings(): if setting_name in ["velocity", "position", "dial_position", "state", "offset", "low_limit", "high_limit", "acceleration", "_set_position"]: elog.debug(" Emotion.py -- std SETTING %s " % (setting_name)) else: _attr_name = setting_name _setting_type = _axis.controller().axis_settings.convert_funcs[_attr_name] _attr_type = types_conv_tab[_setting_type] elog.debug(" Emotion.py -- adds SETTING %s as %s attribute" % (setting_name, _attr_type)) # Updates Attributes list. new_axis_class_class.attr_list.update({_attr_name: [[_attr_type, PyTango._PyTango.AttrDataFormat.SCALAR, PyTango._PyTango.AttrWriteType.READ_WRITE], { 'Display level': PyTango._PyTango.DispLevel.OPERATOR, 'format': '%10.3f', 'description': '%s : u 2' % _attr_name, 'unit': 'user units/s^2', 'label': _attr_name }]}) # Creates functions to read and write settings. def read_custattr(self, attr, _axis=_axis, _attr_name=_attr_name): _val = _axis.get_setting(_attr_name) print "in read_%s %s (%s)" % (_attr_name, _val, _axis.name()) attr.set_value(_val) new_read_attr_method = types.MethodType(read_custattr, new_axis_class, new_axis_class.__class__) setattr(new_axis_class, "read_%s" % _attr_name, new_read_attr_method) def write_custattr(self, attr, _axis=_axis, _attr_name=_attr_name): data = attr.get_write_value() print "in write_%s %s (%s)" % (_attr_name, data, _axis.name()) _axis.set_setting(_attr_name, data) new_write_attr_method = types.MethodType(write_custattr, new_axis_class, new_axis_class.__class__) setattr(new_axis_class, "write_%s" % _attr_name, new_write_attr_method) # End of custom command and settings elog.debug("Emotion.py : Adds new Axis specific class.") py.add_class(new_axis_class_class, new_axis_class) elog.debug("Emotion.py : Class added.") elog.debug("Emotion.py : intitialize server.") U.server_init() except PyTango.DevFailed: print traceback.format_exc() elog.exception( "Error in server initialization") sys.exit(0) try: emotion_admin_device_names = get_devices_from_server().get('Emotion') if emotion_admin_device_names: blname, server_name, device_number = emotion_admin_device_names[ 0].split('/') for axis_name in emotion.config.axis_names_list(): device_name = '/'.join((blname, '%s_%s' % (server_name, device_number), axis_name)) try: elog.debug("Creating %s" % device_name) U.create_device("EmotionAxis_%s" % axis_name, device_name) except PyTango.DevFailed: # print traceback.format_exc() elog.debug("Device %s already defined in Tango database" % device_name) pass # If axis name is not already a tango alias, # define it as an alias of the device. try: db.get_device_alias(axis_name) except PyTango.DevFailed: db.put_device_alias(device_name, axis_name) elog.debug("Created alias %s for device %s" % (axis_name, device_name)) else: # Do not raise exception to be able to use # Jive device creation wizard. elog.error("No emotion supervisor device", raise_exception=False) except PyTango.DevFailed: print traceback.format_exc() elog.exception( "Error in devices initialization") sys.exit(0) U.server_run()
def log_info(self, msg): """Logging method""" log.info(_ICEPAP_TAB + msg)