robotology / idyntree

Multibody Dynamics Library designed for Free Floating Robots
BSD 3-Clause "New" or "Revised" License
155 stars 65 forks source link

Generate Java bindings #160

Closed traversaro closed 4 years ago

traversaro commented 8 years ago

With some minor annoyance (the automatic generation of setters/getters for each public attribute caused some conflict) I got a preliminary version of the bindings correctly compiling in the feature/java branch : https://github.com/robotology/idyntree/compare/feature/java .

Next steps involve:

traversaro commented 6 years ago

cc @francesco-romano @fiorisi

traversaro commented 6 years ago

cc @francesco-romano

traversaro commented 4 years ago

Closing, as discussed in https://github.com/robotology/idyntree/pull/392#issuecomment-457120051 . For future reference, the patch was:

From 454890b22cc28342e755447ef5a5fcd10dedc66b Mon Sep 17 00:00:00 2001
From: Silvio Traversaro <silvio.traversaro@iit.it>
Date: Tue, 17 May 2016 23:24:11 +0200
Subject: [PATCH 1/3] [java] Rename u public attribute in
 ArticulatedBodyInertia buffers

In preparation of the Java bindings generation, rename u in uu.
This is necessary because every public attribute is going to be wrapped
 in Java with a couple of automatically generated set and get, and
the presence in the same class of U and u was generatign two identically
getU() methods.

This change brecks the compilation of Matlab bindings, that will need to
be regenerated and commited before merging the feature/java branch in master.
---
 src/model/include/iDynTree/Model/Dynamics.h    |  2 +-
 src/model/src/Dynamics.cpp                     | 10 +++++-----
 src/model/src/DynamicsLinearization.cpp        | 18 +++++++++---------
 .../DynamicsLinearizationIntegrationTest.cpp   | 10 +++++-----
 4 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/src/model/include/iDynTree/Model/Dynamics.h b/src/model/include/iDynTree/Model/Dynamics.h
index c7e2907c..135e5875 100644
--- a/src/model/include/iDynTree/Model/Dynamics.h
+++ b/src/model/include/iDynTree/Model/Dynamics.h
@@ -113,7 +113,7 @@ namespace iDynTree
         DOFSpatialMotionArray S;
         DOFSpatialForceArray U;
         JointDOFsDoubleArray D;
-        JointDOFsDoubleArray u;
+        JointDOFsDoubleArray uu;
         LinkVelArray linksVel;
         LinkAccArray linksBiasAcceleration;
         LinkAccArray linksAccelerations;
diff --git a/src/model/src/Dynamics.cpp b/src/model/src/Dynamics.cpp
index e237d044..460bc209 100644
--- a/src/model/src/Dynamics.cpp
+++ b/src/model/src/Dynamics.cpp
@@ -281,7 +281,7 @@ void ArticulatedBodyAlgorithmInternalBuffers::resize(const Model& model)
     S.resize(model);
     U.resize(model);
     D.resize(model);
-    u.resize(model);
+    uu.resize(model);
     linksVel.resize(model);
     linksBiasAcceleration.resize(model);
     linksAccelerations.resize(model);
@@ -298,7 +298,7 @@ bool ArticulatedBodyAlgorithmInternalBuffers::isConsistent(const Model& model)
     ok = ok && S.isConsistent(model);
     ok = ok && U.isConsistent(model);
     ok = ok && D.isConsistent(model);
-    ok = ok && u.isConsistent(model);
+    ok = ok && uu.isConsistent(model);
     ok = ok && linksVel.isConsistent(model);
     ok = ok && linksBiasAcceleration.isConsistent(model);
     ok = ok && linkABIs.isConsistent(model);
