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 min distance #167

Merged
merged 82 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 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
9efa13f
feat: compute minimum distances
yrh012 Mar 14, 2024
90bdfdb
feat: compute minimum distance pybind + unit test
yrh012 Mar 15, 2024
396cdd1
fix: adjust comments
yrh012 Mar 15, 2024
b2dd73c
7.3.5 -> 7.3.6
github-actions[bot] Mar 15, 2024
568408d
Update CHANGELOG
github-actions[bot] Mar 15, 2024
4187632
fix: unsigned int for consistency
yrh012 Mar 19, 2024
fdc6ed4
Merge branch 'feat/integrate-min-distance' of github.com:aica-technol…
yrh012 Mar 19, 2024
9d4c558
fix: unsigned to unsigned int
yrh012 Mar 19, 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
1905452
Merge branch 'feat/collision-detection-robot' of github.com:aica-tech…
yrh012 Mar 26, 2024
6748ece
fix: better load collisions check
yrh012 Mar 26, 2024
1d1f120
Merge branch 'feat/collision-detection-robot' of github.com:aica-tech…
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
167a7c3
Merge branch 'feat/integrate-min-distance' of github.com:aica-technol…
yrh012 Apr 2, 2024
3b8c610
merge: collision detection robot
yrh012 Apr 2, 2024
bb73f60
7.3.8 -> 7.3.9
github-actions[bot] Apr 2, 2024
99cd154
7.3.8 -> 7.3.10
yrh012 Apr 2, 2024
16426e9
feat: update change
yrh012 Apr 2, 2024
321fb4a
fix: raise exception if geom not loaded
yrh012 Apr 2, 2024
4981085
fix: nitpick
yrh012 Apr 2, 2024
af1e9fb
merge: develop
yrh012 Apr 3, 2024
a0466b4
Merge branch 'feat/integrate-min-distance' of github.com:aica-technol…
yrh012 Apr 3, 2024
af0d21a
7.3.10 -> 7.3.11
github-actions[bot] Apr 3, 2024
5ce7cb9
model + test collisions
yrh012 Apr 4, 2024
fd3ffac
fix: merge
yrh012 Apr 4, 2024
2444297
fix: apply nitpicks
yrh012 Apr 8, 2024
0025bfe
fix: change method nanme
yrh012 Apr 8, 2024
08310cc
Merge branch 'feat/integrate-min-distance' of github.com:aica-technol…
yrh012 Apr 8, 2024
8d21227
Merge branch 'develop' into feat/integrate-min-distance
yrh012 Apr 8, 2024
6bbdd55
7.3.11 -> 7.3.12
yrh012 Apr 8, 2024
0523c96
Merge branch 'feat/integrate-min-distance' of github.com:aica-technol…
yrh012 Apr 8, 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 minimum distance calculation feature into robot model(#167)
- ci: update workflows (#175)
- feat: integrate collision detection feature into robot model (#163)
- feat: add IO states to state representation (py) (#173)
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.3.11
7.3.12
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.11 CONFIG REQUIRED)
find_package(control_libraries 7.3.12 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.11
PROJECT_NUMBER = 7.3.12

# 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.11)
project(clproto VERSION 7.3.12)

# 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.11"
__version__ = "7.3.12"
__libraries__ = ['state_representation', 'clproto', 'controllers', 'dynamical_systems', 'robot_model']
__include_dirs__ = ['include']

Expand Down
1 change: 1 addition & 0 deletions python/source/robot_model/bind_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ void model(py::module_& m) {


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("compute_minimum_collision_distances", py::overload_cast<const JointPositions&>(&Model::compute_minimum_collision_distances), "Compute the minimum distances between the robot links.", "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(
Expand Down
24 changes: 24 additions & 0 deletions python/test/model/test_collisions.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import os
import unittest

import numpy as np
from robot_model import Model
from state_representation import JointPositions


class RobotModelCollisionTesting(unittest.TestCase):
ur5e_with_geometries = None
ur5e_without_geometries = None
Expand Down Expand Up @@ -78,6 +80,28 @@ def test_collision_detected(self):
is_colliding = self.ur5e_with_geometries.check_collision(config)
self.assertTrue(is_colliding, "Expected collision for configuration")

def test_minimum_distance_computed_no_collision(self):
for config in self.test_non_colliding_configs:
distances = self.ur5e_with_geometries.compute_minimum_collision_distances(config)
self.assertEqual(distances.shape, (6, 6), "Distance matrix has incorrect shape.")

# Check that no element is equal to zero besides the diagonals
for i in range(distances.shape[0]):
for j in range(distances.shape[1]):
if i != j and j != i+1 and i != j+1: # Skip diagonal and adjacent elements
self.assertGreaterEqual(distances[i, j], 0.01, "Found a distance at non-diagonal element indicating a collision.")

def test_minimum_distance_computed_collision(self):
for config in self.test_colliding_configs:
distances = self.ur5e_with_geometries.compute_minimum_collision_distances(config)
self.assertEqual(distances.shape, (6, 6), "Distance matrix has incorrect shape.")

# Initialize a variable to keep track of the minimum non-diagonal distance
minimum_distance = np.min(distances[np.triu_indices(n=6, k=2)])
# Expect the minimum non-diagonal distance to indicate a collision
self.assertLessEqual(minimum_distance, 0.01, "Did not find a minimum distance less than a threshold indicating a collision.")



if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion source/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.15)

project(control_libraries VERSION 7.3.11)
project(control_libraries VERSION 7.3.12)

# Build options
option(BUILD_TESTING "Build all tests." OFF)
Expand Down
9 changes: 9 additions & 0 deletions source/robot_model/include/robot_model/Model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,15 @@ class Model {
*/
static bool create_urdf_from_string(const std::string& urdf_string, const std::string& desired_path);

/**
* @brief Compute the minimum distances between the robot links
* @details The distances are computed for each collision pair, resulting in a square matrix with
* the same size as the number of joints. The diagonal entries are always zero.
* @param joint_positions state_representation object containing the joint positions of the robot
* @return the matrix containing the minimum distance between the robot links
*/
Eigen::MatrixXd compute_minimum_collision_distances(const state_representation::JointPositions& joint_positions);

/**
* @brief Check if the links of the robot are in collision
* @param joint_positions containing the joint positions of the robot
Expand Down
28 changes: 28 additions & 0 deletions source/robot_model/src/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,34 @@ bool Model::check_collision(const state_representation::JointPositions& joint_po
return false;
}

Eigen::MatrixXd Model::compute_minimum_collision_distances(const state_representation::JointPositions& joint_positions) {
if (!this->is_geometry_model_initialized()) {
throw robot_model::exceptions::CollisionGeometryException(
"Geometry model not loaded for " + this->get_robot_name());
}
Eigen::VectorXd configuration = joint_positions.get_positions();
pinocchio::computeDistances(
this->robot_model_, this->robot_data_, this->geom_model_, this->geom_data_, configuration);

// nb_joints is the number of joints in the robot model
unsigned int nb_joints = this->get_number_of_joints();

// create a square matrix to store the distances and initialize to zero
Eigen::MatrixXd distances = Eigen::MatrixXd::Zero(nb_joints, nb_joints);

// iterate over the collision pairs and extract the distances
unsigned int pair_index = 0;
for (unsigned int row_index = 0; row_index < nb_joints; ++row_index) {
for (unsigned int column_index = row_index + 1; column_index < nb_joints; ++column_index) {
distances(row_index, column_index) = this->geom_data_.distanceResults[pair_index].min_distance;
distances(column_index, row_index) = distances(row_index, column_index);
pair_index++;
}
}

return distances;
}

bool Model::init_qp_solver() {
// clear the solver
this->solver_.data()->clearHessianMatrix();
Expand Down
54 changes: 54 additions & 0 deletions source/robot_model/test/tests/test_collisions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,57 @@ TEST_F(RobotModelCollisionTesting, CollisionDetected) {
EXPECT_TRUE(is_colliding) << "Expected collision for configuration " << config;
}
}

// Test that compute_minimum_collision_distances method identifies a collision-free state
TEST_F(RobotModelCollisionTesting, MinimumDistanceComputedNoCollision) {
// iterate over test configurations and check for collision
set_test_non_coliding_configurations();

for (auto& config : test_non_coliding_configs) {
Eigen::MatrixXd distances = ur5e_with_geometries->compute_minimum_collision_distances(config);

// check that no element is equal to zero besided the diagonals
EXPECT_EQ(distances.rows(), 6) << "Distance matrix has incorrect number of rows.";
EXPECT_EQ(distances.cols(), 6) << "Distance matrix has incorrect number of columns.";

// Then check that no element is equal to zero besides the diagonals
for (int i = 0; i < distances.rows(); ++i) {
for (int j = 0; j < distances.cols(); ++j) {
if (i != j && j != i + 1 && i != j + 1) {// Skip diagonal elements & adjacent links
EXPECT_GE(distances(i, j), 0.01)
<< "Found a distance at non-diagonal element [" << i << ", " << j << "], indicating a collision.";
}
}
}
}
}

TEST_F(RobotModelCollisionTesting, MinimumDistanceComputedCollision) {
// Iterate over test configurations expected to result in collisions
set_test_coliding_configurations();

for (auto& config : test_coliding_configs) {
Eigen::MatrixXd distances = ur5e_with_geometries->compute_minimum_collision_distances(config);

// Check the size of the distance matrix is 6x6
EXPECT_EQ(distances.rows(), 6) << "Distance matrix has incorrect number of rows.";
EXPECT_EQ(distances.cols(), 6) << "Distance matrix has incorrect number of columns.";

// Initialize a variable to keep track of the minimum non-diagonal distance
double minimum_distance = std::numeric_limits<double>::max();

// Iterate over the matrix to find the minimum non-diagonal distance
for (int i = 0; i < distances.rows(); ++i) {
for (int j = 0; j < distances.cols(); ++j) {
if (i != j && j != i + 1 && i != j + 1
&& distances(i, j) < minimum_distance) {// Skip diagonal elements & adjacent links
minimum_distance = distances(i, j);
}
}
}

// Expect the minimum non-diagonal distance to be 0, indicating a collision
EXPECT_LE(minimum_distance, 0.01)
<< "Did not find a minimum distance less than a threshold indicating a collision.";
}
}
Loading