Hi everyone,
I’m opening a new thread to better explain my use case and ask for guidance on dynamic parameter identification with the OpenSourceLeg 2.0 (knee + ankle, Dephy Actpack).
Context
My final goal is offline inverse-dynamics / least-squares identification of the leg dynamics. For this reason, I need to reliably acquire:
-
joint position qqq
-
joint velocity q˙\dot{q}q˙
-
joint acceleration q¨\ddot{q}q¨ (offline estimation is fine)
-
joint torque τ\tauτ
I’m currently using position control only (no impedance / current control), with excitation trajectories designed to be LS-friendly (multisine, chirp, decoupled motions, etc.).
One source of confusion for me is that some of the scripts I started from were shown to us directly during a lab demo of the OpenSourceLeg 2.0 (by Humotech), while the repository examples sometimes use slightly different APIs or signal names. So I’m not fully confident about which signals are measured, which are estimated, and which are recommended for identification. Below is a minimal version of the acquisition code, stripped down to only the essential control commands and logged signals.
My doubts are mainly about signal meaning and best practices:
-
Joint torque
-
What exactly is
joint_torque? -
Is it:
-
computed from motor current?
-
model-based?
-
filtered / estimated internally?
-
-
Is this the recommended torque signal for inverse dynamics identification?
-
-
Gear ratio
-
Why is the gear ratio explicitly specified when adding a joint?
-
Does it affect:
-
output_position? -
output_velocity? -
joint_torque?
-
-
In other words: are these quantities already expressed at the joint side, or partially motor-side?
-
-
Joint velocity
-
What is
output_velocityexactly?-
encoder-based differentiation?
-
observer?
-
filtered signal?
-
-
For identification purposes, is it better to use this signal, or to numerically differentiate
output_positionoffline?
-
-
Acceleration
- Is the standard approach to estimate q¨\ddot{q}q¨ offline (e.g. Savitzky–Golay on velocity), or is there any internal signal that should be preferred?
Any advice, clarification, or reference to recommended practices for system identification with OSL + Dephy Actpack would be extremely valuable for me.
Thanks very much in advance for your time and help — any suggestion is genuinely useful.
import time import numpy as np from opensourceleg.osl import OpenSourceLeg from opensourceleg.tools import units
frequency = 200 # Hz run_seconds = 40.0
Simple excitation trajectories
def knee_traj(t): return 40.0 * np.sin(1.2 * t) + 40.0 # deg
def ankle_traj(t): return 20.0 * np.sin(1.0 * t) # deg
-------------------- OSL INIT --------------------
osl = OpenSourceLeg(frequency=frequency) osl.add_joint(“knee”, gear_ratio=9 * 83 / 18, port=“/dev/ttyACM0”) osl.add_joint(“ankle”, gear_ratio=9 * 83 / 18, port=“/dev/ttyACM1”)
t_log = qk_log = ; qa_log = qkp_log = ; qap_log = tau_k_log = ; tau_a_log = ik_log = ; ia_log =
with osl: osl.home() input(“Homing complete. Press ENTER to start.”)
osl.knee.set_mode(osl.knee.control_modes.position)
osl.ankle.set_mode(osl.ankle.control_modes.position)
osl.knee.set_position_gains(kp=10)
osl.ankle.set_position_gains(kp=10)
# Warm-up
for _ in range(20):
osl.update()
time.sleep(0.01)
t0 = time.time()
for t in osl.clock:
if time.time() - t0 > run_seconds:
break
osl.update()
# Commanded positions
qk_cmd = units.convert_to_default(knee_traj(t), units.position.deg)
qa_cmd = units.convert_to_default(ankle_traj(t), units.position.deg)
osl.knee.set_output_position(qk_cmd)
osl.ankle.set_output_position(qa_cmd)
# ---------------- Measurements ----------------
qk = float(osl.knee.output_position)
qa = float(osl.ankle.output_position)
qkp = float(getattr(osl.knee, "output_velocity", np.nan))
qap = float(getattr(osl.ankle, "output_velocity", np.nan))
tau_k = float(getattr(osl.knee, "joint_torque", np.nan))
tau_a = float(getattr(osl.ankle, "joint_torque", np.nan))
ik = float(getattr(osl.knee, "motor_current", np.nan))
ia = float(getattr(osl.ankle, "motor_current", np.nan))
# Log
t_log.append(t)
qk_log.append(qk); qa_log.append(qa)
qkp_log.append(qkp); qap_log.append(qap)
tau_k_log.append(tau_k); tau_a_log.append(tau_a)
ik_log.append(ik); ia_log.append(ia)