@@ -398,13 +398,13 @@ bool ArticulatedBodyAlgorithm(const Model& model,
                 size_t dofIndex = toParentJoint->getDOFsOffset();
                 bufs.U(dofIndex) = bufs.linkABIs(visitedLinkIndex)*bufs.S(dofIndex);
                 bufs.D(dofIndex) = bufs.S(dofIndex).dot(bufs.U(dofIndex));
-                bufs.u(dofIndex) = jointTorques(dofIndex) - bufs.S(dofIndex).dot(bufs.linksBiasWrench(visitedLinkIndex));
+                bufs.uu(dofIndex) = jointTorques(dofIndex) - bufs.S(dofIndex).dot(bufs.linksBiasWrench(visitedLinkIndex));

                 Ia = bufs.linkABIs(visitedLinkIndex) - ArticulatedBodyInertia::ABADyadHelper(bufs.U(dofIndex),bufs.D(dofIndex));

                 pa                 =   bufs.linksBiasWrench(visitedLinkIndex)
                                      + Ia*bufs.linksBiasAcceleration(visitedLinkIndex)
-                                     + bufs.U(dofIndex)*(bufs.u(dofIndex)/bufs.D(dofIndex));
+                                     + bufs.U(dofIndex)*(bufs.uu(dofIndex)/bufs.D(dofIndex));

             }

@@ -457,7 +457,7 @@ bool ArticulatedBodyAlgorithm(const Model& model,
                bufs.linksAccelerations(visitedLinkIndex) =
                    toParentJoint->getTransform(robotPos.jointPos(),visitedLinkIndex,parentLinkIndex)*bufs.linksAccelerations(parentLinkIndex)
                    + bufs.linksBiasAcceleration(visitedLinkIndex);
-               robotAcc.jointAcc()(dofIndex) = (bufs.u(dofIndex)-bufs.U(dofIndex).dot(bufs.linksAccelerations(visitedLinkIndex)))/bufs.D(dofIndex);
+               robotAcc.jointAcc()(dofIndex) = (bufs.uu(dofIndex)-bufs.U(dofIndex).dot(bufs.linksAccelerations(visitedLinkIndex)))/bufs.D(dofIndex);
                bufs.linksAccelerations(visitedLinkIndex) = bufs.linksAccelerations(visitedLinkIndex) + bufs.S(dofIndex)*robotAcc.jointAcc()(dofIndex);
            }
            else
