Skip to content

Commit

Permalink
Testable version of Admittance Controller. IK not yet enables, so the…
Browse files Browse the repository at this point in the history
…re is not output.
  • Loading branch information
destogl committed May 6, 2021
1 parent 421a99a commit 3462763
Show file tree
Hide file tree
Showing 11 changed files with 1,710 additions and 79 deletions.
58 changes: 54 additions & 4 deletions admittance_controller/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,55 @@ endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(control_msgs REQUIRED)
find_package(controller_interface REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(hardware_interface REQUIRED)
find_package(iirob_filters 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/admittance_rule.cpp
src/incremental_ik_calculator.cpp
)
target_include_directories(
admittance_controller
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
${EIGEN3_INCLUDE_DIR}
include
)
ament_target_dependencies(
admittance_controller
control_msgs
controller_interface
${Eigen_LIBRARIES}
geometry_msgs
hardware_interface
iirob_filters
moveit_ros_move_group
moveit_ros_planning_interface
pluginlib
rclcpp
rclcpp_lifecycle
realtime_tools
tf2
tf2_eigen
tf2_geometry_msgs
tf2_ros
)
# prevent pluginlib from using boost
target_compile_definitions(admittance_controller PUBLIC "PLUGINLIB__DISABLE_BOOST_FUNCTIONS")
Expand All @@ -65,14 +83,46 @@ if(BUILD_TESTING)
find_package(hardware_interface REQUIRED)
find_package(ros2_control_test_assets REQUIRED)

ament_add_gmock(test_admittance_controller test/test_load_admittance_controller.cpp)
target_include_directories(test_admittance_controller PRIVATE include)
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_admittance_controller
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
)
endif()

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

ament_package()
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,25 @@
#ifndef ADMITTANCE_CONTROLLER__ADMITTANCE_CONTROLLER_HPP_
#define ADMITTANCE_CONTROLLER__ADMITTANCE_CONTROLLER_HPP_

#include "admittance_controller/incremental_ik_calculator.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 "iirob_filters/low_pass_filter.h"
#include "iirob_filters/gravity_compensation.h"
#include "semantic_components/force_torque_sensor.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"

namespace admittance_controller
{
Expand Down Expand Up @@ -56,14 +70,59 @@ class AdmittanceController : public controller_interface::ControllerInterface

protected:
std::vector<std::string> joint_names_;
std::vector<std::string> interface_names_;
std::vector<std::string> command_interface_types_;
std::vector<std::string> state_interface_types_;
std::string ft_sensor_name_;

// 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_;

// Command subscribers and Controller State publisher
using ControllerCommandForceMsg = geometry_msgs::msg::WrenchStamped;
using ControllerCommandPoseMsg = geometry_msgs::msg::PoseStamped;

rclcpp::Subscription<ControllerCommandForceMsg>::SharedPtr
input_force_command_subscriber_ = nullptr;
rclcpp::Subscription<ControllerCommandPoseMsg>::SharedPtr
input_pose_command_subscriber_ = nullptr;

realtime_tools::RealtimeBuffer<std::shared_ptr<ControllerCommandForceMsg>>
input_force_command_;
realtime_tools::RealtimeBuffer<std::shared_ptr<ControllerCommandPoseMsg>>
input_pose_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_;

std::shared_ptr<IncrementalIKCalculator> ik_;
bool has_velocity_state_interface_ = false;
bool has_position_command_interface_ = false;
bool has_velocity_command_interface_ = false;

Eigen::VectorXd delta_x_;
Eigen::VectorXd delta_theta_;
// TODO(andyz): parameterize this
std::string force_torque_sensor_frame_;
};

} // namespace admittance_controller
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// 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.
//
/// \author: Denis Stogl

#ifndef ADMITTANCE_CONTROLLER__ADMITTANCE_RULE_HPP_
#define ADMITTANCE_CONTROLLER__ADMITTANCE_RULE_HPP_

#include "admittance_controller/incremental_ik_calculator.hpp"
#include "control_msgs/msg/admittance_controller_state.hpp"
#include "controller_interface/controller_interface.hpp"
#include "geometry_msgs/msg/quaternion.hpp"
#include "geometry_msgs/msg/pose_stamped.hpp"
#include "geometry_msgs/msg/transform_stamped.hpp"
#include "geometry_msgs/msg/wrench_stamped.hpp"
#include "tf2_ros/transform_listener.h"
#include "tf2_geometry_msgs/tf2_geometry_msgs.h"

