diff --git a/README.md b/README.md
index 589145509e42bcd9cbffef01818c7d5010983e1f..69d3d5172a07bb442085ec2524ce25191ac27c9e 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,17 @@
-# MoveIt! for FRANKA EMIKA
+# ROS integration for FRANKA EMIKA research robots
 
-## Launch the joint trajectory controllers
+See the [FRANKA Control Interface documentation][fci-docs] for more information.
 
-This assumes that the robot is reachable at robot.franka.de. If this is not the case, add `robot_ip:=<ip>`.
+## MoveIt! quickstart
 
-    roslaunch franka_hw franka_hw.launch
+1. Launch the joint trajectory controller
 
-## Launch MoveIt! and RViz
+    roslaunch franka_control franka_control.launch robot_ip:=<ip>
+
+2. Launch MoveIt!
 
     roslaunch franka_moveit_config franka_moveit.launch
+
+3. Launch RViz
+
     roslaunch franka_moveit_config moveit_rviz.launch
diff --git a/franka_control/CMakeLists.txt b/franka_control/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..00952fc159b85e8a33ee43ef2bd10cc1c2c1d6d5
--- /dev/null
+++ b/franka_control/CMakeLists.txt
@@ -0,0 +1,134 @@
+cmake_minimum_required(VERSION 2.8.3)
+project(franka_control)
+
+list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/../cmake)
+
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+find_package(catkin REQUIRED COMPONENTS
+  actionlib
+  actionlib_msgs
+  controller_interface
+  controller_manager
+  franka_description
+  franka_hw
+  franka_msgs
+  geometry_msgs
+  message_generation
+  pluginlib
+  realtime_tools
+  roscpp
+  sensor_msgs
+  tf
+  tf2_msgs
+)
+
+find_package(Franka REQUIRED)
+
+add_service_files(FILES
+  SetCartesianImpedance.srv
+  SetEEFrame.srv
+  SetForceTorqueCollisionBehavior.srv
+  SetFullCollisionBehavior.srv
+  SetJointImpedance.srv
+  SetKFrame.srv
+  SetLoad.srv
+)
+
+add_action_files(FILES
+  ErrorRecovery.action
+)
+
+generate_messages(DEPENDENCIES actionlib_msgs)
+
+catkin_package(
+  INCLUDE_DIRS include
+  LIBRARIES franka_state_controller franka_control_services
+  CATKIN_DEPENDS
+    actionlib
+    controller_interface
+    franka_hw
+    franka_msgs
+    geometry_msgs
+    message_runtime
+    pluginlib
+    realtime_tools
+    roscpp
+    sensor_msgs
+    tf2_msgs
+  DEPENDS Franka
+)
+
+## franka_state_controller
+add_library(franka_state_controller
+  src/franka_state_controller.cpp
+)
+
+add_dependencies(franka_state_controller
+  ${${PROJECT_NAME}_EXPORTED_TARGETS}
+  ${catkin_EXPORTED_TARGETS}
+)
+
+target_link_libraries(franka_state_controller
+  ${catkin_LIBRARIES}
+  Franka::Franka
+)
+
+target_include_directories(franka_state_controller PUBLIC
+  ${catkin_INCLUDE_DIRS}
+  include
+)
+
+## franka_control_services
+add_library(franka_control_services
+  src/services.cpp
+)
+
+add_dependencies(franka_control_services
+  ${${PROJECT_NAME}_EXPORTED_TARGETS}
+  ${catkin_EXPORTED_TARGETS}
+)
+
+target_link_libraries(franka_control_services
+  ${catkin_LIBRARIES}
+  Franka::Franka
+)
+
+target_include_directories(franka_control_services PUBLIC
+  ${catkin_INCLUDE_DIRS}
+  include
+)
+
+## franka_control_node
+add_executable(franka_control_node
+  src/franka_control_node.cpp
+)
+
+add_dependencies(franka_control_node
+  ${${PROJECT_NAME}_EXPORTED_TARGETS}
+  ${catkin_EXPORTED_TARGETS}
+)
+
+target_link_libraries(franka_control_node
+  ${catkin_LIBRARIES}
+  franka_control_services
+  Franka::Franka
+)
+
+target_include_directories(franka_control_node PUBLIC
+  ${catkin_INCLUDE_DIRS}
+)
+
+## Tools
+file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
+file(GLOB_RECURSE HEADERS
+  ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h
+  ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h
+)
+include(ClangTools)
+add_format_target(franka_control FILES ${SOURCES} ${HEADERS})
+add_tidy_target(franka_control
+  FILES ${SOURCES}
+  DEPENDS franka_control_node franka_state_controller
+)
diff --git a/franka_hw/action/ErrorRecovery.action b/franka_control/action/ErrorRecovery.action
similarity index 100%
rename from franka_hw/action/ErrorRecovery.action
rename to franka_control/action/ErrorRecovery.action
diff --git a/franka_hw/config/default_controllers.yaml b/franka_control/config/default_controllers.yaml
similarity index 91%
rename from franka_hw/config/default_controllers.yaml
rename to franka_control/config/default_controllers.yaml
index 7122c978ca317c84bd25aa02e542dfc063ec2e2b..6a24083e1a3ef16f035899b902a1dca744a0534a 100644
--- a/franka_hw/config/default_controllers.yaml
+++ b/franka_control/config/default_controllers.yaml
@@ -1,5 +1,5 @@
 position_joint_trajectory_controller:
-  type: "position_controllers/JointTrajectoryController"
+  type: position_controllers/JointTrajectoryController
   joints:
     - franka_emika_joint1
     - franka_emika_joint2
@@ -26,7 +26,7 @@ position_joint_trajectory_controller:
       goal: 0.05
 
 effort_joint_trajectory_controller:
-  type: "effort_controllers/JointTrajectoryController"
+  type: effort_controllers/JointTrajectoryController
   joints:
     - franka_emika_joint1
     - franka_emika_joint2
@@ -61,6 +61,6 @@ effort_joint_trajectory_controller:
     franka_emika_joint7: {p: 100, d: 10, i: 0, i_clamp: 1}
 
 franka_state_controller:
-  type: franka_hw/FrankaStateController
+  type: franka_control/FrankaStateController
   publish_rate: 30  # [Hz]
 
diff --git a/franka_hw/config/franka_hw.yaml b/franka_control/config/franka_control.yaml
similarity index 100%
rename from franka_hw/config/franka_hw.yaml
rename to franka_control/config/franka_control.yaml
diff --git a/franka_control/franka_controller_plugins.xml b/franka_control/franka_controller_plugins.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d7ffbfc0367c32c2f7d06ab37c3e559e3b048471
--- /dev/null
+++ b/franka_control/franka_controller_plugins.xml
@@ -0,0 +1,5 @@
+<library path="lib/libfranka_state_controller">
+  <class name="franka_control/FrankaStateController" type="franka_control::FrankaStateController" base_class_type="controller_interface::ControllerBase">
+    <description>A controller that publishes the complete robot state</description>
+  </class>
+</library>
diff --git a/franka_hw/include/franka_hw/franka_state_controller.h b/franka_control/include/franka_control/franka_state_controller.h
similarity index 89%
rename from franka_hw/include/franka_hw/franka_state_controller.h
rename to franka_control/include/franka_control/franka_state_controller.h
index 903c6853e20896f8f640f7a551de32125ecf688f..49fc3ee3d4713c44b80d8e8811fdb6d7cdf8beb3 100644
--- a/franka_hw/include/franka_hw/franka_state_controller.h
+++ b/franka_control/include/franka_control/franka_state_controller.h
@@ -5,19 +5,15 @@
 #include <vector>
 
 #include <controller_interface/multi_interface_controller.h>
-#include <franka_hw/FrankaState.h>
-#include <geometry_msgs/PoseStamped.h>
+#include <franka_hw/franka_state_interface.h>
+#include <franka_hw/trigger_rate.h>
+#include <franka_msgs/FrankaState.h>
 #include <geometry_msgs/WrenchStamped.h>
-#include <hardware_interface/robot_hw.h>
 #include <realtime_tools/realtime_publisher.h>
 #include <sensor_msgs/JointState.h>
 #include <tf2_msgs/TFMessage.h>
 
-#include <franka_hw/FrankaState.h>
-#include <franka_hw/franka_state_interface.h>
-#include <franka_hw/trigger_rate.h>
-
-namespace franka_hw {
+namespace franka_control {
 
 class FrankaStateController
     : public controller_interface::MultiInterfaceController<franka_hw::FrankaStateInterface> {
@@ -79,7 +75,7 @@ class FrankaStateController
   std::unique_ptr<franka_hw::FrankaStateHandle> franka_state_handle_;
 
   realtime_tools::RealtimePublisher<tf2_msgs::TFMessage> publisher_transforms_;
-  realtime_tools::RealtimePublisher<franka_hw::FrankaState> publisher_franka_states_;
+  realtime_tools::RealtimePublisher<franka_msgs::FrankaState> publisher_franka_states_;
   realtime_tools::RealtimePublisher<sensor_msgs::JointState> publisher_joint_states_;
   realtime_tools::RealtimePublisher<geometry_msgs::WrenchStamped> publisher_external_wrench_;
   franka_hw::TriggerRate trigger_publish_;
@@ -88,4 +84,4 @@ class FrankaStateController
   std::vector<std::string> joint_names_;
 };
 
-}  // namespace franka_hw
+}  // namespace franka_control
diff --git a/franka_hw/include/franka_hw/services.h b/franka_control/include/franka_control/services.h
similarity index 83%
rename from franka_hw/include/franka_hw/services.h
rename to franka_control/include/franka_control/services.h
index 5179109136709b185bd3a88426f413a79dd715e9..fd3cc50ece95420a9f92eed072ea2c46b1222144 100644
--- a/franka_hw/include/franka_hw/services.h
+++ b/franka_control/include/franka_control/services.h
@@ -6,16 +6,15 @@
 #include <ros/node_handle.h>
 #include <ros/service_server.h>
 
-#include <franka_hw/SetCartesianImpedance.h>
-#include <franka_hw/SetEEFrame.h>
-#include <franka_hw/SetForceTorqueCollisionBehavior.h>
-#include <franka_hw/SetFullCollisionBehavior.h>
-#include <franka_hw/SetJointImpedance.h>
-#include <franka_hw/SetKFrame.h>
-#include <franka_hw/SetLoad.h>
+#include <franka_control/SetCartesianImpedance.h>
+#include <franka_control/SetEEFrame.h>
+#include <franka_control/SetForceTorqueCollisionBehavior.h>
+#include <franka_control/SetFullCollisionBehavior.h>
+#include <franka_control/SetJointImpedance.h>
+#include <franka_control/SetKFrame.h>
+#include <franka_control/SetLoad.h>
 