diff --git a/src/model/src/DynamicsLinearization.cpp b/src/model/src/DynamicsLinearization.cpp
index b8ccff7d..1064f653 100644
--- a/src/model/src/DynamicsLinearization.cpp
+++ b/src/model/src/DynamicsLinearization.cpp
@@ -196,7 +196,7 @@ void ForwardDynamicsLinearizationWrtJointPos(const Model& model,
                 size_t dofIndex = toParentJoint->getDOFsOffset();
                 bufs.dPos[dofDeriv].U(dofIndex) = bufs.dPos[dofDeriv].linkABIs(visitedLinkIndex)*bufs.aba.S(dofIndex);
                 bufs.dPos[dofDeriv].D(dofIndex) = bufs.aba.S(dofIndex).dot(bufs.dPos[dofDeriv].U(dofIndex));
-                bufs.dPos[dofDeriv].u(dofIndex) =  - bufs.aba.S(dofIndex).dot(bufs.dPos[dofDeriv].linksBiasWrench(visitedLinkIndex));
+                bufs.dPos[dofDeriv].uu(dofIndex) =  - bufs.aba.S(dofIndex).dot(bufs.dPos[dofDeriv].linksBiasWrench(visitedLinkIndex));

                 double invD = 1/(bufs.aba.D(dofIndex));
                 double d_invD = - invD * bufs.dPos[dofDeriv].D(dofIndex) * invD;
@@ -209,8 +209,8 @@ void ForwardDynamicsLinearizationWrtJointPos(const Model& model,
                 dPos_pa    =  bufs.dPos[dofDeriv].linksBiasWrench(visitedLinkIndex)
                                      + dPos_Ia*bufs.aba.linksBiasAcceleration(visitedLinkIndex)
                                      + Ia*bufs.dPos[dofDeriv].linksBiasAcceleration(visitedLinkIndex)
-                                     + bufs.dPos[dofDeriv].U(dofIndex)*(bufs.aba.u(dofIndex)*invD)
-                                     + bufs.aba.U(dofIndex)*(bufs.dPos[dofDeriv].u(dofIndex)*invD + bufs.aba.u(dofIndex)*d_invD);
+                                     + bufs.dPos[dofDeriv].U(dofIndex)*(bufs.aba.uu(dofIndex)*invD)
+                                     + bufs.aba.U(dofIndex)*(bufs.dPos[dofDeriv].uu(dofIndex)*invD + bufs.aba.uu(dofIndex)*d_invD);

             }

@@ -246,7 +246,7 @@ void ForwardDynamicsLinearizationWrtJointPos(const Model& model,

                 SpatialForceVector pa =   bufs.aba.linksBiasWrench(visitedLinkIndex)
                                      + Ia*bufs.aba.linksBiasAcceleration(visitedLinkIndex)
-                                     + bufs.aba.U(dofIndex)*(bufs.aba.u(dofIndex)/bufs.aba.D(dofIndex));
+                                     + bufs.aba.U(dofIndex)*(bufs.aba.uu(dofIndex)/bufs.aba.D(dofIndex));

                 bufs.dPos[dofDeriv].linksBiasWrench(parentLinkIndex) = bufs.dPos[dofDeriv].linksBiasWrench(parentLinkIndex)
                                                                       + parent_dX_visited.transform(parent_X_visited,pa);
@@ -309,8 +309,8 @@ void ForwardDynamicsLinearizationWrtJointPos(const Model& model,
                double invD = 1/(bufs.aba.D(dofIndex));
                double d_invD = - invD * bufs.dPos[dofDeriv].D(dofIndex) * invD;
                double dPos_ddq =
-                    (bufs.aba.u(dofIndex)-bufs.aba.U(dofIndex).dot(bufs.aba.linksAccelerations(visitedLinkIndex)))*d_invD;
-                    (bufs.dPos[dofDeriv].u(dofIndex)
+                    (bufs.aba.uu(dofIndex)-bufs.aba.U(dofIndex).dot(bufs.aba.linksAccelerations(visitedLinkIndex)))*d_invD;
+                    (bufs.dPos[dofDeriv].uu(dofIndex)
                         -bufs.dPos[dofDeriv].U(dofIndex).dot(bufs.aba.linksAccelerations(visitedLinkIndex))
                         -bufs.aba.U(dofIndex).dot(bufs.dPos[dofDeriv].linksAccelerations(visitedLinkIndex)))*invD;

@@ -599,13 +599,13 @@ void ForwardDynamicsLinearizationWrtJointVel(const Model& model,
             {
                 assert(toParentJoint->getNrOfDOFs()==1);
                 size_t dofIndex = toParentJoint->getDOFsOffset();
-                bufs.dVel[dofDeriv].u(dofIndex) = -bufs.aba.S(dofIndex).dot(bufs.dVel[dofDeriv].linksBiasWrench(visitedLinkIndex));
+                bufs.dVel[dofDeriv].uu(dofIndex) = -bufs.aba.S(dofIndex).dot(bufs.dVel[dofDeriv].linksBiasWrench(visitedLinkIndex));

                 Ia = bufs.aba.linkABIs(visitedLinkIndex) - ArticulatedBodyInertia::ABADyadHelper(bufs.aba.U(dofIndex),bufs.aba.D(dofIndex));

                 dVel_dofDeriv_pa   =   bufs.dVel[dofDeriv].linksBiasWrench(visitedLinkIndex)
                                      + Ia*bufs.dVel[dofDeriv].linksBiasAcceleration(visitedLinkIndex)
-                                     + bufs.aba.U(dofIndex)*(bufs.dVel[dofDeriv].u(dofIndex)/bufs.aba.D(dofIndex));
+                                     + bufs.aba.U(dofIndex)*(bufs.dVel[dofDeriv].uu(dofIndex)/bufs.aba.D(dofIndex));

             }

@@ -659,7 +659,7 @@ void ForwardDynamicsLinearizationWrtJointVel(const Model& model,
                    toParentJoint->getTransform(robotPos.jointPos(),visitedLinkIndex,parentLinkIndex)*bufs.dVel[dofDeriv].linksAccelerations(parentLinkIndex)
                    + bufs.dVel[dofDeriv].linksBiasAcceleration(visitedLinkIndex);

-               double dVel_dofDeriv_ddq_dofIndex = (bufs.dVel[dofDeriv].u(dofIndex)-bufs.aba.U(dofIndex).dot(bufs.dVel[dofDeriv].linksAccelerations(visitedLinkIndex)))/bufs.aba.D(dofIndex);
+               double dVel_dofDeriv_ddq_dofIndex = (bufs.dVel[dofDeriv].uu(dofIndex)-bufs.aba.U(dofIndex).dot(bufs.dVel[dofDeriv].linksAccelerations(visitedLinkIndex)))/bufs.aba.D(dofIndex);

                A(6+model.getNrOfDOFs()+6+dofIndex,6+model.getNrOfDOFs()+6+dofDeriv) = dVel_dofDeriv_ddq_dofIndex;

diff --git a/src/tests/integration/DynamicsLinearizationIntegrationTest.cpp b/src/tests/integration/DynamicsLinearizationIntegrationTest.cpp
index 021648d0..ab1e67b3 100644
--- a/src/tests/integration/DynamicsLinearizationIntegrationTest.cpp
+++ b/src/tests/integration/DynamicsLinearizationIntegrationTest.cpp
@@ -108,8 +108,8 @@ void checkDifferenceInBuffers(const ForwardDynamicsLinearizationInternalBuffers
             if( verbose )
             {
                  std::cerr << "Check difference in buffers for dof " << dof << std::endl;
-                 std::cerr << "Norm of diff in u : "
-                           << fabs(bufs.dVel[dofDeriv].u(dof)-numBufs.dVel[dofDeriv].u(dof)) << std::endl;
+                 std::cerr << "Norm of diff in uu : "
+                           << fabs(bufs.dVel[dofDeriv].uu(dof)-numBufs.dVel[dofDeriv].uu(dof)) << std::endl;
             }
         }
     }
@@ -145,7 +145,7 @@ void checkDifferenceInBuffers(const ForwardDynamicsLinearizationInternalBuffers
             {
                  std::cerr << "Check difference in buffers for dof " << dof << std::endl;
                  std::cerr << "Norm of diff in u : "
-                           << fabs(bufs.dPos[dofDeriv].u(dof)-numBufs.dPos[dofDeriv].u(dof)) << std::endl;
+                           << fabs(bufs.dPos[dofDeriv].uu(dof)-numBufs.dPos[dofDeriv].uu(dof)) << std::endl;
                  std::cerr << "Norm of diff in D : "
                            << fabs(bufs.dPos[dofDeriv].D(dof)-numBufs.dPos[dofDeriv].D(dof)) << std::endl;
                  std::cerr << " D "
@@ -218,9 +218,9 @@ void fillLinBufsWithNumericalDerivativesWrtJointQuantity(const ArticulatedBodyAl
     }

     // set dofs buffers
-    for(size_t dof=0; dof < numBufs.u.size(); dof++ )
+    for(size_t dof=0; dof < numBufs.uu.size(); dof++ )
     {
-        numBufs.u(dof) = (bufsUpper.u(dof) - bufsLower.u(dof))/step;
+        numBufs.uu(dof) = (bufsUpper.uu(dof) - bufsLower.uu(dof))/step;
     }
 }

From 09a88e65a0b95e50558a6b190cc555d5ec3b9ec7 Mon Sep 17 00:00:00 2001
From: Silvio Traversaro <silvio.traversaro@iit.it>
Date: Tue, 17 May 2016 23:29:22 +0200
Subject: [PATCH 2/3] [java] Add preliminary java bindings support

The support can be enabled with the IDYNTREE_USES_JAVA cmake option.
Currently the cmake produce a jar with all the generated class files.
---
 bindings/CMakeLists.txt      |  9 ++++++++-
 bindings/iDynTree.i          |  5 +++++
 bindings/java/CMakeLists.txt | 34 ++++++++++++++++++++++++++++++++++
 bindings/java/java.i         |  3 +++
 4 files changed, 50 insertions(+), 1 deletion(-)
 create mode 100644 bindings/java/CMakeLists.txt
 create mode 100644 bindings/java/java.i

diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt
index 151131bd..72e612a8 100644
--- a/bindings/CMakeLists.txt
+++ b/bindings/CMakeLists.txt
@@ -9,6 +9,7 @@ option(IDYNTREE_USES_LUA "Do you want to create the Lua bindings" FALSE)
 option(IDYNTREE_USES_MATLAB "Do you want to create the MATLAB bindings" FALSE)
 option(IDYNTREE_USES_OCTAVE "Do you want to create the OCTAVE bindings" FALSE)
 option(IDYNTREE_GENERATE_MATLAB "Enable if you have the experimental version of SWIG necessary for generating the Matlab wrapper" FALSE)
+option(IDYNTREE_USES_JAVA "Do you want to create the Java Interface" FALSE)

 find_package(SWIG)
 # It is possible to compile matlab/octave bindings without using SWIG
@@ -43,15 +44,21 @@ if(SWIG_FOUND OR IDYNTREE_USES_MATLAB OR IDYNTREE_USES_OCTAVE)
     if(IDYNTREE_USES_PYTHON)
         add_subdirectory(python)
     endif(IDYNTREE_USES_PYTHON)
+    
+    if(IDYNTREE_USES_JAVA)
+       add_subdirectory(java)
+    endif()

     if(IDYNTREE_USES_MATLAB OR IDYNTREE_GENERATE_MATLAB OR IDYNTREE_USES_OCTAVE)
         add_subdirectory(matlab)
     endif()
 endif()

+
 if(IDYNTREE_USES_PYTHON OR
    IDYNTREE_USES_LUA    OR
-   IDYNTREE_GENERATED_MATLAB)
+   IDYNTREE_GENERATED_MATLAB OR
+   IDYNTREE_USES_JAVA)
    if(NOT SWIG_FOUND)
        MESSAGE(FATAL_ERROR "Swig not found, impossible to compile or generate iDynTree bindings.")
    endif()
diff --git a/bindings/iDynTree.i b/bindings/iDynTree.i
index eb406fb8..b831a869 100644
--- a/bindings/iDynTree.i
+++ b/bindings/iDynTree.i
@@ -19,6 +19,11 @@
 %include "./python/python.i"
 #endif

+// Java
+#ifdef SWIGJAVA
+%include "./java/java.i"
+#endif
+
 // Matlab
 #ifdef SWIGMATLAB
 %include "./matlab/matlab.i"
diff --git a/bindings/java/CMakeLists.txt b/bindings/java/CMakeLists.txt
new file mode 100644
index 00000000..08f0baa0
--- /dev/null
+++ b/bindings/java/CMakeLists.txt
@@ -0,0 +1,34 @@
+set(CMAKE_SWIG_FLAGS "-Wextra;-module;iDynTree;-package;iDynTree")
+
+find_package(Java REQUIRED COMPONENTS Runtime Development)
+find_package(JNI  REQUIRED)
+
+include(UseJava)
+
+# CMake structure inspired by http://stackoverflow.com/a/31750207/1379427
+
+# Specify where to place generated *.java files
+SET(CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/java")
+
+# Add module
+set(target_name iDynTree_java)
+set_source_files_properties(../iDynTree.i PROPERTIES CPLUSPLUS ON)
+swig_add_module(${target_name} java ../iDynTree.i)
+include_directories(SYSTEM ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
+
+# Create directory for the *class files
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/classes")
+
+# Create JAR including compiled .class file 
+add_custom_command(TARGET ${target_name} POST_BUILD
+                   COMMAND "${Java_JAVAC_EXECUTABLE}" -d classes java/*.java
+                   COMMAND "${Java_JAR_EXECUTABLE}" -cfM iDynTree.jar -C classes .)
+
+# Store Path to iDynTree JAR in variable:
+SET(IDYNTREE_JAR "${CMAKE_CURRENT_BINARY_DIR}/iDynTree.jar")
+
+
+# if compile tests execute also java tests
+# if(IDYNTREE_COMPILE_TESTS)
+#    add_subdirectory(tests)
+# endif()
diff --git a/bindings/java/java.i b/bindings/java/java.i
new file mode 100644
index 00000000..2eaad1ea
--- /dev/null
+++ b/bindings/java/java.i
@@ -0,0 +1,3 @@
+// getSemantics / setSemantics are already generated in the GeomVector3 because
+// in Java SWIG get/set methods are generated for each public attribute
+%ignore *::setSemantics;

From fc2cd0adbd8f0878e3e9ee2daa4fae75ed7bcaad Mon Sep 17 00:00:00 2001
From: Francesco Romano <francesco.romano.1987@gmail.com>
Date: Thu, 16 Nov 2017 18:17:24 +0100
Subject: [PATCH 3/3] Updated JAVA bindings cmake

Supported generation and installation of .JAR files
---
 bindings/java/CMakeLists.txt | 138 +++++++++++++++++++++++++++++------
 1 file changed, 115 insertions(+), 23 deletions(-)

diff --git a/bindings/java/CMakeLists.txt b/bindings/java/CMakeLists.txt
index 08f0baa0..7ede35bf 100644
--- a/bindings/java/CMakeLists.txt
+++ b/bindings/java/CMakeLists.txt
@@ -1,34 +1,126 @@
-set(CMAKE_SWIG_FLAGS "-Wextra;-module;iDynTree;-package;iDynTree")
-
-find_package(Java REQUIRED COMPONENTS Runtime Development)
-find_package(JNI  REQUIRED)
+# Copyright: (C) 2017 iCub Facility
+# Authors: Francesco Romano, Daniele Domenichelli
+# CopyPolicy: Released under the terms of the LGPLv2.1 or later, see LGPL.TXT

+# include CMake Java utilities and JNI
+find_package(Java REQUIRED)
+find_package(JNI REQUIRED)
 include(UseJava)
+include(${SWIG_USE_FILE})
+
+# this is set in the parent directory, but for some reason it does not get inherited
+set_source_files_properties(../iDynTree.i PROPERTIES CPLUSPLUS ON)

-# CMake structure inspired by http://stackoverflow.com/a/31750207/1379427
+if(NOT ${Java_VERSION_MAJOR} VERSION_LESS 9)
+  # Java >= 9
+  set(JAVA_RELEASE_VERSION 7 CACHE STRING "Compile for a specific VM version. See javac --help (--release option)")
+  mark_as_advanced(JAVA_RELEASE_VERSION)
+  if(NOT JAVA_RELEASE_VERSION STREQUAL "")
+    list(APPEND CMAKE_JAVA_COMPILE_FLAGS "--release" "${JAVA_RELEASE_VERSION}")
+  endif()
+  # clean old variable
+  unset(JAVA_TARGET_VERSION CACHE)
+  unset(JAVA_SOURCE_VERSION CACHE)
+else()
+  # Java < 9: --release option not present
+  set(JAVA_TARGET_VERSION ${Java_VERSION_MINOR} CACHE STRING "Java target version. See javac --help (-target option)")
+  set(JAVA_SOURCE_VERSION ${Java_VERSION_MINOR} CACHE STRING "Java source version. See javac --help (-source option)")
+  mark_as_advanced(JAVA_TARGET_VERSION)
+  mark_as_advanced(JAVA_SOURCE_VERSION)
+  if(NOT JAVA_TARGET_VERSION STREQUAL "")
+    list(APPEND CMAKE_JAVA_COMPILE_FLAGS "-target" "${JAVA_TARGET_VERSION}")
+  endif()
+  if(NOT JAVA_SOURCE_VERSION STREQUAL "")
+    list(APPEND CMAKE_JAVA_COMPILE_FLAGS "-source" "${JAVA_SOURCE_VERSION}")
+  endif()
+  unset(JAVA_RELEASE_VERSION CACHE)
+endif()

-# Specify where to place generated *.java files
-SET(CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/java")
+set(JAVA_FLAGS "" CACHE STRING "Additional flags to be passed to javac. E.g. -bootclasspath if you want to cross compile")
+mark_as_advanced(JAVA_FLAGS)
+list(APPEND CMAKE_JAVA_COMPILE_FLAGS "${JAVA_FLAGS}")

-# Add module
-set(target_name iDynTree_java)
-set_source_files_properties(../iDynTree.i PROPERTIES CPLUSPLUS ON)
-swig_add_module(${target_name} java ../iDynTree.i)
+# SWIG JAVA file generation
+set(CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_BINARY_DIR}")
+set(CMAKE_SWIG_FLAGS "-package;iDynTree;-Wall;-module;iDynTree;${SWIG_COMMON_FLAGS}")
+
+# this includes are needed to compile the JNI lib
 include_directories(SYSTEM ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})

-# Create directory for the *class files
-file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/classes")
+swig_add_library(iDynTree_java
+                 LANGUAGE java
+                 SOURCES ../iDynTree.i)
+
+swig_link_libraries(iDynTree_java ${IDYNTREE_LIBRARIES}) #SWIG_YARP_LIBRARIES
+
+if(NOT MSVC)
+  check_cxx_compiler_flag("-Wno-strict-aliasing" CXX_HAS_WNO_STRICT_ALIASING)
+  if(CXX_HAS_WNO_STRICT_ALIASING)
+    target_compile_options(${SWIG_MODULE_iDynTree_java_REAL_NAME} PRIVATE "-Wno-strict-aliasing")
+  endif()
+endif()
+
+# issue on MINGW where C++ name-mangling prevents java finding methods
+if(MINGW)
+  message(STATUS "untested MINGW patch - see CMakeLists.txt")
+  set_target_properties(${SWIG_MODULE_iDynTree_java_REAL_NAME} PROPERTIES
+    LINK_FLAGS "--add-stdcall-alias")
+endif(MINGW)
+
+set(_CMAKE_INSTALL_JNIDIR "${CMAKE_INSTALL_LIBDIR}/jni")
+set(CMAKE_INSTALL_JNIDIR ${_CMAKE_INSTALL_JNIDIR} CACHE PATH "java bindings (${_CMAKE_INSTALL_JNIDIR})")
+mark_as_advanced(CMAKE_INSTALL_JNIDIR)
+if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_JNIDIR})
+  set(CMAKE_INSTALL_FULL_JNIDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_JNIDIR}")
+else()
+  set(CMAKE_INSTALL_FULL_JNIDIR "${CMAKE_INSTALL_JNIDIR}")
+endif()
+
+set_target_properties(${SWIG_MODULE_iDynTree_java_REAL_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_JNIDIR})
+
+# Update RPATH
+if(NOT CMAKE_SKIP_RPATH AND NOT CMAKE_SKIP_INSTALL_RPATH)
+  file(RELATIVE_PATH _rel_path "${CMAKE_INSTALL_FULL_JNIDIR}" "${CMAKE_INSTALL_FULL_LIBDIR}")
+  get_target_property(_current_rpath "${SWIG_MODULE_iDynTree_java_REAL_NAME}" INSTALL_RPATH)
+  if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+    list(APPEND _current_rpath "@loader_path/${_rel_path}")
+  else()
+    list(APPEND _current_rpath "\$ORIGIN/${_rel_path}")
+  endif()
+  set_target_properties(${SWIG_MODULE_iDynTree_java_REAL_NAME} PROPERTIES INSTALL_RPATH "${_current_rpath}")
+endif()
+
+
+set(CMAKE_JNI_TARGET TRUE)
+set(CMAKE_JAVA_TARGET_OUTPUT_DIR "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/iDynTree/java")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/GenerateSwigiDynTreeFileList.cmake"
+"file(GLOB _JAVA_COMPILE_FILES \"${CMAKE_SWIG_OUTDIR}/*.java\")
+string(REPLACE \";\" \"\\\"\\n\\\"\" _JAVA_COMPILE_STRING \"\\\"\${_JAVA_COMPILE_FILES}\\\"\")
+file(MAKE_DIRECTORY \"${CMAKE_JAVA_TARGET_OUTPUT_DIR}\")
+file(WRITE \"${CMAKE_JAVA_TARGET_OUTPUT_DIR}${CMAKE_FILES_DIRECTORY}/idyntree_java_jar.dir/swig_java_filelist\" \${_JAVA_COMPILE_STRING})
+")
+
+add_custom_command(TARGET ${SWIG_MODULE_iDynTree_java_REAL_NAME} POST_BUILD
+                   COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/GenerateSwigiDynTreeFileList.cmake"
+                   COMMENT "Generating list of JAVA files generated by swig")
+

-# Create JAR including compiled .class file 
-add_custom_command(TARGET ${target_name} POST_BUILD
-                   COMMAND "${Java_JAVAC_EXECUTABLE}" -d classes java/*.java
-                   COMMAND "${Java_JAR_EXECUTABLE}" -cfM iDynTree.jar -C classes .)
+add_jar(idyntree_java_jar
+        SOURCES @${CMAKE_JAVA_TARGET_OUTPUT_DIR}${CMAKE_FILES_DIRECTORY}/idyntree_java_jar.dir/swig_java_filelist
+        OUTPUT_NAME iDynTree
+        VERSION ${iDynTree_VERSION})

-# Store Path to iDynTree JAR in variable:
-SET(IDYNTREE_JAR "${CMAKE_CURRENT_BINARY_DIR}/iDynTree.jar")
+add_dependencies(idyntree_java_jar ${SWIG_MODULE_iDynTree_java_REAL_NAME})

+# installation part
+install(TARGETS ${SWIG_MODULE_iDynTree_java_REAL_NAME}
+        DESTINATION ${CMAKE_INSTALL_JNIDIR}
+        COMPONENT bindings_java)

-# if compile tests execute also java tests
-# if(IDYNTREE_COMPILE_TESTS)
-#    add_subdirectory(tests)
-# endif()
+install_jar(idyntree_java_jar
+            DESTINATION ${CMAKE_INSTALL_DATADIR}/iDynTree/java
+            COMPONENT bindings_java)
+install_jni_symlink(idyntree_java_jar
+                    DESTINATION ${CMAKE_INSTALL_DATADIR}/java
+                    COMPONENT bindings_java)
traversaro commented 1 year ago

@Nicogene @mfussi66 @pattacini this issue (and the connected PR https://github.com/robotology/idyntree/pull/392) are the original attemp to create Java bindings as part of the creo2urdf project. If necessary it should be relatively easy to revive it.