diff --git a/.ci/Dockerfile b/.ci/Dockerfile
index 1846ed32ddb99e38481179408f2d69d328322b09..5f4e55bcf180177d12be6cb5d99567401229fe88 100644
--- a/.ci/Dockerfile
+++ b/.ci/Dockerfile
@@ -1,6 +1,7 @@
 FROM osrf/ros:kinetic-desktop-xenial
 RUN apt-get update && apt-get install -y \
-    clang \
-    clang-format \
-    clang-tidy \
-    ros-kinetic-ros-control
+    clang-5.0 \
+    clang-format-5.0 \
+    clang-tidy-5.0 \
+    ros-kinetic-ros-control \
+    && rm -rf /var/lib/apt/lists/*
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d50473f794c80f5ff771769e99cd6311d5324cc1..6c00a42f9bf23a4f7608171d4c6bb0c57b8b0c51 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,15 +4,18 @@
 
 Requires `libfranka` >= 0.5.0
 
+  * **BREAKING** Fixes for MoveIt, improving robot performance:
+    * Fixed joint velocity and acceleration limits in `joint_limits.yaml`
+    * Use desired joint state for move group
   * **BREAKING** Updated joint limits in URDF
   * **BREAKING** Fixed velocity, acceleration and jerk limits in `franka_hw`
+  * **BREAKING** Start `franka_gripper_node` when giving `load_gripper:=true` to `franka_control.launch`
   * Allow to configure rate limiting, filtering and internal controller in `franka_control_node`
-  * **BREAKING** Enabled limiting and low-pass filtering by default (`franka_control_node.yaml`)
+  * **BREAKING** `FrankaHW::FrankaHW` takes additional parameters.
+  * **BREAKING** Enabled rate limiting and low-pass filtering by default (`franka_control_node.yaml`)
   * Publish desired joint state in `/joint_state_desired`
   * Removed `effort_joint_trajectory_controller` from `default_controllers.yaml`
-  * **BREAKING** Fixes for MoveIt:
-    * Fixed joint velocity and acceleration limits in `joint_limits.yaml`
-    * Use desired joint state for move group
+  * Fixed a bug when switching between controllers using the same `libfranka` interface
 
 ## 0.5.0 - 2018-06-28
 
diff --git a/cmake/ClangTools.cmake b/cmake/ClangTools.cmake
index 7571da91d9af17553432c2c3078033ac4dffbf47..5166474f207d3e63158c83939cf0ab6e100e3377 100644
--- a/cmake/ClangTools.cmake
+++ b/cmake/ClangTools.cmake
@@ -1,11 +1,11 @@
 include(CMakeParseArguments)
 
-find_program(CLANG_FORMAT_PROG clang-format DOC "'clang-format' executable")
+find_program(CLANG_FORMAT_PROG clang-format-5.0 DOC "'clang-format' executable")
 if(CLANG_FORMAT_PROG AND NOT TARGET format)
   add_custom_target(format)
   add_custom_target(check-format)
 endif()
-find_program(CLANG_TIDY_PROG clang-tidy DOC "'clang-tidy' executable")
+find_program(CLANG_TIDY_PROG clang-tidy-5.0 DOC "'clang-tidy' executable")
 if(CLANG_TIDY_PROG AND NOT TARGET tidy)
   if(NOT CMAKE_EXPORT_COMPILE_COMMANDS)
     message(WARNING "Invoke Catkin/CMake with '-DCMAKE_EXPORT_COMPILE_COMMANDS=ON'
@@ -46,7 +46,7 @@ function(add_tidy_target _target)
   cmake_parse_arguments(ARG "" "" "FILES;DEPENDS" ${ARGN})
 
   add_custom_target(tidy-${_target}
-    COMMAND ${CLANG_TIDY_PROG} -p=${CMAKE_BINARY_DIR} ${ARG_FILES}
+    COMMAND ${CLANG_TIDY_PROG} -fix -p=${CMAKE_BINARY_DIR} ${ARG_FILES}
     WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/..
     DEPENDS ${ARG_DEPENDS}
     COMMENT "Running clang-tidy for ${_target}"
diff --git a/franka_control/config/franka_control_node.yaml b/franka_control/config/franka_control_node.yaml
index 7b9a67825386e3e3012983365758bb2c8173406a..fd2524afc14bc81163d105843f6eddd57436117a 100644
--- a/franka_control/config/franka_control_node.yaml
+++ b/franka_control/config/franka_control_node.yaml
@@ -7,11 +7,9 @@ joint_names:
   - panda_joint6
   - panda_joint7
 arm_id: panda
-# Rate limiter activation flag for each interface [true|false]
-# [Joint position, Joint velocity, Cartesian Pose, Cartesian Velocity, Torque]
-rate_limiting: [true, true, true, true, true]
-# Cutoff frequency of the lowpass filter for each interface. Set to >= 1000 to deactivate.
-# [Joint position, Joint velocity, Cartesian Pose, Cartesian Velocity, Torque]
-cutoff_freq: [100, 100, 100, 100, 100]
+# Activate rate limiter? [true|false]
+rate_limiting: true
+# Cutoff frequency of the low-pass filter. Set to >= 1000 to deactivate.
+cutoff_frequency: 100
 # Internal controller for motion generators [joint_impedance|cartesian_impedance]
 internal_controller: joint_impedance
diff --git a/franka_control/include/franka_control/franka_state_controller.h b/franka_control/include/franka_control/franka_state_controller.h
index b2c8fd49ea13453b92454ab1bf936572504facf4..6fe42947309ba715bbc052c00349d42a78307cbc 100644
--- a/franka_control/include/franka_control/franka_state_controller.h
+++ b/franka_control/include/franka_control/franka_state_controller.h
@@ -26,7 +26,7 @@ class FrankaStateController
   /**
    * Creates an instance of a FrankaStateController.
    */
-  FrankaStateController();
+  FrankaStateController() = default;
 
   /**
    * Initializes the controller with interfaces and publishers.
@@ -40,11 +40,11 @@ class FrankaStateController
             ros::NodeHandle& controller_node_handle) override;
 
   /**
-  * Reads the current robot state from the franka_hw::FrankaStateInterface and publishes it.
-  *
-  * @param[in] time Current ROS time.
-  * @param[in] period Time since the last update.
-  */
+   * Reads the current robot state from the franka_hw::FrankaStateInterface and publishes it.
+   *
+   * @param[in] time Current ROS time.
+   * @param[in] period Time since the last update.
+   */
   void update(const ros::Time& time, const ros::Duration& period) override;
 
  private:
@@ -55,8 +55,8 @@ class FrankaStateController
 
   std::string arm_id_;
 
-  franka_hw::FrankaStateInterface* franka_state_interface_;
-  std::unique_ptr<franka_hw::FrankaStateHandle> franka_state_handle_;
+  franka_hw::FrankaStateInterface* franka_state_interface_{};
+  std::unique_ptr<franka_hw::FrankaStateHandle> franka_state_handle_{};
 
   realtime_tools::RealtimePublisher<tf2_msgs::TFMessage> publisher_transforms_;
   realtime_tools::RealtimePublisher<franka_msgs::FrankaState> publisher_franka_states_;
diff --git a/franka_control/launch/franka_control.launch b/franka_control/launch/franka_control.launch
index 4ef1f1aaa320db6273f006840b288f550d088c0c..37adda84e725375094308fb5417cf1547b939dc3 100644
--- a/franka_control/launch/franka_control.launch
+++ b/franka_control/launch/franka_control.launch
@@ -6,6 +6,10 @@
   <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find franka_description)/robots/panda_arm_hand.urdf.xacro'" if="$(arg load_gripper)" />
   <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find franka_description)/robots/panda_arm.urdf.xacro'" unless="$(arg load_gripper)" />
 
+  <include file="$(find franka_gripper)/launch/franka_gripper.launch" if="$(arg load_gripper)">
+    <arg name="robot_ip" value="$(arg robot_ip)" />
+  </include>
+
   <node name="franka_control" pkg="franka_control" type="franka_control_node" output="screen" required="true">
     <rosparam command="load" file="$(find franka_control)/config/franka_control_node.yaml" />
     <param name="robot_ip" value="$(arg robot_ip)" />
diff --git a/franka_control/package.xml b/franka_control/package.xml
index 42b0f05697b1c8eebc5470c50e0cb461a0465b34..026d63157658cdb7d4e2bfe188e49c5d96bbc7cb 100644
--- a/franka_control/package.xml
+++ b/franka_control/package.xml
@@ -31,6 +31,7 @@
   <depend>tf</depend>
 
   <exec_depend>franka_description</exec_depend>
+  <exec_depend>franka_gripper</exec_depend>
   <exec_depend>joint_state_publisher</exec_depend>
   <exec_depend>message_runtime</exec_depend>
   <exec_depend>robot_state_publisher</exec_depend>
diff --git a/franka_control/src/franka_control_node.cpp b/franka_control/src/franka_control_node.cpp
index 2b092411d809d22b389b8ebb9098793f24293dfc..ce116d5e7983749afe4db99afe3fa052e5e66d8b 100644
--- a/franka_control/src/franka_control_node.cpp
+++ b/franka_control/src/franka_control_node.cpp
@@ -40,38 +40,30 @@ int main(int argc, char** argv) {
     return 1;
   }
 
