Standa-Optomechanics / libximc

Cross-platform library for Standa 8SMC5-USB motor controllers
BSD 2-Clause "Simplified" License
0 stars 0 forks source link

Highlevel Python wrapper: settings struct intialization / missing flags in setter functions #1

Closed michelfrising closed 5 days ago

michelfrising commented 4 weeks ago

Hello,

I am using the new highlevel library for python and I am first creating a settings struct, populating the fields I need and then setting it using set_sync_in_settings on an axis object:

import libximc.highlevel as ximc

sync_in_settings = ximc.sync_in_settings_t()
sync_in_settings.ClutterTime = 4
sync_in_settings.Position = 0
sync_in_settings.uPosition = 0
sync_in_settings.Speed = 0
sync_in_settings.uSpeed = 0
# axis is defined elsewhere, left out for brevity
axis.set_sync_in_settings(sync_in_settings)

In this case I get an error message: AttributeError: 'sync_in_settings_t' object has no attribute '_SyncInFlags' (complete trace under message)

axis.set_sync_in_settings(sync_in_settings) works fine if I add sync_in_settings.SyncInFlags = 0x0 which I believe is standard way of initializing the struct in C++ if no initializer list is passed. Also, when I create a bare sync_in_settings_t struct in python it seems none of the fields is initialized:

ClutterTime: Not Initialized
Position: Not Initialized
uPosition: Not Initialized
Speed: Not Initialized
uSpeed: Not Initialized

There is a similar problem with fields that expect arrays such in control_settings_t:

control_settings.MaxSpeed: Not Initialized
control_settings.uMaxSpeed: Not Initialized
control_settings.Timeout: Not Initialized

and that need to be initialized manually.

It would be convenient if the structs returned by the python wrapper would be initialized with sensible values to avoid these kinds of errors. Or what do you suggest best practice should be in this case?

The complete trace:

AttributeError Traceback (most recent call last) File c:... 1 #%% 2 profile = Standa_8MPR16_1() ----> 3 profile.apply_to_device(axis)

File c:... 25 axis.set_pid_settings(settings_struct) 26 elif settings_name == 'sync_in_settings': ---> 27 axis.set_sync_in_settings(settings_struct) 28 elif settings_name == 'sync_out_settings': 29 axis.set_sync_out_settings(settings_struct)

File c:...\libximc\highlevel_highlevel.py:660, in Axis.set_sync_in_settings(self, settings) 658 raise TypeError("settings must be of type sync_in_settings_t. {} was got.".format(type(settings))) 659 _check_fullness(settings) --> 660 sync_in_settings = ll.sync_in_settings_t(int(settings.SyncInFlags), 661 settings.ClutterTime, 662 settings.Position, 663 settings.uPosition, 664 settings.Speed, 665 settings.uSpeed) 666 _check_result(lib.set_sync_in_settings(self._device_id, byref(sync_in_settings))) ... 1562 @property 1563 def SyncInFlags(self) -> flag_enumerations.SyncInFlags: -> 1564 return self._SyncInFlags

AttributeError: 'sync_in_settings_t' object has no attribute '_SyncInFlags'

8smc commented 5 days ago

Hello, michelfrising :wave:

In most cases the best way is to read actual settings from the controller using get_sync_in_settings() method and change given structure:

import libximc.highlevel as ximc

# axis is defined elsewhere, left out for brevity
sync_in_settings = axis.get_sync_in_settings()

# Change desired parameters
sync_in_settings.ClutterTime = 4
sync_in_settings.Position = 0
sync_in_settings.uPosition = 0
sync_in_settings.Speed = 0
sync_in_settings.uSpeed = 0

axis.set_sync_in_settings(sync_in_settings)

If that's not your case, you really need to initialize all parameters of the settings structure.

We intentionally avoid default initialization. Why? Because the controller is used to work with very different motors and positioners. Parameters that are suitable for some devices may be completely unsuitable for other devices (errors, incorrect operation...). Therefore, we've made a mechanism that requires the user to explicitly and meaningfully set parameters.

We've enhance the error prompt: in the next release the error will tell you that you need to manually set all parameters and describe why we avoid default initialization. Also we've found a bug that leads to unclear message AttributeError: 'sync_in_settings_t' object has no attribute '_SyncInFlags' and fixed it. Your issue helped us to improve our product :+1: Thank you!

If you have new ideas, we will be glad to discuss them :)