diff --git a/setup.py b/setup.py
index 7d9a3dc..e73a2ec 100644
--- a/setup.py
+++ b/setup.py
@@ -16,7 +16,7 @@
setup(
name="teleop",
- version="0.1.0",
+ version="0.1.1",
packages=["teleop", "teleop.basic", "teleop.ros2", "teleop.utils", "teleop.ros2_ik", "teleop.xarm"],
long_description=long_description,
long_description_content_type="text/markdown",
diff --git a/teleop/index.html b/teleop/index.html
index 9be2849..4187cdc 100644
--- a/teleop/index.html
+++ b/teleop/index.html
@@ -127,6 +127,14 @@
Teleop
this.gripper = (this.gripper === 'open') ? 'close' : 'open';
}
gamepad.buttons[0].wasPressed = gamepad.buttons[0].pressed;
+
+ this.reservedButtonA = gamepad.buttons[4] && gamepad.buttons[4].pressed;
+ this.reservedButtonB = gamepad.buttons[5] && gamepad.buttons[5].pressed;
+
+ const gamepadAxis = gamepad.axes[0];
+ if (gamepadAxis !== undefined && Math.abs(gamepadAxis) > 0.1) {
+ this.scale = Math.max(0.2, Math.min(1.0, this.scale + gamepadAxis * 0.1));
+ }
}
}
}
diff --git a/teleop/utils/jacobi_robot.py b/teleop/utils/jacobi_robot.py
index 422431a..09e4482 100644
--- a/teleop/utils/jacobi_robot.py
+++ b/teleop/utils/jacobi_robot.py
@@ -39,15 +39,15 @@ def __init__(
self,
urdf_path: str,
ee_link: str = "end_effector",
- max_linear_vel: float = 0.4,
- max_angular_vel: float = 1.8,
- max_linear_acc: float = 3.0,
- max_angular_acc: float = 6.0,
+ max_linear_vel: float = 0.8,
+ max_angular_vel: float = 3.0,
+ max_linear_acc: float = 6.0,
+ max_angular_acc: float = 8.0,
max_joint_vel: float = 5.0,
min_linear_vel: float = 0.03,
min_angular_vel: float = 0.1,
linear_gain: float = 20.0,
- angular_gain: float = 8.0,
+ angular_gain: float = 12.0,
):
"""
Initialize the Pinocchio robot with servo control capabilities.
@@ -93,6 +93,16 @@ def __init__(
self.max_iter = 100
self.damping = 1e-4 # Increased damping for stability
+ # IK regularization parameters
+ self.joint_regularization = 0.01 # Joint position regularization weight
+ self.velocity_regularization = 0.001 # Joint velocity regularization weight
+ self.manipulability_threshold = (
+ 0.01 # Threshold for manipulability-based regularization
+ )
+ self.desired_joint_config = pin.neutral(
+ self.model
+ ).copy() # Target joint configuration for regularization
+
# Previous velocities for acceleration limiting
self.prev_linear_vel = np.zeros(3)
self.prev_angular_vel = np.zeros(3)
@@ -139,11 +149,11 @@ def twist(
J = self.__compute_jacobian()
# Create desired spatial velocity vector
desired_spatial_vel = np.concatenate([linear_velocity, angular_velocity_rpy])
- # Use SVD for more stable pseudo-inverse
- U, s, Vt = np.linalg.svd(J, full_matrices=False)
- s_inv = np.where(s > 1e-6, 1.0 / s, 0.0) # Threshold small singular values
- J_pinv = Vt.T @ np.diag(s_inv) @ U.T
- joint_velocities = J_pinv @ desired_spatial_vel
+
+ # Use regularized pseudo-inverse
+ J_pinv, joint_bias = self.__compute_regularized_jacobian_pinv(J)
+ joint_velocities = J_pinv @ desired_spatial_vel + joint_bias
+
# Apply joint velocity limits
for i in range(len(joint_velocities)):
if i < len(self.dq_max) and self.dq_max[i] > 0:
@@ -268,15 +278,12 @@ def servo_to_pose(
current_spatial_vel = self.__get_ee_velocity()
desired_spatial_vel -= damping_factor * current_spatial_vel
- # Compute joint velocities using damped pseudo-inverse
+ # Compute joint velocities using regularized pseudo-inverse
J = self.__compute_jacobian()
- # Use SVD for more stable pseudo-inverse
- U, s, Vt = np.linalg.svd(J, full_matrices=False)
- s_inv = np.where(s > 1e-6, 1.0 / s, 0.0) # Threshold small singular values
- J_pinv = Vt.T @ np.diag(s_inv) @ U.T
-
- joint_velocities = J_pinv @ desired_spatial_vel
+ # Use regularized pseudo-inverse with multiple regularization terms
+ J_pinv, joint_bias = self.__compute_regularized_jacobian_pinv(J)
+ joint_velocities = J_pinv @ desired_spatial_vel + joint_bias
# Apply joint velocity limits
for i in range(len(joint_velocities)):
@@ -418,7 +425,7 @@ def stop_visualization(self):
plt.close(self.fig)
def print_status(self):
- """Print current robot status."""
+ """Print current robot status including IK diagnostics."""
ee_pose = self.get_ee_pose()
print(f"\n--- Robot Status ---")
@@ -463,6 +470,97 @@ def get_joint_velocity(self, joint_name: str) -> float:
raise ValueError(f"Joint '{joint_name}' not found in model.")
return self.dq[joint_index]
+ def __compute_regularized_jacobian_pinv(self, J: np.ndarray) -> np.ndarray:
+ """
+ Compute regularized pseudo-inverse of Jacobian with multiple regularization terms.
+
+ Args:
+ J: Jacobian matrix
+
+ Returns:
+ Regularized pseudo-inverse of Jacobian
+ """
+ n_joints = J.shape[1]
+
+ # Compute manipulability measure
+ manipulability = np.sqrt(np.linalg.det(J @ J.T))
+
+ # Adaptive damping based on manipulability
+ adaptive_damping = self.damping
+ if manipulability < self.manipulability_threshold:
+ # Increase damping near singularities
+ damping_factor = self.manipulability_threshold / (manipulability + 1e-8)
+ adaptive_damping = self.damping * min(damping_factor, 10.0)
+
+ # Joint position regularization (bias towards desired joint configuration)
+ joint_position_error = self.q - self.desired_joint_config
+ W_joint = np.eye(n_joints) * self.joint_regularization
+
+ # Joint velocity regularization (bias towards zero velocity)
+ W_velocity = np.eye(n_joints) * self.velocity_regularization
+
+ # Combined regularization matrix
+ W_reg = W_joint + W_velocity
+
+ # Damped least squares with regularization
+ # J_pinv = (J^T J + λI + W_reg)^(-1) J^T
+ JTJ = J.T @ J
+ regularization_matrix = adaptive_damping * np.eye(n_joints) + W_reg
+
+ try:
+ # Primary method: Regularized normal equation
+ J_pinv = np.linalg.solve(JTJ + regularization_matrix, J.T)
+ except np.linalg.LinAlgError:
+ # Fallback: SVD-based regularized pseudo-inverse
+ U, s, Vt = np.linalg.svd(J, full_matrices=False)
+ s_reg = s / (s**2 + adaptive_damping) # Regularized singular values
+ J_pinv = Vt.T @ np.diag(s_reg) @ U.T
+
+ # Add joint position bias term
+ joint_bias = -self.joint_regularization * joint_position_error
+
+ return J_pinv, joint_bias
+
+ def set_regularization_params(
+ self,
+ joint_regularization: float = None,
+ velocity_regularization: float = None,
+ manipulability_threshold: float = None,
+ damping: float = None,
+ desired_joint_config: np.ndarray = None,
+ ):
+ """
+ Set IK regularization parameters.
+
+ Args:
+ joint_regularization: Weight for joint position regularization (bias towards desired config)
+ velocity_regularization: Weight for joint velocity regularization (bias towards zero)
+ manipulability_threshold: Threshold for manipulability-based adaptive damping
+ damping: Base damping factor for singularity avoidance
+ desired_joint_config: Target joint configuration for regularization (bias towards these angles)
+ """
+ if joint_regularization is not None:
+ self.joint_regularization = joint_regularization
+ if velocity_regularization is not None:
+ self.velocity_regularization = velocity_regularization
+ if manipulability_threshold is not None:
+ self.manipulability_threshold = manipulability_threshold
+ if damping is not None:
+ self.damping = damping
+ if desired_joint_config is not None:
+ if len(desired_joint_config) != self.model.nq:
+ raise ValueError(
+ f"desired_joint_config must have {self.model.nq} elements, got {len(desired_joint_config)}"
+ )
+ self.desired_joint_config = np.array(desired_joint_config)
+
+ print(f"Regularization parameters updated:")
+ print(f" Joint regularization: {self.joint_regularization}")
+ print(f" Velocity regularization: {self.velocity_regularization}")
+ print(f" Manipulability threshold: {self.manipulability_threshold}")
+ print(f" Damping: {self.damping}")
+ print(f" Desired joint config: {np.round(self.desired_joint_config, 3)}")
+
if __name__ == "__main__":
import time