-  std::vector<bool> limit_rate_vector;
-  if (!node_handle.getParam("rate_limiting", limit_rate_vector) || limit_rate_vector.size() != 5) {
-    ROS_ERROR("Invalid or no rate_limiting parameters provided");
+  std::array<std::string, 7> joint_names;
+  std::copy(joint_names_vector.cbegin(), joint_names_vector.cend(), joint_names.begin());
+
+  bool rate_limiting;
+  if (!node_handle.getParamCached("rate_limiting", rate_limiting)) {
+    ROS_ERROR("Invalid or no rate_limiting parameter provided");
     return 1;
   }
 
-  std::vector<double> cutoff_freq_vector;
-  if (!node_handle.getParam("cutoff_freq", cutoff_freq_vector) || cutoff_freq_vector.size() != 5) {
-    ROS_ERROR("Invalid or no cutoff_freq parameters provided");
+  double cutoff_frequency;
+  if (!node_handle.getParamCached("cutoff_frequency", cutoff_frequency)) {
+    ROS_ERROR("Invalid or no cutoff_frequency parameter provided");
     return 1;
   }
 
-  franka::ControllerMode internal_controller;
-  std::string internal_controller_name;
-  if (!node_handle.getParam("internal_controller", internal_controller_name)) {
+  std::string internal_controller;
+  if (!node_handle.getParam("internal_controller", internal_controller)) {
     ROS_ERROR("No internal_controller parameter provided");
     return 1;
   }
 
-  std::array<std::string, 7> joint_names;
-  std::copy(joint_names_vector.cbegin(), joint_names_vector.cend(), joint_names.begin());
-  std::array<bool, 5> rate_limiting;
-  std::copy(limit_rate_vector.cbegin(), limit_rate_vector.cend(), rate_limiting.begin());
-  std::array<double, 5> cutoff_freq;
-  std::copy(cutoff_freq_vector.cbegin(), cutoff_freq_vector.cend(), cutoff_freq.begin());
-
-  if (internal_controller_name == "joint_impedance") {
-    internal_controller = franka::ControllerMode::kJointImpedance;
-  } else if (internal_controller_name == "cartesian_impedance") {
-    internal_controller = franka::ControllerMode::kCartesianImpedance;
-  } else {
-    ROS_ERROR("Invalid internal_controller parameter provided");
+  urdf::Model urdf_model;
+  if (!urdf_model.initParamWithNodeHandle("robot_description", public_node_handle)) {
+    ROS_ERROR("Could not initialize URDF model from robot_description");
     return 1;
   }
 
@@ -97,29 +89,37 @@ int main(int argc, char** argv) {
 
   std::atomic_bool has_error(false);
 
-  using std::placeholders::_1;
-  using std::placeholders::_2;
   ServiceContainer services;
   services
       .advertiseService<franka_control::SetJointImpedance>(
           node_handle, "set_joint_impedance",
-          std::bind(franka_control::setJointImpedance, std::ref(robot), _1, _2))
+          [&robot](auto&& req, auto&& res) {
+            return franka_control::setJointImpedance(robot, req, res);
+          })
       .advertiseService<franka_control::SetCartesianImpedance>(
           node_handle, "set_cartesian_impedance",
-          std::bind(franka_control::setCartesianImpedance, std::ref(robot), _1, _2))
+          [&robot](auto&& req, auto&& res) {
+            return franka_control::setCartesianImpedance(robot, req, res);
+          })
       .advertiseService<franka_control::SetEEFrame>(
           node_handle, "set_EE_frame",
-          std::bind(franka_control::setEEFrame, std::ref(robot), _1, _2))
+          [&robot](auto&& req, auto&& res) { return franka_control::setEEFrame(robot, req, res); })
       .advertiseService<franka_control::SetKFrame>(
-          node_handle, "set_K_frame", std::bind(franka_control::setKFrame, std::ref(robot), _1, _2))
+          node_handle, "set_K_frame",
+          [&robot](auto&& req, auto&& res) { return franka_control::setKFrame(robot, req, res); })
       .advertiseService<franka_control::SetForceTorqueCollisionBehavior>(
           node_handle, "set_force_torque_collision_behavior",
-          std::bind(franka_control::setForceTorqueCollisionBehavior, std::ref(robot), _1, _2))
+          [&robot](auto&& req, auto&& res) {
+            return franka_control::setForceTorqueCollisionBehavior(robot, req, res);
+          })
       .advertiseService<franka_control::SetFullCollisionBehavior>(
           node_handle, "set_full_collision_behavior",
-          std::bind(franka_control::setFullCollisionBehavior, std::ref(robot), _1, _2))
+          [&robot](auto&& req, auto&& res) {
+            return franka_control::setFullCollisionBehavior(robot, req, res);
+          })
       .advertiseService<franka_control::SetLoad>(
-          node_handle, "set_load", std::bind(franka_control::setLoad, std::ref(robot), _1, _2));
+          node_handle, "set_load",
+          [&robot](auto&& req, auto&& res) { return franka_control::setLoad(robot, req, res); });
 
   actionlib::SimpleActionServer<franka_control::ErrorRecoveryAction> recovery_action_server(
       node_handle, "error_recovery",
@@ -136,8 +136,31 @@ int main(int argc, char** argv) {
       false);
 
   franka::Model model = robot.loadModel();
-  franka_hw::FrankaHW franka_control(joint_names, arm_id, internal_controller, rate_limiting,
-                                     cutoff_freq, public_node_handle, model);
+  auto get_rate_limiting = [&]() {
+    node_handle.getParamCached("rate_limiting", rate_limiting);
+    return rate_limiting;
+  };
+  auto get_internal_controller = [&]() {
+    node_handle.getParamCached("internal_controller", internal_controller);
+
+    franka::ControllerMode controller_mode;
+    if (internal_controller == "joint_impedance") {
+      controller_mode = franka::ControllerMode::kJointImpedance;
+    } else if (internal_controller == "cartesian_impedance") {
+      controller_mode = franka::ControllerMode::kCartesianImpedance;
+    } else {
+      ROS_WARN("Invalid internal_controller parameter provided, falling back to joint impedance");
+      controller_mode = franka::ControllerMode::kJointImpedance;
+    }
+
+    return controller_mode;
+  };
+  auto get_cutoff_frequency = [&]() {
+    node_handle.getParamCached("cutoff_frequency", cutoff_frequency);
+    return cutoff_frequency;
+  };
+  franka_hw::FrankaHW franka_control(joint_names, arm_id, urdf_model, model, get_rate_limiting,
+                                     get_cutoff_frequency, get_internal_controller);
 
   // Initialize robot state before loading any controller
   franka_control.update(robot.readOnce());
diff --git a/franka_control/src/franka_state_controller.cpp b/franka_control/src/franka_state_controller.cpp
index 457e2adce3d0a5afa2e676e32ea78b3a4e1efceb..2e1e510f4bd236a9b63557f9d036d849d350fe61 100644
--- a/franka_control/src/franka_state_controller.cpp
+++ b/franka_control/src/franka_state_controller.cpp
@@ -3,6 +3,7 @@
 #include <franka_control/franka_state_controller.h>
 
 #include <cmath>
+#include <memory>
 #include <mutex>
 #include <string>
 
@@ -134,16 +135,6 @@ franka_msgs::Errors errorsToMessage(const franka::Errors& error) {
 
 namespace franka_control {
 
-FrankaStateController::FrankaStateController()
-    : franka_state_interface_(nullptr),
-      franka_state_handle_(nullptr),
-      publisher_transforms_(),
-      publisher_franka_states_(),
-      publisher_joint_states_(),
-      publisher_joint_states_desired_(),
-      publisher_external_wrench_(),
-      trigger_publish_(30.0) {}
-
 bool FrankaStateController::init(hardware_interface::RobotHW* robot_hardware,
                                  ros::NodeHandle& root_node_handle,
                                  ros::NodeHandle& controller_node_handle) {
@@ -157,12 +148,11 @@ bool FrankaStateController::init(hardware_interface::RobotHW* robot_hardware,
     return false;
   }
   double publish_rate(30.0);
-  if (controller_node_handle.getParam("publish_rate", publish_rate)) {
-    trigger_publish_ = franka_hw::TriggerRate(publish_rate);
-  } else {
+  if (!controller_node_handle.getParam("publish_rate", publish_rate)) {
     ROS_INFO_STREAM("FrankaStateController: Did not find publish_rate. Using default "
                     << publish_rate << " [Hz].");
   }
+  trigger_publish_ = franka_hw::TriggerRate(publish_rate);
 
   if (!controller_node_handle.getParam("joint_names", joint_names_) ||
       joint_names_.size() != robot_state_.q.size()) {
@@ -173,8 +163,8 @@ bool FrankaStateController::init(hardware_interface::RobotHW* robot_hardware,
   }
 
   try {
-    franka_state_handle_.reset(
-        new franka_hw::FrankaStateHandle(franka_state_interface_->getHandle(arm_id_ + "_robot")));
+    franka_state_handle_ = std::make_unique<franka_hw::FrankaStateHandle>(
+        franka_state_interface_->getHandle(arm_id_ + "_robot"));
   } catch (const hardware_interface::HardwareInterfaceException& ex) {
     ROS_ERROR_STREAM("FrankaStateController: Exception getting franka state handle: " << ex.what());
     return false;
diff --git a/franka_control/src/services.cpp b/franka_control/src/services.cpp
index 0445ea2426e594fa2c03a5f75945319a86155cad..c7a47c91b6f8a98d5e2a76cf86b07e5a4c9cafcf 100644
--- a/franka_control/src/services.cpp
+++ b/franka_control/src/services.cpp
@@ -40,7 +40,7 @@ void setKFrame(franka::Robot& robot,
 void setForceTorqueCollisionBehavior(franka::Robot& robot,
                                      const SetForceTorqueCollisionBehavior::Request& req,
                                      SetForceTorqueCollisionBehavior::Response& /* res */
-                                     ) {
+) {
   std::array<double, 7> lower_torque_thresholds_nominal;
   std::copy(req.lower_torque_thresholds_nominal.cbegin(),
             req.lower_torque_thresholds_nominal.cend(), lower_torque_thresholds_nominal.begin());
diff --git a/franka_example_controllers/src/cartesian_impedance_example_controller.cpp b/franka_example_controllers/src/cartesian_impedance_example_controller.cpp
index 84afb873ed47526ea933c7f3da08c238e152e3cd..1d9120adc3f0e5eb0cca2bff66ce58a188cd0a5b 100644
--- a/franka_example_controllers/src/cartesian_impedance_example_controller.cpp
+++ b/franka_example_controllers/src/cartesian_impedance_example_controller.cpp
@@ -3,6 +3,7 @@
 #include <franka_example_controllers/cartesian_impedance_example_controller.h>
 
 #include <cmath>
+#include <memory>
 
 #include <controller_interface/controller_base.h>
 #include <franka/robot_state.h>
@@ -35,16 +36,15 @@ bool CartesianImpedanceExampleController::init(hardware_interface::RobotHW* robo
     return false;
   }
 
-  franka_hw::FrankaModelInterface* model_interface =
-      robot_hw->get<franka_hw::FrankaModelInterface>();
+  auto* model_interface = robot_hw->get<franka_hw::FrankaModelInterface>();
   if (model_interface == nullptr) {
     ROS_ERROR_STREAM(
         "CartesianImpedanceExampleController: Error getting model interface from hardware");
     return false;
   }
   try {
-    model_handle_.reset(
-        new franka_hw::FrankaModelHandle(model_interface->getHandle(arm_id + "_model")));
+    model_handle_ = std::make_unique<franka_hw::FrankaModelHandle>(
+        model_interface->getHandle(arm_id + "_model"));
   } catch (hardware_interface::HardwareInterfaceException& ex) {
     ROS_ERROR_STREAM(
         "CartesianImpedanceExampleController: Exception getting model handle from interface: "
@@ -52,16 +52,15 @@ bool CartesianImpedanceExampleController::init(hardware_interface::RobotHW* robo
     return false;
   }
 
-  franka_hw::FrankaStateInterface* state_interface =
-      robot_hw->get<franka_hw::FrankaStateInterface>();
+  auto* state_interface = robot_hw->get<franka_hw::FrankaStateInterface>();
   if (state_interface == nullptr) {
     ROS_ERROR_STREAM(
         "CartesianImpedanceExampleController: Error getting state interface from hardware");
     return false;
   }
   try {
-    state_handle_.reset(
-        new franka_hw::FrankaStateHandle(state_interface->getHandle(arm_id + "_robot")));
+    state_handle_ = std::make_unique<franka_hw::FrankaStateHandle>(
+        state_interface->getHandle(arm_id + "_robot"));
   } catch (hardware_interface::HardwareInterfaceException& ex) {
     ROS_ERROR_STREAM(
         "CartesianImpedanceExampleController: Exception getting state handle from interface: "
@@ -69,8 +68,7 @@ bool CartesianImpedanceExampleController::init(hardware_interface::RobotHW* robo
     return false;
   }
 
-  hardware_interface::EffortJointInterface* effort_joint_interface =
-      robot_hw->get<hardware_interface::EffortJointInterface>();
+  auto* effort_joint_interface = robot_hw->get<hardware_interface::EffortJointInterface>();
   if (effort_joint_interface == nullptr) {
     ROS_ERROR_STREAM(
         "CartesianImpedanceExampleController: Error getting effort joint interface from hardware");
@@ -89,9 +87,10 @@ bool CartesianImpedanceExampleController::init(hardware_interface::RobotHW* robo
   dynamic_reconfigure_compliance_param_node_ =
       ros::NodeHandle("dynamic_reconfigure_compliance_param_node");
 
-  dynamic_server_compliance_param_.reset(
-      new dynamic_reconfigure::Server<franka_example_controllers::compliance_paramConfig>(
-          dynamic_reconfigure_compliance_param_node_));
+  dynamic_server_compliance_param_ = std::make_unique<
+      dynamic_reconfigure::Server<franka_example_controllers::compliance_paramConfig>>(
+
+      dynamic_reconfigure_compliance_param_node_);
   dynamic_server_compliance_param_->setCallback(
       boost::bind(&CartesianImpedanceExampleController::complianceParamCallback, this, _1, _2));
 
@@ -114,9 +113,9 @@ void CartesianImpedanceExampleController::starting(const ros::Time& /*time*/) {
   std::array<double, 42> jacobian_array =
       model_handle_->getZeroJacobian(franka::Frame::kEndEffector);
   // convert to eigen
-  Eigen::Map<Eigen::Matrix<double, 6, 7> > jacobian(jacobian_array.data());
-  Eigen::Map<Eigen::Matrix<double, 7, 1> > dq_initial(initial_state.dq.data());
-  Eigen::Map<Eigen::Matrix<double, 7, 1> > q_initial(initial_state.q.data());
+  Eigen::Map<Eigen::Matrix<double, 6, 7>> jacobian(jacobian_array.data());
+  Eigen::Map<Eigen::Matrix<double, 7, 1>> dq_initial(initial_state.dq.data());
+  Eigen::Map<Eigen::Matrix<double, 7, 1>> q_initial(initial_state.q.data());
   Eigen::Affine3d initial_transform(Eigen::Matrix4d::Map(initial_state.O_T_EE.data()));
 
   // set equilibrium point to current state
@@ -138,11 +137,11 @@ void CartesianImpedanceExampleController::update(const ros::Time& /*time*/,
       model_handle_->getZeroJacobian(franka::Frame::kEndEffector);
 
   // convert to Eigen
-  Eigen::Map<Eigen::Matrix<double, 7, 1> > coriolis(coriolis_array.data());
-  Eigen::Map<Eigen::Matrix<double, 6, 7> > jacobian(jacobian_array.data());
-  Eigen::Map<Eigen::Matrix<double, 7, 1> > q(robot_state.q.data());
-  Eigen::Map<Eigen::Matrix<double, 7, 1> > dq(robot_state.dq.data());
-  Eigen::Map<Eigen::Matrix<double, 7, 1> > tau_J_d(  // NOLINT (readability-identifier-naming)
+  Eigen::Map<Eigen::Matrix<double, 7, 1>> coriolis(coriolis_array.data());
+  Eigen::Map<Eigen::Matrix<double, 6, 7>> jacobian(jacobian_array.data());
+  Eigen::Map<Eigen::Matrix<double, 7, 1>> q(robot_state.q.data());
+  Eigen::Map<Eigen::Matrix<double, 7, 1>> dq(robot_state.dq.data());
+  Eigen::Map<Eigen::Matrix<double, 7, 1>> tau_J_d(  // NOLINT (readability-identifier-naming)
       robot_state.tau_J_d.data());
   Eigen::Affine3d transform(Eigen::Matrix4d::Map(robot_state.O_T_EE.data()));
   Eigen::Vector3d position(transform.translation());
diff --git a/franka_example_controllers/src/cartesian_pose_example_controller.cpp b/franka_example_controllers/src/cartesian_pose_example_controller.cpp
index ae1b787aa97fe89d8ce80a028a02a698600b95d4..af69500f3b79d783fd08f8361c63f42da69c9e2e 100644
--- a/franka_example_controllers/src/cartesian_pose_example_controller.cpp
+++ b/franka_example_controllers/src/cartesian_pose_example_controller.cpp
@@ -3,6 +3,7 @@
 #include <franka_example_controllers/cartesian_pose_example_controller.h>
 
 #include <cmath>
+#include <memory>
 #include <stdexcept>
 #include <string>
 
@@ -31,8 +32,8 @@ bool CartesianPoseExampleController::init(hardware_interface::RobotHW* robot_har
   }
 
   try {
-    cartesian_pose_handle_.reset(new franka_hw::FrankaCartesianPoseHandle(
-        cartesian_pose_interface_->getHandle(arm_id + "_robot")));
+    cartesian_pose_handle_ = std::make_unique<franka_hw::FrankaCartesianPoseHandle>(
+        cartesian_pose_interface_->getHandle(arm_id + "_robot"));
   } catch (const hardware_interface::HardwareInterfaceException& e) {
     ROS_ERROR_STREAM(
         "CartesianPoseExampleController: Exception getting Cartesian handle: " << e.what());
diff --git a/franka_example_controllers/src/cartesian_velocity_example_controller.cpp b/franka_example_controllers/src/cartesian_velocity_example_controller.cpp
index 59e0f6fedbf02a3d85d5884e74c36780694c8d95..67c34a255b04180b5cb4cfb5d48c003b4637705e 100644
--- a/franka_example_controllers/src/cartesian_velocity_example_controller.cpp
+++ b/franka_example_controllers/src/cartesian_velocity_example_controller.cpp
@@ -4,6 +4,7 @@
 
 #include <array>
 #include <cmath>
+#include <memory>
 #include <string>
 
 #include <controller_interface/controller_base.h>
@@ -31,8 +32,8 @@ bool CartesianVelocityExampleController::init(hardware_interface::RobotHW* robot
     return false;
   }
   try {
-    velocity_cartesian_handle_.reset(new franka_hw::FrankaCartesianVelocityHandle(
-        velocity_cartesian_interface_->getHandle(arm_id + "_robot")));
+    velocity_cartesian_handle_ = std::make_unique<franka_hw::FrankaCartesianVelocityHandle>(
+        velocity_cartesian_interface_->getHandle(arm_id + "_robot"));
   } catch (const hardware_interface::HardwareInterfaceException& e) {
     ROS_ERROR_STREAM(
         "CartesianVelocityExampleController: Exception getting Cartesian handle: " << e.what());
diff --git a/franka_example_controllers/src/elbow_example_controller.cpp b/franka_example_controllers/src/elbow_example_controller.cpp
index f12137ebd6f75927d16de71ad6a13bb2a47d2290..c988cb502164eb85ef0a803f9347b58a28ab625a 100644
--- a/franka_example_controllers/src/elbow_example_controller.cpp
+++ b/franka_example_controllers/src/elbow_example_controller.cpp
@@ -3,6 +3,7 @@
 #include <franka_example_controllers/elbow_example_controller.h>
 
 #include <cmath>
+#include <memory>
 #include <stdexcept>
 #include <string>
 
@@ -29,8 +30,8 @@ bool ElbowExampleController::init(hardware_interface::RobotHW* robot_hardware,
   }
 
   try {
-    cartesian_pose_handle_.reset(new franka_hw::FrankaCartesianPoseHandle(
-        cartesian_pose_interface_->getHandle(arm_id + "_robot")));
+    cartesian_pose_handle_ = std::make_unique<franka_hw::FrankaCartesianPoseHandle>(
+        cartesian_pose_interface_->getHandle(arm_id + "_robot"));
   } catch (const hardware_interface::HardwareInterfaceException& e) {
     ROS_ERROR_STREAM("ElbowExampleController: Exception getting Cartesian handle: " << e.what());
     return false;
diff --git a/franka_example_controllers/src/force_example_controller.cpp b/franka_example_controllers/src/force_example_controller.cpp
index 4e49c2f6ef78ccc01e65e8c1d8870657c5bbaed0..36cce5da7fb74c1f018240ba22615fd88c75e8eb 100644
--- a/franka_example_controllers/src/force_example_controller.cpp
+++ b/franka_example_controllers/src/force_example_controller.cpp
@@ -3,6 +3,7 @@
 #include <franka_example_controllers/force_example_controller.h>
 
 #include <cmath>
+#include <memory>
 
 #include <controller_interface/controller_base.h>
 #include <pluginlib/class_list_macros.h>
@@ -30,38 +31,35 @@ bool ForceExampleController::init(hardware_interface::RobotHW* robot_hw,
     return false;
   }
 
-  franka_hw::FrankaModelInterface* model_interface =
-      robot_hw->get<franka_hw::FrankaModelInterface>();
+  auto* model_interface = robot_hw->get<franka_hw::FrankaModelInterface>();
   if (model_interface == nullptr) {
     ROS_ERROR_STREAM("ForceExampleController: Error getting model interface from hardware");
     return false;
   }
   try {
-    model_handle_.reset(
-        new franka_hw::FrankaModelHandle(model_interface->getHandle(arm_id + "_model")));
+    model_handle_ = std::make_unique<franka_hw::FrankaModelHandle>(
+        model_interface->getHandle(arm_id + "_model"));
   } catch (hardware_interface::HardwareInterfaceException& ex) {
     ROS_ERROR_STREAM(
         "ForceExampleController: Exception getting model handle from interface: " << ex.what());
     return false;
   }
 
-  franka_hw::FrankaStateInterface* state_interface =
-      robot_hw->get<franka_hw::FrankaStateInterface>();
+  auto* state_interface = robot_hw->get<franka_hw::FrankaStateInterface>();
   if (state_interface == nullptr) {
     ROS_ERROR_STREAM("ForceExampleController: Error getting state interface from hardware");
     return false;
   }
   try {
-    state_handle_.reset(
-        new franka_hw::FrankaStateHandle(state_interface->getHandle(arm_id + "_robot")));
+    state_handle_ = std::make_unique<franka_hw::FrankaStateHandle>(
+        state_interface->getHandle(arm_id + "_robot"));
   } catch (hardware_interface::HardwareInterfaceException& ex) {
     ROS_ERROR_STREAM(
         "ForceExampleController: Exception getting state handle from interface: " << ex.what());
     return false;
   }
 
-  hardware_interface::EffortJointInterface* effort_joint_interface =
-      robot_hw->get<hardware_interface::EffortJointInterface>();
+  auto* effort_joint_interface = robot_hw->get<hardware_interface::EffortJointInterface>();
   if (effort_joint_interface == nullptr) {
     ROS_ERROR_STREAM("ForceExampleController: Error getting effort joint interface from hardware");
     return false;
@@ -77,9 +75,10 @@ bool ForceExampleController::init(hardware_interface::RobotHW* robot_hw,
 
   dynamic_reconfigure_desired_mass_param_node_ =
       ros::NodeHandle("dynamic_reconfigure_desired_mass_param_node");
-  dynamic_server_desired_mass_param_.reset(
-      new dynamic_reconfigure::Server<franka_example_controllers::desired_mass_paramConfig>(
-          dynamic_reconfigure_desired_mass_param_node_));
+  dynamic_server_desired_mass_param_ = std::make_unique<
+      dynamic_reconfigure::Server<franka_example_controllers::desired_mass_paramConfig>>(
+
+      dynamic_reconfigure_desired_mass_param_node_);
   dynamic_server_desired_mass_param_->setCallback(
       boost::bind(&ForceExampleController::desiredMassParamCallback, this, _1, _2));
 
@@ -89,8 +88,8 @@ bool ForceExampleController::init(hardware_interface::RobotHW* robot_hw,
 void ForceExampleController::starting(const ros::Time& /*time*/) {
   franka::RobotState robot_state = state_handle_->getRobotState();
   std::array<double, 7> gravity_array = model_handle_->getGravity();
-  Eigen::Map<Eigen::Matrix<double, 7, 1> > tau_measured(robot_state.tau_J.data());
-  Eigen::Map<Eigen::Matrix<double, 7, 1> > gravity(gravity_array.data());
+  Eigen::Map<Eigen::Matrix<double, 7, 1>> tau_measured(robot_state.tau_J.data());
+  Eigen::Map<Eigen::Matrix<double, 7, 1>> gravity(gravity_array.data());
   // Bias correction for the current external torque
   tau_ext_initial_ = tau_measured - gravity;
   tau_error_.setZero();
@@ -101,11 +100,11 @@ void ForceExampleController::update(const ros::Time& /*time*/, const ros::Durati
   std::array<double, 42> jacobian_array =
       model_handle_->getZeroJacobian(franka::Frame::kEndEffector);
   std::array<double, 7> gravity_array = model_handle_->getGravity();
-  Eigen::Map<Eigen::Matrix<double, 6, 7> > jacobian(jacobian_array.data());
-  Eigen::Map<Eigen::Matrix<double, 7, 1> > tau_measured(robot_state.tau_J.data());
-  Eigen::Map<Eigen::Matrix<double, 7, 1> > tau_J_d(  // NOLINT (readability-identifier-naming)
+  Eigen::Map<Eigen::Matrix<double, 6, 7>> jacobian(jacobian_array.data());
+  Eigen::Map<Eigen::Matrix<double, 7, 1>> tau_measured(robot_state.tau_J.data());
+  Eigen::Map<Eigen::Matrix<double, 7, 1>> tau_J_d(  // NOLINT (readability-identifier-naming)
       robot_state.tau_J_d.data());
-  Eigen::Map<Eigen::Matrix<double, 7, 1> > gravity(gravity_array.data());
+  Eigen::Map<Eigen::Matrix<double, 7, 1>> gravity(gravity_array.data());
 
   Eigen::VectorXd tau_d(7), desired_force_torque(6), tau_cmd(7), tau_ext(7);
   desired_force_torque.setZero();
diff --git a/franka_example_controllers/src/joint_impedance_example_controller.cpp b/franka_example_controllers/src/joint_impedance_example_controller.cpp
index bfb075e2873fc056dc60b65320cf43dcdfb7ac85..607e87da9d919f03cef4925f46b92c8b9ab5e1da 100644
--- a/franka_example_controllers/src/joint_impedance_example_controller.cpp
+++ b/franka_example_controllers/src/joint_impedance_example_controller.cpp
@@ -3,6 +3,7 @@
 #include <franka_example_controllers/joint_impedance_example_controller.h>
 
 #include <cmath>
+#include <memory>
 
 #include <controller_interface/controller_base.h>
 #include <pluginlib/class_list_macros.h>
@@ -72,16 +73,15 @@ bool JointImpedanceExampleController::init(hardware_interface::RobotHW* robot_hw
                     << coriolis_factor_);
   }
 
-  franka_hw::FrankaModelInterface* model_interface =
-      robot_hw->get<franka_hw::FrankaModelInterface>();
+  auto* model_interface = robot_hw->get<franka_hw::FrankaModelInterface>();
   if (model_interface == nullptr) {
     ROS_ERROR_STREAM(
         "JointImpedanceExampleController: Error getting model interface from hardware");
     return false;
   }
   try {
-    model_handle_.reset(
-        new franka_hw::FrankaModelHandle(model_interface->getHandle(arm_id + "_model")));
+    model_handle_ = std::make_unique<franka_hw::FrankaModelHandle>(
+        model_interface->getHandle(arm_id + "_model"));
   } catch (hardware_interface::HardwareInterfaceException& ex) {
     ROS_ERROR_STREAM(
         "JointImpedanceExampleController: Exception getting model handle from interface: "
@@ -89,16 +89,15 @@ bool JointImpedanceExampleController::init(hardware_interface::RobotHW* robot_hw
     return false;
   }
 
-  franka_hw::FrankaPoseCartesianInterface* cartesian_pose_interface =
-      robot_hw->get<franka_hw::FrankaPoseCartesianInterface>();
+  auto* cartesian_pose_interface = robot_hw->get<franka_hw::FrankaPoseCartesianInterface>();
   if (cartesian_pose_interface == nullptr) {
     ROS_ERROR_STREAM(
         "JointImpedanceExampleController: Error getting cartesian pose interface from hardware");
     return false;
   }
   try {
-    cartesian_pose_handle_.reset(new franka_hw::FrankaCartesianPoseHandle(
-        cartesian_pose_interface->getHandle(arm_id + "_robot")));
+    cartesian_pose_handle_ = std::make_unique<franka_hw::FrankaCartesianPoseHandle>(
+        cartesian_pose_interface->getHandle(arm_id + "_robot"));
   } catch (hardware_interface::HardwareInterfaceException& ex) {
     ROS_ERROR_STREAM(
         "JointImpedanceExampleController: Exception getting cartesian pose handle from interface: "
@@ -106,8 +105,7 @@ bool JointImpedanceExampleController::init(hardware_interface::RobotHW* robot_hw
     return false;
   }
 
-  hardware_interface::EffortJointInterface* effort_joint_interface =
-      robot_hw->get<hardware_interface::EffortJointInterface>();
+  auto* effort_joint_interface = robot_hw->get<hardware_interface::EffortJointInterface>();
   if (effort_joint_interface == nullptr) {
     ROS_ERROR_STREAM(
         "JointImpedanceExampleController: Error getting effort joint interface from hardware");
diff --git a/franka_example_controllers/src/model_example_controller.cpp b/franka_example_controllers/src/model_example_controller.cpp
index 218855945ae47a92a2bab03ecd4b24729060da14..f9ccea429ad6b0c9ebd47c8f4d704c0e6ec47ff2 100644
--- a/franka_example_controllers/src/model_example_controller.cpp
+++ b/franka_example_controllers/src/model_example_controller.cpp
@@ -7,6 +7,7 @@
 #include <array>
 #include <cstring>
 #include <iterator>
+#include <memory>
 
 #include <controller_interface/controller_base.h>
 #include <hardware_interface/hardware_interface.h>
@@ -48,8 +49,8 @@ bool ModelExampleController::init(hardware_interface::RobotHW* robot_hw,
   }
 
   try {
-    franka_state_handle_.reset(
-        new franka_hw::FrankaStateHandle(franka_state_interface_->getHandle(arm_id + "_robot")));
+    franka_state_handle_ = std::make_unique<franka_hw::FrankaStateHandle>(
+        franka_state_interface_->getHandle(arm_id + "_robot"));
   } catch (const hardware_interface::HardwareInterfaceException& ex) {
     ROS_ERROR_STREAM(
         "ModelExampleController: Exception getting franka state handle: " << ex.what());
@@ -57,8 +58,8 @@ bool ModelExampleController::init(hardware_interface::RobotHW* robot_hw,
   }
 
   try {
-    model_handle_.reset(
-        new franka_hw::FrankaModelHandle(model_interface_->getHandle(arm_id + "_model")));
+    model_handle_ = std::make_unique<franka_hw::FrankaModelHandle>(
+        model_interface_->getHandle(arm_id + "_model"));
   } catch (hardware_interface::HardwareInterfaceException& ex) {
     ROS_ERROR_STREAM(
         "ModelExampleController: Exception getting model handle from interface: " << ex.what());
diff --git a/franka_gripper/src/franka_gripper_node.cpp b/franka_gripper/src/franka_gripper_node.cpp
index 8b5b5eaeeab8a2e39c67d0b8e0d2623f5267f66c..64a8d254854320e7f348159a5d53d5f3fc1688c6 100644
--- a/franka_gripper/src/franka_gripper_node.cpp
+++ b/franka_gripper/src/franka_gripper_node.cpp
@@ -84,46 +84,56 @@ int main(int argc, char** argv) {
 
   franka::Gripper gripper(robot_ip);
 
-  std::function<bool(const HomingGoalConstPtr&)> homing_handler =
-      std::bind(homing, std::cref(gripper), std::placeholders::_1);
-  std::function<bool(const StopGoalConstPtr&)> stop_handler =
-      std::bind(stop, std::cref(gripper), std::placeholders::_1);
-  std::function<bool(const GraspGoalConstPtr&)> grasp_handler =
-      std::bind(grasp, std::cref(gripper), std::placeholders::_1);
-  std::function<bool(const MoveGoalConstPtr&)> move_handler =
-      std::bind(move, std::cref(gripper), std::placeholders::_1);
-
-  SimpleActionServer<HomingAction> homing_action_server_(
+  auto homing_handler = [&gripper](auto&& goal) { return homing(gripper, goal); };
+  auto stop_handler = [&gripper](auto&& goal) { return stop(gripper, goal); };
+  auto grasp_handler = [&gripper](auto&& goal) { return grasp(gripper, goal); };
+  auto move_handler = [&gripper](auto&& goal) { return move(gripper, goal); };
+
+  SimpleActionServer<HomingAction> homing_action_server(
       node_handle, "homing",
-      std::bind(handleErrors<HomingAction, HomingGoalConstPtr, HomingResult>,
-                &homing_action_server_, homing_handler, std::placeholders::_1),
+      [=, &homing_action_server](auto&& goal) {
+        return handleErrors<franka_gripper::HomingAction, franka_gripper::HomingGoalConstPtr,
+                            franka_gripper::HomingResult>(&homing_action_server, homing_handler,
+                                                          goal);
+      },
       false);
 
-  SimpleActionServer<StopAction> stop_action_server_(
-      node_handle, "stop", std::bind(handleErrors<StopAction, StopGoalConstPtr, StopResult>,
-                                     &stop_action_server_, stop_handler, std::placeholders::_1),
+  SimpleActionServer<StopAction> stop_action_server(
+      node_handle, "stop",
+      [=, &stop_action_server](auto&& goal) {
+        return handleErrors<franka_gripper::StopAction, franka_gripper::StopGoalConstPtr,
+                            franka_gripper::StopResult>(&stop_action_server, stop_handler, goal);
+      },
       false);
 
-  SimpleActionServer<MoveAction> move_action_server_(
-      node_handle, "move", std::bind(handleErrors<MoveAction, MoveGoalConstPtr, MoveResult>,
-                                     &move_action_server_, move_handler, std::placeholders::_1),
+  SimpleActionServer<MoveAction> move_action_server(
+      node_handle, "move",
+      [=, &move_action_server](auto&& goal) {
+        return handleErrors<franka_gripper::MoveAction, franka_gripper::MoveGoalConstPtr,
+                            franka_gripper::MoveResult>(&move_action_server, move_handler, goal);
+      },
       false);
 
-  SimpleActionServer<GraspAction> grasp_action_server_(
-      node_handle, "grasp", std::bind(handleErrors<GraspAction, GraspGoalConstPtr, GraspResult>,
-                                      &grasp_action_server_, grasp_handler, std::placeholders::_1),
+  SimpleActionServer<GraspAction> grasp_action_server(
+      node_handle, "grasp",
+      [=, &grasp_action_server](auto&& goal) {
+        return handleErrors<franka_gripper::GraspAction, franka_gripper::GraspGoalConstPtr,
+                            franka_gripper::GraspResult>(&grasp_action_server, grasp_handler, goal);
+      },
       false);
 
   SimpleActionServer<GripperCommandAction> gripper_command_action_server(
       node_handle, "gripper_action",
-      std::bind(&gripperCommandExecuteCallback, std::cref(gripper), default_grasp_epsilon,
-                default_speed, &gripper_command_action_server, std::placeholders::_1),
+      [=, &gripper, &gripper_command_action_server](auto&& goal) {
+        return gripperCommandExecuteCallback(gripper, default_grasp_epsilon, default_speed,
+                                             &gripper_command_action_server, goal);
+      },
       false);
 
-  homing_action_server_.start();
-  stop_action_server_.start();
-  move_action_server_.start();
-  grasp_action_server_.start();
+  homing_action_server.start();
+  stop_action_server.start();
+  move_action_server.start();
+  grasp_action_server.start();
   gripper_command_action_server.start();
 
   double publish_rate(30.0);
diff --git a/franka_hw/CMakeLists.txt b/franka_hw/CMakeLists.txt
index 5d1469932fb1024322c2d3b2ab777d754e652d96..821f48b5e0a652b4c1487ba52b3142de5cb74a6f 100644
--- a/franka_hw/CMakeLists.txt
+++ b/franka_hw/CMakeLists.txt
@@ -9,6 +9,7 @@ find_package(catkin REQUIRED COMPONENTS
   hardware_interface
   joint_limits_interface
   roscpp
+  urdf
 )
 
 find_package(Franka 0.5.0 REQUIRED)
@@ -16,7 +17,7 @@ find_package(Franka 0.5.0 REQUIRED)
 catkin_package(
   INCLUDE_DIRS include
   LIBRARIES franka_hw
-  CATKIN_DEPENDS controller_interface hardware_interface joint_limits_interface roscpp
+  CATKIN_DEPENDS controller_interface hardware_interface joint_limits_interface roscpp urdf
   DEPENDS Franka
 )
 
diff --git a/franka_hw/include/franka_hw/franka_hw.h b/franka_hw/include/franka_hw/franka_hw.h
index e563879d3b364b6f073cc60e3021d474b7d6bb46..3950d81fbca89d91b2ef96dff788c26021b5acef 100644
--- a/franka_hw/include/franka_hw/franka_hw.h
+++ b/franka_hw/include/franka_hw/franka_hw.h
@@ -11,17 +11,16 @@
 #include <franka/model.h>
 #include <franka/robot.h>
 #include <franka/robot_state.h>
+#include <franka_hw/control_mode.h>
+#include <franka_hw/franka_cartesian_command_interface.h>
+#include <franka_hw/franka_model_interface.h>
+#include <franka_hw/franka_state_interface.h>
 #include <hardware_interface/joint_command_interface.h>
 #include <hardware_interface/joint_state_interface.h>
 #include <hardware_interface/robot_hw.h>
 #include <joint_limits_interface/joint_limits_interface.h>
-#include <ros/node_handle.h>
 #include <ros/time.h>
-
-#include <franka_hw/control_mode.h>
-#include <franka_hw/franka_cartesian_command_interface.h>
-#include <franka_hw/franka_model_interface.h>
-#include <franka_hw/franka_state_interface.h>
+#include <urdf/model.h>
 
 namespace franka_hw {
 
@@ -34,42 +33,46 @@ class FrankaHW : public hardware_interface::RobotHW {
    *
    * @param[in] joint_names An array of joint names being controlled.
    * @param[in] arm_id Unique identifier for the robot being controlled.
-   * @param[in] limit_rate An array of booleans indicating if the rate limiter should be used or not
-   * for each interface
-   * @param[in] internal_controller Internal controller to be used for control loops using only
-   * motion generation
-   * @param[in] cutoff_freq An array of doubles indicating the cutoff frequency for the lowpass
-   * applied in each interface
-   * @param[in] node_handle A node handle to get parameters from.
+   * @param[in] urdf_model A URDF model to initialize joint limits from.
+   * @param[in] get_limit_rate Getter that should return true if the rate limiter
+   * should be used, false otherwise. Defaults to true.
+   * @param[in] get_cutoff_frequency Getter for cutoff frequency for the low-pass filter.
+   * Defaults to franka::kDefaultCutoffFrequency.
+   * @param[in] get_internal_controller Getter for an internal controller to
+   * be used for control loops using only motion generation. Defaults to joint impedance.
    */
   FrankaHW(const std::array<std::string, 7>& joint_names,
            const std::string& arm_id,
-           franka::ControllerMode internal_controller,
-           const std::array<bool, 5>& limit_rate,
-           const std::array<double, 5>& cutoff_freq,
-           const ros::NodeHandle& node_handle);
+           const urdf::Model& urdf_model,
+           std::function<bool()> get_limit_rate = []() { return true; },
+           std::function<double()> get_cutoff_frequency =
+               []() { return franka::kDefaultCutoffFrequency; },
+           std::function<franka::ControllerMode()> get_internal_controller =
+               []() { return franka::ControllerMode::kJointImpedance; });
 
   /**
    * Creates an instance of FrankaHW that provides a model interface.
    *
    * @param[in] joint_names An array of joint names being controlled.
    * @param[in] arm_id Unique identifier for the robot being controlled.
-   * @param[in] node_handle A node handle to get parameters from.
-   * @param[in] limit_rate An array of booleans indicating if the rate limiter should be used or not
-   * for each interface
-   * @param[in] internal_controller Internal controller to be used for control loops using only
-   * motion generation
-   * @param[in] cutoff_freq An array of doubles indicating the cutoff frequency for the lowpass
-   * applied in each interface
+   * @param[in] urdf_model A URDF model to initialize joint limits from.
    * @param[in] model Robot model.
+   * @param[in] get_limit_rate Getter that should return true if the rate limiter
+   * should be used, false otherwise. Defaults to true.
+   * @param[in] get_cutoff_frequency Getter for cutoff frequency for the low-pass filter.
+   * Defaults to franka::kDefaultCutoffFrequency.
+   * @param[in] get_internal_controller Getter for an internal controller to
+   * be used for control loops using only motion generation. Defaults to joint impedance.
    */
   FrankaHW(const std::array<std::string, 7>& joint_names,
            const std::string& arm_id,
-           franka::ControllerMode internal_controller,
-           const std::array<bool, 5>& limit_rate,
-           const std::array<double, 5>& cutoff_freq,
-           const ros::NodeHandle& node_handle,
-           franka::Model& model);
+           const urdf::Model& urdf_model,
+           franka::Model& model,
+           std::function<bool()> get_limit_rate = []() { return true; },
+           std::function<double()> get_cutoff_frequency =
+               []() { return franka::kDefaultCutoffFrequency; },
+           std::function<franka::ControllerMode()> get_internal_controller =
+               []() { return franka::ControllerMode::kJointImpedance; });
 
   ~FrankaHW() override = default;
 
@@ -90,7 +93,7 @@ class FrankaHW : public hardware_interface::RobotHW {
    * @throw franka::RealtimeException if realtime priority cannot be set for the current thread.
    */
   void control(franka::Robot& robot,
-               std::function<bool(const ros::Time&, const ros::Duration&)> ros_callback);
+               const std::function<bool(const ros::Time&, const ros::Duration&)>& ros_callback);
 
   /**
    * Updates the controller interfaces from the given robot state.
@@ -126,13 +129,13 @@ class FrankaHW : public hardware_interface::RobotHW {
                 const std::list<hardware_interface::ControllerInfo>&) override;
 
   /**
-  * Prepares switching between controllers (not real-time capable).
-  *
-  * @param[in] start_list Controllers requested to be started.
-  * @param[in] stop_list Controllers requested to be stopped.
-  *
-  * @return True if the preparation has been successful, false otherwise.
-  */
+   * Prepares switching between controllers (not real-time capable).
+   *
+   * @param[in] start_list Controllers requested to be started.
+   * @param[in] stop_list Controllers requested to be stopped.
+   *
+   * @return True if the preparation has been successful, false otherwise.
+   */
   bool prepareSwitch(const std::list<hardware_interface::ControllerInfo>& start_list,
                      const std::list<hardware_interface::ControllerInfo>& stop_list) override;
 
@@ -178,7 +181,7 @@ class FrankaHW : public hardware_interface::RobotHW {
                     const franka::RobotState& robot_state,
                     franka::Duration time_step) {
     robot_state_ = robot_state;
-    if (!controller_active_ || ros_callback && !ros_callback(robot_state, time_step)) {
+    if (!controller_active_ || (ros_callback && !ros_callback(robot_state, time_step))) {
       return franka::MotionFinished(command);
     }
     return command;
@@ -201,9 +204,9 @@ class FrankaHW : public hardware_interface::RobotHW {
 
   std::array<std::string, 7> joint_names_;
   const std::string arm_id_;
-  franka::ControllerMode internal_controller_;
-  std::array<bool, 5> limit_rate_;
-  std::array<double, 5> cutoff_freq_;
+  std::function<franka::ControllerMode()> get_internal_controller_;
+  std::function<bool()> get_limit_rate_;
+  std::function<double()> get_cutoff_frequency_;
 
   franka::JointPositions position_joint_command_;
   franka::JointVelocities velocity_joint_command_;
diff --git a/franka_hw/package.xml b/franka_hw/package.xml
index 78ebaf00519618c18aa597434d5d78302d4276df..0d0b8a1eed3aca6206fb07d706c0023a745e4406 100644
--- a/franka_hw/package.xml
+++ b/franka_hw/package.xml
@@ -13,11 +13,12 @@
 
   <buildtool_depend>catkin</buildtool_depend>
 
-  <depend>libfranka</depend>
   <depend>controller_interface</depend>
   <depend>hardware_interface</depend>
   <depend>joint_limits_interface</depend>
+  <depend>libfranka</depend>
   <depend>roscpp</depend>
+  <depend>urdf</depend>
 
   <test_depend>franka_description</test_depend>
   <test_depend>gtest</test_depend>
diff --git a/franka_hw/src/control_mode.cpp b/franka_hw/src/control_mode.cpp
index c8c724fecbb3a8eb4764f2e770973e20f31b6cf9..cfd89c22e0743c98d0b362b3fc9cc2220a7f98b1 100644
--- a/franka_hw/src/control_mode.cpp
+++ b/franka_hw/src/control_mode.cpp
@@ -15,19 +15,19 @@ std::ostream& operator<<(std::ostream& ostream, ControlMode mode) {
   } else {
     std::vector<std::string> names;
     if ((mode & ControlMode::JointTorque) != ControlMode::None) {
-      names.emplace_back("JointTorque");
+      names.emplace_back("joint_torque");
     }
     if ((mode & ControlMode::JointPosition) != ControlMode::None) {
-      names.emplace_back("JointPosition");
+      names.emplace_back("joint_position");
     }
     if ((mode & ControlMode::JointVelocity) != ControlMode::None) {
-      names.emplace_back("JointVelocity");
+      names.emplace_back("joint_velocity");
     }
     if ((mode & ControlMode::CartesianVelocity) != ControlMode::None) {
-      names.emplace_back("CartesianVelocity");
+      names.emplace_back("cartesian_velocity");
     }
     if ((mode & ControlMode::CartesianPose) != ControlMode::None) {
-      names.emplace_back("CartesianPose");
+      names.emplace_back("cartesian_pose");
     }
     std::copy(names.cbegin(), names.cend() - 1, std::ostream_iterator<std::string>(ostream, ", "));
     ostream << names.back();
diff --git a/franka_hw/src/franka_hw.cpp b/franka_hw/src/franka_hw.cpp
index 5a454a0f989f577fd82cbcd5650ac14b8d1aeb3b..50f20d02d8fd24ac68805612a5443f611061acf5 100644
--- a/franka_hw/src/franka_hw.cpp
+++ b/franka_hw/src/franka_hw.cpp
@@ -3,26 +3,39 @@
 #include <franka_hw/franka_hw.h>
 
 #include <cstdint>
+#include <ostream>
+#include <utility>
 
 #include <franka/rate_limiting.h>
 #include <joint_limits_interface/joint_limits_urdf.h>
-#include <urdf/model.h>
 
 #include "resource_helpers.h"
 
 namespace franka_hw {
 
+namespace {
+std::ostream& operator<<(std::ostream& ostream, franka::ControllerMode mode) {
+  if (mode == franka::ControllerMode::kJointImpedance) {
+    ostream << "joint_impedance";
+  } else if (mode == franka::ControllerMode::kCartesianImpedance) {
+    ostream << "cartesian_impedance";
+  } else {
+    ostream << "<unknown>";
+  }
+}
+}  // anonymous namespace
+
 FrankaHW::FrankaHW(const std::array<std::string, 7>& joint_names,
                    const std::string& arm_id,
-                   franka::ControllerMode internal_controller,
-                   const std::array<bool, 5>& limit_rate,
-                   const std::array<double, 5>& cutoff_freq,
-                   const ros::NodeHandle& node_handle)
+                   const urdf::Model& urdf_model,
+                   std::function<bool()> get_limit_rate,
+                   std::function<double()> get_cutoff_frequency,
+                   std::function<franka::ControllerMode()> get_internal_controller)
     : joint_names_(joint_names),
       arm_id_(arm_id),
-      internal_controller_(internal_controller),
-      limit_rate_(limit_rate),
-      cutoff_freq_(cutoff_freq),
+      get_internal_controller_(std::move(get_internal_controller)),
+      get_limit_rate_(std::move(get_limit_rate)),
+      get_cutoff_frequency_(std::move(get_cutoff_frequency)),
       position_joint_command_({0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}),
       velocity_joint_command_({0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}),
       effort_joint_command_({0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}),
@@ -51,56 +64,50 @@ FrankaHW::FrankaHW(const std::array<std::string, 7>& joint_names,
     effort_joint_interface_.registerHandle(effort_joint_handle);
   }
 
-  if (node_handle.hasParam("robot_description")) {
-    urdf::Model urdf_model;
-    if (!urdf_model.initParamWithNodeHandle("robot_description", node_handle)) {
-      ROS_ERROR("FrankaHW: Could not initialize urdf model from robot_description");
-    } else {
-      joint_limits_interface::SoftJointLimits soft_limits;
-      joint_limits_interface::JointLimits joint_limits;
-
-      for (size_t i = 0; i < joint_names_.size(); i++) {
-        const std::string& joint_name = joint_names_[i];
-        auto urdf_joint = urdf_model.getJoint(joint_name);
-        if (!urdf_joint) {
-          ROS_ERROR_STREAM("FrankaHW: Could not get joint " << joint_name << " from urdf");
-        }
-        if (!urdf_joint->safety) {
-          ROS_ERROR_STREAM("FrankaHW: Joint " << joint_name << " has no safety");
-        }
-        if (!urdf_joint->limits) {
-          ROS_ERROR_STREAM("FrankaHW: Joint " << joint_name << " has no limits");
-        }
+  joint_limits_interface::SoftJointLimits soft_limits;
+  joint_limits_interface::JointLimits joint_limits;
 
-        if (joint_limits_interface::getSoftJointLimits(urdf_joint, soft_limits)) {
-          if (joint_limits_interface::getJointLimits(urdf_joint, joint_limits)) {
-            joint_limits.max_acceleration = franka::kMaxJointAcceleration[i];
-            joint_limits.has_acceleration_limits = true;
-            joint_limits.max_jerk = franka::kMaxJointJerk[i];
-            joint_limits.has_jerk_limits = true;
-            joint_limits_interface::PositionJointSoftLimitsHandle position_limit_handle(
-                position_joint_interface_.getHandle(joint_name), joint_limits, soft_limits);
-            position_joint_limit_interface_.registerHandle(position_limit_handle);
-
-            joint_limits_interface::VelocityJointSoftLimitsHandle velocity_limit_handle(
-                velocity_joint_interface_.getHandle(joint_name), joint_limits, soft_limits);
-            velocity_joint_limit_interface_.registerHandle(velocity_limit_handle);
-
-            joint_limits_interface::EffortJointSoftLimitsHandle effort_limit_handle(
-                effort_joint_interface_.getHandle(joint_name), joint_limits, soft_limits);
-            effort_joint_limit_interface_.registerHandle(effort_limit_handle);
-          } else {
-            ROS_ERROR_STREAM("FrankaHW: Could not parse joint limit for joint "
-                             << joint_name << " for joint limit interfaces");
-          }
-        } else {
-          ROS_ERROR_STREAM("FrankaHW: Could not parse soft joint limit for joint "
-                           << joint_name << " for joint limit interfaces");
-        }
+  for (size_t i = 0; i < joint_names_.size(); i++) {
+    const std::string& joint_name = joint_names_[i];
+    auto urdf_joint = urdf_model.getJoint(joint_name);
+    if (!urdf_joint) {
+      ROS_ERROR_STREAM("FrankaHW: Could not get joint " << joint_name << " from urdf");
+      continue;
+    }
+    if (!urdf_joint->safety) {
+      ROS_ERROR_STREAM("FrankaHW: Joint " << joint_name << " has no safety");
+      continue;
+    }
+    if (!urdf_joint->limits) {
+      ROS_ERROR_STREAM("FrankaHW: Joint " << joint_name << " has no limits");
+      continue;
+    }
+
+    if (joint_limits_interface::getSoftJointLimits(urdf_joint, soft_limits)) {
+      if (joint_limits_interface::getJointLimits(urdf_joint, joint_limits)) {
+        joint_limits.max_acceleration = franka::kMaxJointAcceleration[i];
+        joint_limits.has_acceleration_limits = true;
+        joint_limits.max_jerk = franka::kMaxJointJerk[i];
+        joint_limits.has_jerk_limits = true;
+        joint_limits_interface::PositionJointSoftLimitsHandle position_limit_handle(
+            position_joint_interface_.getHandle(joint_name), joint_limits, soft_limits);
+        position_joint_limit_interface_.registerHandle(position_limit_handle);
+
+        joint_limits_interface::VelocityJointSoftLimitsHandle velocity_limit_handle(
+            velocity_joint_interface_.getHandle(joint_name), joint_limits, soft_limits);
+        velocity_joint_limit_interface_.registerHandle(velocity_limit_handle);
+
+        joint_limits_interface::EffortJointSoftLimitsHandle effort_limit_handle(
+            effort_joint_interface_.getHandle(joint_name), joint_limits, soft_limits);
+        effort_joint_limit_interface_.registerHandle(effort_limit_handle);
+      } else {
+        ROS_ERROR_STREAM("FrankaHW: Could not parse joint limit for joint "
+                         << joint_name << " for joint limit interfaces");
       }
+    } else {
+      ROS_ERROR_STREAM("FrankaHW: Could not parse soft joint limit for joint "
+                       << joint_name << " for joint limit interfaces");
     }
-  } else {
-    ROS_WARN("FrankaHW: No parameter robot_description found to set joint limits!");
   }
 
   FrankaStateHandle franka_state_handle(arm_id_ + "_robot", robot_state_);
@@ -123,12 +130,17 @@ FrankaHW::FrankaHW(const std::array<std::string, 7>& joint_names,
 
 FrankaHW::FrankaHW(const std::array<std::string, 7>& joint_names,
                    const std::string& arm_id,
-                   franka::ControllerMode internal_controller,
-                   const std::array<bool, 5>& limit_rate,
-                   const std::array<double, 5>& cutoff_freq,
-                   const ros::NodeHandle& node_handle,
-                   franka::Model& model)
-    : FrankaHW(joint_names, arm_id, internal_controller, limit_rate, cutoff_freq, node_handle) {
+                   const urdf::Model& urdf_model,
+                   franka::Model& model,
+                   std::function<bool()> get_limit_rate,
+                   std::function<double()> get_cutoff_frequency,
+                   std::function<franka::ControllerMode()> get_internal_controller)
+    : FrankaHW(joint_names,
+               arm_id,
+               urdf_model,
+               std::move(get_limit_rate),
+               std::move(get_cutoff_frequency),
+               std::move(get_internal_controller)) {
   franka_hw::FrankaModelHandle model_handle(arm_id_ + "_model", model, robot_state_);
 
   franka_model_interface_.registerHandle(model_handle);
@@ -144,8 +156,9 @@ bool FrankaHW::controllerActive() const noexcept {
   return controller_active_;
 }
 
-void FrankaHW::control(franka::Robot& robot,
-                       std::function<bool(const ros::Time&, const ros::Duration&)> ros_callback) {
+void FrankaHW::control(
+    franka::Robot& robot,
+    const std::function<bool(const ros::Time&, const ros::Duration&)>& ros_callback) {
   if (!controller_active_) {
     return;
   }
@@ -184,7 +197,7 @@ bool FrankaHW::checkForConflict(const std::list<hardware_interface::ControllerIn
     uint8_t other_claims = 0;
     if (map_it->second.size() == 2) {
       for (auto& claimed_by : map_it->second) {
-        if (claimed_by[2].compare("hardware_interface::EffortJointInterface") == 0) {
+        if (claimed_by[2] == "hardware_interface::EffortJointInterface") {
           torque_claims++;
         } else {
           other_claims++;
@@ -262,8 +275,12 @@ bool FrankaHW::prepareSwitch(const std::list<hardware_interface::ControllerInfo>
   ControlMode stop_control_mode = getControlMode(arm_id_, stop_arm_claim_map);
 
   ControlMode requested_control_mode = current_control_mode_;
-  requested_control_mode |= start_control_mode;
   requested_control_mode &= ~stop_control_mode;
+  requested_control_mode |= start_control_mode;
+
+  auto limit_rate = get_limit_rate_();
+  auto cutoff_frequency = get_cutoff_frequency_();
+  auto internal_controller = get_internal_controller_();
 
   using std::placeholders::_1;
   using std::placeholders::_2;
@@ -272,74 +289,74 @@ bool FrankaHW::prepareSwitch(const std::list<hardware_interface::ControllerInfo>
     case ControlMode::None:
       break;
     case ControlMode::JointTorque:
-      run_function_ = [this](franka::Robot& robot, Callback ros_callback) {
+      run_function_ = [=](franka::Robot& robot, Callback ros_callback) {
         robot.control(std::bind(&FrankaHW::controlCallback<franka::Torques>, this,
                                 std::cref(effort_joint_command_), ros_callback, _1, _2),
-                      limit_rate_[4], cutoff_freq_[4]);
+                      limit_rate, cutoff_frequency);
       };
       break;
     case ControlMode::JointPosition:
-      run_function_ = [this](franka::Robot& robot, Callback ros_callback) {
+      run_function_ = [=](franka::Robot& robot, Callback ros_callback) {
         robot.control(std::bind(&FrankaHW::controlCallback<franka::JointPositions>, this,
                                 std::cref(position_joint_command_), ros_callback, _1, _2),
-                      internal_controller_, limit_rate_[0], cutoff_freq_[0]);
+                      internal_controller, limit_rate, cutoff_frequency);
       };
       break;
     case ControlMode::JointVelocity:
-      run_function_ = [this](franka::Robot& robot, Callback ros_callback) {
+      run_function_ = [=](franka::Robot& robot, Callback ros_callback) {
         robot.control(std::bind(&FrankaHW::controlCallback<franka::JointVelocities>, this,
                                 std::cref(velocity_joint_command_), ros_callback, _1, _2),
-                      internal_controller_, limit_rate_[1], cutoff_freq_[1]);
+                      internal_controller, limit_rate, cutoff_frequency);
       };
       break;
     case ControlMode::CartesianPose:
-      run_function_ = [this](franka::Robot& robot, Callback ros_callback) {
+      run_function_ = [=](franka::Robot& robot, Callback ros_callback) {
         robot.control(std::bind(&FrankaHW::controlCallback<franka::CartesianPose>, this,
                                 std::cref(pose_cartesian_command_), ros_callback, _1, _2),
-                      internal_controller_, limit_rate_[2], cutoff_freq_[2]);
+                      internal_controller, limit_rate, cutoff_frequency);
       };
       break;
     case ControlMode::CartesianVelocity:
-      run_function_ = [this](franka::Robot& robot, Callback ros_callback) {
+      run_function_ = [=](franka::Robot& robot, Callback ros_callback) {
         robot.control(std::bind(&FrankaHW::controlCallback<franka::CartesianVelocities>, this,
                                 std::cref(velocity_cartesian_command_), ros_callback, _1, _2),
-                      internal_controller_, limit_rate_[3], cutoff_freq_[3]);
+                      internal_controller, limit_rate, cutoff_frequency);
       };
       break;
     case (ControlMode::JointTorque | ControlMode::JointPosition):
-      run_function_ = [this](franka::Robot& robot, Callback ros_callback) {
+      run_function_ = [=](franka::Robot& robot, Callback ros_callback) {
         robot.control(std::bind(&FrankaHW::controlCallback<franka::Torques>, this,
                                 std::cref(effort_joint_command_), ros_callback, _1, _2),
                       std::bind(&FrankaHW::controlCallback<franka::JointPositions>, this,
                                 std::cref(position_joint_command_), ros_callback, _1, _2),
-                      limit_rate_[4], cutoff_freq_[4]);
+                      limit_rate, cutoff_frequency);
       };
       break;
     case (ControlMode::JointTorque | ControlMode::JointVelocity):
-      run_function_ = [this](franka::Robot& robot, Callback ros_callback) {
+      run_function_ = [=](franka::Robot& robot, Callback ros_callback) {
         robot.control(std::bind(&FrankaHW::controlCallback<franka::Torques>, this,
                                 std::cref(effort_joint_command_), ros_callback, _1, _2),
                       std::bind(&FrankaHW::controlCallback<franka::JointVelocities>, this,
                                 std::cref(velocity_joint_command_), ros_callback, _1, _2),
-                      limit_rate_[4], cutoff_freq_[4]);
+                      limit_rate, cutoff_frequency);
       };
       break;
     case (ControlMode::JointTorque | ControlMode::CartesianPose):
-      run_function_ = [this](franka::Robot& robot, Callback ros_callback) {
+      run_function_ = [=](franka::Robot& robot, Callback ros_callback) {
         robot.control(std::bind(&FrankaHW::controlCallback<franka::Torques>, this,
                                 std::cref(effort_joint_command_), ros_callback, _1, _2),
                       std::bind(&FrankaHW::controlCallback<franka::CartesianPose>, this,
                                 std::cref(pose_cartesian_command_), ros_callback, _1, _2),
-                      limit_rate_[4], cutoff_freq_[4]);
+                      limit_rate, cutoff_frequency);
       };
       break;
     case (ControlMode::JointTorque | ControlMode::CartesianVelocity):
-      run_function_ = [this](franka::Robot& robot, Callback ros_callback) {
+      run_function_ = [=](franka::Robot& robot, Callback ros_callback) {
         robot.control(std::bind(&FrankaHW::controlCallback<franka::Torques>, this,
                                 std::cref(effort_joint_command_), ros_callback, _1, _2),
                       std::bind(&FrankaHW::controlCallback<franka::CartesianVelocities>, this,
                                 std::cref(velocity_cartesian_command_), ros_callback, _1, _2),
-                      limit_rate_[4], cutoff_freq_[4]);
+                      limit_rate, cutoff_frequency);
       };
       break;
     default:
@@ -348,7 +365,10 @@ bool FrankaHW::prepareSwitch(const std::list<hardware_interface::ControllerInfo>
   }
 
   if (current_control_mode_ != requested_control_mode) {
-    ROS_INFO_STREAM("FrankaHW: Prepared switching controllers to " << requested_control_mode);
+    ROS_INFO_STREAM("FrankaHW: Prepared switching controllers to "
+                    << requested_control_mode << "with parameters "
+                    << "limit_rate=" << limit_rate << ", cutoff_frequency=" << cutoff_frequency
+                    << ", internal_controller=" << internal_controller);
     current_control_mode_ = requested_control_mode;
 
     controller_active_ = false;
diff --git a/franka_hw/test/franka_hw_controller_switching_test.cpp b/franka_hw/test/franka_hw_controller_switching_test.cpp
index 228d9aaf823fa9375f0afe0c04278af2b35b08fb..58639da26544821748e43a479ebf8e04d27e3c78 100644
--- a/franka_hw/test/franka_hw_controller_switching_test.cpp
+++ b/franka_hw/test/franka_hw_controller_switching_test.cpp
@@ -70,7 +70,7 @@ hardware_interface::ControllerInfo newInfo(
 class ControllerConflict :
         public ::testing::TestWithParam<std::list<hardware_interface::ControllerInfo> > {
 public:
- ControllerConflict() : robot_(new FrankaHW(joint_names, arm_id, franka::ControllerMode::kJointImpedance, {}, {}, ros::NodeHandle())) {}
+ ControllerConflict() : robot_(new FrankaHW(joint_names, arm_id, urdf::Model())) {}
  bool callCheckForConflict(const std::list<hardware_interface::ControllerInfo> info_list) {
      return robot_->checkForConflict(info_list);
  }
@@ -84,7 +84,7 @@ public:
 class NoControllerConflict : public
         ::testing::TestWithParam<std::list<hardware_interface::ControllerInfo> > {
 public:
- NoControllerConflict() : robot_(new FrankaHW(joint_names, arm_id, franka::ControllerMode::kJointImpedance, {}, {}, ros::NodeHandle())) {}
+ NoControllerConflict() : robot_(new FrankaHW(joint_names, arm_id, urdf::Model())) {}
  bool callCheckForConflict(const std::list<hardware_interface::ControllerInfo> info_list) {
      return robot_->checkForConflict(info_list);
  }
diff --git a/franka_hw/test/franka_hw_interfaces_test.cpp b/franka_hw/test/franka_hw_interfaces_test.cpp
index a72d29d6144bf0577429bc4d8e3b8aa9a7cac0c5..7984e1e2f71dfb3f43a00c06b42ceaa05c928a5a 100644
--- a/franka_hw/test/franka_hw_interfaces_test.cpp
+++ b/franka_hw/test/franka_hw_interfaces_test.cpp
@@ -23,7 +23,7 @@ extern std::array<std::string, 7> joint_names;
 namespace franka_hw {
 
 TEST(FrankaHWTests, InterfacesWorkForReadAndCommand) {
-  std::unique_ptr<FrankaHW> robotptr(new FrankaHW(joint_names, arm_id, franka::ControllerMode::kJointImpedance, {}, {}, ros::NodeHandle()));
+  std::unique_ptr<FrankaHW> robotptr(new FrankaHW(joint_names, arm_id, urdf::Model()));
   hardware_interface::JointStateInterface* js_interface =
       robotptr->get<hardware_interface::JointStateInterface>();
   hardware_interface::PositionJointInterface* pj_interface =
@@ -73,7 +73,10 @@ TEST(FrankaHWTests, InterfacesWorkForReadAndCommand) {
 }
 
 TEST(FrankaHWTests, JointLimitInterfacesEnforceLimitsOnCommands) {
-  std::unique_ptr<FrankaHW> robot_ptr(new FrankaHW(joint_names, arm_id, franka::ControllerMode::kJointImpedance, {}, {}, ros::NodeHandle()));
+  urdf::Model urdf_model;
+  ASSERT_TRUE(urdf_model.initParamWithNodeHandle("robot_description"));
+
+  std::unique_ptr<FrankaHW> robot_ptr(new FrankaHW(joint_names, arm_id, urdf_model));
 
   hardware_interface::PositionJointInterface* pj_interface =
       robot_ptr->get<hardware_interface::PositionJointInterface>();
@@ -85,8 +88,6 @@ TEST(FrankaHWTests, JointLimitInterfacesEnforceLimitsOnCommands) {
   ASSERT_NE(nullptr, vj_interface);
   ASSERT_NE(nullptr, ej_interface);
 
-  urdf::Model urdf_model;
-  ASSERT_TRUE(urdf_model.initParamWithNodeHandle("robot_description", ros::NodeHandle()));
   std::vector<joint_limits_interface::JointLimits> joint_limits(7);
   std::vector<hardware_interface::JointHandle> position_handles(7);
   std::vector<hardware_interface::JointHandle> velocity_handles(7);
diff --git a/panda_moveit_config/launch/panda_control_moveit_rviz.launch b/panda_moveit_config/launch/panda_control_moveit_rviz.launch
index 7c1d0bb247432f0530575181d5ec29f22795366e..748f260367162031004d78a3b14e2b57432860dd 100644
--- a/panda_moveit_config/launch/panda_control_moveit_rviz.launch
+++ b/panda_moveit_config/launch/panda_control_moveit_rviz.launch
@@ -2,20 +2,16 @@
 <launch>
   <arg name="robot_ip" />
   <arg name="load_gripper" default="true" />
+  <arg name="launch_rviz" default="true" />
 
   <include file="$(find franka_control)/launch/franka_control.launch" >
     <arg name="robot_ip" value="$(arg robot_ip)" />
     <arg name="load_gripper" value="$(arg load_gripper)" />
   </include>
 
-  <include if="$(arg load_gripper)" file="$(find franka_gripper)/launch/franka_gripper.launch" >
-    <arg name="robot_ip" value="$(arg robot_ip)" />
-  </include>
-
   <include file="$(find panda_moveit_config)/launch/panda_moveit.launch">
     <arg name="load_gripper" value="$(arg load_gripper)" />
   </include>
 
-  <include file="$(find panda_moveit_config)/launch/moveit_rviz.launch">
-  </include>
+  <include file="$(find panda_moveit_config)/launch/moveit_rviz.launch" if="$(arg launch_rviz)" />
 </launch>