Skip to content

Commit bd75426

Browse files
authored
Re-add optimizer based on scipy.optimize.minimize (#135)
* Re-add scalar optimizer that can be selected via a configurable parameter * Fix tests
1 parent d475ef2 commit bd75426

File tree

3 files changed

+26
-5
lines changed

3 files changed

+26
-5
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ jobs:
2626
strategy:
2727
max-parallel: 4
2828
matrix:
29-
# Note: We need to quote '3.10' otherwise it's interpreted as as number, e.g. 3.1
30-
python-version: [3.6, 3.7, 3.8, 3.9, '3.10']
29+
# Note: We need to quote '3.10' and '3.11' otherwise it's interpreted as as number, e.g. 3.1
30+
python-version: [3.7, 3.8, 3.9, '3.10', "3.11"]
3131
steps:
3232
- uses: actions/checkout@v1
3333
name: "Checkout branch"

src/ikpy/inverse_kinematics.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
ORIENTATION_COEFF = 1.
88

99

10-
def inverse_kinematic_optimization(chain, target_frame, starting_nodes_angles, regularization_parameter=None, max_iter=None, orientation_mode=None, no_position=False):
10+
def inverse_kinematic_optimization(chain, target_frame, starting_nodes_angles, regularization_parameter=None, max_iter=None, orientation_mode=None, no_position=False, optimizer="least_squares"):
1111
"""
1212
Computes the inverse kinematic on the specified target
1313
@@ -32,7 +32,14 @@ def inverse_kinematic_optimization(chain, target_frame, starting_nodes_angles, r
3232
* "all": Target the three axes
3333
no_position: bool
3434
Do not optimize against position
35+
optimizer: str
36+
The solver to use. Choices:
37+
* "least_squares": Use scipy.optimize.least_squares
38+
* "scalar": Use scipy.optimize.minimize
3539
"""
40+
if optimizer not in ["least_squares", "scalar"]:
41+
raise ValueError("Unknown solver: {}".format(optimizer))
42+
3643
# Begin with the position
3744
target = target_frame[:3, -1]
3845

@@ -124,15 +131,22 @@ def optimize_total(x):
124131
# Compute bounds
125132
real_bounds = [link.bounds for link in chain.links]
126133
# real_bounds = real_bounds[chain.first_active_joint:]
127-
real_bounds = np.moveaxis(chain.active_from_full(real_bounds), -1, 0)
134+
real_bounds = chain.active_from_full(real_bounds)
128135

129136
logs.logger.info("Bounds: {}".format(real_bounds))
130137

131138
if max_iter is not None:
132139
logs.logger.info("max_iter is not used anymore in the IK, using it as a parameter will raise an exception in the future")
133140

134141
# least squares optimization
135-
res = scipy.optimize.least_squares(optimize_total, chain.active_from_full(starting_nodes_angles), bounds=real_bounds)
142+
if optimizer == "scalar":
143+
def optimize_scalar(x):
144+
return np.linalg.norm(optimize_total(x))
145+
res = scipy.optimize.minimize(optimize_scalar, chain.active_from_full(starting_nodes_angles), bounds=real_bounds)
146+
elif optimizer == "least_squares":
147+
# We need to unzip the bounds
148+
real_bounds = np.moveaxis(real_bounds, -1, 0)
149+
res = scipy.optimize.least_squares(optimize_total, chain.active_from_full(starting_nodes_angles), bounds=real_bounds)
136150

137151
if res.status != -1:
138152
logs.logger.info("Inverse kinematic optimisation OK, termination status: {}".format(res.status))

tests/test_chain.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ def test_ik_optimization(torso_right_arm):
7676
np.testing.assert_almost_equal(
7777
torso_right_arm.forward_kinematics(ik)[:3, 3], target, decimal=3)
7878

79+
# Check using the scalar optimizer
80+
ik = torso_right_arm.inverse_kinematics_frame(
81+
frame_target, initial_position=joints, optimizer="scalar")
82+
# Check whether the results are almost equal
83+
np.testing.assert_almost_equal(
84+
torso_right_arm.forward_kinematics(ik)[:3, 3], target, decimal=3)
85+
7986

8087
def test_chain_serialization(torso_right_arm):
8188

0 commit comments

Comments
 (0)