namespace admittance_controller
{
class AdmittanceRule
{
public:
AdmittanceRule() = default;

controller_interface::return_type configure(rclcpp::Clock::SharedPtr clock);

controller_interface::return_type update(
const std::vector<double> & current_joint_state,
const geometry_msgs::msg::Wrench & measured_force,
const geometry_msgs::msg::PoseStamped & target_pose,
const geometry_msgs::msg::WrenchStamped & target_force,
const rclcpp::Duration & period
);

controller_interface::return_type update(
const std::vector<double> & current_joint_state,
const geometry_msgs::msg::Wrench & measured_force,
const geometry_msgs::msg::PoseStamped & target_pose,
const rclcpp::Duration & period);

// controller_interface::return_type update(
// const geometry_msgs::msg::WrenchStamped & measured_force,
// const geometry_msgs::msg::PoseStamped & target_pose,
// const geometry_msgs::msg::PoseStamped & current_pose,
// const rclcpp::Duration & period,
// geometry_msgs::msg::TransformStamped & relative_desired_pose_vec
// );

controller_interface::return_type get_controller_state(
control_msgs::msg::AdmittanceControllerState & state_message
);

controller_interface::return_type reset();

public:
// IK related parameters
std::string ik_base_frame_;
std::string ik_tip_frame_;
std::string ik_group_name_;

// Controller frames
std::string control_frame_;
std::string endeffector_frame_;
std::string fixed_world_frame_;
std::string sensor_frame_;

// Admittance parameters
// bool unified_mode_ = false;
std::array<bool, 6> selected_axes_;
std::array<double, 6> mass_;
std::array<double, 6> damping_;
std::array<double, 6> stiffness_;

protected:
// IK variables
std::shared_ptr<IncrementalIKCalculator> ik_;
Eigen::VectorXd delta_x_;
Eigen::VectorXd delta_theta_;

// Transformation variables
std::shared_ptr<tf2_ros::Buffer> tf_buffer_;
std::shared_ptr<tf2_ros::TransformListener> tf_listener_;

geometry_msgs::msg::WrenchStamped measured_force_;
geometry_msgs::msg::WrenchStamped measured_force_control_frame_;

geometry_msgs::msg::PoseStamped current_origin_;
geometry_msgs::msg::PoseStamped current_pose_;
geometry_msgs::msg::PoseStamped current_pose_control_frame_;

geometry_msgs::msg::WrenchStamped target_force_control_frame_;
geometry_msgs::msg::PoseStamped target_pose_control_frame_;

geometry_msgs::msg::PoseStamped desired_pose_;
geometry_msgs::msg::TransformStamped relative_desired_pose_;

// Pre-reserved update-loop variables
std::array<double, 6> measured_force_control_frame_vec_;
std::array<double, 6> target_pose_control_frame_vec_;
std::array<double, 6> current_pose_control_frame_vec_;

std::array<double, 3> angles_error_;

std::array<double, 6> relative_desired_pose_vec_;
std::array<double, 6> desired_velocity_vec_;
std::array<double, 6> desired_velocity_previous_vec_;
std::array<double, 6> desired_acceleration_previous_vec_;

private:
// TODO: implement doTransform for WrenchStamped
template<typename MsgType>
// using MsgType = geometry_msgs::msg::PoseStamped;
void transform_message_to_control_frame(const MsgType & message_in, MsgType & message_out)
{
if (control_frame_ != message_in.header.frame_id) {
geometry_msgs::msg::TransformStamped transform = tf_buffer_->lookupTransform(
control_frame_, message_in.header.frame_id, tf2::TimePointZero);
tf2::doTransform(message_in, message_out, transform);
} else {
message_out = message_in;
}
}

// using MsgType2 = geometry_msgs::msg::WrenchStamped;
// void transform_message_to_control_frame(const MsgType2 & message_in, MsgType2 & message_out)
// {
// if (control_frame_ != message_in.header.frame_id) {
// geometry_msgs::msg::TransformStamped transform = tf_buffer_->lookupTransform(
// control_frame_, message_in.header.frame_id, tf2::TimePointZero);
//
// geometry_msgs::msg::Vector3Stamped vec_in;
// geometry_msgs::msg::Vector3Stamped vec_out;
//
// vec_in.vector = message_in.wrench.force;
// vec_in.header = message_in.header;
// tf2::doTransform(vec_in, vec_out, transform);
// message_out.wrench.force = vec_out.vector;
//
// vec_in.vector = message_in.wrench.torque;
// tf2::doTransform(vec_in, vec_out, transform);
// message_out.wrench.torque = vec_out.vector;
// } else {
// message_out = message_in;
// }
// }
};

} // namespace admittance_controller

#endif // ADMITTANCE_CONTROLLER__ADMITTANCE_RULE_HPP_
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include <Eigen/Core>
#include <moveit/robot_model_loader/robot_model_loader.h>
#include <moveit/robot_state/robot_state.h>
#include <tf2_eigen/tf2_eigen.h>
#include <tf2_ros/transform_listener.h>

namespace admittance_controller
Expand All @@ -32,7 +31,7 @@ class IncrementalIKCalculator
* \brief Create an object which takes Cartesian delta-x and converts to joint delta-theta.
* It uses the Jacobian from MoveIt.
*/
IncrementalIKCalculator(std::shared_ptr<rclcpp::Node>& node);
IncrementalIKCalculator(std::shared_ptr<rclcpp::Node> & node);

/**
* \brief Convert Cartesian delta-x to joint delta-theta, using the Jacobian.
Expand Down
Loading

0 comments on commit 3462763

Please sign in to comment.