Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
0112fa5
Add shell of the controller with a test
destogl Apr 21, 2021
732d744
Outline the admittance control pipeline
Apr 28, 2021
e096b4f
Hook up with MoveIt
Apr 28, 2021
42dec45
Link against Eigen
Apr 28, 2021
4b61b50
Do the pseudoinverse calculation
Apr 28, 2021
f98a3d0
Set up transform buffer stuff
Apr 28, 2021
663fc77
Transform the incoming wrench
Apr 28, 2021
6e77403
Correct the wrench transformation
Apr 28, 2021
c120eca
Minor renaming to be technically correct
Apr 28, 2021
42ffb92
Testable version of Admittance Controller. IK not yet enables, so the…
destogl May 6, 2021
3d3692f
Try to integrate IK
destogl May 6, 2021
fd8995c
Finish the method for forward kinematics (#4)
AndyZe May 7, 2021
6c05bb3
Version that could work
destogl May 7, 2021
38a3f5b
Corrected subscriptions types and debugging
destogl May 7, 2021
3aed12f
Corrected some tests and extended testing
destogl May 11, 2021
46ca459
Debugging admittance controller
destogl May 11, 2021
0c281cd
Wait for valid wrench data
May 12, 2021
5723950
[WIP] Debug current joint states
May 12, 2021
a8f5542
Now output is working
destogl May 12, 2021
d67853a
Pseudoinverse method was buggy. Use a different one.
May 13, 2021
b92d5ba
Admittance controller is working
destogl May 13, 2021
b90e76c
Remove quaternion calculation because it does not work
destogl May 14, 2021
3ddc929
Corrected admittance rule
destogl May 14, 2021
2ecb284
Clean up unused vars and debug statements
May 14, 2021
d232b78
Added test with hardware state has offset
destogl May 15, 2021
dd9d576
Move calculation of admittance rule into separate method
destogl May 15, 2021
aa7f5f9
Extract force processing and start using desired_joint_deltas
destogl May 15, 2021
8922509
Use JointTrajectoryPoint as internal data structure
destogl May 15, 2021
c52f396
Use JointTrajectoryPoint internally
destogl May 17, 2021
93c42cc
Added gravity compensation
destogl May 17, 2021
117dc56
Add output of filtered forces
destogl May 17, 2021
2711a4a
Try calculating target_pose differently
May 17, 2021
4e6bc0b
Small comment cleanup
May 17, 2021
f9a6ccb
Small bug fix to eliminate spurious rotations
May 17, 2021
4018484
Reverse lookupTransform(). The fixes coordinate frame and rotation is…
May 17, 2021
b2bea4d
Small fixup
May 17, 2021
0226a5c
Remove unnecessary dependencies
destogl May 18, 2021
dc4429c
Add orientation to admittance control. Small simplifications.
May 18, 2021
f326385
Remove small number noise from substraction
destogl May 18, 2021
f4900d0
Remove small number noise from substraction
destogl May 19, 2021
ce47fd2
REnaming of variables
destogl May 19, 2021
d8a189b
Rename force->wrench to be technically correct
May 19, 2021
9ea5a33
Try to debug force input
destogl May 20, 2021
f89777b
Add update_robot_state() function
May 21, 2021
1446be0
Rename get_current_pose_of_endeffector_frame->get_pose_of_endeffector…
May 21, 2021
50b4cfb
Small variable renaming. Refactor get_pose_of_endeffector_in_base_fra…
May 21, 2021
a012587
Hard-code to always use joint commands
May 21, 2021
a34e2ea
This works but does not "spring back"
May 21, 2021
0569217
Feed different transform into IK
May 21, 2021
6a0b735
Rename tf arg to IK. Delete debug statements.
May 21, 2021
0b968f4
General cleanup, variable documentation and renaming
May 21, 2021
c973ab7
More renaming of force->wrench
May 25, 2021
cd60a42
Remove endeffector_frame (redundant with control_frame)
May 25, 2021
821ba91
Debug calculate_desired_joint_state
May 25, 2021
570b3b5
error = target - current
May 25, 2021
8431612
Correct the current pose
May 26, 2021
3773adc
Translation seems fine!
May 26, 2021
4e410f1
Delete commented code blocks
May 26, 2021
9dfb76c
Re-enable orientation control (#13)
AndyZe May 26, 2021
1546a58
Flip the "pose error" calculation
May 27, 2021
c9c8c9c
Implement "spring back" behavior. Use inertial reference frame. (#14)
AndyZe May 27, 2021
f12a8ce
Pre-allocate an identity transform
May 27, 2021
e558db2
Add feedforward acceleration term (#15)
AndyZe May 28, 2021
41391da
configure() admittance differently. Fixes "XBox first" bug
May 28, 2021
80372ae
Revert endeffector frame to publish forces in endeffector frame
destogl May 30, 2021
e5d4104
Enable support of NaN values on command interface
destogl May 30, 2021
46dded8
Add JointDeltas output to see what is happening before XBox is enabled
destogl May 30, 2021
bb35cc8
Squash "not-moving before XBox" bug
destogl May 30, 2021
dd6a764
Enable open loop control (#16)
destogl Jun 1, 2021
2383448
Rename feedforward_pose variable to target_from_joint_deltas
destogl Jun 3, 2021
59e6ae9
Correct rotation issues. Stability is reduced.
destogl Jun 5, 2021
c01827b
Implement get_link_transform(). Rename IncrementalKinematics
Jun 3, 2021
904b384
Renaming of incremental_kinematics -> moveit_kinematics
Jun 3, 2021
211fb1a
Added Andy as author and correct include style.
destogl Jun 5, 2021
16a396c
Update moveit kinematics accepting current joint_state
Jun 6, 2021
bfac9b9
Adjust formating of moveit kinematics file.
destogl Jun 6, 2021
3c2d8ba
Rename desired to reference and interal variables with prefix admittance
destogl Jun 6, 2021
a828a93
Seems working. Neede one more round of checks.
destogl Jun 6, 2021
48518f6
Cleaning of the not used feedforward variables.
destogl Jun 6, 2021
c730ff1
Change approach of calculating absolute desired pose.
destogl Jun 6, 2021
3dd8741
Use logic to force stable behavior when no external forces are measured.
destogl Jun 6, 2021
d1b6e35
Rename the wrench variable (ik_base, not control frame)
Jun 7, 2021
6588004
Use simple forward diff formula. Delete unused vars. Set admittance v…
Jun 7, 2021
1314082
Different "pose error" calculation for open-loop mode. Prevents rotat…
Jun 7, 2021
e79f8bd
Resort calculation of admittance displacement to have it in one place
destogl Jun 7, 2021
329a93d
Do not initialize memory in update joint-deltas method. Simplify calc…
destogl Jun 7, 2021
029f613
Comment gravity comp parameter parsing, for now
Jun 8, 2021
793379e
Delete unused EPSILON variables
Jun 8, 2021
e562fb4
Add admittance controller compile options
destogl Jun 7, 2021
c327cd4
Add filter_chain_ definition
destogl Jun 7, 2021
aa53eef
Add filter chain to admittance controller
destogl Jun 7, 2021
3cf78c3
Enalbe filters by moving admittance_rule impl to a header file.
destogl Jun 8, 2021
58bd473
Remove protection logic since it is not needed anymore
destogl Jun 9, 2021
c386a6e
Remove unused code
destogl Jun 9, 2021
58c6ac9
Add Admittance Controller from 79a2dfe78c73f9a99e899f4bb400424783a202…
destogl Oct 21, 2021
d99ebed
Compilable with changed controllers' update() api -> against destogl:…
destogl Oct 21, 2021
e9d3cb3
Add debuging output to the AdmittanceController to know when SRDF is …
destogl Oct 26, 2021
9c1afc9
Add debuging output to the AdmittanceController to know when SRDF is …
destogl Oct 25, 2021
c3b19c7
Update to new version of ControlParameters and add enable_paramter_up…
destogl Oct 28, 2021
afe216f
Use updated ParameterHandler from control_toolbox.
destogl Oct 31, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions admittance_controller/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
cmake_minimum_required(VERSION 3.5)
project(admittance_controller)

if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(control_msgs REQUIRED)
find_package(control_toolbox REQUIRED)
find_package(controller_interface REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(filters REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(hardware_interface REQUIRED)
find_package(joint_limits REQUIRED)
find_package(moveit_ros_move_group REQUIRED)
find_package(moveit_ros_planning_interface REQUIRED)
find_package(pluginlib REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_lifecycle REQUIRED)
find_package(realtime_tools REQUIRED)
find_package(tf2 REQUIRED)
find_package(tf2_eigen REQUIRED)
find_package(tf2_geometry_msgs REQUIRED)
find_package(tf2_ros REQUIRED)

add_library(
admittance_controller
SHARED
src/admittance_controller.cpp
src/moveit_kinematics.cpp
)
target_include_directories(
admittance_controller
PRIVATE
include
)
ament_target_dependencies(
admittance_controller
control_msgs
control_toolbox
controller_interface
${Eigen_LIBRARIES}
filters
geometry_msgs
hardware_interface
joint_limits
moveit_ros_move_group
moveit_ros_planning_interface
pluginlib
rclcpp
rclcpp_lifecycle
realtime_tools
tf2
tf2_eigen
tf2_geometry_msgs
tf2_ros
)
# Causes the visibility macros to use dllexport rather than dllimport,
# which is appropriate when building the dll but not consuming it.
target_compile_definitions(admittance_controller PRIVATE "ADMITTANCE_CONTROLLER_BUILDING_DLL")

pluginlib_export_plugin_description_file(controller_interface admittance_controller.xml)

install(
TARGETS admittance_controller
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)

install(
DIRECTORY include/
DESTINATION include
)

if(BUILD_TESTING)
find_package(ament_cmake_gmock REQUIRED)
find_package(controller_manager REQUIRED)
find_package(hardware_interface REQUIRED)
find_package(ros2_control_test_assets REQUIRED)

ament_add_gmock(test_load_admittance_controller test/test_load_admittance_controller.cpp)
target_include_directories(test_load_admittance_controller PRIVATE include)
ament_target_dependencies(
test_load_admittance_controller
controller_manager
hardware_interface
ros2_control_test_assets
)

ament_add_gmock(test_admittance_controller test/test_admittance_controller.cpp)
target_include_directories(test_admittance_controller PRIVATE include)
target_link_libraries(test_admittance_controller admittance_controller)
ament_target_dependencies(
test_admittance_controller
control_msgs
controller_interface
hardware_interface
ros2_control_test_assets
)
endif()

ament_export_include_directories(
include
)
ament_export_libraries(
admittance_controller
)
ament_export_dependencies(
control_msgs
control_toolbox
controller_interface
filters
geometry_msgs
hardware_interface
joint_limits
pluginlib
rclcpp
rclcpp_lifecycle
realtime_tools
tf2
tf2_eigen
tf2_geometry_msgs
tf2_ros
)

ament_package()
7 changes: 7 additions & 0 deletions admittance_controller/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
admittance_controller
==========================================

Implemenation of admittance controllers for different input and output interface.

Pluginlib-Library: admittance_controller
Plugin: admittance_controller/AdmittanceController (controller_interface::ControllerInterface)
8 changes: 8 additions & 0 deletions admittance_controller/admittance_controller.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<library path="admittance_controller">
<class name="admittance_controller/AdmittanceController"
type="admittance_controller::AdmittanceController" base_class_type="controller_interface::ControllerInterface">
<description>
AdmittanceController ros2_control controller.
</description>
</class>
</library>
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// Copyright (c) 2021, PickNik, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
/// \authors: Denis Stogl, Andy Zelenak

#ifndef ADMITTANCE_CONTROLLER__ADMITTANCE_CONTROLLER_HPP_
#define ADMITTANCE_CONTROLLER__ADMITTANCE_CONTROLLER_HPP_

#include <memory>
#include <string>
#include <vector>

#include "admittance_controller/admittance_rule.hpp"
#include "admittance_controller/visibility_control.h"
#include "control_msgs/msg/admittance_controller_state.hpp"
#include "controller_interface/controller_interface.hpp"
#include "geometry_msgs/msg/pose_stamped.hpp"
#include "geometry_msgs/msg/transform_stamped.hpp"
#include "geometry_msgs/msg/wrench_stamped.hpp"
#include "hardware_interface/types/hardware_interface_type_values.hpp"
#include "joint_limits/joint_limiter_interface.hpp"
#include "joint_limits/joint_limits.hpp"
#include "pluginlib/class_loader.hpp"
#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp"
#include "rclcpp_lifecycle/state.hpp"
#include "realtime_tools/realtime_buffer.h"
#include "realtime_tools/realtime_publisher.h"
#include "semantic_components/force_torque_sensor.hpp"
// TODO(destogl): this is only temporary to work with servo. It should be either trajectory_msgs/msg/JointTrajectoryPoint or std_msgs/msg/Float64MultiArray
#include "trajectory_msgs/msg/joint_trajectory.hpp"

namespace admittance_controller
{
using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn;

class AdmittanceController : public controller_interface::ControllerInterface
{
public:
ADMITTANCE_CONTROLLER_PUBLIC
AdmittanceController();

ADMITTANCE_CONTROLLER_PUBLIC
CallbackReturn on_init() override;

ADMITTANCE_CONTROLLER_PUBLIC
controller_interface::InterfaceConfiguration command_interface_configuration() const override;

ADMITTANCE_CONTROLLER_PUBLIC
controller_interface::InterfaceConfiguration state_interface_configuration() const override;

ADMITTANCE_CONTROLLER_PUBLIC
CallbackReturn on_configure(const rclcpp_lifecycle::State & previous_state) override;

ADMITTANCE_CONTROLLER_PUBLIC
CallbackReturn on_activate(const rclcpp_lifecycle::State & previous_state) override;

ADMITTANCE_CONTROLLER_PUBLIC
CallbackReturn on_deactivate(const rclcpp_lifecycle::State & previous_state) override;

ADMITTANCE_CONTROLLER_PUBLIC
controller_interface::return_type update(
const rclcpp::Time & time, const rclcpp::Duration & period) override;

protected:
std::vector<std::string> joint_names_;
std::vector<std::string> command_interface_types_;
std::vector<std::string> state_interface_types_;
std::string ft_sensor_name_;
bool use_joint_commands_as_input_;
std::string joint_limiter_type_;

bool hardware_state_has_offset_;
trajectory_msgs::msg::JointTrajectoryPoint last_commanded_state_;

// joint limiter
using JointLimiter = joint_limits::JointLimiterInterface<joint_limits::JointLimits>;
std::shared_ptr<pluginlib::ClassLoader<JointLimiter>> joint_limiter_loader_;
std::unique_ptr<JointLimiter> joint_limiter_;

// Internal variables
std::unique_ptr<semantic_components::ForceTorqueSensor> force_torque_sensor_;

// Admittance rule and dependent variables;
std::unique_ptr<admittance_controller::AdmittanceRule> admittance_;
rclcpp::Time previous_time_;

// Callback for updating dynamic parameters
rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr on_set_callback_handle_;

// Command subscribers and Controller State publisher
using ControllerCommandWrenchMsg = geometry_msgs::msg::WrenchStamped;
using ControllerCommandPoseMsg = geometry_msgs::msg::PoseStamped;
using ControllerCommandJointMsg = trajectory_msgs::msg::JointTrajectory;

rclcpp::Subscription<ControllerCommandWrenchMsg>::SharedPtr
input_wrench_command_subscriber_ = nullptr;
rclcpp::Subscription<ControllerCommandPoseMsg>::SharedPtr
input_pose_command_subscriber_ = nullptr;
rclcpp::Subscription<ControllerCommandJointMsg>::SharedPtr input_joint_command_subscriber_ = nullptr;

realtime_tools::RealtimeBuffer<std::shared_ptr<ControllerCommandWrenchMsg>>
input_wrench_command_;
realtime_tools::RealtimeBuffer<std::shared_ptr<ControllerCommandPoseMsg>>
input_pose_command_;
realtime_tools::RealtimeBuffer<std::shared_ptr<ControllerCommandJointMsg>>
input_joint_command_;

using ControllerStateMsg = control_msgs::msg::AdmittanceControllerState;
using ControllerStatePublisher = realtime_tools::RealtimePublisher<ControllerStateMsg>;

rclcpp::Publisher<ControllerStateMsg>::SharedPtr s_publisher_;
std::unique_ptr<ControllerStatePublisher> state_publisher_;

// Internal access to sorted interfaces

// To reduce number of variables and to make the code shorter the interfaces are ordered in types
// as the following constants
const std::vector<std::string> allowed_interface_types_ = {
hardware_interface::HW_IF_POSITION,
hardware_interface::HW_IF_VELOCITY,
};

// The interfaces are defined as the types in 'allowed_interface_types_' member.
// For convenience, for each type the interfaces are ordered so that i-th position
// matches i-th index in joint_names_
template<typename T>
using InterfaceReferences = std::vector<std::vector<std::reference_wrapper<T>>>;

InterfaceReferences<hardware_interface::LoanedCommandInterface> joint_command_interface_;
InterfaceReferences<hardware_interface::LoanedStateInterface> joint_state_interface_;

bool has_velocity_state_interface_ = false;
bool has_position_command_interface_ = false;
bool has_velocity_command_interface_ = false;

void read_state_from_hardware(trajectory_msgs::msg::JointTrajectoryPoint & state);

/// Use values on command interfaces as states when robot should be controller in open-loop.
/**
* If velocities and positions are both available from the joint command interface, set
* output_state equal to them.
* If velocities or positions are unknown, output_state is unchanged and the function returns false.
*/
bool read_state_from_command_interfaces(trajectory_msgs::msg::JointTrajectoryPoint & state);
};

} // namespace admittance_controller

#endif // ADMITTANCE_CONTROLLER__ADMITTANCE_CONTROLLER_HPP_
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

// Header!!
std::string ik_tip_frame_;

// Frame which position should be controlled
std::string endeffector_frame_;

tf2::Transform ik_tip_to_control_frame_tf_;
tf2::Transform control_frame_to_ik_tip_tf_;

// CPP!!
controller_interface::return_type AdmittanceRule::reset()
{
// Initialize ik_tip and tool_frame transformations - those are fixed transformations
tf2::Stamped<tf2::Transform> tf2_transform;
try {
auto transform = tf_buffer_->lookupTransform(ik_tip_frame_, control_frame_, tf2::TimePointZero);
tf2::fromMsg(transform, tf2_transform);
ik_tip_to_control_frame_tf_ = tf2_transform;
control_frame_to_ik_tip_tf_ = tf2_transform.inverse();
} catch (const tf2::TransformException & e) {
RCLCPP_ERROR_SKIPFIRST_THROTTLE(
rclcpp::get_logger("AdmittanceRule"), *clock_, 5000, "%s", e.what());
return controller_interface::return_type::ERROR;
}
}


controller_interface::return_type AdmittanceRule::get_controller_state(
control_msgs::msg::AdmittanceControllerState & state_message)
{
// FIXME(destogl): Something is wrong with this transformation - check frames...
try {
auto transform = tf_buffer_->lookupTransform(endeffector_frame_, control_frame_, tf2::TimePointZero);
tf2::doTransform(measured_wrench_ik_base_frame_, measured_wrench_endeffector_frame_, transform);
} catch (const tf2::TransformException & e) {
RCLCPP_ERROR_SKIPFIRST_THROTTLE(
rclcpp::get_logger("AdmittanceRule"), *clock_, 5000, "%s", e.what());
}
state_message.measured_wrench_endeffector_frame = measured_wrench_endeffector_frame_;
}
Loading