-namespace franka_hw {
-namespace services {
+namespace franka_control {
 
 template <typename T>
 ros::ServiceServer advertiseService(
@@ -53,5 +52,4 @@ void setFullCollisionBehavior(franka::Robot& robot,
                               SetFullCollisionBehavior::Response& res);
 void setLoad(franka::Robot& robot, const SetLoad::Request& req, SetLoad::Response& res);
 
-}  // namespace services
-}  // namespace franka_hw
+}  // namespace franka_control
diff --git a/franka_hw/launch/franka_hw.launch b/franka_control/launch/franka_control.launch
similarity index 83%
rename from franka_hw/launch/franka_hw.launch
rename to franka_control/launch/franka_control.launch
index eb1b352d628a8c25c69330fc76d763711a270707..23134312c171da838f5b10be8a9a2e0c9a0eb834 100644
--- a/franka_hw/launch/franka_hw.launch
+++ b/franka_control/launch/franka_control.launch
@@ -4,16 +4,16 @@
   <arg name="arm_id" default="franka_emika" />
   <arg name="load_gripper" default="true" />
 
-  <node name="$(arg arm_id)" pkg="franka_hw" type="franka_hw_node" output="screen" required="true">
-    <rosparam command="load" file="$(find franka_hw)/config/franka_hw.yaml" />
+  <node name="$(arg arm_id)" pkg="franka_control" type="franka_control_node" output="screen" required="true">
+    <rosparam command="load" file="$(find franka_control)/config/franka_control.yaml" />
     <param name="robot_ip" value="$(arg robot_ip)" />
     <param name="arm_id" value="$(arg arm_id)" />
     <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find franka_description)/robots/FEA_01_01_Gripper.urdf.xacro'" if="$(arg load_gripper)" />
     <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find franka_description)/robots/FEA_01_01.urdf.xacro'" unless="$(arg load_gripper)" />
   </node>
-  
+
   <group ns="$(arg arm_id)">
-    <rosparam command="load" file="$(find franka_hw)/config/default_controllers.yaml" />
+    <rosparam command="load" file="$(find franka_control)/config/default_controllers.yaml" />
     <node name="state_controller_spawner" pkg="controller_manager" type="spawner" respawn="false" output="screen"  args="franka_state_controller --shutdown-timeout 2"/>
     <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" output="screen"/>
     <node name="joint_state_publisher" type="joint_state_publisher" pkg="joint_state_publisher" output="screen">
@@ -21,6 +21,6 @@
       <rosparam  if="$(arg load_gripper)" param="source_list">[franka_state_controller/joint_states, franka_gripper_node/joint_states] </rosparam>
       <rosparam  unless="$(arg load_gripper)" param="source_list">[franka_state_controller/joint_states] </rosparam>
       <param name="rate" value="30"/>
-    </node>   
+    </node>
   </group>
 </launch>
diff --git a/franka_control/package.xml b/franka_control/package.xml
new file mode 100644
index 0000000000000000000000000000000000000000..636e59634f673e463010cf57f641dea4b7b4a71d
--- /dev/null
+++ b/franka_control/package.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<package format="2">
+  <name>franka_control</name>
+  <version>0.0.1</version>
+  <description>franka_control provides a hardware node to control a FRANKA EMIKA research robot</description>
+  <maintainer email="info@franka.de">FRANKA EMIKA Research Interface Team</maintainer>
+  <license>NONE</license>
+
+  <url type="website">http://wiki.ros.org/franka_control</url>
+  <url type="repository">https://github.com/frankaemika/franka_ros</url>
+  <url type="bugtracker">https://github.com/frankaemika/franka_ros/issues</url>
+  <author>FRANKA EMIKA Research Interface Team</author>
+
+  <buildtool_depend>catkin</buildtool_depend>
+
+  <build_depend>message_generation</build_depend>
+
+  <depend>Franka</depend>
+  <depend>actionlib</depend>
+  <depend>actionlib_msgs</depend>
+  <depend>controller_interface</depend>
+  <depend>controller_manager</depend>
+  <depend>franka_description</depend>
+  <depend>franka_hw</depend>
+  <depend>franka_msgs</depend>
+  <depend>geometry_msgs</depend>
+  <depend>pluginlib</depend>
+  <depend>realtime_tools</depend>
+  <depend>roscpp</depend>
+  <depend>sensor_msgs</depend>
+  <depend>tf2_msgs</depend>
+  <depend>tf</depend>
+
+  <exec_depend>message_runtime</exec_depend>
+
+  <export>
+    <controller_interface plugin="${prefix}/franka_controller_plugins.xml"/>
+  </export>
+</package>
diff --git a/franka_hw/src/franka_hw_node.cpp b/franka_control/src/franka_control_node.cpp
similarity index 65%
rename from franka_hw/src/franka_hw_node.cpp
rename to franka_control/src/franka_control_node.cpp
index 65b9965157e683d1e4a5be240eaa9040fd2403c8..ebdb53486bd37c9e2fed7ec22477f9090ccff06d 100644
--- a/franka_hw/src/franka_hw_node.cpp
+++ b/franka_control/src/franka_control_node.cpp
@@ -1,3 +1,4 @@
+#include <algorithm>
 #include <array>
 #include <atomic>
 #include <string>
