Compare commits

27 Commits

Author SHA1 Message Date
f7b1ef6720 Merge remote-tracking branch 'gitea/ros2_jazzy' into ros2_jazzy 2024-12-28 08:58:48 +09:00
b2826cdce3 remove reference to constraint manager submodule 2024-12-28 08:55:43 +09:00
7ad72b3fa1 bug fix hand driver with parameter initialization default issue 2024-12-20 16:54:40 +09:00
fd98ce22ef [sas_robot_driver_franka_hand_node] added gripper homing option to python module 2024-12-18 15:20:49 +09:00
fc34a7a289 [sas_robot_driver_franka_hand_node] added initialization option for not homing hand on startup 2024-12-18 15:13:33 +09:00
fac7dc597e fix example script for RobotDynamics and gripper control 2024-12-18 10:23:41 +09:00
quentinlin
ed5dc45719 remove submodule reference to constraints manager 2024-12-16 22:49:21 +09:00
8d29513a6b [sas_robot_driver_franka] fix namespace change with some sas parents class 2024-12-16 16:23:07 +09:00
787228d507 added homing service to franka hand node 2024-12-10 23:44:07 +09:00
4f0c5fb97d [EffectorDriverFrankaHand] bug fix and optimization to franka hand code 2024-11-22 23:11:58 +09:00
9968016135 compatability fix for libfranka 0.14 2024-11-21 15:28:20 +09:00
2bcd8e72ff CmakeList minor bugfix 2024-09-19 14:10:55 +09:00
825d39ae5c package cleanup 2024-08-22 09:26:28 +09:00
qlin1806
35131ed59e attempt to merge newer changes 2024-08-21 16:35:22 -07:00
fe5bb31873 bug fix hand initialization 2024-08-20 19:26:34 +09:00
e2f7830e01 bug fix hand initialization 2024-08-20 19:16:23 +09:00
75e00b3111 general bug fix 2024-08-19 15:30:30 +09:00
0358b851df minor bug fix for franka hand again 2024-08-18 21:40:42 +09:00
27b89070aa minor general bug fix 2024-08-18 21:16:47 +09:00
9b2061ba01 minor general bug fix 2024-08-18 20:57:24 +09:00
900f6aa2e1 minor renaming of file and working coppelia node 2024-08-16 11:30:58 +09:00
94a32a0f0c driver and hand tested successful.. next is coppeliamirror node 2024-08-15 20:19:28 +09:00
058c123170 [package] update fix package manifest 2024-07-28 19:49:12 +09:00
db4b1ccd58 attempt to test python 2024-07-27 15:24:26 +09:00
66a45b9ece added robot ui from JuankaEmika 2024-07-27 14:02:42 +09:00
7dfd4d40b8 migration to ros2 done 2024-07-27 13:07:37 +09:00
f5552be8d6 attempt to port ros2 2024-07-26 12:59:23 +09:00
66 changed files with 2235 additions and 2760 deletions

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "constraints_manager"]
path = constraints_manager
url = https://github.com/juanjqo/constraints_manager.git

View File

