Skip to content

Commit 1549990

Browse files
authored
Merge pull request #333 from compas-dev/ik_analytical_addon
Ik analytical addon
2 parents 747ac9f + c4bbe6a commit 1549990

File tree

7 files changed

+71
-5
lines changed

7 files changed

+71
-5
lines changed

CHANGELOG.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Unreleased
1818

1919
**Fixed**
2020

21+
* Consider ``AttachedCollisionMesh`` in ``AnalyticalInverseKinematics``
22+
2123
**Deprecated**
2224

2325
**Removed**

docs/examples/06_backends_kinematics/files/02_iter_ik_pybullet.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from compas.geometry import Frame
2+
from compas.robots import LocalPackageMeshLoader
23
import compas_fab
34
from compas_fab.backends.kinematics import AnalyticalInverseKinematics
45
from compas_fab.backends import PyBulletClient
@@ -13,7 +14,8 @@
1314
with PyBulletClient(connection_type='direct') as client:
1415

1516
# Load UR5
16-
robot = client.load_robot(urdf_filename)
17+
loader = LocalPackageMeshLoader(compas_fab.get('universal_robot'), 'ur_description')
18+
robot = client.load_robot(urdf_filename, [loader])
1719
client.load_semantics(robot, srdf_filename)
1820

1921
ik = AnalyticalInverseKinematics(client)

docs/examples/06_backends_kinematics/files/03_iter_ik_analytic_pybullet.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import compas_fab
22
from compas.geometry import Frame
3+
from compas.robots import LocalPackageMeshLoader
34
from compas_fab.backends.kinematics.client import AnalyticalPyBulletClient
45

56
urdf_filename = compas_fab.get('universal_robot/ur_description/urdf/ur5.urdf')
67
srdf_filename = compas_fab.get('universal_robot/ur5_moveit_config/config/ur5.srdf')
78

89
with AnalyticalPyBulletClient(connection_type='direct') as client:
9-
robot = client.load_robot(urdf_filename)
10+
loader = LocalPackageMeshLoader(compas_fab.get('universal_robot'), 'ur_description')
11+
robot = client.load_robot(urdf_filename, [loader])
1012
client.load_semantics(robot, srdf_filename)
1113

1214
frame_WCF = Frame((0.381, 0.093, 0.382), (0.371, -0.292, -0.882), (0.113, 0.956, -0.269))

docs/examples/06_backends_kinematics/files/04_cartesian_path_analytic_pybullet.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import matplotlib.pyplot as plt
22
from compas.geometry import Frame
3+
from compas.robots import LocalPackageMeshLoader
34
import compas_fab
45
from compas_fab.backends.kinematics.client import AnalyticalPyBulletClient
56

@@ -13,7 +14,8 @@
1314
Frame((0.376, 0.087, 0.299), (0.850, 0.000, 0.528), (0.184, 0.937, -0.296))]
1415

1516
with AnalyticalPyBulletClient(connection_type='direct') as client:
16-
robot = client.load_robot(urdf_filename)
17+
loader = LocalPackageMeshLoader(compas_fab.get('universal_robot'), 'ur_description')
18+
robot = client.load_robot(urdf_filename, [loader])
1719
client.load_semantics(robot, srdf_filename)
1820

1921
options = {"solver": "ur5", "check_collision": True}

src/compas_fab/backends/__init__.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@
3939
PyBulletPlanner
4040
PyBulletError
4141
42+
43+
Analytical Kinematics
44+
---------------------
45+
46+
.. autosummary::
47+
:toctree: generated/
48+
:nosignatures:
49+
50+
AnalyticalPyBulletClient
51+
AnalyticalInverseKinematics
52+
AnalyticalPlanCartesianMotion
53+
54+
4255
Long-running tasks
4356
------------------
4457
@@ -116,6 +129,15 @@
116129
from .pybullet.planner import (
117130
PyBulletPlanner,
118131
)
132+
from .kinematics.client import (
133+
AnalyticalPyBulletClient,
134+
)
135+
from .kinematics import (
136+
AnalyticalInverseKinematics,
137+
)
138+
from .kinematics.client import (
139+
AnalyticalPlanCartesianMotion,
140+
)
119141

120142
__all__ = [
121143
'BackendError',
@@ -138,4 +160,8 @@
138160
'PyBulletClient',
139161
'PyBulletError',
140162
'PyBulletPlanner',
163+
'AnalyticalPyBulletClient',
164+
'AnalyticalInverseKinematics',
165+
'AnalyticalPlanCartesianMotion',
166+
141167
]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,23 @@
1+
"""
2+
*******************************************************************************
3+
compas_fab.backends.kinematics
4+
*******************************************************************************
5+
6+
.. module:: compas_fab.backends.kinematics
7+
8+
.. autosummary::
9+
:toctree: generated/
10+
11+
AnalyticalInverseKinematics
12+
AnalyticalPlanCartesianMotion
13+
InverseKinematicsError
14+
CartesianMotionError
15+
16+
"""
17+
18+
from __future__ import absolute_import
119
from .analytical_inverse_kinematics import AnalyticalInverseKinematics # noqa: F401
220
from .analytical_plan_cartesian_motion import AnalyticalPlanCartesianMotion # noqa: F401
21+
from .exceptions import * # noqa: F401,F403
22+
23+
__all__ = [name for name in dir() if not name.startswith('_')]

src/compas_fab/backends/kinematics/analytical_inverse_kinematics.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ def inverse_kinematics(self, robot, frame_WCF, start_configuration=None, group=N
7676
------
7777
ValueError : If the solver to solve the kinematics has not been passed.
7878
"""
79+
7980
options = options or {}
8081
solver = options.get('solver')
8182
if solver:
@@ -90,11 +91,21 @@ def inverse_kinematics(self, robot, frame_WCF, start_configuration=None, group=N
9091
frame_RCF = base_frame.to_local_coordinates(frame_WCF)
9192

9293
# calculate inverse with 8 solutions
93-
solutions = self.planner.inverse(frame_RCF)
94+
try:
95+
solutions = self.planner.inverse(frame_RCF)
96+
except ValueError:
97+
raise InverseKinematicsError()
9498
configurations = joint_angles_to_configurations(robot, solutions, group=group)
9599

96100
# check collisions for all configurations (>> sets those to `None` that are not working)
97101
if options.get("check_collision", False) is True:
102+
acms = options.get('attached_collision_meshes', [])
103+
for acm in acms:
104+
cached_robot_model = self.client.get_cached_robot(robot)
105+
if not cached_robot_model.get_link_by_name(acm.collision_mesh.id):
106+
self.client.add_attached_collision_mesh(acm, options={'robot': robot})
107+
for touch_link in acm.touch_links:
108+
self.client.disabled_collisions.add((touch_link, acm.collision_mesh.id))
98109
for i, config in enumerate(configurations):
99110
try:
100111
self.client.check_collisions(robot, config)
@@ -105,7 +116,7 @@ def inverse_kinematics(self, robot, frame_WCF, start_configuration=None, group=N
105116
configurations = try_to_fit_configurations_between_bounds(robot, configurations, group=group)
106117

107118
if not any(configurations):
108-
raise InverseKinematicsError("No solutions found.")
119+
raise InverseKinematicsError()
109120

110121
for config in configurations:
111122
if config:

0 commit comments

Comments
 (0)