diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+
diff --git a/LICENSE b/LICENSE
index 92f784cc..f37a869e 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,29 +1,62 @@
-BSD 3-Clause License
-
-Copyright (c) 2018, Kinova Robotics
+Copyright (c) 2018, Kinova inc.
All rights reserved.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+* Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+* Neither the name of the copyright holder nor the names of its contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+____________________________________________________________________
+
+
+Protocol Buffer license
+
+Copyright 2008 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+modification, are permitted provided that the following conditions are
+met:
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Code generated by the Protocol Buffer compiler is owned by the owner
+of the input file used when generating it. This code is not
+standalone and requires a support library to be linked with it. This
+support library is itself covered by the above license.
\ No newline at end of file
diff --git a/kortex_actuator_driver/CMakeLists.txt b/kortex_actuator_driver/CMakeLists.txt
new file mode 100644
index 00000000..7861e100
--- /dev/null
+++ b/kortex_actuator_driver/CMakeLists.txt
@@ -0,0 +1,49 @@
+
+cmake_minimum_required(VERSION 2.8.3)
+project(kortex_actuator_driver)
+
+add_compile_options(-std=c++11)
+add_definitions(-D_OS_UNIX)
+
+## Find catkin and any catkin packages
+find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation)
+
+file(GLOB_RECURSE cpp_list RELATIVE ${PROJECT_SOURCE_DIR} "src/*.cpp")
+
+## Declare ROS messages and services
+add_message_files(DIRECTORY msg)
+add_message_files(DIRECTORY msg/non_generated)
+add_service_files(DIRECTORY srv)
+add_service_files(DIRECTORY srv/non_generated)
+
+## Generate added messages and services
+generate_messages(DEPENDENCIES std_msgs)
+
+## Declare a catkin package
+catkin_package()
+
+include_directories(include ${catkin_INCLUDE_DIRS})
+include_directories(include ${PROJECT_SOURCE_DIR}/src)
+include_directories(include ${PROJECT_SOURCE_DIR}/../kortex_api/include/client)
+include_directories(include ${PROJECT_SOURCE_DIR}/../kortex_api/include/client_stubs)
+include_directories(include ${PROJECT_SOURCE_DIR}/../kortex_api/include/messages)
+include_directories(include ${PROJECT_SOURCE_DIR}/../kortex_api/include/common)
+include_directories(include ${PROJECT_SOURCE_DIR}/src/util)
+
+link_directories(${PROJECT_SOURCE_DIR}/../kortex_api/lib/release)
+
+add_executable(${PROJECT_NAME} ${cpp_list})
+
+target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES} CppKinovaApi gcov)
+
+find_package(Protobuf 3.5.1 REQUIRED)
+
+if(Protobuf_FOUND)
+ target_include_directories(${PROJECT_NAME} PUBLIC ${PROTOBUF_INCLUDE_DIRS})
+ target_link_libraries(${PROJECT_NAME} ${PROTOBUF_LIBRARIES})
+else()
+ message(FATAL_ERROR "Protobuf libraries not found")
+endif()
+
+add_dependencies(${PROJECT_NAME} kortex_actuator_driver_gencpp)
+
diff --git a/kortex_actuator_driver/RosGeneration.py b/kortex_actuator_driver/RosGeneration.py
new file mode 100644
index 00000000..f47a0d01
--- /dev/null
+++ b/kortex_actuator_driver/RosGeneration.py
@@ -0,0 +1,202 @@
+#!/usr/bin/env python
+
+import sys
+
+from google.protobuf.compiler import plugin_pb2 as plugin
+from google.protobuf import json_format as json_f
+
+import jinja2
+
+import itertools
+import json
+import types
+import os
+import sys
+
+from google.protobuf.descriptor_pb2 import DescriptorProto, EnumDescriptorProto, ServiceDescriptorProto, FieldDescriptorProto, OneofDescriptorProto
+
+#Class that holds a protobuf message and some other details needed by the generator(jinja2 template).
+class DetailedMessage:
+ def __init__(self, message=None):
+ self.message = message
+ self.HasOneOf = "false"
+ self.oneOfList = []
+
+#Class that holds a protobuf service and some other details needed by the generator(jinja2 template).
+class DetailedPackage:
+ def __init__(self, service=None):
+ self.name = "NoName"
+ self.service = service
+
+#JINJA2 function to render a file from a template.
+def render(tpl_path, context):
+ path, filename = os.path.split(tpl_path)
+ return jinja2.Environment(loader=jinja2.FileSystemLoader(path or './')).get_template(filename).render(**context)
+
+#Main plugin function
+def generate_code(request, response):
+
+ #The context is the object sent to the JINJA2 template
+ context = types.SimpleNamespace()
+ context.serviceVersion = 1
+
+ context.detailedPackages = []
+
+ MainFilePath = os.path.join(".", "src/main.cpp")
+ function_list = []
+ fileIndex = 0
+
+ for proto_file in request.proto_file:
+ context.detailedPackages.append(DetailedPackage())
+ context.detailedPackages[fileIndex].name = proto_file.package.split(".")[-1]
+ context.detailedPackages[fileIndex].filename = proto_file.name.split(".")[0]
+ context.detailedPackages[fileIndex].namespace = proto_file.package.replace(".", "::")
+ context.detailedPackages[fileIndex].HasRPC = 0
+ context.detailedPackages[fileIndex].HasMessage = 0
+
+ HeaderFilePath = os.path.join(".", "src/node.h")
+ CppFilePath = os.path.join(".", "src/node.cpp")
+
+ #We lower the case to respect ROS coding standard style
+ CppProtoConverterFilePath = os.path.join(".", "src/{}_proto_converter.cpp".format(proto_file.name.split(".")[0].lower()))
+ HeaderProtoConverterFilePath = os.path.join(".", "src/{}_proto_converter.h".format(proto_file.name.split(".")[0].lower()))
+ CppRosConverterFilePath = os.path.join(".", "src/{}_ros_converter.cpp".format(proto_file.name.split(".")[0].lower()))
+ HeaderRosConverterFilePath = os.path.join(".", "src/{}_ros_converter.h".format(proto_file.name.split(".")[0].lower()))
+
+ list_detailedMessage = []
+ list_detailedMethod = []
+
+ # For every item in the current proto file
+ for item, package in traverse(proto_file):
+ context.HasOneOf = 0
+
+
+ if isinstance(item, EnumDescriptorProto):
+ context.item = item
+
+ ros_enumPath = os.path.join(".", "msg/{}.msg".format(item.name))
+
+ with open(ros_enumPath, 'wt') as serviceFile:
+ serviceFile.write(render("./templates/ros_enum.jinja2", context.__dict__))
+ #If this it a message
+ if isinstance(item, DescriptorProto):
+ tempMessage = DetailedMessage(item)
+ context.detailedPackages[fileIndex].HasMessage = 1
+
+ for member in item.field:
+ #If a member is part of a oneof, it will have this additional field
+ if member.HasField("oneof_index"):
+ context.HasOneOf = 1
+ tempMessage.HasOneOf = "true"
+ else:
+ context.HasOneOf = 0
+ tempMessage.HasOneOf = "false"
+
+ context.item = item
+
+ #If the proto file contains a ONEOF we need to generate a separate file to handle it.
+ if context.HasOneOf == 1:
+
+ #This line gets the list of ONEOF that is in the current message.
+ oneOfList = item.ListFields()[-1][1]
+
+ tempMessage.oneOfList = item.ListFields()[-1][1]
+ ros_oneofPath = os.path.join(".", "msg/{}_{}.msg".format(item.name, oneOfList[0].name))
+
+ with open(ros_oneofPath, 'wt') as serviceFile:
+ serviceFile.write(render("./templates/ros_oneof.jinja2", context.__dict__))
+
+
+ list_detailedMessage.append(tempMessage)
+ ros_messagePath = os.path.join(".", "msg/{}.msg".format(item.name))
+
+ #We call jinja2 to generate a ROS message.
+ with open(ros_messagePath, 'wt') as serviceFile:
+ serviceFile.write(render("./templates/ros_message.jinja2", context.__dict__))
+
+ #If this is a service (A group of method)
+ if isinstance(item, ServiceDescriptorProto):
+ for method in item.method:
+ context.item = method
+ if "Topic" not in method.name:
+ function_list.append(method.name)
+ ros_servicePath = os.path.join(".", "srv/{}.srv".format(method.name))
+ with open(ros_servicePath, 'wt') as serviceFile:
+ serviceFile.write(render("./templates/ros_service.jinja2", context.__dict__))
+
+ context.detailedPackages[fileIndex].service = item
+ context.detailedPackages[fileIndex].HasRPC = 1
+
+ context.currentPackageName = context.detailedPackages[fileIndex].name
+ context.currentNamespace = proto_file.package.replace(".", "::")
+ context.currentFilename = context.detailedPackages[fileIndex].filename
+ context.item = list_detailedMessage
+
+ if context.detailedPackages[fileIndex].HasMessage == 1:
+ #Wecall jinja2 to generate a prot/ROS converter for every protobuf message.
+ with open(CppProtoConverterFilePath, 'wt') as converterFile:
+ converterFile.write(render("./templates/proto_converter.cpp.jinja2", context.__dict__))
+ with open(HeaderProtoConverterFilePath, 'wt') as converterFile:
+ converterFile.write(render("./templates/proto_converter.h.jinja2", context.__dict__))
+ with open(CppRosConverterFilePath, 'wt') as converterFile:
+ converterFile.write(render("./templates/ros_converter.cpp.jinja2", context.__dict__))
+ with open(HeaderRosConverterFilePath, 'wt') as converterFile:
+ converterFile.write(render("./templates/ros_converter.h.jinja2", context.__dict__))
+
+ fileIndex = fileIndex + 1
+
+ context.list_function = function_list
+
+ #We jinja2 to generate the ROS node.
+ with open(HeaderFilePath, 'wt') as nodeFile:
+ nodeFile.write(render("./templates/NodeServices.h.jinja2", context.__dict__))
+ with open(CppFilePath, 'wt') as nodeFile:
+ nodeFile.write(render("./templates/NodeServices.cpp.jinja2", context.__dict__))
+ with open(MainFilePath, 'wt') as mainFile:
+ mainFile.write(render("./templates/main.jinja2", context.__dict__))
+
+def traverse(proto_file):
+ #recursive function that browse a protobof item
+ def _traverse(package, items):
+ for item in items:
+ yield item, package
+
+ if isinstance(item, DescriptorProto):
+ for enum in item.enum_type:
+ yield enum, package
+
+ for nested in item.nested_type:
+ nested_package = package + item.name
+
+ for nested_item in _traverse(nested, nested_package):
+ yield nested_item, nested_package
+ if isinstance(item, ServiceDescriptorProto):
+ for rpc in item.method:
+ yield rpc, package
+
+ #return a list of everything found in the proto file
+ return itertools.chain(
+ _traverse(proto_file.package, proto_file.enum_type),
+ _traverse(proto_file.package, proto_file.message_type),
+ _traverse(proto_file.package, proto_file.service),
+ )
+
+if __name__ == '__main__':
+ # Read request message from stdin
+ data = sys.stdin.buffer.read()
+
+ # Parse request
+ request = plugin.CodeGeneratorRequest()
+ request.ParseFromString(data)
+
+ # Create response
+ response = plugin.CodeGeneratorResponse()
+
+ # Generate code
+ generate_code(request, response)
+
+ # Serialise response message
+ output = response.SerializeToString()
+
+ # Write to stdout
+ sys.stdout.buffer.write(output)
\ No newline at end of file
diff --git a/kortex_actuator_driver/build/.gitignore b/kortex_actuator_driver/build/.gitignore
new file mode 100644
index 00000000..e69de29b
diff --git a/kortex_actuator_driver/kortex_actuator_driver.sh b/kortex_actuator_driver/kortex_actuator_driver.sh
new file mode 100755
index 00000000..011eee96
--- /dev/null
+++ b/kortex_actuator_driver/kortex_actuator_driver.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+python3 -u RosGeneration.py
+
diff --git a/kortex_actuator_driver/msg/ArmState.msg b/kortex_actuator_driver/msg/ArmState.msg
new file mode 100644
index 00000000..d85bd69d
--- /dev/null
+++ b/kortex_actuator_driver/msg/ArmState.msg
@@ -0,0 +1,22 @@
+
+uint32 UNSPECIFIED_ARM_STATE = 0
+
+uint32 BASE_INITIALIZATION = 1
+
+uint32 IDLE = 2
+
+uint32 ARM_INITIALIZATION = 3
+
+uint32 ARM_IN_FAULT = 4
+
+uint32 ARM_MAINTENANCE = 5
+
+uint32 ARM_SERVOING_LOW_LEVEL = 6
+
+uint32 ARM_SERVOING_READY = 7
+
+uint32 ARM_SERVOING_PLAYING_SEQUENCE = 8
+
+uint32 ARM_SERVOING_MANUALLY_CONTROLLED = 9
+
+uint32 RESERVED = 255
diff --git a/kortex_actuator_driver/msg/AxisOffsets.msg b/kortex_actuator_driver/msg/AxisOffsets.msg
new file mode 100644
index 00000000..64f67904
--- /dev/null
+++ b/kortex_actuator_driver/msg/AxisOffsets.msg
@@ -0,0 +1,3 @@
+
+float32 absolute_offset
+float32 relative_offset
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/AxisPosition.msg b/kortex_actuator_driver/msg/AxisPosition.msg
new file mode 100644
index 00000000..380da9af
--- /dev/null
+++ b/kortex_actuator_driver/msg/AxisPosition.msg
@@ -0,0 +1,2 @@
+
+float32 position
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/Command.msg b/kortex_actuator_driver/msg/Command.msg
new file mode 100644
index 00000000..25525fa5
--- /dev/null
+++ b/kortex_actuator_driver/msg/Command.msg
@@ -0,0 +1,8 @@
+
+
+MessageId command_id
+uint32 flags
+float32 position
+float32 velocity
+float32 torque_joint
+float32 current_motor
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/CommandMode.msg b/kortex_actuator_driver/msg/CommandMode.msg
new file mode 100644
index 00000000..fad4f4d3
--- /dev/null
+++ b/kortex_actuator_driver/msg/CommandMode.msg
@@ -0,0 +1,12 @@
+
+uint32 CYCLIC = 0
+
+uint32 ASYNC_CYCLIC_FLAGS = 1
+
+uint32 ASYNC = 2
+
+uint32 CYCLIC_JITTERCOMPENSATED_POSITION = 3
+
+uint32 CYCLIC_JITTERCOMPENSATED_VELOCITY = 4
+
+uint32 CYCLIC_JITTERCOMPENSATED_ACCELERATION = 5
diff --git a/kortex_actuator_driver/msg/CommandModeInformation.msg b/kortex_actuator_driver/msg/CommandModeInformation.msg
new file mode 100644
index 00000000..e6342c48
--- /dev/null
+++ b/kortex_actuator_driver/msg/CommandModeInformation.msg
@@ -0,0 +1,3 @@
+
+
+uint32 command_mode
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/Connection.msg b/kortex_actuator_driver/msg/Connection.msg
new file mode 100644
index 00000000..ca08b6c8
--- /dev/null
+++ b/kortex_actuator_driver/msg/Connection.msg
@@ -0,0 +1,5 @@
+
+
+UserProfileHandle user_handle
+string connection_information
+uint32 connection_identifier
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/ControlLoop.msg b/kortex_actuator_driver/msg/ControlLoop.msg
new file mode 100644
index 00000000..17b6d695
--- /dev/null
+++ b/kortex_actuator_driver/msg/ControlLoop.msg
@@ -0,0 +1,2 @@
+
+uint32 control_loop
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/ControlLoopParameters.msg b/kortex_actuator_driver/msg/ControlLoopParameters.msg
new file mode 100644
index 00000000..72b8bbe5
--- /dev/null
+++ b/kortex_actuator_driver/msg/ControlLoopParameters.msg
@@ -0,0 +1,7 @@
+
+
+uint32 loop_selection
+float32 error_saturation
+float32 output_saturation
+float32[] kAz
+float32[] kBz
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/ControlLoopSelection.msg b/kortex_actuator_driver/msg/ControlLoopSelection.msg
new file mode 100644
index 00000000..6b620930
--- /dev/null
+++ b/kortex_actuator_driver/msg/ControlLoopSelection.msg
@@ -0,0 +1,14 @@
+
+uint32 RESERVED = 0
+
+uint32 JOINT_POSITION = 1
+
+uint32 MOTOR_POSITION = 2
+
+uint32 JOINT_VELOCITY = 4
+
+uint32 MOTOR_VELOCITY = 8
+
+uint32 JOINT_TORQUE = 16
+
+uint32 MOTOR_CURRENT = 32
diff --git a/kortex_actuator_driver/msg/ControlMode.msg b/kortex_actuator_driver/msg/ControlMode.msg
new file mode 100644
index 00000000..7f80fdc4
--- /dev/null
+++ b/kortex_actuator_driver/msg/ControlMode.msg
@@ -0,0 +1,12 @@
+
+uint32 NONE = 0
+
+uint32 POSITION = 1
+
+uint32 VELOCITY = 2
+
+uint32 TORQUE = 3
+
+uint32 CURRENT = 4
+
+uint32 CUSTOM = 5
diff --git a/kortex_actuator_driver/msg/ControlModeInformation.msg b/kortex_actuator_driver/msg/ControlModeInformation.msg
new file mode 100644
index 00000000..3bcfa3fa
--- /dev/null
+++ b/kortex_actuator_driver/msg/ControlModeInformation.msg
@@ -0,0 +1,3 @@
+
+
+uint32 control_mode
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/CustomData.msg b/kortex_actuator_driver/msg/CustomData.msg
new file mode 100644
index 00000000..b81c1b26
--- /dev/null
+++ b/kortex_actuator_driver/msg/CustomData.msg
@@ -0,0 +1,19 @@
+
+
+MessageId custom_data_id
+uint32 custom_data_0
+uint32 custom_data_1
+uint32 custom_data_2
+uint32 custom_data_3
+uint32 custom_data_4
+uint32 custom_data_5
+uint32 custom_data_6
+uint32 custom_data_7
+uint32 custom_data_8
+uint32 custom_data_9
+uint32 custom_data_10
+uint32 custom_data_11
+uint32 custom_data_12
+uint32 custom_data_13
+uint32 custom_data_14
+uint32 custom_data_15
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/CustomDataSelection.msg b/kortex_actuator_driver/msg/CustomDataSelection.msg
new file mode 100644
index 00000000..1197aaba
--- /dev/null
+++ b/kortex_actuator_driver/msg/CustomDataSelection.msg
@@ -0,0 +1,2 @@
+
+uint32[] channel
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/DeviceHandle.msg b/kortex_actuator_driver/msg/DeviceHandle.msg
new file mode 100644
index 00000000..49f84366
--- /dev/null
+++ b/kortex_actuator_driver/msg/DeviceHandle.msg
@@ -0,0 +1,5 @@
+
+
+uint32 device_type
+uint32 device_identifier
+uint32 order
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/DeviceTypes.msg b/kortex_actuator_driver/msg/DeviceTypes.msg
new file mode 100644
index 00000000..5a55df07
--- /dev/null
+++ b/kortex_actuator_driver/msg/DeviceTypes.msg
@@ -0,0 +1,14 @@
+
+uint32 UNSPECIFIED_DEVICE_TYPE = 0
+
+uint32 BASE = 1
+
+uint32 VISION = 2
+
+uint32 BIG_ACTUATOR = 3
+
+uint32 SMALL_ACTUATOR = 4
+
+uint32 INTERCONNECT = 5
+
+uint32 GRIPPER = 6
diff --git a/kortex_actuator_driver/msg/Empty.msg b/kortex_actuator_driver/msg/Empty.msg
new file mode 100644
index 00000000..e69de29b
diff --git a/kortex_actuator_driver/msg/EncoderDerivativeParameters.msg b/kortex_actuator_driver/msg/EncoderDerivativeParameters.msg
new file mode 100644
index 00000000..c83b9929
--- /dev/null
+++ b/kortex_actuator_driver/msg/EncoderDerivativeParameters.msg
@@ -0,0 +1,3 @@
+
+uint32 max_window_width
+uint32 min_encoder_tick_count
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/Feedback.msg b/kortex_actuator_driver/msg/Feedback.msg
new file mode 100644
index 00000000..9698d184
--- /dev/null
+++ b/kortex_actuator_driver/msg/Feedback.msg
@@ -0,0 +1,16 @@
+
+
+MessageId feedback_id
+uint32 status_flags
+uint32 jitter_comm
+float32 position
+float32 velocity
+float32 torque
+float32 current_motor
+float32 voltage
+float32 temperature_motor
+float32 temperature_core
+uint32 fault_bank_a
+uint32 fault_bank_b
+uint32 warning_bank_a
+uint32 warning_bank_b
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/FrequencyResponse.msg b/kortex_actuator_driver/msg/FrequencyResponse.msg
new file mode 100644
index 00000000..ea3ce5bd
--- /dev/null
+++ b/kortex_actuator_driver/msg/FrequencyResponse.msg
@@ -0,0 +1,7 @@
+
+
+uint32 loop_selection
+float32 min_frequency
+float32 max_frequency
+float32 amplitude
+float32 duration
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/LoopSelection.msg b/kortex_actuator_driver/msg/LoopSelection.msg
new file mode 100644
index 00000000..f8dc270b
--- /dev/null
+++ b/kortex_actuator_driver/msg/LoopSelection.msg
@@ -0,0 +1,3 @@
+
+
+uint32 loop_selection
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/MessageId.msg b/kortex_actuator_driver/msg/MessageId.msg
new file mode 100644
index 00000000..bd72812b
--- /dev/null
+++ b/kortex_actuator_driver/msg/MessageId.msg
@@ -0,0 +1,2 @@
+
+uint32 identifier
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/NotificationHandle.msg b/kortex_actuator_driver/msg/NotificationHandle.msg
new file mode 100644
index 00000000..bd72812b
--- /dev/null
+++ b/kortex_actuator_driver/msg/NotificationHandle.msg
@@ -0,0 +1,2 @@
+
+uint32 identifier
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/NotificationOptions.msg b/kortex_actuator_driver/msg/NotificationOptions.msg
new file mode 100644
index 00000000..6ff46842
--- /dev/null
+++ b/kortex_actuator_driver/msg/NotificationOptions.msg
@@ -0,0 +1,5 @@
+
+
+uint32 type
+uint32 rate_m_sec
+float32 threshold_value
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/NotificationType.msg b/kortex_actuator_driver/msg/NotificationType.msg
new file mode 100644
index 00000000..79dd058c
--- /dev/null
+++ b/kortex_actuator_driver/msg/NotificationType.msg
@@ -0,0 +1,8 @@
+
+uint32 UNSPECIFIED_NOTIFICATION_TYPE = 0
+
+uint32 THRESHOLD = 1
+
+uint32 FIX_RATE = 2
+
+uint32 EVENT = 3
diff --git a/kortex_actuator_driver/msg/Permission.msg b/kortex_actuator_driver/msg/Permission.msg
new file mode 100644
index 00000000..c5399e9c
--- /dev/null
+++ b/kortex_actuator_driver/msg/Permission.msg
@@ -0,0 +1,8 @@
+
+uint32 NO_PERMISSION = 0
+
+uint32 READ_PERMISSION = 1
+
+uint32 UPDATE_PERMISSION = 2
+
+uint32 DELETE_PERMISSION = 4
diff --git a/kortex_actuator_driver/msg/PositionCommand.msg b/kortex_actuator_driver/msg/PositionCommand.msg
new file mode 100644
index 00000000..5e894e42
--- /dev/null
+++ b/kortex_actuator_driver/msg/PositionCommand.msg
@@ -0,0 +1,4 @@
+
+float32 position
+float32 velocity
+float32 acceleration
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/RampResponse.msg b/kortex_actuator_driver/msg/RampResponse.msg
new file mode 100644
index 00000000..59d88d4e
--- /dev/null
+++ b/kortex_actuator_driver/msg/RampResponse.msg
@@ -0,0 +1,6 @@
+
+
+uint32 loop_selection
+float32 slope
+float32 ramp_delay
+float32 duration
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/SafetyHandle.msg b/kortex_actuator_driver/msg/SafetyHandle.msg
new file mode 100644
index 00000000..bd72812b
--- /dev/null
+++ b/kortex_actuator_driver/msg/SafetyHandle.msg
@@ -0,0 +1,2 @@
+
+uint32 identifier
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/SafetyIdentifier.msg b/kortex_actuator_driver/msg/SafetyIdentifier.msg
new file mode 100644
index 00000000..6e0c3e8d
--- /dev/null
+++ b/kortex_actuator_driver/msg/SafetyIdentifier.msg
@@ -0,0 +1,50 @@
+
+uint32 UNSPECIFIED_ACTUATOR_SAFETY_IDENTIFIER = 0
+
+uint32 FOLLOWING_ERROR = 1
+
+uint32 MAXIMUM_VELOCITY = 2
+
+uint32 JOINT_LIMIT_HIGH = 4
+
+uint32 JOINT_LIMIT_LOW = 8
+
+uint32 STRAIN_GAUGE_MISMATCH = 16
+
+uint32 MAXIMUM_TORQUE = 32
+
+uint32 UNRELIABLE_ABSOLUTE_POSITION = 64
+
+uint32 MAGNETIC_POSITION = 128
+
+uint32 HALL_POSITION = 256
+
+uint32 HALL_SEQUENCE = 512
+
+uint32 INPUT_ENCODER_HALL_MISMATCH = 1024
+
+uint32 INPUT_ENCODER_INDEX_MISMATCH = 2048
+
+uint32 INPUT_ENCODER_MAGNETIC_MISMATCH = 4096
+
+uint32 MAXIMUM_MOTOR_CURRENT = 8192
+
+uint32 MOTOR_CURRENT_MISMATCH = 16384
+
+uint32 MAXIMUM_VOLTAGE = 32768
+
+uint32 MINIMUM_VOLTAGE = 65536
+
+uint32 MAXIMUM_MOTOR_TEMPERATURE = 131072
+
+uint32 MAXIMUM_CORE_TEMPERATURE = 262144
+
+uint32 NON_VOLATILE_MEMORY_CORRUPTED = 524288
+
+uint32 MOTOR_DRIVER_FAULT = 1048576
+
+uint32 EMERGENCY_LINE_ASSERTED = 2097152
+
+uint32 COMMUNICATION_TICK_LOST = 4194304
+
+uint32 WATCHDOG_TRIGGERED = 8388608
diff --git a/kortex_actuator_driver/msg/SafetyLimitType.msg b/kortex_actuator_driver/msg/SafetyLimitType.msg
new file mode 100644
index 00000000..a8d7a177
--- /dev/null
+++ b/kortex_actuator_driver/msg/SafetyLimitType.msg
@@ -0,0 +1,4 @@
+
+uint32 MAXIMAL_LIMIT = 0
+
+uint32 MINIMAL_LIMIT = 1
diff --git a/kortex_actuator_driver/msg/SafetyNotification.msg b/kortex_actuator_driver/msg/SafetyNotification.msg
new file mode 100644
index 00000000..36d88894
--- /dev/null
+++ b/kortex_actuator_driver/msg/SafetyNotification.msg
@@ -0,0 +1,11 @@
+
+
+SafetyHandle safety_handle
+
+uint32 value
+
+Timestamp timestamp
+
+UserProfileHandle user_handle
+
+Connection connection
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/SafetyStatusValue.msg b/kortex_actuator_driver/msg/SafetyStatusValue.msg
new file mode 100644
index 00000000..2ea80554
--- /dev/null
+++ b/kortex_actuator_driver/msg/SafetyStatusValue.msg
@@ -0,0 +1,8 @@
+
+uint32 UNSPECIFIED = 0
+
+uint32 WARNING = 1
+
+uint32 ERROR = 2
+
+uint32 NORMAL = 3
diff --git a/kortex_actuator_driver/msg/ServiceVersion.msg b/kortex_actuator_driver/msg/ServiceVersion.msg
new file mode 100644
index 00000000..9665d1c2
--- /dev/null
+++ b/kortex_actuator_driver/msg/ServiceVersion.msg
@@ -0,0 +1,4 @@
+
+uint32 RESERVED_0 = 0
+
+uint32 CURRENT_VERSION = 1
diff --git a/kortex_actuator_driver/msg/Servoing.msg b/kortex_actuator_driver/msg/Servoing.msg
new file mode 100644
index 00000000..7f2750b4
--- /dev/null
+++ b/kortex_actuator_driver/msg/Servoing.msg
@@ -0,0 +1,2 @@
+
+bool enabled
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/StepResponse.msg b/kortex_actuator_driver/msg/StepResponse.msg
new file mode 100644
index 00000000..bde4ed2e
--- /dev/null
+++ b/kortex_actuator_driver/msg/StepResponse.msg
@@ -0,0 +1,6 @@
+
+
+uint32 loop_selection
+float32 amplitude
+float32 step_delay
+float32 duration
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/Timestamp.msg b/kortex_actuator_driver/msg/Timestamp.msg
new file mode 100644
index 00000000..5e60508c
--- /dev/null
+++ b/kortex_actuator_driver/msg/Timestamp.msg
@@ -0,0 +1,3 @@
+
+uint32 sec
+uint32 usec
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/TorqueCalibration.msg b/kortex_actuator_driver/msg/TorqueCalibration.msg
new file mode 100644
index 00000000..a237df13
--- /dev/null
+++ b/kortex_actuator_driver/msg/TorqueCalibration.msg
@@ -0,0 +1,5 @@
+
+float32 global_gain
+float32 global_offset
+float32[] gain
+float32[] offset
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/TorqueOffset.msg b/kortex_actuator_driver/msg/TorqueOffset.msg
new file mode 100644
index 00000000..198518a2
--- /dev/null
+++ b/kortex_actuator_driver/msg/TorqueOffset.msg
@@ -0,0 +1,2 @@
+
+float32 torque_offset
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/Unit.msg b/kortex_actuator_driver/msg/Unit.msg
new file mode 100644
index 00000000..c019aeba
--- /dev/null
+++ b/kortex_actuator_driver/msg/Unit.msg
@@ -0,0 +1,28 @@
+
+uint32 UNSPECIFIED_UNIT = 0
+
+uint32 CELSIUS = 1
+
+uint32 AMPERE = 2
+
+uint32 VOLT = 3
+
+uint32 METER_PER_SECOND = 4
+
+uint32 DEGREE_PER_SECOND = 5
+
+uint32 METER_PER_SECOND_2 = 6
+
+uint32 DEGREE_PER_SECOND_2 = 7
+
+uint32 NEWTON = 8
+
+uint32 NEWTON_METER = 9
+
+uint32 KILOGRAM = 10
+
+uint32 DEGREE = 11
+
+uint32 TICK = 12
+
+uint32 DEGREE_PER_MILLISECOND = 13
diff --git a/kortex_actuator_driver/msg/UserProfileHandle.msg b/kortex_actuator_driver/msg/UserProfileHandle.msg
new file mode 100644
index 00000000..3038380d
--- /dev/null
+++ b/kortex_actuator_driver/msg/UserProfileHandle.msg
@@ -0,0 +1,3 @@
+
+uint32 identifier
+uint32 permission
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/VectorDriveParameters.msg b/kortex_actuator_driver/msg/VectorDriveParameters.msg
new file mode 100644
index 00000000..8fad9fca
--- /dev/null
+++ b/kortex_actuator_driver/msg/VectorDriveParameters.msg
@@ -0,0 +1,5 @@
+
+float32 kpq
+float32 kiq
+float32 kpd
+float32 kid
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/non_generated/ApiOptions.msg b/kortex_actuator_driver/msg/non_generated/ApiOptions.msg
new file mode 100644
index 00000000..471fddd8
--- /dev/null
+++ b/kortex_actuator_driver/msg/non_generated/ApiOptions.msg
@@ -0,0 +1 @@
+uint32 timeout_ms
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/non_generated/CyclicStatus.msg b/kortex_actuator_driver/msg/non_generated/CyclicStatus.msg
new file mode 100644
index 00000000..cb36958f
--- /dev/null
+++ b/kortex_actuator_driver/msg/non_generated/CyclicStatus.msg
@@ -0,0 +1 @@
+bool isActive
\ No newline at end of file
diff --git a/kortex_actuator_driver/msg/non_generated/KortexError.msg b/kortex_actuator_driver/msg/non_generated/KortexError.msg
new file mode 100644
index 00000000..3ff9c32c
--- /dev/null
+++ b/kortex_actuator_driver/msg/non_generated/KortexError.msg
@@ -0,0 +1,3 @@
+uint32 code
+uint32 subCode
+string description
\ No newline at end of file
diff --git a/kortex_actuator_driver/package.xml b/kortex_actuator_driver/package.xml
new file mode 100644
index 00000000..410d5568
--- /dev/null
+++ b/kortex_actuator_driver/package.xml
@@ -0,0 +1,35 @@
+
+
+ kortex_actuator_driver
+ 1.0.0
+ The kortex package that communicate with an actuator.
+
+
+ KINOVA
+
+
+
+
+
+ BSD
+
+ catkin
+ roscpp
+ rospy
+ std_msgs
+ roscpp
+ rospy
+ std_msgs
+ roscpp
+ rospy
+ std_msgs
+ message_generation
+ message_runtime
+
+
+
+
+
+
+
+
diff --git a/kortex_actuator_driver/protos/ActuatorConfig.options b/kortex_actuator_driver/protos/ActuatorConfig.options
new file mode 100644
index 00000000..ef52a309
--- /dev/null
+++ b/kortex_actuator_driver/protos/ActuatorConfig.options
@@ -0,0 +1,10 @@
+Kinova.Api.ActuatorConfig.TorqueCalibration.gain max_count:4 fixed_count:true
+Kinova.Api.ActuatorConfig.TorqueCalibration.offset max_count:4 fixed_count:true
+Kinova.Api.ActuatorConfig.ControlLoopParameters.kAz max_count:5 fixed_count:true
+Kinova.Api.ActuatorConfig.ControlLoopParameters.kBz max_count:6 fixed_count:true
+Kinova.Api.ActuatorConfig.CustomDataSelection.channel max_count:16
+Kinova.Api.ActuatorConfig.SafetyLimitType long_names:false
+Kinova.Api.ActuatorConfig.ControlMode long_names:false
+Kinova.Api.ActuatorConfig.CommandMode long_names:false
+Kinova.Api.ActuatorConfig.SafetyIdentifier long_names:false
+Kinova.Api.ActuatorConfig.ControlLoopSelection long_names:false
diff --git a/kortex_actuator_driver/protos/ActuatorConfig.proto b/kortex_actuator_driver/protos/ActuatorConfig.proto
new file mode 100644
index 00000000..8aca4183
--- /dev/null
+++ b/kortex_actuator_driver/protos/ActuatorConfig.proto
@@ -0,0 +1,235 @@
+syntax = "proto3";
+
+import public "Common.proto";
+
+package Kinova.Api.ActuatorConfig;
+
+service ActuatorConfig {//@PROXY_ID=10 @ERROR=Kinova.Api.Error
+ rpc GetAxisOffsets (Kinova.Api.Common.Empty) returns (AxisOffsets); //@RPC_ID=1
+ rpc SetAxisOffsets (AxisPosition) returns (Kinova.Api.Common.Empty); //@RPC_ID=2
+ rpc ReadTorqueCalibration (Kinova.Api.Common.Empty) returns (TorqueCalibration); //@RPC_ID=3
+ rpc WriteTorqueCalibration (TorqueCalibration) returns (Kinova.Api.Common.Empty); //@RPC_ID=4
+ rpc SetTorqueOffset (TorqueOffset) returns (Kinova.Api.Common.Empty); //@RPC_ID=5
+ rpc GetControlMode (Kinova.Api.Common.Empty) returns (ControlModeInformation); //@RPC_ID=6
+ rpc SetControlMode (ControlModeInformation) returns (Kinova.Api.Common.Empty); //@RPC_ID=7
+ rpc GetActivatedControlLoop (Kinova.Api.Common.Empty) returns (ControlLoop); //@RPC_ID=8
+ rpc SetActivatedControlLoop (ControlLoop) returns (Kinova.Api.Common.Empty); //@RPC_ID=9
+ rpc GetVectorDriveParameters (Kinova.Api.Common.Empty) returns (VectorDriveParameters); //@RPC_ID=10
+ rpc SetVectorDriveParameters (VectorDriveParameters) returns (Kinova.Api.Common.Empty); //@RPC_ID=11
+ rpc GetEncoderDerivativeParameters (Kinova.Api.Common.Empty) returns (EncoderDerivativeParameters); //@RPC_ID=12
+ rpc SetEncoderDerivativeParameters (EncoderDerivativeParameters) returns (Kinova.Api.Common.Empty); //@RPC_ID=13
+ rpc GetControlLoopParameters (LoopSelection) returns (ControlLoopParameters); //@RPC_ID=14
+ rpc SetControlLoopParameters (ControlLoopParameters) returns (Kinova.Api.Common.Empty); //@RPC_ID=15
+ rpc StartFrequencyResponse (FrequencyResponse) returns (Kinova.Api.Common.Empty); //@RPC_ID=16
+ rpc StopFrequencyResponse (Kinova.Api.Common.Empty) returns (Kinova.Api.Common.Empty); //@RPC_ID=17
+ rpc StartStepResponse (StepResponse) returns (Kinova.Api.Common.Empty); //@RPC_ID=18
+ rpc StopStepResponse (Kinova.Api.Common.Empty) returns (Kinova.Api.Common.Empty); //@RPC_ID=19
+ rpc StartRampResponse (RampResponse) returns (Kinova.Api.Common.Empty); //@RPC_ID=20
+ rpc StopRampResponse (Kinova.Api.Common.Empty) returns (Kinova.Api.Common.Empty); //@RPC_ID=21
+ rpc SelectCustomData (CustomDataSelection) returns (Kinova.Api.Common.Empty); //@RPC_ID=22
+ rpc GetSelectedCustomData (Kinova.Api.Common.Empty) returns (CustomDataSelection); //@RPC_ID=23
+ rpc SetCommandMode (CommandModeInformation) returns (Kinova.Api.Common.Empty); //@RPC_ID=24
+ rpc ClearFaults (Kinova.Api.Common.Empty) returns (Kinova.Api.Common.Empty); //@RPC_ID=25
+ rpc SetServoing (Servoing) returns (Kinova.Api.Common.Empty); //@RPC_ID=26
+ rpc MoveToPosition (PositionCommand) returns (Kinova.Api.Common.Empty); //@RPC_ID=27
+ rpc GetCommandMode (Kinova.Api.Common.Empty) returns (CommandModeInformation); //@RPC_ID=28
+ rpc GetServoing (Kinova.Api.Common.Empty) returns (Servoing); //@RPC_ID=29
+ rpc GetTorqueOffset (Kinova.Api.Common.Empty) returns (TorqueOffset); //@RPC_ID=30
+}
+
+enum ServiceVersion
+{
+ RESERVED_0 = 0; // Reserved
+ CURRENT_VERSION = 1; // Current Version
+}
+
+/**
+ * list of limit types
+ */
+enum SafetyLimitType
+{
+ MAXIMAL_LIMIT = 0; // Maximal limit
+ MINIMAL_LIMIT = 1; // Minimal limit
+}
+
+/**
+ * list of control modes
+ */
+enum ControlMode
+{
+ NONE = 0; // None
+ POSITION = 1; // Position mode
+ VELOCITY = 2; // Velocity mode
+ TORQUE = 3; // Torque mode
+ CURRENT = 4; // Current mode
+ CUSTOM = 5; // Custom mode
+}
+
+/**
+ * list of command modes
+ */
+enum CommandMode
+{
+ CYCLIC = 0; // Only cyclic data
+ ASYNC_CYCLIC_FLAGS = 1; // Not Supported
+ ASYNC = 2; // Only asynchronous messages
+ CYCLIC_JITTERCOMPENSATED_POSITION = 3; // Smoothing using only position inputs
+ CYCLIC_JITTERCOMPENSATED_VELOCITY = 4; // Smoothing using position and velocity inputs
+ CYCLIC_JITTERCOMPENSATED_ACCELERATION = 5; // Smoothing using position, velocity and acceleration inputs (not supported)
+}
+
+enum ControlLoopSelection
+{
+ RESERVED = 0;
+ JOINT_POSITION = 1; // If available
+ MOTOR_POSITION = 2;
+ JOINT_VELOCITY = 4; // If available
+ MOTOR_VELOCITY = 8;
+ JOINT_TORQUE = 16;
+ MOTOR_CURRENT = 32;
+}
+
+message AxisPosition
+{
+ float position = 1; // Axis position
+}
+
+message AxisOffsets
+{
+ float absolute_offset = 1; // Absolute offset value
+ float relative_offset = 2; // Relative offset value
+}
+
+message TorqueCalibration
+{
+ float global_gain = 1; // Global gain value
+ float global_offset = 2; // Global offset value
+ repeated float gain = 3; // Gain (index 0 to 3)
+ repeated float offset = 4; // Offset (index 0 to 3)
+}
+
+message TorqueOffset
+{
+ float torque_offset = 1; // Torque offset value
+}
+
+message ControlModeInformation
+{
+ ControlMode control_mode = 1; // Control mode
+}
+
+/* Control loop bit mask :
+ Bit 0 : JOINT_POSITION // If available
+ Bit 1 : MOTOR_POSITION
+ Bit 2 : JOINT_VELOCITY // If available
+ Bit 3 : MOTOR_VELOCITY
+ Bit 4 : JOINT_TORQUE
+ Bit 5 : MOTOR_CURRENT
+ */
+message ControlLoop
+{
+ fixed32 control_loop = 1; // Use ControlLoopSelection enum values to form bitmask
+}
+
+message LoopSelection
+{
+ ControlLoopSelection loop_selection = 1; // ControlLoopSelection enum
+}
+
+message VectorDriveParameters
+{
+ float kpq = 1; // Kpq
+ float kiq = 2; // Kiq
+ float kpd = 3; // Kpd
+ float kid = 4; // Kid
+}
+
+message EncoderDerivativeParameters
+{
+ uint32 max_window_width = 1; // Maximum window width
+ uint32 min_encoder_tick_count = 2; // Minimum encoder tick count
+}
+
+message ControlLoopParameters
+{
+ ControlLoopSelection loop_selection = 1; // ControlLoopSelection enum
+ float error_saturation = 2; // Error saturation value
+ float output_saturation = 3; // Output saturation value
+ repeated float kAz = 4; // KAz (index 0 to 4)
+ repeated float kBz = 5; // KBz (index 0 to 5)
+}
+
+message FrequencyResponse
+{
+ ControlLoopSelection loop_selection = 1; // ControlLoopSelection enum
+ float min_frequency = 2; // Minimum frequency value
+ float max_frequency = 3; // Maximum frequency value
+ float amplitude = 4; // Amplitude value
+ float duration = 5; // Duration in seconds
+}
+
+message StepResponse
+{
+ ControlLoopSelection loop_selection = 1; // ControlLoopSelection enum
+ float amplitude = 2; // Amplitude value
+ float step_delay = 3; // Step delay value
+ float duration = 4; // Duration in seconds
+}
+
+message RampResponse
+{
+ ControlLoopSelection loop_selection = 1; // ControlLoopSelection enum
+ float slope = 2; // Slope value
+ float ramp_delay = 3; // Ramp delay value
+ float duration = 4; // Duration in seconds
+}
+
+message CustomDataSelection
+{
+ repeated uint32 channel = 1; // 16 channels maximum
+}
+
+message CommandModeInformation
+{
+ CommandMode command_mode = 1; // Command mode
+}
+
+message Servoing
+{
+ bool enabled = 1; // Servoing enabled
+}
+
+message PositionCommand
+{
+ float position = 1; // Position value
+ float velocity = 2; // Velocity value
+ float acceleration = 3; // Acceleration value
+}
+
+enum SafetyIdentifier {
+ UNSPECIFIED_ACTUATOR_SAFETY_IDENTIFIER = 0; //0x0
+ FOLLOWING_ERROR = 1; //0x1
+ MAXIMUM_VELOCITY = 2; //0x2
+ JOINT_LIMIT_HIGH = 4; //0x4
+ JOINT_LIMIT_LOW = 8; //0x8
+ STRAIN_GAUGE_MISMATCH = 16; //0x10
+ MAXIMUM_TORQUE = 32; //0x20
+ UNRELIABLE_ABSOLUTE_POSITION = 64; //0x40
+ MAGNETIC_POSITION = 128; //0x80
+ HALL_POSITION = 256; //0x100
+ HALL_SEQUENCE = 512; //0x200
+ INPUT_ENCODER_HALL_MISMATCH = 1024; //0x400
+ INPUT_ENCODER_INDEX_MISMATCH = 2048; //0x800
+ INPUT_ENCODER_MAGNETIC_MISMATCH = 4096; //0x1000
+ MAXIMUM_MOTOR_CURRENT = 8192; //0x2000
+ MOTOR_CURRENT_MISMATCH = 16384; //0x4000
+ MAXIMUM_VOLTAGE = 32768; //0x8000
+ MINIMUM_VOLTAGE = 65536; //0x10000
+ MAXIMUM_MOTOR_TEMPERATURE = 131072; //0x20000
+ MAXIMUM_CORE_TEMPERATURE = 262144; //0x40000
+ NON_VOLATILE_MEMORY_CORRUPTED = 524288; //0x80000
+ MOTOR_DRIVER_FAULT = 1048576; //0x100000
+ EMERGENCY_LINE_ASSERTED = 2097152; //0x200000
+ COMMUNICATION_TICK_LOST = 4194304; //0x400000
+ WATCHDOG_TRIGGERED = 8388608; //0x800000
+}
diff --git a/kortex_actuator_driver/protos/ActuatorCyclic.proto b/kortex_actuator_driver/protos/ActuatorCyclic.proto
new file mode 100644
index 00000000..5508da2b
--- /dev/null
+++ b/kortex_actuator_driver/protos/ActuatorCyclic.proto
@@ -0,0 +1,78 @@
+syntax = "proto3";
+
+import public "Common.proto";
+
+package Kinova.Api.ActuatorCyclic;
+
+/**
+ * List of services available via remote procedure call
+ */
+service ActuatorCyclic {//@PROXY_ID=11 @ERROR=Kinova.Api.Error
+
+// Commands refresh (with feedback)
+ rpc Refresh (Command) returns (Feedback); //@RPC_ID=1
+
+// Commands refresh (no feedback)
+ rpc RefreshCommand (Command) returns (Kinova.Api.Common.Empty); //@RPC_ID=2
+
+// Gets feedback
+ rpc RefreshFeedback (MessageId) returns (Feedback); //@RPC_ID=3
+
+// Gets custom data
+ rpc RefreshCustomData (MessageId) returns (CustomData); //@RPC_ID=4
+}
+
+enum ServiceVersion {
+ RESERVED_0 = 0; // Reserved
+ CURRENT_VERSION = 1; // Current Service Version
+}
+
+message MessageId {
+ fixed32 identifier = 1; // Message ID (first 2 bytes : device ID, last 2 bytes : sequence number)
+}
+
+message Command {
+ MessageId command_id = 1; // MessageId
+ fixed32 flags = 2; // Flags
+ float position = 3; // Desired position of the actuator in °
+ float velocity = 4; // Desired velocity of the actuator in °/s
+ float torque_joint = 5; // Desired torque of the actuator in N·m
+ float current_motor = 6; // Desired current of the motor in A
+}
+
+message Feedback {
+ MessageId feedback_id = 1; // MessageId
+ fixed32 status_flags = 2; // Status flags
+ fixed32 jitter_comm = 3; // Jitter from the communication in μs
+ float position = 4; // Position of the actuator in °
+ float velocity = 5; // Angular velocity of the actuator in °/s
+ float torque = 6; // Torque of the actuator in N·m
+ float current_motor = 7; // Current of the motor in A
+ float voltage = 8; // Voltage of the main board in V
+ float temperature_motor = 9; // Motor temperature (average of the three (3) temperatures in °C)
+ float temperature_core = 10; // Microcontroller temperature in °C
+ fixed32 fault_bank_a = 11; // Bank A Fault (see ActuatorConfig.SafetyIdentifier)
+ fixed32 fault_bank_b = 12; // Bank B Fault (see ActuatorConfig.SafetyIdentifier)
+ fixed32 warning_bank_a = 13; // Bank A Warning (see ActuatorConfig.SafetyIdentifier)
+ fixed32 warning_bank_b = 14; // Bank B Warning (see ActuatorConfig.SafetyIdentifier)
+}
+
+message CustomData {
+ MessageId custom_data_id = 1; // MessageId
+ fixed32 custom_data_0 = 2; // Custom data word 0
+ fixed32 custom_data_1 = 3; // Custom data word 1
+ fixed32 custom_data_2 = 4; // Custom data word 2
+ fixed32 custom_data_3 = 5; // Custom data word 3
+ fixed32 custom_data_4 = 6; // Custom data word 4
+ fixed32 custom_data_5 = 7; // Custom data word 5
+ fixed32 custom_data_6 = 8; // Custom data word 6
+ fixed32 custom_data_7 = 9; // Custom data word 7
+ fixed32 custom_data_8 = 10; // Custom data word 8
+ fixed32 custom_data_9 = 11; // Custom data word 9
+ fixed32 custom_data_10 = 12; // Custom data word 10
+ fixed32 custom_data_11 = 13; // Custom data word 11
+ fixed32 custom_data_12 = 14; // Custom data word 12
+ fixed32 custom_data_13 = 15; // Custom data word 13
+ fixed32 custom_data_14 = 16; // Custom data word 14
+ fixed32 custom_data_15 = 17; // Custom data word 15
+}
diff --git a/kortex_actuator_driver/protos/Common.options b/kortex_actuator_driver/protos/Common.options
new file mode 100644
index 00000000..5f3020ab
--- /dev/null
+++ b/kortex_actuator_driver/protos/Common.options
@@ -0,0 +1,4 @@
+Kinova.Api.Common.DeviceTypes long_names:false
+Kinova.Api.Common.SafetyStatusValue long_names:false
+Kinova.Api.Common.NotificationType long_names:false
+Kinova.Api.Common.Unit long_names:false
\ No newline at end of file
diff --git a/kortex_actuator_driver/protos/Common.proto b/kortex_actuator_driver/protos/Common.proto
new file mode 100644
index 00000000..50f762ec
--- /dev/null
+++ b/kortex_actuator_driver/protos/Common.proto
@@ -0,0 +1,152 @@
+syntax = "proto3";
+
+package Kinova.Api.Common;
+
+/**
+ * list of possible device types
+ */
+enum DeviceTypes {
+ UNSPECIFIED_DEVICE_TYPE = 0;
+ BASE = 1;
+ VISION = 2;
+ BIG_ACTUATOR = 3;
+ SMALL_ACTUATOR = 4;
+ INTERCONNECT = 5;
+ GRIPPER = 6;
+}
+
+/**
+* Message contains information about a device - device type, device identifier, and the order of the device within the robot
+*/
+message DeviceHandle {
+ DeviceTypes device_type = 1;
+ uint32 device_identifier = 2; // Unique device identifier (used with other services)
+ uint32 order = 3; // Unique value indicating the order of that device versus the others to facilitate representation
+}
+
+/**
+ * list of possible safety statuses
+ */
+enum SafetyStatusValue {
+ UNSPECIFIED = 0;
+ WARNING = 1; //warning safety reached
+ ERROR = 2; //error safety reached
+ NORMAL = 3; //safety is off
+}
+
+/**
+ * Enumeration used as bitfields wih permission field
+ */
+enum Permission {
+ NO_PERMISSION = 0;
+ READ_PERMISSION = 1; //refers to a user's capability to read the entity
+ UPDATE_PERMISSION = 2;//refers to a user's capability to write or modify the entity
+ DELETE_PERMISSION = 4; //refers to a user's capability to delete the entity
+}
+
+/**
+ * list of notification types
+ */
+enum NotificationType {
+ UNSPECIFIED_NOTIFICATION_TYPE = 0;
+ THRESHOLD = 1;
+ FIX_RATE = 2;
+ EVENT = 3; //Event type. Only this one is supported for now
+}
+
+/**
+ * list of units used throughout API methods
+ */
+enum Unit {
+ UNSPECIFIED_UNIT = 0;
+ CELSIUS = 1;
+ AMPERE = 2;
+ VOLT = 3;
+ METER_PER_SECOND = 4;
+ DEGREE_PER_SECOND = 5;
+ METER_PER_SECOND_2 = 6;
+ DEGREE_PER_SECOND_2 = 7;
+ NEWTON = 8;
+ NEWTON_METER =9;
+ KILOGRAM = 10;
+ DEGREE = 11;
+ TICK = 12;
+ DEGREE_PER_MILLISECOND = 13;
+}
+
+/**
+ * Message used when no information needs to be exchanged between client application and robot, and vice versa
+ */
+message Empty {
+}
+
+/**
+ * Notification options
+ */
+message NotificationOptions {
+ NotificationType type = 1; //type of notification
+ uint32 rate_m_sec = 2;
+ float threshold_value = 3;
+}
+
+/**
+ * Handle to a safety
+ */
+message SafetyHandle {
+ uint32 identifier = 1;
+}
+
+/**
+ * Handle to a notification
+ */
+message NotificationHandle {
+ uint32 identifier = 1;
+}
+
+/**
+ * Message that contains a Safety event
+ */
+message SafetyNotification {
+ SafetyHandle safety_handle = 1; //safety handle
+ SafetyStatusValue value = 2; //new safety status
+ Timestamp timestamp = 3; //event timestamp
+ UserProfileHandle user_handle = 4; //user that caused the safety event
+ Connection connection = 5; // connection that caused the safety event
+}
+
+/**
+ * Timestamp based on epoch
+ */
+message Timestamp {
+ uint32 sec = 1; //epoch in seconds since 1970
+ uint32 usec = 2;//microseconds after the second (0-999999)
+}
+
+/**
+ * Handle to an existing User Profile.
+ */
+message UserProfileHandle {
+ uint32 identifier = 1; //User profile identifier
+ fixed32 permission = 2; //must use 'Permission' as bitwise
+}
+
+message Connection {
+ UserProfileHandle user_handle = 1; //user profile handle, or set to zero if no user logged in
+ string connection_information = 2; //connection info (ex. IP address with port number)
+ uint32 connection_identifier = 3; //connection identifier
+}
+
+enum ArmState
+{
+ UNSPECIFIED_ARM_STATE = 0;
+ BASE_INITIALIZATION = 1; // Cannot be reported as the Base initialization must be completed before allowing user connection
+ IDLE = 2;
+ ARM_INITIALIZATION = 3;
+ ARM_IN_FAULT = 4;
+ ARM_MAINTENANCE = 5;
+ ARM_SERVOING_LOW_LEVEL = 6;
+ ARM_SERVOING_READY = 7;
+ ARM_SERVOING_PLAYING_SEQUENCE = 8;
+ ARM_SERVOING_MANUALLY_CONTROLLED = 9;
+ RESERVED = 255; // For debugging, this state must never be reported outside the base. this means that a state is not mapped correctly
+}
\ No newline at end of file
diff --git a/kortex_actuator_driver/readme.md b/kortex_actuator_driver/readme.md
new file mode 100644
index 00000000..8b503711
--- /dev/null
+++ b/kortex_actuator_driver/readme.md
@@ -0,0 +1,121 @@
+
+
+# Kortex actuator driver
+This package is a node that interfaces with a single actuator.
+
+
+
+1. [Content](#content)
+ 1. [build](#build)
+ 1. [msg](#msg)
+ 1. [non_generated](#non_generated)
+ 1. [protos](#protos)
+ 1. [src](#src)
+ 1. [srv](#srv)
+ 1. [non_generated](#non_generated-1)
+ 1. [templates](#templates)
+1. [How to start the node](#how-to-start-the-node)
+ 1. [Normal mode](#normal-mode)
+ 1. [Using the device routing feature](#using-the-device-routing-feature)
+1. [Generation](#generation)
+
+
+
+
+## Content
+
+### build
+This folder's only purpose is to exist as a temp folder during the generation. It should not be used.
+
+### msg
+This folder contains every custom messages used by the node **kortex\_actuator\_driver**. All the .msg files in this folder are generated by a custom protoc plugin described in the [Generation](#generation) section.
+
+#### non_generated
+This folder contains all the non-generated .msg files used by the node **kortex\_actuator\_driver**.
+
+| MSG | Description |
+|:---:|:---:|
+| ApiOptions.msg | A set of option that is supported by the Kortex API. It is used with the service SetApiOptions. For now there is only one option called tiemout_ms and it lets the user set a timeout value on every next service call. |
+| KortexError.msg | Describe the topic /KortexError. Every service call of the node kortex_actuator_driver will publish in /KortexError everytime the Kortex API returns an error. |
+
+
+### protos
+This folder contains the protobuf files from where the MSG, SRV and sources files are generated. The content of this folder should not be modified.
+
+### src
+This folder contains all the generated source files needed to build the node. The content of this folder should not be modified.
+
+### srv
+This folder contains every custom services used by the node **kortex\_actuator\_driver**. All the .srv files in this folder are generated by a custom protoc plugin described in the [Generation](#generation) section.
+
+#### non_generated
+This folder contains all the non-generated .srv files used by the node **kortex\_actuator\_driver**.
+
+| SRV | Description |
+|:---:|:---:|
+| SetApiOptions.srv | It modify the api options of the Kortex API. Once this service is called, the options set will affect every future call to the node. |
+| SetDeviceID.srv | It modify the target device (device routing feature) of the node. The default value is 0.|
+
+
+### templates
+This folder contains all the JINJA2 files needed by the protoc generator. For more details on the generation process, see the [Generation](#generation) section.
+
+| JINJA2 files | Description |
+|:---:|:---:|
+| main.jinja2 | Use to generate src/main.cpp |
+| NodeServices.cpp.jinja2 | Use to generate src/node.cpp |
+| NodeServices.h.jinja2 | Use to generate src/node.h |
+| proto_converterCPP.jinja2 | Use to generate every src/*_proto\_converter.cpp files |
+| proto_converterHeader.jinja2 | Use to generate every src/*_proto\_converter.h files |
+| ros_converterCPP.jinja2 | Use to generate every src/*_ros\_converter.cpp files |
+| ros_converterHeader.jinja2 | Use to generate every src/*_proto\_converter.h files |
+| ros_enum.jinja2 | Use to generate every msg/*.msg files that represent a protobuf enum |
+| ros_message.jinja2 | Use to generate every msg/*.msg files that represent a protobuf message |
+| ros_oneof.jinja2 | Use to generate every msg/*.msg files that represent a protobuf oneof |
+| ros_service.jinja2 | Use to generate every msg/*.msg files that represent a protobuf RPC |
+
+
+## How to start the node
+
+### Normal mode
+Use this mode if you are directly (there is an ethernet cable between your computer and an actuator) connected to an actuator. To be clear, if you are using the WIFI or your cable is connected in the robot's base, don't use this mode.
+
+rosrun kortex\_actuator\_driver kortex\_actuator\_driver 192.168.1.10 100
+
+In the command above, you would be running the kortex_actuator_driver node on an actuator with an IP address of 192.168.1.10. The cyclic data would be refreshed at 100 Hz.
+
+
+### Using the device routing feature
+Use this mode if your are connected via WIFI are directly in the robot's base and you want to have access to an actuator's interface.
+
+rosrun kortex\_actuator\_driver kortex\_actuator\_driver 192.168.1.10 100 4
+
+In the command above, you would be running the kortex_actuator_driver node using the device routing feature on an robot's base with an IP address of 192.168.1.10. The cyclic data would be refreshed at 100 Hz and the actuator's device ID is 4.
+
+
+## Generation
+
+The generation process is based on a custom protobuf plugin. Basically, most of the generation process is in the python file RosGeneration.py located at the package's root folder. Before launching the generation make sure you have the python module Jinja2 installed on your computer.
+
+
+To launch the generation of this package:
+
+1. Open a terminal window.
+1. Browse the root of this package [YOUR\_ROS\_WORKSPACE]/src/ros\_kortex/kortex\_actuator\_driver/
+1. Make sure that the file kortex_actuator_driver.sh can be executed. If not then chmod +x kortex_actuator_driver.sh
+1. Run this command: protoc --plugin=protoc-gen-custom=kortex_actuator_driver.sh -I./protos/ --custom_out=./build ./protos/\*.prot
+1. The result of the generation should be on thos folder:
+ * /src
+ * /msg
+ * /srv
+
diff --git a/kortex_actuator_driver/src/actuatorconfig_proto_converter.cpp b/kortex_actuator_driver/src/actuatorconfig_proto_converter.cpp
new file mode 100644
index 00000000..1c7a4f74
--- /dev/null
+++ b/kortex_actuator_driver/src/actuatorconfig_proto_converter.cpp
@@ -0,0 +1,172 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "actuatorconfig_proto_converter.h"
+
+#include "common_proto_converter.h"
+
+
+int ToProtoData(kortex_actuator_driver::AxisPosition input, AxisPosition *output)
+{
+ output->set_position(input.position);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::AxisOffsets input, AxisOffsets *output)
+{
+ output->set_absolute_offset(input.absolute_offset);
+ output->set_relative_offset(input.relative_offset);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::TorqueCalibration input, TorqueCalibration *output)
+{
+ output->set_global_gain(input.global_gain);
+ output->set_global_offset(input.global_offset);
+ output->clear_gain();
+ for(int i = 0; i < input.gain.size(); i++)
+ {
+ output->add_gain(input.gain[i]);
+ }
+
+ output->clear_offset();
+ for(int i = 0; i < input.offset.size(); i++)
+ {
+ output->add_offset(input.offset[i]);
+ }
+
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::TorqueOffset input, TorqueOffset *output)
+{
+ output->set_torque_offset(input.torque_offset);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::ControlModeInformation input, ControlModeInformation *output)
+{
+ output->set_control_mode((Kinova::Api::ActuatorConfig::ControlMode)input.control_mode);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::ControlLoop input, ControlLoop *output)
+{
+ output->set_control_loop(input.control_loop);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::LoopSelection input, LoopSelection *output)
+{
+ output->set_loop_selection((Kinova::Api::ActuatorConfig::ControlLoopSelection)input.loop_selection);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::VectorDriveParameters input, VectorDriveParameters *output)
+{
+ output->set_kpq(input.kpq);
+ output->set_kiq(input.kiq);
+ output->set_kpd(input.kpd);
+ output->set_kid(input.kid);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::EncoderDerivativeParameters input, EncoderDerivativeParameters *output)
+{
+ output->set_max_window_width(input.max_window_width);
+ output->set_min_encoder_tick_count(input.min_encoder_tick_count);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::ControlLoopParameters input, ControlLoopParameters *output)
+{
+ output->set_loop_selection((Kinova::Api::ActuatorConfig::ControlLoopSelection)input.loop_selection);
+ output->set_error_saturation(input.error_saturation);
+ output->set_output_saturation(input.output_saturation);
+ output->clear_kaz();
+ for(int i = 0; i < input.kAz.size(); i++)
+ {
+ output->add_kaz(input.kAz[i]);
+ }
+
+ output->clear_kbz();
+ for(int i = 0; i < input.kBz.size(); i++)
+ {
+ output->add_kbz(input.kBz[i]);
+ }
+
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::FrequencyResponse input, FrequencyResponse *output)
+{
+ output->set_loop_selection((Kinova::Api::ActuatorConfig::ControlLoopSelection)input.loop_selection);
+ output->set_min_frequency(input.min_frequency);
+ output->set_max_frequency(input.max_frequency);
+ output->set_amplitude(input.amplitude);
+ output->set_duration(input.duration);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::StepResponse input, StepResponse *output)
+{
+ output->set_loop_selection((Kinova::Api::ActuatorConfig::ControlLoopSelection)input.loop_selection);
+ output->set_amplitude(input.amplitude);
+ output->set_step_delay(input.step_delay);
+ output->set_duration(input.duration);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::RampResponse input, RampResponse *output)
+{
+ output->set_loop_selection((Kinova::Api::ActuatorConfig::ControlLoopSelection)input.loop_selection);
+ output->set_slope(input.slope);
+ output->set_ramp_delay(input.ramp_delay);
+ output->set_duration(input.duration);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::CustomDataSelection input, CustomDataSelection *output)
+{
+ output->clear_channel();
+ for(int i = 0; i < input.channel.size(); i++)
+ {
+ output->add_channel(input.channel[i]);
+ }
+
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::CommandModeInformation input, CommandModeInformation *output)
+{
+ output->set_command_mode((Kinova::Api::ActuatorConfig::CommandMode)input.command_mode);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::Servoing input, Servoing *output)
+{
+ output->set_enabled(input.enabled);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::PositionCommand input, PositionCommand *output)
+{
+ output->set_position(input.position);
+ output->set_velocity(input.velocity);
+ output->set_acceleration(input.acceleration);
+
+ return 0;
+}
diff --git a/kortex_actuator_driver/src/actuatorconfig_proto_converter.h b/kortex_actuator_driver/src/actuatorconfig_proto_converter.h
new file mode 100644
index 00000000..78ffe9f7
--- /dev/null
+++ b/kortex_actuator_driver/src/actuatorconfig_proto_converter.h
@@ -0,0 +1,82 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_ActuatorConfigPROTO_CONVERTER_H_
+#define _KORTEX_ActuatorConfigPROTO_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "kortex_actuator_driver/AxisPosition.h"
+#include "kortex_actuator_driver/AxisOffsets.h"
+#include "kortex_actuator_driver/TorqueCalibration.h"
+#include "kortex_actuator_driver/TorqueOffset.h"
+#include "kortex_actuator_driver/ControlModeInformation.h"
+#include "kortex_actuator_driver/ControlLoop.h"
+#include "kortex_actuator_driver/LoopSelection.h"
+#include "kortex_actuator_driver/VectorDriveParameters.h"
+#include "kortex_actuator_driver/EncoderDerivativeParameters.h"
+#include "kortex_actuator_driver/ControlLoopParameters.h"
+#include "kortex_actuator_driver/FrequencyResponse.h"
+#include "kortex_actuator_driver/StepResponse.h"
+#include "kortex_actuator_driver/RampResponse.h"
+#include "kortex_actuator_driver/CustomDataSelection.h"
+#include "kortex_actuator_driver/CommandModeInformation.h"
+#include "kortex_actuator_driver/Servoing.h"
+#include "kortex_actuator_driver/PositionCommand.h"
+
+
+using namespace Kinova::Api::ActuatorConfig;
+
+int ToProtoData(kortex_actuator_driver::AxisPosition intput, AxisPosition *output);
+int ToProtoData(kortex_actuator_driver::AxisOffsets intput, AxisOffsets *output);
+int ToProtoData(kortex_actuator_driver::TorqueCalibration intput, TorqueCalibration *output);
+int ToProtoData(kortex_actuator_driver::TorqueOffset intput, TorqueOffset *output);
+int ToProtoData(kortex_actuator_driver::ControlModeInformation intput, ControlModeInformation *output);
+int ToProtoData(kortex_actuator_driver::ControlLoop intput, ControlLoop *output);
+int ToProtoData(kortex_actuator_driver::LoopSelection intput, LoopSelection *output);
+int ToProtoData(kortex_actuator_driver::VectorDriveParameters intput, VectorDriveParameters *output);
+int ToProtoData(kortex_actuator_driver::EncoderDerivativeParameters intput, EncoderDerivativeParameters *output);
+int ToProtoData(kortex_actuator_driver::ControlLoopParameters intput, ControlLoopParameters *output);
+int ToProtoData(kortex_actuator_driver::FrequencyResponse intput, FrequencyResponse *output);
+int ToProtoData(kortex_actuator_driver::StepResponse intput, StepResponse *output);
+int ToProtoData(kortex_actuator_driver::RampResponse intput, RampResponse *output);
+int ToProtoData(kortex_actuator_driver::CustomDataSelection intput, CustomDataSelection *output);
+int ToProtoData(kortex_actuator_driver::CommandModeInformation intput, CommandModeInformation *output);
+int ToProtoData(kortex_actuator_driver::Servoing intput, Servoing *output);
+int ToProtoData(kortex_actuator_driver::PositionCommand intput, PositionCommand *output);
+
+#endif
\ No newline at end of file
diff --git a/kortex_actuator_driver/src/actuatorconfig_ros_converter.cpp b/kortex_actuator_driver/src/actuatorconfig_ros_converter.cpp
new file mode 100644
index 00000000..f9c7698e
--- /dev/null
+++ b/kortex_actuator_driver/src/actuatorconfig_ros_converter.cpp
@@ -0,0 +1,172 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "actuatorconfig_ros_converter.h"
+
+#include "common_ros_converter.h"
+
+
+int ToRosData(AxisPosition input, kortex_actuator_driver::AxisPosition &output)
+{
+ output.position = input.position();
+
+ return 0;
+}
+int ToRosData(AxisOffsets input, kortex_actuator_driver::AxisOffsets &output)
+{
+ output.absolute_offset = input.absolute_offset();
+ output.relative_offset = input.relative_offset();
+
+ return 0;
+}
+int ToRosData(TorqueCalibration input, kortex_actuator_driver::TorqueCalibration &output)
+{
+ output.global_gain = input.global_gain();
+ output.global_offset = input.global_offset();
+
+ output.gain.clear();
+ for(int i = 0; i < input.gain_size(); i++)
+ {
+ output.gain.push_back(input.gain(i));
+ }
+
+ output.offset.clear();
+ for(int i = 0; i < input.offset_size(); i++)
+ {
+ output.offset.push_back(input.offset(i));
+ }
+
+ return 0;
+}
+int ToRosData(TorqueOffset input, kortex_actuator_driver::TorqueOffset &output)
+{
+ output.torque_offset = input.torque_offset();
+
+ return 0;
+}
+int ToRosData(ControlModeInformation input, kortex_actuator_driver::ControlModeInformation &output)
+{
+ output.control_mode = input.control_mode();
+
+ return 0;
+}
+int ToRosData(ControlLoop input, kortex_actuator_driver::ControlLoop &output)
+{
+ output.control_loop = input.control_loop();
+
+ return 0;
+}
+int ToRosData(LoopSelection input, kortex_actuator_driver::LoopSelection &output)
+{
+ output.loop_selection = input.loop_selection();
+
+ return 0;
+}
+int ToRosData(VectorDriveParameters input, kortex_actuator_driver::VectorDriveParameters &output)
+{
+ output.kpq = input.kpq();
+ output.kiq = input.kiq();
+ output.kpd = input.kpd();
+ output.kid = input.kid();
+
+ return 0;
+}
+int ToRosData(EncoderDerivativeParameters input, kortex_actuator_driver::EncoderDerivativeParameters &output)
+{
+ output.max_window_width = input.max_window_width();
+ output.min_encoder_tick_count = input.min_encoder_tick_count();
+
+ return 0;
+}
+int ToRosData(ControlLoopParameters input, kortex_actuator_driver::ControlLoopParameters &output)
+{
+ output.loop_selection = input.loop_selection();
+ output.error_saturation = input.error_saturation();
+ output.output_saturation = input.output_saturation();
+
+ output.kAz.clear();
+ for(int i = 0; i < input.kaz_size(); i++)
+ {
+ output.kAz.push_back(input.kaz(i));
+ }
+
+ output.kBz.clear();
+ for(int i = 0; i < input.kbz_size(); i++)
+ {
+ output.kBz.push_back(input.kbz(i));
+ }
+
+ return 0;
+}
+int ToRosData(FrequencyResponse input, kortex_actuator_driver::FrequencyResponse &output)
+{
+ output.loop_selection = input.loop_selection();
+ output.min_frequency = input.min_frequency();
+ output.max_frequency = input.max_frequency();
+ output.amplitude = input.amplitude();
+ output.duration = input.duration();
+
+ return 0;
+}
+int ToRosData(StepResponse input, kortex_actuator_driver::StepResponse &output)
+{
+ output.loop_selection = input.loop_selection();
+ output.amplitude = input.amplitude();
+ output.step_delay = input.step_delay();
+ output.duration = input.duration();
+
+ return 0;
+}
+int ToRosData(RampResponse input, kortex_actuator_driver::RampResponse &output)
+{
+ output.loop_selection = input.loop_selection();
+ output.slope = input.slope();
+ output.ramp_delay = input.ramp_delay();
+ output.duration = input.duration();
+
+ return 0;
+}
+int ToRosData(CustomDataSelection input, kortex_actuator_driver::CustomDataSelection &output)
+{
+
+ output.channel.clear();
+ for(int i = 0; i < input.channel_size(); i++)
+ {
+ output.channel.push_back(input.channel(i));
+ }
+
+ return 0;
+}
+int ToRosData(CommandModeInformation input, kortex_actuator_driver::CommandModeInformation &output)
+{
+ output.command_mode = input.command_mode();
+
+ return 0;
+}
+int ToRosData(Servoing input, kortex_actuator_driver::Servoing &output)
+{
+ output.enabled = input.enabled();
+
+ return 0;
+}
+int ToRosData(PositionCommand input, kortex_actuator_driver::PositionCommand &output)
+{
+ output.position = input.position();
+ output.velocity = input.velocity();
+ output.acceleration = input.acceleration();
+
+ return 0;
+}
diff --git a/kortex_actuator_driver/src/actuatorconfig_ros_converter.h b/kortex_actuator_driver/src/actuatorconfig_ros_converter.h
new file mode 100644
index 00000000..39f37707
--- /dev/null
+++ b/kortex_actuator_driver/src/actuatorconfig_ros_converter.h
@@ -0,0 +1,82 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_ActuatorConfigROS_CONVERTER_H_
+#define _KORTEX_ActuatorConfigROS_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "kortex_actuator_driver/AxisPosition.h"
+#include "kortex_actuator_driver/AxisOffsets.h"
+#include "kortex_actuator_driver/TorqueCalibration.h"
+#include "kortex_actuator_driver/TorqueOffset.h"
+#include "kortex_actuator_driver/ControlModeInformation.h"
+#include "kortex_actuator_driver/ControlLoop.h"
+#include "kortex_actuator_driver/LoopSelection.h"
+#include "kortex_actuator_driver/VectorDriveParameters.h"
+#include "kortex_actuator_driver/EncoderDerivativeParameters.h"
+#include "kortex_actuator_driver/ControlLoopParameters.h"
+#include "kortex_actuator_driver/FrequencyResponse.h"
+#include "kortex_actuator_driver/StepResponse.h"
+#include "kortex_actuator_driver/RampResponse.h"
+#include "kortex_actuator_driver/CustomDataSelection.h"
+#include "kortex_actuator_driver/CommandModeInformation.h"
+#include "kortex_actuator_driver/Servoing.h"
+#include "kortex_actuator_driver/PositionCommand.h"
+
+
+using namespace Kinova::Api::ActuatorConfig;
+
+int ToRosData(AxisPosition input, kortex_actuator_driver::AxisPosition &output);
+int ToRosData(AxisOffsets input, kortex_actuator_driver::AxisOffsets &output);
+int ToRosData(TorqueCalibration input, kortex_actuator_driver::TorqueCalibration &output);
+int ToRosData(TorqueOffset input, kortex_actuator_driver::TorqueOffset &output);
+int ToRosData(ControlModeInformation input, kortex_actuator_driver::ControlModeInformation &output);
+int ToRosData(ControlLoop input, kortex_actuator_driver::ControlLoop &output);
+int ToRosData(LoopSelection input, kortex_actuator_driver::LoopSelection &output);
+int ToRosData(VectorDriveParameters input, kortex_actuator_driver::VectorDriveParameters &output);
+int ToRosData(EncoderDerivativeParameters input, kortex_actuator_driver::EncoderDerivativeParameters &output);
+int ToRosData(ControlLoopParameters input, kortex_actuator_driver::ControlLoopParameters &output);
+int ToRosData(FrequencyResponse input, kortex_actuator_driver::FrequencyResponse &output);
+int ToRosData(StepResponse input, kortex_actuator_driver::StepResponse &output);
+int ToRosData(RampResponse input, kortex_actuator_driver::RampResponse &output);
+int ToRosData(CustomDataSelection input, kortex_actuator_driver::CustomDataSelection &output);
+int ToRosData(CommandModeInformation input, kortex_actuator_driver::CommandModeInformation &output);
+int ToRosData(Servoing input, kortex_actuator_driver::Servoing &output);
+int ToRosData(PositionCommand input, kortex_actuator_driver::PositionCommand &output);
+
+#endif
\ No newline at end of file
diff --git a/kortex_actuator_driver/src/actuatorcyclic_proto_converter.cpp b/kortex_actuator_driver/src/actuatorcyclic_proto_converter.cpp
new file mode 100644
index 00000000..dbf2601d
--- /dev/null
+++ b/kortex_actuator_driver/src/actuatorcyclic_proto_converter.cpp
@@ -0,0 +1,79 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "actuatorcyclic_proto_converter.h"
+
+#include "common_proto_converter.h"
+
+
+int ToProtoData(kortex_actuator_driver::MessageId input, MessageId *output)
+{
+ output->set_identifier(input.identifier);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::Command input, Command *output)
+{
+ ToProtoData(input.command_id, output->mutable_command_id());
+ output->set_flags(input.flags);
+ output->set_position(input.position);
+ output->set_velocity(input.velocity);
+ output->set_torque_joint(input.torque_joint);
+ output->set_current_motor(input.current_motor);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::Feedback input, Feedback *output)
+{
+ ToProtoData(input.feedback_id, output->mutable_feedback_id());
+ output->set_status_flags(input.status_flags);
+ output->set_jitter_comm(input.jitter_comm);
+ output->set_position(input.position);
+ output->set_velocity(input.velocity);
+ output->set_torque(input.torque);
+ output->set_current_motor(input.current_motor);
+ output->set_voltage(input.voltage);
+ output->set_temperature_motor(input.temperature_motor);
+ output->set_temperature_core(input.temperature_core);
+ output->set_fault_bank_a(input.fault_bank_a);
+ output->set_fault_bank_b(input.fault_bank_b);
+ output->set_warning_bank_a(input.warning_bank_a);
+ output->set_warning_bank_b(input.warning_bank_b);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::CustomData input, CustomData *output)
+{
+ ToProtoData(input.custom_data_id, output->mutable_custom_data_id());
+ output->set_custom_data_0(input.custom_data_0);
+ output->set_custom_data_1(input.custom_data_1);
+ output->set_custom_data_2(input.custom_data_2);
+ output->set_custom_data_3(input.custom_data_3);
+ output->set_custom_data_4(input.custom_data_4);
+ output->set_custom_data_5(input.custom_data_5);
+ output->set_custom_data_6(input.custom_data_6);
+ output->set_custom_data_7(input.custom_data_7);
+ output->set_custom_data_8(input.custom_data_8);
+ output->set_custom_data_9(input.custom_data_9);
+ output->set_custom_data_10(input.custom_data_10);
+ output->set_custom_data_11(input.custom_data_11);
+ output->set_custom_data_12(input.custom_data_12);
+ output->set_custom_data_13(input.custom_data_13);
+ output->set_custom_data_14(input.custom_data_14);
+ output->set_custom_data_15(input.custom_data_15);
+
+ return 0;
+}
diff --git a/kortex_actuator_driver/src/actuatorcyclic_proto_converter.h b/kortex_actuator_driver/src/actuatorcyclic_proto_converter.h
new file mode 100644
index 00000000..ca58ab6f
--- /dev/null
+++ b/kortex_actuator_driver/src/actuatorcyclic_proto_converter.h
@@ -0,0 +1,56 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_ActuatorCyclicPROTO_CONVERTER_H_
+#define _KORTEX_ActuatorCyclicPROTO_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "kortex_actuator_driver/MessageId.h"
+#include "kortex_actuator_driver/Command.h"
+#include "kortex_actuator_driver/Feedback.h"
+#include "kortex_actuator_driver/CustomData.h"
+
+
+using namespace Kinova::Api::ActuatorCyclic;
+
+int ToProtoData(kortex_actuator_driver::MessageId intput, MessageId *output);
+int ToProtoData(kortex_actuator_driver::Command intput, Command *output);
+int ToProtoData(kortex_actuator_driver::Feedback intput, Feedback *output);
+int ToProtoData(kortex_actuator_driver::CustomData intput, CustomData *output);
+
+#endif
\ No newline at end of file
diff --git a/kortex_actuator_driver/src/actuatorcyclic_ros_converter.cpp b/kortex_actuator_driver/src/actuatorcyclic_ros_converter.cpp
new file mode 100644
index 00000000..94228493
--- /dev/null
+++ b/kortex_actuator_driver/src/actuatorcyclic_ros_converter.cpp
@@ -0,0 +1,79 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "actuatorcyclic_ros_converter.h"
+
+#include "common_ros_converter.h"
+
+
+int ToRosData(MessageId input, kortex_actuator_driver::MessageId &output)
+{
+ output.identifier = input.identifier();
+
+ return 0;
+}
+int ToRosData(Command input, kortex_actuator_driver::Command &output)
+{
+ ToRosData(input.command_id(), output.command_id);
+ output.flags = input.flags();
+ output.position = input.position();
+ output.velocity = input.velocity();
+ output.torque_joint = input.torque_joint();
+ output.current_motor = input.current_motor();
+
+ return 0;
+}
+int ToRosData(Feedback input, kortex_actuator_driver::Feedback &output)
+{
+ ToRosData(input.feedback_id(), output.feedback_id);
+ output.status_flags = input.status_flags();
+ output.jitter_comm = input.jitter_comm();
+ output.position = input.position();
+ output.velocity = input.velocity();
+ output.torque = input.torque();
+ output.current_motor = input.current_motor();
+ output.voltage = input.voltage();
+ output.temperature_motor = input.temperature_motor();
+ output.temperature_core = input.temperature_core();
+ output.fault_bank_a = input.fault_bank_a();
+ output.fault_bank_b = input.fault_bank_b();
+ output.warning_bank_a = input.warning_bank_a();
+ output.warning_bank_b = input.warning_bank_b();
+
+ return 0;
+}
+int ToRosData(CustomData input, kortex_actuator_driver::CustomData &output)
+{
+ ToRosData(input.custom_data_id(), output.custom_data_id);
+ output.custom_data_0 = input.custom_data_0();
+ output.custom_data_1 = input.custom_data_1();
+ output.custom_data_2 = input.custom_data_2();
+ output.custom_data_3 = input.custom_data_3();
+ output.custom_data_4 = input.custom_data_4();
+ output.custom_data_5 = input.custom_data_5();
+ output.custom_data_6 = input.custom_data_6();
+ output.custom_data_7 = input.custom_data_7();
+ output.custom_data_8 = input.custom_data_8();
+ output.custom_data_9 = input.custom_data_9();
+ output.custom_data_10 = input.custom_data_10();
+ output.custom_data_11 = input.custom_data_11();
+ output.custom_data_12 = input.custom_data_12();
+ output.custom_data_13 = input.custom_data_13();
+ output.custom_data_14 = input.custom_data_14();
+ output.custom_data_15 = input.custom_data_15();
+
+ return 0;
+}
diff --git a/kortex_actuator_driver/src/actuatorcyclic_ros_converter.h b/kortex_actuator_driver/src/actuatorcyclic_ros_converter.h
new file mode 100644
index 00000000..b96bb569
--- /dev/null
+++ b/kortex_actuator_driver/src/actuatorcyclic_ros_converter.h
@@ -0,0 +1,56 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_ActuatorCyclicROS_CONVERTER_H_
+#define _KORTEX_ActuatorCyclicROS_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "kortex_actuator_driver/MessageId.h"
+#include "kortex_actuator_driver/Command.h"
+#include "kortex_actuator_driver/Feedback.h"
+#include "kortex_actuator_driver/CustomData.h"
+
+
+using namespace Kinova::Api::ActuatorCyclic;
+
+int ToRosData(MessageId input, kortex_actuator_driver::MessageId &output);
+int ToRosData(Command input, kortex_actuator_driver::Command &output);
+int ToRosData(Feedback input, kortex_actuator_driver::Feedback &output);
+int ToRosData(CustomData input, kortex_actuator_driver::CustomData &output);
+
+#endif
\ No newline at end of file
diff --git a/kortex_actuator_driver/src/common_proto_converter.cpp b/kortex_actuator_driver/src/common_proto_converter.cpp
new file mode 100644
index 00000000..51241a2c
--- /dev/null
+++ b/kortex_actuator_driver/src/common_proto_converter.cpp
@@ -0,0 +1,84 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "common_proto_converter.h"
+
+
+int ToProtoData(kortex_actuator_driver::DeviceHandle input, DeviceHandle *output)
+{
+ output->set_device_type((Kinova::Api::Common::DeviceTypes)input.device_type);
+ output->set_device_identifier(input.device_identifier);
+ output->set_order(input.order);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::Empty input, Empty *output)
+{
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::NotificationOptions input, NotificationOptions *output)
+{
+ output->set_type((Kinova::Api::Common::NotificationType)input.type);
+ output->set_rate_m_sec(input.rate_m_sec);
+ output->set_threshold_value(input.threshold_value);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::SafetyHandle input, SafetyHandle *output)
+{
+ output->set_identifier(input.identifier);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::NotificationHandle input, NotificationHandle *output)
+{
+ output->set_identifier(input.identifier);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::SafetyNotification input, SafetyNotification *output)
+{
+ ToProtoData(input.safety_handle, output->mutable_safety_handle());
+ output->set_value((Kinova::Api::Common::SafetyStatusValue)input.value);
+ ToProtoData(input.timestamp, output->mutable_timestamp());
+ ToProtoData(input.user_handle, output->mutable_user_handle());
+ ToProtoData(input.connection, output->mutable_connection());
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::Timestamp input, Timestamp *output)
+{
+ output->set_sec(input.sec);
+ output->set_usec(input.usec);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::UserProfileHandle input, UserProfileHandle *output)
+{
+ output->set_identifier(input.identifier);
+ output->set_permission(input.permission);
+
+ return 0;
+}
+int ToProtoData(kortex_actuator_driver::Connection input, Connection *output)
+{
+ ToProtoData(input.user_handle, output->mutable_user_handle());
+ output->set_connection_information(input.connection_information);
+ output->set_connection_identifier(input.connection_identifier);
+
+ return 0;
+}
diff --git a/kortex_actuator_driver/src/common_proto_converter.h b/kortex_actuator_driver/src/common_proto_converter.h
new file mode 100644
index 00000000..4112a508
--- /dev/null
+++ b/kortex_actuator_driver/src/common_proto_converter.h
@@ -0,0 +1,66 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_CommonPROTO_CONVERTER_H_
+#define _KORTEX_CommonPROTO_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "kortex_actuator_driver/DeviceHandle.h"
+#include "kortex_actuator_driver/Empty.h"
+#include "kortex_actuator_driver/NotificationOptions.h"
+#include "kortex_actuator_driver/SafetyHandle.h"
+#include "kortex_actuator_driver/NotificationHandle.h"
+#include "kortex_actuator_driver/SafetyNotification.h"
+#include "kortex_actuator_driver/Timestamp.h"
+#include "kortex_actuator_driver/UserProfileHandle.h"
+#include "kortex_actuator_driver/Connection.h"
+
+
+using namespace Kinova::Api::Common;
+
+int ToProtoData(kortex_actuator_driver::DeviceHandle intput, DeviceHandle *output);
+int ToProtoData(kortex_actuator_driver::Empty intput, Empty *output);
+int ToProtoData(kortex_actuator_driver::NotificationOptions intput, NotificationOptions *output);
+int ToProtoData(kortex_actuator_driver::SafetyHandle intput, SafetyHandle *output);
+int ToProtoData(kortex_actuator_driver::NotificationHandle intput, NotificationHandle *output);
+int ToProtoData(kortex_actuator_driver::SafetyNotification intput, SafetyNotification *output);
+int ToProtoData(kortex_actuator_driver::Timestamp intput, Timestamp *output);
+int ToProtoData(kortex_actuator_driver::UserProfileHandle intput, UserProfileHandle *output);
+int ToProtoData(kortex_actuator_driver::Connection intput, Connection *output);
+
+#endif
\ No newline at end of file
diff --git a/kortex_actuator_driver/src/common_ros_converter.cpp b/kortex_actuator_driver/src/common_ros_converter.cpp
new file mode 100644
index 00000000..57946201
--- /dev/null
+++ b/kortex_actuator_driver/src/common_ros_converter.cpp
@@ -0,0 +1,84 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "common_ros_converter.h"
+
+
+int ToRosData(DeviceHandle input, kortex_actuator_driver::DeviceHandle &output)
+{
+ output.device_type = input.device_type();
+ output.device_identifier = input.device_identifier();
+ output.order = input.order();
+
+ return 0;
+}
+int ToRosData(Empty input, kortex_actuator_driver::Empty &output)
+{
+
+ return 0;
+}
+int ToRosData(NotificationOptions input, kortex_actuator_driver::NotificationOptions &output)
+{
+ output.type = input.type();
+ output.rate_m_sec = input.rate_m_sec();
+ output.threshold_value = input.threshold_value();
+
+ return 0;
+}
+int ToRosData(SafetyHandle input, kortex_actuator_driver::SafetyHandle &output)
+{
+ output.identifier = input.identifier();
+
+ return 0;
+}
+int ToRosData(NotificationHandle input, kortex_actuator_driver::NotificationHandle &output)
+{
+ output.identifier = input.identifier();
+
+ return 0;
+}
+int ToRosData(SafetyNotification input, kortex_actuator_driver::SafetyNotification &output)
+{
+ ToRosData(input.safety_handle(), output.safety_handle);
+ output.value = input.value();
+ ToRosData(input.timestamp(), output.timestamp);
+ ToRosData(input.user_handle(), output.user_handle);
+ ToRosData(input.connection(), output.connection);
+
+ return 0;
+}
+int ToRosData(Timestamp input, kortex_actuator_driver::Timestamp &output)
+{
+ output.sec = input.sec();
+ output.usec = input.usec();
+
+ return 0;
+}
+int ToRosData(UserProfileHandle input, kortex_actuator_driver::UserProfileHandle &output)
+{
+ output.identifier = input.identifier();
+ output.permission = input.permission();
+
+ return 0;
+}
+int ToRosData(Connection input, kortex_actuator_driver::Connection &output)
+{
+ ToRosData(input.user_handle(), output.user_handle);
+ output.connection_information = input.connection_information();
+ output.connection_identifier = input.connection_identifier();
+
+ return 0;
+}
diff --git a/kortex_actuator_driver/src/common_ros_converter.h b/kortex_actuator_driver/src/common_ros_converter.h
new file mode 100644
index 00000000..505d5764
--- /dev/null
+++ b/kortex_actuator_driver/src/common_ros_converter.h
@@ -0,0 +1,66 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_CommonROS_CONVERTER_H_
+#define _KORTEX_CommonROS_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "kortex_actuator_driver/DeviceHandle.h"
+#include "kortex_actuator_driver/Empty.h"
+#include "kortex_actuator_driver/NotificationOptions.h"
+#include "kortex_actuator_driver/SafetyHandle.h"
+#include "kortex_actuator_driver/NotificationHandle.h"
+#include "kortex_actuator_driver/SafetyNotification.h"
+#include "kortex_actuator_driver/Timestamp.h"
+#include "kortex_actuator_driver/UserProfileHandle.h"
+#include "kortex_actuator_driver/Connection.h"
+
+
+using namespace Kinova::Api::Common;
+
+int ToRosData(DeviceHandle input, kortex_actuator_driver::DeviceHandle &output);
+int ToRosData(Empty input, kortex_actuator_driver::Empty &output);
+int ToRosData(NotificationOptions input, kortex_actuator_driver::NotificationOptions &output);
+int ToRosData(SafetyHandle input, kortex_actuator_driver::SafetyHandle &output);
+int ToRosData(NotificationHandle input, kortex_actuator_driver::NotificationHandle &output);
+int ToRosData(SafetyNotification input, kortex_actuator_driver::SafetyNotification &output);
+int ToRosData(Timestamp input, kortex_actuator_driver::Timestamp &output);
+int ToRosData(UserProfileHandle input, kortex_actuator_driver::UserProfileHandle &output);
+int ToRosData(Connection input, kortex_actuator_driver::Connection &output);
+
+#endif
\ No newline at end of file
diff --git a/kortex_actuator_driver/src/main.cpp b/kortex_actuator_driver/src/main.cpp
new file mode 100644
index 00000000..ef974c06
--- /dev/null
+++ b/kortex_actuator_driver/src/main.cpp
@@ -0,0 +1,180 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "node.h"
+#include "math_util.h"
+
+#include
+#include
+
+int main(int argc, char **argv)
+{
+ ros::init(argc, argv, "Actuator_Services");
+
+ uint32_t cyclic_data_rate = 100;
+ uint32_t device_id = 0;
+
+ ros::NodeHandle n;
+ bool valid_ip = false;
+
+ if(argc > 3)
+ {
+ stringstream tempId;
+ tempId << argv[3];
+ tempId >> device_id;
+
+ if(tempId.fail() || tempId.bad())
+ {
+ ROS_INFO("ERROR - Bad device ID, shutting down the node...");
+ ros::shutdown();
+ return 0;
+ }
+ }
+ else if(argc > 2)
+ {
+ //Converting the second parameter(the cyclic rate) to an unsigned int variable.
+ stringstream tempRate;
+ tempRate << argv[2];
+ tempRate >> cyclic_data_rate;
+ if(tempRate.fail() || tempRate.bad())
+ {
+ ROS_INFO("ERROR - Bad error rate, shutting down the node...");
+ ros::shutdown();
+ return 0;
+ }
+ ROS_INFO("Connecting to IP = %s - node refresh rate = %s, device ID = %d", argv[1], argv[2], device_id);
+ }
+ else
+ {
+ ROS_INFO("You need to provide an IP adresse as the first parameter and optionnaly a second parameter to specify the cyclic \
+ rate and a third parameter(optionnal) to specify a device ID. ex: rosrun package node 127.0.0.1 100 4");
+ ros::shutdown();
+ return 0;
+ }
+
+ Actuator_Services services_object(argv[1], n, device_id);
+
+ ros::ServiceServer serviceSetDeviceID = n.advertiseService("SetDeviceID", &Actuator_Services::SetDeviceID, &services_object);
+ ros::ServiceServer serviceSetApiOptions = n.advertiseService("SetApiOptions", &Actuator_Services::SetApiOptions, &services_object);
+ ros::ServiceServer serviceSetCyclicStatus = n.advertiseService("SetCyclicStatus", &Actuator_Services::SetCyclicStatus, &services_object);
+ ros::ServiceServer serviceGetCyclicStatus = n.advertiseService("GetCyclicStatus", &Actuator_Services::GetCyclicStatus, &services_object);
+
+ ros::ServiceServer serviceGetAxisOffsets = n.advertiseService("GetAxisOffsets", &Actuator_Services::GetAxisOffsets, &services_object);
+ ros::ServiceServer serviceSetAxisOffsets = n.advertiseService("SetAxisOffsets", &Actuator_Services::SetAxisOffsets, &services_object);
+ ros::ServiceServer serviceReadTorqueCalibration = n.advertiseService("ReadTorqueCalibration", &Actuator_Services::ReadTorqueCalibration, &services_object);
+ ros::ServiceServer serviceWriteTorqueCalibration = n.advertiseService("WriteTorqueCalibration", &Actuator_Services::WriteTorqueCalibration, &services_object);
+ ros::ServiceServer serviceSetTorqueOffset = n.advertiseService("SetTorqueOffset", &Actuator_Services::SetTorqueOffset, &services_object);
+ ros::ServiceServer serviceGetControlMode = n.advertiseService("GetControlMode", &Actuator_Services::GetControlMode, &services_object);
+ ros::ServiceServer serviceSetControlMode = n.advertiseService("SetControlMode", &Actuator_Services::SetControlMode, &services_object);
+ ros::ServiceServer serviceGetActivatedControlLoop = n.advertiseService("GetActivatedControlLoop", &Actuator_Services::GetActivatedControlLoop, &services_object);
+ ros::ServiceServer serviceSetActivatedControlLoop = n.advertiseService("SetActivatedControlLoop", &Actuator_Services::SetActivatedControlLoop, &services_object);
+ ros::ServiceServer serviceGetVectorDriveParameters = n.advertiseService("GetVectorDriveParameters", &Actuator_Services::GetVectorDriveParameters, &services_object);
+ ros::ServiceServer serviceSetVectorDriveParameters = n.advertiseService("SetVectorDriveParameters", &Actuator_Services::SetVectorDriveParameters, &services_object);
+ ros::ServiceServer serviceGetEncoderDerivativeParameters = n.advertiseService("GetEncoderDerivativeParameters", &Actuator_Services::GetEncoderDerivativeParameters, &services_object);
+ ros::ServiceServer serviceSetEncoderDerivativeParameters = n.advertiseService("SetEncoderDerivativeParameters", &Actuator_Services::SetEncoderDerivativeParameters, &services_object);
+ ros::ServiceServer serviceGetControlLoopParameters = n.advertiseService("GetControlLoopParameters", &Actuator_Services::GetControlLoopParameters, &services_object);
+ ros::ServiceServer serviceSetControlLoopParameters = n.advertiseService("SetControlLoopParameters", &Actuator_Services::SetControlLoopParameters, &services_object);
+ ros::ServiceServer serviceStartFrequencyResponse = n.advertiseService("StartFrequencyResponse", &Actuator_Services::StartFrequencyResponse, &services_object);
+ ros::ServiceServer serviceStopFrequencyResponse = n.advertiseService("StopFrequencyResponse", &Actuator_Services::StopFrequencyResponse, &services_object);
+ ros::ServiceServer serviceStartStepResponse = n.advertiseService("StartStepResponse", &Actuator_Services::StartStepResponse, &services_object);
+ ros::ServiceServer serviceStopStepResponse = n.advertiseService("StopStepResponse", &Actuator_Services::StopStepResponse, &services_object);
+ ros::ServiceServer serviceStartRampResponse = n.advertiseService("StartRampResponse", &Actuator_Services::StartRampResponse, &services_object);
+ ros::ServiceServer serviceStopRampResponse = n.advertiseService("StopRampResponse", &Actuator_Services::StopRampResponse, &services_object);
+ ros::ServiceServer serviceSelectCustomData = n.advertiseService("SelectCustomData", &Actuator_Services::SelectCustomData, &services_object);
+ ros::ServiceServer serviceGetSelectedCustomData = n.advertiseService("GetSelectedCustomData", &Actuator_Services::GetSelectedCustomData, &services_object);
+ ros::ServiceServer serviceSetCommandMode = n.advertiseService("SetCommandMode", &Actuator_Services::SetCommandMode, &services_object);
+ ros::ServiceServer serviceClearFaults = n.advertiseService("ClearFaults", &Actuator_Services::ClearFaults, &services_object);
+ ros::ServiceServer serviceSetServoing = n.advertiseService("SetServoing", &Actuator_Services::SetServoing, &services_object);
+ ros::ServiceServer serviceMoveToPosition = n.advertiseService("MoveToPosition", &Actuator_Services::MoveToPosition, &services_object);
+ ros::ServiceServer serviceGetCommandMode = n.advertiseService("GetCommandMode", &Actuator_Services::GetCommandMode, &services_object);
+ ros::ServiceServer serviceGetServoing = n.advertiseService("GetServoing", &Actuator_Services::GetServoing, &services_object);
+ ros::ServiceServer serviceGetTorqueOffset = n.advertiseService("GetTorqueOffset", &Actuator_Services::GetTorqueOffset, &services_object);
+ ros::ServiceServer serviceRefresh = n.advertiseService("Refresh", &Actuator_Services::Refresh, &services_object);
+ ros::ServiceServer serviceRefreshCommand = n.advertiseService("RefreshCommand", &Actuator_Services::RefreshCommand, &services_object);
+ ros::ServiceServer serviceRefreshFeedback = n.advertiseService("RefreshFeedback", &Actuator_Services::RefreshFeedback, &services_object);
+ ros::ServiceServer serviceRefreshCustomData = n.advertiseService("RefreshCustomData", &Actuator_Services::RefreshCustomData, &services_object);
+
+
+ ROS_INFO("Node's services initialized correctly.");
+
+ ros::Publisher pub_feedback = n.advertise("actuator_feedback", 1000);
+ ros::Publisher pub_joint_state = n.advertise("actuator_feedback/joint_state", 1000);
+
+ kortex_actuator_driver::Feedback feedback;
+ kortex_actuator_driver::RefreshFeedback::Request req;
+ kortex_actuator_driver::RefreshFeedback::Response res;
+
+ sensor_msgs::JointState joint_state;
+
+ joint_state.position.resize(1);
+ joint_state.velocity.resize(1);
+ joint_state.effort.resize(1);
+ joint_state.name.resize(1);
+
+ ros::Rate rate(cyclic_data_rate); // 100 hz
+ while (!ros::isShuttingDown())
+ {
+ try
+ {
+ if(services_object.IsCyclicActive())
+ {
+ services_object.RefreshFeedback(req, res);
+
+ feedback.feedback_id = res.output.feedback_id;
+
+ feedback.status_flags = res.output.status_flags;
+ feedback.jitter_comm = res.output.jitter_comm;
+ feedback.position = res.output.position;
+ feedback.velocity = res.output.velocity;
+ feedback.torque = res.output.torque;
+ feedback.current_motor = res.output.current_motor;
+ feedback.voltage = res.output.voltage;
+ feedback.temperature_motor = res.output.temperature_motor;
+ feedback.temperature_core = res.output.temperature_core;
+ feedback.fault_bank_a = res.output.fault_bank_a;
+ feedback.fault_bank_b = res.output.fault_bank_b;
+ feedback.warning_bank_a = res.output.warning_bank_a;
+ feedback.warning_bank_b = res.output.warning_bank_b;
+
+ joint_state.header.stamp = ros::Time::now();
+ joint_state.header.frame_id = std::to_string(res.output.feedback_id.identifier);
+
+ joint_state.name[0] = "Actuator";
+ joint_state.position[0] = TO_RAD(res.output.position);
+ joint_state.velocity[0] = TO_RAD(res.output.velocity);
+ joint_state.effort[0] = res.output.torque;
+
+ pub_feedback.publish(feedback);
+ pub_joint_state.publish(joint_state);
+ }
+ }
+
+ catch (KDetailedException& ex)
+ {
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ }
+ catch (std::runtime_error& ex2)
+ {
+ ROS_INFO("RUN TIME ERROR: %s\n", ex2.what());
+ }
+
+ ros::spinOnce();
+
+ rate.sleep();
+ }
+
+ return 1;
+}
\ No newline at end of file
diff --git a/kortex_actuator_driver/src/node.cpp b/kortex_actuator_driver/src/node.cpp
new file mode 100644
index 00000000..1b542590
--- /dev/null
+++ b/kortex_actuator_driver/src/node.cpp
@@ -0,0 +1,1009 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "node.h"
+#include "common_ros_converter.h"
+#include "common_proto_converter.h"
+#include "actuatorconfig_ros_converter.h"
+#include "actuatorconfig_proto_converter.h"
+#include "actuatorcyclic_ros_converter.h"
+#include "actuatorcyclic_proto_converter.h"
+Actuator_Services::Actuator_Services(char* ip, ros::NodeHandle& n, uint32_t device_id) : m_n(n)
+{
+ m_transport = new TransportClientUdp();
+ m_transport->connect(ip, 10000);
+
+ m_router = new RouterClient(m_transport, [](KError err) { cout << "_________ callback error _________" << err.toString(); });
+ m_CurrentDeviceID = device_id;
+ m_apiOptions.timeout_ms = 3000;
+
+ m_actuatorconfig = new ActuatorConfig::ActuatorConfigClient(m_router);
+ m_actuatorcyclic = new ActuatorCyclic::ActuatorCyclicClient(m_router);//If the Device ID is different than 0, it means that we are using the feature DEVICE ROUTING.
+ if(m_CurrentDeviceID != 0)
+ {
+ m_SessionManager = new SessionManager(m_router);
+ auto createSessionInfo = Kinova::Api::Session::CreateSessionInfo();
+
+ createSessionInfo.set_username("admin");
+ createSessionInfo.set_password("admin");
+ createSessionInfo.set_session_inactivity_timeout(35000);
+
+ m_SessionManager->CreateSession(createSessionInfo);
+ }
+
+ m_pub_Error = m_n.advertise("KortexError", 1000);std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+}
+
+bool Actuator_Services::SetDeviceID(kortex_actuator_driver::SetDeviceID::Request &req, kortex_actuator_driver::SetDeviceID::Response &res)
+{
+ if(m_CurrentDeviceID == 0)
+ {
+ auto sessionManager = new SessionManager(m_router);
+ auto createSessionInfo = Kinova::Api::Session::CreateSessionInfo();
+
+ createSessionInfo.set_username("admin");
+ createSessionInfo.set_password("admin");
+ createSessionInfo.set_session_inactivity_timeout(35000);
+
+ sessionManager->CreateSession(createSessionInfo);
+ }
+
+ m_CurrentDeviceID = req.device_id;
+}
+
+bool Actuator_Services::SetApiOptions(kortex_actuator_driver::SetApiOptions::Request &req, kortex_actuator_driver::SetApiOptions::Response &res)
+{
+ m_apiOptions.timeout_ms = req.input.timeout_ms;
+
+ return true;
+}
+
+bool Actuator_Services::GetCyclicStatus(kortex_actuator_driver::GetCyclicStatus::Request &req, kortex_actuator_driver::GetCyclicStatus::Response &res)
+{
+ res.status.isActive = m_cyclicActive;
+}
+
+bool Actuator_Services::SetCyclicStatus(kortex_actuator_driver::SetCyclicStatus::Request &req, kortex_actuator_driver::SetCyclicStatus::Response &res)
+{
+ m_cyclicActive = req.status.isActive;
+}
+
+bool Actuator_Services::IsCyclicActive()
+{
+ return m_cyclicActive;
+}
+
+
+
+
+bool Actuator_Services::GetAxisOffsets(kortex_actuator_driver::GetAxisOffsets::Request &req, kortex_actuator_driver::GetAxisOffsets::Response &res)
+{
+ Empty input;
+ AxisOffsets output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorconfig->GetAxisOffsets(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+bool Actuator_Services::SetAxisOffsets(kortex_actuator_driver::SetAxisOffsets::Request &req, kortex_actuator_driver::SetAxisOffsets::Response &res)
+{
+ AxisPosition input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->SetAxisOffsets(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::ReadTorqueCalibration(kortex_actuator_driver::ReadTorqueCalibration::Request &req, kortex_actuator_driver::ReadTorqueCalibration::Response &res)
+{
+ Empty input;
+ TorqueCalibration output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorconfig->ReadTorqueCalibration(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+bool Actuator_Services::WriteTorqueCalibration(kortex_actuator_driver::WriteTorqueCalibration::Request &req, kortex_actuator_driver::WriteTorqueCalibration::Response &res)
+{
+ TorqueCalibration input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->WriteTorqueCalibration(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::SetTorqueOffset(kortex_actuator_driver::SetTorqueOffset::Request &req, kortex_actuator_driver::SetTorqueOffset::Response &res)
+{
+ TorqueOffset input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->SetTorqueOffset(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::GetControlMode(kortex_actuator_driver::GetControlMode::Request &req, kortex_actuator_driver::GetControlMode::Response &res)
+{
+ Empty input;
+ ControlModeInformation output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorconfig->GetControlMode(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+bool Actuator_Services::SetControlMode(kortex_actuator_driver::SetControlMode::Request &req, kortex_actuator_driver::SetControlMode::Response &res)
+{
+ ControlModeInformation input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->SetControlMode(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::GetActivatedControlLoop(kortex_actuator_driver::GetActivatedControlLoop::Request &req, kortex_actuator_driver::GetActivatedControlLoop::Response &res)
+{
+ Empty input;
+ ControlLoop output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorconfig->GetActivatedControlLoop(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+bool Actuator_Services::SetActivatedControlLoop(kortex_actuator_driver::SetActivatedControlLoop::Request &req, kortex_actuator_driver::SetActivatedControlLoop::Response &res)
+{
+ ControlLoop input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->SetActivatedControlLoop(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::GetVectorDriveParameters(kortex_actuator_driver::GetVectorDriveParameters::Request &req, kortex_actuator_driver::GetVectorDriveParameters::Response &res)
+{
+ Empty input;
+ VectorDriveParameters output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorconfig->GetVectorDriveParameters(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+bool Actuator_Services::SetVectorDriveParameters(kortex_actuator_driver::SetVectorDriveParameters::Request &req, kortex_actuator_driver::SetVectorDriveParameters::Response &res)
+{
+ VectorDriveParameters input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->SetVectorDriveParameters(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::GetEncoderDerivativeParameters(kortex_actuator_driver::GetEncoderDerivativeParameters::Request &req, kortex_actuator_driver::GetEncoderDerivativeParameters::Response &res)
+{
+ Empty input;
+ EncoderDerivativeParameters output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorconfig->GetEncoderDerivativeParameters(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+bool Actuator_Services::SetEncoderDerivativeParameters(kortex_actuator_driver::SetEncoderDerivativeParameters::Request &req, kortex_actuator_driver::SetEncoderDerivativeParameters::Response &res)
+{
+ EncoderDerivativeParameters input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->SetEncoderDerivativeParameters(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::GetControlLoopParameters(kortex_actuator_driver::GetControlLoopParameters::Request &req, kortex_actuator_driver::GetControlLoopParameters::Response &res)
+{
+ LoopSelection input;
+ ToProtoData(req.input, &input);
+ ControlLoopParameters output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorconfig->GetControlLoopParameters(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+bool Actuator_Services::SetControlLoopParameters(kortex_actuator_driver::SetControlLoopParameters::Request &req, kortex_actuator_driver::SetControlLoopParameters::Response &res)
+{
+ ControlLoopParameters input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->SetControlLoopParameters(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::StartFrequencyResponse(kortex_actuator_driver::StartFrequencyResponse::Request &req, kortex_actuator_driver::StartFrequencyResponse::Response &res)
+{
+ FrequencyResponse input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->StartFrequencyResponse(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::StopFrequencyResponse(kortex_actuator_driver::StopFrequencyResponse::Request &req, kortex_actuator_driver::StopFrequencyResponse::Response &res)
+{
+ Empty input;
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->StopFrequencyResponse(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::StartStepResponse(kortex_actuator_driver::StartStepResponse::Request &req, kortex_actuator_driver::StartStepResponse::Response &res)
+{
+ StepResponse input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->StartStepResponse(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::StopStepResponse(kortex_actuator_driver::StopStepResponse::Request &req, kortex_actuator_driver::StopStepResponse::Response &res)
+{
+ Empty input;
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->StopStepResponse(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::StartRampResponse(kortex_actuator_driver::StartRampResponse::Request &req, kortex_actuator_driver::StartRampResponse::Response &res)
+{
+ RampResponse input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->StartRampResponse(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::StopRampResponse(kortex_actuator_driver::StopRampResponse::Request &req, kortex_actuator_driver::StopRampResponse::Response &res)
+{
+ Empty input;
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->StopRampResponse(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::SelectCustomData(kortex_actuator_driver::SelectCustomData::Request &req, kortex_actuator_driver::SelectCustomData::Response &res)
+{
+ CustomDataSelection input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->SelectCustomData(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::GetSelectedCustomData(kortex_actuator_driver::GetSelectedCustomData::Request &req, kortex_actuator_driver::GetSelectedCustomData::Response &res)
+{
+ Empty input;
+ CustomDataSelection output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorconfig->GetSelectedCustomData(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+bool Actuator_Services::SetCommandMode(kortex_actuator_driver::SetCommandMode::Request &req, kortex_actuator_driver::SetCommandMode::Response &res)
+{
+ CommandModeInformation input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->SetCommandMode(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::ClearFaults(kortex_actuator_driver::ClearFaults::Request &req, kortex_actuator_driver::ClearFaults::Response &res)
+{
+ Empty input;
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->ClearFaults(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::SetServoing(kortex_actuator_driver::SetServoing::Request &req, kortex_actuator_driver::SetServoing::Response &res)
+{
+ Servoing input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->SetServoing(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::MoveToPosition(kortex_actuator_driver::MoveToPosition::Request &req, kortex_actuator_driver::MoveToPosition::Response &res)
+{
+ PositionCommand input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorconfig->MoveToPosition(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::GetCommandMode(kortex_actuator_driver::GetCommandMode::Request &req, kortex_actuator_driver::GetCommandMode::Response &res)
+{
+ Empty input;
+ CommandModeInformation output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorconfig->GetCommandMode(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+bool Actuator_Services::GetServoing(kortex_actuator_driver::GetServoing::Request &req, kortex_actuator_driver::GetServoing::Response &res)
+{
+ Empty input;
+ Servoing output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorconfig->GetServoing(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+bool Actuator_Services::GetTorqueOffset(kortex_actuator_driver::GetTorqueOffset::Request &req, kortex_actuator_driver::GetTorqueOffset::Response &res)
+{
+ Empty input;
+ TorqueOffset output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorconfig->GetTorqueOffset(m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+
+bool Actuator_Services::Refresh(kortex_actuator_driver::Refresh::Request &req, kortex_actuator_driver::Refresh::Response &res)
+{
+ Command input;
+ ToProtoData(req.input, &input);
+ Feedback output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorcyclic->Refresh(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+bool Actuator_Services::RefreshCommand(kortex_actuator_driver::RefreshCommand::Request &req, kortex_actuator_driver::RefreshCommand::Response &res)
+{
+ Command input;
+ ToProtoData(req.input, &input);
+ Empty output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ m_actuatorcyclic->RefreshCommand(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool Actuator_Services::RefreshFeedback(kortex_actuator_driver::RefreshFeedback::Request &req, kortex_actuator_driver::RefreshFeedback::Response &res)
+{
+ MessageId input;
+ ToProtoData(req.input, &input);
+ Feedback output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorcyclic->RefreshFeedback(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
+
+bool Actuator_Services::RefreshCustomData(kortex_actuator_driver::RefreshCustomData::Request &req, kortex_actuator_driver::RefreshCustomData::Response &res)
+{
+ MessageId input;
+ ToProtoData(req.input, &input);
+ CustomData output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ output = m_actuatorcyclic->RefreshCustomData(input, m_CurrentDeviceID, m_apiOptions);
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ ToRosData(output, res.output);
+ return true;
+}
diff --git a/kortex_actuator_driver/src/node.h b/kortex_actuator_driver/src/node.h
new file mode 100644
index 00000000..6c743e23
--- /dev/null
+++ b/kortex_actuator_driver/src/node.h
@@ -0,0 +1,154 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_SERVICES_H_
+#define _KORTEX_SERVICES_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "kortex_actuator_driver/GetAxisOffsets.h"
+#include "kortex_actuator_driver/SetAxisOffsets.h"
+#include "kortex_actuator_driver/ReadTorqueCalibration.h"
+#include "kortex_actuator_driver/WriteTorqueCalibration.h"
+#include "kortex_actuator_driver/SetTorqueOffset.h"
+#include "kortex_actuator_driver/GetControlMode.h"
+#include "kortex_actuator_driver/SetControlMode.h"
+#include "kortex_actuator_driver/GetActivatedControlLoop.h"
+#include "kortex_actuator_driver/SetActivatedControlLoop.h"
+#include "kortex_actuator_driver/GetVectorDriveParameters.h"
+#include "kortex_actuator_driver/SetVectorDriveParameters.h"
+#include "kortex_actuator_driver/GetEncoderDerivativeParameters.h"
+#include "kortex_actuator_driver/SetEncoderDerivativeParameters.h"
+#include "kortex_actuator_driver/GetControlLoopParameters.h"
+#include "kortex_actuator_driver/SetControlLoopParameters.h"
+#include "kortex_actuator_driver/StartFrequencyResponse.h"
+#include "kortex_actuator_driver/StopFrequencyResponse.h"
+#include "kortex_actuator_driver/StartStepResponse.h"
+#include "kortex_actuator_driver/StopStepResponse.h"
+#include "kortex_actuator_driver/StartRampResponse.h"
+#include "kortex_actuator_driver/StopRampResponse.h"
+#include "kortex_actuator_driver/SelectCustomData.h"
+#include "kortex_actuator_driver/GetSelectedCustomData.h"
+#include "kortex_actuator_driver/SetCommandMode.h"
+#include "kortex_actuator_driver/ClearFaults.h"
+#include "kortex_actuator_driver/SetServoing.h"
+#include "kortex_actuator_driver/MoveToPosition.h"
+#include "kortex_actuator_driver/GetCommandMode.h"
+#include "kortex_actuator_driver/GetServoing.h"
+#include "kortex_actuator_driver/GetTorqueOffset.h"
+#include "kortex_actuator_driver/Refresh.h"
+#include "kortex_actuator_driver/RefreshCommand.h"
+#include "kortex_actuator_driver/RefreshFeedback.h"
+#include "kortex_actuator_driver/RefreshCustomData.h"
+#include "kortex_actuator_driver/KortexError.h"
+#include "kortex_actuator_driver/SetDeviceID.h"
+#include "kortex_actuator_driver/SetApiOptions.h"
+#include "kortex_actuator_driver/SetCyclicStatus.h"
+#include "kortex_actuator_driver/GetCyclicStatus.h"
+#include "kortex_actuator_driver/ApiOptions.h"
+#include "kortex_actuator_driver/CyclicStatus.h"
+
+using namespace std;
+using namespace Kinova::Api;
+using namespace Kinova::Api::Common;
+using namespace Kinova::Api::ActuatorConfig;
+using namespace Kinova::Api::ActuatorCyclic;
+
+class Actuator_Services
+{
+ public:
+ Actuator_Services(char* ip, ros::NodeHandle& n, uint32_t device_id);
+ bool SetDeviceID(kortex_actuator_driver::SetDeviceID::Request &req, kortex_actuator_driver::SetDeviceID::Response &res);
+ bool SetApiOptions(kortex_actuator_driver::SetApiOptions::Request &req, kortex_actuator_driver::SetApiOptions::Response &res);
+ bool GetCyclicStatus(kortex_actuator_driver::GetCyclicStatus::Request &req, kortex_actuator_driver::GetCyclicStatus::Response &res);
+ bool SetCyclicStatus(kortex_actuator_driver::SetCyclicStatus::Request &req, kortex_actuator_driver::SetCyclicStatus::Response &res);
+ bool IsCyclicActive();
+
+
+ bool GetAxisOffsets(kortex_actuator_driver::GetAxisOffsets::Request &req, kortex_actuator_driver::GetAxisOffsets::Response &res);
+ bool SetAxisOffsets(kortex_actuator_driver::SetAxisOffsets::Request &req, kortex_actuator_driver::SetAxisOffsets::Response &res);
+ bool ReadTorqueCalibration(kortex_actuator_driver::ReadTorqueCalibration::Request &req, kortex_actuator_driver::ReadTorqueCalibration::Response &res);
+ bool WriteTorqueCalibration(kortex_actuator_driver::WriteTorqueCalibration::Request &req, kortex_actuator_driver::WriteTorqueCalibration::Response &res);
+ bool SetTorqueOffset(kortex_actuator_driver::SetTorqueOffset::Request &req, kortex_actuator_driver::SetTorqueOffset::Response &res);
+ bool GetControlMode(kortex_actuator_driver::GetControlMode::Request &req, kortex_actuator_driver::GetControlMode::Response &res);
+ bool SetControlMode(kortex_actuator_driver::SetControlMode::Request &req, kortex_actuator_driver::SetControlMode::Response &res);
+ bool GetActivatedControlLoop(kortex_actuator_driver::GetActivatedControlLoop::Request &req, kortex_actuator_driver::GetActivatedControlLoop::Response &res);
+ bool SetActivatedControlLoop(kortex_actuator_driver::SetActivatedControlLoop::Request &req, kortex_actuator_driver::SetActivatedControlLoop::Response &res);
+ bool GetVectorDriveParameters(kortex_actuator_driver::GetVectorDriveParameters::Request &req, kortex_actuator_driver::GetVectorDriveParameters::Response &res);
+ bool SetVectorDriveParameters(kortex_actuator_driver::SetVectorDriveParameters::Request &req, kortex_actuator_driver::SetVectorDriveParameters::Response &res);
+ bool GetEncoderDerivativeParameters(kortex_actuator_driver::GetEncoderDerivativeParameters::Request &req, kortex_actuator_driver::GetEncoderDerivativeParameters::Response &res);
+ bool SetEncoderDerivativeParameters(kortex_actuator_driver::SetEncoderDerivativeParameters::Request &req, kortex_actuator_driver::SetEncoderDerivativeParameters::Response &res);
+ bool GetControlLoopParameters(kortex_actuator_driver::GetControlLoopParameters::Request &req, kortex_actuator_driver::GetControlLoopParameters::Response &res);
+ bool SetControlLoopParameters(kortex_actuator_driver::SetControlLoopParameters::Request &req, kortex_actuator_driver::SetControlLoopParameters::Response &res);
+ bool StartFrequencyResponse(kortex_actuator_driver::StartFrequencyResponse::Request &req, kortex_actuator_driver::StartFrequencyResponse::Response &res);
+ bool StopFrequencyResponse(kortex_actuator_driver::StopFrequencyResponse::Request &req, kortex_actuator_driver::StopFrequencyResponse::Response &res);
+ bool StartStepResponse(kortex_actuator_driver::StartStepResponse::Request &req, kortex_actuator_driver::StartStepResponse::Response &res);
+ bool StopStepResponse(kortex_actuator_driver::StopStepResponse::Request &req, kortex_actuator_driver::StopStepResponse::Response &res);
+ bool StartRampResponse(kortex_actuator_driver::StartRampResponse::Request &req, kortex_actuator_driver::StartRampResponse::Response &res);
+ bool StopRampResponse(kortex_actuator_driver::StopRampResponse::Request &req, kortex_actuator_driver::StopRampResponse::Response &res);
+ bool SelectCustomData(kortex_actuator_driver::SelectCustomData::Request &req, kortex_actuator_driver::SelectCustomData::Response &res);
+ bool GetSelectedCustomData(kortex_actuator_driver::GetSelectedCustomData::Request &req, kortex_actuator_driver::GetSelectedCustomData::Response &res);
+ bool SetCommandMode(kortex_actuator_driver::SetCommandMode::Request &req, kortex_actuator_driver::SetCommandMode::Response &res);
+ bool ClearFaults(kortex_actuator_driver::ClearFaults::Request &req, kortex_actuator_driver::ClearFaults::Response &res);
+ bool SetServoing(kortex_actuator_driver::SetServoing::Request &req, kortex_actuator_driver::SetServoing::Response &res);
+ bool MoveToPosition(kortex_actuator_driver::MoveToPosition::Request &req, kortex_actuator_driver::MoveToPosition::Response &res);
+ bool GetCommandMode(kortex_actuator_driver::GetCommandMode::Request &req, kortex_actuator_driver::GetCommandMode::Response &res);
+ bool GetServoing(kortex_actuator_driver::GetServoing::Request &req, kortex_actuator_driver::GetServoing::Response &res);
+ bool GetTorqueOffset(kortex_actuator_driver::GetTorqueOffset::Request &req, kortex_actuator_driver::GetTorqueOffset::Response &res);
+
+ bool Refresh(kortex_actuator_driver::Refresh::Request &req, kortex_actuator_driver::Refresh::Response &res);
+ bool RefreshCommand(kortex_actuator_driver::RefreshCommand::Request &req, kortex_actuator_driver::RefreshCommand::Response &res);
+ bool RefreshFeedback(kortex_actuator_driver::RefreshFeedback::Request &req, kortex_actuator_driver::RefreshFeedback::Response &res);
+ bool RefreshCustomData(kortex_actuator_driver::RefreshCustomData::Request &req, kortex_actuator_driver::RefreshCustomData::Response &res);
+
+
+private:
+ TransportClientUdp* m_transport;
+ RouterClient* m_router;
+
+ ActuatorConfigClient* m_actuatorconfig;
+ ActuatorCyclicClient* m_actuatorcyclic;
+ uint32_t m_CurrentDeviceID;
+ RouterClientSendOptions m_apiOptions;
+
+ SessionManager* m_SessionManager;
+ bool m_cyclicActive = false;
+
+ ros::NodeHandle m_n;
+ ros::Publisher m_pub_Error;
+};
+#endif
diff --git a/kortex_actuator_driver/src/util/diagnostic.h b/kortex_actuator_driver/src/util/diagnostic.h
new file mode 100644
index 00000000..f0199870
--- /dev/null
+++ b/kortex_actuator_driver/src/util/diagnostic.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2018 Kinova inc. All rights reserved.
+ *
+ * This software may be modified and distributed under the
+ * terms of the BSD 3-Clause license.
+ *
+ * Refer to the LICENSE file for details.
+ *
+ */
+#include
+
+struct kortex_error
+{
+ int error_code;
+ std::string description;
+};
\ No newline at end of file
diff --git a/kortex_actuator_driver/src/util/math_util.h b/kortex_actuator_driver/src/util/math_util.h
new file mode 100644
index 00000000..bf935386
--- /dev/null
+++ b/kortex_actuator_driver/src/util/math_util.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2018 Kinova inc. All rights reserved.
+ *
+ * This software may be modified and distributed under the
+ * terms of the BSD 3-Clause license.
+ *
+ * Refer to the LICENSE file for details.
+ *
+ */
+#include
+
+#define TO_RAD(degree) degree * M_PI / 180.0
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/ClearFaults.srv b/kortex_actuator_driver/srv/ClearFaults.srv
new file mode 100644
index 00000000..4d7a11a3
--- /dev/null
+++ b/kortex_actuator_driver/srv/ClearFaults.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/GetActivatedControlLoop.srv b/kortex_actuator_driver/srv/GetActivatedControlLoop.srv
new file mode 100644
index 00000000..a19e2136
--- /dev/null
+++ b/kortex_actuator_driver/srv/GetActivatedControlLoop.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+ControlLoop output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/GetAxisOffsets.srv b/kortex_actuator_driver/srv/GetAxisOffsets.srv
new file mode 100644
index 00000000..4735b95e
--- /dev/null
+++ b/kortex_actuator_driver/srv/GetAxisOffsets.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+AxisOffsets output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/GetCommandMode.srv b/kortex_actuator_driver/srv/GetCommandMode.srv
new file mode 100644
index 00000000..bdfef0a5
--- /dev/null
+++ b/kortex_actuator_driver/srv/GetCommandMode.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+CommandModeInformation output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/GetControlLoopParameters.srv b/kortex_actuator_driver/srv/GetControlLoopParameters.srv
new file mode 100644
index 00000000..d999a54e
--- /dev/null
+++ b/kortex_actuator_driver/srv/GetControlLoopParameters.srv
@@ -0,0 +1,3 @@
+LoopSelection input
+---
+ControlLoopParameters output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/GetControlMode.srv b/kortex_actuator_driver/srv/GetControlMode.srv
new file mode 100644
index 00000000..6eb15fb1
--- /dev/null
+++ b/kortex_actuator_driver/srv/GetControlMode.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+ControlModeInformation output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/GetEncoderDerivativeParameters.srv b/kortex_actuator_driver/srv/GetEncoderDerivativeParameters.srv
new file mode 100644
index 00000000..7815939b
--- /dev/null
+++ b/kortex_actuator_driver/srv/GetEncoderDerivativeParameters.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+EncoderDerivativeParameters output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/GetSelectedCustomData.srv b/kortex_actuator_driver/srv/GetSelectedCustomData.srv
new file mode 100644
index 00000000..cdc73093
--- /dev/null
+++ b/kortex_actuator_driver/srv/GetSelectedCustomData.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+CustomDataSelection output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/GetServoing.srv b/kortex_actuator_driver/srv/GetServoing.srv
new file mode 100644
index 00000000..d4a6734b
--- /dev/null
+++ b/kortex_actuator_driver/srv/GetServoing.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+Servoing output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/GetTorqueOffset.srv b/kortex_actuator_driver/srv/GetTorqueOffset.srv
new file mode 100644
index 00000000..f8d55a75
--- /dev/null
+++ b/kortex_actuator_driver/srv/GetTorqueOffset.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+TorqueOffset output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/GetVectorDriveParameters.srv b/kortex_actuator_driver/srv/GetVectorDriveParameters.srv
new file mode 100644
index 00000000..e6ea88c5
--- /dev/null
+++ b/kortex_actuator_driver/srv/GetVectorDriveParameters.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+VectorDriveParameters output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/MoveToPosition.srv b/kortex_actuator_driver/srv/MoveToPosition.srv
new file mode 100644
index 00000000..bca986c7
--- /dev/null
+++ b/kortex_actuator_driver/srv/MoveToPosition.srv
@@ -0,0 +1,3 @@
+PositionCommand input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/ReadTorqueCalibration.srv b/kortex_actuator_driver/srv/ReadTorqueCalibration.srv
new file mode 100644
index 00000000..45dec9f4
--- /dev/null
+++ b/kortex_actuator_driver/srv/ReadTorqueCalibration.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+TorqueCalibration output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/Refresh.srv b/kortex_actuator_driver/srv/Refresh.srv
new file mode 100644
index 00000000..432de516
--- /dev/null
+++ b/kortex_actuator_driver/srv/Refresh.srv
@@ -0,0 +1,3 @@
+Command input
+---
+Feedback output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/RefreshCommand.srv b/kortex_actuator_driver/srv/RefreshCommand.srv
new file mode 100644
index 00000000..9bd2e9fc
--- /dev/null
+++ b/kortex_actuator_driver/srv/RefreshCommand.srv
@@ -0,0 +1,3 @@
+Command input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/RefreshCustomData.srv b/kortex_actuator_driver/srv/RefreshCustomData.srv
new file mode 100644
index 00000000..5822ae31
--- /dev/null
+++ b/kortex_actuator_driver/srv/RefreshCustomData.srv
@@ -0,0 +1,3 @@
+MessageId input
+---
+CustomData output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/RefreshFeedback.srv b/kortex_actuator_driver/srv/RefreshFeedback.srv
new file mode 100644
index 00000000..f850c63d
--- /dev/null
+++ b/kortex_actuator_driver/srv/RefreshFeedback.srv
@@ -0,0 +1,3 @@
+MessageId input
+---
+Feedback output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/SelectCustomData.srv b/kortex_actuator_driver/srv/SelectCustomData.srv
new file mode 100644
index 00000000..0bf1dfab
--- /dev/null
+++ b/kortex_actuator_driver/srv/SelectCustomData.srv
@@ -0,0 +1,3 @@
+CustomDataSelection input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/SetActivatedControlLoop.srv b/kortex_actuator_driver/srv/SetActivatedControlLoop.srv
new file mode 100644
index 00000000..14dbadcd
--- /dev/null
+++ b/kortex_actuator_driver/srv/SetActivatedControlLoop.srv
@@ -0,0 +1,3 @@
+ControlLoop input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/SetAxisOffsets.srv b/kortex_actuator_driver/srv/SetAxisOffsets.srv
new file mode 100644
index 00000000..00602436
--- /dev/null
+++ b/kortex_actuator_driver/srv/SetAxisOffsets.srv
@@ -0,0 +1,3 @@
+AxisPosition input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/SetCommandMode.srv b/kortex_actuator_driver/srv/SetCommandMode.srv
new file mode 100644
index 00000000..9ba28a53
--- /dev/null
+++ b/kortex_actuator_driver/srv/SetCommandMode.srv
@@ -0,0 +1,3 @@
+CommandModeInformation input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/SetControlLoopParameters.srv b/kortex_actuator_driver/srv/SetControlLoopParameters.srv
new file mode 100644
index 00000000..8f7419af
--- /dev/null
+++ b/kortex_actuator_driver/srv/SetControlLoopParameters.srv
@@ -0,0 +1,3 @@
+ControlLoopParameters input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/SetControlMode.srv b/kortex_actuator_driver/srv/SetControlMode.srv
new file mode 100644
index 00000000..d5a258a6
--- /dev/null
+++ b/kortex_actuator_driver/srv/SetControlMode.srv
@@ -0,0 +1,3 @@
+ControlModeInformation input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/SetEncoderDerivativeParameters.srv b/kortex_actuator_driver/srv/SetEncoderDerivativeParameters.srv
new file mode 100644
index 00000000..d6d6530d
--- /dev/null
+++ b/kortex_actuator_driver/srv/SetEncoderDerivativeParameters.srv
@@ -0,0 +1,3 @@
+EncoderDerivativeParameters input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/SetServoing.srv b/kortex_actuator_driver/srv/SetServoing.srv
new file mode 100644
index 00000000..3eb88018
--- /dev/null
+++ b/kortex_actuator_driver/srv/SetServoing.srv
@@ -0,0 +1,3 @@
+Servoing input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/SetTorqueOffset.srv b/kortex_actuator_driver/srv/SetTorqueOffset.srv
new file mode 100644
index 00000000..6f2857b9
--- /dev/null
+++ b/kortex_actuator_driver/srv/SetTorqueOffset.srv
@@ -0,0 +1,3 @@
+TorqueOffset input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/SetVectorDriveParameters.srv b/kortex_actuator_driver/srv/SetVectorDriveParameters.srv
new file mode 100644
index 00000000..68aba166
--- /dev/null
+++ b/kortex_actuator_driver/srv/SetVectorDriveParameters.srv
@@ -0,0 +1,3 @@
+VectorDriveParameters input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/StartFrequencyResponse.srv b/kortex_actuator_driver/srv/StartFrequencyResponse.srv
new file mode 100644
index 00000000..38761145
--- /dev/null
+++ b/kortex_actuator_driver/srv/StartFrequencyResponse.srv
@@ -0,0 +1,3 @@
+FrequencyResponse input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/StartRampResponse.srv b/kortex_actuator_driver/srv/StartRampResponse.srv
new file mode 100644
index 00000000..246d7fa3
--- /dev/null
+++ b/kortex_actuator_driver/srv/StartRampResponse.srv
@@ -0,0 +1,3 @@
+RampResponse input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/StartStepResponse.srv b/kortex_actuator_driver/srv/StartStepResponse.srv
new file mode 100644
index 00000000..d5f063e6
--- /dev/null
+++ b/kortex_actuator_driver/srv/StartStepResponse.srv
@@ -0,0 +1,3 @@
+StepResponse input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/StopFrequencyResponse.srv b/kortex_actuator_driver/srv/StopFrequencyResponse.srv
new file mode 100644
index 00000000..4d7a11a3
--- /dev/null
+++ b/kortex_actuator_driver/srv/StopFrequencyResponse.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/StopRampResponse.srv b/kortex_actuator_driver/srv/StopRampResponse.srv
new file mode 100644
index 00000000..4d7a11a3
--- /dev/null
+++ b/kortex_actuator_driver/srv/StopRampResponse.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/StopStepResponse.srv b/kortex_actuator_driver/srv/StopStepResponse.srv
new file mode 100644
index 00000000..4d7a11a3
--- /dev/null
+++ b/kortex_actuator_driver/srv/StopStepResponse.srv
@@ -0,0 +1,3 @@
+Empty input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/WriteTorqueCalibration.srv b/kortex_actuator_driver/srv/WriteTorqueCalibration.srv
new file mode 100644
index 00000000..cf4dac5d
--- /dev/null
+++ b/kortex_actuator_driver/srv/WriteTorqueCalibration.srv
@@ -0,0 +1,3 @@
+TorqueCalibration input
+---
+Empty output
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/non_generated/GetCyclicStatus.srv b/kortex_actuator_driver/srv/non_generated/GetCyclicStatus.srv
new file mode 100644
index 00000000..2ec06d8c
--- /dev/null
+++ b/kortex_actuator_driver/srv/non_generated/GetCyclicStatus.srv
@@ -0,0 +1,2 @@
+---
+CyclicStatus status
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/non_generated/SetApiOptions.srv b/kortex_actuator_driver/srv/non_generated/SetApiOptions.srv
new file mode 100644
index 00000000..cab7c810
--- /dev/null
+++ b/kortex_actuator_driver/srv/non_generated/SetApiOptions.srv
@@ -0,0 +1,3 @@
+ApiOptions input
+---
+
diff --git a/kortex_actuator_driver/srv/non_generated/SetCyclicStatus.srv b/kortex_actuator_driver/srv/non_generated/SetCyclicStatus.srv
new file mode 100644
index 00000000..05417e2c
--- /dev/null
+++ b/kortex_actuator_driver/srv/non_generated/SetCyclicStatus.srv
@@ -0,0 +1,2 @@
+CyclicStatus status
+---
\ No newline at end of file
diff --git a/kortex_actuator_driver/srv/non_generated/SetDeviceID.srv b/kortex_actuator_driver/srv/non_generated/SetDeviceID.srv
new file mode 100644
index 00000000..396957c5
--- /dev/null
+++ b/kortex_actuator_driver/srv/non_generated/SetDeviceID.srv
@@ -0,0 +1,2 @@
+uint32 device_id
+---
diff --git a/kortex_actuator_driver/templates/NodeServices.cpp.jinja2 b/kortex_actuator_driver/templates/NodeServices.cpp.jinja2
new file mode 100644
index 00000000..9105fde0
--- /dev/null
+++ b/kortex_actuator_driver/templates/NodeServices.cpp.jinja2
@@ -0,0 +1,167 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "node.h"
+{% for package in detailedPackages %}
+{%- if package.HasMessage == 1 -%}
+#include "{{package.filename|lower}}_ros_converter.h"
+#include "{{package.filename|lower}}_proto_converter.h"
+{%- endif %}
+{% endfor -%}
+
+Actuator_Services::Actuator_Services(char* ip, ros::NodeHandle& n, uint32_t device_id) : m_n(n)
+{
+ m_transport = new TransportClientUdp();
+ m_transport->connect(ip, 10000);
+
+ m_router = new RouterClient(m_transport, [](KError err) { cout << "_________ callback error _________" << err.toString(); });
+ m_CurrentDeviceID = device_id;
+ m_apiOptions.timeout_ms = 3000;
+{% for package in detailedPackages %}
+ {%- if package.HasRPC == 1 %}
+ m_{{package.name|lower}} = new {{package.name}}::{{package.name}}Client(m_router);
+ {%- endif -%}
+{% endfor -%}
+ //If the Device ID is different than 0, it means that we are using the feature DEVICE ROUTING.
+ if(m_CurrentDeviceID != 0)
+ {
+ m_SessionManager = new SessionManager(m_router);
+ auto createSessionInfo = Kinova::Api::Session::CreateSessionInfo();
+
+ createSessionInfo.set_username("admin");
+ createSessionInfo.set_password("admin");
+ createSessionInfo.set_session_inactivity_timeout(35000);
+
+ m_SessionManager->CreateSession(createSessionInfo);
+ }
+
+ m_pub_Error = m_n.advertise("KortexError", 1000);
+{%- for package in detailedPackages -%}
+{%- for method in package.service.method -%}
+{%- if 'Topic' in method.name %}
+ m_pub_{{method.name}} = m_n.advertise("{{method.name}}", 1000);
+{%- endif -%}
+{%- endfor -%}
+{%- endfor -%}
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+}
+
+bool Actuator_Services::SetDeviceID(kortex_actuator_driver::SetDeviceID::Request &req, kortex_actuator_driver::SetDeviceID::Response &res)
+{
+ if(m_CurrentDeviceID == 0)
+ {
+ auto sessionManager = new SessionManager(m_router);
+ auto createSessionInfo = Kinova::Api::Session::CreateSessionInfo();
+
+ createSessionInfo.set_username("admin");
+ createSessionInfo.set_password("admin");
+ createSessionInfo.set_session_inactivity_timeout(35000);
+
+ sessionManager->CreateSession(createSessionInfo);
+ }
+
+ m_CurrentDeviceID = req.device_id;
+}
+
+bool Actuator_Services::SetApiOptions(kortex_actuator_driver::SetApiOptions::Request &req, kortex_actuator_driver::SetApiOptions::Response &res)
+{
+ m_apiOptions.timeout_ms = req.input.timeout_ms;
+
+ return true;
+}
+
+bool Actuator_Services::GetCyclicStatus(kortex_actuator_driver::GetCyclicStatus::Request &req, kortex_actuator_driver::GetCyclicStatus::Response &res)
+{
+ res.status.isActive = m_cyclicActive;
+}
+
+bool Actuator_Services::SetCyclicStatus(kortex_actuator_driver::SetCyclicStatus::Request &req, kortex_actuator_driver::SetCyclicStatus::Response &res)
+{
+ m_cyclicActive = req.status.isActive;
+}
+
+bool Actuator_Services::IsCyclicActive()
+{
+ return m_cyclicActive;
+}
+
+{% for package in detailedPackages %}
+{% for method in package.service.method %}
+{%- if 'Topic' in method.name %}
+bool Actuator_Services::OnNotification{{method.name}}(kortex_actuator_driver::{{method.name}}::Request &req, kortex_actuator_driver::{{method.name}}::Response &res)
+{%- else %}
+bool Actuator_Services::{{method.name}}(kortex_actuator_driver::{{method.name}}::Request &req, kortex_actuator_driver::{{method.name}}::Response &res)
+{%- endif %}
+{
+ {%- set splitInputTypeName = method.input_type.split('.') -%}
+ {% set splitOutputTypeName = method.output_type.split('.') %}
+ {{splitInputTypeName[4]}} input;
+ {%- if not method.input_type.split('.')[4] == "Empty" %}
+ ToProtoData(req.input, &input);
+ {%- endif %}
+ {{splitOutputTypeName[4]}} output;
+ kortex_actuator_driver::KortexError result_error;
+
+ try
+ {
+ {%- if not method.output_type.split('.')[4] == "Empty" %}
+ {%- if not method.input_type.split('.')[4] == "Empty" %}
+ {%- if 'Topic' in method.name %}
+ std::function< void ({{package.name}}::{{method.name|replace("Topic", "")}}Notification) > callback = std::bind(&BaseServices::cb_{{method.name}}, this, std::placeholders::_1);
+ output = m_{{package.name|lower}}->OnNotification{{method.name}}(callback, input);
+ {%- else %}
+ output = m_{{package.name|lower}}->{{method.name}}(input, m_CurrentDeviceID, m_apiOptions);
+ {%- endif %}
+ {%- else %}
+ output = m_{{package.name|lower}}->{{method.name}}(m_CurrentDeviceID, m_apiOptions);
+ {%- endif %}
+ {%- else %}
+ {%- if not method.input_type.split('.')[4] == "Empty" %}
+ m_{{package.name|lower}}->{{method.name}}(input, m_CurrentDeviceID, m_apiOptions);
+ {%- else %}
+ m_{{package.name|lower}}->{{method.name}}(m_CurrentDeviceID, m_apiOptions);
+ {%- endif %}
+ {%- endif %}
+ }
+ catch (KDetailedException& ex)
+ {
+ result_error.subCode = ex.getErrorInfo().getError().error_sub_code();
+ result_error.code = ex.getErrorInfo().getError().error_code();
+ result_error.description = ex.what();
+ m_pub_Error.publish(result_error);
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ return false;
+ }
+ catch (std::runtime_error& ex2)
+ {
+ return false;
+ }
+ {%- if not method.output_type.split('.')[4] == "Empty" %}
+ ToRosData(output, res.output);
+ {%- endif %}
+ return true;
+}
+{%- if 'Topic' in method.name %}
+void Actuator_Services::cb_{{method.name}}({{package.name}}::{{method.name|replace("Topic", "")}}Notification notif)
+{
+ kortex_actuator_driver::{{method.name|replace("Topic", "")}}Notification ros_msg;
+ ToRosData(notif, ros_msg);
+ m_pub_{{method.name}}.publish(ros_msg);
+}
+{%- endif %}
+{% endfor -%}
+{% endfor -%}
\ No newline at end of file
diff --git a/kortex_actuator_driver/templates/NodeServices.h.jinja2 b/kortex_actuator_driver/templates/NodeServices.h.jinja2
new file mode 100644
index 00000000..1b7ca737
--- /dev/null
+++ b/kortex_actuator_driver/templates/NodeServices.h.jinja2
@@ -0,0 +1,113 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_{{packageName}}SERVICES_H_
+#define _KORTEX_{{packageName}}SERVICES_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+{%- for package in detailedPackages %}
+#include <{{package.filename}}.pb.h>
+{%- endfor %}
+
+#include
+#include
+
+#include
+#include
+
+{%- for package in detailedPackages %}
+{%- if package.HasRPC == 1 %}
+#include <{{package.name}}ClientRpc.h>
+{%- endif %}
+{%- endfor %}
+#include
+#include
+
+{%- for package in detailedPackages %}
+{%- for method in package.service.method %}
+#include "kortex_actuator_driver/{{method.name}}.h"
+{%- endfor %}
+{%- endfor %}
+#include "kortex_actuator_driver/KortexError.h"
+#include "kortex_actuator_driver/SetDeviceID.h"
+#include "kortex_actuator_driver/SetApiOptions.h"
+#include "kortex_actuator_driver/SetCyclicStatus.h"
+#include "kortex_actuator_driver/GetCyclicStatus.h"
+#include "kortex_actuator_driver/ApiOptions.h"
+#include "kortex_actuator_driver/CyclicStatus.h"
+
+using namespace std;
+using namespace Kinova::Api;
+{%- for package in detailedPackages %}
+using namespace {{package.namespace}};
+{%- endfor %}
+
+class Actuator_Services
+{
+ public:
+ Actuator_Services(char* ip, ros::NodeHandle& n, uint32_t device_id);
+ bool SetDeviceID(kortex_actuator_driver::SetDeviceID::Request &req, kortex_actuator_driver::SetDeviceID::Response &res);
+ bool SetApiOptions(kortex_actuator_driver::SetApiOptions::Request &req, kortex_actuator_driver::SetApiOptions::Response &res);
+ bool GetCyclicStatus(kortex_actuator_driver::GetCyclicStatus::Request &req, kortex_actuator_driver::GetCyclicStatus::Response &res);
+ bool SetCyclicStatus(kortex_actuator_driver::SetCyclicStatus::Request &req, kortex_actuator_driver::SetCyclicStatus::Response &res);
+ bool IsCyclicActive();
+{% for package in detailedPackages %}
+{%- for method in package.service.method %}
+{%- if 'Topic' in method.name %}
+ bool OnNotification{{method.name}}(kortex_actuator_driver::{{method.name}}::Request &req, kortex_actuator_driver::{{method.name}}::Response &res);
+ void cb_{{method.name}}({{method.name|replace("Topic", "")}}Notification notif);
+{%- else %}
+ bool {{method.name}}(kortex_actuator_driver::{{method.name}}::Request &req, kortex_actuator_driver::{{method.name}}::Response &res);
+{%- endif %}
+{%- endfor %}
+{% endfor %}
+
+private:
+ TransportClientUdp* m_transport;
+ RouterClient* m_router;
+ {% for package in detailedPackages %}
+ {%- if package.HasRPC == 1 %}
+ {{package.name}}Client* m_{{package.name|lower}};
+ {%- endif -%}
+ {% endfor %}
+ uint32_t m_CurrentDeviceID;
+ RouterClientSendOptions m_apiOptions;
+
+ SessionManager* m_SessionManager;
+ bool m_cyclicActive = false;
+
+ ros::NodeHandle m_n;
+ ros::Publisher m_pub_Error;
+
+ {%- for package in detailedPackages %}
+ {%- for method in package.service.method %}
+ {%- if 'Topic' in method.name %}
+ ros::Publisher m_pub_{{method.name}};
+ {%- endif %}
+ {%- endfor %}
+ {%- endfor %}
+};
+#endif
+
diff --git a/kortex_actuator_driver/templates/main.jinja2 b/kortex_actuator_driver/templates/main.jinja2
new file mode 100644
index 00000000..3accd393
--- /dev/null
+++ b/kortex_actuator_driver/templates/main.jinja2
@@ -0,0 +1,148 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "node.h"
+#include "math_util.h"
+
+#include
+#include
+
+int main(int argc, char **argv)
+{
+ ros::init(argc, argv, "Actuator_Services");
+
+ uint32_t cyclic_data_rate = 100;
+ uint32_t device_id = 0;
+
+ ros::NodeHandle n;
+ bool valid_ip = false;
+
+ if(argc > 3)
+ {
+ stringstream tempId;
+ tempId << argv[3];
+ tempId >> device_id;
+
+ if(tempId.fail() || tempId.bad())
+ {
+ ROS_INFO("ERROR - Bad device ID, shutting down the node...");
+ ros::shutdown();
+ return 0;
+ }
+ }
+ else if(argc > 2)
+ {
+ //Converting the second parameter(the cyclic rate) to an unsigned int variable.
+ stringstream tempRate;
+ tempRate << argv[2];
+ tempRate >> cyclic_data_rate;
+ if(tempRate.fail() || tempRate.bad())
+ {
+ ROS_INFO("ERROR - Bad error rate, shutting down the node...");
+ ros::shutdown();
+ return 0;
+ }
+ ROS_INFO("Connecting to IP = %s - node refresh rate = %s, device ID = %d", argv[1], argv[2], device_id);
+ }
+ else
+ {
+ ROS_INFO("You need to provide an IP adresse as the first parameter and optionnaly a second parameter to specify the cyclic \
+ rate and a third parameter(optionnal) to specify a device ID. ex: rosrun package node 127.0.0.1 100 4");
+ ros::shutdown();
+ return 0;
+ }
+
+ Actuator_Services services_object(argv[1], n, device_id);
+
+ ros::ServiceServer serviceSetDeviceID = n.advertiseService("SetDeviceID", &Actuator_Services::SetDeviceID, &services_object);
+ ros::ServiceServer serviceSetApiOptions = n.advertiseService("SetApiOptions", &Actuator_Services::SetApiOptions, &services_object);
+ ros::ServiceServer serviceSetCyclicStatus = n.advertiseService("SetCyclicStatus", &Actuator_Services::SetCyclicStatus, &services_object);
+ ros::ServiceServer serviceGetCyclicStatus = n.advertiseService("GetCyclicStatus", &Actuator_Services::GetCyclicStatus, &services_object);
+
+ {% for function in list_function -%}
+ ros::ServiceServer service{{function}} = n.advertiseService("{{function}}", &Actuator_Services::{{function}}, &services_object);
+ {% endfor %}
+
+ ROS_INFO("Node's services initialized correctly.");
+
+ ros::Publisher pub_feedback = n.advertise("actuator_feedback", 1000);
+ ros::Publisher pub_joint_state = n.advertise("actuator_feedback/joint_state", 1000);
+
+ kortex_actuator_driver::Feedback feedback;
+ kortex_actuator_driver::RefreshFeedback::Request req;
+ kortex_actuator_driver::RefreshFeedback::Response res;
+
+ sensor_msgs::JointState joint_state;
+
+ joint_state.position.resize(1);
+ joint_state.velocity.resize(1);
+ joint_state.effort.resize(1);
+ joint_state.name.resize(1);
+
+ ros::Rate rate(cyclic_data_rate); // 100 hz
+ while (!ros::isShuttingDown())
+ {
+ try
+ {
+ if(services_object.IsCyclicActive())
+ {
+ services_object.RefreshFeedback(req, res);
+
+ feedback.feedback_id = res.output.feedback_id;
+
+ feedback.status_flags = res.output.status_flags;
+ feedback.jitter_comm = res.output.jitter_comm;
+ feedback.position = res.output.position;
+ feedback.velocity = res.output.velocity;
+ feedback.torque = res.output.torque;
+ feedback.current_motor = res.output.current_motor;
+ feedback.voltage = res.output.voltage;
+ feedback.temperature_motor = res.output.temperature_motor;
+ feedback.temperature_core = res.output.temperature_core;
+ feedback.fault_bank_a = res.output.fault_bank_a;
+ feedback.fault_bank_b = res.output.fault_bank_b;
+ feedback.warning_bank_a = res.output.warning_bank_a;
+ feedback.warning_bank_b = res.output.warning_bank_b;
+
+ joint_state.header.stamp = ros::Time::now();
+ joint_state.header.frame_id = std::to_string(res.output.feedback_id.identifier);
+
+ joint_state.name[0] = "Actuator";
+ joint_state.position[0] = TO_RAD(res.output.position);
+ joint_state.velocity[0] = TO_RAD(res.output.velocity);
+ joint_state.effort[0] = res.output.torque;
+
+ pub_feedback.publish(feedback);
+ pub_joint_state.publish(joint_state);
+ }
+ }
+
+ catch (KDetailedException& ex)
+ {
+ ROS_INFO("KINOVA exception: %d\n", ex.getErrorInfo().getError().error_sub_code());
+ }
+ catch (std::runtime_error& ex2)
+ {
+ ROS_INFO("RUN TIME ERROR: %s\n", ex2.what());
+ }
+
+ ros::spinOnce();
+
+ rate.sleep();
+ }
+
+ return 1;
+}
diff --git a/kortex_actuator_driver/templates/proto_converter.cpp.jinja2 b/kortex_actuator_driver/templates/proto_converter.cpp.jinja2
new file mode 100644
index 00000000..a2e26763
--- /dev/null
+++ b/kortex_actuator_driver/templates/proto_converter.cpp.jinja2
@@ -0,0 +1,77 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "{{currentFilename|lower}}_proto_converter.h"
+{% if 'Common' not in currentPackageName %}
+#include "common_proto_converter.h"
+{% endif %}
+
+{% for detailed_message in item -%}
+int ToProtoData(kortex_actuator_driver::{{detailed_message.message.name}} input, {{detailed_message.message.name}} *output)
+{
+ {%- for field in detailed_message.message.field %}
+ {%- if not field.HasField("oneof_index") -%}
+ {%- if field.label == 3 %} {# Si c'est un repeated #}
+ {%- if field.type == 11 %}
+ output->clear_{{field.name|lower}}();
+ for(int i = 0; i < input.{{field.name}}.size(); i++)
+ {
+ ToProtoData(input.{{field.name}}[i], output->add_{{field.name|lower}}());
+ }
+ {%- else %}
+ output->clear_{{field.name|lower}}();
+ for(int i = 0; i < input.{{field.name}}.size(); i++)
+ {
+ output->add_{{field.name|lower}}(input.{{field.name}}[i]);
+ }
+ {% endif -%}
+ {% else -%}
+ {%- if field.type == 11 %}
+ ToProtoData(input.{{field.name}}, output->mutable_{{field.name}}());
+ {%- elif field.type == 14 %}{# ENUM #}
+ {%- set list1 = field.type_name.split('.') -%} {# Cette ligne sert à enlever les namespace dans le nom du type #}
+ output->set_{{field.name}}(({{field.type_name|replace(".", "", 1)|replace(".", "::")}})input.{{field.name}});
+ {%- elif field.type == 12 %}
+ output->set_{{field.name}}(std::string(input.{{field.name}}.begin(), input.{{field.name}}.end()));
+ {%- else %}
+ output->set_{{field.name}}(input.{{field.name}});
+ {%- endif -%}
+ {%- endif -%}
+ {%- endif -%}
+ {%- endfor -%}
+
+ {% if detailed_message.HasOneOf == "true" %}
+
+ {% for field in detailed_message.message.field %}
+ {%- if field.HasField("oneof_index") -%}
+ if(input.oneof_{{detailed_message.message.ListFields()[-1][1][0].name}}.{{field.name}}.size() > 0)
+ {
+ {% if field.type == 11 -%}
+ ToProtoData(input.oneof_{{detailed_message.message.ListFields()[-1][1][0].name}}.{{field.name}}[0], output->mutable_{{field.name}}());
+ {%- elif field.type == 14 %}
+ {%- set list1 = field.type_name.split('.') -%}
+ output->set_{{field.name}}(({{list1[4]}})input.oneof_{{detailed_message.message.ListFields()[-1][1][0].name}}.{{field.name}}[0]);
+ {%- else %}
+ output->set_{{field.name}}(input.oneof_{{detailed_message.message.ListFields()[-1][1][0].name}}.{{field.name}}[0]);
+ {%- endif %}
+ }
+ {% endif %}
+ {%- endfor -%}
+ {% endif %}
+
+ return 0;
+}
+{% endfor %}
diff --git a/kortex_actuator_driver/templates/proto_converter.h.jinja2 b/kortex_actuator_driver/templates/proto_converter.h.jinja2
new file mode 100644
index 00000000..049cc9a2
--- /dev/null
+++ b/kortex_actuator_driver/templates/proto_converter.h.jinja2
@@ -0,0 +1,52 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_{{currentPackageName}}PROTO_CONVERTER_H_
+#define _KORTEX_{{currentPackageName}}PROTO_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include <{{currentFilename}}.pb.h>
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+{% for detailed_message in item -%}
+#include "kortex_actuator_driver/{{detailed_message.message.name}}.h"
+{% endfor %}
+
+using namespace {{currentNamespace}};
+
+{% for detailed_message in item -%}
+int ToProtoData(kortex_actuator_driver::{{detailed_message.message.name}} intput, {{detailed_message.message.name}} *output);
+{% endfor %}
+#endif
\ No newline at end of file
diff --git a/kortex_actuator_driver/templates/ros_converter.cpp.jinja2 b/kortex_actuator_driver/templates/ros_converter.cpp.jinja2
new file mode 100644
index 00000000..cdc873f7
--- /dev/null
+++ b/kortex_actuator_driver/templates/ros_converter.cpp.jinja2
@@ -0,0 +1,86 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "{{currentFilename|lower}}_ros_converter.h"
+{% if 'Common' not in currentPackageName %}
+#include "common_ros_converter.h"
+{% endif %}
+
+{% for detailed_message in item -%}
+int ToRosData({{detailed_message.message.name}} input, kortex_actuator_driver::{{detailed_message.message.name}} &output)
+{
+ {%- for field in detailed_message.message.field %}
+ {%- if not field.HasField("oneof_index") %}
+ {%- if field.label == 3 %} {# Si c'est un repeated #}
+ {% if field.type == 11 %}
+ {%- set splitTypeName = field.type_name.split('.') -%}
+ output.{{field.name}}.clear();
+ for(int i = 0; i < input.{{field.name|lower}}_size(); i++)
+ {
+ gen3_actuator::{{splitTypeName[4]}} temp;
+ ToRosData(input.{{field.name}}(i), temp);
+ output.{{field.name}}.push_back(temp);
+ }
+ {%- else %}
+ output.{{field.name}}.clear();
+ for(int i = 0; i < input.{{field.name|lower}}_size(); i++)
+ {
+ output.{{field.name}}.push_back(input.{{field.name|lower}}(i));
+ }
+ {%- endif %}
+ {%- else %}
+ {%- if field.type == 11 %}
+ ToRosData(input.{{field.name}}(), output.{{field.name}});
+ {%- elif field.type == 14 %}
+ {%- set list1 = field.type_name.split('.') -%} {# Cette ligne sert à enlever les namespace dans le nom du type #}
+ output.{{field.name}} = input.{{field.name}}();
+ {%- elif field.type == 12 %}
+ output.{{field.name}} = std::vector(input.{{field.name}}().begin(), input.{{field.name}}().end());
+ {%- else %}
+ output.{{field.name}} = input.{{field.name}}();
+ {%- endif %}
+ {%- endif %}
+ {%- endif %}
+ {%- endfor %}
+
+ {% if detailed_message.HasOneOf == "true" %}
+ auto oneof_type = input.{{detailed_message.message.ListFields()[-1][1][0].name}}_case();
+
+ switch(oneof_type)
+ {
+ {%- for field in detailed_message.message.field -%}
+ {%- if field.HasField("oneof_index") -%}
+ {%- set splitTypeName = field.type_name.split('.') %}
+ {%- set EnumName = field.name.replace("_", " ").title().replace(" ", "") %}
+ case {{detailed_message.message.name}}::k{{EnumName}}:
+ {
+ {%- if field.type == 11 %}
+ gen3_actuator::{{splitTypeName[4]}} temp;
+ ToRosData(input.{{field.name}}(), temp);
+ output.oneof_{{detailed_message.message.ListFields()[-1][1][0].name}}.{{field.name}}.push_back(temp);
+ {%- elif field.type == 14 %}
+ output.oneof_{{detailed_message.message.ListFields()[-1][1][0].name}}.{{field.name}}.push_back(input.{{field.name}}());
+ {% endif %}
+ break;
+ }
+ {% endif %}
+ {%- endfor %}
+ }
+ {% endif -%}
+
+ return 0;
+}
+{% endfor %}
diff --git a/kortex_actuator_driver/templates/ros_converter.h.jinja2 b/kortex_actuator_driver/templates/ros_converter.h.jinja2
new file mode 100644
index 00000000..254292c2
--- /dev/null
+++ b/kortex_actuator_driver/templates/ros_converter.h.jinja2
@@ -0,0 +1,52 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_{{currentPackageName}}ROS_CONVERTER_H_
+#define _KORTEX_{{currentPackageName}}ROS_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include <{{currentFilename}}.pb.h>
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+{% for detailed_message in item -%}
+#include "kortex_actuator_driver/{{detailed_message.message.name}}.h"
+{% endfor %}
+
+using namespace {{currentNamespace}};
+
+{% for detailed_message in item -%}
+int ToRosData({{detailed_message.message.name}} input, kortex_actuator_driver::{{detailed_message.message.name}} &output);
+{% endfor %}
+#endif
\ No newline at end of file
diff --git a/kortex_actuator_driver/templates/ros_enum.jinja2 b/kortex_actuator_driver/templates/ros_enum.jinja2
new file mode 100644
index 00000000..164146fc
--- /dev/null
+++ b/kortex_actuator_driver/templates/ros_enum.jinja2
@@ -0,0 +1,3 @@
+{% for member in item.value %}
+uint32 {{member.name}} = {{member.number}}
+{% endfor %}
diff --git a/kortex_actuator_driver/templates/ros_message.jinja2 b/kortex_actuator_driver/templates/ros_message.jinja2
new file mode 100644
index 00000000..167f685f
--- /dev/null
+++ b/kortex_actuator_driver/templates/ros_message.jinja2
@@ -0,0 +1,44 @@
+{%- for member in item.field -%}
+{%- if not member.HasField("oneof_index") -%}
+{%- if member.type == 9 %} {# TYPE_STRING #}
+string{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 12 %} {# TYPE_BYTES #}
+uint8[] {{member.name}}
+{%- elif member.type == 1 %} {# TYPE_DOUBLE #}
+float64{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 7 %} {# TYPE_FIXED32 #}
+uint32{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 6 %} {# TYPE_FIXED64 #}
+uint64{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 2 %} {# TYPE_FLOAT #}
+float32{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 5 %} {# TYPE_INT32 #}
+int32{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 3 %} {# TYPE_INT64 #}
+int64{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 15 %} {# TYPE_SFIXED32 #}
+int32{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 16 %} {# TYPE_SFIXED64 #}
+int64{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 17 %} {# TYPE_SINT32 #}
+int32{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 18 %} {# TYPE_SINT64 #}
+int64{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 13 %} {# TYPE_UINT32 #}
+uint32{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 4 %} {# TYPE_UINT64 #}
+uint64{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 14 -%} {# TYPE_ENUM #}
+{% set list1 = member.type_name.split('.') %}
+uint32{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- elif member.type == 8 %} {# TYPE_BOOL #}
+bool {{member.name}}
+{%- elif member.type == 11 %}{# TYPE MESSAGE #}
+{% set list1 = member.type_name.split('.') %}
+{{list1|last}}{%- if member.label == 3 -%}[]{% endif %} {{member.name}}
+{%- endif -%}
+{%- endif -%}
+{%- endfor -%}
+{%- if HasOneOf %}
+{{item.name}}_{{item.ListFields()[-1][1][0].name}} oneof_{{item.ListFields()[-1][1][0].name}}
+{%- endif -%}
\ No newline at end of file
diff --git a/kortex_actuator_driver/templates/ros_oneof.jinja2 b/kortex_actuator_driver/templates/ros_oneof.jinja2
new file mode 100644
index 00000000..4fac302a
--- /dev/null
+++ b/kortex_actuator_driver/templates/ros_oneof.jinja2
@@ -0,0 +1,9 @@
+{%- for member in item.field -%}
+{% if member.HasField("oneof_index") %}
+{% if member.type == 11 %}
+{% set list1 = member.type_name.split('.') %}{{list1[4]}}[] {{member.name}}
+{%- else -%}
+uint32[] {{member.name}}
+{%- endif -%}
+{%- endif -%}
+{% endfor %}
\ No newline at end of file
diff --git a/kortex_actuator_driver/templates/ros_service.jinja2 b/kortex_actuator_driver/templates/ros_service.jinja2
new file mode 100644
index 00000000..cc015cf8
--- /dev/null
+++ b/kortex_actuator_driver/templates/ros_service.jinja2
@@ -0,0 +1,5 @@
+{% set split_input_type = item.input_type.split('.') %}
+{%- set split_output_type = item.output_type.split('.') -%}
+{{split_input_type[4]}} input
+---
+{{split_output_type[4]}} output
\ No newline at end of file
diff --git a/kortex_api/include/.gitignore b/kortex_api/include/.gitignore
new file mode 100644
index 00000000..e69de29b
diff --git a/kortex_api/lib/.gitignore b/kortex_api/lib/.gitignore
new file mode 100644
index 00000000..e69de29b
diff --git a/kortex_api/readme.md b/kortex_api/readme.md
new file mode 100644
index 00000000..681edf0b
--- /dev/null
+++ b/kortex_api/readme.md
@@ -0,0 +1,39 @@
+
+# Kortex API
+This package contains all the files needed to use the c++ Kortex API which is used by all the driver nodes and the device manager. This package is mandatory because most of the other package refer to it. A more detailed documentation is available on the Kortex API [repository](https://github.com/Kinovarobotics/kortex).
+
+
+
+1. [Install Cpp Kortex Api & the needed dependencies](#install-cpp-kortex-api-the-needed-dependencies)
+1. [Content](#content)
+ 1. [include](#include)
+ 1. [lib](#lib)
+
+
+
+
+## Install Cpp Kortex Api & the needed dependencies
+
+> *Manual installation using downloaded archive:*
+> + Download the archive via the [Kinova drive](https://drive.google.com/file/d/19zfCNlRUfNBbZoMW9LOpLjVrYOO2BwYb/view).
+> + Uncompress the content of the archive and copy the content of /kortex_api/cpp/linux_x86/include/ and /kortex_api/cpp/linux_x86/lib/ respectively in kortex_api/include/ and kortex_api/lib/ .
+> + Remove the folder /kortex_api/include/google/
+
+
+
+## Content
+The content of this package should not be deleted or changed.
+
+### include
+Contains header files of the Kortex API.
+
+### lib
+Contains binaries files of the Kortex API.
diff --git a/kortex_description/CMakeLists.txt b/kortex_description/CMakeLists.txt
new file mode 100644
index 00000000..bb671d14
--- /dev/null
+++ b/kortex_description/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 2.8.3)
+
+project(kortex_description)
+
+find_package(catkin REQUIRED)
+
+catkin_package()
+
+find_package(roslaunch)
+
+foreach(dir config launch meshes urdf)
+ install(DIRECTORY ${dir}/
+ DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/${dir})
+endforeach(dir)
diff --git a/kortex_description/config/joint_names_JACO3_URDF_V10.yaml b/kortex_description/config/joint_names_JACO3_URDF_V10.yaml
new file mode 100644
index 00000000..39d5611d
--- /dev/null
+++ b/kortex_description/config/joint_names_JACO3_URDF_V10.yaml
@@ -0,0 +1 @@
+controller_joint_names: ['Actuator1', 'Actuator2', 'Actuator3', 'Actuator4', 'Actuator5', 'Actuator6', 'Actuator7', ]
diff --git a/kortex_description/launch/display.launch b/kortex_description/launch/display.launch
new file mode 100644
index 00000000..c695a85d
--- /dev/null
+++ b/kortex_description/launch/display.launch
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
diff --git a/kortex_description/launch/gazebo.launch b/kortex_description/launch/gazebo.launch
new file mode 100644
index 00000000..70ad31fa
--- /dev/null
+++ b/kortex_description/launch/gazebo.launch
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/kortex_description/meshes/Bracelet_Link.STL b/kortex_description/meshes/Bracelet_Link.STL
new file mode 100644
index 00000000..e8a9f58e
Binary files /dev/null and b/kortex_description/meshes/Bracelet_Link.STL differ
diff --git a/kortex_description/meshes/EndEffector_Link.STL b/kortex_description/meshes/EndEffector_Link.STL
new file mode 100644
index 00000000..6dc3cfa9
Binary files /dev/null and b/kortex_description/meshes/EndEffector_Link.STL differ
diff --git a/kortex_description/meshes/ForeArm_Link.STL b/kortex_description/meshes/ForeArm_Link.STL
new file mode 100644
index 00000000..21ee2dbe
Binary files /dev/null and b/kortex_description/meshes/ForeArm_Link.STL differ
diff --git a/kortex_description/meshes/HalfArm1_Link.STL b/kortex_description/meshes/HalfArm1_Link.STL
new file mode 100644
index 00000000..0d4d324c
Binary files /dev/null and b/kortex_description/meshes/HalfArm1_Link.STL differ
diff --git a/kortex_description/meshes/HalfArm2_Link.STL b/kortex_description/meshes/HalfArm2_Link.STL
new file mode 100644
index 00000000..6d23022d
Binary files /dev/null and b/kortex_description/meshes/HalfArm2_Link.STL differ
diff --git a/kortex_description/meshes/Shoulder_Link.STL b/kortex_description/meshes/Shoulder_Link.STL
new file mode 100644
index 00000000..6cfaedc1
Binary files /dev/null and b/kortex_description/meshes/Shoulder_Link.STL differ
diff --git a/kortex_description/meshes/Wrist1_Link.STL b/kortex_description/meshes/Wrist1_Link.STL
new file mode 100644
index 00000000..7ab8f92b
Binary files /dev/null and b/kortex_description/meshes/Wrist1_Link.STL differ
diff --git a/kortex_description/meshes/Wrist2_Link.STL b/kortex_description/meshes/Wrist2_Link.STL
new file mode 100644
index 00000000..95bb979b
Binary files /dev/null and b/kortex_description/meshes/Wrist2_Link.STL differ
diff --git a/kortex_description/meshes/base_link.STL b/kortex_description/meshes/base_link.STL
new file mode 100644
index 00000000..2b29c6a9
Binary files /dev/null and b/kortex_description/meshes/base_link.STL differ
diff --git a/kortex_description/package.xml b/kortex_description/package.xml
new file mode 100644
index 00000000..fe825e87
--- /dev/null
+++ b/kortex_description/package.xml
@@ -0,0 +1,21 @@
+
+ kortex_description
+ 1.0.0
+
+
URDF Description package for ultra_lightweight
+
This package contains configuration data, 3D models and launch files
+for ultra_lightweight robot
+
+ KINOVA
+
+ BSD
+ catkin
+ roslaunch
+ robot_state_publisher
+ rviz
+ joint_state_publisher
+ gazebo
+
+
+
+
\ No newline at end of file
diff --git a/kortex_description/readme.md b/kortex_description/readme.md
new file mode 100644
index 00000000..9d38b9fe
--- /dev/null
+++ b/kortex_description/readme.md
@@ -0,0 +1,15 @@
+
+# Kortex Description
+This package contains the URDF, with the STL files of a Gen3 robot.
+
+
+
+
diff --git a/kortex_description/urdf/JACO3_URDF_V10.urdf b/kortex_description/urdf/JACO3_URDF_V10.urdf
new file mode 100644
index 00000000..99df3ea6
--- /dev/null
+++ b/kortex_description/urdf/JACO3_URDF_V10.urdf
@@ -0,0 +1,494 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/kortex_device_manager/CMakeLists.txt b/kortex_device_manager/CMakeLists.txt
new file mode 100644
index 00000000..cd5b2aaf
--- /dev/null
+++ b/kortex_device_manager/CMakeLists.txt
@@ -0,0 +1,40 @@
+
+cmake_minimum_required(VERSION 2.8.3)
+project(kortex_device_manager)
+
+add_compile_options(-std=c++11)
+add_definitions(-D_OS_UNIX)
+
+## Find catkin and any catkin packages
+find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation)
+
+file(GLOB_RECURSE msg_list RELATIVE ${PROJECT_SOURCE_DIR}/msg "*.msg")
+file(GLOB_RECURSE srv_list RELATIVE ${PROJECT_SOURCE_DIR}/srv "*.srv")
+file(GLOB_RECURSE cpp_list RELATIVE ${PROJECT_SOURCE_DIR} "src/*.cpp")
+
+## Declare ROS messages and services
+add_message_files(DIRECTORY msg FILES ${msg_list})
+add_service_files(DIRECTORY srv FILES ${srv_list})
+
+## Generate added messages and services
+generate_messages(DEPENDENCIES std_msgs)
+
+## Declare a catkin package
+catkin_package()
+
+include_directories(include ${catkin_INCLUDE_DIRS})
+include_directories(include ${PROJECT_SOURCE_DIR}/src)
+include_directories(include ${PROJECT_SOURCE_DIR}/../kortex_api/include/client)
+include_directories(include ${PROJECT_SOURCE_DIR}/../kortex_api/include/client_stubs)
+include_directories(include ${PROJECT_SOURCE_DIR}/../kortex_api/include/messages)
+include_directories(include ${PROJECT_SOURCE_DIR}/../kortex_api/include/common)
+include_directories(include ${PROJECT_SOURCE_DIR}/src/util)
+
+link_directories(${PROJECT_SOURCE_DIR}/../kortex_api/lib/release)
+
+add_executable(${PROJECT_NAME} ${cpp_list})
+
+target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES} CppKinovaApi gcov)
+
+add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}_gencpp)
+
diff --git a/kortex_device_manager/RosGeneration.py b/kortex_device_manager/RosGeneration.py
new file mode 100644
index 00000000..a93fc316
--- /dev/null
+++ b/kortex_device_manager/RosGeneration.py
@@ -0,0 +1,202 @@
+#!/usr/bin/env python
+
+import sys
+
+from google.protobuf.compiler import plugin_pb2 as plugin
+from google.protobuf import json_format as json_f
+
+import jinja2
+
+import itertools
+import json
+import types
+import os
+import sys
+
+from google.protobuf.descriptor_pb2 import DescriptorProto, EnumDescriptorProto, ServiceDescriptorProto, FieldDescriptorProto, OneofDescriptorProto
+
+#Class that holds a protobuf message and some other details needed by the generator(jinja2 template).
+class DetailedMessage:
+ def __init__(self, message=None):
+ self.message = message
+ self.HasOneOf = "false"
+ self.oneOfList = []
+
+#Class that holds a protobuf service and some other details needed by the generator(jinja2 template).
+class DetailedPackage:
+ def __init__(self, service=None):
+ self.name = "NoName"
+ self.service = service
+
+#JINJA2 function to render a file from a template.
+def render(tpl_path, context):
+ path, filename = os.path.split(tpl_path)
+ return jinja2.Environment(loader=jinja2.FileSystemLoader(path or './')).get_template(filename).render(**context)
+
+#Main plugin function
+def generate_code(request, response):
+
+ #The context is the object sent to the JINJA2 template
+ context = types.SimpleNamespace()
+ context.serviceVersion = 1
+
+ context.detailedPackages = []
+
+ MainFilePath = os.path.join(".", "src/main.cpp")
+ function_list = []
+ fileIndex = 0
+
+ for proto_file in request.proto_file:
+ context.detailedPackages.append(DetailedPackage())
+ context.detailedPackages[fileIndex].name = proto_file.package.split(".")[-1]
+ context.detailedPackages[fileIndex].filename = proto_file.name.split(".")[0]
+ context.detailedPackages[fileIndex].namespace = proto_file.package.replace(".", "::")
+ context.detailedPackages[fileIndex].HasRPC = 0
+ context.detailedPackages[fileIndex].HasMessage = 0
+
+ HeaderFilePath = os.path.join(".", "src/node.h")
+ CppFilePath = os.path.join(".", "src/node.cpp")
+
+ #We lower the case to respect ROS coding standard style
+ CppProtoConverterFilePath = os.path.join(".", "src/{}_proto_converter.cpp".format(proto_file.name.split(".")[0].lower()))
+ HeaderProtoConverterFilePath = os.path.join(".", "src/{}_proto_converter.h".format(proto_file.name.split(".")[0].lower()))
+ CppRosConverterFilePath = os.path.join(".", "src/{}_ros_converter.cpp".format(proto_file.name.split(".")[0].lower()))
+ HeaderRosConverterFilePath = os.path.join(".", "src/{}_ros_converter.h".format(proto_file.name.split(".")[0].lower()))
+
+ list_detailedMessage = []
+
+ # For every item in the current proto file
+ for item, package in traverse(proto_file):
+ context.HasOneOf = 0
+
+
+ if isinstance(item, EnumDescriptorProto):
+ context.item = item
+
+ ros_enumPath = os.path.join(".", "msg/{}.msg".format(item.name))
+
+ with open(ros_enumPath, 'wt') as serviceFile:
+ serviceFile.write(render("./templates/ros_enum.jinja2", context.__dict__))
+ #If this it a message
+ if isinstance(item, DescriptorProto):
+ tempMessage = DetailedMessage(item)
+
+ context.detailedPackages[fileIndex].HasMessage = 1
+
+ for member in item.field:
+ #If a member is part of a oneof, it will have this additional field
+ if member.HasField("oneof_index"):
+ context.HasOneOf = 1
+ tempMessage.HasOneOf = "true"
+ else:
+ context.HasOneOf = 0
+ tempMessage.HasOneOf = "false"
+
+ context.item = item
+
+ #If the proto file contains a ONEOF we need to generate a separate file to handle it.
+ if context.HasOneOf == 1:
+
+ #This line gets the list of ONEOF that is in the current message.
+ oneOfList = item.ListFields()[-1][1]
+
+ tempMessage.oneOfList = item.ListFields()[-1][1]
+ ros_oneofPath = os.path.join(".", "msg/{}_{}.msg".format(item.name, oneOfList[0].name))
+
+ with open(ros_oneofPath, 'wt') as serviceFile:
+ serviceFile.write(render("./templates/ros_oneof.jinja2", context.__dict__))
+
+
+ list_detailedMessage.append(tempMessage)
+ ros_messagePath = os.path.join(".", "msg/{}.msg".format(item.name))
+
+ #We call jinja2 to generate a ROS message.
+ with open(ros_messagePath, 'wt') as serviceFile:
+ serviceFile.write(render("./templates/ros_message.jinja2", context.__dict__))
+
+ #If this is a service (A group of method)
+ if isinstance(item, ServiceDescriptorProto):
+ for method in item.method:
+ context.item = method
+ if "Topic" not in method.name:
+ function_list.append(method.name)
+ ros_servicePath = os.path.join(".", "srv/{}.srv".format(method.name))
+ with open(ros_servicePath, 'wt') as serviceFile:
+ serviceFile.write(render("./templates/ros_service.jinja2", context.__dict__))
+
+ context.detailedPackages[fileIndex].service = item
+ context.detailedPackages[fileIndex].HasRPC = 1
+
+ context.currentPackageName = context.detailedPackages[fileIndex].name
+ context.currentNamespace = proto_file.package.replace(".", "::")
+ context.currentFilename = context.detailedPackages[fileIndex].filename
+ context.item = list_detailedMessage
+
+ if context.detailedPackages[fileIndex].HasMessage == 1:
+ #Wecall jinja2 to generate a prot/ROS converter for every protobuf message.
+ with open(CppProtoConverterFilePath, 'wt') as converterFile:
+ converterFile.write(render("./templates/proto_converter.cpp.jinja2", context.__dict__))
+ with open(HeaderProtoConverterFilePath, 'wt') as converterFile:
+ converterFile.write(render("./templates/proto_converter.h.jinja2", context.__dict__))
+ with open(CppRosConverterFilePath, 'wt') as converterFile:
+ converterFile.write(render("./templates/ros_converter.cpp.jinja2", context.__dict__))
+ with open(HeaderRosConverterFilePath, 'wt') as converterFile:
+ converterFile.write(render("./templates/ros_converter.h.jinja2", context.__dict__))
+
+ fileIndex = fileIndex + 1
+
+ context.list_function = function_list
+
+ #We jinja2 to generate the ROS node.
+ with open(HeaderFilePath, 'wt') as nodeFile:
+ nodeFile.write(render("./templates/NodeServices.h.jinja2", context.__dict__))
+ with open(CppFilePath, 'wt') as nodeFile:
+ nodeFile.write(render("./templates/NodeServices.cpp.jinja2", context.__dict__))
+ with open(MainFilePath, 'wt') as mainFile:
+ mainFile.write(render("./templates/main.jinja2", context.__dict__))
+
+def traverse(proto_file):
+ #recursive function that browse a protobof item
+ def _traverse(package, items):
+ for item in items:
+ yield item, package
+
+ if isinstance(item, DescriptorProto):
+ for enum in item.enum_type:
+ yield enum, package
+
+ for nested in item.nested_type:
+ nested_package = package + item.name
+
+ for nested_item in _traverse(nested, nested_package):
+ yield nested_item, nested_package
+ if isinstance(item, ServiceDescriptorProto):
+ for rpc in item.method:
+ yield rpc, package
+
+ #return a list of everything found in the proto file
+ return itertools.chain(
+ _traverse(proto_file.package, proto_file.enum_type),
+ _traverse(proto_file.package, proto_file.message_type),
+ _traverse(proto_file.package, proto_file.service),
+ )
+
+if __name__ == '__main__':
+ # Read request message from stdin
+ data = sys.stdin.buffer.read()
+
+ # Parse request
+ request = plugin.CodeGeneratorRequest()
+ request.ParseFromString(data)
+
+ # Create response
+ response = plugin.CodeGeneratorResponse()
+
+ # Generate code
+ generate_code(request, response)
+
+ # Serialise response message
+ output = response.SerializeToString()
+
+ # Write to stdout
+ sys.stdout.buffer.write(output)
\ No newline at end of file
diff --git a/kortex_device_manager/build/.gitignore b/kortex_device_manager/build/.gitignore
new file mode 100644
index 00000000..e69de29b
diff --git a/kortex_device_manager/kortex_device_manager.sh b/kortex_device_manager/kortex_device_manager.sh
new file mode 100755
index 00000000..011eee96
--- /dev/null
+++ b/kortex_device_manager/kortex_device_manager.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+python3 -u RosGeneration.py
+
diff --git a/kortex_device_manager/msg/ArmState.msg b/kortex_device_manager/msg/ArmState.msg
new file mode 100644
index 00000000..d85bd69d
--- /dev/null
+++ b/kortex_device_manager/msg/ArmState.msg
@@ -0,0 +1,22 @@
+
+uint32 UNSPECIFIED_ARM_STATE = 0
+
+uint32 BASE_INITIALIZATION = 1
+
+uint32 IDLE = 2
+
+uint32 ARM_INITIALIZATION = 3
+
+uint32 ARM_IN_FAULT = 4
+
+uint32 ARM_MAINTENANCE = 5
+
+uint32 ARM_SERVOING_LOW_LEVEL = 6
+
+uint32 ARM_SERVOING_READY = 7
+
+uint32 ARM_SERVOING_PLAYING_SEQUENCE = 8
+
+uint32 ARM_SERVOING_MANUALLY_CONTROLLED = 9
+
+uint32 RESERVED = 255
diff --git a/kortex_device_manager/msg/BootloaderVersion.msg b/kortex_device_manager/msg/BootloaderVersion.msg
new file mode 100644
index 00000000..d6dc8352
--- /dev/null
+++ b/kortex_device_manager/msg/BootloaderVersion.msg
@@ -0,0 +1,2 @@
+
+uint32 bootloader_version
\ No newline at end of file
diff --git a/kortex_device_manager/msg/Connection.msg b/kortex_device_manager/msg/Connection.msg
new file mode 100644
index 00000000..ca08b6c8
--- /dev/null
+++ b/kortex_device_manager/msg/Connection.msg
@@ -0,0 +1,5 @@
+
+
+UserProfileHandle user_handle
+string connection_information
+uint32 connection_identifier
\ No newline at end of file
diff --git a/kortex_device_manager/msg/DeviceHandle.msg b/kortex_device_manager/msg/DeviceHandle.msg
new file mode 100644
index 00000000..49f84366
--- /dev/null
+++ b/kortex_device_manager/msg/DeviceHandle.msg
@@ -0,0 +1,5 @@
+
+
+uint32 device_type
+uint32 device_identifier
+uint32 order
\ No newline at end of file
diff --git a/kortex_device_manager/msg/DeviceHandles.msg b/kortex_device_manager/msg/DeviceHandles.msg
new file mode 100644
index 00000000..739f4ff3
--- /dev/null
+++ b/kortex_device_manager/msg/DeviceHandles.msg
@@ -0,0 +1,3 @@
+
+
+DeviceHandle[] device_handle
\ No newline at end of file
diff --git a/kortex_device_manager/msg/DeviceType.msg b/kortex_device_manager/msg/DeviceType.msg
new file mode 100644
index 00000000..b4dd97c2
--- /dev/null
+++ b/kortex_device_manager/msg/DeviceType.msg
@@ -0,0 +1,3 @@
+
+
+uint32 device_type
\ No newline at end of file
diff --git a/kortex_device_manager/msg/DeviceTypes.msg b/kortex_device_manager/msg/DeviceTypes.msg
new file mode 100644
index 00000000..5a55df07
--- /dev/null
+++ b/kortex_device_manager/msg/DeviceTypes.msg
@@ -0,0 +1,14 @@
+
+uint32 UNSPECIFIED_DEVICE_TYPE = 0
+
+uint32 BASE = 1
+
+uint32 VISION = 2
+
+uint32 BIG_ACTUATOR = 3
+
+uint32 SMALL_ACTUATOR = 4
+
+uint32 INTERCONNECT = 5
+
+uint32 GRIPPER = 6
diff --git a/kortex_device_manager/msg/Empty.msg b/kortex_device_manager/msg/Empty.msg
new file mode 100644
index 00000000..e69de29b
diff --git a/kortex_device_manager/msg/FirmwareVersion.msg b/kortex_device_manager/msg/FirmwareVersion.msg
new file mode 100644
index 00000000..ef44f90b
--- /dev/null
+++ b/kortex_device_manager/msg/FirmwareVersion.msg
@@ -0,0 +1,2 @@
+
+uint32 firmware_version
\ No newline at end of file
diff --git a/kortex_device_manager/msg/IPv4Settings.msg b/kortex_device_manager/msg/IPv4Settings.msg
new file mode 100644
index 00000000..5be19d99
--- /dev/null
+++ b/kortex_device_manager/msg/IPv4Settings.msg
@@ -0,0 +1,4 @@
+
+uint32 ipv4_address
+uint32 ipv4_subnet_mask
+uint32 ipv4_default_gateway
\ No newline at end of file
diff --git a/kortex_device_manager/msg/MACAddress.msg b/kortex_device_manager/msg/MACAddress.msg
new file mode 100644
index 00000000..a2764fac
--- /dev/null
+++ b/kortex_device_manager/msg/MACAddress.msg
@@ -0,0 +1,2 @@
+
+uint8[] mac_address
\ No newline at end of file
diff --git a/kortex_device_manager/msg/ModelNumber.msg b/kortex_device_manager/msg/ModelNumber.msg
new file mode 100644
index 00000000..adb82526
--- /dev/null
+++ b/kortex_device_manager/msg/ModelNumber.msg
@@ -0,0 +1,2 @@
+
+string model_number
\ No newline at end of file
diff --git a/kortex_device_manager/msg/NotificationHandle.msg b/kortex_device_manager/msg/NotificationHandle.msg
new file mode 100644
index 00000000..bd72812b
--- /dev/null
+++ b/kortex_device_manager/msg/NotificationHandle.msg
@@ -0,0 +1,2 @@
+
+uint32 identifier
\ No newline at end of file
diff --git a/kortex_device_manager/msg/NotificationOptions.msg b/kortex_device_manager/msg/NotificationOptions.msg
new file mode 100644
index 00000000..6ff46842
--- /dev/null
+++ b/kortex_device_manager/msg/NotificationOptions.msg
@@ -0,0 +1,5 @@
+
+
+uint32 type
+uint32 rate_m_sec
+float32 threshold_value
\ No newline at end of file
diff --git a/kortex_device_manager/msg/NotificationType.msg b/kortex_device_manager/msg/NotificationType.msg
new file mode 100644
index 00000000..79dd058c
--- /dev/null
+++ b/kortex_device_manager/msg/NotificationType.msg
@@ -0,0 +1,8 @@
+
+uint32 UNSPECIFIED_NOTIFICATION_TYPE = 0
+
+uint32 THRESHOLD = 1
+
+uint32 FIX_RATE = 2
+
+uint32 EVENT = 3
diff --git a/kortex_device_manager/msg/PartNumber.msg b/kortex_device_manager/msg/PartNumber.msg
new file mode 100644
index 00000000..0cd6468f
--- /dev/null
+++ b/kortex_device_manager/msg/PartNumber.msg
@@ -0,0 +1,2 @@
+
+string part_number
\ No newline at end of file
diff --git a/kortex_device_manager/msg/PartNumberRevision.msg b/kortex_device_manager/msg/PartNumberRevision.msg
new file mode 100644
index 00000000..90cb8f65
--- /dev/null
+++ b/kortex_device_manager/msg/PartNumberRevision.msg
@@ -0,0 +1,2 @@
+
+string part_number_revision
\ No newline at end of file
diff --git a/kortex_device_manager/msg/Permission.msg b/kortex_device_manager/msg/Permission.msg
new file mode 100644
index 00000000..c5399e9c
--- /dev/null
+++ b/kortex_device_manager/msg/Permission.msg
@@ -0,0 +1,8 @@
+
+uint32 NO_PERMISSION = 0
+
+uint32 READ_PERMISSION = 1
+
+uint32 UPDATE_PERMISSION = 2
+
+uint32 DELETE_PERMISSION = 4
diff --git a/kortex_device_manager/msg/PowerOnSelfTestResult.msg b/kortex_device_manager/msg/PowerOnSelfTestResult.msg
new file mode 100644
index 00000000..53a0cef1
--- /dev/null
+++ b/kortex_device_manager/msg/PowerOnSelfTestResult.msg
@@ -0,0 +1,2 @@
+
+uint32 power_on_self_test_result
\ No newline at end of file
diff --git a/kortex_device_manager/msg/RebootRqst.msg b/kortex_device_manager/msg/RebootRqst.msg
new file mode 100644
index 00000000..befd3fc3
--- /dev/null
+++ b/kortex_device_manager/msg/RebootRqst.msg
@@ -0,0 +1,2 @@
+
+uint32 delay
\ No newline at end of file
diff --git a/kortex_device_manager/msg/RunMode.msg b/kortex_device_manager/msg/RunMode.msg
new file mode 100644
index 00000000..7b3b1a3a
--- /dev/null
+++ b/kortex_device_manager/msg/RunMode.msg
@@ -0,0 +1,3 @@
+
+
+uint32 run_mode
\ No newline at end of file
diff --git a/kortex_device_manager/msg/RunModes.msg b/kortex_device_manager/msg/RunModes.msg
new file mode 100644
index 00000000..15c2a7da
--- /dev/null
+++ b/kortex_device_manager/msg/RunModes.msg
@@ -0,0 +1,10 @@
+
+uint32 RUN_MODE = 0
+
+uint32 CALIBRATION_MODE = 1
+
+uint32 CONFIGURATION_MODE = 2
+
+uint32 DEBUG_MODE = 3
+
+uint32 TUNING_MODE = 4
diff --git a/kortex_device_manager/msg/SafetyConfiguration.msg b/kortex_device_manager/msg/SafetyConfiguration.msg
new file mode 100644
index 00000000..6f1f0819
--- /dev/null
+++ b/kortex_device_manager/msg/SafetyConfiguration.msg
@@ -0,0 +1,7 @@
+
+
+SafetyHandle handle
+float32 error_threshold
+float32 warning_threshold
+
+SafetyEnable enable
\ No newline at end of file
diff --git a/kortex_device_manager/msg/SafetyConfigurationList.msg b/kortex_device_manager/msg/SafetyConfigurationList.msg
new file mode 100644
index 00000000..8ae23b3d
--- /dev/null
+++ b/kortex_device_manager/msg/SafetyConfigurationList.msg
@@ -0,0 +1,3 @@
+
+
+SafetyConfiguration[] configuration
\ No newline at end of file
diff --git a/kortex_device_manager/msg/SafetyEnable.msg b/kortex_device_manager/msg/SafetyEnable.msg
new file mode 100644
index 00000000..771f7400
--- /dev/null
+++ b/kortex_device_manager/msg/SafetyEnable.msg
@@ -0,0 +1,4 @@
+
+
+SafetyHandle handle
+bool enable
\ No newline at end of file
diff --git a/kortex_device_manager/msg/SafetyHandle.msg b/kortex_device_manager/msg/SafetyHandle.msg
new file mode 100644
index 00000000..bd72812b
--- /dev/null
+++ b/kortex_device_manager/msg/SafetyHandle.msg
@@ -0,0 +1,2 @@
+
+uint32 identifier
\ No newline at end of file
diff --git a/kortex_device_manager/msg/SafetyInformation.msg b/kortex_device_manager/msg/SafetyInformation.msg
new file mode 100644
index 00000000..66be9094
--- /dev/null
+++ b/kortex_device_manager/msg/SafetyInformation.msg
@@ -0,0 +1,16 @@
+
+
+SafetyHandle handle
+bool can_change_safety_state
+bool has_warning_threshold
+bool has_error_threshold
+
+uint32 limit_type
+float32 default_warning_threshold
+float32 default_error_threshold
+float32 upper_hard_limit
+float32 lower_hard_limit
+
+uint32 status
+
+uint32 unit
\ No newline at end of file
diff --git a/kortex_device_manager/msg/SafetyInformationList.msg b/kortex_device_manager/msg/SafetyInformationList.msg
new file mode 100644
index 00000000..ff11edbe
--- /dev/null
+++ b/kortex_device_manager/msg/SafetyInformationList.msg
@@ -0,0 +1,3 @@
+
+
+SafetyInformation[] information
\ No newline at end of file
diff --git a/kortex_device_manager/msg/SafetyLimitType.msg b/kortex_device_manager/msg/SafetyLimitType.msg
new file mode 100644
index 00000000..f0beacf4
--- /dev/null
+++ b/kortex_device_manager/msg/SafetyLimitType.msg
@@ -0,0 +1,8 @@
+
+uint32 UNSPECIFIED_SAFETY_LIMIT_TYPE = 0
+
+uint32 MINIMAL_LIMIT = 1
+
+uint32 MAXIMAL_LIMIT = 2
+
+uint32 EVENT_LIMIT = 3
diff --git a/kortex_device_manager/msg/SafetyNotification.msg b/kortex_device_manager/msg/SafetyNotification.msg
new file mode 100644
index 00000000..36d88894
--- /dev/null
+++ b/kortex_device_manager/msg/SafetyNotification.msg
@@ -0,0 +1,11 @@
+
+
+SafetyHandle safety_handle
+
+uint32 value
+
+Timestamp timestamp
+
+UserProfileHandle user_handle
+
+Connection connection
\ No newline at end of file
diff --git a/kortex_device_manager/msg/SafetyStatus.msg b/kortex_device_manager/msg/SafetyStatus.msg
new file mode 100644
index 00000000..b82ac221
--- /dev/null
+++ b/kortex_device_manager/msg/SafetyStatus.msg
@@ -0,0 +1,3 @@
+
+
+uint32 value
\ No newline at end of file
diff --git a/kortex_device_manager/msg/SafetyStatusValue.msg b/kortex_device_manager/msg/SafetyStatusValue.msg
new file mode 100644
index 00000000..2ea80554
--- /dev/null
+++ b/kortex_device_manager/msg/SafetyStatusValue.msg
@@ -0,0 +1,8 @@
+
+uint32 UNSPECIFIED = 0
+
+uint32 WARNING = 1
+
+uint32 ERROR = 2
+
+uint32 NORMAL = 3
diff --git a/kortex_device_manager/msg/SafetyThreshold.msg b/kortex_device_manager/msg/SafetyThreshold.msg
new file mode 100644
index 00000000..b50b25e3
--- /dev/null
+++ b/kortex_device_manager/msg/SafetyThreshold.msg
@@ -0,0 +1,4 @@
+
+
+SafetyHandle handle
+float32 value
\ No newline at end of file
diff --git a/kortex_device_manager/msg/SerialNumber.msg b/kortex_device_manager/msg/SerialNumber.msg
new file mode 100644
index 00000000..9831a3ee
--- /dev/null
+++ b/kortex_device_manager/msg/SerialNumber.msg
@@ -0,0 +1,2 @@
+
+string serial_number
\ No newline at end of file
diff --git a/kortex_device_manager/msg/ServiceVersion.msg b/kortex_device_manager/msg/ServiceVersion.msg
new file mode 100644
index 00000000..9665d1c2
--- /dev/null
+++ b/kortex_device_manager/msg/ServiceVersion.msg
@@ -0,0 +1,4 @@
+
+uint32 RESERVED_0 = 0
+
+uint32 CURRENT_VERSION = 1
diff --git a/kortex_device_manager/msg/Timestamp.msg b/kortex_device_manager/msg/Timestamp.msg
new file mode 100644
index 00000000..5e60508c
--- /dev/null
+++ b/kortex_device_manager/msg/Timestamp.msg
@@ -0,0 +1,3 @@
+
+uint32 sec
+uint32 usec
\ No newline at end of file
diff --git a/kortex_device_manager/msg/Unit.msg b/kortex_device_manager/msg/Unit.msg
new file mode 100644
index 00000000..c019aeba
--- /dev/null
+++ b/kortex_device_manager/msg/Unit.msg
@@ -0,0 +1,28 @@
+
+uint32 UNSPECIFIED_UNIT = 0
+
+uint32 CELSIUS = 1
+
+uint32 AMPERE = 2
+
+uint32 VOLT = 3
+
+uint32 METER_PER_SECOND = 4
+
+uint32 DEGREE_PER_SECOND = 5
+
+uint32 METER_PER_SECOND_2 = 6
+
+uint32 DEGREE_PER_SECOND_2 = 7
+
+uint32 NEWTON = 8
+
+uint32 NEWTON_METER = 9
+
+uint32 KILOGRAM = 10
+
+uint32 DEGREE = 11
+
+uint32 TICK = 12
+
+uint32 DEGREE_PER_MILLISECOND = 13
diff --git a/kortex_device_manager/msg/UserProfileHandle.msg b/kortex_device_manager/msg/UserProfileHandle.msg
new file mode 100644
index 00000000..3038380d
--- /dev/null
+++ b/kortex_device_manager/msg/UserProfileHandle.msg
@@ -0,0 +1,3 @@
+
+uint32 identifier
+uint32 permission
\ No newline at end of file
diff --git a/kortex_device_manager/msg/non_generated/KortexError.msg b/kortex_device_manager/msg/non_generated/KortexError.msg
new file mode 100644
index 00000000..45392615
--- /dev/null
+++ b/kortex_device_manager/msg/non_generated/KortexError.msg
@@ -0,0 +1,3 @@
+string description
+uint32 code
+uint32 subCode
\ No newline at end of file
diff --git a/kortex_device_manager/package.xml b/kortex_device_manager/package.xml
new file mode 100644
index 00000000..9c848b67
--- /dev/null
+++ b/kortex_device_manager/package.xml
@@ -0,0 +1,30 @@
+
+
+ kortex_device_manager
+ 1.0.0
+ The kortex package that act as a device manager.
+
+ KINOVA
+
+ BSD
+
+ catkin
+ roscpp
+ rospy
+ std_msgs
+ roscpp
+ rospy
+ std_msgs
+ roscpp
+ rospy
+ std_msgs
+ message_generation
+ message_runtime
+
+
+
+
+
+
+
+
diff --git a/kortex_device_manager/protos/Common.options b/kortex_device_manager/protos/Common.options
new file mode 100644
index 00000000..5f3020ab
--- /dev/null
+++ b/kortex_device_manager/protos/Common.options
@@ -0,0 +1,4 @@
+Kinova.Api.Common.DeviceTypes long_names:false
+Kinova.Api.Common.SafetyStatusValue long_names:false
+Kinova.Api.Common.NotificationType long_names:false
+Kinova.Api.Common.Unit long_names:false
\ No newline at end of file
diff --git a/kortex_device_manager/protos/Common.proto b/kortex_device_manager/protos/Common.proto
new file mode 100644
index 00000000..50f762ec
--- /dev/null
+++ b/kortex_device_manager/protos/Common.proto
@@ -0,0 +1,152 @@
+syntax = "proto3";
+
+package Kinova.Api.Common;
+
+/**
+ * list of possible device types
+ */
+enum DeviceTypes {
+ UNSPECIFIED_DEVICE_TYPE = 0;
+ BASE = 1;
+ VISION = 2;
+ BIG_ACTUATOR = 3;
+ SMALL_ACTUATOR = 4;
+ INTERCONNECT = 5;
+ GRIPPER = 6;
+}
+
+/**
+* Message contains information about a device - device type, device identifier, and the order of the device within the robot
+*/
+message DeviceHandle {
+ DeviceTypes device_type = 1;
+ uint32 device_identifier = 2; // Unique device identifier (used with other services)
+ uint32 order = 3; // Unique value indicating the order of that device versus the others to facilitate representation
+}
+
+/**
+ * list of possible safety statuses
+ */
+enum SafetyStatusValue {
+ UNSPECIFIED = 0;
+ WARNING = 1; //warning safety reached
+ ERROR = 2; //error safety reached
+ NORMAL = 3; //safety is off
+}
+
+/**
+ * Enumeration used as bitfields wih permission field
+ */
+enum Permission {
+ NO_PERMISSION = 0;
+ READ_PERMISSION = 1; //refers to a user's capability to read the entity
+ UPDATE_PERMISSION = 2;//refers to a user's capability to write or modify the entity
+ DELETE_PERMISSION = 4; //refers to a user's capability to delete the entity
+}
+
+/**
+ * list of notification types
+ */
+enum NotificationType {
+ UNSPECIFIED_NOTIFICATION_TYPE = 0;
+ THRESHOLD = 1;
+ FIX_RATE = 2;
+ EVENT = 3; //Event type. Only this one is supported for now
+}
+
+/**
+ * list of units used throughout API methods
+ */
+enum Unit {
+ UNSPECIFIED_UNIT = 0;
+ CELSIUS = 1;
+ AMPERE = 2;
+ VOLT = 3;
+ METER_PER_SECOND = 4;
+ DEGREE_PER_SECOND = 5;
+ METER_PER_SECOND_2 = 6;
+ DEGREE_PER_SECOND_2 = 7;
+ NEWTON = 8;
+ NEWTON_METER =9;
+ KILOGRAM = 10;
+ DEGREE = 11;
+ TICK = 12;
+ DEGREE_PER_MILLISECOND = 13;
+}
+
+/**
+ * Message used when no information needs to be exchanged between client application and robot, and vice versa
+ */
+message Empty {
+}
+
+/**
+ * Notification options
+ */
+message NotificationOptions {
+ NotificationType type = 1; //type of notification
+ uint32 rate_m_sec = 2;
+ float threshold_value = 3;
+}
+
+/**
+ * Handle to a safety
+ */
+message SafetyHandle {
+ uint32 identifier = 1;
+}
+
+/**
+ * Handle to a notification
+ */
+message NotificationHandle {
+ uint32 identifier = 1;
+}
+
+/**
+ * Message that contains a Safety event
+ */
+message SafetyNotification {
+ SafetyHandle safety_handle = 1; //safety handle
+ SafetyStatusValue value = 2; //new safety status
+ Timestamp timestamp = 3; //event timestamp
+ UserProfileHandle user_handle = 4; //user that caused the safety event
+ Connection connection = 5; // connection that caused the safety event
+}
+
+/**
+ * Timestamp based on epoch
+ */
+message Timestamp {
+ uint32 sec = 1; //epoch in seconds since 1970
+ uint32 usec = 2;//microseconds after the second (0-999999)
+}
+
+/**
+ * Handle to an existing User Profile.
+ */
+message UserProfileHandle {
+ uint32 identifier = 1; //User profile identifier
+ fixed32 permission = 2; //must use 'Permission' as bitwise
+}
+
+message Connection {
+ UserProfileHandle user_handle = 1; //user profile handle, or set to zero if no user logged in
+ string connection_information = 2; //connection info (ex. IP address with port number)
+ uint32 connection_identifier = 3; //connection identifier
+}
+
+enum ArmState
+{
+ UNSPECIFIED_ARM_STATE = 0;
+ BASE_INITIALIZATION = 1; // Cannot be reported as the Base initialization must be completed before allowing user connection
+ IDLE = 2;
+ ARM_INITIALIZATION = 3;
+ ARM_IN_FAULT = 4;
+ ARM_MAINTENANCE = 5;
+ ARM_SERVOING_LOW_LEVEL = 6;
+ ARM_SERVOING_READY = 7;
+ ARM_SERVOING_PLAYING_SEQUENCE = 8;
+ ARM_SERVOING_MANUALLY_CONTROLLED = 9;
+ RESERVED = 255; // For debugging, this state must never be reported outside the base. this means that a state is not mapped correctly
+}
\ No newline at end of file
diff --git a/kortex_device_manager/protos/DeviceConfig.options b/kortex_device_manager/protos/DeviceConfig.options
new file mode 100644
index 00000000..8dba0376
--- /dev/null
+++ b/kortex_device_manager/protos/DeviceConfig.options
@@ -0,0 +1,7 @@
+Kinova.Api.DeviceConfig.ModelNumber.model_number max_size:25
+Kinova.Api.DeviceConfig.PartNumber.part_number max_size:25
+Kinova.Api.DeviceConfig.SerialNumber.serial_number max_size:25
+Kinova.Api.DeviceConfig.PartNumberRevision.part_number_revision max_size:9
+Kinova.Api.DeviceConfig.MACAddress.mac_address max_size:6 fixed_length:true
+Kinova.Api.DeviceConfig.RunModes long_names:false
+Kinova.Api.DeviceConfig.SafetyLimitType long_names:false
\ No newline at end of file
diff --git a/kortex_device_manager/protos/DeviceConfig.proto b/kortex_device_manager/protos/DeviceConfig.proto
new file mode 100644
index 00000000..d9a28047
--- /dev/null
+++ b/kortex_device_manager/protos/DeviceConfig.proto
@@ -0,0 +1,271 @@
+syntax = "proto3";
+
+import public "Common.proto";
+
+package Kinova.Api.DeviceConfig;
+
+/**
+* Service to get and set device configuration information
+*/
+service DeviceConfig {//@PROXY_ID=9 @ERROR=Kinova.Api.Error
+
+ // Returns the run mode for the device
+ rpc GetRunMode (Kinova.Api.Common.Empty) returns (RunMode); //@RPC_ID=1
+
+ // Sets the run mode for the device
+ rpc SetRunMode (RunMode) returns (Kinova.Api.Common.Empty); //@RPC_ID=2
+
+ // Returns the type for the device
+ rpc GetDeviceType (Kinova.Api.Common.Empty) returns (DeviceType); //@RPC_ID=3
+
+ // Returns the device firmware version
+ rpc GetFirmwareVersion (Kinova.Api.Common.Empty) returns (FirmwareVersion); //@RPC_ID=4
+
+ // Returns the device bootloader version
+ rpc GetBootloaderVersion (Kinova.Api.Common.Empty) returns (BootloaderVersion); //@RPC_ID=5
+
+ // Returns the device model number
+ rpc GetModelNumber (Kinova.Api.Common.Empty) returns (ModelNumber); //@RPC_ID=6
+
+ // Returns the device part number
+ rpc GetPartNumber (Kinova.Api.Common.Empty) returns (PartNumber); //@RPC_ID=7
+
+ // Returns the device serial number
+ rpc GetSerialNumber (Kinova.Api.Common.Empty) returns (SerialNumber); //@RPC_ID=8
+
+ // Returns the device MAC address
+ rpc GetMACAddress (Kinova.Api.Common.Empty) returns (MACAddress); //@RPC_ID=9
+
+ // Returns the device IPv4 settings
+ rpc GetIPv4Settings (Kinova.Api.Common.Empty) returns (IPv4Settings); //@RPC_ID=10
+
+ // Configures the device IPv4 settings
+ rpc SetIPv4Settings (IPv4Settings) returns (Kinova.Api.Common.Empty); //@RPC_ID=11
+
+ // Returns the device part number revision
+ rpc GetPartNumberRevision (Kinova.Api.Common.Empty) returns (PartNumberRevision); //@RPC_ID=12
+
+ // Returns the result on the device power on self test
+ rpc GetPowerOnSelfTestResult (Kinova.Api.Common.Empty) returns (PowerOnSelfTestResult); //@RPC_ID=13
+
+ // Sends a request to the device to reboot
+ rpc RebootRequest (RebootRqst) returns (Kinova.Api.Common.Empty); //@RPC_ID=14
+
+ //Enables (disable) the specified safety
+ rpc SetSafetyEnable (SafetyEnable) returns (Kinova.Api.Common.Empty); //@RPC_ID=15
+
+ //Sets the Error threshold for the specified safety
+ rpc SetSafetyErrorThreshold (SafetyThreshold) returns (Kinova.Api.Common.Empty); //@RPC_ID=16
+
+ //Sets the Warning threshold for the specified safety
+ rpc SetSafetyWarningThreshold (SafetyThreshold) returns (Kinova.Api.Common.Empty); //@RPC_ID=17
+
+ //Configures the specified safety (i.e. sets error and warning thresholds)
+ rpc SetSafetyConfiguration (SafetyConfiguration) returns (Kinova.Api.Common.Empty); //@RPC_ID=18
+
+ //Retrieves configuration about the specified safety
+ rpc GetSafetyConfiguration (Kinova.Api.Common.SafetyHandle) returns (SafetyConfiguration); //@RPC_ID=19
+
+ //Retrieves information about the specified safety
+ rpc GetSafetyInformation (Kinova.Api.Common.SafetyHandle) returns (SafetyInformation); //@RPC_ID=20
+
+ //Indicates if specified safety is enabled (or disabled)
+ rpc GetSafetyEnable (Kinova.Api.Common.SafetyHandle) returns (SafetyEnable); //@RPC_ID=21
+
+ //Indicates if the specified safety is raised
+ rpc GetSafetyStatus (Kinova.Api.Common.SafetyHandle) returns (SafetyStatus); //@RPC_ID=22
+
+ //Clear all safety status for this device if they are no longer raised
+ rpc ClearAllSafetyStatus (Kinova.Api.Common.Empty) returns (Kinova.Api.Common.Empty); //@RPC_ID=23
+
+ //Clear a specific safety status if it is no longer raised
+ rpc ClearSafetyStatus (Kinova.Api.Common.SafetyHandle) returns (Kinova.Api.Common.Empty); //@RPC_ID=24
+
+ //Gets configuration on every safeties
+ rpc GetAllSafetyConfiguration (Kinova.Api.Common.Empty) returns (SafetyConfigurationList); //@RPC_ID=25
+
+ //Gets information on every safeties
+ rpc GetAllSafetyInformation (Kinova.Api.Common.Empty) returns (SafetyInformationList); //@RPC_ID=26
+
+ //Puts back all safety configuration to factory defaults
+ rpc ResetSafetyDefaults (Kinova.Api.Common.Empty) returns (Kinova.Api.Common.Empty); //@RPC_ID=27
+
+ //Subscribes to safety notifications
+ rpc SafetyTopic (Kinova.Api.Common.NotificationOptions) returns (Kinova.Api.Common.NotificationHandle); //@RPC_ID=28 @PUB_SUB=Kinova.Api.Common.SafetyNotification
+
+ // Sets the device model number (intented for Kinova Production)
+ rpc SetModelNumber (ModelNumber) returns (Kinova.Api.Common.Empty); //@RPC_ID=29
+
+ // Sets the device part number (intented for Kinova Production)
+ rpc SetPartNumber (PartNumber) returns (Kinova.Api.Common.Empty); //@RPC_ID=30
+
+ // Sets the device part number revision (intented for Kinova Production)
+ rpc SetPartNumberRevision (PartNumberRevision) returns (Kinova.Api.Common.Empty); //@RPC_ID=31
+
+ // Sets the device serial number (intented for Kinova Production)
+ rpc SetSerialNumber (SerialNumber) returns (Kinova.Api.Common.Empty); //@RPC_ID=32
+
+ // Sets the device MAC address (intented for Kinova Production)
+ rpc SetMACAddress (MACAddress) returns (Kinova.Api.Common.Empty); //@RPC_ID=33
+}
+
+enum ServiceVersion {
+ RESERVED_0 = 0;
+ CURRENT_VERSION = 1; // Current Version
+}
+
+/**
+* Options for the run mode for the device
+*/
+enum RunModes {
+ RUN_MODE = 0;
+ CALIBRATION_MODE = 1; // calibration mode
+ CONFIGURATION_MODE = 2; // configuration mode
+ DEBUG_MODE = 3; // debug mode
+ TUNING_MODE = 4; // tuning mode
+}
+
+/**
+* Message specifying the device type
+*/
+message DeviceType {
+ Kinova.Api.Common.DeviceTypes device_type = 1; // Device type
+}
+
+
+/**
+* Message specifying the run mode
+*/
+message RunMode {
+ RunModes run_mode = 1; // Run mode
+}
+
+/**
+* Message specifying the firmware version for the device
+*/
+message FirmwareVersion {
+ uint32 firmware_version = 1; // Firmware version
+}
+
+/**
+* Message specifying the bootloader version for the device
+*/
+message BootloaderVersion {
+ uint32 bootloader_version = 1; // Bootloader version
+}
+
+/**
+* Message specifying the model number for the device
+*/
+message ModelNumber {
+ string model_number = 1; // Model number of size 25 including null character
+}
+
+/**
+* String specifiying the part number for the device
+*/
+message PartNumber {
+ string part_number = 1; // Part number of size 25 including null character
+}
+
+/**
+* String specifying the serial number for the device
+*/
+message SerialNumber {
+ string serial_number = 1; // Serial number of size 25 including null character
+}
+
+/**
+* MAC address for the device
+*/
+message MACAddress {
+ bytes mac_address = 1; // MAC address
+}
+
+/**
+* Message containing the IPv4 settings for the device, including address, subnet mask, and default gateway
+*/
+message IPv4Settings {
+ uint32 ipv4_address = 1; // IPv4Address
+ uint32 ipv4_subnet_mask = 2; // IPv4SubnetMask
+ uint32 ipv4_default_gateway = 3; // IPv4DefaultGateway
+}
+
+/**
+* String specifying part number revision for the device
+*/
+message PartNumberRevision {
+ string part_number_revision = 1; // Part number revision
+}
+
+/**
+* Result of power on self test
+*/
+message PowerOnSelfTestResult {
+ uint32 power_on_self_test_result = 1; // Power on self test result
+}
+
+/**
+* Reboot request with bootloader delay
+*/
+message RebootRqst {
+ uint32 delay = 1; // Bootloader delay
+}
+
+/**
+ * Types of safeties limits
+ */
+enum SafetyLimitType {
+ UNSPECIFIED_SAFETY_LIMIT_TYPE = 0;
+ MINIMAL_LIMIT = 1; // Safety that will kick in below a certain Minimum threshold (ex. Minimum temperature safety)
+ MAXIMAL_LIMIT = 2; // Safety that will kick in above a certain Maximum threshold (ex. Maximum voltage safety)
+ EVENT_LIMIT = 3; // Safety that will kick in in reaction to a specific event (ex. motor drive fault)
+
+}
+
+/**
+ * Information about a particular safety
+ */
+message SafetyInformation {
+ Kinova.Api.Common.SafetyHandle handle = 1; // safety handle that this information is about
+ bool can_change_safety_state = 2; // true if related safety configuration can be modified
+ bool has_warning_threshold = 3; // true if safety status can go in Warning
+ bool has_error_threshold = 4; // true if safety status can go in Error
+ SafetyLimitType limit_type = 5; // safety limit type
+ float default_warning_threshold = 6; // default warning threshold (if 'limit_type' is either MINIMAL_LIMIT or MAXIMAL_LIMIT and 'has_warning_threshold' is true)
+ float default_error_threshold = 7; // default error threshold (if 'limit_type' is either MINIMAL_LIMIT or MAXIMAL_LIMIT and 'has_error_threshold' is true)
+ float upper_hard_limit = 8; // maximal threshold value (if 'limit_type' is either MINIMAL_LIMIT or MAXIMAL_LIMIT)
+ float lower_hard_limit = 9; // minimal threshold value (if 'limit_type' is either MINIMAL_LIMIT or MAXIMAL_LIMIT)
+ Kinova.Api.Common.SafetyStatusValue status = 11;// current Safety status
+ Kinova.Api.Common.Unit unit = 12; // Unit that the safety status is in
+}
+
+message SafetyInformationList {
+ repeated SafetyInformation information = 1;
+}
+
+message SafetyEnable {
+ Kinova.Api.Common.SafetyHandle handle = 1;
+ bool enable = 2;
+}
+
+message SafetyThreshold {
+ Kinova.Api.Common.SafetyHandle handle = 1;
+ float value = 2;
+}
+
+message SafetyConfiguration {
+ Kinova.Api.Common.SafetyHandle handle = 1;
+ float error_threshold = 2;
+ float warning_threshold = 3;
+ SafetyEnable enable = 4;
+}
+
+message SafetyConfigurationList {
+ repeated SafetyConfiguration configuration = 1;
+}
+
+message SafetyStatus {
+ Kinova.Api.Common.SafetyStatusValue value = 1;
+}
+
diff --git a/kortex_device_manager/protos/DeviceManager.proto b/kortex_device_manager/protos/DeviceManager.proto
new file mode 100644
index 00000000..abdf4e2a
--- /dev/null
+++ b/kortex_device_manager/protos/DeviceManager.proto
@@ -0,0 +1,27 @@
+syntax = "proto3";
+
+import public "Common.proto";
+
+package Kinova.Api.DeviceManager;
+
+/****************************************************************
+ * This service is always present on every framework 3 robot
+ * Its purpose is to provide information about presence of devices
+ *****************************************************************/
+service DeviceManager {//@PROXY_ID=23 @ERROR=Kinova.Api.Error
+
+ //Retrieves the list of every device that the robot contains, along with its type and order within the robot
+ rpc ReadAllDevices (Kinova.Api.Common.Empty) returns (DeviceHandles);//@RPC_ID=1
+}
+
+enum ServiceVersion {
+ RESERVED_0 = 0;
+ CURRENT_VERSION = 1; // Current Version
+}
+
+/**
+*Message containing a list of DeviceHandle objects
+*/
+message DeviceHandles {
+ repeated Kinova.Api.Common.DeviceHandle device_handle = 1;
+}
diff --git a/kortex_device_manager/readme.md b/kortex_device_manager/readme.md
new file mode 100644
index 00000000..c8a6c275
--- /dev/null
+++ b/kortex_device_manager/readme.md
@@ -0,0 +1,96 @@
+
+# Kortex Device Manager
+
+
+
+1. [Content](#content)
+ 1. [build](#build)
+ 1. [msg](#msg)
+ 1. [non_generated](#non_generated)
+ 1. [protos](#protos)
+ 1. [src](#src)
+ 1. [srv](#srv)
+ 1. [templates](#templates)
+1. [How to start the node](#how-to-start-the-node)
+1. [Generation](#generation)
+
+
+
+
+## Content
+
+### build
+This folder's only purpose is to exist as a temp folder during the generation. It should not be used.
+
+### msg
+This folder contains every custom message used by the node **kortex\_device\_manager**. All the .msg files in this folder are generated by a custom protoc plugin described in the [Generation](#generation) section.
+
+#### non_generated
+This folder contains all the non-generated .msg files used by the node **kortex\_device\_manager**.
+
+| MSG | Description |
+|:---:|:---:|
+| KortexError.msg | Describe the topic /KortexError. Every service call of the node kortex_driver will publish in /KortexError everytime the Kortex API returns an error. |
+
+
+### protos
+This folder contains the protobuf files from where the MSG, SRV and sources files are generated. The content of this folder should not be modified.
+
+### src
+This folder contains all the generated source files needed to build the node. The content of this folder should not be modified.
+
+### srv
+This folder contains every custom services used by the node **kortex\_device\_manager**. All the .srv files in this folder are generated by a custom protoc plugin described in the [Generation](#generation) section.
+
+
+### templates
+This folder contains all the JINJA2 files needed by the protoc generator. For more details on the generation process, see the [Generation](#generation) section.
+
+| JINJA2 files | Description |
+|:---:|:---:|
+| main.jinja2 | Use to generate src/main.cpp |
+| NodeServices.cpp.jinja2 | Use to generate src/node.cpp |
+| NodeServices.h.jinja2 | Use to generate src/node.h |
+| proto_converterCPP.jinja2 | Use to generate every src/*_proto\_converter.cpp files |
+| proto_converterHeader.jinja2 | Use to generate every src/*_proto\_converter.h files |
+| ros_converterCPP.jinja2 | Use to generate every src/*_ros\_converter.cpp files |
+| ros_converterHeader.jinja2 | Use to generate every src/*_proto\_converter.h files |
+| ros_enum.jinja2 | Use to generate every msg/*.msg files that represent a protobuf enum |
+| ros_message.jinja2 | Use to generate every msg/*.msg files that represent a protobuf message |
+| ros_oneof.jinja2 | Use to generate every msg/*.msg files that represent a protobuf oneof |
+| ros_service.jinja2 | Use to generate every msg/*.msg files that represent a protobuf RPC |
+
+
+## How to start the node
+
+rosrun kortex\_device\_manager kortex\_device\_manager 192.168.1.10
+
+In the command above, you would be running the kortex\_device\_manager node on a Gen3 robot with an IP address of 192.168.1.10
+
+
+## Generation
+
+The generation process is based on a custom protobuf plugin. Basically, most of the generation process is in the python file RosGeneration.py located at the package's root folder. Before launching the generation make sure you have the python module Jinja2 installed on your computer.
+
+
+To launch the generation of this package:
+
+1. Open a terminal window.
+1. Browse the root of this package [YOUR\_ROS\_WORKSPACE]/src/ros\_kortex/kortex\_device\_manager/
+1. Make sure that the file kortex_driver.sh can be executed. If not then chmod +x kortex_device_manager.sh
+1. Run this command: protoc --plugin=protoc-gen-custom=kortex_device_manager.sh -I./protos/ --custom_out=./build ./protos/\*.prot
+1. The result of the generation should be on thos folder:
+ * /src
+ * /msg
+ * /srv
+
diff --git a/kortex_device_manager/src/common_proto_converter.cpp b/kortex_device_manager/src/common_proto_converter.cpp
new file mode 100644
index 00000000..f6bcd03f
--- /dev/null
+++ b/kortex_device_manager/src/common_proto_converter.cpp
@@ -0,0 +1,84 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "common_proto_converter.h"
+
+
+int ToProtoData(kortex_device_manager::DeviceHandle input, DeviceHandle *output)
+{
+ output->set_device_type((Kinova::Api::Common::DeviceTypes)input.device_type);
+ output->set_device_identifier(input.device_identifier);
+ output->set_order(input.order);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::Empty input, Empty *output)
+{
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::NotificationOptions input, NotificationOptions *output)
+{
+ output->set_type((Kinova::Api::Common::NotificationType)input.type);
+ output->set_rate_m_sec(input.rate_m_sec);
+ output->set_threshold_value(input.threshold_value);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::SafetyHandle input, SafetyHandle *output)
+{
+ output->set_identifier(input.identifier);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::NotificationHandle input, NotificationHandle *output)
+{
+ output->set_identifier(input.identifier);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::SafetyNotification input, SafetyNotification *output)
+{
+ ToProtoData(input.safety_handle, output->mutable_safety_handle());
+ output->set_value((Kinova::Api::Common::SafetyStatusValue)input.value);
+ ToProtoData(input.timestamp, output->mutable_timestamp());
+ ToProtoData(input.user_handle, output->mutable_user_handle());
+ ToProtoData(input.connection, output->mutable_connection());
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::Timestamp input, Timestamp *output)
+{
+ output->set_sec(input.sec);
+ output->set_usec(input.usec);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::UserProfileHandle input, UserProfileHandle *output)
+{
+ output->set_identifier(input.identifier);
+ output->set_permission(input.permission);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::Connection input, Connection *output)
+{
+ ToProtoData(input.user_handle, output->mutable_user_handle());
+ output->set_connection_information(input.connection_information);
+ output->set_connection_identifier(input.connection_identifier);
+
+ return 0;
+}
diff --git a/kortex_device_manager/src/common_proto_converter.h b/kortex_device_manager/src/common_proto_converter.h
new file mode 100644
index 00000000..c16d8738
--- /dev/null
+++ b/kortex_device_manager/src/common_proto_converter.h
@@ -0,0 +1,66 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_CommonPROTO_CONVERTER_H_
+#define _KORTEX_CommonPROTO_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "kortex_device_manager/DeviceHandle.h"
+#include "kortex_device_manager/Empty.h"
+#include "kortex_device_manager/NotificationOptions.h"
+#include "kortex_device_manager/SafetyHandle.h"
+#include "kortex_device_manager/NotificationHandle.h"
+#include "kortex_device_manager/SafetyNotification.h"
+#include "kortex_device_manager/Timestamp.h"
+#include "kortex_device_manager/UserProfileHandle.h"
+#include "kortex_device_manager/Connection.h"
+
+
+using namespace Kinova::Api::Common;
+
+int ToProtoData(kortex_device_manager::DeviceHandle intput, DeviceHandle *output);
+int ToProtoData(kortex_device_manager::Empty intput, Empty *output);
+int ToProtoData(kortex_device_manager::NotificationOptions intput, NotificationOptions *output);
+int ToProtoData(kortex_device_manager::SafetyHandle intput, SafetyHandle *output);
+int ToProtoData(kortex_device_manager::NotificationHandle intput, NotificationHandle *output);
+int ToProtoData(kortex_device_manager::SafetyNotification intput, SafetyNotification *output);
+int ToProtoData(kortex_device_manager::Timestamp intput, Timestamp *output);
+int ToProtoData(kortex_device_manager::UserProfileHandle intput, UserProfileHandle *output);
+int ToProtoData(kortex_device_manager::Connection intput, Connection *output);
+
+#endif
\ No newline at end of file
diff --git a/kortex_device_manager/src/common_ros_converter.cpp b/kortex_device_manager/src/common_ros_converter.cpp
new file mode 100644
index 00000000..bdfd6e33
--- /dev/null
+++ b/kortex_device_manager/src/common_ros_converter.cpp
@@ -0,0 +1,84 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "common_ros_converter.h"
+
+
+int ToRosData(DeviceHandle input, kortex_device_manager::DeviceHandle &output)
+{
+ output.device_type = input.device_type();
+ output.device_identifier = input.device_identifier();
+ output.order = input.order();
+
+ return 0;
+}
+int ToRosData(Empty input, kortex_device_manager::Empty &output)
+{
+
+ return 0;
+}
+int ToRosData(NotificationOptions input, kortex_device_manager::NotificationOptions &output)
+{
+ output.type = input.type();
+ output.rate_m_sec = input.rate_m_sec();
+ output.threshold_value = input.threshold_value();
+
+ return 0;
+}
+int ToRosData(SafetyHandle input, kortex_device_manager::SafetyHandle &output)
+{
+ output.identifier = input.identifier();
+
+ return 0;
+}
+int ToRosData(NotificationHandle input, kortex_device_manager::NotificationHandle &output)
+{
+ output.identifier = input.identifier();
+
+ return 0;
+}
+int ToRosData(SafetyNotification input, kortex_device_manager::SafetyNotification &output)
+{
+ ToRosData(input.safety_handle(), output.safety_handle);
+ output.value = input.value();
+ ToRosData(input.timestamp(), output.timestamp);
+ ToRosData(input.user_handle(), output.user_handle);
+ ToRosData(input.connection(), output.connection);
+
+ return 0;
+}
+int ToRosData(Timestamp input, kortex_device_manager::Timestamp &output)
+{
+ output.sec = input.sec();
+ output.usec = input.usec();
+
+ return 0;
+}
+int ToRosData(UserProfileHandle input, kortex_device_manager::UserProfileHandle &output)
+{
+ output.identifier = input.identifier();
+ output.permission = input.permission();
+
+ return 0;
+}
+int ToRosData(Connection input, kortex_device_manager::Connection &output)
+{
+ ToRosData(input.user_handle(), output.user_handle);
+ output.connection_information = input.connection_information();
+ output.connection_identifier = input.connection_identifier();
+
+ return 0;
+}
diff --git a/kortex_device_manager/src/common_ros_converter.h b/kortex_device_manager/src/common_ros_converter.h
new file mode 100644
index 00000000..164b3a3f
--- /dev/null
+++ b/kortex_device_manager/src/common_ros_converter.h
@@ -0,0 +1,66 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_CommonROS_CONVERTER_H_
+#define _KORTEX_CommonROS_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "kortex_device_manager/DeviceHandle.h"
+#include "kortex_device_manager/Empty.h"
+#include "kortex_device_manager/NotificationOptions.h"
+#include "kortex_device_manager/SafetyHandle.h"
+#include "kortex_device_manager/NotificationHandle.h"
+#include "kortex_device_manager/SafetyNotification.h"
+#include "kortex_device_manager/Timestamp.h"
+#include "kortex_device_manager/UserProfileHandle.h"
+#include "kortex_device_manager/Connection.h"
+
+
+using namespace Kinova::Api::Common;
+
+int ToRosData(DeviceHandle input, kortex_device_manager::DeviceHandle &output);
+int ToRosData(Empty input, kortex_device_manager::Empty &output);
+int ToRosData(NotificationOptions input, kortex_device_manager::NotificationOptions &output);
+int ToRosData(SafetyHandle input, kortex_device_manager::SafetyHandle &output);
+int ToRosData(NotificationHandle input, kortex_device_manager::NotificationHandle &output);
+int ToRosData(SafetyNotification input, kortex_device_manager::SafetyNotification &output);
+int ToRosData(Timestamp input, kortex_device_manager::Timestamp &output);
+int ToRosData(UserProfileHandle input, kortex_device_manager::UserProfileHandle &output);
+int ToRosData(Connection input, kortex_device_manager::Connection &output);
+
+#endif
\ No newline at end of file
diff --git a/kortex_device_manager/src/deviceconfig_proto_converter.cpp b/kortex_device_manager/src/deviceconfig_proto_converter.cpp
new file mode 100644
index 00000000..a3a2d11b
--- /dev/null
+++ b/kortex_device_manager/src/deviceconfig_proto_converter.cpp
@@ -0,0 +1,160 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "deviceconfig_proto_converter.h"
+
+#include "common_proto_converter.h"
+
+
+int ToProtoData(kortex_device_manager::DeviceType input, DeviceType *output)
+{
+ output->set_device_type((Kinova::Api::Common::DeviceTypes)input.device_type);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::RunMode input, RunMode *output)
+{
+ output->set_run_mode((Kinova::Api::DeviceConfig::RunModes)input.run_mode);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::FirmwareVersion input, FirmwareVersion *output)
+{
+ output->set_firmware_version(input.firmware_version);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::BootloaderVersion input, BootloaderVersion *output)
+{
+ output->set_bootloader_version(input.bootloader_version);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::ModelNumber input, ModelNumber *output)
+{
+ output->set_model_number(input.model_number);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::PartNumber input, PartNumber *output)
+{
+ output->set_part_number(input.part_number);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::SerialNumber input, SerialNumber *output)
+{
+ output->set_serial_number(input.serial_number);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::MACAddress input, MACAddress *output)
+{
+ output->set_mac_address(std::string(input.mac_address.begin(), input.mac_address.end()));
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::IPv4Settings input, IPv4Settings *output)
+{
+ output->set_ipv4_address(input.ipv4_address);
+ output->set_ipv4_subnet_mask(input.ipv4_subnet_mask);
+ output->set_ipv4_default_gateway(input.ipv4_default_gateway);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::PartNumberRevision input, PartNumberRevision *output)
+{
+ output->set_part_number_revision(input.part_number_revision);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::PowerOnSelfTestResult input, PowerOnSelfTestResult *output)
+{
+ output->set_power_on_self_test_result(input.power_on_self_test_result);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::RebootRqst input, RebootRqst *output)
+{
+ output->set_delay(input.delay);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::SafetyInformation input, SafetyInformation *output)
+{
+ ToProtoData(input.handle, output->mutable_handle());
+ output->set_can_change_safety_state(input.can_change_safety_state);
+ output->set_has_warning_threshold(input.has_warning_threshold);
+ output->set_has_error_threshold(input.has_error_threshold);
+ output->set_limit_type((Kinova::Api::DeviceConfig::SafetyLimitType)input.limit_type);
+ output->set_default_warning_threshold(input.default_warning_threshold);
+ output->set_default_error_threshold(input.default_error_threshold);
+ output->set_upper_hard_limit(input.upper_hard_limit);
+ output->set_lower_hard_limit(input.lower_hard_limit);
+ output->set_status((Kinova::Api::Common::SafetyStatusValue)input.status);
+ output->set_unit((Kinova::Api::Common::Unit)input.unit);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::SafetyInformationList input, SafetyInformationList *output)
+{
+ output->clear_information();
+ for(int i = 0; i < input.information.size(); i++)
+ {
+ ToProtoData(input.information[i], output->add_information());
+ }
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::SafetyEnable input, SafetyEnable *output)
+{
+ ToProtoData(input.handle, output->mutable_handle());
+ output->set_enable(input.enable);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::SafetyThreshold input, SafetyThreshold *output)
+{
+ ToProtoData(input.handle, output->mutable_handle());
+ output->set_value(input.value);
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::SafetyConfiguration input, SafetyConfiguration *output)
+{
+ ToProtoData(input.handle, output->mutable_handle());
+ output->set_error_threshold(input.error_threshold);
+ output->set_warning_threshold(input.warning_threshold);
+ ToProtoData(input.enable, output->mutable_enable());
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::SafetyConfigurationList input, SafetyConfigurationList *output)
+{
+ output->clear_configuration();
+ for(int i = 0; i < input.configuration.size(); i++)
+ {
+ ToProtoData(input.configuration[i], output->add_configuration());
+ }
+
+ return 0;
+}
+int ToProtoData(kortex_device_manager::SafetyStatus input, SafetyStatus *output)
+{
+ output->set_value((Kinova::Api::Common::SafetyStatusValue)input.value);
+
+ return 0;
+}
diff --git a/kortex_device_manager/src/deviceconfig_proto_converter.h b/kortex_device_manager/src/deviceconfig_proto_converter.h
new file mode 100644
index 00000000..9be3f0ba
--- /dev/null
+++ b/kortex_device_manager/src/deviceconfig_proto_converter.h
@@ -0,0 +1,86 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_DeviceConfigPROTO_CONVERTER_H_
+#define _KORTEX_DeviceConfigPROTO_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "kortex_device_manager/DeviceType.h"
+#include "kortex_device_manager/RunMode.h"
+#include "kortex_device_manager/FirmwareVersion.h"
+#include "kortex_device_manager/BootloaderVersion.h"
+#include "kortex_device_manager/ModelNumber.h"
+#include "kortex_device_manager/PartNumber.h"
+#include "kortex_device_manager/SerialNumber.h"
+#include "kortex_device_manager/MACAddress.h"
+#include "kortex_device_manager/IPv4Settings.h"
+#include "kortex_device_manager/PartNumberRevision.h"
+#include "kortex_device_manager/PowerOnSelfTestResult.h"
+#include "kortex_device_manager/RebootRqst.h"
+#include "kortex_device_manager/SafetyInformation.h"
+#include "kortex_device_manager/SafetyInformationList.h"
+#include "kortex_device_manager/SafetyEnable.h"
+#include "kortex_device_manager/SafetyThreshold.h"
+#include "kortex_device_manager/SafetyConfiguration.h"
+#include "kortex_device_manager/SafetyConfigurationList.h"
+#include "kortex_device_manager/SafetyStatus.h"
+
+
+using namespace Kinova::Api::DeviceConfig;
+
+int ToProtoData(kortex_device_manager::DeviceType intput, DeviceType *output);
+int ToProtoData(kortex_device_manager::RunMode intput, RunMode *output);
+int ToProtoData(kortex_device_manager::FirmwareVersion intput, FirmwareVersion *output);
+int ToProtoData(kortex_device_manager::BootloaderVersion intput, BootloaderVersion *output);
+int ToProtoData(kortex_device_manager::ModelNumber intput, ModelNumber *output);
+int ToProtoData(kortex_device_manager::PartNumber intput, PartNumber *output);
+int ToProtoData(kortex_device_manager::SerialNumber intput, SerialNumber *output);
+int ToProtoData(kortex_device_manager::MACAddress intput, MACAddress *output);
+int ToProtoData(kortex_device_manager::IPv4Settings intput, IPv4Settings *output);
+int ToProtoData(kortex_device_manager::PartNumberRevision intput, PartNumberRevision *output);
+int ToProtoData(kortex_device_manager::PowerOnSelfTestResult intput, PowerOnSelfTestResult *output);
+int ToProtoData(kortex_device_manager::RebootRqst intput, RebootRqst *output);
+int ToProtoData(kortex_device_manager::SafetyInformation intput, SafetyInformation *output);
+int ToProtoData(kortex_device_manager::SafetyInformationList intput, SafetyInformationList *output);
+int ToProtoData(kortex_device_manager::SafetyEnable intput, SafetyEnable *output);
+int ToProtoData(kortex_device_manager::SafetyThreshold intput, SafetyThreshold *output);
+int ToProtoData(kortex_device_manager::SafetyConfiguration intput, SafetyConfiguration *output);
+int ToProtoData(kortex_device_manager::SafetyConfigurationList intput, SafetyConfigurationList *output);
+int ToProtoData(kortex_device_manager::SafetyStatus intput, SafetyStatus *output);
+
+#endif
\ No newline at end of file
diff --git a/kortex_device_manager/src/deviceconfig_ros_converter.cpp b/kortex_device_manager/src/deviceconfig_ros_converter.cpp
new file mode 100644
index 00000000..1fefb387
--- /dev/null
+++ b/kortex_device_manager/src/deviceconfig_ros_converter.cpp
@@ -0,0 +1,164 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "deviceconfig_ros_converter.h"
+
+#include "common_ros_converter.h"
+
+
+int ToRosData(DeviceType input, kortex_device_manager::DeviceType &output)
+{
+ output.device_type = input.device_type();
+
+ return 0;
+}
+int ToRosData(RunMode input, kortex_device_manager::RunMode &output)
+{
+ output.run_mode = input.run_mode();
+
+ return 0;
+}
+int ToRosData(FirmwareVersion input, kortex_device_manager::FirmwareVersion &output)
+{
+ output.firmware_version = input.firmware_version();
+
+ return 0;
+}
+int ToRosData(BootloaderVersion input, kortex_device_manager::BootloaderVersion &output)
+{
+ output.bootloader_version = input.bootloader_version();
+
+ return 0;
+}
+int ToRosData(ModelNumber input, kortex_device_manager::ModelNumber &output)
+{
+ output.model_number = input.model_number();
+
+ return 0;
+}
+int ToRosData(PartNumber input, kortex_device_manager::PartNumber &output)
+{
+ output.part_number = input.part_number();
+
+ return 0;
+}
+int ToRosData(SerialNumber input, kortex_device_manager::SerialNumber &output)
+{
+ output.serial_number = input.serial_number();
+
+ return 0;
+}
+int ToRosData(MACAddress input, kortex_device_manager::MACAddress &output)
+{
+ output.mac_address = std::vector(input.mac_address().begin(), input.mac_address().end());
+
+ return 0;
+}
+int ToRosData(IPv4Settings input, kortex_device_manager::IPv4Settings &output)
+{
+ output.ipv4_address = input.ipv4_address();
+ output.ipv4_subnet_mask = input.ipv4_subnet_mask();
+ output.ipv4_default_gateway = input.ipv4_default_gateway();
+
+ return 0;
+}
+int ToRosData(PartNumberRevision input, kortex_device_manager::PartNumberRevision &output)
+{
+ output.part_number_revision = input.part_number_revision();
+
+ return 0;
+}
+int ToRosData(PowerOnSelfTestResult input, kortex_device_manager::PowerOnSelfTestResult &output)
+{
+ output.power_on_self_test_result = input.power_on_self_test_result();
+
+ return 0;
+}
+int ToRosData(RebootRqst input, kortex_device_manager::RebootRqst &output)
+{
+ output.delay = input.delay();
+
+ return 0;
+}
+int ToRosData(SafetyInformation input, kortex_device_manager::SafetyInformation &output)
+{
+ ToRosData(input.handle(), output.handle);
+ output.can_change_safety_state = input.can_change_safety_state();
+ output.has_warning_threshold = input.has_warning_threshold();
+ output.has_error_threshold = input.has_error_threshold();
+ output.limit_type = input.limit_type();
+ output.default_warning_threshold = input.default_warning_threshold();
+ output.default_error_threshold = input.default_error_threshold();
+ output.upper_hard_limit = input.upper_hard_limit();
+ output.lower_hard_limit = input.lower_hard_limit();
+ output.status = input.status();
+ output.unit = input.unit();
+
+ return 0;
+}
+int ToRosData(SafetyInformationList input, kortex_device_manager::SafetyInformationList &output)
+{
+ output.information.clear();
+ for(int i = 0; i < input.information_size(); i++)
+ {
+ kortex_device_manager::SafetyInformation temp;
+ ToRosData(input.information(i), temp);
+ output.information.push_back(temp);
+ }
+
+ return 0;
+}
+int ToRosData(SafetyEnable input, kortex_device_manager::SafetyEnable &output)
+{
+ ToRosData(input.handle(), output.handle);
+ output.enable = input.enable();
+
+ return 0;
+}
+int ToRosData(SafetyThreshold input, kortex_device_manager::SafetyThreshold &output)
+{
+ ToRosData(input.handle(), output.handle);
+ output.value = input.value();
+
+ return 0;
+}
+int ToRosData(SafetyConfiguration input, kortex_device_manager::SafetyConfiguration &output)
+{
+ ToRosData(input.handle(), output.handle);
+ output.error_threshold = input.error_threshold();
+ output.warning_threshold = input.warning_threshold();
+ ToRosData(input.enable(), output.enable);
+
+ return 0;
+}
+int ToRosData(SafetyConfigurationList input, kortex_device_manager::SafetyConfigurationList &output)
+{
+ output.configuration.clear();
+ for(int i = 0; i < input.configuration_size(); i++)
+ {
+ kortex_device_manager::SafetyConfiguration temp;
+ ToRosData(input.configuration(i), temp);
+ output.configuration.push_back(temp);
+ }
+
+ return 0;
+}
+int ToRosData(SafetyStatus input, kortex_device_manager::SafetyStatus &output)
+{
+ output.value = input.value();
+
+ return 0;
+}
diff --git a/kortex_device_manager/src/deviceconfig_ros_converter.h b/kortex_device_manager/src/deviceconfig_ros_converter.h
new file mode 100644
index 00000000..cc1632c7
--- /dev/null
+++ b/kortex_device_manager/src/deviceconfig_ros_converter.h
@@ -0,0 +1,86 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_DeviceConfigROS_CONVERTER_H_
+#define _KORTEX_DeviceConfigROS_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "kortex_device_manager/DeviceType.h"
+#include "kortex_device_manager/RunMode.h"
+#include "kortex_device_manager/FirmwareVersion.h"
+#include "kortex_device_manager/BootloaderVersion.h"
+#include "kortex_device_manager/ModelNumber.h"
+#include "kortex_device_manager/PartNumber.h"
+#include "kortex_device_manager/SerialNumber.h"
+#include "kortex_device_manager/MACAddress.h"
+#include "kortex_device_manager/IPv4Settings.h"
+#include "kortex_device_manager/PartNumberRevision.h"
+#include "kortex_device_manager/PowerOnSelfTestResult.h"
+#include "kortex_device_manager/RebootRqst.h"
+#include "kortex_device_manager/SafetyInformation.h"
+#include "kortex_device_manager/SafetyInformationList.h"
+#include "kortex_device_manager/SafetyEnable.h"
+#include "kortex_device_manager/SafetyThreshold.h"
+#include "kortex_device_manager/SafetyConfiguration.h"
+#include "kortex_device_manager/SafetyConfigurationList.h"
+#include "kortex_device_manager/SafetyStatus.h"
+
+
+using namespace Kinova::Api::DeviceConfig;
+
+int ToRosData(DeviceType input, kortex_device_manager::DeviceType &output);
+int ToRosData(RunMode input, kortex_device_manager::RunMode &output);
+int ToRosData(FirmwareVersion input, kortex_device_manager::FirmwareVersion &output);
+int ToRosData(BootloaderVersion input, kortex_device_manager::BootloaderVersion &output);
+int ToRosData(ModelNumber input, kortex_device_manager::ModelNumber &output);
+int ToRosData(PartNumber input, kortex_device_manager::PartNumber &output);
+int ToRosData(SerialNumber input, kortex_device_manager::SerialNumber &output);
+int ToRosData(MACAddress input, kortex_device_manager::MACAddress &output);
+int ToRosData(IPv4Settings input, kortex_device_manager::IPv4Settings &output);
+int ToRosData(PartNumberRevision input, kortex_device_manager::PartNumberRevision &output);
+int ToRosData(PowerOnSelfTestResult input, kortex_device_manager::PowerOnSelfTestResult &output);
+int ToRosData(RebootRqst input, kortex_device_manager::RebootRqst &output);
+int ToRosData(SafetyInformation input, kortex_device_manager::SafetyInformation &output);
+int ToRosData(SafetyInformationList input, kortex_device_manager::SafetyInformationList &output);
+int ToRosData(SafetyEnable input, kortex_device_manager::SafetyEnable &output);
+int ToRosData(SafetyThreshold input, kortex_device_manager::SafetyThreshold &output);
+int ToRosData(SafetyConfiguration input, kortex_device_manager::SafetyConfiguration &output);
+int ToRosData(SafetyConfigurationList input, kortex_device_manager::SafetyConfigurationList &output);
+int ToRosData(SafetyStatus input, kortex_device_manager::SafetyStatus &output);
+
+#endif
\ No newline at end of file
diff --git a/kortex_device_manager/src/devicemanager_proto_converter.cpp b/kortex_device_manager/src/devicemanager_proto_converter.cpp
new file mode 100644
index 00000000..ec89c604
--- /dev/null
+++ b/kortex_device_manager/src/devicemanager_proto_converter.cpp
@@ -0,0 +1,31 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "devicemanager_proto_converter.h"
+
+#include "common_proto_converter.h"
+
+
+int ToProtoData(kortex_device_manager::DeviceHandles input, DeviceHandles *output)
+{
+ output->clear_device_handle();
+ for(int i = 0; i < input.device_handle.size(); i++)
+ {
+ ToProtoData(input.device_handle[i], output->add_device_handle());
+ }
+
+ return 0;
+}
diff --git a/kortex_device_manager/src/devicemanager_proto_converter.h b/kortex_device_manager/src/devicemanager_proto_converter.h
new file mode 100644
index 00000000..d04d1eae
--- /dev/null
+++ b/kortex_device_manager/src/devicemanager_proto_converter.h
@@ -0,0 +1,50 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_DeviceManagerPROTO_CONVERTER_H_
+#define _KORTEX_DeviceManagerPROTO_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "kortex_device_manager/DeviceHandles.h"
+
+
+using namespace Kinova::Api::DeviceManager;
+
+int ToProtoData(kortex_device_manager::DeviceHandles intput, DeviceHandles *output);
+
+#endif
\ No newline at end of file
diff --git a/kortex_device_manager/src/devicemanager_ros_converter.cpp b/kortex_device_manager/src/devicemanager_ros_converter.cpp
new file mode 100644
index 00000000..35027ed0
--- /dev/null
+++ b/kortex_device_manager/src/devicemanager_ros_converter.cpp
@@ -0,0 +1,33 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#include "devicemanager_ros_converter.h"
+
+#include "common_ros_converter.h"
+
+
+int ToRosData(DeviceHandles input, kortex_device_manager::DeviceHandles &output)
+{
+ output.device_handle.clear();
+ for(int i = 0; i < input.device_handle_size(); i++)
+ {
+ kortex_device_manager::DeviceHandle temp;
+ ToRosData(input.device_handle(i), temp);
+ output.device_handle.push_back(temp);
+ }
+
+ return 0;
+}
diff --git a/kortex_device_manager/src/devicemanager_ros_converter.h b/kortex_device_manager/src/devicemanager_ros_converter.h
new file mode 100644
index 00000000..2d319260
--- /dev/null
+++ b/kortex_device_manager/src/devicemanager_ros_converter.h
@@ -0,0 +1,50 @@
+/*
+* KINOVA (R) KORTEX (TM)
+*
+* Copyright (c) 2018 Kinova inc. All rights reserved.
+*
+* This software may be modified and distributed under the
+* terms of the BSD 3-Clause license.
+*
+* Refer to the LICENSE file for details.
+*
+*/
+
+/*
+ * This file has been auto-generated and should not be modified.
+ */
+
+#ifndef _KORTEX_DeviceManagerROS_CONVERTER_H_
+#define _KORTEX_DeviceManagerROS_CONVERTER_H_
+
+#include "ros/ros.h"
+
+#include
+#include
+#include
+#include