@@ -1,68 +1,33 @@
cmake_minimum_required(VERSION 3.0.2) cmake_minimum_required(VERSION 3.8)
project(sas_robot_driver_franka) project(sas_robot_driver_franka)
## Compile as C++11, supported in ROS Kinetic and newer ## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11) # add_compile_options(-std=c++11)
#add_compile_options(-std=c++11) #add_compile_options(-std=c++11)
add_compile_options(-Werror=return-type) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
#Add custom (non compiling) targets so launch scripts and python files show up in QT Creator's project view. find_package(pybind11 REQUIRED)
file(GLOB_RECURSE EXTRA_FILES */*) find_package(ament_cmake REQUIRED)
#add_custom_target(${PROJECT_NAME}_OTHER_FILES ALL WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} SOURCES ${EXTRA_FILES}) find_package(rclcpp REQUIRED)
add_custom_target(cfg ALL WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} SOURCES ${EXTRA_FILES}) find_package(geometry_msgs REQUIRED)
find_package(std_msgs REQUIRED)
## Find catkin macros and libraries find_package(std_srvs REQUIRED)
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) find_package(sas_common REQUIRED)
## is used, also find other catkin packages find_package(sas_core REQUIRED)
find_package(catkin REQUIRED COMPONENTS find_package(sas_msgs REQUIRED)
roscpp find_package(sas_conversions REQUIRED)
rospy
std_msgs
tf2_ros
tf2
sas_common
sas_clock
sas_robot_driver
sas_patient_side_manager
message_generation
pybind11_catkin
)
add_service_files(
DIRECTORY srv
FILES
Move.srv
Grasp.srv
)
add_message_files(
DIRECTORY msg
FILES
GripperState.msg
)
catkin_python_setup()
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(
INCLUDE_DIRS include
CATKIN_DEPENDS roscpp rospy sas_common sas_clock sas_robot_driver tf2_ros tf2 pybind11_catkin message_runtime std_msgs
)
find_package(Franka REQUIRED)
find_package(Eigen3 REQUIRED) find_package(Eigen3 REQUIRED)
find_package(yaml-cpp REQUIRED) find_package(tf2_ros REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR}) find_package(tf2 REQUIRED)
find_package(sas_robot_driver REQUIRED)
find_package(Franka REQUIRED)
find_package(pinocchio REQUIRED)
find_package(sas_robot_driver_franka_interfaces REQUIRED) # Add this line
# To correctly find and link with QT ## To correctly find and link with QT
set(CMAKE_PREFIX_PATH $ENV{QT_PATH}) set(CMAKE_PREFIX_PATH $ENV{QT_PATH})
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON) set(CMAKE_AUTORCC ON)
@@ -72,15 +37,76 @@ if (CMAKE_VERSION VERSION_LESS "3.7.0")
endif () endif ()
find_package(Qt5 COMPONENTS Widgets REQUIRED) find_package(Qt5 COMPONENTS Widgets REQUIRED)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) ##### CPP LIBRARY initial #####
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) include_directories(
include
constraints_manager/include
)
install(
DIRECTORY include/
DESTINATION include
)
ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET)
ament_export_dependencies(Eigen3 rclcpp geometry_msgs std_msgs
sas_common sas_core sas_conversions sas_robot_driver_franka_interfaces
tf2_ros tf2 sas_robot_driver)
##### CPP LIBRARY initial end #####
##### CPP LIBRARY ROBOT_DYNAMICS #####
add_library(${PROJECT_NAME}_robot_dynamics SHARED
src/robot_dynamics/qros_robot_dynamics_client.cpp
src/robot_dynamics/qros_robot_dynamics_server.cpp
)
ament_target_dependencies(${PROJECT_NAME}_robot_dynamics
rclcpp geometry_msgs std_msgs
sas_common sas_core sas_conversions
tf2_ros tf2 sas_robot_driver)
target_include_directories(${PROJECT_NAME}_robot_dynamics
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
target_link_libraries(${PROJECT_NAME}_robot_dynamics
-ldqrobotics
Eigen3::Eigen
)
install(
TARGETS ${PROJECT_NAME}_robot_dynamics # ${PROJECT_NAME}
EXPORT export_${PROJECT_NAME} #export_${PROJECT_NAME}
LIBRARY DESTINATION lib
#ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
##END## CPP LIBRARY ROBOT_DYNAMICS #####
##### CPP LIBRARY Motion Generation #####
add_library(MotionGenerator src/generator/motion_generator.cpp) add_library(MotionGenerator src/generator/motion_generator.cpp)
target_link_libraries(MotionGenerator Franka::Franka) target_link_libraries(MotionGenerator Franka::Franka pinocchio::pinocchio Eigen3::Eigen)
add_library(ConstraintsManager constraints_manager/src/constraints_manager.cpp) add_library(ConstraintsManager constraints_manager/src/constraints_manager.cpp)
target_link_libraries(ConstraintsManager Eigen3::Eigen)
install(
DIRECTORY constraints_manager/include/
DESTINATION include/constraints_manager
)
target_include_directories(ConstraintsManager
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/constraints_manager/include>
$<INSTALL_INTERFACE:include/constraints_manager>)
add_library(QuadraticProgramMotionGenerator src/generator/quadratic_program_motion_generator.cpp) add_library(QuadraticProgramMotionGenerator src/generator/quadratic_program_motion_generator.cpp)
target_link_libraries(QuadraticProgramMotionGenerator target_link_libraries(QuadraticProgramMotionGenerator
@@ -88,14 +114,21 @@ target_link_libraries(QuadraticProgramMotionGenerator
dqrobotics dqrobotics
ConstraintsManager) ConstraintsManager)
add_library(CustomMotionGeneration src/generator/custom_motion_generation.cpp) add_library(CustomMotionGeneration src/generator/custom_motion_generation.cpp)
target_link_libraries(CustomMotionGeneration target_link_libraries(CustomMotionGeneration
qpOASES qpOASES
dqrobotics dqrobotics
ConstraintsManager) ConstraintsManager)
##### CPP LIBRARY Motion Generation end #####
##### CPP LIBRARY franka low level interface #####
add_library(robot_interface_franka src/joint/robot_interface_franka.cpp) add_library(robot_interface_franka src/joint/robot_interface_franka.cpp)
target_link_libraries(robot_interface_franka Franka::Franka target_link_libraries(robot_interface_franka Franka::Franka
pinocchio::pinocchio
dqrobotics dqrobotics
MotionGenerator MotionGenerator
ConstraintsManager ConstraintsManager
@@ -104,136 +137,163 @@ target_link_libraries(robot_interface_franka Franka::Franka
add_library(robot_interface_hand src/hand/robot_interface_hand.cpp) add_library(robot_interface_hand src/hand/robot_interface_hand.cpp)
target_link_libraries(robot_interface_hand Franka::Franka target_link_libraries(robot_interface_hand Franka::Franka
pinocchio::pinocchio
dqrobotics) dqrobotics)
############ ##### CPP LIBRARY franka low level interface end #####
## Build ###
############
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
include
include/generator
src/
src/robot_dynamics
src/hand
src/joint
${catkin_INCLUDE_DIRS}
constraints_manager/include
)
add_library(qros_robot_dynamics_provider src/robot_dynamics/qros_robot_dynamics_provider.cpp)
target_link_libraries(qros_robot_dynamics_provider
${catkin_LIBRARIES}
dqrobotics)
add_library(qros_robot_dynamics_interface src/robot_dynamics/qros_robot_dynamics_interface.cpp)
target_link_libraries(qros_robot_dynamics_interface
${catkin_LIBRARIES}
dqrobotics)
##### SAS Franka Robot Driver #####
add_library(sas_robot_driver_franka src/joint/sas_robot_driver_franka.cpp) add_library(sas_robot_driver_franka src/joint/sas_robot_driver_franka.cpp)
target_link_libraries(sas_robot_driver_franka target_link_libraries(sas_robot_driver_franka
qros_robot_dynamics_provider ${PROJECT_NAME}_robot_dynamics
dqrobotics dqrobotics
dqrobotics-interface-json11 dqrobotics-interface-json11
robot_interface_franka) robot_interface_franka)
##### SAS Franka Robot Driver end #####
##### qros hand effector driver #####
add_library(qros_effector_driver_franka_hand src/hand/qros_effector_driver_franka_hand.cpp) add_library(qros_effector_driver_franka_hand src/hand/qros_effector_driver_franka_hand.cpp)
ament_target_dependencies(qros_effector_driver_franka_hand
rclcpp sas_common sas_core std_srvs
sas_robot_driver_franka_interfaces
)
#ament_target_dependencies(${PROJECT_NAME}_robot_dynamics
# rclcpp geometry_msgs std_msgs
# sas_common sas_core sas_conversions
# tf2_ros tf2 sas_robot_driver)
target_link_libraries(qros_effector_driver_franka_hand target_link_libraries(qros_effector_driver_franka_hand
dqrobotics dqrobotics
# robot_interface_hand Franka::Franka
Franka::Franka) pinocchio::pinocchio
)
#target_include_directories(qros_effector_driver_franka_hand
# PUBLIC
# $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/interface>
# $<INSTALL_INTERFACE:include/interface>)
##### qros hand effector driver end #####
add_library(sas_robot_driver_coppelia src/coppelia/sas_robot_driver_coppelia.cpp) ##### SAS Franka Robot Driver Node #####
target_link_libraries(sas_robot_driver_coppelia
dqrobotics
dqrobotics-interface-vrep)
add_dependencies(sas_robot_driver_franka ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_dependencies(sas_robot_driver_coppelia ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_dependencies(qros_effector_driver_franka_hand ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_executable(sas_robot_driver_coppelia_node src/sas_robot_driver_coppelia_node.cpp)
target_link_libraries(sas_robot_driver_coppelia_node
sas_robot_driver_coppelia
${catkin_LIBRARIES})
add_executable(sas_robot_driver_franka_node src/sas_robot_driver_franka_node.cpp) add_executable(sas_robot_driver_franka_node src/sas_robot_driver_franka_node.cpp)
target_link_libraries(sas_robot_driver_franka_node ament_target_dependencies(sas_robot_driver_franka_node
sas_robot_driver_franka rclcpp sas_common sas_core
${catkin_LIBRARIES}) sas_robot_driver)
target_link_libraries(sas_robot_driver_franka_node sas_robot_driver_franka)
install(TARGETS
sas_robot_driver_franka_node
DESTINATION lib/${PROJECT_NAME})
##### SAS Franka Robot Hand Driver Node #####
add_executable(sas_robot_driver_franka_hand_node src/sas_robot_driver_franka_hand_node.cpp) add_executable(sas_robot_driver_franka_hand_node src/sas_robot_driver_franka_hand_node.cpp)
ament_target_dependencies(sas_robot_driver_franka_node
rclcpp sas_common sas_core)
target_link_libraries(sas_robot_driver_franka_hand_node target_link_libraries(sas_robot_driver_franka_hand_node
qros_effector_driver_franka_hand qros_effector_driver_franka_hand)
${catkin_LIBRARIES})
install(TARGETS
sas_robot_driver_franka_hand_node
DESTINATION lib/${PROJECT_NAME})
##### Coppelia Mirror Node #####
add_executable(sas_robot_driver_franka_coppelia_node
src/sas_robot_driver_coppelia_node.cpp
src/coppelia/sas_robot_driver_coppelia.cpp
)
ament_target_dependencies(sas_robot_driver_franka_coppelia_node
rclcpp sas_common sas_core sas_conversions sas_robot_driver
)
target_link_libraries(sas_robot_driver_franka_coppelia_node
dqrobotics
dqrobotics-interface-json11
dqrobotics-interface-vrep
)
install(TARGETS
sas_robot_driver_franka_coppelia_node
DESTINATION lib/${PROJECT_NAME})
##### JuanEmika
add_executable(JuankaEmika add_executable(JuankaEmika
qt/configuration_window/main.cpp qt/configuration_window/main.cpp
qt/configuration_window/mainwindow.cpp qt/configuration_window/mainwindow.cpp
qt/configuration_window/mainwindow.ui qt/configuration_window/mainwindow.ui
) )
ament_target_dependencies(sas_robot_driver_franka_node
rclcpp sas_common sas_core
sas_robot_driver)
target_link_libraries(JuankaEmika PRIVATE Qt${QT_VERSION_MAJOR}::Widgets target_link_libraries(JuankaEmika PRIVATE Qt${QT_VERSION_MAJOR}::Widgets
dqrobotics dqrobotics
${catkin_LIBRARIES}
robot_interface_franka robot_interface_franka
) )
#####################################################################################
# python binding
include_directories(
include/robot_dynamic
)
pybind_add_module(_qros_robot_dynamic SHARED
src/robot_dynamics/qros_robot_dynamic_py.cpp src/robot_dynamics/qros_robot_dynamics_interface.cpp src/robot_dynamics/qros_robot_dynamics_provider.cpp
)
target_compile_definitions(_qros_robot_dynamic PRIVATE BUILD_PYBIND)
# https://github.com/pybind/pybind11/issues/387
target_link_libraries(_qros_robot_dynamic PRIVATE ${catkin_LIBRARIES} -ldqrobotics)
if (QT_VERSION_MAJOR EQUAL 6) if (QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(JuankaEmika) qt_finalize_executable(JuankaEmika)
endif () endif ()
install(TARGETS ${PROJECT_NAME} install(TARGETS
DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} JuankaEmika
DESTINATION lib/${PROJECT_NAME})
##### PYBIND11 LIBRARY ROBOT_DYNAMICS #####
ament_python_install_package(${PROJECT_NAME})
pybind11_add_module(_qros_franka_robot_dynamics_py SHARED
src/robot_dynamics/qros_robot_dynamics_py.cpp
src/robot_dynamics/qros_robot_dynamics_client.cpp
src/robot_dynamics/qros_robot_dynamics_server.cpp
) )
install(TARGETS sas_robot_driver_franka_node target_include_directories(_qros_franka_robot_dynamics_py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} PUBLIC
) $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/robot_dynamics>
$<INSTALL_INTERFACE:include/robot_dynamics>)
install(TARGETS sas_robot_driver_coppelia_node target_compile_definitions(_qros_franka_robot_dynamics_py PRIVATE IS_SAS_PYTHON_BUILD)
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} # https://github.com/pybind/pybind11/issues/387
) target_link_libraries(_qros_franka_robot_dynamics_py PRIVATE ${PROJECT_NAME}_robot_dynamics -ldqrobotics)
install(TARGETS sas_robot_driver_franka_hand_node install(TARGETS _qros_franka_robot_dynamics_py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} DESTINATION "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}"
) )
##END## PYBIND11 LIBRARY ROBOT_DYNAMICS #####
## Mark cpp header files for installation
install(DIRECTORY include/${PROJECT_NAME}/ install(
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} DIRECTORY include/
FILES_MATCHING PATTERN "*.h" DESTINATION include
# PATTERN ".svn" EXCLUDE
) )
install(TARGETS _qros_robot_dynamic
LIBRARY DESTINATION ${PYTHON_INSTALL_DIR}
##### LAUNCH FILES #####
install(DIRECTORY
launch
DESTINATION share/${PROJECT_NAME}/
) )
##END## LAUNCH FILES #####
ament_package()

View File

@@ -1,5 +1,3 @@
![](https://img.shields.io/github/license/juanjqo/sas_robot_driver_franka)![](https://img.shields.io/github/contributors/juanjqo/sas_robot_driver_franka)![](https://img.shields.io/github/last-commit/juanjqo/sas_robot_driver_franka)![](https://img.shields.io/github/last-commit/juanjqo/sas_robot_driver_franka/master)![](https://img.shields.io/badge/status-experimental-red) ![](https://img.shields.io/github/license/juanjqo/sas_robot_driver_franka)![](https://img.shields.io/github/contributors/juanjqo/sas_robot_driver_franka)![](https://img.shields.io/github/last-commit/juanjqo/sas_robot_driver_franka)![](https://img.shields.io/github/last-commit/juanjqo/sas_robot_driver_franka/master)![](https://img.shields.io/badge/status-experimental-red)
# sas_robot_driver_franka # sas_robot_driver_franka
![ezgif com-video-to-gif (1)](https://github.com/SmartArmStack/sas_robot_driver/assets/23158313/b4e1efa7-8d93-4a67-ab87-a74c41d8f4bc)

165
constraints_manager/LICENSE Normal file
View File

@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@@ -0,0 +1,2 @@
![](https://img.shields.io/github/license/juanjqo/constraints_manager)![](https://img.shields.io/github/contributors/juanjqo/constraints_manager)![](https://img.shields.io/github/last-commit/juanjqo/constraints_manager/main)![](https://img.shields.io/github/commit-activity/t/juanjqo/constraints_manager/main)
# constraints_manager

View File

@@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.5)
project(constraints_manager_example LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
FIND_PACKAGE(Eigen3 REQUIRED)
INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIR})
ADD_COMPILE_OPTIONS(-Werror=return-type -Wall -Wextra -Wmissing-declarations -Wredundant-decls -Woverloaded-virtual)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/../include
)
add_library(ConstraintsManager ${CMAKE_CURRENT_SOURCE_DIR}/../src/constraints_manager.cpp)
add_executable(constraints_manager_example main.cpp)
target_link_libraries(constraints_manager_example
ConstraintsManager)

View File

@@ -0,0 +1,26 @@
#include <iostream>
#include "constraints_manager.h"
using namespace Eigen;
int main()
{
auto manager = ConstraintsManager(3);
auto A1 = MatrixXd::Zero(3,3);
auto b1 = VectorXd::Zero(3);
auto A2 = MatrixXd::Ones(1,3);
auto b2 = VectorXd::Ones(1);
manager.add_inequality_constraint(A1, b1);
manager.add_inequality_constraint(A2, b2);
MatrixXd A;
VectorXd b;
std::tie(A,b) = manager.get_inequality_constraints();
std::cout<<"A: "<<std::endl;
std::cout<<A<<std::endl;
std::cout<<"b: "<<std::endl;
std::cout<<b<<std::endl;
}

View File

@@ -0,0 +1,67 @@
/*
# Copyright (c) 2023 Juan Jose Quiroz Omana
#
# constraints_manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# constraints_manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with constraints_manager. If not, see <https://www.gnu.org/licenses/>.
#
# ################################################################
#
# Author: Juan Jose Quiroz Omana, email: juanjqogm@gmail.com
#
# ################################################################*/
#pragma once
#include <Eigen/Dense>
#include <vector>
using namespace Eigen;
class ConstraintsManager
{
protected:
int dim_configuration_;
VectorXd q_dot_min_ = VectorXd::Zero(0);
VectorXd q_dot_max_ = VectorXd::Zero(0);
VectorXd q_min_ = VectorXd::Zero(0);
VectorXd q_max_ = VectorXd::Zero(0);
MatrixXd equality_constraint_matrix_ = MatrixXd::Zero(0,0);
VectorXd equality_constraint_vector_ = VectorXd::Zero(0);
MatrixXd inequality_constraint_matrix_ = MatrixXd::Zero(0,0);
VectorXd inequality_constraint_vector_ = VectorXd::Zero(0);
MatrixXd _raw_add_matrix_constraint(const MatrixXd& A0, const MatrixXd& A);
VectorXd _raw_add_vector_constraint(const VectorXd& b0, const VectorXd& b);
void _check_matrix_and_vector_sizes(const MatrixXd& A, const VectorXd& b);
void _check_vectors_size(const VectorXd& q1, const VectorXd& q2, const std::string &msg);
void _check_vector_initialization(const VectorXd& q, const std::string &msg);
MatrixXd _create_matrix(const MatrixXd& A);
public:
ConstraintsManager() = delete;
ConstraintsManager(const int& dim_configuration);
void add_equality_constraint(const MatrixXd& A, const VectorXd& b);
void add_inequality_constraint(const MatrixXd& A, const VectorXd& b);
std::tuple<MatrixXd, VectorXd> get_equality_constraints();
std::tuple<MatrixXd, VectorXd> get_inequality_constraints();
void set_joint_position_limits(const VectorXd& q_lower_bound, const VectorXd& q_upper_bound);
void set_joint_velocity_limits(const VectorXd& q_dot_lower_bound, const VectorXd& q_dot_upper_bound);
};

View File

@@ -0,0 +1,259 @@
/*
# Copyright (c) 2023 Juan Jose Quiroz Omana
#
# constraints_manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# constraints_manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with constraints_manager. If not, see <https://www.gnu.org/licenses/>.
#
# ################################################################
#
# Author: Juan Jose Quiroz Omana, email: juanjqogm@gmail.com
#
# ################################################################*/
#include "constraints_manager.h"
/**
* @brief Constructor
* @param int dim_configuration Dimension of the robot configuration
*/
ConstraintsManager::ConstraintsManager(const int& dim_configuration):dim_configuration_(dim_configuration)
{
}
/**
* @brief The method _create_matrix returns a matrix containing the matrix A
* and taking into acount the dimension of the robot configuration. If matrix A has lower columns than
* dim_configuration then _create_matrix completes the correct size with zeros.
* @param MatrixXd A Input matrix
* @return
*/
MatrixXd ConstraintsManager::_create_matrix(const MatrixXd& A)
{
MatrixXd constraint_matrix = MatrixXd::Zero(A.rows(), dim_configuration_);
constraint_matrix.block(0,0, A.rows(), A.cols()) = A;
return constraint_matrix;
}
/**
* @brief The method _check_matrix_and_vector_sizes(A,b) check the if the rows of Matrix A
* has the same dimension of Vector b.
* @param MatrixXd A
* @param VectorXd b
*/
void ConstraintsManager::_check_matrix_and_vector_sizes(const MatrixXd& A, const VectorXd& b)
{
int m = A.rows();
int n = A.cols();
int nb = b.size();
if (m != nb)
{
throw std::runtime_error(std::string("Incompatible sizes. The rows of Matrix A must have the same dimension of Vector b. ")
+ std::string("But you used A ")+ std::to_string(m)+ std::string("x")+ std::to_string(n)
+ std::string(" and b ")+ std::to_string(nb) + std::string("x1"));
}
if (n != dim_configuration_)
{
throw std::runtime_error(std::string("Incompatible sizes. The cols of Matrix A must have dimension ") + std::to_string(dim_configuration_)
+ std::string(". But you used A ")+ std::to_string(m)+ std::string("x")+ std::to_string(n)
+ std::string(" and b ")+ std::to_string(nb) + std::string("x1"));
}
}
/**
* @brief ConstraintsManager::_check_vectors_size() checks the dimensions of two vectors.
* @param VectorXd q1 First vector to be checked.
* @param VectorXd q2 Second vector to be checked.
* @param std::string msg Desired error message if vectors q1 and q2 have different size.
*/
void ConstraintsManager::_check_vectors_size(const VectorXd& q1, const VectorXd& q2, const std::string &msg)
{
if (q1.size() != q2.size() )
{
throw std::runtime_error(msg);
}
}
/**
* @brief ConstraintsManager::_check_vector_initialization()
* @param VectorXd q
* @param std::string msg
*/
void ConstraintsManager::_check_vector_initialization(const VectorXd& q, const std::string &msg)
{
if (q.size() == 0)
{
throw std::runtime_error(msg);
}
}
/**
* @brief The method _raw_add_matrix_constraint(A0, A) returns a constraint_matrix, which is given as
* constraint_matrix = [A0
* A]
* @param MatrixXd A0
* @param MatrixXd A
* @return MatrixXd constraint_matrix
*/
MatrixXd ConstraintsManager::_raw_add_matrix_constraint(const MatrixXd& A0, const MatrixXd& A)
{
int m = A.rows();
int n = A.cols();
int m0 = A0.rows();
int n0 = A0.cols();
MatrixXd constraint_matrix = MatrixXd::Zero(m0+m, dim_configuration_);
if(n != n0)
{
throw std::runtime_error(std::string("Incompatible sizes. The equality matrix must be ")
+ std::string("m x ")+ std::to_string(n0)
+ std::string(". But you used m x ")+ std::to_string(n));
}
constraint_matrix.block(0,0, m0, n0) = A0;
constraint_matrix.block(m0,0, m, n) = A;
return constraint_matrix;
}
/**
* @brief The method _raw_add_vector_constraint(b0, b) returns the vector constraint_vector,
* which is given as
* constraint_vector = [b0
* b];
* @param VectorXd b0
* @param VectorXd b
* @return VectorXd constraint_vector
*/
VectorXd ConstraintsManager::_raw_add_vector_constraint(const VectorXd& b0, const VectorXd& b)
{
int nb = b.size();
int nb0 = b0.size();
VectorXd constraint_vector = VectorXd::Zero(nb0+nb);
constraint_vector.head(nb0) = b0;
constraint_vector.segment(nb0, nb) = b;
return constraint_vector;
}
/**
* @brief The method add_equality_constraint(A, b) adds the equality constraint A*x = b
* to the set of equality constraints.
*
* @param MatrixXd A
* @param VectorXd b
*/
void ConstraintsManager::add_equality_constraint(const MatrixXd& A, const VectorXd& b)
{
_check_matrix_and_vector_sizes(A, b);
if (equality_constraint_matrix_.size() == 0)
{
equality_constraint_matrix_ = _create_matrix(A);
equality_constraint_vector_ = b;
}else
{
equality_constraint_matrix_ = _raw_add_matrix_constraint(equality_constraint_matrix_, A);
equality_constraint_vector_ = _raw_add_vector_constraint(equality_constraint_vector_, b);
}
}
/**
* @brief The method add_inequality_constraint(A, b) adds the inequality constraint A*x <= b
* to the set of ineequality constraints.
* @param MatrixXd A
* @param VectorXd b
*/
void ConstraintsManager::add_inequality_constraint(const MatrixXd& A, const VectorXd& b)
{
_check_matrix_and_vector_sizes(A, b);
if (inequality_constraint_matrix_.size() == 0)
{
inequality_constraint_matrix_ = _create_matrix(A);
inequality_constraint_vector_ = b;
}else
{
inequality_constraint_matrix_ = _raw_add_matrix_constraint(inequality_constraint_matrix_, A);
inequality_constraint_vector_ = _raw_add_vector_constraint(inequality_constraint_vector_, b);
}
}
/**
* @brief The method get_equality_constraints() returns the set of equality constraints
* composed of the Matrix A and the vector b, where
* A*x = b.
* Warning: This method deletes all the equality constraints stored.
* @return std::tuple<MatrixXd A, VectorXd b>
*/
std::tuple<MatrixXd, VectorXd> ConstraintsManager::get_equality_constraints()
{
MatrixXd A = equality_constraint_matrix_;
equality_constraint_matrix_ = MatrixXd::Zero(0,0);
return std::make_tuple(A, equality_constraint_vector_);
}
/**
* @brief The method get_inequality_constraints() returns the set of inequality constraints
* composed of the Matrix A and the vector b, where
* A*x <= b
* Warning: This method deletes all the inequality constraints stored.
* @return
*/
std::tuple<MatrixXd, VectorXd> ConstraintsManager::get_inequality_constraints()
{
MatrixXd A = inequality_constraint_matrix_;
inequality_constraint_matrix_ = MatrixXd::Zero(0,0);
return std::make_tuple(A, inequality_constraint_vector_);
}
/**
* @brief ConstraintsManager::set_joint_position_limits
* @param VectorXd q_lower_bound
* @param VectorXd q_upper_bound
*/
void ConstraintsManager::set_joint_position_limits(const VectorXd& q_lower_bound, const VectorXd& q_upper_bound)
{
_check_vectors_size(q_lower_bound, q_upper_bound,
std::string("The sizes are incompatibles. q_lower_bound has size ") + std::to_string(q_lower_bound.size())
+ std::string(" and q_upper_bound has size ") + std::to_string(q_upper_bound.size()));
_check_vectors_size(q_lower_bound, VectorXd::Zero(dim_configuration_),
std::string("The sizes are incompatibles. The joint limits have size ") + std::to_string(q_lower_bound.size())
+ std::string(" and the robot configuration has size ") + std::to_string(dim_configuration_));
q_min_ = q_lower_bound;
q_max_ = q_upper_bound;
}
/**
* @brief ConstraintsManager::set_joint_velocity_limits
* @param q_dot_lower_bound
* @param q_dot_upper_bound
*/
void ConstraintsManager::set_joint_velocity_limits(const VectorXd& q_dot_lower_bound, const VectorXd& q_dot_upper_bound)
{
_check_vectors_size(q_dot_lower_bound, q_dot_upper_bound,
std::string("The sizes are incompatibles. q_dot_lower_bound has size ") + std::to_string(q_dot_lower_bound.size())
+ std::string(" and q_dot_upper_bound has size ") + std::to_string(q_dot_upper_bound.size()));
_check_vectors_size(q_dot_lower_bound, VectorXd::Zero(dim_configuration_),
std::string("The sizes are incompatibles. The joint limits have size ") + std::to_string(q_dot_lower_bound.size())
+ std::string(" and the robot configuration has size ") + std::to_string(dim_configuration_));
q_dot_min_ = q_dot_lower_bound;
q_dot_max_ = q_dot_upper_bound;
}

View File

@@ -1,123 +0,0 @@
// Generated by gencpp from file sas_robot_driver_franka/Grasp.msg
// DO NOT EDIT!
#ifndef SAS_ROBOT_DRIVER_FRANKA_MESSAGE_GRASP_H
#define SAS_ROBOT_DRIVER_FRANKA_MESSAGE_GRASP_H
#include <ros/service_traits.h>
#include <sas_robot_driver_franka/GraspRequest.h>
#include <sas_robot_driver_franka/GraspResponse.h>
namespace sas_robot_driver_franka
{
struct Grasp
{
typedef GraspRequest Request;
typedef GraspResponse Response;
Request request;
Response response;
typedef Request RequestType;
typedef Response ResponseType;
}; // struct Grasp
} // namespace sas_robot_driver_franka
namespace ros
{
namespace service_traits
{
template<>
struct MD5Sum< ::sas_robot_driver_franka::Grasp > {
static const char* value()
{
return "6752ec080e002a60682f31654d420583";
}
static const char* value(const ::sas_robot_driver_franka::Grasp&) { return value(); }
};
template<>
struct DataType< ::sas_robot_driver_franka::Grasp > {
static const char* value()
{
return "sas_robot_driver_franka/Grasp";
}
static const char* value(const ::sas_robot_driver_franka::Grasp&) { return value(); }
};
// service_traits::MD5Sum< ::sas_robot_driver_franka::GraspRequest> should match
// service_traits::MD5Sum< ::sas_robot_driver_franka::Grasp >
template<>
struct MD5Sum< ::sas_robot_driver_franka::GraspRequest>
{
static const char* value()
{
return MD5Sum< ::sas_robot_driver_franka::Grasp >::value();
}
static const char* value(const ::sas_robot_driver_franka::GraspRequest&)
{
return value();
}
};
// service_traits::DataType< ::sas_robot_driver_franka::GraspRequest> should match
// service_traits::DataType< ::sas_robot_driver_franka::Grasp >
template<>
struct DataType< ::sas_robot_driver_franka::GraspRequest>
{
static const char* value()
{
return DataType< ::sas_robot_driver_franka::Grasp >::value();
}
static const char* value(const ::sas_robot_driver_franka::GraspRequest&)
{
return value();
}
};
// service_traits::MD5Sum< ::sas_robot_driver_franka::GraspResponse> should match
// service_traits::MD5Sum< ::sas_robot_driver_franka::Grasp >
template<>
struct MD5Sum< ::sas_robot_driver_franka::GraspResponse>
{
static const char* value()
{
return MD5Sum< ::sas_robot_driver_franka::Grasp >::value();
}
static const char* value(const ::sas_robot_driver_franka::GraspResponse&)
{
return value();
}
};
// service_traits::DataType< ::sas_robot_driver_franka::GraspResponse> should match
// service_traits::DataType< ::sas_robot_driver_franka::Grasp >
template<>
struct DataType< ::sas_robot_driver_franka::GraspResponse>
{
static const char* value()
{
return DataType< ::sas_robot_driver_franka::Grasp >::value();
}
static const char* value(const ::sas_robot_driver_franka::GraspResponse&)
{
return value();
}
};
} // namespace service_traits
} // namespace ros
#endif // SAS_ROBOT_DRIVER_FRANKA_MESSAGE_GRASP_H

View File

@@ -1,235 +0,0 @@
// Generated by gencpp from file sas_robot_driver_franka/GraspRequest.msg
// DO NOT EDIT!
#ifndef SAS_ROBOT_DRIVER_FRANKA_MESSAGE_GRASPREQUEST_H
#define SAS_ROBOT_DRIVER_FRANKA_MESSAGE_GRASPREQUEST_H
#include <string>
#include <vector>
#include <memory>
#include <ros/types.h>
#include <ros/serialization.h>
#include <ros/builtin_message_traits.h>
#include <ros/message_operations.h>
namespace sas_robot_driver_franka
{
template <class ContainerAllocator>
struct GraspRequest_
{
typedef GraspRequest_<ContainerAllocator> Type;
GraspRequest_()
: width(0.0)
, speed(0.0)
, force(0.0)
, epsilon_inner(0.0)
, epsilon_outer(0.0) {
}
GraspRequest_(const ContainerAllocator& _alloc)
: width(0.0)
, speed(0.0)
, force(0.0)
, epsilon_inner(0.0)
, epsilon_outer(0.0) {
(void)_alloc;
}
typedef float _width_type;
_width_type width;
typedef float _speed_type;
_speed_type speed;
typedef float _force_type;
_force_type force;
typedef float _epsilon_inner_type;
_epsilon_inner_type epsilon_inner;
typedef float _epsilon_outer_type;
_epsilon_outer_type epsilon_outer;
typedef boost::shared_ptr< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> > Ptr;
typedef boost::shared_ptr< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> const> ConstPtr;
}; // struct GraspRequest_
typedef ::sas_robot_driver_franka::GraspRequest_<std::allocator<void> > GraspRequest;
typedef boost::shared_ptr< ::sas_robot_driver_franka::GraspRequest > GraspRequestPtr;
typedef boost::shared_ptr< ::sas_robot_driver_franka::GraspRequest const> GraspRequestConstPtr;
// constants requiring out of line definition
template<typename ContainerAllocator>
std::ostream& operator<<(std::ostream& s, const ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> & v)
{
ros::message_operations::Printer< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> >::stream(s, "", v);
return s;
}
template<typename ContainerAllocator1, typename ContainerAllocator2>
bool operator==(const ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator1> & lhs, const ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator2> & rhs)
{
return lhs.width == rhs.width &&
lhs.speed == rhs.speed &&
lhs.force == rhs.force &&
lhs.epsilon_inner == rhs.epsilon_inner &&
lhs.epsilon_outer == rhs.epsilon_outer;
}
template<typename ContainerAllocator1, typename ContainerAllocator2>
bool operator!=(const ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator1> & lhs, const ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator2> & rhs)
{
return !(lhs == rhs);
}
} // namespace sas_robot_driver_franka
namespace ros
{
namespace message_traits
{
template <class ContainerAllocator>
struct IsMessage< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> >
: TrueType
{ };
template <class ContainerAllocator>
struct IsMessage< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> const>
: TrueType
{ };
template <class ContainerAllocator>
struct IsFixedSize< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> >
: TrueType
{ };
template <class ContainerAllocator>
struct IsFixedSize< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> const>
: TrueType
{ };
template <class ContainerAllocator>
struct HasHeader< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> >
: FalseType
{ };
template <class ContainerAllocator>
struct HasHeader< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> const>
: FalseType
{ };
template<class ContainerAllocator>
struct MD5Sum< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> >
{
static const char* value()
{
return "337f46ba15e58c568d47e27881cf893c";
}
static const char* value(const ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator>&) { return value(); }
static const uint64_t static_value1 = 0x337f46ba15e58c56ULL;
static const uint64_t static_value2 = 0x8d47e27881cf893cULL;
};
template<class ContainerAllocator>
struct DataType< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> >
{
static const char* value()
{
return "sas_robot_driver_franka/GraspRequest";
}
static const char* value(const ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator>&) { return value(); }
};
template<class ContainerAllocator>
struct Definition< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> >
{
static const char* value()
{
return "float32 width\n"
"float32 speed\n"
"float32 force\n"
"float32 epsilon_inner\n"
"float32 epsilon_outer\n"
;
}
static const char* value(const ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator>&) { return value(); }
};
} // namespace message_traits
} // namespace ros
namespace ros
{
namespace serialization
{
template<class ContainerAllocator> struct Serializer< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> >
{
template<typename Stream, typename T> inline static void allInOne(Stream& stream, T m)
{
stream.next(m.width);
stream.next(m.speed);
stream.next(m.force);
stream.next(m.epsilon_inner);
stream.next(m.epsilon_outer);
}
ROS_DECLARE_ALLINONE_SERIALIZER
}; // struct GraspRequest_
} // namespace serialization
} // namespace ros
namespace ros
{
namespace message_operations
{
template<class ContainerAllocator>
struct Printer< ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator> >
{
template<typename Stream> static void stream(Stream& s, const std::string& indent, const ::sas_robot_driver_franka::GraspRequest_<ContainerAllocator>& v)
{
s << indent << "width: ";
Printer<float>::stream(s, indent + " ", v.width);
s << indent << "speed: ";
Printer<float>::stream(s, indent + " ", v.speed);
s << indent << "force: ";
Printer<float>::stream(s, indent + " ", v.force);
s << indent << "epsilon_inner: ";
Printer<float>::stream(s, indent + " ", v.epsilon_inner);
s << indent << "epsilon_outer: ";
Printer<float>::stream(s, indent + " ", v.epsilon_outer);
}
};
} // namespace message_operations
} // namespace ros
#endif // SAS_ROBOT_DRIVER_FRANKA_MESSAGE_GRASPREQUEST_H

View File

@@ -1,195 +0,0 @@
// Generated by gencpp from file sas_robot_driver_franka/GraspResponse.msg
// DO NOT EDIT!
#ifndef SAS_ROBOT_DRIVER_FRANKA_MESSAGE_GRASPRESPONSE_H
#define SAS_ROBOT_DRIVER_FRANKA_MESSAGE_GRASPRESPONSE_H
#include <string>
#include <vector>
#include <memory>
#include <ros/types.h>
#include <ros/serialization.h>
#include <ros/builtin_message_traits.h>
#include <ros/message_operations.h>
namespace sas_robot_driver_franka
{
template <class ContainerAllocator>
struct GraspResponse_
{
typedef GraspResponse_<ContainerAllocator> Type;
GraspResponse_()
: success(false) {
}
GraspResponse_(const ContainerAllocator& _alloc)
: success(false) {
(void)_alloc;
}
typedef uint8_t _success_type;
_success_type success;
typedef boost::shared_ptr< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> > Ptr;
typedef boost::shared_ptr< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> const> ConstPtr;
}; // struct GraspResponse_
typedef ::sas_robot_driver_franka::GraspResponse_<std::allocator<void> > GraspResponse;
typedef boost::shared_ptr< ::sas_robot_driver_franka::GraspResponse > GraspResponsePtr;
typedef boost::shared_ptr< ::sas_robot_driver_franka::GraspResponse const> GraspResponseConstPtr;
// constants requiring out of line definition
template<typename ContainerAllocator>
std::ostream& operator<<(std::ostream& s, const ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> & v)
{
ros::message_operations::Printer< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> >::stream(s, "", v);
return s;
}
template<typename ContainerAllocator1, typename ContainerAllocator2>
bool operator==(const ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator1> & lhs, const ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator2> & rhs)
{
return lhs.success == rhs.success;
}
template<typename ContainerAllocator1, typename ContainerAllocator2>
bool operator!=(const ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator1> & lhs, const ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator2> & rhs)
{
return !(lhs == rhs);
}
} // namespace sas_robot_driver_franka
namespace ros
{
namespace message_traits
{
template <class ContainerAllocator>
struct IsMessage< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> >
: TrueType
{ };
template <class ContainerAllocator>
struct IsMessage< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> const>
: TrueType
{ };
template <class ContainerAllocator>
struct IsFixedSize< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> >
: TrueType
{ };
template <class ContainerAllocator>
struct IsFixedSize< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> const>
: TrueType
{ };
template <class ContainerAllocator>
struct HasHeader< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> >
: FalseType
{ };
template <class ContainerAllocator>
struct HasHeader< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> const>
: FalseType
{ };
template<class ContainerAllocator>
struct MD5Sum< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> >
{
static const char* value()
{
return "358e233cde0c8a8bcfea4ce193f8fc15";
}
static const char* value(const ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator>&) { return value(); }
static const uint64_t static_value1 = 0x358e233cde0c8a8bULL;
static const uint64_t static_value2 = 0xcfea4ce193f8fc15ULL;
};
template<class ContainerAllocator>
struct DataType< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> >
{
static const char* value()
{
return "sas_robot_driver_franka/GraspResponse";
}
static const char* value(const ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator>&) { return value(); }
};
template<class ContainerAllocator>
struct Definition< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> >
{
static const char* value()
{
return "bool success\n"
;
}
static const char* value(const ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator>&) { return value(); }
};
} // namespace message_traits
} // namespace ros
namespace ros
{
namespace serialization
{
template<class ContainerAllocator> struct Serializer< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> >
{
template<typename Stream, typename T> inline static void allInOne(Stream& stream, T m)
{
stream.next(m.success);
}
ROS_DECLARE_ALLINONE_SERIALIZER
}; // struct GraspResponse_
} // namespace serialization
} // namespace ros
namespace ros
{
namespace message_operations
{
template<class ContainerAllocator>
struct Printer< ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator> >
{
template<typename Stream> static void stream(Stream& s, const std::string& indent, const ::sas_robot_driver_franka::GraspResponse_<ContainerAllocator>& v)
{
s << indent << "success: ";
Printer<uint8_t>::stream(s, indent + " ", v.success);
}
};
} // namespace message_operations
} // namespace ros
#endif // SAS_ROBOT_DRIVER_FRANKA_MESSAGE_GRASPRESPONSE_H

View File

@@ -1,235 +0,0 @@
// Generated by gencpp from file sas_robot_driver_franka/GripperState.msg
// DO NOT EDIT!
#ifndef SAS_ROBOT_DRIVER_FRANKA_MESSAGE_GRIPPERSTATE_H
#define SAS_ROBOT_DRIVER_FRANKA_MESSAGE_GRIPPERSTATE_H
#include <string>
#include <vector>
#include <memory>
#include <ros/types.h>
#include <ros/serialization.h>
#include <ros/builtin_message_traits.h>
#include <ros/message_operations.h>
namespace sas_robot_driver_franka
{
template <class ContainerAllocator>
struct GripperState_
{
typedef GripperState_<ContainerAllocator> Type;
GripperState_()
: width(0.0)
, max_width(0.0)
, is_grasped(false)
, temperature(0)
, duration_ms(0) {
}
GripperState_(const ContainerAllocator& _alloc)
: width(0.0)
, max_width(0.0)
, is_grasped(false)
, temperature(0)
, duration_ms(0) {
(void)_alloc;
}
typedef float _width_type;
_width_type width;
typedef float _max_width_type;
_max_width_type max_width;
typedef uint8_t _is_grasped_type;
_is_grasped_type is_grasped;
typedef uint16_t _temperature_type;
_temperature_type temperature;
typedef uint64_t _duration_ms_type;
_duration_ms_type duration_ms;
typedef boost::shared_ptr< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> > Ptr;
typedef boost::shared_ptr< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> const> ConstPtr;
}; // struct GripperState_
typedef ::sas_robot_driver_franka::GripperState_<std::allocator<void> > GripperState;
typedef boost::shared_ptr< ::sas_robot_driver_franka::GripperState > GripperStatePtr;
typedef boost::shared_ptr< ::sas_robot_driver_franka::GripperState const> GripperStateConstPtr;
// constants requiring out of line definition
template<typename ContainerAllocator>
std::ostream& operator<<(std::ostream& s, const ::sas_robot_driver_franka::GripperState_<ContainerAllocator> & v)
{
ros::message_operations::Printer< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> >::stream(s, "", v);
return s;
}
template<typename ContainerAllocator1, typename ContainerAllocator2>
bool operator==(const ::sas_robot_driver_franka::GripperState_<ContainerAllocator1> & lhs, const ::sas_robot_driver_franka::GripperState_<ContainerAllocator2> & rhs)
{
return lhs.width == rhs.width &&
lhs.max_width == rhs.max_width &&
lhs.is_grasped == rhs.is_grasped &&
lhs.temperature == rhs.temperature &&
lhs.duration_ms == rhs.duration_ms;
}
template<typename ContainerAllocator1, typename ContainerAllocator2>
bool operator!=(const ::sas_robot_driver_franka::GripperState_<ContainerAllocator1> & lhs, const ::sas_robot_driver_franka::GripperState_<ContainerAllocator2> & rhs)
{
return !(lhs == rhs);
}
} // namespace sas_robot_driver_franka
namespace ros
{
namespace message_traits
{
template <class ContainerAllocator>
struct IsMessage< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> >
: TrueType
{ };
template <class ContainerAllocator>
struct IsMessage< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> const>
: TrueType
{ };
template <class ContainerAllocator>
struct IsFixedSize< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> >
: TrueType
{ };
template <class ContainerAllocator>
struct IsFixedSize< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> const>
: TrueType
{ };
template <class ContainerAllocator>
struct HasHeader< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> >
: FalseType
{ };
template <class ContainerAllocator>
struct HasHeader< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> const>
: FalseType
{ };
template<class ContainerAllocator>
struct MD5Sum< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> >
{
static const char* value()
{
return "53f8669159aaded70b1783087f07679d";
}
static const char* value(const ::sas_robot_driver_franka::GripperState_<ContainerAllocator>&) { return value(); }
static const uint64_t static_value1 = 0x53f8669159aaded7ULL;
static const uint64_t static_value2 = 0x0b1783087f07679dULL;
};
template<class ContainerAllocator>
struct DataType< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> >
{
static const char* value()
{
return "sas_robot_driver_franka/GripperState";
}
static const char* value(const ::sas_robot_driver_franka::GripperState_<ContainerAllocator>&) { return value(); }
};
template<class ContainerAllocator>
struct Definition< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> >
{
static const char* value()
{
return "float32 width\n"
"float32 max_width\n"
"bool is_grasped\n"
"uint16 temperature\n"
"uint64 duration_ms\n"
;
}
static const char* value(const ::sas_robot_driver_franka::GripperState_<ContainerAllocator>&) { return value(); }
};
} // namespace message_traits
} // namespace ros
namespace ros
{
namespace serialization
{
template<class ContainerAllocator> struct Serializer< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> >
{
template<typename Stream, typename T> inline static void allInOne(Stream& stream, T m)
{
stream.next(m.width);
stream.next(m.max_width);
stream.next(m.is_grasped);
stream.next(m.temperature);
stream.next(m.duration_ms);
}
ROS_DECLARE_ALLINONE_SERIALIZER
}; // struct GripperState_
} // namespace serialization
} // namespace ros
namespace ros
{
namespace message_operations
{
template<class ContainerAllocator>
struct Printer< ::sas_robot_driver_franka::GripperState_<ContainerAllocator> >
{
template<typename Stream> static void stream(Stream& s, const std::string& indent, const ::sas_robot_driver_franka::GripperState_<ContainerAllocator>& v)
{
s << indent << "width: ";
Printer<float>::stream(s, indent + " ", v.width);
s << indent << "max_width: ";
Printer<float>::stream(s, indent + " ", v.max_width);
s << indent << "is_grasped: ";
Printer<uint8_t>::stream(s, indent + " ", v.is_grasped);
s << indent << "temperature: ";
Printer<uint16_t>::stream(s, indent + " ", v.temperature);
s << indent << "duration_ms: ";
Printer<uint64_t>::stream(s, indent + " ", v.duration_ms);
}
};
} // namespace message_operations
} // namespace ros
#endif // SAS_ROBOT_DRIVER_FRANKA_MESSAGE_GRIPPERSTATE_H

View File

@@ -1,123 +0,0 @@
// Generated by gencpp from file sas_robot_driver_franka/Move.msg
// DO NOT EDIT!
#ifndef SAS_ROBOT_DRIVER_FRANKA_MESSAGE_MOVE_H
#define SAS_ROBOT_DRIVER_FRANKA_MESSAGE_MOVE_H
#include <ros/service_traits.h>
#include <sas_robot_driver_franka/MoveRequest.h>
#include <sas_robot_driver_franka/MoveResponse.h>
namespace sas_robot_driver_franka
{
struct Move
{
typedef MoveRequest Request;
typedef MoveResponse Response;
Request request;
Response response;
typedef Request RequestType;
typedef Response ResponseType;
}; // struct Move
} // namespace sas_robot_driver_franka
namespace ros
{
namespace service_traits
{
template<>
struct MD5Sum< ::sas_robot_driver_franka::Move > {
static const char* value()
{
return "73e650ba1526b28d9e3f1be7ee33a441";
}
static const char* value(const ::sas_robot_driver_franka::Move&) { return value(); }
};
template<>
struct DataType< ::sas_robot_driver_franka::Move > {
static const char* value()
{
return "sas_robot_driver_franka/Move";
}
static const char* value(const ::sas_robot_driver_franka::Move&) { return value(); }
};
// service_traits::MD5Sum< ::sas_robot_driver_franka::MoveRequest> should match
// service_traits::MD5Sum< ::sas_robot_driver_franka::Move >
template<>
struct MD5Sum< ::sas_robot_driver_franka::MoveRequest>
{
static const char* value()
{
return MD5Sum< ::sas_robot_driver_franka::Move >::value();
}
static const char* value(const ::sas_robot_driver_franka::MoveRequest&)
{
return value();
}
};
// service_traits::DataType< ::sas_robot_driver_franka::MoveRequest> should match
// service_traits::DataType< ::sas_robot_driver_franka::Move >
template<>
struct DataType< ::sas_robot_driver_franka::MoveRequest>
{
static const char* value()
{
return DataType< ::sas_robot_driver_franka::Move >::value();
}
static const char* value(const ::sas_robot_driver_franka::MoveRequest&)
{
return value();
}
};
// service_traits::MD5Sum< ::sas_robot_driver_franka::MoveResponse> should match
// service_traits::MD5Sum< ::sas_robot_driver_franka::Move >
template<>
struct MD5Sum< ::sas_robot_driver_franka::MoveResponse>
{
static const char* value()
{
return MD5Sum< ::sas_robot_driver_franka::Move >::value();
}
static const char* value(const ::sas_robot_driver_franka::MoveResponse&)
{
return value();
}
};
// service_traits::DataType< ::sas_robot_driver_franka::MoveResponse> should match
// service_traits::DataType< ::sas_robot_driver_franka::Move >
template<>
struct DataType< ::sas_robot_driver_franka::MoveResponse>
{
static const char* value()
{
return DataType< ::sas_robot_driver_franka::Move >::value();
}
static const char* value(const ::sas_robot_driver_franka::MoveResponse&)
{
return value();
}
};
} // namespace service_traits
} // namespace ros
#endif // SAS_ROBOT_DRIVER_FRANKA_MESSAGE_MOVE_H

View File

@@ -1,205 +0,0 @@
// Generated by gencpp from file sas_robot_driver_franka/MoveRequest.msg
// DO NOT EDIT!
#ifndef SAS_ROBOT_DRIVER_FRANKA_MESSAGE_MOVEREQUEST_H
#define SAS_ROBOT_DRIVER_FRANKA_MESSAGE_MOVEREQUEST_H
#include <string>
#include <vector>
#include <memory>
#include <ros/types.h>
#include <ros/serialization.h>
#include <ros/builtin_message_traits.h>
#include <ros/message_operations.h>
namespace sas_robot_driver_franka
{
template <class ContainerAllocator>
struct MoveRequest_
{
typedef MoveRequest_<ContainerAllocator> Type;
MoveRequest_()
: width(0.0)
, speed(0.0) {
}
MoveRequest_(const ContainerAllocator& _alloc)
: width(0.0)
, speed(0.0) {
(void)_alloc;
}
typedef float _width_type;
_width_type width;
typedef float _speed_type;
_speed_type speed;
typedef boost::shared_ptr< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> > Ptr;
typedef boost::shared_ptr< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> const> ConstPtr;
}; // struct MoveRequest_
typedef ::sas_robot_driver_franka::MoveRequest_<std::allocator<void> > MoveRequest;
typedef boost::shared_ptr< ::sas_robot_driver_franka::MoveRequest > MoveRequestPtr;
typedef boost::shared_ptr< ::sas_robot_driver_franka::MoveRequest const> MoveRequestConstPtr;
// constants requiring out of line definition
template<typename ContainerAllocator>
std::ostream& operator<<(std::ostream& s, const ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> & v)
{
ros::message_operations::Printer< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> >::stream(s, "", v);
return s;
}
template<typename ContainerAllocator1, typename ContainerAllocator2>
bool operator==(const ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator1> & lhs, const ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator2> & rhs)
{
return lhs.width == rhs.width &&
lhs.speed == rhs.speed;
}
template<typename ContainerAllocator1, typename ContainerAllocator2>
bool operator!=(const ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator1> & lhs, const ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator2> & rhs)
{
return !(lhs == rhs);
}
} // namespace sas_robot_driver_franka
namespace ros
{
namespace message_traits
{
template <class ContainerAllocator>
struct IsMessage< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> >
: TrueType
{ };
template <class ContainerAllocator>
struct IsMessage< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> const>
: TrueType
{ };
template <class ContainerAllocator>
struct IsFixedSize< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> >
: TrueType
{ };
template <class ContainerAllocator>
struct IsFixedSize< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> const>
: TrueType
{ };
template <class ContainerAllocator>
struct HasHeader< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> >
: FalseType
{ };
template <class ContainerAllocator>
struct HasHeader< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> const>
: FalseType
{ };
template<class ContainerAllocator>
struct MD5Sum< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> >
{
static const char* value()
{
return "b2d4f46fe020a06d64128c90310c767d";
}
static const char* value(const ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator>&) { return value(); }
static const uint64_t static_value1 = 0xb2d4f46fe020a06dULL;
static const uint64_t static_value2 = 0x64128c90310c767dULL;
};
template<class ContainerAllocator>
struct DataType< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> >
{
static const char* value()
{
return "sas_robot_driver_franka/MoveRequest";
}
static const char* value(const ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator>&) { return value(); }
};
template<class ContainerAllocator>
struct Definition< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> >
{
static const char* value()
{
return "float32 width\n"
"float32 speed\n"
;
}
static const char* value(const ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator>&) { return value(); }
};
} // namespace message_traits
} // namespace ros
namespace ros
{
namespace serialization
{
template<class ContainerAllocator> struct Serializer< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> >
{
template<typename Stream, typename T> inline static void allInOne(Stream& stream, T m)
{
stream.next(m.width);
stream.next(m.speed);
}
ROS_DECLARE_ALLINONE_SERIALIZER
}; // struct MoveRequest_
} // namespace serialization
} // namespace ros
namespace ros
{
namespace message_operations
{
template<class ContainerAllocator>
struct Printer< ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator> >
{
template<typename Stream> static void stream(Stream& s, const std::string& indent, const ::sas_robot_driver_franka::MoveRequest_<ContainerAllocator>& v)
{
s << indent << "width: ";
Printer<float>::stream(s, indent + " ", v.width);
s << indent << "speed: ";
Printer<float>::stream(s, indent + " ", v.speed);
}
};
} // namespace message_operations
} // namespace ros
#endif // SAS_ROBOT_DRIVER_FRANKA_MESSAGE_MOVEREQUEST_H

View File

@@ -1,195 +0,0 @@
// Generated by gencpp from file sas_robot_driver_franka/MoveResponse.msg
// DO NOT EDIT!
#ifndef SAS_ROBOT_DRIVER_FRANKA_MESSAGE_MOVERESPONSE_H
#define SAS_ROBOT_DRIVER_FRANKA_MESSAGE_MOVERESPONSE_H
#include <string>
#include <vector>
#include <memory>
#include <ros/types.h>
#include <ros/serialization.h>
#include <ros/builtin_message_traits.h>
#include <ros/message_operations.h>
namespace sas_robot_driver_franka
{
template <class ContainerAllocator>
struct MoveResponse_
{
typedef MoveResponse_<ContainerAllocator> Type;
MoveResponse_()
: success(false) {
}
MoveResponse_(const ContainerAllocator& _alloc)
: success(false) {
(void)_alloc;
}
typedef uint8_t _success_type;
_success_type success;
typedef boost::shared_ptr< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> > Ptr;
typedef boost::shared_ptr< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> const> ConstPtr;
}; // struct MoveResponse_
typedef ::sas_robot_driver_franka::MoveResponse_<std::allocator<void> > MoveResponse;
typedef boost::shared_ptr< ::sas_robot_driver_franka::MoveResponse > MoveResponsePtr;
typedef boost::shared_ptr< ::sas_robot_driver_franka::MoveResponse const> MoveResponseConstPtr;
// constants requiring out of line definition
template<typename ContainerAllocator>
std::ostream& operator<<(std::ostream& s, const ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> & v)
{
ros::message_operations::Printer< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> >::stream(s, "", v);
return s;
}
template<typename ContainerAllocator1, typename ContainerAllocator2>
bool operator==(const ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator1> & lhs, const ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator2> & rhs)
{
return lhs.success == rhs.success;
}
template<typename ContainerAllocator1, typename ContainerAllocator2>
bool operator!=(const ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator1> & lhs, const ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator2> & rhs)
{
return !(lhs == rhs);
}
} // namespace sas_robot_driver_franka
namespace ros
{
namespace message_traits
{
template <class ContainerAllocator>
struct IsMessage< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> >
: TrueType
{ };
template <class ContainerAllocator>
struct IsMessage< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> const>
: TrueType
{ };
template <class ContainerAllocator>
struct IsFixedSize< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> >
: TrueType
{ };
template <class ContainerAllocator>
struct IsFixedSize< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> const>
: TrueType
{ };
template <class ContainerAllocator>
struct HasHeader< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> >
: FalseType
{ };
template <class ContainerAllocator>
struct HasHeader< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> const>
: FalseType
{ };
template<class ContainerAllocator>
struct MD5Sum< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> >
{
static const char* value()
{
return "358e233cde0c8a8bcfea4ce193f8fc15";
}
static const char* value(const ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator>&) { return value(); }
static const uint64_t static_value1 = 0x358e233cde0c8a8bULL;
static const uint64_t static_value2 = 0xcfea4ce193f8fc15ULL;
};
template<class ContainerAllocator>
struct DataType< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> >
{
static const char* value()
{
return "sas_robot_driver_franka/MoveResponse";
}
static const char* value(const ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator>&) { return value(); }
};
template<class ContainerAllocator>
struct Definition< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> >
{
static const char* value()
{
return "bool success\n"
;
}
static const char* value(const ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator>&) { return value(); }
};
} // namespace message_traits
} // namespace ros
namespace ros
{
namespace serialization
{
template<class ContainerAllocator> struct Serializer< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> >
{
template<typename Stream, typename T> inline static void allInOne(Stream& stream, T m)
{
stream.next(m.success);
}
ROS_DECLARE_ALLINONE_SERIALIZER
}; // struct MoveResponse_
} // namespace serialization
} // namespace ros
namespace ros
{
namespace message_operations
{
template<class ContainerAllocator>
struct Printer< ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator> >
{
template<typename Stream> static void stream(Stream& s, const std::string& indent, const ::sas_robot_driver_franka::MoveResponse_<ContainerAllocator>& v)
{
s << indent << "success: ";
Printer<uint8_t>::stream(s, indent + " ", v.success);
}
};
} // namespace message_operations
} // namespace ros
#endif // SAS_ROBOT_DRIVER_FRANKA_MESSAGE_MOVERESPONSE_H

View File

@@ -0,0 +1,139 @@
/*
# Copyright (c) 2023 Juan Jose Quiroz Omana
#
# This file is part of sas_robot_driver_franka.
#
# sas_robot_driver_franka is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# sas_robot_driver_franka is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with sas_robot_driver. If not, see <https://www.gnu.org/licenses/>.
#
# ################################################################
#
# Author: Juan Jose Quiroz Omana, email: juanjqogm@gmail.com
#
# ################################################################
#
# Contributors:
# 1. Juan Jose Quiroz Omana (juanjqogm@gmail.com)
# - Adapted from sas_robot_driver_denso.cpp
# (https://github.com/SmartArmStack/sas_robot_driver_denso/blob/master/src/sas_robot_driver_denso.cpp)
#
# ################################################################
*/
#pragma once
#include <exception>
#include <tuple>
#include <atomic>
#include <vector>
#include <memory>
#include <dqrobotics/DQ.h>
#include <sas_core/sas_clock.hpp>
// #include <dqrobotics/interfaces/vrep/DQ_VrepRobot.h>
#include <dqrobotics/interfaces/vrep/DQ_VrepInterface.h>
#include <dqrobotics/interfaces/json11/DQ_JsonReader.h>
// #include <dqrobotics/robot_modeling/DQ_SerialManipulatorDH.h>
#include <thread>
#include <atomic>
#include <sas_robot_driver/sas_robot_driver_server.hpp>
#include <sas_robot_driver/sas_robot_driver_client.hpp>
#define VIRTUAL_ROBOT_SIMULATION_SAMPLING_TIME_SEC 0.002 // 2ms, 500Hz
#define REAL_ROBOT_INTERFACE_INIT_TIMEOUT_COUNT 500
using namespace DQ_robotics;
using namespace Eigen;
namespace qros
{
struct RobotDriverCoppeliaConfiguration
{
double thread_sampling_time_sec; // frontend vrep update rate
int vrep_port;
std::string vrep_ip;
std::vector<std::string> vrep_joint_names;
bool vrep_dynamically_enabled = false;
std::string robot_mode;
bool using_real_robot;
std::string robot_topic_prefix;
std::string robot_parameter_file_path;
// VectorXd q_min;
// VectorXd q_max;
};
class RobotDriverCoppelia
{
private:
enum ControlMode{
Position=0,
Velocity
};
RobotDriverCoppeliaConfiguration configuration_;
std::shared_ptr<Node> node_sptr_;
sas::Clock clock_;
std::atomic_bool* break_loops_;
bool _should_shutdown() const {return (*break_loops_);}
ControlMode robot_mode_;
std::shared_ptr<DQ_VrepInterface> vi_;
std::shared_ptr<sas::RobotDriverClient> real_robot_interface_ = nullptr;
std::shared_ptr<sas::RobotDriverServer> robot_provider_ = nullptr;
// backend thread for simulaton
/**
* Current simulation mechanism is not accounting for any robot dynamics, just the joint limits
*/
std::thread velocity_control_simulation_thread_;
VectorXd simulated_joint_positions_;
VectorXd simulated_joint_velocities_;
void start_simulation_thread(); // thread entry point
void _velocity_control_simulation_thread_main();
std::atomic_bool simulation_thread_started_{false};
bool initialized_ = false;
inline void _assert_initialized() const{
if (!initialized_){throw std::runtime_error("[RobotDriverCoppelia] Robot driver not initialized");}
}
inline void _assert_is_alive() const{
if(!configuration_.using_real_robot && !simulation_thread_started_){throw std::runtime_error("[RobotDriverCoppelia] Robot Simulation is not alive");}
}
void _start_control_loop();
protected:
inline void _update_vrep_position(const VectorXd &joint_positions, const bool& force_update=false) const;
inline void _update_vrep_velocity(const VectorXd & joint_velocity) const;
public:
RobotDriverCoppelia(const RobotDriverCoppelia&)=delete;
RobotDriverCoppelia()=delete;
~RobotDriverCoppelia();
RobotDriverCoppelia(const std::shared_ptr<Node> &node_sptr, const RobotDriverCoppeliaConfiguration& configuration, std::atomic_bool* break_loops);
int start_control_loop(); // public entry point
void connect();
void disconnect();
void initialize();
void deinitialize();
std::tuple<VectorXd, VectorXd> joint_limits_;
};
}

View File

@@ -32,13 +32,13 @@
#pragma once #pragma once
#include <array> #include <array>
#include <Eigen/Core> #include <eigen3/Eigen/Core>
#include <Eigen/Dense> #include <eigen3/Eigen/Dense>
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <dqrobotics/solvers/DQ_QPOASESSolver.h> #include <dqrobotics/solvers/DQ_QPOASESSolver.h>
#include <memory> #include <memory>
#include "constraints_manager.h" #include <constraints_manager.h>
using namespace DQ_robotics; using namespace DQ_robotics;

View File

@@ -4,8 +4,8 @@
#include <array> #include <array>
#include <Eigen/Core> #include <eigen3/Eigen/Core>
#include <Eigen/Dense> #include <eigen3/Eigen/Dense>
#include <franka/control_types.h> #include <franka/control_types.h>
#include <franka/duration.h> #include <franka/duration.h>
#include <franka/robot.h> #include <franka/robot.h>

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include <array> #include <array>
#include <Eigen/Core> #include <eigen3/Eigen/Core>
#include <Eigen/Dense> #include <eigen3/Eigen/Dense>
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <dqrobotics/solvers/DQ_QPOASESSolver.h> #include <dqrobotics/solvers/DQ_QPOASESSolver.h>

View File

@@ -42,21 +42,26 @@
// #define IN_TESTING // #define IN_TESTING
// #include <sas_robot_driver/sas_robot_driver.h> // #include <sas_robot_driver/sas_robot_driver.h>
#include <sas_clock/sas_clock.h> #include <sas_core/sas_clock.hpp>
#include <ros/ros.h>
#include <ros/service.h>
#include <sas_robot_driver_franka/Grasp.h>
#include <sas_robot_driver_franka/Move.h>
#include <sas_robot_driver_franka/GripperState.h>
#ifdef IN_TESTING
#include <Move.h> // dummy include
#include <Grasp.h> // dummy include
#include <GripperState.h> // dummy include
#endif
#include <rclcpp/service.hpp>
#include <rclcpp/rclcpp.hpp>
#ifdef IN_TESTING
#include "local/srv/grasp.hpp"
#include "local/srv/move.hpp"
#include "local/msg/gripper_state.hpp"
#else
#include <sas_robot_driver_franka_interfaces/srv/grasp.hpp>
#include <sas_robot_driver_franka_interfaces/srv/move.hpp>
#include <sas_robot_driver_franka_interfaces/msg/gripper_state.hpp>
#endif
#include <std_srvs/srv/trigger.hpp>
// using namespace DQ_robotics; // using namespace DQ_robotics;
// using namespace Eigen; // using namespace Eigen;
using namespace rclcpp;
using namespace sas_robot_driver_franka_interfaces;
namespace qros { namespace qros {
@@ -64,7 +69,8 @@ namespace qros {
struct EffectorDriverFrankaHandConfiguration struct EffectorDriverFrankaHandConfiguration
{ {
std::string robot_ip; std::string robot_ip;
int thread_sampeling_time_ns = 1e8; // 10Hz bool initialize_with_homing = true;
double thread_sampeling_time_s = 1e8; // 10Hz
double default_force = 3.0; double default_force = 3.0;
double default_speed = 0.1; double default_speed = 0.1;
double default_epsilon_inner = 0.005; double default_epsilon_inner = 0.005;
@@ -75,7 +81,7 @@ class EffectorDriverFrankaHand{
private: private:
std::string driver_node_prefix_; std::string driver_node_prefix_;
EffectorDriverFrankaHandConfiguration configuration_; EffectorDriverFrankaHandConfiguration configuration_;
ros::NodeHandle& node_handel_; std::shared_ptr<Node> node_;
std::shared_ptr<franka::Gripper> gripper_sptr_; std::shared_ptr<franka::Gripper> gripper_sptr_;
@@ -88,17 +94,30 @@ private:
void _gripper_status_loop(); void _gripper_status_loop();
std::thread status_loop_thread_; std::thread status_loop_thread_;
std::atomic_bool status_loop_running_{false}; std::atomic_bool status_loop_running_{false};
ros::Publisher gripper_status_publisher_;
Publisher<msg::GripperState>::SharedPtr gripper_status_publisher_;
std::mutex gripper_in_use_; std::mutex gripper_in_use_;
ros::ServiceServer grasp_server_; Service<srv::Grasp>::SharedPtr grasp_srv_;
ros::ServiceServer move_server_; Service<srv::Move>::SharedPtr move_srv_;
Service<std_srvs::srv::Trigger>::SharedPtr homing_srv_;
public: public:
bool _grasp_srv_callback(sas_robot_driver_franka::Grasp::Request& req, sas_robot_driver_franka::Grasp::Response& res); bool _grasp_srv_callback(
const std::shared_ptr<srv::Grasp::Request> &req,
std::shared_ptr<srv::Grasp::Response> res
);
bool _move_srv_callback(sas_robot_driver_franka::Move::Request& req, sas_robot_driver_franka::Move::Response& res); bool _move_srv_callback(
const std::shared_ptr<srv::Move::Request> &req,
std::shared_ptr<srv::Move::Response> res
);
bool _home_srv_callback(
const std::shared_ptr<std_srvs::srv::Trigger::Request> &req,
std::shared_ptr<std_srvs::srv::Trigger::Response> res
);
EffectorDriverFrankaHand(const EffectorDriverFrankaHand&)=delete; EffectorDriverFrankaHand(const EffectorDriverFrankaHand&)=delete;
EffectorDriverFrankaHand()=delete; EffectorDriverFrankaHand()=delete;
@@ -107,7 +126,7 @@ public:
EffectorDriverFrankaHand( EffectorDriverFrankaHand(
const std::string &driver_node_prefix, const std::string &driver_node_prefix,
const EffectorDriverFrankaHandConfiguration& configuration, const EffectorDriverFrankaHandConfiguration& configuration,
ros::NodeHandle& node_handel, std::shared_ptr<Node> node,
std::atomic_bool* break_loops); std::atomic_bool* break_loops);
void start_control_loop(); void start_control_loop();

View File

@@ -40,12 +40,12 @@
#include <franka/robot.h> #include <franka/robot.h>
#include <franka/gripper.h> #include <franka/gripper.h>
#include <franka/exception.h> #include <franka/exception.h>
#include "generator/motion_generator.h" #include <sas_robot_driver_franka/generator/motion_generator.h>
#include <sas_robot_driver_franka/generator/quadratic_program_motion_generator.h>
#include <sas_robot_driver_franka/generator/custom_motion_generation.h>
#include <thread> #include <thread>
#include "generator/quadratic_program_motion_generator.h"
#include <dqrobotics/robots/FrankaEmikaPandaRobot.h> #include <dqrobotics/robots/FrankaEmikaPandaRobot.h>
#include <atomic> #include <atomic>
#include "generator/custom_motion_generation.h"
using namespace DQ_robotics; using namespace DQ_robotics;
using namespace Eigen; using namespace Eigen;

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
/* /*
# Copyright (c) 2023 Juan Jose Quiroz Omana # Copyright (c) 2024 Quenitin Lin
# #
# This file is part of sas_robot_driver_franka. # This file is part of sas_robot_driver_franka.
# #
@@ -28,63 +28,66 @@
# #
# ################################################################ # ################################################################
*/ */
#include <ros/ros.h>
#include <ros/node_handle.h> #include <rclcpp/rclcpp.hpp>
#include <sas_common/sas_common.h> #include <rclcpp/node.hpp>
#include <sas_conversions/sas_conversions.h> // #include <sas_common/sas_common.hpp>
#include <geometry_msgs/WrenchStamped.h> #include <sas_conversions/sas_conversions.hpp>
#include <geometry_msgs/Transform.h> #include <geometry_msgs/msg/wrench_stamped.hpp>
#include <geometry_msgs/TransformStamped.h> #include <geometry_msgs/msg/transform.hpp>
#include <geometry_msgs/msg/transform_stamped.hpp>
#include <tf2_ros/transform_listener.h> #include <tf2_ros/transform_listener.h>
#include <tf2_geometry_msgs/tf2_geometry_msgs.h> #include <tf2_ros/buffer.h>
#include <geometry_msgs/Pose.h> #include <tf2/time.h>
#include <std_msgs/Header.h> // #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
#include <geometry_msgs/msg/pose.hpp>
#include <std_msgs/msg/header.hpp>
#include <dqrobotics/DQ.h> #include <dqrobotics/DQ.h>
#define BUFFER_DURATION_DEFAULT_S 2.0 // 2 second #define BUFFER_DURATION_DEFAULT_S 2.0 // 2 second
using namespace rclcpp;
namespace qros { namespace qros {
using namespace DQ_robotics; using namespace DQ_robotics;
class RobotDynamicInterface { class RobotDynamicsClient {
private: private:
unsigned int seq_ = 0; std::shared_ptr<Node> node_;
std::string node_prefix_; std::string topic_prefix_;
std::string child_frame_id_; std::string child_frame_id_;
std::string parent_frame_id_; std::string parent_frame_id_;
ros::Subscriber subscriber_cartesian_stiffness_; Subscription<geometry_msgs::msg::WrenchStamped>::SharedPtr subscriber_cartesian_stiffness_;
tf2_ros::Buffer tf_buffer_; std::unique_ptr<tf2_ros::Buffer> tf_buffer_;
tf2_ros::TransformListener tf_listener_; std::shared_ptr<tf2_ros::TransformListener> tf_listener_;
static geometry_msgs::Transform _dq_to_geometry_msgs_transform(const DQ& pose) ; static geometry_msgs::msg::Transform _dq_to_geometry_msgs_transform(const DQ& pose) ;
Vector3d last_stiffness_force_; Vector3d last_stiffness_force_;
Vector3d last_stiffness_torque_; Vector3d last_stiffness_torque_;
DQ last_stiffness_frame_pose_; DQ last_stiffness_frame_pose_;
void _callback_cartesian_stiffness(const geometry_msgs::WrenchStampedConstPtr &msg); void _callback_cartesian_stiffness(const geometry_msgs::msg::WrenchStamped &msg);
static DQ _geometry_msgs_transform_to_dq(const geometry_msgs::Transform& transform); static DQ _geometry_msgs_transform_to_dq(const geometry_msgs::msg::Transform& transform);
public: public:
RobotDynamicInterface() = delete; RobotDynamicsClient() = delete;
RobotDynamicInterface(const RobotDynamicInterface&) = delete; RobotDynamicsClient(const RobotDynamicsClient&) = delete;
#ifdef BUILD_PYBIND // #ifdef BUILD_PYBIND
explicit RobotDynamicInterface(const std::string& node_prefix):RobotDynamicInterface(sas::common::get_static_node_handle(),node_prefix){} // explicit RobotDynamicsClient(const std::string& node_prefix):RobotDynamicsClient(sas::common::get_static_node_handle(),node_prefix){}
#endif // #endif
explicit RobotDynamicInterface(ros::NodeHandle& nodehandle, const std::string& node_prefix=ros::this_node::getName()); explicit RobotDynamicsClient(const std::shared_ptr<Node> &node, const std::string& topic_prefix="GET_FROM_NODE");
RobotDynamicInterface(ros::NodeHandle& publisher_nodehandle, ros::NodeHandle& subscriber_nodehandle, const std::string& node_prefix=ros::this_node::getName());
VectorXd get_stiffness_force(); VectorXd get_stiffness_force();
VectorXd get_stiffness_torque(); VectorXd get_stiffness_torque();
DQ get_stiffness_frame_pose(); DQ get_stiffness_frame_pose();
bool is_enabled() const; bool is_enabled() const;
std::string get_topic_prefix() const {return node_prefix_;} std::string get_topic_prefix() const {return topic_prefix_;}
}; };

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
/* /*
# Copyright (c) 2023 Juan Jose Quiroz Omana # Copyright (c) 2024 Quenitin Lin
# #
# This file is part of sas_robot_driver_franka. # This file is part of sas_robot_driver_franka.
# #
@@ -28,60 +28,60 @@
# #
# ################################################################ # ################################################################
*/ */
#include <ros/ros.h> #include <rclcpp/rclcpp.hpp>
#include <ros/node_handle.h> #include <rclcpp/node.hpp>
#include <sas_common/sas_common.h> // #include <sas_common/sas_common.hpp>
#include <sas_conversions/sas_conversions.h> #include <sas_conversions/sas_conversions.hpp>
#include <geometry_msgs/WrenchStamped.h> #include <geometry_msgs/msg/wrench_stamped.hpp>
#include <geometry_msgs/Transform.h> #include <geometry_msgs/msg/transform.hpp>
#include <geometry_msgs/TransformStamped.h> #include <geometry_msgs/msg/transform_stamped.hpp>
#include <tf2_ros/transform_broadcaster.h> #include <tf2_ros/transform_broadcaster.h>
#include <tf2_ros//static_transform_broadcaster.h> #include <tf2_ros//static_transform_broadcaster.h>
#include <tf2_geometry_msgs/tf2_geometry_msgs.h> #include <geometry_msgs/msg/pose.hpp>
#include <geometry_msgs/Pose.h> #include <std_msgs/msg/header.hpp>
#include <std_msgs/Header.h>
#include <dqrobotics/DQ.h> #include <dqrobotics/DQ.h>
#define REDUCE_TF_PUBLISH_RATE 10 #define REDUCE_TF_PUBLISH_RATE 10
#define WORLD_FRAME_ID "world" #define WORLD_FRAME_ID "world"
using namespace rclcpp;
namespace qros { namespace qros {
using namespace DQ_robotics; using namespace DQ_robotics;
class RobotDynamicProvider { class RobotDynamicsServer {
private: private:
unsigned int seq_ = 0; unsigned int seq_ = 0;
std::shared_ptr<Node> node_;
std::string node_prefix_; std::string topic_prefix_;
std::string child_frame_id_; std::string child_frame_id_;
std::string parent_frame_id_; std::string parent_frame_id_;
ros::Publisher publisher_cartesian_stiffness_; rclcpp::Publisher<geometry_msgs::msg::WrenchStamped>::SharedPtr publisher_cartesian_stiffness_;
tf2_ros::TransformBroadcaster tf_broadcaster_; std::shared_ptr<tf2_ros::TransformBroadcaster> tf_broadcaster_;
tf2_ros::StaticTransformBroadcaster static_base_tf_broadcaster_; std::shared_ptr<tf2_ros::StaticTransformBroadcaster> static_base_tf_broadcaster_;
DQ world_to_base_tf_; DQ world_to_base_tf_ = DQ(0);
static geometry_msgs::Transform _dq_to_geometry_msgs_transform(const DQ& pose); static geometry_msgs::msg::Transform _dq_to_geometry_msgs_transform(const DQ& pose);
void _publish_base_static_tf(); void _publish_base_static_tf();
public: public:
RobotDynamicProvider() = delete; RobotDynamicsServer() = delete;
RobotDynamicProvider(const RobotDynamicProvider&) = delete; RobotDynamicsServer(const RobotDynamicsServer&) = delete;
#ifdef BUILD_PYBIND // #ifdef BUILD_PYBIND
explicit RobotDynamicProvider(const std::string& node_prefix):RobotDynamicProvider(sas::common::get_static_node_handle(),node_prefix){} // explicit RobotDynamicsServer(const std::string& node_prefix):RobotDynamicsServer(sas::common::get_static_node_handle(),node_prefix){}
#endif // #endif
explicit RobotDynamicProvider(ros::NodeHandle& nodehandle, const std::string& node_prefix=ros::this_node::getName()); explicit RobotDynamicsServer(const std::shared_ptr<Node> &node, const std::string& topic_prefix="GET_FROM_NODE");
RobotDynamicProvider(ros::NodeHandle& publisher_nodehandle, ros::NodeHandle& subscriber_nodehandle, const std::string& node_prefix=ros::this_node::getName());
void publish_stiffness(const DQ& base_to_stiffness, const Vector3d& force, const Vector3d& torque); void publish_stiffness(const DQ& base_to_stiffness, const Vector3d& force, const Vector3d& torque);
void set_world_to_base_tf(const DQ& world_to_base_tf); void set_world_to_base_tf(const DQ& world_to_base_tf);
bool is_enabled() const; bool is_enabled() const;
std::string get_topic_prefix() const {return node_prefix_;} std::string get_topic_prefix() const {return topic_prefix_;}
}; };

View File

@@ -40,10 +40,10 @@
#include <dqrobotics/DQ.h> #include <dqrobotics/DQ.h>
#include <sas_robot_driver/sas_robot_driver.h> #include <sas_core/sas_robot_driver.hpp>
#include "robot_interface_franka.h" #include <sas_robot_driver_franka/interfaces/robot_interface_franka.hpp>
#include <ros/common.h> #include <rclcpp/rclcpp.hpp>
#include <robot_dynamic/qros_robot_dynamics_provider.h> #include <sas_robot_driver_franka/robot_dynamic/qros_robot_dynamics_server.hpp>
using namespace DQ_robotics; using namespace DQ_robotics;
using namespace Eigen; using namespace Eigen;
@@ -64,14 +64,16 @@ struct RobotDriverFrankaConfiguration
}; };
class RobotDriverFranka: public RobotDriver class RobotDriverFranka: public sas::RobotDriver
{ {
private: private:
std::shared_ptr<Node> node_;
RobotDriverFrankaConfiguration configuration_; RobotDriverFrankaConfiguration configuration_;
std::shared_ptr<RobotInterfaceFranka> robot_driver_interface_sptr_ = nullptr; std::shared_ptr<RobotInterfaceFranka> robot_driver_interface_sptr_ = nullptr;
qros::RobotDynamicProvider* robot_dynamic_provider_; std::shared_ptr<qros::RobotDynamicsServer> robot_dynamic_provider_sptr_;
//Joint positions //Joint positions
VectorXd joint_positions_; VectorXd joint_positions_;
@@ -98,7 +100,8 @@ public:
~RobotDriverFranka(); ~RobotDriverFranka();
RobotDriverFranka( RobotDriverFranka(
qros::RobotDynamicProvider* robot_dynamic_provider, const std::shared_ptr<Node> &node,
const std::shared_ptr<qros::RobotDynamicsServer> &robot_dynamic_provider,
const RobotDriverFrankaConfiguration& configuration, const RobotDriverFrankaConfiguration& configuration,
std::atomic_bool* break_loops std::atomic_bool* break_loops
); );
@@ -110,7 +113,7 @@ public:
VectorXd get_joint_velocities() override; VectorXd get_joint_velocities() override;
void set_target_joint_velocities(const VectorXd& desired_joint_velocities) override; void set_target_joint_velocities(const VectorXd& desired_joint_velocities) override;
VectorXd get_joint_forces() override; VectorXd get_joint_torques() override;
void connect() override; void connect() override;
void disconnect() override; void disconnect() override;

View File

@@ -0,0 +1,45 @@
from launch import LaunchDescription
from launch_ros.actions import Node
import os
def generate_launch_description():
return LaunchDescription([
Node(
package='sas_robot_driver_franka',
executable='sas_robot_driver_franka_node',
name='arm3',
parameters=[{
"robot_ip_address": "172.16.0.4",
"thread_sampling_time_sec": 0.004,
# "thread_sampling_time_nsec": 4000000,
"q_min": [-2.3093, -1.5133, -2.4937, -2.7478, -2.4800, 0.8521, -2.6895],
"q_max": [2.3093, 1.5133, 2.4937, -0.4461, 2.4800, 4.2094, 2.6895],
"force_upper_limits_scaling_factor": 4.0,
"upper_torque_threshold": [40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0],
"upper_force_threshold": [40.0, 40.0, 40.0, 40.0, 40.0, 40.0],
"robot_mode": "VelocityControl",
"robot_parameter_file_path": os.environ["ROBOT_3_JSON_PATH"]
}],
output="screen"
),
Node(
package='sas_robot_driver_franka',
executable='sas_robot_driver_franka_coppelia_node',
name='arm3_coppelia',
parameters=[{
"thread_sampling_time_sec": 0.008,
"vrep_ip": os.environ["VREP_IP"],
"vrep_port": 20012,
"vrep_dynamically_enabled": True,
"using_real_robot": True,
"vrep_joint_names": ["Franka_joint1#1", "Franka_joint2#1", "Franka_joint3#1", "Franka_joint4#1",
"Franka_joint5#1", "Franka_joint6#1", "Franka_joint7#1"],
"robot_topic_prefix": "/arm3",
"robot_mode": "VelocityControl",
"robot_parameter_file_path": os.environ["ROBOT_3_JSON_PATH"]
}],
output="screen"
),
])

View File

@@ -0,0 +1,24 @@
from launch import LaunchDescription
from launch_ros.actions import Node
import os
def generate_launch_description():
return LaunchDescription([
Node(
package='sas_robot_driver_franka',
executable='sas_robot_driver_franka_hand_node',
name='arm3_hand',
parameters=[{
"robot_ip_address": "172.16.0.2",
# "thread_sampling_time_nsec": 20000000, # 20ms , 50Hz
"thread_sampling_time_sec": 0.02,
"default_force": 2.0,
"default_speed": 0.07,
"default_epsilon_inner": 0.007,
"default_epsilon_outer": 0.007,
}],
output="screen"
),
])

View File

@@ -0,0 +1,27 @@
from launch import LaunchDescription
from launch_ros.actions import Node
import os
def generate_launch_description():
return LaunchDescription([
Node(
package='sas_robot_driver_franka',
executable='sas_robot_driver_franka_coppelia_node',
name='arm3_coppelia',
parameters=[{
"thread_sampling_time_sec": 0.008,
"vrep_ip": os.environ["VREP_IP"],
"vrep_port": 20012,
"vrep_dynamically_enabled": True,
"using_real_robot": False,
"vrep_joint_names": ["Franka_joint1#1", "Franka_joint2#1", "Franka_joint3#1", "Franka_joint4#1",
"Franka_joint5#1", "Franka_joint6#1", "Franka_joint7#1"],
"robot_topic_prefix": "/arm3",
"robot_mode": "VelocityControl",
"robot_parameter_file_path": os.environ["ROBOT_3_JSON_PATH"]
}],
output="screen"
),
])

View File

@@ -1,5 +0,0 @@
float32 width
float32 max_width
bool is_grasped
uint16 temperature
uint64 duration_ms

View File

@@ -1,94 +1,32 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<package format="2"> <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>sas_robot_driver_franka</name> <name>sas_robot_driver_franka</name>
<version>0.0.0</version> <version>0.0.0</version>
<description>The sas_driver_franka package</description> <description>The sas_driver_franka package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="moonshot@todo.todo">moonshot</maintainer> <maintainer email="moonshot@todo.todo">moonshot</maintainer>
<license>LGPLv3</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<!-- One license tag required, multiple allowed, one license per tag --> <depend>rclcpp</depend>
<!-- Commonly used license strings: --> <depend>rclpy</depend>
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 --> <depend>tf2_ros</depend>
<license>TODO</license> <depend>tf2</depend>
<depend>std_msgs</depend>
<depend>sas_core</depend>
<depend>sas_robot_driver</depend>
<depend>sas_common</depend>
<depend>sas_robot_driver_franka_interface</depend>
<!-- Url tags are optional, but multiple are allowed, one per tag --> <test_depend>ament_lint_auto</test_depend>
<!-- Optional attribute type can be: website, bugtracker, or repository --> <test_depend>ament_lint_common</test_depend>
<!-- Example: --> <test_depend>ament_copyright</test_depend>
<!-- <url type="website">http://wiki.ros.org/sas_driver_franka</url> --> <test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<!-- Author tags are optional, multiple are allowed, one per tag -->
<!-- Authors do not have to be maintainers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<!-- The *depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
<!-- <depend>roscpp</depend> -->
<!-- Note that this is equivalent to the following: -->
<!-- <build_depend>roscpp</build_depend> -->
<!-- <exec_depend>roscpp</exec_depend> -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use build_export_depend for packages you need in order to build against this package: -->
<!-- <build_export_depend>message_generation</build_export_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use exec_depend for packages you need at runtime: -->
<!-- <exec_depend>message_runtime</exec_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<!-- Use doc_depend for packages you need only for building documentation: -->
<!-- <doc_depend>doxygen</doc_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>tf2_ros</build_depend>
<build_depend>tf2</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>sas_clock</build_depend>
<build_depend>sas_robot_driver</build_depend>
<build_depend>sas_common</build_depend>
<build_depend>sas_patient_side_manager</build_depend>
<build_depend>pybind11_catkin</build_depend>
<build_depend>message_generation</build_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>rospy</build_export_depend>
<build_export_depend>tf2_ros</build_export_depend>
<build_export_depend>tf2</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<build_export_depend>sas_clock</build_export_depend>
<build_export_depend>sas_robot_driver</build_export_depend>
<build_export_depend>sas_common</build_export_depend>
<build_export_depend>sas_patient_side_manager</build_export_depend>
<build_export_depend>pybind11_catkin</build_export_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>tf2_ros</exec_depend>
<exec_depend>tf2</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>sas_clock</exec_depend>
<exec_depend>sas_robot_driver</exec_depend>
<exec_depend>sas_common</exec_depend>
<exec_depend>sas_patient_side_manager</exec_depend>
<exec_depend>message_runtime</exec_depend>
<!-- The export tag contains other, unspecified, tags -->
<export> <export>
<!-- Other tools can request additional information be placed here --> <build_type>ament_cmake</build_type>
</export> </export>
</package> </package>

View File

@@ -7,7 +7,7 @@
#include <QMainWindow> #include <QMainWindow>
#include "qspinbox.h" #include "qspinbox.h"
#include "robot_interface_franka.h" #include <sas_robot_driver_franka/interfaces/robot_interface_franka.hpp>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } namespace Ui { class MainWindow; }

View File

@@ -0,0 +1,229 @@
"""
"""
from typing import Union
from sas_robot_driver_franka._qros_franka_robot_dynamics_py import RobotDynamicsClient, RobotDynamicsServer
import rclpy
from rclpy.node import Node
from rclpy.client import Client
from sas_common import rclcpp_init, rclcpp_Node, rclcpp_spin_some, rclcpp_shutdown
from sas_robot_driver_franka_interfaces.srv import Move, Grasp
from std_srvs.srv import Trigger
from sas_robot_driver_franka_interfaces.msg import GripperState
import os
import threading
from queue import Queue
import time
import struct
MOVE_TOPIC_SUFFIX = "move"
GRASP_TOPIC_SUFFIX = "grasp"
STATUS_TOPIC_SUFFIX = "gripper_status"
class FrankaGripperInterface:
"""
Non blocking interface to control the Franka gripper
"""
def __init__(self, node: Node, robot_prefix):
self.last_message = None
self.robot_prefix = robot_prefix
self.node = node
self.move_service = node.create_client(Move, os.path.join(robot_prefix, MOVE_TOPIC_SUFFIX))
self._moving = False
self.grasp_service = node.create_client(Grasp, os.path.join(robot_prefix, GRASP_TOPIC_SUFFIX))
self._grasping = False
self.home_service = node.create_client(Trigger, os.path.join(robot_prefix, "homing"))
self._homing = False
self.status_subscriber = node.create_subscription(GripperState, os.path.join(robot_prefix, STATUS_TOPIC_SUFFIX),
self._status_callback, 10)
self.service_future: Union[rclpy.Future, None] = None
# gripper state
self.state_width = None
self.state_max_width = None
self.state_temperature = None
self.state_is_grasped = None
self.spin_handler = self._default_spin_handler
def _default_spin_handler(self):
rclpy.spin_once(self.node)
def _is_service_ready(self, service: Client):
try:
# self.node.get_logger().info("Waiting for service: " + service.service_name)
ret = service.wait_for_service(timeout_sec=0.1)
return ret
except Exception as e:
self.node.get_logger().info("Service error: " + service.service_name + ": " + str(e))
return False
def is_enabled(self):
if self.state_width is None:
return False
if not self._is_service_ready(self.move_service):
return False
if not self._is_service_ready(self.grasp_service):
return False
return True
def _status_callback(self, msg: GripperState):
self.state_width = msg.width
self.state_max_width = msg.max_width
self.state_temperature = msg.temperature
self.state_is_grasped = msg.is_grasped
def home(self):
"""
Reinitialize the gripper
:return: None
"""
if self.is_busy():
raise Exception("Gripper is already moving or grasping, please wait until the previous action is finished")
self._home()
def move(self, width, speed=0):
"""
Move the gripper to a specific width
:param width: width in meters
:param speed: speed in meters per second
:return: None
"""
if self.is_busy():
raise Exception("Gripper is already moving or grasping, please wait until the previous action is finished")
self._move(width, speed)
def grasp(self, width, force=0, speed=0, epsilon_inner=0, epsilon_outer=0):
"""
Grasp an object with the gripper
:param width:
:param force:
:param speed:
:param epsilon_inner:
:param epsilon_outer:
:return:
"""
if self.is_busy():
raise Exception("Gripper is already moving or grasping, please wait until the previous action is finished")
self._grasp(width, force, speed, epsilon_inner, epsilon_outer)
def get_max_width(self):
""" Get the maximum width of the gripper """
if not self.is_enabled():
raise Exception("Gripper is not enabled")
return self.state_max_width
def get_width(self):
""" Get the current width of the gripper """
if not self.is_enabled():
raise Exception("Gripper is not enabled")
return self.state_width
def get_temperature(self):
""" Get the temperature of the gripper """
if not self.is_enabled():
raise Exception("Gripper is not enabled")
return self.state_temperature
def is_grasped(self):
""" Check if an object is grasped """
if not self.is_enabled():
raise Exception("Gripper is not enabled")
return self.state_is_grasped
def is_moving(self):
""" Check if the gripper is currently moving """
return self._moving
def is_grasping(self):
""" Check if the gripper is currently grasping """
return self._grasping
def is_busy(self):
""" Check if the gripper is currently moving or grasping """
return self._moving or self._grasping or self.service_future is not None
def is_done(self):
""" Check if the gripper is done moving or grasping """
if not self.is_busy():
self.node.get_logger().warn("Gripper is not moving or grasping")
return False
else:
if self.service_future is not None:
if self.service_future.done():
return True
return False
else:
return True
def get_result(self):
"""
Get the result of the last action
:return:
"""
if self.service_future is not None:
if self.service_future.done():
response = self.service_future.result()
if isinstance(response, Move.Response):
self._moving = False
elif isinstance(response, Grasp.Response):
self._grasping = False
elif isinstance(response, Trigger.Response):
self._homing = False
else:
raise Exception("Invalid response type")
self.service_future = None
self.last_message = hasattr(response, "message") and response.message or ""
return response.success
else:
raise Exception("No result available")
else:
raise Exception("No result available")
def get_last_message(self):
return self.last_message
def wait_until_done(self):
"""
Wait until the gripper is done moving or grasping
:return: success
"""
if not self.is_enabled():
raise Exception("Gripper is not enabled")
if not self.is_busy():
return
while not self.is_done():
self.spin_handler()
time.sleep(0.01)
def _home(self):
self._homing = True
# self.node.get_logger().info("Homing gripper")
request = Trigger.Request()
# self.node.get_logger().info("Calling home service")
self.service_future = self.home_service.call_async(request)
def _move(self, width, speed):
self._moving = True
# self.node.get_logger().info("Moving gripper to width: " + str(width) + " speed: " + str(speed))
request = Move.Request()
request.width = float(width)
request.speed = float(speed)
# self.node.get_logger().info("Calling move service")
self.service_future = self.move_service.call_async(request)
def _grasp(self, width, force, speed, epsilon_inner, epsilon_outer):
self._grasping = True
# self.node.get_logger().info("Grasping object at width: " + str(width) + " force: " + str(force) + " speed: " + str(speed))
request = Grasp.Request()
request.width = float(width)
request.force = float(force)
request.speed = float(speed)
request.epsilon_inner = float(epsilon_inner)
request.epsilon_outer = float(epsilon_outer)
# self.node.get_logger().info("Calling grasp service")
self.service_future = self.grasp_service.call_async(request)
def set_spin_handler(self, spin_handler):
self.spin_handler = spin_handler

View File

@@ -1,48 +1,58 @@
import rospy import threading
import rclpy
from sas_robot_driver_franka import FrankaGripperInterface from sas_robot_driver_franka import FrankaGripperInterface
import time
def main_loop(): def main_loop(node):
rate = rospy.Rate(10) # 10 Hz
iteration_ = 0 iteration_ = 0
node_name = node.get_name()
hand1 = FrankaGripperInterface("/franka_hand_1") hand1 = FrankaGripperInterface(node, "/franka_hand_1")
logger = rclpy.node.get_logger(node_name)
while not hand1.is_enabled(): while not hand1.is_enabled():
rospy.loginfo("Waiting for gripper to be enabled...") logger.info("Waiting for gripper to be enabled...")
rate.sleep() time.sleep(0.1)
rospy.loginfo("Gripper enabled!") rclpy.node.get_logger(node_name).info("Gripper enabled!")
rate = rospy.Rate(2) # 0.5 Hz def spin_all(node_):
while rclpy.ok():
rclpy.spin_once(node_, timeout_sec=0.1)
time.sleep(0.1)
while not rospy.is_shutdown(): thread = threading.Thread(target=spin_all, args=(node, ), daemon=True)
rospy.loginfo("Main loop running...") thread.start()
rate = node.create_rate(2)
while rclpy.ok():
logger.info("Main loop running...")
# Get the temperature of the gripper # Get the temperature of the gripper
temperature = hand1.get_temperature() temperature = hand1.get_temperature()
rospy.loginfo(f"Temperature: {temperature}") logger.info(f"Temperature: {temperature}")
max_width = hand1.get_max_width() max_width = hand1.get_max_width()
rospy.loginfo(f"Max width: {max_width}") logger.info(f"Max width: {max_width}")
width = hand1.get_width() width = hand1.get_width()
rospy.loginfo(f"Width: {width}") logger.info(f"Width: {width}")
is_grasped = hand1.is_grasped() is_grasped = hand1.is_grasped()
rospy.loginfo(f"Is grasped: {is_grasped}") logger.info(f"Is grasped: {is_grasped}")
is_moving = hand1.is_moving() is_moving = hand1.is_moving()
rospy.loginfo(f"Is moving: {is_moving}") logger.info(f"Is moving: {is_moving}")
is_grasping = hand1.is_grasping() is_grasping = hand1.is_grasping()
rospy.loginfo(f"Is grasping: {is_grasping}") logger.info(f"Is grasping: {is_grasping}")
rospy.logwarn("calling move(0.01)") logger.warn("calling move(0.01)")
if not hand1.is_busy(): if not hand1.is_busy():
hand1.grasp(0.01) hand1.grasp(0.01)
else: else:
rospy.logwarn("Gripper is busy. Waiting...") logger.warn("Gripper is busy. Waiting...")
result_ready = hand1.is_done() result_ready = hand1.is_done()
if not result_ready: if not result_ready:
rospy.loginfo("Waiting for gripper to finish moving...") logger.info("Waiting for gripper to finish moving...")
else: else:
result = hand1.get_result() result = hand1.get_result()
rospy.loginfo(f"Result: {result}") logger.info(f"Result: {result}")
# Check if there is a response in the queue # Check if there is a response in the queue
@@ -50,7 +60,12 @@ def main_loop():
iteration_ += 1 iteration_ += 1
rate.sleep() rate.sleep()
rclpy.shutdown()
thread.join()
if __name__ == "__main__": if __name__ == "__main__":
rospy.init_node("example_gripper_control_node") rclpy.init()
main_loop() node_name_ = "example_gripper_control_node"
NODE = rclpy.create_node(node_name_)
main_loop(NODE)

View File

@@ -1,29 +1,46 @@
import rospy import time
from sas_robot_driver_franka import RobotDynamicsProvider
import rclpy
from sas_common import rclcpp_init, rclcpp_Node, rclcpp_spin_some, rclcpp_shutdown
from sas_robot_driver_franka import RobotDynamicsClient, RobotDynamicsServer
import dqrobotics as dql import dqrobotics as dql
import numpy as np import numpy as np
if __name__ == "__main__":
rospy.init_node("dummy_robot_dynamics_provider")
dynam_provider = RobotDynamicsProvider("/franka1")
if __name__ == "__main__":
rclcpp_init()
rclpy.init()
sas_node = rclcpp_Node("dummy_robot_dynamics_server_sas")
node = rclpy.create_node("dummy_robot_dynamics_server")
dynam_provider = RobotDynamicsServer(sas_node, "/franka1")
t = dql.DQ([0, 0, 1]) t = dql.DQ([0, 0, 1])
r = dql.DQ([1, 0, 0, 0]) r = dql.DQ([1, 0, 0, 0])
base_pose = r + 0.5 * dql.E_ * t * r base_pose = r + 0.5 * dql.E_ * t * r
dynam_provider.set_world_to_base_tf(base_pose) dynam_provider.set_world_to_base_tf(base_pose)
t_ = 0 t_ = 0
rospy.loginfo("Publishing dummy robot dynamics") node.get_logger().info("Dummy robot dynamics server started")
r = dql.DQ([0, 0, 0, 1]) r = dql.DQ([0, 0, 0, 1])
rate = rospy.Rate(100) rate = node.create_rate(100)
dummy_force = np.random.rand(3) * 100 dummy_force = np.random.rand(3) * 100
dummy_torque = np.random.rand(3) * 10 dummy_torque = np.random.rand(3) * 10
try:
while rclpy.ok():
t = dql.DQ([1, 2, 1]) + dql.i_ * np.sin(t_/2/np.pi) + dql.j_ * np.cos(t_/2/np.pi)
ee_pose = r + 0.5 * dql.E_ * t * r
dummy_force = dummy_force * 0.9 + np.random.rand(3) * 10
dummy_torque = dummy_torque * 0.9 + np.random.rand(3) * 1
dynam_provider.publish_stiffness(ee_pose, dummy_force, dummy_torque)
rclcpp_spin_some(sas_node)
rclpy.spin_once(node)
t_ += 0.01
time.sleep(0.1)
except KeyboardInterrupt:
pass
finally:
rclcpp_shutdown()
node.destroy_node()
rclpy.shutdown()
while not rospy.is_shutdown():
t = dql.DQ([1, 2, 1]) + dql.i_ * np.sin(t_/2/np.pi) + dql.j_ * np.cos(t_/2/np.pi)
ee_pose = r + 0.5 * dql.E_ * t * r
dummy_force = dummy_force * 0.9 + np.random.rand(3) * 10
dummy_torque = dummy_torque * 0.9 + np.random.rand(3) * 1
dynam_provider.publish_stiffness(ee_pose, dummy_force, dummy_torque)
rate.sleep()
t_ += 0.01

View File

@@ -1,30 +1,53 @@
import rospy import time
from sas_robot_driver_franka import RobotDynamicsInterface
import rclpy
from sas_common import rclcpp_init, rclcpp_Node, rclcpp_spin_some, rclcpp_shutdown
from sas_robot_driver_franka import RobotDynamicsClient, RobotDynamicsServer
import dqrobotics as dql import dqrobotics as dql
import numpy as np import numpy as np
from dqrobotics.interfaces.vrep import DQ_VrepInterface from dqrobotics.interfaces.vrep import DQ_VrepInterface
vrep = DQ_VrepInterface() # vrep = DQ_VrepInterface()
vrep.connect("192.168.10.103", 19997, 100, 10) # vrep.connect("192.168.10.103", 19997, 100, 10)
vrep = None
if __name__ == "__main__": if __name__ == "__main__":
rospy.init_node("dummy_robot_dynamics_subscriber") rclcpp_init()
rclpy.init()
sas_node = rclcpp_Node("dummy_robot_dynamics_client_sas")
node = rclpy.create_node("dummy_robot_dynamics_client")
executor = rclpy.executors.MultiThreadedExecutor()
executor.add_node(node)
try:
executor.spin_once(timeout_sec=0.1)
dynam_provider = RobotDynamicsClient(sas_node, "/franka1")
rclcpp_spin_some(sas_node)
while not dynam_provider.is_enabled():
node.get_logger().info("Waiting for robot dynamics provider to be enabled")
rclcpp_spin_some(sas_node)
executor.spin_once(timeout_sec=0.1)
node.get_logger().info("retrying...")
time.sleep(0.5)
dynam_provider = RobotDynamicsInterface("/franka1") node.get_logger().info("Dummy robot dynamics client started")
while not dynam_provider.is_enabled(): while rclpy.ok():
rospy.loginfo("Waiting for robot dynamics provider to be enabled") force = dynam_provider.get_stiffness_force()
rospy.sleep(1) torque = dynam_provider.get_stiffness_torque()
ee_pose = dynam_provider.get_stiffness_frame_pose()
rospy.loginfo("Subscribing to dummy robot dynamics") if vrep is not None:
rate = rospy.Rate(50) vrep.set_object_pose("xd1", ee_pose)
node.get_logger().info(f"EE Pose: {ee_pose}")
while not rospy.is_shutdown(): node.get_logger().info(f"Force: {force}")
force = dynam_provider.get_stiffness_force() node.get_logger().info(f"Torque: {torque}")
torque = dynam_provider.get_stiffness_torque() rclcpp_spin_some(sas_node)
ee_pose = dynam_provider.get_stiffness_frame_pose() executor.spin_once(timeout_sec=0.1)
vrep.set_object_pose("xd1", ee_pose) time.sleep(0.5)
rospy.loginfo("EE Pose: %s", ee_pose) except KeyboardInterrupt:
rospy.loginfo("Force: %s", force) pass
rospy.loginfo("Torque: %s", torque) finally:
rate.sleep() rclcpp_shutdown()
node.destroy_node()
if vrep is not None:
vrep.disconnect()
rclpy.shutdown()

View File

@@ -1,12 +0,0 @@
# ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD
from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup
# fetch values from package.xml
setup_args = generate_distutils_setup(
packages=['sas_robot_driver_franka'],
package_dir={'': 'src'},
)
setup(**setup_args)

View File

@@ -1,252 +1,246 @@
#include "sas_robot_driver_coppelia.h" #include <sas_robot_driver_franka/coppelia/sas_robot_driver_coppelia.hpp>
namespace sas namespace qros
{ {
RobotDriverCoppelia::~RobotDriverCoppelia() {
RobotDriverCoppelia::RobotDriverCoppelia(const RobotDriverCoppeliaConfiguration &configuration, std::atomic_bool *break_loops): deinitialize();
RobotDriver(break_loops), disconnect();
configuration_(configuration),
robot_mode_(configuration.robot_mode),
jointnames_(configuration.jointnames),
mirror_mode_(configuration.mirror_mode),
dim_configuration_space_(configuration.jointnames.size()),
real_robot_topic_prefix_(configuration.real_robot_topic_prefix)
{
vi_ = std::make_shared<DQ_VrepInterface>();
desired_joint_velocities_ = VectorXd::Zero(dim_configuration_space_);
auto nodehandle = ros::NodeHandle();
std::cout<<"RobotDriverCoppelia::Rostopic: "<<"/"+real_robot_topic_prefix_<<std::endl;
franka1_ros_ = std::make_shared<sas::RobotDriverInterface>(nodehandle, "/"+real_robot_topic_prefix_);
} }
VectorXd RobotDriverCoppelia::get_joint_positions() RobotDriverCoppelia::RobotDriverCoppelia(const std::shared_ptr<Node> &node_sptr, const RobotDriverCoppeliaConfiguration &configuration, std::atomic_bool *break_loops):
configuration_(configuration),
node_sptr_(node_sptr),
clock_(configuration.thread_sampling_time_sec),
break_loops_(break_loops),
robot_mode_(ControlMode::Position),
vi_(std::make_shared<DQ_VrepInterface>())
{ {
return current_joint_positions_; // should initialize robot driver interface to real robot
} DQ_SerialManipulatorDH smdh = DQ_JsonReader::get_from_json<DQ_SerialManipulatorDH>(configuration_.robot_parameter_file_path);
joint_limits_ = {smdh.get_lower_q_limit(),smdh.get_upper_q_limit()};
void RobotDriverCoppelia::set_target_joint_positions(const VectorXd &desired_joint_positions_rad) if(configuration_.using_real_robot)
{
desired_joint_positions_ = desired_joint_positions_rad;
}
VectorXd RobotDriverCoppelia::get_joint_velocities()
{
return current_joint_velocities_;
}
void RobotDriverCoppelia::set_target_joint_velocities(const VectorXd &desired_joint_velocities)
{
desired_joint_velocities_ = desired_joint_velocities;
}
VectorXd RobotDriverCoppelia::get_joint_forces()
{
return current_joint_forces_;
}
RobotDriverCoppelia::~RobotDriverCoppelia()=default;
void RobotDriverCoppelia::connect()
{
vi_->connect(configuration_.ip, configuration_.port, 500, 10);
vi_->set_joint_target_velocities(jointnames_, VectorXd::Zero(dim_configuration_space_));
std::cout<<"RobotDriverCoppelia::Connecting..."<<std::endl;
}
void RobotDriverCoppelia::disconnect()
{
vi_->disconnect();
if (joint_velocity_control_mode_thread_.joinable())
{ {
joint_velocity_control_mode_thread_.join(); RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Using real robot, Instantiating robot interface to real driver at ["+configuration_.robot_topic_prefix+"].");
} real_robot_interface_ = std::make_shared<sas::RobotDriverClient>(node_sptr_, configuration_.robot_topic_prefix);
if (joint_velocity_control_mirror_mode_thread_.joinable())
{
joint_velocity_control_mirror_mode_thread_.join();
}
std::cout<<"RobotDriverCoppelia::Disconnected."<<std::endl;
}
void RobotDriverCoppelia::initialize()
{
vi_->start_simulation();
if (mirror_mode_ == false)
{
_start_joint_velocity_control_thread();
}else{ }else{
_start_joint_velocity_control_mirror_thread(); RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Using simulation robot, simulation mode is set to "+ configuration_.robot_mode);
} robot_provider_ = std::make_shared<sas::RobotDriverServer>(node_sptr_, configuration_.robot_topic_prefix);
std::cout<<"RobotDriverCoppelia::Velocity loop running..."<<std::endl; std::string _mode_upper = configuration_.robot_mode;
} std::transform(_mode_upper.begin(), _mode_upper.end(), _mode_upper.begin(), ::toupper);
if(_mode_upper == "POSITIONCONTROL"){
void RobotDriverCoppelia::deinitialize() robot_mode_ = ControlMode::Position;
{ }else if(_mode_upper == "VELOCITYCONTROL"){
vi_->set_joint_target_velocities(jointnames_, VectorXd::Zero(dim_configuration_space_)); robot_mode_ = ControlMode::Velocity;
vi_->stop_simulation(); }else{
finish_motion(); throw std::invalid_argument("[" + std::string(node_sptr_->get_name()) + "]::Robot mode must be either 'position' or 'velocity'");
std::cout<<"RobotDriverCoppelia::Deinitialized."<<std::endl;
}
void RobotDriverCoppelia::_update_robot_state(const VectorXd &q, const VectorXd &q_dot, const VectorXd &forces)
{
current_joint_positions_ = q;
current_joint_velocities_ = q_dot;
current_joint_forces_ = forces;
}
void RobotDriverCoppelia::finish_motion()
{
for (int i=0;i<1000;i++)
{
set_target_joint_positions(current_joint_positions_);
set_target_joint_velocities(VectorXd::Zero(dim_configuration_space_));
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
finish_motion_ = true;
}
void RobotDriverCoppelia::_start_joint_velocity_control_mode()
{
try{
finish_motion_ = false;
VectorXd q = vi_->get_joint_positions(jointnames_);
VectorXd q_dot = vi_->get_joint_velocities(jointnames_);
VectorXd forces = vi_->get_joint_torques(jointnames_);
_update_robot_state(q, q_dot, forces);
desired_joint_positions_ = q;
while(true)
{
VectorXd q = vi_->get_joint_positions(jointnames_);
VectorXd q_dot = vi_->get_joint_velocities(jointnames_);
VectorXd forces = vi_->get_joint_torques(jointnames_);
_update_robot_state(q, q_dot, forces);
if (robot_mode_ == std::string("VelocityControl"))
{
vi_->set_joint_target_velocities(jointnames_, desired_joint_velocities_);
}
else if (robot_mode_ == std::string("PositionControl"))
{
vi_->set_joint_target_positions(jointnames_, desired_joint_positions_);
}
if (finish_motion_) {
finish_motion_ = false;
return;
}
} }
} }
}
void RobotDriverCoppelia::_update_vrep_position(const VectorXd &joint_positions, const bool& force_update) const{
if(configuration_.vrep_dynamically_enabled){
if(force_update){
vi_->set_joint_positions(configuration_.vrep_joint_names, joint_positions);
}
vi_->set_joint_target_positions(configuration_.vrep_joint_names, joint_positions);
}else{
vi_->set_joint_positions(configuration_.vrep_joint_names, joint_positions);
}
}
void RobotDriverCoppelia::_update_vrep_velocity(const VectorXd & joint_velocity) const{
if(!configuration_.vrep_dynamically_enabled){
throw std::runtime_error("[RobotDriverCoppelia]::[_update_vrep_velocity]::Vrep is not dynamically enabled");
}
vi_->set_joint_target_velocities(configuration_.vrep_joint_names, joint_velocity);
}
void RobotDriverCoppelia::_start_control_loop(){
clock_.init();
RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Starting control loop...");
while(!_should_shutdown()){
clock_.update_and_sleep();
rclcpp::spin_some(node_sptr_);
if(!rclcpp::ok()){break_loops_->store(true);}
if(configuration_.using_real_robot){
// real_robot_interface_
auto joint_position = real_robot_interface_->get_joint_positions();
_update_vrep_position(joint_position);
}else{
// robot_provider_
VectorXd target_joint_positions;
auto current_joint_positions = vi_->get_joint_positions(configuration_.vrep_joint_names);
VectorXd current_joint_velocity;
if(robot_provider_->is_enabled()) {
if(robot_mode_ == ControlMode::Velocity)
{
if(robot_provider_->is_enabled(sas::RobotDriver::Functionality::VelocityControl)) {
simulated_joint_velocities_ = robot_provider_->get_target_joint_velocities();
current_joint_velocity = simulated_joint_velocities_;
// try{_update_vrep_velocity(simulated_joint_velocities_);}catch (...){}
}
else{
RCLCPP_DEBUG_STREAM(node_sptr_->get_logger(), "::Velocity control is not enabled.");
}
target_joint_positions = simulated_joint_positions_;
}else{
target_joint_positions = robot_provider_->get_target_joint_positions();
}
}else {
target_joint_positions = current_joint_positions;
}
_update_vrep_position(target_joint_positions);
robot_provider_->send_joint_states(current_joint_positions, current_joint_velocity, VectorXd());
robot_provider_->send_joint_limits(joint_limits_);
}
}
}
int RobotDriverCoppelia::start_control_loop(){
try{
RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Waiting to connect with coppelia...");
connect();
RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Connected to coppelia.");
RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Initializing...");
initialize();
RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::initialized.");
_start_control_loop();
}
catch(const std::exception& e) catch(const std::exception& e)
{ {
std::cout<<"RobotDriverCoppelia::sas_robot_coppelia_driver::_start_joint_velocity_control_mode(). Error or exception caught " << e.what()<<std::endl; RCLCPP_WARN_STREAM(node_sptr_->get_logger(), "::Error or exception caught::" << e.what());
} }
catch(...) catch(...)
{ {
std::cout<<"RobotDriverCoppelia::sas_robot_coppelia_driver::_start_joint_velocity_control_mode(). Error or exception caught " <<std::endl; RCLCPP_WARN_STREAM(node_sptr_->get_logger(), "::Unexpected error or exception caught");
} }
RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Deinitializing...");
deinitialize();
RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::deinitialized.");
RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Disconnecting from coppelia...");
disconnect();
RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::Disconnected from coppelia.");
return 0;
} }
void RobotDriverCoppelia::_start_joint_velocity_control_thread()
{ void RobotDriverCoppelia::connect(){
finish_motion_ = false; auto ret = vi_->connect(configuration_.vrep_ip, configuration_.vrep_port, 100, 10);
if (joint_velocity_control_mode_thread_.joinable()) if(!ret){
{ throw std::runtime_error("[RobotDriverCoppelia]::connect::Could not connect to Vrep");
joint_velocity_control_mode_thread_.join();
} }
if (joint_velocity_control_mirror_mode_thread_.joinable()) RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::connect::Connected to Vrep");
{ }
joint_velocity_control_mirror_mode_thread_.join(); void RobotDriverCoppelia::disconnect(){
} vi_->disconnect_all();
joint_velocity_control_mode_thread_ = std::thread(&RobotDriverCoppelia::_start_joint_velocity_control_mode, this);
} }
void RobotDriverCoppelia::_start_joint_velocity_control_mirror_thread() void RobotDriverCoppelia::initialize(){
{ if(configuration_.using_real_robot)
finish_motion_ = false;
if (joint_velocity_control_mode_thread_.joinable())
{ {
joint_velocity_control_mode_thread_.join(); RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::initialize::Waiting for real robot interface to initialize...");
} rclcpp::spin_some(node_sptr_);
if (joint_velocity_control_mirror_mode_thread_.joinable()) int count = 0;
{ while (!real_robot_interface_->is_enabled(sas::RobotDriver::Functionality::PositionControl)) {
joint_velocity_control_mirror_mode_thread_.join(); rclcpp::spin_some(node_sptr_);
} // std::cout<<"Waiting for real robot interface to initialize..."<<std::endl;
joint_velocity_control_mirror_mode_thread_ = std::thread(&RobotDriverCoppelia::_start_joint_velocity_control_mirror_mode, this); std::this_thread::sleep_for(std::chrono::milliseconds(100));
} rclcpp::spin_some(node_sptr_);
count++;
void RobotDriverCoppelia::_start_joint_velocity_control_mirror_mode() if(count > REAL_ROBOT_INTERFACE_INIT_TIMEOUT_COUNT){
{ RCLCPP_ERROR_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::initialize::Real robot interface not initialized. Exiting on TIMEOUT...");
throw std::runtime_error("[" + std::string(node_sptr_->get_name()) +"]::[RobotDriverCoppelia]::initialize::Real robot interface not initialized.");
try{ }
finish_motion_ = false; if(!rclcpp::ok()) {
std::cout<<"RobotDriverCoppelia::Waiting for real robot topics..."<<std::endl; RCLCPP_WARN_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::initialize::ROS shutdown received. Exiting...");
VectorXd q; throw std::runtime_error("[" + std::string(node_sptr_->get_name()) +"]::[RobotDriverCoppelia]::initialize::ROS shutdown received, not OK.");
while (ros::ok()) {
if (franka1_ros_->is_enabled())
{
q = franka1_ros_->get_joint_positions();
break;
} }
ros::spinOnce();
} }
std::cout<<"RobotDriverCoppelia::Done!"<<std::endl; RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::initialize::Real robot interface initialized.");
joint_limits_ = real_robot_interface_->get_joint_limits();
VectorXd q_vrep = vi_->get_joint_positions(jointnames_); _update_vrep_position(real_robot_interface_->get_joint_positions(), true);
VectorXd q_dot_vrep = vi_->get_joint_velocities(jointnames_); }else{
VectorXd forces_vrep = vi_->get_joint_torques(jointnames_); RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::initialize::Simulation mode.");
_update_robot_state(q_vrep, q_dot_vrep, forces_vrep); // initialization information for robot driver provider
/**
desired_joint_positions_ = q_vrep; * TODO: check for making sure real robot is not actually connected
*/
auto current_joint_positions = vi_->get_joint_positions(configuration_.vrep_joint_names);
while(ros::ok()) VectorXd current_joint_velocity;
if(robot_mode_ == ControlMode::Velocity)
{current_joint_velocity = VectorXd::Zero(current_joint_positions.size());}
robot_provider_->send_joint_states(current_joint_positions, current_joint_velocity, VectorXd());
robot_provider_->send_joint_limits(joint_limits_);
// start velocity control simulation thread if needed
if(robot_mode_ == ControlMode::Velocity)
{ {
q = franka1_ros_->get_joint_positions(); simulated_joint_positions_ = current_joint_positions;
if (q.size() == dim_configuration_space_) simulated_joint_velocities_ = current_joint_velocity;
{ start_simulation_thread();
VectorXd q_vrep = vi_->get_joint_positions(jointnames_);
VectorXd q_dot_vrep = vi_->get_joint_velocities(jointnames_);
VectorXd forces_vrep = vi_->get_joint_torques(jointnames_);
_update_robot_state(q_vrep, q_dot_vrep, forces_vrep);
if (robot_mode_ == std::string("VelocityControl"))
{
vi_->set_joint_target_velocities(jointnames_, gain_*(q-q_vrep));
}
else if (robot_mode_ == std::string("PositionControl"))
{
vi_->set_joint_target_positions(jointnames_, q);
}
if (finish_motion_) {
finish_motion_ = false;
return;
}
}
} }
} }
catch(const std::exception& e) }
{ void RobotDriverCoppelia::deinitialize(){
std::cout<<"RobotDriverCoppelia::sas_robot_coppelia_driver::_start_joint_velocity_control_mirror_mode(). Error or exception caught " << e.what()<<std::endl; // nothing to do
}
catch(...)
{
std::cout<<"RobotDriverCoppelia::sas_robot_coppelia_driver::_start_joint_velocity_control_mirror_mode(). Error or exception caught " <<std::endl;
}
} }
void RobotDriverCoppelia::start_simulation_thread(){ // thread entry point
if(simulation_thread_started_){
throw std::runtime_error("[RobotDriverCoppelia]::start_simulation_thread::Simulation thread already started");
}
if(velocity_control_simulation_thread_.joinable()){
velocity_control_simulation_thread_.join();
}
velocity_control_simulation_thread_ = std::thread(&RobotDriverCoppelia::_velocity_control_simulation_thread_main, this);
}
void RobotDriverCoppelia::_velocity_control_simulation_thread_main(){
/**
* This thread should not access vrep
*/
simulation_thread_started_ = true;
try{
RCLCPP_INFO_STREAM(node_sptr_->get_logger(), "::RobotDriverCoppelia]::[_velocity_control_simulation_thread_main]::Simulation thread started.");
sas::Clock clock = sas::Clock(VIRTUAL_ROBOT_SIMULATION_SAMPLING_TIME_SEC);
double tau = VIRTUAL_ROBOT_SIMULATION_SAMPLING_TIME_SEC;
auto current_joint_positions = simulated_joint_positions_;
clock.init();
while (!(*break_loops_) && rclcpp::ok()) {
current_joint_positions += tau * simulated_joint_velocities_; // no dynamic model
// cap joint limit
auto q_min = std::get<0>(joint_limits_);
auto q_max = std::get<1>(joint_limits_);
for (int i = 0; i < current_joint_positions.size(); i++) {
if (current_joint_positions(i) < q_min(i)) {
current_joint_positions(i) = q_min(i);
}
if (current_joint_positions(i) > q_max(i)) {
current_joint_positions(i) = q_max(i);
}
}
simulated_joint_positions_ = current_joint_positions;
clock.update_and_sleep();
}
}catch(std::exception &e){
RCLCPP_ERROR_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::[_velocity_control_simulation_thread_main]::Exception::" << e.what());
simulation_thread_started_ = false;
}catch(...){
RCLCPP_ERROR_STREAM(node_sptr_->get_logger(), "::[RobotDriverCoppelia]::[_velocity_control_simulation_thread_main]::Exception::Unknown");
simulation_thread_started_ = false;
}
break_loops_->store(true);
}

View File

@@ -1,134 +0,0 @@
/*
# Copyright (c) 2023 Juan Jose Quiroz Omana
#
# This file is part of sas_robot_driver_franka.
#
# sas_robot_driver_franka is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# sas_robot_driver_franka is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with sas_robot_driver. If not, see <https://www.gnu.org/licenses/>.
#
# ################################################################
#
# Author: Juan Jose Quiroz Omana, email: juanjqogm@gmail.com
#
# ################################################################
#
# Contributors:
# 1. Juan Jose Quiroz Omana (juanjqogm@gmail.com)
# - Adapted from sas_robot_driver_denso.cpp
# (https://github.com/SmartArmStack/sas_robot_driver_denso/blob/master/src/sas_robot_driver_denso.cpp)
#
# ################################################################
*/
#pragma once
#include <exception>
#include <tuple>
#include <atomic>
#include <vector>
#include <memory>
#include <dqrobotics/DQ.h>
#include <sas_robot_driver/sas_robot_driver.h>
#include <dqrobotics/interfaces/vrep/DQ_VrepRobot.h>
#include <thread>
#include <sas_robot_driver/sas_robot_driver_interface.h>
using namespace DQ_robotics;
using namespace Eigen;
namespace sas
{
struct RobotDriverCoppeliaConfiguration
{
int thread_sampling_time_nsec;
int port;
std::string ip;
std::vector<std::string> jointnames;
std::string robot_mode;
bool mirror_mode;
std::string real_robot_topic_prefix;
};
class RobotDriverCoppelia: public RobotDriver
{
private:
RobotDriverCoppeliaConfiguration configuration_;
std::string robot_mode_ = std::string("VelocityControl"); // PositionControl
bool mirror_mode_ = false;
double gain_ = 3.0;
std::string real_robot_topic_prefix_;
VectorXd current_joint_positions_;
VectorXd current_joint_velocities_;
VectorXd current_joint_forces_;
VectorXd desired_joint_velocities_;
VectorXd desired_joint_positions_;
std::atomic<bool> finish_motion_;
int dim_configuration_space_;
void _update_robot_state(const VectorXd& q, const VectorXd& q_dot, const VectorXd& forces);
void finish_motion();
void _start_joint_velocity_control_mode();
std::thread joint_velocity_control_mode_thread_;
void _start_joint_velocity_control_thread();
void _start_joint_velocity_control_mirror_mode();
std::thread joint_velocity_control_mirror_mode_thread_;
void _start_joint_velocity_control_mirror_thread();
std::shared_ptr<sas::RobotDriverInterface> franka1_ros_;
protected:
std::shared_ptr<DQ_VrepInterface> vi_;
std::vector<std::string> jointnames_;
public:
RobotDriverCoppelia(const RobotDriverCoppelia&)=delete;
RobotDriverCoppelia()=delete;
~RobotDriverCoppelia();
RobotDriverCoppelia(const RobotDriverCoppeliaConfiguration& configuration, std::atomic_bool* break_loops);
VectorXd get_joint_positions() override;
void set_target_joint_positions(const VectorXd& desired_joint_positions_rad) override;
VectorXd get_joint_velocities() override;
void set_target_joint_velocities(const VectorXd& desired_joint_velocities) override;
VectorXd get_joint_forces() override;
void connect() override;
void disconnect() override;
void initialize() override;
void deinitialize() override;
};
}

View File

@@ -28,7 +28,7 @@
# #
# ################################################################ # ################################################################
*/ */
#include "generator/custom_motion_generation.h" #include <sas_robot_driver_franka/generator/custom_motion_generation.h>
/** /**
* @brief CustomMotionGeneration::CustomMotionGeneration * @brief CustomMotionGeneration::CustomMotionGeneration

View File

@@ -1,6 +1,6 @@
// Copyright (c) 2017 Franka Emika GmbH // Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE // Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include "generator/motion_generator.h" #include <sas_robot_driver_franka/generator/motion_generator.h>
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <cmath> #include <cmath>

View File

@@ -1,4 +1,4 @@
#include "generator/quadratic_program_motion_generator.h" #include <sas_robot_driver_franka/generator/quadratic_program_motion_generator.h>
QuadraticProgramMotionGenerator::QuadraticProgramMotionGenerator(const double &speed_factor, QuadraticProgramMotionGenerator::QuadraticProgramMotionGenerator(const double &speed_factor,

View File

@@ -27,10 +27,13 @@
# #
# ################################################################ # ################################################################
*/ */
#include "hand/qros_effector_driver_franka_hand.h" #include <sas_robot_driver_franka/interfaces/qros_effector_driver_franka_hand.hpp>
#include <franka/exception.h> #include <franka/exception.h>
using namespace std::placeholders;
using namespace sas_robot_driver_franka_interfaces;
namespace qros namespace qros
{ {
@@ -48,19 +51,21 @@ namespace qros
EffectorDriverFrankaHand::EffectorDriverFrankaHand( EffectorDriverFrankaHand::EffectorDriverFrankaHand(
const std::string& driver_node_prefix, const std::string& driver_node_prefix,
const EffectorDriverFrankaHandConfiguration& configuration, const EffectorDriverFrankaHandConfiguration& configuration,
ros::NodeHandle& node_handel, std::shared_ptr<Node> node,
std::atomic_bool* break_loops): std::atomic_bool* break_loops):
driver_node_prefix_(driver_node_prefix), driver_node_prefix_(driver_node_prefix),
configuration_(configuration), configuration_(configuration),
node_handel_(node_handel), node_(node),
break_loops_(break_loops) break_loops_(break_loops)
{ {
gripper_sptr_ = nullptr; gripper_sptr_ = nullptr;
grasp_server_ = node_handel_.advertiseService(driver_node_prefix_ + "/grasp", grasp_srv_ = node->create_service<srv::Grasp>(driver_node_prefix_ + "/grasp",
&EffectorDriverFrankaHand::_grasp_srv_callback, this); std::bind(&EffectorDriverFrankaHand::_grasp_srv_callback, this, _1, _2));
move_server_ = node_handel_.advertiseService(driver_node_prefix_ + "/move", move_srv_ = node->create_service<srv::Move>(driver_node_prefix_ + "/move",
&EffectorDriverFrankaHand::_move_srv_callback, this); std::bind(&EffectorDriverFrankaHand::_move_srv_callback, this, _1, _2));
gripper_status_publisher_ = node_handel_.advertise<sas_robot_driver_franka::GripperState>( homing_srv_ = node->create_service<std_srvs::srv::Trigger>(driver_node_prefix_ + "/homing",
std::bind(&EffectorDriverFrankaHand::_home_srv_callback, this, _1, _2));
gripper_status_publisher_ = node->create_publisher<msg::GripperState>(
driver_node_prefix_ + "/gripper_status", 1); driver_node_prefix_ + "/gripper_status", 1);
} }
@@ -75,56 +80,48 @@ namespace qros
} }
void EffectorDriverFrankaHand::start_control_loop() void EffectorDriverFrankaHand::start_control_loop() {
{ sas::Clock clock = sas::Clock(configuration_.thread_sampeling_time_s);
sas::Clock clock = sas::Clock(configuration_.thread_sampeling_time_ns);
clock.init(); clock.init();
ROS_INFO_STREAM( RCLCPP_INFO_STREAM(node_->get_logger(),"[EffectorDriverFrankaHand]::start_control_loop::Starting control loop.");
"["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::start_control_loop::Starting control loop."); RCLCPP_WARN_STREAM(node_->get_logger(),"[EffectorDriverFrankaHand]::Gripper READY.");
while (!(*break_loops_)) while (!(*break_loops_))
{ {
if (!_is_connected()) throw std::runtime_error( if (!_is_connected()) throw std::runtime_error("[" + std::string(node_->get_name())+"]::[EffectorDriverFrankaHand]::start_control_loop::Robot is not connected.");
"[" + ros::this_node::getName() +
"]::[EffectorDriverFrankaHand]::start_control_loop::Robot is not connected.");
if (!status_loop_running_) if (!status_loop_running_)
{ {
ROS_WARN_STREAM( RCLCPP_WARN_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_is_connected::Status loop is not running.");
"["+ ros::this_node::getName()+
"]::[EffectorDriverFrankaHand]::_is_connected::Status loop is not running.");
break_loops_->store(true); break_loops_->store(true);
break; break;
} }
clock.update_and_sleep(); clock.update_and_sleep();
ros::spinOnce(); spin_some(node_);
} }
ROS_INFO_STREAM( RCLCPP_INFO_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::start_control_loop::Exiting control loop.");
"["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::start_control_loop::Exiting control loop.");
} }
void EffectorDriverFrankaHand::connect() void EffectorDriverFrankaHand::connect()
{ {
#ifdef IN_TESTING #ifdef IN_TESTING
ROS_WARN_STREAM( RCLCPP_WARN_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::connect::In testing mode. to DUMMY");
"["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::connect::In testing mode. to DUMMY");
return; return;
#endif #endif
gripper_sptr_ = std::make_shared<franka::Gripper>(configuration_.robot_ip); gripper_sptr_ = std::make_shared<franka::Gripper>(configuration_.robot_ip);
if (!_is_connected()) throw std::runtime_error( if (!_is_connected()) throw std::runtime_error(
"[" + ros::this_node::getName() + "[" + std::string(node_->get_name())+
"]::[EffectorDriverFrankaHand]::connect::Could not connect to the robot."); "]::[EffectorDriverFrankaHand]::connect::Could not connect to the robot.");
} }
void EffectorDriverFrankaHand::disconnect() noexcept void EffectorDriverFrankaHand::disconnect() noexcept
{ {
#ifdef IN_TESTING #ifdef IN_TESTING
ROS_WARN_STREAM( RCLCPP_WARN_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::disconnect::In testing mode. from DUMMY");
"["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::disconnect::In testing mode. from DUMMY");
return; return;
#endif #endif
ROS_WARN_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::disconnecting..."); RCLCPP_WARN_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::disconnecting...");
gripper_sptr_->~Gripper(); gripper_sptr_->~Gripper();
gripper_sptr_ = nullptr; gripper_sptr_ = nullptr;
} }
@@ -135,35 +132,42 @@ namespace qros
void EffectorDriverFrankaHand::gripper_homing() void EffectorDriverFrankaHand::gripper_homing()
{ {
#ifdef IN_TESTING #ifdef IN_TESTING
ROS_WARN_STREAM( RCLCPP_WARN_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::gripper_homing::In testing mode.");
"["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::gripper_homing::In testing mode.");
return; return;
#endif #endif
if (!_is_connected()) throw std::runtime_error( if (!_is_connected()) throw std::runtime_error(
"[" + ros::this_node::getName() + "]::[EffectorDriverFrankaHand]::gripper_homing::Robot is not connected."); "[" + std::string(node_->get_name())+ "]::[EffectorDriverFrankaHand]::gripper_homing::Robot is not connected.");
auto ret = gripper_sptr_->homing(); auto ret = gripper_sptr_->homing();
if (!ret) if (!ret)
{ {
throw std::runtime_error( throw std::runtime_error("[" + std::string(node_->get_name())+"]::[EffectorDriverFrankaHand]::gripper_homing::Failed to home the gripper.");
"[" + ros::this_node::getName() +
"]::[EffectorDriverFrankaHand]::gripper_homing::Failed to home the gripper.");
} }
ROS_INFO_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::gripper_homing::Gripper homed."); RCLCPP_INFO_STREAM(node_->get_logger(),"[EffectorDriverFrankaHand]::gripper_homing::Gripper homed.");
} }
void EffectorDriverFrankaHand::initialize() void EffectorDriverFrankaHand::initialize()
{ {
if (!_is_connected()) throw std::runtime_error( if (!_is_connected()) throw std::runtime_error(
"[" + ros::this_node::getName() + "]::[EffectorDriverFrankaHand]::initialize::Robot is not connected."); "[" + std::string(node_->get_name())+ "]::[EffectorDriverFrankaHand]::initialize::Robot is not connected.");
gripper_homing(); if (configuration_.initialize_with_homing) {
gripper_homing();
}
// start gripper status loop // start gripper status loop
status_loop_thread_ = std::thread(&EffectorDriverFrankaHand::_gripper_status_loop, this); status_loop_thread_ = std::thread(&EffectorDriverFrankaHand::_gripper_status_loop, this);
// check status loop with timeout
auto time_now = std::chrono::system_clock::now();
auto time_out = time_now + std::chrono::seconds(5);
while (!status_loop_running_)
{
if (std::chrono::system_clock::now() > time_out){throw std::runtime_error("[" + std::string(node_->get_name()) + "]::[EffectorDriverFrankaHand]::initialize::Could not start status loop.");}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
} }
void EffectorDriverFrankaHand::deinitialize() void EffectorDriverFrankaHand::deinitialize()
{ {
#ifdef IN_TESTING #ifdef IN_TESTING
ROS_WARN_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::deinitialize::In testing mode."); RCLCPP_WARN_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::deinitialize::In testing mode.");
return; return;
#endif #endif
if (_is_connected()) if (_is_connected())
@@ -177,130 +181,144 @@ namespace qros
} }
bool EffectorDriverFrankaHand::_grasp_srv_callback(sas_robot_driver_franka::Grasp::Request& req, bool EffectorDriverFrankaHand::_grasp_srv_callback(const std::shared_ptr<srv::Grasp::Request> &req, std::shared_ptr<srv::Grasp::Response> res)
sas_robot_driver_franka::Grasp::Response& res)
{ {
ROS_DEBUG_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_grasp_srv_callback::Grasping..."); RCLCPP_DEBUG_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_grasp_srv_callback::Grasping...");
auto force = req.force; auto force = req->force;
auto speed = req.speed; auto speed = req->speed;
auto epsilon_inner = req.epsilon_inner; auto epsilon_inner = req->epsilon_inner;
auto epsilon_outer = req.epsilon_outer; auto epsilon_outer = req->epsilon_outer;
if (force <= 0.0) force = configuration_.default_force; if (force <= 0.0) force = configuration_.default_force;
if (speed <= 0.0) speed = configuration_.default_speed; if (speed <= 0.0) speed = configuration_.default_speed;
if (epsilon_inner <= 0.0) epsilon_inner = configuration_.default_epsilon_inner; if (epsilon_inner <= 0.0) epsilon_inner = configuration_.default_epsilon_inner;
if (epsilon_outer <= 0.0) epsilon_outer = configuration_.default_epsilon_outer; if (epsilon_outer <= 0.0) epsilon_outer = configuration_.default_epsilon_outer;
ROS_DEBUG_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_grasp_srv_callback::Width: " + std::to_string(req.width)); RCLCPP_DEBUG_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_grasp_srv_callback::Width: " + std::to_string(req->width));
ROS_DEBUG_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_grasp_srv_callback::force: " + std::to_string(force) + " speed: " + std::to_string(speed)); RCLCPP_DEBUG_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_grasp_srv_callback::force: " + std::to_string(force) + " speed: " + std::to_string(speed));
bool ret = false; bool ret = false;
bool function_ret = true; bool function_ret = true;
gripper_in_use_.lock();
#ifdef IN_TESTING #ifdef IN_TESTING
ret = true; ret = true;
std::this_thread::sleep_for(std::chrono::milliseconds(2000)); std::this_thread::sleep_for(std::chrono::milliseconds(2000));
#else #else
try try
{ {
ret = gripper_sptr_->grasp(req.width, speed, force, epsilon_inner, epsilon_outer); std::lock_guard<std::mutex> lock(gripper_in_use_);
ret = gripper_sptr_->grasp(req->width, speed, force, epsilon_inner, epsilon_outer);
}catch(franka::CommandException& e) }catch(franka::CommandException& e)
{ {
ROS_ERROR_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_grasp_srv_callback::CommandException::" + e.what()); RCLCPP_ERROR_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_grasp_srv_callback::CommandException::" + std::string(e.what()));
function_ret = false; function_ret = false;
}catch(franka::NetworkException& e) }catch(franka::NetworkException& e)
{ {
ROS_ERROR_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_grasp_srv_callback::NetworkException::" + e.what()); RCLCPP_ERROR_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_grasp_srv_callback::NetworkException::" + std::string(e.what()));
function_ret = false; function_ret = false;
} }
#endif #endif
gripper_in_use_.unlock(); res->set__success(ret);
res.success = ret;
return function_ret; return function_ret;
} }
bool EffectorDriverFrankaHand::_move_srv_callback(sas_robot_driver_franka::Move::Request& req, bool EffectorDriverFrankaHand::_move_srv_callback(const std::shared_ptr<srv::Move::Request> &req, std::shared_ptr<srv::Move::Response> res)
sas_robot_driver_franka::Move::Response& res)
{ {
ROS_DEBUG_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_move_srv_callback::Moving..."); RCLCPP_DEBUG_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_move_srv_callback::Moving...");
auto speed = req.speed; auto speed = req->speed;
if (speed <= 0.0) speed = configuration_.default_speed; if (speed <= 0.0) speed = configuration_.default_speed;
ROS_DEBUG_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_move_srv_callback::Speed: " + std::to_string(speed) + " Width: " + std::to_string(req.width)); RCLCPP_DEBUG_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_move_srv_callback::Speed: " + std::to_string(speed) + " Width: " + std::to_string(req->width));
bool ret = false; bool ret = false;
bool function_ret = true; bool function_ret = true;
gripper_in_use_.lock();
#ifdef IN_TESTING #ifdef IN_TESTING
ret = true; ret = true;
std::this_thread::sleep_for(std::chrono::milliseconds(2000)); std::this_thread::sleep_for(std::chrono::milliseconds(2000));
#else #else
try try
{ {
ret = gripper_sptr_->move(req.width, speed); std::lock_guard<std::mutex> lock(gripper_in_use_);
ret = gripper_sptr_->move(req->width, speed);
}catch(franka::CommandException& e) }catch(franka::CommandException& e)
{ {
ROS_ERROR_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_move_srv_callback::CommandException::" + e.what()); RCLCPP_ERROR_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_move_srv_callback::CommandException::" + std::string(e.what()));
function_ret = false; function_ret = false;
}catch(franka::NetworkException& e) }catch(franka::NetworkException& e)
{ {
ROS_ERROR_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_move_srv_callback::NetworkException::" + e.what()); RCLCPP_ERROR_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_move_srv_callback::NetworkException::" + std::string(e.what()));
function_ret = false; function_ret = false;
} }
#endif #endif
gripper_in_use_.unlock(); res->set__success(ret);
res.success = ret; return function_ret;
}
bool EffectorDriverFrankaHand::_home_srv_callback(const std::shared_ptr<std_srvs::srv::Trigger::Request> &req, std::shared_ptr<std_srvs::srv::Trigger::Response> res)
{
RCLCPP_DEBUG_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_home_srv_callback::Homing...");
bool ret = false;
bool function_ret = true;
#ifdef IN_TESTING
ret = true;
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
#else
try
{
std::lock_guard<std::mutex> lock(gripper_in_use_);
ret = gripper_sptr_->homing();
}catch(franka::CommandException& e)
{
RCLCPP_ERROR_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_home_srv_callback::CommandException::" + std::string(e.what()));
res->set__message("_home_srv_callback::CommandException::" + std::string(e.what()));
function_ret = false;
ret = false;
}catch(franka::NetworkException& e)
{
RCLCPP_ERROR_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_home_srv_callback::NetworkException::" + std::string(e.what()));
res->set__message("_home_srv_callback::NetworkException::" + std::string(e.what()));
function_ret = false;
ret = false;
}
#endif
res->set__success(ret);
return function_ret; return function_ret;
} }
void EffectorDriverFrankaHand::_gripper_status_loop() void EffectorDriverFrankaHand::_gripper_status_loop()
{ {
status_loop_running_ = true; sas::Clock clock = sas::Clock(configuration_.thread_sampeling_time_s);
sas::Clock clock = sas::Clock(configuration_.thread_sampeling_time_ns); RCLCPP_INFO_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_gripper_status_loop::Starting status loop.");
ROS_INFO_STREAM(
"["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_gripper_status_loop::Starting status loop.")
;
clock.init(); clock.init();
try try
{ {
status_loop_running_ = true;
while (status_loop_running_) while (status_loop_running_)
{ {
bool should_unlock = false; if (!_is_connected()) throw std::runtime_error("[" + std::string(node_->get_name())+"]::[EffectorDriverFrankaHand]::_gripper_status_loop::Robot is not connected.");
if (!_is_connected()) throw std::runtime_error(
"[" + ros::this_node::getName() +
"]::[EffectorDriverFrankaHand]::_gripper_status_loop::Robot is not connected.");
try try
{ {
#ifdef IN_TESTING #ifdef IN_TESTING
ROS_WARN_STREAM( RCLCPP_WARN_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_gripper_status_loop::In testing mode.");
"["+ ros::this_node::getName()+ throw std::runtime_error("[" + std::string(node_->get_name())+"]::[EffectorDriverFrankaHand]::_gripper_status_loop::In testing mode.");
"]::[EffectorDriverFrankaHand]::_gripper_status_loop::In testing mode.");
throw std::runtime_error(
"[" + ros::this_node::getName() +
"]::[EffectorDriverFrankaHand]::_gripper_status_loop::In testing mode.");
#endif #endif
msg::GripperState msg;
{
#ifdef BLOCK_READ_IN_USED #ifdef BLOCK_READ_IN_USED
gripper_in_use_.lock(); std::lock_guard<std::mutex> lock(gripper_in_use_);
should_unlock = true;
#endif #endif
franka::GripperState gripper_state = gripper_sptr_->readOnce(); franka::GripperState gripper_state = gripper_sptr_->readOnce();
#ifdef BLOCK_READ_IN_USED msg.set__width(static_cast<float>(gripper_state.width));
gripper_in_use_.unlock(); msg.set__max_width(static_cast<float>(gripper_state.max_width));
#endif msg.set__is_grasped(gripper_state.is_grasped);
sas_robot_driver_franka::GripperState msg; msg.set__temperature(gripper_state.temperature);
msg.width = static_cast<float>(gripper_state.width); msg.set__duration_ms(gripper_state.time.toMSec());
msg.max_width = static_cast<float>(gripper_state.max_width); }
msg.is_grasped = gripper_state.is_grasped; gripper_status_publisher_->publish(msg);
msg.temperature = gripper_state.temperature;
msg.duration_ms = gripper_state.time.toMSec();
gripper_status_publisher_.publish(msg);
} }
catch (...) catch (...)
{ {
#ifdef BLOCK_READ_IN_USED RCLCPP_INFO_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_gripper_status_loop::Could not read gripper state. Unavailable.");
if (should_unlock) gripper_in_use_.unlock(); msg::GripperState msg;
#endif
ROS_INFO_STREAM("["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_gripper_status_loop::Could not read gripper state. Unavailable.");
sas_robot_driver_franka::GripperState msg;
msg.width = 0.0; msg.width = 0.0;
gripper_status_publisher_.publish(msg); gripper_status_publisher_->publish(msg);
} }
clock.update_and_sleep(); clock.update_and_sleep();
@@ -309,19 +327,14 @@ namespace qros
} }
catch (std::exception& e) catch (std::exception& e)
{ {
ROS_ERROR_STREAM( RCLCPP_ERROR_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_gripper_status_loop::Exception::" + std::string(e.what()));
"["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_gripper_status_loop::Exception::" + e.
what());
status_loop_running_ = false; status_loop_running_ = false;
} }
catch (...) catch (...)
{ {
ROS_ERROR_STREAM( RCLCPP_ERROR_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_gripper_status_loop::Exception::Unknown exception.");
"["+ ros::this_node::getName()+
"]::[EffectorDriverFrankaHand]::_gripper_status_loop::Exception::Unknown exception.");
status_loop_running_ = false; status_loop_running_ = false;
} }
ROS_INFO_STREAM( RCLCPP_INFO_STREAM(node_->get_logger(),"::[EffectorDriverFrankaHand]::_gripper_status_loop::Exiting status loop.");
"["+ ros::this_node::getName()+"]::[EffectorDriverFrankaHand]::_gripper_status_loop::Exiting status loop.");
} }
} // qros } // qros

View File

@@ -1,4 +1,33 @@
#include "robot_interface_hand.h" /*
# Copyright (c) 2023 Juan Jose Quiroz Omana
#
# This file is part of sas_robot_driver_franka.
#
# sas_robot_driver_franka is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# sas_robot_driver_franka is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with sas_robot_driver. If not, see <https://www.gnu.org/licenses/>.
#
# ################################################################
#
# Author: Juan Jose Quiroz Omana, email: juanjqogm@gmail.com
#
# ################################################################
#
# Contributors:
# 1. Quenitin Lin
#
# ################################################################
*/
#include <sas_robot_driver_franka/robot_interface_hand.hpp>

View File

@@ -30,10 +30,7 @@
*/ */
#include "robot_interface_franka.h" #include <sas_robot_driver_franka/interfaces/robot_interface_franka.hpp>
#include <ros/this_node.h>
#include <rosconsole/macros_generated.h>
/** /**
@@ -313,6 +310,7 @@ void RobotInterfaceFranka::initialize()
initialize_flag_ = true; initialize_flag_ = true;
// initialize and set the robot to default behavior (collision behavior, impedance, etc) // initialize and set the robot to default behavior (collision behavior, impedance, etc)
// robot_sptr_->setDefaultBehavior();
setDefaultBehavior(*robot_sptr_); setDefaultBehavior(*robot_sptr_);
robot_sptr_->setCollisionBehavior( robot_sptr_->setCollisionBehavior(
franka_configuration_.lower_torque_threshold, franka_configuration_.lower_torque_threshold,

View File

@@ -31,32 +31,34 @@
*/ */
#include "../../include/sas_robot_driver_franka.h" #include <sas_robot_driver_franka/sas_robot_driver_franka.hpp>
#include "sas_clock/sas_clock.h" #include <sas_core/sas_clock.hpp>
#include <dqrobotics/utils/DQ_Math.h> #include <dqrobotics/utils/DQ_Math.h>
#include <ros/this_node.h>
#include <rosconsole/macros_generated.h>
namespace sas namespace sas
{ {
RobotDriverFranka::RobotDriverFranka(qros::RobotDynamicProvider* robot_dynamic_provider, const RobotDriverFrankaConfiguration &configuration, std::atomic_bool *break_loops): RobotDriverFranka::RobotDriverFranka(
const std::shared_ptr<Node> &node,
const std::shared_ptr<qros::RobotDynamicsServer> &robot_dynamic_provider, const RobotDriverFrankaConfiguration &configuration, std::atomic_bool *break_loops
):
RobotDriver(break_loops), RobotDriver(break_loops),
node_(node),
configuration_(configuration), configuration_(configuration),
robot_dynamic_provider_(robot_dynamic_provider), robot_dynamic_provider_sptr_(robot_dynamic_provider),
break_loops_(break_loops) break_loops_(break_loops)
{ {
joint_positions_.resize(7); joint_positions_.resize(7);
joint_velocities_.resize(7); joint_velocities_.resize(7);
joint_forces_.resize(7); joint_torques_.resize(7);
//end_effector_pose_.resize(7); //end_effector_pose_.resize(7);
//joint_positions_buffer_.resize(8,0); //joint_positions_buffer_.resize(8,0);
//end_effector_pose_euler_buffer_.resize(7,0); //end_effector_pose_euler_buffer_.resize(7,0);
//end_effector_pose_homogenous_transformation_buffer_.resize(10,0); //end_effector_pose_homogenous_transformation_buffer_.resize(10,0);
std::cout<<configuration.ip_address<<std::endl; // std::cout<<configuration.ip_address<<std::endl;
RobotInterfaceFranka::MODE mode = RobotInterfaceFranka::MODE::None; RobotInterfaceFranka::MODE mode = RobotInterfaceFranka::MODE::None;
RCLCPP_INFO_STREAM(node_->get_logger(), "Mode: " << configuration_.mode);
std::cout<<configuration.mode<<std::endl;
if (configuration_.mode == std::string("None")) if (configuration_.mode == std::string("None"))
{ {
@@ -90,7 +92,7 @@ namespace sas
Vector3d force, torque; Vector3d force, torque;
std::tie(force, torque) = robot_driver_interface_sptr_->get_stiffness_force_torque(); std::tie(force, torque) = robot_driver_interface_sptr_->get_stiffness_force_torque();
const auto pose = robot_driver_interface_sptr_->get_stiffness_pose(); const auto pose = robot_driver_interface_sptr_->get_stiffness_pose();
robot_dynamic_provider_->publish_stiffness(pose, force, torque); robot_dynamic_provider_sptr_->publish_stiffness(pose, force, torque);
} }
@@ -143,9 +145,16 @@ namespace sas
VectorXd RobotDriverFranka::get_joint_positions() VectorXd RobotDriverFranka::get_joint_positions()
{ {
if(robot_driver_interface_sptr_->get_err_state()) { if(robot_driver_interface_sptr_->get_err_state()) {
ROS_ERROR_STREAM("["+ros::this_node::getName()+"]::driver interface error on:"+robot_driver_interface_sptr_->get_status_message()); RCLCPP_ERROR_STREAM(node_->get_logger(),
"["+std::string(node_->get_name())+"]::driver interface "
"error on:"+robot_driver_interface_sptr_->get_status_message());
break_loops_->store(true); break_loops_->store(true);
} }
if(!ok()) {
RCLCPP_WARN_STREAM(node_->get_logger(),
"["+std::string(node_->get_name())+"]::driver interface exit on shotdown signal recieved."
);
}
_update_stiffness_contact_and_pose(); _update_stiffness_contact_and_pose();
return robot_driver_interface_sptr_->get_joint_positions(); return robot_driver_interface_sptr_->get_joint_positions();
} }
@@ -160,7 +169,9 @@ namespace sas
{ {
robot_driver_interface_sptr_->set_target_joint_positions(desired_joint_positions_rad); robot_driver_interface_sptr_->set_target_joint_positions(desired_joint_positions_rad);
if(robot_driver_interface_sptr_->get_err_state()) { if(robot_driver_interface_sptr_->get_err_state()) {
ROS_ERROR_STREAM("["+ros::this_node::getName()+"]::driver interface error on:"+robot_driver_interface_sptr_->get_status_message()); RCLCPP_ERROR_STREAM(node_->get_logger(),
"["+std::string(node_->get_name())+"]::driver interface "
"error on:"+robot_driver_interface_sptr_->get_status_message());
break_loops_->store(true); break_loops_->store(true);
} }
} }
@@ -182,10 +193,12 @@ namespace sas
*/ */
void RobotDriverFranka::set_target_joint_velocities(const VectorXd &desired_joint_velocities) void RobotDriverFranka::set_target_joint_velocities(const VectorXd &desired_joint_velocities)
{ {
desired_joint_velocities_ = desired_joint_velocities; // desired_joint_velocities_ = desired_joint_velocities;
robot_driver_interface_sptr_->set_target_joint_velocities(desired_joint_velocities); robot_driver_interface_sptr_->set_target_joint_velocities(desired_joint_velocities);
if(robot_driver_interface_sptr_->get_err_state()) { if(robot_driver_interface_sptr_->get_err_state()) {
ROS_ERROR_STREAM("["+ros::this_node::getName()+"]::driver interface error on:"+robot_driver_interface_sptr_->get_status_message()); RCLCPP_ERROR_STREAM(node_->get_logger(),
"["+std::string(node_->get_name())+"]::driver interface "
"error on:"+robot_driver_interface_sptr_->get_status_message());
break_loops_->store(true); break_loops_->store(true);
} }
} }
@@ -194,10 +207,10 @@ namespace sas
* @brief RobotDriverFranka::get_joint_forces * @brief RobotDriverFranka::get_joint_forces
* @return * @return
*/ */
VectorXd RobotDriverFranka::get_joint_forces() VectorXd RobotDriverFranka::get_joint_torques()
{ {
joint_forces_ = robot_driver_interface_sptr_->get_joint_forces(); joint_torques_ = robot_driver_interface_sptr_->get_joint_forces();
return joint_forces_; return joint_torques_;
} }
} }

View File

@@ -0,0 +1,102 @@
/*
# Copyright (c) 2024 Quenitin Lin
#
# This file is part of sas_robot_driver_franka.
#
# sas_robot_driver_franka is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# sas_robot_driver_franka is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with sas_robot_driver. If not, see <https://www.gnu.org/licenses/>.
#
# ################################################################
#
# Author: Quenitin Lin
#
# ################################################################
#
# Contributors:
# 1. Quenitin Lin
#
# ################################################################
*/
#include <memory>
#include <sas_robot_driver_franka/robot_dynamic/qros_robot_dynamics_client.hpp>
using namespace qros;
RobotDynamicsClient::RobotDynamicsClient(const std::shared_ptr<Node> &node, const std::string& topic_prefix):
node_(node), topic_prefix_(topic_prefix == "GET_FROM_NODE"? node->get_name() : topic_prefix),
child_frame_id_(topic_prefix_ + "_stiffness_frame"), parent_frame_id_(topic_prefix_ + "_base"),
last_stiffness_force_(Vector3d::Zero()),
last_stiffness_torque_(Vector3d::Zero()),
last_stiffness_frame_pose_(0)
{
tf_buffer_ = std::make_unique<tf2_ros::Buffer>(node->get_clock());
tf_listener_ = std::make_shared<tf2_ros::TransformListener>(*tf_buffer_);
// Strip potential leading slash
if(child_frame_id_.front() == '/'){child_frame_id_ = child_frame_id_.substr(1);}
if(parent_frame_id_.front() == '/'){parent_frame_id_ = parent_frame_id_.substr(1);}
RCLCPP_INFO_STREAM(node_->get_logger(),
"["+ std::string(node_->get_name()) + "]::Initializing RobotDynamicsClient with prefix " + topic_prefix);
subscriber_cartesian_stiffness_ = node_->create_subscription<geometry_msgs::msg::WrenchStamped>(topic_prefix + "/get/cartesian_stiffness", 1,
std::bind(&RobotDynamicsClient::_callback_cartesian_stiffness, this, std::placeholders::_1)
);
}
void RobotDynamicsClient::_callback_cartesian_stiffness(const geometry_msgs::msg::WrenchStamped &msg)
{
last_stiffness_force_(0) = msg.wrench.force.x;
last_stiffness_force_(1) = msg.wrench.force.y;
last_stiffness_force_(2) = msg.wrench.force.z;
last_stiffness_torque_(0) = msg.wrench.torque.x;
last_stiffness_torque_(1) = msg.wrench.torque.y;
last_stiffness_torque_(2) = msg.wrench.torque.z;
try {
const auto transform_stamped = tf_buffer_->lookupTransform( parent_frame_id_, child_frame_id_, tf2::TimePointZero);
last_stiffness_frame_pose_ = _geometry_msgs_transform_to_dq(transform_stamped.transform);
} catch (tf2::TransformException &ex) {
RCLCPP_WARN_STREAM(node_->get_logger(), "["+ std::string(node_->get_name()) + "]::" + ex.what());
}
}
DQ RobotDynamicsClient::_geometry_msgs_transform_to_dq(const geometry_msgs::msg::Transform& transform)
{
const auto t = DQ(0,transform.translation.x,transform.translation.y,transform.translation.z);
const auto r = DQ(transform.rotation.w, transform.rotation.x, transform.rotation.y, transform.rotation.z);
return r + 0.5 * E_ * t * r;
}
VectorXd RobotDynamicsClient::get_stiffness_force()
{
if(!is_enabled()) throw std::runtime_error("[RobotDynamicsClient]::calling get_stiffness_force on uninitialized topic");
return last_stiffness_force_;
}
VectorXd RobotDynamicsClient::get_stiffness_torque()
{
if(!is_enabled()) throw std::runtime_error("[RobotDynamicsClient]::calling get_stiffness_torque on uninitialized topic");
return last_stiffness_torque_;
}
DQ RobotDynamicsClient::get_stiffness_frame_pose()
{
if(!is_enabled()) throw std::runtime_error("[RobotDynamicsClient]::calling get_stiffness_frame_pose on uninitialized Interface");
return last_stiffness_frame_pose_;
}
bool RobotDynamicsClient::is_enabled() const
{
if(last_stiffness_frame_pose_==0) return false;
return true;
}

View File

@@ -1,103 +0,0 @@
/*
# Copyright (c) 2023 Juan Jose Quiroz Omana
#
# This file is part of sas_robot_driver_franka.
#
# sas_robot_driver_franka is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# sas_robot_driver_franka is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with sas_robot_driver. If not, see <https://www.gnu.org/licenses/>.
#
# ################################################################
#
# Author: Juan Jose Quiroz Omana, email: juanjqogm@gmail.com
#
# ################################################################
#
# Contributors:
# 1. Quenitin Lin
#
# ################################################################
*/
#include <robot_dynamic/qros_robot_dynamics_interface.h>
using namespace qros;
RobotDynamicInterface::RobotDynamicInterface(ros::NodeHandle &nodehandle, const std::string &node_prefix):
RobotDynamicInterface(nodehandle, nodehandle, node_prefix)
{
//Delegated
}
RobotDynamicInterface::RobotDynamicInterface(ros::NodeHandle &publisher_nodehandle, ros::NodeHandle &subscriber_nodehandle, const std::string &node_prefix):
node_prefix_(node_prefix),
child_frame_id_(node_prefix + "_stiffness_frame"),
parent_frame_id_(node_prefix + "_base"),
tf_buffer_(ros::Duration(BUFFER_DURATION_DEFAULT_S)),
tf_listener_(tf_buffer_, subscriber_nodehandle),
last_stiffness_force_(Vector3d::Zero()),
last_stiffness_torque_(Vector3d::Zero()),
last_stiffness_frame_pose_(0)
{
// Strip potential leading slash
if(child_frame_id_.front() == '/'){child_frame_id_ = child_frame_id_.substr(1);}
if(parent_frame_id_.front() == '/'){parent_frame_id_ = parent_frame_id_.substr(1);}
ROS_INFO_STREAM(ros::this_node::getName() + "::Initializing RobotDynamicInterface with prefix " + node_prefix);
subscriber_cartesian_stiffness_ = subscriber_nodehandle.subscribe(node_prefix_ + "/get/cartesian_stiffness", 1, &RobotDynamicInterface::_callback_cartesian_stiffness, this);
}
void RobotDynamicInterface::_callback_cartesian_stiffness(const geometry_msgs::WrenchStampedConstPtr &msg)
{
last_stiffness_force_(0) = msg->wrench.force.x;
last_stiffness_force_(1) = msg->wrench.force.y;
last_stiffness_force_(2) = msg->wrench.force.z;
last_stiffness_torque_(0) = msg->wrench.torque.x;
last_stiffness_torque_(1) = msg->wrench.torque.y;
last_stiffness_torque_(2) = msg->wrench.torque.z;
try {
const auto transform_stamped = tf_buffer_.lookupTransform( parent_frame_id_, child_frame_id_, ros::Time(0));
last_stiffness_frame_pose_ = _geometry_msgs_transform_to_dq(transform_stamped.transform);
} catch (tf2::TransformException &ex) {
ROS_WARN_STREAM(ros::this_node::getName() + "::" + ex.what());
}
}
DQ RobotDynamicInterface::_geometry_msgs_transform_to_dq(const geometry_msgs::Transform& transform)
{
const auto t = DQ(0,transform.translation.x,transform.translation.y,transform.translation.z);
const auto r = DQ(transform.rotation.w, transform.rotation.x, transform.rotation.y, transform.rotation.z);
return r + 0.5 * E_ * t * r;
}
VectorXd RobotDynamicInterface::get_stiffness_force()
{
if(!is_enabled()) throw std::runtime_error("[RobotDynamicInterface]::calling get_stiffness_force on uninitialized topic");
return last_stiffness_force_;
}
VectorXd RobotDynamicInterface::get_stiffness_torque()
{
if(!is_enabled()) throw std::runtime_error("[RobotDynamicInterface]::calling get_stiffness_torque on uninitialized topic");
return last_stiffness_torque_;
}
DQ RobotDynamicInterface::get_stiffness_frame_pose()
{
if(!is_enabled()) throw std::runtime_error("[RobotDynamicInterface]::calling get_stiffness_frame_pose on uninitialized Interface");
return last_stiffness_frame_pose_;
}
bool RobotDynamicInterface::is_enabled() const
{
if(last_stiffness_frame_pose_==0) return false;
return true;
}

View File

@@ -1,126 +0,0 @@
/*
# Copyright (c) 2023 Juan Jose Quiroz Omana
#
# This file is part of sas_robot_driver_franka.
#
# sas_robot_driver_franka is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# sas_robot_driver_franka is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with sas_robot_driver. If not, see <https://www.gnu.org/licenses/>.
#
# ################################################################
#
# Author: Juan Jose Quiroz Omana, email: juanjqogm@gmail.com
#
# ################################################################
#
# Contributors:
# 1. Quenitin Lin
#
# ################################################################
*/
#include <robot_dynamic/qros_robot_dynamics_provider.h>
using namespace qros;
RobotDynamicProvider::RobotDynamicProvider(ros::NodeHandle &nodehandle, const std::string &node_prefix):
RobotDynamicProvider(nodehandle, nodehandle, node_prefix)
{
//Delegated
}
RobotDynamicProvider::RobotDynamicProvider(ros::NodeHandle &publisher_nodehandle, ros::NodeHandle &subscriber_nodehandle, const std::string &node_prefix):
node_prefix_(node_prefix),
child_frame_id_(node_prefix + "_stiffness_frame"),
parent_frame_id_(node_prefix + "_base"),
world_to_base_tf_(0)
{
// Strip potential leading slash
if(child_frame_id_.front() == '/'){child_frame_id_ = child_frame_id_.substr(1);}
if(parent_frame_id_.front() == '/'){parent_frame_id_ = parent_frame_id_.substr(1);}
ROS_INFO_STREAM(ros::this_node::getName() + "::Initializing RobotDynamicProvider with prefix " + node_prefix);
publisher_cartesian_stiffness_ = publisher_nodehandle.advertise<geometry_msgs::WrenchStamped>(node_prefix + "/get/cartesian_stiffness", 1);
}
geometry_msgs::Transform RobotDynamicProvider::_dq_to_geometry_msgs_transform(const DQ& pose)
{
geometry_msgs::Transform tf_msg;
const auto t = translation(pose);
const auto r = rotation(pose);
tf_msg.translation.x = t.q(1);
tf_msg.translation.y = t.q(2);
tf_msg.translation.z = t.q(3);
tf_msg.rotation.w = r.q(0);
tf_msg.rotation.x = r.q(1);
tf_msg.rotation.y = r.q(2);
tf_msg.rotation.z = r.q(3);
return tf_msg;
}
void RobotDynamicProvider::set_world_to_base_tf(const DQ& world_to_base_tf)
{
if(world_to_base_tf_==0)
{
world_to_base_tf_ = world_to_base_tf;
_publish_base_static_tf();
}else
{
throw std::runtime_error("The world to base transform has already been set");
}
}
void RobotDynamicProvider::_publish_base_static_tf()
{
geometry_msgs::TransformStamped base_tf;
base_tf.transform = _dq_to_geometry_msgs_transform(world_to_base_tf_);
base_tf.header.stamp = ros::Time::now();
base_tf.header.frame_id = WORLD_FRAME_ID;
base_tf.child_frame_id = parent_frame_id_;
static_base_tf_broadcaster_.sendTransform(base_tf);
}
void RobotDynamicProvider::publish_stiffness(const DQ& base_to_stiffness, const Vector3d& force, const Vector3d& torque)
{
std_msgs::Header header;
header.stamp = ros::Time::now();
header.seq = seq_++;
geometry_msgs::WrenchStamped msg;
msg.header = header;
msg.header.frame_id = child_frame_id_;
msg.wrench.force.x = force(0);
msg.wrench.force.y = force(1);
msg.wrench.force.z = force(2);
msg.wrench.torque.x = torque(0);
msg.wrench.torque.y = torque(1);
msg.wrench.torque.z = torque(2);
publisher_cartesian_stiffness_.publish(msg);
if(seq_ % REDUCE_TF_PUBLISH_RATE == 0)
{
geometry_msgs::TransformStamped tf_msg;
tf_msg.transform = _dq_to_geometry_msgs_transform(base_to_stiffness);
tf_msg.header = header;
tf_msg.header.frame_id = parent_frame_id_;
tf_msg.child_frame_id = child_frame_id_;
tf_broadcaster_.sendTransform(tf_msg);
}
}
bool RobotDynamicProvider::is_enabled() const
{
return true; //Always enabled
}

View File

@@ -32,29 +32,29 @@
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/eigen.h> #include <pybind11/eigen.h>
#include <robot_dynamic/qros_robot_dynamics_provider.h> #include <sas_robot_driver_franka/robot_dynamic/qros_robot_dynamics_client.hpp>
#include <robot_dynamic/qros_robot_dynamics_interface.h> #include <sas_robot_driver_franka/robot_dynamic/qros_robot_dynamics_server.hpp>
namespace py = pybind11; namespace py = pybind11;
using RDI = qros::RobotDynamicInterface; using RDC = qros::RobotDynamicsClient;
using RDP = qros::RobotDynamicProvider; using RDS = qros::RobotDynamicsServer;
PYBIND11_MODULE(_qros_robot_dynamic, m) PYBIND11_MODULE(_qros_franka_robot_dynamics_py, m)
{ {
py::class_<RDI>(m, "RobotDynamicsInterface") py::class_<RDC>(m, "RobotDynamicsClient")
.def(py::init<const std::string&>()) .def(py::init<const std::shared_ptr<rclcpp::Node>&,const std::string&>())
.def("get_stiffness_force",&RDI::get_stiffness_force) .def("get_stiffness_force",&RDC::get_stiffness_force)
.def("get_stiffness_torque",&RDI::get_stiffness_torque) .def("get_stiffness_torque",&RDC::get_stiffness_torque)
.def("get_stiffness_frame_pose",&RDI::get_stiffness_frame_pose) .def("get_stiffness_frame_pose",&RDC::get_stiffness_frame_pose)
.def("is_enabled",&RDI::is_enabled,"Returns true if the RobotDynamicInterface is enabled.") .def("is_enabled",&RDC::is_enabled,"Returns true if the RobotDynamicInterface is enabled.")
.def("get_topic_prefix",&RDI::get_topic_prefix); .def("get_topic_prefix",&RDC::get_topic_prefix);
py::class_<RDP>(m, "RobotDynamicsProvider") py::class_<RDS>(m, "RobotDynamicsServer")
.def(py::init<const std::string&>()) .def(py::init<const std::shared_ptr<rclcpp::Node>&,const std::string&>())
.def("publish_stiffness",&RDP::publish_stiffness) .def("publish_stiffness",&RDS::publish_stiffness)
.def("set_world_to_base_tf", &RDP::set_world_to_base_tf) .def("set_world_to_base_tf", &RDS::set_world_to_base_tf)
.def("is_enabled",&RDP::is_enabled,"Returns true if the RobotDynamicProvider is enabled.") .def("is_enabled",&RDS::is_enabled,"Returns true if the RobotDynamicProvider is enabled.")
.def("get_topic_prefix",&RDP::get_topic_prefix); .def("get_topic_prefix",&RDS::get_topic_prefix);
} }

View File

@@ -0,0 +1,120 @@
/*
# Copyright (c) 2024 Quenitin Lin
#
# This file is part of sas_robot_driver_franka.
#
# sas_robot_driver_franka is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# sas_robot_driver_franka is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with sas_robot_driver. If not, see <https://www.gnu.org/licenses/>.
#
# ################################################################
#
# Author: Quenitin Lin
#
# ################################################################
#
# Contributors:
# 1. Quenitin Lin
#
# ################################################################
*/
#include <sas_robot_driver_franka/robot_dynamic/qros_robot_dynamics_server.hpp>
using namespace qros;
RobotDynamicsServer::RobotDynamicsServer(const std::shared_ptr<Node> &node, const std::string& topic_prefix):
node_(node), topic_prefix_(topic_prefix == "GET_FROM_NODE"? node->get_name() : topic_prefix),
child_frame_id_(topic_prefix_ + "_stiffness_frame"), parent_frame_id_(topic_prefix_ + "_base"),
tf_broadcaster_(std::make_shared<tf2_ros::TransformBroadcaster>(node_)),
static_base_tf_broadcaster_(std::make_shared<tf2_ros::StaticTransformBroadcaster>(node_)),
world_to_base_tf_(0)
{
// Strip potential leading slash
if(child_frame_id_.front() == '/'){child_frame_id_ = child_frame_id_.substr(1);}
if(parent_frame_id_.front() == '/'){parent_frame_id_ = parent_frame_id_.substr(1);}
RCLCPP_INFO_STREAM(node_->get_logger(),
"["+ std::string(node_->get_name()) + "]::Initializing RobotDynamicsServer with prefix " + topic_prefix);
publisher_cartesian_stiffness_ = node_->create_publisher<geometry_msgs::msg::WrenchStamped>(topic_prefix + "/get/cartesian_stiffness", 1);
}
geometry_msgs::msg::Transform RobotDynamicsServer::_dq_to_geometry_msgs_transform(const DQ& pose)
{
geometry_msgs::msg::Transform tf_msg;
const auto t = translation(pose);
const auto r = rotation(pose);
tf_msg.translation.x = t.q(1);
tf_msg.translation.y = t.q(2);
tf_msg.translation.z = t.q(3);
tf_msg.rotation.w = r.q(0);
tf_msg.rotation.x = r.q(1);
tf_msg.rotation.y = r.q(2);
tf_msg.rotation.z = r.q(3);
return tf_msg;
}
void RobotDynamicsServer::set_world_to_base_tf(const DQ& world_to_base_tf)
{
if(world_to_base_tf_==0)
{
world_to_base_tf_ = world_to_base_tf;
_publish_base_static_tf();
}else
{
throw std::runtime_error("["+ std::string(node_->get_name()) + "]::[RobotDynamicsServer]::The world to base transform has already been set");
}
}
void RobotDynamicsServer::_publish_base_static_tf()
{
geometry_msgs::msg::TransformStamped base_tf;
base_tf.set__transform(_dq_to_geometry_msgs_transform(world_to_base_tf_));
std_msgs::msg::Header header;
header.set__stamp(node_->now());
header.set__frame_id(WORLD_FRAME_ID);
base_tf.set__header(header);
base_tf.set__child_frame_id(parent_frame_id_);
static_base_tf_broadcaster_->sendTransform(base_tf);
}
void RobotDynamicsServer::publish_stiffness(const DQ& base_to_stiffness, const Vector3d& force, const Vector3d& torque)
{
std_msgs::msg::Header header;
header.set__stamp(node_->now());
geometry_msgs::msg::WrenchStamped msg;
msg.set__header(header);
msg.header.set__frame_id(child_frame_id_);
msg.wrench.force.set__x(force(0));
msg.wrench.force.set__y(force(1));
msg.wrench.force.set__z(force(2));
msg.wrench.torque.set__x(torque(0));
msg.wrench.torque.set__y(torque(1));
msg.wrench.torque.set__z(torque(2));
publisher_cartesian_stiffness_->publish(msg);
if(seq_ % REDUCE_TF_PUBLISH_RATE == 0)
{
header.set__frame_id(parent_frame_id_);
geometry_msgs::msg::TransformStamped tf_msg;
tf_msg.set__transform(_dq_to_geometry_msgs_transform(base_to_stiffness));
tf_msg.set__header(header);
tf_msg.set__child_frame_id(child_frame_id_);
tf_broadcaster_->sendTransform(tf_msg);
}
}
bool RobotDynamicsServer::is_enabled() const
{
return true; //Always enabled
}

View File

@@ -26,6 +26,9 @@
# 1. Juan Jose Quiroz Omana (juanjqogm@gmail.com) # 1. Juan Jose Quiroz Omana (juanjqogm@gmail.com)
# - Adapted from sas_robot_driver_denso_node.cpp # - Adapted from sas_robot_driver_denso_node.cpp
# (https://github.com/SmartArmStack/sas_robot_driver_denso/blob/master/src/sas_robot_driver_denso_node.cpp) # (https://github.com/SmartArmStack/sas_robot_driver_denso/blob/master/src/sas_robot_driver_denso_node.cpp)
# 2. Quentin Lin (qlin1806@g.ecc.u-tokyo.ac.jp)
# - Adapted for simplify operation
# - porting to ROS2
# #
# ################################################################ # ################################################################
*/ */
@@ -36,10 +39,9 @@
#include <exception> #include <exception>
#include <dqrobotics/utils/DQ_Math.h> #include <dqrobotics/utils/DQ_Math.h>
//#include <dqrobotics/interfaces/json11/DQ_JsonReader.h> //#include <dqrobotics/interfaces/json11/DQ_JsonReader.h>
#include <sas_common/sas_common.h> #include <sas_common/sas_common.hpp>
#include <sas_conversions/eigen3_std_conversions.h> #include <sas_conversions/eigen3_std_conversions.hpp>
#include <sas_robot_driver/sas_robot_driver_ros.h> #include <sas_robot_driver_franka/coppelia/sas_robot_driver_coppelia.hpp>
#include "coppelia/sas_robot_driver_coppelia.h"
/********************************************* /*********************************************
* SIGNAL HANDLER * SIGNAL HANDLER
@@ -52,52 +54,51 @@ void sig_int_handler(int)
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
if(signal(SIGINT, sig_int_handler) == SIG_ERR) if(signal(SIGINT, sig_int_handler) == SIG_ERR)
{ {
throw std::runtime_error(ros::this_node::getName() + "::Error setting the signal int handler."); throw std::runtime_error("Error setting the signal int handler.");
} }
ros::init(argc, argv, "sas_robot_driver_coppelia_node", ros::init_options::NoSigintHandler); rclcpp::init(argc,argv,rclcpp::InitOptions(),rclcpp::SignalHandlerOptions::None);
ROS_WARN("====================================================================="); auto context = rclcpp::contexts::get_global_default_context();
ROS_WARN("----------------------Juan Jose Quiroz Omana------------------------");
ROS_WARN("====================================================================="); auto node = std::make_shared<rclcpp::Node>("sas_robot_driver_franka_coppelia_node");
ROS_INFO_STREAM(ros::this_node::getName()+"::Loading parameters from parameter server.");
const auto node_name = std::string(node->get_name());
RCLCPP_WARN(node->get_logger(),"=====================================================================");
RCLCPP_WARN(node->get_logger(),"-----------------Adapted by Quentin Lin ------------------------");
RCLCPP_WARN(node->get_logger(),"=====================================================================");
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),":Loading parameters from parameter server.");
ros::NodeHandle nh; qros::RobotDriverCoppeliaConfiguration robot_driver_coppelia_configuration;
sas::RobotDriverCoppeliaConfiguration robot_driver_coppelia_configuration; sas::get_ros_parameter(node,"thread_sampling_time_sec",robot_driver_coppelia_configuration.thread_sampling_time_sec);
sas::get_ros_parameter(node,"vrep_ip",robot_driver_coppelia_configuration.vrep_ip);
sas::get_ros_param(nh,"/robot_ip_address",robot_driver_coppelia_configuration.ip); sas::get_ros_parameter(node,"vrep_port",robot_driver_coppelia_configuration.vrep_port);
sas::get_ros_param(nh,"/robot_mode", robot_driver_coppelia_configuration.robot_mode); sas::get_ros_parameter(node,"vrep_joint_names", robot_driver_coppelia_configuration.vrep_joint_names);
sas::get_ros_param(nh,"/vrep_port", robot_driver_coppelia_configuration.port); sas::get_ros_parameter(node,"vrep_dynamically_enabled", robot_driver_coppelia_configuration.vrep_dynamically_enabled);
sas::get_ros_param(nh,"/vrep_robot_joint_names", robot_driver_coppelia_configuration.jointnames); sas::get_ros_parameter(node,"robot_mode", robot_driver_coppelia_configuration.robot_mode);
sas::get_ros_param(nh,"/mirror_mode", robot_driver_coppelia_configuration.mirror_mode); sas::get_ros_parameter(node,"using_real_robot", robot_driver_coppelia_configuration.using_real_robot);
sas::get_ros_param(nh, "/real_robot_topic_prefix", robot_driver_coppelia_configuration.real_robot_topic_prefix); sas::get_ros_parameter(node,"robot_topic_prefix", robot_driver_coppelia_configuration.robot_topic_prefix);
sas::RobotDriverROSConfiguration robot_driver_ros_configuration; sas::get_ros_parameter(node,"robot_parameter_file_path", robot_driver_coppelia_configuration.robot_parameter_file_path);
sas::get_ros_param(nh,"/thread_sampling_time_nsec",robot_driver_ros_configuration.thread_sampling_time_nsec);
sas::get_ros_param(nh,"/q_min",robot_driver_ros_configuration.q_min);
sas::get_ros_param(nh,"/q_max",robot_driver_ros_configuration.q_max);
robot_driver_ros_configuration.robot_driver_provider_prefix = ros::this_node::getName();
try try
{ {
ROS_INFO_STREAM(ros::this_node::getName()+"::Instantiating Coppelia robot."); RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"::Instantiating Coppelia robot mirror.");
sas::RobotDriverCoppelia robot_driver_coppelia(robot_driver_coppelia_configuration, qros::RobotDriverCoppelia robot_driver_coppelia(node, robot_driver_coppelia_configuration,
&kill_this_process); &kill_this_process);
ROS_INFO_STREAM(ros::this_node::getName()+"::Instantiating RobotDriverROS.");
sas::RobotDriverROS robot_driver_ros(nh, return robot_driver_coppelia.start_control_loop();
&robot_driver_coppelia,
robot_driver_ros_configuration,
&kill_this_process);
robot_driver_ros.control_loop();
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
ROS_ERROR_STREAM(ros::this_node::getName() + "::Exception::" + e.what()); kill_this_process = true;
RCLCPP_ERROR_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Exception::" + e.what());
shutdown(context, "Exception in main function: " + std::string(e.what()));
return -1;
} }

View File

@@ -1,4 +0,0 @@
"""
"""
from _qros_robot_dynamic import RobotDynamicsInterface, RobotDynamicsProvider
from .franka_gripper_interface import FrankaGripperInterface

View File

@@ -1,182 +0,0 @@
import rospy
from sas_robot_driver_franka.srv import Move, MoveRequest, MoveResponse, Grasp, GraspRequest, GraspResponse
from sas_robot_driver_franka.msg import GripperState
import os
import threading
from queue import Queue
import struct
MOVE_TOPIC_SUFFIX = "move"
GRASP_TOPIC_SUFFIX = "grasp"
STATUS_TOPIC_SUFFIX = "gripper_status"
class FrankaGripperInterface:
"""
Non blocking interface to control the Franka gripper
"""
def __init__(self, robot_prefix):
self.robot_prefix = robot_prefix
self.move_service = rospy.ServiceProxy(os.path.join(robot_prefix, MOVE_TOPIC_SUFFIX), Move)
self._moving = False
self.grasp_service = rospy.ServiceProxy(os.path.join(robot_prefix, GRASP_TOPIC_SUFFIX), Grasp)
self._grasping = False
self.status_subscriber = rospy.Subscriber(os.path.join(robot_prefix, STATUS_TOPIC_SUFFIX), GripperState,
self._status_callback)
self.result_queue = Queue()
# gripper state
self.state_width = None
self.state_max_width = None
self.state_temperature = None
self.state_is_grasped = None
def _is_service_ready(self, service):
try:
rospy.wait_for_service(service, timeout=0.1)
return True
except rospy.ROSException:
return False
def is_enabled(self):
if self.state_width is None:
return False
if not self._is_service_ready(self.move_service.resolved_name):
return False
if not self._is_service_ready(self.grasp_service.resolved_name):
return False
return True
def _status_callback(self, msg: GripperState):
self.state_width = msg.width
self.state_max_width = msg.max_width
self.state_temperature = msg.temperature
self.state_is_grasped = msg.is_grasped
def move(self, width, speed=0):
"""
Move the gripper to a specific width
:param width: width in meters
:param speed: speed in meters per second
:return: None
"""
if self.is_busy():
raise Exception("Gripper is already moving or grasping, please wait until the previous action is finished")
threading.Thread(target=self._move, args=(width, speed)).start()
def grasp(self, width, force=0, speed=0, epsilon_inner=0, epsilon_outer=0):
"""
Grasp an object with the gripper
:param width:
:param force:
:param speed:
:param epsilon_inner:
:param epsilon_outer:
:return:
"""
if self.is_busy():
raise Exception("Gripper is already moving or grasping, please wait until the previous action is finished")
threading.Thread(target=self._grasp, args=(width, force, speed, epsilon_inner, epsilon_outer)).start()
def get_max_width(self):
""" Get the maximum width of the gripper """
if not self.is_enabled():
raise Exception("Gripper is not enabled")
return self.state_max_width
def get_width(self):
""" Get the current width of the gripper """
if not self.is_enabled():
raise Exception("Gripper is not enabled")
return self.state_width
def get_temperature(self):
""" Get the temperature of the gripper """
if not self.is_enabled():
raise Exception("Gripper is not enabled")
return self.state_temperature
def is_grasped(self):
""" Check if an object is grasped """
if not self.is_enabled():
raise Exception("Gripper is not enabled")
return self.state_is_grasped
def is_moving(self):
""" Check if the gripper is currently moving """
return self._moving
def is_grasping(self):
""" Check if the gripper is currently grasping """
return self._grasping
def is_busy(self):
""" Check if the gripper is currently moving or grasping """
return self._moving or self._grasping
def is_done(self):
""" Check if the gripper is done moving or grasping """
if not self.is_busy():
rospy.logwarn("Gripper is not moving or grasping")
return False
else:
if self.result_queue.empty():
return False
else:
return True
def get_result(self):
"""
Get the result of the last action
:return:
"""
if not self.result_queue.empty():
response = self.result_queue.get()
self._moving = False
self._grasping = False
return response.success
else:
raise Exception("No result available")
def wait_until_done(self):
"""
Wait until the gripper is done moving or grasping
:return: success
"""
if not self.is_enabled():
raise Exception("Gripper is not enabled")
if not self._moving and not self._grasping:
raise Exception("Gripper is not moving or grasping")
while self._moving or self._grasping:
rospy.sleep(0.1)
if not self.result_queue.empty():
response = self.result_queue.get()
if isinstance(response, MoveResponse):
self._moving = False
elif isinstance(response, GraspResponse):
self._grasping = False
else:
raise Exception("Invalid response type")
break
return response.success
def _move(self, width, speed):
self._moving = True
request = MoveRequest()
request.width = width
request.speed = speed
response = self.move_service(request)
self.result_queue.put(response)
def _grasp(self, width, force, speed, epsilon_inner, epsilon_outer):
self._grasping = True
request = GraspRequest()
request.width = width
request.force = force
request.speed = speed
request.epsilon_inner = epsilon_inner
request.epsilon_outer = epsilon_outer
response = self.grasp_service(request)
self.result_queue.put(response)

View File

@@ -33,10 +33,9 @@
#include <exception> #include <exception>
#include <dqrobotics/utils/DQ_Math.h> #include <dqrobotics/utils/DQ_Math.h>
#include <sas_common/sas_common.h> #include <sas_common/sas_common.hpp>
#include <sas_conversions/eigen3_std_conversions.h> // #include <sas_conversions/eigen3_std_conversions.hpp>
#include <sas_robot_driver/sas_robot_driver_ros.h> #include <sas_robot_driver_franka/interfaces/qros_effector_driver_franka_hand.hpp>
#include "hand/qros_effector_driver_franka_hand.h"
/********************************************* /*********************************************
@@ -52,14 +51,14 @@ void sig_int_handler(int)
template<typename T> template<typename T>
void get_optional_parameter(const std::string &node_prefix, ros::NodeHandle &nh, const std::string &param_name, T &param) void get_optional_parameter(std::shared_ptr<Node> node, const std::string &param_name, T &param)
{ {
if(nh.hasParam(node_prefix + param_name)) try
{ {
sas::get_ros_param(nh,param_name,param); sas::get_ros_parameter(node,param_name,param);
}else }catch (const std::exception& e)
{ {
ROS_INFO_STREAM(ros::this_node::getName() + "::Parameter " + param_name + " not found. Using default value. " + std::to_string(param)); RCLCPP_INFO_STREAM(node->get_logger(), "["+std::string(node->get_name())+"]:Parameter " + param_name + " not found. Using default value. " + std::to_string(param));
} }
} }
@@ -69,55 +68,54 @@ int main(int argc, char **argv)
{ {
if(signal(SIGINT, sig_int_handler) == SIG_ERR) if(signal(SIGINT, sig_int_handler) == SIG_ERR)
{ {
throw std::runtime_error(ros::this_node::getName() + "::Error setting the signal int handler."); throw std::runtime_error("Error setting the signal int handler.");
} }
ros::init(argc, argv, "sas_robot_driver_franka_hand_node", ros::init_options::NoSigintHandler);
ROS_WARN("=====================================================================");
ROS_WARN("---------------------------Quentin Lin-------------------------------");
ROS_WARN("=====================================================================");
ROS_INFO_STREAM(ros::this_node::getName()+"::Loading parameters from parameter server.");
const std::string& effector_driver_provider_prefix = ros::this_node::getName();
rclcpp::init(argc,argv,rclcpp::InitOptions(),rclcpp::SignalHandlerOptions::None);
auto node = std::make_shared<rclcpp::Node>("sas_robot_driver_franka_hand_node");
const auto node_name = std::string(node->get_name());
RCLCPP_WARN(node->get_logger(),"=====================================================================");
RCLCPP_WARN(node->get_logger(),"---------------------------Quentin Lin-------------------------------");
RCLCPP_WARN(node->get_logger(),"=====================================================================");
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Loading parameters from parameter server.");
ros::NodeHandle nh;
qros::EffectorDriverFrankaHandConfiguration robot_driver_franka_hand_configuration; qros::EffectorDriverFrankaHandConfiguration robot_driver_franka_hand_configuration;
get_optional_parameter(node, "initialize_with_homing", robot_driver_franka_hand_configuration.initialize_with_homing);
sas::get_ros_param(nh,"/robot_ip_address",robot_driver_franka_hand_configuration.robot_ip); sas::get_ros_parameter(node,"robot_ip_address",robot_driver_franka_hand_configuration.robot_ip);
sas::get_ros_parameter(node,"thread_sampling_time_sec",robot_driver_franka_hand_configuration.thread_sampeling_time_s);
get_optional_parameter(effector_driver_provider_prefix,nh,"/thread_sampling_time_nsec",robot_driver_franka_hand_configuration.thread_sampeling_time_ns); sas::get_ros_parameter(node,"default_force",robot_driver_franka_hand_configuration.default_force);
get_optional_parameter(effector_driver_provider_prefix,nh,"/default_force",robot_driver_franka_hand_configuration.default_force); sas::get_ros_parameter(node,"default_speed",robot_driver_franka_hand_configuration.default_speed);
get_optional_parameter(effector_driver_provider_prefix,nh,"/default_speed",robot_driver_franka_hand_configuration.default_speed); sas::get_ros_parameter(node,"default_epsilon_inner",robot_driver_franka_hand_configuration.default_epsilon_inner);
get_optional_parameter(effector_driver_provider_prefix,nh,"/default_epsilon_inner",robot_driver_franka_hand_configuration.default_epsilon_inner); sas::get_ros_parameter(node,"default_epsilon_outer",robot_driver_franka_hand_configuration.default_epsilon_outer);
get_optional_parameter(effector_driver_provider_prefix,nh,"/default_epsilon_outer",robot_driver_franka_hand_configuration.default_epsilon_outer);
qros::EffectorDriverFrankaHand franka_hand_driver( qros::EffectorDriverFrankaHand franka_hand_driver(
effector_driver_provider_prefix, node_name,
robot_driver_franka_hand_configuration, robot_driver_franka_hand_configuration,
nh, node,
&kill_this_process &kill_this_process
); );
try try
{ {
ROS_INFO_STREAM(ros::this_node::getName()+"::Instantiating Franka hand."); RCLCPP_INFO_STREAM(node->get_logger(),"["+node_name+"]::Instantiating Franka hand.");
franka_hand_driver.connect(); franka_hand_driver.connect();
franka_hand_driver.initialize(); franka_hand_driver.initialize();
RCLCPP_INFO_STREAM(node->get_logger(),"["+node_name+"]::Starting control loop.");
ROS_INFO_STREAM(ros::this_node::getName()+"::Instantiating control loop.");
franka_hand_driver.start_control_loop(); franka_hand_driver.start_control_loop();
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
ROS_ERROR_STREAM(ros::this_node::getName() + "::Exception::" + e.what()); RCLCPP_ERROR_STREAM(node->get_logger(), "["+node_name+"]::Exception::" + e.what());
}catch (...) }catch (...)
{ {
ROS_ERROR_STREAM(ros::this_node::getName() + "::Exception::Unknown exception."); RCLCPP_ERROR_STREAM(node->get_logger(), "["+node_name+"]::Exception::Unknown exception.");
} }
ROS_INFO_STREAM(ros::this_node::getName()+"::Exiting..."); RCLCPP_INFO_STREAM(node->get_logger(),"["+node_name+"]::Exiting...");
franka_hand_driver.deinitialize(); franka_hand_driver.deinitialize();
ROS_INFO_STREAM(ros::this_node::getName()+"::deinitialized."); RCLCPP_INFO_STREAM(node->get_logger(),"["+node_name+"]::Deinitialized.");
franka_hand_driver.disconnect(); franka_hand_driver.disconnect();
ROS_INFO_STREAM(ros::this_node::getName()+"::disconnected."); RCLCPP_INFO_STREAM(node->get_logger(),"["+node_name+"]::Disconnected.");
return 0; return 0;

View File

@@ -26,6 +26,8 @@
# 1. Juan Jose Quiroz Omana (juanjqogm@gmail.com) # 1. Juan Jose Quiroz Omana (juanjqogm@gmail.com)
# - Adapted from sas_robot_driver_denso_node.cpp # - Adapted from sas_robot_driver_denso_node.cpp
# (https://github.com/SmartArmStack/sas_robot_driver_denso/blob/master/src/sas_robot_driver_denso_node.cpp) # (https://github.com/SmartArmStack/sas_robot_driver_denso/blob/master/src/sas_robot_driver_denso_node.cpp)
# 2. Quentin Lin
# - Adaption to ROS2
# #
# ################################################################ # ################################################################
*/ */
@@ -36,11 +38,11 @@
#include <exception> #include <exception>
#include <dqrobotics/utils/DQ_Math.h> #include <dqrobotics/utils/DQ_Math.h>
#include <dqrobotics/interfaces/json11/DQ_JsonReader.h> #include <dqrobotics/interfaces/json11/DQ_JsonReader.h>
#include <sas_common/sas_common.h> #include <sas_common/sas_common.hpp>
#include <sas_conversions/eigen3_std_conversions.h> #include <sas_conversions/eigen3_std_conversions.hpp>
#include <sas_robot_driver/sas_robot_driver_ros.h> #include <sas_robot_driver/sas_robot_driver_ros.hpp>
#include "sas_robot_driver_franka.h" #include <sas_robot_driver_franka/sas_robot_driver_franka.hpp>
#include <robot_dynamic/qros_robot_dynamics_provider.h> #include <sas_robot_driver_franka/robot_dynamic/qros_robot_dynamics_server.hpp>
/********************************************* /*********************************************
@@ -74,90 +76,106 @@ std::array<T, N> std_vec_to_std_array(const std::vector<T>& vector)
} }
return array; return array;
} }
VectorXd std_vec_to_eigen_vector(const std::vector<double>& vector)
{
VectorXd eigen_vector(vector.size());
for(std::size_t i = 0; i < vector.size(); i++)
{
eigen_vector(i) = vector[i];
}
return eigen_vector;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
if(signal(SIGINT, sig_int_handler) == SIG_ERR) if(signal(SIGINT, sig_int_handler) == SIG_ERR)
{ {
throw std::runtime_error(ros::this_node::getName() + "::Error setting the signal int handler."); throw std::runtime_error("Error setting the signal int handler.");
} }
ros::init(argc, argv, "sas_robot_driver_franka_node", ros::init_options::NoSigintHandler); rclcpp::init(argc,argv,rclcpp::InitOptions(),rclcpp::SignalHandlerOptions::None);
ROS_WARN("====================================================================="); auto node = std::make_shared<rclcpp::Node>("sas_robot_driver_franka_node");
ROS_WARN("----------------------Juan Jose Quiroz Omana------------------------");
ROS_WARN("=====================================================================");
ROS_INFO_STREAM(ros::this_node::getName()+"::Loading parameters from parameter server.");
const auto node_name = std::string(node->get_name());
RCLCPP_WARN(node->get_logger(),"=====================================================================");
RCLCPP_WARN(node->get_logger(),"-----------------Adapted by Quentin Lin ------------------------");
RCLCPP_WARN(node->get_logger(),"=====================================================================");
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Loading parameters from parameter server.");
ros::NodeHandle nh;
sas::RobotDriverFrankaConfiguration robot_driver_franka_configuration; sas::RobotDriverFrankaConfiguration robot_driver_franka_configuration;
RobotInterfaceFranka::FrankaInterfaceConfiguration franka_interface_configuration; RobotInterfaceFranka::FrankaInterfaceConfiguration franka_interface_configuration;
sas::get_ros_param(nh,"/robot_ip_address",robot_driver_franka_configuration.ip_address); sas::get_ros_parameter(node,"robot_ip_address",robot_driver_franka_configuration.ip_address);
sas::get_ros_param(nh,"/robot_mode", robot_driver_franka_configuration.mode); sas::get_ros_parameter(node,"robot_mode", robot_driver_franka_configuration.mode);
double upper_scale_factor = 1.0; double upper_scale_factor = 1.0;
std::vector<std::string> all_params; std::vector<std::string> all_params;
if(nh.hasParam(ros::this_node::getName()+"/force_upper_limits_scaling_factor"))
{ try {
sas::get_ros_param(nh,"/force_upper_limits_scaling_factor",upper_scale_factor); sas::get_ros_parameter(node,"force_upper_limits_scaling_factor",upper_scale_factor);
ROS_WARN_STREAM(ros::this_node::getName()+"::Set force upper limits scaling factor: " << upper_scale_factor); RCLCPP_WARN_STREAM_ONCE(node->get_logger(),"Set force upper limits scaling factor: " << upper_scale_factor);
}catch(...) {
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"Force upper limits scaling factor is not set.");
} }
if(nh.hasParam(ros::this_node::getName()+"/upper_torque_threshold")) {
ROS_INFO_STREAM(ros::this_node::getName()+"::Upper torque threshold override and set."); try {
std::vector<double> upper_torque_threshold_std_vec; std::vector<double> upper_torque_threshold_std_vec;
sas::get_ros_param(nh,"/upper_torque_threshold",upper_torque_threshold_std_vec); sas::get_ros_parameter(node,"upper_torque_threshold",upper_torque_threshold_std_vec);
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Upper torque threshold override and set.");
franka_interface_configuration.upper_torque_threshold = std_vec_to_std_array<double,7>(upper_torque_threshold_std_vec); franka_interface_configuration.upper_torque_threshold = std_vec_to_std_array<double,7>(upper_torque_threshold_std_vec);
}else { }catch(...) {
ROS_INFO_STREAM(ros::this_node::getName()+"::Upper torque threshold not set. Using default with value scalling."); RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Upper torque threshold not set. Using default with value scalling.");
franka_interface_configuration.upper_torque_threshold = apply_scale_to_std_array(franka_interface_configuration.upper_torque_threshold, upper_scale_factor); franka_interface_configuration.upper_torque_threshold = apply_scale_to_std_array(franka_interface_configuration.upper_torque_threshold, upper_scale_factor);
} }
if(nh.hasParam(ros::this_node::getName()+"/upper_force_threshold")) { try {
ROS_INFO_STREAM(ros::this_node::getName()+"::Upper force threshold override and set."); std::vector<double> upper_force_threshold_std_vec;
std::vector<double> upper_torque_threshold_std_vec; sas::get_ros_parameter(node,"upper_force_threshold",upper_force_threshold_std_vec);
sas::get_ros_param(nh,"/upper_force_threshold",upper_torque_threshold_std_vec); RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Upper force threshold override and set.");
franka_interface_configuration.upper_force_threshold = std_vec_to_std_array<double,6>(upper_torque_threshold_std_vec); franka_interface_configuration.upper_force_threshold = std_vec_to_std_array<double,6>(upper_force_threshold_std_vec);
}else { }catch(...) {
ROS_INFO_STREAM(ros::this_node::getName()+"::Upper force threshold not set. Using default with value scalling."); RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Upper torque threshold not set. Using default with value scalling.");
franka_interface_configuration.upper_force_threshold = apply_scale_to_std_array(franka_interface_configuration.upper_force_threshold, upper_scale_factor); franka_interface_configuration.upper_force_threshold = apply_scale_to_std_array(franka_interface_configuration.upper_force_threshold, upper_scale_factor);
} }
if(nh.hasParam(ros::this_node::getName()+"/robot_parameter_file_path")) try {
{
std::string robot_parameter_file_path; std::string robot_parameter_file_path;
sas::get_ros_param(nh,"/robot_parameter_file_path",robot_parameter_file_path); sas::get_ros_parameter(node,"robot_parameter_file_path",robot_parameter_file_path);
ROS_INFO_STREAM(ros::this_node::getName()+"::Loading robot parameters from file: " + robot_parameter_file_path); RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Loading robot parameters from file: " + robot_parameter_file_path);
const auto robot = DQ_JsonReader::get_from_json<DQ_SerialManipulatorDH>(robot_parameter_file_path); const auto robot = DQ_JsonReader::get_from_json<DQ_SerialManipulatorDH>(robot_parameter_file_path);
robot_driver_franka_configuration.robot_reference_frame = robot.get_reference_frame(); robot_driver_franka_configuration.robot_reference_frame = robot.get_reference_frame();
}else{ROS_INFO_STREAM(ros::this_node::getName()+"::Robot parameter file path not set. Robot Model Unknow.");} }catch(...) {
RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Robot parameter file path not set. Robot Model Unknow.");
}
robot_driver_franka_configuration.interface_configuration = franka_interface_configuration; robot_driver_franka_configuration.interface_configuration = franka_interface_configuration;
sas::RobotDriverROSConfiguration robot_driver_ros_configuration; sas::RobotDriverROSConfiguration robot_driver_ros_configuration;
sas::get_ros_param(nh,"/thread_sampling_time_nsec",robot_driver_ros_configuration.thread_sampling_time_nsec); sas::get_ros_parameter(node,"thread_sampling_time_sec",robot_driver_ros_configuration.thread_sampling_time_sec);
sas::get_ros_param(nh,"/q_min",robot_driver_ros_configuration.q_min); sas::get_ros_parameter(node,"q_min",robot_driver_ros_configuration.q_min);
sas::get_ros_param(nh,"/q_max",robot_driver_ros_configuration.q_max); sas::get_ros_parameter(node,"q_max",robot_driver_ros_configuration.q_max);
// initialize the robot dynamic provider // initialize the robot dynamic provider
robot_driver_ros_configuration.robot_driver_provider_prefix = ros::this_node::getName(); robot_driver_ros_configuration.robot_driver_provider_prefix = node_name;
qros::RobotDynamicProvider robot_dynamic_provider(nh, robot_driver_ros_configuration.robot_driver_provider_prefix); std::shared_ptr<qros::RobotDynamicsServer> robot_dynamic_provider_ptr = std::make_shared<qros::RobotDynamicsServer>(node, robot_driver_ros_configuration.robot_driver_provider_prefix);
if(robot_driver_franka_configuration.robot_reference_frame!=0) if(robot_driver_franka_configuration.robot_reference_frame!=0)
{ {
robot_dynamic_provider.set_world_to_base_tf(robot_driver_franka_configuration.robot_reference_frame); robot_dynamic_provider_ptr->set_world_to_base_tf(robot_driver_franka_configuration.robot_reference_frame);
} }
try try
{ {
ROS_INFO_STREAM(ros::this_node::getName()+"::Instantiating Franka robot."); RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Instantiating Franka robot.");
sas::RobotDriverFranka robot_driver_franka( std::shared_ptr<sas::RobotDriverFranka> robot_driver_franka = std::make_shared<sas::RobotDriverFranka>(
&robot_dynamic_provider, node,
robot_dynamic_provider_ptr,
robot_driver_franka_configuration, robot_driver_franka_configuration,
&kill_this_process &kill_this_process
); );
//robot_driver_franka.set_joint_limits({qmin, qmax}); std::tuple<VectorXd, VectorXd> joint_limits = {std_vec_to_eigen_vector(robot_driver_ros_configuration.q_min), std_vec_to_eigen_vector(robot_driver_ros_configuration.q_max)};
ROS_INFO_STREAM(ros::this_node::getName()+"::Instantiating RobotDriverROS."); robot_driver_franka -> set_joint_limits(joint_limits);
sas::RobotDriverROS robot_driver_ros(nh, RCLCPP_INFO_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Instantiating RobotDriverROS.");
&robot_driver_franka, sas::RobotDriverROS robot_driver_ros(node,
robot_driver_franka,
robot_driver_ros_configuration, robot_driver_ros_configuration,
&kill_this_process); &kill_this_process);
robot_driver_ros.control_loop(); robot_driver_ros.control_loop();
@@ -165,7 +183,7 @@ int main(int argc, char **argv)
catch (const std::exception& e) catch (const std::exception& e)
{ {
kill_this_process = true; kill_this_process = true;
ROS_ERROR_STREAM(ros::this_node::getName() + "::Exception::" + e.what()); RCLCPP_ERROR_STREAM_ONCE(node->get_logger(),"["+node_name+"]::Exception::" + e.what());
} }

View File

@@ -1,7 +0,0 @@
float32 width
float32 speed
float32 force
float32 epsilon_inner
float32 epsilon_outer
---
bool success

View File

@@ -1,4 +0,0 @@
float32 width
float32 speed
---
bool success