Monitoring¶
Position, IPOC, motor currents, applied corrections, override and STATUS reads, as dicts, NumPy or pandas.
Usage¶
# Comprehensive snapshot
data = api.monitoring.get_live_data()
# {"position": {X,Y,Z,A,B,C}, "velocity": {...}, "force": {...}, "ipoc": 123456}
# Individual reads
pos = api.monitoring.get_position() # {X, Y, Z, A, B, C}
ipoc = api.monitoring.get_ipoc() # Interrupt point counter
# Motor currents (MACur, an INTERNAL tag: Max and Full contexts). Units are
# not stated by KUKA - treat as relative. Raises RSIVariableError if the
# context has no MACur; get_force() is the older name and returns zeros then.
currents = api.monitoring.get_motor_currents() # {A1..A6}
# Max context only: what the controller actually applied, and $OV_PRO
api.monitoring.get_applied_correction() # POSCORRMON {X..C}, {} if not wired
api.monitoring.get_applied_joint_correction() # AXISCORRMON {A1..A6}
api.monitoring.get_override() # $OV_PRO %, None if not wired
api.monitoring.set_override(50) # 1-100; ValueError outside that
api.monitoring.get_correction_limit_status() # POSCORR Stat decoded, if your context
# gets it to the PC (it cannot come back over Ethernet - see docs/rsi-objects.md);
# None on the shipped contexts
api.monitoring.get_robot_status(1, "Mode_Op") # STATUS object n decoded ("T1", "AUT"...)
# NumPy/Pandas formats
arr = api.monitoring.get_live_data_as_numpy() # shape (4, 6)
df = api.monitoring.get_live_data_as_dataframe() # single-row DataFrame
# Console watch (blocking, Ctrl+C to stop)
api.monitoring.watch_network(duration=10, rate=0.2)
Reference¶
MonitoringAPI
¶
Real-time monitoring interface for KUKA RSI robot data.
Provides access to live position, velocity, force, and IPOC data in various formats for external processing and analysis.
Initialize MonitoringAPI namespace.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
RSIClient
|
RSIClient instance for accessing receive variables |
required |
get_live_data
¶
Retrieve comprehensive real-time RSI data.
Returns:
| Type | Description |
|---|---|
Dictionary containing
|
|
Velocity and acceleration are taken from Velocity/Acceleration
SEND variables when the config declares them (e.g. POSACT wired
through D objects in the RSI context); otherwise they are derived
from successive position samples - see _derive_motion() for the
accuracy caveats.
Example
data = api.monitoring.get_live_data() print(f"Position: {data['position']}") Position: {'X': 600.5, 'Y': -200.3, 'Z': 1450.8, 'A': 0.0, 'B': 0.0, 'C': 0.0} print(f"IPOC: {data['ipoc']}") IPOC: 123456
get_velocity
¶
Current TCP velocity in mm/s.
Returns:
| Type | Description |
|---|---|
Dict[str, float]
|
{X, Y, Z} in mm/s - from the config's Velocity variable if it declares one, otherwise differentiated from position. |
get_acceleration
¶
Current TCP acceleration in mm/s^2.
Returns:
| Type | Description |
|---|---|
Dict[str, float]
|
{X, Y, Z} in mm/s^2 - a second difference of position unless the config declares an Acceleration variable, so treat as indicative. |
get_live_data_as_numpy
¶
Retrieve live RSI data as a NumPy array.
Returns 2D array with rows: [position, velocity, acceleration, force] and columns padded to max length (6 for force axes).
Returns:
| Type | Description |
|---|---|
ndarray
|
NumPy array (4 x max_length) with robot state data |
Example
arr = api.monitoring.get_live_data_as_numpy() print(arr.shape) (4, 6) print(arr[0]) # Position row [600.5 -200.3 1450.8 0.0 0.0 0.0]
get_live_data_as_dataframe
¶
Retrieve live RSI data as a Pandas DataFrame.
Returns:
| Type | Description |
|---|---|
DataFrame
|
DataFrame with single row containing current robot state |
Example
df = api.monitoring.get_live_data_as_dataframe() print(df.columns)
Index(['position', 'velocity', 'acceleration', 'force', 'ipoc'])print(df['ipoc'][0])123456
get_ipoc
¶
Get current IPOC (Interrupt Point Counter) value.
The IPOC increments with each RSI cycle (typically every 4ms) and is used for synchronization between client and controller.
Returns:
| Type | Description |
|---|---|
Union[int, str]
|
Current IPOC value, or "N/A" if not available |
Example
ipoc = api.monitoring.get_ipoc() print(ipoc) 123456
get_position
¶
Get current TCP position in Cartesian coordinates.
Returns:
| Type | Description |
|---|---|
Dict[str, float]
|
Dictionary with X, Y, Z (mm) and A, B, C (degrees) orientation |
Example
pos = api.monitoring.get_position() print(f"TCP at X={pos['X']}, Y={pos['Y']}, Z={pos['Z']}") TCP at X=600.5, Y=-200.3, Z=1450.8
get_force
¶
Get current motor currents for all joints.
Motor current is a proxy for force/torque applied at each joint. Units depend on robot model and configuration.
Returns:
| Type | Description |
|---|---|
Dict[str, float]
|
Dictionary with A1-A6 motor current values |
Example
force = api.monitoring.get_force() print(f"Joint A1 current: {force['A1']}") Joint A1 current: 12.5
get_motor_currents
¶
Motor currents of the robot axes A1-A6, as the controller reports
them through the DEF_MACur INTERNAL tag (no channel cost).
Unlike :meth:get_force (the older name for the same data) this
raises when the context does not declare MACur instead of
returning zeros: a zero that means "not wired" looks exactly like a
real reading, and that kind of silent default has bitten this
project before. Only the Max and Full contexts declare MACur;
pass --internal DEF_MACur to RSIPI.config_builder to add it
to a generated config.
The object reference does not state the units. Treat the values as relative until they have been compared against the pendant.
Returns:
| Type | Description |
|---|---|
Dict[str, float]
|
Dictionary with A1-A6 motor current values (a copy). |
Raises:
| Type | Description |
|---|---|
RSIVariableError
|
if the config declares no |
Example
currents = api.monitoring.get_motor_currents() print(f"A1: {currents['A1']:.2f}")
get_applied_correction
¶
Cartesian correction the controller has actually applied (POSCORRMON).
This is the answer to "did the robot do what I asked?", which the commanded value cannot give you. A STOP object once silently stopped the controller applying any correction at all while RSI kept running perfectly - full packet rate, zero late packets, no error - and the only symptom was a pose that never changed. POSCORRMON would have shown that immediately.
Needs a context wiring POSCORRMON (max); returns an empty dict
otherwise.
Returns:
| Type | Description |
|---|---|
Dict[str, float]
|
X, Y, Z (mm) and A, B, C (degrees) of applied correction |
Example
api.motion.update_cartesian(X=5.0) api.monitoring.get_applied_correction()
get_applied_joint_correction
¶
Joint correction the controller has actually applied (AXISCORRMON).
The per-axis counterpart of :meth:get_applied_correction. Needs a
context wiring AXISCORRMON (max); returns an empty dict otherwise.
Returns:
| Type | Description |
|---|---|
Dict[str, float]
|
A1-A6 applied correction in degrees |
Example
api.monitoring.get_applied_joint_correction()['A6'] 0.02
get_correction_limit_status
¶
Is the controller clamping the Cartesian correction, and where?
POSCORR limits the cumulative correction and, per the RSI
reference, "if an input exceeds the valid range, the corresponding
maximum value is used" - it clamps and reports nothing. Its Stat
output is the only signal that this is happening, which is why a move
can stop dead at exactly the limit with no error anywhere.
Needs a context wiring POSCORR's Stat output (RSIPI_Max);
returns None otherwise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
raw
|
bool
|
return the integer instead of the decoded dict |
False
|
Returns:
| Type | Description |
|---|---|
dict | int | None
|
|
Example
api.monitoring.get_correction_limit_status()
get_robot_status
¶
Read a STATUS object's value, optionally decoded.
A STATUS object reports one controller status chosen by its Type
parameter, so a context may wire several. They appear as Status1,
Status2 and so on.
No shipped context includes a STATUS object - its Type is an enum
whose numeric value must come from RSIVisual rather than be guessed -
so this returns None unless you have added one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index
|
int
|
which Status |
1
|
meaning
|
Optional[str]
|
decode the number using one of STATUS_MEANINGS, e.g. "Sensor" or "Mode_Op". Omit for the raw integer. |
None
|
Returns:
| Type | Description |
|---|---|
Optional[Any]
|
The raw int, the decoded string, or None if not wired. |
Example
api.monitoring.get_robot_status(1, "Sensor") 'CYCLE' api.monitoring.get_robot_status(2, "Mode_Op") 'T1'
get_override
¶
Program override ($OV_PRO) as a percentage, or None if not wired.
Needs a context with an OV_PRO object (max).
Example
api.monitoring.get_override() 100
set_override
¶
Set the program override ($OV_PRO) from Python.
Slows or speeds the robot's programmed motion while RSI runs, which is a gentler lever than an E-stop when something looks wrong.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
percent
|
int
|
1-100. Values outside that are rejected rather than clamped - a silently clamped speed request is the kind of thing you only notice on the robot. |
required |
Raises:
| Type | Description |
|---|---|
RSIVariableError
|
if the config declares no OvProW channel, i.e. the context has no MAP2OV_PRO object |
ValueError
|
if percent is outside 1-100 |
Example
api.monitoring.set_override(30) 'Override set to 30%'
watch_network
¶
Continuously print live position and IPOC data to console.
Useful for monitoring network communication health and robot movement during testing and debugging.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
duration
|
Optional[float]
|
Watch duration in seconds (None = until Ctrl+C) |
None
|
rate
|
float
|
Update rate in seconds (default: 0.2 = 5 Hz) |
0.2
|