@@ -7,18 +8,17 @@
 #include <controller_manager/controller_manager.h>
 #include <franka/exception.h>
 #include <franka/robot.h>
-#include <franka_hw/ErrorRecoveryAction.h>
 #include <franka_hw/franka_hw.h>
-#include <franka_hw/services.h>
 #include <ros/ros.h>
-#include <xmlrpcpp/XmlRpc.h>
+
+#include <franka_control/ErrorRecoveryAction.h>
+#include <franka_control/services.h>
 
 class ServiceContainer {
  public:
   template <typename T, typename... TArgs>
   ServiceContainer& advertiseService(TArgs&&... args) {
-    ros::ServiceServer server =
-        franka_hw::services::advertiseService<T>(std::forward<TArgs>(args)...);
+    ros::ServiceServer server = franka_control::advertiseService<T>(std::forward<TArgs>(args)...);
     services_.push_back(server);
     return *this;
   }
@@ -31,12 +31,14 @@ int main(int argc, char** argv) {
   ros::init(argc, argv, "franka_hw");
   ros::NodeHandle node_handle("~");
 
-  XmlRpc::XmlRpcValue params;
-  node_handle.getParam("joint_names", params);
-  std::array<std::string, 7> joint_names;
-  for (size_t i = 0; i < joint_names.size(); i++) {
-    joint_names[i] = static_cast<std::string>(params[i]);
+  std::vector<std::string> joint_names_vector;
+  if (!node_handle.getParam("joint_names", joint_names_vector) || joint_names_vector.size() != 7) {
+    ROS_ERROR("Invalid or no joint_names parameters provided");
+    return 1;
   }
+  std::array<std::string, 7> joint_names;
+  std::copy(joint_names_vector.cbegin(), joint_names_vector.cend(), joint_names.begin());
+
   std::string robot_ip;
   node_handle.getParam("robot_ip", robot_ip);
   std::string arm_id;
@@ -56,37 +58,35 @@ int main(int argc, char** argv) {
   using std::placeholders::_2;
   ServiceContainer services;
   services
-      .advertiseService<franka_hw::SetJointImpedance>(
+      .advertiseService<franka_control::SetJointImpedance>(
           node_handle, "set_joint_impedance",
-          std::bind(franka_hw::services::setJointImpedance, std::ref(robot), _1, _2))
-      .advertiseService<franka_hw::SetCartesianImpedance>(
+          std::bind(franka_control::setJointImpedance, std::ref(robot), _1, _2))
+      .advertiseService<franka_control::SetCartesianImpedance>(
           node_handle, "set_cartesian_impedance",
-          std::bind(franka_hw::services::setCartesianImpedance, std::ref(robot), _1, _2))
-      .advertiseService<franka_hw::SetEEFrame>(
+          std::bind(franka_control::setCartesianImpedance, std::ref(robot), _1, _2))
+      .advertiseService<franka_control::SetEEFrame>(
           node_handle, "set_EE_frame",
-          std::bind(franka_hw::services::setEEFrame, std::ref(robot), _1, _2))
-      .advertiseService<franka_hw::SetKFrame>(
-          node_handle, "set_K_frame",
-          std::bind(franka_hw::services::setKFrame, std::ref(robot), _1, _2))
-      .advertiseService<franka_hw::SetForceTorqueCollisionBehavior>(
+          std::bind(franka_control::setEEFrame, std::ref(robot), _1, _2))
+      .advertiseService<franka_control::SetKFrame>(
+          node_handle, "set_K_frame", std::bind(franka_control::setKFrame, std::ref(robot), _1, _2))
+      .advertiseService<franka_control::SetForceTorqueCollisionBehavior>(
           node_handle, "set_force_torque_collision_behavior",
-          std::bind(franka_hw::services::setForceTorqueCollisionBehavior, std::ref(robot), _1, _2))
-      .advertiseService<franka_hw::SetFullCollisionBehavior>(
+          std::bind(franka_control::setForceTorqueCollisionBehavior, std::ref(robot), _1, _2))
+      .advertiseService<franka_control::SetFullCollisionBehavior>(
           node_handle, "set_full_collision_behavior",
-          std::bind(franka_hw::services::setFullCollisionBehavior, std::ref(robot), _1, _2))
-      .advertiseService<franka_hw::SetLoad>(
-          node_handle, "set_load",
-          std::bind(franka_hw::services::setLoad, std::ref(robot), _1, _2));
+          std::bind(franka_control::setFullCollisionBehavior, std::ref(robot), _1, _2))
+      .advertiseService<franka_control::SetLoad>(
+          node_handle, "set_load", std::bind(franka_control::setLoad, std::ref(robot), _1, _2));
 
-  actionlib::SimpleActionServer<franka_hw::ErrorRecoveryAction> recovery_action_server(
+  actionlib::SimpleActionServer<franka_control::ErrorRecoveryAction> recovery_action_server(
       node_handle, "error_recovery",
-      [&](const franka_hw::ErrorRecoveryGoalConstPtr&) {
+      [&](const franka_control::ErrorRecoveryGoalConstPtr&) {
         try {
           robot.automaticErrorRecovery();
           has_error = false;
           recovery_action_server.setSucceeded();
         } catch (const franka::Exception& ex) {
-          recovery_action_server.setAborted(franka_hw::ErrorRecoveryResult(), ex.what());
+          recovery_action_server.setAborted(franka_control::ErrorRecoveryResult(), ex.what());
         }
       },
       false);
diff --git a/franka_hw/src/franka_state_controller.cpp b/franka_control/src/franka_state_controller.cpp
similarity index 97%
rename from franka_hw/src/franka_state_controller.cpp
rename to franka_control/src/franka_state_controller.cpp
index 80f67dd6a28627cb3878d02705f17a0716ad4b28..df5947ddd7905798d09436f1b7c7ce0816d62c08 100644
--- a/franka_hw/src/franka_state_controller.cpp
+++ b/franka_control/src/franka_state_controller.cpp
@@ -1,21 +1,20 @@
-#include <franka_hw/franka_state_controller.h>
+#include <franka_control/franka_state_controller.h>
 
 #include <cmath>
 #include <mutex>
 #include <string>
 
-#include <controller_interface/controller_base.h>
+#include <franka/errors.h>
+#include <franka_hw/franka_cartesian_command_interface.h>
+#include <franka_msgs/Errors.h>
 #include <hardware_interface/hardware_interface.h>
 #include <pluginlib/class_list_macros.h>
 #include <ros/ros.h>
 #include <tf/tf.h>
 #include <tf/transform_datatypes.h>
-#include <xmlrpcpp/XmlRpcValue.h>
-
-#include <franka_hw/Errors.h>
-#include <franka_hw/franka_cartesian_command_interface.h>
 
 namespace {
+
 tf::Transform convertArrayToTf(const std::array<double, 16>& transform) {
   tf::Matrix3x3 rotation(transform[0], transform[4], transform[8], transform[1], transform[5],
                          transform[9], transform[2], transform[6], transform[10]);
@@ -23,8 +22,8 @@ tf::Transform convertArrayToTf(const std::array<double, 16>& transform) {
   return tf::Transform(rotation, translation);
 }
 
-franka_hw::Errors errorsToMessage(const franka::Errors& error) {
-  franka_hw::Errors message;
+franka_msgs::Errors errorsToMessage(const franka::Errors& error) {
+  franka_msgs::Errors message;
   message.joint_position_limits_violation =
       static_cast<decltype(message.joint_position_limits_violation)>(
           error.joint_position_limits_violation);
@@ -124,7 +123,7 @@ franka_hw::Errors errorsToMessage(const franka::Errors& error) {
 
 }  // anonymous namespace
 
-namespace franka_hw {
+namespace franka_control {
 
 FrankaStateController::FrankaStateController()
     : franka_state_interface_(nullptr),
@@ -360,6 +359,6 @@ void FrankaStateController::publishExternalWrench(const ros::Time& time) {
   }
 }
 
-}  // namespace franka_hw
+}  // namespace franka_control
 
-PLUGINLIB_EXPORT_CLASS(franka_hw::FrankaStateController, controller_interface::ControllerBase)
+PLUGINLIB_EXPORT_CLASS(franka_control::FrankaStateController, controller_interface::ControllerBase)
diff --git a/franka_hw/src/services.cpp b/franka_control/src/services.cpp
similarity index 97%
rename from franka_hw/src/services.cpp
rename to franka_control/src/services.cpp
index 71360e085f70415d81490dd0ce92be4e332029c4..8357dded9f1c0537e24da3f2ae3622d4365e93e1 100644
--- a/franka_hw/src/services.cpp
+++ b/franka_control/src/services.cpp
@@ -1,7 +1,6 @@
-#include "franka_hw/services.h"
+#include <franka_control/services.h>
 
-namespace franka_hw {
-namespace services {
+namespace franka_control {
 
 void setCartesianImpedance(franka::Robot& robot,
                            const SetCartesianImpedance::Request& req,
@@ -105,5 +104,4 @@ void setLoad(franka::Robot& robot, const SetLoad::Request& req, SetLoad::Respons
   robot.setLoad(mass, F_x_center_load, load_inertia);
 }
 
-}  // namespace services
-}  // namespace franka_hw
+}  // namespace franka_control
diff --git a/franka_hw/srv/SetCartesianImpedance.srv b/franka_control/srv/SetCartesianImpedance.srv
similarity index 100%
rename from franka_hw/srv/SetCartesianImpedance.srv
rename to franka_control/srv/SetCartesianImpedance.srv
diff --git a/franka_hw/srv/SetEEFrame.srv b/franka_control/srv/SetEEFrame.srv
similarity index 100%
rename from franka_hw/srv/SetEEFrame.srv
rename to franka_control/srv/SetEEFrame.srv
diff --git a/franka_hw/srv/SetForceTorqueCollisionBehavior.srv b/franka_control/srv/SetForceTorqueCollisionBehavior.srv
similarity index 100%
rename from franka_hw/srv/SetForceTorqueCollisionBehavior.srv
rename to franka_control/srv/SetForceTorqueCollisionBehavior.srv
diff --git a/franka_hw/srv/SetFullCollisionBehavior.srv b/franka_control/srv/SetFullCollisionBehavior.srv
similarity index 100%
rename from franka_hw/srv/SetFullCollisionBehavior.srv
rename to franka_control/srv/SetFullCollisionBehavior.srv
diff --git a/franka_hw/srv/SetJointImpedance.srv b/franka_control/srv/SetJointImpedance.srv
similarity index 100%
rename from franka_hw/srv/SetJointImpedance.srv
rename to franka_control/srv/SetJointImpedance.srv
diff --git a/franka_hw/srv/SetKFrame.srv b/franka_control/srv/SetKFrame.srv
similarity index 100%
rename from franka_hw/srv/SetKFrame.srv
rename to franka_control/srv/SetKFrame.srv
diff --git a/franka_hw/srv/SetLoad.srv b/franka_control/srv/SetLoad.srv
similarity index 100%
rename from franka_hw/srv/SetLoad.srv
rename to franka_control/srv/SetLoad.srv
diff --git a/franka_hw/CMakeLists.txt b/franka_hw/CMakeLists.txt
index a85969abdc2ba71dd3ab785a0762f1910733e157..8774cde8cc1a895ad3c019b754ff28c15020c870 100644
--- a/franka_hw/CMakeLists.txt
+++ b/franka_hw/CMakeLists.txt
@@ -7,81 +7,26 @@ set(CMAKE_CXX_STANDARD 14)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 find_package(catkin REQUIRED COMPONENTS
-  actionlib_msgs
   controller_interface
-  controller_manager
   franka_description
-  geometry_msgs
   hardware_interface
   joint_limits_interface
-  message_generation
-  pluginlib
-  realtime_tools
   roscpp
-  sensor_msgs
-  std_msgs
-  tf
-  tf2_msgs
-  urdf
-  xmlrpcpp
 )
 
 find_package(Franka REQUIRED)
 
-add_message_files(FILES
-  Errors.msg
-  FrankaState.msg
-)
-
-add_service_files(FILES
-  SetCartesianImpedance.srv
-  SetEEFrame.srv
-  SetForceTorqueCollisionBehavior.srv
-  SetFullCollisionBehavior.srv
-  SetJointImpedance.srv
-  SetKFrame.srv
-  SetLoad.srv
-)
-
-add_action_files(FILES
-  ErrorRecovery.action
-)
-
-generate_messages(DEPENDENCIES
-  actionlib_msgs
-  std_msgs
-)
-
 catkin_package(
   INCLUDE_DIRS include
-  LIBRARIES franka_hw franka_state_controller
-  CATKIN_DEPENDS actionlib_msgs controller_interface pluginlib
-                 hardware_interface message_runtime realtime_tools roscpp
+  LIBRARIES franka_hw
+  CATKIN_DEPENDS controller_interface hardware_interface roscpp
   DEPENDS Franka
 )
 
-add_library(franka_hw_services src/services.cpp)
-
-add_dependencies(franka_hw_services
-  ${${PROJECT_NAME}_EXPORTED_TARGETS}
-  ${catkin_EXPORTED_TARGETS}
-  ${PROJECT_NAME}_generate_messages_cpp
-)
-
-target_link_libraries(franka_hw_services
-   ${catkin_LIBRARIES}
-   Franka::Franka
-)
-
-target_include_directories(franka_hw_services PUBLIC
-  ${catkin_INCLUDE_DIRS}
-  include
-)
-
 add_library(franka_hw
+  src/control_mode.cpp
   src/franka_hw.cpp
-  src/franka_controller_switching_types.cpp
-  src/franka_hw_helper_functions.cpp
+  src/resource_helpers.cpp
   src/trigger_rate.cpp
 )
 
@@ -100,46 +45,6 @@ target_include_directories(franka_hw PUBLIC
   include
 )
 
-add_library(franka_state_controller
-  src/franka_state_controller.cpp
-)
-
-add_dependencies(franka_state_controller
-  ${${PROJECT_NAME}_EXPORTED_TARGETS}
-  ${catkin_EXPORTED_TARGETS}
-  ${PROJECT_NAME}_generate_messages_cpp
-)
-
-target_link_libraries(franka_state_controller
-  ${catkin_LIBRARIES}
-  Franka::Franka
-)
-
-target_include_directories(franka_state_controller PUBLIC
-  ${catkin_INCLUDE_DIRS}
-  include
-)
-
-add_executable(franka_hw_node
-  src/franka_hw_node.cpp
-)
-
-add_dependencies(franka_hw_node
-  ${${PROJECT_NAME}_EXPORTED_TARGETS}
-  ${catkin_EXPORTED_TARGETS}
-  franka_hw_services
-)
-
-target_link_libraries(franka_hw_node
-  ${catkin_LIBRARIES}
-  franka_hw
-  franka_hw_services
-)
-
-target_include_directories(franka_hw_node PUBLIC
-  ${catkin_INCLUDE_DIRS}
-)
-
 if(CATKIN_ENABLE_TESTING)
   add_subdirectory(test)
 endif()
@@ -154,5 +59,5 @@ include(ClangTools)
 add_format_target(franka_hw FILES ${SOURCES} ${HEADERS})
 add_tidy_target(franka_hw
   FILES ${SOURCES}
-  DEPENDS franka_hw franka_hw_node
+  DEPENDS franka_hw
 )
diff --git a/franka_hw/franka_hw_controller_plugin.xml b/franka_hw/franka_hw_controller_plugin.xml
deleted file mode 100644
index e4e6fe6066546b793022bc0097aa8932ba92e380..0000000000000000000000000000000000000000
--- a/franka_hw/franka_hw_controller_plugin.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<library path="lib/libfranka_state_controller">
-  <class name="franka_hw/FrankaStateController" type="franka_hw::FrankaStateController" base_class_type="controller_interface::ControllerBase">
-    <description>
-      A controller that publishes all relevant franka robot states
-    </description>
-  </class>
-</library>
diff --git a/franka_hw/include/franka_hw/franka_controller_switching_types.h b/franka_hw/include/franka_hw/control_mode.h
similarity index 77%
rename from franka_hw/include/franka_hw/franka_controller_switching_types.h
rename to franka_hw/include/franka_hw/control_mode.h
index b81d88722de11788e253a4d84b759856e6b8b3f8..3e83ee73a3f80b642d3adb24b8a954e3b2befb90 100644
--- a/franka_hw/include/franka_hw/franka_controller_switching_types.h
+++ b/franka_hw/include/franka_hw/control_mode.h
@@ -1,25 +1,9 @@
 #pragma once
 
-#include <cstdint>
-#include <map>
 #include <ostream>
-#include <string>
-#include <vector>
 
 namespace franka_hw {
 
-using ResourceWithClaimsMap = std::map<std::string, std::vector<std::vector<std::string>>>;
-
-struct ResourceClaims {
-  uint8_t joint_position_claims = 0;
-  uint8_t joint_velocity_claims = 0;
-  uint8_t joint_torque_claims = 0;
-  uint8_t cartesian_velocity_claims = 0;
-  uint8_t cartesian_pose_claims = 0;
-};
-
-using ArmClaimedMap = std::map<std::string, ResourceClaims>;
-
 enum class ControlMode {
   None = 0,
   JointTorque = (1 << 0),
diff --git a/franka_hw/include/franka_hw/franka_hw.h b/franka_hw/include/franka_hw/franka_hw.h
index 364f82d0c4c274e46440ec57cc28b14fc867401f..20fd6d2eb0a1baecc317dbabafd44c4fcf547de3 100644
--- a/franka_hw/include/franka_hw/franka_hw.h
+++ b/franka_hw/include/franka_hw/franka_hw.h
@@ -16,8 +16,8 @@
 #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_controller_switching_types.h>
 #include <franka_hw/franka_model_interface.h>
 #include <franka_hw/franka_state_interface.h>
 
diff --git a/franka_hw/package.xml b/franka_hw/package.xml
index 78cfa758e7467466feea000894820f4b0d38885f..afbc4db47b1ee577e0743c7b66bb4de13fd3d2a0 100644
--- a/franka_hw/package.xml
+++ b/franka_hw/package.xml
@@ -2,10 +2,10 @@
 <package format="2">
   <name>franka_hw</name>
   <version>0.0.1</version>
-  <description>This package implements the franka_hw of Franka Emika for the use with ros_control</description>
+  <description>franka_hw provides hardware interfaces for using FRANKA EMIKA research robots with ros_control</description>
   <maintainer email="info@franka.de">FRANKA EMIKA Research Interface Team</maintainer>
   <license>NONE</license>
-  
+
   <url type="website">http://wiki.ros.org/franka_hw</url>
   <url type="repository">https://github.com/frankaemika/franka_ros</url>
   <url type="bugtracker">https://github.com/frankaemika/franka_ros/issues</url>
@@ -13,32 +13,12 @@
 
   <buildtool_depend>catkin</buildtool_depend>
 
-  <build_depend>message_generation</build_depend>
-
   <depend>Franka</depend>
-  <depend>actionlib</depend>
-  <depend>actionlib_msgs</depend>
   <depend>controller_interface</depend>
-  <depend>controller_manager</depend>
-  <depend>geometry_msgs</depend>
   <depend>hardware_interface</depend>
   <depend>joint_limits_interface</depend>
-  <depend>pluginlib</depend>
-  <depend>realtime_tools</depend>
   <depend>roscpp</depend>
-  <depend>sensor_msgs</depend>
-  <depend>std_msgs</depend>
-  <depend>tf2_msgs</depend>
-  <depend>tf</depend>
-  <depend>urdf</depend>
-  <depend>xmlrpcpp</depend>
-
-  <exec_depend>message_runtime</exec_depend>
 
   <test_depend>gtest</test_depend>
   <test_depend>rostest</test_depend>
-
-  <export>
-    <controller_interface plugin="${prefix}/franka_hw_controller_plugin.xml"/>
-  </export>
 </package>
diff --git a/franka_hw/src/franka_controller_switching_types.cpp b/franka_hw/src/control_mode.cpp
similarity index 94%
rename from franka_hw/src/franka_controller_switching_types.cpp
rename to franka_hw/src/control_mode.cpp
index a00e478b3f5705c10ad68d5bcd4a8b7408bf16d3..b60c1cf33f89ff6c699903598db7d67118fa46df 100644
--- a/franka_hw/src/franka_controller_switching_types.cpp
+++ b/franka_hw/src/control_mode.cpp
@@ -1,4 +1,4 @@
-#include <franka_hw/franka_controller_switching_types.h>
+#include <franka_hw/control_mode.h>
 
 #include <algorithm>
 #include <iterator>
diff --git a/franka_hw/src/franka_hw.cpp b/franka_hw/src/franka_hw.cpp
index a9f3f18f03b785fef007a4b4f9db9eac46250fb7..34dd36b68910e01fb8ff56f9cbf31e1060540f5d 100644
--- a/franka_hw/src/franka_hw.cpp
+++ b/franka_hw/src/franka_hw.cpp
@@ -5,7 +5,7 @@
 #include <joint_limits_interface/joint_limits_urdf.h>
 #include <urdf/model.h>
 
-#include "franka_hw_helper_functions.h"
+#include "resource_helpers.h"
 
 namespace franka_hw {
 
diff --git a/franka_hw/src/franka_hw_helper_functions.cpp b/franka_hw/src/resource_helpers.cpp
similarity index 99%
rename from franka_hw/src/franka_hw_helper_functions.cpp
rename to franka_hw/src/resource_helpers.cpp
index 11637d33d31c4171253ada8914fedc81d0a22c95..b0ecb250029fcf816d6ae1b1bb08b4a55ca269e9 100644
--- a/franka_hw/src/franka_hw_helper_functions.cpp
+++ b/franka_hw/src/resource_helpers.cpp
@@ -1,4 +1,4 @@
-#include "franka_hw_helper_functions.h"
+#include "resource_helpers.h"
 
 #include <ros/console.h>
 
diff --git a/franka_hw/src/franka_hw_helper_functions.h b/franka_hw/src/resource_helpers.h
similarity index 53%
rename from franka_hw/src/franka_hw_helper_functions.h
rename to franka_hw/src/resource_helpers.h
index abfe69c1a043dc6ac6674e493c856341e74ff894..1260a9da074eace1e6d073ba2089d07b51d8e850 100644
--- a/franka_hw/src/franka_hw_helper_functions.h
+++ b/franka_hw/src/resource_helpers.h
@@ -1,13 +1,28 @@
 #pragma once
 
 #include <list>
+#include <map>
 #include <string>
+#include <vector>
 
-#include <franka_hw/franka_controller_switching_types.h>
 #include <hardware_interface/controller_info.h>
 
+#include <franka_hw/control_mode.h>
+
 namespace franka_hw {
 
+using ResourceWithClaimsMap = std::map<std::string, std::vector<std::vector<std::string>>>;
+
+struct ResourceClaims {
+  uint8_t joint_position_claims = 0;
+  uint8_t joint_velocity_claims = 0;
+  uint8_t joint_torque_claims = 0;
+  uint8_t cartesian_velocity_claims = 0;
+  uint8_t cartesian_pose_claims = 0;
+};
+
+using ArmClaimedMap = std::map<std::string, ResourceClaims>;
+
 bool findArmIdInResourceId(const std::string& resource_id, std::string* arm_id);
 
 ResourceWithClaimsMap getResourceMap(const std::list<hardware_interface::ControllerInfo>& info);
diff --git a/franka_msgs/CMakeLists.txt b/franka_msgs/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..01e483594964d600a7245fdf7840fab50a5b4ec0
--- /dev/null
+++ b/franka_msgs/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 2.8.3)
+project(franka_msgs)
+
+find_package(catkin REQUIRED COMPONENTS message_generation std_msgs)
+
+add_message_files(FILES Errors.msg FrankaState.msg)
+generate_messages(DEPENDENCIES std_msgs)
+catkin_package(CATKIN_DEPENDS message_runtime std_msgs)
diff --git a/franka_hw/msg/Errors.msg b/franka_msgs/msg/Errors.msg
similarity index 100%
rename from franka_hw/msg/Errors.msg
rename to franka_msgs/msg/Errors.msg
diff --git a/franka_hw/msg/FrankaState.msg b/franka_msgs/msg/FrankaState.msg
similarity index 87%
rename from franka_hw/msg/FrankaState.msg
rename to franka_msgs/msg/FrankaState.msg
index d909396eed6d5fc57fb184263da39537c8967922..31d56e807eef2a3d138336188eff7a3e924a12eb 100644
--- a/franka_hw/msg/FrankaState.msg
+++ b/franka_msgs/msg/FrankaState.msg
@@ -22,5 +22,5 @@ float64[16] O_T_EE_d
 float64[16] F_T_EE
 float64[16] EE_T_K
 float64 time
-franka_hw/Errors current_errors
-franka_hw/Errors last_motion_errors
+franka_msgs/Errors current_errors
+franka_msgs/Errors last_motion_errors
diff --git a/franka_msgs/package.xml b/franka_msgs/package.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9cc1bbf95ea67e17c60d5606ea71cda2a8683bc5
--- /dev/null
+++ b/franka_msgs/package.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<package format="2">
+  <name>franka_msgs</name>
+  <version>0.0.1</version>
+  <description>franka_msgs provides messages specific to FRANKA EMIKA research robots</description>
+  <maintainer email="info@franka.de">FRANKA EMIKA Research Interface Team</maintainer>
+  <license>NONE</license>
+
+  <url type="website">http://wiki.ros.org/franka_msgs</url>
+  <url type="repository">https://github.com/frankaemika/franka_ros</url>
+  <url type="bugtracker">https://github.com/frankaemika/franka_ros/issues</url>
+  <author>FRANKA EMIKA Research Interface Team</author>
+
+  <buildtool_depend>catkin</buildtool_depend>
+
+  <depend>std_msgs</depend>
+  <build_depend>message_generation</build_depend>
+  <exec_depend>message_runtime</exec_depend>
+
+  <export>
+    <architecture_independent/>
+  </export>
+</package>