Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature request: Quantities in DictFeat #35

Open
vascotenner opened this issue Dec 2, 2014 · 3 comments
Open

feature request: Quantities in DictFeat #35

vascotenner opened this issue Dec 2, 2014 · 3 comments

Comments

@vascotenner
Copy link

I have a device that returns the unit that is used in the device. This given as a number, and should be converted in a quatitity. I also can set this unit. The logical way would be to use a DictFeat. However, to do this one should make a dict, which does not work with Quantities objects:

    @DictFeat(values={Q_('encodercount'): 0,
                        Q_('motor step'): 1,
                        Q_('millimeter'): 2,
                        Q_('micrometer'): 3,
                        Q_('inches'): 4,
                        Q_('milli-inches'): 5,
                        Q_('micro-inches'): 6,
                        Q_('degree'): 7,
                        Q_('gradian'): 8,
                        Q_('radian'): 9,
                        Q_('milliradian'): 10,
                        Q_('microradian'): 11})
    def units(self):
        return self.parent.query('%SN?' % self.num)

    @units.setter
    def units(self, val):
        self.parent.send('%SN%' % (self.num, val))

Furthermore I want to use this unit as default unit for all my functions in my driver. Is there an easy somultion

@hgrecco
Copy link
Contributor

hgrecco commented Dec 3, 2014

This is something that we need to resolve in a more general way. The following things need to be considered:

  1. Most of the times the unit is associated with a Feat and you do are not supposed to change it.
  2. With a device with enough significant digits when getting/setting a value, you can use in your program the unit that you want and it is transparently converted to the units the device needs.
  3. If you want/need to change it, you need two things
    1. inform the device that you are using a new unit (as in your example)
    2. change the unit of the feats in question. You can use a (still provisional) API shown here

In this context, consider an hypothetical instrument that can change the position with the command POS followed by a number which is the value in some predefine units. The following program would make sense:

# Position has cm units by default
>>> print(inst.position)
0 centimeter
>>> inst.position = Q_(1, 'cm') 
# Transmitted to the instrument as POS 1  (meaning 1 centimeter)
>>> inst.units = 'mm'
>>> inst.position = Q_(1, 'cm')
# Transmitted to the instrument as POS 10 (meaning 10 millimeter)

But your case is a different one which only applies to 'dimensionless' feats. I say dimensionless (in quotes) because even if you are changing a physical magnitude the API will be dimensionless because the units might:

  • not be of the same dimensionality and therefore are not interconvertible (in your example, how do you convert from 1 inch to radian)
  • not be defined in the registry and not definable because they are not really universal (in your example, how much is 1 encodercount depends on the encoder)

So the program would look like:

>>> print(inst.position)
0
>>> inst.position = 1
# Transmitted to the instrument as POS 1  (meaning 1 centimeter)
>>> inst.units = 'encodercount'
>>> inst.position = 1
# Transmitted to the instrument as POS 1 (meaning 1 encodercount)

There is no proper and easy way (that I can think of) to have units in this type of position Feat because it can lead to problems like this:

# Position has cm units by default
>>> print(inst.position)
0 centimeter
>>> inst.position = Q_(1, 'cm') 
# Transmitted to the instrument as POS 1  (meaning 1 centimeter)
>>> inst.units = 'encodercount'
>>> inst.position = Q_(1, 'cm')
# What should it do????

The only way will be to define a context attached to the Feat to teach non specific unit conversions.

The way I have used in the past to deal with something like this was defining only certain units for the Feat (millimeter, inch, etc). And if really need radians or encodercount I define other feats. It is not nice but it works.

Going back to your question. If you are NOT going to relate to a Feat, the best way is to use string instead of Quantities. (Additionally, quantities might not be a good idea as "2 meters" and "1 meter" will be different keys even though is the same unit.

@vascotenner
Copy link
Author

This is a long standing open issue.

I came across it when using an newport motion controller, which can have several axis connected. Depending on the connected motion device, it can use different units (radian for rotational devices). It would be nice if Lantz could automatically determine the kind of motion device and set the relevant units.

@vascotenner
Copy link
Author

I have implemented the ability to set the units of feats after creation of the object: https://github.com/vascotenner/lantz/tree/drivers_developv

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants