Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: integrate collision detection feature into robot model #163

Merged
merged 57 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
14f7775
feat: add headers
yrh012 Mar 13, 2024
3825e80
feat: implement source code
yrh012 Mar 13, 2024
f3641b7
feat: add cpp tests
yrh012 Mar 13, 2024
e0f38ce
feat: add meshes
yrh012 Mar 13, 2024
0234ab5
feat: add python bindings
yrh012 Mar 13, 2024
342ad6c
feat: test collisions in python
yrh012 Mar 13, 2024
aa34e49
fix: rename ur5e folder
yrh012 Mar 13, 2024
8664e82
fix: Dockerfile cache ID
yrh012 Mar 13, 2024
13a62f0
7.3.4 -> 7.3.5
github-actions[bot] Mar 13, 2024
7162321
Update CHANGELOG
github-actions[bot] Mar 13, 2024
044e891
Update source/robot_model/include/robot_model/Model.hpp
yrh012 Mar 13, 2024
584a2df
fix: apply review changes
yrh012 Mar 13, 2024
ae1f05f
Merge branch 'feat/collision-detection-robot' of github.com:aica-tech…
yrh012 Mar 13, 2024
3543719
fix: move import from hpp to cpp
yrh012 Mar 14, 2024
116a35a
fix: integrate function callback - WIP
yrh012 Mar 25, 2024
86d6803
feat: update tests
yrh012 Mar 26, 2024
e6151f5
fix: remove un-needed imports
yrh012 Mar 26, 2024
dba8693
fix: renove cache ID in docker
yrh012 Mar 26, 2024
6fbe7e9
fix: imports
yrh012 Mar 26, 2024
f70ad5c
Merge branch 'develop' into feat/collision-detection-robot
yrh012 Mar 26, 2024
9b05c05
7.3.5 -> 7.3.6
github-actions[bot] Mar 26, 2024
b543de6
fix: better check
yrh012 Mar 26, 2024
3fcb8b6
Merge branch 'feat/collision-detection-robot' of github.com:aica-tech…
yrh012 Mar 26, 2024
97b2396
fix: remove ros control blocks from URDF
yrh012 Mar 26, 2024
6748ece
fix: better load collisions check
yrh012 Mar 26, 2024
aa10d2a
suggestions
domire8 Mar 26, 2024
df7fe0c
fix: indendation
yrh012 Mar 26, 2024
d14b588
fix: urdf ros control blocks
yrh012 Mar 26, 2024
510eb56
7.3.6 -> 7.3.7
github-actions[bot] Mar 26, 2024
0a1a8ab
Update CHANGELOG
github-actions[bot] Mar 26, 2024
c00e516
Merge pull request #171 from aica-technology/feat/collision-improvements
yrh012 Mar 26, 2024
90453bb
fix: add exception if geometry model not loaded
yrh012 Mar 26, 2024
de5545e
fix: update doc strings
yrh012 Mar 26, 2024
41ca111
Update CHANGELOG.md
yrh012 Mar 26, 2024
fe09cb7
fix: optional parameter
yrh012 Mar 26, 2024
7b53eeb
fix: changelog
yrh012 Mar 26, 2024
0c0b573
fix: changelog
yrh012 Mar 26, 2024
b2ba71c
fix: create two Model constructors
yrh012 Mar 26, 2024
68c0df6
fix: remove ambiguity in binding
yrh012 Mar 26, 2024
0c95f0e
fix: adjust doc string
yrh012 Mar 26, 2024
4a560b9
fix: indentation
yrh012 Mar 26, 2024
95d8753
fix: nitpicks
yrh012 Mar 26, 2024
08c666e
Merge branch 'develop' into feat/collision-detection-robot
yrh012 Mar 26, 2024
36bb3e1
7.3.6 -> 7.3.7
github-actions[bot] Mar 26, 2024
4b312ca
fix: apply nitpicks from code review
yrh012 Mar 27, 2024
0dbb1ab
fix: add flag for copy constructor
yrh012 Mar 27, 2024
d119712
feat: add default flag
yrh012 Mar 27, 2024
72df3be
fix: suggestions from code review
yrh012 Mar 28, 2024
b983c92
fix: last nitpicks
yrh012 Mar 28, 2024
553727d
fix: spaces
yrh012 Mar 28, 2024
2d52b88
formatting
domire8 Mar 28, 2024
ab4e04a
fix: space between namings
yrh012 Mar 28, 2024
0d2d7f6
Merge branch 'develop' into feat/collision-detection-robot
yrh012 Mar 28, 2024
439e0dd
7.3.7 -> 7.3.8
github-actions[bot] Mar 28, 2024
df3c457
Merge branch 'develop' into feat/collision-detection-robot
yrh012 Apr 2, 2024
e8ab208
fix: remove space
yrh012 Apr 2, 2024
d3b3883
7.3.8 -> 7.3.10
yrh012 Apr 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Release Versions:

## Upcoming changes (in development)

- feat: integrate collision detection feature into robot model (#163)
- feat: add IO states to state representation (cpp) (#158)
- build: add missing licenses (#170)
- feat(build): handle installation and linking of dependencies for pinocchio collision support (#161)
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.3.6
7.3.7
2 changes: 1 addition & 1 deletion demos/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(control_libraries 7.3.6 CONFIG REQUIRED)
find_package(control_libraries 7.3.7 CONFIG REQUIRED)

set(DEMOS_SCRIPTS
task_space_control_loop
Expand Down
2 changes: 1 addition & 1 deletion doxygen/doxygen.conf
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ PROJECT_NAME = "Control Libraries"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = 7.3.6
PROJECT_NUMBER = 7.3.7

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
2 changes: 1 addition & 1 deletion protocol/clproto_cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.15)

project(clproto VERSION 7.3.6)
project(clproto VERSION 7.3.7)

# Default to C99
if(NOT CMAKE_C_STANDARD)
Expand Down
2 changes: 1 addition & 1 deletion python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# names of the environment variables that define osqp and openrobots include directories
osqp_path_var = 'OSQP_INCLUDE_DIR'

__version__ = "7.3.6"
__version__ = "7.3.7"
__libraries__ = ['state_representation', 'clproto', 'controllers', 'dynamical_systems', 'robot_model']
__include_dirs__ = ['include']

Expand Down
2 changes: 2 additions & 0 deletions python/source/robot_model/bind_exceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
#include <robot_model/exceptions/FrameNotFoundException.hpp>
#include <robot_model/exceptions/InvalidJointStateSizeException.hpp>
#include <robot_model/exceptions/InverseKinematicsNotConvergingException.hpp>
#include <robot_model/exceptions/CollisionGeometryException.hpp>

void bind_exceptions(py::module_& m) {
py::register_exception<robot_model::exceptions::FrameNotFoundException>(m, "FrameNotFoundError", PyExc_RuntimeError);
py::register_exception<robot_model::exceptions::InvalidJointStateSizeException>(m, "InvalidJointStateSizeError", PyExc_RuntimeError);
py::register_exception<robot_model::exceptions::InverseKinematicsNotConvergingException>(m, "InverseKinematicsNotConvergingErrors", PyExc_RuntimeError);
py::register_exception<robot_model::exceptions::CollisionGeometryException>(m, "CollisionGeometryError", PyExc_RuntimeError);
}
22 changes: 21 additions & 1 deletion python/source/robot_model/bind_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,23 @@ void model(py::module_& m) {

py::class_<Model> c(m, "Model");

c.def(py::init<const std::string&, const std::string&>(), "Constructor with robot name and path to URDF file.", "robot_name"_a, "urdf_path"_a);
c.def(py::init([](const std::string& robot_name, const std::string& urdf_path, py::object meshloader_callback) {
std::function<std::string(const std::string&)> callback_cpp = nullptr;
if (!meshloader_callback.is_none()) {
callback_cpp = [meshloader_callback](const std::string& package_name) -> std::string {
auto result = meshloader_callback(package_name).template cast<std::string>();
return result;
};
}
return new Model(robot_name, urdf_path, callback_cpp);
}), py::arg("robot_name"), py::arg("urdf_path"), py::arg("meshloader_callback"));


c.def(py::init<const std::string&, const std::string&>(),
domire8 marked this conversation as resolved.
Show resolved Hide resolved
py::arg("robot_name"),
py::arg("urdf_path")
);

c.def(py::init<const Model&>(), "Copy constructor from another Model", "model"_a);

c.def("get_robot_name", &Model::get_robot_name, "Getter of the robot name.");
Expand All @@ -44,6 +60,10 @@ void model(py::module_& m) {
c.def("set_gravity_vector", &Model::set_gravity_vector, "Setter of the gravity vector.", "gravity"_a);
// c.def("get_pinocchio_model", &Model::get_pinocchio_model, "Getter of the pinocchio model.");


c.def("check_collision", py::overload_cast<const JointPositions&>(&Model::check_collision), "Check if the robot is in collision at a given joint state.", "joint_positions"_a);
c.def("get_number_of_collision_pairs", &Model::get_number_of_collision_pairs, "Get the number of collision pairs in the model.");
c.def("is_geometry_model_initialized", &Model::is_geometry_model_initialized, "Check if the geometry model is initialized.");
c.def(
"compute_jacobian", py::overload_cast<const JointPositions&, const std::string&>(&Model::compute_jacobian),
"Compute the Jacobian from a given joint state at the frame given in parameter.", "joint_positions"_a, "frame"_a = std::string(""));
Expand Down
Binary file added python/test/model/meshes/ur5e/collision/base.stl
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
83 changes: 83 additions & 0 deletions python/test/model/test_collisions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import os
import unittest

from robot_model import Model
from state_representation import JointPositions

class RobotModelCollisionTesting(unittest.TestCase):
ur5e_with_geometries = None
ur5e_without_geometries = None
test_non_colliding_configs = []
test_colliding_configs = []

@staticmethod
def get_package_path_from_name(name):
if name == "ur_description":
return f'{os.path.dirname(os.path.realpath(__file__))}/'


@classmethod
def setUpClass(cls):
test_fixtures_path = os.path.join(os.path.dirname(os.path.realpath(__file__)))
cls.ur5e_with_geometries = Model("ur5e", os.path.join(test_fixtures_path, "ur5e.urdf"), meshloader_callback=cls.get_package_path_from_name)
cls.ur5e_without_geometries = Model("ur5e", os.path.join(test_fixtures_path, "ur5e.urdf"))
cls.set_test_non_colliding_configurations()
cls.set_test_colliding_configurations()

@classmethod
def set_test_non_colliding_configurations(cls):
config1 = JointPositions(cls.ur5e_with_geometries.get_robot_name(), 6)
config1.set_positions([0.0, -1.63, 1.45, 0.38, 0.0, 0.0])
cls.test_non_colliding_configs.append(config1)

config2 = JointPositions(cls.ur5e_with_geometries.get_robot_name(), 6)
config2.set_positions([0.0, -1.88, 1.45, 0.38, -4.4, -3.14])
cls.test_non_colliding_configs.append(config2)

config3 = JointPositions(cls.ur5e_with_geometries.get_robot_name(), 6)
config3.set_positions([1.26, -1.26, 0.82, 0.38, -4.4, 3.14])
cls.test_non_colliding_configs.append(config3)

@classmethod
def set_test_colliding_configurations(cls):
config1 = JointPositions(cls.ur5e_with_geometries.get_robot_name(), 6)
config1.set_positions([1.26, -1.76, 2.89, 0.38, -4.4, -6.16])
cls.test_colliding_configs.append(config1)

config2 = JointPositions(cls.ur5e_with_geometries.get_robot_name(), 6)
config2.set_positions([1.26, -1.76, 2.89, 0.38, -1.38, -1.16])
cls.test_colliding_configs.append(config2)

config3 = JointPositions(cls.ur5e_with_geometries.get_robot_name(), 6)
config3.set_positions([1.26, -1.76, -3.08, 0.75, -1.38, -6.16])
cls.test_colliding_configs.append(config3)

def test_number_of_collision_pairs_with_geometries(self):
num_pairs = self.ur5e_with_geometries.get_number_of_collision_pairs()
self.assertEqual(num_pairs, 15, "Expected 15 collision pairs for ur5e with geometries.")

def test_number_of_collision_pairs_without_geometries(self):
num_pairs = self.ur5e_without_geometries.get_number_of_collision_pairs()
self.assertEqual(num_pairs, 0, "Expected zero collision pairs for model without geometries.")

def test_geom_model_initialized_with_geometries(self):
is_initialized = self.ur5e_with_geometries.is_geometry_model_initialized()
self.assertTrue(is_initialized, "Expected geometry model to be initialized for model with geometries.")

def test_geom_model_initialized_without_geometries(self):
is_initialized = self.ur5e_without_geometries.is_geometry_model_initialized()
self.assertFalse(is_initialized, "Expected geometry model to not be initialized for model without geometries.")

def test_no_collision_detected(self):
for config in self.test_non_colliding_configs:
is_colliding = self.ur5e_with_geometries.check_collision(config)
self.assertFalse(is_colliding, "Expected no collision for configuration")

def test_collision_detected(self):
for config in self.test_colliding_configs:
is_colliding = self.ur5e_with_geometries.check_collision(config)
self.assertTrue(is_colliding, "Expected collision for configuration")


if __name__ == '__main__':
unittest.main()
Loading
Loading