[ros-ros-controllers] 07/07: New upstream version 0.12.3
Leopold Palomo-Avellaneda
leo at alaxarxa.net
Mon Jul 17 12:58:39 UTC 2017
This is an automated email from the git hooks/post-receive script.
lepalom-guest pushed a commit to branch master
in repository ros-ros-controllers.
commit 31c65918b9a0296219019af284937bf352bbf1c8
Author: Leopold Palomo-Avellaneda <leo at alaxarxa.net>
Date: Fri Jul 14 15:16:03 2017 +0200
New upstream version 0.12.3
---
README.md | 8 +-
diff_drive_controller/CHANGELOG.rst | 24 +
diff_drive_controller/CMakeLists.txt | 10 +-
diff_drive_controller/package.xml | 27 +-
.../src/diff_drive_controller.cpp | 12 +-
.../test/diff_drive_bad_urdf.test | 2 +-
.../test/diff_drive_common.launch | 2 +-
.../test/diff_drive_limits_test.cpp | 2 +
.../test/diff_drive_radius_param.test | 2 +-
.../test/diff_drive_radius_param_fail.test | 2 +-
.../test/diff_drive_separation_param.test | 2 +-
.../test/skid_steer_common.launch | 2 +-
diff_drive_controller/test/sphere_wheel.xacro | 6 +-
diff_drive_controller/test/view_diffbot.launch | 2 +-
.../test/view_skidsteerbot.launch | 2 +-
diff_drive_controller/test/wheel.xacro | 6 +-
effort_controllers/CHANGELOG.rst | 20 +
effort_controllers/CMakeLists.txt | 4 +-
.../effort_controllers/joint_position_controller.h | 2 +-
effort_controllers/package.xml | 30 +-
.../src/joint_position_controller.cpp | 2 +-
force_torque_sensor_controller/CHANGELOG.rst | 17 +
force_torque_sensor_controller/CMakeLists.txt | 21 +-
force_torque_sensor_controller/package.xml | 25 +-
forward_command_controller/CHANGELOG.rst | 15 +
forward_command_controller/package.xml | 18 +-
gripper_action_controller/CHANGELOG.rst | 18 +
gripper_action_controller/CMakeLists.txt | 144 +----
.../gripper_action_controller_impl.h | 21 +-
gripper_action_controller/package.xml | 76 +--
imu_sensor_controller/CHANGELOG.rst | 16 +
imu_sensor_controller/CMakeLists.txt | 22 +-
imu_sensor_controller/package.xml | 25 +-
joint_state_controller/CHANGELOG.rst | 14 +
joint_state_controller/package.xml | 4 +-
joint_trajectory_controller/CHANGELOG.rst | 27 +
joint_trajectory_controller/CMakeLists.txt | 18 +-
.../init_joint_trajectory.h | 280 ++++++---
.../joint_trajectory_controller.h | 44 +-
.../joint_trajectory_controller_impl.h | 318 +++++-----
.../joint_trajectory_segment.h | 89 +--
.../joint_trajectory_controller/tolerances.h | 61 ++
joint_trajectory_controller/package.xml | 54 +-
.../test/init_joint_trajectory_test.cpp | 198 ++++---
.../test/joint_partial_trajectory_controller.test | 39 ++
.../joint_partial_trajectory_controller_test.cpp | 637 +++++++++++++++++++++
.../test/joint_trajectory_controller.test | 24 +-
.../test/joint_trajectory_controller_test.cpp | 15 +-
.../test/joint_trajectory_controller_vel.test | 39 ++
.../test/joint_trajectory_segment_test.cpp | 129 ++---
joint_trajectory_controller/test/rrbot.cpp | 70 ++-
.../test/rrbot_partial_controllers.yaml | 15 +
.../test/rrbot_vel_controllers.yaml | 18 +
position_controllers/CHANGELOG.rst | 15 +
position_controllers/package.xml | 12 +-
ros_controllers/CHANGELOG.rst | 16 +
ros_controllers/package.xml | 29 +-
rqt_joint_trajectory_controller/CHANGELOG.rst | 15 +
rqt_joint_trajectory_controller/package.xml | 19 +-
velocity_controllers/CHANGELOG.rst | 18 +
.../joint_position_controller.h | 2 +-
velocity_controllers/package.xml | 28 +-
.../src/joint_position_controller.cpp | 2 +-
63 files changed, 1907 insertions(+), 929 deletions(-)
diff --git a/README.md b/README.md
index b43ba8d..f0fd810 100644
--- a/README.md
+++ b/README.md
@@ -3,12 +3,6 @@ ros_controllers
See [ros_control documentation](http://ros.org/wiki/ros_control) on ros.org
-
-rosbuild support
----------------
-
-By the hydro-devel branch of ros_controllers has been catkinized but remains backwards compatible with Fuerte and earlier via a bash script that enables manifest.xml files to be shown. To enable, run ``. enable_manifest_xml.sh`` in the root of this meta package and all of the manifest.xml files will be enabled.
-
### Build Status
-[![Build Status](https://travis-ci.org/ros-controls/ros_controllers.png?branch=hydro-devel)](https://travis-ci.org/ros-controls/ros_controllers)
\ No newline at end of file
+[![Build Status](https://travis-ci.org/ros-controls/ros_controllers.png?branch=hydro-devel)](https://travis-ci.org/ros-controls/ros_controllers)
diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst
index 6b6f607..6fe2aa1 100644
--- a/diff_drive_controller/CHANGELOG.rst
+++ b/diff_drive_controller/CHANGELOG.rst
@@ -2,6 +2,30 @@
Changelog for package diff_drive_controller
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+0.12.3 (2017-04-23)
+-------------------
+
+0.12.2 (2017-04-21)
+-------------------
+
+0.12.1 (2017-03-08)
+-------------------
+* Add exporting include dirs
+* Contributors: Bence Magyar
+
+0.12.0 (2017-02-15)
+-------------------
+* Fix most catkin lint issues
+* Change for format2
+* Add Enrique and Bence to maintainers
+* Add urdf compatibility header
+* Add --inorder to xacro calls
+* Add missing xacro tags
+* Use xacro instead of xacro.py
+* Disable angular jerk limit test
+* Replace boost::shared_ptr<urdf::XY> with urdf::XYConstSharedPtr when exists
+* Contributors: Bence Magyar
+
0.11.2 (2016-08-16)
-------------------
diff --git a/diff_drive_controller/CMakeLists.txt b/diff_drive_controller/CMakeLists.txt
index b0389ca..101d86f 100644
--- a/diff_drive_controller/CMakeLists.txt
+++ b/diff_drive_controller/CMakeLists.txt
@@ -3,10 +3,11 @@ project(diff_drive_controller)
find_package(catkin REQUIRED COMPONENTS
controller_interface
- urdf
+ nav_msgs
realtime_tools
tf
- nav_msgs)
+ urdf
+)
catkin_package(
INCLUDE_DIRS include
@@ -20,6 +21,9 @@ include_directories(
add_library(${PROJECT_NAME} src/diff_drive_controller.cpp src/odometry.cpp src/speed_limiter.cpp)
target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})
+install(DIRECTORY include/${PROJECT_NAME}/
+ DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION})
+
install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
@@ -30,7 +34,7 @@ install(FILES diff_drive_controller_plugins.xml
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
if (CATKIN_ENABLE_TESTING)
- find_package(catkin COMPONENTS rostest std_srvs controller_manager tf)
+ find_package(catkin REQUIRED COMPONENTS controller_manager rostest std_srvs tf)
include_directories(include ${catkin_INCLUDE_DIRS})
add_executable(diffbot test/diffbot.cpp)
diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml
index 3115d2c..274581f 100644
--- a/diff_drive_controller/package.xml
+++ b/diff_drive_controller/package.xml
@@ -1,8 +1,9 @@
-<package>
+<package format="2">
<name>diff_drive_controller</name>
- <version>0.11.2</version>
+ <version>0.12.3</version>
<description>Controller for a differential drive mobile base.</description>
- <maintainer email="bence.magyar at pal-robotics.com">Bence Magyar</maintainer>
+ <maintainer email="bence.magyar.robotics at gmail.com">Bence Magyar</maintainer>
+ <maintainer email="enrique.fernandez.perdomo at gmail.com">Enrique Fernandez</maintainer>
<license>BSD</license>
@@ -14,21 +15,13 @@
<buildtool_depend>catkin</buildtool_depend>
- <build_depend>controller_interface</build_depend>
- <build_depend>nav_msgs</build_depend>
- <build_depend>realtime_tools</build_depend>
- <build_depend>tf</build_depend>
- <build_depend>urdf</build_depend>
-
- <run_depend>controller_interface</run_depend>
- <run_depend>nav_msgs</run_depend>
- <run_depend>realtime_tools</run_depend>
- <run_depend>tf</run_depend>
- <run_depend>urdf</run_depend>
-
- <!--Tests-->
- <build_depend>rostest</build_depend>
+ <depend>controller_interface</depend>
+ <depend>nav_msgs</depend>
+ <depend>realtime_tools</depend>
+ <depend>tf</depend>
+ <depend>urdf</depend>
+ <test_depend>rostest</test_depend>
<test_depend>std_srvs</test_depend>
<test_depend>controller_manager</test_depend>
<test_depend>xacro</test_depend>
diff --git a/diff_drive_controller/src/diff_drive_controller.cpp b/diff_drive_controller/src/diff_drive_controller.cpp
index b581b04..2565dcf 100644
--- a/diff_drive_controller/src/diff_drive_controller.cpp
+++ b/diff_drive_controller/src/diff_drive_controller.cpp
@@ -42,6 +42,8 @@
#include <urdf_parser/urdf_parser.h>
+#include <urdf/urdfdom_compatibility.h>
+
#include <boost/assign.hpp>
#include <diff_drive_controller/diff_drive_controller.h>
@@ -58,7 +60,7 @@ static double euclideanOfVectors(const urdf::Vector3& vec1, const urdf::Vector3&
* \param link Link
* \return true if the link is modeled as a Cylinder; false otherwise
*/
-static bool isCylinder(const boost::shared_ptr<const urdf::Link>& link)
+static bool isCylinder(const urdf::LinkConstSharedPtr& link)
{
if (!link)
{
@@ -93,7 +95,7 @@ static bool isCylinder(const boost::shared_ptr<const urdf::Link>& link)
* \param [out] wheel_radius Wheel radius [m]
* \return true if the wheel radius was found; false otherwise
*/
-static bool getWheelRadius(const boost::shared_ptr<const urdf::Link>& wheel_link, double& wheel_radius)
+static bool getWheelRadius(const urdf::LinkConstSharedPtr& wheel_link, double& wheel_radius)
{
if (!isCylinder(wheel_link))
{
@@ -464,10 +466,10 @@ namespace diff_drive_controller{
return false;
}
- boost::shared_ptr<urdf::ModelInterface> model(urdf::parseURDF(robot_model_str));
+ urdf::ModelInterfaceSharedPtr model(urdf::parseURDF(robot_model_str));
- boost::shared_ptr<const urdf::Joint> left_wheel_joint(model->getJoint(left_wheel_name));
- boost::shared_ptr<const urdf::Joint> right_wheel_joint(model->getJoint(right_wheel_name));
+ urdf::JointConstSharedPtr left_wheel_joint(model->getJoint(left_wheel_name));
+ urdf::JointConstSharedPtr right_wheel_joint(model->getJoint(right_wheel_name));
if (lookup_wheel_separation)
{
diff --git a/diff_drive_controller/test/diff_drive_bad_urdf.test b/diff_drive_controller/test/diff_drive_bad_urdf.test
index 2932c6f..fc774f9 100644
--- a/diff_drive_controller/test/diff_drive_bad_urdf.test
+++ b/diff_drive_controller/test/diff_drive_bad_urdf.test
@@ -4,7 +4,7 @@
<!-- Override robot_description with bad urdf -->
<param name="robot_description"
- command="$(find xacro)/xacro.py '$(find diff_drive_controller)/test/diffbot_bad.xacro'" />
+ command="$(find xacro)/xacro '$(find diff_drive_controller)/test/diffbot_bad.xacro' --inorder" />
<!-- Controller test -->
<test test-name="diff_drive_fail_test"
diff --git a/diff_drive_controller/test/diff_drive_common.launch b/diff_drive_controller/test/diff_drive_common.launch
index b63aaa8..8be22b5 100644
--- a/diff_drive_controller/test/diff_drive_common.launch
+++ b/diff_drive_controller/test/diff_drive_common.launch
@@ -1,7 +1,7 @@
<launch>
<!-- Load diffbot model -->
<param name="robot_description"
- command="$(find xacro)/xacro.py '$(find diff_drive_controller)/test/diffbot.xacro'" />
+ command="$(find xacro)/xacro '$(find diff_drive_controller)/test/diffbot.xacro' --inorder" />
<!-- Start diffbot -->
<node name="diffbot"
diff --git a/diff_drive_controller/test/diff_drive_limits_test.cpp b/diff_drive_controller/test/diff_drive_limits_test.cpp
index 6f69b8f..f2d5f9d 100644
--- a/diff_drive_controller/test/diff_drive_limits_test.cpp
+++ b/diff_drive_controller/test/diff_drive_limits_test.cpp
@@ -123,6 +123,7 @@ TEST_F(DiffDriveControllerTest, testLinearVelocityLimits)
publish(cmd_vel);
}
+/* This test has been failing on Travis for a long time due to timing issues however it works well when ran manually
TEST_F(DiffDriveControllerTest, testAngularJerkLimits)
{
// wait for ROS
@@ -153,6 +154,7 @@ TEST_F(DiffDriveControllerTest, testAngularJerkLimits)
cmd_vel.angular.z = 0.0;
publish(cmd_vel);
}
+*/
TEST_F(DiffDriveControllerTest, testAngularAccelerationLimits)
{
diff --git a/diff_drive_controller/test/diff_drive_radius_param.test b/diff_drive_controller/test/diff_drive_radius_param.test
index cfd6a6e..c0e4f85 100644
--- a/diff_drive_controller/test/diff_drive_radius_param.test
+++ b/diff_drive_controller/test/diff_drive_radius_param.test
@@ -4,7 +4,7 @@
<!-- Override robot_description with sphere wheel urdf -->
<param name="robot_description"
- command="$(find xacro)/xacro.py '$(find diff_drive_controller)/test/diffbot_sphere_wheels.xacro'" />
+ command="$(find xacro)/xacro '$(find diff_drive_controller)/test/diffbot_sphere_wheels.xacro' --inorder" />
<!-- Provide the radius, since the bot's wheels are spheres, not cylinders -->
<param name="diffbot_controller/wheel_radius" value="0.11"/>
diff --git a/diff_drive_controller/test/diff_drive_radius_param_fail.test b/diff_drive_controller/test/diff_drive_radius_param_fail.test
index 8f99587..28a3b4d 100644
--- a/diff_drive_controller/test/diff_drive_radius_param_fail.test
+++ b/diff_drive_controller/test/diff_drive_radius_param_fail.test
@@ -4,7 +4,7 @@
<!-- Override robot_description with bad urdf -->
<param name="robot_description"
- command="$(find xacro)/xacro.py '$(find diff_drive_controller)/test/diffbot_sphere_wheels.xacro'" />
+ command="$(find xacro)/xacro '$(find diff_drive_controller)/test/diffbot_sphere_wheels.xacro' --inorder" />
<!-- Don't provide the radius parameter, so the controller should break -->
<!-- <param name="diffbot_controller/wheel_radius" value="0.11"/> -->
diff --git a/diff_drive_controller/test/diff_drive_separation_param.test b/diff_drive_controller/test/diff_drive_separation_param.test
index e39af27..4120242 100644
--- a/diff_drive_controller/test/diff_drive_separation_param.test
+++ b/diff_drive_controller/test/diff_drive_separation_param.test
@@ -4,7 +4,7 @@
<!-- Override robot_description with sphere wheel urdf -->
<param name="robot_description"
- command="$(find xacro)/xacro.py '$(find diff_drive_controller)/test/diffbot_sphere_wheels.xacro'" />
+ command="$(find xacro)/xacro '$(find diff_drive_controller)/test/diffbot_sphere_wheels.xacro' --inorder" />
<!-- Provide the radius, since the bot's wheels are spheres, not cylinders -->
<param name="diffbot_controller/wheel_radius" value="0.11"/>
<!-- Provide the wheel separation -->
diff --git a/diff_drive_controller/test/skid_steer_common.launch b/diff_drive_controller/test/skid_steer_common.launch
index fe7e948..0c61789 100644
--- a/diff_drive_controller/test/skid_steer_common.launch
+++ b/diff_drive_controller/test/skid_steer_common.launch
@@ -1,7 +1,7 @@
<launch>
<!-- Load skidsteerbot model -->
<param name="robot_description"
- command="$(find xacro)/xacro.py '$(find diff_drive_controller)/test/skidsteerbot.xacro'" />
+ command="$(find xacro)/xacro '$(find diff_drive_controller)/test/skidsteerbot.xacro' --inorder" />
<!-- Start skidsteerbot -->
<node name="skidsteerbot"
diff --git a/diff_drive_controller/test/sphere_wheel.xacro b/diff_drive_controller/test/sphere_wheel.xacro
index 0694a30..bd8dd47 100644
--- a/diff_drive_controller/test/sphere_wheel.xacro
+++ b/diff_drive_controller/test/sphere_wheel.xacro
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">
- <macro name="sphere_wheel" params="name parent radius *origin">
+ <xacro:macro name="sphere_wheel" params="name parent radius *origin">
<link name="${name}_link">
<inertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
@@ -24,7 +24,7 @@
<joint name="${name}_joint" type="continuous">
<parent link="${parent}_link"/>
<child link="${name}_link"/>
- <insert_block name="origin"/>
+ <xacro:insert_block name="origin"/>
<axis xyz="0 0 1"/>
</joint>
@@ -39,5 +39,5 @@
<gazebo reference="${name}_link">
<material>Gazebo/Red</material>
</gazebo>
- </macro>
+ </xacro:macro>
</robot>
diff --git a/diff_drive_controller/test/view_diffbot.launch b/diff_drive_controller/test/view_diffbot.launch
index cdc362e..5ce4247 100644
--- a/diff_drive_controller/test/view_diffbot.launch
+++ b/diff_drive_controller/test/view_diffbot.launch
@@ -4,7 +4,7 @@
<!-- load robot -->
<param name="robot_description"
- command="$(find xacro)/xacro.py '$(find diff_drive_controller)/test/diffbot.xacro'" />
+ command="$(find xacro)/xacro '$(find diff_drive_controller)/test/diffbot.xacro' --inorder" />
<!-- Start diffbot -->
<node name="diffbot"
diff --git a/diff_drive_controller/test/view_skidsteerbot.launch b/diff_drive_controller/test/view_skidsteerbot.launch
index 66d8d5c..ce82994 100644
--- a/diff_drive_controller/test/view_skidsteerbot.launch
+++ b/diff_drive_controller/test/view_skidsteerbot.launch
@@ -4,7 +4,7 @@
<!-- load robot -->
<param name="robot_description"
- command="$(find xacro)/xacro.py '$(find diff_drive_controller)/test/skidsteerbot.xacro'" />
+ command="$(find xacro)/xacro '$(find diff_drive_controller)/test/skidsteerbot.xacro' --inorder" />
<!-- Start skidsteerbot -->
<node name="skidsteerbot"
diff --git a/diff_drive_controller/test/wheel.xacro b/diff_drive_controller/test/wheel.xacro
index 6fa1bd6..1e8dd89 100644
--- a/diff_drive_controller/test/wheel.xacro
+++ b/diff_drive_controller/test/wheel.xacro
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">
- <macro name="wheel" params="name parent radius thickness *origin">
+ <xacro:macro name="wheel" params="name parent radius thickness *origin">
<link name="${name}_link">
<inertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
@@ -24,7 +24,7 @@
<joint name="${name}_joint" type="continuous">
<parent link="${parent}_link"/>
<child link="${name}_link"/>
- <insert_block name="origin"/>
+ <xacro:insert_block name="origin"/>
<axis xyz="0 0 1"/>
</joint>
@@ -39,5 +39,5 @@
<gazebo reference="${name}_link">
<material>Gazebo/Red</material>
</gazebo>
- </macro>
+ </xacro:macro>
</robot>
diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst
index 7f4ffdc..4cfd52d 100644
--- a/effort_controllers/CHANGELOG.rst
+++ b/effort_controllers/CHANGELOG.rst
@@ -2,6 +2,26 @@
Changelog for package effort_controllers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+0.12.3 (2017-04-23)
+-------------------
+* Supply NodeHandle to urdf::Model. Closes `#244 <https://github.com/ros-controls/ros_controllers/issues/244>`_
+* Contributors: Piyush Khandelwal
+
+0.12.2 (2017-04-21)
+-------------------
+
+0.12.1 (2017-03-08)
+-------------------
+
+0.12.0 (2017-02-15)
+-------------------
+* Fix most catkin lint issues
+* Remove unused dependency
+* Change for format2
+* Add Enrique and Bence to maintainers
+* Replace boost::shared_ptr<urdf::XY> with urdf::XYConstSharedPtr when exists
+* Contributors: Bence Magyar
+
0.11.2 (2016-08-16)
-------------------
* Included angles in dependencies
diff --git a/effort_controllers/CMakeLists.txt b/effort_controllers/CMakeLists.txt
index 68b844e..8b1bf40 100644
--- a/effort_controllers/CMakeLists.txt
+++ b/effort_controllers/CMakeLists.txt
@@ -6,8 +6,8 @@ find_package(catkin REQUIRED COMPONENTS
angles
controller_interface
control_msgs
- forward_command_controller
control_toolbox
+ forward_command_controller
realtime_tools
urdf
)
@@ -21,9 +21,9 @@ catkin_package(
controller_interface
control_msgs
control_toolbox
+ forward_command_controller
realtime_tools
urdf
- forward_command_controller
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
)
diff --git a/effort_controllers/include/effort_controllers/joint_position_controller.h b/effort_controllers/include/effort_controllers/joint_position_controller.h
index 15267c8..4846078 100644
--- a/effort_controllers/include/effort_controllers/joint_position_controller.h
+++ b/effort_controllers/include/effort_controllers/joint_position_controller.h
@@ -167,7 +167,7 @@ public:
double getPosition();
hardware_interface::JointHandle joint_;
- boost::shared_ptr<const urdf::Joint> joint_urdf_;
+ urdf::JointConstSharedPtr joint_urdf_;
realtime_tools::RealtimeBuffer<Commands> command_;
Commands command_struct_; // pre-allocated memory that is re-used to set the realtime buffer
diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml
index d529412..13bf50d 100644
--- a/effort_controllers/package.xml
+++ b/effort_controllers/package.xml
@@ -1,8 +1,10 @@
-<package>
+<package format="2">
<name>effort_controllers</name>
- <version>0.11.2</version>
+ <version>0.12.3</version>
<description>effort_controllers</description>
<maintainer email="adolfo.rodriguez at pal-robotics.com">Adolfo Rodriguez Tsouroukdissian</maintainer>
+ <maintainer email="bence.magyar.robotics at gmail.com">Bence Magyar</maintainer>
+ <maintainer email="enrique.fernandez.perdomo at gmail.com">Enrique Fernandez</maintainer>
<license>BSD</license>
@@ -14,23 +16,13 @@
<buildtool_depend>catkin</buildtool_depend>
- <build_depend>angles</build_depend>
- <build_depend>controller_interface</build_depend>
- <build_depend>control_msgs</build_depend>
- <build_depend>control_toolbox</build_depend>
- <build_depend>realtime_tools</build_depend>
- <build_depend>urdf</build_depend>
- <build_depend>forward_command_controller</build_depend>
- <build_depend>dynamic_reconfigure</build_depend>
-
- <run_depend>angles</run_depend>
- <run_depend>controller_interface</run_depend>
- <run_depend>control_msgs</run_depend>
- <run_depend>control_toolbox</run_depend>
- <run_depend>realtime_tools</run_depend>
- <run_depend>urdf</run_depend>
- <run_depend>forward_command_controller</run_depend>
- <run_depend>dynamic_reconfigure</run_depend>
+ <depend>angles</depend>
+ <depend>controller_interface</depend>
+ <depend>control_msgs</depend>
+ <depend>control_toolbox</depend>
+ <depend>realtime_tools</depend>
+ <depend>urdf</depend>
+ <depend>forward_command_controller</depend>
<export>
<controller_interface plugin="${prefix}/effort_controllers_plugins.xml"/>
diff --git a/effort_controllers/src/joint_position_controller.cpp b/effort_controllers/src/joint_position_controller.cpp
index a9f4be5..1cad388 100644
--- a/effort_controllers/src/joint_position_controller.cpp
+++ b/effort_controllers/src/joint_position_controller.cpp
@@ -80,7 +80,7 @@ bool JointPositionController::init(hardware_interface::EffortJointInterface *rob
// Get URDF info about joint
urdf::Model urdf;
- if (!urdf.initParam("robot_description"))
+ if (!urdf.initParamWithNodeHandle("robot_description", n))
{
ROS_ERROR("Failed to parse urdf file");
return false;
diff --git a/force_torque_sensor_controller/CHANGELOG.rst b/force_torque_sensor_controller/CHANGELOG.rst
index 3fcb2bb..7787b9b 100644
--- a/force_torque_sensor_controller/CHANGELOG.rst
+++ b/force_torque_sensor_controller/CHANGELOG.rst
@@ -2,6 +2,23 @@
Changelog for package force_torque_sensor_controller
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+0.12.3 (2017-04-23)
+-------------------
+
+0.12.2 (2017-04-21)
+-------------------
+
+0.12.1 (2017-03-08)
+-------------------
+
+0.12.0 (2017-02-15)
+-------------------
+* Fix most catkin lint issues
+* Sort dependencies
+* Change for format2
+* Add Enrique and Bence to maintainers
+* Contributors: Bence Magyar
+
0.11.2 (2016-08-16)
-------------------
diff --git a/force_torque_sensor_controller/CMakeLists.txt b/force_torque_sensor_controller/CMakeLists.txt
index 437f097..47fefa2 100644
--- a/force_torque_sensor_controller/CMakeLists.txt
+++ b/force_torque_sensor_controller/CMakeLists.txt
@@ -2,11 +2,24 @@ cmake_minimum_required(VERSION 2.8.3)
project(force_torque_sensor_controller)
# Load catkin and all dependencies required for this package
-find_package(catkin REQUIRED COMPONENTS controller_interface hardware_interface geometry_msgs realtime_tools)
+find_package(catkin REQUIRED COMPONENTS
+ controller_interface
+ geometry_msgs
+ hardware_interface
+ pluginlib
+ realtime_tools
+ roscpp
+)
# Declare catkin package
catkin_package(
- CATKIN_DEPENDS controller_interface hardware_interface geometry_msgs realtime_tools
+ CATKIN_DEPENDS
+ controller_interface
+ geometry_msgs
+ hardware_interface
+ pluginlib
+ realtime_tools
+ roscpp
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
)
@@ -14,7 +27,9 @@ catkin_package(
include_directories(include ${Boost_INCLUDE_DIR} ${catkin_INCLUDE_DIRS})
add_library(${PROJECT_NAME}
- src/force_torque_sensor_controller.cpp include/force_torque_sensor_controller/force_torque_sensor_controller.h)
+ src/force_torque_sensor_controller.cpp
+ include/force_torque_sensor_controller/force_torque_sensor_controller.h
+)
target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})
# Install
diff --git a/force_torque_sensor_controller/package.xml b/force_torque_sensor_controller/package.xml
index aaaff75..3031e2c 100644
--- a/force_torque_sensor_controller/package.xml
+++ b/force_torque_sensor_controller/package.xml
@@ -1,8 +1,10 @@
-<package>
+<package format="2">
<name>force_torque_sensor_controller</name>
- <version>0.11.2</version>
+ <version>0.12.3</version>
<description>Controller to publish state of force-torque sensors</description>
<maintainer email="adolfo.rodriguez at pal-robotics.com">Adolfo Rodriguez Tsouroukdissian</maintainer>
+ <maintainer email="bence.magyar.robotics at gmail.com">Bence Magyar</maintainer>
+ <maintainer email="enrique.fernandez.perdomo at gmail.com">Enrique Fernandez</maintainer>
<license>BSD</license>
@@ -14,19 +16,12 @@
<buildtool_depend>catkin</buildtool_depend>
- <build_depend>realtime_tools</build_depend>
- <build_depend>roscpp</build_depend>
- <build_depend>hardware_interface</build_depend>
- <build_depend>pluginlib</build_depend>
- <build_depend>controller_interface</build_depend>
- <build_depend>geometry_msgs</build_depend>
-
- <run_depend>realtime_tools</run_depend>
- <run_depend>roscpp</run_depend>
- <run_depend>hardware_interface</run_depend>
- <run_depend>pluginlib</run_depend>
- <run_depend>controller_interface</run_depend>
- <run_depend>geometry_msgs</run_depend>
+ <depend>controller_interface</depend>
+ <depend>geometry_msgs</depend>
+ <depend>hardware_interface</depend>
+ <depend>pluginlib</depend>
+ <depend>realtime_tools</depend>
+ <depend>roscpp</depend>
<export>
<controller_interface plugin="${prefix}/force_torque_sensor_plugin.xml"/>
diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst
index 1ecb380..283254d 100644
--- a/forward_command_controller/CHANGELOG.rst
+++ b/forward_command_controller/CHANGELOG.rst
@@ -2,6 +2,21 @@
Changelog for package forward_command_controller
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+0.12.3 (2017-04-23)
+-------------------
+
+0.12.2 (2017-04-21)
+-------------------
+
+0.12.1 (2017-03-08)
+-------------------
+
+0.12.0 (2017-02-15)
+-------------------
+* Change for format2
+* Add Enrique and Bence to maintainers
+* Contributors: Bence Magyar
+
0.11.2 (2016-08-16)
-------------------
diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml
index 45c361d..1d40baa 100644
--- a/forward_command_controller/package.xml
+++ b/forward_command_controller/package.xml
@@ -1,8 +1,10 @@
-<package>
+<package format="2">
<name>forward_command_controller</name>
- <version>0.11.2</version>
+ <version>0.12.3</version>
<description>forward_command_controller</description>
<maintainer email="adolfo.rodriguez at pal-robotics.com">Adolfo Rodriguez Tsouroukdissian</maintainer>
+ <maintainer email="bence.magyar.robotics at gmail.com">Bence Magyar</maintainer>
+ <maintainer email="enrique.fernandez.perdomo at gmail.com">Enrique Fernandez</maintainer>
<license>BSD</license>
@@ -14,14 +16,10 @@
<author>Adolfo Rodriguez Tsouroukdissian</author>
<buildtool_depend>catkin</buildtool_depend>
- <build_depend>controller_interface</build_depend>
- <build_depend>hardware_interface</build_depend>
- <build_depend>std_msgs</build_depend>
- <build_depend>realtime_tools</build_depend>
- <run_depend>controller_interface</run_depend>
- <run_depend>hardware_interface</run_depend>
- <run_depend>std_msgs</run_depend>
- <run_depend>realtime_tools</run_depend>
+ <depend>controller_interface</depend>
+ <depend>hardware_interface</depend>
+ <depend>std_msgs</depend>
+ <depend>realtime_tools</depend>
<export>
<cpp cflags="-I${prefix}/include"/>
diff --git a/gripper_action_controller/CHANGELOG.rst b/gripper_action_controller/CHANGELOG.rst
index 84296c3..1f1e212 100644
--- a/gripper_action_controller/CHANGELOG.rst
+++ b/gripper_action_controller/CHANGELOG.rst
@@ -2,6 +2,24 @@
Changelog for package gripper_action_controller
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+0.12.3 (2017-04-23)
+-------------------
+
+0.12.2 (2017-04-21)
+-------------------
+
+0.12.1 (2017-03-08)
+-------------------
+
+0.12.0 (2017-02-15)
+-------------------
+* Fix most catkin lint issues
+* Change for format2
+* Add Enrique and Bence to maintainers
+* urdf::Model typedefs had to be added to a different repo first
+* Replace boost::shared_ptr<urdf::XY> with urdf::XYConstSharedPtr when exists
+* Contributors: Bence Magyar
+
0.11.2 (2016-08-16)
-------------------
diff --git a/gripper_action_controller/CMakeLists.txt b/gripper_action_controller/CMakeLists.txt
index 2b925a9..b35a0c7 100644
--- a/gripper_action_controller/CMakeLists.txt
+++ b/gripper_action_controller/CMakeLists.txt
@@ -1,114 +1,40 @@
cmake_minimum_required(VERSION 2.8.3)
project(gripper_action_controller)
-## Find catkin macros and libraries
-## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
-## is used, also find other catkin packages
find_package(catkin
REQUIRED COMPONENTS
actionlib
angles
cmake_modules
- roscpp
- urdf
- control_toolbox
controller_interface
+ controller_manager
+ control_msgs
+ control_toolbox
hardware_interface
realtime_tools
- control_msgs
+ roscpp
trajectory_msgs
- controller_manager
+ urdf
xacro
)
-## System dependencies are found with CMake's conventions
-# find_package(Boost REQUIRED COMPONENTS system)
-
-
-## Uncomment this if the package has a setup.py. This macro ensures
-## modules and global scripts declared therein get installed
-## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
-# catkin_python_setup()
-
-################################################
-## Declare ROS messages, services and actions ##
-################################################
-
-## To declare and build messages, services or actions from within this
-## package, follow these steps:
-## * Let MSG_DEP_SET be the set of packages whose message types you use in
-## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
-## * In the file package.xml:
-## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
-## * If MSG_DEP_SET isn't empty the following dependencies might have been
-## pulled in transitively but can be declared for certainty nonetheless:
-## * add a build_depend tag for "message_generation"
-## * add a run_depend tag for "message_runtime"
-## * In this file (CMakeLists.txt):
-## * add "message_generation" and every package in MSG_DEP_SET to
-## find_package(catkin REQUIRED COMPONENTS ...)
-## * add "message_runtime" and every package in MSG_DEP_SET to
-## catkin_package(CATKIN_DEPENDS ...)
-## * uncomment the add_*_files sections below as needed
-## and list every .msg/.srv/.action file to be processed
-## * uncomment the generate_messages entry below
-## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
-
-## Generate messages in the 'msg' folder
-# add_message_files(
-# FILES
-# Message1.msg
-# Message2.msg
-# )
-
-## Generate services in the 'srv' folder
-# add_service_files(
-# FILES
-# Service1.srv
-# Service2.srv
-# )
-
-## Generate actions in the 'action' folder
-# add_action_files(
-# FILES
-# Action1.action
-# Action2.action
-# )
-
-## Generate added messages and services with any dependencies listed here
-# generate_messages(
-# DEPENDENCIES
-# control_msgs
-# )
-
-###################################
-## catkin specific configuration ##
-###################################
-## The catkin_package macro generates cmake config files for your package
-## Declare things to be passed to dependent projects
-## INCLUDE_DIRS: uncomment this if you package contains header files
-## LIBRARIES: libraries you create in this project that dependent projects also need
-## CATKIN_DEPENDS: catkin_packages dependent projects also need
-## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
INCLUDE_DIRS include
LIBRARIES gripper_action_controller
-CATKIN_DEPENDS actionlib cmake_modules control_msgs controller_interface hardware_interface realtime_tools
-# DEPENDS system_lib
+CATKIN_DEPENDS
+ actionlib
+ cmake_modules
+ controller_interface
+ control_msgs
+ hardware_interface
+ realtime_tools
+ trajectory_msgs
)
-###########
-## Build ##
-###########
-
-## Specify additional locations of header files
-## Your package locations should be listed before other locations
-# include_directories(include)
include_directories(
include ${catkin_INCLUDE_DIRS}
)
-## Declare a cpp library
add_library(gripper_action_controller
src/gripper_action_controller.cpp
include/gripper_action_controller/gripper_action_controller.h
@@ -118,60 +44,16 @@ target_link_libraries(gripper_action_controller
${catkin_LIBRARIES}
)
-## Declare a cpp executable
-# add_executable(gripper_action_controller_node src/gripper_action_controller_node.cpp)
-
-## Add cmake target dependencies of the executable/library
-## as an example, message headers may need to be generated before nodes
-# add_dependencies(gripper_action_controller_node gripper_action_controller_generate_messages_cpp)
-
-## Specify libraries to link a library or executable target against
-# target_link_libraries(gripper_action_controller_node
-# ${catkin_LIBRARIES}
-# )
-
-#############
-## Install ##
-#############
-
-# all install targets should use catkin DESTINATION variables
-# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
-
-## Mark executable scripts (Python etc.) for installation
-## in contrast to setup.py, you can choose the destination
-# install(PROGRAMS
-# scripts/my_python_script
-# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
-# )
-
-## Mark executables and/or libraries for installation
install(TARGETS gripper_action_controller
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
-## Mark cpp header files for installation
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
-# FILES_MATCHING PATTERN "*.h"
-# PATTERN ".svn" EXCLUDE
)
-## Mark other files for installation (e.g. launch and bag files, etc.)
install(FILES ros_control_plugins.xml
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
)
-
-#############
-## Testing ##
-#############
-
-## Add gtest based cpp test target and link libraries
-# catkin_add_gtest(${PROJECT_NAME}-test test/test_gripper_action_controller.cpp)
-# if(TARGET ${PROJECT_NAME}-test)
-# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
-# endif()
-
-## Add folders to be run by python nosetests
-# catkin_add_nosetests(test)
diff --git a/gripper_action_controller/include/gripper_action_controller/gripper_action_controller_impl.h b/gripper_action_controller/include/gripper_action_controller/gripper_action_controller_impl.h
index 2900741..6a868b3 100644
--- a/gripper_action_controller/include/gripper_action_controller/gripper_action_controller_impl.h
+++ b/gripper_action_controller/include/gripper_action_controller/gripper_action_controller_impl.h
@@ -41,9 +41,9 @@ std::string getLeafNamespace(const ros::NodeHandle& nh)
return complete_ns.substr(id + 1);
}
-boost::shared_ptr<urdf::Model> getUrdf(const ros::NodeHandle& nh, const std::string& param_name)
+urdf::ModelSharedPtr getUrdf(const ros::NodeHandle& nh, const std::string& param_name)
{
- boost::shared_ptr<urdf::Model> urdf(new urdf::Model);
+ urdf::ModelSharedPtr urdf(new urdf::Model);
std::string urdf_str;
// Check for robot_description in proper namespace
@@ -53,25 +53,24 @@ boost::shared_ptr<urdf::Model> getUrdf(const ros::NodeHandle& nh, const std::str
{
ROS_ERROR_STREAM("Failed to parse URDF contained in '" << param_name << "' parameter (namespace: " <<
nh.getNamespace() << ").");
- return boost::shared_ptr<urdf::Model>();
+ return urdf::ModelSharedPtr();
}
}
// Check for robot_description in root
else if (!urdf->initParam("robot_description"))
{
ROS_ERROR_STREAM("Failed to parse URDF contained in '" << param_name << "' parameter");
- return boost::shared_ptr<urdf::Model>();
+ return urdf::ModelSharedPtr();
}
return urdf;
}
-typedef boost::shared_ptr<const urdf::Joint> UrdfJointConstPtr;
-std::vector<UrdfJointConstPtr> getUrdfJoints(const urdf::Model& urdf, const std::vector<std::string>& joint_names)
+std::vector<urdf::JointConstSharedPtr> getUrdfJoints(const urdf::Model& urdf, const std::vector<std::string>& joint_names)
{
- std::vector<UrdfJointConstPtr> out;
+ std::vector<urdf::JointConstSharedPtr> out;
for (unsigned int i = 0; i < joint_names.size(); ++i)
{
- UrdfJointConstPtr urdf_joint = urdf.getJoint(joint_names[i]);
+ urdf::JointConstSharedPtr urdf_joint = urdf.getJoint(joint_names[i]);
if (urdf_joint)
{
out.push_back(urdf_joint);
@@ -79,7 +78,7 @@ std::vector<UrdfJointConstPtr> getUrdfJoints(const urdf::Model& urdf, const std:
else
{
ROS_ERROR_STREAM("Could not find joint '" << joint_names[i] << "' in URDF model.");
- return std::vector<UrdfJointConstPtr>();
+ return std::vector<urdf::JointConstSharedPtr>();
}
}
return out;
@@ -157,7 +156,7 @@ bool GripperActionController<HardwareInterface>::init(HardwareInterface* hw,
}
// URDF joints
- boost::shared_ptr<urdf::Model> urdf = getUrdf(root_nh, "robot_description");
+ urdf::ModelSharedPtr urdf = getUrdf(root_nh, "robot_description");
if (!urdf)
{
return false;
@@ -165,7 +164,7 @@ bool GripperActionController<HardwareInterface>::init(HardwareInterface* hw,
std::vector<std::string> joint_names;
joint_names.push_back(joint_name_);
- std::vector<UrdfJointConstPtr> urdf_joints = getUrdfJoints(*urdf, joint_names);
+ std::vector<urdf::JointConstSharedPtr> urdf_joints = getUrdfJoints(*urdf, joint_names);
if (urdf_joints.empty())
{
return false;
diff --git a/gripper_action_controller/package.xml b/gripper_action_controller/package.xml
index 37bbd33..c2871ea 100644
--- a/gripper_action_controller/package.xml
+++ b/gripper_action_controller/package.xml
@@ -1,74 +1,32 @@
<?xml version="1.0"?>
-<package>
+<package format="2">
<name>gripper_action_controller</name>
- <version>0.11.2</version>
+ <version>0.12.3</version>
<description>The gripper_action_controller package</description>
-
- <!-- One maintainer tag required, multiple allowed, one person per tag -->
- <!-- Example: -->
- <!-- <maintainer email="jane.doe at example.com">Jane Doe</maintainer> -->
<maintainer email="robot.moveit at gmail.com">Sachin Chitta</maintainer>
+ <maintainer email="bence.magyar.robotics at gmail.com">Bence Magyar</maintainer>
+ <maintainer email="enrique.fernandez.perdomo at gmail.com">Enrique Fernandez</maintainer>
-
- <!-- One license tag required, multiple allowed, one license per tag -->
- <!-- Commonly used license strings: -->
- <!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>BSD</license>
-
- <!-- Url tags are optional, but mutiple are allowed, one per tag -->
- <!-- Optional attribute type can be: website, bugtracker, or repository -->
- <!-- Example: -->
- <!-- <url type="website">http://wiki.ros.org/gripper_action_controller</url> -->
-
-
- <!-- Author tags are optional, mutiple are allowed, one per tag -->
- <!-- Authors do not have to be maintianers, but could be -->
- <!-- Example: -->
- <!-- <author email="jane.doe at example.com">Jane Doe</author> -->
<author email="robot.moveit at gmail.com">Sachin Chitta</author>
- <!-- The *_depend tags are used to specify dependencies -->
- <!-- Dependencies can be catkin packages or system dependencies -->
- <!-- Examples: -->
- <!-- Use build_depend for packages you need at compile time: -->
- <!-- <build_depend>message_generation</build_depend> -->
- <!-- Use buildtool_depend for build tool packages: -->
- <!-- <buildtool_depend>catkin</buildtool_depend> -->
- <!-- Use run_depend for packages you need at runtime: -->
- <!-- <run_depend>message_runtime</run_depend> -->
- <!-- Use test_depend for packages you need only for testing: -->
- <!-- <test_depend>gtest</test_depend> -->
<buildtool_depend>catkin</buildtool_depend>
- <build_depend>actionlib</build_depend>
- <build_depend>angles</build_depend>
- <build_depend>cmake_modules</build_depend>
- <build_depend>control_msgs</build_depend>
- <build_depend>control_toolbox</build_depend>
- <build_depend>controller_interface</build_depend>
- <build_depend>controller_manager</build_depend>
- <build_depend>hardware_interface</build_depend>
- <build_depend>realtime_tools</build_depend>
- <build_depend>roscpp</build_depend>
- <build_depend>trajectory_msgs</build_depend>
- <build_depend>urdf</build_depend>
- <build_depend>xacro</build_depend>
- <run_depend>actionlib</run_depend>
- <run_depend>angles</run_depend>
- <run_depend>cmake_modules</run_depend>
- <run_depend>control_msgs</run_depend>
- <run_depend>control_toolbox</run_depend>
- <run_depend>controller_interface</run_depend>
- <run_depend>controller_manager</run_depend>
- <run_depend>hardware_interface</run_depend>
- <run_depend>realtime_tools</run_depend>
- <run_depend>roscpp</run_depend>
- <run_depend>trajectory_msgs</run_depend>
- <run_depend>urdf</run_depend>
- <run_depend>xacro</run_depend>
+ <depend>actionlib</depend>
+ <depend>angles</depend>
+ <depend>cmake_modules</depend>
+ <depend>control_msgs</depend>
+ <depend>control_toolbox</depend>
+ <depend>controller_interface</depend>
+ <depend>controller_manager</depend>
+ <depend>hardware_interface</depend>
+ <depend>realtime_tools</depend>
+ <depend>roscpp</depend>
+ <depend>trajectory_msgs</depend>
+ <depend>urdf</depend>
+ <depend>xacro</depend>
- <!-- The export tag contains other, unspecified, tags -->
<export>
<controller_interface plugin="${prefix}/ros_control_plugins.xml"/>
</export>
diff --git a/imu_sensor_controller/CHANGELOG.rst b/imu_sensor_controller/CHANGELOG.rst
index b23e3c2..9bdf13e 100644
--- a/imu_sensor_controller/CHANGELOG.rst
+++ b/imu_sensor_controller/CHANGELOG.rst
@@ -2,6 +2,22 @@
Changelog for package imu_sensor_controller
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+0.12.3 (2017-04-23)
+-------------------
+
+0.12.2 (2017-04-21)
+-------------------
+
+0.12.1 (2017-03-08)
+-------------------
+
+0.12.0 (2017-02-15)
+-------------------
+* Fix most catkin lint issues
+* Change for format2
+* Add Enrique and Bence to maintainers
+* Contributors: Bence Magyar
+
0.11.2 (2016-08-16)
-------------------
diff --git a/imu_sensor_controller/CMakeLists.txt b/imu_sensor_controller/CMakeLists.txt
index 2f44b7d..df712fb 100644
--- a/imu_sensor_controller/CMakeLists.txt
+++ b/imu_sensor_controller/CMakeLists.txt
@@ -1,12 +1,23 @@
cmake_minimum_required(VERSION 2.8.3)
project(imu_sensor_controller)
-# Load catkin and all dependencies required for this package
-find_package(catkin REQUIRED COMPONENTS controller_interface hardware_interface sensor_msgs realtime_tools)
+find_package(catkin REQUIRED COMPONENTS
+ controller_interface
+ hardware_interface
+ pluginlib
+ realtime_tools
+ roscpp
+ sensor_msgs
+)
-# Declare catkin package
catkin_package(
- CATKIN_DEPENDS controller_interface hardware_interface sensor_msgs realtime_tools
+ CATKIN_DEPENDS
+ controller_interface
+ hardware_interface
+ pluginlib
+ realtime_tools
+ roscpp
+ sensor_msgs
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
)
@@ -14,7 +25,8 @@ catkin_package(
include_directories(include ${Boost_INCLUDE_DIR} ${catkin_INCLUDE_DIRS})
add_library(${PROJECT_NAME}
- src/imu_sensor_controller.cpp include/imu_sensor_controller/imu_sensor_controller.h)
+ src/imu_sensor_controller.cpp
+ include/imu_sensor_controller/imu_sensor_controller.h)
target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})
# Install
diff --git a/imu_sensor_controller/package.xml b/imu_sensor_controller/package.xml
index 121170d..b4bd718 100644
--- a/imu_sensor_controller/package.xml
+++ b/imu_sensor_controller/package.xml
@@ -1,8 +1,10 @@
-<package>
+<package format="2">
<name>imu_sensor_controller</name>
- <version>0.11.2</version>
+ <version>0.12.3</version>
<description>Controller to publish state of IMU sensors</description>
<maintainer email="adolfo.rodriguez at pal-robotics.com">Adolfo Rodriguez Tsouroukdissian</maintainer>
+ <maintainer email="bence.magyar.robotics at gmail.com">Bence Magyar</maintainer>
+ <maintainer email="enrique.fernandez.perdomo at gmail.com">Enrique Fernandez</maintainer>
<license>BSD</license>
@@ -14,19 +16,12 @@
<buildtool_depend>catkin</buildtool_depend>
- <build_depend>realtime_tools</build_depend>
- <build_depend>roscpp</build_depend>
- <build_depend>hardware_interface</build_depend>
- <build_depend>pluginlib</build_depend>
- <build_depend>controller_interface</build_depend>
- <build_depend>sensor_msgs</build_depend>
-
- <run_depend>realtime_tools</run_depend>
- <run_depend>roscpp</run_depend>
- <run_depend>hardware_interface</run_depend>
- <run_depend>pluginlib</run_depend>
- <run_depend>controller_interface</run_depend>
- <run_depend>sensor_msgs</run_depend>
+ <depend>realtime_tools</depend>
+ <depend>roscpp</depend>
+ <depend>hardware_interface</depend>
+ <depend>pluginlib</depend>
+ <depend>controller_interface</depend>
+ <depend>sensor_msgs</depend>
<export>
<controller_interface plugin="${prefix}/imu_sensor_plugin.xml"/>
diff --git a/joint_state_controller/CHANGELOG.rst b/joint_state_controller/CHANGELOG.rst
index 7dfc4e7..055f2fb 100644
--- a/joint_state_controller/CHANGELOG.rst
+++ b/joint_state_controller/CHANGELOG.rst
@@ -2,6 +2,20 @@
Changelog for package joint_state_controller
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+0.12.3 (2017-04-23)
+-------------------
+
+0.12.2 (2017-04-21)
+-------------------
+
+0.12.1 (2017-03-08)
+-------------------
+
+0.12.0 (2017-02-15)
+-------------------
+* Add Enrique and Bence to maintainers
+* Contributors: Bence Magyar
+
0.11.2 (2016-08-16)
-------------------
diff --git a/joint_state_controller/package.xml b/joint_state_controller/package.xml
index a3941e2..f5b02c5 100644
--- a/joint_state_controller/package.xml
+++ b/joint_state_controller/package.xml
@@ -1,8 +1,10 @@
<package format="2">
<name>joint_state_controller</name>
- <version>0.11.2</version>
+ <version>0.12.3</version>
<description>Controller to publish joint state</description>
<maintainer email="adolfo.rodriguez at pal-robotics.com">Adolfo Rodriguez Tsouroukdissian</maintainer>
+ <maintainer email="bence.magyar.robotics at gmail.com">Bence Magyar</maintainer>
+ <maintainer email="enrique.fernandez.perdomo at gmail.com">Enrique Fernandez</maintainer>
<license>BSD</license>
diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst
index d1d4f56..8c82b5a 100644
--- a/joint_trajectory_controller/CHANGELOG.rst
+++ b/joint_trajectory_controller/CHANGELOG.rst
@@ -2,6 +2,33 @@
Changelog for package joint_trajectory_controller
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+0.12.3 (2017-04-23)
+-------------------
+
+0.12.2 (2017-04-21)
+-------------------
+* Remove rqt_plot test_depend & make plots optional
+* Contributors: Bence Magyar
+
+0.12.1 (2017-03-08)
+-------------------
+
+0.12.0 (2017-02-15)
+-------------------
+* Fix missing controller_manager include
+* Ordered dependencies & cleanup
+* Change for format2
+* Add Enrique and Bence to maintainers
+* Add test that sends trajectory entirely in past
+* Use xacro instead of xacro.py
+* urdf::Model typedefs had to be added to a different repo first
+* Updated copyright info
+* jtc: Enable sending trajectories with a partial set of joints
+* Replace boost::shared_ptr<urdf::XY> with urdf::XYConstSharedPtr when exists
+* Infrastructure for testing the velocity_controllers::JointTrajectoryController.
+* jtc: Enable sending trajectories with a partial set of joints
+* Contributors: Beatriz Leon, Bence Magyar, Miguel Prada
+
0.11.2 (2016-08-16)
-------------------
diff --git a/joint_trajectory_controller/CMakeLists.txt b/joint_trajectory_controller/CMakeLists.txt
index 985e042..87ef18a 100644
--- a/joint_trajectory_controller/CMakeLists.txt
+++ b/joint_trajectory_controller/CMakeLists.txt
@@ -15,8 +15,6 @@ find_package(catkin
realtime_tools
control_msgs
trajectory_msgs
- controller_manager
- xacro
)
# Declare catkin package
@@ -32,8 +30,6 @@ catkin_package(
realtime_tools
control_msgs
trajectory_msgs
- controller_manager
- xacro
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
)
@@ -54,9 +50,16 @@ add_library(${PROJECT_NAME} src/joint_trajectory_controller.cpp
target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})
-
if(CATKIN_ENABLE_TESTING)
+ find_package(catkin
+ REQUIRED COMPONENTS
+ actionlib
+ controller_manager
+ xacro
+ )
+
find_package(rostest REQUIRED)
+ include_directories(include ${catkin_INCLUDE_DIRS})
catkin_add_gtest(quintic_spline_segment_test test/quintic_spline_segment_test.cpp)
target_link_libraries(quintic_spline_segment_test ${catkin_LIBRARIES})
@@ -88,6 +91,11 @@ if(CATKIN_ENABLE_TESTING)
test/joint_trajectory_controller.test
test/joint_trajectory_controller_test.cpp)
target_link_libraries(joint_trajectory_controller_test ${catkin_LIBRARIES})
+
+ add_rostest_gtest(joint_trajectory_controller_vel_test
+ test/joint_trajectory_controller_vel.test
+ test/joint_trajectory_controller_test.cpp)
+ target_link_libraries(joint_trajectory_controller_vel_test ${catkin_LIBRARIES})
endif()
# Install
diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/init_joint_trajectory.h b/joint_trajectory_controller/include/joint_trajectory_controller/init_joint_trajectory.h
index 75cf188..37269ef 100644
--- a/joint_trajectory_controller/include/joint_trajectory_controller/init_joint_trajectory.h
+++ b/joint_trajectory_controller/include/joint_trajectory_controller/init_joint_trajectory.h
@@ -57,19 +57,19 @@ namespace joint_trajectory_controller
namespace internal
{
/**
- * \return The permutation vector between two containers.
- * If \p t1 is <tt>"{A, B, C, D}"</tt> and \p t2 is <tt>"{B, D, A, C}"</tt>, the associated permutation vector is
- * <tt>"{2, 0, 3, 1}"</tt>.
+ * \return The map between \p t1 indices (implicitly encoded in return vector indices) to \t2 indices.
+ * If \p t1 is <tt>"{C, B}"</tt> and \p t2 is <tt>"{A, B, C, D}"</tt>, the associated mapping vector is
+ * <tt>"{2, 1}"</tt>.
*/
template <class T>
-inline std::vector<unsigned int> permutation(const T& t1, const T& t2)
+inline std::vector<unsigned int> mapping(const T& t1, const T& t2)
{
typedef unsigned int SizeType;
+
+ // t1 must be a subset of t2
+ if (t1.size() > t2.size()) {return std::vector<SizeType>();}
- // Arguments must have the same size
- if (t1.size() != t2.size()) {return std::vector<SizeType>();}
-
- std::vector<SizeType> permutation_vector(t1.size()); // Return value
+ std::vector<SizeType> mapping_vector(t1.size()); // Return value
for (typename T::const_iterator t1_it = t1.begin(); t1_it != t1.end(); ++t1_it)
{
typename T::const_iterator t2_it = std::find(t2.begin(), t2.end(), *t1_it);
@@ -78,10 +78,10 @@ inline std::vector<unsigned int> permutation(const T& t1, const T& t2)
{
const SizeType t1_dist = std::distance(t1.begin(), t1_it);
const SizeType t2_dist = std::distance(t2.begin(), t2_it);
- permutation_vector[t1_dist] = t2_dist;
+ mapping_vector[t1_dist] = t2_dist;
}
}
- return permutation_vector;
+ return mapping_vector;
}
} // namespace
@@ -95,7 +95,9 @@ struct InitJointTrajectoryOptions
{
typedef realtime_tools::RealtimeServerGoalHandle<control_msgs::FollowJointTrajectoryAction> RealtimeGoalHandle;
typedef boost::shared_ptr<RealtimeGoalHandle> RealtimeGoalHandlePtr;
- typedef typename Trajectory::value_type::Scalar Scalar;
+ typedef typename Trajectory::value_type TrajectoryPerJoint;
+ typedef typename TrajectoryPerJoint::value_type Segment;
+ typedef typename Segment::Scalar Scalar;
InitJointTrajectoryOptions()
: current_trajectory(0),
@@ -103,7 +105,8 @@ struct InitJointTrajectoryOptions
angle_wraparound(0),
rt_goal_handle(),
default_tolerances(0),
- other_time_base(0)
+ other_time_base(0),
+ allow_partial_joints_goal(false)
{}
Trajectory* current_trajectory;
@@ -112,6 +115,13 @@ struct InitJointTrajectoryOptions
RealtimeGoalHandlePtr rt_goal_handle;
SegmentTolerances<Scalar>* default_tolerances;
ros::Time* other_time_base;
+ bool allow_partial_joints_goal;
+};
+
+template <class Trajectory>
+bool isNotEmpty(typename Trajectory::value_type trajPerJoint)
+{
+ return !trajPerJoint.empty();
};
/**
@@ -164,7 +174,6 @@ struct InitJointTrajectoryOptions
* Segment(const ros::Time& traj_start_time,
* const trajectory_msgs::JointTrajectoryPoint& start_point,
* const trajectory_msgs::JointTrajectoryPoint& end_point,
- * const std::vector<unsigned int>& permutation,
* const std::vector<Scalar>& position_offset)
* \endcode
* The following function must also be defined to properly handle continuous joints:
@@ -184,8 +193,10 @@ Trajectory initJointTrajectory(const trajectory_msgs::JointTrajectory& msg
const InitJointTrajectoryOptions<Trajectory>& options =
InitJointTrajectoryOptions<Trajectory>())
{
- typedef typename Trajectory::value_type Segment;
+ typedef typename Trajectory::value_type TrajectoryPerJoint;
+ typedef typename TrajectoryPerJoint::value_type Segment;
typedef typename Segment::Scalar Scalar;
+ typedef typename TrajectoryPerJoint::const_iterator TrajIter;
const unsigned int n_joints = msg.joint_names.size();
@@ -239,13 +250,35 @@ Trajectory initJointTrajectory(const trajectory_msgs::JointTrajectory& msg
o_msg_start_time = msg_start_time;
}
- // Permutation vector mapping the expected joint order to the message joint order
- // If unspecified, a trivial map (no permutation) is computed
const std::vector<std::string> joint_names = has_joint_names ? *(options.joint_names) : msg.joint_names;
- std::vector<unsigned int> permutation_vector = internal::permutation(joint_names, msg.joint_names);
+ if (has_angle_wraparound)
+ {
+ // Preconditions
+ const unsigned int n_angle_wraparound = options.angle_wraparound->size();
+ if (n_angle_wraparound != joint_names.size())
+ {
+ ROS_ERROR("Cannot create trajectory from message. "
+ "Vector specifying whether joints wrap around has an invalid size.");
+ return Trajectory();
+ }
+ }
+
+ // If partial joints goals are not allowed, goal should specify all controller joints
+ if (!options.allow_partial_joints_goal)
+ {
+ if (msg.joint_names.size() != joint_names.size())
+ {
+ ROS_ERROR("Cannot create trajectory from message. It does not contain the expected joints.");
+ return Trajectory();
+ }
+ }
+
+ // Mapping vector contains the map between the message joint order and the expected joint order
+ // If unspecified, a trivial map is computed
+ std::vector<unsigned int> mapping_vector = internal::mapping(msg.joint_names,joint_names);
- if (permutation_vector.empty())
+ if (mapping_vector.empty())
{
ROS_ERROR("Cannot create trajectory from message. It does not contain the expected joints.");
return Trajectory();
@@ -264,17 +297,17 @@ Trajectory initJointTrajectory(const trajectory_msgs::JointTrajectory& msg
// This point is used later on in this function, but is computed here, in advance because if the trajectory message
// contains a trajectory in the past, we can quickly return without spending additional computational resources
std::vector<trajectory_msgs::JointTrajectoryPoint>::const_iterator
- it = findPoint(msg, time); // Points to last point occurring before current time (NOTE: Using time, not o_time)
- if (it == msg.points.end())
+ msg_it = findPoint(msg, time); // Points to last point occurring before current time (NOTE: Using time, not o_time)
+ if (msg_it == msg.points.end())
{
- it = msg.points.begin(); // Entire trajectory is after current time
+ msg_it = msg.points.begin(); // Entire trajectory is after current time
}
else
{
- ++it; // Points to first point after current time OR sequence end
- if (it == msg.points.end())
+ ++msg_it; // Points to first point after current time OR sequence end
+ if (msg_it == msg.points.end())
{
- ros::Duration last_point_dur = time - (msg_start_time + (--it)->time_from_start);
+ ros::Duration last_point_dur = time - (msg_start_time + (--msg_it)->time_from_start);
ROS_WARN_STREAM("Dropping all " << msg.points.size() <<
" trajectory point(s), as they occur before the current time.\n" <<
"Last point is " << std::fixed << std::setprecision(3) << last_point_dur.toSec() <<
@@ -283,8 +316,8 @@ Trajectory initJointTrajectory(const trajectory_msgs::JointTrajectory& msg
}
else
{
- ros::Duration next_point_dur = msg_start_time + it->time_from_start - time;
- ROS_WARN_STREAM("Dropping first " << std::distance(msg.points.begin(), it) <<
+ ros::Duration next_point_dur = msg_start_time + msg_it->time_from_start - time;
+ ROS_WARN_STREAM("Dropping first " << std::distance(msg.points.begin(), msg_it) <<
" trajectory point(s) out of " << msg.points.size() <<
", as they occur before the current time.\n" <<
"First valid point will be reached in " << std::fixed << std::setprecision(3) <<
@@ -297,91 +330,156 @@ Trajectory initJointTrajectory(const trajectory_msgs::JointTrajectory& msg
// - Useful segments of new trajectory (contained in ROS message)
Trajectory result_traj; // Currently empty
- // Initialize offsets due to wrapping joints to zero
- std::vector<Scalar> position_offset(n_joints, 0.0);
-
- // Bridge current trajectory to new one
+ // Set active goal to segments after current time
if (has_current_trajectory)
{
- const Trajectory& curr_traj = *(options.current_trajectory);
-
- // Get the last time and state that will be executed from the current trajectory
- const typename Segment::Time last_curr_time = std::max(o_msg_start_time.toSec(), o_time.toSec()); // Important!
- typename Segment::State last_curr_state;
- sample(curr_traj, last_curr_time, last_curr_state);
-
- // Get the first time and state that will be executed from the new trajectory
- const typename Segment::Time first_new_time = o_msg_start_time.toSec() + (it->time_from_start).toSec();
- typename Segment::State first_new_state(*it, permutation_vector); // Here offsets are not yet applied
+ result_traj = *(options.current_trajectory);
- // Compute offsets due to wrapping joints
- if (has_angle_wraparound)
+ //Iterate to all segments after current time to set the new goal handler
+ for (unsigned int joint_id=0; joint_id < joint_names.size();joint_id++)
{
- position_offset = wraparoundOffset(last_curr_state.position,
- first_new_state.position,
- *(options.angle_wraparound));
- if (position_offset.empty())
+ const TrajectoryPerJoint& curr_joint_traj = result_traj[joint_id];
+ TrajIter active_seg = findSegment(curr_joint_traj, o_time.toSec()); // Currently active segment
+
+ while (std::distance(active_seg, curr_joint_traj.end())>=1)
{
- ROS_ERROR("Cannot create trajectory from message. "
- "Vector specifying whether joints wrap around has an invalid size.");
- return Trajectory();
+ (result_traj[joint_id])[std::distance(curr_joint_traj.begin(),active_seg)].setGoalHandle(options.rt_goal_handle);
+ ++active_seg;
}
}
+ }
+ else
+ result_traj.resize(joint_names.size());
+
+ //Iterate through the joints that are in the message, in the order of the mapping vector
+ //for (unsigned int joint_id=0; joint_id < joint_names.size();joint_id++)
+ for (unsigned int msg_joint_it=0; msg_joint_it < mapping_vector.size();msg_joint_it++)
+ {
+ std::vector<trajectory_msgs::JointTrajectoryPoint>::const_iterator it = msg_it;
+ if (!isValid(*it, it->positions.size()))
+ throw(std::invalid_argument("Size mismatch in trajectory point position, velocity or acceleration data."));
- // Apply offset to first state that will be executed from the new trajectory
- first_new_state = typename Segment::State(*it, permutation_vector, position_offset); // Now offsets are applied
+ TrajectoryPerJoint result_traj_per_joint; // Currently empty
+ unsigned int joint_id = mapping_vector[msg_joint_it];
- // Add useful segments of current trajectory to result
+ // Initialize offsets due to wrapping joints to zero
+ std::vector<Scalar> position_offset(1, 0.0);
+
+ //Initialize segment tolerance per joint
+ SegmentTolerancesPerJoint<Scalar> tolerances_per_joint;
+ tolerances_per_joint.state_tolerance = tolerances.state_tolerance[joint_id];
+ tolerances_per_joint.goal_state_tolerance = tolerances.goal_state_tolerance[joint_id];
+ tolerances_per_joint.goal_time_tolerance = tolerances.goal_time_tolerance;
+
+ // Bridge current trajectory to new one
+ if (has_current_trajectory)
{
- typedef typename Trajectory::const_iterator TrajIter;
- TrajIter first = findSegment(curr_traj, o_time.toSec()); // Currently active segment
- TrajIter last = findSegment(curr_traj, last_curr_time); // Segment active when new trajectory starts
- if (first == curr_traj.end() || last == curr_traj.end())
+ const TrajectoryPerJoint& curr_joint_traj = (*options.current_trajectory)[joint_id];
+
+ // Get the last time and state that will be executed from the current trajectory
+ const typename Segment::Time last_curr_time = std::max(o_msg_start_time.toSec(), o_time.toSec()); // Important!
+ typename Segment::State last_curr_state;
+ sample(curr_joint_traj, last_curr_time, last_curr_state);
+
+ // Get the first time and state that will be executed from the new trajectory
+ trajectory_msgs::JointTrajectoryPoint point_per_joint;
+ if (!it->positions.empty()) {point_per_joint.positions.resize(1, it->positions[msg_joint_it]);}
+ if (!it->velocities.empty()) {point_per_joint.velocities.resize(1, it->velocities[msg_joint_it]);}
+ if (!it->accelerations.empty()) {point_per_joint.accelerations.resize(1, it->accelerations[msg_joint_it]);}
+ point_per_joint.time_from_start = it->time_from_start;
+
+ const typename Segment::Time first_new_time = o_msg_start_time.toSec() + (it->time_from_start).toSec();
+ typename Segment::State first_new_state(point_per_joint); // Here offsets are not yet applied
+
+ // Compute offsets due to wrapping joints
+ if (has_angle_wraparound)
+ {
+ position_offset[0] = wraparoundJointOffset(last_curr_state.position[0],
+ first_new_state.position[0],
+ (*options.angle_wraparound)[joint_id]);
+ }
+
+ // Apply offset to first state that will be executed from the new trajectory
+ first_new_state = typename Segment::State(point_per_joint, position_offset); // Now offsets are applied
+
+ // Add useful segments of current trajectory to result
{
- ROS_ERROR("Unexpected error: Could not find segments in current trajectory. Please contact the package maintainer.");
- return Trajectory();
+ TrajIter first = findSegment(curr_joint_traj, o_time.toSec()); // Currently active segment
+ TrajIter last = findSegment(curr_joint_traj, last_curr_time); // Segment active when new trajectory starts
+ if (first == curr_joint_traj.end() || last == curr_joint_traj.end())
+ {
+ ROS_ERROR("Unexpected error: Could not find segments in current trajectory. Please contact the package maintainer.");
+ return Trajectory();
+ }
+ result_traj_per_joint.insert(result_traj_per_joint.begin(), first, ++last); // Range [first,last) will still be executed
}
- result_traj.insert(result_traj.begin(), first, ++last); // Range [first,last) will still be executed
+
+ // Add segment bridging current and new trajectories to result
+ Segment bridge_seg(last_curr_time, last_curr_state,
+ first_new_time, first_new_state);
+ bridge_seg.setGoalHandle(options.rt_goal_handle);
+ if (has_rt_goal_handle) {bridge_seg.setTolerances(tolerances_per_joint);}
+ result_traj_per_joint.push_back(bridge_seg);
}
- // Add segment bridging current and new trajectories to result
- Segment bridge_seg(last_curr_time, last_curr_state,
- first_new_time, first_new_state);
- bridge_seg.setGoalHandle(options.rt_goal_handle);
- if (has_rt_goal_handle) {bridge_seg.setTolerances(tolerances);}
- result_traj.push_back(bridge_seg);
- }
+ // Constants used in log statement at the end
+ const unsigned int num_old_segments = result_traj_per_joint.size() -1;
+ const unsigned int num_new_segments = std::distance(it, msg.points.end()) -1;
- // Constants used in log statement at the end
- const unsigned int num_old_segments = result_traj.size() -1;
- const unsigned int num_new_segments = std::distance(it, msg.points.end()) -1;
+ // Add useful segments of new trajectory to result
+ // - Construct all trajectory segments occurring after current time
+ // - As long as there remain two trajectory points we can construct the next trajectory segment
+ while (std::distance(it, msg.points.end()) >= 2)
+ {
+ std::vector<trajectory_msgs::JointTrajectoryPoint>::const_iterator next_it = it; ++next_it;
+
+ trajectory_msgs::JointTrajectoryPoint it_point_per_joint, next_it_point_per_joint;
+
+ if (!isValid(*it, it->positions.size()))
+ throw(std::invalid_argument("Size mismatch in trajectory point position, velocity or acceleration data."));
+ if (!it->positions.empty()) {it_point_per_joint.positions.resize(1, it->positions[msg_joint_it]);}
+ if (!it->velocities.empty()) {it_point_per_joint.velocities.resize(1, it->velocities[msg_joint_it]);}
+ if (!it->accelerations.empty()) {it_point_per_joint.accelerations.resize(1, it->accelerations[msg_joint_it]);}
+ it_point_per_joint.time_from_start = it->time_from_start;
+
+ if (!isValid(*next_it, next_it->positions.size()))
+ throw(std::invalid_argument("Size mismatch in trajectory point position, velocity or acceleration data."));
+ if (!next_it->positions.empty()) {next_it_point_per_joint.positions.resize(1, next_it->positions[msg_joint_it]);}
+ if (!next_it->velocities.empty()) {next_it_point_per_joint.velocities.resize(1, next_it->velocities[msg_joint_it]);}
+ if (!next_it->accelerations.empty()) {next_it_point_per_joint.accelerations.resize(1, next_it->accelerations[msg_joint_it]);}
+ next_it_point_per_joint.time_from_start = next_it->time_from_start;
+
+ Segment segment(o_msg_start_time, it_point_per_joint, next_it_point_per_joint, position_offset);
+ segment.setGoalHandle(options.rt_goal_handle);
+ if (has_rt_goal_handle) {segment.setTolerances(tolerances_per_joint);}
+ result_traj_per_joint.push_back(segment);
+ ++it;
+ }
- // Add useful segments of new trajectory to result
- // - Construct all trajectory segments occurring after current time
- // - As long as there remain two trajectory points we can construct the next trajectory segment
- while (std::distance(it, msg.points.end()) >= 2)
- {
- std::vector<trajectory_msgs::JointTrajectoryPoint>::const_iterator next_it = it; ++next_it;
- Segment segment(o_msg_start_time, *it, *next_it, permutation_vector, position_offset);
- segment.setGoalHandle(options.rt_goal_handle);
- if (has_rt_goal_handle) {segment.setTolerances(tolerances);}
- result_traj.push_back(segment);
- ++it;
+ // Useful debug info
+ std::stringstream log_str;
+ log_str << "Trajectory of joint " << joint_names[joint_id] << "has " << result_traj_per_joint.size() << " segments";
+ if (has_current_trajectory)
+ {
+ log_str << ":";
+ log_str << "\n- " << num_old_segments << " segment(s) will still be executed from previous trajectory.";
+ log_str << "\n- 1 segment added for transitioning between the current trajectory and first point of the input message.";
+ if (num_new_segments > 0) {log_str << "\n- " << num_new_segments << " new segments (" << (num_new_segments + 1) <<
+ " points) taken from the input trajectory.";}
+ }
+ else {log_str << ".";}
+ ROS_DEBUG_STREAM(log_str.str());
+
+ if (result_traj_per_joint.size() > 0)
+ result_traj[joint_id] = result_traj_per_joint;
}
- // Useful debug info
- std::stringstream log_str;
- log_str << "Trajectory has " << result_traj.size() << " segments";
- if (has_current_trajectory)
+ // If the trajectory for all joints is empty, empty the trajectory vector
+ typename Trajectory::const_iterator trajIter = std::find_if (result_traj.begin(), result_traj.end(), isNotEmpty<Trajectory>);
+ if (trajIter == result_traj.end())
{
- log_str << ":";
- log_str << "\n- " << num_old_segments << " segment(s) will still be executed from previous trajectory.";
- log_str << "\n- 1 segment added for transitioning between the current trajectory and first point of the input message.";
- if (num_new_segments > 0) {log_str << "\n- " << num_new_segments << " new segments (" << (num_new_segments + 1) <<
- " points) taken from the input trajectory.";}
+ result_traj.clear();
}
- else {log_str << ".";}
- ROS_DEBUG_STREAM(log_str.str());
return result_traj;
}
diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.h b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.h
index 4aaf291..7b5f469 100644
--- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.h
+++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.h
@@ -40,6 +40,7 @@
// Boost
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
+#include <boost/dynamic_bitset.hpp>
// ROS
#include <ros/node_handle.h>
@@ -166,8 +167,10 @@ private:
typedef boost::scoped_ptr<StatePublisher> StatePublisherPtr;
typedef JointTrajectorySegment<SegmentImpl> Segment;
- typedef std::vector<Segment> Trajectory;
+ typedef std::vector<Segment> TrajectoryPerJoint;
+ typedef std::vector<TrajectoryPerJoint> Trajectory;
typedef boost::shared_ptr<Trajectory> TrajectoryPtr;
+ typedef boost::shared_ptr<TrajectoryPerJoint> TrajectoryPerJointPtr;
typedef realtime_tools::RealtimeBox<TrajectoryPtr> TrajectoryBox;
typedef typename Segment::Scalar Scalar;
@@ -194,11 +197,11 @@ private:
TrajectoryBox curr_trajectory_box_;
TrajectoryPtr hold_trajectory_ptr_; ///< Last hold trajectory values.
- typename Segment::State current_state_; ///< Preallocated workspace variable.
- typename Segment::State desired_state_; ///< Preallocated workspace variable.
- typename Segment::State state_error_; ///< Preallocated workspace variable.
- typename Segment::State hold_start_state_; ///< Preallocated workspace variable.
- typename Segment::State hold_end_state_; ///< Preallocated workspace variable.
+ typename Segment::State current_state_; ///< Preallocated workspace variable.
+ typename Segment::State desired_state_; ///< Preallocated workspace variable.
+ typename Segment::State state_error_; ///< Preallocated workspace variable.
+ typename Segment::State desired_joint_state_; ///< Preallocated workspace variable.
+ typename Segment::State state_joint_error_; ///< Preallocated workspace variable.
realtime_tools::RealtimeBuffer<TimeData> time_data_;
@@ -206,6 +209,8 @@ private:
ros::Duration action_monitor_period_;
typename Segment::Time stop_trajectory_duration_;
+ boost::dynamic_bitset<> successful_joint_traj_;
+ bool allow_partial_joints_goal_;
// ROS API
ros::NodeHandle controller_nh_;
@@ -241,33 +246,6 @@ private:
*/
void setHoldPosition(const ros::Time& time);
- /**
- * \brief Check path tolerances.
- *
- * If path tolerances are violated, the currently active action goal will be aborted.
- *
- * \param state_error Error between the current and desired trajectory states.
- * \param segment Currently active trajectory segment.
- *
- * \pre \p segment is associated to the active goal handle.
- **/
- void checkPathTolerances(const typename Segment::State& state_error,
- const Segment& segment);
-
- /**
- * \brief Check goal tolerances.
- *
- * If goal tolerances are fulfilled, the currently active action goal will be considered successful.
- * If they are violated, the action goal will be aborted.
- *
- * \param state_error Error between the current and desired trajectory states.
- * \param segment Currently active trajectory segment.
- *
- * \pre \p segment is associated to the active goal handle.
- **/
- void checkGoalTolerances(const typename Segment::State& state_error,
- const Segment& segment);
-
};
} // namespace
diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller_impl.h b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller_impl.h
index 25f913f..cda6841 100644
--- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller_impl.h
+++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller_impl.h
@@ -76,9 +76,9 @@ std::vector<std::string> getStrings(const ros::NodeHandle& nh, const std::string
return out;
}
-boost::shared_ptr<urdf::Model> getUrdf(const ros::NodeHandle& nh, const std::string& param_name)
+urdf::ModelSharedPtr getUrdf(const ros::NodeHandle& nh, const std::string& param_name)
{
- boost::shared_ptr<urdf::Model> urdf(new urdf::Model);
+ urdf::ModelSharedPtr urdf(new urdf::Model);
std::string urdf_str;
// Check for robot_description in proper namespace
@@ -88,25 +88,24 @@ boost::shared_ptr<urdf::Model> getUrdf(const ros::NodeHandle& nh, const std::str
{
ROS_ERROR_STREAM("Failed to parse URDF contained in '" << param_name << "' parameter (namespace: " <<
nh.getNamespace() << ").");
- return boost::shared_ptr<urdf::Model>();
+ return urdf::ModelSharedPtr();
}
}
// Check for robot_description in root
else if (!urdf->initParam("robot_description"))
{
ROS_ERROR_STREAM("Failed to parse URDF contained in '" << param_name << "' parameter");
- return boost::shared_ptr<urdf::Model>();
+ return urdf::ModelSharedPtr();
}
return urdf;
}
-typedef boost::shared_ptr<const urdf::Joint> UrdfJointConstPtr;
-std::vector<UrdfJointConstPtr> getUrdfJoints(const urdf::Model& urdf, const std::vector<std::string>& joint_names)
+std::vector<urdf::JointConstSharedPtr> getUrdfJoints(const urdf::Model& urdf, const std::vector<std::string>& joint_names)
{
- std::vector<UrdfJointConstPtr> out;
+ std::vector<urdf::JointConstSharedPtr> out;
for (unsigned int i = 0; i < joint_names.size(); ++i)
{
- UrdfJointConstPtr urdf_joint = urdf.getJoint(joint_names[i]);
+ urdf::JointConstSharedPtr urdf_joint = urdf.getJoint(joint_names[i]);
if (urdf_joint)
{
out.push_back(urdf_joint);
@@ -114,7 +113,7 @@ std::vector<UrdfJointConstPtr> getUrdfJoints(const urdf::Model& urdf, const std:
else
{
ROS_ERROR_STREAM("Could not find joint '" << joint_names[i] << "' in URDF model.");
- return std::vector<UrdfJointConstPtr>();
+ return std::vector<urdf::JointConstSharedPtr>();
}
}
return out;
@@ -180,60 +179,6 @@ preemptActiveGoal()
}
template <class SegmentImpl, class HardwareInterface>
-inline void JointTrajectoryController<SegmentImpl, HardwareInterface>::
-checkPathTolerances(const typename Segment::State& state_error,
- const Segment& segment)
-{
- const RealtimeGoalHandlePtr rt_segment_goal = segment.getGoalHandle();
- const SegmentTolerances<Scalar>& tolerances = segment.getTolerances();
- if (!checkStateTolerance(state_error, tolerances.state_tolerance))
- {
- rt_segment_goal->preallocated_result_->error_code =
- control_msgs::FollowJointTrajectoryResult::PATH_TOLERANCE_VIOLATED;
- rt_segment_goal->setAborted(rt_segment_goal->preallocated_result_);
- rt_active_goal_.reset();
- }
-}
-
-template <class SegmentImpl, class HardwareInterface>
-inline void JointTrajectoryController<SegmentImpl, HardwareInterface>::
-checkGoalTolerances(const typename Segment::State& state_error,
- const Segment& segment)
-{
- // Controller uptime
- const ros::Time uptime = time_data_.readFromRT()->uptime;
-
- // Checks that we have ended inside the goal tolerances
- const RealtimeGoalHandlePtr rt_segment_goal = segment.getGoalHandle();
- const SegmentTolerances<Scalar>& tolerances = segment.getTolerances();
- const bool inside_goal_tolerances = checkStateTolerance(state_error, tolerances.goal_state_tolerance);
-
- if (inside_goal_tolerances)
- {
- rt_segment_goal->preallocated_result_->error_code = control_msgs::FollowJointTrajectoryResult::SUCCESSFUL;
- rt_segment_goal->setSucceeded(rt_segment_goal->preallocated_result_);
- rt_active_goal_.reset();
- }
- else if (uptime.toSec() < segment.endTime() + tolerances.goal_time_tolerance)
- {
- // Still have some time left to meet the goal state tolerances
- }
- else
- {
- if (verbose_)
- {
- ROS_ERROR_STREAM_NAMED(name_,"Goal tolerances failed");
- // Check the tolerances one more time to output the errors that occures
- checkStateTolerance(state_error, tolerances.goal_state_tolerance, true);
- }
-
- rt_segment_goal->preallocated_result_->error_code = control_msgs::FollowJointTrajectoryResult::GOAL_TOLERANCE_VIOLATED;
- rt_segment_goal->setAborted(rt_segment_goal->preallocated_result_);
- rt_active_goal_.reset();
- }
-}
-
-template <class SegmentImpl, class HardwareInterface>
JointTrajectoryController<SegmentImpl, HardwareInterface>::
JointTrajectoryController()
: verbose_(false), // Set to true during debugging
@@ -277,16 +222,23 @@ bool JointTrajectoryController<SegmentImpl, HardwareInterface>::init(HardwareInt
}
ROS_DEBUG_STREAM_NAMED(name_, "Stop trajectory has a duration of " << stop_trajectory_duration_ << "s.");
+ // Checking if partial trajectories are allowed
+ controller_nh_.param<bool>("allow_partial_joints_goal", allow_partial_joints_goal_, false);
+ if (allow_partial_joints_goal_)
+ {
+ ROS_DEBUG_NAMED(name_, "Goals with partial set of joints are allowed");
+ }
+
// List of controlled joints
joint_names_ = getStrings(controller_nh_, "joints");
if (joint_names_.empty()) {return false;}
const unsigned int n_joints = joint_names_.size();
// URDF joints
- boost::shared_ptr<urdf::Model> urdf = getUrdf(root_nh, "robot_description");
+ urdf::ModelSharedPtr urdf = getUrdf(root_nh, "robot_description");
if (!urdf) {return false;}
- std::vector<UrdfJointConstPtr> urdf_joints = getUrdfJoints(*urdf, joint_names_);
+ std::vector<urdf::JointConstSharedPtr> urdf_joints = getUrdfJoints(*urdf, joint_names_);
if (urdf_joints.empty()) {return false;}
assert(n_joints == urdf_joints.size());
@@ -344,14 +296,26 @@ bool JointTrajectoryController<SegmentImpl, HardwareInterface>::init(HardwareInt
this);
// Preeallocate resources
- current_state_ = typename Segment::State(n_joints);
- desired_state_ = typename Segment::State(n_joints);
- state_error_ = typename Segment::State(n_joints);
- hold_start_state_ = typename Segment::State(n_joints);
- hold_end_state_ = typename Segment::State(n_joints);
+ current_state_ = typename Segment::State(n_joints);
+ desired_state_ = typename Segment::State(n_joints);
+ state_error_ = typename Segment::State(n_joints);
+ desired_joint_state_ = typename Segment::State(1);
+ state_joint_error_ = typename Segment::State(1);
- Segment hold_segment(0.0, current_state_, 0.0, current_state_);
- hold_trajectory_ptr_->resize(1, hold_segment);
+ successful_joint_traj_ = boost::dynamic_bitset<>(joints_.size());
+
+ // Initialize trajectory with all joints
+ typename Segment::State current_joint_state_ = typename Segment::State(1);
+ for (unsigned int i = 0; i < n_joints; ++i)
+ {
+ current_joint_state_.position[0]= current_state_.position[i];
+ current_joint_state_.velocity[0]= current_state_.velocity[i];
+ Segment hold_segment(0.0, current_joint_state_, 0.0, current_joint_state_);
+
+ TrajectoryPerJoint joint_segment;
+ joint_segment.resize(1, hold_segment);
+ hold_trajectory_ptr_->push_back(joint_segment);
+ }
{
state_publisher_->lock();
@@ -393,16 +357,6 @@ update(const ros::Time& time, const ros::Duration& period)
// fetch the currently followed trajectory, it has been updated by the non-rt thread with something that starts in the
// next control cycle, leaving the current cycle without a valid trajectory.
- // Update desired state: sample trajectory at current time
- typename Trajectory::const_iterator segment_it = sample(curr_traj, time_data.uptime.toSec(), desired_state_);
- if (curr_traj.end() == segment_it)
- {
- // Non-realtime safe, but should never happen under normal operation
- ROS_ERROR_NAMED(name_,
- "Unexpected error: No trajectory defined at current time. Please contact the package maintainer.");
- return;
- }
-
// Update current state and state error
for (unsigned int i = 0; i < joints_.size(); ++i)
{
@@ -410,31 +364,95 @@ update(const ros::Time& time, const ros::Duration& period)
current_state_.velocity[i] = joints_[i].getVelocity();
// There's no acceleration data available in a joint handle
- state_error_.position[i] = desired_state_.position[i] - current_state_.position[i];
- state_error_.velocity[i] = desired_state_.velocity[i] - current_state_.velocity[i];
+ typename TrajectoryPerJoint::const_iterator segment_it = sample(curr_traj[i], time_data.uptime.toSec(), desired_joint_state_);
+ if (curr_traj[i].end() == segment_it)
+ {
+ // Non-realtime safe, but should never happen under normal operation
+ ROS_ERROR_NAMED(name_,
+ "Unexpected error: No trajectory defined at current time. Please contact the package maintainer.");
+ return;
+ }
+ desired_state_.position[i] = desired_joint_state_.position[0];
+ desired_state_.velocity[i] = desired_joint_state_.velocity[0];
+ desired_state_.acceleration[i] = 0.0;
+
+ state_joint_error_.position[0] = desired_joint_state_.position[0] - current_state_.position[i];
+ state_joint_error_.velocity[0] = desired_joint_state_.velocity[0] - current_state_.velocity[i];
+ state_joint_error_.acceleration[0] = 0.0;
+
+ state_error_.position[i] = desired_joint_state_.position[0] - current_state_.position[i];
+ state_error_.velocity[i] = desired_joint_state_.velocity[0] - current_state_.velocity[i];
state_error_.acceleration[i] = 0.0;
- }
- // Check tolerances if segment corresponds to currently active action goal
- const RealtimeGoalHandlePtr rt_segment_goal = segment_it->getGoalHandle();
- if (rt_segment_goal && rt_segment_goal == rt_active_goal_)
- {
- // Check tolerances
- if (time_data.uptime.toSec() < segment_it->endTime())
+ //Check tolerances
+ const RealtimeGoalHandlePtr rt_segment_goal = segment_it->getGoalHandle();
+ if (rt_segment_goal && rt_segment_goal == rt_active_goal_)
{
- // Currently executing a segment: check path tolerances
- checkPathTolerances(state_error_,
- *segment_it);
+ // Check tolerances
+ if (time_data.uptime.toSec() < segment_it->endTime())
+ {
+ // Currently executing a segment: check path tolerances
+ const SegmentTolerancesPerJoint<Scalar>& joint_tolerances = segment_it->getTolerances();
+ if (!checkStateTolerancePerJoint(state_joint_error_, joint_tolerances.state_tolerance))
+ {
+ if (verbose_)
+ {
+ ROS_ERROR_STREAM_NAMED(name_,"Path tolerances failed for joint: " << joint_names_[i]);
+ checkStateTolerancePerJoint(state_joint_error_, joint_tolerances.state_tolerance, true);
+ }
+ rt_segment_goal->preallocated_result_->error_code =
+ control_msgs::FollowJointTrajectoryResult::PATH_TOLERANCE_VIOLATED;
+ rt_segment_goal->setAborted(rt_segment_goal->preallocated_result_);
+ rt_active_goal_.reset();
+ successful_joint_traj_.reset();
+ }
+ }
+ else if (segment_it == --curr_traj[i].end())
+ {
+ if (verbose_)
+ ROS_DEBUG_STREAM_THROTTLE_NAMED(1,name_,"Finished executing last segment, checking goal tolerances");
+
+ // Controller uptime
+ const ros::Time uptime = time_data_.readFromRT()->uptime;
+
+ // Checks that we have ended inside the goal tolerances
+ const SegmentTolerancesPerJoint<Scalar>& tolerances = segment_it->getTolerances();
+ const bool inside_goal_tolerances = checkStateTolerancePerJoint(state_joint_error_, tolerances.goal_state_tolerance);
+
+ if (inside_goal_tolerances)
+ {
+ successful_joint_traj_[i] = 1;
+ }
+ else if (uptime.toSec() < segment_it->endTime() + tolerances.goal_time_tolerance)
+ {
+ // Still have some time left to meet the goal state tolerances
+ }
+ else
+ {
+ if (verbose_)
+ {
+ ROS_ERROR_STREAM_NAMED(name_,"Goal tolerances failed for joint: "<< joint_names_[i]);
+ // Check the tolerances one more time to output the errors that occurs
+ checkStateTolerancePerJoint(state_joint_error_, tolerances.goal_state_tolerance, true);
+ }
+
+ rt_segment_goal->preallocated_result_->error_code = control_msgs::FollowJointTrajectoryResult::GOAL_TOLERANCE_VIOLATED;
+ rt_segment_goal->setAborted(rt_segment_goal->preallocated_result_);
+ rt_active_goal_.reset();
+ successful_joint_traj_.reset();
+ }
+ }
}
- else if (segment_it == --curr_traj.end())
- {
- if (verbose_)
- ROS_DEBUG_STREAM_THROTTLE_NAMED(1,name_,"Finished executing last segement, checking goal tolerances");
+ }
- // Finished executing the LAST segment: check goal tolerances
- checkGoalTolerances(state_error_,
- *segment_it);
- }
+ //If there is an active goal and all segments finished successfully then set goal as succeeded
+ RealtimeGoalHandlePtr current_active_goal(rt_active_goal_);
+ if (current_active_goal and successful_joint_traj_.count() == joints_.size())
+ {
+ current_active_goal->preallocated_result_->error_code = control_msgs::FollowJointTrajectoryResult::SUCCESSFUL;
+ current_active_goal->setSucceeded(current_active_goal->preallocated_result_);
+ rt_active_goal_.reset();
+ successful_joint_traj_.reset();
}
// Hardware interface adapter: Generate and send commands
@@ -500,12 +518,13 @@ updateTrajectoryCommand(const JointTrajectoryConstPtr& msg, RealtimeGoalHandlePt
curr_trajectory_box_.get(curr_traj_ptr);
Options options;
- options.other_time_base = &next_update_uptime;
- options.current_trajectory = curr_traj_ptr.get();
- options.joint_names = &joint_names_;
- options.angle_wraparound = &angle_wraparound_;
- options.rt_goal_handle = gh;
- options.default_tolerances = &default_tolerances_;
+ options.other_time_base = &next_update_uptime;
+ options.current_trajectory = curr_traj_ptr.get();
+ options.joint_names = &joint_names_;
+ options.angle_wraparound = &angle_wraparound_;
+ options.rt_goal_handle = gh;
+ options.default_tolerances = &default_tolerances_;
+ options.allow_partial_joints_goal = allow_partial_joints_goal_;
// Update currently executing trajectory
try
@@ -540,7 +559,7 @@ template <class SegmentImpl, class HardwareInterface>
void JointTrajectoryController<SegmentImpl, HardwareInterface>::
goalCB(GoalHandle gh)
{
- ROS_DEBUG_STREAM_NAMED(name_,"Recieved new action goal");
+ ROS_DEBUG_STREAM_NAMED(name_,"Received new action goal");
// Precondition: Running controller
if (!this->isRunning())
@@ -552,11 +571,24 @@ goalCB(GoalHandle gh)
return;
}
- // Goal should specify all controller joints (they can be ordered differently). Reject if this is not the case
- using internal::permutation;
- std::vector<unsigned int> permutation_vector = permutation(joint_names_, gh.getGoal()->trajectory.joint_names);
+ // If partial joints goals are not allowed, goal should specify all controller joints
+ if (!allow_partial_joints_goal_)
+ {
+ if (gh.getGoal()->trajectory.joint_names.size() != joint_names_.size())
+ {
+ ROS_ERROR_NAMED(name_, "Joints on incoming goal don't match the controller joints.");
+ control_msgs::FollowJointTrajectoryResult result;
+ result.error_code = control_msgs::FollowJointTrajectoryResult::INVALID_JOINTS;
+ gh.setRejected(result);
+ return;
+ }
+ }
- if (permutation_vector.empty())
+ // Goal should specify valid controller joints (they can be ordered differently). Reject if this is not the case
+ using internal::mapping;
+ std::vector<unsigned int> mapping_vector = mapping(gh.getGoal()->trajectory.joint_names, joint_names_);
+
+ if (mapping_vector.empty())
{
ROS_ERROR_NAMED(name_, "Joints on incoming goal don't match the controller joints.");
control_msgs::FollowJointTrajectoryResult result;
@@ -639,19 +671,28 @@ queryStateService(control_msgs::QueryTrajectoryState::Request& req,
curr_trajectory_box_.get(curr_traj_ptr);
Trajectory& curr_traj = *curr_traj_ptr;
- typename Segment::State state;
- typename Trajectory::const_iterator segment_it = sample(curr_traj, sample_time.toSec(), state);
- if (curr_traj.end() == segment_it)
+ typename Segment::State response_point = typename Segment::State(joint_names_.size());
+
+ for (unsigned int i = 0; i < joints_.size(); ++i)
{
- ROS_ERROR_STREAM_NAMED(name_, "Requested sample time preceeds trajectory start time.");
- return false;
- }
+ typename Segment::State state;
+ typename TrajectoryPerJoint::const_iterator segment_it = sample(curr_traj[i], sample_time.toSec(), state);
+ if (curr_traj[i].end() == segment_it)
+ {
+ ROS_ERROR_STREAM_NAMED(name_, "Requested sample time precedes trajectory start time.");
+ return false;
+ }
+ response_point.position[i] = state.position[0];
+ response_point.velocity[i] = state.velocity[0];
+ response_point.acceleration[i] = state.acceleration[0];
+ }
+
// Populate response
resp.name = joint_names_;
- resp.position = state.position;
- resp.velocity = state.velocity;
- resp.acceleration = state.acceleration;
+ resp.position = response_point.position;
+ resp.velocity = response_point.velocity;
+ resp.acceleration = response_point.acceleration;
return true;
}
@@ -691,7 +732,10 @@ setHoldPosition(const ros::Time& time)
// - Create segment that goes from current state to above zero velocity state, in the desired time
// NOTE: The symmetry assumption from the second point above might not hold for all possible segment types
- assert(1 == hold_trajectory_ptr_->size());
+ assert(joint_names_.size() == hold_trajectory_ptr_->size());
+
+ typename Segment::State hold_start_state_ = typename Segment::State(1);
+ typename Segment::State hold_end_state_ = typename Segment::State(1);
const typename Segment::Time start_time = time.toSec();
const typename Segment::Time end_time = time.toSec() + stop_trajectory_duration_;
@@ -701,24 +745,24 @@ setHoldPosition(const ros::Time& time)
const unsigned int n_joints = joints_.size();
for (unsigned int i = 0; i < n_joints; ++i)
{
- hold_start_state_.position[i] = joints_[i].getPosition();
- hold_start_state_.velocity[i] = joints_[i].getVelocity();
- hold_start_state_.acceleration[i] = 0.0;
+ hold_start_state_.position[0] = joints_[i].getPosition();
+ hold_start_state_.velocity[0] = joints_[i].getVelocity();
+ hold_start_state_.acceleration[0] = 0.0;
- hold_end_state_.position[i] = joints_[i].getPosition();
- hold_end_state_.velocity[i] = -joints_[i].getVelocity();
- hold_end_state_.acceleration[i] = 0.0;
- }
- hold_trajectory_ptr_->front().init(start_time, hold_start_state_,
- end_time_2x, hold_end_state_);
+ hold_end_state_.position[0] = joints_[i].getPosition();
+ hold_end_state_.velocity[0] = -joints_[i].getVelocity();
+ hold_end_state_.acceleration[0] = 0.0;
- // Sample segment at its midpoint, that should have zero velocity
- hold_trajectory_ptr_->front().sample(end_time, hold_end_state_);
+ (*hold_trajectory_ptr_)[i].front().init(start_time, hold_start_state_,
+ end_time_2x, hold_end_state_);
- // Now create segment that goes from current state to one with zero end velocity
- hold_trajectory_ptr_->front().init(start_time, hold_start_state_,
- end_time, hold_end_state_);
+ // Sample segment at its midpoint, that should have zero velocity
+ (*hold_trajectory_ptr_)[i].front().sample(end_time, hold_end_state_);
+ // Now create segment that goes from current state to one with zero end velocity
+ (*hold_trajectory_ptr_)[i].front().init(start_time, hold_start_state_,
+ end_time, hold_end_state_);
+ }
curr_trajectory_box_.set(hold_trajectory_ptr_);
}
diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_segment.h b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_segment.h
index 3c024c7..6915a79 100644
--- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_segment.h
+++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_segment.h
@@ -85,31 +85,18 @@ public:
/**
* \param point Trajectory point.
*
- * \param permutation Permutation vector for mapping the joint order of a \p point to a desired order.
- * For instance, if \p point contains data associated to joints <tt>"{B, D, A, C}"</tt>, and we are interested in
- * constructing a segment with joints ordered as <tt>"{A, B, C, D}"</tt>, the permutation vector should
- * be set to <tt>"{2, 0, 3, 1}"</tt>.
- * If unspecified (empty), the joint order of \p point is preserved; if specified, its size must coincide with that
- * of \p point.
- * This vector can be computed using the \ref trajectory_interface::internal::permutation()
- * "permutation" utility function.
- *
- * \param position_offset Position offset to applpy to the data in \p point. This parameter is useful for handling
+ * \param position_offset Position offset to apply to the data in \p point. This parameter is useful for handling
* joints that wrap around (ie. continuous), to compensate for multi-turn offsets.
* If unspecified (empty), zero offsets are applied; if specified, its size must coincide with that of \p point.
*
- * \note The offsets in \p position_offsets correspond to joints not ordered according to \p point, but to joints
- * in the expected order, that is \p point with \p permutation applied to it.
*/
State(const trajectory_msgs::JointTrajectoryPoint& point,
- const std::vector<unsigned int>& permutation = std::vector<unsigned int>(),
const std::vector<Scalar>& position_offset = std::vector<Scalar>())
{
- init(point, permutation, position_offset);
+ init(point, position_offset);
}
void init(const trajectory_msgs::JointTrajectoryPoint& point,
- const std::vector<unsigned int>& permutation = std::vector<unsigned int>(),
const std::vector<Scalar>& position_offset = std::vector<Scalar>())
{
using std::invalid_argument;
@@ -121,17 +108,6 @@ public:
{
throw(invalid_argument("Size mismatch in trajectory point position, velocity or acceleration data."));
}
- if (!permutation.empty() && joint_dim != permutation.size())
- {
- throw(invalid_argument("Size mismatch between trajectory point and permutation vector."));
- }
- for (unsigned int i = 0; i < permutation.size(); ++i)
- {
- if (permutation[i] >= joint_dim)
- {
- throw(invalid_argument("Permutation vector contains out-of-range indices."));
- }
- }
if (!position_offset.empty() && joint_dim != position_offset.size())
{
throw(invalid_argument("Size mismatch between trajectory point "
@@ -145,15 +121,12 @@ public:
for (unsigned int i = 0; i < joint_dim; ++i)
{
- // Apply permutation only if it was specified, otherwise preserve original message order
- const unsigned int id = permutation.empty() ? i : permutation[i];
-
// Apply position offset only if it was specified
const Scalar offset = position_offset.empty() ? 0.0 : position_offset[i];
- if (!point.positions.empty()) {this->position[i] = point.positions[id] + offset;}
- if (!point.velocities.empty()) {this->velocity[i] = point.velocities[id];}
- if (!point.accelerations.empty()) {this->acceleration[i] = point.accelerations[id];}
+ if (!point.positions.empty()) {this->position[i] = point.positions[i] + offset;}
+ if (!point.velocities.empty()) {this->velocity[i] = point.velocities[i];}
+ if (!point.accelerations.empty()) {this->acceleration[i] = point.accelerations[i];}
}
}
};
@@ -171,7 +144,7 @@ public:
const Time& end_time,
const State& end_state)
: rt_goal_handle_(),
- tolerances_(start_state.position.size())
+ tolerances_()
{
Segment::init(start_time, start_state, end_time, end_state);
}
@@ -183,7 +156,6 @@ public:
* segment start time.
* \param start_point Start state in ROS message format.
* \param end_point End state in ROS message format.
- * \param permutation See \ref JointTrajectorySegment::State.
* \param position_offset See \ref JointTrajectorySegment::State.
*
* \throw std::invalid_argument If input parameters are inconsistent and a valid segment can't be constructed.
@@ -191,10 +163,9 @@ public:
JointTrajectorySegment(const ros::Time& traj_start_time,
const trajectory_msgs::JointTrajectoryPoint& start_point,
const trajectory_msgs::JointTrajectoryPoint& end_point,
- const std::vector<unsigned int>& permutation = std::vector<unsigned int>(),
const std::vector<Scalar>& position_offset = std::vector<Scalar>())
: rt_goal_handle_(),
- tolerances_(start_point.positions.size())
+ tolerances_()
{
if (start_point.positions.size() != end_point.positions.size())
{
@@ -207,8 +178,8 @@ public:
try
{
- const State start_state(start_point, permutation, position_offset);
- const State end_state(end_point, permutation, position_offset);
+ const State start_state(start_point, position_offset);
+ const State end_state(end_point, position_offset);
this->init(start_time, start_state,
end_time, end_state);
@@ -227,51 +198,45 @@ public:
void setGoalHandle(RealtimeGoalHandlePtr rt_goal_handle) {rt_goal_handle_ = rt_goal_handle;}
/** \return Tolerances this segment is associated to. */
- const SegmentTolerances<Scalar>& getTolerances() const {return tolerances_;}
+ const SegmentTolerancesPerJoint<Scalar>& getTolerances() const {return tolerances_;}
/** \brief Set the tolerances this segment is associated to. */
- void setTolerances(const SegmentTolerances<Scalar>& tolerances) {tolerances_ = tolerances;}
+ void setTolerances(const SegmentTolerancesPerJoint<Scalar>& tolerances) {tolerances_ = tolerances;}
private:
RealtimeGoalHandlePtr rt_goal_handle_;
- SegmentTolerances<Scalar> tolerances_;
+ SegmentTolerancesPerJoint<Scalar> tolerances_;
};
/**
* \param prev_position Previous position from which to compute the wraparound offset.
* \param next_position Next position from which to compute the wraparound offset.
- * \param angle_wraparound Vector of booleans where true values correspond to joints that wrap around
- * (ie. are continuous). Offsets will be computed only for these joints, otherwise they are set to zero.
- * \return Wraparound offsets that should be applied to \p next_position such that no multi-turns are performed when
+ * \param angle_wraparound Boolean where true value corresponds to a joint that wrap around
+ * (ie. is continuous). Offset will be computed only for this joint, otherwise it is set to zero.
+ * \return Wraparound offset that should be applied to \p next_position such that no multi-turns are performed when
* transitioning from \p prev_position.
* \tparam Scalar Scalar type.
*/
template <class Scalar>
-std::vector<Scalar> wraparoundOffset(const std::vector<Scalar>& prev_position,
- const std::vector<Scalar>& next_position,
- const std::vector<bool>& angle_wraparound)
+Scalar wraparoundJointOffset(const Scalar& prev_position,
+ const Scalar& next_position,
+ const bool& angle_wraparound)
{
- // Preconditions
- const unsigned int n_joints = angle_wraparound.size();
- if (n_joints != prev_position.size() || n_joints != next_position.size()) {return std::vector<Scalar>();}
-
// Return value
- std::vector<Scalar> pos_offset(n_joints, 0.0);
+ Scalar pos_offset = 0.0;
- for (unsigned int i = 0; i < angle_wraparound.size(); ++i)
+ if (angle_wraparound)
{
- if (angle_wraparound[i])
- {
- Scalar dist = angles::shortest_angular_distance(prev_position[i], next_position[i]);
+ Scalar dist = angles::shortest_angular_distance(prev_position, next_position);
- // Deal with singularity at M_PI shortest distance
- if (std::abs(dist) - M_PI < 1e-9)
- {
- dist = next_position[i] > prev_position[i] ? std::abs(dist) : -std::abs(dist);
- }
- pos_offset[i] = (prev_position[i] + dist) - next_position[i];
+ // Deal with singularity at M_PI shortest distance
+ if (std::abs(dist) - M_PI < 1e-9)
+ {
+ dist = next_position > prev_position ? std::abs(dist) : -std::abs(dist);
}
+ pos_offset = (prev_position + dist) - next_position;
}
+
return pos_offset;
}
diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.h b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.h
index efc0658..02e03e0 100644
--- a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.h
+++ b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.h
@@ -89,6 +89,28 @@ struct SegmentTolerances
};
/**
+ * \brief Trajectory segment tolerances per Joint
+ */
+template<class Scalar>
+struct SegmentTolerancesPerJoint
+{
+ SegmentTolerancesPerJoint()
+ : state_tolerance(static_cast<Scalar>(0.0)),
+ goal_state_tolerance(static_cast<Scalar>(0.0)),
+ goal_time_tolerance(static_cast<Scalar>(0.0))
+ {}
+
+ /** State tolerances that appply during segment execution. */
+ StateTolerances<Scalar> state_tolerance;
+
+ /** State tolerances that apply for the goal state only.*/
+ StateTolerances<Scalar> goal_state_tolerance;
+
+ /** Extra time after the segment end time allowed to reach the goal state tolerances. */
+ Scalar goal_time_tolerance;
+};
+
+/**
* \param state_error State error to check.
* \param state_tolerance State tolerances to check \p state_error against.
* \param show_errors If the joints that violate their tolerances should be output to console. NOT REALTIME if true
@@ -137,6 +159,45 @@ inline bool checkStateTolerance(const State&
}
/**
+ * \param state_error State error to check.
+ * \param state_tolerance State tolerances to check \p state_error against.
+ * \param show_errors If the joint that violate its tolerance should be output to console. NOT REALTIME if true
+ * \return True if \p state_error fulfills \p state_tolerance.
+ */
+template <class State>
+inline bool checkStateTolerancePerJoint(const State& state_error,
+ const StateTolerances<typename State::Scalar>& state_tolerance,
+ bool show_errors = false)
+{
+
+ using std::abs;
+
+ const bool is_valid = !(state_tolerance.position > 0.0 && abs(state_error.position[0]) > state_tolerance.position) &&
+ !(state_tolerance.velocity > 0.0 && abs(state_error.velocity[0]) > state_tolerance.velocity) &&
+ !(state_tolerance.acceleration > 0.0 && abs(state_error.acceleration[0]) > state_tolerance.acceleration);
+
+ if (!is_valid)
+ {
+ if( show_errors )
+ {
+ ROS_ERROR_STREAM_NAMED("tolerances","Path state tolerances failed:");
+
+ if (state_tolerance.position > 0.0 && abs(state_error.position[0]) > state_tolerance.position)
+ ROS_ERROR_STREAM_NAMED("tolerances","Position Error: " << state_error.position[0] <<
+ " Position Tolerance: " << state_tolerance.position);
+ if (state_tolerance.velocity > 0.0 && abs(state_error.velocity[0]) > state_tolerance.velocity)
+ ROS_ERROR_STREAM_NAMED("tolerances","Velocity Error: " << state_error.velocity[0] <<
+ " Velocity Tolerance: " << state_tolerance.velocity);
+ if (state_tolerance.acceleration > 0.0 && abs(state_error.acceleration[0]) > state_tolerance.acceleration)
+ ROS_ERROR_STREAM_NAMED("tolerances","Acceleration Error: " << state_error.acceleration[0] <<
+ " Acceleration Tolerance: " << state_tolerance.acceleration);
+ }
+ return false;
+ }
+ return true;
+}
+
+/**
* \brief Update data in \p tols from data in \p msg_tol.
*
* - If a value in \p tol_msg is positive, the corresponding values in \p tols will be overritten.
diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml
index ea0dbbf..05d3467 100644
--- a/joint_trajectory_controller/package.xml
+++ b/joint_trajectory_controller/package.xml
@@ -1,9 +1,11 @@
-<package>
+<package format="2">
<name>joint_trajectory_controller</name>
<description> Controller for executing joint-space trajectories on a group of joints. </description>
- <version>0.11.2</version>
+ <version>0.12.3</version>
<maintainer email="adolfo.rodriguez at pal-robotics.com">Adolfo Rodriguez Tsouroukdissian</maintainer>
+ <maintainer email="bence.magyar.robotics at gmail.com">Bence Magyar</maintainer>
+ <maintainer email="enrique.fernandez.perdomo at gmail.com">Enrique Fernandez</maintainer>
<license>BSD</license>
@@ -16,41 +18,21 @@
<buildtool_depend>catkin</buildtool_depend>
<build_depend>cmake_modules</build_depend>
- <build_depend>actionlib</build_depend>
- <build_depend>angles</build_depend>
- <build_depend>roscpp</build_depend>
- <build_depend>urdf</build_depend>
- <build_depend>control_toolbox</build_depend>
- <build_depend>controller_interface</build_depend>
- <build_depend>hardware_interface</build_depend>
- <build_depend>realtime_tools</build_depend>
-
- <build_depend>control_msgs</build_depend>
- <build_depend>trajectory_msgs</build_depend>
-
- <build_depend>rostest</build_depend> <!--Tests-only!-->
- <build_depend>controller_manager</build_depend> <!--Tests-only!-->
- <build_depend>xacro</build_depend> <!--Tests-only!-->
-
-
- <run_depend>actionlib</run_depend>
- <run_depend>angles</run_depend>
- <run_depend>roscpp</run_depend>
- <run_depend>urdf</run_depend>
-
- <run_depend>control_toolbox</run_depend>
- <run_depend>controller_interface</run_depend>
- <run_depend>hardware_interface</run_depend>
- <run_depend>realtime_tools</run_depend>
-
- <run_depend>control_msgs</run_depend>
- <run_depend>trajectory_msgs</run_depend>
-
- <run_depend>rostest</run_depend> <!--Tests-only!-->
- <run_depend>controller_manager</run_depend> <!--Tests-only!-->
- <run_depend>xacro</run_depend> <!--Tests-only!-->
- <run_depend>rqt_plot</run_depend> <!--Tests-only!-->
+ <depend>actionlib</depend>
+ <depend>angles</depend>
+ <depend>control_msgs</depend>
+ <depend>control_toolbox</depend>
+ <depend>controller_interface</depend>
+ <depend>hardware_interface</depend>
+ <depend>realtime_tools</depend>
+ <depend>roscpp</depend>
+ <depend>trajectory_msgs</depend>
+ <depend>urdf</depend>
+
+ <test_depend>rostest</test_depend>
+ <test_depend>controller_manager</test_depend>
+ <test_depend>xacro</test_depend>
<export>
<controller_interface plugin="${prefix}/ros_control_plugins.xml"/>
diff --git a/joint_trajectory_controller/test/init_joint_trajectory_test.cpp b/joint_trajectory_controller/test/init_joint_trajectory_test.cpp
index b26985d..c72035c 100644
--- a/joint_trajectory_controller/test/init_joint_trajectory_test.cpp
+++ b/joint_trajectory_controller/test/init_joint_trajectory_test.cpp
@@ -45,61 +45,73 @@ using std::string;
const double EPS = 1e-9;
typedef JointTrajectorySegment<trajectory_interface::QuinticSplineSegment<double> > Segment;
-typedef vector<Segment> Trajectory;
+typedef vector<Segment> TrajectoryPerJoint;
+typedef vector<TrajectoryPerJoint> Trajectory;
-TEST(PermutationTest, Permutation)
+TEST(MappingTest, Mapping)
{
vector<string> t1(4);
- t1[0] = "A";
- t1[1] = "B";
- t1[2] = "C";
- t1[3] = "D";
+ t1[0] = "B";
+ t1[1] = "D";
+ t1[2] = "A";
+ t1[3] = "C";
vector<string> t2(4);
- t2[0] = "B";
- t2[1] = "D";
- t2[2] = "A";
- t2[3] = "C";
+ t2[0] = "A";
+ t2[1] = "B";
+ t2[2] = "C";
+ t2[3] = "D";
- typedef vector<unsigned int> PermutationType;
- PermutationType ground_truth(4);
+ typedef vector<unsigned int> MappingType;
+ MappingType ground_truth(4);
ground_truth[0] = 2;
ground_truth[1] = 0;
ground_truth[2] = 3;
ground_truth[3] = 1;
- // Mismatching sizes: Return empty permutation vector
+ // Mismatching sizes (t2 smaller than t1): Return empty mapping vector
{
vector<string> t2_bad(1,"A");
- PermutationType perm = internal::permutation(t1, t2_bad);
- EXPECT_TRUE(perm.empty());
+ MappingType mapping = internal::mapping(t1, t2_bad);
+ EXPECT_TRUE(mapping.empty());
}
- // Mismatching contents: Return empty permutation vector
+ // Mismatching contents: Return empty mapping vector
{
vector<string> t2_bad(3,"A");
- PermutationType perm = internal::permutation(t1, t2_bad);
- EXPECT_TRUE(perm.empty());
+ MappingType mapping = internal::mapping(t1, t2_bad);
+ EXPECT_TRUE(mapping.empty());
}
// Valid parameters
{
- PermutationType perm = internal::permutation(t1, t2);
- EXPECT_EQ(ground_truth.size(), perm.size());
- EXPECT_EQ(ground_truth[0], perm[0]);
- EXPECT_EQ(ground_truth[1], perm[1]);
- EXPECT_EQ(ground_truth[2], perm[2]);
- EXPECT_EQ(ground_truth[3], perm[3]);
+ MappingType mapping = internal::mapping(t1, t2);
+ EXPECT_EQ(ground_truth.size(), mapping.size());
+ EXPECT_EQ(ground_truth[3], mapping[0]);
+ EXPECT_EQ(ground_truth[2], mapping[1]);
+ EXPECT_EQ(ground_truth[1], mapping[2]);
+ EXPECT_EQ(ground_truth[0], mapping[3]);
}
- // Valid parameters, inverse parameter order yields inverse permutation vector
+ // Valid parameters, inverse parameter order yields inverse mapping vector
{
- PermutationType perm = internal::permutation(t2, t1);
- EXPECT_EQ(ground_truth.size(), perm.size());
- EXPECT_EQ(ground_truth[3], perm[0]);
- EXPECT_EQ(ground_truth[2], perm[1]);
- EXPECT_EQ(ground_truth[1], perm[2]);
- EXPECT_EQ(ground_truth[0], perm[3]);
+ MappingType mapping = internal::mapping(t2, t1);
+ EXPECT_EQ(ground_truth.size(), mapping.size());
+ EXPECT_EQ(ground_truth[0], mapping[0]);
+ EXPECT_EQ(ground_truth[1], mapping[1]);
+ EXPECT_EQ(ground_truth[2], mapping[2]);
+ EXPECT_EQ(ground_truth[3], mapping[3]);
+ }
+
+ // Valid parameters, partial trajectory
+ {
+ vector<string> t1_partial(2);
+ t1_partial[0] = "B";
+ t1_partial[1] = "D";
+ MappingType mapping = internal::mapping(t1_partial, t2);
+ EXPECT_EQ(t1_partial.size(), mapping.size());
+ EXPECT_EQ(1, mapping[0]);
+ EXPECT_EQ(3, mapping[1]);
}
}
@@ -140,11 +152,15 @@ public:
state[1].velocity.push_back(1.0);
state[1].acceleration.push_back(1.0);
- curr_traj.push_back(Segment(0.0, state[0],
+ TrajectoryPerJoint joint_segment;
+
+ joint_segment.push_back(Segment(0.0, state[0],
1.0, state[1]));
- curr_traj.push_back(Segment(3.0, state[1],
+ joint_segment.push_back(Segment(3.0, state[1],
10.0, state[0])); // This is just junk that should be discarded in the tests
+
+ curr_traj.push_back(joint_segment);
}
protected:
@@ -182,14 +198,14 @@ TEST_F(InitTrajectoryTest, InitLogic)
{
const ros::Time time = msg_start_time;
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time);
- EXPECT_EQ(points.size() - 1, trajectory.size());
+ EXPECT_EQ(points.size() - 1, trajectory[0].size());
}
// First point: Return partial trajectory (last segment)
{
const ros::Time time = msg_start_time + msg_points.begin()->time_from_start;
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time);
- EXPECT_EQ(points.size() - 2, trajectory.size());
+ EXPECT_EQ(points.size() - 2, trajectory[0].size());
}
// Between the first and second points: Return partial trajectory (last segment)
@@ -197,7 +213,7 @@ TEST_F(InitTrajectoryTest, InitLogic)
const ros::Time time = msg_start_time +
ros::Duration((msg_points.begin()->time_from_start + (++msg_points.begin())->time_from_start).toSec() / 2.0);
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time);
- EXPECT_EQ(msg_points.size() - 2, trajectory.size());
+ EXPECT_EQ(msg_points.size() - 2, trajectory[0].size());
}
// Second point: Return empty trajectory
@@ -249,23 +265,23 @@ TEST_F(InitTrajectoryTest, InitLogicCombine)
// Before first point, starting the current trajectory: Return 4 segments: Last of current + bridge + full message
{
- const ros::Time time(curr_traj[0].startTime());
+ const ros::Time time(curr_traj[0][0].startTime());
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time, options);
- EXPECT_EQ(points.size() + 1, trajectory.size());
+ EXPECT_EQ(points.size() + 1, trajectory[0].size());
}
// Before first point: Return 4 segments: Last of current + bridge + full message
{
const ros::Time time = msg_start_time;
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time, options);
- EXPECT_EQ(points.size() + 1, trajectory.size());
+ EXPECT_EQ(points.size() + 1, trajectory[0].size());
}
// First point: Return partial trajectory, 3 segments: Last of current + bridge + last of message
{
const ros::Time time = msg_start_time + msg_points.begin()->time_from_start;
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time, options);
- EXPECT_EQ(points.size(), trajectory.size());
+ EXPECT_EQ(points.size(), trajectory[0].size());
}
// Between the first and second points: Same as before
@@ -273,14 +289,14 @@ TEST_F(InitTrajectoryTest, InitLogicCombine)
const ros::Time time = msg_start_time +
ros::Duration((msg_points.begin()->time_from_start + (++msg_points.begin())->time_from_start).toSec() / 2.0);
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time, options);
- EXPECT_EQ(msg_points.size(), trajectory.size());
+ EXPECT_EQ(msg_points.size(), trajectory[0].size());
}
// Second point: Return partial trajectory, 2 segments: Last of current + bridge (only one point of message made it)
{
const ros::Time time = msg_start_time + (++msg_points.begin())->time_from_start;
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time, options);
- EXPECT_EQ(msg_points.size() - 1, trajectory.size());
+ EXPECT_EQ(msg_points.size() - 1, trajectory[0].size());
}
// Between the second and third points: Same as before
@@ -288,7 +304,7 @@ TEST_F(InitTrajectoryTest, InitLogicCombine)
const ros::Time time = msg_start_time +
ros::Duration(((++msg_points.begin())->time_from_start + (--msg_points.end())->time_from_start).toSec() / 2.0);
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time, options);
- EXPECT_EQ(msg_points.size() - 1, trajectory.size());
+ EXPECT_EQ(msg_points.size() - 1, trajectory[0].size());
}
// Last point: Return empty trajectory
@@ -314,12 +330,12 @@ TEST_F(InitTrajectoryTest, InitValues)
// Input time is before first point: Return full trajectory (2 segments)
const ros::Time time = msg_start_time;
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time);
- ASSERT_EQ(points.size() - 1, trajectory.size());
+ ASSERT_EQ(points.size() - 1, trajectory[0].size());
// Check all segment start/end times and states
- for (unsigned int i = 0; i < trajectory.size(); ++i)
+ for (unsigned int i = 0; i < trajectory[0].size(); ++i)
{
- const Segment& segment = trajectory[i];
+ const Segment& segment = trajectory[0][i];
const JointTrajectoryPoint& p_start = msg_points[i];
const JointTrajectoryPoint& p_end = msg_points[i + 1];
@@ -354,17 +370,17 @@ TEST_F(InitTrajectoryTest, InitValues)
TEST_F(InitTrajectoryTest, InitValuesCombine)
{
// Before first point: Return 4 segments: Last of current + bridge + full message
- const ros::Time time(curr_traj[0].startTime());
+ const ros::Time time(curr_traj[0][0].startTime());
InitJointTrajectoryOptions<Trajectory> options;
options.current_trajectory = &curr_traj;
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time, options);
- ASSERT_EQ(points.size() + 1, trajectory.size());
+ ASSERT_EQ(points.size() + 1, trajectory[0].size());
// Check current trajectory segment start/end times and states (only one)
{
- const Segment& ref_segment = curr_traj[0];
- const Segment& segment = trajectory[0];
+ const Segment& ref_segment = curr_traj[0][0];
+ const Segment& segment = trajectory[0][0];
// Check start/end times
{
@@ -395,8 +411,8 @@ TEST_F(InitTrajectoryTest, InitValuesCombine)
// Check bridge trajectory segment start/end times and states (only one)
{
- const Segment& ref_segment = curr_traj[0];
- const Segment& segment = trajectory[1];
+ const Segment& ref_segment = curr_traj[0][0];
+ const Segment& segment = trajectory[0][1];
const vector<JointTrajectoryPoint>& msg_points = trajectory_msg.points;
@@ -433,12 +449,12 @@ TEST_F(InitTrajectoryTest, InitValuesCombine)
}
// Check all segment start/end times and states (2 segments)
- for (unsigned int traj_it = 2, msg_it = 0; traj_it < trajectory.size(); ++traj_it, ++msg_it)
+ for (unsigned int traj_it = 2, msg_it = 0; traj_it < trajectory[0].size(); ++traj_it, ++msg_it)
{
const ros::Time msg_start_time = trajectory_msg.header.stamp;
const vector<JointTrajectoryPoint>& msg_points = trajectory_msg.points;
- const Segment& segment = trajectory[traj_it];
+ const Segment& segment = trajectory[0][traj_it];
const JointTrajectoryPoint& p_start = msg_points[msg_it];
const JointTrajectoryPoint& p_end = msg_points[msg_it + 1];
@@ -470,7 +486,7 @@ TEST_F(InitTrajectoryTest, InitValuesCombine)
}
}
-TEST_F(InitTrajectoryTest, JointPermutation)
+TEST_F(InitTrajectoryTest, JointMapping)
{
// Add an extra joint to the trajectory message created in the fixture
trajectory_msg.points[0].positions.push_back(-2.0);
@@ -492,11 +508,13 @@ TEST_F(InitTrajectoryTest, JointPermutation)
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, trajectory_msg.header.stamp);
// Check position values only
- const Segment& segment = trajectory[0];
+ const Segment& segment_foo_joint = trajectory[0][0];
+ const Segment& segment_bar_joint = trajectory[1][0];
typename Segment::State state;
- segment.sample(segment.startTime(), state);
+ segment_foo_joint.sample(segment_foo_joint.startTime(), state);
EXPECT_EQ(trajectory_msg.points[0].positions[0], state.position[0]);
- EXPECT_EQ(trajectory_msg.points[0].positions[1], state.position[1]);
+ segment_bar_joint.sample(segment_bar_joint.startTime(), state);
+ EXPECT_EQ(trajectory_msg.points[0].positions[1], state.position[0]);
}
// Reference joint names vector that reverses joint order
@@ -510,13 +528,17 @@ TEST_F(InitTrajectoryTest, JointPermutation)
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, trajectory_msg.header.stamp, options);
// Check position values only
- const Segment& segment = trajectory[0];
- typename Segment::State state;
- segment.sample(segment.startTime(), state);
- EXPECT_NE(trajectory_msg.points[0].positions[0], state.position[0]);
- EXPECT_NE(trajectory_msg.points[0].positions[1], state.position[1]);
- EXPECT_EQ(trajectory_msg.points[0].positions[0], state.position[1]);
- EXPECT_EQ(trajectory_msg.points[0].positions[1], state.position[0]);
+ const Segment& segment_bar_joint = trajectory[0][0];
+ const Segment& segment_foo_joint = trajectory[1][0];
+
+ typename Segment::State state_foo_joint;
+ typename Segment::State state_bar_joint;
+ segment_foo_joint.sample(segment_foo_joint.startTime(), state_foo_joint);
+ segment_bar_joint.sample(segment_bar_joint.startTime(), state_bar_joint);
+ EXPECT_NE(trajectory_msg.points[0].positions[0], state_bar_joint.position[0]);
+ EXPECT_NE(trajectory_msg.points[0].positions[1], state_foo_joint.position[0]);
+ EXPECT_EQ(trajectory_msg.points[0].positions[0], state_foo_joint.position[0]);
+ EXPECT_EQ(trajectory_msg.points[0].positions[1], state_bar_joint.position[0]);
}
// Reference joint names size mismatch
@@ -553,19 +575,19 @@ TEST_F(InitTrajectoryTest, WrappingSpec)
}
// Before first point: Return 4 segments: Last of current + bridge + full message
- const ros::Time time(curr_traj[0].startTime());
+ const ros::Time time(curr_traj[0][0].startTime());
std::vector<bool> angle_wraparound(1, true);
InitJointTrajectoryOptions<Trajectory> options;
options.current_trajectory = &curr_traj;
options.angle_wraparound = &angle_wraparound;
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time, options);
- ASSERT_EQ(points.size() + 1, trajectory.size());
+ ASSERT_EQ(points.size() + 1, trajectory[0].size());
// Check current trajectory segment start/end times and states (only one)
{
- const Segment& ref_segment = curr_traj[0];
- const Segment& segment = trajectory[0];
+ const Segment& ref_segment = curr_traj[0][0];
+ const Segment& segment = trajectory[0][0];
// Check start/end times
{
@@ -596,8 +618,8 @@ TEST_F(InitTrajectoryTest, WrappingSpec)
// Check bridge trajectory segment start/end times and states (only one)
{
- const Segment& ref_segment = curr_traj[0];
- const Segment& segment = trajectory[1];
+ const Segment& ref_segment = curr_traj[0][0];
+ const Segment& segment = trajectory[0][1];
const vector<JointTrajectoryPoint>& msg_points = trajectory_msg.points;
@@ -634,12 +656,12 @@ TEST_F(InitTrajectoryTest, WrappingSpec)
}
// Check all segment start/end times and states (2 segments)
- for (unsigned int traj_it = 2, msg_it = 0; traj_it < trajectory.size(); ++traj_it, ++msg_it)
+ for (unsigned int traj_it = 2, msg_it = 0; traj_it < trajectory[0].size(); ++traj_it, ++msg_it)
{
const ros::Time msg_start_time = trajectory_msg.header.stamp;
const vector<JointTrajectoryPoint>& msg_points = trajectory_msg.points;
- const Segment& segment = trajectory[traj_it];
+ const Segment& segment = trajectory[0][traj_it];
const JointTrajectoryPoint& p_start = msg_points[msg_it];
const JointTrajectoryPoint& p_end = msg_points[msg_it + 1];
@@ -696,18 +718,18 @@ TEST_F(InitTrajectoryTest, IgnoreWrappingSpec)
}
// Before first point: Return 2 segments: Full message
- const ros::Time time(curr_traj[0].startTime());
+ const ros::Time time(curr_traj[0][0].startTime());
std::vector<bool> angle_wraparound(1, true);
InitJointTrajectoryOptions<Trajectory> options;
options.angle_wraparound = &angle_wraparound;
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time, options);
- ASSERT_EQ(points.size() - 1, trajectory.size());
+ ASSERT_EQ(points.size() - 1, trajectory[0].size());
// Check all segment start/end times and states (2 segments)
- for (unsigned int i = 0; i < trajectory.size(); ++i)
+ for (unsigned int i = 0; i < trajectory[0].size(); ++i)
{
- const Segment& segment = trajectory[i];
+ const Segment& segment = trajectory[0][i];
const JointTrajectoryPoint& p_start = msg_points[i];
const JointTrajectoryPoint& p_end = msg_points[i + 1];
@@ -751,21 +773,21 @@ TEST_F(InitTrajectoryTest, GoalHandleTest)
RealtimeGoalHandlePtr rt_goal(new RealtimeGoalHandle(gh));
// Before first point: Return 4 segments: Last of current + bridge + full message
- const ros::Time time(curr_traj[0].startTime());
+ const ros::Time time(curr_traj[0][0].startTime());
InitJointTrajectoryOptions<Trajectory> options;
options.current_trajectory = &curr_traj;
options.rt_goal_handle = rt_goal;
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time, options);
- ASSERT_EQ(points.size() + 1, trajectory.size());
+ ASSERT_EQ(points.size() + 1, trajectory[0].size());
// Segment of current trajectory preserves existing null goal handle
- ASSERT_FALSE(trajectory[0].getGoalHandle());
+ ASSERT_FALSE(trajectory[0][0].getGoalHandle());
// All further segments should be associated to the new goal handle
- for (unsigned int i = 1; i < trajectory.size(); ++i) // NOTE: Start index != 0
+ for (unsigned int i = 1; i < trajectory[0].size(); ++i) // NOTE: Start index != 0
{
- ASSERT_EQ(rt_goal, trajectory[i].getGoalHandle());
+ ASSERT_EQ(rt_goal, trajectory[0][i].getGoalHandle());
}
}
@@ -783,12 +805,12 @@ TEST_F(InitTrajectoryTest, OtherTimeBase)
// Before first point: Return 4 segments: Last of current + bridge + full message
const ros::Time time = msg_start_time;
Trajectory trajectory = initJointTrajectory<Trajectory>(trajectory_msg, time, options);
- ASSERT_EQ(points.size() + 1, trajectory.size());
+ ASSERT_EQ(points.size() + 1, trajectory[0].size());
// Check current trajectory segment start/end times (only one). Time offset does NOT apply
{
- const Segment& ref_segment = curr_traj[0];
- const Segment& segment = trajectory[0];
+ const Segment& ref_segment = curr_traj[0][0];
+ const Segment& segment = trajectory[0][0];
// Check start/end times
{
@@ -799,7 +821,7 @@ TEST_F(InitTrajectoryTest, OtherTimeBase)
// Check bridge trajectory segment start/end times and states (only one). Time offset applies to end state only
{
- const Segment& segment = trajectory[1];
+ const Segment& segment = trajectory[0][1];
const vector<JointTrajectoryPoint>& msg_points = trajectory_msg.points;
@@ -817,12 +839,12 @@ TEST_F(InitTrajectoryTest, OtherTimeBase)
}
// Check all segment start/end times and states (2 segments). Time offset does apply
- for (unsigned int traj_it = 2, msg_it = 0; traj_it < trajectory.size(); ++traj_it, ++msg_it)
+ for (unsigned int traj_it = 2, msg_it = 0; traj_it < trajectory[0].size(); ++traj_it, ++msg_it)
{
const ros::Time msg_start_time = trajectory_msg.header.stamp;
const vector<JointTrajectoryPoint>& msg_points = trajectory_msg.points;
- const Segment& segment = trajectory[traj_it];
+ const Segment& segment = trajectory[0][traj_it];
const JointTrajectoryPoint& p_start = msg_points[msg_it];
const JointTrajectoryPoint& p_end = msg_points[msg_it + 1];
diff --git a/joint_trajectory_controller/test/joint_partial_trajectory_controller.test b/joint_trajectory_controller/test/joint_partial_trajectory_controller.test
new file mode 100644
index 0000000..5c314d2
--- /dev/null
+++ b/joint_trajectory_controller/test/joint_partial_trajectory_controller.test
@@ -0,0 +1,39 @@
+<launch>
+ <arg name="display_plots" default="false"/>
+
+ <!-- Load RRbot model -->
+ <param name="robot_description"
+ command="$(find xacro)/xacro '$(find joint_trajectory_controller)/test/rrbot.xacro'" />
+
+ <!-- Start RRbot -->
+ <node name="rrbot"
+ pkg="joint_trajectory_controller"
+ type="rrbot"/>
+
+ <!-- Load controller config -->
+ <rosparam command="load" file="$(find joint_trajectory_controller)/test/rrbot_partial_controllers.yaml" />
+
+ <!-- Spawn controller -->
+ <node name="controller_spawner"
+ pkg="controller_manager" type="spawner" output="screen"
+ args="rrbot_controller" />
+
+ <group if="$(arg display_plots)">
+ <!-- rqt_plot monitoring -->
+ <node name="rrbot_pos_monitor"
+ pkg="rqt_plot"
+ type="rqt_plot"
+ args="/rrbot_controller/state/desired/positions[0]:positions[1],/rrbot_controller/state/actual/positions[0]:positions[1]" />
+
+ <node name="rrbot_vel_monitor"
+ pkg="rqt_plot"
+ type="rqt_plot"
+ args="/rrbot_controller/state/desired/velocities[0]:velocities[1],/rrbot_controller/state/actual/velocities[0]:velocities[1]" />
+ </group>
+
+ <!-- Controller test -->
+ <test test-name="joint_partial_trajectory_controller_test"
+ pkg="joint_trajectory_controller"
+ type="joint_partial_trajectory_controller_test"
+ time-limit="80.0"/>
+</launch>
diff --git a/joint_trajectory_controller/test/joint_partial_trajectory_controller_test.cpp b/joint_trajectory_controller/test/joint_partial_trajectory_controller_test.cpp
new file mode 100644
index 0000000..ad45a71
--- /dev/null
+++ b/joint_trajectory_controller/test/joint_partial_trajectory_controller_test.cpp
@@ -0,0 +1,637 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2016, Shadow Robot Company Ltd.
+//
+// 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 PAL Robotics S.L. 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 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.
+//////////////////////////////////////////////////////////////////////////////
+
+/// \author Beatriz Leon
+
+#include <algorithm>
+#include <cmath>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include <gtest/gtest.h>
+
+#include <ros/ros.h>
+#include <actionlib/client/simple_action_client.h>
+
+#include <std_msgs/Float64.h>
+#include <control_msgs/FollowJointTrajectoryAction.h>
+#include <control_msgs/JointTrajectoryControllerState.h>
+#include <control_msgs/QueryTrajectoryState.h>
+
+// Floating-point value comparison threshold
+const double EPS = 0.01;
+
+using actionlib::SimpleClientGoalState;
+
+class JointPartialTrajectoryControllerTest : public ::testing::Test
+{
+public:
+ JointPartialTrajectoryControllerTest()
+ : nh("rrbot_controller"),
+ short_timeout(1.0),
+ long_timeout(10.0),
+ controller_state()
+ {
+ n_joints = (2);
+ n_partial_joints = (2);
+ joint_names.resize(n_joints);
+ joint_names[0] = "joint1";
+ joint_names[1] = "joint2";
+
+ trajectory_msgs::JointTrajectoryPoint point;
+ point.positions.resize(n_joints, 0.0);
+ point.velocities.resize(n_joints, 0.0);
+ point.accelerations.resize(n_joints, 0.0);
+
+ // Go home trajectory
+ traj_home.joint_names = joint_names;
+ traj_home.points.resize(1, point);
+ traj_home.points[0].time_from_start = ros::Duration(1.0);
+
+ // Three-point trajectory
+ points.resize(3, point);
+ points[0].positions[0] = M_PI / 4.0;
+ points[0].positions[1] = 0.0;
+ points[0].time_from_start = ros::Duration(1.0);
+
+ points[1].positions[0] = 0.0;
+ points[1].positions[1] = -M_PI / 4.0;
+ points[1].time_from_start = ros::Duration(2.0);
+
+ points[2].positions[0] = -M_PI / 4.0;
+ points[2].positions[1] = M_PI / 4.0;
+ points[2].time_from_start = ros::Duration(4.0);
+
+ traj.joint_names = joint_names;
+ traj.points = points;
+
+ // Partial trajectory
+ traj_partial.joint_names.resize(1, "joint2");
+ points.resize(3, point);
+ points[0].positions[0] = M_PI / 4.0;
+ points[0].time_from_start = ros::Duration(1.0);
+
+ points[1].positions[0] = M_PI / 2.0;
+ points[1].time_from_start = ros::Duration(2.0);
+
+ points[2].positions[0] = -M_PI / 2.0;
+ points[2].time_from_start = ros::Duration(4.0);
+ traj_partial.points = points;
+
+ // Action goals
+ traj_home_goal.trajectory = traj_home;
+ traj_goal.trajectory = traj;
+ traj_partial_goal.trajectory = traj_partial;
+
+ // Smoothing publisher (determines how well the robot follows a trajectory)
+ smoothing_pub = ros::NodeHandle().advertise<std_msgs::Float64>("smoothing", 1);
+
+ // Trajectory publisher
+ traj_pub = nh.advertise<trajectory_msgs::JointTrajectory>("command", 1);
+
+ // State subscriber
+ state_sub = nh.subscribe<control_msgs::JointTrajectoryControllerState>("state",
+ 1,
+ &JointPartialTrajectoryControllerTest::stateCB,
+ this);
+
+ // Query state service client
+ query_state_service = nh.serviceClient<control_msgs::QueryTrajectoryState>("query_state");
+
+ // Action client
+ const std::string action_server_name = nh.getNamespace() + "/follow_joint_trajectory";
+ action_client.reset(new ActionClient(action_server_name));
+ action_client2.reset(new ActionClient(action_server_name));
+ }
+
+ ~JointPartialTrajectoryControllerTest()
+ {
+ state_sub.shutdown(); // This is important, to make sure that the callback is not woken up later in the destructor
+ }
+
+protected:
+ typedef actionlib::SimpleActionClient<control_msgs::FollowJointTrajectoryAction> ActionClient;
+ typedef boost::shared_ptr<ActionClient> ActionClientPtr;
+ typedef control_msgs::FollowJointTrajectoryGoal ActionGoal;
+ typedef control_msgs::JointTrajectoryControllerStateConstPtr StateConstPtr;
+
+ boost::mutex mutex;
+ ros::NodeHandle nh;
+
+ unsigned int n_joints;
+ unsigned int n_partial_joints;
+ std::vector<std::string> joint_names;
+ std::vector<trajectory_msgs::JointTrajectoryPoint> points;
+
+ trajectory_msgs::JointTrajectory traj_home;
+ trajectory_msgs::JointTrajectory traj;
+ trajectory_msgs::JointTrajectory traj_partial;
+ ActionGoal traj_home_goal;
+ ActionGoal traj_goal;
+ ActionGoal traj_partial_goal;
+
+ ros::Duration short_timeout;
+ ros::Duration long_timeout;
+
+ ros::Publisher smoothing_pub;
+ ros::Publisher traj_pub;
+ ros::Subscriber state_sub;
+ ros::ServiceClient query_state_service;
+ ActionClientPtr action_client;
+ ActionClientPtr action_client2;
+
+
+ StateConstPtr controller_state;
+
+ void stateCB(const StateConstPtr& state)
+ {
+ boost::mutex::scoped_lock lock(mutex);
+ controller_state = state;
+ }
+
+ StateConstPtr getState()
+ {
+ boost::mutex::scoped_lock lock(mutex);
+ return controller_state;
+ }
+
+ bool initState(const ros::Duration& timeout = ros::Duration(5.0))
+ {
+ bool init_ok = false;
+ ros::Time start_time = ros::Time::now();
+ while (!init_ok && (ros::Time::now() - start_time) < timeout)
+ {
+ {
+ boost::mutex::scoped_lock lock(mutex);
+ init_ok = controller_state && !controller_state->joint_names.empty();
+ }
+ ros::Duration(0.1).sleep();
+ }
+ return init_ok;
+ }
+
+ static bool waitForState(const ActionClientPtr& action_client,
+ const actionlib::SimpleClientGoalState& state,
+ const ros::Duration& timeout)
+ {
+ using ros::Time;
+ using ros::Duration;
+
+ Time start_time = Time::now();
+ while (action_client->getState() != state && ros::ok())
+ {
+ if (timeout >= Duration(0.0) && (Time::now() - start_time) > timeout) {return false;} // Timed-out
+ ros::Duration(0.01).sleep();
+ }
+ return true;
+ }
+};
+
+// Invalid messages ////////////////////////////////////////////////////////////////////////////////////////////////////
+
+TEST_F(JointPartialTrajectoryControllerTest, invalidMessages)
+{
+ ASSERT_TRUE(initState());
+ ASSERT_TRUE(action_client->waitForServer(long_timeout));
+
+ // Incompatible joint names
+ {
+ ActionGoal bad_goal = traj_home_goal;
+ bad_goal.trajectory.joint_names[0] = "bad_name";
+
+ bad_goal.trajectory.header.stamp = ros::Time(0); // Start immediately
+ action_client->sendGoal(bad_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::REJECTED, long_timeout));
+ EXPECT_EQ(action_client->getResult()->error_code, control_msgs::FollowJointTrajectoryResult::INVALID_JOINTS);
+ }
+
+ // No position data
+ {
+ ActionGoal bad_goal = traj_home_goal;
+ bad_goal.trajectory.points[0].positions.clear();
+
+ bad_goal.trajectory.header.stamp = ros::Time(0); // Start immediately
+ action_client->sendGoal(bad_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::REJECTED, long_timeout));
+ EXPECT_EQ(action_client->getResult()->error_code, control_msgs::FollowJointTrajectoryResult::INVALID_GOAL);
+ }
+
+ // Incompatible data sizes
+ {
+ ActionGoal bad_goal = traj_home_goal;
+ bad_goal.trajectory.points[0].positions.pop_back();
+
+ bad_goal.trajectory.header.stamp = ros::Time(0); // Start immediately
+ action_client->sendGoal(bad_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::REJECTED, long_timeout));
+ EXPECT_EQ(action_client->getResult()->error_code, control_msgs::FollowJointTrajectoryResult::INVALID_GOAL);
+ }
+
+ // Non-strictly increasing waypoint times
+ {
+ ActionGoal bad_goal = traj_goal;
+ bad_goal.trajectory.points[2].time_from_start = bad_goal.trajectory.points[1].time_from_start;
+
+ action_client->sendGoal(bad_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::REJECTED, long_timeout));
+ EXPECT_EQ(action_client->getResult()->error_code, control_msgs::FollowJointTrajectoryResult::INVALID_GOAL);
+ }
+
+ // Empty trajectory through action interface
+ // NOTE: Sending an empty trajectory through the topic interface cancels execution of all queued segments, but
+ // an empty trajectory is interpreted by the action interface as not having the correct joint names.
+ {
+ ActionGoal empty_goal;
+ action_client->sendGoal(empty_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::REJECTED, long_timeout));
+ EXPECT_EQ(action_client->getResult()->error_code, control_msgs::FollowJointTrajectoryResult::INVALID_JOINTS);
+ }
+}
+
+// Partial trajectory execution //////////////////////////////////////////////////////////////////////////////////////
+
+TEST_F(JointPartialTrajectoryControllerTest, allowPartialTrajIfSpecified)
+{
+ ASSERT_TRUE(initState());
+ ASSERT_TRUE(action_client->waitForServer(long_timeout));
+
+ // Send partial trajectory.
+ action_client->sendGoal(traj_partial_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::ACTIVE, long_timeout));
+}
+
+// Uninterrupted Partial trajectory execution //////////////////////////////////////////////////////////////////////////////////
+
+TEST_F(JointPartialTrajectoryControllerTest, topicSinglePartialTraj)
+{
+ ASSERT_TRUE(initState());
+
+ // Send partial trajectory
+ traj_partial.header.stamp = ros::Time(0); // Start immediately
+ traj_pub.publish(traj_partial);
+ ros::Duration wait_duration = traj_partial.points.back().time_from_start + ros::Duration(0.5);
+ wait_duration.sleep(); // Wait until done
+
+ // Validate state topic values
+ StateConstPtr state = getState();
+
+ EXPECT_NEAR(traj_partial.points.back().positions[0], state->desired.positions[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().velocities[0], state->desired.velocities[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().accelerations[0], state->desired.accelerations[1], EPS);
+
+ EXPECT_NEAR(traj_partial.points.back().positions[0], state->actual.positions[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().velocities[0], state->actual.velocities[1], EPS);
+
+ EXPECT_NEAR(0.0, state->error.positions[1], EPS);
+ EXPECT_NEAR(0.0, state->error.velocities[1], EPS);
+
+ // Validate query state service
+ control_msgs::QueryTrajectoryState srv;
+ srv.request.time = ros::Time::now();
+ ASSERT_TRUE(query_state_service.call(srv));
+ for (unsigned int i = 0; i < n_joints; ++i)
+ {
+ EXPECT_NEAR(state->desired.positions[i], srv.response.position[i], EPS);
+ EXPECT_NEAR(state->desired.velocities[i], srv.response.velocity[i], EPS);
+ EXPECT_NEAR(state->desired.accelerations[i], srv.response.acceleration[i], EPS);
+ }
+}
+
+TEST_F(JointPartialTrajectoryControllerTest, actionSinglePartialTraj)
+{
+ ASSERT_TRUE(initState());
+ ASSERT_TRUE(action_client->waitForServer(long_timeout));
+
+ // Send partial trajectory
+ traj_partial_goal.trajectory.header.stamp = ros::Time(0); // Start immediately
+ action_client->sendGoal(traj_partial_goal);
+
+ // Wait until done
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::SUCCEEDED, long_timeout));
+ EXPECT_EQ(action_client->getResult()->error_code, control_msgs::FollowJointTrajectoryResult::SUCCESSFUL);
+ ros::Duration(0.5).sleep(); // Allows values to settle to within EPS, especially accelerations
+
+ // Validate state topic values
+ StateConstPtr state = getState();
+
+ EXPECT_NEAR(traj_partial.points.back().positions[0], state->desired.positions[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().velocities[0], state->desired.velocities[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().accelerations[0], state->desired.accelerations[1], EPS);
+
+ EXPECT_NEAR(traj_partial.points.back().positions[0], state->actual.positions[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().velocities[0], state->actual.velocities[1], EPS);
+
+ EXPECT_NEAR(0.0, state->error.positions[1], EPS);
+ EXPECT_NEAR(0.0, state->error.velocities[1], EPS);
+}
+
+// Trajectory replacement //////////////////////////////////////////////////////////////////////////////////////////////
+
+TEST_F(JointPartialTrajectoryControllerTest, topicReplacesTopicTraj)
+{
+ ASSERT_TRUE(initState());
+ ASSERT_TRUE(action_client->waitForServer(long_timeout));
+
+ // Send trajectory
+ traj.header.stamp = ros::Time(0); // Start immediately
+ traj_pub.publish(traj);
+ ros::Duration wait_duration = traj.points.front().time_from_start;
+ wait_duration.sleep(); // Wait until ~first waypoint
+
+ // Send partial trajectory that preempts the previous one
+ traj_partial.header.stamp = ros::Time(0); // Start immediately
+ traj_pub.publish(traj_partial);
+ wait_duration = traj_partial.points.back().time_from_start + ros::Duration(0.5);
+ wait_duration.sleep(); // Wait until done
+
+ // Check that we're at the original trajectory for joint1 and on the partial trajectory for joint2
+ StateConstPtr state = getState();
+ EXPECT_NEAR(traj.points.back().positions[0], state->desired.positions[0], EPS);
+ EXPECT_NEAR(traj.points.back().velocities[0], state->desired.velocities[0], EPS);
+ EXPECT_NEAR(traj.points.back().accelerations[0], state->desired.accelerations[0], EPS);
+
+ EXPECT_NEAR(traj_partial.points.back().positions[0], state->desired.positions[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().velocities[0], state->desired.velocities[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().accelerations[0], state->desired.accelerations[1], EPS);
+}
+
+TEST_F(JointPartialTrajectoryControllerTest, actionReplacesActionTraj)
+{
+ ASSERT_TRUE(initState());
+ ASSERT_TRUE(action_client->waitForServer(long_timeout));
+
+ // Send trajectory
+ traj_goal.trajectory.header.stamp = ros::Time(0); // Start immediately
+ action_client->sendGoal(traj_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::ACTIVE, short_timeout));
+
+ ros::Duration wait_duration = traj.points.front().time_from_start;
+ wait_duration.sleep(); // Wait until ~first waypoint
+
+ // Send partial trajectory that preempts the previous one
+ traj_partial_goal.trajectory.header.stamp = ros::Time(0); // Start immediately
+ action_client2->sendGoal(traj_partial_goal);
+ ASSERT_TRUE(waitForState(action_client2, SimpleClientGoalState::ACTIVE, short_timeout));
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::PREEMPTED, short_timeout));
+ //ROS_ERROR_STREAM("state: "<< action_client->getState().toString());
+
+ // Wait until done
+ ASSERT_TRUE(waitForState(action_client2, SimpleClientGoalState::SUCCEEDED, long_timeout));
+ ros::Duration(0.5).sleep(); // Allows values to settle to within EPS, especially accelerations
+
+ // Check that we're at the original trajectory for joint1 and on the partial trajectory for joint2
+ StateConstPtr state = getState();
+ EXPECT_NEAR(traj.points.back().positions[0], state->desired.positions[0], EPS);
+ EXPECT_NEAR(traj.points.back().velocities[0], state->desired.velocities[0], EPS);
+ EXPECT_NEAR(traj.points.back().accelerations[0], state->desired.accelerations[0], EPS);
+
+ EXPECT_NEAR(traj_partial.points.back().positions[0], state->desired.positions[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().velocities[0], state->desired.velocities[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().accelerations[0], state->desired.accelerations[1], EPS);
+}
+
+TEST_F(JointPartialTrajectoryControllerTest, actionReplacesTopicTraj)
+{
+ ASSERT_TRUE(initState());
+ ASSERT_TRUE(action_client->waitForServer(long_timeout));
+
+ // Send trajectory
+ traj.header.stamp = ros::Time(0); // Start immediately
+ traj_pub.publish(traj);
+ ros::Duration wait_duration = traj.points.front().time_from_start;
+ wait_duration.sleep(); // Wait until ~first waypoint
+
+ // Send partial trajectory that preempts the previous one
+ traj_partial_goal.trajectory.header.stamp = ros::Time(0); // Start immediately
+ action_client->sendGoal(traj_partial_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::ACTIVE, short_timeout));
+
+ // Wait until done
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::SUCCEEDED, long_timeout));
+ ros::Duration(0.5).sleep(); // Allows values to settle to within EPS, especially accelerations
+
+ // Check that we're at the original trajectory for joint1 and on the partial trajectory for joint2
+ StateConstPtr state = getState();
+ EXPECT_NEAR(traj.points.back().positions[0], state->desired.positions[0], EPS);
+ EXPECT_NEAR(traj.points.back().velocities[0], state->desired.velocities[0], EPS);
+ EXPECT_NEAR(traj.points.back().accelerations[0], state->desired.accelerations[0], EPS);
+
+ EXPECT_NEAR(traj_partial.points.back().positions[0], state->desired.positions[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().velocities[0], state->desired.velocities[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().accelerations[0], state->desired.accelerations[1], EPS);
+}
+
+TEST_F(JointPartialTrajectoryControllerTest, topicReplacesActionTraj)
+{
+ ASSERT_TRUE(initState());
+ ASSERT_TRUE(action_client->waitForServer(long_timeout));
+
+ // Send trajectory
+ traj_goal.trajectory.header.stamp = ros::Time(0); // Start immediately
+ action_client->sendGoal(traj_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::ACTIVE, short_timeout));
+
+ ros::Duration wait_duration = traj.points.front().time_from_start;
+ wait_duration.sleep(); // Wait until ~first waypoint
+
+ // Send partial trajectory that preempts the previous one
+ traj_partial.header.stamp = ros::Time(0); // Start immediately
+ traj_pub.publish(traj_partial);
+
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::PREEMPTED, short_timeout));
+
+ wait_duration = traj_partial.points.back().time_from_start + ros::Duration(0.5);
+ wait_duration.sleep(); // Wait until done
+
+ // Check that we're at the original trajectory for joint1 and on the partial trajectory for joint2
+ StateConstPtr state = getState();
+ EXPECT_NEAR(traj.points.back().positions[0], state->desired.positions[0], EPS);
+ EXPECT_NEAR(traj.points.back().velocities[0], state->desired.velocities[0], EPS);
+ EXPECT_NEAR(traj.points.back().accelerations[0], state->desired.accelerations[0], EPS);
+
+ EXPECT_NEAR(traj_partial.points.back().positions[0], state->desired.positions[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().velocities[0], state->desired.velocities[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().accelerations[0], state->desired.accelerations[1], EPS);
+}
+
+// Ignore old trajectory points ////////////////////////////////////////////////////////////////////////////////////////
+
+TEST_F(JointPartialTrajectoryControllerTest, ignoreOldTopicTraj)
+{
+ ASSERT_TRUE(initState());
+
+ // Send trajectory
+ traj.header.stamp = ros::Time(0); // Start immediately
+ traj_pub.publish(traj);
+ ros::Duration wait_duration = traj.points.front().time_from_start;
+ wait_duration.sleep(); // Wait until ~first waypoint
+
+ // Send partial trajectory with all points occuring in the past. Should not preempts the previous one
+ traj_partial.header.stamp = ros::Time::now() - traj_partial.points.back().time_from_start - ros::Duration(0.5);
+ traj_pub.publish(traj_partial);
+
+ wait_duration = traj.points.back().time_from_start - traj.points.front().time_from_start + ros::Duration(0.5);
+ wait_duration.sleep(); // Wait until first trajectory is done
+
+ // Check that we're at the original trajectory end (Joint2 has not moved according to traj_partial)
+ StateConstPtr state = getState();
+ for (unsigned int i = 0; i < n_joints; ++i)
+ {
+ EXPECT_NEAR(traj.points.back().positions[i], state->desired.positions[i], EPS);
+ EXPECT_NEAR(traj.points.back().velocities[i], state->desired.velocities[i], EPS);
+ EXPECT_NEAR(traj.points.back().accelerations[i], state->desired.accelerations[i], EPS);
+ }
+}
+
+TEST_F(JointPartialTrajectoryControllerTest, ignoreOldActionTraj)
+{
+ ASSERT_TRUE(initState());
+ ASSERT_TRUE(action_client->waitForServer(long_timeout));
+
+ // Send trajectory
+ traj_goal.trajectory.header.stamp = ros::Time(0); // Start immediately
+ action_client->sendGoal(traj_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::ACTIVE, short_timeout));
+
+ ros::Duration wait_duration = traj.points.front().time_from_start;
+ wait_duration.sleep(); // Wait until ~first waypoint
+
+ // Send partial trajectory with all points occuring in the past. Should not preempts the previous one
+ traj_partial_goal.trajectory.header.stamp = ros::Time::now() - traj_partial.points.back().time_from_start - ros::Duration(0.5);
+ action_client2->sendGoal(traj_partial_goal);
+ ASSERT_TRUE(waitForState(action_client2, SimpleClientGoalState::REJECTED, short_timeout));
+
+ // Wait until done
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::SUCCEEDED, long_timeout));
+ ros::Duration(0.5).sleep(); // Allows values to settle to within EPS, especially accelerations
+
+ // Check that we're at the original trajectory end (Joint2 has not moved according to traj_partial)
+ StateConstPtr state = getState();
+ for (unsigned int i = 0; i < n_joints; ++i)
+ {
+ EXPECT_NEAR(traj.points.back().positions[i], state->desired.positions[i], EPS);
+ EXPECT_NEAR(traj.points.back().velocities[i], state->desired.velocities[i], EPS);
+ EXPECT_NEAR(traj.points.back().accelerations[i], state->desired.accelerations[i], EPS);
+ }
+}
+
+TEST_F(JointPartialTrajectoryControllerTest, ignorePartiallyOldActionTraj)
+{
+ ASSERT_TRUE(initState());
+ ASSERT_TRUE(action_client->waitForServer(long_timeout));
+
+ // Send trajectory
+ ActionGoal first_goal = traj_goal;
+ first_goal.trajectory.header.stamp = ros::Time(0); // Start immediately
+ action_client->sendGoal(first_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::ACTIVE, short_timeout));
+
+ ros::Duration wait_duration = first_goal.trajectory.points.front().time_from_start;
+ wait_duration.sleep(); // Wait until ~first waypoint
+
+ // Send partial trajectory with only the last point not occuring in the past. Only the last point should be executed
+ traj_partial_goal.trajectory.header.stamp = ros::Time::now() - traj.points.back().time_from_start + ros::Duration(1.0);
+ action_client2->sendGoal(traj_partial_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::PREEMPTED, short_timeout));
+ ASSERT_TRUE(waitForState(action_client2, SimpleClientGoalState::ACTIVE, short_timeout));
+
+ // Wait until done
+ ASSERT_TRUE(waitForState(action_client2, SimpleClientGoalState::SUCCEEDED, long_timeout));
+ ros::Duration(0.5).sleep(); // Allows values to settle to within EPS, especially accelerations
+
+ // Check that we're at the original trajectory for joint1 and on the partial trajectory for joint2
+ StateConstPtr state = getState();
+ EXPECT_NEAR(traj.points.back().positions[0], state->desired.positions[0], EPS);
+ EXPECT_NEAR(traj.points.back().velocities[0], state->desired.velocities[0], EPS);
+ EXPECT_NEAR(traj.points.back().accelerations[0], state->desired.accelerations[0], EPS);
+
+ EXPECT_NEAR(traj_partial.points.back().positions[0], state->desired.positions[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().velocities[0], state->desired.velocities[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().accelerations[0], state->desired.accelerations[1], EPS);
+}
+
+TEST_F(JointPartialTrajectoryControllerTest, executeParitalActionTrajInFuture)
+{
+ ASSERT_TRUE(initState());
+ ASSERT_TRUE(action_client->waitForServer(long_timeout));
+
+ // Send trajectory
+ ActionGoal first_goal = traj_goal;
+ first_goal.trajectory.header.stamp = ros::Time(0); // Start immediately
+ action_client->sendGoal(first_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::ACTIVE, short_timeout));
+
+ ros::Duration wait_duration = first_goal.trajectory.points.front().time_from_start;
+ wait_duration.sleep(); // Wait until ~first waypoint
+
+ // Send partial trajectory with only the last point not occuring in the past. Only the last point should be executed
+ traj_partial_goal.trajectory.header.stamp = ros::Time::now() + traj.points.back().time_from_start + ros::Duration(2.0);
+ action_client2->sendGoal(traj_partial_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::PREEMPTED, short_timeout));
+ ASSERT_TRUE(waitForState(action_client2, SimpleClientGoalState::ACTIVE, short_timeout));
+
+ // Wait until first traj is done
+ wait_duration = first_goal.trajectory.points.back().time_from_start;
+ wait_duration.sleep(); // Wait until ~first waypoint
+
+ StateConstPtr state = getState();
+ for (unsigned int i = 0; i < n_joints; ++i)
+ {
+ EXPECT_NEAR(traj.points.back().positions[i], state->desired.positions[i], EPS);
+ EXPECT_NEAR(traj.points.back().velocities[i], state->desired.velocities[i], EPS);
+ EXPECT_NEAR(traj.points.back().accelerations[i], state->desired.accelerations[i], EPS);
+ }
+
+ // Wait until done
+ ASSERT_TRUE(waitForState(action_client2, SimpleClientGoalState::SUCCEEDED, long_timeout));
+ ros::Duration(0.5).sleep(); // Allows values to settle to within EPS, especially accelerations
+
+ // Check that we're at the original trajectory for joint1 and on the partial trajectory for joint2
+ state = getState();
+ EXPECT_NEAR(traj.points.back().positions[0], state->desired.positions[0], EPS);
+ EXPECT_NEAR(traj.points.back().velocities[0], state->desired.velocities[0], EPS);
+ EXPECT_NEAR(traj.points.back().accelerations[0], state->desired.accelerations[0], EPS);
+
+ EXPECT_NEAR(traj_partial.points.back().positions[0], state->desired.positions[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().velocities[0], state->desired.velocities[1], EPS);
+ EXPECT_NEAR(traj_partial.points.back().accelerations[0], state->desired.accelerations[1], EPS);
+}
+
+
+int main(int argc, char** argv)
+{
+ testing::InitGoogleTest(&argc, argv);
+ ros::init(argc, argv, "joint_partial_trajectory_controller_test");
+
+ ros::AsyncSpinner spinner(1);
+ spinner.start();
+ int ret = RUN_ALL_TESTS();
+ spinner.stop();
+ ros::shutdown();
+ return ret;
+}
diff --git a/joint_trajectory_controller/test/joint_trajectory_controller.test b/joint_trajectory_controller/test/joint_trajectory_controller.test
index 499e34d..d943488 100644
--- a/joint_trajectory_controller/test/joint_trajectory_controller.test
+++ b/joint_trajectory_controller/test/joint_trajectory_controller.test
@@ -1,7 +1,9 @@
<launch>
+ <arg name="display_plots" default="false"/>
+
<!-- Load RRbot model -->
<param name="robot_description"
- command="$(find xacro)/xacro.py '$(find joint_trajectory_controller)/test/rrbot.xacro'" />
+ command="$(find xacro)/xacro '$(find joint_trajectory_controller)/test/rrbot.xacro'" />
<!-- Start RRbot -->
<node name="rrbot"
@@ -16,16 +18,18 @@
pkg="controller_manager" type="spawner" output="screen"
args="rrbot_controller" />
- <!-- Rxplot monitoring -->
- <node name="rrbot_pos_monitor"
- pkg="rqt_plot"
- type="rqt_plot"
- args="/rrbot_controller/state/desired/positions[0]:positions[1],/rrbot_controller/state/actual/positions[0]:positions[1]" />
+ <group if="$(arg display_plots)">
+ <!-- rqt_plot monitoring -->
+ <node name="rrbot_pos_monitor"
+ pkg="rqt_plot"
+ type="rqt_plot"
+ args="/rrbot_controller/state/desired/positions[0]:positions[1],/rrbot_controller/state/actual/positions[0]:positions[1]" />
- <node name="rrbot_vel_monitor"
- pkg="rqt_plot"
- type="rqt_plot"
- args="/rrbot_controller/state/desired/velocities[0]:velocities[1],/rrbot_controller/state/actual/velocities[0]:velocities[1]" />
+ <node name="rrbot_vel_monitor"
+ pkg="rqt_plot"
+ type="rqt_plot"
+ args="/rrbot_controller/state/desired/velocities[0]:velocities[1],/rrbot_controller/state/actual/velocities[0]:velocities[1]" />
+ </group>
<!-- Controller test -->
<test test-name="joint_trajectory_controller_test"
diff --git a/joint_trajectory_controller/test/joint_trajectory_controller_test.cpp b/joint_trajectory_controller/test/joint_trajectory_controller_test.cpp
index bb357c5..ce4f4bc 100644
--- a/joint_trajectory_controller/test/joint_trajectory_controller_test.cpp
+++ b/joint_trajectory_controller/test/joint_trajectory_controller_test.cpp
@@ -248,7 +248,7 @@ TEST_F(JointTrajectoryControllerTest, invalidMessages)
ASSERT_TRUE(initState());
ASSERT_TRUE(action_client->waitForServer(long_timeout));
- // Invalid size
+ // Invalid size (No partial joints goals allowed)
{
trajectory_msgs::JointTrajectoryPoint point;
point.positions.resize(1, 0.0);
@@ -776,7 +776,7 @@ TEST_F(JointTrajectoryControllerTest, ignoreOldTopicTraj)
}
}
-TEST_F(JointTrajectoryControllerTest, ignoreOldActionTraj)
+TEST_F(JointTrajectoryControllerTest, ignorePreemptOfOldActionTraj)
{
ASSERT_TRUE(initState());
ASSERT_TRUE(action_client->waitForServer(long_timeout));
@@ -808,6 +808,17 @@ TEST_F(JointTrajectoryControllerTest, ignoreOldActionTraj)
}
}
+TEST_F(JointTrajectoryControllerTest, ignoreSingleOldActionTraj)
+{
+ ASSERT_TRUE(initState());
+ ASSERT_TRUE(action_client->waitForServer(long_timeout));
+
+ // Send trajectory
+ traj_home_goal.trajectory.header.stamp = ros::Time::now() - ros::Duration(10000);
+ action_client->sendGoal(traj_home_goal);
+ ASSERT_TRUE(waitForState(action_client, SimpleClientGoalState::REJECTED, short_timeout));
+}
+
TEST_F(JointTrajectoryControllerTest, ignorePartiallyOldActionTraj)
{
ASSERT_TRUE(initState());
diff --git a/joint_trajectory_controller/test/joint_trajectory_controller_vel.test b/joint_trajectory_controller/test/joint_trajectory_controller_vel.test
new file mode 100644
index 0000000..b0b352d
--- /dev/null
+++ b/joint_trajectory_controller/test/joint_trajectory_controller_vel.test
@@ -0,0 +1,39 @@
+<launch>
+ <arg name="display_plots" default="false"/>
+
+ <!-- Load RRbot model -->
+ <param name="robot_description"
+ command="$(find xacro)/xacro '$(find joint_trajectory_controller)/test/rrbot.xacro'" />
+
+ <!-- Start RRbot -->
+ <node name="rrbot"
+ pkg="joint_trajectory_controller"
+ type="rrbot"/>
+
+ <!-- Load controller config -->
+ <rosparam command="load" file="$(find joint_trajectory_controller)/test/rrbot_vel_controllers.yaml" />
+
+ <!-- Spawn controller -->
+ <node name="controller_spawner"
+ pkg="controller_manager" type="spawner" output="screen"
+ args="rrbot_controller" />
+
+ <group if="$(arg display_plots)">
+ <!-- rqt_plot monitoring -->
+ <node name="rrbot_pos_monitor"
+ pkg="rqt_plot"
+ type="rqt_plot"
+ args="/rrbot_controller/state/desired/positions[0]:positions[1],/rrbot_controller/state/actual/positions[0]:positions[1]" />
+
+ <node name="rrbot_vel_monitor"
+ pkg="rqt_plot"
+ type="rqt_plot"
+ args="/rrbot_controller/state/desired/velocities[0]:velocities[1],/rrbot_controller/state/actual/velocities[0]:velocities[1]" />
+ </group>
+
+ <!-- Controller test -->
+ <test test-name="joint_trajectory_controller_vel_test"
+ pkg="joint_trajectory_controller"
+ type="joint_trajectory_controller_test"
+ time-limit="80.0"/>
+</launch>
diff --git a/joint_trajectory_controller/test/joint_trajectory_segment_test.cpp b/joint_trajectory_controller/test/joint_trajectory_segment_test.cpp
index 546dec4..14ac71c 100644
--- a/joint_trajectory_controller/test/joint_trajectory_segment_test.cpp
+++ b/joint_trajectory_controller/test/joint_trajectory_segment_test.cpp
@@ -41,7 +41,7 @@ using namespace trajectory_msgs;
const double EPS = 1e-9;
typedef JointTrajectorySegment<trajectory_interface::QuinticSplineSegment<double> > Segment;
-typedef std::vector<unsigned int> PermutationType;
+typedef std::vector<unsigned int> MappingType;
TEST(WraparoundOffsetTest, WrappingPositions)
{
@@ -60,10 +60,10 @@ TEST(WraparoundOffsetTest, WrappingPositions)
// No wrapping joints
{
std::vector<bool> angle_wraparound(2, false);
- std::vector<double> wraparound_offset = wraparoundOffset(pos1, pos2, angle_wraparound);
- EXPECT_NEAR(pos1.size(), wraparound_offset.size(), EPS);
- EXPECT_NEAR(0.0, wraparound_offset[0], EPS);
- EXPECT_NEAR(0.0, wraparound_offset[1], EPS);
+ double wraparound_offset1 = wraparoundJointOffset(pos1[0], pos2[0], angle_wraparound[0]);
+ double wraparound_offset2 = wraparoundJointOffset(pos1[1], pos2[1], angle_wraparound[1]);
+ EXPECT_NEAR(0.0, wraparound_offset1, EPS);
+ EXPECT_NEAR(0.0, wraparound_offset2, EPS);
}
// Single wrapping joint
@@ -74,18 +74,18 @@ TEST(WraparoundOffsetTest, WrappingPositions)
// From state1 to state2
{
- std::vector<double> wraparound_offset = wraparoundOffset<double>(pos1, pos2, angle_wraparound);
- EXPECT_NEAR(pos1.size(), wraparound_offset.size(), EPS);
- EXPECT_NEAR(-two_pi, wraparound_offset[0], EPS);
- EXPECT_NEAR(0.0, wraparound_offset[1], EPS);
+ double wraparound_offset1 = wraparoundJointOffset(pos1[0], pos2[0], angle_wraparound[0]);
+ double wraparound_offset2 = wraparoundJointOffset(pos1[1], pos2[1], angle_wraparound[1]);
+ EXPECT_NEAR(-two_pi, wraparound_offset1, EPS);
+ EXPECT_NEAR(0.0, wraparound_offset2, EPS);
}
// From state2 to state1
{
- std::vector<double> wraparound_offset = wraparoundOffset<double>(pos2, pos1, angle_wraparound);
- EXPECT_NEAR(pos1.size(), wraparound_offset.size(), EPS);
- EXPECT_NEAR(two_pi, wraparound_offset[0], EPS);
- EXPECT_NEAR(0.0, wraparound_offset[1], EPS);
+ double wraparound_offset1 = wraparoundJointOffset(pos2[0], pos1[0], angle_wraparound[0]);
+ double wraparound_offset2 = wraparoundJointOffset(pos2[1], pos1[1], angle_wraparound[1]);
+ EXPECT_NEAR(two_pi, wraparound_offset1, EPS);
+ EXPECT_NEAR(0.0, wraparound_offset2, EPS);
}
}
@@ -95,18 +95,18 @@ TEST(WraparoundOffsetTest, WrappingPositions)
// From state1 to state2
{
- std::vector<double> wraparound_offset = wraparoundOffset<double>(pos1, pos2, angle_wraparound);
- EXPECT_NEAR(pos1.size(), wraparound_offset.size(), EPS);
- EXPECT_NEAR(-two_pi, wraparound_offset[0], EPS);
- EXPECT_NEAR(-2.0 * two_pi, wraparound_offset[1], EPS);
+ double wraparound_offset1 = wraparoundJointOffset(pos1[0], pos2[0], angle_wraparound[0]);
+ double wraparound_offset2 = wraparoundJointOffset(pos1[1], pos2[1], angle_wraparound[1]);
+ EXPECT_NEAR(-two_pi, wraparound_offset1, EPS);
+ EXPECT_NEAR(-2.0 * two_pi, wraparound_offset2, EPS);
}
// From state2 to state1
{
- std::vector<double> wraparound_offset = wraparoundOffset<double>(pos2, pos1, angle_wraparound);
- EXPECT_NEAR(pos1.size(), wraparound_offset.size(), EPS);
- EXPECT_NEAR(two_pi, wraparound_offset[0], EPS);
- EXPECT_NEAR(2.0 * two_pi, wraparound_offset[1], EPS);
+ double wraparound_offset1 = wraparoundJointOffset(pos2[0], pos1[0], angle_wraparound[0]);
+ double wraparound_offset2 = wraparoundJointOffset(pos2[1], pos1[1], angle_wraparound[1]);
+ EXPECT_NEAR(two_pi, wraparound_offset1, EPS);
+ EXPECT_NEAR(2.0 * two_pi, wraparound_offset2, EPS);
}
}
}
@@ -122,16 +122,14 @@ TEST(WraparoundOffsetTest, WrappingPositionsPiSingularity)
std::vector<bool> angle_wraparound(1, true);
// From state1 to state2
{
- std::vector<double> wraparound_offset = wraparoundOffset<double>(pos1, pos2, angle_wraparound);
- EXPECT_EQ(pos1.size(), wraparound_offset.size());
- EXPECT_NEAR(0.0, wraparound_offset[0], EPS);
+ double wraparound_offset1 = wraparoundJointOffset(pos1[0], pos2[0], angle_wraparound[0]);
+ EXPECT_NEAR(0.0, wraparound_offset1, EPS);
}
// From state2 to state1
{
- std::vector<double> wraparound_offset = wraparoundOffset<double>(pos2, pos1, angle_wraparound);
- EXPECT_EQ(pos1.size(), wraparound_offset.size());
- EXPECT_NEAR(0.0, wraparound_offset[0], EPS);
+ double wraparound_offset1 = wraparoundJointOffset(pos2[0], pos1[0], angle_wraparound[0]);
+ EXPECT_NEAR(0.0, wraparound_offset1, EPS);
}
}
@@ -154,18 +152,18 @@ TEST(WraparoundOffsetTest, NonWrappingPositions)
// From state1 to state2
{
- std::vector<double> wraparound_offset = wraparoundOffset<double>(pos1, pos2, angle_wraparound);
- EXPECT_NEAR(pos1.size(), wraparound_offset.size(), EPS);
- EXPECT_NEAR(0.0, wraparound_offset[0], EPS);
- EXPECT_NEAR(0.0, wraparound_offset[1], EPS);
+ double wraparound_offset1 = wraparoundJointOffset(pos1[0], pos2[0], angle_wraparound[0]);
+ double wraparound_offset2 = wraparoundJointOffset(pos1[1], pos2[1], angle_wraparound[1]);
+ EXPECT_NEAR(0.0, wraparound_offset1, EPS);
+ EXPECT_NEAR(0.0, wraparound_offset2, EPS);
}
// From state2 to state1
{
- std::vector<double> wraparound_offset = wraparoundOffset<double>(pos2, pos1, angle_wraparound);
- EXPECT_NEAR(pos1.size(), wraparound_offset.size(), EPS);
- EXPECT_NEAR(0.0, wraparound_offset[0], EPS);
- EXPECT_NEAR(0.0, wraparound_offset[1], EPS);
+ double wraparound_offset1 = wraparoundJointOffset(pos2[0], pos1[0], angle_wraparound[0]);
+ double wraparound_offset2 = wraparoundJointOffset(pos2[1], pos1[1], angle_wraparound[1]);
+ EXPECT_NEAR(0.0, wraparound_offset1, EPS);
+ EXPECT_NEAR(0.0, wraparound_offset2, EPS);
}
}
}
@@ -239,28 +237,11 @@ TEST_F(JointTrajectorySegmentTest, InvalidSegmentConstruction)
catch (const std::invalid_argument& ex) {ROS_ERROR_STREAM(ex.what());}
}
- // Invalid permutation vector size
- {
- PermutationType permutation(2, 1);
- EXPECT_THROW(Segment(traj_start_time, p_start, p_end, permutation), std::invalid_argument);
- try {Segment(traj_start_time, p_start, p_end, permutation);}
- catch (const std::invalid_argument& ex) {ROS_ERROR_STREAM(ex.what());}
- }
-
- // Invalid permutation vector indices
- {
- PermutationType permutation(1, 1);
- EXPECT_THROW(Segment(traj_start_time, p_start, p_end, permutation), std::invalid_argument);
- try {Segment(traj_start_time, p_start, p_end, permutation);}
- catch (const std::invalid_argument& ex) {ROS_ERROR_STREAM(ex.what());}
- }
-
// Invalid joint wraparound specification
{
- PermutationType permutation;
std::vector<double> pos_offset(2);
- EXPECT_THROW(Segment(traj_start_time, p_start, p_end, permutation, pos_offset), std::invalid_argument);
- try {Segment(traj_start_time, p_start, p_end, permutation, pos_offset);}
+ EXPECT_THROW(Segment(traj_start_time, p_start, p_end, pos_offset), std::invalid_argument);
+ try {Segment(traj_start_time, p_start, p_end, pos_offset);}
catch (const std::invalid_argument& ex) {ROS_ERROR_STREAM(ex.what());}
}
}
@@ -372,7 +353,7 @@ TEST_F(JointTrajectorySegmentTest, CrossValidateSegmentConstruction)
}
// TODO: Test with dimension four data
-TEST_F(JointTrajectorySegmentTest, PermutationTest)
+TEST_F(JointTrajectorySegmentTest, MappingTest)
{
// Add an extra joint to the trajectory point messages created in the fixture
p_start.positions.push_back(-p_start.positions[0]);
@@ -381,7 +362,7 @@ TEST_F(JointTrajectorySegmentTest, PermutationTest)
p_end.positions.push_back(-p_end.positions[0]);
p_end.velocities.push_back(-p_end.velocities[0]);
- // No permutation vector
+ // No mapping vector
{
// Construct segment from ROS message
EXPECT_NO_THROW(Segment(traj_start_time, p_start, p_end));
@@ -393,42 +374,6 @@ TEST_F(JointTrajectorySegmentTest, PermutationTest)
EXPECT_EQ(p_start.positions[0], state.position[0]);
EXPECT_EQ(p_start.positions[1], state.position[1]);
}
-
- // Permutation vector preserving trajectory message joint order
- {
- PermutationType permutation(2);
- permutation[0] = 0;
- permutation[1] = 1;
-
- // Construct segment from ROS message
- EXPECT_NO_THROW(Segment(traj_start_time, p_start, p_end, permutation));
- Segment segment(traj_start_time, p_start, p_end, permutation);
-
- // Check position values of start state only
- typename Segment::State state;
- segment.sample(segment.startTime(), state);
- EXPECT_EQ(p_start.positions[0], state.position[0]);
- EXPECT_EQ(p_start.positions[1], state.position[1]);
- }
-
- // Permutation vector reversing trajectory message joint order
- {
- PermutationType permutation(2);
- permutation[0] = 1;
- permutation[1] = 0;
-
- // Construct segment from ROS message
- EXPECT_NO_THROW(Segment(traj_start_time, p_start, p_end, permutation));
- Segment segment(traj_start_time, p_start, p_end, permutation);
-
- // Check position values of start state only
- typename Segment::State state;
- segment.sample(segment.startTime(), state);
- EXPECT_NE(p_start.positions[0], state.position[0]);
- EXPECT_NE(p_start.positions[1], state.position[1]);
- EXPECT_EQ(p_start.positions[0], state.position[1]);
- EXPECT_EQ(p_start.positions[1], state.position[0]);
- }
}
int main(int argc, char** argv)
diff --git a/joint_trajectory_controller/test/rrbot.cpp b/joint_trajectory_controller/test/rrbot.cpp
index 47c7597..f304f9a 100644
--- a/joint_trajectory_controller/test/rrbot.cpp
+++ b/joint_trajectory_controller/test/rrbot.cpp
@@ -47,7 +47,8 @@ public:
pos_[0] = 0.0; pos_[1] = 0.0;
vel_[0] = 0.0; vel_[1] = 0.0;
eff_[0] = 0.0; eff_[1] = 0.0;
- cmd_[0] = 0.0; cmd_[1] = 0.0;
+ pos_cmd_[0] = 0.0; pos_cmd_[1] = 0.0;
+ vel_cmd_[0] = 0.0; vel_cmd_[1] = 0.0;
// Connect and register the joint state interface
hardware_interface::JointStateHandle state_handle_1("joint1", &pos_[0], &vel_[0], &eff_[0]);
@@ -59,14 +60,23 @@ public:
registerInterface(&jnt_state_interface_);
// Connect and register the joint position interface
- hardware_interface::JointHandle pos_handle_1(jnt_state_interface_.getHandle("joint1"), &cmd_[0]);
+ hardware_interface::JointHandle pos_handle_1(jnt_state_interface_.getHandle("joint1"), &pos_cmd_[0]);
jnt_pos_interface_.registerHandle(pos_handle_1);
- hardware_interface::JointHandle pos_handle_2(jnt_state_interface_.getHandle("joint2"), &cmd_[1]);
+ hardware_interface::JointHandle pos_handle_2(jnt_state_interface_.getHandle("joint2"), &pos_cmd_[1]);
jnt_pos_interface_.registerHandle(pos_handle_2);
registerInterface(&jnt_pos_interface_);
+ // Connect and register the joint velocity interface
+ hardware_interface::JointHandle vel_handle_1(jnt_state_interface_.getHandle("joint1"), &vel_cmd_[0]);
+ jnt_vel_interface_.registerHandle(vel_handle_1);
+
+ hardware_interface::JointHandle vel_handle_2(jnt_state_interface_.getHandle("joint2"), &vel_cmd_[1]);
+ jnt_vel_interface_.registerHandle(vel_handle_2);
+
+ registerInterface(&jnt_vel_interface_);
+
// Smoothing subscriber
smoothing_sub_ = ros::NodeHandle().subscribe("smoothing", 1, &RRbot::smoothingCB, this);
smoothing_.initRT(0.0);
@@ -82,21 +92,67 @@ public:
const double smoothing = *(smoothing_.readFromRT());
for (unsigned int i = 0; i < 2; ++i)
{
- vel_[i] = (cmd_[i] - pos_[i]) / getPeriod().toSec();
+ if(active_interface_[i] == "hardware_interface::PositionJointInterface")
+ {
+ vel_[i] = (pos_cmd_[i] - pos_[i]) / getPeriod().toSec();
+
+ const double next_pos = smoothing * pos_[i] + (1.0 - smoothing) * pos_cmd_[i];
+ pos_[i] = next_pos;
+ }
+ else if(active_interface_[i] == "hardware_interface::VelocityJointInterface")
+ {
+ vel_[i] = (1.0 - smoothing) * vel_cmd_[i];
+ pos_[i] = pos_[i] + vel_[i] * getPeriod().toSec();
+ }
+ }
+ }
+
+ typedef std::list<hardware_interface::ControllerInfo> ControllerList;
- const double next_pos = smoothing * pos_[i] + (1.0 - smoothing) * cmd_[i];
- pos_[i] = next_pos;
+ bool prepareSwitch(const ControllerList& start_list,
+ const ControllerList& stop_list)
+ {
+ for(ControllerList::const_iterator it = start_list.begin(); it != start_list.end(); ++it)
+ {
+ for(std::vector<hardware_interface::InterfaceResources>::const_iterator iface_it = it->claimed_resources.begin(); iface_it != it->claimed_resources.end(); ++iface_it)
+ {
+ for(std::set<std::string>::const_iterator res_it = iface_it->resources.begin(); res_it != iface_it->resources.end(); ++res_it)
+ {
+ if(*res_it == "joint1")
+ {
+ next_active_interface_[0] = iface_it->hardware_interface;
+ }
+ else if(*res_it == "joint2")
+ {
+ next_active_interface_[1] = iface_it->hardware_interface;
+ }
+ }
+ }
}
+
+ return true;
+ }
+
+ void doSwitch(const ControllerList& start_list,
+ const ControllerList& stop_list)
+ {
+ active_interface_[0] = next_active_interface_[0];
+ active_interface_[1] = next_active_interface_[1];
}
private:
hardware_interface::JointStateInterface jnt_state_interface_;
hardware_interface::PositionJointInterface jnt_pos_interface_;
- double cmd_[2];
+ hardware_interface::VelocityJointInterface jnt_vel_interface_;
+ double pos_cmd_[2];
+ double vel_cmd_[2];
double pos_[2];
double vel_[2];
double eff_[2];
+ std::string active_interface_[2];
+ std::string next_active_interface_[2];
+
realtime_tools::RealtimeBuffer<double> smoothing_;
void smoothingCB(const std_msgs::Float64& smoothing) {smoothing_.writeFromNonRT(smoothing.data);}
diff --git a/joint_trajectory_controller/test/rrbot_partial_controllers.yaml b/joint_trajectory_controller/test/rrbot_partial_controllers.yaml
new file mode 100644
index 0000000..e7a3195
--- /dev/null
+++ b/joint_trajectory_controller/test/rrbot_partial_controllers.yaml
@@ -0,0 +1,15 @@
+rrbot_controller:
+ type: "position_controllers/JointTrajectoryController"
+ joints:
+ - joint1
+ - joint2
+
+ constraints:
+ goal_time: 0.5
+ joint1:
+ goal: 0.01
+ trajectory: 0.05
+ joint2:
+ goal: 0.01
+ trajectory: 0.05
+ allow_partial_joints_goal: true
diff --git a/joint_trajectory_controller/test/rrbot_vel_controllers.yaml b/joint_trajectory_controller/test/rrbot_vel_controllers.yaml
new file mode 100644
index 0000000..0a660f5
--- /dev/null
+++ b/joint_trajectory_controller/test/rrbot_vel_controllers.yaml
@@ -0,0 +1,18 @@
+rrbot_controller:
+ type: "velocity_controllers/JointTrajectoryController"
+ joints:
+ - joint1
+ - joint2
+
+ constraints:
+ goal_time: 0.5
+ joint1:
+ goal: 0.01
+ trajectory: 0.05
+ joint2:
+ goal: 0.01
+ trajectory: 0.05
+
+ gains:
+ joint1: {p: 60.0, i: 0.0, d: 0.0, i_clamp: 1}
+ joint2: {p: 60.0, i: 0.0, d: 0.0, i_clamp: 1}
diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst
index ae51d81..fd122e8 100644
--- a/position_controllers/CHANGELOG.rst
+++ b/position_controllers/CHANGELOG.rst
@@ -2,6 +2,21 @@
Changelog for package position_controllers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+0.12.3 (2017-04-23)
+-------------------
+
+0.12.2 (2017-04-21)
+-------------------
+
+0.12.1 (2017-03-08)
+-------------------
+
+0.12.0 (2017-02-15)
+-------------------
+* Change for format2
+* Add Enrique and Bence to maintainers
+* Contributors: Bence Magyar
+
0.11.2 (2016-08-16)
-------------------
diff --git a/position_controllers/package.xml b/position_controllers/package.xml
index 9c5b7c8..2e62760 100644
--- a/position_controllers/package.xml
+++ b/position_controllers/package.xml
@@ -1,10 +1,12 @@
-<package>
+<package format="2">
<name>position_controllers</name>
- <version>0.11.2</version>
+ <version>0.12.3</version>
<description>position_controllers</description>
<maintainer email="adolfo.rodriguez at pal-robotics.com">Adolfo Rodriguez Tsouroukdissian</maintainer>
+ <maintainer email="bence.magyar.robotics at gmail.com">Bence Magyar</maintainer>
<maintainer email="davetcoleman at gmail.com">Dave Coleman</maintainer>
+ <maintainer email="enrique.fernandez.perdomo at gmail.com">Enrique Fernandez</maintainer>
<license>BSD</license>
@@ -15,10 +17,8 @@
<author>Vijay Pradeep</author>
<buildtool_depend>catkin</buildtool_depend>
- <build_depend>controller_interface</build_depend>
- <build_depend>forward_command_controller</build_depend>
- <run_depend>controller_interface</run_depend>
- <run_depend>forward_command_controller</run_depend>
+ <depend>controller_interface</depend>
+ <depend>forward_command_controller</depend>
<export>
<controller_interface plugin="${prefix}/position_controllers_plugins.xml"/>
diff --git a/ros_controllers/CHANGELOG.rst b/ros_controllers/CHANGELOG.rst
index 9e8a46d..00034d1 100644
--- a/ros_controllers/CHANGELOG.rst
+++ b/ros_controllers/CHANGELOG.rst
@@ -2,6 +2,22 @@
Changelog for package ros_controllers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+0.12.3 (2017-04-23)
+-------------------
+
+0.12.2 (2017-04-21)
+-------------------
+
+0.12.1 (2017-03-08)
+-------------------
+
+0.12.0 (2017-02-15)
+-------------------
+* Ordered dependencies & cleanup
+* Change for format2
+* Add Enrique and Bence to maintainers
+* Contributors: Bence Magyar
+
0.11.2 (2016-08-16)
-------------------
diff --git a/ros_controllers/package.xml b/ros_controllers/package.xml
index 7b43b90..1ae5992 100644
--- a/ros_controllers/package.xml
+++ b/ros_controllers/package.xml
@@ -1,10 +1,12 @@
-<package>
+<package format="2">
<name>ros_controllers</name>
- <version>0.11.2</version>
+ <version>0.12.3</version>
<description>Library of ros controllers</description>
<maintainer email="adolfo.rodriguez at pal-robotics.com">Adolfo Rodriguez Tsouroukdissian</maintainer>
+ <maintainer email="bence.magyar.robotics at gmail.com">Bence Magyar</maintainer>
<maintainer email="davetcoleman at gmail.com">Dave Coleman</maintainer>
+ <maintainer email="enrique.fernandez.perdomo at gmail.com">Enrique Fernandez</maintainer>
<license>BSD</license>
@@ -14,20 +16,19 @@
<author>Wim Meeussen</author>
-
<buildtool_depend>catkin</buildtool_depend>
- <run_depend>imu_sensor_controller</run_depend>
- <run_depend>force_torque_sensor_controller</run_depend>
- <run_depend>position_controllers</run_depend>
- <run_depend>velocity_controllers</run_depend>
- <run_depend>effort_controllers</run_depend>
- <run_depend>forward_command_controller</run_depend>
- <run_depend>joint_state_controller</run_depend>
- <run_depend>joint_trajectory_controller</run_depend>
- <run_depend>diff_drive_controller</run_depend>
- <run_depend>gripper_action_controller</run_depend>
- <run_depend>rqt_joint_trajectory_controller</run_depend>
+ <exec_depend>diff_drive_controller</exec_depend>
+ <exec_depend>effort_controllers</exec_depend>
+ <exec_depend>force_torque_sensor_controller</exec_depend>
+ <exec_depend>forward_command_controller</exec_depend>
+ <exec_depend>gripper_action_controller</exec_depend>
+ <exec_depend>imu_sensor_controller</exec_depend>
+ <exec_depend>joint_state_controller</exec_depend>
+ <exec_depend>joint_trajectory_controller</exec_depend>
+ <exec_depend>position_controllers</exec_depend>
+ <exec_depend>rqt_joint_trajectory_controller</exec_depend>
+ <exec_depend>velocity_controllers</exec_depend>
<export>
<metapackage/>
diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst
index 3b8de4d..5a3b52a 100644
--- a/rqt_joint_trajectory_controller/CHANGELOG.rst
+++ b/rqt_joint_trajectory_controller/CHANGELOG.rst
@@ -2,6 +2,21 @@
Changelog for package rqt_joint_trajectory_controller
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+0.12.3 (2017-04-23)
+-------------------
+
+0.12.2 (2017-04-21)
+-------------------
+
+0.12.1 (2017-03-08)
+-------------------
+
+0.12.0 (2017-02-15)
+-------------------
+* Change for format2
+* Add Enrique and Bence to maintainers
+* Contributors: Bence Magyar
+
0.11.2 (2016-08-16)
-------------------
* Changes in import of Qt modules
diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml
index b20771d..728df72 100644
--- a/rqt_joint_trajectory_controller/package.xml
+++ b/rqt_joint_trajectory_controller/package.xml
@@ -1,22 +1,25 @@
<?xml version="1.0"?>
-<package>
+<package format="2">
<name>rqt_joint_trajectory_controller</name>
- <version>0.11.2</version>
+ <version>0.12.3</version>
<description>Graphical frontend for interacting with joint_trajectory_controller instances.</description>
<maintainer email="adolfo.rodriguez at pal-robotics.com">Adolfo Rodriguez Tsouroukdissian</maintainer>
+ <maintainer email="bence.magyar.robotics at gmail.com">Bence Magyar</maintainer>
+ <maintainer email="enrique.fernandez.perdomo at gmail.com">Enrique Fernandez</maintainer>
+
<author email="adolfo.rodriguez at pal-robotics.com">Adolfo Rodriguez Tsouroukdissian</author>
<license>Modified BSD</license>
<url type="website">http://wiki.ros.org/rqt_joint_trajectory_controller</url>
<buildtool_depend>catkin</buildtool_depend>
- <run_depend>control_msgs</run_depend>
- <run_depend>controller_manager_msgs</run_depend>
- <run_depend>trajectory_msgs</run_depend>
- <run_depend>rospy</run_depend>
- <run_depend>rqt_gui</run_depend>
- <run_depend>rqt_gui_py</run_depend>
+ <exec_depend>control_msgs</exec_depend>
+ <exec_depend>controller_manager_msgs</exec_depend>
+ <exec_depend>trajectory_msgs</exec_depend>
+ <exec_depend>rospy</exec_depend>
+ <exec_depend>rqt_gui</exec_depend>
+ <exec_depend>rqt_gui_py</exec_depend>
<export>
<rqt_gui plugin="${prefix}/plugin.xml"/>
diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst
index 36e026a..fb43735 100644
--- a/velocity_controllers/CHANGELOG.rst
+++ b/velocity_controllers/CHANGELOG.rst
@@ -2,6 +2,24 @@
Changelog for package velocity_controllers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+0.12.3 (2017-04-23)
+-------------------
+* Supply NodeHandle to urdf::Model. Closes `#244 <https://github.com/ros-controls/ros_controllers/issues/244>`_
+* Contributors: Piyush Khandelwal
+
+0.12.2 (2017-04-21)
+-------------------
+
+0.12.1 (2017-03-08)
+-------------------
+
+0.12.0 (2017-02-15)
+-------------------
+* Change for format2
+* Add Enrique and Bence to maintainers
+* Replace boost::shared_ptr<urdf::XY> with urdf::XYConstSharedPtr when exists
+* Contributors: Bence Magyar
+
0.11.2 (2016-08-16)
-------------------
diff --git a/velocity_controllers/include/velocity_controllers/joint_position_controller.h b/velocity_controllers/include/velocity_controllers/joint_position_controller.h
index 716660b..91ab72e 100644
--- a/velocity_controllers/include/velocity_controllers/joint_position_controller.h
+++ b/velocity_controllers/include/velocity_controllers/joint_position_controller.h
@@ -174,7 +174,7 @@ public:
double getPosition();
hardware_interface::JointHandle joint_;
- boost::shared_ptr<const urdf::Joint> joint_urdf_;
+ urdf::JointConstSharedPtr joint_urdf_;
realtime_tools::RealtimeBuffer<Commands> command_;
Commands command_struct_; // pre-allocated memory that is re-used to set the realtime buffer
diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml
index 338e4c4..f415277 100644
--- a/velocity_controllers/package.xml
+++ b/velocity_controllers/package.xml
@@ -1,9 +1,11 @@
-<package>
+<package format="2">
<name>velocity_controllers</name>
- <version>0.11.2</version>
+ <version>0.12.3</version>
<description>velocity_controllers</description>
<maintainer email="adolfo.rodriguez at pal-robotics.com">Adolfo Rodriguez Tsouroukdissian</maintainer>
+ <maintainer email="bence.magyar.robotics at gmail.com">Bence Magyar</maintainer>
+ <maintainer email="enrique.fernandez.perdomo at gmail.com">Enrique Fernandez</maintainer>
<license>BSD</license>
@@ -15,21 +17,13 @@
<buildtool_depend>catkin</buildtool_depend>
- <build_depend>angles</build_depend>
- <build_depend>control_msgs</build_depend>
- <build_depend>control_toolbox</build_depend>
- <build_depend>controller_interface</build_depend>
- <build_depend>forward_command_controller</build_depend>
- <build_depend>realtime_tools</build_depend>
- <build_depend>urdf</build_depend>
-
- <run_depend>angles</run_depend>
- <run_depend>control_msgs</run_depend>
- <run_depend>control_toolbox</run_depend>
- <run_depend>controller_interface</run_depend>
- <run_depend>forward_command_controller</run_depend>
- <run_depend>realtime_tools</run_depend>
- <run_depend>urdf</run_depend>
+ <depend>angles</depend>
+ <depend>control_msgs</depend>
+ <depend>control_toolbox</depend>
+ <depend>controller_interface</depend>
+ <depend>forward_command_controller</depend>
+ <depend>realtime_tools</depend>
+ <depend>urdf</depend>
<export>
<controller_interface plugin="${prefix}/velocity_controllers_plugins.xml"/>
diff --git a/velocity_controllers/src/joint_position_controller.cpp b/velocity_controllers/src/joint_position_controller.cpp
index 3103158..cbe361f 100644
--- a/velocity_controllers/src/joint_position_controller.cpp
+++ b/velocity_controllers/src/joint_position_controller.cpp
@@ -81,7 +81,7 @@ bool JointPositionController::init(hardware_interface::VelocityJointInterface *r
// Get URDF info about joint
urdf::Model urdf;
- if (!urdf.initParam("robot_description"))
+ if (!urdf.initParamWithNodeHandle("robot_description", n))
{
ROS_ERROR("Failed to parse urdf file");
return false;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/ros/ros-ros-controllers.git
More information about the debian-science-commits
mailing list