Galil Axis Agent
The Galil Axis Agent provides motion control and telemetry readout for the Galil DMC motor controller. When used in the Simons Observatory SAT Coupling Optics system, the agent controls four axes—two linear and two angular—that move the hardware as needed to perform detector passband measurements.
usage: python3 agent.py [-h] [--ip IP] [--port PORT] [--configfile CONFIGFILE]
[--input_config INPUT_CONFIG] [--mode {init,acq}]
Agent Options
- --ip
- --port
Default: 23
- --configfile
- --input_config
- --mode
Possible choices: init, acq
Configuration File Examples
Below are configuration examples for the ocs config file and for running the Agent in a docker container.
OCS Site Config
To configure your Galil axis motor controller for use with OCS you need to add a GalilAxisAgent block to your ocs configuration file. Here is an example configuration block:
{'agent-class': 'GalilAxisAgent',
'instance-id': 'satcouplingoptics',
['--ip', '10.120.1.6',
'--configfile', 'axes_config.yaml',
'--input_config', True,
'--mode', 'acq']}
Each device requires configuration under ‘agent-instances’. See the OCS site configs documentation for more details.
Note
The input_config argument is a boolean flag. When True, the
init task loads and applies all motor-controller settings from
the agent’s configuration file (see Galil Motor Axis Config below) to
bring the controller and its axes into the desired state.
Galil Axis Config
A Galil axis configuration file defines the motion settings, motor parameters, and brake mappings for each controlled axis. This allows the user to easily adapt to different hardware configurations or coordinate multiple axes (e.g., A, B, C, D) during operation:
galil:
motorsettings:
countspermm: 4000
countsperdeg: 2000
limitsetting:
polarity: '1'
disable_limits:
B: '3'
D: '3'
brakes:
output_map:
A: '1'
B: '2'
C: '3'
D: '4'
motorconfigparams:
A: # linear axis
MT: '1'
OE: '1'
AG: '2'
TL: '5'
AU: '9'
B: # linear axis
MT: '1'
OE: '1'
AG: '2'
TL: '5'
AU: '9'
C: # rotary axis
MT: '1'
OE: '1'
AG: '2'
TL: '5'
AU: '9'
D: # rotary axis
MT: '1'
OE: '1'
AG: '2'
TL: '5'
AU: '9'
initaxisparams:
BA: 'True' # if True, will drive motors for each axis at 3V (BZ) for prepping for servo'd motion
BM: '3276.8'
BZ: '3'
dwell_times:
first_ms: '1000'
second_ms: '1500'
Docker Compose
The Galil Axis Agent should be configured to run in a Docker container. An example configuration is:
ocs-galil-agent:
image: simonsobs/socs:latest
hostname: ocs-docker
network_mode: "host"
environment:
- INSTANCE_ID=satcouplingoptics
- SITE_HUB=ws://127.0.0.1:8001/ws
- SITE_HTTP=http://127.0.0.1:8001/call
volumes:
- ${OCS_CONFIG_DIR}:/config:ro
Example Clients
Below are some example use cases for using this agent.
Note
The examples below assume the Galil motor controller has sinusoidal amplifers, limit switches, and brakes (i.e., the Galil motor controllers used for the SAT coupling optics system)
Updating the config file
Though the agent can be configured to initialize the axes via the input_config
boolean parameter in the OCS site config file, any changes made to the
configuration file after agent startup will require reloading it. The following
client command is used to update the motor controller settings accordingly:
client.input_configfile(configfile='axes_config.yaml')
Note
It is important to call the input_configfile task even if the only update to
the configuration file is a change to countspermm or countsperdeg, since
these calibration values are necessary for commanding axis motion in physical
units (mm/deg) rather than raw encoder counts.
Homing Procedure
The SAT coupling optics Galil axes are equipped with limit switches, so
the chosen homing procedure is to move each axis continuously until it is
stopped by its limit switch. When the axis is forced to stop at the switch,
that raw encoder position should then be defined as 0.
To continuously move an axis, we use set_jog_speed to define the speed at
which the axis will jog:
client.set_jog_speed(axis='A', speed=5000.0)
Here, 5000.0 is in units of counts/sec. Note that the speed set through set_jog_speed
is always specified in counts/sec, unlike other tasks that alow motion in physical units
of millimeter or degrees (e.g., set_relative_position or set_absolute_position).
To begin motion:
client.begin_axis_motion(axis='A')
After the axis stops at the limit switch, we define that position using:
client.define_position(axis='A', val=0.00)
Gearing Settings
The following tasks are used to define leader–follower relationships between axes. For the SAT coupling optics system, axes A and B are the linear pair, and axes C and D are the angular pair. In this configuration, A is the leader for B, and C is the leader for D.
The gearing ratio determines the velocity at which each follower axis moves relative to its
leader. For example, a ratio of 1 means that B will follow A at the exact same speed defined
for A. A ratio of -1 means the follower moves at the same speed scale but in the opposite direction.
Once the leader–follower mapping and gearing ratios are set, commanding motion on the leader (e.g., A) will cause both A and B to move. If this does not occur, stop motion and query the gearing ratio for the relevant axes.
When querying the ratio, the expected response for a leader axis is 0, since leaders do not
follow any other axis. The follower axis should return the ratio you set (e.g., 1 for B).
Occasionally, the Galil motor controller may lose the gearing ratio values while still
correctly remembering the leader/follower assignments. If a gearing-ratio query for the
follower axis returns 0, reapply the gearing ratio.
Example usage of defining leader/follower axes and the gearing ratio:
# configure A and C as the leader axes
client.set_gearing(order=',A,C')
client.set_gearing_ratio(order=',-1,1')
Here, the second field corresponds to B and the fourth field corresponds to D.
Another example using axes E and F for a 6-axis Galil motor controller system:
# using axes E and F
client.set_gearing(order=',,,,,E')
client.set_gearing_ratio(order=',,,,,1')
In this case, F (the sixth position) follows E with a ratio of 1.
Note
The order argument encodes leader–follower relationships—each
comma-delimited field corresponds to one axis in alphabetical order. An empty field
means the axis is independent (i.e., not following another axis),
while a non-empty field specifies which axis it should follow.
To query the gearing ratio:
>>> response = client.get_gearing_ratio(axis='F')
>>> print(response)
OCSReply: OK : Operation "get_gearing_ratio" is currently not running (SUCCEEDED).
get_gearing_ratio[session=5]; status=done without error 0.006998 s ago, took 0.545369 s
messages (4 of 4):
1762986294.032 Status is now "starting".
1762986294.032 Status is now "running".
1762986294.576 Gearing ratio for axis F is: 1.0.
1762986294.577 Status is now "done".
other keys in .session: op_code, degraded, data
Here, the agent states that the gearing ratio for axis F is 1, which also
indirectly confirms that the set_gearing task was successful.
Examples of sets and gets
Below are 2 examples of setting and querying a specific state for a Galil axis:
>>> client.set_motor_state(axis='F', state='disable')
>>> response = client.get_motor_state(axis='F')
>>> OCSReply: OK : Operation "get_motor_state" is currently not running (SUCCEEDED).
get_motor_state[session=3]; status=done without error 0.007853 s ago, took 1.4 s
messages (4 of 4):
1762987023.477 Status is now "starting".
1762987023.477 Status is now "running".
1762987024.889 Motor F state: off (raw=1)
1762987024.889 Status is now "done".
other keys in .session: op_code, degraded, data
Here, get_motor_state reports that axis F is disabled. The raw value shown as
(raw=1) reflects how the Galil command works internally: the controller
returns a value of 1 when the axis is off.
Another set/get example below:
>>> client.set_torque_limit(axis='E', val=2.0)
>>> print(client.get_torque_limit(axis='E'))
>>> OCSReply: OK : Operation "get_torque_limit" is currently not running (SUCCEEDED).
get_torque_limit[session=4]; status=done without error 0.006350 s ago, took 2.8 s
messages (4 of 4):
1762987510.209 Status is now "starting".
1762987510.209 Status is now "running".
1762987512.988 Torque limit for axis E is 2.0000.
1762987512.988 Status is now "done".
other keys in .session: op_code, degraded, data
Agent API
- class socs.agents.galil_axis.agent.GalilAxisAgent(agent, ip, configfile, port=23)[source]
Agent for controlling Galil axis motors used in SAT coupling optics instrument for passband measurements on-site.
- Parameters:
ip (str) – IP address for the Galil axis motor controller
configfile (str) – Path to .yaml config file containing axis and motor settings
port (int, optional) – TCP port for controller communication. Default is 23
- init(input_config=False, auto_acquire=False)[source]
Task - Initalize connection to Galil axis controller.
- Parameters:
input_config (bool, optional) – If True, init task will also run input_configfile task as part of agent initialization. Defaults to False.
auto_acquire (bool) – If True, start acquisition immediately after initialization. Defaults to False.
- acq()[source]
Process - Starts acquisition of data from the Galil Stage Controller.
- Parameters:
test_mode (bool, optional) – Run the process loop only once. This is meant only for testing. Default is False.
Notes
The data collected is stored in session data in the structure:
>> response.session['data'] {'fields': {'A_position': -1129.0, 'A_velocity': 0.0, 'A_torque': 0.0, 'A_position_error': 7.0, 'B_position': -542.0, 'B_velocity': 0.0, 'B_torque': 0.0, 'B_position_error': 14.0, 'C_position': 810637.0, 'C_velocity': -14983.0, 'C_torque': -1.0501, 'C_position_error': -558.0, 'D_position': 810711.0, 'D_velocity': -15240.0, 'D_torque': -1.0421, 'D_position_error': -580.0}, 'timestamp': 1764009732.0866072}
- set_relative_position(axis, distance, movetype)[source]
Task - Set the relative position location for a specified axis.
- Parameters:
axis (str) – Axis to command position. Ex: ‘A’
distance (float) – Relative distance value, in millimeter, degrees, or raw counts, depending on movetype.
movetype (str) – ‘linear’ (mm) or ‘angular’ (deg), or ‘encoder’ for raw encoder counts.
Notes
The conversion from millimeters to encoder counts is defined in the configuration file under galil.motorsettings.countspermm or galil.motorsettings.countsperdeg
- set_absolute_position(axis, position, movetype)[source]
Task - Set the absolute position location for a specified axis.
- Parameters:
axis (str) – Axis to command position. Example: ‘A’
position (float) – Absolute position distance value in mm, deg, or raw encoder counts.
movetype (str) – ‘linear’ (mm) or ‘angular’ (deg), or ‘encoder’ for raw encoder counts.
Notes
The conversion from millimeters to encoder counts is defined in the configuration file under galil.motorsettings.countspermm or galil.motorsettings.countsperdeg
- get_brake_status(axis)[source]
Task - Get brake status for a given axis.
- Parameters:
axis (str) – Axis to query (e.g. ‘A’, ‘B’).
- set_axis_brake(axis, state)[source]
Task - Engages or releases the brake for the specified axis.
- Parameters:
axis (str) – Axis to control brake for. Ex. ‘A’
state (str) – Desired brake state: ‘engage’ or ‘release’.
- get_thermistor_voltage(axis)[source]
Task - Returns a given motor’s thermistor reading in volts.
- Parameters:
axis (str) – Axis/motor to query (e.g. ‘A’)
- begin_axis_motion(axis)[source]
Task - Moves the specified axis.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
- set_motor_type(axis)[source]
Task - Sets motor type for each axis, depending on servo motor features
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
- get_motor_type(axis)[source]
Task - Queries the motor type for a given axis.
- Parameters:
axis (str) – Axis to query (e.g. ‘A’, ‘B’).
- set_off_on_error(axis)[source]
Task - Configure the off-on-error behavior for a specified axis.
This task enables or disables the Galil controller’s off-on-error function, which determines whether the motor power is shut off when a position error occurs.
- Parameters:
axis (str) – Axis to configure. Ex. ‘A’
errtype (int) – Error handling mode, as defined by the controller’s disable/enable settings.
- get_off_on_error(axis)[source]
Task - Query the Off-On-Error (OE) state for a given axis.
- Parameters:
axis (str) – Axis to query (e.g. ‘A’, ‘B’, ‘E’).
- set_amp_gain(axis, val)[source]
Task - Set amplifier gain for internal amplifier per axis.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
val (int) – Amplifier gain value to apply, as defined by controller’s internal gain settings
- get_amp_gain(axis)[source]
Task - Query the amplifier gain value for a given axis.
- Parameters:
axis (str) – Axis to query (e.g. ‘A’, ‘B’, ‘E’).
- get_amp_currentloop_gain(axis)[source]
Task - Query the amplifier current loop gain value for a given axis.
- Parameters:
axis (str) – Axis to query (e.g. ‘A’).
- set_amp_currentloop_gain(axis, val)[source]
Task - Set amplifier current loop gain for a given axis.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
val (int) – Current-loop gain value to apply.
- set_torque_limit(axis, val)[source]
Task - Set motor torque limit per axis.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
val (float) – Torque limit value in volts. Defines max
current (allowable motor)
controller's (as specifiied by)
settings. (internal)
- get_torque_limit(axis)[source]
Task - Query motor torque limit for specified axis.
- Parameters:
axis (str) – Axis to query (e.g. ‘A’).
- set_motor_state(axis, state)[source]
Task - Enable or disable axis motor, and query its state.
- Parameters:
axis (str) – Axis to set motor state for (e.g. ‘A’, ‘B’, ‘E’).
state (str) – Desired motor state — ‘enable’ or ‘disable’.
- get_motor_state(axis)[source]
Task - Query and interpret whether a motor is ON or OFF for a given axis.
- Parameters:
axis (str) – Axis to query (e.g. ‘A’).
- set_magnetic_cycle(axis, val)[source]
Task - Set magnetic cycle value for motors with sinusoidal amplifiers for specific axis.
Defines the length of the motor’s magnetic cycle in encoder units.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
val (float) – Magnetic cycle value to apply.
- set_dwell_times(t_first, t_second)[source]
Task - Define dwell times for the initialization task.
This task defines the time between driving each axis motor to 2 different locations.
- Parameters:
t_first (int) – timing in milliseconds for driviing the motor to the first location. Ex: 1500
t_second (int) – timing in milliseconds for driving the motor to the second location. Ex: 1000
- initialize_axis(axis, val)[source]
Task - Initialize axes configured with sinusoidal amplifiers.
During this procedure, each motor is driven to two magnetic positions to establish the commutation angle required for motion.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
val (float) – Torque command voltage to be applied during initialization. Ex: 3.0
Notes
To run this task, you must run the enable_sin_commutation, set_magnetic_cycle, and set_dwell_times tasks first.
- define_position(axis, val)[source]
Task - Resets the position of an axis encoder to a specifically set value.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
val (float) – The value to set the current motor position as specified by user. (i.e., 0.00 if homing)
- set_jog_speed(axis, speed)[source]
Task - Defines the jog speed for the specified axis.
This task will set the speed to move the axis continuously when ready to begin motion, but does not begin motion.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
speed (float) – The value of the speed in raw encoder units
Notes
The speed value here is not defined in terms of millimeters or degrees. User will have to define in encoder counts (i.e., 4000 for 4000 counts/sec).
- set_speed(axis, speed)[source]
Task - Sets the speed for a subsequent motion/move-to command (such as relative or absolute position motion).
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
speed (float) – Specified speed value in raw encoder units
Notes
The speed value here is not defined in terms of millimeters or degrees. User will have to define in encoder counts (i.e., 4000 for 4000 counts/sec).
- get_speed(axis)[source]
Task - Return the set speed for a given axis.
- Parameters:
axis (str) – Axis to query (e.g. ‘A’)
- set_acceleration(axis, acc)[source]
Task - Sets the acceleration for a subsequent motion/move-to command.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
acc (float) – Specified acceleration value in raw encoder units.
Notes
The acceleration value here is not defined in terms of millimters or degrees. User will have to define in encoder counts that are powers of 2. (i.e., ‘4096’ for 4096 counts/sec^2).
- get_acceleration(axis)[source]
Task - Query acceleration for a given axis.
- Parameters:
axis (str) – Axis to query (e.g. ‘A’)
- set_deceleration(axis, decel)[source]
Task - Sets the deceleration for a subsequent motion/move-to command.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
decel (float) – Deceleration in encoder units (counts/s^2)
Notes
User will have to define in encoder counts/s^2 in powers of 2, (e.g. 8192).
- get_deceleration(axis)[source]
Task - Returns the deceleration for a given axis.
- Parameters:
axis (str) – Axis to query (e.g. ‘A’)
- enable_sin_commutation(axis)[source]
Task - Enable sinusoidal commutation for a specified brushless axis.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
- set_limitswitch_mode(axis, val)[source]
Task - Enable or disable limit switch for a specified axis.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
val (int) – 0 = both enabled; 1 = forward disabled; 2 = reverse disabled; 3 = both disabled
- get_limitswitch_mode(axis)[source]
Task - Get the limit switch enable/disable setting for a given axis.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
- set_limitswitch_polarity(polarity)[source]
Task - Configure the limit switch polarity for all axes.
- Parameters:
polarity (int) – Limit switch polarity value. 0 is active-low (limit triggers when input goes low), 1 is active-high (limit triggers when input goes high).
- stop_axis_motion(axis)[source]
Task - Stop motion for specified axis.
- Parameters:
axis (str) – Specified axis. Ex. ‘A’
- set_gearing(order)[source]
Task - Configure electronic gearing relationships between follower and leader axes.
- Parameters:
order (str) – Comma-separated axis assignment string defining the leader/follower mapping (e.g., ‘,,,,,E’ assigns E as the leader for F axis).
- set_gearing_ratio(order)[source]
Task - Set electronic gearing ratio between leader and follower axes.
A ratio of 1 means the follower axis moves at the same speed as its leader axis.
- Parameters:
order (str) – Comma-separated string of gearing ratios for each axis, similar in format as set_gearing task. (e.g., ‘,,,,,1’)
- get_gearing_ratio(axis)[source]
Task - Query the current electronic gearing ratio for a specified axis
- Parameters:
axis (str) – Axis to query (e.g., ‘A’)