diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index fcefed3ff70d39b558214431217036b67edac6f9..5463ef857beed42f718ba1800eccc0d85bf9805c 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,2 +1,6 @@ 0067c8aa66aac548601e2a3fd029aa264cc59f2a 76b68f785df31b00e153290b45ec290a9c5f7963 +# ruff --fix . (Guilhem Saurel, 2023-10-24) +58dee5ae90eded5125825a2da0fe76a5031f3334 +# black . (Guilhem Saurel, 2023-10-24) +889ff8d1ca00b9e317e1da4136e233bb49a049df diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0281d6e180a654024a34de55a293f03aac574343..fcd4d41458b519594780898d5e79b6ce0f97f495 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1 +1 @@ -include: http://rainboard.laas.fr/project/hpp-fcl/.gitlab-ci.yml +include: https://rainboard.laas.fr/project/hpp-fcl/.gitlab-ci.yml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2ce48fbda3bbdab678fdf2f1fa1e31dcf5644456..aa16d1dd24d9ece0618b3a3c80abcd8f321916b6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,16 +1,24 @@ ci: - autoupdate_branch: 'devel' + autoupdate_branch: devel repos: -- repo: https://github.com/pre-commit/mirrors-clang-format - rev: v17.0.3 - hooks: - - id: clang-format - args: ['--style={BasedOnStyle: Google, SortIncludes: false}'] -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 - hooks: - - id: trailing-whitespace -- repo: https://github.com/psf/black - rev: 23.10.0 - hooks: - - id: black +- repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.0.267 + hooks: + - id: ruff + args: + - --fix + - --exit-non-zero-on-fix +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v17.0.3 + hooks: + - id: clang-format + args: + - '--style={BasedOnStyle: Google, SortIncludes: false}' +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: trailing-whitespace +- repo: https://github.com/psf/black + rev: 23.10.0 + hooks: + - id: black diff --git a/README.md b/README.md index ba47568eee26e7fc0fd0651a81399218bc1837be..8c454ed3f6febd8abc2b1a4cbf7816c71b7a386f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -HPP-FCL — An extension of the Flexible Collision Library -======= +# HPP-FCL — An extension of the Flexible Collision Library <p align="center"> <a href="https://gepgitlab.laas.fr/humanoid-path-planner/hpp-fcl/commits/master/"><img src="https://gepgitlab.laas.fr/humanoid-path-planner/hpp-fcl/badges/master/pipeline.svg" alt="Pipeline status"/></a> @@ -8,6 +7,8 @@ HPP-FCL — An extension of the Flexible Collision Library <a href="https://anaconda.org/conda-forge/hpp-fcl"><img src="https://img.shields.io/conda/dn/conda-forge/hpp-fcl.svg" alt="Conda Downloads"/></a> <a href="https://anaconda.org/conda-forge/hpp-fcl"><img src="https://img.shields.io/conda/vn/conda-forge/hpp-fcl.svg" alt="Conda Version"/></a> <a href="https://badge.fury.io/py/hpp-fcl"><img src="https://badge.fury.io/py/hpp-fcl.svg" alt="PyPI version"></a> + <a href="https://github.com/psf/black"><img alt="black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a> + <a href="https://github.com/astral-sh/ruff"><img alt="ruff" src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json"></a> </p> [FCL](https://github.com/flexible-collision-library/fcl) was forked in 2015. Since then, a large part of the code has been rewritten or removed (for the unused and untested part). @@ -37,4 +38,3 @@ Unlike the original FCL library, HPP-FCL implements the well-established GJK alg ## Acknowledgments The development of **HPP-FCL** is actively supported by the [Gepetto team](http://projects.laas.fr/gepetto/) [@LAAS-CNRS](http://www.laas.fr), the [Willow team](https://www.di.ens.fr/willow/) [@INRIA](http://www.inria.fr) and, to some extend, [Eureka Robotics](https://eurekarobotics.com/). - diff --git a/doc/generate_distance_plot.py b/doc/generate_distance_plot.py index bfc66deb822ff910ba5d5d92920581bf87640828..1456a2f88353191c890af6eb789ff5ebddb69a7b 100644 --- a/doc/generate_distance_plot.py +++ b/doc/generate_distance_plot.py @@ -1,6 +1,5 @@ import matplotlib.pyplot as plt import numpy as np -from math import sqrt interactive = False diff --git a/doc/gjk.py b/doc/gjk.py index 3d200b128a59c111316d8aff773072e0c88da885..d80564c4bed01c5384afb397e8dfcfb872d3fbf1 100644 --- a/doc/gjk.py +++ b/doc/gjk.py @@ -10,7 +10,8 @@ plane_fmt = "" edge_fmt = "{j}a * {b}a_{c}a + {j}{b} * {c}a_aa - {j}{c} * {b}a_aa" # These checks must be negative and not positive, as in the cheat sheet. -# They are the same as in the cheat sheet, except that we consider (...).dot(A) instead of (...).dot(-A) +# They are the same as in the cheat sheet, except that we consider (...).dot(A) +# instead of (...).dot(-A) plane_tests = ["C.dot (a_cross_b)", "D.dot(a_cross_c)", "-D.dot(a_cross_b)"] checks = ( plane_tests @@ -247,9 +248,9 @@ implications = [ def set_test_values(current_tests, test_values, itest, value): def satisfies(values, indices): for k in indices: - if k > 0 and values[k - 1] != True: + if k > 0 and values[k - 1] is not True: return False - if k < 0 and values[-k - 1] != False: + if k < 0 and values[-k - 1] is not False: return False return True @@ -286,17 +287,17 @@ def set_tests_values(current_tests, test_values, itests, values): def apply_test_values(cases, test_values): def canSatisfy(values, indices): for k in indices: - if k > 0 and values[k - 1] == False: + if k > 0 and values[k - 1] is False: return False - if k < 0 and values[-k - 1] == True: + if k < 0 and values[-k - 1] is True: return False return True def satisfies(values, indices): for k in indices: - if k > 0 and values[k - 1] != True: + if k > 0 and values[k - 1] is not True: return False - if k < 0 and values[-k - 1] != False: + if k < 0 and values[-k - 1] is not False: return False return True @@ -337,7 +338,7 @@ def max_number_of_tests( prevScore=0, ): for test in current_tests: - assert test_values[test] == None, "Test " + str(test) + " already performed" + assert test_values[test] is None, "Test " + str(test) + " already performed" left_cases = apply_test_values(cases, test_values) @@ -375,7 +376,8 @@ def max_number_of_tests( remaining_tests = None if remaining_tests is not None: - # Do not put this in try catch as I do not want other ValueError to be understood as an infeasible branch. + # Do not put this in try catch as I do not want other ValueError to be + # understood as an infeasible branch. score_if_t, order_if_t = max_number_of_tests( remaining_tests, left_cases, @@ -396,7 +398,8 @@ def max_number_of_tests( remaining_tests = None if remaining_tests is not None: - # Do not put this in try catch as I do not want other ValueError to be understood as an infeasible branch. + # Do not put this in try catch as I do not want other ValueError to be + # understood as an infeasible branch. score_if_f, order_if_f = max_number_of_tests( remaining_tests, left_cases, @@ -438,37 +441,37 @@ def printOrder(order, indent="", start=True, file=sys.stdout, curTests=[]): file=file, ) print(indent + "const vertex_id_t a = 3, b = 2, c = 1, d = 0;", file=file) - for l in "abcd": + for v in "abcd": print( indent - + "const Vec3f& {} (current.vertex[{}]->w);".format(l.upper(), l), + + "const Vec3f& {} (current.vertex[{}]->w);".format(v.upper(), v), file=file, ) - print(indent + "const FCL_REAL aa = A.squaredNorm();".format(l), file=file) - for l in "dcb": + print(indent + "const FCL_REAL aa = A.squaredNorm();".format(), file=file) + for v in "dcb": for m in "abcd": - if m <= l: + if m <= v: print( indent + "const FCL_REAL {0}{1} = {2}.dot({3});".format( - l, m, l.upper(), m.upper() + v, m, v.upper(), m.upper() ), file=file, ) else: print( - indent + "const FCL_REAL& {0}{1} = {1}{0};".format(l, m), + indent + "const FCL_REAL& {0}{1} = {1}{0};".format(v, m), file=file, ) - print(indent + "const FCL_REAL {0}a_aa = {0}a - aa;".format(l), file=file) + print(indent + "const FCL_REAL {0}a_aa = {0}a - aa;".format(v), file=file) for l0, l1 in zip("bcd", "cdb"): print( indent + "const FCL_REAL {0}a_{1}a = {0}a - {1}a;".format(l0, l1), file=file, ) - for l in "bc": + for v in "bc": print( - indent + "const Vec3f a_cross_{0} = A.cross({1});".format(l, l.upper()), + indent + "const Vec3f a_cross_{0} = A.cross({1});".format(v, v.upper()), file=file, ) print("", file=file) @@ -502,15 +505,12 @@ def printOrder(order, indent="", start=True, file=sys.stdout, curTests=[]): elif region == "A": print(indent + "originToPoint (current, a, A, next, ray);", file=file) elif len(region) == 2: - a = region[0] + region[0] B = region[1] print( - indent - + "originToSegment (current, a, {b}, A, {B}, {B}-A, -{b}a_aa, next, ray);".format( - **{ - "b": B.lower(), - "B": B, - } + indent + "originToSegment " + "(current, a, {b}, A, {B}, {B}-A, -{b}a_aa, next, ray);".format( + **{"b": B.lower(), "B": B} ), file=file, ) @@ -524,8 +524,8 @@ def printOrder(order, indent="", start=True, file=sys.stdout, curTests=[]): else: test = "-" + test print( - indent - + "originToTriangle (current, a, {b}, {c}, ({B}-A).cross({C}-A), {t}, next, ray);".format( + indent + "originToTriangle " + "(current, a, {b}, {c}, ({B}-A).cross({C}-A), {t}, next, ray);".format( **{"b": B.lower(), "c": C.lower(), "B": B, "C": C, "t": test} ), file=file, diff --git a/doc/python/doxygen_xml_parser.py b/doc/python/doxygen_xml_parser.py index a0235dace105a49b6eae41b438a3a61b6446e789..d9590b7e2c2e21c301e8d15d48bb92cc7397c234 100755 --- a/doc/python/doxygen_xml_parser.py +++ b/doc/python/doxygen_xml_parser.py @@ -1,4 +1,5 @@ #!/usr/bin/python3 +# ruff: noqa: E501 from __future__ import print_function from lxml import etree @@ -120,8 +121,6 @@ def _templateParamToDict(param): def makeHeaderGuard(filename): - import os - return filename.upper().replace(".", "_").replace("/", "_").replace("-", "_") @@ -326,8 +325,6 @@ class MemberDef(Reference): return ", ".join([arg.format(n) for n in argnames]) def include(self): - import os.path - loc = self.xml.find("location") # The location is based on $CMAKE_SOURCE_DIR. Remove first directory. return loc.attrib["file"].split("/", 1)[1] @@ -705,8 +702,6 @@ class Index: def write(self): # Header - from os.path import abspath, dirname - from time import asctime self.output.open("doxygen_xml_parser_for_cmake.hh") # self.output.out ("// Generated on {}".format (asctime())) @@ -821,7 +816,7 @@ class OutputStreams(object): self._created_files = dict() def open(self, name): - assert self._out == None, "You did not close the previous file" + assert self._out is None, "You did not close the previous file" import os fullname = os.path.join(self.output_dir, name) @@ -895,4 +890,4 @@ if __name__ == "__main__": index.parseCompound() index.write() index.output.writeFooterAndCloseFiles() - assert index.output._out == None + assert index.output._out is None diff --git a/doc/python/xml_docstring.py b/doc/python/xml_docstring.py index 0b1fd09752f709592bf87d173c24f5681f386b64..d36618b71f131e039989e8a83ab9c0ade92c885a 100644 --- a/doc/python/xml_docstring.py +++ b/doc/python/xml_docstring.py @@ -59,14 +59,14 @@ class XmlDocString(object): def _clean(self): s = 0 - for l in self.lines: - if len(l.strip()) == 0: + for line in self.lines: + if len(line.strip()) == 0: s += 1 else: break e = len(self.lines) - for l in reversed(self.lines): - if len(l.strip()) == 0: + for line in reversed(self.lines): + if len(line.strip()) == 0: e -= 1 else: break @@ -80,7 +80,7 @@ class XmlDocString(object): if brief is not None: self._newline() self.visit(detailled) - from sys import stdout, stderr, version_info + from sys import version_info self.writeErrors(output) self._clean() diff --git a/python/hppfcl/__init__.py b/python/hppfcl/__init__.py index 34f11992627594885d3cfa093815314ed79d5633..b93784303693b41c29b0e3f89f9f37e4a3691a40 100644 --- a/python/hppfcl/__init__.py +++ b/python/hppfcl/__init__.py @@ -31,5 +31,6 @@ # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +# ruff: noqa: F401, F403 from .hppfcl import * -from .hppfcl import __version__, __raw_version__ +from .hppfcl import __raw_version__, __version__ diff --git a/python/hppfcl/viewer.py b/python/hppfcl/viewer.py index 29cdb2ac8779c5528dad14bc1d4d3f5942ae59bf..15bf53c2d05410b4b6b1fdebfb2b0a92eb5bf7cb 100644 --- a/python/hppfcl/viewer.py +++ b/python/hppfcl/viewer.py @@ -3,9 +3,13 @@ # Copyright (c) 2019 CNRS # Author: Joseph Mirabel -import hppfcl, numpy as np +import warnings + +import numpy as np from gepetto import Color +import hppfcl + def applyConfiguration(gui, name, tf): gui.applyConfiguration( @@ -43,10 +47,7 @@ def displayShape(gui, name, geom, color=(0.9, 0.9, 0.9, 1.0)): gui.setLightingMode(name, "OFF") return True else: - msg = "Unsupported geometry type for %s (%s)" % ( - geometry_object.name, - type(geom), - ) + msg = "Unsupported geometry type for %s (%s)" % (name, type(geom)) warnings.warn(msg, category=UserWarning, stacklevel=2) return False diff --git a/test/python_unit/geometric_shapes.py b/test/python_unit/geometric_shapes.py index c6b6b6ee4325b4828a66952552c31dab9f3295fb..b64850e5996c1a20eea9cbee33820434cd3cb728 100644 --- a/test/python_unit/geometric_shapes.py +++ b/test/python_unit/geometric_shapes.py @@ -167,11 +167,11 @@ class TestGeometricShapes(TestCase): ] ) faces.append(hppfcl.Triangle(0, 1, 2)) - convex = hppfcl.Convex(verts, faces) + hppfcl.Convex(verts, faces) verts.append(np.array([0, 0, 1])) try: - convexHull = hppfcl.Convex.convexHull(verts, False, None) + hppfcl.Convex.convexHull(verts, False, None) qhullAvailable = True except Exception as e: self.assertEqual( @@ -180,11 +180,11 @@ class TestGeometricShapes(TestCase): qhullAvailable = False if qhullAvailable: - convexHull = hppfcl.Convex.convexHull(verts, False, "") - convexHull = hppfcl.Convex.convexHull(verts, True, "") + hppfcl.Convex.convexHull(verts, False, "") + hppfcl.Convex.convexHull(verts, True, "") try: - convexHull = hppfcl.Convex.convexHull(verts[:3], False, None) + hppfcl.Convex.convexHull(verts[:3], False, None) except Exception as e: self.assertIn( str(e), "You shouldn't use this function with less than 4 points." diff --git a/test/scripts/collision-bench.py b/test/scripts/collision-bench.py index 885995ad3dd9852d72e3da9bfa24ad296b8ac657..62d6e87ef86030f7937e82f0f6c13889904d56c3 100644 --- a/test/scripts/collision-bench.py +++ b/test/scripts/collision-bench.py @@ -1,6 +1,7 @@ +import csv +import sys + import matplotlib.pyplot as plt -import csv, sys, numpy as np -from math import sqrt filename = sys.argv[1] @@ -43,8 +44,8 @@ cases = [ idx_reorder = sorted(list(range(len(xvals))), key=lambda i: xvals[i]) -def reorder(l): - return [l[i] for i in idx_reorder] +def reorder(v): + return [v[i] for i in idx_reorder] xvals_s = reorder(xvals) diff --git a/test/scripts/collision.py b/test/scripts/collision.py index 1604b9637c948e6e923fb2a0b1536790994a266a..73fc979cee5de8d4d7aa76cae9dfa964694cd501 100644 --- a/test/scripts/collision.py +++ b/test/scripts/collision.py @@ -1,6 +1,5 @@ # Load "env.obj" and "rob.obj" in gepetto-gui -import numpy as np import os from gepetto.corbaserver import Client diff --git a/test/scripts/distance_lower_bound.py b/test/scripts/distance_lower_bound.py index 1e4b29b52396c7bdaa20f870e1b2b395f02991d6..61e7b3ab318a3a5df4da2896749ef416a9dd2402 100644 --- a/test/scripts/distance_lower_bound.py +++ b/test/scripts/distance_lower_bound.py @@ -1,6 +1,5 @@ # Load "env.obj" and "rob.obj" in gepetto-gui -import numpy as np import os from gepetto.corbaserver import Client diff --git a/test/scripts/geometric_shapes.py b/test/scripts/geometric_shapes.py index 02dccadea390742740807d6ceb9e8621a5b623f1..1e893bbf390fd26e6d0bcd33c5bd25ef764c5d48 100644 --- a/test/scripts/geometric_shapes.py +++ b/test/scripts/geometric_shapes.py @@ -1,6 +1,6 @@ # Datas for compare_convex_box -from gepetto.corbaserver import Client from gepetto import Quaternion +from gepetto.corbaserver import Client def translate(tr, t, d): @@ -10,7 +10,7 @@ def translate(tr, t, d): cl = Client() try: cl.gui.getWindowID("fcl") -except: +except Exception: cl.gui.createWindow("fcl") cl.gui.addBox("fcl/b0", 2, 2, 2, [1, 0, 0, 0.5]) diff --git a/test/scripts/gjk.py b/test/scripts/gjk.py index bdad975369bd22ab098cf5964b13a88a4d9be536..6eee6d88f9836e1e70aa06b6439c3e66cfecbb0f 100644 --- a/test/scripts/gjk.py +++ b/test/scripts/gjk.py @@ -1,6 +1,5 @@ # This script displays two triangles and two spheres in gepetto-gui # It is useful to debug distance computation between two triangles. -import numpy as np from gepetto.corbaserver import Client Red = [1, 0, 0, 0.5] diff --git a/test/scripts/obb.py b/test/scripts/obb.py index 7b59e61593b779afad1c498fecda5c05cbe0b33f..1418e0ee4be4fa2f04ceada4b125f62b41b3c9ed 100644 --- a/test/scripts/obb.py +++ b/test/scripts/obb.py @@ -1,7 +1,10 @@ -import matplotlib.pyplot as plt -import csv, sys, numpy as np +import csv +import sys from math import sqrt +import matplotlib.pyplot as plt +import numpy as np + filename = sys.argv[1] with open(filename, "r") as file: @@ -67,9 +70,25 @@ if time_vs_sep_axis: plt.figure(iplot) plt.title("Time, with std dev, versus separating axis") for k, n in enumerate(fieldnames[4:]): - # plt.errorbar ([ np.linspace(0, 11, 12) + shift for shift in np.linspace (-0.2, 0.2, ) ], means[k], stddevs[k], label=n) + # plt.errorbar( + # [ + # np.linspace(0, 11, 12) + shift + # for shift in np.linspace( + # -0.2, + # 0.2, + # ) + # ], + # means[k], + # stddevs[k], + # label=n, + # ) plt.errorbar(np.linspace(0, 11, 12), means[k], stddevs[k], label=n) - # plt.errorbar (np.linspace(0, 11, 12), means[k], [ [ 0 ] * len(stddevs[k]), stddevs[k] ], label=n) + # plt.errorbar( + # np.linspace(0, 11, 12), + # means[k], + # [[0] * len(stddevs[k]), stddevs[k]], + # label=n, + # ) plt.xlim([-0.5, 11.5]) plt.ylabel("Time (ns)") plt.xlabel("Separating axis") @@ -120,23 +139,23 @@ if avg_time_vs_impl: zip(fieldnames[4:], _means, _stddev, _mins, _maxs), key=lambda x: x[1] ) plt.errorbar( - [f for f, m, s, l, u in _sorted], - [m for f, m, s, l, u in _sorted], - [s for f, m, s, l, u in _sorted], + [f for f, _, _, _, _ in _sorted], + [m for _, m, _, _, _ in _sorted], + [s for _, _, s, _, _ in _sorted], fmt="go", linestyle="", label="mean and std deviation", ) plt.plot( - [f for f, m, s, l, u in _sorted], - [l for f, m, s, l, u in _sorted], + [f for f, _, _, _, _ in _sorted], + [v for _, _, _, v, _ in _sorted], "b+", ls="", label="min", ) plt.plot( - [f for f, m, s, l, u in _sorted], - [u for f, m, s, l, u in _sorted], + [f for f, _, _, _, _ in _sorted], + [u for _, _, _, _, u in _sorted], "r+", ls="", label="max", diff --git a/test/scripts/octree.py b/test/scripts/octree.py index a5c865f1444747f5f43c5c44d2346c9bdddb11e4..c0ef6e4c726d0ef72b4a66acf31ed6dfce9519be 100644 --- a/test/scripts/octree.py +++ b/test/scripts/octree.py @@ -1,6 +1,5 @@ # Load "env.obj" and "rob.obj" in gepetto-gui -import numpy as np import csv import os from gepetto.corbaserver import Client