From 2e71b902456b07e732ddf090259cab35d5db55f0 Mon Sep 17 00:00:00 2001 From: Bjar Ne <43565432+gleichdick@users.noreply.github.com> Date: Tue, 13 Oct 2020 12:51:14 +0100 Subject: [PATCH 001/179] Make GILReleaser exception-safe (#2363) If an exception occurs while the GIL is released, it won't be reacquired and the stack unwinding will take place without the GIL. GILReleaser::release() and GILReleaser::reacquire() is removed, because it is unsafe. --- .../src/wrap_python_move_group.cpp | 76 ++++++++++--------- .../moveit/py_bindings_tools/gil_releaser.h | 27 ++----- 2 files changed, 47 insertions(+), 56 deletions(-) diff --git a/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp b/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp index 7d421ac016..bb60acd95b 100644 --- a/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp +++ b/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp @@ -466,10 +466,12 @@ class MoveGroupInterfaceWrapper : protected py_bindings_tools::ROScppInitializer py_bindings_tools::ByteString getPlanPython() { - GILReleaser gr; MoveGroupInterface::Plan plan; - MoveGroupInterface::plan(plan); - gr.reacquire(); + moveit_msgs::MoveItErrorCodes res; + { + GILReleaser gr; + res = MoveGroupInterface::plan(plan); + } return py_bindings_tools::serializeMsg(plan.trajectory_); } @@ -495,10 +497,11 @@ class MoveGroupInterfaceWrapper : protected py_bindings_tools::ROScppInitializer std::vector poses; convertListToArrayOfPoses(waypoints, poses); moveit_msgs::RobotTrajectory trajectory; - GILReleaser gr; - double fraction = - computeCartesianPath(poses, eef_step, jump_threshold, trajectory, path_constraints, avoid_collisions); - gr.reacquire(); + double fraction; + { + GILReleaser gr; + fraction = computeCartesianPath(poses, eef_step, jump_threshold, trajectory, path_constraints, avoid_collisions); + } return bp::make_tuple(py_bindings_tools::serializeMsg(trajectory), fraction); } @@ -547,36 +550,39 @@ class MoveGroupInterfaceWrapper : protected py_bindings_tools::ROScppInitializer // Convert trajectory message to object moveit_msgs::RobotTrajectory traj_msg; py_bindings_tools::deserializeMsg(traj_str, traj_msg); - GILReleaser gr; - robot_trajectory::RobotTrajectory traj_obj(getRobotModel(), getName()); - traj_obj.setRobotTrajectoryMsg(ref_state_obj, traj_msg); - - // Do the actual retiming - if (algorithm == "iterative_time_parameterization") - { - trajectory_processing::IterativeParabolicTimeParameterization time_param; - time_param.computeTimeStamps(traj_obj, velocity_scaling_factor, acceleration_scaling_factor); - } - else if (algorithm == "iterative_spline_parameterization") + bool algorithm_found = true; { - trajectory_processing::IterativeSplineParameterization time_param; - time_param.computeTimeStamps(traj_obj, velocity_scaling_factor, acceleration_scaling_factor); - } - else if (algorithm == "time_optimal_trajectory_generation") - { - trajectory_processing::TimeOptimalTrajectoryGeneration time_param; - time_param.computeTimeStamps(traj_obj, velocity_scaling_factor, acceleration_scaling_factor); - } - else - { - ROS_ERROR_STREAM_NAMED("move_group_py", "Unknown time parameterization algorithm: " << algorithm); - gr.reacquire(); - return py_bindings_tools::serializeMsg(moveit_msgs::RobotTrajectory()); - } + GILReleaser gr; + robot_trajectory::RobotTrajectory traj_obj(getRobotModel(), getName()); + traj_obj.setRobotTrajectoryMsg(ref_state_obj, traj_msg); + + // Do the actual retiming + if (algorithm == "iterative_time_parameterization") + { + trajectory_processing::IterativeParabolicTimeParameterization time_param; + time_param.computeTimeStamps(traj_obj, velocity_scaling_factor, acceleration_scaling_factor); + } + else if (algorithm == "iterative_spline_parameterization") + { + trajectory_processing::IterativeSplineParameterization time_param; + time_param.computeTimeStamps(traj_obj, velocity_scaling_factor, acceleration_scaling_factor); + } + else if (algorithm == "time_optimal_trajectory_generation") + { + trajectory_processing::TimeOptimalTrajectoryGeneration time_param; + time_param.computeTimeStamps(traj_obj, velocity_scaling_factor, acceleration_scaling_factor); + } + else + { + ROS_ERROR_STREAM_NAMED("move_group_py", "Unknown time parameterization algorithm: " << algorithm); + algorithm_found = false; + traj_msg = moveit_msgs::RobotTrajectory(); + } - // Convert the retimed trajectory back into a message - traj_obj.getRobotTrajectoryMsg(traj_msg); - gr.reacquire(); + if (algorithm_found) + // Convert the retimed trajectory back into a message + traj_obj.getRobotTrajectoryMsg(traj_msg); + } return py_bindings_tools::serializeMsg(traj_msg); } else diff --git a/moveit_ros/planning_interface/py_bindings_tools/include/moveit/py_bindings_tools/gil_releaser.h b/moveit_ros/planning_interface/py_bindings_tools/include/moveit/py_bindings_tools/gil_releaser.h index 697a0a446e..215a470810 100644 --- a/moveit_ros/planning_interface/py_bindings_tools/include/moveit/py_bindings_tools/gil_releaser.h +++ b/moveit_ros/planning_interface/py_bindings_tools/include/moveit/py_bindings_tools/gil_releaser.h @@ -59,13 +59,16 @@ class GILReleaser /** \brief Release the GIL on construction */ GILReleaser() noexcept { - m_thread_state = nullptr; - release(); + m_thread_state = PyEval_SaveThread(); } /** \brief Reacquire the GIL on destruction */ ~GILReleaser() noexcept { - reacquire(); + if (m_thread_state) + { + PyEval_RestoreThread(m_thread_state); + m_thread_state = nullptr; + } } GILReleaser(const GILReleaser&) = delete; @@ -87,24 +90,6 @@ class GILReleaser { std::swap(other.m_thread_state, m_thread_state); } - - /** \brief Reacquire the GIL, noop if already acquired */ - void reacquire() noexcept - { - if (m_thread_state) - { - PyEval_RestoreThread(m_thread_state); - m_thread_state = nullptr; - } - } - /** \brief Release the GIL (again), noop if already released */ - void release() noexcept - { - if (!m_thread_state) - { - m_thread_state = PyEval_SaveThread(); - } - } }; } // namespace py_bindings_tools From 285301881fa7cc340688d5af541597a4e47aebe9 Mon Sep 17 00:00:00 2001 From: Bjar Ne <43565432+gleichdick@users.noreply.github.com> Date: Tue, 13 Oct 2020 22:31:16 +0100 Subject: [PATCH 002/179] Unit Test for ByteString-based ROS msg conversion (#2362) --- .../planning_interface/test/CMakeLists.txt | 12 ++ .../planning_interface/test/serialize_msg.py | 110 ++++++++++++++ .../test/serialize_msg_python_cpp_helpers.cpp | 134 ++++++++++++++++++ 3 files changed, 256 insertions(+) create mode 100644 moveit_ros/planning_interface/test/serialize_msg.py create mode 100644 moveit_ros/planning_interface/test/serialize_msg_python_cpp_helpers.cpp diff --git a/moveit_ros/planning_interface/test/CMakeLists.txt b/moveit_ros/planning_interface/test/CMakeLists.txt index 871dddebe6..61609181cb 100644 --- a/moveit_ros/planning_interface/test/CMakeLists.txt +++ b/moveit_ros/planning_interface/test/CMakeLists.txt @@ -15,4 +15,16 @@ if (CATKIN_ENABLE_TESTING) add_rostest(python_move_group_ns.test) add_rostest(robot_state_update.test) add_rostest(cleanup.test) + + SET(HELPER_LIB moveit_planning_interface_test_serialize_msg_cpp_helper) + add_library(${HELPER_LIB} serialize_msg_python_cpp_helpers.cpp) + set_target_properties(${HELPER_LIB} PROPERTIES VERSION "${${PROJECT_NAME}_VERSION}") + target_link_libraries(${HELPER_LIB} ${PYTHON_LIBRARIES} ${catkin_LIBRARIES} ${Boost_LIBRARIES} moveit_py_bindings_tools) + set_target_properties(${HELPER_LIB} PROPERTIES OUTPUT_NAME "_${HELPER_LIB}" PREFIX "") + set_target_properties(${HELPER_LIB} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}") + if(WIN32) + set_target_properties(${HELPER_LIB} PROPERTIES SUFFIX .pyd) + endif(WIN32) + + catkin_add_nosetests(serialize_msg.py) endif() diff --git a/moveit_ros/planning_interface/test/serialize_msg.py b/moveit_ros/planning_interface/test/serialize_msg.py new file mode 100644 index 0000000000..0497d5d9f9 --- /dev/null +++ b/moveit_ros/planning_interface/test/serialize_msg.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python + +# Software License Agreement (BSD License) +# +# Copyright (c) 2020, RWTH Aachen University +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of RWTH Aachen University 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: Bjarne von Horn +# + +from moveit_ros_planning_interface._moveit_planning_interface_test_serialize_msg_cpp_helper import ByteStringTestHelper +from geometry_msgs.msg import Vector3 +import unittest + +try: + # Try Python 2.7 behaviour first + from StringIO import StringIO + py_version_maj = 2 +except ImportError: + # Use Python 3.x behaviour as fallback and choose the non-unicode version + from io import BytesIO as StringIO + py_version_maj = 3 + + +class PythonMsgSerializeTest(unittest.TestCase): + def setUp(self): + self.helper = ByteStringTestHelper() + + def test_EmbeddedZeros(self): + self.assertTrue(self.helper.compareEmbeddedZeros(b"\xff\xef\x00\x10")) + + def test_ByteStringFromPchar(self): + # ByteString(const char*) constructor + self.assertEqual(self.helper.getBytesPChar(), b"abcdef") + + def test_ByteStringFromStdString(self): + # ByteString(const std::string&) constructor + self.assertEqual(self.helper.getBytesStdString(), b"\xff\xfe\x10\x00\x00") + + def test_ByteStringDefaultCtor(self): + self.assertEqual(self.helper.getDefaultBytes(), b"") + + def test_CxxTupleToPy(self): + # sending a tuple from C++ to Python + ans = self.helper.getTuple() + self.assertIsInstance(ans, tuple) + self.assertEqual(len(ans), 1) + self.assertEqual(ans[0], b"abcdef") + + def test_PyTupleToCxx(self): + # sending a tuple from Python to C++ + self.assertTrue(self.helper.compareTuple((b"mno",))) + + def test_sendMessage(self): + tmp = StringIO() + Vector3(x=1.0, y=-2.0, z=0.25).serialize(tmp) + self.assertTrue(self.helper.compareVector(tmp.getvalue())) + + def test_recieveMessage(self): + tmp = Vector3() + tmp.deserialize(self.helper.getVector()) + self.assertEqual(tmp, Vector3(1.0, -2.0, 0.25)) + + def test_rejectInt(self): + with self.assertRaisesRegexp(Exception, "Python argument types in"): + self.helper.compareEmbeddedZeros(4711) + + def test_rejectIntTuple(self): + with self.assertRaisesRegexp(Exception, "Python argument types in"): + self.helper.compareEmbeddedZeros((4711,)) + + def test_rejectUnicode(self): + with self.assertRaisesRegexp(Exception, "Python argument types in"): + self.helper.compareEmbeddedZeros(u'kdasd') + + @unittest.skipIf(py_version_maj == 2, "does not trigger with python 2.7") + def test_rejectUnicodeTuple(self): + with self.assertRaisesRegexp(RuntimeError, "Underlying python object is not a Bytes/String instance"): + self.helper.compareVectorTuple((u'kdasd',)) + + +if __name__ == '__main__': + unittest.main() diff --git a/moveit_ros/planning_interface/test/serialize_msg_python_cpp_helpers.cpp b/moveit_ros/planning_interface/test/serialize_msg_python_cpp_helpers.cpp new file mode 100644 index 0000000000..13c6e446d6 --- /dev/null +++ b/moveit_ros/planning_interface/test/serialize_msg_python_cpp_helpers.cpp @@ -0,0 +1,134 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2020, RWTH Aachen University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of RWTH Aachen University 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: Bjarne von Horn */ + +#include +#include +#include +#include +#include + +namespace bp = boost::python; +using moveit::py_bindings_tools::ByteString; + +// Helper class to be exposed to Python +class ByteStringTestHelper +{ + // Helper to test whether a vector of unsigned chars has the same content as a bytes Object + bool doCompare(const std::vector& data, PyObject* obj) + { + const char* py_data = PyBytes_AsString(obj); + if (!py_data) + return false; + Py_ssize_t size = PyBytes_GET_SIZE(obj); + if (size < 0 || std::vector::size_type(size) != data.size()) + return false; + return std::memcmp(py_data, &data[0], size) == 0; + } + +public: + bool compareEmbeddedZeros(const ByteString& s) + { + const std::vector testdata{ 0xff, 0xef, 0x00, 0x10 }; + return doCompare(testdata, s.ptr()); + } + bool compareTuple(const bp::tuple& t) + { + const ByteString s(t[0]); + const std::vector testdata{ 'm', 'n', 'o' }; + return doCompare(testdata, s.ptr()); + } + + ByteString getBytesPChar() + { + return ByteString("abcdef"); + } + ByteString getBytesStdString() + { + std::string s; + s.push_back('\xff'); + s.push_back('\xfe'); + s.push_back('\x10'); + s.push_back('\x00'); + s.push_back('\x00'); + return ByteString(s); + } + ByteString getDefaultBytes() + { + return ByteString(); + } + bp::tuple getTuple() + { + return bp::make_tuple(ByteString("abcdef")); + } + ByteString getVector() + { + geometry_msgs::Vector3 v; + v.x = 1.0; + v.y = -2.0; + v.z = 0.25; + return ByteString(v); + } + bool compareVector(const ByteString& s) + { + geometry_msgs::Vector3 v; + s.deserialize(v); + return v.x == 1.0 && v.y == -2.0 && v.z == 0.25; + } + bool compareVectorTuple(const bp::tuple& t) + { + const ByteString s(t[0]); + return compareVector(s); + } + + static void setup() + { + bp::class_ cls("ByteStringTestHelper"); + cls.def("compareEmbeddedZeros", &ByteStringTestHelper::compareEmbeddedZeros); + cls.def("compareTuple", &ByteStringTestHelper::compareTuple); + cls.def("compareVectorTuple", &ByteStringTestHelper::compareVectorTuple); + cls.def("getBytesPChar", &ByteStringTestHelper::getBytesPChar); + cls.def("getBytesStdString", &ByteStringTestHelper::getBytesStdString); + cls.def("getDefaultBytes", &ByteStringTestHelper::getDefaultBytes); + cls.def("getTuple", &ByteStringTestHelper::getTuple); + cls.def("getVector", &ByteStringTestHelper::getVector); + cls.def("compareVector", &ByteStringTestHelper::compareVector); + } +}; + +BOOST_PYTHON_MODULE(_moveit_planning_interface_test_serialize_msg_cpp_helper) +{ + ByteStringTestHelper::setup(); +} From 3da197e0f4a74b2f767887f428f975bd5e0f4951 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Tue, 13 Oct 2020 23:46:31 +0200 Subject: [PATCH 003/179] Fixup 2e71b90: Remove unused variable --- .../move_group_interface/src/wrap_python_move_group.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp b/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp index bb60acd95b..f8bcccecce 100644 --- a/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp +++ b/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp @@ -467,10 +467,9 @@ class MoveGroupInterfaceWrapper : protected py_bindings_tools::ROScppInitializer py_bindings_tools::ByteString getPlanPython() { MoveGroupInterface::Plan plan; - moveit_msgs::MoveItErrorCodes res; { GILReleaser gr; - res = MoveGroupInterface::plan(plan); + MoveGroupInterface::plan(plan); } return py_bindings_tools::serializeMsg(plan.trajectory_); } From ff552bf861609f99ca97a7e173fcbeb0c03e9f45 Mon Sep 17 00:00:00 2001 From: Ghenohenomohe <71963599+Ghenohenomohe@users.noreply.github.com> Date: Fri, 23 Oct 2020 12:22:44 +0900 Subject: [PATCH 004/179] Update collision-related comments (#2382) --- .../include/moveit/collision_detection_fcl/collision_common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_common.h b/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_common.h index f7dff1dec5..9f1565442d 100644 --- a/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_common.h +++ b/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_common.h @@ -273,7 +273,7 @@ struct FCLManager * \param o1 First FCL collision object * \param o2 Second FCL collision object * \data General pointer to arbitrary data which is used during the callback - * \return True terminates the distance check, false continues it to the next pair of objects */ + * \return True terminates the collision check, false continues it to the next pair of objects */ bool collisionCallback(fcl::CollisionObjectd* o1, fcl::CollisionObjectd* o2, void* data); /** \brief Callback function used by the FCLManager used for each pair of collision objects to @@ -282,7 +282,7 @@ bool collisionCallback(fcl::CollisionObjectd* o1, fcl::CollisionObjectd* o2, voi * \param o1 First FCL collision object * \param o2 Second FCL collision object * \data General pointer to arbitrary data which is used during the callback - * \return True terminates the collision check, false continues it to the next pair of objects */ + * \return True terminates the distance check, false continues it to the next pair of objects */ bool distanceCallback(fcl::CollisionObjectd* o1, fcl::CollisionObjectd* o2, void* data, double& min_dist); /** \brief Create new FCLGeometry object out of robot link model. */ From 0f9e6ac6daf9c098c87c9de0e5a08d4db876692a Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Wed, 19 Aug 2020 15:21:16 +0200 Subject: [PATCH 005/179] Start new joint_state_publisher_gui on param use_gui (#2257) --- .../test/rrbot_move_group.launch | 8 +++++--- .../test_cancel_before_plan_execution.test | 20 +++++++++++++++++-- .../launch/demo.launch | 6 ++++-- .../launch/demo_gazebo.launch | 8 ++++++-- .../package.xml.template | 1 + 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/moveit_planners/chomp/chomp_interface/test/rrbot_move_group.launch b/moveit_planners/chomp/chomp_interface/test/rrbot_move_group.launch index 2bdfe3c0b5..782b702447 100644 --- a/moveit_planners/chomp/chomp_interface/test/rrbot_move_group.launch +++ b/moveit_planners/chomp/chomp_interface/test/rrbot_move_group.launch @@ -1,6 +1,6 @@ - + @@ -17,8 +17,10 @@ - - + + [move_group/fake_controller_joint_states] + + [move_group/fake_controller_joint_states] diff --git a/moveit_ros/move_group/test/test_cancel_before_plan_execution.test b/moveit_ros/move_group/test/test_cancel_before_plan_execution.test index a4f22e456f..4acb89e476 100644 --- a/moveit_ros/move_group/test/test_cancel_before_plan_execution.test +++ b/moveit_ros/move_group/test/test_cancel_before_plan_execution.test @@ -1,6 +1,22 @@ - - + + + + + + + + [move_group/fake_controller_joint_states] + + + + + + + + + + diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch index ef52573466..6c0a4edbbf 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch @@ -31,8 +31,10 @@ [VIRTUAL_JOINT_BROADCASTER] - - + + [move_group/fake_controller_joint_states] + + [move_group/fake_controller_joint_states] diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo_gazebo.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo_gazebo.launch index 6249188164..c2257e535f 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo_gazebo.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo_gazebo.launch @@ -40,8 +40,12 @@ [VIRTUAL_JOINT_BROADCASTER] - - + + [move_group/fake_controller_joint_states] + [/joint_states] + + + [move_group/fake_controller_joint_states] [/joint_states] diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/package.xml.template b/moveit_setup_assistant/templates/moveit_config_pkg_template/package.xml.template index ba305540fc..60202e870e 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/package.xml.template +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/package.xml.template @@ -23,6 +23,7 @@ moveit_ros_visualization moveit_setup_assistant joint_state_publisher + joint_state_publisher_gui robot_state_publisher tf2_ros xacro From f9c4a1596cc46df924ca519359f843756d2174bc Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Wed, 19 Aug 2020 11:19:06 -0600 Subject: [PATCH 006/179] add soname version to moveit_servo (#2266) --- moveit_ros/moveit_servo/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/moveit_ros/moveit_servo/CMakeLists.txt b/moveit_ros/moveit_servo/CMakeLists.txt index 239461754a..a196af86d7 100644 --- a/moveit_ros/moveit_servo/CMakeLists.txt +++ b/moveit_ros/moveit_servo/CMakeLists.txt @@ -65,6 +65,7 @@ add_library(${LIBRARY_NAME} SHARED src/joint_state_subscriber.cpp src/low_pass_filter.cpp ) +set_target_properties(${LIBRARY_NAME} PROPERTIES VERSION "${${PROJECT_NAME}_VERSION}") add_dependencies(${LIBRARY_NAME} ${catkin_EXPORTED_TARGETS}) target_link_libraries(${LIBRARY_NAME} ${catkin_LIBRARIES} From 947c6007cd293831696bee1d2a6c41bbc762be40 Mon Sep 17 00:00:00 2001 From: Dave Coleman Date: Wed, 19 Aug 2020 14:16:00 -0600 Subject: [PATCH 007/179] Move constraint representation dox to moveit_tutorials (#2147) --- .../dox/constraint_representation.dox | 17 ----------------- .../dox/img/exact_opposites.png | Bin 3079 -> 0 bytes .../dox/img/fingertip_collision.png | Bin 77053 -> 0 bytes .../dox/img/fingertip_cone.jpg | Bin 26612 -> 0 bytes .../dox/img/fingertip_cone.png | Bin 80571 -> 0 bytes .../dox/img/fourty_five.png | Bin 2897 -> 0 bytes .../dox/img/other_side.png | Bin 2771 -> 0 bytes .../dox/img/perpindicular.png | Bin 1699 -> 0 bytes .../dox/img/range_angle.png | Bin 5697 -> 0 bytes 9 files changed, 17 deletions(-) delete mode 100644 moveit_core/kinematic_constraints/dox/constraint_representation.dox delete mode 100644 moveit_core/kinematic_constraints/dox/img/exact_opposites.png delete mode 100644 moveit_core/kinematic_constraints/dox/img/fingertip_collision.png delete mode 100644 moveit_core/kinematic_constraints/dox/img/fingertip_cone.jpg delete mode 100644 moveit_core/kinematic_constraints/dox/img/fingertip_cone.png delete mode 100644 moveit_core/kinematic_constraints/dox/img/fourty_five.png delete mode 100644 moveit_core/kinematic_constraints/dox/img/other_side.png delete mode 100644 moveit_core/kinematic_constraints/dox/img/perpindicular.png delete mode 100644 moveit_core/kinematic_constraints/dox/img/range_angle.png diff --git a/moveit_core/kinematic_constraints/dox/constraint_representation.dox b/moveit_core/kinematic_constraints/dox/constraint_representation.dox deleted file mode 100644 index 886a3100e9..0000000000 --- a/moveit_core/kinematic_constraints/dox/constraint_representation.dox +++ /dev/null @@ -1,17 +0,0 @@ -/** -\page constraint_representation Representation and Evaluation of Constraints - -Constraints are integral component of MoveIt! and they are used both to constrain robot motion as well as to define planning goals. There following set of constraints are defined in the kinematic_constraints namespace: -- kinematic_constraints::JointConstraint -- kinematic_constraints::OrientationConstraint -- kinematic_constraints::PositionConstraint -- kinematic_constraints::VisibilityConstraint -. - -All of these constraints inherit from the kinematic_constraints::KinematicConstraint base class and thus more constraint types can be added by the user by providing their own derived classes. The main operation each constraint implements is the KinematicConstraint::decide() function, which decides whether a constraint is satisfied, and optionally returns a distance (an error) when a constraint is not satisfied. - -Often multiple constraints need to be imposed on a particular motion plan or for a particular goal. The class kinematic_constraints::KinematicConstraintSet facilitates operating with sets of constraints. - -A related functionality to representing and evaluating constraints is \ref constraint_sampling "generating samples" that satisfy those constraints. - -*/ diff --git a/moveit_core/kinematic_constraints/dox/img/exact_opposites.png b/moveit_core/kinematic_constraints/dox/img/exact_opposites.png deleted file mode 100644 index 64e2470d9cadbb66267962fcc48d85c153e6b716..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3079 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 Ws(Wc$i6J_qW2}isEpyF(3;P$mey#8T diff --git a/moveit_core/kinematic_constraints/dox/img/fingertip_collision.png b/moveit_core/kinematic_constraints/dox/img/fingertip_collision.png deleted file mode 100644 index cf55ddbf1ff9b2928f2ccc38ba322f259fb6b5f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77053 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 C2deM@ diff --git a/moveit_core/kinematic_constraints/dox/img/fingertip_cone.jpg b/moveit_core/kinematic_constraints/dox/img/fingertip_cone.jpg deleted file mode 100644 index 4c6e8ea35e7884bb759cef269b2f485181446514..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26612 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 diff --git a/moveit_core/kinematic_constraints/dox/img/fourty_five.png b/moveit_core/kinematic_constraints/dox/img/fourty_five.png deleted file mode 100644 index 925cb551244afb751594f3be1a628cb37c2af7a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2897 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 diff --git a/moveit_core/kinematic_constraints/dox/img/perpindicular.png b/moveit_core/kinematic_constraints/dox/img/perpindicular.png deleted file mode 100644 index 8e1787439420c2dc9879a27b7327b252f0a32e39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1699 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 O;H~Tq799Bf%6|cC6jX)) From e36f76cf93c2949191d4317f686396252e010145 Mon Sep 17 00:00:00 2001 From: AdamPettinger Date: Wed, 26 Aug 2020 10:50:10 -0500 Subject: [PATCH 008/179] Update last_sent_command_ at ServoCalcs start (#2249) * Move last_sent_command_ update from constructor to start * Tweak demo configs * Add install folders to CMakeLists * Add clarity to parameter warning --- moveit_ros/moveit_servo/CMakeLists.txt | 3 ++ .../config/ur_simulated_config.yaml | 2 +- moveit_ros/moveit_servo/src/servo.cpp | 2 +- moveit_ros/moveit_servo/src/servo_calcs.cpp | 36 ++++++++++--------- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/moveit_ros/moveit_servo/CMakeLists.txt b/moveit_ros/moveit_servo/CMakeLists.txt index a196af86d7..cadc430e90 100644 --- a/moveit_ros/moveit_servo/CMakeLists.txt +++ b/moveit_ros/moveit_servo/CMakeLists.txt @@ -128,6 +128,9 @@ install(DIRECTORY include/${PROJECT_NAME}/ DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} ) +install(DIRECTORY launch DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) +install(DIRECTORY config DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) + ############# ## TESTING ## ############# diff --git a/moveit_ros/moveit_servo/config/ur_simulated_config.yaml b/moveit_ros/moveit_servo/config/ur_simulated_config.yaml index 5c477ffb70..21fd7cbb36 100644 --- a/moveit_ros/moveit_servo/config/ur_simulated_config.yaml +++ b/moveit_ros/moveit_servo/config/ur_simulated_config.yaml @@ -55,7 +55,7 @@ collision_check_rate: 50 # [Hz] Collision-checking can easily bog down a CPU if # Two collision check algorithms are available: # "threshold_distance" begins slowing down when nearer than a specified distance. Good if you want to tune collision thresholds manually. # "stop_distance" stops if a collision is nearer than the worst-case stopping distance and the distance is decreasing. Requires joint acceleration limits -collision_check_type: stop_distance +collision_check_type: threshold_distance # Parameters for "threshold_distance"-type collision checking self_collision_proximity_threshold: 0.01 # Start decelerating when a self-collision is this far [m] scene_collision_proximity_threshold: 0.05 # Start decelerating when a scene collision is this far [m] diff --git a/moveit_ros/moveit_servo/src/servo.cpp b/moveit_ros/moveit_servo/src/servo.cpp index ee567f8bb3..8cc834a047 100644 --- a/moveit_ros/moveit_servo/src/servo.cpp +++ b/moveit_ros/moveit_servo/src/servo.cpp @@ -196,7 +196,7 @@ bool Servo::readParameters() if (parameters_.joint_limit_margin < 0.) { ROS_WARN_NAMED(LOGNAME, "Parameter 'joint_limit_margin' should be " - "greater than zero. Check yaml file."); + "greater than or equal to zero. Check yaml file."); return false; } if (parameters_.command_in_type != "unitless" && parameters_.command_in_type != "speed_units") diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index f2282ef69c..5e756697f5 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -134,14 +134,31 @@ ServoCalcs::ServoCalcs(ros::NodeHandle& nh, const ServoParameters& parameters, internal_joint_state_.position.resize(num_joints_); internal_joint_state_.velocity.resize(num_joints_); - // Set up the "last" published message, in case we need to send it first + // A map for the indices of incoming joint commands + for (std::size_t i = 0; i < num_joints_; ++i) + { + joint_state_name_map_[internal_joint_state_.name[i]] = i; + } + + // Low-pass filters for the joint positions + for (size_t i = 0; i < num_joints_; ++i) + { + position_filters_.emplace_back(parameters_.low_pass_filter_coeff); + } +} + +void ServoCalcs::start() +{ + // We will update last_sent_command_ every time we start servo auto initial_joint_trajectory = moveit::util::make_shared_from_pool(); - auto latest_joints = joint_state_subscriber_->getLatest(); + initial_joint_trajectory->header.frame_id = parameters_.planning_frame; initial_joint_trajectory->header.stamp = ros::Time::now(); initial_joint_trajectory->joint_names = internal_joint_state_.name; trajectory_msgs::JointTrajectoryPoint point; point.time_from_start = ros::Duration(parameters_.publish_period); + + auto latest_joints = joint_state_subscriber_->getLatest(); if (parameters_.publish_joint_positions) point.positions = latest_joints->position; if (parameters_.publish_joint_velocities) @@ -160,21 +177,6 @@ ServoCalcs::ServoCalcs(ros::NodeHandle& nh, const ServoParameters& parameters, initial_joint_trajectory->points.push_back(point); last_sent_command_ = initial_joint_trajectory; - // A map for the indices of incoming joint commands - for (std::size_t i = 0; i < num_joints_; ++i) - { - joint_state_name_map_[internal_joint_state_.name[i]] = i; - } - - // Low-pass filters for the joint positions - for (size_t i = 0; i < num_joints_; ++i) - { - position_filters_.emplace_back(parameters_.low_pass_filter_coeff); - } -} - -void ServoCalcs::start() -{ stop_requested_ = false; timer_ = nh_.createTimer(period_, &ServoCalcs::run, this); } From 2565c0d214953a87490128102c795a37b86ce406 Mon Sep 17 00:00:00 2001 From: AndyZe Date: Wed, 26 Aug 2020 15:22:43 -0500 Subject: [PATCH 009/179] Add a utility to print collision pairs (#2275) * Add a utility for logging collision pairs * Update printing style, rename function, move constants into the struct --- .../collision_detection/collision_common.h | 33 ++++++++++++++++++- .../include/moveit_servo/collision_check.h | 3 -- .../moveit_servo/src/collision_check.cpp | 22 +------------ 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h b/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h index edf7914d2e..bdf2d810bc 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h @@ -136,7 +136,12 @@ struct CostSource /** \brief Representation of a collision checking result */ struct CollisionResult { - CollisionResult() : collision(false), distance(std::numeric_limits::max()), contact_count(0) + CollisionResult() + : collision(false) + , distance(std::numeric_limits::max()) + , contact_count(0) + , collision_log_period(5) + , collision_log_name("collision_common") { } typedef std::map, std::vector > ContactMap; @@ -153,6 +158,26 @@ struct CollisionResult cost_sources.clear(); } + /** \brief Throttled warning of the first collision pair, if any. Other collisions are logged at the DEBUG level */ + void print() + { + if (!contacts.empty()) + { + ROS_WARN_STREAM_THROTTLE_NAMED(collision_log_period, collision_log_name, + "Objects in collision (printing first collision pair of " + << contacts.size() << "): " << contacts.begin()->first.first << ", " + << contacts.begin()->first.second); + + // Log all collisions at the debug level + ROS_DEBUG_STREAM_THROTTLE_NAMED(collision_log_period, collision_log_name, "Objects in collision:"); + for (auto contact : contacts) + { + ROS_DEBUG_STREAM_THROTTLE_NAMED(collision_log_period, collision_log_name, + "\t" << contact.first.first << ", " << contact.first.second); + } + } + } + /** \brief True if collision was found, false otherwise */ bool collision; @@ -167,6 +192,12 @@ struct CollisionResult /** \brief These are the individual cost sources when costs are computed */ std::set cost_sources; + + /** \brief Period for logging collisions */ + double collision_log_period; + + /** Log name, for printed messages */ + std::string collision_log_name; }; /** \brief Representation of a collision checking request */ diff --git a/moveit_ros/moveit_servo/include/moveit_servo/collision_check.h b/moveit_ros/moveit_servo/include/moveit_servo/collision_check.h index 30ddaff162..a02fe4750a 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/collision_check.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/collision_check.h @@ -79,9 +79,6 @@ class CollisionCheck /** \brief Run one iteration of collision checking */ void run(const ros::TimerEvent& timer_event); - /** \brief Print objects in collision. Useful for debugging. */ - void printCollisionPairs(collision_detection::CollisionResult::ContactMap& contact_map); - /** \brief Get a read-only copy of the planning scene */ planning_scene_monitor::LockedPlanningSceneRO getLockedPlanningSceneRO() const; diff --git a/moveit_ros/moveit_servo/src/collision_check.cpp b/moveit_ros/moveit_servo/src/collision_check.cpp index 122ced12f1..1f85d40cd1 100644 --- a/moveit_ros/moveit_servo/src/collision_check.cpp +++ b/moveit_ros/moveit_servo/src/collision_check.cpp @@ -132,7 +132,6 @@ void CollisionCheck::run(const ros::TimerEvent& timer_event) scene_collision_distance_ = collision_result_.distance; collision_detected_ |= collision_result_.collision; - printCollisionPairs(collision_result_.contacts); collision_result_.clear(); // Self-collisions and scene collisions are checked separately so different thresholds can be used @@ -142,7 +141,7 @@ void CollisionCheck::run(const ros::TimerEvent& timer_event) self_collision_distance_ = collision_result_.distance; collision_detected_ |= collision_result_.collision; - printCollisionPairs(collision_result_.contacts); + collision_result_.print(); velocity_scale_ = 1; // If we're definitely in collision, stop immediately @@ -213,25 +212,6 @@ void CollisionCheck::run(const ros::TimerEvent& timer_event) } } -void CollisionCheck::printCollisionPairs(collision_detection::CollisionResult::ContactMap& contact_map) -{ - if (!contact_map.empty()) - { - // Throttled error message about the first contact in the list - ROS_WARN_STREAM_THROTTLE_NAMED(ROS_LOG_THROTTLE_PERIOD, LOGNAME, - "Objects in collision (among others, possibly): " - << contact_map.begin()->first.first << ", " - << contact_map.begin()->first.second); - // Log all other contacts if in debug mode - ROS_DEBUG_STREAM_THROTTLE_NAMED(ROS_LOG_THROTTLE_PERIOD, LOGNAME, "Objects in collision:"); - for (auto contact : contact_map) - { - ROS_DEBUG_STREAM_THROTTLE_NAMED(ROS_LOG_THROTTLE_PERIOD, LOGNAME, - "\t" << contact.first.first << ", " << contact.first.second); - } - } -} - void CollisionCheck::worstCaseStopTimeCB(const std_msgs::Float64ConstPtr& msg) { worst_case_stop_time_ = msg->data; From f6cbae20b2507a34edf6019a71573323be98e251 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Thu, 27 Aug 2020 19:51:41 +0200 Subject: [PATCH 010/179] Cleanup: Add a utility to print collision pairs (#2278) --- .../collision_detection/CMakeLists.txt | 1 + .../collision_detection/collision_common.h | 34 +---------- .../src/collision_common.cpp | 61 +++++++++++++++++++ 3 files changed, 65 insertions(+), 31 deletions(-) create mode 100644 moveit_core/collision_detection/src/collision_common.cpp diff --git a/moveit_core/collision_detection/CMakeLists.txt b/moveit_core/collision_detection/CMakeLists.txt index 21d3bcb5d3..9249588be5 100644 --- a/moveit_core/collision_detection/CMakeLists.txt +++ b/moveit_core/collision_detection/CMakeLists.txt @@ -3,6 +3,7 @@ set(MOVEIT_LIB_NAME moveit_collision_detection) add_library(${MOVEIT_LIB_NAME} src/allvalid/collision_robot_allvalid.cpp src/allvalid/collision_world_allvalid.cpp + src/collision_common.cpp src/collision_matrix.cpp src/collision_octomap_filter.cpp src/collision_robot.cpp diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h b/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h index bdf2d810bc..c5b49c1c81 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h @@ -136,12 +136,7 @@ struct CostSource /** \brief Representation of a collision checking result */ struct CollisionResult { - CollisionResult() - : collision(false) - , distance(std::numeric_limits::max()) - , contact_count(0) - , collision_log_period(5) - , collision_log_name("collision_common") + CollisionResult() : collision(false), distance(std::numeric_limits::max()), contact_count(0) { } typedef std::map, std::vector > ContactMap; @@ -158,25 +153,8 @@ struct CollisionResult cost_sources.clear(); } - /** \brief Throttled warning of the first collision pair, if any. Other collisions are logged at the DEBUG level */ - void print() - { - if (!contacts.empty()) - { - ROS_WARN_STREAM_THROTTLE_NAMED(collision_log_period, collision_log_name, - "Objects in collision (printing first collision pair of " - << contacts.size() << "): " << contacts.begin()->first.first << ", " - << contacts.begin()->first.second); - - // Log all collisions at the debug level - ROS_DEBUG_STREAM_THROTTLE_NAMED(collision_log_period, collision_log_name, "Objects in collision:"); - for (auto contact : contacts) - { - ROS_DEBUG_STREAM_THROTTLE_NAMED(collision_log_period, collision_log_name, - "\t" << contact.first.first << ", " << contact.first.second); - } - } - } + /** \brief Throttled warning printing the first collision pair, if any. All collisions are logged at DEBUG level */ + void print() const; /** \brief True if collision was found, false otherwise */ bool collision; @@ -192,12 +170,6 @@ struct CollisionResult /** \brief These are the individual cost sources when costs are computed */ std::set cost_sources; - - /** \brief Period for logging collisions */ - double collision_log_period; - - /** Log name, for printed messages */ - std::string collision_log_name; }; /** \brief Representation of a collision checking request */ diff --git a/moveit_core/collision_detection/src/collision_common.cpp b/moveit_core/collision_detection/src/collision_common.cpp new file mode 100644 index 0000000000..0f54dfdfd3 --- /dev/null +++ b/moveit_core/collision_detection/src/collision_common.cpp @@ -0,0 +1,61 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2011, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT 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. + *********************************************************************/ + +#include + +static const char LOGNAME[] = "collision_common"; +constexpr size_t LOG_THROTTLE_PERIOD = 5; + +namespace collision_detection +{ +void CollisionResult::print() const +{ + if (!contacts.empty()) + { + ROS_WARN_STREAM_THROTTLE_NAMED(LOG_THROTTLE_PERIOD, LOGNAME, + "Objects in collision (printing 1st of " + << contacts.size() << " pairs): " << contacts.begin()->first.first << ", " + << contacts.begin()->first.second); + + // Log all collisions at the debug level + ROS_DEBUG_STREAM_THROTTLE_NAMED(LOG_THROTTLE_PERIOD, LOGNAME, "Objects in collision:"); + for (const auto& contact : contacts) + { + ROS_DEBUG_STREAM_THROTTLE_NAMED(LOG_THROTTLE_PERIOD, LOGNAME, + "\t" << contact.first.first << ", " << contact.first.second); + } + } +} + +} // namespace collision_detection From 91cf2320ec0d023f31ca9f68918edeaa8afbb6a0 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 28 Aug 2020 10:28:18 +0200 Subject: [PATCH 011/179] Replace $(find xacro)/xacro -> xacro (#2282) --- .../chomp/chomp_interface/test/rrbot_move_group.launch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moveit_planners/chomp/chomp_interface/test/rrbot_move_group.launch b/moveit_planners/chomp/chomp_interface/test/rrbot_move_group.launch index 782b702447..ab54cf53fc 100644 --- a/moveit_planners/chomp/chomp_interface/test/rrbot_move_group.launch +++ b/moveit_planners/chomp/chomp_interface/test/rrbot_move_group.launch @@ -6,7 +6,7 @@ - + From c6b4a8a0758b5da458501afdaa34ebd883005c6a Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Thu, 3 Sep 2020 16:28:44 -0400 Subject: [PATCH 012/179] [maint] Remove kinetic from Travis CI testing (#2295) --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4a79fcd05d..c05d44d40f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,6 @@ jobs: - env: TEST="clang-format catkin_lint" - env: TEST=code-coverage - env: ROS_DISTRO=melodic - - env: ROS_DISTRO=kinetic - env: BEFORE_DOCKER_SCRIPT="source moveit_kinematics/test/test_ikfast_plugins.sh" - if: branch =~ /^(.*-devel|master)$/ env: ROS_REPO=ros-shadow-fixed From 75c284100c6e85c9ae46bb305a4f5681e990d405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Mon, 7 Sep 2020 18:33:16 +0200 Subject: [PATCH 013/179] MSA: only write default_planner_config field if any is selected (#2293) Otherwise, we get entries like this in ompl_planning.yaml, where "None", of course, is not a valid planner config: arm: default_planner_config: None --- moveit_setup_assistant/src/tools/moveit_config_data.cpp | 7 ++++--- .../src/widgets/planning_groups_widget.cpp | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/moveit_setup_assistant/src/tools/moveit_config_data.cpp b/moveit_setup_assistant/src/tools/moveit_config_data.cpp index 63ad7d59fc..0946efe9f7 100644 --- a/moveit_setup_assistant/src/tools/moveit_config_data.cpp +++ b/moveit_setup_assistant/src/tools/moveit_config_data.cpp @@ -241,8 +241,9 @@ bool MoveItConfigData::outputOMPLPlanningYAML(const std::string& file_path) emitter << YAML::Key << group_it->name_; emitter << YAML::Value << YAML::BeginMap; // Output associated planners - emitter << YAML::Key << "default_planner_config" << YAML::Value - << group_meta_data_[group_it->name_].default_planner_; + if (!group_meta_data_[group_it->name_].default_planner_.empty()) + emitter << YAML::Key << "default_planner_config" << YAML::Value + << group_meta_data_[group_it->name_].default_planner_; emitter << YAML::Key << "planner_configs"; emitter << YAML::Value << YAML::BeginSeq; for (std::size_t i = 0; i < pconfigs.size(); ++i) @@ -272,7 +273,7 @@ bool MoveItConfigData::outputOMPLPlanningYAML(const std::string& file_path) return false; } - output_stream << emitter.c_str(); + output_stream << emitter.c_str() << std::endl; output_stream.close(); return true; // file created successfully diff --git a/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp b/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp index 697d916269..d0890001f3 100644 --- a/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp +++ b/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp @@ -1250,7 +1250,7 @@ bool PlanningGroupsWidget::saveGroupScreen() config_data_->group_meta_data_[group_name].kinematics_solver_search_resolution_ = kinematics_resolution_double; config_data_->group_meta_data_[group_name].kinematics_solver_timeout_ = kinematics_timeout_double; config_data_->group_meta_data_[group_name].kinematics_parameters_file_ = kinematics_parameters_file; - config_data_->group_meta_data_[group_name].default_planner_ = default_planner; + config_data_->group_meta_data_[group_name].default_planner_ = (default_planner == "None" ? "" : default_planner); config_data_->changes |= MoveItConfigData::GROUP_KINEMATICS; // Reload main screen table From 56c93195a2f159e8014cf6d29817980ae0b5cd9f Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Sun, 13 Sep 2020 14:02:14 -0600 Subject: [PATCH 014/179] [fix] Servo heap-buffer-overflow bug (#2307) --- moveit_ros/moveit_servo/src/servo_calcs.cpp | 22 +++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index 5e756697f5..c28a36fd0b 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -37,6 +37,8 @@ * Author : Brian O'Neil, Andy Zelenak, Blake Anderson */ +#include + #include #include @@ -796,22 +798,26 @@ bool ServoCalcs::enforceSRDFPositionLimits() // Is handled differently for position vs. velocity control. void ServoCalcs::suddenHalt(trajectory_msgs::JointTrajectory& joint_trajectory) { - if (joint_trajectory.points.empty()) - { - joint_trajectory.points.push_back(trajectory_msgs::JointTrajectoryPoint()); - joint_trajectory.points[0].positions.resize(num_joints_); - joint_trajectory.points[0].velocities.resize(num_joints_); - } + // Prepare the joint trajectory message to stop the robot + joint_trajectory.points.clear(); + joint_trajectory.points.emplace_back(); + trajectory_msgs::JointTrajectoryPoint& point = joint_trajectory.points.front(); + point.positions.resize(num_joints_); + point.velocities.resize(num_joints_); + + // Assert the following loop is safe to execute + assert(original_joint_state_.position.size() >= num_joints_); + // Set the positions and velocities vectors for (std::size_t i = 0; i < num_joints_; ++i) { // For position-controlled robots, can reset the joints to a known, good state if (parameters_.publish_joint_positions) - joint_trajectory.points[0].positions[i] = original_joint_state_.position[i]; + point.positions[i] = original_joint_state_.position[i]; // For velocity-controlled robots, stop if (parameters_.publish_joint_velocities) - joint_trajectory.points[0].velocities[i] = 0; + point.velocities[i] = 0; } } From f898ea0b2be67d5131fdda585000fe48ff0c4a93 Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Tue, 15 Sep 2020 15:36:06 +0900 Subject: [PATCH 015/179] Add comment to MOVEIT_CLASS_FORWARD (#2315) --- .../collision_detection/collision_common.h | 2 +- .../collision_detector_allocator.h | 2 +- .../collision_detection/collision_matrix.h | 2 +- .../collision_detection/collision_plugin.h | 2 +- .../collision_detection/collision_robot.h | 2 +- .../moveit/collision_detection/world.h | 4 +- .../moveit/collision_detection/world_diff.h | 2 +- .../collision_distance_field_types.h | 2 +- .../collision_robot_distance_field.h | 2 +- .../constraint_samplers/constraint_sampler.h | 2 +- .../constraint_sampler_allocator.h | 2 +- .../constraint_sampler_manager.h | 2 +- .../default_constraint_samplers.h | 4 +- .../controller_manager/controller_manager.h | 4 +- .../moveit/distance_field/distance_field.h | 4 +- .../moveit/dynamics_solver/dynamics_solver.h | 2 +- .../kinematic_constraint.h | 12 +- .../moveit/kinematics_base/kinematics_base.h | 2 +- .../kinematics_metrics/kinematics_metrics.h | 2 +- .../planning_interface/planning_interface.h | 6 +- .../planning_request_adapter.h | 2 +- .../moveit/planning_scene/planning_scene.h | 2 +- .../include/moveit/robot_model/link_model.h | 2 +- .../include/moveit/robot_model/robot_model.h | 2 +- .../include/moveit/robot_state/robot_state.h | 2 +- .../robot_trajectory/robot_trajectory.h | 2 +- .../moveit/sensor_manager/sensor_manager.h | 2 +- .../include/moveit/transforms/transforms.h | 2 +- .../include/chomp_interface/chomp_interface.h | 2 +- .../chomp_interface/chomp_planning_context.h | 2 +- .../OMPLDynamicReconfigureConfig.h | 4 +- .../ompl_interface/constraints_library.h | 2 +- .../detail/constrained_valid_state_sampler.h | 2 +- .../model_based_planning_context.h | 4 +- .../model_based_state_space_factory.h | 2 +- .../trajopt_interface/problem_description.h | 367 ++++++++++++++++++ .../trajopt_interface/trajopt_interface.h | 77 ++++ .../trajopt_planning_context.h | 32 ++ .../src/moveit_fake_controllers.h | 2 +- .../ControllerHandle.h | 2 +- .../src/controller_manager_plugin.cpp | 2 +- .../action_based_controller_handle.h | 3 +- .../moveit/pick_place/manipulation_stage.h | 2 +- .../include/moveit/pick_place/pick_place.h | 6 +- .../moveit/move_group/move_group_capability.h | 2 +- .../moveit/move_group/move_group_context.h | 10 +- .../occupancy_map_updater.h | 2 +- .../include/moveit/mesh_filter/filter_job.h | 2 +- .../include/moveit/mesh_filter/gl_renderer.h | 2 +- .../moveit/mesh_filter/mesh_filter_base.h | 4 +- .../include/moveit/mesh_filter/sensor_model.h | 2 +- .../moveit/mesh_filter/transform_provider.h | 2 +- .../moveit/semantic_world/semantic_world.h | 4 +- .../collision_plugin_loader.h | 2 +- .../constraint_sampler_manager_loader.h | 3 +- .../kinematics_plugin_loader.h | 4 +- .../moveit/plan_execution/plan_execution.h | 2 +- .../moveit/plan_execution/plan_with_sensing.h | 2 +- .../planning_pipeline/planning_pipeline.h | 2 +- .../current_state_monitor.h | 2 +- .../planning_scene_monitor.h | 2 +- .../trajectory_monitor.h | 2 +- .../include/moveit/rdf_loader/rdf_loader.h | 2 +- .../robot_model_loader/robot_model_loader.h | 2 +- .../trajectory_execution_manager.h | 2 +- .../move_group_interface.h | 2 +- .../include/moveit/moveit_cpp/moveit_cpp.h | 2 +- .../moveit/moveit_cpp/planning_component.h | 2 +- .../planning_scene_interface.h | 2 +- .../robot_interaction/interaction_handler.h | 6 +- .../robot_interaction/locked_robot_state.h | 2 +- .../robot_interaction/robot_interaction.h | 6 +- .../motion_planning_frame.h | 6 +- .../motion_planning_param_widget.h | 2 +- .../planning_scene_render.h | 6 +- .../rviz_plugin_render_tools/render_shapes.h | 4 +- .../robot_state_visualization.h | 4 +- .../trajectory_visualization.h | 2 +- .../moveit/warehouse/constraints_storage.h | 2 +- .../moveit/warehouse/planning_scene_storage.h | 2 +- .../include/moveit/warehouse/state_storage.h | 2 +- .../trajectory_constraints_storage.h | 2 +- .../tools/compute_default_collisions.h | 2 +- .../tools/moveit_config_data.h | 2 +- 84 files changed, 591 insertions(+), 113 deletions(-) create mode 100644 moveit_planners/trajopt/include/trajopt_interface/problem_description.h create mode 100644 moveit_planners/trajopt/include/trajopt_interface/trajopt_interface.h create mode 100644 moveit_planners/trajopt/include/trajopt_interface/trajopt_planning_context.h diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h b/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h index c5b49c1c81..25f1fdb8bf 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h @@ -48,7 +48,7 @@ namespace collision_detection { -MOVEIT_CLASS_FORWARD(AllowedCollisionMatrix); +MOVEIT_CLASS_FORWARD(AllowedCollisionMatrix); // Defines AllowedCollisionMatrixPtr, ConstPtr, WeakPtr... etc /** \brief The types of bodies that are considered for collision */ namespace BodyTypes diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/collision_detector_allocator.h b/moveit_core/collision_detection/include/moveit/collision_detection/collision_detector_allocator.h index 01335bc465..ac01f9a34d 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/collision_detector_allocator.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/collision_detector_allocator.h @@ -43,7 +43,7 @@ namespace collision_detection { -MOVEIT_CLASS_FORWARD(CollisionDetectorAllocator); +MOVEIT_CLASS_FORWARD(CollisionDetectorAllocator); // Defines CollisionDetectorAllocatorPtr, ConstPtr, WeakPtr... etc /** \brief An allocator for a compatible CollisionWorld/CollisionRobot pair. */ class CollisionDetectorAllocator diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/collision_matrix.h b/moveit_core/collision_detection/include/moveit/collision_detection/collision_matrix.h index 20ec95acae..d9cba840c2 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/collision_matrix.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/collision_matrix.h @@ -72,7 +72,7 @@ enum Type * CONDITIONAL) */ typedef boost::function DecideContactFn; -MOVEIT_CLASS_FORWARD(AllowedCollisionMatrix); +MOVEIT_CLASS_FORWARD(AllowedCollisionMatrix); // Defines AllowedCollisionMatrixPtr, ConstPtr, WeakPtr... etc /** @class AllowedCollisionMatrix * @brief Definition of a structure for the allowed collision matrix. All elements in the collision world are referred diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/collision_plugin.h b/moveit_core/collision_detection/include/moveit/collision_detection/collision_plugin.h index 156318f4bc..9c419b31e5 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/collision_plugin.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/collision_plugin.h @@ -42,7 +42,7 @@ namespace collision_detection { -MOVEIT_CLASS_FORWARD(CollisionPlugin); +MOVEIT_CLASS_FORWARD(CollisionPlugin); // Defines CollisionPluginPtr, ConstPtr, WeakPtr... etc /** * @brief Plugin API for loading a custom collision detection robot/world. diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/collision_robot.h b/moveit_core/collision_detection/include/moveit/collision_detection/collision_robot.h index dcd1445c0d..ce49caf9ff 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/collision_robot.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/collision_robot.h @@ -45,7 +45,7 @@ namespace collision_detection { -MOVEIT_CLASS_FORWARD(CollisionRobot); +MOVEIT_CLASS_FORWARD(CollisionRobot); // Defines CollisionRobotPtr, ConstPtr, WeakPtr... etc /** @brief This class represents a collision model of the robot and can be used for self collision checks (to check if the robot is in collision with itself) or in collision checks with a different robot. Collision checks diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/world.h b/moveit_core/collision_detection/include/moveit/collision_detection/world.h index 9166a9bfb8..f940f2fe4e 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/world.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/world.h @@ -48,12 +48,12 @@ namespace shapes { -MOVEIT_CLASS_FORWARD(Shape); +MOVEIT_CLASS_FORWARD(Shape); // Defines ShapePtr, ConstPtr, WeakPtr... etc } namespace collision_detection { -MOVEIT_CLASS_FORWARD(World); +MOVEIT_CLASS_FORWARD(World); // Defines WorldPtr, ConstPtr, WeakPtr... etc /** \brief Maintain a representation of the environment */ class World diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/world_diff.h b/moveit_core/collision_detection/include/moveit/collision_detection/world_diff.h index 620a9efd6d..46587136d8 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/world_diff.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/world_diff.h @@ -42,7 +42,7 @@ namespace collision_detection { -MOVEIT_CLASS_FORWARD(WorldDiff); +MOVEIT_CLASS_FORWARD(WorldDiff); // Defines WorldDiffPtr, ConstPtr, WeakPtr... etc /** \brief Maintain a diff list of changes that have happened to a World. */ class WorldDiff diff --git a/moveit_core/collision_distance_field/include/moveit/collision_distance_field/collision_distance_field_types.h b/moveit_core/collision_distance_field/include/moveit/collision_distance_field/collision_distance_field_types.h index 7f5e957a2e..fbae8af8a7 100644 --- a/moveit_core/collision_distance_field/include/moveit/collision_distance_field/collision_distance_field_types.h +++ b/moveit_core/collision_distance_field/include/moveit/collision_distance_field/collision_distance_field_types.h @@ -106,7 +106,7 @@ struct GradientInfo }; MOVEIT_CLASS_FORWARD(PosedDistanceField) -MOVEIT_CLASS_FORWARD(BodyDecomposition); +MOVEIT_CLASS_FORWARD(BodyDecomposition); // Defines BodyDecompositionPtr, ConstPtr, WeakPtr... etc MOVEIT_CLASS_FORWARD(PosedBodySphereDecomposition) MOVEIT_CLASS_FORWARD(PosedBodyPointDecomposition) MOVEIT_CLASS_FORWARD(PosedBodySphereDecompositionVector) diff --git a/moveit_core/collision_distance_field/include/moveit/collision_distance_field/collision_robot_distance_field.h b/moveit_core/collision_distance_field/include/moveit/collision_distance_field/collision_robot_distance_field.h index 4ecc0fec48..7b292f157b 100644 --- a/moveit_core/collision_distance_field/include/moveit/collision_distance_field/collision_robot_distance_field.h +++ b/moveit_core/collision_distance_field/include/moveit/collision_distance_field/collision_robot_distance_field.h @@ -54,7 +54,7 @@ static const double DEFAULT_RESOLUTION = .02; static const double DEFAULT_COLLISION_TOLERANCE = 0.0; static const double DEFAULT_MAX_PROPOGATION_DISTANCE = .25; -MOVEIT_CLASS_FORWARD(CollisionRobotDistanceField); +MOVEIT_CLASS_FORWARD(CollisionRobotDistanceField); // Defines CollisionRobotDistanceFieldPtr, ConstPtr, WeakPtr... etc class CollisionRobotDistanceField : public CollisionRobot { diff --git a/moveit_core/constraint_samplers/include/moveit/constraint_samplers/constraint_sampler.h b/moveit_core/constraint_samplers/include/moveit/constraint_samplers/constraint_sampler.h index d41541f025..3b1ed03da2 100644 --- a/moveit_core/constraint_samplers/include/moveit/constraint_samplers/constraint_sampler.h +++ b/moveit_core/constraint_samplers/include/moveit/constraint_samplers/constraint_sampler.h @@ -51,7 +51,7 @@ */ namespace constraint_samplers { -MOVEIT_CLASS_FORWARD(ConstraintSampler); +MOVEIT_CLASS_FORWARD(ConstraintSampler); // Defines ConstraintSamplerPtr, ConstPtr, WeakPtr... etc /** * \brief ConstraintSampler is an abstract base class that allows the diff --git a/moveit_core/constraint_samplers/include/moveit/constraint_samplers/constraint_sampler_allocator.h b/moveit_core/constraint_samplers/include/moveit/constraint_samplers/constraint_sampler_allocator.h index 1f5d56ad15..65dd147eb5 100644 --- a/moveit_core/constraint_samplers/include/moveit/constraint_samplers/constraint_sampler_allocator.h +++ b/moveit_core/constraint_samplers/include/moveit/constraint_samplers/constraint_sampler_allocator.h @@ -42,7 +42,7 @@ namespace constraint_samplers { -MOVEIT_CLASS_FORWARD(ConstraintSamplerAllocator); +MOVEIT_CLASS_FORWARD(ConstraintSamplerAllocator); // Defines ConstraintSamplerAllocatorPtr, ConstPtr, WeakPtr... etc class ConstraintSamplerAllocator { diff --git a/moveit_core/constraint_samplers/include/moveit/constraint_samplers/constraint_sampler_manager.h b/moveit_core/constraint_samplers/include/moveit/constraint_samplers/constraint_sampler_manager.h index 8ebcd6a48c..69f1eb8b0e 100644 --- a/moveit_core/constraint_samplers/include/moveit/constraint_samplers/constraint_sampler_manager.h +++ b/moveit_core/constraint_samplers/include/moveit/constraint_samplers/constraint_sampler_manager.h @@ -42,7 +42,7 @@ namespace constraint_samplers { -MOVEIT_CLASS_FORWARD(ConstraintSamplerManager); +MOVEIT_CLASS_FORWARD(ConstraintSamplerManager); // Defines ConstraintSamplerManagerPtr, ConstPtr, WeakPtr... etc /** * \brief This class assists in the generation of a ConstraintSampler for a diff --git a/moveit_core/constraint_samplers/include/moveit/constraint_samplers/default_constraint_samplers.h b/moveit_core/constraint_samplers/include/moveit/constraint_samplers/default_constraint_samplers.h index e6068653e0..6d424493be 100644 --- a/moveit_core/constraint_samplers/include/moveit/constraint_samplers/default_constraint_samplers.h +++ b/moveit_core/constraint_samplers/include/moveit/constraint_samplers/default_constraint_samplers.h @@ -43,7 +43,7 @@ namespace constraint_samplers { -MOVEIT_CLASS_FORWARD(JointConstraintSampler); +MOVEIT_CLASS_FORWARD(JointConstraintSampler); // Defines JointConstraintSamplerPtr, ConstPtr, WeakPtr... etc /** * \brief JointConstraintSampler is a class that allows the sampling @@ -280,7 +280,7 @@ struct IKSamplingPose orientation_constraint_; /**< \brief Holds the orientation constraint for sampling */ }; -MOVEIT_CLASS_FORWARD(IKConstraintSampler); +MOVEIT_CLASS_FORWARD(IKConstraintSampler); // Defines IKConstraintSamplerPtr, ConstPtr, WeakPtr... etc /** * \brief A class that allows the sampling of IK constraints. diff --git a/moveit_core/controller_manager/include/moveit/controller_manager/controller_manager.h b/moveit_core/controller_manager/include/moveit/controller_manager/controller_manager.h index c5db73b02e..f25288a81b 100644 --- a/moveit_core/controller_manager/include/moveit/controller_manager/controller_manager.h +++ b/moveit_core/controller_manager/include/moveit/controller_manager/controller_manager.h @@ -99,7 +99,7 @@ struct ExecutionStatus Value status_; }; -MOVEIT_CLASS_FORWARD(MoveItControllerHandle); +MOVEIT_CLASS_FORWARD(MoveItControllerHandle); // Defines MoveItControllerHandlePtr, ConstPtr, WeakPtr... etc /** \brief MoveIt! sends commands to a controller via a handle that satisfies this interface. */ class MoveItControllerHandle @@ -147,7 +147,7 @@ class MoveItControllerHandle std::string name_; }; -MOVEIT_CLASS_FORWARD(MoveItControllerManager); +MOVEIT_CLASS_FORWARD(MoveItControllerManager); // Defines MoveItControllerManagerPtr, ConstPtr, WeakPtr... etc /** @brief MoveIt! does not enforce how controllers are implemented. To make your controllers usable by MoveIt, this interface needs to be implemented. diff --git a/moveit_core/distance_field/include/moveit/distance_field/distance_field.h b/moveit_core/distance_field/include/moveit/distance_field/distance_field.h index 569cc64015..69340a33d3 100644 --- a/moveit_core/distance_field/include/moveit/distance_field/distance_field.h +++ b/moveit_core/distance_field/include/moveit/distance_field/distance_field.h @@ -48,7 +48,7 @@ namespace shapes { -MOVEIT_CLASS_FORWARD(Shape); +MOVEIT_CLASS_FORWARD(Shape); // Defines ShapePtr, ConstPtr, WeakPtr... etc } namespace octomap { @@ -72,7 +72,7 @@ enum PlaneVisualizationType YZPlane }; -MOVEIT_CLASS_FORWARD(DistanceField); +MOVEIT_CLASS_FORWARD(DistanceField); // Defines DistanceFieldPtr, ConstPtr, WeakPtr... etc /** * \brief DistanceField is an abstract base class for computing diff --git a/moveit_core/dynamics_solver/include/moveit/dynamics_solver/dynamics_solver.h b/moveit_core/dynamics_solver/include/moveit/dynamics_solver/dynamics_solver.h index a454c99749..54bfaa2a19 100644 --- a/moveit_core/dynamics_solver/include/moveit/dynamics_solver/dynamics_solver.h +++ b/moveit_core/dynamics_solver/include/moveit/dynamics_solver/dynamics_solver.h @@ -50,7 +50,7 @@ /** \brief This namespace includes the dynamics_solver library */ namespace dynamics_solver { -MOVEIT_CLASS_FORWARD(DynamicsSolver); +MOVEIT_CLASS_FORWARD(DynamicsSolver); // Defines DynamicsSolverPtr, ConstPtr, WeakPtr... etc /** * This solver currently computes the required torques given a diff --git a/moveit_core/kinematic_constraints/include/moveit/kinematic_constraints/kinematic_constraint.h b/moveit_core/kinematic_constraints/include/moveit/kinematic_constraints/kinematic_constraint.h index a197e00c41..f227cf5fc5 100644 --- a/moveit_core/kinematic_constraints/include/moveit/kinematic_constraints/kinematic_constraint.h +++ b/moveit_core/kinematic_constraints/include/moveit/kinematic_constraints/kinematic_constraint.h @@ -72,7 +72,7 @@ struct ConstraintEvaluationResult double distance; /**< \brief The distance evaluation from the constraint or constraints */ }; -MOVEIT_CLASS_FORWARD(KinematicConstraint); +MOVEIT_CLASS_FORWARD(KinematicConstraint); // Defines KinematicConstraintPtr, ConstPtr, WeakPtr... etc /// \brief Base class for representing a kinematic constraint class KinematicConstraint @@ -179,7 +179,7 @@ class KinematicConstraint distance computed by the decide() function */ }; -MOVEIT_CLASS_FORWARD(JointConstraint); +MOVEIT_CLASS_FORWARD(JointConstraint); // Defines JointConstraintPtr, ConstPtr, WeakPtr... etc /** * \brief Class for handling single DOF joint constraints. @@ -332,7 +332,7 @@ class JointConstraint : public KinematicConstraint double joint_position_, joint_tolerance_above_, joint_tolerance_below_; /**< \brief Position and tolerance values*/ }; -MOVEIT_CLASS_FORWARD(OrientationConstraint); +MOVEIT_CLASS_FORWARD(OrientationConstraint); // Defines OrientationConstraintPtr, ConstPtr, WeakPtr... etc /** * \brief Class for constraints on the orientation of a link @@ -487,7 +487,7 @@ class OrientationConstraint : public KinematicConstraint absolute_z_axis_tolerance_; /**< \brief Storage for the tolerances */ }; -MOVEIT_CLASS_FORWARD(PositionConstraint); +MOVEIT_CLASS_FORWARD(PositionConstraint); // Defines PositionConstraintPtr, ConstPtr, WeakPtr... etc /** * \brief Class for constraints on the XYZ position of a link @@ -648,7 +648,7 @@ class PositionConstraint : public KinematicConstraint const robot_model::LinkModel* link_model_; /**< \brief The link model constraint subject */ }; -MOVEIT_CLASS_FORWARD(VisibilityConstraint); +MOVEIT_CLASS_FORWARD(VisibilityConstraint); // Defines VisibilityConstraintPtr, ConstPtr, WeakPtr... etc /** * \brief Class for constraints on the visibility relationship between @@ -848,7 +848,7 @@ class VisibilityConstraint : public KinematicConstraint double max_range_angle_; /**< \brief Storage for the max range angle */ }; -MOVEIT_CLASS_FORWARD(KinematicConstraintSet); +MOVEIT_CLASS_FORWARD(KinematicConstraintSet); // Defines KinematicConstraintSetPtr, ConstPtr, WeakPtr... etc /** * \brief A class that contains many different constraints, and can diff --git a/moveit_core/kinematics_base/include/moveit/kinematics_base/kinematics_base.h b/moveit_core/kinematics_base/include/moveit/kinematics_base/kinematics_base.h index fb8cc98f7f..6c6340fb34 100644 --- a/moveit_core/kinematics_base/include/moveit/kinematics_base/kinematics_base.h +++ b/moveit_core/kinematics_base/include/moveit/kinematics_base/kinematics_base.h @@ -136,7 +136,7 @@ struct KinematicsResult of solutions explored. */ }; -MOVEIT_CLASS_FORWARD(KinematicsBase); +MOVEIT_CLASS_FORWARD(KinematicsBase); // Defines KinematicsBasePtr, ConstPtr, WeakPtr... etc /** * @class KinematicsBase diff --git a/moveit_core/kinematics_metrics/include/moveit/kinematics_metrics/kinematics_metrics.h b/moveit_core/kinematics_metrics/include/moveit/kinematics_metrics/kinematics_metrics.h index 280099eb26..5147b10c98 100644 --- a/moveit_core/kinematics_metrics/include/moveit/kinematics_metrics/kinematics_metrics.h +++ b/moveit_core/kinematics_metrics/include/moveit/kinematics_metrics/kinematics_metrics.h @@ -42,7 +42,7 @@ /** @brief Namespace for kinematics metrics */ namespace kinematics_metrics { -MOVEIT_CLASS_FORWARD(KinematicsMetrics); +MOVEIT_CLASS_FORWARD(KinematicsMetrics); // Defines KinematicsMetricsPtr, ConstPtr, WeakPtr... etc /** * \brief Compute different kinds of metrics for kinematics evaluation. Currently includes diff --git a/moveit_core/planning_interface/include/moveit/planning_interface/planning_interface.h b/moveit_core/planning_interface/include/moveit/planning_interface/planning_interface.h index cc09b7d424..abfea8506d 100644 --- a/moveit_core/planning_interface/include/moveit/planning_interface/planning_interface.h +++ b/moveit_core/planning_interface/include/moveit/planning_interface/planning_interface.h @@ -45,7 +45,7 @@ namespace planning_scene { -MOVEIT_CLASS_FORWARD(PlanningScene); +MOVEIT_CLASS_FORWARD(PlanningScene); // Defines PlanningScenePtr, ConstPtr, WeakPtr... etc } /** \brief This namespace includes the base class for MoveIt! planners */ @@ -74,7 +74,7 @@ struct PlannerConfigurationSettings /** \brief Map from PlannerConfigurationSettings.name to PlannerConfigurationSettings */ typedef std::map PlannerConfigurationMap; -MOVEIT_CLASS_FORWARD(PlanningContext); +MOVEIT_CLASS_FORWARD(PlanningContext); // Defines PlanningContextPtr, ConstPtr, WeakPtr... etc /** \brief Representation of a particular planning context -- the planning scene and the request are known, solution is not yet computed. */ @@ -145,7 +145,7 @@ class PlanningContext MotionPlanRequest request_; }; -MOVEIT_CLASS_FORWARD(PlannerManager); +MOVEIT_CLASS_FORWARD(PlannerManager); // Defines PlannerManagerPtr, ConstPtr, WeakPtr... etc /** \brief Base class for a MoveIt! planner */ class PlannerManager diff --git a/moveit_core/planning_request_adapter/include/moveit/planning_request_adapter/planning_request_adapter.h b/moveit_core/planning_request_adapter/include/moveit/planning_request_adapter/planning_request_adapter.h index 19c95e396c..58396b4e72 100644 --- a/moveit_core/planning_request_adapter/include/moveit/planning_request_adapter/planning_request_adapter.h +++ b/moveit_core/planning_request_adapter/include/moveit/planning_request_adapter/planning_request_adapter.h @@ -45,7 +45,7 @@ /** \brief Generic interface to adapting motion planning requests */ namespace planning_request_adapter { -MOVEIT_CLASS_FORWARD(PlanningRequestAdapter); +MOVEIT_CLASS_FORWARD(PlanningRequestAdapter); // Defines PlanningRequestAdapterPtr, ConstPtr, WeakPtr... etc class PlanningRequestAdapter { diff --git a/moveit_core/planning_scene/include/moveit/planning_scene/planning_scene.h b/moveit_core/planning_scene/include/moveit/planning_scene/planning_scene.h index 8cfc019030..e7cbe83314 100644 --- a/moveit_core/planning_scene/include/moveit/planning_scene/planning_scene.h +++ b/moveit_core/planning_scene/include/moveit/planning_scene/planning_scene.h @@ -59,7 +59,7 @@ /** \brief This namespace includes the central class for representing planning contexts */ namespace planning_scene { -MOVEIT_CLASS_FORWARD(PlanningScene); +MOVEIT_CLASS_FORWARD(PlanningScene); // Defines PlanningScenePtr, ConstPtr, WeakPtr... etc /** \brief This is the function signature for additional feasibility checks to be imposed on states (in addition to respecting constraints and collision avoidance). diff --git a/moveit_core/robot_model/include/moveit/robot_model/link_model.h b/moveit_core/robot_model/include/moveit/robot_model/link_model.h index fb4ea46413..7c40c43fd3 100644 --- a/moveit_core/robot_model/include/moveit/robot_model/link_model.h +++ b/moveit_core/robot_model/include/moveit/robot_model/link_model.h @@ -47,7 +47,7 @@ namespace shapes { -MOVEIT_CLASS_FORWARD(Shape); +MOVEIT_CLASS_FORWARD(Shape); // Defines ShapePtr, ConstPtr, WeakPtr... etc } namespace moveit diff --git a/moveit_core/robot_model/include/moveit/robot_model/robot_model.h b/moveit_core/robot_model/include/moveit/robot_model/robot_model.h index 53f5c558dc..e23a91a99d 100644 --- a/moveit_core/robot_model/include/moveit/robot_model/robot_model.h +++ b/moveit_core/robot_model/include/moveit/robot_model/robot_model.h @@ -60,7 +60,7 @@ namespace moveit /** \brief Core components of MoveIt! */ namespace core { -MOVEIT_CLASS_FORWARD(RobotModel); +MOVEIT_CLASS_FORWARD(RobotModel); // Defines RobotModelPtr, ConstPtr, WeakPtr... etc /** \brief Definition of a kinematic model. This class is not thread safe, however multiple instances can be created */ diff --git a/moveit_core/robot_state/include/moveit/robot_state/robot_state.h b/moveit_core/robot_state/include/moveit/robot_state/robot_state.h index 869ceaa8ef..abb97e69fe 100644 --- a/moveit_core/robot_state/include/moveit/robot_state/robot_state.h +++ b/moveit_core/robot_state/include/moveit/robot_state/robot_state.h @@ -52,7 +52,7 @@ namespace moveit { namespace core { -MOVEIT_CLASS_FORWARD(RobotState); +MOVEIT_CLASS_FORWARD(RobotState); // Defines RobotStatePtr, ConstPtr, WeakPtr... etc /** \brief Signature for functions that can verify that if the group \e joint_group in \e robot_state is set to \e joint_group_variable_values diff --git a/moveit_core/robot_trajectory/include/moveit/robot_trajectory/robot_trajectory.h b/moveit_core/robot_trajectory/include/moveit/robot_trajectory/robot_trajectory.h index ba890a160c..6c93b91312 100644 --- a/moveit_core/robot_trajectory/include/moveit/robot_trajectory/robot_trajectory.h +++ b/moveit_core/robot_trajectory/include/moveit/robot_trajectory/robot_trajectory.h @@ -45,7 +45,7 @@ namespace robot_trajectory { -MOVEIT_CLASS_FORWARD(RobotTrajectory); +MOVEIT_CLASS_FORWARD(RobotTrajectory); // Defines RobotTrajectoryPtr, ConstPtr, WeakPtr... etc /** \brief Maintain a sequence of waypoints and the time durations between these waypoints */ diff --git a/moveit_core/sensor_manager/include/moveit/sensor_manager/sensor_manager.h b/moveit_core/sensor_manager/include/moveit/sensor_manager/sensor_manager.h index d3dca71b52..b274d374c7 100644 --- a/moveit_core/sensor_manager/include/moveit/sensor_manager/sensor_manager.h +++ b/moveit_core/sensor_manager/include/moveit/sensor_manager/sensor_manager.h @@ -71,7 +71,7 @@ struct SensorInfo double y_angle; }; -MOVEIT_CLASS_FORWARD(MoveItSensorManager); +MOVEIT_CLASS_FORWARD(MoveItSensorManager); // Defines MoveItSensorManagerPtr, ConstPtr, WeakPtr... etc class MoveItSensorManager { diff --git a/moveit_core/transforms/include/moveit/transforms/transforms.h b/moveit_core/transforms/include/moveit/transforms/transforms.h index 720e16135e..4b6cbe4e97 100644 --- a/moveit_core/transforms/include/moveit/transforms/transforms.h +++ b/moveit_core/transforms/include/moveit/transforms/transforms.h @@ -46,7 +46,7 @@ namespace moveit { namespace core { -MOVEIT_CLASS_FORWARD(Transforms); +MOVEIT_CLASS_FORWARD(Transforms); // Defines TransformsPtr, ConstPtr, WeakPtr... etc /// @brief Map frame names to the transformation matrix that can transform objects from the frame name to the planning /// frame diff --git a/moveit_planners/chomp/chomp_interface/include/chomp_interface/chomp_interface.h b/moveit_planners/chomp/chomp_interface/include/chomp_interface/chomp_interface.h index df9c952d62..7e946d0cd3 100644 --- a/moveit_planners/chomp/chomp_interface/include/chomp_interface/chomp_interface.h +++ b/moveit_planners/chomp/chomp_interface/include/chomp_interface/chomp_interface.h @@ -43,7 +43,7 @@ namespace chomp_interface { -MOVEIT_CLASS_FORWARD(CHOMPInterface); +MOVEIT_CLASS_FORWARD(CHOMPInterface); // Defines CHOMPInterfacePtr, ConstPtr, WeakPtr... etc class CHOMPInterface : public chomp::ChompPlanner { diff --git a/moveit_planners/chomp/chomp_interface/include/chomp_interface/chomp_planning_context.h b/moveit_planners/chomp/chomp_interface/include/chomp_interface/chomp_planning_context.h index 8bb25b2245..3bc74ce995 100644 --- a/moveit_planners/chomp/chomp_interface/include/chomp_interface/chomp_planning_context.h +++ b/moveit_planners/chomp/chomp_interface/include/chomp_interface/chomp_planning_context.h @@ -42,7 +42,7 @@ namespace chomp_interface { -MOVEIT_CLASS_FORWARD(CHOMPPlanningContext); +MOVEIT_CLASS_FORWARD(CHOMPPlanningContext); // Defines CHOMPPlanningContextPtr, ConstPtr, WeakPtr... etc class CHOMPPlanningContext : public planning_interface::PlanningContext { diff --git a/moveit_planners/ompl/ompl_interface/cfg/cpp/ompl_interface_ros/OMPLDynamicReconfigureConfig.h b/moveit_planners/ompl/ompl_interface/cfg/cpp/ompl_interface_ros/OMPLDynamicReconfigureConfig.h index 36a70b0c49..7c00769870 100644 --- a/moveit_planners/ompl/ompl_interface/cfg/cpp/ompl_interface_ros/OMPLDynamicReconfigureConfig.h +++ b/moveit_planners/ompl/ompl_interface/cfg/cpp/ompl_interface_ros/OMPLDynamicReconfigureConfig.h @@ -63,7 +63,7 @@ class OMPLDynamicReconfigureConfigStatics; class OMPLDynamicReconfigureConfig { public: - MOVEIT_CLASS_FORWARD(AbstractParamDescription); + MOVEIT_CLASS_FORWARD(AbstractParamDescription); // Defines AbstractParamDescriptionPtr, ConstPtr, WeakPtr... etc class AbstractParamDescription : public dynamic_reconfigure::ParamDescription { public: @@ -142,7 +142,7 @@ class OMPLDynamicReconfigureConfig } }; - MOVEIT_CLASS_FORWARD(AbstractGroupDescription); + MOVEIT_CLASS_FORWARD(AbstractGroupDescription); // Defines AbstractGroupDescriptionPtr, ConstPtr, WeakPtr... etc class AbstractGroupDescription : public dynamic_reconfigure::Group { public: diff --git a/moveit_planners/ompl/ompl_interface/include/moveit/ompl_interface/constraints_library.h b/moveit_planners/ompl/ompl_interface/include/moveit/ompl_interface/constraints_library.h index ed8ddb10e8..c81112a7e5 100644 --- a/moveit_planners/ompl/ompl_interface/include/moveit/ompl_interface/constraints_library.h +++ b/moveit_planners/ompl/ompl_interface/include/moveit/ompl_interface/constraints_library.h @@ -156,7 +156,7 @@ struct ConstraintApproximationConstructionResults double sampling_success_rate; }; -MOVEIT_CLASS_FORWARD(ConstraintsLibrary); +MOVEIT_CLASS_FORWARD(ConstraintsLibrary); // Defines ConstraintsLibraryPtr, ConstPtr, WeakPtr... etc class ConstraintsLibrary { diff --git a/moveit_planners/ompl/ompl_interface/include/moveit/ompl_interface/detail/constrained_valid_state_sampler.h b/moveit_planners/ompl/ompl_interface/include/moveit/ompl_interface/detail/constrained_valid_state_sampler.h index 49f93dbdb0..e0ba6670f1 100644 --- a/moveit_planners/ompl/ompl_interface/include/moveit/ompl_interface/detail/constrained_valid_state_sampler.h +++ b/moveit_planners/ompl/ompl_interface/include/moveit/ompl_interface/detail/constrained_valid_state_sampler.h @@ -46,7 +46,7 @@ namespace ompl_interface { class ModelBasedPlanningContext; -MOVEIT_CLASS_FORWARD(ValidStateSampler); +MOVEIT_CLASS_FORWARD(ValidStateSampler); // Defines ValidStateSamplerPtr, ConstPtr, WeakPtr... etc /** @class ValidConstrainedSampler * This class defines a sampler that tries to find a valid sample that satisfies the specified constraints */ diff --git a/moveit_planners/ompl/ompl_interface/include/moveit/ompl_interface/model_based_planning_context.h b/moveit_planners/ompl/ompl_interface/include/moveit/ompl_interface/model_based_planning_context.h index 083d91f203..9efe70a841 100644 --- a/moveit_planners/ompl/ompl_interface/include/moveit/ompl_interface/model_based_planning_context.h +++ b/moveit_planners/ompl/ompl_interface/include/moveit/ompl_interface/model_based_planning_context.h @@ -53,8 +53,8 @@ namespace ob = ompl::base; namespace og = ompl::geometric; namespace ot = ompl::tools; -MOVEIT_CLASS_FORWARD(ModelBasedPlanningContext); -MOVEIT_CLASS_FORWARD(ConstraintsLibrary); +MOVEIT_CLASS_FORWARD(ModelBasedPlanningContext); // Defines ModelBasedPlanningContextPtr, ConstPtr, WeakPtr... etc +MOVEIT_CLASS_FORWARD(ConstraintsLibrary); // Defines ConstraintsLibraryPtr, ConstPtr, WeakPtr... etc struct ModelBasedPlanningContextSpecification; typedef std::function +#include +#include + +#include +#include + +#include + +namespace trajopt_interface +{ +/** +@brief Used to apply cost/constraint to joint-space velocity + +Term is applied to every step between first_step and last_step. It applies two limits, upper_limits/lower_limits, +to the joint velocity subject to the following cases. + +* term_type = TT_COST +** upper_limit = lower_limit = 0 - Cost is applied with a SQUARED error scaled for each joint by coeffs +** upper_limit != lower_limit - 2 hinge costs are applied scaled for each joint by coeffs. If velocity < upper_limit and +velocity > lower_limit, no penalty. + +* term_type = TT_CNT +** upper_limit = lower_limit = 0 - Equality constraint is applied +** upper_limit != lower_limit - 2 Inequality constraints are applied. These are both satisfied when velocity < +upper_limit and velocity > lower_limit + +Note: coeffs, upper_limits, and lower_limits are optional. If a term is not given it will default to 0 for all joints. +If one value is given, this will be broadcast to all joints. + +Note: Velocity is calculated numerically using forward finite difference + +\f{align*}{ + cost = \sum_{t=0}^{T-2} \sum_j c_j (x_{t+1,j} - x_{t,j})^2 +\f} +where j indexes over DOF, and \f$c_j\f$ are the coeffs. +*/ + +struct TermInfo; +MOVEIT_CLASS_FORWARD(TermInfo); // Defines TermInfoPtr, ConstPtr, WeakPtr... etc + +class TrajOptProblem; +MOVEIT_CLASS_FORWARD(TrajOptProblem); // Defines TrajOptProblemPtr, ConstPtr, WeakPtr... etc + +struct JointPoseTermInfo; +MOVEIT_CLASS_FORWARD(JointPoseTermInfo); // Defines JointPoseTermInfoPtr, ConstPtr, WeakPtr... etc + +struct CartPoseTermInfo; +MOVEIT_CLASS_FORWARD(CartPoseTermInfo); // Defines CartPoseTermInfoPtr, ConstPtr, WeakPtr... etc + +struct JointVelTermInfo; +MOVEIT_CLASS_FORWARD(JointVelTermInfo); // Defines JointVelTermInfoPtr, ConstPtr, WeakPtr... etc + +struct ProblemInfo; +TrajOptProblemPtr ConstructProblem(const ProblemInfo&); + +enum TermType +{ + TT_COST = 0x1, // 0000 0001 + TT_CNT = 0x2, // 0000 0010 + TT_USE_TIME = 0x4, // 0000 0100 +}; + +struct BasicInfo +{ + /** @brief If true, first time step is fixed with a joint level constraint + If this is false, the starting point of the trajectory will + not be the current position of the robot. The use case example is: if we are trying to execute a process like + sanding the critical part which is the actual process path not how we get to the start of the process path. So we + plan the + process path first leaving the start free to hopefully get the most optimal and then we plan from the current + location with + start fixed to the start of the process path. It depends on what we want the default behavior to be + */ + bool start_fixed; + /** @brief Number of time steps (rows) in the optimization matrix */ + int n_steps; + sco::IntVec dofs_fixed; // optional + sco::ModelType convex_solver; // which convex solver to use + + /** @brief If true, the last column in the optimization matrix will be 1/dt */ + bool use_time = false; + /** @brief The upper limit of 1/dt values allowed in the optimization*/ + double dt_upper_lim = 1.0; + /** @brief The lower limit of 1/dt values allowed in the optimization*/ + double dt_lower_lim = 1.0; +}; + +/** +Initialization info read from json +*/ +struct InitInfo +{ + /** @brief Methods of initializing the optimization matrix. This defines how robot moves from the current + state to the start state + + STATIONARY: Initializes all joint values to the initial value (the current value in the env) + JOINT_INTERPOLATED: Linearly interpolates between initial value and the joint position specified in InitInfo.data + GIVEN_TRAJ: Initializes the matrix to a given trajectory + + In all cases the dt column (if present) is appended the selected method is defined. + */ + enum Type + { + STATIONARY, + JOINT_INTERPOLATED, + GIVEN_TRAJ, + }; + /** @brief Specifies the type of initialization to use */ + Type type; + /** @brief Data used during initialization. Use depends on the initialization selected. This data will be used + to create initialization matrix. We need to give the goal information to this init info + */ + trajopt::TrajArray data; + // Eigen::VectorXd data_vec; + // trajopt::TrajArray data_trajectory; + /** @brief Default value the final column of the optimization is initialized too if time is being used */ + double dt = 1.0; +}; + +/** +When cost or constraint element of JSON doc is read, one of these guys gets +constructed to hold the parameters. +Then it later gets converted to a Cost object by the addObjectiveTerms method +*/ +struct TermInfo +{ + std::string name; + int term_type; + int getSupportedTypes() + { + return supported_term_types_; + } + // virtual void fromJson(ProblemConstructionInfo& pci, const Json::Value& v) = 0; + virtual void addObjectiveTerms(TrajOptProblem& prob) = 0; + + static TermInfoPtr fromName(const std::string& type); + + /** + * Registers a user-defined TermInfo so you can use your own cost + * see function RegisterMakers.cpp + */ + using MakerFunc = TermInfoPtr (*)(void); + static void RegisterMaker(const std::string& type, MakerFunc); + + virtual ~TermInfo() = default; + +protected: + TermInfo(int supported_term_types) : supported_term_types_(supported_term_types) + { + } + +private: + static std::map name_to_maker_; + int supported_term_types_; +}; + +struct ProblemInfo +{ +public: + BasicInfo basic_info; + sco::BasicTrustRegionSQPParameters opt_info; + std::vector cost_infos; + std::vector cnt_infos; + InitInfo init_info; + + planning_scene::PlanningSceneConstPtr planning_scene; + std::string planning_group_name; + + ProblemInfo(planning_scene::PlanningSceneConstPtr ps, const std::string& pg) + : planning_scene(ps), planning_group_name(pg) + { + } +}; + +/** + * Holds all the data for a trajectory optimization problem + * so you can modify it programmatically, e.g. add your own costs + */ +class TrajOptProblem : public sco::OptProb +{ +public: + TrajOptProblem(); + TrajOptProblem(const ProblemInfo& problem_info); + virtual ~TrajOptProblem() = default; + /** @brief Returns the values of the specified joints (start_col to num_col) for the specified timestep i.*/ + sco::VarVector GetVarRow(int i, int start_col, int num_col) + { + return matrix_traj_vars.rblock(i, start_col, num_col); + } + /** @brief Returns the values of all joints for the specified timestep i.*/ + sco::VarVector GetVarRow(int i) + { + return matrix_traj_vars.row(i); + } + /** @brief Returns the value of the specified joint j for the specified timestep i.*/ + sco::Var& GetVar(int i, int j) + { + return matrix_traj_vars.at(i, j); + } + trajopt::VarArray& GetVars() + { + return matrix_traj_vars; + } + /** @brief Returns the number of steps in the problem. This is the number of rows in the optimization matrix.*/ + int GetNumSteps() + { + return matrix_traj_vars.rows(); + } + /** @brief Returns the problem DOF. This is the number of columns in the optization matrix. + * Note that this is not necessarily the same as the kinematic DOF.*/ + int GetNumDOF() + { + return matrix_traj_vars.cols(); + } + /** @brief Returns the kinematic DOF of the active joint model group + */ + int GetActiveGroupNumDOF() + { + return dof_; + } + planning_scene::PlanningSceneConstPtr GetPlanningScene() + { + return planning_scene_; + } + void SetInitTraj(const trajopt::TrajArray& x) + { + matrix_init_traj = x; + } + trajopt::TrajArray GetInitTraj() + { + return matrix_init_traj; + } + // friend TrajOptProbPtr ConstructProblem(const ProblemConstructionInfo&); + /** @brief Returns TrajOptProb.has_time */ + bool GetHasTime() + { + return has_time; + } + /** @brief Sets TrajOptProb.has_time */ + void SetHasTime(bool tmp) + { + has_time = tmp; + } + +private: + /** @brief If true, the last column in the optimization matrix will be 1/dt */ + bool has_time; + /** @brief is the matrix holding the joint values of the trajectory for all timesteps */ + trajopt::VarArray matrix_traj_vars; + planning_scene::PlanningSceneConstPtr planning_scene_; + std::string planning_group_; + /** @brief Kinematic DOF of the active joint model group */ + int dof_; + trajopt::TrajArray matrix_init_traj; +}; + +/** @brief This term is used when the goal frame is fixed in cartesian space + + Set term_type == TT_COST or TT_CNT for cost or constraint. +*/ +struct CartPoseTermInfo : public TermInfo +{ + // EIGEN_MAKE_ALIGNED_OPERATOR_NEW + + /** @brief Timestep at which to apply term */ + int timestep; + /** @brief Cartesian position */ + Eigen::Vector3d xyz; + /** @brief Rotation quaternion */ + Eigen::Vector4d wxyz; + /** @brief coefficients for position and rotation */ + Eigen::Vector3d pos_coeffs, rot_coeffs; + /** @brief Link which should reach desired pose */ + std::string link; + /** @brief Static transform applied to the link */ + Eigen::Isometry3d tcp; + + CartPoseTermInfo(); + + /** @brief Used to add term to pci from json */ + // void fromJson(ProblemConstructionInfo& pci, const Json::Value& v) override; + /** @brief Converts term info into cost/constraint and adds it to trajopt problem */ + void addObjectiveTerms(TrajOptProblem& prob) override; + + static TermInfoPtr create() + { + TermInfoPtr out(new CartPoseTermInfo()); + return out; + } +}; + +/** + \brief Joint space position cost + Position operates on a single point (unlike velocity, etc). This is b/c the primary usecase is joint-space + position waypoints + + \f{align*}{ + \sum_i c_i (x_i - xtarg_i)^2 + \f} + where \f$i\f$ indexes over dof and \f$c_i\f$ are coeffs + */ +struct JointPoseTermInfo : public TermInfo +{ + /** @brief Vector of coefficients that scale the cost. Size should be the DOF of the system. Default: vector of 0's*/ + trajopt::DblVec coeffs; + /** @brief Vector of position targets. This is a required value. Size should be the DOF of the system */ + trajopt::DblVec targets; + /** @brief Vector of position upper limits. Size should be the DOF of the system. Default: vector of 0's*/ + trajopt::DblVec upper_tols; + /** @brief Vector of position lower limits. Size should be the DOF of the system. Default: vector of 0's*/ + trajopt::DblVec lower_tols; + /** @brief First time step to which the term is applied. Default: 0 */ + int first_step = 0; + /** @brief Last time step to which the term is applied. Default: prob.GetNumSteps() - 1*/ + int last_step = -1; + + /** @brief Initialize term with it's supported types */ + JointPoseTermInfo() : TermInfo(TT_COST | TT_CNT | TT_USE_TIME) + { + } + + /** @brief Converts term info into cost/constraint and adds it to trajopt problem */ + void addObjectiveTerms(TrajOptProblem& prob) override; + + static TermInfoPtr create() + { + TermInfoPtr out(new JointPoseTermInfo()); + return out; + } +}; + +struct JointVelTermInfo : public TermInfo +{ + /** @brief Vector of coefficients that scale the cost. Size should be the DOF of the system. Default: vector of 0's*/ + trajopt::DblVec coeffs; + /** @brief Vector of velocity targets. This is a required value. Size should be the DOF of the system */ + trajopt::DblVec targets; + /** @brief Vector of velocity upper limits. Size should be the DOF of the system. Default: vector of 0's*/ + trajopt::DblVec upper_tols; + /** @brief Vector of velocity lower limits. Size should be the DOF of the system. Default: vector of 0's*/ + trajopt::DblVec lower_tols; + /** @brief First time step to which the term is applied. Default: 0*/ + int first_step = 0; + /** @brief Last time step to which the term is applied. Default: prob.GetNumSteps() - 1*/ + int last_step = -1; + + /** @brief Initialize term with it's supported types */ + JointVelTermInfo() : TermInfo(TT_COST | TT_CNT | TT_USE_TIME) + { + } + + /** @brief Converts term info into cost/constraint and adds it to trajopt problem */ + void addObjectiveTerms(TrajOptProblem& prob) override; + + static TermInfoPtr create() + { + TermInfoPtr out(new JointVelTermInfo()); + return out; + } +}; + +void generateInitialTrajectory(const ProblemInfo& pci, const std::vector& current_joint_values, + trajopt::TrajArray& init_traj); + +} // namespace trajopt_interface diff --git a/moveit_planners/trajopt/include/trajopt_interface/trajopt_interface.h b/moveit_planners/trajopt/include/trajopt_interface/trajopt_interface.h new file mode 100644 index 0000000000..bb48692b88 --- /dev/null +++ b/moveit_planners/trajopt/include/trajopt_interface/trajopt_interface.h @@ -0,0 +1,77 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019, PickNik, LLC. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of PickNik 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: Omid Heidari */ +#pragma once + +#include +#include +#include +#include "problem_description.h" + +namespace trajopt_interface +{ +MOVEIT_CLASS_FORWARD(TrajOptInterface); // Defines TrajOptInterfacePtr, ConstPtr, WeakPtr... etc + +class TrajOptInterface +{ +public: + TrajOptInterface(const ros::NodeHandle& nh = ros::NodeHandle("~")); + + const sco::BasicTrustRegionSQPParameters& getParams() const + { + return params_; + } + + bool solve(const planning_scene::PlanningSceneConstPtr& planning_scene, + const planning_interface::MotionPlanRequest& req, moveit_msgs::MotionPlanDetailedResponse& res); + +protected: + /** @brief Configure everything using the param server */ + void setTrajOptParams(sco::BasicTrustRegionSQPParameters& param); + void setDefaultTrajOPtParams(); + void setProblemInfoParam(ProblemInfo& problem_info); + void setJointPoseTermInfoParams(JointPoseTermInfoPtr& jp, std::string name); + trajopt::DblVec extractStartJointValues(const planning_interface::MotionPlanRequest& req, + const std::vector& group_joint_names); + + ros::NodeHandle nh_; /// The ROS node handle + sco::BasicTrustRegionSQPParameters params_; + std::vector optimizer_callbacks_; + TrajOptProblemPtr trajopt_problem_; + std::string name_; +}; + +void callBackFunc(sco::OptProb* opt_prob, sco::OptResults& opt_res); +} // namespace trajopt_interface diff --git a/moveit_planners/trajopt/include/trajopt_interface/trajopt_planning_context.h b/moveit_planners/trajopt/include/trajopt_interface/trajopt_planning_context.h new file mode 100644 index 0000000000..9c06eb0f5e --- /dev/null +++ b/moveit_planners/trajopt/include/trajopt_interface/trajopt_planning_context.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include +#include + +namespace trajopt_interface +{ +MOVEIT_CLASS_FORWARD(TrajOptPlanningContext); // Defines TrajOptPlanningContextPtr, ConstPtr, WeakPtr... etc + +class TrajOptPlanningContext : public planning_interface::PlanningContext +{ +public: + TrajOptPlanningContext(const std::string& name, const std::string& group, + const moveit::core::RobotModelConstPtr& model); + ~TrajOptPlanningContext() override + { + } + + bool solve(planning_interface::MotionPlanResponse& res) override; + bool solve(planning_interface::MotionPlanDetailedResponse& res) override; + + bool terminate() override; + void clear() override; + +private: + moveit::core::RobotModelConstPtr robot_model_; + + TrajOptInterfacePtr trajopt_interface_; +}; +} // namespace trajopt_interface diff --git a/moveit_plugins/moveit_fake_controller_manager/src/moveit_fake_controllers.h b/moveit_plugins/moveit_fake_controller_manager/src/moveit_fake_controllers.h index f33ed0656a..818696fc00 100644 --- a/moveit_plugins/moveit_fake_controller_manager/src/moveit_fake_controllers.h +++ b/moveit_plugins/moveit_fake_controller_manager/src/moveit_fake_controllers.h @@ -46,7 +46,7 @@ namespace moveit_fake_controller_manager { -MOVEIT_CLASS_FORWARD(BaseFakeController); +MOVEIT_CLASS_FORWARD(BaseFakeController); // Defines BaseFakeControllerPtr, ConstPtr, WeakPtr... etc // common base class to all fake controllers in this package class BaseFakeController : public moveit_controller_manager::MoveItControllerHandle diff --git a/moveit_plugins/moveit_ros_control_interface/include/moveit_ros_control_interface/ControllerHandle.h b/moveit_plugins/moveit_ros_control_interface/include/moveit_ros_control_interface/ControllerHandle.h index c9527dfacd..55358202f9 100644 --- a/moveit_plugins/moveit_ros_control_interface/include/moveit_ros_control_interface/ControllerHandle.h +++ b/moveit_plugins/moveit_ros_control_interface/include/moveit_ros_control_interface/ControllerHandle.h @@ -42,7 +42,7 @@ namespace moveit_ros_control_interface { -MOVEIT_CLASS_FORWARD(ControllerHandleAllocator); +MOVEIT_CLASS_FORWARD(ControllerHandleAllocator); // Defines ControllerHandleAllocatorPtr, ConstPtr, WeakPtr... etc /** * Base class for MoveItControllerHandle allocators diff --git a/moveit_plugins/moveit_ros_control_interface/src/controller_manager_plugin.cpp b/moveit_plugins/moveit_ros_control_interface/src/controller_manager_plugin.cpp index c8d6e02c2b..e81065be2c 100644 --- a/moveit_plugins/moveit_ros_control_interface/src/controller_manager_plugin.cpp +++ b/moveit_plugins/moveit_ros_control_interface/src/controller_manager_plugin.cpp @@ -73,7 +73,7 @@ bool checkTimeout(ros::Time& t, double timeout, bool force = false) return false; } -MOVEIT_CLASS_FORWARD(MoveItControllerManager); +MOVEIT_CLASS_FORWARD(MoveItControllerManager); // Defines MoveItControllerManagerPtr, ConstPtr, WeakPtr... etc /** * \brief moveit_controller_manager::MoveItControllerManager sub class that interfaces one ros_control diff --git a/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/action_based_controller_handle.h b/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/action_based_controller_handle.h index 4a788556d5..3225538d79 100644 --- a/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/action_based_controller_handle.h +++ b/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/action_based_controller_handle.h @@ -62,7 +62,8 @@ class ActionBasedControllerHandleBase : public moveit_controller_manager::MoveIt } }; -MOVEIT_CLASS_FORWARD(ActionBasedControllerHandleBase); +MOVEIT_CLASS_FORWARD( + ActionBasedControllerHandleBase); // Defines ActionBasedControllerHandleBasePtr, ConstPtr, WeakPtr... etc /* * This is a simple base class, which handles all of the action creation/etc diff --git a/moveit_ros/manipulation/pick_place/include/moveit/pick_place/manipulation_stage.h b/moveit_ros/manipulation/pick_place/include/moveit/pick_place/manipulation_stage.h index a68e9ed523..19556386e4 100644 --- a/moveit_ros/manipulation/pick_place/include/moveit/pick_place/manipulation_stage.h +++ b/moveit_ros/manipulation/pick_place/include/moveit/pick_place/manipulation_stage.h @@ -43,7 +43,7 @@ namespace pick_place { -MOVEIT_CLASS_FORWARD(ManipulationStage); +MOVEIT_CLASS_FORWARD(ManipulationStage); // Defines ManipulationStagePtr, ConstPtr, WeakPtr... etc class ManipulationStage { diff --git a/moveit_ros/manipulation/pick_place/include/moveit/pick_place/pick_place.h b/moveit_ros/manipulation/pick_place/include/moveit/pick_place/pick_place.h index 7c9af7a3d2..3b53bcd290 100644 --- a/moveit_ros/manipulation/pick_place/include/moveit/pick_place/pick_place.h +++ b/moveit_ros/manipulation/pick_place/include/moveit/pick_place/pick_place.h @@ -49,7 +49,7 @@ namespace pick_place { -MOVEIT_CLASS_FORWARD(PickPlace); +MOVEIT_CLASS_FORWARD(PickPlace); // Defines PickPlacePtr, ConstPtr, WeakPtr... etc class PickPlacePlanBase { @@ -93,7 +93,7 @@ class PickPlacePlanBase moveit_msgs::MoveItErrorCodes error_code_; }; -MOVEIT_CLASS_FORWARD(PickPlan); +MOVEIT_CLASS_FORWARD(PickPlan); // Defines PickPlanPtr, ConstPtr, WeakPtr... etc class PickPlan : public PickPlacePlanBase { @@ -102,7 +102,7 @@ class PickPlan : public PickPlacePlanBase bool plan(const planning_scene::PlanningSceneConstPtr& planning_scene, const moveit_msgs::PickupGoal& goal); }; -MOVEIT_CLASS_FORWARD(PlacePlan); +MOVEIT_CLASS_FORWARD(PlacePlan); // Defines PlacePlanPtr, ConstPtr, WeakPtr... etc class PlacePlan : public PickPlacePlanBase { diff --git a/moveit_ros/move_group/include/moveit/move_group/move_group_capability.h b/moveit_ros/move_group/include/moveit/move_group/move_group_capability.h index 26d9c645ef..f46558a14b 100644 --- a/moveit_ros/move_group/include/moveit/move_group/move_group_capability.h +++ b/moveit_ros/move_group/include/moveit/move_group/move_group_capability.h @@ -53,7 +53,7 @@ enum MoveGroupState LOOK }; -MOVEIT_CLASS_FORWARD(MoveGroupCapability); +MOVEIT_CLASS_FORWARD(MoveGroupCapability); // Defines MoveGroupCapabilityPtr, ConstPtr, WeakPtr... etc class MoveGroupCapability { diff --git a/moveit_ros/move_group/include/moveit/move_group/move_group_context.h b/moveit_ros/move_group/include/moveit/move_group/move_group_context.h index 8ba3150481..4ba3a33d1e 100644 --- a/moveit_ros/move_group/include/moveit/move_group/move_group_context.h +++ b/moveit_ros/move_group/include/moveit/move_group/move_group_context.h @@ -41,23 +41,23 @@ namespace planning_scene_monitor { -MOVEIT_CLASS_FORWARD(PlanningSceneMonitor); +MOVEIT_CLASS_FORWARD(PlanningSceneMonitor); // Defines PlanningSceneMonitorPtr, ConstPtr, WeakPtr... etc } namespace planning_pipeline { -MOVEIT_CLASS_FORWARD(PlanningPipeline); +MOVEIT_CLASS_FORWARD(PlanningPipeline); // Defines PlanningPipelinePtr, ConstPtr, WeakPtr... etc } namespace plan_execution { -MOVEIT_CLASS_FORWARD(PlanExecution); -MOVEIT_CLASS_FORWARD(PlanWithSensing); +MOVEIT_CLASS_FORWARD(PlanExecution); // Defines PlanExecutionPtr, ConstPtr, WeakPtr... etc +MOVEIT_CLASS_FORWARD(PlanWithSensing); // Defines PlanWithSensingPtr, ConstPtr, WeakPtr... etc } // namespace plan_execution namespace trajectory_execution_manager { -MOVEIT_CLASS_FORWARD(TrajectoryExecutionManager); +MOVEIT_CLASS_FORWARD(TrajectoryExecutionManager); // Defines TrajectoryExecutionManagerPtr, ConstPtr, WeakPtr... etc } namespace move_group diff --git a/moveit_ros/occupancy_map_monitor/include/moveit/occupancy_map_monitor/occupancy_map_updater.h b/moveit_ros/occupancy_map_monitor/include/moveit/occupancy_map_monitor/occupancy_map_updater.h index a0c5410563..17748b4a13 100644 --- a/moveit_ros/occupancy_map_monitor/include/moveit/occupancy_map_monitor/occupancy_map_updater.h +++ b/moveit_ros/occupancy_map_monitor/include/moveit/occupancy_map_monitor/occupancy_map_updater.h @@ -54,7 +54,7 @@ typedef boost::function groups_; diff --git a/moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_execution.h b/moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_execution.h index 9ba9db39c3..0eb02648fa 100644 --- a/moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_execution.h +++ b/moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_execution.h @@ -48,7 +48,7 @@ /** \brief This namespace includes functionality specific to the execution and monitoring of motion plans */ namespace plan_execution { -MOVEIT_CLASS_FORWARD(PlanExecution); +MOVEIT_CLASS_FORWARD(PlanExecution); // Defines PlanExecutionPtr, ConstPtr, WeakPtr... etc class PlanExecution { diff --git a/moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_with_sensing.h b/moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_with_sensing.h index cba80504d6..5400495367 100644 --- a/moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_with_sensing.h +++ b/moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_with_sensing.h @@ -49,7 +49,7 @@ namespace plan_execution { -MOVEIT_CLASS_FORWARD(PlanWithSensing); +MOVEIT_CLASS_FORWARD(PlanWithSensing); // Defines PlanWithSensingPtr, ConstPtr, WeakPtr... etc class PlanWithSensing { diff --git a/moveit_ros/planning/planning_pipeline/include/moveit/planning_pipeline/planning_pipeline.h b/moveit_ros/planning/planning_pipeline/include/moveit/planning_pipeline/planning_pipeline.h index 282cb6c33b..138abb7b87 100644 --- a/moveit_ros/planning/planning_pipeline/include/moveit/planning_pipeline/planning_pipeline.h +++ b/moveit_ros/planning/planning_pipeline/include/moveit/planning_pipeline/planning_pipeline.h @@ -195,7 +195,7 @@ class PlanningPipeline ros::Publisher contacts_publisher_; }; -MOVEIT_CLASS_FORWARD(PlanningPipeline); +MOVEIT_CLASS_FORWARD(PlanningPipeline); // Defines PlanningPipelinePtr, ConstPtr, WeakPtr... etc } // namespace planning_pipeline #endif diff --git a/moveit_ros/planning/planning_scene_monitor/include/moveit/planning_scene_monitor/current_state_monitor.h b/moveit_ros/planning/planning_scene_monitor/include/moveit/planning_scene_monitor/current_state_monitor.h index 306e67055b..ef484ced56 100644 --- a/moveit_ros/planning/planning_scene_monitor/include/moveit/planning_scene_monitor/current_state_monitor.h +++ b/moveit_ros/planning/planning_scene_monitor/include/moveit/planning_scene_monitor/current_state_monitor.h @@ -211,7 +211,7 @@ class CurrentStateMonitor std::shared_ptr tf_connection_; }; -MOVEIT_CLASS_FORWARD(CurrentStateMonitor); +MOVEIT_CLASS_FORWARD(CurrentStateMonitor); // Defines CurrentStateMonitorPtr, ConstPtr, WeakPtr... etc } // namespace planning_scene_monitor #endif diff --git a/moveit_ros/planning/planning_scene_monitor/include/moveit/planning_scene_monitor/planning_scene_monitor.h b/moveit_ros/planning/planning_scene_monitor/include/moveit/planning_scene_monitor/planning_scene_monitor.h index f2fc78a5c2..d84f80823b 100644 --- a/moveit_ros/planning/planning_scene_monitor/include/moveit/planning_scene_monitor/planning_scene_monitor.h +++ b/moveit_ros/planning/planning_scene_monitor/include/moveit/planning_scene_monitor/planning_scene_monitor.h @@ -54,7 +54,7 @@ namespace planning_scene_monitor { -MOVEIT_CLASS_FORWARD(PlanningSceneMonitor); +MOVEIT_CLASS_FORWARD(PlanningSceneMonitor); // Defines PlanningSceneMonitorPtr, ConstPtr, WeakPtr... etc /** * @brief PlanningSceneMonitor diff --git a/moveit_ros/planning/planning_scene_monitor/include/moveit/planning_scene_monitor/trajectory_monitor.h b/moveit_ros/planning/planning_scene_monitor/include/moveit/planning_scene_monitor/trajectory_monitor.h index be9997432d..51823c6d00 100644 --- a/moveit_ros/planning/planning_scene_monitor/include/moveit/planning_scene_monitor/trajectory_monitor.h +++ b/moveit_ros/planning/planning_scene_monitor/include/moveit/planning_scene_monitor/trajectory_monitor.h @@ -48,7 +48,7 @@ namespace planning_scene_monitor typedef boost::function TrajectoryStateAddedCallback; -MOVEIT_CLASS_FORWARD(TrajectoryMonitor); +MOVEIT_CLASS_FORWARD(TrajectoryMonitor); // Defines TrajectoryMonitorPtr, ConstPtr, WeakPtr... etc /** @class TrajectoryMonitor @brief Monitors the joint_states topic and tf to record the trajectory of the robot. */ diff --git a/moveit_ros/planning/rdf_loader/include/moveit/rdf_loader/rdf_loader.h b/moveit_ros/planning/rdf_loader/include/moveit/rdf_loader/rdf_loader.h index 85c12e1d49..67573fe67a 100644 --- a/moveit_ros/planning/rdf_loader/include/moveit/rdf_loader/rdf_loader.h +++ b/moveit_ros/planning/rdf_loader/include/moveit/rdf_loader/rdf_loader.h @@ -43,7 +43,7 @@ namespace rdf_loader { -MOVEIT_CLASS_FORWARD(RDFLoader); +MOVEIT_CLASS_FORWARD(RDFLoader); // Defines RDFLoaderPtr, ConstPtr, WeakPtr... etc /** @class RDFLoader * @brief Default constructor diff --git a/moveit_ros/planning/robot_model_loader/include/moveit/robot_model_loader/robot_model_loader.h b/moveit_ros/planning/robot_model_loader/include/moveit/robot_model_loader/robot_model_loader.h index bf4aa2c973..e2d6aa75c7 100644 --- a/moveit_ros/planning/robot_model_loader/include/moveit/robot_model_loader/robot_model_loader.h +++ b/moveit_ros/planning/robot_model_loader/include/moveit/robot_model_loader/robot_model_loader.h @@ -44,7 +44,7 @@ namespace robot_model_loader { -MOVEIT_CLASS_FORWARD(RobotModelLoader); +MOVEIT_CLASS_FORWARD(RobotModelLoader); // Defines RobotModelLoaderPtr, ConstPtr, WeakPtr... etc /** @class RobotModelLoader */ class RobotModelLoader diff --git a/moveit_ros/planning/trajectory_execution_manager/include/moveit/trajectory_execution_manager/trajectory_execution_manager.h b/moveit_ros/planning/trajectory_execution_manager/include/moveit/trajectory_execution_manager/trajectory_execution_manager.h index 7d94940b36..c4bfeab3f6 100644 --- a/moveit_ros/planning/trajectory_execution_manager/include/moveit/trajectory_execution_manager/trajectory_execution_manager.h +++ b/moveit_ros/planning/trajectory_execution_manager/include/moveit/trajectory_execution_manager/trajectory_execution_manager.h @@ -52,7 +52,7 @@ namespace trajectory_execution_manager { -MOVEIT_CLASS_FORWARD(TrajectoryExecutionManager); +MOVEIT_CLASS_FORWARD(TrajectoryExecutionManager); // Defines TrajectoryExecutionManagerPtr, ConstPtr, WeakPtr... etc // Two modes: // Managed controllers diff --git a/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h b/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h index 7fca23fb17..c9632dfd86 100644 --- a/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h +++ b/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h @@ -89,7 +89,7 @@ class MoveItErrorCode : public moveit_msgs::MoveItErrorCodes } }; -MOVEIT_CLASS_FORWARD(MoveGroupInterface); +MOVEIT_CLASS_FORWARD(MoveGroupInterface); // Defines MoveGroupInterfacePtr, ConstPtr, WeakPtr... etc /** \class MoveGroupInterface move_group_interface.h moveit/planning_interface/move_group_interface.h diff --git a/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/moveit_cpp.h b/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/moveit_cpp.h index affeceb1a7..eb3d5e6296 100644 --- a/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/moveit_cpp.h +++ b/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/moveit_cpp.h @@ -50,7 +50,7 @@ namespace moveit { namespace planning_interface { -MOVEIT_CLASS_FORWARD(MoveItCpp); +MOVEIT_CLASS_FORWARD(MoveItCpp); // Defines MoveItCppPtr, ConstPtr, WeakPtr... etc class MoveItCpp { diff --git a/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/planning_component.h b/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/planning_component.h index 3d1475da6b..0bc2d5ef1c 100644 --- a/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/planning_component.h +++ b/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/planning_component.h @@ -49,7 +49,7 @@ namespace moveit { namespace planning_interface { -MOVEIT_CLASS_FORWARD(PlanningComponent); +MOVEIT_CLASS_FORWARD(PlanningComponent); // Defines PlanningComponentPtr, ConstPtr, WeakPtr... etc class PlanningComponent { diff --git a/moveit_ros/planning_interface/planning_scene_interface/include/moveit/planning_scene_interface/planning_scene_interface.h b/moveit_ros/planning_interface/planning_scene_interface/include/moveit/planning_scene_interface/planning_scene_interface.h index c0d056dcb9..2c86938409 100644 --- a/moveit_ros/planning_interface/planning_scene_interface/include/moveit/planning_scene_interface/planning_scene_interface.h +++ b/moveit_ros/planning_interface/planning_scene_interface/include/moveit/planning_scene_interface/planning_scene_interface.h @@ -48,7 +48,7 @@ namespace moveit { namespace planning_interface { -MOVEIT_CLASS_FORWARD(PlanningSceneInterface); +MOVEIT_CLASS_FORWARD(PlanningSceneInterface); // Defines PlanningSceneInterfacePtr, ConstPtr, WeakPtr... etc class PlanningSceneInterface { diff --git a/moveit_ros/robot_interaction/include/moveit/robot_interaction/interaction_handler.h b/moveit_ros/robot_interaction/include/moveit/robot_interaction/interaction_handler.h index 4841fab90a..bbea62da1f 100644 --- a/moveit_ros/robot_interaction/include/moveit/robot_interaction/interaction_handler.h +++ b/moveit_ros/robot_interaction/include/moveit/robot_interaction/interaction_handler.h @@ -47,9 +47,9 @@ namespace robot_interaction { -MOVEIT_CLASS_FORWARD(InteractionHandler); -MOVEIT_CLASS_FORWARD(RobotInteraction); -MOVEIT_CLASS_FORWARD(KinematicOptionsMap); +MOVEIT_CLASS_FORWARD(InteractionHandler); // Defines InteractionHandlerPtr, ConstPtr, WeakPtr... etc +MOVEIT_CLASS_FORWARD(RobotInteraction); // Defines RobotInteractionPtr, ConstPtr, WeakPtr... etc +MOVEIT_CLASS_FORWARD(KinematicOptionsMap); // Defines KinematicOptionsMapPtr, ConstPtr, WeakPtr... etc struct EndEffectorInteraction; struct JointInteraction; diff --git a/moveit_ros/robot_interaction/include/moveit/robot_interaction/locked_robot_state.h b/moveit_ros/robot_interaction/include/moveit/robot_interaction/locked_robot_state.h index 022042d78a..dd0862562b 100644 --- a/moveit_ros/robot_interaction/include/moveit/robot_interaction/locked_robot_state.h +++ b/moveit_ros/robot_interaction/include/moveit/robot_interaction/locked_robot_state.h @@ -45,7 +45,7 @@ namespace robot_interaction { -MOVEIT_CLASS_FORWARD(LockedRobotState); +MOVEIT_CLASS_FORWARD(LockedRobotState); // Defines LockedRobotStatePtr, ConstPtr, WeakPtr... etc /// Maintain a RobotState in a multithreaded environment. // diff --git a/moveit_ros/robot_interaction/include/moveit/robot_interaction/robot_interaction.h b/moveit_ros/robot_interaction/include/moveit/robot_interaction/robot_interaction.h index bbbd9585cc..a649961906 100644 --- a/moveit_ros/robot_interaction/include/moveit/robot_interaction/robot_interaction.h +++ b/moveit_ros/robot_interaction/include/moveit/robot_interaction/robot_interaction.h @@ -58,9 +58,9 @@ class InteractiveMarkerServer; namespace robot_interaction { -MOVEIT_CLASS_FORWARD(InteractionHandler); -MOVEIT_CLASS_FORWARD(KinematicOptionsMap); -MOVEIT_CLASS_FORWARD(RobotInteraction); +MOVEIT_CLASS_FORWARD(InteractionHandler); // Defines InteractionHandlerPtr, ConstPtr, WeakPtr... etc +MOVEIT_CLASS_FORWARD(KinematicOptionsMap); // Defines KinematicOptionsMapPtr, ConstPtr, WeakPtr... etc +MOVEIT_CLASS_FORWARD(RobotInteraction); // Defines RobotInteractionPtr, ConstPtr, WeakPtr... etc // Manage interactive markers for controlling a robot state. // diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_frame.h b/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_frame.h index f39c15afdb..d9f58bdefc 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_frame.h +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_frame.h @@ -74,9 +74,9 @@ class MotionPlanningUI; namespace moveit_warehouse { -MOVEIT_CLASS_FORWARD(PlanningSceneStorage); -MOVEIT_CLASS_FORWARD(ConstraintsStorage); -MOVEIT_CLASS_FORWARD(RobotStateStorage); +MOVEIT_CLASS_FORWARD(PlanningSceneStorage); // Defines PlanningSceneStoragePtr, ConstPtr, WeakPtr... etc +MOVEIT_CLASS_FORWARD(ConstraintsStorage); // Defines ConstraintsStoragePtr, ConstPtr, WeakPtr... etc +MOVEIT_CLASS_FORWARD(RobotStateStorage); // Defines RobotStateStoragePtr, ConstPtr, WeakPtr... etc } // namespace moveit_warehouse namespace moveit_rviz_plugin diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_param_widget.h b/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_param_widget.h index d631b582ea..4cc55720ee 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_param_widget.h +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_param_widget.h @@ -43,7 +43,7 @@ namespace moveit { namespace planning_interface { -MOVEIT_CLASS_FORWARD(MoveGroupInterface); +MOVEIT_CLASS_FORWARD(MoveGroupInterface); // Defines MoveGroupInterfacePtr, ConstPtr, WeakPtr... etc } } // namespace moveit diff --git a/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/planning_scene_render.h b/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/planning_scene_render.h index 1923d8d54f..73296be1e7 100644 --- a/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/planning_scene_render.h +++ b/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/planning_scene_render.h @@ -55,9 +55,9 @@ class DisplayContext; namespace moveit_rviz_plugin { -MOVEIT_CLASS_FORWARD(RobotStateVisualization); -MOVEIT_CLASS_FORWARD(RenderShapes); -MOVEIT_CLASS_FORWARD(PlanningSceneRender); +MOVEIT_CLASS_FORWARD(RobotStateVisualization); // Defines RobotStateVisualizationPtr, ConstPtr, WeakPtr... etc +MOVEIT_CLASS_FORWARD(RenderShapes); // Defines RenderShapesPtr, ConstPtr, WeakPtr... etc +MOVEIT_CLASS_FORWARD(PlanningSceneRender); // Defines PlanningSceneRenderPtr, ConstPtr, WeakPtr... etc class PlanningSceneRender { diff --git a/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/render_shapes.h b/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/render_shapes.h index 52ae8d685c..045b4b51fe 100644 --- a/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/render_shapes.h +++ b/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/render_shapes.h @@ -57,8 +57,8 @@ class Shape; namespace moveit_rviz_plugin { -MOVEIT_CLASS_FORWARD(OcTreeRender); -MOVEIT_CLASS_FORWARD(RenderShapes); +MOVEIT_CLASS_FORWARD(OcTreeRender); // Defines OcTreeRenderPtr, ConstPtr, WeakPtr... etc +MOVEIT_CLASS_FORWARD(RenderShapes); // Defines RenderShapesPtr, ConstPtr, WeakPtr... etc class RenderShapes { diff --git a/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/robot_state_visualization.h b/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/robot_state_visualization.h index 2b3208b942..bab2a74af4 100644 --- a/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/robot_state_visualization.h +++ b/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/robot_state_visualization.h @@ -44,8 +44,8 @@ namespace moveit_rviz_plugin { -MOVEIT_CLASS_FORWARD(RenderShapes); -MOVEIT_CLASS_FORWARD(RobotStateVisualization); +MOVEIT_CLASS_FORWARD(RenderShapes); // Defines RenderShapesPtr, ConstPtr, WeakPtr... etc +MOVEIT_CLASS_FORWARD(RobotStateVisualization); // Defines RobotStateVisualizationPtr, ConstPtr, WeakPtr... etc /** \brief Update the links of an rviz::Robot using a robot_state::RobotState */ class RobotStateVisualization diff --git a/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/trajectory_visualization.h b/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/trajectory_visualization.h index 412c64251b..62b83fd2da 100644 --- a/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/trajectory_visualization.h +++ b/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/trajectory_visualization.h @@ -69,7 +69,7 @@ class MovableText; namespace moveit_rviz_plugin { -MOVEIT_CLASS_FORWARD(TrajectoryVisualization); +MOVEIT_CLASS_FORWARD(TrajectoryVisualization); // Defines TrajectoryVisualizationPtr, ConstPtr, WeakPtr... etc class TrajectoryVisualization : public QObject { diff --git a/moveit_ros/warehouse/warehouse/include/moveit/warehouse/constraints_storage.h b/moveit_ros/warehouse/warehouse/include/moveit/warehouse/constraints_storage.h index f7d82bad7b..128b9b3469 100644 --- a/moveit_ros/warehouse/warehouse/include/moveit/warehouse/constraints_storage.h +++ b/moveit_ros/warehouse/warehouse/include/moveit/warehouse/constraints_storage.h @@ -46,7 +46,7 @@ namespace moveit_warehouse typedef warehouse_ros::MessageWithMetadata::ConstPtr ConstraintsWithMetadata; typedef warehouse_ros::MessageCollection::Ptr ConstraintsCollection; -MOVEIT_CLASS_FORWARD(ConstraintsStorage); +MOVEIT_CLASS_FORWARD(ConstraintsStorage); // Defines ConstraintsStoragePtr, ConstPtr, WeakPtr... etc class ConstraintsStorage : public MoveItMessageStorage { diff --git a/moveit_ros/warehouse/warehouse/include/moveit/warehouse/planning_scene_storage.h b/moveit_ros/warehouse/warehouse/include/moveit/warehouse/planning_scene_storage.h index 239f531212..17a0e98dd2 100644 --- a/moveit_ros/warehouse/warehouse/include/moveit/warehouse/planning_scene_storage.h +++ b/moveit_ros/warehouse/warehouse/include/moveit/warehouse/planning_scene_storage.h @@ -53,7 +53,7 @@ typedef warehouse_ros::MessageCollection::Ptr Planni typedef warehouse_ros::MessageCollection::Ptr MotionPlanRequestCollection; typedef warehouse_ros::MessageCollection::Ptr RobotTrajectoryCollection; -MOVEIT_CLASS_FORWARD(PlanningSceneStorage); +MOVEIT_CLASS_FORWARD(PlanningSceneStorage); // Defines PlanningSceneStoragePtr, ConstPtr, WeakPtr... etc class PlanningSceneStorage : public MoveItMessageStorage { diff --git a/moveit_ros/warehouse/warehouse/include/moveit/warehouse/state_storage.h b/moveit_ros/warehouse/warehouse/include/moveit/warehouse/state_storage.h index 1c31e68825..feded144f0 100644 --- a/moveit_ros/warehouse/warehouse/include/moveit/warehouse/state_storage.h +++ b/moveit_ros/warehouse/warehouse/include/moveit/warehouse/state_storage.h @@ -46,7 +46,7 @@ namespace moveit_warehouse typedef warehouse_ros::MessageWithMetadata::ConstPtr RobotStateWithMetadata; typedef warehouse_ros::MessageCollection::Ptr RobotStateCollection; -MOVEIT_CLASS_FORWARD(RobotStateStorage); +MOVEIT_CLASS_FORWARD(RobotStateStorage); // Defines RobotStateStoragePtr, ConstPtr, WeakPtr... etc class RobotStateStorage : public MoveItMessageStorage { diff --git a/moveit_ros/warehouse/warehouse/include/moveit/warehouse/trajectory_constraints_storage.h b/moveit_ros/warehouse/warehouse/include/moveit/warehouse/trajectory_constraints_storage.h index ed2c5393f5..5b6df5e4de 100644 --- a/moveit_ros/warehouse/warehouse/include/moveit/warehouse/trajectory_constraints_storage.h +++ b/moveit_ros/warehouse/warehouse/include/moveit/warehouse/trajectory_constraints_storage.h @@ -47,7 +47,7 @@ typedef warehouse_ros::MessageWithMetadata:: TrajectoryConstraintsWithMetadata; typedef warehouse_ros::MessageCollection::Ptr TrajectoryConstraintsCollection; -MOVEIT_CLASS_FORWARD(TrajectoryConstraintsStorage); +MOVEIT_CLASS_FORWARD(TrajectoryConstraintsStorage); // Defines TrajectoryConstraintsStoragePtr, ConstPtr, WeakPtr... etc class TrajectoryConstraintsStorage : public MoveItMessageStorage { diff --git a/moveit_setup_assistant/include/moveit/setup_assistant/tools/compute_default_collisions.h b/moveit_setup_assistant/include/moveit/setup_assistant/tools/compute_default_collisions.h index 0a2c29caec..a13030efc4 100644 --- a/moveit_setup_assistant/include/moveit/setup_assistant/tools/compute_default_collisions.h +++ b/moveit_setup_assistant/include/moveit/setup_assistant/tools/compute_default_collisions.h @@ -41,7 +41,7 @@ #include namespace planning_scene { -MOVEIT_CLASS_FORWARD(PlanningScene); +MOVEIT_CLASS_FORWARD(PlanningScene); // Defines PlanningScenePtr, ConstPtr, WeakPtr... etc } namespace moveit_setup_assistant diff --git a/moveit_setup_assistant/include/moveit/setup_assistant/tools/moveit_config_data.h b/moveit_setup_assistant/include/moveit/setup_assistant/tools/moveit_config_data.h index 9c4654df72..5334d0678b 100644 --- a/moveit_setup_assistant/include/moveit/setup_assistant/tools/moveit_config_data.h +++ b/moveit_setup_assistant/include/moveit/setup_assistant/tools/moveit_config_data.h @@ -173,7 +173,7 @@ class GenericParameter std::string comment_; // comment briefly describing what this parameter does }; -MOVEIT_CLASS_FORWARD(MoveItConfigData); +MOVEIT_CLASS_FORWARD(MoveItConfigData); // Defines MoveItConfigDataPtr, ConstPtr, WeakPtr... etc /** \brief This class is shared with all widgets and contains the common configuration data needed for generating each robot's MoveIt! configuration package. From aec6bbe2192347d0d323f01a458a4be47761f42f Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Tue, 15 Sep 2020 08:52:47 +0200 Subject: [PATCH 016/179] robot_description is already loaded in move_group.launch (#2313) --- .../moveit_config_pkg_template/launch/demo.launch | 9 ++++----- .../moveit_config_pkg_template/launch/demo_gazebo.launch | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch index 6c0a4edbbf..5ee0462e0a 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch @@ -11,6 +11,9 @@ + + + - - - - [VIRTUAL_JOINT_BROADCASTER] @@ -48,6 +46,7 @@ + diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo_gazebo.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo_gazebo.launch index c2257e535f..75ea8eb387 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo_gazebo.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo_gazebo.launch @@ -8,6 +8,9 @@ + + + - - - - [VIRTUAL_JOINT_BROADCASTER] @@ -58,6 +56,7 @@ + From 3db166511ca907eee5a75fe47f505d61d880239b Mon Sep 17 00:00:00 2001 From: AndyZe Date: Tue, 15 Sep 2020 11:02:11 -0500 Subject: [PATCH 017/179] Refactor velocity limit enforcement and add a unit test (#2260) * Rework velocity limit enforcement, add unit test * Test every command out of Servo * Minor variable renaming * Clang format & clang tidy * Delete unused acceleration variable --- .../include/moveit_servo/servo_calcs.h | 4 +- moveit_ros/moveit_servo/src/servo_calcs.cpp | 68 +++++++---------- .../test/config/servo_settings.yaml | 2 +- .../test/servo_cpp_interface_test.cpp | 73 ++++++++++++++++++- 4 files changed, 98 insertions(+), 49 deletions(-) diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h index c67afb6e0c..69ad46cf27 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h @@ -113,10 +113,10 @@ class ServoCalcs void suddenHalt(trajectory_msgs::JointTrajectory& joint_trajectory); /** \brief Scale the delta theta to match joint velocity/acceleration limits */ - void enforceSRDFAccelVelLimits(Eigen::ArrayXd& delta_theta); + void enforceVelLimits(Eigen::ArrayXd& delta_theta); /** \brief Avoid overshooting joint limits */ - bool enforceSRDFPositionLimits(); + bool enforcePositionLimits(); /** \brief Possibly calculate a velocity scaling factor, due to proximity of * singularity and direction of motion diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index c28a36fd0b..ac56a6216d 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -458,7 +458,7 @@ bool ServoCalcs::cartesianServoCalcs(geometry_msgs::TwistStamped& cmd, delta_theta_ = pseudo_inverse * delta_x; - enforceSRDFAccelVelLimits(delta_theta_); + enforceVelLimits(delta_theta_); // If close to a collision or a singularity, decelerate applyVelocityScaling(delta_theta_, velocityScalingFactorForSingularity(delta_x, svd, pseudo_inverse)); @@ -484,7 +484,7 @@ bool ServoCalcs::jointServoCalcs(const control_msgs::JointJog& cmd, trajectory_m // Apply user-defined scaling delta_theta_ = scaleJointCommand(cmd); - enforceSRDFAccelVelLimits(delta_theta_); + enforceVelLimits(delta_theta_); // If close to a collision, decelerate applyVelocityScaling(delta_theta_, 1.0 /* scaling for singularities -- ignore for joint motions */); @@ -507,7 +507,7 @@ bool ServoCalcs::convertDeltasToOutgoingCmd(trajectory_msgs::JointTrajectory& jo composeJointTrajMessage(internal_joint_state_, joint_trajectory); - if (!enforceSRDFPositionLimits()) + if (!enforcePositionLimits()) { suddenHalt(joint_trajectory); status_ = StatusCode::JOINT_BOUND; @@ -680,45 +680,18 @@ double ServoCalcs::velocityScalingFactorForSingularity(const Eigen::VectorXd& co return velocity_scale; } -void ServoCalcs::enforceSRDFAccelVelLimits(Eigen::ArrayXd& delta_theta) +void ServoCalcs::enforceVelLimits(Eigen::ArrayXd& delta_theta) { Eigen::ArrayXd velocity = delta_theta / parameters_.publish_period; - const Eigen::ArrayXd acceleration = (velocity - prev_joint_velocity_) / parameters_.publish_period; std::size_t joint_delta_index = 0; + // Track the smallest velocity scaling factor required, across all joints + double velocity_limit_scaling_factor = 1; + for (auto joint : joint_model_group_->getActiveJointModels()) { // Some joints do not have bounds defined const auto bounds = joint->getVariableBounds(joint->getName()); - if (bounds.acceleration_bounded_) - { - bool clip_acceleration = false; - double acceleration_limit = 0.0; - if (acceleration(joint_delta_index) < bounds.min_acceleration_) - { - clip_acceleration = true; - acceleration_limit = bounds.min_acceleration_; - } - else if (acceleration(joint_delta_index) > bounds.max_acceleration_) - { - clip_acceleration = true; - acceleration_limit = bounds.max_acceleration_; - } - - // Apply acceleration bounds - if (clip_acceleration) - { - // accel = (vel - vel_prev) / delta_t = ((delta_theta / delta_t) - vel_prev) / delta_t - // --> delta_theta = (accel * delta_t _ + vel_prev) * delta_t - const double relative_change = - ((acceleration_limit * parameters_.publish_period + prev_joint_velocity_(joint_delta_index)) * - parameters_.publish_period) / - delta_theta(joint_delta_index); - // Avoid nan - if (fabs(relative_change) < 1) - delta_theta(joint_delta_index) = relative_change * delta_theta(joint_delta_index); - } - } if (bounds.velocity_bounded_) { @@ -740,21 +713,30 @@ void ServoCalcs::enforceSRDFAccelVelLimits(Eigen::ArrayXd& delta_theta) // Apply velocity bounds if (clip_velocity) { - // delta_theta = joint_velocity * delta_t - const double relative_change = (velocity_limit * parameters_.publish_period) / delta_theta(joint_delta_index); - // Avoid nan - if (fabs(relative_change) < 1) - { - delta_theta(joint_delta_index) = relative_change * delta_theta(joint_delta_index); - velocity(joint_delta_index) = relative_change * velocity(joint_delta_index); - } + const double scaling_factor = + fabs(velocity_limit * parameters_.publish_period) / fabs(delta_theta(joint_delta_index)); + + // Store the scaling factor if it's the smallest yet + if (scaling_factor < velocity_limit_scaling_factor) + velocity_limit_scaling_factor = scaling_factor; } } ++joint_delta_index; } + + // Apply the velocity scaling to all joints + if (velocity_limit_scaling_factor < 1) + { + for (joint_delta_index = 0; joint_delta_index < joint_model_group_->getActiveJointModels().size(); + ++joint_delta_index) + { + delta_theta(joint_delta_index) = velocity_limit_scaling_factor * delta_theta(joint_delta_index); + velocity(joint_delta_index) = velocity_limit_scaling_factor * velocity(joint_delta_index); + } + } } -bool ServoCalcs::enforceSRDFPositionLimits() +bool ServoCalcs::enforcePositionLimits() { bool halting = false; diff --git a/moveit_ros/moveit_servo/test/config/servo_settings.yaml b/moveit_ros/moveit_servo/test/config/servo_settings.yaml index 9a674425b6..30e4cb59d2 100644 --- a/moveit_ros/moveit_servo/test/config/servo_settings.yaml +++ b/moveit_ros/moveit_servo/test/config/servo_settings.yaml @@ -5,7 +5,7 @@ use_gazebo: false # Whether the robot is started in a Gazebo simulation environm ## Properties of incoming commands robot_link_command_frame: panda_link0 # commands must be given in the frame of a robot link. Usually either the base or end effector -command_in_type: "unitless" # "unitless"> in the range [-1:1], as if from joystick. "speed_units"> cmds are in m/s and rad/s +command_in_type: "speed_units" # "unitless"> in the range [-1:1], as if from joystick. "speed_units"> cmds are in m/s and rad/s scale: # Scale parameters are only used if command_in_type=="unitless" linear: 0.003 # Max linear velocity. Meters per publish_period. Unit is [m/s]. Only used for Cartesian commands. diff --git a/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp b/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp index 4fd01fc73e..c565894e0b 100644 --- a/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp +++ b/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp @@ -46,10 +46,11 @@ #include // Servo -#include #include +#include static const std::string LOGNAME = "servo_cpp_interface_test"; +static constexpr double LARGEST_ALLOWABLE_PANDA_VEL = 2.8710; // to test joint velocity limit enforcement namespace moveit_servo { @@ -110,7 +111,7 @@ TEST_F(ServoFixture, SendTwistStampedTest) // count trajectory messages sent by servo size_t received_count = 0; boost::function traj_callback = - [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& msg) { received_count++; }; + [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& msg) { ++received_count; }; auto traj_sub = nh_.subscribe(parameters.command_out_topic, 1, traj_callback); // Create publisher to send servo commands @@ -136,6 +137,7 @@ TEST_F(ServoFixture, SendTwistStampedTest) } EXPECT_GT(received_count, num_commands - 20); + EXPECT_GT(received_count, (unsigned)0); EXPECT_LT(received_count, num_commands + 20); servo_->stop(); } @@ -150,7 +152,7 @@ TEST_F(ServoFixture, SendJointServoTest) // count trajectory messages sent by servo size_t received_count = 0; boost::function traj_callback = - [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& msg) { received_count++; }; + [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& msg) { ++received_count; }; auto traj_sub = nh_.subscribe(parameters.command_out_topic, 1, traj_callback); // Create publisher to send servo commands @@ -180,6 +182,71 @@ TEST_F(ServoFixture, SendJointServoTest) servo_->stop(); } +TEST_F(ServoFixture, JointVelocityEnforcementTest) +{ + servo_->start(); + EXPECT_TRUE(waitForFirstStatus()) << "Timeout waiting for Status message"; + + auto parameters = servo_->getParameters(); + double publish_period = parameters.publish_period; + + // count trajectory messages sent by servo + size_t received_count = 0; + trajectory_msgs::JointTrajectory joint_command_from_servo; + trajectory_msgs::JointTrajectory prev_joint_command_from_servo; + boost::function traj_callback = + [&](const trajectory_msgs::JointTrajectoryConstPtr& msg) { + ++received_count; + // Store a series of two commands so we can calculate velocities + // from positions + prev_joint_command_from_servo = joint_command_from_servo; + joint_command_from_servo = *msg; + + // Start running checks when we have at least two datapoints + if (received_count > 1) + { + // Need a sequence of two commands to calculate a velocity + EXPECT_GT(joint_command_from_servo.points.size(), (unsigned)0); + EXPECT_GT(prev_joint_command_from_servo.points.size(), (unsigned)0); + EXPECT_EQ(prev_joint_command_from_servo.points.size(), joint_command_from_servo.points.size()); + // No velocities larger than the largest allowable Panda velocity + for (size_t joint_index = 0; joint_index < joint_command_from_servo.points[0].positions.size(); ++joint_index) + { + double joint_velocity = (joint_command_from_servo.points[0].positions[joint_index] - + prev_joint_command_from_servo.points[0].positions[joint_index]) / + publish_period; + EXPECT_LE(joint_velocity, LARGEST_ALLOWABLE_PANDA_VEL); + } + } + }; + auto traj_sub = nh_.subscribe(parameters.command_out_topic, 1, traj_callback); + + // Create publisher to send servo commands + auto twist_stamped_pub = nh_.advertise(parameters.cartesian_command_in_topic, 1); + + constexpr double test_duration = 1.0; + const size_t num_commands = static_cast(test_duration / publish_period); + + ros::Rate publish_rate(1. / publish_period); + + // Send a few Cartesian commands with very high velocity + for (size_t i = 0; i < num_commands && ros::ok(); ++i) + { + auto msg = moveit::util::make_shared_from_pool(); + msg->header.stamp = ros::Time::now(); + msg->header.frame_id = "panda_link0"; + msg->twist.linear.x = 10.0; + msg->twist.angular.y = 5 * LARGEST_ALLOWABLE_PANDA_VEL; + + // Send the message + twist_stamped_pub.publish(msg); + publish_rate.sleep(); + } + + EXPECT_GT(received_count, num_commands - 20); + EXPECT_LT(received_count, num_commands + 20); + servo_->stop(); +} } // namespace moveit_servo int main(int argc, char** argv) From 9d02f4a4069bb43a623d179c81eb6428f0236406 Mon Sep 17 00:00:00 2001 From: AndyZe Date: Thu, 17 Sep 2020 12:57:01 -0500 Subject: [PATCH 018/179] Fix Servo thread interruption (#2314) --- .../include/moveit_servo/collision_check.h | 8 ++++++-- .../moveit_servo/include/moveit_servo/servo.h | 3 --- .../include/moveit_servo/servo_calcs.h | 9 ++++++--- moveit_ros/moveit_servo/src/collision_check.cpp | 5 ----- .../cpp_interface_example.cpp | 2 +- moveit_ros/moveit_servo/src/servo.cpp | 8 +------- moveit_ros/moveit_servo/src/servo_calcs.cpp | 11 +---------- moveit_ros/moveit_servo/src/servo_server.cpp | 2 +- .../moveit_servo/test/servo_cpp_interface_test.cpp | 14 +++++++------- 9 files changed, 23 insertions(+), 39 deletions(-) diff --git a/moveit_ros/moveit_servo/include/moveit_servo/collision_check.h b/moveit_ros/moveit_servo/include/moveit_servo/collision_check.h index a02fe4750a..9accf79484 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/collision_check.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/collision_check.h @@ -68,9 +68,13 @@ class CollisionCheck const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, const std::shared_ptr& joint_state_subscriber); - /** \brief start and stop the Timer */ + ~CollisionCheck() + { + timer_.stop(); + } + + /** \brief start the Timer that regulates collision check rate */ void start(); - void stop(); /** \brief Pause or unpause processing servo commands while keeping the timers alive */ void setPaused(bool paused); diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo.h b/moveit_ros/moveit_servo/include/moveit_servo/servo.h index 5e9f26fe64..139c11b44b 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo.h @@ -60,9 +60,6 @@ class Servo /** \brief start servo node */ void start(); - /** \brief stop servo node */ - void stop(); - /** \brief Pause or unpause processing servo commands while keeping the timers alive */ void setPaused(bool paused); diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h index 69ad46cf27..fa477eaabc 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h @@ -66,9 +66,13 @@ class ServoCalcs const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, const std::shared_ptr& joint_state_subscriber); - /** \brief Start and stop the timer where we do work and publish outputs */ + ~ServoCalcs() + { + timer_.stop(); + } + + /** \brief Start the timer where we do work and publish outputs */ void start(); - void stop(); /** * Get the MoveIt planning link transform. @@ -252,7 +256,6 @@ class ServoCalcs // Status StatusCode status_ = StatusCode::NO_WARNING; - bool stop_requested_ = false; bool paused_ = false; bool twist_command_is_stale_ = false; bool joint_command_is_stale_ = false; diff --git a/moveit_ros/moveit_servo/src/collision_check.cpp b/moveit_ros/moveit_servo/src/collision_check.cpp index 1f85d40cd1..38b62c383c 100644 --- a/moveit_ros/moveit_servo/src/collision_check.cpp +++ b/moveit_ros/moveit_servo/src/collision_check.cpp @@ -94,11 +94,6 @@ void CollisionCheck::start() timer_ = nh_.createTimer(period_, &CollisionCheck::run, this); } -void CollisionCheck::stop() -{ - timer_.stop(); -} - void CollisionCheck::run(const ros::TimerEvent& timer_event) { // Log warning when the last loop duration was longer than the period diff --git a/moveit_ros/moveit_servo/src/cpp_interface_example/cpp_interface_example.cpp b/moveit_ros/moveit_servo/src/cpp_interface_example/cpp_interface_example.cpp index 53e919ee33..c1170d10a9 100644 --- a/moveit_ros/moveit_servo/src/cpp_interface_example/cpp_interface_example.cpp +++ b/moveit_ros/moveit_servo/src/cpp_interface_example/cpp_interface_example.cpp @@ -150,6 +150,6 @@ int main(int argc, char** argv) ++num_commands; } - servo.stop(); + servo.setPaused(true); return 0; } diff --git a/moveit_ros/moveit_servo/src/servo.cpp b/moveit_ros/moveit_servo/src/servo.cpp index 8cc834a047..761be5903e 100644 --- a/moveit_ros/moveit_servo/src/servo.cpp +++ b/moveit_ros/moveit_servo/src/servo.cpp @@ -286,15 +286,9 @@ void Servo::start() collision_checker_->start(); } -void Servo::stop() -{ - servo_calcs_->stop(); - collision_checker_->stop(); -} - Servo::~Servo() { - stop(); + setPaused(true); } void Servo::setPaused(bool paused) diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index ac56a6216d..dd39f569c1 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -179,16 +179,9 @@ void ServoCalcs::start() initial_joint_trajectory->points.push_back(point); last_sent_command_ = initial_joint_trajectory; - stop_requested_ = false; timer_ = nh_.createTimer(period_, &ServoCalcs::run, this); } -void ServoCalcs::stop() -{ - stop_requested_ = true; - timer_.stop(); -} - void ServoCalcs::run(const ros::TimerEvent& timer_event) { // Log warning when the last loop duration was longer than the period @@ -209,8 +202,6 @@ void ServoCalcs::run(const ros::TimerEvent& timer_event) // 2) so the low-pass filters are up to date and don't cause a jump while (!updateJoints() && ros::ok()) { - if (stop_requested_) - return; default_sleep_rate_.sleep(); } @@ -335,7 +326,7 @@ void ServoCalcs::run(const ros::TimerEvent& timer_event) zero_velocity_count_ = 0; } - if (ok_to_publish_) + if (ok_to_publish_ && !paused_) { // Put the outgoing msg in the right format // (trajectory_msgs/JointTrajectory or std_msgs/Float64MultiArray). diff --git a/moveit_ros/moveit_servo/src/servo_server.cpp b/moveit_ros/moveit_servo/src/servo_server.cpp index 590061609f..31e477c837 100644 --- a/moveit_ros/moveit_servo/src/servo_server.cpp +++ b/moveit_ros/moveit_servo/src/servo_server.cpp @@ -80,7 +80,7 @@ int main(int argc, char** argv) ros::waitForShutdown(); // Stop the servo server - servo.stop(); + servo.setPaused(true); return 0; } diff --git a/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp b/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp index c565894e0b..a5637a6eda 100644 --- a/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp +++ b/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp @@ -77,7 +77,7 @@ class ServoFixture : public ::testing::Test bool waitForFirstStatus() { - auto msg = ros::topic::waitForMessage(servo_->getParameters().status_topic, nh_, ros::Duration(15)); + auto msg = ros::topic::waitForMessage(servo_->getParameters().status_topic, nh_, ros::Duration(1)); return static_cast(msg); } @@ -91,14 +91,14 @@ TEST_F(ServoFixture, StartStopTest) { servo_->start(); EXPECT_TRUE(waitForFirstStatus()) << "Timeout waiting for Status message"; - servo_->stop(); + servo_->setPaused(true); ros::Duration(1.0).sleep(); // Start and stop again - servo_->start(); + servo_->setPaused(false); EXPECT_TRUE(waitForFirstStatus()) << "Timeout waiting for Status message"; - servo_->stop(); + servo_->setPaused(true); } TEST_F(ServoFixture, SendTwistStampedTest) @@ -139,7 +139,7 @@ TEST_F(ServoFixture, SendTwistStampedTest) EXPECT_GT(received_count, num_commands - 20); EXPECT_GT(received_count, (unsigned)0); EXPECT_LT(received_count, num_commands + 20); - servo_->stop(); + servo_->setPaused(true); } TEST_F(ServoFixture, SendJointServoTest) @@ -179,7 +179,7 @@ TEST_F(ServoFixture, SendJointServoTest) EXPECT_GT(received_count, num_commands - 20); EXPECT_LT(received_count, num_commands + 20); - servo_->stop(); + servo_->setPaused(true); } TEST_F(ServoFixture, JointVelocityEnforcementTest) @@ -245,7 +245,7 @@ TEST_F(ServoFixture, JointVelocityEnforcementTest) EXPECT_GT(received_count, num_commands - 20); EXPECT_LT(received_count, num_commands + 20); - servo_->stop(); + servo_->setPaused(true); } } // namespace moveit_servo From 5244ce27b63bac93eb0d5c9b6bb30c0a47e94e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Fri, 18 Sep 2020 07:58:09 +0200 Subject: [PATCH 019/179] MGC: Improve exception messages (#2318) --- moveit_commander/src/moveit_commander/move_group.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moveit_commander/src/moveit_commander/move_group.py b/moveit_commander/src/moveit_commander/move_group.py index d10bebab17..c13cf5d0a7 100644 --- a/moveit_commander/src/moveit_commander/move_group.py +++ b/moveit_commander/src/moveit_commander/move_group.py @@ -82,7 +82,7 @@ def get_end_effector_link(self): def set_end_effector_link(self, link_name): """ Set the name of the link to be considered as an end effector """ if not self._g.set_end_effector_link(link_name): - raise MoveItCommanderException("Unable to set end efector link") + raise MoveItCommanderException("Unable to set end effector link") def get_interface_description(self): """ Get the description of the planner interface (list of planner ids) """ @@ -218,7 +218,7 @@ def set_joint_value_target(self, arg1, arg2 = None, arg3 = None): if approx: raise MoveItCommanderException("Error setting joint target. Does your IK solver support approximate IK?") else: - raise MoveItCommanderException("Error setting joint target. Is IK running?") + raise MoveItCommanderException("Error setting joint target. Is the IK solver functional?") elif (hasattr(arg1, '__iter__')): if (arg2 is not None or arg3 is not None): From 1fb8b2ca4a96bd420ad4a1b24bf08b8134ee7a61 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Thu, 24 Sep 2020 18:47:55 +0200 Subject: [PATCH 020/179] Install python scripts via catkin_install_python() ... to correctly rewrite shebang --- moveit_commander/CMakeLists.txt | 5 +++-- moveit_kinematics/ikfast_kinematics_plugin/CMakeLists.txt | 6 ++++++ moveit_ros/benchmarks/CMakeLists.txt | 5 +++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/moveit_commander/CMakeLists.txt b/moveit_commander/CMakeLists.txt index 74a0c315af..cb0618035e 100644 --- a/moveit_commander/CMakeLists.txt +++ b/moveit_commander/CMakeLists.txt @@ -7,7 +7,8 @@ catkin_python_setup() catkin_package() -install(PROGRAMS bin/${PROJECT_NAME}_cmdline.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) +catkin_install_python( + PROGRAMS bin/${PROJECT_NAME}_cmdline.py + DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) add_subdirectory(test) diff --git a/moveit_kinematics/ikfast_kinematics_plugin/CMakeLists.txt b/moveit_kinematics/ikfast_kinematics_plugin/CMakeLists.txt index 49c1a345ec..1d5f8399cd 100644 --- a/moveit_kinematics/ikfast_kinematics_plugin/CMakeLists.txt +++ b/moveit_kinematics/ikfast_kinematics_plugin/CMakeLists.txt @@ -7,6 +7,12 @@ set(MOVEIT_LIB_NAME moveit_ikfast_kinematics_plugin) install( PROGRAMS scripts/auto_create_ikfast_moveit_plugin.sh + DESTINATION + ${CATKIN_PACKAGE_BIN_DESTINATION} +) + +catkin_install_python( + PROGRAMS scripts/create_ikfast_moveit_plugin.py scripts/round_collada_numbers.py DESTINATION diff --git a/moveit_ros/benchmarks/CMakeLists.txt b/moveit_ros/benchmarks/CMakeLists.txt index 5c2bf96808..d056e83287 100644 --- a/moveit_ros/benchmarks/CMakeLists.txt +++ b/moveit_ros/benchmarks/CMakeLists.txt @@ -58,7 +58,8 @@ install( install(DIRECTORY include/ DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}) -install(PROGRAMS scripts/moveit_benchmark_statistics.py - DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) +catkin_install_python( + PROGRAMS scripts/moveit_benchmark_statistics.py + DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) install(DIRECTORY examples/ DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/examples) From e9336794c84312a2f6f42d6bf5edcad56d13e79a Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Thu, 24 Sep 2020 18:52:43 +0200 Subject: [PATCH 021/179] Remove shebang line from moveitjoy_module.py --- .../src/moveit_ros_visualization/moveitjoy_module.py | 1 - 1 file changed, 1 deletion(-) diff --git a/moveit_ros/visualization/src/moveit_ros_visualization/moveitjoy_module.py b/moveit_ros/visualization/src/moveit_ros_visualization/moveitjoy_module.py index 5d503b8f4b..435eb611ff 100644 --- a/moveit_ros/visualization/src/moveit_ros_visualization/moveitjoy_module.py +++ b/moveit_ros/visualization/src/moveit_ros_visualization/moveitjoy_module.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # ******************************************************************** # Software License Agreement (BSD License) # From cab07be3d15a25663ebfcacdf01858529f1f5be7 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 30 Sep 2020 07:52:20 +0200 Subject: [PATCH 022/179] Remove custom copy-assignment operator for DistanceResultsData It was just performing the operations of the default operator. Newer clang requires either both or none of copy constructor and assignment operator to be defined. warning: definition of implicit copy constructor for 'DistanceResultsData' is deprecated because it has a user-declared copy assignment operator [-Wdeprecated-copy] --- .../moveit/collision_detection/collision_common.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h b/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h index 25f1fdb8bf..76f60eb401 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/collision_common.h @@ -334,19 +334,6 @@ struct DistanceResultsData normal.setZero(); } - /// Update structure data given DistanceResultsData object - void operator=(const DistanceResultsData& other) - { - distance = other.distance; - nearest_points[0] = other.nearest_points[0]; - nearest_points[1] = other.nearest_points[1]; - link_names[0] = other.link_names[0]; - link_names[1] = other.link_names[1]; - body_types[0] = other.body_types[0]; - body_types[1] = other.body_types[1]; - normal = other.normal; - } - /// Compare if the distance is less than another bool operator<(const DistanceResultsData& other) { From 1f7c21b536a6b315a14c2dd344f57488418be03a Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 30 Sep 2020 08:01:52 +0200 Subject: [PATCH 023/179] perception: add missing dependency to OpenMP --- moveit_ros/perception/package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/moveit_ros/perception/package.xml b/moveit_ros/perception/package.xml index 22cd6c877c..51821cdac4 100644 --- a/moveit_ros/perception/package.xml +++ b/moveit_ros/perception/package.xml @@ -27,6 +27,7 @@ image_transport glut libglew-dev + libomp-dev opengl cv_bridge sensor_msgs From f2ea5aeda12935da39c6bcec0ec92a781febdf4c Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 30 Sep 2020 09:23:45 +0200 Subject: [PATCH 024/179] Silent deprecation warnings of gtest's typed test suites --- .../collision_detection_bullet/CMakeLists.txt | 43 +++++++++++++++++++ .../collision_detection_fcl/CMakeLists.txt | 3 ++ .../perception/mesh_filter/CMakeLists.txt | 2 + 3 files changed, 48 insertions(+) create mode 100644 moveit_core/collision_detection_bullet/CMakeLists.txt diff --git a/moveit_core/collision_detection_bullet/CMakeLists.txt b/moveit_core/collision_detection_bullet/CMakeLists.txt new file mode 100644 index 0000000000..775fba1bd3 --- /dev/null +++ b/moveit_core/collision_detection_bullet/CMakeLists.txt @@ -0,0 +1,43 @@ +set(MOVEIT_LIB_NAME moveit_collision_detection_bullet) + +add_library(${MOVEIT_LIB_NAME} + src/bullet_integration/bullet_utils.cpp + src/bullet_integration/bullet_discrete_bvh_manager.cpp + src/bullet_integration/bullet_cast_bvh_manager.cpp + src/collision_env_bullet.cpp + src/bullet_integration/bullet_bvh_manager.cpp +) +set_target_properties(${MOVEIT_LIB_NAME} PROPERTIES VERSION "${${PROJECT_NAME}_VERSION}") + +target_link_libraries(${MOVEIT_LIB_NAME} moveit_collision_detection + ${catkin_LIBRARIES} ${urdfdom_LIBRARIES} + ${urdfdom_headers_LIBRARIES} ${Boost_LIBRARIES} + ${BULLET_LIBRARIES}) +add_dependencies(${MOVEIT_LIB_NAME} ${catkin_EXPORTED_TARGETS}) + +add_library(collision_detector_bullet_plugin src/collision_detector_bullet_plugin_loader.cpp) +set_target_properties(collision_detector_bullet_plugin PROPERTIES VERSION "${${PROJECT_NAME}_VERSION}") +target_link_libraries(collision_detector_bullet_plugin ${catkin_LIBRARIES} ${MOVEIT_LIB_NAME}) + +install(TARGETS ${MOVEIT_LIB_NAME} collision_detector_bullet_plugin + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}) + +install(DIRECTORY include/ DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}) + +install(FILES ../collision_detector_bullet_description.xml DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) + +if(CATKIN_ENABLE_TESTING) + catkin_add_gtest(test_bullet_collision_detection test/test_bullet_collision_detection_pr2.cpp) + target_link_libraries(test_bullet_collision_detection moveit_test_utils ${MOVEIT_LIB_NAME} ${Boost_LIBRARIES}) + # TODO: remove if transition to gtest's new API TYPED_TEST_SUITE_P is finished + target_compile_options(test_bullet_collision_detection PRIVATE -Wno-deprecated-declarations) + + catkin_add_gtest(test_bullet_collision_detection_panda test/test_bullet_collision_detection_panda.cpp) + target_link_libraries(test_bullet_collision_detection_panda moveit_test_utils ${MOVEIT_LIB_NAME} ${Boost_LIBRARIES}) + # TODO: remove if transition to gtest's new API TYPED_TEST_SUITE_P is finished + target_compile_options(test_bullet_collision_detection_panda PRIVATE -Wno-deprecated-declarations) + + catkin_add_gtest(test_bullet_continuous_collision_checking test/test_bullet_continuous_collision_checking.cpp) + target_link_libraries(test_bullet_continuous_collision_checking moveit_test_utils ${MOVEIT_LIB_NAME} ${Boost_LIBRARIES}) +endif() diff --git a/moveit_core/collision_detection_fcl/CMakeLists.txt b/moveit_core/collision_detection_fcl/CMakeLists.txt index 51415e69b0..7ebf674b9d 100644 --- a/moveit_core/collision_detection_fcl/CMakeLists.txt +++ b/moveit_core/collision_detection_fcl/CMakeLists.txt @@ -27,4 +27,7 @@ install(FILES ../collision_detector_fcl_description.xml DESTINATION ${CATKIN_PAC if(CATKIN_ENABLE_TESTING) catkin_add_gtest(test_fcl_collision_detection test/test_fcl_collision_detection.cpp) target_link_libraries(test_fcl_collision_detection moveit_test_utils ${MOVEIT_LIB_NAME} ${Boost_LIBRARIES}) + # TODO: remove if transition to gtest's new API TYPED_TEST_SUITE_P is finished + target_compile_options(test_fcl_collision_detection PRIVATE -Wno-deprecated-declarations) + endif() diff --git a/moveit_ros/perception/mesh_filter/CMakeLists.txt b/moveit_ros/perception/mesh_filter/CMakeLists.txt index 8d8a00743b..100350e472 100644 --- a/moveit_ros/perception/mesh_filter/CMakeLists.txt +++ b/moveit_ros/perception/mesh_filter/CMakeLists.txt @@ -17,6 +17,8 @@ if (CATKIN_ENABLE_TESTING) if (DEFINED ENV{DISPLAY} AND NOT $ENV{DISPLAY} STREQUAL "") catkin_add_gtest(mesh_filter_test test/mesh_filter_test.cpp) target_link_libraries(mesh_filter_test ${catkin_LIBRARIES} ${Boost_LIBRARIES} moveit_mesh_filter) + # TODO: remove if transition to gtest's new API TYPED_TEST_SUITE_P is finished + target_compile_options(mesh_filter_test PRIVATE -Wno-deprecated-declarations) else() message("No display, will not configure tests for moveit_ros_perception/mesh_filter") endif() From ca031665a4577b76e0f764160266ff8615c1f15b Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 30 Sep 2020 11:46:37 +0200 Subject: [PATCH 025/179] Handle multiple link libraries for FCL (#2325) --- moveit_core/CMakeLists.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/moveit_core/CMakeLists.txt b/moveit_core/CMakeLists.txt index 53a8acb171..f24c98497d 100644 --- a/moveit_core/CMakeLists.txt +++ b/moveit_core/CMakeLists.txt @@ -35,9 +35,13 @@ find_package(Eigen3 REQUIRED) find_package(PkgConfig REQUIRED) pkg_check_modules(LIBFCL_PC REQUIRED fcl) -# find *absolute* paths to LIBFCL_INCLUDE_DIRS and LIBFCL_LIBRARIES -find_path(LIBFCL_INCLUDE_DIRS fcl/config.h HINTS ${LIBFCL_PC_INCLUDE_DIR} ${LIBFCL_PC_INCLUDE_DIRS}) -find_library(LIBFCL_LIBRARIES fcl HINTS ${LIBFCL_PC_LIBRARY_DIRS}) +set(LIBFCL_INCLUDE_DIRS ${LIBFCL_PC_INCLUDE_DIRS}) +# find *absolute* paths to LIBFCL_LIBRARIES +set(LIBFCL_LIBRARIES) +foreach(_lib ${LIBFCL_PC_LIBRARIES}) + find_library(_lib_${_lib} ${_lib} HINTS ${LIBFCL_PC_LIBRARY_DIRS}) + list(APPEND LIBFCL_LIBRARIES ${_lib_${_lib}}) +endforeach() find_package(octomap REQUIRED) find_package(urdfdom REQUIRED) From 67ccabbff18e243b79c6db65d0618ab2e86ae59c Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Fri, 2 Oct 2020 14:09:57 -0600 Subject: [PATCH 026/179] [fix] Segfault when editing pose in moveit_setup_assistant (#2340) --- .../src/widgets/robot_poses_widget.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp b/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp index a17c6365ae..046b02bd96 100644 --- a/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp +++ b/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp @@ -321,13 +321,17 @@ void RobotPosesWidget::editDoubleClicked(int row, int column) // ****************************************************************************************** void RobotPosesWidget::previewClicked(int row, int /*column*/, int /*previous_row*/, int /*previous_column*/) { - const std::string& name = data_table_->item(row, 0)->text().toStdString(); - const std::string& group = data_table_->item(row, 1)->text().toStdString(); + QTableWidgetItem* name = data_table_->item(row, 0); + QTableWidgetItem* group = data_table_->item(row, 1); - // Find the selected in datastructure - srdf::Model::GroupState* pose = findPoseByName(name, group); + // nullptr check before dereferencing + if (name && group) + { + // Find the selected in datastructure + srdf::Model::GroupState* pose = findPoseByName(name->text().toStdString(), group->text().toStdString()); - showPose(pose); + showPose(pose); + } } // ****************************************************************************************** From 0ab82c3c07dc61be39863a5407348869881e1d1e Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Sun, 4 Oct 2020 18:48:42 +0900 Subject: [PATCH 027/179] Fix "Clear Octomap" button, disable when no octomap is published (#2320) * Enable/disable "Clear Octomap" button * Correctly remove octomap from scene in clearOctomap() --- .../planning_scene_monitor/src/planning_scene_monitor.cpp | 2 ++ .../src/motion_planning_frame_objects.cpp | 5 +++++ .../src/motion_planning_frame_planning.cpp | 1 + .../src/ui/motion_planning_rviz_plugin_frame.ui | 3 +++ 4 files changed, 11 insertions(+) diff --git a/moveit_ros/planning/planning_scene_monitor/src/planning_scene_monitor.cpp b/moveit_ros/planning/planning_scene_monitor/src/planning_scene_monitor.cpp index 5f75d60794..2c7c116780 100644 --- a/moveit_ros/planning/planning_scene_monitor/src/planning_scene_monitor.cpp +++ b/moveit_ros/planning/planning_scene_monitor/src/planning_scene_monitor.cpp @@ -537,6 +537,8 @@ void PlanningSceneMonitor::newPlanningSceneCallback(const moveit_msgs::PlanningS void PlanningSceneMonitor::clearOctomap() { + if (scene_->getWorldNonConst()->removeObject(scene_->OCTOMAP_NS)) + triggerSceneUpdateEvent(UPDATE_SCENE); if (octomap_monitor_) { octomap_monitor_->getOcTreePtr()->lockWrite(); diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_objects.cpp b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_objects.cpp index dd21924e7c..1a1ac2d207 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_objects.cpp +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_objects.cpp @@ -890,6 +890,7 @@ void MotionPlanningFrame::populateCollisionObjectsList() { ui_->collision_objects_list->setUpdatesEnabled(false); bool old_state = ui_->collision_objects_list->blockSignals(true); + bool octomap_in_scene = false; { QList sel = ui_->collision_objects_list->selectedItems(); @@ -907,7 +908,10 @@ void MotionPlanningFrame::populateCollisionObjectsList() for (std::size_t i = 0; i < collision_object_names.size(); ++i) { if (collision_object_names[i] == planning_scene::PlanningScene::OCTOMAP_NS) + { + octomap_in_scene = true; continue; + } QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(collision_object_names[i]), ui_->collision_objects_list, (int)i); @@ -939,6 +943,7 @@ void MotionPlanningFrame::populateCollisionObjectsList() } } + ui_->clear_octomap_button->setEnabled(octomap_in_scene); ui_->collision_objects_list->blockSignals(old_state); ui_->collision_objects_list->setUpdatesEnabled(true); selectedCollisionObjectChanged(); diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_planning.cpp b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_planning.cpp index e7fbd57865..de3c3548a2 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_planning.cpp +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_planning.cpp @@ -110,6 +110,7 @@ void MotionPlanningFrame::onClearOctomapClicked() { std_srvs::Empty srv; clear_octomap_service_client_.call(srv); + ui_->clear_octomap_button->setEnabled(false); } bool MotionPlanningFrame::computeCartesianPlan() diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/src/ui/motion_planning_rviz_plugin_frame.ui b/moveit_ros/visualization/motion_planning_rviz_plugin/src/ui/motion_planning_rviz_plugin_frame.ui index 22154c05da..a54c23e4ee 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/src/ui/motion_planning_rviz_plugin_frame.ui +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/src/ui/motion_planning_rviz_plugin_frame.ui @@ -433,6 +433,9 @@ + + false + Clear octomap From 3063b5f6188ed49a4fdf1c8d66b48b1b792c84d4 Mon Sep 17 00:00:00 2001 From: AndyZe Date: Mon, 5 Oct 2020 04:27:25 -0500 Subject: [PATCH 028/179] moveit_cpp: more informative error message, cover another potential failure condition. (#2336) --- .../planning_interface/moveit_cpp/src/moveit_cpp.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/moveit_ros/planning_interface/moveit_cpp/src/moveit_cpp.cpp b/moveit_ros/planning_interface/moveit_cpp/src/moveit_cpp.cpp index 6bf1eccc89..c188bb6a47 100644 --- a/moveit_ros/planning_interface/moveit_cpp/src/moveit_cpp.cpp +++ b/moveit_ros/planning_interface/moveit_cpp/src/moveit_cpp.cpp @@ -244,7 +244,9 @@ std::set MoveItCpp::getPlanningPipelineNames(const std::string& gro std::set result_names; if (!group_name.empty() && groups_pipelines_map_.count(group_name) == 0) { - ROS_ERROR_NAMED(LOGNAME, "There are no planning pipelines loaded for group '%s'.", group_name.c_str()); + ROS_ERROR_NAMED(LOGNAME, + "No planning pipelines loaded for group '%s'. Check planning pipeline and controller setup.", + group_name.c_str()); return result_names; // empty } for (const auto& pipeline_entry : planning_pipelines_) @@ -259,6 +261,11 @@ std::set MoveItCpp::getPlanningPipelineNames(const std::string& gro } result_names.insert(pipeline_name); } + // No valid planning pipelines + if (result_names.empty()) + ROS_ERROR_NAMED(LOGNAME, + "No planning pipelines loaded for group '%s'. Check planning pipeline and controller setup.", + group_name.c_str()); return result_names; } From 6212609b331de2d7f2d22dd7baa03aedebfd0bfa Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Mon, 5 Oct 2020 17:08:19 +0200 Subject: [PATCH 029/179] remove commented, copy-pasted code --- .../src/widgets/virtual_joints_widget.cpp | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp b/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp index 7a56df09f3..d81bded62b 100644 --- a/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp +++ b/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp @@ -255,29 +255,6 @@ void VirtualJointsWidget::editDoubleClicked(int row, int column) // ****************************************************************************************** void VirtualJointsWidget::previewClicked(int row, int column) { - // TODO: highlight the virtual joint? - - /* // Get list of all selected items - QList selected = data_table_->selectedItems(); - - // Check that an element was selected - if( !selected.size() ) - return; - - // Find the selected in datastructure - srdf::Model::GroupState *vjoint = findVjointByName( selected[0]->text().toStdString() ); - - // Set vjoint joint values by adding them to the local joint state map - for( std::map >::const_iterator value_it = vjoint->joint_values_.begin(); - value_it != vjoint->joint_values_.end(); ++value_it ) - { - // Only copy the first joint value - joint_state_map_[ value_it->first ] = value_it->second[0]; - } - - // Update the joints - publishJoints(); - */ } // ****************************************************************************************** From efd20cc440cff9a20b481fe9394c21310365a4a2 Mon Sep 17 00:00:00 2001 From: Peter Mitrano Date: Mon, 5 Oct 2020 12:23:10 -0400 Subject: [PATCH 030/179] Fix ROS namespacing in moveit_commander's PSI (#2347) --- .../planning_scene_interface.py | 7 +- .../python_moveit_commander_ros_namespace.py | 70 +++++++++++++++++++ ...python_moveit_commander_ros_namespace.test | 9 +++ 3 files changed, 83 insertions(+), 3 deletions(-) create mode 100755 moveit_commander/test/python_moveit_commander_ros_namespace.py create mode 100644 moveit_commander/test/python_moveit_commander_ros_namespace.test diff --git a/moveit_commander/src/moveit_commander/planning_scene_interface.py b/moveit_commander/src/moveit_commander/planning_scene_interface.py index cbc3c72021..9de2da057f 100644 --- a/moveit_commander/src/moveit_commander/planning_scene_interface.py +++ b/moveit_commander/src/moveit_commander/planning_scene_interface.py @@ -33,6 +33,7 @@ # Author: Ioan Sucan, Felix Messmer import rospy +from rosgraph.names import ns_join from . import conversions from moveit_msgs.msg import PlanningScene, CollisionObject, AttachedCollisionObject @@ -60,11 +61,11 @@ def __init__(self, ns='', synchronous=False, service_timeout=5.0): """ Create a planning scene interface; it uses both C++ wrapped methods and scene manipulation topics. """ self._psi = _moveit_planning_scene_interface.PlanningSceneInterface(ns) - self._pub_co = rospy.Publisher(ns + '/collision_object', CollisionObject, queue_size=100) - self._pub_aco = rospy.Publisher(ns + '/attached_collision_object', AttachedCollisionObject, queue_size=100) + self._pub_co = rospy.Publisher(ns_join(ns, 'collision_object'), CollisionObject, queue_size=100) + self._pub_aco = rospy.Publisher(ns_join(ns, 'attached_collision_object'), AttachedCollisionObject, queue_size=100) self.__synchronous = synchronous if self.__synchronous: - self._apply_planning_scene_diff = rospy.ServiceProxy(ns + '/apply_planning_scene', ApplyPlanningScene) + self._apply_planning_scene_diff = rospy.ServiceProxy(ns_join(ns, 'apply_planning_scene'), ApplyPlanningScene) self._apply_planning_scene_diff.wait_for_service(service_timeout) def __submit(self, collision_object, attach=False): diff --git a/moveit_commander/test/python_moveit_commander_ros_namespace.py b/moveit_commander/test/python_moveit_commander_ros_namespace.py new file mode 100755 index 0000000000..2b36e937a2 --- /dev/null +++ b/moveit_commander/test/python_moveit_commander_ros_namespace.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +# Software License Agreement (BSD License) +# +# Copyright (c) 2020, Open Source Robotics Foundation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Open Source Robotics Foundation. 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: Peter Mitrano +# +# This test is used to ensure planning with a RobotCommander is +# possible if the robot's move_group node is in a different namespace + +import unittest +import rospy +import rostest +import os + +from moveit_commander import PlanningSceneInterface + + +class PythonMoveitCommanderRosNamespaceTest(unittest.TestCase): + + def test_namespace(self): + self.scene = PlanningSceneInterface() + expected_resolved_co_name = "/test_ros_namespace/collision_object" + expected_resolved_aco_name = "/test_ros_namespace/attached_collision_object" + self.assertEqual(self.scene._pub_co.resolved_name, expected_resolved_co_name) + self.assertEqual(self.scene._pub_aco.resolved_name, expected_resolved_aco_name) + + def test_namespace_synchronous(self): + self.scene = PlanningSceneInterface(synchronous=True) + expected_resolved_apply_diff_name = "/test_ros_namespace/apply_planning_scene" + self.assertEqual(self.scene._apply_planning_scene_diff.resolved_name, expected_resolved_apply_diff_name) + + +if __name__ == '__main__': + PKGNAME = 'moveit_ros_planning_interface' + NODENAME = 'moveit_test_python_moveit_commander_ros_namespace' + rospy.init_node(NODENAME) + rostest.rosrun(PKGNAME, NODENAME, PythonMoveitCommanderRosNamespaceTest) + + # suppress cleanup segfault + os._exit(0) diff --git a/moveit_commander/test/python_moveit_commander_ros_namespace.test b/moveit_commander/test/python_moveit_commander_ros_namespace.test new file mode 100644 index 0000000000..a2c3800c57 --- /dev/null +++ b/moveit_commander/test/python_moveit_commander_ros_namespace.test @@ -0,0 +1,9 @@ + + + + + + + From c6e195891032924202df11b6e060257dc7d354fe Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Mon, 5 Oct 2020 17:46:29 +0200 Subject: [PATCH 031/179] Reorder buttons in GroupEditWidgets --- .../src/widgets/group_edit_widget.cpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/moveit_setup_assistant/src/widgets/group_edit_widget.cpp b/moveit_setup_assistant/src/widgets/group_edit_widget.cpp index 4a0f75ba7f..277b341f4e 100644 --- a/moveit_setup_assistant/src/widgets/group_edit_widget.cpp +++ b/moveit_setup_assistant/src/widgets/group_edit_widget.cpp @@ -142,6 +142,12 @@ GroupEditWidget::GroupEditWidget(QWidget* parent, const MoveItConfigDataPtr& con add_subtitle->setFont(add_subtitle_font); recommended_options->addWidget(add_subtitle, 0, Qt::AlignLeft); + // Save and add chain + QPushButton* btn_save_chain = new QPushButton("Add Kin. Chain", this); + btn_save_chain->setMaximumWidth(200); + connect(btn_save_chain, SIGNAL(clicked()), this, SIGNAL(saveChain())); + recommended_options->addWidget(btn_save_chain); + // Save and add joints QPushButton* btn_save_joints = new QPushButton("Add Joints", this); btn_save_joints->setMaximumWidth(200); @@ -153,24 +159,18 @@ GroupEditWidget::GroupEditWidget(QWidget* parent, const MoveItConfigDataPtr& con add_subtitle2->setFont(add_subtitle_font); advanced_options->addWidget(add_subtitle2, 0, Qt::AlignLeft); - // Save and add links - QPushButton* btn_save_links = new QPushButton("Add Links", this); - btn_save_links->setMaximumWidth(200); - connect(btn_save_links, SIGNAL(clicked()), this, SIGNAL(saveLinks())); - advanced_options->addWidget(btn_save_links); - - // Save and add chain - QPushButton* btn_save_chain = new QPushButton("Add Kin. Chain", this); - btn_save_chain->setMaximumWidth(200); - connect(btn_save_chain, SIGNAL(clicked()), this, SIGNAL(saveChain())); - advanced_options->addWidget(btn_save_chain); - // Save and add subgroups QPushButton* btn_save_subgroups = new QPushButton("Add Subgroups", this); btn_save_subgroups->setMaximumWidth(200); connect(btn_save_subgroups, SIGNAL(clicked()), this, SIGNAL(saveSubgroups())); advanced_options->addWidget(btn_save_subgroups); + // Save and add links + QPushButton* btn_save_links = new QPushButton("Add Links", this); + btn_save_links->setMaximumWidth(200); + connect(btn_save_links, SIGNAL(clicked()), this, SIGNAL(saveLinks())); + advanced_options->addWidget(btn_save_links); + // Add layouts new_buttons_layout_container->addLayout(label_layout); new_buttons_layout_container->addLayout(recommended_options); From d991a230c606e6b972f5e6541383ce9ab77e6aed Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Mon, 5 Oct 2020 18:24:27 +0200 Subject: [PATCH 032/179] Replace dummy QWidgets with QSpacerItems --- .../src/widgets/controller_edit_widget.cpp | 10 +++------- .../src/widgets/double_list_widget.cpp | 4 +--- .../src/widgets/end_effectors_widget.cpp | 8 ++------ .../src/widgets/group_edit_widget.cpp | 10 +++------- .../src/widgets/kinematic_chain_widget.cpp | 4 +--- .../src/widgets/planning_groups_widget.cpp | 4 +--- .../src/widgets/robot_poses_widget.cpp | 8 ++------ .../src/widgets/ros_controllers_widget.cpp | 4 +--- .../src/widgets/start_screen_widget.cpp | 4 +--- .../src/widgets/virtual_joints_widget.cpp | 8 ++------ 10 files changed, 17 insertions(+), 47 deletions(-) diff --git a/moveit_setup_assistant/src/widgets/controller_edit_widget.cpp b/moveit_setup_assistant/src/widgets/controller_edit_widget.cpp index f86d0f7d5a..62c2feb300 100644 --- a/moveit_setup_assistant/src/widgets/controller_edit_widget.cpp +++ b/moveit_setup_assistant/src/widgets/controller_edit_widget.cpp @@ -114,10 +114,8 @@ ControllerEditWidget::ControllerEditWidget(QWidget* parent, const MoveItConfigDa new_buttons_widget_->setLayout(new_buttons_layout); layout->addWidget(new_buttons_widget_); - // Verticle Spacer ----------------------------------------------------- - QWidget* vspacer = new QWidget(this); - vspacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); - layout->addWidget(vspacer); + // Vertical Spacer + layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); // Bottom Controls --------------------------------------------------------- QHBoxLayout* controls_layout = new QHBoxLayout(); @@ -130,9 +128,7 @@ ControllerEditWidget::ControllerEditWidget(QWidget* parent, const MoveItConfigDa controls_layout->setAlignment(btn_delete_, Qt::AlignRight); // Horizontal Spacer - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controls_layout->addWidget(spacer); + controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); // Save btn_save_ = new QPushButton("&Save", this); diff --git a/moveit_setup_assistant/src/widgets/double_list_widget.cpp b/moveit_setup_assistant/src/widgets/double_list_widget.cpp index 59e550ba29..51ab5f9980 100644 --- a/moveit_setup_assistant/src/widgets/double_list_widget.cpp +++ b/moveit_setup_assistant/src/widgets/double_list_widget.cpp @@ -140,9 +140,7 @@ DoubleListWidget::DoubleListWidget(QWidget* parent, const MoveItConfigDataPtr& c controls_layout->setContentsMargins(0, 25, 0, 15); // Spacer - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controls_layout->addWidget(spacer); + controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); // Save QPushButton* btn_save = new QPushButton("&Save", this); diff --git a/moveit_setup_assistant/src/widgets/end_effectors_widget.cpp b/moveit_setup_assistant/src/widgets/end_effectors_widget.cpp index a38c5f3140..9a434cbc1d 100644 --- a/moveit_setup_assistant/src/widgets/end_effectors_widget.cpp +++ b/moveit_setup_assistant/src/widgets/end_effectors_widget.cpp @@ -116,9 +116,7 @@ QWidget* EndEffectorsWidget::createContentsWidget() QHBoxLayout* controls_layout = new QHBoxLayout(); // Spacer - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controls_layout->addWidget(spacer); + controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); // Edit Selected Button btn_edit_ = new QPushButton("&Edit Selected", this); @@ -196,9 +194,7 @@ QWidget* EndEffectorsWidget::createEditWidget() controls_layout->setContentsMargins(0, 25, 0, 15); // Spacer - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controls_layout->addWidget(spacer); + controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); // Save btn_save_ = new QPushButton("&Save", this); diff --git a/moveit_setup_assistant/src/widgets/group_edit_widget.cpp b/moveit_setup_assistant/src/widgets/group_edit_widget.cpp index 277b341f4e..02fc45688f 100644 --- a/moveit_setup_assistant/src/widgets/group_edit_widget.cpp +++ b/moveit_setup_assistant/src/widgets/group_edit_widget.cpp @@ -180,10 +180,8 @@ GroupEditWidget::GroupEditWidget(QWidget* parent, const MoveItConfigDataPtr& con new_buttons_widget_->setLayout(new_buttons_layout_container); layout->addWidget(new_buttons_widget_); - // Verticle Spacer ----------------------------------------------------- - QWidget* vspacer = new QWidget(this); - vspacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); - layout->addWidget(vspacer); + // Vertical Spacer + layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); // Bottom Controls --------------------------------------------------------- QHBoxLayout* controls_layout = new QHBoxLayout(); @@ -196,9 +194,7 @@ GroupEditWidget::GroupEditWidget(QWidget* parent, const MoveItConfigDataPtr& con controls_layout->setAlignment(btn_delete_, Qt::AlignRight); // Horizontal Spacer - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controls_layout->addWidget(spacer); + controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); // Save btn_save_ = new QPushButton("&Save", this); diff --git a/moveit_setup_assistant/src/widgets/kinematic_chain_widget.cpp b/moveit_setup_assistant/src/widgets/kinematic_chain_widget.cpp index 926cbb18f4..f6a0caa7df 100644 --- a/moveit_setup_assistant/src/widgets/kinematic_chain_widget.cpp +++ b/moveit_setup_assistant/src/widgets/kinematic_chain_widget.cpp @@ -108,9 +108,7 @@ KinematicChainWidget::KinematicChainWidget(QWidget* parent, const MoveItConfigDa controls_layout->addWidget(expand_controls); // Spacer - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controls_layout->addWidget(spacer); + controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); // Save QPushButton* btn_save = new QPushButton("&Save", this); diff --git a/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp b/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp index d0890001f3..5fa5698cc2 100644 --- a/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp +++ b/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp @@ -208,9 +208,7 @@ QWidget* PlanningGroupsWidget::createContentsWidget() controls_layout->addWidget(expand_controls); // Spacer - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controls_layout->addWidget(spacer); + controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); // Delete Selected Button btn_delete_ = new QPushButton("&Delete Selected", this); diff --git a/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp b/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp index 046b02bd96..f753e20ab4 100644 --- a/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp +++ b/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp @@ -154,9 +154,7 @@ QWidget* RobotPosesWidget::createContentsWidget() controls_layout->setAlignment(btn_play, Qt::AlignLeft); // Spacer - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controls_layout->addWidget(spacer); + controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); // Edit Selected Button btn_edit_ = new QPushButton("&Edit Selected", this); @@ -258,9 +256,7 @@ QWidget* RobotPosesWidget::createEditWidget() controls_layout->setContentsMargins(0, 25, 0, 15); // Spacer - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controls_layout->addWidget(spacer); + controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); // Save btn_save_ = new QPushButton("&Save", this); diff --git a/moveit_setup_assistant/src/widgets/ros_controllers_widget.cpp b/moveit_setup_assistant/src/widgets/ros_controllers_widget.cpp index cc70aab17a..8a896e72d1 100644 --- a/moveit_setup_assistant/src/widgets/ros_controllers_widget.cpp +++ b/moveit_setup_assistant/src/widgets/ros_controllers_widget.cpp @@ -162,9 +162,7 @@ QWidget* ROSControllersWidget::createContentsWidget() controls_layout_->addWidget(expand_controls); // Spacer - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controls_layout_->addWidget(spacer); + controls_layout_->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); // Delete btn_delete_ = new QPushButton("&Delete Controller", this); diff --git a/moveit_setup_assistant/src/widgets/start_screen_widget.cpp b/moveit_setup_assistant/src/widgets/start_screen_widget.cpp index 337f0c7c79..47759c4f37 100644 --- a/moveit_setup_assistant/src/widgets/start_screen_widget.cpp +++ b/moveit_setup_assistant/src/widgets/start_screen_widget.cpp @@ -188,9 +188,7 @@ StartScreenWidget::StartScreenWidget(QWidget* parent, const MoveItConfigDataPtr& layout->addLayout(hlayout); // Verticle Spacer - QWidget* vspacer = new QWidget(this); - vspacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); - layout->addWidget(vspacer); + layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); // Attach bottom layout layout->addWidget(next_label_); diff --git a/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp b/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp index d81bded62b..711125fe81 100644 --- a/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp +++ b/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp @@ -114,9 +114,7 @@ QWidget* VirtualJointsWidget::createContentsWidget() QHBoxLayout* controls_layout = new QHBoxLayout(); // Spacer - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controls_layout->addWidget(spacer); + controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); // Edit Selected Button btn_edit_ = new QPushButton("&Edit Selected", this); @@ -194,9 +192,7 @@ QWidget* VirtualJointsWidget::createEditWidget() controls_layout->setContentsMargins(0, 25, 0, 15); // Spacer - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controls_layout->addWidget(spacer); + controls_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); // Save QPushButton* btn_save = new QPushButton("&Save", this); From d31d712cae0186da04ef8a7e9d9c3c02570c97f1 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Mon, 5 Oct 2020 19:47:14 +0200 Subject: [PATCH 033/179] Use QStackedWidget instead of QWidget+QStackedLayout --- .../src/widgets/end_effectors_widget.cpp | 25 +++++++---------- .../src/widgets/end_effectors_widget.h | 4 +-- .../src/widgets/passive_joints_widget.h | 1 - .../src/widgets/planning_groups_widget.cpp | 27 ++++++++----------- .../src/widgets/planning_groups_widget.h | 4 +-- .../src/widgets/robot_poses_widget.cpp | 25 +++++++---------- .../src/widgets/robot_poses_widget.h | 4 +-- .../src/widgets/ros_controllers_widget.cpp | 23 ++++++---------- .../src/widgets/ros_controllers_widget.h | 4 +-- .../src/widgets/setup_assistant_widget.cpp | 11 +++----- .../src/widgets/setup_assistant_widget.h | 3 +-- .../src/widgets/virtual_joints_widget.cpp | 23 +++++++--------- .../src/widgets/virtual_joints_widget.h | 4 +-- 13 files changed, 62 insertions(+), 96 deletions(-) diff --git a/moveit_setup_assistant/src/widgets/end_effectors_widget.cpp b/moveit_setup_assistant/src/widgets/end_effectors_widget.cpp index 9a434cbc1d..16f89b5287 100644 --- a/moveit_setup_assistant/src/widgets/end_effectors_widget.cpp +++ b/moveit_setup_assistant/src/widgets/end_effectors_widget.cpp @@ -68,15 +68,10 @@ EndEffectorsWidget::EndEffectorsWidget(QWidget* parent, const MoveItConfigDataPt effector_edit_widget_ = createEditWidget(); // Create stacked layout ----------------------------------------- - stacked_layout_ = new QStackedLayout(this); - stacked_layout_->addWidget(effector_list_widget_); // screen index 0 - stacked_layout_->addWidget(effector_edit_widget_); // screen index 1 - - // Create Widget wrapper for layout - QWidget* stacked_layout_widget = new QWidget(this); - stacked_layout_widget->setLayout(stacked_layout_); - - layout->addWidget(stacked_layout_widget); + stacked_widget_ = new QStackedWidget(this); + stacked_widget_->addWidget(effector_list_widget_); // screen index 0 + stacked_widget_->addWidget(effector_edit_widget_); // screen index 1 + layout->addWidget(stacked_widget_); // Finish Layout -------------------------------------------------- this->setLayout(layout); @@ -234,7 +229,7 @@ void EndEffectorsWidget::showNewScreen() parent_group_name_field_->clearEditText(); // actually this just chooses first option // Switch to screen - stacked_layout_->setCurrentIndex(1); + stacked_widget_->setCurrentIndex(1); // Announce that this widget is in modal mode Q_EMIT isModal(true); @@ -276,7 +271,7 @@ void EndEffectorsWidget::previewClicked(int row, int column) void EndEffectorsWidget::previewClickedString(const QString& name) { // Don't highlight if we are on the overview end effectors screen. we are just populating drop down box - if (stacked_layout_->currentIndex() == 0) + if (stacked_widget_->currentIndex() == 0) return; // Unhighlight all links @@ -344,7 +339,7 @@ void EndEffectorsWidget::edit(const std::string& name) parent_group_name_field_->setCurrentIndex(index); // Switch to screen - stacked_layout_->setCurrentIndex(1); + stacked_widget_->setCurrentIndex(1); // Announce that this widget is in modal mode Q_EMIT isModal(true); @@ -570,7 +565,7 @@ void EndEffectorsWidget::doneEditing() loadDataTable(); // Switch to screen - stacked_layout_->setCurrentIndex(0); + stacked_widget_->setCurrentIndex(0); // Announce that this widget is not in modal mode Q_EMIT isModal(false); @@ -582,7 +577,7 @@ void EndEffectorsWidget::doneEditing() void EndEffectorsWidget::cancelEditing() { // Switch to screen - stacked_layout_->setCurrentIndex(0); + stacked_widget_->setCurrentIndex(0); // Re-highlight the currently selected end effector group previewClicked(0, 0); // the number parameters are actually meaningless @@ -650,7 +645,7 @@ void EndEffectorsWidget::loadDataTable() void EndEffectorsWidget::focusGiven() { // Show the current effectors screen - stacked_layout_->setCurrentIndex(0); + stacked_widget_->setCurrentIndex(0); // Load the data to the tree loadDataTable(); diff --git a/moveit_setup_assistant/src/widgets/end_effectors_widget.h b/moveit_setup_assistant/src/widgets/end_effectors_widget.h index dd75249b4e..4c818d0b30 100644 --- a/moveit_setup_assistant/src/widgets/end_effectors_widget.h +++ b/moveit_setup_assistant/src/widgets/end_effectors_widget.h @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include @@ -82,7 +82,7 @@ class EndEffectorsWidget : public SetupScreenWidget QPushButton* btn_delete_; QPushButton* btn_save_; QPushButton* btn_cancel_; - QStackedLayout* stacked_layout_; + QStackedWidget* stacked_widget_; QLineEdit* effector_name_field_; QComboBox* parent_name_field_; QComboBox* parent_group_name_field_; diff --git a/moveit_setup_assistant/src/widgets/passive_joints_widget.h b/moveit_setup_assistant/src/widgets/passive_joints_widget.h index 8e23450eef..802fba7076 100644 --- a/moveit_setup_assistant/src/widgets/passive_joints_widget.h +++ b/moveit_setup_assistant/src/widgets/passive_joints_widget.h @@ -44,7 +44,6 @@ #include #include #include -#include #include #include diff --git a/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp b/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp index 5fa5698cc2..1a600c4f7a 100644 --- a/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp +++ b/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp @@ -57,7 +57,7 @@ #include #include #include -#include +#include #include #include #include @@ -154,24 +154,19 @@ PlanningGroupsWidget::PlanningGroupsWidget(QWidget* parent, const MoveItConfigDa connect(group_edit_widget_, SIGNAL(saveSubgroups()), this, SLOT(saveGroupScreenSubgroups())); // Combine into stack - stacked_layout_ = new QStackedLayout(this); - stacked_layout_->addWidget(groups_tree_widget_); // screen index 0 - stacked_layout_->addWidget(joints_widget_); // screen index 1 - stacked_layout_->addWidget(links_widget_); // screen index 2 - stacked_layout_->addWidget(chain_widget_); // screen index 3 - stacked_layout_->addWidget(subgroups_widget_); // screen index 4 - stacked_layout_->addWidget(group_edit_widget_); // screen index 5 + stacked_widget_ = new QStackedWidget(this); + stacked_widget_->addWidget(groups_tree_widget_); // screen index 0 + stacked_widget_->addWidget(joints_widget_); // screen index 1 + stacked_widget_->addWidget(links_widget_); // screen index 2 + stacked_widget_->addWidget(chain_widget_); // screen index 3 + stacked_widget_->addWidget(subgroups_widget_); // screen index 4 + stacked_widget_->addWidget(group_edit_widget_); // screen index 5 showMainScreen(); // Finish GUI ----------------------------------------------------------- - // Create Widget wrapper for layout - QWidget* stacked_layout_widget = new QWidget(this); - stacked_layout_widget->setLayout(stacked_layout_); - - layout->addWidget(stacked_layout_widget); - + layout->addWidget(stacked_widget_); setLayout(layout); // process the gui @@ -1394,7 +1389,7 @@ void PlanningGroupsWidget::alterTree(const QString& link) // ****************************************************************************************** void PlanningGroupsWidget::showMainScreen() { - stacked_layout_->setCurrentIndex(0); + stacked_widget_->setCurrentIndex(0); // Announce that this widget is not in modal mode Q_EMIT isModal(false); @@ -1405,7 +1400,7 @@ void PlanningGroupsWidget::showMainScreen() // ****************************************************************************************** void PlanningGroupsWidget::changeScreen(int index) { - stacked_layout_->setCurrentIndex(index); + stacked_widget_->setCurrentIndex(index); // Announce this widget's mode Q_EMIT isModal(index != 0); diff --git a/moveit_setup_assistant/src/widgets/planning_groups_widget.h b/moveit_setup_assistant/src/widgets/planning_groups_widget.h index 5b850dc3db..ce2786a41d 100644 --- a/moveit_setup_assistant/src/widgets/planning_groups_widget.h +++ b/moveit_setup_assistant/src/widgets/planning_groups_widget.h @@ -39,7 +39,7 @@ // Qt class QPushButton; -class QStackedLayout; +class QStackedWidget; class QTreeWidget; class QTreeWidgetItem; @@ -147,7 +147,7 @@ private Q_SLOTS: QTreeWidget* groups_tree_; /// For changing between table and different add/edit views - QStackedLayout* stacked_layout_; + QStackedWidget* stacked_widget_; /// Show and hide edit button QPushButton* btn_edit_; diff --git a/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp b/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp index f753e20ab4..e706ab57ca 100644 --- a/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp +++ b/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp @@ -75,15 +75,10 @@ RobotPosesWidget::RobotPosesWidget(QWidget* parent, const MoveItConfigDataPtr& c pose_edit_widget_ = createEditWidget(); // Create stacked layout ----------------------------------------- - stacked_layout_ = new QStackedLayout(this); - stacked_layout_->addWidget(pose_list_widget_); // screen index 0 - stacked_layout_->addWidget(pose_edit_widget_); // screen index 1 - - // Create Widget wrapper for layout - QWidget* stacked_layout_widget = new QWidget(this); - stacked_layout_widget->setLayout(stacked_layout_); - - layout->addWidget(stacked_layout_widget); + stacked_widget_ = new QStackedWidget(this); + stacked_widget_->addWidget(pose_list_widget_); // screen index 0 + stacked_widget_->addWidget(pose_edit_widget_); // screen index 1 + layout->addWidget(stacked_widget_); // Finish Layout -------------------------------------------------- this->setLayout(layout); @@ -287,7 +282,7 @@ QWidget* RobotPosesWidget::createEditWidget() void RobotPosesWidget::showNewScreen() { // Switch to screen - do this before clearEditText() - stacked_layout_->setCurrentIndex(1); + stacked_widget_->setCurrentIndex(1); // Remember that this is a new pose current_edit_pose_ = nullptr; @@ -449,7 +444,7 @@ void RobotPosesWidget::edit(int row) publishJoints(); // Switch to screen - do this before setCurrentIndex - stacked_layout_->setCurrentIndex(1); + stacked_widget_->setCurrentIndex(1); // Announce that this widget is in modal mode Q_EMIT isModal(true); @@ -481,7 +476,7 @@ void RobotPosesWidget::loadJointSliders(const QString& selected) { // Ignore this event if the combo box is empty. This occurs when clearing the combo box and reloading with the // newest groups. Also ignore if we are not on the edit screen - if (!group_name_field_->count() || selected.isEmpty() || stacked_layout_->currentIndex() == 0) + if (!group_name_field_->count() || selected.isEmpty() || stacked_widget_->currentIndex() == 0) return; // Get group name from input @@ -708,7 +703,7 @@ void RobotPosesWidget::doneEditing() loadDataTable(); // Switch to screen - stacked_layout_->setCurrentIndex(0); + stacked_widget_->setCurrentIndex(0); // Announce that this widget is done with modal mode Q_EMIT isModal(false); @@ -720,7 +715,7 @@ void RobotPosesWidget::doneEditing() void RobotPosesWidget::cancelEditing() { // Switch to screen - stacked_layout_->setCurrentIndex(0); + stacked_widget_->setCurrentIndex(0); // Announce that this widget is done with modal mode Q_EMIT isModal(false); @@ -777,7 +772,7 @@ void RobotPosesWidget::loadDataTable() void RobotPosesWidget::focusGiven() { // Show the current poses screen - stacked_layout_->setCurrentIndex(0); + stacked_widget_->setCurrentIndex(0); // Load the data to the tree loadDataTable(); diff --git a/moveit_setup_assistant/src/widgets/robot_poses_widget.h b/moveit_setup_assistant/src/widgets/robot_poses_widget.h index ffdbb73217..984876fbfb 100644 --- a/moveit_setup_assistant/src/widgets/robot_poses_widget.h +++ b/moveit_setup_assistant/src/widgets/robot_poses_widget.h @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include @@ -84,7 +84,7 @@ class RobotPosesWidget : public SetupScreenWidget QPushButton* btn_delete_; QPushButton* btn_save_; QPushButton* btn_cancel_; - QStackedLayout* stacked_layout_; + QStackedWidget* stacked_widget_; QScrollArea* scroll_area_; QVBoxLayout* column2_; QLineEdit* pose_name_field_; diff --git a/moveit_setup_assistant/src/widgets/ros_controllers_widget.cpp b/moveit_setup_assistant/src/widgets/ros_controllers_widget.cpp index 8a896e72d1..c4e5d6dff1 100644 --- a/moveit_setup_assistant/src/widgets/ros_controllers_widget.cpp +++ b/moveit_setup_assistant/src/widgets/ros_controllers_widget.cpp @@ -95,19 +95,12 @@ ROSControllersWidget::ROSControllersWidget(QWidget* parent, const MoveItConfigDa connect(controller_edit_widget_, SIGNAL(saveJointsGroups()), this, SLOT(saveControllerScreenGroups())); // Combine into stack - stacked_layout_ = new QStackedLayout(this); - stacked_layout_->addWidget(controllers_tree_widget_); // screen index 0 - stacked_layout_->addWidget(joints_widget_); // screen index 1 - stacked_layout_->addWidget(controller_edit_widget_); // screen index 2 - stacked_layout_->addWidget(joint_groups_widget_); // screen index 3 - - // Finish GUI ----------------------------------------------------------- - - // Create Widget wrapper for layout - QWidget* stacked_layout_widget = new QWidget(this); - stacked_layout_widget->setLayout(stacked_layout_); - - layout->addWidget(stacked_layout_widget); + stacked_widget_ = new QStackedWidget(this); + stacked_widget_->addWidget(controllers_tree_widget_); // screen index 0 + stacked_widget_->addWidget(joints_widget_); // screen index 1 + stacked_widget_->addWidget(controller_edit_widget_); // screen index 2 + stacked_widget_->addWidget(joint_groups_widget_); // screen index 3 + layout->addWidget(stacked_widget_); this->setLayout(layout); } @@ -803,7 +796,7 @@ void ROSControllersWidget::editController() // ****************************************************************************************** void ROSControllersWidget::showMainScreen() { - stacked_layout_->setCurrentIndex(0); + stacked_widget_->setCurrentIndex(0); // Announce that this widget is not in modal mode Q_EMIT isModal(false); @@ -814,7 +807,7 @@ void ROSControllersWidget::showMainScreen() // ****************************************************************************************** void ROSControllersWidget::changeScreen(int index) { - stacked_layout_->setCurrentIndex(index); + stacked_widget_->setCurrentIndex(index); // Announce this widget's mode Q_EMIT isModal(index != 0); diff --git a/moveit_setup_assistant/src/widgets/ros_controllers_widget.h b/moveit_setup_assistant/src/widgets/ros_controllers_widget.h index 57fc7d3c8b..5e0485c9c3 100644 --- a/moveit_setup_assistant/src/widgets/ros_controllers_widget.h +++ b/moveit_setup_assistant/src/widgets/ros_controllers_widget.h @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include // SA @@ -129,7 +129,7 @@ private Q_SLOTS: QWidget* controllers_tree_widget_; /// For changing between table and different add/edit views - QStackedLayout* stacked_layout_; + QStackedWidget* stacked_widget_; ControllerEditWidget* controller_edit_widget_; QPushButton* btn_delete_; diff --git a/moveit_setup_assistant/src/widgets/setup_assistant_widget.cpp b/moveit_setup_assistant/src/widgets/setup_assistant_widget.cpp index 8feffda315..5ecc8bd635 100644 --- a/moveit_setup_assistant/src/widgets/setup_assistant_widget.cpp +++ b/moveit_setup_assistant/src/widgets/setup_assistant_widget.cpp @@ -38,7 +38,7 @@ #include "setup_screen_widget.h" // a base class for screens in the setup assistant #include "setup_assistant_widget.h" // Qt -#include +#include #include #include #include @@ -83,14 +83,9 @@ SetupAssistantWidget::SetupAssistantWidget(QWidget* parent, const boost::program layout->setAlignment(Qt::AlignTop); // Create main content stack for various screens - main_content_ = new QStackedLayout(); + main_content_ = new QStackedWidget(); current_index_ = 0; - // Wrap main_content_ with a widget - middle_frame_ = new QWidget(this); - middle_frame_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - middle_frame_->setLayout(main_content_); - // Screens -------------------------------------------------------- // Start Screen @@ -145,7 +140,7 @@ SetupAssistantWidget::SetupAssistantWidget(QWidget* parent, const boost::program splitter_ = new QSplitter(Qt::Horizontal, this); splitter_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); splitter_->addWidget(navs_view_); - splitter_->addWidget(middle_frame_); + splitter_->addWidget(main_content_); splitter_->addWidget(rviz_container_); splitter_->setHandleWidth(6); // splitter_->setCollapsible( 0, false ); // don't let navigation collapse diff --git a/moveit_setup_assistant/src/widgets/setup_assistant_widget.h b/moveit_setup_assistant/src/widgets/setup_assistant_widget.h index 98c7878ddb..62392d5c8e 100644 --- a/moveit_setup_assistant/src/widgets/setup_assistant_widget.h +++ b/moveit_setup_assistant/src/widgets/setup_assistant_widget.h @@ -203,10 +203,9 @@ private Q_SLOTS: QList nav_name_list_; NavigationWidget* navs_view_; - QWidget* middle_frame_; QWidget* rviz_container_; QSplitter* splitter_; - QStackedLayout* main_content_; + QStackedWidget* main_content_; int current_index_; boost::mutex change_screen_lock_; diff --git a/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp b/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp index 711125fe81..5db4c21baa 100644 --- a/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp +++ b/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp @@ -65,16 +65,11 @@ VirtualJointsWidget::VirtualJointsWidget(QWidget* parent, const MoveItConfigData vjoint_list_widget_ = createContentsWidget(); vjoint_edit_widget_ = createEditWidget(); - // Create stacked layout ----------------------------------------- - stacked_layout_ = new QStackedLayout(this); - stacked_layout_->addWidget(vjoint_list_widget_); // screen index 0 - stacked_layout_->addWidget(vjoint_edit_widget_); // screen index 1 - // Create Widget wrapper for layout - QWidget* stacked_layout_widget = new QWidget(this); - stacked_layout_widget->setLayout(stacked_layout_); - - layout->addWidget(stacked_layout_widget); + stacked_widget_ = new QStackedWidget(this); + stacked_widget_->addWidget(vjoint_list_widget_); // screen index 0 + stacked_widget_->addWidget(vjoint_edit_widget_); // screen index 1 + layout->addWidget(stacked_widget_); // Finish Layout -------------------------------------------------- this->setLayout(layout); @@ -232,7 +227,7 @@ void VirtualJointsWidget::showNewScreen() joint_type_field_->clearEditText(); // actually this just chooses first option // Switch to screen - stacked_layout_->setCurrentIndex(1); + stacked_widget_->setCurrentIndex(1); // Announce that this widget is in modal mode Q_EMIT isModal(true); @@ -303,7 +298,7 @@ void VirtualJointsWidget::edit(const std::string& name) joint_type_field_->setCurrentIndex(index); // Switch to screen - stacked_layout_->setCurrentIndex(1); + stacked_widget_->setCurrentIndex(1); // Announce that this widget is in modal mode Q_EMIT isModal(true); @@ -510,7 +505,7 @@ void VirtualJointsWidget::doneEditing() loadDataTable(); // Switch to screen - stacked_layout_->setCurrentIndex(0); + stacked_widget_->setCurrentIndex(0); // Announce that this widget is not in modal mode Q_EMIT isModal(false); @@ -528,7 +523,7 @@ void VirtualJointsWidget::doneEditing() void VirtualJointsWidget::cancelEditing() { // Switch to screen - stacked_layout_->setCurrentIndex(0); + stacked_widget_->setCurrentIndex(0); // Announce that this widget is not in modal mode Q_EMIT isModal(false); @@ -593,7 +588,7 @@ void VirtualJointsWidget::loadDataTable() void VirtualJointsWidget::focusGiven() { // Show the current vjoints screen - stacked_layout_->setCurrentIndex(0); + stacked_widget_->setCurrentIndex(0); // Load the data to the tree loadDataTable(); diff --git a/moveit_setup_assistant/src/widgets/virtual_joints_widget.h b/moveit_setup_assistant/src/widgets/virtual_joints_widget.h index c8e7361037..9e9cd03854 100644 --- a/moveit_setup_assistant/src/widgets/virtual_joints_widget.h +++ b/moveit_setup_assistant/src/widgets/virtual_joints_widget.h @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include #include @@ -80,7 +80,7 @@ class VirtualJointsWidget : public SetupScreenWidget QPushButton* btn_delete_; QPushButton* btn_save_; QPushButton* btn_cancel_; - QStackedLayout* stacked_layout_; + QStackedWidget* stacked_widget_; QLineEdit* vjoint_name_field_; QLineEdit* parent_name_field_; QComboBox* child_link_field_; From 42a9cf1c02ea079abef8c89f59290280f33602b0 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Mon, 5 Oct 2020 21:20:00 +0200 Subject: [PATCH 034/179] Increase minimal window size --- moveit_setup_assistant/src/setup_assistant_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moveit_setup_assistant/src/setup_assistant_main.cpp b/moveit_setup_assistant/src/setup_assistant_main.cpp index a514696622..0f4485dd2d 100644 --- a/moveit_setup_assistant/src/setup_assistant_main.cpp +++ b/moveit_setup_assistant/src/setup_assistant_main.cpp @@ -95,8 +95,8 @@ int main(int argc, char** argv) // Load Qt Widget moveit_setup_assistant::SetupAssistantWidget saw(nullptr, vm); - saw.setMinimumWidth(980); - saw.setMinimumHeight(550); + saw.setMinimumWidth(1090); + saw.setMinimumHeight(600); // saw.setWindowState( Qt::WindowMaximized ); saw.show(); From e0ecb24a1bf24964d8bf0b06353c87a4c71fba6e Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Mon, 5 Oct 2020 22:33:52 +0200 Subject: [PATCH 035/179] Cleanup Qt includes --- .../src/widgets/author_information_widget.cpp | 6 ++-- .../src/widgets/author_information_widget.h | 5 +-- .../widgets/configuration_files_widget.cpp | 19 ++++++++--- .../src/widgets/configuration_files_widget.h | 14 ++++---- .../src/widgets/controller_edit_widget.cpp | 10 ++++-- .../src/widgets/controller_edit_widget.h | 8 ++--- .../src/widgets/default_collisions_widget.cpp | 22 ++++++++---- .../src/widgets/default_collisions_widget.h | 34 +++++++++++-------- .../src/widgets/double_list_widget.cpp | 12 ++++--- .../src/widgets/double_list_widget.h | 6 ++-- .../src/widgets/end_effectors_widget.cpp | 16 ++++++++- .../src/widgets/end_effectors_widget.h | 17 +++------- .../src/widgets/group_edit_widget.cpp | 13 ++++--- .../src/widgets/group_edit_widget.h | 8 ++--- .../src/widgets/header_widget.cpp | 8 +++-- .../src/widgets/header_widget.h | 5 +-- .../src/widgets/kinematic_chain_widget.cpp | 3 +- .../src/widgets/kinematic_chain_widget.h | 6 ++-- .../src/widgets/navigation_widget.cpp | 3 ++ .../src/widgets/navigation_widget.h | 5 +-- .../src/widgets/passive_joints_widget.cpp | 5 +++ .../src/widgets/passive_joints_widget.h | 13 +------ .../src/widgets/perception_widget.cpp | 9 +++-- .../src/widgets/perception_widget.h | 9 ++--- .../src/widgets/planning_groups_widget.cpp | 10 ++++-- .../src/widgets/robot_poses_widget.cpp | 13 +++++-- .../src/widgets/robot_poses_widget.h | 21 +++++------- .../src/widgets/ros_controllers_widget.cpp | 18 ++++++++-- .../src/widgets/ros_controllers_widget.h | 19 +++++------ .../src/widgets/setup_assistant_widget.cpp | 15 +++++--- .../src/widgets/setup_assistant_widget.h | 18 +++------- .../src/widgets/simulation_widget.cpp | 7 ++-- .../src/widgets/simulation_widget.h | 6 ++-- .../src/widgets/start_screen_widget.cpp | 17 ++++++---- .../src/widgets/start_screen_widget.h | 9 ++--- .../src/widgets/virtual_joints_widget.cpp | 13 ++++++- .../src/widgets/virtual_joints_widget.h | 16 ++++----- 37 files changed, 253 insertions(+), 185 deletions(-) diff --git a/moveit_setup_assistant/src/widgets/author_information_widget.cpp b/moveit_setup_assistant/src/widgets/author_information_widget.cpp index fc9dc50727..1ca1d6cbbb 100644 --- a/moveit_setup_assistant/src/widgets/author_information_widget.cpp +++ b/moveit_setup_assistant/src/widgets/author_information_widget.cpp @@ -39,10 +39,10 @@ #include #include #include -#include -// ROS +#include +#include #include "author_information_widget.h" -#include +#include "header_widget.h" namespace moveit_setup_assistant { diff --git a/moveit_setup_assistant/src/widgets/author_information_widget.h b/moveit_setup_assistant/src/widgets/author_information_widget.h index 15ed0036ec..68f32e122e 100644 --- a/moveit_setup_assistant/src/widgets/author_information_widget.h +++ b/moveit_setup_assistant/src/widgets/author_information_widget.h @@ -37,15 +37,12 @@ #ifndef MOVEIT_ROS_MOVEIT_SETUP_ASSISTANT_WIDGETS_AUTHOR_INFORMATION_WIDGET_ #define MOVEIT_ROS_MOVEIT_SETUP_ASSISTANT_WIDGETS_AUTHOR_INFORMATION_WIDGET_ -#include -#include -#include +class QLineEdit; #ifndef Q_MOC_RUN #include #endif -#include "header_widget.h" #include "setup_screen_widget.h" // a base class for screens in the setup assistant namespace moveit_setup_assistant diff --git a/moveit_setup_assistant/src/widgets/configuration_files_widget.cpp b/moveit_setup_assistant/src/widgets/configuration_files_widget.cpp index 689aa91601..fe23804e36 100644 --- a/moveit_setup_assistant/src/widgets/configuration_files_widget.cpp +++ b/moveit_setup_assistant/src/widgets/configuration_files_widget.cpp @@ -35,15 +35,24 @@ /* Author: Dave Coleman */ // Qt -#include -#include -#include #include -#include +#include +#include +#include +#include +#include +#include +#include #include -// ROS +#include +#include + #include "configuration_files_widget.h" +#include "header_widget.h" + +// ROS #include + // Boost #include // for string find and replace in templates #include // for creating folders/files diff --git a/moveit_setup_assistant/src/widgets/configuration_files_widget.h b/moveit_setup_assistant/src/widgets/configuration_files_widget.h index f0787af004..aa7aa6c1c7 100644 --- a/moveit_setup_assistant/src/widgets/configuration_files_widget.h +++ b/moveit_setup_assistant/src/widgets/configuration_files_widget.h @@ -37,23 +37,23 @@ #ifndef MOVEIT_ROS_MOVEIT_SETUP_ASSISTANT_WIDGETS_CONFIGURATION_FILES_WIDGET_ #define MOVEIT_ROS_MOVEIT_SETUP_ASSISTANT_WIDGETS_CONFIGURATION_FILES_WIDGET_ -#include -#include -#include -#include -#include -#include #include +class QLabel; +class QListWidget; +class QListWidgetItem; +class QProgressBar; +class QPushButton; #ifndef Q_MOC_RUN #include #endif -#include "header_widget.h" #include "setup_screen_widget.h" // a base class for screens in the setup assistant namespace moveit_setup_assistant { +class LoadPathWidget; + // Struct for storing all the file operations struct GenerateFile { diff --git a/moveit_setup_assistant/src/widgets/controller_edit_widget.cpp b/moveit_setup_assistant/src/widgets/controller_edit_widget.cpp index 62c2feb300..38be579c2f 100644 --- a/moveit_setup_assistant/src/widgets/controller_edit_widget.cpp +++ b/moveit_setup_assistant/src/widgets/controller_edit_widget.cpp @@ -33,12 +33,16 @@ /* Author: Mohamad Ayman */ -#include +#include +#include +#include #include +#include +#include #include -#include +#include #include -#include +#include #include "controller_edit_widget.h" namespace moveit_setup_assistant diff --git a/moveit_setup_assistant/src/widgets/controller_edit_widget.h b/moveit_setup_assistant/src/widgets/controller_edit_widget.h index 76ef935831..de1545b563 100644 --- a/moveit_setup_assistant/src/widgets/controller_edit_widget.h +++ b/moveit_setup_assistant/src/widgets/controller_edit_widget.h @@ -37,10 +37,10 @@ #define MOVEIT_ROS_MOVEIT_SETUP_ASSISTANT_WIDGETS_CONTROLLER_EDIT_WIDGET_H #include -#include -#include -#include -#include +class QComboBox; +class QLabel; +class QLineEdit; +class QPushButton; #ifndef Q_MOC_RUN #include diff --git a/moveit_setup_assistant/src/widgets/default_collisions_widget.cpp b/moveit_setup_assistant/src/widgets/default_collisions_widget.cpp index 480ab150f2..4454db176e 100644 --- a/moveit_setup_assistant/src/widgets/default_collisions_widget.cpp +++ b/moveit_setup_assistant/src/widgets/default_collisions_widget.cpp @@ -34,16 +34,26 @@ /* Author: Dave Coleman */ -#include -#include -#include -#include -#include +#include #include #include -#include +#include +#include +#include +#include #include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "default_collisions_widget.h" #include "header_widget.h" diff --git a/moveit_setup_assistant/src/widgets/default_collisions_widget.h b/moveit_setup_assistant/src/widgets/default_collisions_widget.h index 37c5cad980..c0d4cf1c07 100644 --- a/moveit_setup_assistant/src/widgets/default_collisions_widget.h +++ b/moveit_setup_assistant/src/widgets/default_collisions_widget.h @@ -34,22 +34,26 @@ /* Author: Dave Coleman */ -#ifndef MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_DEFAULT_COLLISIONS_WIDGET__ -#define MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_DEFAULT_COLLISIONS_WIDGET__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#pragma once + #include -#include -#include +class QAbstractItemModel; +class QAction; +class QButtonGroup; +class QCheckBox; +class QGroupBox; +class QHeaderView; +class QItemSelection; +class QItemSelectionModel; +class QLabel; +class QLineEdit; +class QProgressBar; +class QPushButton; +class QRadioButton; +class QSlider; +class QSpinBox; +class QTableView; +class QVBoxLayout; #ifndef Q_MOC_RUN #include diff --git a/moveit_setup_assistant/src/widgets/double_list_widget.cpp b/moveit_setup_assistant/src/widgets/double_list_widget.cpp index 51ab5f9980..edcf029058 100644 --- a/moveit_setup_assistant/src/widgets/double_list_widget.cpp +++ b/moveit_setup_assistant/src/widgets/double_list_widget.cpp @@ -34,15 +34,17 @@ /* Author: Dave Coleman */ -#include -#include -#include -#include #include +#include +#include +#include +#include #include #include +#include #include -#include +#include +#include #include "double_list_widget.h" namespace moveit_setup_assistant diff --git a/moveit_setup_assistant/src/widgets/double_list_widget.h b/moveit_setup_assistant/src/widgets/double_list_widget.h index c4e511bd14..80357a8f1b 100644 --- a/moveit_setup_assistant/src/widgets/double_list_widget.h +++ b/moveit_setup_assistant/src/widgets/double_list_widget.h @@ -38,8 +38,10 @@ #define MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_DOUBLE_LIST_WIDGET_ #include -#include -#include +class QLabel; +class QTableWidget; +class QTableWidgetItem; +class QItemSelection; #ifndef Q_MOC_RUN #include diff --git a/moveit_setup_assistant/src/widgets/end_effectors_widget.cpp b/moveit_setup_assistant/src/widgets/end_effectors_widget.cpp index 16f89b5287..eb092e6a1b 100644 --- a/moveit_setup_assistant/src/widgets/end_effectors_widget.cpp +++ b/moveit_setup_assistant/src/widgets/end_effectors_widget.cpp @@ -36,10 +36,24 @@ // SA #include "end_effectors_widget.h" +#include "header_widget.h" + // Qt +#include +#include #include +#include +#include +#include +#include #include -#include +#include +#include +#include +#include +#include +#include +#include namespace moveit_setup_assistant { diff --git a/moveit_setup_assistant/src/widgets/end_effectors_widget.h b/moveit_setup_assistant/src/widgets/end_effectors_widget.h index 4c818d0b30..69be8c18f2 100644 --- a/moveit_setup_assistant/src/widgets/end_effectors_widget.h +++ b/moveit_setup_assistant/src/widgets/end_effectors_widget.h @@ -38,24 +38,17 @@ #define MOVEIT_ROS_MOVEIT_SETUP_ASSISTANT_WIDGETS_END_EFFECTORS_WIDGET_ // Qt -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +class QComboBox; +class QLineEdit; +class QPushButton; +class QStackedWidget; +class QTableWidget; // SA #ifndef Q_MOC_RUN #include #endif -#include "header_widget.h" #include "setup_screen_widget.h" // a base class for screens in the setup assistant namespace moveit_setup_assistant diff --git a/moveit_setup_assistant/src/widgets/group_edit_widget.cpp b/moveit_setup_assistant/src/widgets/group_edit_widget.cpp index 02fc45688f..a975ce69d6 100644 --- a/moveit_setup_assistant/src/widgets/group_edit_widget.cpp +++ b/moveit_setup_assistant/src/widgets/group_edit_widget.cpp @@ -34,13 +34,18 @@ /* Author: Dave Coleman */ -#include -#include -#include +#include #include #include -#include #include +#include +#include +#include +#include +#include +#include +#include + #include "group_edit_widget.h" #include // for loading all avail kinematic planners diff --git a/moveit_setup_assistant/src/widgets/group_edit_widget.h b/moveit_setup_assistant/src/widgets/group_edit_widget.h index 76b33ccd57..23970afe81 100644 --- a/moveit_setup_assistant/src/widgets/group_edit_widget.h +++ b/moveit_setup_assistant/src/widgets/group_edit_widget.h @@ -38,10 +38,10 @@ #define MOVEIT_ROS_MOVEIT_SETUP_ASSISTANT_WIDGETS_GROUP_EDIT_WIDGET_ #include -#include -#include -#include -#include +class QComboBox; +class QLabel; +class QLineEdit; +class QPushButton; #ifndef Q_MOC_RUN #include diff --git a/moveit_setup_assistant/src/widgets/header_widget.cpp b/moveit_setup_assistant/src/widgets/header_widget.cpp index e42d06f5e1..695efbece0 100644 --- a/moveit_setup_assistant/src/widgets/header_widget.cpp +++ b/moveit_setup_assistant/src/widgets/header_widget.cpp @@ -34,11 +34,13 @@ /* Author: Dave Coleman */ -#include -#include +#include "header_widget.h" #include +#include +#include +#include +#include #include -#include "header_widget.h" namespace moveit_setup_assistant { diff --git a/moveit_setup_assistant/src/widgets/header_widget.h b/moveit_setup_assistant/src/widgets/header_widget.h index e8ac0ea777..c79157d247 100644 --- a/moveit_setup_assistant/src/widgets/header_widget.h +++ b/moveit_setup_assistant/src/widgets/header_widget.h @@ -38,8 +38,9 @@ #define MOVEIT_ROS_MOVEIT_SETUP_ASSISTANT_WIDGETS_HEADER_WIDGET_ #include -#include -#include +#include +class QLabel; +class QLineEdit; namespace moveit_setup_assistant { diff --git a/moveit_setup_assistant/src/widgets/kinematic_chain_widget.cpp b/moveit_setup_assistant/src/widgets/kinematic_chain_widget.cpp index f6a0caa7df..70550744a1 100644 --- a/moveit_setup_assistant/src/widgets/kinematic_chain_widget.cpp +++ b/moveit_setup_assistant/src/widgets/kinematic_chain_widget.cpp @@ -41,7 +41,8 @@ #include #include #include -#include +#include +#include #include "kinematic_chain_widget.h" namespace moveit_setup_assistant diff --git a/moveit_setup_assistant/src/widgets/kinematic_chain_widget.h b/moveit_setup_assistant/src/widgets/kinematic_chain_widget.h index ccfb26f987..721b637351 100644 --- a/moveit_setup_assistant/src/widgets/kinematic_chain_widget.h +++ b/moveit_setup_assistant/src/widgets/kinematic_chain_widget.h @@ -38,8 +38,10 @@ #define MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_KINEMATIC_CHAIN_WIDGET_ #include -#include -#include +class QLabel; +class QLineEdit; +class QTreeWidget; +class QTreeWidgetItem; #ifndef Q_MOC_RUN #include diff --git a/moveit_setup_assistant/src/widgets/navigation_widget.cpp b/moveit_setup_assistant/src/widgets/navigation_widget.cpp index d9cef1fa43..0f2ca8dd5f 100644 --- a/moveit_setup_assistant/src/widgets/navigation_widget.cpp +++ b/moveit_setup_assistant/src/widgets/navigation_widget.cpp @@ -36,6 +36,9 @@ #include "navigation_widget.h" #include +#include +#include +#include #include namespace moveit_setup_assistant diff --git a/moveit_setup_assistant/src/widgets/navigation_widget.h b/moveit_setup_assistant/src/widgets/navigation_widget.h index 241355988b..b9df37ca0d 100644 --- a/moveit_setup_assistant/src/widgets/navigation_widget.h +++ b/moveit_setup_assistant/src/widgets/navigation_widget.h @@ -38,11 +38,8 @@ #define MOVEIT_ROS_MOVEIT_SETUP_ASSISTANT_WIDGETS_NAVIGATION_WIDGET_ #include -#include -#include -#include #include -#include +class QStandardItemModel; namespace moveit_setup_assistant { diff --git a/moveit_setup_assistant/src/widgets/passive_joints_widget.cpp b/moveit_setup_assistant/src/widgets/passive_joints_widget.cpp index 72fa2a45c7..8f2b2e2d35 100644 --- a/moveit_setup_assistant/src/widgets/passive_joints_widget.cpp +++ b/moveit_setup_assistant/src/widgets/passive_joints_widget.cpp @@ -36,9 +36,14 @@ // SA #include "passive_joints_widget.h" +#include "header_widget.h" +#include "double_list_widget.h" + // Qt #include +#include #include +#include namespace moveit_setup_assistant { diff --git a/moveit_setup_assistant/src/widgets/passive_joints_widget.h b/moveit_setup_assistant/src/widgets/passive_joints_widget.h index 802fba7076..e4da1f2878 100644 --- a/moveit_setup_assistant/src/widgets/passive_joints_widget.h +++ b/moveit_setup_assistant/src/widgets/passive_joints_widget.h @@ -37,27 +37,16 @@ #ifndef MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_PASSIVE_JOINTS_WIDGET_ #define MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_PASSIVE_JOINTS_WIDGET_ -// Qt -#include -#include -#include -#include -#include -#include -#include -#include - // SA #ifndef Q_MOC_RUN #include #endif -#include "header_widget.h" -#include "double_list_widget.h" #include "setup_screen_widget.h" // a base class for screens in the setup assistant namespace moveit_setup_assistant { +class DoubleListWidget; class PassiveJointsWidget : public SetupScreenWidget { Q_OBJECT diff --git a/moveit_setup_assistant/src/widgets/perception_widget.cpp b/moveit_setup_assistant/src/widgets/perception_widget.cpp index 7a496cabac..0958ddce4f 100644 --- a/moveit_setup_assistant/src/widgets/perception_widget.cpp +++ b/moveit_setup_assistant/src/widgets/perception_widget.cpp @@ -35,11 +35,16 @@ // SA #include "perception_widget.h" +#include "header_widget.h" // Qt -#include -#include #include +#include +#include +#include +#include +#include +#include namespace moveit_setup_assistant { diff --git a/moveit_setup_assistant/src/widgets/perception_widget.h b/moveit_setup_assistant/src/widgets/perception_widget.h index 336fe8a80e..9111121051 100644 --- a/moveit_setup_assistant/src/widgets/perception_widget.h +++ b/moveit_setup_assistant/src/widgets/perception_widget.h @@ -37,18 +37,15 @@ #define MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_PERCEPTION_WIDGET_ // Qt -#include -#include -#include -#include -#include +class QComboBox; +class QGroupBox; +class QLineEdit; // SA #ifndef Q_MOC_RUN #include #endif -#include "header_widget.h" #include "setup_screen_widget.h" // a base class for screens in the setup assistant namespace moveit_setup_assistant diff --git a/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp b/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp index 1a600c4f7a..8e1a864a8d 100644 --- a/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp +++ b/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp @@ -55,13 +55,17 @@ #include "group_edit_widget.h" // for group rename page // Qt #include -#include +#include #include -#include -#include +#include +#include #include +#include +#include +#include #include #include +#include //// Cycle checking #include diff --git a/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp b/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp index e706ab57ca..f34565bb85 100644 --- a/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp +++ b/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp @@ -36,12 +36,21 @@ // SA #include "robot_poses_widget.h" +#include "header_widget.h" #include // Qt +#include +#include +#include #include +#include +#include #include -#include -#include +#include +#include +#include +#include +#include #include #include diff --git a/moveit_setup_assistant/src/widgets/robot_poses_widget.h b/moveit_setup_assistant/src/widgets/robot_poses_widget.h index 984876fbfb..5b8b66ff7e 100644 --- a/moveit_setup_assistant/src/widgets/robot_poses_widget.h +++ b/moveit_setup_assistant/src/widgets/robot_poses_widget.h @@ -38,17 +38,15 @@ #define MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_ROBOT_POSES_WIDGET_ // Qt -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +class QComboBox; +class QLabel; +class QLineEdit; +class QPushButton; +class QScrollArea; +class QSlider; +class QStackedWidget; +class QTableWidget; +class QVBoxLayout; // SA #ifndef Q_MOC_RUN @@ -57,7 +55,6 @@ #include #endif -#include "header_widget.h" #include "setup_screen_widget.h" // a base class for screens in the setup assistant namespace moveit_setup_assistant diff --git a/moveit_setup_assistant/src/widgets/ros_controllers_widget.cpp b/moveit_setup_assistant/src/widgets/ros_controllers_widget.cpp index c4e5d6dff1..ce9bb1c869 100644 --- a/moveit_setup_assistant/src/widgets/ros_controllers_widget.cpp +++ b/moveit_setup_assistant/src/widgets/ros_controllers_widget.cpp @@ -35,13 +35,27 @@ // SA #include "ros_controllers_widget.h" +#include "double_list_widget.h" +#include "controller_edit_widget.h" +#include "header_widget.h" #include // Qt +#include +#include #include +#include +#include +#include +#include #include -#include +#include +#include +#include +#include +#include +#include #include -#include +#include #include #include diff --git a/moveit_setup_assistant/src/widgets/ros_controllers_widget.h b/moveit_setup_assistant/src/widgets/ros_controllers_widget.h index 5e0485c9c3..b93a791b3e 100644 --- a/moveit_setup_assistant/src/widgets/ros_controllers_widget.h +++ b/moveit_setup_assistant/src/widgets/ros_controllers_widget.h @@ -37,27 +37,24 @@ #define MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_ROS_CONTROLLERS_WIDGET_H // Qt -#include -#include -#include -#include -#include -#include -#include -#include +class QHBoxLayout; +class QPushButton; +class QStackedWidget; +class QTreeWidget; +class QTreeWidgetItem; // SA #ifndef Q_MOC_RUN #include #endif -#include "double_list_widget.h" // for joints, links and subgroups pages -#include "header_widget.h" #include "setup_screen_widget.h" // a base class for screens in the setup assistant -#include "controller_edit_widget.h" namespace moveit_setup_assistant { +class DoubleListWidget; +class ControllerEditWidget; + class ROSControllersWidget : public SetupScreenWidget { Q_OBJECT diff --git a/moveit_setup_assistant/src/widgets/setup_assistant_widget.cpp b/moveit_setup_assistant/src/widgets/setup_assistant_widget.cpp index 5ecc8bd635..e438e3dce6 100644 --- a/moveit_setup_assistant/src/widgets/setup_assistant_widget.cpp +++ b/moveit_setup_assistant/src/widgets/setup_assistant_widget.cpp @@ -37,15 +37,20 @@ // SA #include "setup_screen_widget.h" // a base class for screens in the setup assistant #include "setup_assistant_widget.h" +#include "header_widget.h" + // Qt -#include -#include -#include +#include +#include #include +#include #include -#include -#include +#include +#include #include +#include +#include +#include #include #include // for loading all avail kinematic planners // Rviz diff --git a/moveit_setup_assistant/src/widgets/setup_assistant_widget.h b/moveit_setup_assistant/src/widgets/setup_assistant_widget.h index 62392d5c8e..d7e853fcf2 100644 --- a/moveit_setup_assistant/src/widgets/setup_assistant_widget.h +++ b/moveit_setup_assistant/src/widgets/setup_assistant_widget.h @@ -38,18 +38,9 @@ #define MOVEIT_ROS_MOVEIT_SETUP_ASSISTANT_WIDGETS_SETUP_ASSISTANT_WIDGET_ // Qt -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -// Setup Asst +class QSplitter; + +// Setup Assistant #include "navigation_widget.h" #include "start_screen_widget.h" #include "default_collisions_widget.h" @@ -68,8 +59,7 @@ #include // Other -#include -#include // for parsing input arguments +#include // for parsing input arguments #include #endif diff --git a/moveit_setup_assistant/src/widgets/simulation_widget.cpp b/moveit_setup_assistant/src/widgets/simulation_widget.cpp index 14542fa7f2..bba4b5bd1a 100644 --- a/moveit_setup_assistant/src/widgets/simulation_widget.cpp +++ b/moveit_setup_assistant/src/widgets/simulation_widget.cpp @@ -35,12 +35,15 @@ // SA #include "simulation_widget.h" +#include "header_widget.h" // Qt -#include +#include +#include #include #include -#include +#include +#include #include #include diff --git a/moveit_setup_assistant/src/widgets/simulation_widget.h b/moveit_setup_assistant/src/widgets/simulation_widget.h index 2b3ac58331..ed1ae0b509 100644 --- a/moveit_setup_assistant/src/widgets/simulation_widget.h +++ b/moveit_setup_assistant/src/widgets/simulation_widget.h @@ -37,16 +37,14 @@ #define MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_SIMULATION_WIDGET_H // Qt -#include -#include -#include +class QLabel; +class QTextEdit; // SA #ifndef Q_MOC_RUN #include #endif -#include "header_widget.h" #include "setup_screen_widget.h" // a base class for screens in the setup assistant namespace moveit_setup_assistant diff --git a/moveit_setup_assistant/src/widgets/start_screen_widget.cpp b/moveit_setup_assistant/src/widgets/start_screen_widget.cpp index 47759c4f37..d8b9629926 100644 --- a/moveit_setup_assistant/src/widgets/start_screen_widget.cpp +++ b/moveit_setup_assistant/src/widgets/start_screen_widget.cpp @@ -35,15 +35,20 @@ /* Author: Dave Coleman */ // Qt -#include -#include -#include +#include +#include +#include #include +#include +#include #include +#include +#include #include -#include -#include -#include +#include +#include +#include + // ROS #include #include // for getting file path for loadng images diff --git a/moveit_setup_assistant/src/widgets/start_screen_widget.h b/moveit_setup_assistant/src/widgets/start_screen_widget.h index 116f3b987e..9b5f28e8c6 100644 --- a/moveit_setup_assistant/src/widgets/start_screen_widget.h +++ b/moveit_setup_assistant/src/widgets/start_screen_widget.h @@ -37,12 +37,9 @@ #ifndef MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_START_SCREEN_WIDGET_ #define MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_START_SCREEN_WIDGET_ -#include -#include -#include -#include -#include -#include +class QLabel; +class QProgressBar; +class QPushButton; #ifndef Q_MOC_RUN #include // for testing a valid urdf is loaded diff --git a/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp b/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp index 5db4c21baa..9c926b1088 100644 --- a/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp +++ b/moveit_setup_assistant/src/widgets/virtual_joints_widget.cpp @@ -36,10 +36,21 @@ // SA #include "virtual_joints_widget.h" +#include "header_widget.h" + // Qt +#include +#include #include +#include +#include +#include #include -#include +#include +#include +#include +#include +#include namespace moveit_setup_assistant { diff --git a/moveit_setup_assistant/src/widgets/virtual_joints_widget.h b/moveit_setup_assistant/src/widgets/virtual_joints_widget.h index 9e9cd03854..99ee02d262 100644 --- a/moveit_setup_assistant/src/widgets/virtual_joints_widget.h +++ b/moveit_setup_assistant/src/widgets/virtual_joints_widget.h @@ -38,22 +38,18 @@ #define MOVEIT_MOVEIT_SETUP_ASSISTANT_WIDGETS_VIRTUAL_JOINTS_WIDGET_ // Qt -#include -#include -#include -#include -#include -#include -#include -#include -#include +class QLabel; +class QLineEdit; +class QPushButton; +class QTableWidget; +class QStackedWidget; +class QComboBox; // SA #ifndef Q_MOC_RUN #include #endif -#include "header_widget.h" #include "setup_screen_widget.h" // a base class for screens in the setup assistant namespace moveit_setup_assistant From 16861c6c7922f0ffa30610a346ec92d951813c73 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Mon, 5 Oct 2020 22:34:08 +0200 Subject: [PATCH 036/179] Cleanup ROS includes --- moveit_setup_assistant/src/collisions_updater.cpp | 1 - .../src/widgets/configuration_files_widget.cpp | 3 --- moveit_setup_assistant/src/widgets/kinematic_chain_widget.h | 1 - moveit_setup_assistant/src/widgets/planning_groups_widget.cpp | 1 - moveit_setup_assistant/src/widgets/robot_poses_widget.cpp | 1 + moveit_setup_assistant/src/widgets/robot_poses_widget.h | 2 -- moveit_setup_assistant/src/widgets/start_screen_widget.cpp | 1 - 7 files changed, 1 insertion(+), 9 deletions(-) diff --git a/moveit_setup_assistant/src/collisions_updater.cpp b/moveit_setup_assistant/src/collisions_updater.cpp index b5f16d98c4..edc15610be 100644 --- a/moveit_setup_assistant/src/collisions_updater.cpp +++ b/moveit_setup_assistant/src/collisions_updater.cpp @@ -34,7 +34,6 @@ /* Author: Mathias Lüdtke */ -#include #include #include diff --git a/moveit_setup_assistant/src/widgets/configuration_files_widget.cpp b/moveit_setup_assistant/src/widgets/configuration_files_widget.cpp index fe23804e36..3f7fda2bdb 100644 --- a/moveit_setup_assistant/src/widgets/configuration_files_widget.cpp +++ b/moveit_setup_assistant/src/widgets/configuration_files_widget.cpp @@ -50,9 +50,6 @@ #include "configuration_files_widget.h" #include "header_widget.h" -// ROS -#include - // Boost #include // for string find and replace in templates #include // for creating folders/files diff --git a/moveit_setup_assistant/src/widgets/kinematic_chain_widget.h b/moveit_setup_assistant/src/widgets/kinematic_chain_widget.h index 721b637351..2e5e7f3b35 100644 --- a/moveit_setup_assistant/src/widgets/kinematic_chain_widget.h +++ b/moveit_setup_assistant/src/widgets/kinematic_chain_widget.h @@ -45,7 +45,6 @@ class QTreeWidgetItem; #ifndef Q_MOC_RUN #include -#include #endif namespace moveit_setup_assistant diff --git a/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp b/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp index 8e1a864a8d..c5ddf9aad4 100644 --- a/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp +++ b/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp @@ -47,7 +47,6 @@ */ // ****************************************************************************************** -#include "ros/ros.h" #include "header_widget.h" #include "planning_groups_widget.h" #include "double_list_widget.h" // for joints, links and subgroups pages diff --git a/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp b/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp index f34565bb85..eb1605b948 100644 --- a/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp +++ b/moveit_setup_assistant/src/widgets/robot_poses_widget.cpp @@ -54,6 +54,7 @@ #include #include +#include namespace moveit_setup_assistant { diff --git a/moveit_setup_assistant/src/widgets/robot_poses_widget.h b/moveit_setup_assistant/src/widgets/robot_poses_widget.h index 5b8b66ff7e..a24e826a23 100644 --- a/moveit_setup_assistant/src/widgets/robot_poses_widget.h +++ b/moveit_setup_assistant/src/widgets/robot_poses_widget.h @@ -51,8 +51,6 @@ class QVBoxLayout; // SA #ifndef Q_MOC_RUN #include -#include // for collision stuff -#include #endif #include "setup_screen_widget.h" // a base class for screens in the setup assistant diff --git a/moveit_setup_assistant/src/widgets/start_screen_widget.cpp b/moveit_setup_assistant/src/widgets/start_screen_widget.cpp index d8b9629926..a5534e41a9 100644 --- a/moveit_setup_assistant/src/widgets/start_screen_widget.cpp +++ b/moveit_setup_assistant/src/widgets/start_screen_widget.cpp @@ -50,7 +50,6 @@ #include // ROS -#include #include // for getting file path for loadng images // SA #include "header_widget.h" // title and instructions From 2bc71248762a5ee6fa8f135d4f05f6047c82bfe2 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Tue, 6 Oct 2020 07:43:45 +0200 Subject: [PATCH 037/179] Fix unused-parameter warnings --- moveit_ros/moveit_servo/src/servo_calcs.cpp | 2 +- moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp | 4 ++-- .../src/motion_planning_frame_joints_widget.cpp | 6 +++--- .../src/motion_planning_frame_objects.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index dd39f569c1..8dbb1be123 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -1035,7 +1035,7 @@ bool ServoCalcs::changeControlDimensions(moveit_msgs::ChangeControlDimensions::R return true; } -bool ServoCalcs::resetServoStatus(std_srvs::Empty::Request& req, std_srvs::Empty::Response& res) +bool ServoCalcs::resetServoStatus(std_srvs::Empty::Request& /*req*/, std_srvs::Empty::Response& /*res*/) { status_ = StatusCode::NO_WARNING; return true; diff --git a/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp b/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp index a5637a6eda..1579f1f12b 100644 --- a/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp +++ b/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp @@ -111,7 +111,7 @@ TEST_F(ServoFixture, SendTwistStampedTest) // count trajectory messages sent by servo size_t received_count = 0; boost::function traj_callback = - [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& msg) { ++received_count; }; + [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& /*msg*/) { ++received_count; }; auto traj_sub = nh_.subscribe(parameters.command_out_topic, 1, traj_callback); // Create publisher to send servo commands @@ -152,7 +152,7 @@ TEST_F(ServoFixture, SendJointServoTest) // count trajectory messages sent by servo size_t received_count = 0; boost::function traj_callback = - [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& msg) { ++received_count; }; + [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& /*msg*/) { ++received_count; }; auto traj_sub = nh_.subscribe(parameters.command_out_topic, 1, traj_callback); // Create publisher to send servo commands diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_joints_widget.cpp b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_joints_widget.cpp index 7f4782f66c..d33563a76d 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_joints_widget.cpp +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_joints_widget.cpp @@ -50,7 +50,7 @@ JMGItemModel::JMGItemModel(const moveit::core::RobotState& robot_state, const st jmg_ = robot_state_.getRobotModel()->getJointModelGroup(group_name); } -int JMGItemModel::rowCount(const QModelIndex& parent) const +int JMGItemModel::rowCount(const QModelIndex& /*parent*/) const { if (!jmg_) return robot_state_.getVariableCount(); @@ -58,7 +58,7 @@ int JMGItemModel::rowCount(const QModelIndex& parent) const return jmg_->getVariableCount(); } -int JMGItemModel::columnCount(const QModelIndex& parent) const +int JMGItemModel::columnCount(const QModelIndex& /*parent*/) const { return 2; } @@ -461,7 +461,7 @@ JointsWidgetEventFilter::JointsWidgetEventFilter(QAbstractItemView* view) : QObj { } -bool JointsWidgetEventFilter::eventFilter(QObject* target, QEvent* event) +bool JointsWidgetEventFilter::eventFilter(QObject* /*target*/, QEvent* event) { if (event->type() == QEvent::MouseButtonPress) { diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_objects.cpp b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_objects.cpp index 1a1ac2d207..b056969c13 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_objects.cpp +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_objects.cpp @@ -58,7 +58,7 @@ namespace moveit_rviz_plugin { -void MotionPlanningFrame::shapesComboBoxChanged(const QString& text) +void MotionPlanningFrame::shapesComboBoxChanged(const QString& /*text*/) { switch (ui_->shapes_combo_box->currentData().toInt()) // fetch shape ID from current combobox item { From 41d6e4a8976e7f1492bf8233ef6c572ce723e123 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 7 Oct 2020 00:50:25 +0200 Subject: [PATCH 038/179] MSA: Allow showing both, visual and collision geometry (#2352) --- .../src/widgets/default_collisions_widget.h | 2 -- .../src/widgets/setup_assistant_widget.cpp | 22 ++++++++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/moveit_setup_assistant/src/widgets/default_collisions_widget.h b/moveit_setup_assistant/src/widgets/default_collisions_widget.h index c0d4cf1c07..e17ad54ca6 100644 --- a/moveit_setup_assistant/src/widgets/default_collisions_widget.h +++ b/moveit_setup_assistant/src/widgets/default_collisions_widget.h @@ -261,5 +261,3 @@ class MonitorThread : public QThread bool canceled_; }; } // namespace moveit_setup_assistant - -#endif diff --git a/moveit_setup_assistant/src/widgets/setup_assistant_widget.cpp b/moveit_setup_assistant/src/widgets/setup_assistant_widget.cpp index e438e3dce6..4737db016e 100644 --- a/moveit_setup_assistant/src/widgets/setup_assistant_widget.cpp +++ b/moveit_setup_assistant/src/widgets/setup_assistant_widget.cpp @@ -45,8 +45,9 @@ #include #include #include -#include -#include +#include +#include +#include #include #include #include @@ -404,10 +405,25 @@ void SetupAssistantWidget::loadRviz() view->subProp("Distance")->setValue(4.0f); // Add Rviz to Planning Groups Widget - QHBoxLayout* rviz_layout = new QHBoxLayout(); + QVBoxLayout* rviz_layout = new QVBoxLayout(); rviz_layout->addWidget(rviz_render_panel_); rviz_container_->setLayout(rviz_layout); + // visual / collision buttons + auto btn_layout = new QHBoxLayout(); + rviz_layout->addLayout(btn_layout); + + QCheckBox* btn; + btn_layout->addWidget(btn = new QCheckBox("visual"), 0); + btn->setChecked(true); + connect(btn, &QCheckBox::toggled, + [this](bool checked) { robot_state_display_->subProp("Visual Enabled")->setValue(checked); }); + + btn_layout->addWidget(btn = new QCheckBox("collision"), 1); + btn->setChecked(false); + connect(btn, &QCheckBox::toggled, + [this](bool checked) { robot_state_display_->subProp("Collision Enabled")->setValue(checked); }); + rviz_container_->show(); } From 3a81c52a9eeeade60dc1d8cd226f83e031948f5e Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 7 Oct 2020 14:44:44 +0200 Subject: [PATCH 039/179] MSA: Fix group editing (#2350) Group Editing: Cancel falls back to previous screen When entering joints/links/chain/subgroup edit screen from "Add Group" screen, cancel was cancelling the whole operation, loosing all info that was already entered for the group. Now it just returns to the previous screen and thus allows to continue editing the new group. --- .../src/widgets/planning_groups_widget.cpp | 94 ++++++++----------- .../src/widgets/planning_groups_widget.h | 14 +-- 2 files changed, 45 insertions(+), 63 deletions(-) diff --git a/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp b/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp index c5ddf9aad4..fc54f9bafc 100644 --- a/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp +++ b/moveit_setup_assistant/src/widgets/planning_groups_widget.cpp @@ -156,7 +156,7 @@ PlanningGroupsWidget::PlanningGroupsWidget(QWidget* parent, const MoveItConfigDa connect(group_edit_widget_, SIGNAL(saveChain()), this, SLOT(saveGroupScreenChain())); connect(group_edit_widget_, SIGNAL(saveSubgroups()), this, SLOT(saveGroupScreenSubgroups())); - // Combine into stack + // Combine into stack: Note, order is same as GroupType! stacked_widget_ = new QStackedWidget(this); stacked_widget_->addWidget(groups_tree_widget_); // screen index 0 stacked_widget_->addWidget(joints_widget_); // screen index 1 @@ -467,50 +467,29 @@ void PlanningGroupsWidget::editSelected() // Get the user custom properties of the currently selected row PlanGroupType plan_group = item->data(0, Qt::UserRole).value(); - if (plan_group.type_ == JOINT) + switch (plan_group.type_) { - // Load the data - loadJointsScreen(plan_group.group_); - - // Switch to screen - changeScreen(1); // 1 is index of joints - } - else if (plan_group.type_ == LINK) - { - // Load the data - loadLinksScreen(plan_group.group_); - - // Switch to screen - changeScreen(2); - } - else if (plan_group.type_ == CHAIN) - { - // Load the data - loadChainScreen(plan_group.group_); - - // Switch to screen - changeScreen(3); - } - else if (plan_group.type_ == SUBGROUP) - { - // Load the data - loadSubgroupsScreen(plan_group.group_); - - // Switch to screen - changeScreen(4); - } - else if (plan_group.type_ == GROUP) - { - // Load the data - loadGroupScreen(plan_group.group_); - - // Switch to screen - changeScreen(5); - } - else - { - QMessageBox::critical(this, "Error Loading", "An internal error has occured while loading."); + case JOINT: + loadJointsScreen(plan_group.group_); + break; + case LINK: + loadLinksScreen(plan_group.group_); + break; + case CHAIN: + loadChainScreen(plan_group.group_); + break; + case SUBGROUP: + loadSubgroupsScreen(plan_group.group_); + break; + case GROUP: + loadGroupScreen(plan_group.group_); + break; + default: + QMessageBox::critical(this, "Error Loading", "An internal error has occured while loading."); + return; } + return_screen_ = 0; // return to main screen directly + changeScreen(plan_group.type_); } // ****************************************************************************************** @@ -542,7 +521,6 @@ void PlanningGroupsWidget::loadJointsScreen(srdf::Model::Group* this_group) // Remember what is currently being edited so we can later save changes current_edit_group_ = this_group->name_; - current_edit_element_ = JOINT; } // ****************************************************************************************** @@ -574,7 +552,6 @@ void PlanningGroupsWidget::loadLinksScreen(srdf::Model::Group* this_group) // Remember what is currently being edited so we can later save changes current_edit_group_ = this_group->name_; - current_edit_element_ = LINK; } // ****************************************************************************************** @@ -607,7 +584,6 @@ void PlanningGroupsWidget::loadChainScreen(srdf::Model::Group* this_group) // Remember what is currently being edited so we can later save changes current_edit_group_ = this_group->name_; - current_edit_element_ = CHAIN; } // ****************************************************************************************** @@ -641,7 +617,6 @@ void PlanningGroupsWidget::loadSubgroupsScreen(srdf::Model::Group* this_group) // Remember what is currently being edited so we can later save changes current_edit_group_ = this_group->name_; - current_edit_element_ = SUBGROUP; } // ****************************************************************************************** @@ -672,9 +647,6 @@ void PlanningGroupsWidget::loadGroupScreen(srdf::Model::Group* this_group) // Set the data in the edit box group_edit_widget_->setSelected(current_edit_group_); - - // Remember what is currently being edited so we can later save changes - current_edit_element_ = GROUP; } // ****************************************************************************************** @@ -845,7 +817,7 @@ void PlanningGroupsWidget::addGroup() loadGroupScreen(nullptr); // NULL indicates this is a new group, not an existing one // Switch to screen - changeScreen(5); + changeScreen(GROUP); } // ****************************************************************************************** @@ -1282,9 +1254,10 @@ void PlanningGroupsWidget::saveGroupScreenJoints() // Find the group we are editing based on the goup name string loadJointsScreen(config_data_->findGroupByName(current_edit_group_)); + return_screen_ = GROUP; // Switch to screen - changeScreen(1); // 1 is index of joints + changeScreen(JOINT); } // ****************************************************************************************** @@ -1298,9 +1271,10 @@ void PlanningGroupsWidget::saveGroupScreenLinks() // Find the group we are editing based on the goup name string loadLinksScreen(config_data_->findGroupByName(current_edit_group_)); + return_screen_ = GROUP; // Switch to screen - changeScreen(2); // 2 is index of links + changeScreen(LINK); } // ****************************************************************************************** @@ -1314,9 +1288,10 @@ void PlanningGroupsWidget::saveGroupScreenChain() // Find the group we are editing based on the goup name string loadChainScreen(config_data_->findGroupByName(current_edit_group_)); + return_screen_ = GROUP; // Switch to screen - changeScreen(3); + changeScreen(CHAIN); } // ****************************************************************************************** @@ -1330,9 +1305,10 @@ void PlanningGroupsWidget::saveGroupScreenSubgroups() // Find the group we are editing based on the goup name string loadSubgroupsScreen(config_data_->findGroupByName(current_edit_group_)); + return_screen_ = GROUP; // Switch to screen - changeScreen(4); + changeScreen(SUBGROUP); } // ****************************************************************************************** @@ -1340,6 +1316,12 @@ void PlanningGroupsWidget::saveGroupScreenSubgroups() // ****************************************************************************************** void PlanningGroupsWidget::cancelEditing() { + if (return_screen_) + { + changeScreen(return_screen_); + return_screen_ = 0; + return; + } if (!current_edit_group_.empty() && adding_new_group_) { srdf::Model::Group* editing = config_data_->findGroupByName(current_edit_group_); @@ -1394,7 +1376,7 @@ void PlanningGroupsWidget::showMainScreen() { stacked_widget_->setCurrentIndex(0); - // Announce that this widget is not in modal mode + // Announce that this widget is not in modal mode anymore Q_EMIT isModal(false); } diff --git a/moveit_setup_assistant/src/widgets/planning_groups_widget.h b/moveit_setup_assistant/src/widgets/planning_groups_widget.h index ce2786a41d..5404e00c1a 100644 --- a/moveit_setup_assistant/src/widgets/planning_groups_widget.h +++ b/moveit_setup_assistant/src/widgets/planning_groups_widget.h @@ -62,11 +62,11 @@ class GroupEditWidget; // Custom Type enum GroupType { - JOINT, - LINK, - CHAIN, - SUBGROUP, - GROUP + JOINT = 1, + LINK = 2, + CHAIN = 3, + SUBGROUP = 4, + GROUP = 5 }; // ****************************************************************************************** @@ -173,8 +173,8 @@ private Q_SLOTS: /// Remember what group we are editing when an edit screen is being shown std::string current_edit_group_; - /// Remember what group element we are editing when an edit screen is being shown - GroupType current_edit_element_; + /// Remember to which editing screen we should return on Cancel + int return_screen_; /// Remember whethere we're editing a group or adding a new one bool adding_new_group_; From 9dab7b1e6e0609b2375b2d054e86aeede0f66ac1 Mon Sep 17 00:00:00 2001 From: v4hn Date: Fri, 9 Oct 2020 12:43:17 +0200 Subject: [PATCH 040/179] move_group: simplify test launch files --- .../test_cancel_before_plan_execution.test | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/moveit_ros/move_group/test/test_cancel_before_plan_execution.test b/moveit_ros/move_group/test/test_cancel_before_plan_execution.test index 4acb89e476..a4f22e456f 100644 --- a/moveit_ros/move_group/test/test_cancel_before_plan_execution.test +++ b/moveit_ros/move_group/test/test_cancel_before_plan_execution.test @@ -1,22 +1,6 @@ - - - - - - - - [move_group/fake_controller_joint_states] - - - - - - - - - - + + From 3bde6176d47e807e3062e8cef71cbdd4acffe585 Mon Sep 17 00:00:00 2001 From: AndyZe Date: Sun, 11 Oct 2020 14:19:33 -0500 Subject: [PATCH 041/179] A library for servoing toward a moving pose (#2203) * A library for servoing toward a moving pose * Use the control_toolbox version of PID control * Minor cleanup after switching to control_toolbox PID * Use default ROS1 library type * Decrease the default windup limit * Add a basic unit test * Add orientation tracking, too * Warning if no target pose is provided * One PID for orientation instead of 3 * A different method of ensuring a new target pose is received * Multithread the test pose publisher * Correct service namespaces * Clang format and clang tidy * Minor tweaks for CI * Add function to update PID settings * Add a method to get PID errors * Be consistent with service namespacing This is important if there are multiple arms Servoing simultaneously * Address Adam's more minor comments * First attempt at using pose tracking * Small updates to launch files and CMakeLists * Address Andy comments * Get Pose Tracking demo working (#3) * Rework command frame name and target pose * Add EE frame tf and make it available thru C++ interface * Pass getEEFrameTransform thru PoseTracking * Update TF calcs at servo start * Modify pose demo to move slightly from current position * Make PoseTracking use EE tf instead of command frame tf * Clean up the demo * Make helper func for converting eigen to tf message * Make the Servo instance public, to access functions like setPaused() * Use an enum class for status codes, so entries can be duplicated * Add a timeout argument * Clang format * Fix a race condition with initial joint reception * Update config file for testing * Wrap tf lookup in a try/catch block * Use a tf2 utility for Eigen->msg conversion * Explicitly initialize transforms to zero * More robust test setup * Update the command frame at runtime * Update angular PID configs, too * Properly wait for test setup Co-authored-by: AdamPettinger --- moveit_ros/moveit_servo/CMakeLists.txt | 80 ++-- .../config/pose_tracking_settings.yaml | 21 + .../config/ur_simulated_config.yaml | 5 +- .../moveit_servo/make_shared_from_pool.h | 1 + .../include/moveit_servo/pose_tracking.h | 195 ++++++++++ .../moveit_servo/include/moveit_servo/servo.h | 25 +- .../include/moveit_servo/servo_calcs.h | 29 +- .../include/moveit_servo/servo_parameters.h | 1 + .../include/moveit_servo/status_codes.h | 18 +- .../launch/pose_tracking_example.launch | 10 + moveit_ros/moveit_servo/package.xml | 8 +- .../pose_tracking_example.cpp | 155 ++++++++ .../src/joint_state_subscriber.cpp | 8 +- moveit_ros/moveit_servo/src/pose_tracking.cpp | 359 ++++++++++++++++++ moveit_ros/moveit_servo/src/servo.cpp | 113 +++--- moveit_ros/moveit_servo/src/servo_calcs.cpp | 92 ++++- .../test/config/servo_settings.yaml | 5 +- .../moveit_servo/test/pose_tracking_test.cpp | 162 ++++++++ .../moveit_servo/test/pose_tracking_test.test | 24 ++ .../test/servo_cpp_interface_test.cpp | 7 + 20 files changed, 1219 insertions(+), 99 deletions(-) create mode 100644 moveit_ros/moveit_servo/config/pose_tracking_settings.yaml create mode 100644 moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h create mode 100644 moveit_ros/moveit_servo/launch/pose_tracking_example.launch create mode 100644 moveit_ros/moveit_servo/src/cpp_interface_example/pose_tracking_example.cpp create mode 100644 moveit_ros/moveit_servo/src/pose_tracking.cpp create mode 100644 moveit_ros/moveit_servo/test/pose_tracking_test.cpp create mode 100644 moveit_ros/moveit_servo/test/pose_tracking_test.test diff --git a/moveit_ros/moveit_servo/CMakeLists.txt b/moveit_ros/moveit_servo/CMakeLists.txt index cadc430e90..878d4515a9 100644 --- a/moveit_ros/moveit_servo/CMakeLists.txt +++ b/moveit_ros/moveit_servo/CMakeLists.txt @@ -7,16 +7,17 @@ endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -set(LIBRARY_NAME moveit_servo_cpp_api) +set(SERVO_LIB_NAME moveit_servo_cpp_api) if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() find_package(Boost REQUIRED) - +find_package(Eigen3 REQUIRED) find_package(catkin REQUIRED COMPONENTS control_msgs + control_toolbox geometry_msgs moveit_msgs moveit_ros_planning_interface @@ -24,17 +25,19 @@ find_package(catkin REQUIRED COMPONENTS sensor_msgs std_msgs std_srvs + tf2_eigen trajectory_msgs ) -find_package(Eigen3 REQUIRED) catkin_package( INCLUDE_DIRS include LIBRARIES - ${LIBRARY_NAME} + pose_tracking + ${SERVO_LIB_NAME} CATKIN_DEPENDS control_msgs + control_toolbox geometry_msgs moveit_msgs moveit_ros_planning_interface @@ -42,6 +45,7 @@ catkin_package( sensor_msgs std_msgs std_srvs + tf2_eigen trajectory_msgs DEPENDS EIGEN3 @@ -54,35 +58,59 @@ include_directories( ${Boost_INCLUDE_DIR} ) -######################################### -## A library providing a C++ interface ## -######################################### +######################################################### +## Library to process realtime twist or joint commands ## +######################################################### -add_library(${LIBRARY_NAME} SHARED +# This library provides an interface for sending realtime twist or joint commands to a robot +add_library(${SERVO_LIB_NAME} + # These files are used to produce differential motion src/collision_check.cpp src/servo_calcs.cpp src/servo.cpp src/joint_state_subscriber.cpp src/low_pass_filter.cpp ) -set_target_properties(${LIBRARY_NAME} PROPERTIES VERSION "${${PROJECT_NAME}_VERSION}") -add_dependencies(${LIBRARY_NAME} ${catkin_EXPORTED_TARGETS}) -target_link_libraries(${LIBRARY_NAME} +set_target_properties(${SERVO_LIB_NAME} PROPERTIES VERSION "${${PROJECT_NAME}_VERSION}") +add_dependencies(${SERVO_LIB_NAME} ${catkin_EXPORTED_TARGETS}) +target_link_libraries(${SERVO_LIB_NAME} ${catkin_LIBRARIES} ${Eigen_LIBRARIES} ${Boost_LIBRARIES} ) -# An example of using the C++ library +# An example of streaming realtime Cartesian and joint commands add_executable(cpp_interface_example src/cpp_interface_example/cpp_interface_example.cpp ) add_dependencies(cpp_interface_example ${catkin_EXPORTED_TARGETS}) target_link_libraries(cpp_interface_example ${catkin_LIBRARIES} - ${Eigen_LIBRARIES} - ${Boost_LIBRARIES} - ${LIBRARY_NAME} + ${SERVO_LIB_NAME} +) + +# An example of pose tracking +add_executable(pose_tracking_example + src/cpp_interface_example/pose_tracking_example.cpp +) +add_dependencies(pose_tracking_example ${catkin_EXPORTED_TARGETS}) +target_link_libraries(pose_tracking_example + ${catkin_LIBRARIES} + ${SERVO_LIB_NAME} + pose_tracking +) + +######################################## +## Library for servoing toward a pose ## +######################################## + +add_library(pose_tracking + src/pose_tracking.cpp +) +add_dependencies(pose_tracking ${catkin_EXPORTED_TARGETS}) +target_link_libraries(pose_tracking + ${catkin_LIBRARIES} + ${SERVO_LIB_NAME} ) ############################ @@ -94,10 +122,8 @@ add_executable(servo_server ) add_dependencies(servo_server ${catkin_EXPORTED_TARGETS}) target_link_libraries(servo_server - ${LIBRARY_NAME} + ${SERVO_LIB_NAME} ${catkin_LIBRARIES} - ${Eigen_LIBRARIES} - ${Boost_LIBRARIES} ) ################################################ @@ -116,7 +142,9 @@ target_link_libraries(spacenav_to_twist ${catkin_LIBRARIES}) install( TARGETS - ${LIBRARY_NAME} + ${SERVO_LIB_NAME} + pose_tracking + pose_tracking_example servo_server spacenav_to_twist ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} @@ -144,9 +172,17 @@ if(CATKIN_ENABLE_TESTING) test/servo_cpp_interface_test.cpp ) target_link_libraries(servo_cpp_interface_test - ${LIBRARY_NAME} + ${SERVO_LIB_NAME} + ${catkin_LIBRARIES} + ) + + # pose_tracking + add_rostest_gtest(pose_tracking_test + test/pose_tracking_test.test + test/pose_tracking_test.cpp + ) + target_link_libraries(pose_tracking_test + pose_tracking ${catkin_LIBRARIES} - ${Eigen_LIBRARIES} - ${Boost_LIBRARIES} ) endif() diff --git a/moveit_ros/moveit_servo/config/pose_tracking_settings.yaml b/moveit_ros/moveit_servo/config/pose_tracking_settings.yaml new file mode 100644 index 0000000000..e4b803774d --- /dev/null +++ b/moveit_ros/moveit_servo/config/pose_tracking_settings.yaml @@ -0,0 +1,21 @@ +################################# +# PID parameters for pose seeking +################################# + +# Maximum value of error integral for all PID controllers +windup_limit: 0.05 + +# PID gains +x_proportional_gain: 1.5 +y_proportional_gain: 1.5 +z_proportional_gain: 1.5 +x_integral_gain: 0.0 +y_integral_gain: 0.0 +z_integral_gain: 0.0 +x_derivative_gain: 0.0 +y_derivative_gain: 0.0 +z_derivative_gain: 0.0 + +angular_proportional_gain: 0.5 +angular_integral_gain: 0.0 +angular_derivative_gain: 0.0 diff --git a/moveit_ros/moveit_servo/config/ur_simulated_config.yaml b/moveit_ros/moveit_servo/config/ur_simulated_config.yaml index 21fd7cbb36..d2ea184f40 100644 --- a/moveit_ros/moveit_servo/config/ur_simulated_config.yaml +++ b/moveit_ros/moveit_servo/config/ur_simulated_config.yaml @@ -4,7 +4,6 @@ use_gazebo: true # Whether the robot is started in a Gazebo simulation environment ## Properties of incoming commands -robot_link_command_frame: world # commands must be given in the frame of a robot link. Usually either the base or end effector command_in_type: "speed_units" # "unitless"> in the range [-1:1], as if from joystick. "speed_units"> cmds are in m/s and rad/s scale: # Scale parameters are only used if command_in_type=="unitless" @@ -31,6 +30,10 @@ publish_joint_accelerations: false move_group_name: manipulator # Often 'manipulator' or 'arm' planning_frame: world # The MoveIt planning frame. Often 'base_link' or 'world' +## Other frames +ee_frame_name: ee_link # The name of the end effector link, used to return the EE pose +robot_link_command_frame: world # commands must be given in the frame of a robot link. Usually either the base or end effector + ## Stopping behaviour incoming_command_timeout: 0.1 # Stop servoing if X seconds elapse without a new command # If 0, republish commands forever even if the robot is stationary. Otherwise, specify num. to publish. diff --git a/moveit_ros/moveit_servo/include/moveit_servo/make_shared_from_pool.h b/moveit_ros/moveit_servo/include/moveit_servo/make_shared_from_pool.h index a593da6127..d3931dad37 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/make_shared_from_pool.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/make_shared_from_pool.h @@ -38,6 +38,7 @@ #pragma once +#include #include namespace moveit diff --git a/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h b/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h new file mode 100644 index 0000000000..bd7c24fbce --- /dev/null +++ b/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h @@ -0,0 +1,195 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2020, PickNik LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of PickNik LLC 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: Andy Zelenak + Desc: Servoing. Track a pose setpoint in real time. +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +// Conventions: +// Calculations are done in the planning_frame_ unless otherwise noted. + +namespace moveit_servo +{ +struct PIDConfig +{ + // Default values + double dt = 0.001; + double k_p = 1; + double k_i = 0; + double k_d = 0; + double windup_limit = 0.1; +}; + +enum class PoseTrackingStatusCode : int8_t +{ + INVALID = -1, + SUCCESS = 0, + NO_RECENT_TARGET_POSE = 1, + NO_RECENT_END_EFFECTOR_POSE = 2, + STOP_REQUESTED = 3 +}; + +const std::unordered_map POSE_TRACKING_STATUS_CODE_MAP( + { { PoseTrackingStatusCode::INVALID, "Invalid" }, + { PoseTrackingStatusCode::SUCCESS, "Success" }, + { PoseTrackingStatusCode::NO_RECENT_TARGET_POSE, "No recent target pose" }, + { PoseTrackingStatusCode::NO_RECENT_END_EFFECTOR_POSE, "No recent end effector pose" }, + { PoseTrackingStatusCode::STOP_REQUESTED, "Stop requested" } }); + +/** + * Class PoseTracking - subscribe to a target pose. + * Servo toward the target pose. + */ +class PoseTracking +{ +public: + /** \brief Constructor. Loads ROS parameters under the given namespace. */ + PoseTracking(const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, + const std::string& parameter_ns = ""); + + PoseTrackingStatusCode moveToPose(const Eigen::Vector3d& positional_tolerance, const double angular_tolerance, + const double target_pose_timeout); + + /** \brief A method for a different thread to stop motion and return early from control loop */ + void stopMotion() + { + stop_requested_ = true; + } + + /** \brief Change PID parameters. Motion is stopped before the udpate */ + void updatePIDConfig(const double x_proportional_gain, const double x_integral_gain, const double x_derivative_gain, + const double y_proportional_gain, const double y_integral_gain, const double y_derivative_gain, + const double z_proportional_gain, const double z_integral_gain, const double z_derivative_gain, + const double angular_proportional_gain, const double angular_integral_gain, + const double angular_derivative_gain); + + void getPIDErrors(double& x_error, double& y_error, double& z_error, double& orientation_error); + + /** + * Get the End Effector link transform. + * The transform from the MoveIt planning frame to EE link + * + * @param transform the transform that will be calculated + * @return true if a valid transform was available + */ + bool getCommandFrameTransform(geometry_msgs::TransformStamped& transform); + + // moveit_servo::Servo instance. Public so we can access member functions like setPaused() + std::unique_ptr servo_; + +private: + /** \brief Load ROS parameters for controller settings. */ + void readROSParams(); + + /** \brief Initialize a PID controller and add it to vector of controllers */ + void initializePID(const PIDConfig& pid_config, std::vector& pid_vector); + + /** \brief Return true if a target pose has been received within timeout [seconds] */ + bool haveRecentTargetPose(const double timeout); + + /** \brief Return true if an end effector pose has been received within timeout [seconds] */ + bool haveRecentEndEffectorPose(const double timeout); + + /** \brief Check if XYZ, roll/pitch/yaw tolerances are satisfied */ + bool satisfiesPoseTolerance(const Eigen::Vector3d& positional_tolerance, const double angular_tolerance); + + /** \brief Subscribe to the target pose on this topic */ + void targetPoseCallback(const geometry_msgs::PoseStampedConstPtr& msg); + + /** \brief Update PID controller target positions & orientations */ + void updateControllerSetpoints(); + + /** \brief Update PID controller states (positions & orientations) */ + void updateControllerStateMeasurements(); + + /** \brief Use PID controllers to calculate a full spatial velocity toward a pose */ + geometry_msgs::TwistStampedConstPtr calculateTwistCommand(); + + /** \brief Reset flags and PID controllers after a motion completes */ + void doPostMotionReset(); + + ros::NodeHandle nh_; + + planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_; + robot_model::RobotModelConstPtr robot_model_; + const moveit::core::JointModelGroup* joint_model_group_; + // Joint group used for controlling the motions + std::string move_group_name_; + + ros::Rate loop_rate_; + + // ROS interface to Servo + ros::Publisher twist_stamped_pub_; + + std::vector cartesian_position_pids_; + std::vector cartesian_orientation_pids_; + // Cartesian PID configs + PIDConfig x_pid_config_, y_pid_config_, z_pid_config_, angular_pid_config_; + + // Transforms w.r.t. planning_frame_ + Eigen::Isometry3d command_frame_transform_; + ros::Time command_frame_transform_stamp_; + geometry_msgs::PoseStamped target_pose_; + + // Subscribe to target pose + ros::Subscriber target_pose_sub_; + + tf2_ros::Buffer transform_buffer_; + tf2_ros::TransformListener transform_listener_; + + // Expected frame name, for error checking and transforms + std::string planning_frame_; + + // Flag that a different thread has requested a stop. + std::atomic stop_requested_; + + // Read parameters from this namespace + std::string parameter_ns_; + + double angular_error_; +}; + +// using alias +using PoseTrackingPtr = std::shared_ptr; +} // namespace moveit_servo diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo.h b/moveit_ros/moveit_servo/include/moveit_servo/servo.h index 139c11b44b..b520d807d6 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo.h @@ -53,7 +53,8 @@ namespace moveit_servo class Servo { public: - Servo(ros::NodeHandle& nh, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor); + Servo(ros::NodeHandle& nh, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, + const std::string& parameter_ns = ""); ~Servo(); @@ -71,6 +72,17 @@ class Servo * @return true if a valid transform was available */ bool getCommandFrameTransform(Eigen::Isometry3d& transform); + bool getCommandFrameTransform(geometry_msgs::TransformStamped& transform); + + /** + * Get the End Effector link transform. + * The transform from the MoveIt planning frame to EE link + * + * @param transform the transform that will be calculated + * @return true if a valid transform was available + */ + bool getEEFrameTransform(Eigen::Isometry3d& transform); + bool getEEFrameTransform(geometry_msgs::TransformStamped& transform); /** \brief Get the parameters used by servo node. */ const ServoParameters& getParameters() const; @@ -78,6 +90,14 @@ class Servo /** \brief Get the latest joint state. */ sensor_msgs::JointStateConstPtr getLatestJointState() const; + /** \brief Change the controlled link. Often, this is the end effector + * This must be a link on the robot since MoveIt tracks the transform (not tf) + */ + void changeRobotLinkCommandFrame(const std::string& new_command_frame) + { + servo_calcs_->changeRobotLinkCommandFrame(new_command_frame); + } + private: bool readParameters(); @@ -92,6 +112,9 @@ class Servo std::shared_ptr joint_state_subscriber_; std::unique_ptr servo_calcs_; std::unique_ptr collision_checker_; + + // Read parameters from this namespace + std::string parameter_ns_; }; // ServoPtr using alias diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h index fa477eaabc..26f7c4c947 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h @@ -39,6 +39,9 @@ #pragma once // ROS +#include +#include +#include #include #include #include @@ -47,8 +50,7 @@ #include #include #include -#include -#include +#include #include // moveit_servo @@ -62,9 +64,9 @@ namespace moveit_servo class ServoCalcs { public: - ServoCalcs(ros::NodeHandle& nh, const ServoParameters& parameters, + ServoCalcs(ros::NodeHandle& nh, ServoParameters& parameters, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, - const std::shared_ptr& joint_state_subscriber); + const std::shared_ptr& joint_state_subscriber, std::string& ros_namespace); ~ServoCalcs() { @@ -82,10 +84,26 @@ class ServoCalcs * @return true if a valid transform was available */ bool getCommandFrameTransform(Eigen::Isometry3d& transform); + bool getCommandFrameTransform(geometry_msgs::TransformStamped& transform); + + /** + * Get the End Effector link transform. + * The transform from the MoveIt planning frame to EE link + * + * @param transform the transform that will be calculated + * @return true if a valid transform was available + */ + bool getEEFrameTransform(Eigen::Isometry3d& transform); + bool getEEFrameTransform(geometry_msgs::TransformStamped& transform); /** \brief Pause or unpause processing servo commands while keeping the timers alive */ void setPaused(bool paused); + /** \brief Change the controlled link. Often, this is the end effector + * This must be a link on the robot since MoveIt tracks the transform (not tf) + */ + void changeRobotLinkCommandFrame(const std::string& new_command_frame); + private: /** \brief Timer method */ void run(const ros::TimerEvent& timer_event); @@ -197,7 +215,7 @@ class ServoCalcs ros::NodeHandle nh_; // Parameters from yaml - const ServoParameters& parameters_; + ServoParameters& parameters_; // Pointer to the collision environment planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_; @@ -282,6 +300,7 @@ class ServoCalcs // latest_state_mutex_ is used to protect the state below it mutable std::mutex latest_state_mutex_; Eigen::Isometry3d tf_moveit_to_robot_cmd_frame_; + Eigen::Isometry3d tf_moveit_to_ee_frame_; geometry_msgs::TwistStampedConstPtr latest_twist_stamped_; control_msgs::JointJogConstPtr latest_joint_cmd_; ros::Time latest_twist_command_stamp_ = ros::Time(0.); diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo_parameters.h b/moveit_ros/moveit_servo/include/moveit_servo/servo_parameters.h index ad0deec16f..45b208db8e 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo_parameters.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo_parameters.h @@ -52,6 +52,7 @@ struct ServoParameters std::string robot_link_command_frame; std::string command_out_topic; std::string planning_frame; + std::string ee_frame_name; std::string status_topic; std::string joint_command_in_topic; std::string command_in_type; diff --git a/moveit_ros/moveit_servo/include/moveit_servo/status_codes.h b/moveit_ros/moveit_servo/include/moveit_servo/status_codes.h index 97e92210cc..5164f46a9e 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/status_codes.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/status_codes.h @@ -43,7 +43,7 @@ namespace moveit_servo { -enum StatusCode : int8_t +enum class StatusCode : int8_t { INVALID = -1, NO_WARNING = 0, @@ -54,12 +54,12 @@ enum StatusCode : int8_t JOINT_BOUND = 5 }; -const std::unordered_map - SERVO_STATUS_CODE_MAP({ { INVALID, "Invalid" }, - { NO_WARNING, "No warnings" }, - { DECELERATE_FOR_SINGULARITY, "Close to a singularity, decelerating" }, - { HALT_FOR_SINGULARITY, "Very close to a singularity, emergency stop" }, - { DECELERATE_FOR_COLLISION, "Close to a collision, decelerating" }, - { HALT_FOR_COLLISION, "Collision detected, emergency stop" }, - { JOINT_BOUND, "Close to a joint bound (position or velocity), halting" } }); +const std::unordered_map + SERVO_STATUS_CODE_MAP({ { StatusCode::INVALID, "Invalid" }, + { StatusCode::NO_WARNING, "No warnings" }, + { StatusCode::DECELERATE_FOR_SINGULARITY, "Close to a singularity, decelerating" }, + { StatusCode::HALT_FOR_SINGULARITY, "Very close to a singularity, emergency stop" }, + { StatusCode::DECELERATE_FOR_COLLISION, "Close to a collision, decelerating" }, + { StatusCode::HALT_FOR_COLLISION, "Collision detected, emergency stop" }, + { StatusCode::JOINT_BOUND, "Close to a joint bound (position or velocity), halting" } }); } // namespace moveit_servo diff --git a/moveit_ros/moveit_servo/launch/pose_tracking_example.launch b/moveit_ros/moveit_servo/launch/pose_tracking_example.launch new file mode 100644 index 0000000000..b3fcc374d2 --- /dev/null +++ b/moveit_ros/moveit_servo/launch/pose_tracking_example.launch @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/moveit_ros/moveit_servo/package.xml b/moveit_ros/moveit_servo/package.xml index cbbc9c6701..1376a83625 100644 --- a/moveit_ros/moveit_servo/package.xml +++ b/moveit_ros/moveit_servo/package.xml @@ -21,14 +21,16 @@ catkin control_msgs + control_toolbox geometry_msgs + moveit_msgs + moveit_ros_planning_interface + rosparam_shortcuts sensor_msgs std_msgs std_srvs + tf2_eigen trajectory_msgs - moveit_msgs - moveit_ros_planning_interface - rosparam_shortcuts joy_teleop spacenav_node diff --git a/moveit_ros/moveit_servo/src/cpp_interface_example/pose_tracking_example.cpp b/moveit_ros/moveit_servo/src/cpp_interface_example/pose_tracking_example.cpp new file mode 100644 index 0000000000..95d3a0aa4e --- /dev/null +++ b/moveit_ros/moveit_servo/src/cpp_interface_example/pose_tracking_example.cpp @@ -0,0 +1,155 @@ +/******************************************************************************* + * Title : pose_tracking_example.cpp + * Project : moveit_servo + * Created : 09/04/2020 + * Author : Adam Pettinger + * + * BSD 3-Clause License + * + * Copyright (c) 2019, Los Alamos National Security, LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include + +static const std::string LOGNAME = "cpp_interface_example"; + +// Class for monitoring status of moveit_servo +class StatusMonitor +{ +public: + StatusMonitor(ros::NodeHandle& nh, const std::string& topic) + { + sub_ = nh.subscribe(topic, 1, &StatusMonitor::statusCB, this); + } + +private: + void statusCB(const std_msgs::Int8ConstPtr& msg) + { + moveit_servo::StatusCode latest_status = static_cast(msg->data); + if (latest_status != status_) + { + status_ = latest_status; + const auto& status_str = moveit_servo::SERVO_STATUS_CODE_MAP.at(status_); + ROS_INFO_STREAM_NAMED(LOGNAME, "Servo status: " << status_str); + } + } + moveit_servo::StatusCode status_ = moveit_servo::StatusCode::INVALID; + ros::Subscriber sub_; +}; + +/** + * Instantiate the pose tracking interface. + * Send a pose slightly different from the starting pose + * Then keep updating the target pose a little bit + */ +int main(int argc, char** argv) +{ + ros::init(argc, argv, LOGNAME); + ros::NodeHandle nh; + ros::AsyncSpinner spinner(8); + spinner.start(); + + // Load the planning scene monitor + planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor; + planning_scene_monitor = std::make_shared("robot_description"); + if (!planning_scene_monitor->getPlanningScene()) + { + ROS_ERROR_STREAM_NAMED(LOGNAME, "Error in setting up the PlanningSceneMonitor."); + exit(EXIT_FAILURE); + } + + planning_scene_monitor->startSceneMonitor(); + planning_scene_monitor->startWorldGeometryMonitor( + planning_scene_monitor::PlanningSceneMonitor::DEFAULT_COLLISION_OBJECT_TOPIC, + planning_scene_monitor::PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_WORLD_TOPIC, + false /* skip octomap monitor */); + planning_scene_monitor->startStateMonitor(); + + // Create the pose tracker + moveit_servo::PoseTracking tracker(planning_scene_monitor, "servo_server"); + + // Make a publisher for sending pose commands + ros::Publisher target_pose_pub = + nh.advertise("/servo_server/target_pose", 1 /* queue */, true /* latch */); + + // Subscribe to servo status (and log it when it changes) + StatusMonitor status_monitor(nh, "servo_server/status"); + + Eigen::Vector3d lin_tol{ 0.01, 0.01, 0.01 }; + double rot_tol = 0.1; + + // Get the current EE transform + geometry_msgs::TransformStamped current_ee_tf; + tracker.getCommandFrameTransform(current_ee_tf); + + // Convert it to a Pose + geometry_msgs::PoseStamped target_pose; + target_pose.header.frame_id = current_ee_tf.header.frame_id; + target_pose.pose.position.x = current_ee_tf.transform.translation.x; + target_pose.pose.position.y = current_ee_tf.transform.translation.y; + target_pose.pose.position.z = current_ee_tf.transform.translation.z; + target_pose.pose.orientation = current_ee_tf.transform.rotation; + + // Modify it a little bit + target_pose.pose.position.x += 0.1; + + // Publish target pose + target_pose.header.stamp = ros::Time::now(); + target_pose_pub.publish(target_pose); + + // Run the pose tracking in a new thread + std::thread move_to_pose_thread( + [&tracker, &lin_tol, &rot_tol] { tracker.moveToPose(lin_tol, rot_tol, 0.1 /* target pose timeout */); }); + + ros::Rate loop_rate(50); + for (size_t i = 0; i < 500; ++i) + { + // Modify the pose target a little bit each cycle + // This is a dynamic pose target + target_pose.pose.position.z += 0.0004; + target_pose.header.stamp = ros::Time::now(); + target_pose_pub.publish(target_pose); + + loop_rate.sleep(); + } + + // Make sure the tracker is stopped and clean up + tracker.stopMotion(); + move_to_pose_thread.join(); + + return EXIT_SUCCESS; +} diff --git a/moveit_ros/moveit_servo/src/joint_state_subscriber.cpp b/moveit_ros/moveit_servo/src/joint_state_subscriber.cpp index c60b331119..22b8b4bfab 100644 --- a/moveit_ros/moveit_servo/src/joint_state_subscriber.cpp +++ b/moveit_ros/moveit_servo/src/joint_state_subscriber.cpp @@ -49,9 +49,15 @@ JointStateSubscriber::JointStateSubscriber(ros::NodeHandle& nh, const std::strin // subscribe to joints joint_state_sub_ = nh.subscribe(joint_state_topic_name, ROS_QUEUE_SIZE, &JointStateSubscriber::jointStateCB, this); + ros::AsyncSpinner spinner(1); + spinner.start(); + // Wait for initial messages ROS_INFO_NAMED(LOGNAME, "Waiting for first joint msg."); - ros::topic::waitForMessage(joint_state_topic_name); + while (latest_joint_state_ == nullptr) + { + ros::Duration(0.01).sleep(); + } ROS_INFO_NAMED(LOGNAME, "Received first joint msg."); } diff --git a/moveit_ros/moveit_servo/src/pose_tracking.cpp b/moveit_ros/moveit_servo/src/pose_tracking.cpp new file mode 100644 index 0000000000..82ed5b8868 --- /dev/null +++ b/moveit_ros/moveit_servo/src/pose_tracking.cpp @@ -0,0 +1,359 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2020, PickNik LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of PickNik LLC 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. + *********************************************************************/ + +#include "moveit_servo/pose_tracking.h" + +namespace +{ +constexpr char LOGNAME[] = "pose_tracking"; +constexpr double DEFAULT_LOOP_RATE = 100; // Hz +constexpr double ROS_STARTUP_WAIT = 10; // sec +} // namespace + +namespace moveit_servo +{ +PoseTracking::PoseTracking(const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, + const std::string& parameter_ns) + : planning_scene_monitor_(planning_scene_monitor) + , loop_rate_(DEFAULT_LOOP_RATE) + , transform_listener_(transform_buffer_) + , stop_requested_(false) + , parameter_ns_(parameter_ns) + , angular_error_(0) +{ + readROSParams(); + + robot_model_ = planning_scene_monitor_->getRobotModel(); + joint_model_group_ = robot_model_->getJointModelGroup(move_group_name_); + + // Initialize PID controllers + initializePID(x_pid_config_, cartesian_position_pids_); + initializePID(y_pid_config_, cartesian_position_pids_); + initializePID(z_pid_config_, cartesian_position_pids_); + initializePID(angular_pid_config_, cartesian_orientation_pids_); + + // Use the C++ interface that Servo provides + servo_ = std::make_unique(nh_, planning_scene_monitor_, parameter_ns_); + servo_->start(); + + // Connect to Servo ROS interfaces + std::string target_pose_topic = "/" + parameter_ns_ + "/target_pose"; + target_pose_sub_ = + nh_.subscribe(target_pose_topic, 1, &PoseTracking::targetPoseCallback, this); + + // Publish outgoing twist commands to the Servo object + twist_stamped_pub_ = + nh_.advertise(servo_->getParameters().cartesian_command_in_topic, 1); +} + +PoseTrackingStatusCode PoseTracking::moveToPose(const Eigen::Vector3d& positional_tolerance, + const double angular_tolerance, const double target_pose_timeout) +{ + // Roll back the target pose timestamp to ensure we wait for a new target pose message + target_pose_.header.stamp = ros::Time::now() - ros::Duration(2 * target_pose_timeout); + + // Wait a bit for a target pose message to arrive. + // The target pose may get updated by new messages as the robot moves (in a callback function). + ros::Time start_time = ros::Time::now(); + while ((!haveRecentTargetPose(target_pose_timeout) || !haveRecentEndEffectorPose(target_pose_timeout)) && + ((ros::Time::now() - start_time).toSec() < target_pose_timeout)) + { + if (servo_->getCommandFrameTransform(command_frame_transform_)) + { + command_frame_transform_stamp_ = ros::Time::now(); + } + ros::Duration(0.001).sleep(); + } + if (!haveRecentTargetPose(target_pose_timeout)) + { + ROS_ERROR_STREAM_NAMED(LOGNAME, "The target pose was not updated recently. Aborting."); + return PoseTrackingStatusCode::NO_RECENT_TARGET_POSE; + } + + while (ros::ok()) + { + // Check for reasons to stop: + // - Goal tolerance is satisfied + // - Timeout + // - Another thread requested a stop + // - PID controllers aren't initialized + if (satisfiesPoseTolerance(positional_tolerance, angular_tolerance)) + { + break; + } + + // Attempt to update robot pose + if (servo_->getCommandFrameTransform(command_frame_transform_)) + { + command_frame_transform_stamp_ = ros::Time::now(); + } + + if (!haveRecentEndEffectorPose(target_pose_timeout)) + { + ROS_ERROR_STREAM_NAMED(LOGNAME, "The end effector pose was not updated in time. Aborting."); + doPostMotionReset(); + return PoseTrackingStatusCode::NO_RECENT_END_EFFECTOR_POSE; + } + if (stop_requested_) + { + ROS_INFO_STREAM_NAMED(LOGNAME, "Halting servo motion, a stop was requested."); + doPostMotionReset(); + return PoseTrackingStatusCode::STOP_REQUESTED; + } + + // Compute servo command from PID controller output + auto msg = calculateTwistCommand(); + + // Send command to the Servo object, for execution + twist_stamped_pub_.publish(*msg); + } + + doPostMotionReset(); + return PoseTrackingStatusCode::SUCCESS; +} + +void PoseTracking::readROSParams() +{ + std::size_t error = 0; + + // Check for parameter namespace from launch file. All other parameters will be read from this namespace. + std::string yaml_namespace; + if (ros::param::get("~parameter_ns", yaml_namespace)) + { + if (!parameter_ns_.empty()) + ROS_WARN_STREAM_NAMED(LOGNAME, + "A parameter namespace was specified in the launch file AND in the constructor argument."); + + parameter_ns_ = yaml_namespace; + } + + // Wait for ROS parameters to load + ros::Time begin = ros::Time::now(); + while (ros::ok() && !ros::param::has(parameter_ns_ + "/planning_frame") && + ((ros::Time::now() - begin).toSec() < ROS_STARTUP_WAIT)) + { + ROS_WARN_STREAM_NAMED(LOGNAME, "Waiting for parameter: " << parameter_ns_ + "/planning_frame"); + ros::Duration(0.1).sleep(); + } + + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/planning_frame", planning_frame_); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/move_group_name", move_group_name_); + if (!planning_scene_monitor_->getRobotModel()->hasJointModelGroup(move_group_name_)) + { + ++error; + ROS_ERROR_STREAM_NAMED(LOGNAME, "Unable to find the specified joint model group: " << move_group_name_); + } + + double publish_period; + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/publish_period", publish_period); + loop_rate_ = ros::Rate(1 / publish_period); + + x_pid_config_.dt = publish_period; + y_pid_config_.dt = publish_period; + z_pid_config_.dt = publish_period; + angular_pid_config_.dt = publish_period; + + double windup_limit; + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/windup_limit", windup_limit); + x_pid_config_.windup_limit = windup_limit; + y_pid_config_.windup_limit = windup_limit; + z_pid_config_.windup_limit = windup_limit; + angular_pid_config_.windup_limit = windup_limit; + + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/x_proportional_gain", x_pid_config_.k_p); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/y_proportional_gain", y_pid_config_.k_p); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/z_proportional_gain", z_pid_config_.k_p); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/x_integral_gain", x_pid_config_.k_i); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/y_integral_gain", y_pid_config_.k_i); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/z_integral_gain", z_pid_config_.k_i); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/x_derivative_gain", x_pid_config_.k_d); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/y_derivative_gain", y_pid_config_.k_d); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/z_derivative_gain", z_pid_config_.k_d); + + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/angular_proportional_gain", angular_pid_config_.k_p); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/angular_integral_gain", angular_pid_config_.k_i); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/angular_derivative_gain", angular_pid_config_.k_d); + + rosparam_shortcuts::shutdownIfError(ros::this_node::getName(), error); +} + +void PoseTracking::initializePID(const PIDConfig& pid_config, std::vector& pid_vector) +{ + bool use_anti_windup = true; + pid_vector.push_back(control_toolbox::Pid(pid_config.k_p, pid_config.k_i, pid_config.k_d, -pid_config.windup_limit, + pid_config.windup_limit, use_anti_windup)); +} + +bool PoseTracking::haveRecentTargetPose(const double timespan) +{ + return ((ros::Time::now() - target_pose_.header.stamp).toSec() < timespan); +} + +bool PoseTracking::haveRecentEndEffectorPose(const double timespan) +{ + return ((ros::Time::now() - command_frame_transform_stamp_).toSec() < timespan); +} + +bool PoseTracking::satisfiesPoseTolerance(const Eigen::Vector3d& positional_tolerance, const double angular_tolerance) +{ + double x_error = target_pose_.pose.position.x - command_frame_transform_.translation()(0); + double y_error = target_pose_.pose.position.y - command_frame_transform_.translation()(1); + double z_error = target_pose_.pose.position.z - command_frame_transform_.translation()(2); + + return (fabs(x_error) < positional_tolerance(0)) && (fabs(y_error) < positional_tolerance(1)) && + (fabs(z_error) < positional_tolerance(2) && fabs(angular_error_) < angular_tolerance); +} + +void PoseTracking::targetPoseCallback(const geometry_msgs::PoseStampedConstPtr& msg) +{ + // Transform to planning frame + target_pose_ = *msg; + geometry_msgs::TransformStamped target_to_planning_frame; + if (target_pose_.header.frame_id != planning_frame_) + { + try + { + target_to_planning_frame = transform_buffer_.lookupTransform(planning_frame_, target_pose_.header.frame_id, + ros::Time(0), ros::Duration(0.1)); + } + catch (tf2::TransformException& ex) + { + ROS_WARN_NAMED(LOGNAME, "%s", ex.what()); + return; + } + tf2::doTransform(target_pose_, target_pose_, target_to_planning_frame); + } + target_pose_.header.stamp = ros::Time::now(); +} + +geometry_msgs::TwistStampedConstPtr PoseTracking::calculateTwistCommand() +{ + // use the shared pool to create a message more efficiently + auto msg = moveit::util::make_shared_from_pool(); + msg->header.frame_id = target_pose_.header.frame_id; + + // Get twist components from PID controllers + geometry_msgs::Twist& twist = msg->twist; + + // Position + twist.linear.x = cartesian_position_pids_[0].computeCommand( + target_pose_.pose.position.x - command_frame_transform_.translation()(0), loop_rate_.expectedCycleTime()); + twist.linear.y = cartesian_position_pids_[1].computeCommand( + target_pose_.pose.position.y - command_frame_transform_.translation()(1), loop_rate_.expectedCycleTime()); + twist.linear.z = cartesian_position_pids_[2].computeCommand( + target_pose_.pose.position.z - command_frame_transform_.translation()(2), loop_rate_.expectedCycleTime()); + + // Orientation algorithm: + // - Find the orientation error as a quaternion: q_error = q_desired * q_current ^ -1 + // - Use the quaternion PID controllers to calculate a quaternion rate, q_error_dot + // - Convert to angular velocity for the TwistStamped message + Eigen::Quaterniond q_desired(target_pose_.pose.orientation.w, target_pose_.pose.orientation.x, + target_pose_.pose.orientation.y, target_pose_.pose.orientation.z); + Eigen::Quaterniond q_current(command_frame_transform_.rotation()); + Eigen::Quaterniond q_error = q_desired * q_current.inverse(); + + // Convert axis-angle to angular velocity + Eigen::AngleAxisd axis_angle(q_error); + // Cache the angular error, for rotation tolerance checking + angular_error_ = axis_angle.angle(); + double ang_vel_magnitude = + cartesian_orientation_pids_[0].computeCommand(angular_error_, loop_rate_.expectedCycleTime()); + twist.angular.x = ang_vel_magnitude * axis_angle.axis()[0]; + twist.angular.y = ang_vel_magnitude * axis_angle.axis()[1]; + twist.angular.z = ang_vel_magnitude * axis_angle.axis()[2]; + + msg->header.stamp = ros::Time::now(); + + return msg; +} + +void PoseTracking::doPostMotionReset() +{ + stop_requested_ = false; + angular_error_ = 0; + + // Reset error integrals and previous errors of PID controllers + cartesian_position_pids_[0].reset(); + cartesian_position_pids_[1].reset(); + cartesian_position_pids_[2].reset(); + cartesian_orientation_pids_[0].reset(); +} + +void PoseTracking::updatePIDConfig(const double x_proportional_gain, const double x_integral_gain, + const double x_derivative_gain, const double y_proportional_gain, + const double y_integral_gain, const double y_derivative_gain, + const double z_proportional_gain, const double z_integral_gain, + const double z_derivative_gain, const double angular_proportional_gain, + const double angular_integral_gain, const double angular_derivative_gain) +{ + stopMotion(); + + x_pid_config_.k_p = x_proportional_gain; + x_pid_config_.k_i = x_integral_gain; + x_pid_config_.k_d = x_derivative_gain; + y_pid_config_.k_p = y_proportional_gain; + y_pid_config_.k_i = y_integral_gain; + y_pid_config_.k_d = y_derivative_gain; + z_pid_config_.k_p = z_proportional_gain; + z_pid_config_.k_i = z_integral_gain; + z_pid_config_.k_d = z_derivative_gain; + + angular_pid_config_.k_p = angular_proportional_gain; + angular_pid_config_.k_i = angular_integral_gain; + angular_pid_config_.k_d = angular_derivative_gain; + + cartesian_position_pids_.clear(); + cartesian_orientation_pids_.clear(); + initializePID(x_pid_config_, cartesian_position_pids_); + initializePID(y_pid_config_, cartesian_position_pids_); + initializePID(z_pid_config_, cartesian_position_pids_); + initializePID(angular_pid_config_, cartesian_orientation_pids_); + + doPostMotionReset(); +} + +void PoseTracking::getPIDErrors(double& x_error, double& y_error, double& z_error, double& orientation_error) +{ + double dummy1, dummy2; + cartesian_position_pids_.at(0).getCurrentPIDErrors(&x_error, &dummy1, &dummy2); + cartesian_position_pids_.at(1).getCurrentPIDErrors(&y_error, &dummy1, &dummy2); + cartesian_position_pids_.at(2).getCurrentPIDErrors(&z_error, &dummy1, &dummy2); + cartesian_orientation_pids_.at(0).getCurrentPIDErrors(&orientation_error, &dummy1, &dummy2); +} + +bool PoseTracking::getCommandFrameTransform(geometry_msgs::TransformStamped& transform) +{ + return servo_->getCommandFrameTransform(transform); +} +} // namespace moveit_servo diff --git a/moveit_ros/moveit_servo/src/servo.cpp b/moveit_ros/moveit_servo/src/servo.cpp index 761be5903e..f278d18f67 100644 --- a/moveit_ros/moveit_servo/src/servo.cpp +++ b/moveit_ros/moveit_servo/src/servo.cpp @@ -45,8 +45,9 @@ static const std::string LOGNAME = "servo_node"; namespace moveit_servo { -Servo::Servo(ros::NodeHandle& nh, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor) - : nh_(nh), planning_scene_monitor_(planning_scene_monitor) +Servo::Servo(ros::NodeHandle& nh, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, + const std::string& parameter_ns) + : nh_(nh), planning_scene_monitor_(planning_scene_monitor), parameter_ns_(parameter_ns) { // Read ROS parameters, typically from YAML file if (!readParameters()) @@ -54,7 +55,8 @@ Servo::Servo(ros::NodeHandle& nh, const planning_scene_monitor::PlanningSceneMon joint_state_subscriber_ = std::make_shared(nh_, parameters_.joint_topic); - servo_calcs_ = std::make_unique(nh_, parameters_, planning_scene_monitor_, joint_state_subscriber_); + servo_calcs_ = + std::make_unique(nh_, parameters_, planning_scene_monitor_, joint_state_subscriber_, parameter_ns_); collision_checker_ = std::make_unique(nh_, parameters_, planning_scene_monitor_, joint_state_subscriber_); @@ -65,67 +67,67 @@ bool Servo::readParameters() { std::size_t error = 0; - // Specified in the launch file. All other parameters will be read from this namespace. - std::string parameter_ns; - ros::param::get("~parameter_ns", parameter_ns); - if (parameter_ns.empty()) + // Check for parameter namespace from launch file. All other parameters will be read from this namespace. + std::string yaml_namespace; + if (ros::param::get("~parameter_ns", yaml_namespace)) { - ROS_ERROR_STREAM_NAMED(LOGNAME, "A namespace must be specified in the launch file, like:"); - ROS_ERROR_STREAM_NAMED(LOGNAME, ""); - return false; + if (!parameter_ns_.empty()) + ROS_WARN_STREAM_NAMED(LOGNAME, + "A parameter namespace was specified in the launch file AND in the constructor argument."); + + parameter_ns_ = yaml_namespace; } - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/publish_period", parameters_.publish_period); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/collision_check_rate", parameters_.collision_check_rate); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/num_outgoing_halt_msgs_to_publish", + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/publish_period", parameters_.publish_period); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/collision_check_rate", parameters_.collision_check_rate); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/num_outgoing_halt_msgs_to_publish", parameters_.num_outgoing_halt_msgs_to_publish); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/scale/linear", parameters_.linear_scale); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/scale/rotational", parameters_.rotational_scale); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/scale/joint", parameters_.joint_scale); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/scale/linear", parameters_.linear_scale); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/scale/rotational", parameters_.rotational_scale); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/scale/joint", parameters_.joint_scale); error += - !rosparam_shortcuts::get("", nh_, parameter_ns + "/low_pass_filter_coeff", parameters_.low_pass_filter_coeff); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/joint_topic", parameters_.joint_topic); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/command_in_type", parameters_.command_in_type); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/cartesian_command_in_topic", + !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/low_pass_filter_coeff", parameters_.low_pass_filter_coeff); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/joint_topic", parameters_.joint_topic); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/command_in_type", parameters_.command_in_type); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/cartesian_command_in_topic", parameters_.cartesian_command_in_topic); error += - !rosparam_shortcuts::get("", nh_, parameter_ns + "/joint_command_in_topic", parameters_.joint_command_in_topic); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/robot_link_command_frame", + !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/joint_command_in_topic", parameters_.joint_command_in_topic); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/robot_link_command_frame", parameters_.robot_link_command_frame); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/incoming_command_timeout", + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/incoming_command_timeout", parameters_.incoming_command_timeout); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/lower_singularity_threshold", + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/lower_singularity_threshold", parameters_.lower_singularity_threshold); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/hard_stop_singularity_threshold", + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/hard_stop_singularity_threshold", parameters_.hard_stop_singularity_threshold); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/move_group_name", parameters_.move_group_name); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/planning_frame", parameters_.planning_frame); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/use_gazebo", parameters_.use_gazebo); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/joint_limit_margin", parameters_.joint_limit_margin); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/command_out_topic", parameters_.command_out_topic); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/command_out_type", parameters_.command_out_type); - error += - !rosparam_shortcuts::get("", nh_, parameter_ns + "/publish_joint_positions", parameters_.publish_joint_positions); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/publish_joint_velocities", + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/move_group_name", parameters_.move_group_name); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/planning_frame", parameters_.planning_frame); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/ee_frame_name", parameters_.ee_frame_name); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/use_gazebo", parameters_.use_gazebo); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/joint_limit_margin", parameters_.joint_limit_margin); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/command_out_topic", parameters_.command_out_topic); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/command_out_type", parameters_.command_out_type); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/publish_joint_positions", + parameters_.publish_joint_positions); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/publish_joint_velocities", parameters_.publish_joint_velocities); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/publish_joint_accelerations", + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/publish_joint_accelerations", parameters_.publish_joint_accelerations); // Parameters for collision checking - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/check_collisions", parameters_.check_collisions); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/collision_check_type", parameters_.collision_check_type); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/check_collisions", parameters_.check_collisions); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/collision_check_type", parameters_.collision_check_type); bool have_self_collision_proximity_threshold = rosparam_shortcuts::get( - "", nh_, parameter_ns + "/self_collision_proximity_threshold", parameters_.self_collision_proximity_threshold); + "", nh_, parameter_ns_ + "/self_collision_proximity_threshold", parameters_.self_collision_proximity_threshold); bool have_scene_collision_proximity_threshold = rosparam_shortcuts::get( - "", nh_, parameter_ns + "/scene_collision_proximity_threshold", parameters_.scene_collision_proximity_threshold); + "", nh_, parameter_ns_ + "/scene_collision_proximity_threshold", parameters_.scene_collision_proximity_threshold); double collision_proximity_threshold; // 'collision_proximity_threshold' parameter was removed, replaced with separate self- and scene-collision proximity // thresholds // TODO(JStech): remove this deprecation warning in ROS Noetic; simplify error case handling - if (nh_.hasParam(parameter_ns + "/collision_proximity_threshold") && - rosparam_shortcuts::get("", nh_, parameter_ns + "/collision_proximity_threshold", collision_proximity_threshold)) + if (nh_.hasParam(parameter_ns_ + "/collision_proximity_threshold") && + rosparam_shortcuts::get("", nh_, parameter_ns_ + "/collision_proximity_threshold", collision_proximity_threshold)) { ROS_WARN_NAMED(LOGNAME, "'collision_proximity_threshold' parameter is deprecated, and has been replaced by separate" "'self_collision_proximity_threshold' and 'scene_collision_proximity_threshold' " @@ -143,22 +145,22 @@ bool Servo::readParameters() } error += !have_self_collision_proximity_threshold; error += !have_scene_collision_proximity_threshold; - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/collision_distance_safety_factor", + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/collision_distance_safety_factor", parameters_.collision_distance_safety_factor); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/min_allowable_collision_distance", + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/min_allowable_collision_distance", parameters_.min_allowable_collision_distance); // This parameter name was changed recently. // Try retrieving from the correct name. If it fails, then try the deprecated name. // TODO(andyz): remove this deprecation warning in ROS Noetic - if (!rosparam_shortcuts::get("", nh_, parameter_ns + "/status_topic", parameters_.status_topic)) + if (!rosparam_shortcuts::get("", nh_, parameter_ns_ + "/status_topic", parameters_.status_topic)) { ROS_WARN_NAMED(LOGNAME, "'status_topic' parameter is missing. Recently renamed from 'warning_topic'. Please update " "the servoing yaml file."); - error += !rosparam_shortcuts::get("", nh_, parameter_ns + "/warning_topic", parameters_.status_topic); + error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/warning_topic", parameters_.status_topic); } - rosparam_shortcuts::shutdownIfError(parameter_ns, error); + rosparam_shortcuts::shutdownIfError(parameter_ns_, error); // Input checking if (parameters_.publish_period <= 0.) @@ -302,6 +304,21 @@ bool Servo::getCommandFrameTransform(Eigen::Isometry3d& transform) return servo_calcs_->getCommandFrameTransform(transform); } +bool Servo::getCommandFrameTransform(geometry_msgs::TransformStamped& transform) +{ + return servo_calcs_->getEEFrameTransform(transform); +} + +bool Servo::getEEFrameTransform(Eigen::Isometry3d& transform) +{ + return servo_calcs_->getEEFrameTransform(transform); +} + +bool Servo::getEEFrameTransform(geometry_msgs::TransformStamped& transform) +{ + return servo_calcs_->getEEFrameTransform(transform); +} + const ServoParameters& Servo::getParameters() const { return parameters_; diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index 8dbb1be123..f7cbfc48c3 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -69,12 +69,24 @@ bool isNonZero(const control_msgs::JointJog& msg) }; return !all_zeros; } + +// Helper function for converting Eigen::Isometry3d to geometry_msgs/TransformStamped +geometry_msgs::TransformStamped convertIsometryToTransform(const Eigen::Isometry3d& eigen_tf, + const std::string& parent_frame, + const std::string& child_frame) +{ + geometry_msgs::TransformStamped output = tf2::eigenToTransform(eigen_tf); + output.header.frame_id = parent_frame; + output.child_frame_id = child_frame; + + return output; +} } // namespace // Constructor for the class that handles servoing calculations -ServoCalcs::ServoCalcs(ros::NodeHandle& nh, const ServoParameters& parameters, +ServoCalcs::ServoCalcs(ros::NodeHandle& nh, ServoParameters& parameters, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, - const std::shared_ptr& joint_state_subscriber) + const std::shared_ptr& joint_state_subscriber, std::string& ros_namespace) : nh_(nh) , parameters_(parameters) , planning_scene_monitor_(planning_scene_monitor) @@ -102,18 +114,15 @@ ServoCalcs::ServoCalcs(ros::NodeHandle& nh, const ServoParameters& parameters, // ROS Server for allowing drift in some dimensions drift_dimensions_server_ = - nh_.advertiseService(nh_.getNamespace() + "/" + ros::this_node::getName() + "/change_drift_dimensions", - &ServoCalcs::changeDriftDimensions, this); + nh_.advertiseService(ros_namespace + "/change_drift_dimensions", &ServoCalcs::changeDriftDimensions, this); // ROS Server for changing the control dimensions control_dimensions_server_ = - nh_.advertiseService(nh_.getNamespace() + "/" + ros::this_node::getName() + "/change_control_dimensions", - &ServoCalcs::changeControlDimensions, this); + nh_.advertiseService(ros_namespace + "/change_control_dimensions", &ServoCalcs::changeControlDimensions, this); // ROS Server to reset the status, e.g. so the arm can move again after a collision reset_servo_status_ = - nh_.advertiseService(nh_.getNamespace() + "/" + ros::this_node::getName() + "/reset_servo_status", - &ServoCalcs::resetServoStatus, this); + nh_.advertiseService(ros_namespace + "/reset_servo_status", &ServoCalcs::resetServoStatus, this); // Publish and Subscribe to internal namespace topics ros::NodeHandle internal_nh("~internal"); @@ -147,6 +156,12 @@ ServoCalcs::ServoCalcs(ros::NodeHandle& nh, const ServoParameters& parameters, { position_filters_.emplace_back(parameters_.low_pass_filter_coeff); } + + // A matrix of all zeros is used to check whether matrices have been initialized + Eigen::Matrix3d empty_matrix; + empty_matrix.setZero(); + tf_moveit_to_ee_frame_ = empty_matrix; + tf_moveit_to_robot_cmd_frame_ = empty_matrix; } void ServoCalcs::start() @@ -180,6 +195,15 @@ void ServoCalcs::start() last_sent_command_ = initial_joint_trajectory; timer_ = nh_.createTimer(period_, &ServoCalcs::run, this); + + // TODO(adamp or andyz): after rebasing on upstream master, update this section. Maybe put the tf updates in a tiny + // function by themselves + sensor_msgs::JointStateConstPtr latest_joint_state = joint_state_subscriber_->getLatest(); + kinematic_state_->setVariableValues(*latest_joint_state); + tf_moveit_to_ee_frame_ = kinematic_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * + kinematic_state_->getGlobalLinkTransform(parameters_.ee_frame_name); + tf_moveit_to_robot_cmd_frame_ = kinematic_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * + kinematic_state_->getGlobalLinkTransform(parameters_.robot_link_command_frame); } void ServoCalcs::run(const ros::TimerEvent& timer_event) @@ -232,6 +256,11 @@ void ServoCalcs::run(const ros::TimerEvent& timer_event) tf_moveit_to_robot_cmd_frame_ = kinematic_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * kinematic_state_->getGlobalLinkTransform(parameters_.robot_link_command_frame); + // Calculate the transform from MoveIt planning frame to End Effector frame + // Calculate this transform to ensure it is available via C++ API + tf_moveit_to_ee_frame_ = kinematic_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * + kinematic_state_->getGlobalLinkTransform(parameters_.ee_frame_name); + have_nonzero_command_ = have_nonzero_twist_stamped_ || have_nonzero_joint_command_; // Don't end this function without updating the filters @@ -403,6 +432,12 @@ bool ServoCalcs::cartesianServoCalcs(geometry_msgs::TwistStamped& cmd, translation_vector = tf_moveit_to_robot_cmd_frame_.linear() * translation_vector; angular_vector = tf_moveit_to_robot_cmd_frame_.linear() * angular_vector; } + else if (cmd.header.frame_id == parameters_.ee_frame_name) + { + // If the frame is the EE frame, we already have that transform as well + translation_vector = tf_moveit_to_ee_frame_.linear() * translation_vector; + angular_vector = tf_moveit_to_ee_frame_.linear() * angular_vector; + } else { // We solve (planning_frame -> base -> cmd.header.frame_id) @@ -982,6 +1017,42 @@ bool ServoCalcs::getCommandFrameTransform(Eigen::Isometry3d& transform) return !transform.matrix().isZero(0); } +bool ServoCalcs::getCommandFrameTransform(geometry_msgs::TransformStamped& transform) +{ + const std::lock_guard lock(latest_state_mutex_); + // All zeros means the transform wasn't initialized, so return false + if (tf_moveit_to_robot_cmd_frame_.matrix().isZero(0)) + { + return false; + } + + transform = convertIsometryToTransform(tf_moveit_to_robot_cmd_frame_, parameters_.planning_frame, + parameters_.robot_link_command_frame); + return true; +} + +bool ServoCalcs::getEEFrameTransform(Eigen::Isometry3d& transform) +{ + const std::lock_guard lock(latest_state_mutex_); + transform = tf_moveit_to_ee_frame_; + + // All zeros means the transform wasn't initialized, so return false + return !transform.matrix().isZero(0); +} + +bool ServoCalcs::getEEFrameTransform(geometry_msgs::TransformStamped& transform) +{ + const std::lock_guard lock(latest_state_mutex_); + // All zeros means the transform wasn't initialized, so return false + if (tf_moveit_to_ee_frame_.matrix().isZero(0)) + { + return false; + } + + transform = convertIsometryToTransform(tf_moveit_to_ee_frame_, parameters_.planning_frame, parameters_.ee_frame_name); + return true; +} + void ServoCalcs::twistStampedCB(const geometry_msgs::TwistStampedConstPtr& msg) { const std::lock_guard lock(latest_state_mutex_); @@ -1046,4 +1117,9 @@ void ServoCalcs::setPaused(bool paused) paused_ = paused; } +void ServoCalcs::changeRobotLinkCommandFrame(const std::string& new_command_frame) +{ + parameters_.robot_link_command_frame = new_command_frame; +} + } // namespace moveit_servo diff --git a/moveit_ros/moveit_servo/test/config/servo_settings.yaml b/moveit_ros/moveit_servo/test/config/servo_settings.yaml index 30e4cb59d2..802aeadca2 100644 --- a/moveit_ros/moveit_servo/test/config/servo_settings.yaml +++ b/moveit_ros/moveit_servo/test/config/servo_settings.yaml @@ -4,7 +4,6 @@ use_gazebo: false # Whether the robot is started in a Gazebo simulation environment ## Properties of incoming commands -robot_link_command_frame: panda_link0 # commands must be given in the frame of a robot link. Usually either the base or end effector command_in_type: "speed_units" # "unitless"> in the range [-1:1], as if from joystick. "speed_units"> cmds are in m/s and rad/s scale: # Scale parameters are only used if command_in_type=="unitless" @@ -31,6 +30,10 @@ publish_joint_accelerations: false move_group_name: panda_arm # Often 'manipulator' or 'arm' planning_frame: panda_link0 # The MoveIt planning frame. Often 'panda_link0' or 'world' +## Other frames +ee_frame_name: panda_link7 # The name of the end effector link, used to return the EE pose +robot_link_command_frame: panda_link0 # commands must be given in the frame of a robot link. Usually either the base or end effector + ## Stopping behaviour incoming_command_timeout: 1 # Stop servoing if X seconds elapse without a new command # If 0, republish commands forever even if the robot is stationary. Otherwise, specify num. to publish. diff --git a/moveit_ros/moveit_servo/test/pose_tracking_test.cpp b/moveit_ros/moveit_servo/test/pose_tracking_test.cpp new file mode 100644 index 0000000000..782fa23c5a --- /dev/null +++ b/moveit_ros/moveit_servo/test/pose_tracking_test.cpp @@ -0,0 +1,162 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2020, PickNik LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of PickNik LLC 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: Andy Zelenak + Desc: Test of tracking toward a pose +*/ + +// C++ +#include +#include + +// ROS +#include + +// Testing +#include + +// Servo +#include +#include + +static const std::string LOGNAME = "servo_cpp_interface_test"; +static constexpr double TRANSLATION_TOLERANCE = 0.01; // meters +static constexpr double ROTATION_TOLERANCE = 0.1; // quaternion +static constexpr double ROS_PUB_SUB_DELAY = 4; // allow for subscribers to initialize + +namespace moveit_servo +{ +class PoseTrackingFixture : public ::testing::Test +{ +public: + void SetUp() override + { + // Wait for several key topics / parameters + ros::topic::waitForMessage("/joint_states"); + while (!nh_.hasParam("/robot_description") && ros::ok()) + { + ros::Duration(0.1).sleep(); + } + + // Load the planning scene monitor + planning_scene_monitor_ = std::make_shared("robot_description"); + planning_scene_monitor_->startSceneMonitor(); + planning_scene_monitor_->startStateMonitor(); + planning_scene_monitor_->startWorldGeometryMonitor( + planning_scene_monitor::PlanningSceneMonitor::DEFAULT_COLLISION_OBJECT_TOPIC, + planning_scene_monitor::PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_WORLD_TOPIC, + false /* skip octomap monitor */); + + tracker_ = std::make_shared(planning_scene_monitor_, ""); + + target_pose_pub_ = + nh_.advertise("/pose_tracking_test/target_pose", 1 /* queue */, true /* latch */); + + // Tolerance for pose seeking + translation_tolerance_ << TRANSLATION_TOLERANCE, TRANSLATION_TOLERANCE, TRANSLATION_TOLERANCE; + } + void TearDown() override + { + } + +protected: + ros::NodeHandle nh_; + planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_; + Eigen::Vector3d translation_tolerance_; + moveit_servo::PoseTrackingPtr tracker_; + ros::Publisher target_pose_pub_; +}; // class PoseTrackingFixture + +// Check for commands going out to ros_control +TEST_F(PoseTrackingFixture, OutgoingMsgTest) +{ + // halt Servoing when first msg to ros_control is received + // and test some conditions + trajectory_msgs::JointTrajectory last_received_msg; + boost::function traj_callback = + [&/* this */](const trajectory_msgs::JointTrajectoryConstPtr& msg) { + EXPECT_EQ(msg->header.frame_id, "panda_link0"); + // Check for an expected joint position command + // As of now, the robot doesn't actually move because there are no controllers enabled. + double angle_tolerance = 0.08; // rad + EXPECT_NEAR(msg->points[0].positions[0], 0, angle_tolerance); + EXPECT_NEAR(msg->points[0].positions[1], -0.785, angle_tolerance); + EXPECT_NEAR(msg->points[0].positions[2], 0, angle_tolerance); + EXPECT_NEAR(msg->points[0].positions[3], -2.360, angle_tolerance); + EXPECT_NEAR(msg->points[0].positions[4], 0, angle_tolerance); + EXPECT_NEAR(msg->points[0].positions[5], 1.571, angle_tolerance); + EXPECT_NEAR(msg->points[0].positions[6], 0.785, angle_tolerance); + + this->tracker_->stopMotion(); + return; + }; + auto traj_sub = nh_.subscribe("servo_server/command", 1, traj_callback); + + geometry_msgs::PoseStamped target_pose; + target_pose.header.frame_id = "panda_link4"; + target_pose.header.stamp = ros::Time::now(); + target_pose.pose.position.x = 0.2; + target_pose.pose.position.y = 0.2; + target_pose.pose.position.z = 0.2; + target_pose.pose.orientation.w = 1; + + // Republish the target pose in a new thread, as if the target is moving + std::thread target_pub_thread([&] { + size_t msg_count = 0; + while (++msg_count < 100) + { + target_pose_pub_.publish(target_pose); + ros::Duration(0.01).sleep(); + } + }); + + ros::Duration(ROS_PUB_SUB_DELAY).sleep(); + tracker_->moveToPose(translation_tolerance_, ROTATION_TOLERANCE, 1 /* target pose timeout */); + + target_pub_thread.join(); +} + +} // namespace moveit_servo + +int main(int argc, char** argv) +{ + ros::init(argc, argv, LOGNAME); + testing::InitGoogleTest(&argc, argv); + + ros::AsyncSpinner spinner(8); + spinner.start(); + + int result = RUN_ALL_TESTS(); + return result; +} diff --git a/moveit_ros/moveit_servo/test/pose_tracking_test.test b/moveit_ros/moveit_servo/test/pose_tracking_test.test new file mode 100644 index 0000000000..4f162d0c0d --- /dev/null +++ b/moveit_ros/moveit_servo/test/pose_tracking_test.test @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp b/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp index 1579f1f12b..53684c1787 100644 --- a/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp +++ b/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp @@ -59,6 +59,13 @@ class ServoFixture : public ::testing::Test public: void SetUp() override { + // Wait for several key topics / parameters + ros::topic::waitForMessage("/joint_states"); + while (!nh_.hasParam("/robot_description") && ros::ok()) + { + ros::Duration(0.1).sleep(); + } + // Load the planning scene monitor planning_scene_monitor_ = std::make_shared("robot_description"); planning_scene_monitor_->startSceneMonitor(); From 6a5c1574256b5018b52d1e0216640a4efc6b279e Mon Sep 17 00:00:00 2001 From: Peter Mitrano Date: Wed, 14 Oct 2020 11:21:36 -0400 Subject: [PATCH 042/179] Python interface improvements. Fix #1966, add enforceBounds (#2356) * implement get state and get state bounded * add enforceBounds Co-authored-by: Peter --- .../src/moveit_commander/move_group.py | 23 +++++++++++++-- .../test/python_moveit_commander.py | 29 +++++++++++++++++++ .../src/wrap_python_move_group.cpp | 28 ++++++++++++++++++ 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/moveit_commander/src/moveit_commander/move_group.py b/moveit_commander/src/moveit_commander/move_group.py index c13cf5d0a7..a9af06c79b 100644 --- a/moveit_commander/src/moveit_commander/move_group.py +++ b/moveit_commander/src/moveit_commander/move_group.py @@ -155,6 +155,20 @@ def set_start_state(self, msg): """ self._g.set_start_state(conversions.msg_to_string(msg)) + def get_current_state_bounded(self): + """ Get the current state of the robot bounded.""" + s = RobotState() + c_str = self._g.get_current_state_bounded() + conversions.msg_from_string(s, c_str) + return s + + def get_current_state(self): + """ Get the current state of the robot.""" + s = RobotState() + c_str = self._g.get_current_state() + conversions.msg_from_string(s, c_str) + return s + def get_joint_value_target(self): return self._g.get_joint_value_target() @@ -229,8 +243,7 @@ def set_joint_value_target(self, arg1, arg2 = None, arg3 = None): else: raise MoveItCommanderException("Unsupported argument of type %s" % type(arg1)) - - def set_rpy_target(self, rpy, end_effector_link = ""): + def set_rpy_target(self, rpy, end_effector_link=""): """ Specify a target orientation for the end-effector. Any position of the end-effector is acceptable.""" if len(end_effector_link) > 0 or self.has_end_effector_link(): if len(rpy) == 3: @@ -598,3 +611,9 @@ def get_jacobian_matrix(self, joint_values, reference_point=None): """ Get the jacobian matrix of the group as a list""" return self._g.get_jacobian_matrix(joint_values, [0.0, 0.0, 0.0] if reference_point is None else reference_point) + def enforce_bounds(self, robot_state_msg): + """ Takes a moveit_msgs RobotState and enforces the state bounds, based on the C++ RobotState enforceBounds() """ + s = RobotState() + c_str = self._g.enforce_bounds(conversions.msg_to_string(robot_state_msg)) + conversions.msg_from_string(s, c_str) + return s diff --git a/moveit_commander/test/python_moveit_commander.py b/moveit_commander/test/python_moveit_commander.py index 41d77dc922..294f562e83 100755 --- a/moveit_commander/test/python_moveit_commander.py +++ b/moveit_commander/test/python_moveit_commander.py @@ -35,11 +35,15 @@ # Author: William Baker import unittest + +import genpy import numpy as np import rospy import rostest import os +from moveit_msgs.msg import RobotState + from moveit_commander import RobotCommander, PlanningSceneInterface @@ -55,6 +59,31 @@ def setUpClass(self): def tearDown(self): pass + def test_enforce_bounds_empty_state(self): + in_msg = RobotState() + with self.assertRaises(genpy.DeserializationError): + self.group.enforce_bounds(in_msg) + + def test_enforce_bounds(self): + in_msg = RobotState() + in_msg.joint_state.header.frame_id = 'base_link' + in_msg.joint_state.name = ['joint_1', 'joint_2', 'joint_3', 'joint_4', 'joint_5', 'joint_6'] + in_msg.joint_state.position = [0] * 6 + in_msg.joint_state.position[0] = 1000 + + out_msg = self.group.enforce_bounds(in_msg) + + self.assertEqual(in_msg.joint_state.position[0], 1000) + self.assertLess(out_msg.joint_state.position[0], 1000) + + def test_get_current_state(self): + expected_state = RobotState() + expected_state.joint_state.header.frame_id = 'base_link' + expected_state.multi_dof_joint_state.header.frame_id = 'base_link' + expected_state.joint_state.name = ['joint_1', 'joint_2', 'joint_3', 'joint_4', 'joint_5', 'joint_6'] + expected_state.joint_state.position = [0] * 6 + self.assertEqual(self.group.get_current_state(), expected_state) + def check_target_setting(self, expect, *args): if len(args) == 0: args = [expect] diff --git a/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp b/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp index f8bcccecce..4244838404 100644 --- a/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp +++ b/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp @@ -350,6 +350,14 @@ class MoveGroupInterfaceWrapper : protected py_bindings_tools::ROScppInitializer return output; } + py_bindings_tools::ByteString getCurrentStatePython() + { + moveit::core::RobotStatePtr current_state = getCurrentState(); + moveit_msgs::RobotState state_message; + moveit::core::robotStateToRobotStateMsg(*current_state, state_message); + return py_bindings_tools::serializeMsg(state_message); + } + void setStartStatePython(const py_bindings_tools::ByteString& msg_str) { moveit_msgs::RobotState msg; @@ -608,6 +616,24 @@ class MoveGroupInterfaceWrapper : protected py_bindings_tools::ROScppInitializer state.setJointGroupPositions(group, v); return state.getJacobian(group, Eigen::Map(&ref[0])); } + + py_bindings_tools::ByteString enforceBoundsPython(const py_bindings_tools::ByteString& msg_str) + { + moveit_msgs::RobotState state_msg; + py_bindings_tools::deserializeMsg(msg_str, state_msg); + moveit::core::RobotState state(getRobotModel()); + if (moveit::core::robotStateMsgToRobotState(state_msg, state, true)) + { + state.enforceBounds(); + moveit::core::robotStateToRobotStateMsg(state, state_msg); + return py_bindings_tools::serializeMsg(state_msg); + } + else + { + ROS_ERROR("Unable to convert RobotState message to RobotState instance."); + return py_bindings_tools::ByteString(""); + } + } }; BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(getJacobianMatrixOverloads, getJacobianMatrixPython, 1, 2) @@ -749,8 +775,10 @@ static void wrap_move_group_interface() move_group_interface_class.def("get_named_targets", &MoveGroupInterfaceWrapper::getNamedTargetsPython); move_group_interface_class.def("get_named_target_values", &MoveGroupInterfaceWrapper::getNamedTargetValuesPython); move_group_interface_class.def("get_current_state_bounded", &MoveGroupInterfaceWrapper::getCurrentStateBoundedPython); + move_group_interface_class.def("get_current_state", &MoveGroupInterfaceWrapper::getCurrentStatePython); move_group_interface_class.def("get_jacobian_matrix", &MoveGroupInterfaceWrapper::getJacobianMatrixPython, getJacobianMatrixOverloads()); + move_group_interface_class.def("enforce_bounds", &MoveGroupInterfaceWrapper::enforceBoundsPython); } } // namespace planning_interface } // namespace moveit From e8fe263c8628bbde1869f0972434dc107e534169 Mon Sep 17 00:00:00 2001 From: Nathan Brooks Date: Thu, 15 Oct 2020 11:12:49 -0600 Subject: [PATCH 043/179] Fix ordering of windup args to control_toolbox::Pid (#2370) --- moveit_ros/moveit_servo/src/pose_tracking.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moveit_ros/moveit_servo/src/pose_tracking.cpp b/moveit_ros/moveit_servo/src/pose_tracking.cpp index 82ed5b8868..aeee8255fb 100644 --- a/moveit_ros/moveit_servo/src/pose_tracking.cpp +++ b/moveit_ros/moveit_servo/src/pose_tracking.cpp @@ -211,8 +211,8 @@ void PoseTracking::readROSParams() void PoseTracking::initializePID(const PIDConfig& pid_config, std::vector& pid_vector) { bool use_anti_windup = true; - pid_vector.push_back(control_toolbox::Pid(pid_config.k_p, pid_config.k_i, pid_config.k_d, -pid_config.windup_limit, - pid_config.windup_limit, use_anti_windup)); + pid_vector.push_back(control_toolbox::Pid(pid_config.k_p, pid_config.k_i, pid_config.k_d, pid_config.windup_limit, + -pid_config.windup_limit, use_anti_windup)); } bool PoseTracking::haveRecentTargetPose(const double timespan) From 080c5e389e11c521f5138be75cbf220320552259 Mon Sep 17 00:00:00 2001 From: "David V. Lu!!" Date: Fri, 16 Oct 2020 03:13:40 -0400 Subject: [PATCH 044/179] MSA launch files: fix indentation (#2371) converting tabs to spaces --- moveit_setup_assistant/launch/setup_assistant.launch | 2 +- .../templates/moveit_config_pkg_template/launch/demo.launch | 2 +- .../launch/edit_configuration_package.launch | 4 ++-- .../moveit_config_pkg_template/launch/move_group.launch | 2 +- .../moveit_config_pkg_template/launch/moveit_rviz.launch | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/moveit_setup_assistant/launch/setup_assistant.launch b/moveit_setup_assistant/launch/setup_assistant.launch index 4d908ba325..d3446da716 100644 --- a/moveit_setup_assistant/launch/setup_assistant.launch +++ b/moveit_setup_assistant/launch/setup_assistant.launch @@ -8,7 +8,7 @@ diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch index 5ee0462e0a..78452951eb 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch @@ -26,7 +26,7 @@ - [VIRTUAL_JOINT_BROADCASTER] +[VIRTUAL_JOINT_BROADCASTER] diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/edit_configuration_package.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/edit_configuration_package.launch index 6a313304a9..613028d317 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/edit_configuration_package.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/edit_configuration_package.launch @@ -8,8 +8,8 @@ diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/move_group.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/move_group.launch index fb1959b048..b41620c229 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/move_group.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/move_group.launch @@ -4,7 +4,7 @@ + value="gdb -x $(find [GENERATED_PACKAGE_NAME])/launch/gdb_settings.gdb --ex run --args" /> diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/moveit_rviz.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/moveit_rviz.launch index 615b2f12a5..a4605c0374 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/moveit_rviz.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/moveit_rviz.launch @@ -9,7 +9,7 @@ + args="$(arg command_args)" output="screen"> From 11419517bdb2d0ab16dac4d0673115043b3d6e72 Mon Sep 17 00:00:00 2001 From: "David V. Lu!!" Date: Wed, 21 Oct 2020 02:05:52 -0400 Subject: [PATCH 045/179] Update .github files (#2380) --- .github/ISSUE_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 62f551be4a..2f81a5e828 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -3,8 +3,8 @@ Overview of your issue here. ### Your environment -* ROS Distro: [Indigo|Jade|Kinetic] -* OS Version: e.g. Ubuntu 16.04 +* ROS Distro: [Kinetic|Melodic|Noetic] +* OS Version: e.g. Ubuntu 18.04 * Source or Binary build? * If binary, which release version? * If source, which git commit or tag? From e200231d97e2cbad25c0ecaba5fe13becd85b1be Mon Sep 17 00:00:00 2001 From: Jere Liukkonen Date: Wed, 21 Oct 2020 12:58:50 -0600 Subject: [PATCH 046/179] Fix servo trajectory point timestamping (#2375) --- moveit_ros/moveit_servo/src/pose_tracking.cpp | 7 ++----- moveit_ros/moveit_servo/src/servo_calcs.cpp | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/moveit_ros/moveit_servo/src/pose_tracking.cpp b/moveit_ros/moveit_servo/src/pose_tracking.cpp index aeee8255fb..bd45fbf91f 100644 --- a/moveit_ros/moveit_servo/src/pose_tracking.cpp +++ b/moveit_ros/moveit_servo/src/pose_tracking.cpp @@ -132,11 +132,8 @@ PoseTrackingStatusCode PoseTracking::moveToPose(const Eigen::Vector3d& positiona return PoseTrackingStatusCode::STOP_REQUESTED; } - // Compute servo command from PID controller output - auto msg = calculateTwistCommand(); - - // Send command to the Servo object, for execution - twist_stamped_pub_.publish(*msg); + // Compute servo command from PID controller output and send it to the Servo object, for execution + twist_stamped_pub_.publish(calculateTwistCommand()); } doPostMotionReset(); diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index f7cbfc48c3..aca414e649 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -169,8 +169,10 @@ void ServoCalcs::start() // We will update last_sent_command_ every time we start servo auto initial_joint_trajectory = moveit::util::make_shared_from_pool(); + // When a joint_trajectory_controller receives a new command, a stamp of 0 indicates "begin immediately" + // See http://wiki.ros.org/joint_trajectory_controller#Trajectory_replacement + initial_joint_trajectory->header.stamp = ros::Time(0); initial_joint_trajectory->header.frame_id = parameters_.planning_frame; - initial_joint_trajectory->header.stamp = ros::Time::now(); initial_joint_trajectory->joint_names = internal_joint_state_.name; trajectory_msgs::JointTrajectoryPoint point; point.time_from_start = ros::Duration(parameters_.publish_period); @@ -361,7 +363,9 @@ void ServoCalcs::run(const ros::TimerEvent& timer_event) // (trajectory_msgs/JointTrajectory or std_msgs/Float64MultiArray). if (parameters_.command_out_type == "trajectory_msgs/JointTrajectory") { - joint_trajectory->header.stamp = ros::Time::now(); + // When a joint_trajectory_controller receives a new command, a stamp of 0 indicates "begin immediately" + // See http://wiki.ros.org/joint_trajectory_controller#Trajectory_replacement + joint_trajectory->header.stamp = ros::Time(0); outgoing_cmd_pub_.publish(joint_trajectory); } else if (parameters_.command_out_type == "std_msgs/Float64MultiArray") @@ -594,8 +598,10 @@ void ServoCalcs::calculateJointVelocities(sensor_msgs::JointState& joint_state, void ServoCalcs::composeJointTrajMessage(const sensor_msgs::JointState& joint_state, trajectory_msgs::JointTrajectory& joint_trajectory) const { + // When a joint_trajectory_controller receives a new command, a stamp of 0 indicates "begin immediately" + // See http://wiki.ros.org/joint_trajectory_controller#Trajectory_replacement + joint_trajectory.header.stamp = ros::Time(0); joint_trajectory.header.frame_id = parameters_.planning_frame; - joint_trajectory.header.stamp = ros::Time::now(); joint_trajectory.joint_names = joint_state.name; trajectory_msgs::JointTrajectoryPoint point; @@ -810,6 +816,13 @@ void ServoCalcs::suddenHalt(trajectory_msgs::JointTrajectory& joint_trajectory) joint_trajectory.points.clear(); joint_trajectory.points.emplace_back(); trajectory_msgs::JointTrajectoryPoint& point = joint_trajectory.points.front(); + + // When sending out trajectory_msgs/JointTrajectory type messages, the "trajectory" is just a single point. + // That point cannot have the same timestamp as the start of trajectory execution since that would mean the + // arm has to reach the first trajectory point the moment execution begins. To prevent errors about points + // being 0 seconds in the past, the smallest supported timestep is added as time from start to the trajectory point. + point.time_from_start.fromNSec(1); + point.positions.resize(num_joints_); point.velocities.resize(num_joints_); From ff32c43a83ef6375a29587bfcbbb875ff0a66fe9 Mon Sep 17 00:00:00 2001 From: Jere Liukkonen Date: Thu, 22 Oct 2020 11:20:38 -0600 Subject: [PATCH 047/179] Change servo namespacing logic (#2354) * Publish services correctly in the namespace of the node. * Set relative joint state topic names be relative to the parent namespace of the servo node. * Make parameter sub-namespace optional. By default load the parameters into node namespace. * Fix node handles for the servo server node and the cpp interface example to use node namespace instead of the parent namespace. * Fix formatting * Reading ee_frame_name parameter got lost somewhere along the way. Add it back. * Remove explicit parameter_ns variables and used namespaced node handles instead. * Fix internal namespace to truly be internal even in case where two or more Servo instances are launched from a single node. * Fix command_out_topic parameter in ur_simulated_config.yaml example config. * Apply namespacing fixes also to tests. * Shorten the comment about joint states topic names. --- .../config/ur_simulated_config.yaml | 10 +- .../include/moveit_servo/pose_tracking.h | 6 +- .../moveit_servo/include/moveit_servo/servo.h | 6 +- .../include/moveit_servo/servo_calcs.h | 2 +- .../launch/cpp_interface_example.launch | 4 +- .../moveit_servo/launch/spacenav_cpp.launch | 4 +- .../launch/spacenav_teleop_tools.launch | 4 +- .../moveit_servo/src/collision_check.cpp | 2 +- .../cpp_interface_example.cpp | 2 +- .../pose_tracking_example.cpp | 8 +- moveit_ros/moveit_servo/src/pose_tracking.cpp | 72 ++++++------ moveit_ros/moveit_servo/src/servo.cpp | 110 ++++++++---------- moveit_ros/moveit_servo/src/servo_calcs.cpp | 16 +-- moveit_ros/moveit_servo/src/servo_server.cpp | 2 +- .../moveit_servo/test/pose_tracking_test.cpp | 7 +- .../moveit_servo/test/pose_tracking_test.test | 2 +- .../test/servo_cpp_interface_test.cpp | 2 +- .../test/servo_cpp_interface_test.test | 4 +- 18 files changed, 121 insertions(+), 142 deletions(-) diff --git a/moveit_ros/moveit_servo/config/ur_simulated_config.yaml b/moveit_ros/moveit_servo/config/ur_simulated_config.yaml index d2ea184f40..59b6599e5d 100644 --- a/moveit_ros/moveit_servo/config/ur_simulated_config.yaml +++ b/moveit_ros/moveit_servo/config/ur_simulated_config.yaml @@ -46,11 +46,11 @@ hard_stop_singularity_threshold: 30 # Stop when the condition number hits this joint_limit_margin: 0.1 # added as a buffer to joint limits [radians]. If moving quickly, make this larger. ## Topic names -cartesian_command_in_topic: servo_server/delta_twist_cmds # Topic for incoming Cartesian twist commands -joint_command_in_topic: servo_server/delta_joint_cmds # Topic for incoming joint angle commands -joint_topic: joint_states -status_topic: servo_server/status # Publish status to this topic -command_out_topic: joint_group_position_controller/command # Publish outgoing commands here +cartesian_command_in_topic: delta_twist_cmds # Topic for incoming Cartesian twist commands +joint_command_in_topic: delta_joint_cmds # Topic for incoming joint angle commands +joint_topic: joint_states +status_topic: status # Publish status to this topic +command_out_topic: /joint_group_position_controller/command # Publish outgoing commands here ## Collision checking for the entire robot body check_collisions: true # Check collisions? diff --git a/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h b/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h index bd7c24fbce..d76c58481b 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h @@ -85,8 +85,7 @@ class PoseTracking { public: /** \brief Constructor. Loads ROS parameters under the given namespace. */ - PoseTracking(const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, - const std::string& parameter_ns = ""); + PoseTracking(const ros::NodeHandle& nh, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor); PoseTrackingStatusCode moveToPose(const Eigen::Vector3d& positional_tolerance, const double angular_tolerance, const double target_pose_timeout); @@ -184,9 +183,6 @@ class PoseTracking // Flag that a different thread has requested a stop. std::atomic stop_requested_; - // Read parameters from this namespace - std::string parameter_ns_; - double angular_error_; }; diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo.h b/moveit_ros/moveit_servo/include/moveit_servo/servo.h index b520d807d6..6205e09c97 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo.h @@ -53,8 +53,7 @@ namespace moveit_servo class Servo { public: - Servo(ros::NodeHandle& nh, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, - const std::string& parameter_ns = ""); + Servo(ros::NodeHandle& nh, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor); ~Servo(); @@ -112,9 +111,6 @@ class Servo std::shared_ptr joint_state_subscriber_; std::unique_ptr servo_calcs_; std::unique_ptr collision_checker_; - - // Read parameters from this namespace - std::string parameter_ns_; }; // ServoPtr using alias diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h index 26f7c4c947..37e7e647db 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h @@ -66,7 +66,7 @@ class ServoCalcs public: ServoCalcs(ros::NodeHandle& nh, ServoParameters& parameters, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, - const std::shared_ptr& joint_state_subscriber, std::string& ros_namespace); + const std::shared_ptr& joint_state_subscriber); ~ServoCalcs() { diff --git a/moveit_ros/moveit_servo/launch/cpp_interface_example.launch b/moveit_ros/moveit_servo/launch/cpp_interface_example.launch index c2ac9b8748..7498446ff8 100644 --- a/moveit_ros/moveit_servo/launch/cpp_interface_example.launch +++ b/moveit_ros/moveit_servo/launch/cpp_interface_example.launch @@ -2,8 +2,8 @@ - - + + diff --git a/moveit_ros/moveit_servo/launch/spacenav_cpp.launch b/moveit_ros/moveit_servo/launch/spacenav_cpp.launch index 41d81862db..b60db1fa0e 100644 --- a/moveit_ros/moveit_servo/launch/spacenav_cpp.launch +++ b/moveit_ros/moveit_servo/launch/spacenav_cpp.launch @@ -13,8 +13,8 @@ - - + + diff --git a/moveit_ros/moveit_servo/launch/spacenav_teleop_tools.launch b/moveit_ros/moveit_servo/launch/spacenav_teleop_tools.launch index 93847e35a1..e3834b5e16 100644 --- a/moveit_ros/moveit_servo/launch/spacenav_teleop_tools.launch +++ b/moveit_ros/moveit_servo/launch/spacenav_teleop_tools.launch @@ -10,8 +10,8 @@ - - + + diff --git a/moveit_ros/moveit_servo/src/collision_check.cpp b/moveit_ros/moveit_servo/src/collision_check.cpp index 38b62c383c..3d79a4421e 100644 --- a/moveit_ros/moveit_servo/src/collision_check.cpp +++ b/moveit_ros/moveit_servo/src/collision_check.cpp @@ -75,7 +75,7 @@ CollisionCheck::CollisionCheck(ros::NodeHandle& nh, const moveit_servo::ServoPar safety_factor_ = parameters_.collision_distance_safety_factor; // Internal namespace - ros::NodeHandle internal_nh("~internal"); + ros::NodeHandle internal_nh(nh_, "internal"); collision_velocity_scale_pub_ = internal_nh.advertise("collision_velocity_scale", ROS_QUEUE_SIZE); worst_case_stop_time_sub_ = internal_nh.subscribe("worst_case_stop_time", ROS_QUEUE_SIZE, &CollisionCheck::worstCaseStopTimeCB, this); diff --git a/moveit_ros/moveit_servo/src/cpp_interface_example/cpp_interface_example.cpp b/moveit_ros/moveit_servo/src/cpp_interface_example/cpp_interface_example.cpp index c1170d10a9..d51ce11b19 100644 --- a/moveit_ros/moveit_servo/src/cpp_interface_example/cpp_interface_example.cpp +++ b/moveit_ros/moveit_servo/src/cpp_interface_example/cpp_interface_example.cpp @@ -75,7 +75,7 @@ class StatusMonitor int main(int argc, char** argv) { ros::init(argc, argv, LOGNAME); - ros::NodeHandle nh; + ros::NodeHandle nh("~"); ros::AsyncSpinner spinner(8); spinner.start(); diff --git a/moveit_ros/moveit_servo/src/cpp_interface_example/pose_tracking_example.cpp b/moveit_ros/moveit_servo/src/cpp_interface_example/pose_tracking_example.cpp index 95d3a0aa4e..b5ec8d176f 100644 --- a/moveit_ros/moveit_servo/src/cpp_interface_example/pose_tracking_example.cpp +++ b/moveit_ros/moveit_servo/src/cpp_interface_example/pose_tracking_example.cpp @@ -79,7 +79,7 @@ class StatusMonitor int main(int argc, char** argv) { ros::init(argc, argv, LOGNAME); - ros::NodeHandle nh; + ros::NodeHandle nh("~"); ros::AsyncSpinner spinner(8); spinner.start(); @@ -100,14 +100,14 @@ int main(int argc, char** argv) planning_scene_monitor->startStateMonitor(); // Create the pose tracker - moveit_servo::PoseTracking tracker(planning_scene_monitor, "servo_server"); + moveit_servo::PoseTracking tracker(nh, planning_scene_monitor); // Make a publisher for sending pose commands ros::Publisher target_pose_pub = - nh.advertise("/servo_server/target_pose", 1 /* queue */, true /* latch */); + nh.advertise("target_pose", 1 /* queue */, true /* latch */); // Subscribe to servo status (and log it when it changes) - StatusMonitor status_monitor(nh, "servo_server/status"); + StatusMonitor status_monitor(nh, "status"); Eigen::Vector3d lin_tol{ 0.01, 0.01, 0.01 }; double rot_tol = 0.1; diff --git a/moveit_ros/moveit_servo/src/pose_tracking.cpp b/moveit_ros/moveit_servo/src/pose_tracking.cpp index bd45fbf91f..065e547f8e 100644 --- a/moveit_ros/moveit_servo/src/pose_tracking.cpp +++ b/moveit_ros/moveit_servo/src/pose_tracking.cpp @@ -43,13 +43,13 @@ constexpr double ROS_STARTUP_WAIT = 10; // sec namespace moveit_servo { -PoseTracking::PoseTracking(const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, - const std::string& parameter_ns) - : planning_scene_monitor_(planning_scene_monitor) +PoseTracking::PoseTracking(const ros::NodeHandle& nh, + const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor) + : nh_(nh) + , planning_scene_monitor_(planning_scene_monitor) , loop_rate_(DEFAULT_LOOP_RATE) , transform_listener_(transform_buffer_) , stop_requested_(false) - , parameter_ns_(parameter_ns) , angular_error_(0) { readROSParams(); @@ -64,13 +64,12 @@ PoseTracking::PoseTracking(const planning_scene_monitor::PlanningSceneMonitorPtr initializePID(angular_pid_config_, cartesian_orientation_pids_); // Use the C++ interface that Servo provides - servo_ = std::make_unique(nh_, planning_scene_monitor_, parameter_ns_); + servo_ = std::make_unique(nh_, planning_scene_monitor_); servo_->start(); // Connect to Servo ROS interfaces - std::string target_pose_topic = "/" + parameter_ns_ + "/target_pose"; target_pose_sub_ = - nh_.subscribe(target_pose_topic, 1, &PoseTracking::targetPoseCallback, this); + nh_.subscribe("target_pose", 1, &PoseTracking::targetPoseCallback, this); // Publish outgoing twist commands to the Servo object twist_stamped_pub_ = @@ -142,30 +141,27 @@ PoseTrackingStatusCode PoseTracking::moveToPose(const Eigen::Vector3d& positiona void PoseTracking::readROSParams() { - std::size_t error = 0; - - // Check for parameter namespace from launch file. All other parameters will be read from this namespace. - std::string yaml_namespace; - if (ros::param::get("~parameter_ns", yaml_namespace)) - { - if (!parameter_ns_.empty()) - ROS_WARN_STREAM_NAMED(LOGNAME, - "A parameter namespace was specified in the launch file AND in the constructor argument."); + // Optional parameter sub-namespace specified in the launch file. All other parameters will be read from this namespace. + std::string parameter_ns; + ros::param::get("~parameter_ns", parameter_ns); - parameter_ns_ = yaml_namespace; - } + // If parameters have been loaded into sub-namespace within the node namespace, append the parameter namespace + // to load the parameters correctly. + ros::NodeHandle nh = parameter_ns.empty() ? nh_ : ros::NodeHandle(nh_, parameter_ns); // Wait for ROS parameters to load ros::Time begin = ros::Time::now(); - while (ros::ok() && !ros::param::has(parameter_ns_ + "/planning_frame") && - ((ros::Time::now() - begin).toSec() < ROS_STARTUP_WAIT)) + while (ros::ok() && !nh.hasParam("planning_frame") && ((ros::Time::now() - begin).toSec() < ROS_STARTUP_WAIT)) { - ROS_WARN_STREAM_NAMED(LOGNAME, "Waiting for parameter: " << parameter_ns_ + "/planning_frame"); + ROS_WARN_STREAM_NAMED(LOGNAME, "Waiting for parameter: " + << "planning_frame"); ros::Duration(0.1).sleep(); } - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/planning_frame", planning_frame_); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/move_group_name", move_group_name_); + std::size_t error = 0; + + error += !rosparam_shortcuts::get(LOGNAME, nh, "planning_frame", planning_frame_); + error += !rosparam_shortcuts::get(LOGNAME, nh, "move_group_name", move_group_name_); if (!planning_scene_monitor_->getRobotModel()->hasJointModelGroup(move_group_name_)) { ++error; @@ -173,7 +169,7 @@ void PoseTracking::readROSParams() } double publish_period; - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/publish_period", publish_period); + error += !rosparam_shortcuts::get(LOGNAME, nh, "publish_period", publish_period); loop_rate_ = ros::Rate(1 / publish_period); x_pid_config_.dt = publish_period; @@ -182,25 +178,25 @@ void PoseTracking::readROSParams() angular_pid_config_.dt = publish_period; double windup_limit; - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/windup_limit", windup_limit); + error += !rosparam_shortcuts::get(LOGNAME, nh, "windup_limit", windup_limit); x_pid_config_.windup_limit = windup_limit; y_pid_config_.windup_limit = windup_limit; z_pid_config_.windup_limit = windup_limit; angular_pid_config_.windup_limit = windup_limit; - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/x_proportional_gain", x_pid_config_.k_p); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/y_proportional_gain", y_pid_config_.k_p); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/z_proportional_gain", z_pid_config_.k_p); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/x_integral_gain", x_pid_config_.k_i); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/y_integral_gain", y_pid_config_.k_i); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/z_integral_gain", z_pid_config_.k_i); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/x_derivative_gain", x_pid_config_.k_d); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/y_derivative_gain", y_pid_config_.k_d); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/z_derivative_gain", z_pid_config_.k_d); - - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/angular_proportional_gain", angular_pid_config_.k_p); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/angular_integral_gain", angular_pid_config_.k_i); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/angular_derivative_gain", angular_pid_config_.k_d); + error += !rosparam_shortcuts::get(LOGNAME, nh, "x_proportional_gain", x_pid_config_.k_p); + error += !rosparam_shortcuts::get(LOGNAME, nh, "y_proportional_gain", y_pid_config_.k_p); + error += !rosparam_shortcuts::get(LOGNAME, nh, "z_proportional_gain", z_pid_config_.k_p); + error += !rosparam_shortcuts::get(LOGNAME, nh, "x_integral_gain", x_pid_config_.k_i); + error += !rosparam_shortcuts::get(LOGNAME, nh, "y_integral_gain", y_pid_config_.k_i); + error += !rosparam_shortcuts::get(LOGNAME, nh, "z_integral_gain", z_pid_config_.k_i); + error += !rosparam_shortcuts::get(LOGNAME, nh, "x_derivative_gain", x_pid_config_.k_d); + error += !rosparam_shortcuts::get(LOGNAME, nh, "y_derivative_gain", y_pid_config_.k_d); + error += !rosparam_shortcuts::get(LOGNAME, nh, "z_derivative_gain", z_pid_config_.k_d); + + error += !rosparam_shortcuts::get(LOGNAME, nh, "angular_proportional_gain", angular_pid_config_.k_p); + error += !rosparam_shortcuts::get(LOGNAME, nh, "angular_integral_gain", angular_pid_config_.k_i); + error += !rosparam_shortcuts::get(LOGNAME, nh, "angular_derivative_gain", angular_pid_config_.k_d); rosparam_shortcuts::shutdownIfError(ros::this_node::getName(), error); } diff --git a/moveit_ros/moveit_servo/src/servo.cpp b/moveit_ros/moveit_servo/src/servo.cpp index f278d18f67..8467837429 100644 --- a/moveit_ros/moveit_servo/src/servo.cpp +++ b/moveit_ros/moveit_servo/src/servo.cpp @@ -45,18 +45,19 @@ static const std::string LOGNAME = "servo_node"; namespace moveit_servo { -Servo::Servo(ros::NodeHandle& nh, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, - const std::string& parameter_ns) - : nh_(nh), planning_scene_monitor_(planning_scene_monitor), parameter_ns_(parameter_ns) +Servo::Servo(ros::NodeHandle& nh, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor) + : nh_(nh), planning_scene_monitor_(planning_scene_monitor) { // Read ROS parameters, typically from YAML file if (!readParameters()) exit(EXIT_FAILURE); - joint_state_subscriber_ = std::make_shared(nh_, parameters_.joint_topic); + // By default, joint topic name is relative to the node parent namespace. Fully custom joint name topics can be + // set by using absolute topic names in config files. For example, "/foo/my_joint_state_topic". + ros::NodeHandle nh_parent_ns = ros::NodeHandle(""); + joint_state_subscriber_ = std::make_shared(nh_parent_ns, parameters_.joint_topic); - servo_calcs_ = - std::make_unique(nh_, parameters_, planning_scene_monitor_, joint_state_subscriber_, parameter_ns_); + servo_calcs_ = std::make_unique(nh_, parameters_, planning_scene_monitor_, joint_state_subscriber_); collision_checker_ = std::make_unique(nh_, parameters_, planning_scene_monitor_, joint_state_subscriber_); @@ -67,67 +68,58 @@ bool Servo::readParameters() { std::size_t error = 0; - // Check for parameter namespace from launch file. All other parameters will be read from this namespace. - std::string yaml_namespace; - if (ros::param::get("~parameter_ns", yaml_namespace)) - { - if (!parameter_ns_.empty()) - ROS_WARN_STREAM_NAMED(LOGNAME, - "A parameter namespace was specified in the launch file AND in the constructor argument."); + // Optional parameter sub-namespace specified in the launch file. All other parameters will be read from this namespace. + std::string parameter_ns; + ros::param::get("~parameter_ns", parameter_ns); - parameter_ns_ = yaml_namespace; - } + // If parameters have been loaded into sub-namespace within the node namespace, append the parameter namespace + // to load the parameters correctly. + ros::NodeHandle nh = parameter_ns.empty() ? nh_ : ros::NodeHandle(nh_, parameter_ns); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/publish_period", parameters_.publish_period); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/collision_check_rate", parameters_.collision_check_rate); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/num_outgoing_halt_msgs_to_publish", + error += !rosparam_shortcuts::get(LOGNAME, nh, "publish_period", parameters_.publish_period); + error += !rosparam_shortcuts::get(LOGNAME, nh, "collision_check_rate", parameters_.collision_check_rate); + error += !rosparam_shortcuts::get(LOGNAME, nh, "num_outgoing_halt_msgs_to_publish", parameters_.num_outgoing_halt_msgs_to_publish); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/scale/linear", parameters_.linear_scale); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/scale/rotational", parameters_.rotational_scale); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/scale/joint", parameters_.joint_scale); - error += - !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/low_pass_filter_coeff", parameters_.low_pass_filter_coeff); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/joint_topic", parameters_.joint_topic); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/command_in_type", parameters_.command_in_type); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/cartesian_command_in_topic", - parameters_.cartesian_command_in_topic); + error += !rosparam_shortcuts::get(LOGNAME, nh, "scale/linear", parameters_.linear_scale); + error += !rosparam_shortcuts::get(LOGNAME, nh, "scale/rotational", parameters_.rotational_scale); + error += !rosparam_shortcuts::get(LOGNAME, nh, "scale/joint", parameters_.joint_scale); + error += !rosparam_shortcuts::get(LOGNAME, nh, "low_pass_filter_coeff", parameters_.low_pass_filter_coeff); + error += !rosparam_shortcuts::get(LOGNAME, nh, "joint_topic", parameters_.joint_topic); + error += !rosparam_shortcuts::get(LOGNAME, nh, "command_in_type", parameters_.command_in_type); + error += !rosparam_shortcuts::get(LOGNAME, nh, "cartesian_command_in_topic", parameters_.cartesian_command_in_topic); + error += !rosparam_shortcuts::get(LOGNAME, nh, "joint_command_in_topic", parameters_.joint_command_in_topic); + error += !rosparam_shortcuts::get(LOGNAME, nh, "robot_link_command_frame", parameters_.robot_link_command_frame); + error += !rosparam_shortcuts::get(LOGNAME, nh, "incoming_command_timeout", parameters_.incoming_command_timeout); error += - !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/joint_command_in_topic", parameters_.joint_command_in_topic); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/robot_link_command_frame", - parameters_.robot_link_command_frame); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/incoming_command_timeout", - parameters_.incoming_command_timeout); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/lower_singularity_threshold", - parameters_.lower_singularity_threshold); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/hard_stop_singularity_threshold", + !rosparam_shortcuts::get(LOGNAME, nh, "lower_singularity_threshold", parameters_.lower_singularity_threshold); + error += !rosparam_shortcuts::get(LOGNAME, nh, "hard_stop_singularity_threshold", parameters_.hard_stop_singularity_threshold); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/move_group_name", parameters_.move_group_name); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/planning_frame", parameters_.planning_frame); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/ee_frame_name", parameters_.ee_frame_name); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/use_gazebo", parameters_.use_gazebo); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/joint_limit_margin", parameters_.joint_limit_margin); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/command_out_topic", parameters_.command_out_topic); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/command_out_type", parameters_.command_out_type); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/publish_joint_positions", - parameters_.publish_joint_positions); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/publish_joint_velocities", - parameters_.publish_joint_velocities); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/publish_joint_accelerations", - parameters_.publish_joint_accelerations); + error += !rosparam_shortcuts::get(LOGNAME, nh, "move_group_name", parameters_.move_group_name); + error += !rosparam_shortcuts::get(LOGNAME, nh, "planning_frame", parameters_.planning_frame); + error += !rosparam_shortcuts::get(LOGNAME, nh, "ee_frame_name", parameters_.ee_frame_name); + error += !rosparam_shortcuts::get(LOGNAME, nh, "use_gazebo", parameters_.use_gazebo); + error += !rosparam_shortcuts::get(LOGNAME, nh, "joint_limit_margin", parameters_.joint_limit_margin); + error += !rosparam_shortcuts::get(LOGNAME, nh, "command_out_topic", parameters_.command_out_topic); + error += !rosparam_shortcuts::get(LOGNAME, nh, "command_out_type", parameters_.command_out_type); + error += !rosparam_shortcuts::get(LOGNAME, nh, "publish_joint_positions", parameters_.publish_joint_positions); + error += !rosparam_shortcuts::get(LOGNAME, nh, "publish_joint_velocities", parameters_.publish_joint_velocities); + error += + !rosparam_shortcuts::get(LOGNAME, nh, "publish_joint_accelerations", parameters_.publish_joint_accelerations); // Parameters for collision checking - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/check_collisions", parameters_.check_collisions); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/collision_check_type", parameters_.collision_check_type); + error += !rosparam_shortcuts::get(LOGNAME, nh, "check_collisions", parameters_.check_collisions); + error += !rosparam_shortcuts::get(LOGNAME, nh, "collision_check_type", parameters_.collision_check_type); bool have_self_collision_proximity_threshold = rosparam_shortcuts::get( - "", nh_, parameter_ns_ + "/self_collision_proximity_threshold", parameters_.self_collision_proximity_threshold); + LOGNAME, nh, "self_collision_proximity_threshold", parameters_.self_collision_proximity_threshold); bool have_scene_collision_proximity_threshold = rosparam_shortcuts::get( - "", nh_, parameter_ns_ + "/scene_collision_proximity_threshold", parameters_.scene_collision_proximity_threshold); + LOGNAME, nh, "scene_collision_proximity_threshold", parameters_.scene_collision_proximity_threshold); + double collision_proximity_threshold; // 'collision_proximity_threshold' parameter was removed, replaced with separate self- and scene-collision proximity // thresholds // TODO(JStech): remove this deprecation warning in ROS Noetic; simplify error case handling - if (nh_.hasParam(parameter_ns_ + "/collision_proximity_threshold") && - rosparam_shortcuts::get("", nh_, parameter_ns_ + "/collision_proximity_threshold", collision_proximity_threshold)) + if (nh_.hasParam("collision_proximity_threshold") && + rosparam_shortcuts::get(LOGNAME, nh, "collision_proximity_threshold", collision_proximity_threshold)) { ROS_WARN_NAMED(LOGNAME, "'collision_proximity_threshold' parameter is deprecated, and has been replaced by separate" "'self_collision_proximity_threshold' and 'scene_collision_proximity_threshold' " @@ -145,22 +137,22 @@ bool Servo::readParameters() } error += !have_self_collision_proximity_threshold; error += !have_scene_collision_proximity_threshold; - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/collision_distance_safety_factor", + error += !rosparam_shortcuts::get(LOGNAME, nh, "collision_distance_safety_factor", parameters_.collision_distance_safety_factor); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/min_allowable_collision_distance", + error += !rosparam_shortcuts::get(LOGNAME, nh, "min_allowable_collision_distance", parameters_.min_allowable_collision_distance); // This parameter name was changed recently. // Try retrieving from the correct name. If it fails, then try the deprecated name. // TODO(andyz): remove this deprecation warning in ROS Noetic - if (!rosparam_shortcuts::get("", nh_, parameter_ns_ + "/status_topic", parameters_.status_topic)) + if (!rosparam_shortcuts::get(LOGNAME, nh, "status_topic", parameters_.status_topic)) { ROS_WARN_NAMED(LOGNAME, "'status_topic' parameter is missing. Recently renamed from 'warning_topic'. Please update " "the servoing yaml file."); - error += !rosparam_shortcuts::get("", nh_, parameter_ns_ + "/warning_topic", parameters_.status_topic); + error += !rosparam_shortcuts::get(LOGNAME, nh, "warning_topic", parameters_.status_topic); } - rosparam_shortcuts::shutdownIfError(parameter_ns_, error); + rosparam_shortcuts::shutdownIfError(LOGNAME, error); // Input checking if (parameters_.publish_period <= 0.) diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index aca414e649..4b06627621 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -86,7 +86,7 @@ geometry_msgs::TransformStamped convertIsometryToTransform(const Eigen::Isometry // Constructor for the class that handles servoing calculations ServoCalcs::ServoCalcs(ros::NodeHandle& nh, ServoParameters& parameters, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, - const std::shared_ptr& joint_state_subscriber, std::string& ros_namespace) + const std::shared_ptr& joint_state_subscriber) : nh_(nh) , parameters_(parameters) , planning_scene_monitor_(planning_scene_monitor) @@ -113,19 +113,19 @@ ServoCalcs::ServoCalcs(ros::NodeHandle& nh, ServoParameters& parameters, joint_cmd_sub_ = nh_.subscribe(parameters_.joint_command_in_topic, ROS_QUEUE_SIZE, &ServoCalcs::jointCmdCB, this); // ROS Server for allowing drift in some dimensions - drift_dimensions_server_ = - nh_.advertiseService(ros_namespace + "/change_drift_dimensions", &ServoCalcs::changeDriftDimensions, this); + drift_dimensions_server_ = nh_.advertiseService(ros::names::append(nh_.getNamespace(), "change_drift_dimensions"), + &ServoCalcs::changeDriftDimensions, this); // ROS Server for changing the control dimensions - control_dimensions_server_ = - nh_.advertiseService(ros_namespace + "/change_control_dimensions", &ServoCalcs::changeControlDimensions, this); + control_dimensions_server_ = nh_.advertiseService(ros::names::append(nh_.getNamespace(), "change_control_dimensions"), + &ServoCalcs::changeControlDimensions, this); // ROS Server to reset the status, e.g. so the arm can move again after a collision - reset_servo_status_ = - nh_.advertiseService(ros_namespace + "/reset_servo_status", &ServoCalcs::resetServoStatus, this); + reset_servo_status_ = nh_.advertiseService(ros::names::append(nh_.getNamespace(), "reset_servo_status"), + &ServoCalcs::resetServoStatus, this); // Publish and Subscribe to internal namespace topics - ros::NodeHandle internal_nh("~internal"); + ros::NodeHandle internal_nh(nh_, "internal"); collision_velocity_scale_sub_ = internal_nh.subscribe("collision_velocity_scale", ROS_QUEUE_SIZE, &ServoCalcs::collisionVelocityScaleCB, this); worst_case_stop_time_pub_ = internal_nh.advertise("worst_case_stop_time", ROS_QUEUE_SIZE); diff --git a/moveit_ros/moveit_servo/src/servo_server.cpp b/moveit_ros/moveit_servo/src/servo_server.cpp index 31e477c837..5c630f3082 100644 --- a/moveit_ros/moveit_servo/src/servo_server.cpp +++ b/moveit_ros/moveit_servo/src/servo_server.cpp @@ -52,7 +52,7 @@ int main(int argc, char** argv) ros::AsyncSpinner spinner(ROS_THREADS); spinner.start(); - ros::NodeHandle nh; + ros::NodeHandle nh("~"); // Load the planning scene monitor auto planning_scene_monitor = std::make_shared("robot_description"); diff --git a/moveit_ros/moveit_servo/test/pose_tracking_test.cpp b/moveit_ros/moveit_servo/test/pose_tracking_test.cpp index 782fa23c5a..765094899d 100644 --- a/moveit_ros/moveit_servo/test/pose_tracking_test.cpp +++ b/moveit_ros/moveit_servo/test/pose_tracking_test.cpp @@ -78,10 +78,9 @@ class PoseTrackingFixture : public ::testing::Test planning_scene_monitor::PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_WORLD_TOPIC, false /* skip octomap monitor */); - tracker_ = std::make_shared(planning_scene_monitor_, ""); + tracker_ = std::make_shared(nh_, planning_scene_monitor_); - target_pose_pub_ = - nh_.advertise("/pose_tracking_test/target_pose", 1 /* queue */, true /* latch */); + target_pose_pub_ = nh_.advertise("target_pose", 1 /* queue */, true /* latch */); // Tolerance for pose seeking translation_tolerance_ << TRANSLATION_TOLERANCE, TRANSLATION_TOLERANCE, TRANSLATION_TOLERANCE; @@ -91,7 +90,7 @@ class PoseTrackingFixture : public ::testing::Test } protected: - ros::NodeHandle nh_; + ros::NodeHandle nh_{ "~" }; planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_; Eigen::Vector3d translation_tolerance_; moveit_servo::PoseTrackingPtr tracker_; diff --git a/moveit_ros/moveit_servo/test/pose_tracking_test.test b/moveit_ros/moveit_servo/test/pose_tracking_test.test index 4f162d0c0d..f149e48c32 100644 --- a/moveit_ros/moveit_servo/test/pose_tracking_test.test +++ b/moveit_ros/moveit_servo/test/pose_tracking_test.test @@ -17,7 +17,7 @@ - + diff --git a/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp b/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp index 53684c1787..fa61c32e0a 100644 --- a/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp +++ b/moveit_ros/moveit_servo/test/servo_cpp_interface_test.cpp @@ -89,7 +89,7 @@ class ServoFixture : public ::testing::Test } protected: - ros::NodeHandle nh_; + ros::NodeHandle nh_{ "~" }; planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_; moveit_servo::ServoPtr servo_; }; // class ServoFixture diff --git a/moveit_ros/moveit_servo/test/servo_cpp_interface_test.test b/moveit_ros/moveit_servo/test/servo_cpp_interface_test.test index f165250d82..94c6a2a7f4 100644 --- a/moveit_ros/moveit_servo/test/servo_cpp_interface_test.test +++ b/moveit_ros/moveit_servo/test/servo_cpp_interface_test.test @@ -12,7 +12,7 @@ - - + + From 696df9fc3cedb84e3d2e116b1ba28f7c1e86da26 Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Thu, 22 Oct 2020 17:07:46 -0600 Subject: [PATCH 048/179] Cleanup current state handling in servo (#2372) --- moveit_ros/moveit_servo/CMakeLists.txt | 1 - moveit_ros/moveit_servo/MIGRATION.md | 6 + .../include/moveit_servo/collision_check.h | 9 +- .../moveit_servo/joint_state_subscriber.h | 68 ----------- .../moveit_servo/include/moveit_servo/servo.h | 5 - .../include/moveit_servo/servo_calcs.h | 17 +-- .../moveit_servo/src/collision_check.cpp | 13 +- .../src/joint_state_subscriber.cpp | 76 ------------ moveit_ros/moveit_servo/src/servo.cpp | 37 ++++-- moveit_ros/moveit_servo/src/servo_calcs.cpp | 115 ++++++------------ 10 files changed, 79 insertions(+), 268 deletions(-) create mode 100644 moveit_ros/moveit_servo/MIGRATION.md delete mode 100644 moveit_ros/moveit_servo/include/moveit_servo/joint_state_subscriber.h delete mode 100644 moveit_ros/moveit_servo/src/joint_state_subscriber.cpp diff --git a/moveit_ros/moveit_servo/CMakeLists.txt b/moveit_ros/moveit_servo/CMakeLists.txt index 878d4515a9..e2562ea35c 100644 --- a/moveit_ros/moveit_servo/CMakeLists.txt +++ b/moveit_ros/moveit_servo/CMakeLists.txt @@ -68,7 +68,6 @@ add_library(${SERVO_LIB_NAME} src/collision_check.cpp src/servo_calcs.cpp src/servo.cpp - src/joint_state_subscriber.cpp src/low_pass_filter.cpp ) set_target_properties(${SERVO_LIB_NAME} PROPERTIES VERSION "${${PROJECT_NAME}_VERSION}") diff --git a/moveit_ros/moveit_servo/MIGRATION.md b/moveit_ros/moveit_servo/MIGRATION.md new file mode 100644 index 0000000000..ae97f6a75a --- /dev/null +++ b/moveit_ros/moveit_servo/MIGRATION.md @@ -0,0 +1,6 @@ +# Migration Notes + +API changes since last Noetic Release + +- Servo::getLatestJointState was removed. To get the latest joint positions of the group servo is working with use the CSM in the PSM. Here is an example of how to get the latest joint positions: + planning_scene_monitor_->getStateMonitor()->getCurrentState()->copyJointGroupPositions(move_group_name, positions); diff --git a/moveit_ros/moveit_servo/include/moveit_servo/collision_check.h b/moveit_ros/moveit_servo/include/moveit_servo/collision_check.h index 9accf79484..08aadaad46 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/collision_check.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/collision_check.h @@ -46,7 +46,6 @@ #include #include -#include namespace moveit_servo { @@ -65,8 +64,7 @@ class CollisionCheck * already started when passed into this class */ CollisionCheck(ros::NodeHandle& nh, const moveit_servo::ServoParameters& parameters, - const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, - const std::shared_ptr& joint_state_subscriber); + const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor); ~CollisionCheck() { @@ -97,11 +95,8 @@ class CollisionCheck // Pointer to the collision environment planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_; - // Subscriber to joint states - const std::shared_ptr joint_state_subscriber_; - // Robot state and collision matrix from planning scene - std::unique_ptr current_state_; + std::shared_ptr current_state_; collision_detection::AllowedCollisionMatrix acm_; // Scale robot velocity according to collision proximity and user-defined thresholds. diff --git a/moveit_ros/moveit_servo/include/moveit_servo/joint_state_subscriber.h b/moveit_ros/moveit_servo/include/moveit_servo/joint_state_subscriber.h deleted file mode 100644 index 64c55367bc..0000000000 --- a/moveit_ros/moveit_servo/include/moveit_servo/joint_state_subscriber.h +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * Title : joint_state_subscriber.h - * Project : moveit_servo - * Created : 06/11/2020 - * Author : Tyler Weaver - * - * BSD 3-Clause License - * - * Copyright (c) 2019, Los Alamos National Security, LLC - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *******************************************************************************/ - -#pragma once - -#include - -#include -#include - -#include - -namespace moveit_servo -{ -class JointStateSubscriber -{ -public: - /** \brief Constructor */ - JointStateSubscriber(ros::NodeHandle& nh, const std::string& joint_state_topic_name); - - /** \brief Get the latest joint state message */ - sensor_msgs::JointStateConstPtr getLatest() const; - -private: - void jointStateCB(const sensor_msgs::JointStateConstPtr& msg); - - ros::Subscriber joint_state_sub_; - - // Latest joint state, updated by ROS callback - mutable std::mutex joint_state_mutex_; - sensor_msgs::JointStateConstPtr latest_joint_state_; -}; -} // namespace moveit_servo diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo.h b/moveit_ros/moveit_servo/include/moveit_servo/servo.h index 6205e09c97..aeb61dab2b 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo.h @@ -43,7 +43,6 @@ #include #include #include -#include namespace moveit_servo { @@ -86,9 +85,6 @@ class Servo /** \brief Get the parameters used by servo node. */ const ServoParameters& getParameters() const; - /** \brief Get the latest joint state. */ - sensor_msgs::JointStateConstPtr getLatestJointState() const; - /** \brief Change the controlled link. Often, this is the end effector * This must be a link on the robot since MoveIt tracks the transform (not tf) */ @@ -108,7 +104,6 @@ class Servo // Store the parameters that were read from ROS server ServoParameters parameters_; - std::shared_ptr joint_state_subscriber_; std::unique_ptr servo_calcs_; std::unique_ptr collision_checker_; }; diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h index 37e7e647db..c92171b179 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h @@ -38,6 +38,9 @@ #pragma once +// C++ +#include + // ROS #include #include @@ -57,7 +60,6 @@ #include #include #include -#include namespace moveit_servo { @@ -65,8 +67,7 @@ class ServoCalcs { public: ServoCalcs(ros::NodeHandle& nh, ServoParameters& parameters, - const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, - const std::shared_ptr& joint_state_subscriber); + const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor); ~ServoCalcs() { @@ -115,7 +116,7 @@ class ServoCalcs bool jointServoCalcs(const control_msgs::JointJog& cmd, trajectory_msgs::JointTrajectory& joint_trajectory); /** \brief Parse the incoming joint msg for the joints of our MoveGroup */ - bool updateJoints(); + void updateJoints(); /** \brief If incoming velocity commands are from a unitless joystick, scale them to physical units. * Also, multiply by timestep to calculate a position change. @@ -220,9 +221,6 @@ class ServoCalcs // Pointer to the collision environment planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_; - // Subscriber to the latest joint states - const std::shared_ptr joint_state_subscriber_; - // Track the number of cycles during which motion has not occurred. // Will avoid re-publishing zero velocities endlessly. int zero_velocity_count_ = 0; @@ -244,7 +242,7 @@ class ServoCalcs const moveit::core::JointModelGroup* joint_model_group_; - moveit::core::RobotStatePtr kinematic_state_; + moveit::core::RobotStatePtr current_state_; // incoming_joint_state_ is the incoming message. It may contain passive joints or other joints we don't care about. // (mutex protected below) @@ -294,9 +292,6 @@ class ServoCalcs // The dimesions to control. In the command frame. [x, y, z, roll, pitch, yaw] std::array control_dimensions_ = { { true, true, true, true, true, true } }; - // Amount we sleep when waiting - ros::Rate default_sleep_rate_ = 100; - // latest_state_mutex_ is used to protect the state below it mutable std::mutex latest_state_mutex_; Eigen::Isometry3d tf_moveit_to_robot_cmd_frame_; diff --git a/moveit_ros/moveit_servo/src/collision_check.cpp b/moveit_ros/moveit_servo/src/collision_check.cpp index 3d79a4421e..44b89271d2 100644 --- a/moveit_ros/moveit_servo/src/collision_check.cpp +++ b/moveit_ros/moveit_servo/src/collision_check.cpp @@ -51,12 +51,10 @@ namespace moveit_servo { // Constructor for the class that handles collision checking CollisionCheck::CollisionCheck(ros::NodeHandle& nh, const moveit_servo::ServoParameters& parameters, - const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, - const std::shared_ptr& joint_state_subscriber) + const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor) : nh_(nh) , parameters_(parameters) , planning_scene_monitor_(planning_scene_monitor) - , joint_state_subscriber_(joint_state_subscriber) , self_velocity_scale_coefficient_(-log(0.001) / parameters.self_collision_proximity_threshold) , scene_velocity_scale_coefficient_(-log(0.001) / parameters.scene_collision_proximity_threshold) , period_(1. / parameters_.collision_check_rate) @@ -80,7 +78,7 @@ CollisionCheck::CollisionCheck(ros::NodeHandle& nh, const moveit_servo::ServoPar worst_case_stop_time_sub_ = internal_nh.subscribe("worst_case_stop_time", ROS_QUEUE_SIZE, &CollisionCheck::worstCaseStopTimeCB, this); - current_state_ = std::make_unique(getLockedPlanningSceneRO()->getCurrentState()); + current_state_ = planning_scene_monitor_->getStateMonitor()->getCurrentState(); acm_ = getLockedPlanningSceneRO()->getAllowedCollisionMatrix(); } @@ -109,11 +107,8 @@ void CollisionCheck::run(const ros::TimerEvent& timer_event) return; } - // Copy the latest joint state - auto latest_joint_state = joint_state_subscriber_->getLatest(); - for (std::size_t i = 0; i < latest_joint_state->position.size(); ++i) - current_state_->setJointPositions(latest_joint_state->name[i], &latest_joint_state->position[i]); - + // Update to the latest current state + current_state_ = planning_scene_monitor_->getStateMonitor()->getCurrentState(); current_state_->updateCollisionBodyTransforms(); collision_detected_ = false; diff --git a/moveit_ros/moveit_servo/src/joint_state_subscriber.cpp b/moveit_ros/moveit_servo/src/joint_state_subscriber.cpp deleted file mode 100644 index 22b8b4bfab..0000000000 --- a/moveit_ros/moveit_servo/src/joint_state_subscriber.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/******************************************************************************* - * BSD 3-Clause License - * - * Copyright (c) 2019, Los Alamos National Security, LLC - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *******************************************************************************/ - -/* Title : joint_state_subscriber.cpp - * Project : moveit_servo - * Created : 06/11/2020 - * Author : Tyler Weaver - */ - -#include - -namespace moveit_servo -{ -constexpr char LOGNAME[] = "joint_state_subscriber"; - -// Constructor for the class that handles collision checking -JointStateSubscriber::JointStateSubscriber(ros::NodeHandle& nh, const std::string& joint_state_topic_name) -{ - // subscribe to joints - joint_state_sub_ = nh.subscribe(joint_state_topic_name, ROS_QUEUE_SIZE, &JointStateSubscriber::jointStateCB, this); - - ros::AsyncSpinner spinner(1); - spinner.start(); - - // Wait for initial messages - ROS_INFO_NAMED(LOGNAME, "Waiting for first joint msg."); - while (latest_joint_state_ == nullptr) - { - ros::Duration(0.01).sleep(); - } - ROS_INFO_NAMED(LOGNAME, "Received first joint msg."); -} - -sensor_msgs::JointStateConstPtr JointStateSubscriber::getLatest() const -{ - const std::lock_guard lock(joint_state_mutex_); - return latest_joint_state_; -} - -void JointStateSubscriber::jointStateCB(const sensor_msgs::JointStateConstPtr& msg) -{ - const std::lock_guard lock(joint_state_mutex_); - latest_joint_state_ = msg; -} - -} // namespace moveit_servo diff --git a/moveit_ros/moveit_servo/src/servo.cpp b/moveit_ros/moveit_servo/src/servo.cpp index 8467837429..b35267cc5b 100644 --- a/moveit_ros/moveit_servo/src/servo.cpp +++ b/moveit_ros/moveit_servo/src/servo.cpp @@ -39,12 +39,18 @@ #include +#include #include static const std::string LOGNAME = "servo_node"; namespace moveit_servo { +namespace +{ +constexpr double ROBOT_STATE_WAIT_TIME = 10.0; // seconds +} // namespace + Servo::Servo(ros::NodeHandle& nh, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor) : nh_(nh), planning_scene_monitor_(planning_scene_monitor) { @@ -52,15 +58,27 @@ Servo::Servo(ros::NodeHandle& nh, const planning_scene_monitor::PlanningSceneMon if (!readParameters()) exit(EXIT_FAILURE); - // By default, joint topic name is relative to the node parent namespace. Fully custom joint name topics can be - // set by using absolute topic names in config files. For example, "/foo/my_joint_state_topic". - ros::NodeHandle nh_parent_ns = ros::NodeHandle(""); - joint_state_subscriber_ = std::make_shared(nh_parent_ns, parameters_.joint_topic); + // Async spinner is needed to receive messages to wait for the robot state to be complete + ros::AsyncSpinner spinner(1); + spinner.start(); + + // Confirm the planning scene monitor is ready to be used + if (!planning_scene_monitor_->getStateMonitor()) + { + planning_scene_monitor_->startStateMonitor(parameters_.joint_topic); + } + planning_scene_monitor->getStateMonitor()->enableCopyDynamics(true); + + if (!planning_scene_monitor_->getStateMonitor()->waitForCompleteState(parameters_.move_group_name, + ROBOT_STATE_WAIT_TIME)) + { + ROS_FATAL_NAMED(LOGNAME, "Timeout waiting for current state"); + exit(EXIT_FAILURE); + } - servo_calcs_ = std::make_unique(nh_, parameters_, planning_scene_monitor_, joint_state_subscriber_); + servo_calcs_ = std::make_unique(nh_, parameters_, planning_scene_monitor_); - collision_checker_ = - std::make_unique(nh_, parameters_, planning_scene_monitor_, joint_state_subscriber_); + collision_checker_ = std::make_unique(nh_, parameters_, planning_scene_monitor_); } // Read ROS parameters, typically from YAML file @@ -316,9 +334,4 @@ const ServoParameters& Servo::getParameters() const return parameters_; } -sensor_msgs::JointStateConstPtr Servo::getLatestJointState() const -{ - return joint_state_subscriber_->getLatest(); -} - } // namespace moveit_servo diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index 4b06627621..8e34341380 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -42,8 +42,8 @@ #include #include -#include #include +#include static const std::string LOGNAME = "servo_calcs"; constexpr size_t ROS_LOG_THROTTLE_PERIOD = 30; // Seconds to throttle logs inside loops @@ -85,26 +85,12 @@ geometry_msgs::TransformStamped convertIsometryToTransform(const Eigen::Isometry // Constructor for the class that handles servoing calculations ServoCalcs::ServoCalcs(ros::NodeHandle& nh, ServoParameters& parameters, - const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, - const std::shared_ptr& joint_state_subscriber) - : nh_(nh) - , parameters_(parameters) - , planning_scene_monitor_(planning_scene_monitor) - , joint_state_subscriber_(joint_state_subscriber) - , period_(parameters.publish_period) + const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor) + : nh_(nh), parameters_(parameters), planning_scene_monitor_(planning_scene_monitor), period_(parameters.publish_period) { // MoveIt Setup - const robot_model_loader::RobotModelLoaderPtr& model_loader_ptr = planning_scene_monitor_->getRobotModelLoader(); - while (ros::ok() && !model_loader_ptr) - { - ROS_WARN_THROTTLE_NAMED(ROS_LOG_THROTTLE_PERIOD, LOGNAME, "Waiting for a non-null robot_model_loader pointer"); - default_sleep_rate_.sleep(); - } - const moveit::core::RobotModelPtr& kinematic_model = model_loader_ptr->getModel(); - kinematic_state_ = std::make_shared(kinematic_model); - kinematic_state_->setToDefaultValues(); - - joint_model_group_ = kinematic_model->getJointModelGroup(parameters_.move_group_name); + current_state_ = planning_scene_monitor_->getStateMonitor()->getCurrentState(); + joint_model_group_ = current_state_->getJointModelGroup(parameters_.move_group_name); prev_joint_velocity_ = Eigen::ArrayXd::Zero(joint_model_group_->getActiveJointModels().size()); // Subscribe to command topics @@ -177,9 +163,9 @@ void ServoCalcs::start() trajectory_msgs::JointTrajectoryPoint point; point.time_from_start = ros::Duration(parameters_.publish_period); - auto latest_joints = joint_state_subscriber_->getLatest(); if (parameters_.publish_joint_positions) - point.positions = latest_joints->position; + planning_scene_monitor_->getStateMonitor()->getCurrentState()->copyJointGroupPositions(joint_model_group_, + point.positions); if (parameters_.publish_joint_velocities) { std::vector velocity(num_joints_); @@ -198,14 +184,11 @@ void ServoCalcs::start() timer_ = nh_.createTimer(period_, &ServoCalcs::run, this); - // TODO(adamp or andyz): after rebasing on upstream master, update this section. Maybe put the tf updates in a tiny - // function by themselves - sensor_msgs::JointStateConstPtr latest_joint_state = joint_state_subscriber_->getLatest(); - kinematic_state_->setVariableValues(*latest_joint_state); - tf_moveit_to_ee_frame_ = kinematic_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * - kinematic_state_->getGlobalLinkTransform(parameters_.ee_frame_name); - tf_moveit_to_robot_cmd_frame_ = kinematic_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * - kinematic_state_->getGlobalLinkTransform(parameters_.robot_link_command_frame); + current_state_ = planning_scene_monitor_->getStateMonitor()->getCurrentState(); + tf_moveit_to_ee_frame_ = current_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * + current_state_->getGlobalLinkTransform(parameters_.ee_frame_name); + tf_moveit_to_robot_cmd_frame_ = current_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * + current_state_->getGlobalLinkTransform(parameters_.robot_link_command_frame); } void ServoCalcs::run(const ros::TimerEvent& timer_event) @@ -226,14 +209,10 @@ void ServoCalcs::run(const ros::TimerEvent& timer_event) // Always update the joints and end-effector transform for 2 reasons: // 1) in case the getCommandFrameTransform() method is being used // 2) so the low-pass filters are up to date and don't cause a jump - while (!updateJoints() && ros::ok()) - { - default_sleep_rate_.sleep(); - } + updateJoints(); // Update from latest state - sensor_msgs::JointStateConstPtr latest_joint_state = joint_state_subscriber_->getLatest(); - kinematic_state_->setVariableValues(*latest_joint_state); + current_state_ = planning_scene_monitor_->getStateMonitor()->getCurrentState(); { const std::lock_guard lock(latest_state_mutex_); if (latest_twist_stamped_) @@ -255,13 +234,13 @@ void ServoCalcs::run(const ros::TimerEvent& timer_event) // Calculate this transform to ensure it is available via C++ API // We solve (planning_frame -> base -> robot_link_command_frame) // by computing (base->planning_frame)^-1 * (base->robot_link_command_frame) - tf_moveit_to_robot_cmd_frame_ = kinematic_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * - kinematic_state_->getGlobalLinkTransform(parameters_.robot_link_command_frame); + tf_moveit_to_robot_cmd_frame_ = current_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * + current_state_->getGlobalLinkTransform(parameters_.robot_link_command_frame); // Calculate the transform from MoveIt planning frame to End Effector frame // Calculate this transform to ensure it is available via C++ API - tf_moveit_to_ee_frame_ = kinematic_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * - kinematic_state_->getGlobalLinkTransform(parameters_.ee_frame_name); + tf_moveit_to_ee_frame_ = current_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * + current_state_->getGlobalLinkTransform(parameters_.ee_frame_name); have_nonzero_command_ = have_nonzero_twist_stamped_ || have_nonzero_joint_command_; @@ -447,8 +426,8 @@ bool ServoCalcs::cartesianServoCalcs(geometry_msgs::TwistStamped& cmd, // We solve (planning_frame -> base -> cmd.header.frame_id) // by computing (base->planning_frame)^-1 * (base->cmd.header.frame_id) const auto tf_moveit_to_incoming_cmd_frame = - kinematic_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * - kinematic_state_->getGlobalLinkTransform(cmd.header.frame_id); + current_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * + current_state_->getGlobalLinkTransform(cmd.header.frame_id); translation_vector = tf_moveit_to_incoming_cmd_frame.linear() * translation_vector; angular_vector = tf_moveit_to_incoming_cmd_frame.linear() * angular_vector; @@ -467,7 +446,7 @@ bool ServoCalcs::cartesianServoCalcs(geometry_msgs::TwistStamped& cmd, Eigen::VectorXd delta_x = scaleCartesianCommand(cmd); // Convert from cartesian commands to joint commands - Eigen::MatrixXd jacobian = kinematic_state_->getJacobian(joint_model_group_); + Eigen::MatrixXd jacobian = current_state_->getJacobian(joint_model_group_); // May allow some dimensions to drift, based on drift_dimensions // i.e. take advantage of task redundancy. @@ -671,10 +650,10 @@ double ServoCalcs::velocityScalingFactorForSingularity(const Eigen::VectorXd& co // Calculate a small change in joints Eigen::VectorXd new_theta; - kinematic_state_->copyJointGroupPositions(joint_model_group_, new_theta); + current_state_->copyJointGroupPositions(joint_model_group_, new_theta); new_theta += pseudo_inverse * delta_x; - kinematic_state_->setJointGroupPositions(joint_model_group_, new_theta); - auto new_jacobian = kinematic_state_->getJacobian(joint_model_group_); + current_state_->setJointGroupPositions(joint_model_group_, new_theta); + Eigen::MatrixXd new_jacobian = current_state_->getJacobian(joint_model_group_); Eigen::JacobiSVD new_svd(new_jacobian); double new_condition = new_svd.singularValues()(0) / new_svd.singularValues()(new_svd.singularValues().size() - 1); @@ -784,16 +763,16 @@ bool ServoCalcs::enforcePositionLimits() break; } } - if (!kinematic_state_->satisfiesPositionBounds(joint, -parameters_.joint_limit_margin)) + if (!current_state_->satisfiesPositionBounds(joint, -parameters_.joint_limit_margin)) { const std::vector limits = joint->getVariableBoundsMsg(); // Joint limits are not defined for some joints. Skip them. if (!limits.empty()) { - if ((kinematic_state_->getJointVelocities(joint)[0] < 0 && + if ((current_state_->getJointVelocities(joint)[0] < 0 && (joint_angle < (limits[0].min_position + parameters_.joint_limit_margin))) || - (kinematic_state_->getJointVelocities(joint)[0] > 0 && + (current_state_->getJointVelocities(joint)[0] > 0 && (joint_angle > (limits[0].max_position - parameters_.joint_limit_margin)))) { ROS_WARN_STREAM_THROTTLE_NAMED(ROS_LOG_THROTTLE_PERIOD, LOGNAME, @@ -843,31 +822,12 @@ void ServoCalcs::suddenHalt(trajectory_msgs::JointTrajectory& joint_trajectory) } // Parse the incoming joint msg for the joints of our MoveGroup -bool ServoCalcs::updateJoints() +void ServoCalcs::updateJoints() { - sensor_msgs::JointStateConstPtr latest_joint_state = joint_state_subscriber_->getLatest(); - - // Check that the msg contains enough joints - if (latest_joint_state->name.size() < num_joints_) - return false; - - // Store joints in a member variable - for (std::size_t m = 0; m < latest_joint_state->name.size(); ++m) - { - std::size_t c; - try - { - c = joint_state_name_map_.at(latest_joint_state->name[m]); - } - catch (const std::out_of_range& e) - { - ROS_DEBUG_STREAM_THROTTLE_NAMED(ROS_LOG_THROTTLE_PERIOD, LOGNAME, - "Ignoring joint " << latest_joint_state->name[m]); - continue; - } - - internal_joint_state_.position[c] = latest_joint_state->position[m]; - } + // Get the latest joint group positions + current_state_ = planning_scene_monitor_->getStateMonitor()->getCurrentState(); + current_state_->copyJointGroupPositions(joint_model_group_, internal_joint_state_.position); + current_state_->copyJointGroupVelocities(joint_model_group_, internal_joint_state_.velocity); // Cache the original joints in case they need to be reset original_joint_state_ = internal_joint_state_; @@ -878,9 +838,9 @@ bool ServoCalcs::updateJoints() double accel_limit = 0; double joint_velocity = 0; double worst_case_stop_time = 0; - for (size_t jt_state_idx = 0; jt_state_idx < latest_joint_state->velocity.size(); ++jt_state_idx) + for (size_t jt_state_idx = 0; jt_state_idx < internal_joint_state_.velocity.size(); ++jt_state_idx) { - joint_name = latest_joint_state->name[jt_state_idx]; + joint_name = internal_joint_state_.name[jt_state_idx]; // Get acceleration limit for this joint for (auto joint_model : joint_model_group_->getActiveJointModels()) @@ -906,7 +866,7 @@ bool ServoCalcs::updateJoints() } // Get the current joint velocity - joint_velocity = latest_joint_state->velocity[jt_state_idx]; + joint_velocity = internal_joint_state_.velocity[jt_state_idx]; // Calculate worst case stop time worst_case_stop_time = std::max(worst_case_stop_time, fabs(joint_velocity / accel_limit)); @@ -918,8 +878,6 @@ bool ServoCalcs::updateJoints() msg->data = worst_case_stop_time; worst_case_stop_time_pub_.publish(msg); } - - return true; } // Scale the incoming servo command @@ -967,8 +925,7 @@ Eigen::VectorXd ServoCalcs::scaleJointCommand(const control_msgs::JointJog& comm } catch (const std::out_of_range& e) { - ROS_WARN_STREAM_THROTTLE_NAMED(ROS_LOG_THROTTLE_PERIOD, LOGNAME, - "Ignoring joint " << joint_state_subscriber_->getLatest()->name[m]); + ROS_WARN_STREAM_THROTTLE_NAMED(ROS_LOG_THROTTLE_PERIOD, LOGNAME, "Ignoring joint " << command.joint_names[m]); continue; } // Apply user-defined scaling if inputs are unitless [-1:1] From 4bad84b483fc07a4011bba66ee451dcff42c7cc8 Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Thu, 19 Nov 2020 23:26:55 +0900 Subject: [PATCH 049/179] Clean up Rviz Motion Planning plugin, add tooltips (#2310) - better use of space / overall smaller panel - remove goal constraints field, it's not used and not intuitive in the GUI either - reorder check boxes by subjective usefulness - Add better tooltips - Remove autoScroll from Planning Parameters field - Fix tabstop order - Align columns of Planning tab Co-authored-by: Robert Haschke --- .../src/motion_planning_display.cpp | 4 - .../src/motion_planning_frame.cpp | 2 - .../ui/motion_planning_rviz_plugin_frame.ui | 510 +++++++++++++++--- 3 files changed, 422 insertions(+), 94 deletions(-) diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_display.cpp b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_display.cpp index f27a54f86a..95097f0e45 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_display.cpp +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_display.cpp @@ -1329,8 +1329,6 @@ void MotionPlanningDisplay::load(const rviz::Config& config) frame_->ui_->velocity_scaling_factor->setValue(d); if (config.mapGetFloat("Acceleration_Scaling_Factor", &d)) frame_->ui_->acceleration_scaling_factor->setValue(d); - if (config.mapGetFloat("MoveIt_Goal_Tolerance", &d)) - frame_->ui_->goal_tolerance->setValue(d); bool b; if (config.mapGetBool("MoveIt_Allow_Replanning", &b)) @@ -1389,8 +1387,6 @@ void MotionPlanningDisplay::save(rviz::Config config) const config.mapSetValue("MoveIt_Warehouse_Host", frame_->ui_->database_host->text()); config.mapSetValue("MoveIt_Warehouse_Port", frame_->ui_->database_port->value()); - config.mapSetValue("MoveIt_Goal_Tolerance", frame_->ui_->goal_tolerance->value()); - // "Options" Section config.mapSetValue("MoveIt_Planning_Time", frame_->ui_->planning_time->value()); config.mapSetValue("MoveIt_Planning_Attempts", frame_->ui_->planning_attempts->value()); diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame.cpp b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame.cpp index 16311397d8..ab5bc6e208 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame.cpp +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame.cpp @@ -156,8 +156,6 @@ MotionPlanningFrame::MotionPlanningFrame(MotionPlanningDisplay* pdisplay, rviz:: connect(ui_->database_host, SIGNAL(textChanged(QString)), this, SIGNAL(configChanged())); connect(ui_->database_port, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged())); - connect(ui_->goal_tolerance, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); - connect(ui_->planning_time, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); connect(ui_->planning_attempts, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged())); connect(ui_->velocity_scaling_factor, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged())); diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/src/ui/motion_planning_rviz_plugin_frame.ui b/moveit_ros/visualization/motion_planning_rviz_plugin/src/ui/motion_planning_rviz_plugin_frame.ui index a54c23e4ee..e99f8bd2b9 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/src/ui/motion_planning_rviz_plugin_frame.ui +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/src/ui/motion_planning_rviz_plugin_frame.ui @@ -6,8 +6,8 @@ 0 0 - 532 - 389 + 507 + 380 @@ -26,7 +26,7 @@ false - 3 + 1 @@ -96,6 +96,9 @@ + + false + 0 @@ -157,6 +160,12 @@ + + + 0 + 0 + + color:red @@ -401,7 +410,7 @@ - Plan and E&xecute + Plan && E&xecute @@ -410,6 +419,9 @@ false + + Stop execution by sending a stop command to the move_group. + &Stop @@ -512,12 +524,12 @@ Qt::Vertical - QSizePolicy::Fixed + QSizePolicy::Expanding 20 - 6 + 32 @@ -541,38 +553,15 @@ 6 - - - - - - - - Goal Tolerance: - - - - - - - + + + Select path constraints from the database. + + - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -587,7 +576,7 @@ - 2 + 1 4 @@ -599,6 +588,9 @@ + + Total time allowed for planning. Planning stops if time or number of attempts is exceeded, or goal is reached. + Planning Time (s): @@ -612,6 +604,18 @@ 0 + + + 40 + 0 + + + + Total time allowed for planning. Planning stops if time or number of attempts is exceeded, or goal is reached. + + + 1 + 300.000000000000000 @@ -629,6 +633,9 @@ + + Allowed number of planning attempts. Planning stops if time or number of attempts is exceeded, or goal is reached. + Planning Attempts: @@ -642,6 +649,15 @@ 0 + + + 40 + 0 + + + + Allowed number of planning attempts. Planning stops if time or number of attempts is exceeded, or goal is reached. + 1000 @@ -659,6 +675,9 @@ + + Factor (between 0 and 1) to scale down maximum joint velocities + Velocity Scaling: @@ -666,11 +685,20 @@ + + + 40 + 0 + + + + Factor (between 0 and 1) to scale down maximum joint velocities + 1.000000000000000 - 0.010000000000000 + 0.100000000000000 1.000000000000000 @@ -686,18 +714,30 @@ + + Factor (between 0 and 1) to scale down maximum joint accelerations + - Acceleration Scaling: + Accel. Scaling: + + + 40 + 0 + + + + Factor (between 0 and 1) to scale down maximum joint accelerations + 1.000000000000000 - 0.010000000000000 + 0.100000000000000 1.000000000000000 @@ -707,9 +747,39 @@ - + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + + 30 + 0 + + + + Check this to generate a linear path in Cartesian (3D) space. + + This does not plan around obstacles. + - Allow Replanning + Use Cartesian Path false @@ -717,9 +787,26 @@ - + + + + 0 + 0 + + + + + 30 + 0 + + + + If checked, the IK solver tries to avoid collisions when searching for a start/end state set via the interactive marker. + +This is usually achieved by random seeding, which can flip the robot configuration (e.g. elbow up/down). Note that motion planning is always collision-aware, regardless of this checkbox. + - Allow Sensor Positioning + Collision-aware IK false @@ -727,19 +814,46 @@ - - - Allow External Comm. + + + + 0 + 0 + - - false + + + 30 + 0 + + + + Allow approximate IK solutions, which deviate from the target pose. Useful when an exact solution cannot be found, e.g. for underactuated arms or when trying to reach an unreachable target. + + + Approx IK Solutions - + + + + 0 + 0 + + + + + 30 + 0 + + + + Allow other nodes to control start and end poses as well as planning and execution, using ROS topics (/rviz/moveit/ ). + - Use Cartesian Path + External Comm. false @@ -747,38 +861,61 @@ - + + + + 0 + 0 + + + + + 30 + 0 + + + + EXPERIMENTAL: Trigger replanning if new collisions are detected during plan execution. Only works for the "Plan & Execute" button. + + + false + - Use Collision-Aware IK + Replanning - true + false - + + + + 0 + 0 + + + + + 30 + 0 + + + + EXPERIMENTAL: Allows the robot to reposition its sensor to look around to resolve apparent collisions. A sensor needs to be set up and the new measurements have to affect the collision scene, otherwise it has no effect. See tutorial. + - Allow Approx IK Solutions + Sensor Positioning + + + false - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -860,6 +997,18 @@ + + + 0 + 0 + + + + + 40 + 0 + + -99.000000000000000 @@ -870,6 +1019,18 @@ + + + 0 + 0 + + + + + 40 + 0 + + 0.010000000000000 @@ -880,6 +1041,18 @@ + + + 0 + 0 + + + + + 40 + 0 + + 0.010000000000000 @@ -890,6 +1063,18 @@ + + + 0 + 0 + + + + + 40 + 0 + + 0.010000000000000 @@ -907,6 +1092,18 @@ + + + 0 + 0 + + + + + 40 + 0 + + -99.000000000000000 @@ -924,6 +1121,18 @@ + + + 0 + 0 + + + + + 40 + 0 + + -99.000000000000000 @@ -1012,6 +1221,18 @@ + + + 0 + 0 + + + + + 20 + 0 + + x dimension @@ -1025,6 +1246,18 @@ + + + 0 + 0 + + + + + 20 + 0 + + y dimension @@ -1038,6 +1271,18 @@ + + + 0 + 0 + + + + + 20 + 0 + + z dimension @@ -1054,7 +1299,14 @@ - + + + + 30 + 0 + + + @@ -1127,8 +1379,11 @@ + + Change the pose and scale of the selected object + - Change pose and scale of selected object + Change object pose/scale @@ -1162,6 +1417,12 @@ + + + 20 + 0 + + -999.990000000000009 @@ -1175,6 +1436,12 @@ + + + 20 + 0 + + -3.140000000000000 @@ -1188,6 +1455,12 @@ + + + 20 + 0 + + -3.140000000000000 @@ -1201,6 +1474,12 @@ + + + 20 + 0 + + -3.140000000000000 @@ -1214,6 +1493,12 @@ + + + 20 + 0 + + -999.990000000000009 @@ -1245,7 +1530,7 @@ - 160 + 40 0 @@ -1283,6 +1568,12 @@ + + + 20 + 0 + + -999.990000000000009 @@ -1299,8 +1590,11 @@ + + Describes the selected object's pose and geometry. + - Status of selected object + Object status @@ -1332,6 +1626,9 @@ Qt::AutoText + + true + true @@ -1374,11 +1671,17 @@ - + 0 0 + + + 40 + 0 + + &Publish @@ -1399,6 +1702,18 @@ + + + 0 + 0 + + + + + 40 + 0 + + Export scene geometry to a .scene file (only geometry information is preserved) @@ -1409,6 +1724,18 @@ + + + 0 + 0 + + + + + 40 + 0 + + Import scene geometry from a .scene file (only geometry information is preserved) @@ -1823,25 +2150,35 @@ database_port reset_db_button database_connect_button + wcenter_x + wcenter_y + wcenter_z + wsize_x + wsize_y + wsize_z plan_button execute_button plan_and_execute_button stop_button + clear_octomap_button planning_group_combo_box start_state_combo_box goal_state_combo_box - clear_octomap_button + path_constraints_combo_box planning_time planning_attempts velocity_scaling_factor acceleration_scaling_factor - allow_replanning - allow_looking - allow_external_program + use_cartesian_path collision_aware_ik approximate_ik - path_constraints_combo_box - goal_tolerance + allow_external_program + allow_replanning + allow_looking + detected_objects_list + detect_objects_button + support_surfaces_list + pick_button place_button roi_center_x roi_center_y @@ -1850,6 +2187,13 @@ roi_size_y roi_size_z collision_objects_list + shape_size_x_spin_box + shape_size_z_spin_box + shape_size_y_spin_box + shapes_combo_box + add_object_button + remove_object_button + clear_scene_button object_x object_y object_z @@ -1877,16 +2221,6 @@ save_goal_state_button status_text tabWidget - wcenter_x - wcenter_y - wcenter_z - wsize_x - wsize_y - wsize_z - pick_button - support_surfaces_list - detected_objects_list - detect_objects_button From ac39a6e70826f3cc131f7a6fe8295b7e3db65673 Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Fri, 20 Nov 2020 08:46:28 -0700 Subject: [PATCH 050/179] Changelogs for 1.0.7 --- moveit/CHANGELOG.rst | 21 ++++++++++++++----- moveit_commander/CHANGELOG.rst | 8 +++++++ moveit_core/CHANGELOG.rst | 9 ++++++++ moveit_kinematics/CHANGELOG.rst | 5 +++++ .../chomp/chomp_interface/CHANGELOG.rst | 7 +++++++ .../chomp/chomp_motion_planner/CHANGELOG.rst | 3 +++ .../chomp_optimizer_adapter/CHANGELOG.rst | 3 +++ moveit_planners/moveit_planners/CHANGELOG.rst | 3 +++ moveit_planners/ompl/CHANGELOG.rst | 13 ++++++++++++ .../CHANGELOG.rst | 5 ++++- .../CHANGELOG.rst | 5 +++++ moveit_plugins/moveit_plugins/CHANGELOG.rst | 3 +++ .../CHANGELOG.rst | 5 +++++ .../CHANGELOG.rst | 5 +++++ moveit_ros/benchmarks/CHANGELOG.rst | 3 +++ moveit_ros/manipulation/CHANGELOG.rst | 5 +++++ moveit_ros/move_group/CHANGELOG.rst | 7 +++++++ moveit_ros/moveit_ros/CHANGELOG.rst | 3 +++ moveit_ros/moveit_servo/CHANGELOG.rst | 15 +++++++++++++ .../occupancy_map_monitor/CHANGELOG.rst | 5 +++++ moveit_ros/perception/CHANGELOG.rst | 5 +++++ moveit_ros/planning/CHANGELOG.rst | 6 ++++++ moveit_ros/planning_interface/CHANGELOG.rst | 11 ++++++++++ moveit_ros/robot_interaction/CHANGELOG.rst | 5 +++++ moveit_ros/visualization/CHANGELOG.rst | 7 +++++++ moveit_ros/warehouse/CHANGELOG.rst | 5 +++++ moveit_runtime/CHANGELOG.rst | 3 +++ moveit_setup_assistant/CHANGELOG.rst | 13 ++++++++++++ 28 files changed, 182 insertions(+), 6 deletions(-) diff --git a/moveit/CHANGELOG.rst b/moveit/CHANGELOG.rst index 5156491c08..19ae911557 100644 --- a/moveit/CHANGELOG.rst +++ b/moveit/CHANGELOG.rst @@ -2,6 +2,17 @@ Changelog for package moveit ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [feature][moveit_setup_assistant] Fix group editing (`#2350 `_) +* [feature][moveit_setup_assistant] Allow showing both, visual and collision geometry (`#2352 `_) +* [feature][moveit_setup_assistant] Start new joint_state_publisher_gui on param use_gui (`#2257 `_) +* [feature][moveit_servo] A library for servoing toward a moving pose (`#2203 `_) +* [fix][moveit_setup_assistant] Segfault when editing pose in moveit_setup_assistant (`#2340 `_) +* [fix][moveit_setup_assistant] only write default_planner_config field if any is selected (`#2293 `_) +* [fix][moveit_setup_assistant] Fix disappearing robot on change of reference frame (`#2335 `_) +* Contributors: AdamPettinger, AndyZe, Jere Liukkonen, David V. Lu!!, Felix von Drigalski, Michael Görner, Robert Haschke, Tyler Weaver, Yoan Mollard + 1.0.6 (2020-08-19) ------------------ @@ -43,7 +54,7 @@ Changelog for package moveit * [improve][moveit_kinematics] KDL IK solver improvements (`#1321 `_) * [improve][moveit_setup_assistant] support dark themes (`#1173 `_) * [improve][moveit_ros_robot_interaction] cleanup RobotInteraction (`#1287 `_) -* [improve][moveit_ros_robot_interaction] limit IK timeout to 0.1s for a responsive interaction behaviour (`#1291 `_) +* [improve][moveit_ros_robot_interaction] limit IK timeout to 0.1s for a responsive interaction behaviour (`#1291 `_) * [maintenance] cleanup SimpleControllerManager https://github.com/ros-planning/moveit/pull/1352 * [maintenance][moveit_core] Add coverage analysis for moveit_core (`#1133 `_) * Contributors: Alexander Gutenkunst, Dave Coleman, Jonathan Binney, Keerthana Subramanian Manivannan, Martin Oehler, Michael Görner, Mike Lautman, Robert Haschke, Simon Schmeisser @@ -177,7 +188,7 @@ Changelog for package moveit * [fix][moveit_ros_visualization] RobotStateVisualization: clear before load to avoid segfault `#572 `_ * [fix][setup_assistant] Fix for lunar (`#542 `_) (fix `#506 `_) * [fix][moveit_core] segfault due to missing string format parameter. (`#547 `_) - * [fix][moveit_core] doc-comment for robot_state::computeAABB (`#516 `_) + * [fix][moveit_core] doc-comment for robot_state::computeAABB (`#516 `_) * Improvement in the contained packages: * [improve][moveit_ros_planning] Chomp use PlanningScene (`#546 `_) to partially address `#305 `_ @@ -231,12 +242,12 @@ Changelog for package moveit 0.9.5 (2017-03-08) ------------------ -* [fix] correct "simplify widget handling" `#452 `_ This reverts "simplify widget handling (`#442 `_)" -* [fix][moveit_ros_warehouse] gcc6 build error `#423 `_ +* [fix] correct "simplify widget handling" `#452 `_ This reverts "simplify widget handling (`#442 `_)" +* [fix][moveit_ros_warehouse] gcc6 build error `#423 `_ * [fix] Regression on Ubuntu Xenial; numpy.ndarray indices bug (from `#86 `_) (`#450 `_). * [enhancement] Remove "catch (...)" instances, catch std::exception instead of std::runtime_error (`#445 `_) * [enhancement][MoveGroup] Add getLinkNames function (`#440 `_) -* [doc][moveit_commander] added description for set_start_state (`#447 `_) +* [doc][moveit_commander] added description for set_start_state (`#447 `_) * Contributors: Adam Allevato, Dave Coleman, Bence Magyar, Dave Coleman, Isaac I.Y. Saito, Yannick Jonetzko, Ravi Prakash Joshi 0.9.4 (2017-02-06) diff --git a/moveit_commander/CHANGELOG.rst b/moveit_commander/CHANGELOG.rst index 7df74415a1..ba970c62e4 100644 --- a/moveit_commander/CHANGELOG.rst +++ b/moveit_commander/CHANGELOG.rst @@ -2,6 +2,14 @@ Changelog for package moveit_commander ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [feature] Python interface improvements. (`#2356 `_) +* [feature] Fix ROS namespacing in moveit_commander's PSI (`#2347 `_) +* [feature] MGC: Improve exception messages (`#2318 `_) +* [feature] Add missing variants of place from list of PlaceLocations and Poses in the python interface (`#2231 `_) +* Contributors: Gerard Canal, Michael Görner, Peter Mitrano, Robert Haschke + 1.0.6 (2020-08-19) ------------------ * [maint] Adapt repository for splitted moveit_resources layout (`#2199 `_) diff --git a/moveit_core/CHANGELOG.rst b/moveit_core/CHANGELOG.rst index c2f2a9bd5f..b6d03a9695 100644 --- a/moveit_core/CHANGELOG.rst +++ b/moveit_core/CHANGELOG.rst @@ -2,6 +2,15 @@ Changelog for package moveit_core ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [feature] Handle multiple link libraries for FCL (`#2325 `_) +* [feature] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* [feature] Add a utility to print collision pairs (`#2278 `_) (`#2275 `_) +* [maint] Move constraint representation dox to moveit_tutorials (`#2147 `_) +* [maint] Update collision-related comments (`#2382 `_) +* Contributors: AndyZe, Dave Coleman, Felix von Drigalski, Ghenohenomohe, Robert Haschke + 1.0.6 (2020-08-19) ------------------ * [maint] Adapt repository for splitted moveit_resources layout (`#2199 `_) diff --git a/moveit_kinematics/CHANGELOG.rst b/moveit_kinematics/CHANGELOG.rst index 1a3e0b4ef4..b7250ffc74 100644 --- a/moveit_kinematics/CHANGELOG.rst +++ b/moveit_kinematics/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_kinematics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [fix] Fix IKfast tests (`#2331 `_) +* Contributors: Robert Haschke + 1.0.6 (2020-08-19) ------------------ * [maint] Adapt repository for splitted moveit_resources layout (`#2199 `_) diff --git a/moveit_planners/chomp/chomp_interface/CHANGELOG.rst b/moveit_planners/chomp/chomp_interface/CHANGELOG.rst index 9f2a2eee6d..af52156880 100644 --- a/moveit_planners/chomp/chomp_interface/CHANGELOG.rst +++ b/moveit_planners/chomp/chomp_interface/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package chomp_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [feature] Start new joint_state_publisher_gui on param use_gui (`#2257 `_) +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* [maint] Replace $(find xacro)/xacro -> xacro (`#2282 `_) +* Contributors: Felix von Drigalski, Robert Haschke, Yoan Mollard + 1.0.6 (2020-08-19) ------------------ * [maint] Migrate to clang-format-10 diff --git a/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst b/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst index f4f24acfb4..52782adb5a 100644 --- a/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst +++ b/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package chomp_motion_planner ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ + 1.0.6 (2020-08-19) ------------------ * [maint] Migrate to clang-format-10 diff --git a/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst b/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst index 923433cc15..1045759cc8 100644 --- a/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst +++ b/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_chomp_optimizer_adapter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ + 1.0.6 (2020-08-19) ------------------ * [maint] Migrate to clang-format-10 diff --git a/moveit_planners/moveit_planners/CHANGELOG.rst b/moveit_planners/moveit_planners/CHANGELOG.rst index 1c81adc421..919e68f468 100644 --- a/moveit_planners/moveit_planners/CHANGELOG.rst +++ b/moveit_planners/moveit_planners/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_planners ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ + 1.0.6 (2020-08-19) ------------------ diff --git a/moveit_planners/ompl/CHANGELOG.rst b/moveit_planners/ompl/CHANGELOG.rst index a1cfb44fea..83f1395127 100644 --- a/moveit_planners/ompl/CHANGELOG.rst +++ b/moveit_planners/ompl/CHANGELOG.rst @@ -2,6 +2,19 @@ Changelog for package moveit_planners_ompl ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [feature] Melodic backports in ompl interface (cleanup) (`#2277 `_) + * add consistent named logging to ompl interface + * add named logging to the ompl planner service script + * Remove dead code from ompl interface (related to subspaces and state validity cache) + * add some documentation to the ompl interface + * fix clang-tidy warnings in ompl interface + * fix some spelling errors in the ompl interface + * fix melodic specific clang-tidy warnings in ompl interface +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: Felix von Drigalski, Jeroen + 1.0.6 (2020-08-19) ------------------ * [maint] Adapt repository for splitted moveit_resources layout (`#2199 `_) diff --git a/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst b/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst index 96fa53d782..3ab381936c 100644 --- a/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst +++ b/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_controller_manager_example ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ + 1.0.6 (2020-08-19) ------------------ @@ -78,7 +81,7 @@ Changelog for package moveit_controller_manager_example 0.9.5 (2017-03-08) ------------------ -* [fix][moveit_ros_warehouse] gcc6 build error `#423 `_ +* [fix][moveit_ros_warehouse] gcc6 build error `#423 `_ * Contributors: Dave Coleman 0.9.4 (2017-02-06) diff --git a/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst b/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst index 1a11be105f..4f3acbcff6 100644 --- a/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst +++ b/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_fake_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: Felix von Drigalski + 1.0.6 (2020-08-19) ------------------ * [maint] Migrate to clang-format-10 diff --git a/moveit_plugins/moveit_plugins/CHANGELOG.rst b/moveit_plugins/moveit_plugins/CHANGELOG.rst index 19caf1932f..988579a53c 100644 --- a/moveit_plugins/moveit_plugins/CHANGELOG.rst +++ b/moveit_plugins/moveit_plugins/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_plugins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ + 1.0.6 (2020-08-19) ------------------ diff --git a/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst b/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst index efe7802c4a..a6686c7841 100644 --- a/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst +++ b/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_ros_control_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: Felix von Drigalski + 1.0.6 (2020-08-19) ------------------ diff --git a/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst b/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst index cbe35ba3fb..c4ca4f1619 100644 --- a/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst +++ b/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_simple_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: Felix von Drigalski + 1.0.6 (2020-08-19) ------------------ * [maint] Migrate to clang-format-10 diff --git a/moveit_ros/benchmarks/CHANGELOG.rst b/moveit_ros/benchmarks/CHANGELOG.rst index fba9919806..041c8890b3 100644 --- a/moveit_ros/benchmarks/CHANGELOG.rst +++ b/moveit_ros/benchmarks/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_benchmarks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ + 1.0.6 (2020-08-19) ------------------ * [maint] Adapt repository for splitted moveit_resources layout (`#2199 `_) diff --git a/moveit_ros/manipulation/CHANGELOG.rst b/moveit_ros/manipulation/CHANGELOG.rst index ab82336de0..50fc85f591 100644 --- a/moveit_ros/manipulation/CHANGELOG.rst +++ b/moveit_ros/manipulation/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_ros_manipulation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: Felix von Drigalski + 1.0.6 (2020-08-19) ------------------ * [maint] Migrate to clang-format-10 diff --git a/moveit_ros/move_group/CHANGELOG.rst b/moveit_ros/move_group/CHANGELOG.rst index 5347c78797..2b0363b233 100644 --- a/moveit_ros/move_group/CHANGELOG.rst +++ b/moveit_ros/move_group/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package moveit_ros_move_group ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [feature] Start new joint_state_publisher_gui on param use_gui (`#2257 `_) +* [feature] Let the max number of contacts be the amount of world objects + link models with geometry (`#2361 `_) +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: Felix von Drigalski, Loy van Beek, Michael Görner, Yoan Mollard, v4hn + 1.0.6 (2020-08-19) ------------------ * [maint] Adapt repository for splitted moveit_resources layout (`#2199 `_) diff --git a/moveit_ros/moveit_ros/CHANGELOG.rst b/moveit_ros/moveit_ros/CHANGELOG.rst index f516514d7c..64db092924 100644 --- a/moveit_ros/moveit_ros/CHANGELOG.rst +++ b/moveit_ros/moveit_ros/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ + 1.0.6 (2020-08-19) ------------------ diff --git a/moveit_ros/moveit_servo/CHANGELOG.rst b/moveit_ros/moveit_servo/CHANGELOG.rst index 81b06cc007..0d43b53375 100644 --- a/moveit_ros/moveit_servo/CHANGELOG.rst +++ b/moveit_ros/moveit_servo/CHANGELOG.rst @@ -2,6 +2,21 @@ Changelog for package moveit_servo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [feature] Cleanup current state handling in servo (`#2372 `_) +* [feature] Servo namespacing logic (`#2354 `_) +* [feature] A library for servoing toward a moving pose (`#2203 `_) +* [feature] Refactor velocity limit enforcement and add a unit test (`#2260 `_) +* [feature] Add a utility to print collision pairs (`#2275 `_) +* [feature] Update last_sent_command\_ at ServoCalcs start (`#2249 `_) +* [fix] Fix servo trajectory point timestamping (`#2375 `_) +* [fix] Fix ordering of windup args to control_toolbox::Pid (`#2370 `_) +* [fix] Fix Servo thread interruption (`#2314 `_) +* [fix] Servo heap-buffer-overflow bug (`#2307 `_) +* [maint] add soname version to moveit_servo (`#2266 `_) +* Contributors: AdamPettinger, AndyZe, Jere Liukkonen, Nathan Brooks, Robert Haschke, Tyler Weaver + 1.0.6 (2020-08-19) ------------------ * [feature] A ROS service to reset the Servo status (`#2246 `_) diff --git a/moveit_ros/occupancy_map_monitor/CHANGELOG.rst b/moveit_ros/occupancy_map_monitor/CHANGELOG.rst index 9c255ed440..be85bd6be1 100644 --- a/moveit_ros/occupancy_map_monitor/CHANGELOG.rst +++ b/moveit_ros/occupancy_map_monitor/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_ros_occupancy_map_monitor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: Felix von Drigalski + 1.0.6 (2020-08-19) ------------------ * [maint] Migrate to clang-format-10 diff --git a/moveit_ros/perception/CHANGELOG.rst b/moveit_ros/perception/CHANGELOG.rst index 839eca6690..7d9ffa8c0a 100644 --- a/moveit_ros/perception/CHANGELOG.rst +++ b/moveit_ros/perception/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_ros_perception ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: Felix von Drigalski, Robert Haschke + 1.0.6 (2020-08-19) ------------------ * [maint] Migrate to clang-format-10 diff --git a/moveit_ros/planning/CHANGELOG.rst b/moveit_ros/planning/CHANGELOG.rst index 7c5dc53ad0..f8ab433102 100644 --- a/moveit_ros/planning/CHANGELOG.rst +++ b/moveit_ros/planning/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package moveit_ros_planning ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [fix] Fix "Clear Octomap" button, disable when no octomap is published (`#2320 `_) +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: Felix von Drigalski + 1.0.6 (2020-08-19) ------------------ * [fix] Fix segfault in PSM::clearOctomap() (`#2193 `_) diff --git a/moveit_ros/planning_interface/CHANGELOG.rst b/moveit_ros/planning_interface/CHANGELOG.rst index dd57124213..911cd9415e 100644 --- a/moveit_ros/planning_interface/CHANGELOG.rst +++ b/moveit_ros/planning_interface/CHANGELOG.rst @@ -2,6 +2,17 @@ Changelog for package moveit_ros_planning_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [feature] Python interface improvements. (`#2356 `_) +* [feature] moveit_cpp: more informative error message, cover another potential failure condition. (`#2336 `_) +* [feature] Unit Test for ByteString-based ROS msg conversion (`#2362 `_) +* [feature] Make GILReleaser exception-safe (`#2363 `_) +* [feature] Added GILRelease to pick and place (`#2272 `_) +* [feature] Add missing variants of place from list of PlaceLocations and Poses in the python interface (`#2231 `_) +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: AndyZe, Bjar Ne, Felix von Drigalski, Gerard Canal, Peter Mitrano, Robert Haschke + 1.0.6 (2020-08-19) ------------------ * [maint] Adapt repository for splitted moveit_resources layout (`#2199 `_) diff --git a/moveit_ros/robot_interaction/CHANGELOG.rst b/moveit_ros/robot_interaction/CHANGELOG.rst index a843d0ca51..78e5034e94 100644 --- a/moveit_ros/robot_interaction/CHANGELOG.rst +++ b/moveit_ros/robot_interaction/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_ros_robot_interaction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: Felix von Drigalski + 1.0.6 (2020-08-19) ------------------ * [maint] Migrate to clang-format-10 diff --git a/moveit_ros/visualization/CHANGELOG.rst b/moveit_ros/visualization/CHANGELOG.rst index d37e2e9a52..bd5298d08c 100644 --- a/moveit_ros/visualization/CHANGELOG.rst +++ b/moveit_ros/visualization/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package moveit_ros_visualization ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [feature] Clean up Rviz Motion Planning plugin, add tooltips (`#2310 `_) +* [fix] Fix "Clear Octomap" button, disable when no octomap is published (`#2320 `_) +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: Felix von Drigalski, Robert Haschke + 1.0.6 (2020-08-19) ------------------ * [feature] MP display: add units to joints tab (`#2264 `_) diff --git a/moveit_ros/warehouse/CHANGELOG.rst b/moveit_ros/warehouse/CHANGELOG.rst index c29d1eed7d..6afec1335d 100644 --- a/moveit_ros/warehouse/CHANGELOG.rst +++ b/moveit_ros/warehouse/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_ros_warehouse ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: Felix von Drigalski + 1.0.6 (2020-08-19) ------------------ * [maint] Migrate to clang-format-10 diff --git a/moveit_runtime/CHANGELOG.rst b/moveit_runtime/CHANGELOG.rst index c16e8925d4..b5016d0da4 100644 --- a/moveit_runtime/CHANGELOG.rst +++ b/moveit_runtime/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_runtime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ + 1.0.6 (2020-08-19) ------------------ diff --git a/moveit_setup_assistant/CHANGELOG.rst b/moveit_setup_assistant/CHANGELOG.rst index d3332a8d34..4eb1a8c1f8 100644 --- a/moveit_setup_assistant/CHANGELOG.rst +++ b/moveit_setup_assistant/CHANGELOG.rst @@ -2,6 +2,19 @@ Changelog for package moveit_setup_assistant ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.7 (2020-11-20) +------------------ +* [feature] MSA: Fix group editing (`#2350 `_) +* [feature] MSA: Allow showing both, visual and collision geometry (`#2352 `_) +* [feature] Start new joint_state_publisher_gui on param use_gui (`#2257 `_) +* [fix] MSA launch files: fix indentation (`#2371 `_) +* [fix] Segfault when editing pose in moveit_setup_assistant (`#2340 `_) +* [fix] robot_description is already loaded in move_group.launch (`#2313 `_) +* [fix] MSA: only write default_planner_config field if any is selected (`#2293 `_) +* [fix] MSA: Fix disappearing robot on change of reference frame (`#2335 `_) +* [maint] Add comment to MOVEIT_CLASS_FORWARD (`#2315 `_) +* Contributors: David V. Lu!!, Felix von Drigalski, Michael Görner, Robert Haschke, Tyler Weaver, Yoan Mollard + 1.0.6 (2020-08-19) ------------------ * [maint] Adapt repository for splitted moveit_resources layout (`#2199 `_) From 701fbddb26f5aa4e752235b893292fc4618da135 Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Fri, 20 Nov 2020 08:47:18 -0700 Subject: [PATCH 051/179] 1.0.7 --- moveit/package.xml | 2 +- moveit_commander/package.xml | 2 +- moveit_core/package.xml | 2 +- moveit_kinematics/package.xml | 2 +- moveit_planners/chomp/chomp_interface/package.xml | 2 +- moveit_planners/chomp/chomp_motion_planner/package.xml | 2 +- moveit_planners/chomp/chomp_optimizer_adapter/package.xml | 2 +- moveit_planners/moveit_planners/package.xml | 2 +- moveit_planners/ompl/package.xml | 2 +- moveit_plugins/moveit_controller_manager_example/package.xml | 2 +- moveit_plugins/moveit_fake_controller_manager/package.xml | 2 +- moveit_plugins/moveit_plugins/package.xml | 2 +- moveit_plugins/moveit_ros_control_interface/package.xml | 2 +- moveit_plugins/moveit_simple_controller_manager/package.xml | 2 +- moveit_ros/benchmarks/package.xml | 2 +- moveit_ros/manipulation/package.xml | 2 +- moveit_ros/move_group/package.xml | 2 +- moveit_ros/moveit_ros/package.xml | 2 +- moveit_ros/moveit_servo/package.xml | 2 +- moveit_ros/occupancy_map_monitor/package.xml | 2 +- moveit_ros/perception/package.xml | 2 +- moveit_ros/planning/package.xml | 2 +- moveit_ros/planning_interface/package.xml | 2 +- moveit_ros/robot_interaction/package.xml | 2 +- moveit_ros/visualization/package.xml | 2 +- moveit_ros/warehouse/package.xml | 2 +- moveit_runtime/package.xml | 2 +- moveit_setup_assistant/package.xml | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) diff --git a/moveit/package.xml b/moveit/package.xml index fc1e8a92ca..7a93361df2 100644 --- a/moveit/package.xml +++ b/moveit/package.xml @@ -1,7 +1,7 @@ moveit - 1.0.6 + 1.0.7 Meta package that contains all essential package of MoveIt!. Until Summer 2016 MoveIt! had been developed over multiple repositories, where developers' usability and maintenance effort was non-trivial. See the detailed discussion for the merge of several repositories. Dave Coleman Michael Ferguson diff --git a/moveit_commander/package.xml b/moveit_commander/package.xml index 852af669d4..ec20cb7082 100644 --- a/moveit_commander/package.xml +++ b/moveit_commander/package.xml @@ -1,6 +1,6 @@ moveit_commander - 1.0.6 + 1.0.7 Python interfaces to MoveIt Ioan Sucan diff --git a/moveit_core/package.xml b/moveit_core/package.xml index 04ae1a6a24..54d0bd8595 100644 --- a/moveit_core/package.xml +++ b/moveit_core/package.xml @@ -1,6 +1,6 @@ moveit_core - 1.0.6 + 1.0.7 Core libraries used by MoveIt! Ioan Sucan Sachin Chitta diff --git a/moveit_kinematics/package.xml b/moveit_kinematics/package.xml index 0da3673b8a..ceb257c65b 100644 --- a/moveit_kinematics/package.xml +++ b/moveit_kinematics/package.xml @@ -1,7 +1,7 @@ moveit_kinematics - 1.0.6 + 1.0.7 Package for all inverse kinematics solvers in MoveIt! Dave Coleman diff --git a/moveit_planners/chomp/chomp_interface/package.xml b/moveit_planners/chomp/chomp_interface/package.xml index bf16f03eac..fd8ef1f3a5 100644 --- a/moveit_planners/chomp/chomp_interface/package.xml +++ b/moveit_planners/chomp/chomp_interface/package.xml @@ -2,7 +2,7 @@ moveit_planners_chomp The interface for using CHOMP within MoveIt! - 1.0.6 + 1.0.7 Gil Jones Chittaranjan Srinivas Swaminathan diff --git a/moveit_planners/chomp/chomp_motion_planner/package.xml b/moveit_planners/chomp/chomp_motion_planner/package.xml index 2165cbc1a2..a839f2bd90 100644 --- a/moveit_planners/chomp/chomp_motion_planner/package.xml +++ b/moveit_planners/chomp/chomp_motion_planner/package.xml @@ -2,7 +2,7 @@ chomp_motion_planner chomp_motion_planner - 1.0.6 + 1.0.7 Gil Jones Mrinal Kalakrishnan diff --git a/moveit_planners/chomp/chomp_optimizer_adapter/package.xml b/moveit_planners/chomp/chomp_optimizer_adapter/package.xml index c71ea6053f..4549750929 100644 --- a/moveit_planners/chomp/chomp_optimizer_adapter/package.xml +++ b/moveit_planners/chomp/chomp_optimizer_adapter/package.xml @@ -3,7 +3,7 @@ moveit_chomp_optimizer_adapter MoveIt planning request adapter utilizing chomp for solution optimization - 1.0.6 + 1.0.7 Raghavender Sahdev Raghavender Sahdev MoveIt! Release Team diff --git a/moveit_planners/moveit_planners/package.xml b/moveit_planners/moveit_planners/package.xml index 83e74f8d62..3bd5530275 100644 --- a/moveit_planners/moveit_planners/package.xml +++ b/moveit_planners/moveit_planners/package.xml @@ -1,6 +1,6 @@ moveit_planners - 1.0.6 + 1.0.7 Metapacakge that installs all available planners for MoveIt Ioan Sucan Sachin Chitta diff --git a/moveit_planners/ompl/package.xml b/moveit_planners/ompl/package.xml index e1610eada2..959e9437b3 100644 --- a/moveit_planners/ompl/package.xml +++ b/moveit_planners/ompl/package.xml @@ -1,6 +1,6 @@ moveit_planners_ompl - 1.0.6 + 1.0.7 MoveIt! interface to OMPL Ioan Sucan diff --git a/moveit_plugins/moveit_controller_manager_example/package.xml b/moveit_plugins/moveit_controller_manager_example/package.xml index 711b4b505f..95e1746b8a 100644 --- a/moveit_plugins/moveit_controller_manager_example/package.xml +++ b/moveit_plugins/moveit_controller_manager_example/package.xml @@ -1,6 +1,6 @@ moveit_controller_manager_example - 1.0.6 + 1.0.7 An example controller manager plugin for MoveIt. This is not functional code. Ioan Sucan diff --git a/moveit_plugins/moveit_fake_controller_manager/package.xml b/moveit_plugins/moveit_fake_controller_manager/package.xml index 533ab7940e..b006d786fa 100644 --- a/moveit_plugins/moveit_fake_controller_manager/package.xml +++ b/moveit_plugins/moveit_fake_controller_manager/package.xml @@ -1,6 +1,6 @@ moveit_fake_controller_manager - 1.0.6 + 1.0.7 A fake controller manager plugin for MoveIt. Ioan Sucan diff --git a/moveit_plugins/moveit_plugins/package.xml b/moveit_plugins/moveit_plugins/package.xml index 7d04760de1..fa9e7a15b3 100644 --- a/moveit_plugins/moveit_plugins/package.xml +++ b/moveit_plugins/moveit_plugins/package.xml @@ -1,6 +1,6 @@ moveit_plugins - 1.0.6 + 1.0.7 Metapackage for MoveIt! plugins. Michael Ferguson diff --git a/moveit_plugins/moveit_ros_control_interface/package.xml b/moveit_plugins/moveit_ros_control_interface/package.xml index 943295d0b4..9aae6051b8 100644 --- a/moveit_plugins/moveit_ros_control_interface/package.xml +++ b/moveit_plugins/moveit_ros_control_interface/package.xml @@ -1,7 +1,7 @@ moveit_ros_control_interface - 1.0.6 + 1.0.7 ros_control controller manager interface for MoveIt! Mathias Lüdtke diff --git a/moveit_plugins/moveit_simple_controller_manager/package.xml b/moveit_plugins/moveit_simple_controller_manager/package.xml index da405230c6..268b88b940 100644 --- a/moveit_plugins/moveit_simple_controller_manager/package.xml +++ b/moveit_plugins/moveit_simple_controller_manager/package.xml @@ -1,6 +1,6 @@ moveit_simple_controller_manager - 1.0.6 + 1.0.7 A generic, simple controller manager plugin for MoveIt. Michael Ferguson diff --git a/moveit_ros/benchmarks/package.xml b/moveit_ros/benchmarks/package.xml index c0a9614cb3..5c52643006 100644 --- a/moveit_ros/benchmarks/package.xml +++ b/moveit_ros/benchmarks/package.xml @@ -1,6 +1,6 @@ moveit_ros_benchmarks - 1.0.6 + 1.0.7 Enhanced tools for benchmarks in MoveIt! diff --git a/moveit_ros/manipulation/package.xml b/moveit_ros/manipulation/package.xml index a7e6c70b53..fba9e2c255 100644 --- a/moveit_ros/manipulation/package.xml +++ b/moveit_ros/manipulation/package.xml @@ -1,6 +1,6 @@ moveit_ros_manipulation - 1.0.6 + 1.0.7 Components of MoveIt! used for manipulation Ioan Sucan diff --git a/moveit_ros/move_group/package.xml b/moveit_ros/move_group/package.xml index 1b86d2a6cb..2b5a1fb762 100644 --- a/moveit_ros/move_group/package.xml +++ b/moveit_ros/move_group/package.xml @@ -1,6 +1,6 @@ moveit_ros_move_group - 1.0.6 + 1.0.7 The move_group node for MoveIt Ioan Sucan Sachin Chitta diff --git a/moveit_ros/moveit_ros/package.xml b/moveit_ros/moveit_ros/package.xml index 9652939c77..b41451f5c8 100644 --- a/moveit_ros/moveit_ros/package.xml +++ b/moveit_ros/moveit_ros/package.xml @@ -1,6 +1,6 @@ moveit_ros - 1.0.6 + 1.0.7 Components of MoveIt! that use ROS Ioan Sucan Sachin Chitta diff --git a/moveit_ros/moveit_servo/package.xml b/moveit_ros/moveit_servo/package.xml index 1376a83625..a5934c8adb 100644 --- a/moveit_ros/moveit_servo/package.xml +++ b/moveit_ros/moveit_servo/package.xml @@ -1,7 +1,7 @@ moveit_servo - 1.0.6 + 1.0.7 Provides real-time manipulator Cartesian and joint servoing. diff --git a/moveit_ros/occupancy_map_monitor/package.xml b/moveit_ros/occupancy_map_monitor/package.xml index 86b515af0b..f2b79a4d18 100644 --- a/moveit_ros/occupancy_map_monitor/package.xml +++ b/moveit_ros/occupancy_map_monitor/package.xml @@ -1,7 +1,7 @@ moveit_ros_occupancy_map_monitor - 1.0.6 + 1.0.7 Components of MoveIt! connecting to occupancy map Ioan Sucan diff --git a/moveit_ros/perception/package.xml b/moveit_ros/perception/package.xml index 51821cdac4..07e4555811 100644 --- a/moveit_ros/perception/package.xml +++ b/moveit_ros/perception/package.xml @@ -1,6 +1,6 @@ moveit_ros_perception - 1.0.6 + 1.0.7 Components of MoveIt! connecting to perception Ioan Sucan diff --git a/moveit_ros/planning/package.xml b/moveit_ros/planning/package.xml index 01435e5ffd..e21878bf1a 100644 --- a/moveit_ros/planning/package.xml +++ b/moveit_ros/planning/package.xml @@ -1,7 +1,7 @@ moveit_ros_planning - 1.0.6 + 1.0.7 Planning components of MoveIt! that use ROS Ioan Sucan Sachin Chitta diff --git a/moveit_ros/planning_interface/package.xml b/moveit_ros/planning_interface/package.xml index b936a4acec..d3df88689f 100644 --- a/moveit_ros/planning_interface/package.xml +++ b/moveit_ros/planning_interface/package.xml @@ -1,6 +1,6 @@ moveit_ros_planning_interface - 1.0.6 + 1.0.7 Components of MoveIt! that offer simpler interfaces to planning and execution Ioan Sucan diff --git a/moveit_ros/robot_interaction/package.xml b/moveit_ros/robot_interaction/package.xml index 0a8a3519f2..0a4eb096b4 100644 --- a/moveit_ros/robot_interaction/package.xml +++ b/moveit_ros/robot_interaction/package.xml @@ -1,6 +1,6 @@ moveit_ros_robot_interaction - 1.0.6 + 1.0.7 Components of MoveIt! that offer interaction via interactive markers Ioan Sucan diff --git a/moveit_ros/visualization/package.xml b/moveit_ros/visualization/package.xml index ffae042382..8a23de5fdc 100644 --- a/moveit_ros/visualization/package.xml +++ b/moveit_ros/visualization/package.xml @@ -1,6 +1,6 @@ moveit_ros_visualization - 1.0.6 + 1.0.7 Components of MoveIt! that offer visualization Ioan Sucan diff --git a/moveit_ros/warehouse/package.xml b/moveit_ros/warehouse/package.xml index 6e98a0ff0d..eb3b279bcd 100644 --- a/moveit_ros/warehouse/package.xml +++ b/moveit_ros/warehouse/package.xml @@ -1,6 +1,6 @@ moveit_ros_warehouse - 1.0.6 + 1.0.7 Components of MoveIt! connecting to MongoDB Ioan Sucan diff --git a/moveit_runtime/package.xml b/moveit_runtime/package.xml index 486a511cf0..7e40d8a77d 100644 --- a/moveit_runtime/package.xml +++ b/moveit_runtime/package.xml @@ -1,7 +1,7 @@ moveit_runtime - 1.0.6 + 1.0.7 moveit_runtime meta package contains MoveIt! packages that are essential for its runtime (e.g. running MoveIt! on robots). Isaac I. Y. Saito diff --git a/moveit_setup_assistant/package.xml b/moveit_setup_assistant/package.xml index 585ed83ba3..965e4c84c1 100644 --- a/moveit_setup_assistant/package.xml +++ b/moveit_setup_assistant/package.xml @@ -1,6 +1,6 @@ moveit_setup_assistant - 1.0.6 + 1.0.7 Generates a configuration package that makes it easy to use MoveIt! From 0d62a3496394654e356ac325a1ec94ea8fb3b514 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 9 Dec 2020 08:24:50 +0100 Subject: [PATCH 052/179] RobotModelBuilder: Allow adding end effectors (#2454) --- .../include/moveit/utils/robot_model_test_utils.h | 3 +++ moveit_core/utils/src/robot_model_test_utils.cpp | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/moveit_core/utils/include/moveit/utils/robot_model_test_utils.h b/moveit_core/utils/include/moveit/utils/robot_model_test_utils.h index 28489d53f1..2da0a1188d 100644 --- a/moveit_core/utils/include/moveit/utils/robot_model_test_utils.h +++ b/moveit_core/utils/include/moveit/utils/robot_model_test_utils.h @@ -165,6 +165,9 @@ class RobotModelBuilder */ void addGroup(const std::vector& links, const std::vector& joints, const std::string& name); + void addEndEffector(const std::string& name, const std::string& parent_link, const std::string& parent_group = "", + const std::string& component_group = ""); + /** \} */ /** \brief Returns true if the building process so far has been valid. */ diff --git a/moveit_core/utils/src/robot_model_test_utils.cpp b/moveit_core/utils/src/robot_model_test_utils.cpp index 71f8d358b9..eaafaa246c 100644 --- a/moveit_core/utils/src/robot_model_test_utils.cpp +++ b/moveit_core/utils/src/robot_model_test_utils.cpp @@ -342,6 +342,17 @@ void RobotModelBuilder::addGroup(const std::vector& links, const st srdf_writer_->groups_.push_back(new_group); } +void RobotModelBuilder::addEndEffector(const std::string& name, const std::string& parent_link, + const std::string& parent_group, const std::string& component_group) +{ + srdf::Model::EndEffector eef; + eef.name_ = name; + eef.parent_link_ = parent_link; + eef.parent_group_ = parent_group; + eef.component_group_ = component_group; + srdf_writer_->end_effectors_.push_back(eef); +} + bool RobotModelBuilder::isValid() { return is_valid_; From 83379557fcad793817a31b7314a69865a02d6964 Mon Sep 17 00:00:00 2001 From: JafarAbdi Date: Fri, 27 Nov 2020 23:18:33 +0300 Subject: [PATCH 053/179] RobotModelBuilder: Add parameter to specify the joint rotation axis --- .../utils/include/moveit/utils/robot_model_test_utils.h | 4 +++- moveit_core/utils/src/robot_model_test_utils.cpp | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/moveit_core/utils/include/moveit/utils/robot_model_test_utils.h b/moveit_core/utils/include/moveit/utils/robot_model_test_utils.h index 2da0a1188d..bb267f2a09 100644 --- a/moveit_core/utils/include/moveit/utils/robot_model_test_utils.h +++ b/moveit_core/utils/include/moveit/utils/robot_model_test_utils.h @@ -102,9 +102,11 @@ class RobotModelBuilder * the joints will be given this type. To add multiple types of joints, call this method multiple times * \param[in] joint_origins The "parent to joint" origins for the joints connecting the links. If not used, all * origins will default to the identity transform + * \param[in] joint_axis The joint axis specified in the joint frame defaults to (1,0,0) */ void addChain(const std::string& section, const std::string& type, - const std::vector& joint_origins = {}); + const std::vector& joint_origins = {}, + urdf::Vector3 joint_axis = urdf::Vector3(1.0, 0.0, 0.0)); /** \brief Adds a collision mesh to a specific link. * \param[in] link_name The name of the link to which the mesh will be added. Must already be in the builder diff --git a/moveit_core/utils/src/robot_model_test_utils.cpp b/moveit_core/utils/src/robot_model_test_utils.cpp index eaafaa246c..ff3238baad 100644 --- a/moveit_core/utils/src/robot_model_test_utils.cpp +++ b/moveit_core/utils/src/robot_model_test_utils.cpp @@ -110,7 +110,7 @@ RobotModelBuilder::RobotModelBuilder(const std::string& name, const std::string& } void RobotModelBuilder::addChain(const std::string& section, const std::string& type, - const std::vector& joint_origins) + const std::vector& joint_origins, urdf::Vector3 joint_axis) { std::vector link_names; boost::split_regex(link_names, section, boost::regex("->")); @@ -182,7 +182,7 @@ void RobotModelBuilder::addChain(const std::string& section, const std::string& return; } - joint->axis = urdf::Vector3(1.0, 0.0, 0.0); + joint->axis = joint_axis; if (joint->type == urdf::Joint::REVOLUTE || joint->type == urdf::Joint::PRISMATIC) { urdf::JointLimitsSharedPtr limits(new urdf::JointLimits); From 1e6fd1455f0053919879072f8ea1f5c0a34e8c6d Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Thu, 14 Jan 2021 11:45:14 +0100 Subject: [PATCH 054/179] Suppress warnings "mesh_use_embedded_materials is ignored" rviz more stricly checks marker parameters and thus issues this warning if mesh_use_embedded_materials was set although no mesh_resource was specified --- moveit_ros/robot_interaction/src/robot_interaction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moveit_ros/robot_interaction/src/robot_interaction.cpp b/moveit_ros/robot_interaction/src/robot_interaction.cpp index fddf7962b6..0bf627cf07 100644 --- a/moveit_ros/robot_interaction/src/robot_interaction.cpp +++ b/moveit_ros/robot_interaction/src/robot_interaction.cpp @@ -414,7 +414,7 @@ void RobotInteraction::addEndEffectorMarkers(const InteractionHandlerPtr& handle for (std::size_t i = 0; i < marker_array.markers.size(); ++i) { marker_array.markers[i].header = im.header; - marker_array.markers[i].mesh_use_embedded_materials = true; + marker_array.markers[i].mesh_use_embedded_materials = !marker_array.markers[i].mesh_resource.empty(); // - - - - - - Do some math for the offset - - - - - - tf2::Transform tf_root_to_im, tf_root_to_mesh, tf_im_to_eef; tf2::fromMsg(im.pose, tf_root_to_im); From 45e2be9879880ac9c18b228c64ca7c0d17d5041d Mon Sep 17 00:00:00 2001 From: Immanuel Martini <35950815+martiniil@users.noreply.github.com> Date: Tue, 2 Mar 2021 10:21:05 +0100 Subject: [PATCH 055/179] [backport] Pilz planner merge (#2507) * Add Pilz industrial motion planner (#1893) * Add pilz_industrial_motion_planner to moveit_planners * Update license, document consent to this change by contributers * Fix formatting, code style, catkin_lint, clang-tidy * Add and update tests, use new prvt_moveit_config from moveit_resources * New codeowners for pilz_industrial_motion planner * Add pipeline configuration teimplates to MSA * Fix file not found error (adjust to melodic `moveit::core::PlanningScene::isEmpty()` functions) Co-authored-by: Christian Henkel Co-authored-by: Joachim Schleicher Co-authored-by: rfeistenauer Co-authored-by: Giuseppe Sansone --- .../CHANGELOG.rst | 106 + .../CMakeLists.txt | 519 ++ .../pilz_industrial_motion_planner/README.md | 4 + .../doc/.gitignore | 12 + .../doc/MotionBlendAlgorithmDescription.pdf | Bin 0 -> 534094 bytes .../doc/MotionBlendAlgorithmDescription.tex | 114 + .../doc/README.md | 22 + .../doc/diag_class_capabilities.png | Bin 0 -> 41398 bytes .../doc/diag_class_capabilities.uxf | 413 ++ .../doc/diag_class_planning_context.png | Bin 0 -> 133824 bytes .../doc/diag_class_planning_context.uxf | 906 ++++ .../doc/figure/blend_case_1.eps | 1648 +++++++ .../doc/figure/blend_case_2.eps | 1548 ++++++ .../doc/figure/blend_case_3.eps | 1567 ++++++ .../doc/figure/blend_radius.png | Bin 0 -> 56819 bytes .../doc/figure/original_trajectories.eps | 4376 +++++++++++++++++ .../doc/figure/ptp.png | Bin 0 -> 16444 bytes .../doc/figure/ptp.svg | 860 ++++ .../doc/figure/ptp_movement_1.png | Bin 0 -> 100740 bytes .../doc/figure/ptp_movement_2.png | Bin 0 -> 117675 bytes .../doc/figure/rviz_planner.png | Bin 0 -> 177046 bytes .../doc/sequence_processing_overview.png | Bin 0 -> 187694 bytes .../doc/sequence_processing_overview.uxf | 1130 +++++ .../capability_names.h | 42 + .../cartesian_limit.h | 159 + .../cartesian_limits_aggregator.h | 65 + .../cartesian_trajectory.h | 51 + .../cartesian_trajectory_point.h | 53 + .../command_list_manager.h | 225 + .../joint_limits_aggregator.h | 150 + .../joint_limits_container.h | 163 + .../joint_limits_extension.h | 66 + .../joint_limits_interface_extension.h | 101 + .../joint_limits_validator.h | 153 + .../limits_container.h | 104 + .../move_group_sequence_action.h | 90 + .../move_group_sequence_service.h | 66 + .../path_circle_generator.h | 101 + .../pilz_industrial_motion_planner.h | 139 + .../plan_components_builder.h | 158 + .../planning_context_base.h | 181 + .../planning_context_circ.h | 67 + .../planning_context_lin.h | 65 + .../planning_context_loader.h | 144 + .../planning_context_loader_circ.h | 68 + .../planning_context_loader_lin.h | 68 + .../planning_context_loader_ptp.h | 68 + .../planning_context_ptp.h | 67 + .../planning_exceptions.h | 71 + .../tip_frame_getter.h | 90 + .../trajectory_blend_request.h | 59 + .../trajectory_blend_response.h | 57 + .../trajectory_blender.h | 74 + .../trajectory_blender_transition_window.h | 178 + .../trajectory_functions.h | 219 + .../trajectory_generation_exceptions.h | 121 + .../trajectory_generator.h | 291 ++ .../trajectory_generator_circ.h | 107 + .../trajectory_generator_lin.h | 85 + .../trajectory_generator_ptp.h | 94 + .../velocity_profile_atrap.h | 215 + .../package.xml | 55 + ...rial_motion_planner_plugin_description.xml | 5 + .../planning_context_plugin_description.xml | 18 + ...sequence_capability_plugin_description.xml | 13 + .../rosdoc.yaml | 6 + .../src/cartesian_limit.cpp | 119 + .../src/cartesian_limits_aggregator.cpp | 96 + .../src/command_list_manager.cpp | 315 ++ .../src/joint_limits_aggregator.cpp | 181 + .../src/joint_limits_container.cpp | 182 + .../src/joint_limits_validator.cpp | 157 + .../src/limits_container.cpp | 78 + .../src/move_group_sequence_action.cpp | 293 ++ .../src/move_group_sequence_service.cpp | 105 + .../src/path_circle_generator.cpp | 147 + .../src/pilz_industrial_motion_planner.cpp | 173 + .../src/plan_components_builder.cpp | 137 + .../src/planning_context_loader.cpp | 64 + .../src/planning_context_loader_circ.cpp | 75 + .../src/planning_context_loader_lin.cpp | 75 + .../src/planning_context_loader_ptp.cpp | 74 + .../trajectory_blender_transition_window.cpp | 301 ++ .../src/trajectory_functions.cpp | 584 +++ .../src/trajectory_generator.cpp | 332 ++ .../src/trajectory_generator_circ.cpp | 270 + .../src/trajectory_generator_lin.cpp | 203 + .../src/trajectory_generator_ptp.cpp | 261 + .../src/velocity_profile_atrap.cpp | 451 ++ .../acceptance_tests/acceptance_test_lin.md | 62 + .../acceptance_tests/acceptance_test_ptp.md | 54 + .../img/acceptance_test_lin_img1.png | Bin 0 -> 229896 bytes .../img/acceptance_test_lin_img2.png | Bin 0 -> 280710 bytes .../img/acceptance_test_lin_img3.png | Bin 0 -> 253603 bytes .../img/acceptance_test_lin_img4.png | Bin 0 -> 280613 bytes .../img/acceptance_test_ptp_img1.png | Bin 0 -> 163741 bytes .../img/acceptance_test_ptp_img2.png | Bin 0 -> 215064 bytes .../integrationtest_command_list_manager.cpp | 661 +++ .../integrationtest_command_list_manager.test | 68 + .../test/integrationtest_command_planning.cpp | 501 ++ .../integrationtest_command_planning.test | 62 + ...st_command_planning_frankaemika_panda.test | 63 + ...iontest_command_planning_with_gripper.test | 61 + .../integrationtest_get_solver_tip_frame.cpp | 116 + .../integrationtest_get_solver_tip_frame.test | 48 + ...ntegrationtest_plan_components_builder.cpp | 132 + ...tegrationtest_plan_components_builder.test | 65 + .../test/integrationtest_sequence_action.cpp | 628 +++ .../test/integrationtest_sequence_action.test | 59 + ...e_action_capability_frankaemika_panda.test | 65 + ...quence_action_capability_with_gripper.test | 60 + ...grationtest_sequence_action_preemption.cpp | 180 + ...rationtest_sequence_action_preemption.test | 59 + ...rationtest_sequence_service_capability.cpp | 426 ++ ...ationtest_sequence_service_capability.test | 57 + ..._service_capability_frankaemika_panda.test | 59 + ...uence_service_capability_with_gripper.test | 57 + .../test/test_robots/concept_testdata.odp | Bin 0 -> 14825 bytes .../test/test_robots/concept_testdata.png | Bin 0 -> 74304 bytes .../launch/moveit_planning_execution.launch | 77 + .../test_data/testdata_sequence.xml | 173 + .../prbt/launch/test_context.launch | 43 + .../prbt/test_data/testdata_deprecated.xml | 434 ++ .../prbt/test_data/testdata_sequence.xml | 227 + .../prbt/test_data/testdata_with_gripper.xml | 95 + .../test_cartesian_limit_all.yaml | 37 + .../test_cartesian_limit_only_vel.yaml | 34 + .../test_joint_limits_valid_1.yaml | 52 + ...est_joint_limits_violate_position_max.yaml | 37 + ...est_joint_limits_violate_position_min.yaml | 37 + .../test_joint_limits_violate_velocity.yaml | 36 + .../test/test_robots/testpoints.py | 141 + .../test/test_utils.cpp | 1430 ++++++ .../test/test_utils.h | 484 ++ .../unittest_cartesian_limits_aggregator.cpp | 92 + .../unittest_cartesian_limits_aggregator.test | 53 + .../test/unittest_get_solver_tip_frame.cpp | 145 + .../test/unittest_joint_limit.cpp | 111 + .../test/unittest_joint_limit.test | 40 + .../test/unittest_joint_limit_config.yaml | 31 + .../test/unittest_joint_limits_aggregator.cpp | 208 + .../unittest_joint_limits_aggregator.test | 58 + .../test/unittest_joint_limits_container.cpp | 229 + .../test/unittest_joint_limits_validator.cpp | 490 ++ ...nittest_pilz_industrial_motion_planner.cpp | 232 + ...ittest_pilz_industrial_motion_planner.test | 48 + ..._pilz_industrial_motion_planner_direct.cpp | 121 + .../test/unittest_planning_context.cpp | 282 ++ .../test/unittest_planning_context.test | 48 + .../unittest_planning_context_loaders.cpp | 179 + .../unittest_planning_context_loaders.test | 48 + ...t_trajectory_blender_transition_window.cpp | 727 +++ ..._trajectory_blender_transition_window.test | 65 + .../test/unittest_trajectory_functions.cpp | 971 ++++ .../test/unittest_trajectory_functions.test | 53 + .../test/unittest_trajectory_generator.cpp | 146 + .../unittest_trajectory_generator_circ.cpp | 785 +++ .../unittest_trajectory_generator_circ.test | 61 + .../unittest_trajectory_generator_common.cpp | 434 ++ .../unittest_trajectory_generator_common.test | 59 + .../unittest_trajectory_generator_lin.cpp | 470 ++ .../unittest_trajectory_generator_lin.test | 62 + .../unittest_trajectory_generator_ptp.cpp | 971 ++++ .../unittest_trajectory_generator_ptp.test | 56 + .../test/unittest_velocity_profile_atrap.cpp | 631 +++ .../CHANGELOG.rst | 84 + .../CMakeLists.txt | 88 + .../doc/README.md | 34 + .../diagrams/diag_class_circ_auxiliary.png | Bin 0 -> 24644 bytes .../diagrams/diag_class_circ_auxiliary.uxf | 133 + .../doc/diagrams/diag_class_commands.png | Bin 0 -> 9020 bytes .../doc/diagrams/diag_class_commands.uxf | 175 + .../diag_class_robot_configurations.png | Bin 0 -> 18548 bytes .../diag_class_robot_configurations.uxf | 133 + .../diag_seq_testdataloader_usage.png | Bin 0 -> 16098 bytes .../diag_seq_testdataloader_usage.uxf | 215 + .../async_test.h | 176 + .../basecmd.h | 128 + .../cartesianconfiguration.h | 188 + .../cartesianpathconstraintsbuilder.h | 90 + .../center.h | 60 + .../checks.h | 62 + .../circ.h | 106 + .../circ_auxiliary_types.h | 49 + .../circauxiliary.h | 91 + .../command_types_typedef.h | 69 + .../default_values.h | 51 + .../exception_types.h | 52 + .../goalconstraintsmsgconvertible.h | 56 + .../gripper.h | 48 + .../interim.h | 60 + .../jointconfiguration.h | 145 + .../lin.h | 67 + .../motioncmd.h | 93 + .../motionplanrequestconvertible.h | 54 + .../ptp.h | 67 + .../robotconfiguration.h | 92 + .../robotstatemsgconvertible.h | 54 + .../sequence.h | 147 + .../testdata_loader.h | 117 + .../xml_constants.h | 80 + .../xml_testdata_loader.h | 223 + .../package.xml | 29 + .../src/cartesianconfiguration.cpp | 132 + .../src/jointconfiguration.cpp | 161 + .../src/robotconfiguration.cpp | 62 + .../src/sequence.cpp | 120 + .../src/xml_testdata_loader.cpp | 555 +++ .../src/tools/moveit_config_data.cpp | 2 + .../widgets/configuration_files_widget.cpp | 23 + .../config/cartesian_limits.yaml | 5 + .../launch/chomp_planning_pipeline.launch.xml | 42 +- .../fake_moveit_controller_manager.launch.xml | 5 +- .../launch/move_group.launch | 6 +- .../launch/ompl_planning_pipeline.launch.xml | 8 + ...otion_planner_planning_pipeline.launch.xml | 28 + .../launch/planning_context.launch | 1 + .../launch/planning_pipeline.launch.xml | 11 +- .../launch/trajectory_execution.launch.xml | 6 +- 219 files changed, 41518 insertions(+), 21 deletions(-) create mode 100644 moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst create mode 100644 moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt create mode 100644 moveit_planners/pilz_industrial_motion_planner/README.md create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/.gitignore create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/MotionBlendAlgorithmDescription.pdf create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/MotionBlendAlgorithmDescription.tex create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/README.md create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/diag_class_capabilities.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/diag_class_capabilities.uxf create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/diag_class_planning_context.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/diag_class_planning_context.uxf create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_case_1.eps create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_case_2.eps create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_case_3.eps create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_radius.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/figure/original_trajectories.eps create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/figure/ptp.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/figure/ptp.svg create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/figure/ptp_movement_1.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/figure/ptp_movement_2.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/figure/rviz_planner.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/sequence_processing_overview.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/doc/sequence_processing_overview.uxf create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/capability_names.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_limit.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_limits_aggregator.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_trajectory.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_trajectory_point.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/command_list_manager.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_aggregator.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_container.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_extension.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_interface_extension.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_validator.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/limits_container.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/move_group_sequence_action.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/move_group_sequence_service.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/path_circle_generator.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/pilz_industrial_motion_planner.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/plan_components_builder.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_base.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_circ.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_lin.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader_circ.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader_lin.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader_ptp.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_ptp.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_exceptions.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/tip_frame_getter.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blend_request.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blend_response.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blender.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blender_transition_window.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_functions.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generation_exceptions.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator_circ.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator_lin.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator_ptp.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/velocity_profile_atrap.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/package.xml create mode 100644 moveit_planners/pilz_industrial_motion_planner/plugins/pilz_industrial_motion_planner_plugin_description.xml create mode 100644 moveit_planners/pilz_industrial_motion_planner/plugins/planning_context_plugin_description.xml create mode 100644 moveit_planners/pilz_industrial_motion_planner/plugins/sequence_capability_plugin_description.xml create mode 100644 moveit_planners/pilz_industrial_motion_planner/rosdoc.yaml create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/cartesian_limit.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/cartesian_limits_aggregator.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/command_list_manager.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/joint_limits_aggregator.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/joint_limits_container.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/joint_limits_validator.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/limits_container.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/move_group_sequence_action.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/move_group_sequence_service.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/path_circle_generator.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/pilz_industrial_motion_planner.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/plan_components_builder.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader_circ.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader_lin.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader_ptp.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/trajectory_blender_transition_window.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/trajectory_functions.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_circ.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_lin.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_ptp.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/src/velocity_profile_atrap.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_lin.md create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_ptp.md create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_lin_img1.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_lin_img2.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_lin_img3.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_lin_img4.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_ptp_img1.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_ptp_img2.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_list_manager.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_list_manager.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_frankaemika_panda.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_with_gripper.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_get_solver_tip_frame.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_get_solver_tip_frame.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_plan_components_builder.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_plan_components_builder.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_frankaemika_panda.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_with_gripper.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_frankaemika_panda.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_with_gripper.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/concept_testdata.odp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/concept_testdata.png create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/launch/moveit_planning_execution.launch create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/test_data/testdata_sequence.xml create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/launch/test_context.launch create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/testdata_deprecated.xml create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/testdata_sequence.xml create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/testdata_with_gripper.xml create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_cartesian_limits_aggregator/test_cartesian_limit_all.yaml create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_cartesian_limits_aggregator/test_cartesian_limit_only_vel.yaml create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_valid_1.yaml create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_violate_position_max.yaml create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_violate_position_min.yaml create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_violate_velocity.yaml create mode 100755 moveit_planners/pilz_industrial_motion_planner/test/test_robots/testpoints.py create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_utils.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_utils.h create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_cartesian_limits_aggregator.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_cartesian_limits_aggregator.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_get_solver_tip_frame.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limit.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limit.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limit_config.yaml create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_aggregator.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_aggregator.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_container.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_validator.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_pilz_industrial_motion_planner.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_pilz_industrial_motion_planner.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_pilz_industrial_motion_planner_direct.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context_loaders.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context_loaders.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_blender_transition_window.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_blender_transition_window.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_functions.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_functions.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_circ.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_circ.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_common.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_common.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_lin.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_lin.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_ptp.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_ptp.test create mode 100644 moveit_planners/pilz_industrial_motion_planner/test/unittest_velocity_profile_atrap.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/CMakeLists.txt create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/doc/README.md create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_circ_auxiliary.png create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_circ_auxiliary.uxf create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_commands.png create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_commands.uxf create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_robot_configurations.png create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_robot_configurations.uxf create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_seq_testdataloader_usage.png create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_seq_testdataloader_usage.uxf create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/async_test.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/basecmd.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/cartesianconfiguration.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/cartesianpathconstraintsbuilder.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/center.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/checks.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/circ.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/circ_auxiliary_types.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/circauxiliary.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/command_types_typedef.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/default_values.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/exception_types.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/goalconstraintsmsgconvertible.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/gripper.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/interim.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/jointconfiguration.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/lin.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/motioncmd.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/motionplanrequestconvertible.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/ptp.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/robotconfiguration.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/robotstatemsgconvertible.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/sequence.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/testdata_loader.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/xml_constants.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/xml_testdata_loader.h create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/package.xml create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/src/cartesianconfiguration.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/src/jointconfiguration.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/src/robotconfiguration.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/src/sequence.cpp create mode 100644 moveit_planners/pilz_industrial_motion_planner_testutils/src/xml_testdata_loader.cpp create mode 100644 moveit_setup_assistant/templates/moveit_config_pkg_template/config/cartesian_limits.yaml create mode 100644 moveit_setup_assistant/templates/moveit_config_pkg_template/launch/pilz_industrial_motion_planner_planning_pipeline.launch.xml diff --git a/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst b/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst new file mode 100644 index 0000000000..1acf7f0272 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst @@ -0,0 +1,106 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package pilz_industrial_motion_planner +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +0.4.10 (2019-12-04) +------------------- + +0.4.9 (2019-11-28) +------------------ + +0.4.8 (2019-11-22) +------------------ + +0.4.7 (2019-09-10) +------------------ +* Fix clang-tidy issues +* integrate clang-tidy via CMake flag +* Contributors: Pilz GmbH and Co. KG + +0.4.6 (2019-09-04) +------------------ + +0.4.5 (2019-09-03) +------------------ +* Adapt to changes in pilz_robots +* add static code analyzing (clang-tidy) +* drop deprecated isRobotStateEqual() +* Contributors: Pilz GmbH and Co. KG + +0.4.4 (2019-06-19) +------------------ +* fixed an error that led to trajectories not strictly increasing in time +* Contributors: Pilz GmbH and Co. KG + +0.4.3 (2019-04-08) +------------------ +* update dependencies of trajectory_generation +* fix CIRC path generator and increase test coverage +* adopt strictest limits in ptp planner (refactor JointLimitsContainer and TrajectoryGeneratorPTP) +* Enable gripper commands inside a sequence +* Contributors: Pilz GmbH and Co. KG + +0.4.2 (2019-03-13) +------------------ +* re-adapt to new RobotState API: remove #attempts +* Contributors: Pilz GmbH and Co. KG + +0.4.1 (2019-02-27) +------------------ + +0.3.6 (2019-02-26) +------------------ +* refactor the testdataloader +* adapt to new RobotState API: remove #attempts +* Contributors: Pilz GmbH and Co. KG + +0.3.5 (2019-02-06) +------------------ +* Increase line coverage for blending to 100% +* refactor determining the trajectory alignment in the blend implementation +* extend and refactor unittest of blender_transition_window +* add planning group check to blender_transition_window +* add more details to blend algorithm description +* change handling of empty sequences in capabilities to be non-erroneous +* rename command_planner -> pilz_command_planner +* use pilz_testutils package for blend test +* use collision-aware ik calculation +* Contributors: Pilz GmbH and Co. KG + +0.4.0 (2018-12-18) +------------------ +* Use Eigen::Isometry3d to keep up with the recent changes in moveit +* Contributors: Chris Lalancette + +0.3.1 (2018-12-17) +------------------ + +0.3.0 (2018-11-28) +------------------ +* add append method for avoiding duplicate points in robot_trajectory trajectories +* Relax the precondition on trajectory generators from v_start==0 to |v_start| < 1e-10 to gain robustness +* Set last point of generated trajectories to have vel=acc=0 to match the first point. +* add sequence action and service capabilities to concatenate multiple requests +* Contributors: Pilz GmbH and Co. KG + +0.2.2 (2018-09-26) +------------------ + +0.2.1 (2018-09-25) +------------------ + +0.1.1 (2018-09-25) +------------------ +* port to melodic +* drop unused dependencies +* Contributors: Pilz GmbH and Co. KG + +0.2.0 (2018-09-14) +------------------ +* Changes for melodic +* Contributors: Pilz GmbH and Co. KG + +0.1.0 (2018-09-14) +------------------ +* Created trajectory generation package with ptp, lin, circ and blend planner +* Contributors: Pilz GmbH and Co. KG diff --git a/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt b/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt new file mode 100644 index 0000000000..7c3f86c8a1 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt @@ -0,0 +1,519 @@ +cmake_minimum_required(VERSION 2.8.3) +project(pilz_industrial_motion_planner) + +## Add support for C++11, supported in ROS Kinetic and newer +add_definitions(-std=c++11) +add_definitions(-Wall) +add_definitions(-Wextra) +add_definitions(-Wno-unused-parameter) + +find_package(catkin REQUIRED COMPONENTS + eigen_conversions + kdl_conversions + moveit_core + moveit_msgs + moveit_ros_move_group + moveit_ros_planning + moveit_ros_planning_interface + pluginlib + roscpp + tf2 + tf2_eigen + tf2_geometry_msgs + tf2_kdl + tf2_ros +) + +find_package(orocos_kdl) +find_package(Boost REQUIRED COMPONENTS ) + +if(CATKIN_ENABLE_TESTING AND ENABLE_COVERAGE_TESTING) + find_package(code_coverage REQUIRED) + APPEND_COVERAGE_COMPILER_FLAGS() +endif() + +################ +## Clang tidy ## +################ +if(CATKIN_ENABLE_CLANG_TIDY) + find_program( + CLANG_TIDY_EXE + NAMES "clang-tidy" + DOC "Path to clang-tidy executable" + ) + if(NOT CLANG_TIDY_EXE) + message(FATAL_ERROR "clang-tidy not found.") + else() + message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") + set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE}") + endif() +endif() + +################################### +## catkin specific configuration ## +################################### +catkin_package( + CATKIN_DEPENDS + moveit_msgs + roscpp + tf2_geometry_msgs +) + +########### +## Build ## +########### +include_directories( + include +) + +# To avoid Warnings from clang-tidy declare system +include_directories( + SYSTEM + ${Boost_INCLUDE_DIRS} + ${catkin_INCLUDE_DIRS} +) + +## Declare a C++ library +add_library(${PROJECT_NAME}_lib + src/${PROJECT_NAME}.cpp + src/planning_context_loader.cpp + src/joint_limits_validator.cpp + src/joint_limits_aggregator.cpp + src/joint_limits_container.cpp + src/cartesian_limits_aggregator.cpp + src/cartesian_limit.cpp + src/limits_container.cpp + src/trajectory_functions.cpp + src/plan_components_builder.cpp +) + +target_link_libraries(${PROJECT_NAME}_lib + ${catkin_LIBRARIES} +) + +############# +## Plugins ## +############# +add_library(${PROJECT_NAME} + src/${PROJECT_NAME}.cpp + src/planning_context_loader.cpp + src/joint_limits_aggregator.cpp + src/joint_limits_container.cpp + src/limits_container.cpp + src/cartesian_limit.cpp + src/cartesian_limits_aggregator.cpp + ) +target_link_libraries(${PROJECT_NAME} + ${catkin_LIBRARIES}) + +add_library(planning_context_loader_ptp + src/planning_context_loader_ptp.cpp + src/planning_context_loader.cpp + src/trajectory_functions.cpp + src/trajectory_generator.cpp + src/trajectory_generator_ptp.cpp + src/velocity_profile_atrap.cpp + src/joint_limits_container.cpp + ) +target_link_libraries(planning_context_loader_ptp + ${catkin_LIBRARIES}) + +add_library(planning_context_loader_lin + src/planning_context_loader_lin.cpp + src/planning_context_loader.cpp + src/trajectory_functions.cpp + src/trajectory_generator.cpp + src/trajectory_generator_lin.cpp + src/velocity_profile_atrap.cpp + ) +target_link_libraries(planning_context_loader_lin + ${catkin_LIBRARIES}) + +add_library(planning_context_loader_circ + src/planning_context_loader_circ.cpp + src/planning_context_loader.cpp + src/trajectory_functions.cpp + src/trajectory_generator.cpp + src/trajectory_generator_circ.cpp + src/path_circle_generator.cpp + ) +target_link_libraries(planning_context_loader_circ + ${catkin_LIBRARIES}) + +add_library(command_list_manager + src/command_list_manager.cpp + src/plan_components_builder.cpp) +target_link_libraries(command_list_manager + ${catkin_LIBRARIES}) +add_dependencies(command_list_manager + ${catkin_EXPORTED_TARGETS}) + +add_library(sequence_capability + src/move_group_sequence_action.cpp + src/move_group_sequence_service.cpp + src/plan_components_builder.cpp + src/command_list_manager.cpp + src/trajectory_blender_transition_window.cpp + src/joint_limits_aggregator.cpp # do we need joint limits and cartesian_limit here? + src/joint_limits_container.cpp + src/limits_container.cpp + src/cartesian_limit.cpp + src/cartesian_limits_aggregator.cpp + ) +target_link_libraries(sequence_capability + ${catkin_LIBRARIES}) +add_dependencies(sequence_capability + ${catkin_EXPORTED_TARGETS}) + +############# +## Install ## +############# +install(FILES + plugins/sequence_capability_plugin_description.xml + plugins/${PROJECT_NAME}_plugin_description.xml + plugins/planning_context_plugin_description.xml + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/plugins + ) + +## Mark libraries for installation +install(TARGETS + ${PROJECT_NAME} + planning_context_loader_ptp + planning_context_loader_lin + planning_context_loader_circ + command_list_manager + sequence_capability + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +) + +############# +## Testing ## +############# +if(CATKIN_ENABLE_TESTING) + find_package(rostest REQUIRED) + find_package(${PROJECT_NAME}_testutils REQUIRED) + + include_directories( + ${${PROJECT_NAME}_testutils_INCLUDE_DIRS} + ) + + if(ENABLE_COVERAGE_TESTING) + include(CodeCoverage) + APPEND_COVERAGE_COMPILER_FLAGS() + endif() + + ######################### + ####Integration Tests#### + ######################### + set(${PROJECT_NAME}_INTEGRATIONTEST_LIBRARIES + sequence_capability + ${PROJECT_NAME} + planning_context_loader_ptp + planning_context_loader_lin + planning_context_loader_circ + ) + + # Planning Integration tests + add_rostest_gmock(integrationtest_sequence_action_preemption + test/integrationtest_sequence_action_preemption.test + test/integrationtest_sequence_action_preemption.cpp + ) + target_link_libraries(integrationtest_sequence_action_preemption + ${catkin_LIBRARIES} + ${${PROJECT_NAME}_testutils_LIBRARIES} + ${${PROJECT_NAME}_INTEGRATIONTEST_LIBRARIES} + ) + + add_rostest_gmock(integrationtest_sequence_action + test/integrationtest_sequence_action.test + test/integrationtest_sequence_action.cpp + ) + target_link_libraries(integrationtest_sequence_action + ${catkin_LIBRARIES} + ${${PROJECT_NAME}_testutils_LIBRARIES} + ${${PROJECT_NAME}_INTEGRATIONTEST_LIBRARIES} + ) + + add_rostest(test/integrationtest_sequence_action_capability_with_gripper.test + DEPENDENCIES integrationtest_sequence_action + ) + + add_rostest(test/integrationtest_sequence_action_capability_frankaemika_panda.test + DEPENDENCIES integrationtest_sequence_action + ) + + add_rostest_gtest(integrationtest_sequence_service_capability + test/integrationtest_sequence_service_capability.test + test/integrationtest_sequence_service_capability.cpp + ) + target_link_libraries(integrationtest_sequence_service_capability + ${catkin_LIBRARIES} + ${${PROJECT_NAME}_testutils_LIBRARIES} + ${${PROJECT_NAME}_INTEGRATIONTEST_LIBRARIES} + ) + + add_rostest(test/integrationtest_sequence_service_capability_frankaemika_panda.test + DEPENDENCIES integrationtest_sequence_service_capability ) + + add_rostest(test/integrationtest_sequence_service_capability_with_gripper.test + DEPENDENCIES integrationtest_sequence_service_capability + ) + + # Planning Integration tests + add_rostest_gtest(integrationtest_command_planning + test/integrationtest_command_planning.test + test/integrationtest_command_planning.cpp + test/test_utils.cpp + ) + target_link_libraries(integrationtest_command_planning + ${catkin_LIBRARIES} + ${${PROJECT_NAME}_testutils_LIBRARIES} + ${${PROJECT_NAME}_INTEGRATIONTEST_LIBRARIES} + ) + + add_rostest(test/integrationtest_command_planning_with_gripper.test + DEPENDENCIES integrationtest_command_planning + ) + + add_rostest(test/integrationtest_command_planning_frankaemika_panda.test + DEPENDENCIES integrationtest_command_planning ) + + # Blending Integration tests + add_rostest_gtest(integrationtest_command_list_manager + test/integrationtest_command_list_manager.test + test/integrationtest_command_list_manager.cpp + test/test_utils.cpp + ) + target_link_libraries(integrationtest_command_list_manager + ${catkin_LIBRARIES} + ${${PROJECT_NAME}_testutils_LIBRARIES} + ${${PROJECT_NAME}_INTEGRATIONTEST_LIBRARIES} + ) + + add_rostest_gtest(integrationtest_get_solver_tip_frame + test/integrationtest_get_solver_tip_frame.test + test/integrationtest_get_solver_tip_frame.cpp + ) + target_link_libraries(integrationtest_get_solver_tip_frame + ${catkin_LIBRARIES} + ${${PROJECT_NAME}_INTEGRATIONTEST_LIBRARIES} + ) + + add_rostest_gtest(integrationtest_plan_components_builder + test/integrationtest_plan_components_builder.test + test/integrationtest_plan_components_builder.cpp + ) + target_link_libraries(integrationtest_plan_components_builder + ${catkin_LIBRARIES} + ${${PROJECT_NAME}_INTEGRATIONTEST_LIBRARIES} + ) + + ################## + ####Unit Tests#### + ################## + add_library(${PROJECT_NAME}_testhelpers + test/test_utils.cpp + src/trajectory_generator.cpp + src/trajectory_generator_circ.cpp + src/trajectory_generator_lin.cpp + src/trajectory_generator_ptp.cpp + src/path_circle_generator.cpp + src/velocity_profile_atrap.cpp + ) + + target_link_libraries(${PROJECT_NAME}_testhelpers ${PROJECT_NAME}_lib) + + ## Add gtest based cpp test target and link libraries + catkin_add_gtest(unittest_${PROJECT_NAME}_direct + test/unittest_${PROJECT_NAME}_direct.cpp + src/planning_context_loader_ptp.cpp + ) + target_link_libraries(unittest_${PROJECT_NAME}_direct + ${catkin_LIBRARIES} + ${PROJECT_NAME}_testhelpers + ) + + ## Add gtest based cpp test target and link libraries + catkin_add_gtest(unittest_velocity_profile_atrap + test/unittest_velocity_profile_atrap.cpp + src/velocity_profile_atrap.cpp + ) + target_link_libraries(unittest_velocity_profile_atrap + ${catkin_LIBRARIES} + ) + + catkin_add_gtest(unittest_trajectory_generator + test/unittest_trajectory_generator.cpp + src/trajectory_generator.cpp + ) + target_link_libraries(unittest_trajectory_generator + ${catkin_LIBRARIES} + ${${PROJECT_NAME}_testutils_LIBRARIES} + ${PROJECT_NAME}_lib + ) + + # Trajectory Generator Unit Test + add_rostest_gtest(unittest_trajectory_functions + test/unittest_trajectory_functions.test + test/unittest_trajectory_functions.cpp + ) + target_link_libraries(unittest_trajectory_functions + ${catkin_LIBRARIES} + ${PROJECT_NAME}_testhelpers + ) + + # unittest for trajectory blender transition window + add_rostest_gtest(unittest_trajectory_blender_transition_window + test/unittest_trajectory_blender_transition_window.test + test/unittest_trajectory_blender_transition_window.cpp + src/trajectory_blender_transition_window.cpp + ) + target_link_libraries(unittest_trajectory_blender_transition_window + ${catkin_LIBRARIES} + ${${PROJECT_NAME}_testutils_LIBRARIES} + ${PROJECT_NAME}_testhelpers + ) + + # trajectory generator Unit Test + add_rostest_gtest(unittest_trajectory_generator_common + test/unittest_trajectory_generator_common.test + test/unittest_trajectory_generator_common.cpp + ) + target_link_libraries(unittest_trajectory_generator_common + ${catkin_LIBRARIES} + ${PROJECT_NAME}_testhelpers + ) + + # trajectory generator circ Unit Test + add_rostest_gtest(unittest_trajectory_generator_circ + test/unittest_trajectory_generator_circ.test + test/unittest_trajectory_generator_circ.cpp + ) + target_link_libraries(unittest_trajectory_generator_circ + ${catkin_LIBRARIES} + ${${PROJECT_NAME}_testutils_LIBRARIES} + ${PROJECT_NAME}_testhelpers + ) + + # trajectory generator lin Unit Test + add_rostest_gtest(unittest_trajectory_generator_lin + test/unittest_trajectory_generator_lin.test + test/unittest_trajectory_generator_lin.cpp + ) + target_link_libraries(unittest_trajectory_generator_lin + ${catkin_LIBRARIES} + ${${PROJECT_NAME}_testutils_LIBRARIES} + ${PROJECT_NAME}_testhelpers + ) + + # trajectory generator ptp Unit Test + add_rostest_gtest(unittest_trajectory_generator_ptp + test/unittest_trajectory_generator_ptp.test + test/unittest_trajectory_generator_ptp.cpp + ) + target_link_libraries(unittest_trajectory_generator_ptp + ${catkin_LIBRARIES} + ${PROJECT_NAME}_testhelpers + ) + + # Command Planner Unit Test + add_rostest_gtest(unittest_${PROJECT_NAME} + test/unittest_${PROJECT_NAME}.test + test/unittest_${PROJECT_NAME}.cpp + ) + target_link_libraries(unittest_${PROJECT_NAME} + ${catkin_LIBRARIES} + ${PROJECT_NAME}_lib + ) + + # JointLimits Unit Test + add_rostest_gtest(unittest_joint_limit + test/unittest_joint_limit.test + test/unittest_joint_limit.cpp + ) + target_link_libraries(unittest_joint_limit + ${catkin_LIBRARIES} + ${PROJECT_NAME}_lib + ) + + # JointLimitsAggregator Unit Test + add_rostest_gtest(unittest_joint_limits_aggregator + test/unittest_joint_limits_aggregator.test + test/unittest_joint_limits_aggregator.cpp + ) + target_link_libraries(unittest_joint_limits_aggregator + ${catkin_LIBRARIES} + ${PROJECT_NAME}_lib + ) + + # JointLimitsContainer Unit Test + catkin_add_gtest(unittest_joint_limits_container + test/unittest_joint_limits_container.cpp + ) + target_link_libraries(unittest_joint_limits_container + ${catkin_LIBRARIES} + ${PROJECT_NAME}_lib + ) + + # JointLimitsValidator Unit Test + catkin_add_gtest(unittest_joint_limits_validator + test/unittest_joint_limits_validator.cpp + ) + target_link_libraries(unittest_joint_limits_validator + ${catkin_LIBRARIES} + ${PROJECT_NAME}_lib + ) + + # Cartesian Limits Aggregator Unit Test + add_rostest_gtest(unittest_cartesian_limits_aggregator + test/unittest_cartesian_limits_aggregator.test + test/unittest_cartesian_limits_aggregator.cpp + ) + target_link_libraries(unittest_cartesian_limits_aggregator + ${catkin_LIBRARIES} + ${PROJECT_NAME}_lib + ) + + # PlanningContextLoaderPTP Unit Test + add_rostest_gtest(unittest_planning_context_loaders + test/unittest_planning_context_loaders.test + test/unittest_planning_context_loaders.cpp + ) + target_link_libraries(unittest_planning_context_loaders + ${catkin_LIBRARIES} + ${PROJECT_NAME}_testhelpers + ) + + # PlanningContext Unit Test (Typed test) + add_rostest_gtest(unittest_planning_context + test/unittest_planning_context.test + test/unittest_planning_context.cpp + src/planning_context_loader_circ.cpp + src/planning_context_loader_lin.cpp + src/planning_context_loader_ptp.cpp + ) + target_link_libraries(unittest_planning_context + ${catkin_LIBRARIES} + ${PROJECT_NAME}_testhelpers + ) + + # GetTipFrames Unit Test + catkin_add_gmock(unittest_get_solver_tip_frame + test/unittest_get_solver_tip_frame.cpp + ) + target_link_libraries(unittest_get_solver_tip_frame + ${catkin_LIBRARIES} + ) + + # to run: catkin_make -DCMAKE_BUILD_TYPE=Debug -DENABLE_COVERAGE_TESTING=ON package_name_coverage + if(ENABLE_COVERAGE_TESTING) + set(COVERAGE_EXCLUDES "*/${PROJECT_NAME}/test*") + add_code_coverage( + NAME ${PROJECT_NAME}_coverage + # specifying dependencies in a reliable way is on open issue + # see https://github.com/mikeferguson/code_coverage/pull/14 + #DEPENDENCIES tests + ) + endif() +endif() diff --git a/moveit_planners/pilz_industrial_motion_planner/README.md b/moveit_planners/pilz_industrial_motion_planner/README.md new file mode 100644 index 0000000000..632224f5ec --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/README.md @@ -0,0 +1,4 @@ +Please consult tutorials and the official [documentation](https://moveit.ros.org/documentation/concepts/). + +For details about the blend algorithm please refer to +![doc/MotionBlendAlgorithmDescription.pdf](doc/MotionBlendAlgorithmDescription.pdf). diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/.gitignore b/moveit_planners/pilz_industrial_motion_planner/doc/.gitignore new file mode 100644 index 0000000000..2edfaf4621 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/doc/.gitignore @@ -0,0 +1,12 @@ +*.aux +*.bbl +*.blg +*.dvi +*.log +*.ps +*.tps +*.fdb_latexmk +*.fls +*.out +*.synctex.gz +*.pdf \ No newline at end of file diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/MotionBlendAlgorithmDescription.pdf b/moveit_planners/pilz_industrial_motion_planner/doc/MotionBlendAlgorithmDescription.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7a3f127e884496614820c3f9e8098850d918137f GIT binary patch literal 534094 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

5o-*aZU|#`fi~(L;+=914$E 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 z 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 literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/MotionBlendAlgorithmDescription.tex b/moveit_planners/pilz_industrial_motion_planner/doc/MotionBlendAlgorithmDescription.tex new file mode 100644 index 0000000000..a040465426 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/doc/MotionBlendAlgorithmDescription.tex @@ -0,0 +1,114 @@ +\documentclass{article} +%-------------------------------------------------------- +\usepackage{hyperref} +\usepackage{caption} +\usepackage{subcaption} + +\usepackage{graphicx} + + +\usepackage[left=2.9cm, right=2.9cm, top=3cm, bottom=2cm]{geometry} + +\usepackage{fancyhdr} +\pagestyle{fancy} +\fancyhf{} +\rhead{31.01.2019} +\lhead{Pilz GmbH \& Co. KG} +\cfoot{\thepage} +\renewcommand{\headrulewidth}{0pt} +\renewcommand{\footrulewidth}{0pt} + +\begin{document} +\title{Motion Blending} +\author{Pilz GmbH \& Co. KG} +\date{31.01.2019} + +\maketitle + +\begin{abstract} +\noindent This article describes the techniques used to blend the position and orientation of two robot trajectories within the {\tt pilz\_industrial\_motion\_planner}\cite{pilztrajectorygeneration} ROS package. +\end{abstract} + + +\newpage + +\section{Position blending} + +\subsection{Introduction} + +Suppose we have two trajectories $x_1(t)$, $t\in[0,T_1]$ and $x_2(t)$, $t\in[0,T_2]$ and we want to make a transition from $x_1(t)$ to $x_2(t)$. The transition window technique assumes that the transition happens in a predefined time window. During this transition window, the resulted trajectory (blending trajectory) is given by: +\begin{equation} + x_b(t) = x_1(t) + \alpha(s(t))(x_2(t)-x_1(t)), t \in [t_0, t_0 + T] +\end{equation} +in which $x_b(t)$ is the transition trajectory. $t_0$ is the start time of transition window and $T$ represents the transition time. $\alpha(s)$ is the blend function and $s$ is normalized time parameter: +\begin{equation} +s = \frac{t - t_0}{T} +\label{eq:1} +\end{equation} +which changes from 0 to 1 during the transition window. Following polynomial is selected as $\alpha(s)$ so that the boundary conditions at the start and end point of the transition window are fulfilled \cite{lloyd1993trajectory}: +\begin{equation} +\alpha(s) = 6s^5 - 15s^4 + 10s^3. +\label{eq:2} +\end{equation} + +\subsection{Application for blending robot trajectory} +We want to move the robot from $p_1$ to $p_2$, then from $p_2$ to $p_3$. $p_2$ is a blending way-point which means that it does not need to be reached exactly. We want the robot moves alongside $p_2$ without stop. The whole process is described below with an one dimensional example. + +\begin{enumerate} + \item Generate motion trajectories $x_1(t)$ from $p_1$ to $p_2$ and $x_2(t)$ from $p_2$ to $p_3$. $x_1(t)$ and $x_2(t)$ both start and stop with zero velocity/acceleration. Both trajectories start with time zero. As a simple example we generated two one-dimensional linear trajectories in Figure.\ref{ori_traj}. For robot motion without blending, the two trajectories are executed one after the other, which means $x_2(t)$ needs to be timely shifted by the duration of $x_1(t)$. + \begin{figure}[ht]% + \includegraphics[width=0.9\columnwidth]{figure/original_trajectories.eps}% + \caption{One-dimensional linear trajectory}% + \label{ori_traj} + \end{figure} + + \item According to the blending radius $r$, the points $p_{b1}$ on $x_1(t)$ and $p_{b2}$ on $x_2(t)$ which intersects with the blending sphere are computed. We also compute the durations $d_1$ for moving from $p_{b1}$ to $p_2$ on $x_1$ and $d_2$ for moving from $p_2$ to $p_{b2}$ on $x_2$. The transition window should start earliest from the time of $p_{b1}$ on $x_1(t)$ is reached, and ends latest at the time of $p_{b2}$ on $x_2(t)$ is reached. In the example, we take $r=3$ and $p_{b1} = p_{b2} = 5$ (see Figure.\ref{ori_traj}). + + \item Timely shift the $x_2(t)$ and select the transition window time $T$ according to the above rules. In order to avoid stop on the blending trajectory, the time shift $T_s$ of $x_2(t)$ should be smaller than the duration of $x_1(t)$. We now have the second trajectory as $x_2(t-T_s)$ for blending. In the example the duration of $x_1(t)$ is $6s$. Figure.\ref{blend_case_1} shows a blending case that we shift the $x_2(t)$ with $6s$, which is almost the same as motion without blending. Figure.\ref{blend_case_2} shows a blending case that we shift the $x_2(t)$ with $3.5s$ and the blending starts at 3.5s, ends at 5.5s. Figure.\ref{blend_case_3} shows a blending case that we shift the $x_2(t)$ with $4.5s$ and the blending starts at 3.5s, ends at 6.5s. +\end{enumerate} + +In the actual implementation, we make the following choice given the durations $d_1$ and $d_2$ inside the blending sphere: +\begin{itemize} +\item If $d_1\leq d_2$ we shift exactly to the time when $p_{b1}$ is reached on $x_1$ (when the blending sphere is entered), +\item if $d_1>d_2$ we compute $T_s$ such that $T_s+d_2=T_1$. This choice minimizes increases in acceleration/deceleration on the resulting blend trajectory. +\end{itemize} + + +\section{Blending the orientation} +To blend the orientation, the method described in \cite{dantam2014orientation} is used. The equations (18)-(20) in \cite{dantam2014orientation} are used to calculate the orientation along the blend trajectory. In our application, due to the fact that the orientation change along the original (not blended) trajectories has smooth acceleration and deceleration phases, (18) and (19) from paper \cite{dantam2014orientation} do not need to be calculated.\newline +For the sake of clarity, it is important to note that our functions for $u_{ij}(t)$ and $u_{jk}(t)$ are different. However, we account for this difference by not explicitly calculating (18) and (19) and using the given samples of the original (not blended) trajectories instead. Furthermore, (\ref{eq:2}) is used for $u_{j}(t)$, in other words, $u_{j}(t) = \alpha(s(t))$. + + +\begin{figure}[ht] + \vspace*{-5mm} + \centering + \begin{subfigure}[ht]{0.8\textwidth}% + \centering + \includegraphics[width=0.8\columnwidth]{figure/blend_case_1.eps}% + \caption{Motion blend case 1: $T_s = 6s$, blending starts at 3.5s, ends at 8s. The resulted blending trajectory comes to a stop in the middle.}% + \label{blend_case_1}% + \end{subfigure} + + \begin{subfigure}[ht]{0.8\textwidth}% + \centering + \includegraphics[width=0.8\columnwidth]{figure/blend_case_2.eps}% + \caption{Motion blend case 2: $T_s = 3.5s$, blending starts at 3.5s, ends at 5.5s. The resulted blending trajectory smoothly transits from first trajectory to the second trajectory. The velocity profile has no jumps.}% + \label{blend_case_2}% + \end{subfigure} + + \begin{subfigure}[ht]{0.8\textwidth}% + \centering + \includegraphics[width=0.8\columnwidth]{figure/blend_case_3.eps}% + \caption{Motion blend case 3: $T_s = 4.5s$, blending starts at 3.5s, ends at 6.5s. The resulted blending trajectory smoothly transits from first trajectory to the second trajectory. The velocity profile has no jumps.}% + \label{blend_case_3}% + \end{subfigure} + +\end{figure} + + +\begin{thebibliography}{9} +\bibitem {lloyd1993trajectory}Lloyd, John and Hayward, Vincent \textit{Trajectory generation for sensor-driven and time-varying tasks}, The International journal of robotics research, 1993 +\bibitem {dantam2014orientation}Dantam, Neil and Stilman, Mike \textit{Spherical Parabolic Blends for Robot Workspace Trajectories}, International Conference on Intelligent Robots and Systems (IROS), 2014 +\bibitem{pilztrajectorygeneration}\url{https://github.com/ros-planning/moveit/tree/master/moveit_planners/pilz_industrial_motion_planner} +\end{thebibliography} +\end{document} diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/README.md b/moveit_planners/pilz_industrial_motion_planner/doc/README.md new file mode 100644 index 0000000000..65966e8415 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/doc/README.md @@ -0,0 +1,22 @@ +# Trajectory generation + +## Overview sequence processing +The following diagram shows the steps to process and execute +a list of commands given as sequence. The diagram also shows the resulting data +structures of each processing step. +![OverviewProcessing](sequence_processing_overview.png) + +## Overview classes PlanningContext +The following diagram shows the different classes responsible for the loading +of the different planning contexts (e.g. Ptp, Lin, Circ) and the +relationship between them. +![DiagClassPlanningContext](diag_class_planning_context.png) + +## Relationship MoveGroupCapabilities and ComandListManager +The following diagram shows the relationship between the MoveGroupCapabilities +and the CommandListManager. +![DiagClassCapabilities](diag_class_capabilities.png) + +## Blending algorithm description +A description of the used blending algorithm can be found +[here](MotionBlendAlgorithmDescription.pdf). diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/diag_class_capabilities.png b/moveit_planners/pilz_industrial_motion_planner/doc/diag_class_capabilities.png new file mode 100644 index 0000000000000000000000000000000000000000..eeb13715b7c475621885cac19501c728f9aa8fc3 GIT binary patch literal 41398 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 literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/diag_class_capabilities.uxf b/moveit_planners/pilz_industrial_motion_planner/doc/diag_class_capabilities.uxf new file mode 100644 index 0000000000..6922b787e5 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/doc/diag_class_capabilities.uxf @@ -0,0 +1,413 @@ + + // Uncomment the following line to change the fontsize and font: +fontsize=10 +// fontfamily=SansSerif //possible: SansSerif,Serif,Monospaced + + +////////////////////////////////////////////////////////////////////////////////////////////// +// Welcome to UMLet! +// +// Double-click on elements to add them to the diagram, or to copy them +// Edit elements by modifying the text in this panel +// Hold Ctrl to select multiple elements +// Use Ctrl+mouse to select via lasso +// +// Use +/- or Ctrl+mouse wheel to zoom +// Drag a whole relation at its central square icon +// +// Press Ctrl+C to copy the whole diagram to the system clipboard (then just paste it to, eg, Word) +// Edit the files in the "palettes" directory to create your own element palettes +// +// Select "Custom Elements > New..." to create new element types +////////////////////////////////////////////////////////////////////////////////////////////// + + +// This text will be stored with each diagram; use it for notes. + 7 + + UMLClass + + 819 + 308 + 147 + 56 + + MoveGroupCapability +-- + + + + + UMLClass + + 917 + 420 + 168 + 63 + + MoveGroupSequenceAction +-- + + + + + + UMLClass + + 742 + 420 + 140 + 63 + + MoveGroupSequenceService +-- + + + + + + Relation + + 833 + 357 + 21 + 77 + + lt=<<- + 10.0;10.0;10.0;90.0 + + + Relation + + 938 + 357 + 21 + 77 + + lt=<<- + 10.0;10.0;10.0;90.0 + + + UMLNote + + 980 + 308 + 98 + 21 + + Plugin interface + + + + Relation + + 959 + 308 + 35 + 21 + + lt=.. + 30.0;10.0;10.0;10.0 + + + UMLClass + + 763 + 532 + 168 + 63 + + CommandListManager +-- + + + + + + + UMLClass + + 1155 + 525 + 126 + 35 + + plan_execution::PlanExecution +-- ++planAndExecute() + + + + Relation + + 1204 + 469 + 21 + 70 + + lt=<<<<- + 10.0;10.0;10.0;80.0 + + + UMLClass + + 1155 + 427 + 112 + 49 + + MoveGroupContext +-- ++ plan_execution_ + + + + + Relation + + 1078 + 448 + 91 + 21 + + lt=<<<<- + 10.0;10.0;110.0;10.0 + + + UMLClass + + 749 + 644 + 182 + 63 + + TrajectoryBlenderTransitionWindow +-- + + + + + Relation + + 924 + 476 + 21 + 70 + + lt=<<<<- + 10.0;10.0;10.0;80.0 + + + Relation + + 784 + 476 + 21 + 70 + + lt=<<<<- + 10.0;10.0;10.0;80.0 + + + UMLState + + 329 + 553 + 203 + 70 + + /planning_interface::PlannerManager/ +CommandPlanner + + + + Relation + + 392 + 616 + 21 + 63 + + lt=<- + 10.0;70.0;10.0;10.0 + + + Relation + + 434 + 616 + 21 + 63 + + lt=<- + 10.0;10.0;10.0;70.0 + + + UMLState + + 168 + 665 + 126 + 49 + + Plugin +PTP TrajectoryGenerator + + + + + UMLState + + 546 + 665 + 133 + 49 + + Plugin +CIRC TrajectoryGenerator + + + + + UMLState + + 364 + 665 + 126 + 49 + + Plugin +LIN TrajectoryGenerator + + + + + Relation + + 210 + 574 + 133 + 105 + + lt=<- + 10.0;130.0;10.0;10.0;170.0;10.0 + + + Relation + + 224 + 588 + 119 + 91 + + lt=<- + 150.0;10.0;10.0;10.0;10.0;110.0 + + + Relation + + 525 + 588 + 126 + 91 + + lt=<- + 160.0;110.0;160.0;10.0;10.0;10.0 + + + UMLGeneric + + 161 + 539 + 532 + 182 + + MoveIt Planning Pipeline +halign=left +fg=blue + + + + Text + + 252 + 637 + 203 + 21 + + planning_interface::MotionPlanRequest + + + + Text + + 441 + 637 + 210 + 21 + + planning_pipeline::MotionPlanResponse + + + + Relation + + 525 + 574 + 140 + 105 + + lt=<- + 10.0;10.0;180.0;10.0;180.0;130.0 + + + Relation + + 686 + 546 + 91 + 28 + + lt=<- +<<uses>> + 10.0;20.0;110.0;20.0 + + + Relation + + 826 + 588 + 42 + 70 + + lt=<- +<<uses>> + 10.0;80.0;10.0;10.0 + + + UMLClass + + 147 + 287 + 959 + 448 + + Motion planning +layer=-1000 +halign=left + + + + UMLClass + + 1127 + 287 + 168 + 448 + + Motion execution +layer=-1000 +halign=left + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/diag_class_planning_context.png b/moveit_planners/pilz_industrial_motion_planner/doc/diag_class_planning_context.png new file mode 100644 index 0000000000000000000000000000000000000000..724cdf19115eaad006e7ebfa97dcbfb3afbfb950 GIT binary patch literal 133824 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

?>}Y?Dips^-A-~MLDeT|XgWUk% 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%0DRMLLZ{|$MEi9Pk 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 + 7 + + UMLClass + + 287 + 273 + 567 + 133 + + PlanningContextLoader +-- +... +-- ++getAlgorithm(): std::string ++setModel(model: moveit::core::RobotModelConstPtr&): bool ++setLimits(joint_limits: pilz_industrial_motion_planner::JointLimitsContainer&): bool ++loadContext(planning_context: planning_interface::PlanningContextPtr&, name: std::string&, group: std::string&): bool +#loadContext<T>(planning_context: planning_interface::PlanningContextPtr&, name: std::string&, group: std::string&): bool +-- + + + + UMLGeneric + + 0 + 525 + 259 + 70 + + symbol=component +PlanningContextLoaderPTP +-- +-- ++loadContext(planning_context, name, group) +-- + + + + UMLGeneric + + 448 + 525 + 259 + 70 + + symbol=component +PlanningContextLoaderLIN +-- +-- ++loadContext(planning_context, name, group) +-- + + + + Relation + + 119 + 350 + 182 + 189 + + lt=<<- + 240.0;10.0;10.0;10.0;10.0;250.0 + + + Relation + + 567 + 399 + 21 + 140 + + lt=<<- + 10.0;10.0;10.0;180.0 + + + UMLGeneric + + 35 + 756 + 133 + 35 + + PlanningContextPTP +-- +-- + + + + UMLGeneric + + 511 + 749 + 126 + 35 + + PlanningContextLIN +-- +-- + + + + UMLClass + + 1260 + 616 + 119 + 126 + + template=T +PlanningContextBase +-- +-- + + + + Text + + 21 + 609 + 175 + 14 + + <<bind>><T->TrajectoryGeneratorPTP> + + + + Relation + + 133 + 644 + 1141 + 126 + + lt=<<- + 1610.0;10.0;10.0;10.0;10.0;160.0 + + + Relation + + 602 + 672 + 672 + 91 + + lt=<<- + 940.0;10.0;10.0;10.0;10.0;110.0 + + + Text + + 490 + 609 + 175 + 14 + + <<bind>><T->TrajectoryGeneratorLIN> + + + + UMLGeneric + + 511 + 1001 + 126 + 35 + + TrajectoryGeneratorLIN +-- +-- + + + + Relation + + 98 + 588 + 21 + 182 + + lt=<.. + 10.0;240.0;10.0;10.0 + + + UMLGeneric + + 35 + 1001 + 126 + 35 + + TrajectoryGeneratorPTP +-- +-- + + + + UMLGeneric + + 1176 + 861 + 308 + 98 + + TrajectoryGenerator +-- +-- +TrajectoryGenerator(RobotModelConstPtr, LimitsContainer) +generate(request, response, sampling_time) + + + + + Relation + + 567 + 588 + 21 + 175 + + lt=<.. + 10.0;230.0;10.0;10.0 + + + Relation + + 567 + 777 + 21 + 238 + + lt=<<<<- +m1=1 + 10.0;10.0;10.0;320.0 + + + Relation + + 98 + 784 + 21 + 231 + + lt=<<<<- +m1=1 + 10.0;10.0;10.0;310.0 + + + Relation + + 602 + 903 + 588 + 112 + + lt=<<- + 820.0;10.0;10.0;10.0;10.0;140.0 + + + Relation + + 126 + 875 + 1064 + 140 + + lt=<<- + 1500.0;10.0;10.0;10.0;10.0;180.0 + + + UMLNote + + 0 + 441 + 98 + 49 + + Plugin + + + + + Relation + + 42 + 483 + 21 + 56 + + lt=.. + 10.0;10.0;10.0;60.0 + + + UMLClass + + 1589 + 525 + 147 + 112 + + JointLimitsContainer +-- +-- +-- + + + + + UMLClass + + 1792 + 525 + 147 + 112 + + CartesianLimit +-- ++max_trans_vel_: double ++max_trans_acc_: double ++max_trans_dec_: double ++max_rot_vel_: double ++max_rot_acc_: double ++max_rot_dec_: double +-- +-- + + + + + UMLClass + + 1673 + 399 + 196 + 91 + + LimitsContainer +-- +-- ++hasCartesianLimit(): bool ++getCartesianLimit(): pilz_industrial_motion_planner::CartesianLimit ++hasJointLimits(): bool ++getJointLimits(): pilz_industrial_motion_planner::JointLimitsContainer +-- + + + + + Relation + + 1764 + 483 + 126 + 56 + + lt=<<<<- +m1=1 + 10.0;10.0;160.0;60.0 + + + Relation + + 1659 + 483 + 70 + 56 + + lt=<<<<- +m1=1 + 80.0;10.0;10.0;60.0 + + + UMLClass + + 168 + 1232 + 126 + 42 + + /KDL::VelocityProfile/ +-- +-- +-- + + + + + UMLClass + + 28 + 1302 + 147 + 63 + + VelocityProfileATrap +-- ++ SetProfile ++ SetProfileDuration ++ SetProfileAllDurations +-- +-- + + + + + + Relation + + 126 + 1246 + 56 + 70 + + lt=<<- + 60.0;10.0;10.0;10.0;10.0;80.0 + + + Relation + + 91 + 1029 + 21 + 287 + + lt=<<<<- +m1=n + 10.0;10.0;10.0;390.0 + + + UMLClass + + 525 + 1316 + 91 + 42 + + Package::KDL +Path_Line +-- +-- + + + + + UMLClass + + 833 + 1316 + 84 + 42 + + Package::KDL +Path_Circle +-- +-- + + + + + UMLClass + + 980 + 1316 + 105 + 42 + + Package::KDL +Path_Circle_Wrapper +-- +-- + + + + + UMLNote + + 1393 + 1176 + 98 + 49 + + Class to manage the Cartesian path +bg=white + + + + Relation + + 1330 + 1190 + 77 + 21 + + lt=.. + 10.0;10.0;90.0;10.0 + + + Relation + + 560 + 1029 + 21 + 301 + + lt=<<<<- + 10.0;10.0;10.0;410.0 + + + UMLGeneric + + 882 + 1001 + 168 + 35 + + TrajectoryGeneratorCIRC +-- +-- + + + + Relation + + 1022 + 1029 + 21 + 301 + + lt=<<<<- + 10.0;10.0;10.0;410.0 + + + Relation + + 581 + 1197 + 693 + 133 + + lt=<<- + 970.0;10.0;10.0;10.0;10.0;170.0 + + + Relation + + 889 + 1232 + 385 + 98 + + lt=<<- + 530.0;10.0;10.0;10.0;10.0;120.0 + + + Relation + + 1050 + 1267 + 224 + 63 + + lt=<<- + 300.0;10.0;10.0;10.0;10.0;70.0 + + + UMLGeneric + + 896 + 742 + 126 + 35 + + PlanningContextCIRC +-- +-- + + + + Relation + + 952 + 770 + 21 + 245 + + lt=<<<<- +m1=1 + 10.0;10.0;10.0;330.0 + + + Relation + + 987 + 700 + 287 + 56 + + lt=<<- + 390.0;10.0;10.0;10.0;10.0;60.0 + + + UMLGeneric + + 826 + 525 + 259 + 70 + + symbol=component +PlanningContextLoaderCIRC +-- +-- ++loadContext(planning_context, name, group) +-- + + + + Relation + + 952 + 588 + 21 + 168 + + lt=<.. + 10.0;220.0;10.0;10.0 + + + Text + + 875 + 609 + 175 + 14 + + <<bind>><T->TrajectoryGeneratorLIN> + + + + Relation + + 987 + 931 + 203 + 84 + + lt=<<- + 270.0;10.0;10.0;10.0;10.0;100.0 + + + Relation + + 847 + 350 + 119 + 189 + + lt=<<- + 10.0;10.0;150.0;10.0;150.0;250.0 + + + Relation + + 91 + 469 + 434 + 70 + + lt=.. + 10.0;10.0;600.0;10.0;600.0;80.0 + + + Relation + + 91 + 448 + 812 + 91 + + lt=.. + 10.0;10.0;1140.0;10.0;1140.0;110.0 + + + UMLClass + + 287 + 126 + 567 + 63 + + CommandPlanner +-- +-- ++getPlanningContext(const planning_scene::PlanningSceneConstPtr& planning_scene, +const planning_interface::MotionPlanRequest& req, +moveit_msgs::MoveItErrorCodes& error_code):planning_interface::PlanningContextPtr +-- + + + + + Relation + + 567 + 182 + 21 + 105 + + lt=<<<<- +m1=n + 10.0;10.0;10.0;130.0 + + + UMLClass + + 476 + 0 + 203 + 49 + + PlanningInterface::PlannerManager +-- +-- + +-- + + + + Relation + + 567 + 42 + 21 + 98 + + lt=<<- + 10.0;10.0;10.0;120.0 + + + UMLClass + + 1211 + 518 + 203 + 49 + + PlanningInterface::PlanningContext +-- +-- + +-- + + + + Relation + + 1309 + 560 + 21 + 77 + + lt=<<- + 10.0;10.0;10.0;90.0 + + + Relation + + 910 + 1330 + 84 + 21 + + lt=<<<<- + 100.0;10.0;10.0;10.0 + + + UMLClass + + 308 + 1302 + 147 + 63 + + Package::KDL +VelocityProfile_Trap +-- ++ SetProfile ++ SetProfileDuration +-- +-- + + + + + + Relation + + 420 + 1008 + 476 + 308 + + lt=<<<<- + 660.0;10.0;410.0;10.0;410.0;140.0;10.0;140.0;10.0;420.0 + + + UMLClass + + 770 + 1141 + 126 + 42 + + Package::KDL +Trajectory_Segment +-- +-- + + + + + Relation + + 889 + 1029 + 63 + 147 + + lt=<<<<- + 70.0;10.0;70.0;190.0;10.0;190.0 + + + Relation + + 287 + 1246 + 63 + 70 + + lt=<<- + 10.0;10.0;70.0;10.0;70.0;80.0 + + + UMLClass + + 784 + 1064 + 98 + 35 + + /KDL::Trajectory/ +-- +-- +-- + + + + + Relation + + 826 + 1092 + 21 + 63 + + lt=<<- + 10.0;10.0;10.0;70.0 + + + UMLClass + + 1260 + 1183 + 77 + 112 + + /KDL::Path/ +-- +-- + + + + + Relation + + 588 + 1029 + 196 + 147 + + lt=<<<<- + 10.0;10.0;10.0;190.0;260.0;190.0 + + + Relation + + 357 + 1008 + 168 + 308 + + lt=<<<<- + 220.0;10.0;10.0;10.0;10.0;420.0 + + diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_case_1.eps b/moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_case_1.eps new file mode 100644 index 0000000000..91d0feecd9 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_case_1.eps @@ -0,0 +1,1648 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: (MATLAB, The Mathworks, Inc. Version 9.2.0.556344 \(R2017a\). Operating System: Windows 7) +%%Title: I:/Entw-Technologien/Studenten/temp_kai/blend_case_1.eps +%%CreationDate: 2017-10-06T19:06:40 +%%Pages: (atend) +%%BoundingBox: 0 0 774 521 +%%LanguageLevel: 3 +%%EndComments +%%BeginProlog +%%BeginResource: procset (Apache XML Graphics Std ProcSet) 1.2 0 +%%Version: 1.2 0 +%%Copyright: (Copyright 2001-2003,2010 The Apache Software Foundation. License terms: http://www.apache.org/licenses/LICENSE-2.0) +/bd{bind def}bind def +/ld{load def}bd +/GR/grestore ld +/M/moveto ld +/LJ/setlinejoin ld +/C/curveto ld +/f/fill ld +/LW/setlinewidth ld +/GC/setgray ld +/t/show ld +/N/newpath ld +/CT/concat ld +/cp/closepath ld +/S/stroke ld +/L/lineto ld +/CC/setcmykcolor ld +/A/ashow ld +/GS/gsave ld +/RC/setrgbcolor ld +/RM/rmoveto ld +/ML/setmiterlimit ld +/re {4 2 roll M +1 index 0 rlineto +0 exch rlineto +neg 0 rlineto +cp } bd +/_ctm matrix def +/_tm matrix def +/BT { _ctm currentmatrix pop matrix _tm copy pop 0 0 moveto } bd +/ET { _ctm setmatrix } bd +/iTm { _ctm setmatrix _tm concat } bd +/Tm { _tm astore pop iTm 0 0 moveto } bd +/ux 0.0 def +/uy 0.0 def +/F { + /Tp exch def + /Tf exch def + Tf findfont Tp scalefont setfont + /cf Tf def /cs Tp def +} bd +/ULS {currentpoint /uy exch def /ux exch def} bd +/ULE { + /Tcx currentpoint pop def + gsave + newpath + cf findfont cs scalefont dup + /FontMatrix get 0 get /Ts exch def /FontInfo get dup + /UnderlinePosition get Ts mul /To exch def + /UnderlineThickness get Ts mul /Tt exch def + ux uy To add moveto Tcx uy To add lineto + Tt setlinewidth stroke + grestore +} bd +/OLE { + /Tcx currentpoint pop def + gsave + newpath + cf findfont cs scalefont dup + /FontMatrix get 0 get /Ts exch def /FontInfo get dup + /UnderlinePosition get Ts mul /To exch def + /UnderlineThickness get Ts mul /Tt exch def + ux uy To add cs add moveto Tcx uy To add cs add lineto + Tt setlinewidth stroke + grestore +} bd +/SOE { + /Tcx currentpoint pop def + gsave + newpath + cf findfont cs scalefont dup + /FontMatrix get 0 get /Ts exch def /FontInfo get dup + /UnderlinePosition get Ts mul /To exch def + /UnderlineThickness get Ts mul /Tt exch def + ux uy To add cs 10 mul 26 idiv add moveto Tcx uy To add cs 10 mul 26 idiv add lineto + Tt setlinewidth stroke + grestore +} bd +/QT { +/Y22 exch store +/X22 exch store +/Y21 exch store +/X21 exch store +currentpoint +/Y21 load 2 mul add 3 div exch +/X21 load 2 mul add 3 div exch +/X21 load 2 mul /X22 load add 3 div +/Y21 load 2 mul /Y22 load add 3 div +/X22 load /Y22 load curveto +} bd +/SSPD { +dup length /d exch dict def +{ +/v exch def +/k exch def +currentpagedevice k known { +/cpdv currentpagedevice k get def +v cpdv ne { +/upd false def +/nullv v type /nulltype eq def +/nullcpdv cpdv type /nulltype eq def +nullv nullcpdv or +{ +/upd true def +} { +/sametype v type cpdv type eq def +sametype { +v type /arraytype eq { +/vlen v length def +/cpdvlen cpdv length def +vlen cpdvlen eq { +0 1 vlen 1 sub { +/i exch def +/obj v i get def +/cpdobj cpdv i get def +obj cpdobj ne { +/upd true def +exit +} if +} for +} { +/upd true def +} ifelse +} { +v type /dicttype eq { +v { +/dv exch def +/dk exch def +/cpddv cpdv dk get def +dv cpddv ne { +/upd true def +exit +} if +} forall +} { +/upd true def +} ifelse +} ifelse +} if +} ifelse +upd true eq { +d k v put +} if +} if +} if +} forall +d length 0 gt { +d setpagedevice +} if +} bd +/RE { % /NewFontName [NewEncodingArray] /FontName RE - + findfont dup length dict begin + { + 1 index /FID ne + {def} {pop pop} ifelse + } forall + /Encoding exch def + /FontName 1 index def + currentdict definefont pop + end +} bind def +%%EndResource +%%BeginResource: procset (Apache XML Graphics EPS ProcSet) 1.0 0 +%%Version: 1.0 0 +%%Copyright: (Copyright 2002-2003 The Apache Software Foundation. License terms: http://www.apache.org/licenses/LICENSE-2.0) +/BeginEPSF { %def +/b4_Inc_state save def % Save state for cleanup +/dict_count countdictstack def % Count objects on dict stack +/op_count count 1 sub def % Count objects on operand stack +userdict begin % Push userdict on dict stack +/showpage { } def % Redefine showpage, { } = null proc +0 setgray 0 setlinecap % Prepare graphics state +1 setlinewidth 0 setlinejoin +10 setmiterlimit [ ] 0 setdash newpath +/languagelevel where % If level not equal to 1 then +{pop languagelevel % set strokeadjust and +1 ne % overprint to their defaults. +{false setstrokeadjust false setoverprint +} if +} if +} bd +/EndEPSF { %def +count op_count sub {pop} repeat % Clean up stacks +countdictstack dict_count sub {end} repeat +b4_Inc_state restore +} bd +%%EndResource +%%EndProlog +%%Page: 1 1 +%%PageBoundingBox: 0 0 774 521 +%%BeginPageSetup +[1 0 0 -1 0 521] CT +%%EndPageSetup +GS +[0.6 0 0 0.60069 0 0.20001] CT +1 GC +N +0 0 1290 867 re +f +GR +GS +[0.6 0 0 0.60069 0 0.20001] CT +N +0 0 M +0 867 L +1290 867 L +1290 0 L +cp +clip +1 GC +N +0 0 1290 868 re +f +GR +GS +[0.6 0 0 0.60069 0 -0.40068] CT +N +0 1 M +0 286 L +1283 286 L +1283 1 L +cp +clip +1 GC +N +0 0 1283 286 re +f +GR +GS +[0.6 0 0 0.60069 0 -0.40068] CT +N +0 1 M +0 286 L +1283 286 L +1283 1 L +cp +clip +0.941 GC +N +0 0 1284 287 re +f +GR +GS +[0.6 0 0 0.60069 0 -0.40068] CT +N +0 1 M +0 286 L +1283 286 L +1283 1 L +cp +clip +1 GC +N +0 0 1284 287 re +f +GR +GS +[0.6 0 0 0.60069 0 -0.40068] CT +N +0 1 M +0 286 L +1283 286 L +1283 1 L +cp +clip +1 GC +N +0 0 1284 287 re +f +GR +GS +[0.48 0 0 0.48055 0 33.71863] CT +[1 0 0 1 0 0] CT +N +0 -69.75 M +0 286.5 L +1603.75 286.5 L +1603.75 -69.75 L +cp +clip +GS +0 0 translate +1284 287 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 287 0 0] + /Height 287 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0Wd;*"]RJ?g=lsJ]:"^N!^JqJ&N0pjXffo+9<\GSZd=Asr^Jj\`gnWKAW"Fg]ukHtS*Q +MgT5QlW?uD#_u/G`2SPP'fF5e9\c\P^,kYJ5eE:[j5oCaDKi4Qp6Lp"]ggq8kK)a$%!"=BP>O^;fEK%$ +HC-?[8AqK`3#+G0X[LSK%YosU04)0km3'K:;6&/&t4,#1R$1CFk/S[,-u]:ccG7c<6. +f_iq/3#p2"I1ORSS-d\kFY#i`&=9MC/#J^](X"[jrsZD[e+% +*;BDD@H+B;lH3#/]*[?laMn&UV_+2\4K*0,hRdA26^PFn@,GOEL9rpd71kKfdhQ)";&Ams]#doj,oB)s+J-/ao= +7%B.%9Qc.r=rR,[_K&U\IB[]0-K8u4S;JZdpu@F-3-!s#Pq+e2gph\'CAI8]e#0tYo#l%1Irn$5DYI/` +l2:AKds_T3>?Udpfs?/jHM!-o4:Cr*OX"MbT"T71dWAj&OGHgI#Oq&EQ*kN(Mk`e_D3q43Ot/%5dse.# +M8KpFMd4ZGB&W(-YCH,b-iMqOp=X(iJ:6[YQYL-kKDc*B=pRZl(\.NhEOGHgI+kr??CHaaf +j#$YrE($4RikGHkmpE_PESS;d$PR0D:=lE`6.b!/VPtM##765H'bOLWWb9YL/X(+t:i,/KHZD(i:.5il +qWk?BIJ;QkRn/lKq"a*F+8;CpKo*-2&)U^>!hT'X^`s/B3#.RMKXCD[imlSJkKR!c(p(J&$]E6fLc?,D +UtQE/q=2egj`cK-I+Y82#D_;n>osu*_Ao@WJD7@+]Sd(RYeQ/mC)7Ub@,BM,#1Rj +\p3c)ace+0H0:ahcSoe!4Ep5Kj,ZERqtBDshes8Wc8oglp;bd"/ccKTPtgdp,#TC7V!=kJ[6N64 +b?[8ijD[MWMOJ,m-I+ZS=3\M9DKk047n8$LCu2>qO!Z.3<()U?8@9D7X,jing,QbG*0,hR;:Eb+`*&u_ +eNA@lgmpqOr,R@MLf4m7&jdMCEI-j2%m:l0kEj'uE@P^l=dV27Zu=/7i,K8o>22cd,702d'p0[rUk+NS +j.6Naj7HSs3$M*d9f!.jB:Wq4l-rr>*^91`f,I!\$&LVVOWm#cmIuI+[u'CP+o-VPWH'sB:.7l5$PU": +lZCX9T^1at7CWqOcsh_t/esMC\WBin=$)sJrBtJ^oR(U;,#1R$1CFl*;!W5,H_S"QHuKH.&e.\M.@LaG +qERdRO&*H5[%5)HE@P^l=dZ_0?`3dM(9gHI+`e_NGU*0,hR;:Eb+`3j]Xm^rZb +p=!1t!?[brL;Zb_&Lh<9Ut+#?:1oWEfZ*.n2A6hQE[kgm=dZ^BXj]H%oi`o^VMk7SrM4*@>^M5%JN3LfpLIVO<-p4+q`[q^gYGPHRWpmH&joS;KkbhN5n7 +jm)-rR((996a8Sk_pR=uQlRYkRTZ#fk18eB9>KSt"?\%On;1'U.HVbKRZ5c,h_K&=DUKM(`71cbBkCf5 +En>$m-/]A"hf]Od=b618jtFsH3rj+'pq +MF]I7+Ur=ZY.M4KWTL9+VF!^G1CFk?i,q*C=ho1OYK'#S0aE*c<()Uh%;G-@aPH8*\!saE3m#$8`*lP@ +e',\I9tF()/ch#]"L(P7$ci@@3#.Qbc9nU\&mb);"rjHrb]uVs$5GGC/54iJf'/Pp^uKl!m1Sn4Ekj%t +7AO%AONJO6l>#,oZ]3Eg$W.KF;c2#f_Sk!+e*S)?f3ACN/79N>^aDlGUfa^[b"t3Lj)jtCl(3m`P?Y,G +BSMD5Ael_2BUt0p&bI.9Y9,m5l$uP6'p2r;6Q3@PH;M**om*Bj/7M%Y;c2#f_SfI?[.[Y?$mc!.i?dkt)mS;NbI(1s1^h?\F7oC(u0lEjnUD;p(AS;Ki\ +Ud8Q9/oTsE:1qekTPU,>9h!""W+fjPC/jfnW.tr8?NTXiqh7ajc.L'hO<2.1SNV>N-",^Pn;1'U.>1Z1grAT6V[2,HVR$==O[2E11CLO7s!,=3>G1`^/Du;M +J?;aJ#`1MUO[;Tcl>N160aeNK0lqoFLc?,,bq-N3b.Cbu$`jSOA7M83]B=g.XA`"&M)Z646:guTD4Id) +dJ;@)ie>%[QAUJs;:Eb+$Y@rf4*ktsmPhEITBoaZU_"/Y.O'S.-^OrUd;@&+='p1gR%GF"N +WVQ2;gh`K]&TK:8RTXmdll:J0lokA$02LO2NRfO-KLD>f80Oe+Q*[#:nCB_\@Lb:kX,&_M29d[7?+k+8 +LYk7,iCP,?e.Cr1'LF!=7ALLCTdaV?h/9]6+tin=b%E^>V'=nue24N$+mXX?[iF*LHJhYM(@GQ-/Uu9/ +YYIb5,iVck$6^Fq?L>bsqe&-1gGl;Zi`+DaZZ)\^\6;$k@*B(`p8.VZkk6BRVu?X.%-s,l66]/nU_(sR +$uVRV]O!;i@Bc%o&TK:8RTVUI2>Q\5S>1KqoB=P=H^2H/-&%G:;\:I31gP_QVoRU7FS7XgX,&_M29d\" +@-'XZB%0McWf>J3PAe]/6YCZ([#0Z<;:Eb+qc)t;g$9tdqgI0q +s"hDA*I`cGVkak:E@N/dOCh%kjfW41h5kLakkb;8h'4ZCDB-&%G:;\:I3 +1lKNP=ZN%QR>>Klj0X]";c2!ZGo#i*d^crio9c.0:?peZNljUM98DR4=f8&,&ofBFKofnJF\gHU)lK$g +Q<%X.j0X]";c2$+IMT(-i7n9>n+`;pZJ/UVofq_G%_VDS5p5A +.QWrVNK"H4pu&3V^=r0?k?o(n:V6SOo9S@Be*2g:HLClQDcIfZb9'se:R(mihX!A^GM9,s;@&+='p1gR +Xg)s-oZ.CUe%/MP,2uRD!3a'+b44N4O)B=,R:gEp^0U?TZTeh!+5e`+Ym6o[^&Q$FnnWT)bbXrZH`LnR +F#EYDlil9pZ;*t7,iVck$6ch$K8n>;]D)kcj0X]";phDD?+X.WgT+DZhRe"#P>=A&F6:^"-B/BMqVgn\hc[ +526,)gMai4VVR]s]_e=THhVCNJ!J-\s(ccMricjYW7ZYB4Xf52n+KraUcgE5dq5P)J7 +S&dW:Koh*h&LiC_C?99>SFY4#'->H=Bb_5XU5=9pmC-Z8IH-;GqHmB4?S>c3rUnd_r?m*hGCR*/do9r0 +pn(p,p]goiZG"M0M_b!]L[#&DM#bJ2bIEoXNaLf;\hhL"_)1ASZUc9$Yc4E9B!M_De( +mQW_==Z-!;=.>U>SVR*1+'dZF&$+s$:.ZTSi`&;Q+jH"8NRJD60q6iUXWlb(1m&_9DNn;69Z2Qj4F-MY +$ST.HmQ[--/:?N0o!2&04+$[^j]Aq'cFDYUNf<6t$cC[B(s5c5\B:(a:6b<(%':c)^i` +l+0BA,]0&P&TK:ha9Nf70^0YC^]42G?Q62X9B6$oBHc]+'LF!=7ALLCI+p]U/H]ph;`>;D2bpE03#,/` +\l71LDn\7(Q,1(H%@R1X$T%[];c3mX3#.QB8;j2N`SGFf6sT`Y6#X]A,2uQYWH77J4nm`QrSJqc;[LIK +:.ZTSi`&;Q+YB"#T"M_K=hA["Fn1O@.O%VVPIbr)=rD6cHgS4fp[3J-n],:fS/E<+G;BU?B:Y2P8AqK` +'LGtk[2Z$Qn!UMh4NYTW'bR@<"1WC5b44N4O)DRKiPP!:[qi_2/52RV8dZ^RV]o"EBq^O?3'D3sfqiSq +]=*c[djcP:70g0(Z1643+4X0''sfT6egW&$7%B-*+X@7N:60\-arVM"5Wf +gDd%PS^."cNG`U'*dMB>'bR@\CI3'H9k`(Nam[WgZZ3SV<8qf)]4U([]/UQ`bq)PYF\2ua&Z6gN#`6&''ibq;^rGU^ALLlmELHog +785QG'5*l!6:f%oL_N0"DJV`P2GW]ZKca(.2GR1j/8CVVQoODr'LF!=7ALJ-EI1_c4d``k,.;J0a.fH! +Ko*-28KfA=<(%':&\$)DWen5Z^,89_NRJ9YZ)DAK@H+@e;@&+='p1gR`(a3.R>B&%gY$B&oVRVs$c]HM +BkCf5XA`"&M)Z646:f$8XJ2/Ce+]J,h!K"535%!cMje5n-I+XuKoh*h&LiB$>bn*V)lJH49Y>*"oE&t_ +C78:m39ueC66]/nU_"/YnVRN0:@EWinbn1*ZMF\m9iY!d,<=^FZR>>^MSl:Y< +9f!.jB:Y2P8AqK`'LEur^S5He/sC5PARaeX@o:_!_SfTTU_"/Y.O'S.Lhj#b1(g^mDK\)6'62@f80K8<)R$)_j7LdJ;RbCdZZ3S<*/g7t(+.$L(:.ZTSi`&;Q+VAqN'b+uLhQ<6&D4GJaa.fH!Ko*-28KfA=<(%':&N?8<[P&;TRYL9,`&:B"MdoW5 +beh;$Vkak:E@N/dOGKB87D3#GH$Qqo^,89_NRP#f=O]160QGYm.>1*ZMF\m9ib"mYe^`2FVc,elgGh@> +AtbspAel`=3[KKALf4m7KLFV^<)d-MY*k))]A61#Ve=HE<&Cf&_SfTTU_"/Y.O'S.Lmtf0`bh4eH8+lr +?R@kY>"/&'/52RV8dZ^RV]o"EM7AtUBP?Gun?[tPM:fi4feB`Ibmh!5ERlQfKLD>f80K8Uq>)/eciSS6iOAq@L'?U/iuV'5*l!6:f%oL_N0"Y/M-@ +M0O/cjMpH##89o1f +80K8$G4sG.[D\Z&R48k-^r:@2:383[KKALf4m7KLFUC=&c'Q1@s'j`+<93ZuJ-C^+5WUAms]# +;c3mX3#.QB8Am)H7D7E7dgmNobX!gI7FPf`-I+XuKoh*h&LiB$gd5!tEoZeP#8/;@2:38 +3[KKALf4m7KLFSs<]%=+HM=b&[sm!i4eW%\k`D3dM6frK+XH&H6jb(L\$-TI)lGVVS^HK%NRO(nfSU/u +=dV27PS?G.:.:ri&ofDTg(`B1mP,=.3*f0G9f!.jB:Y2P8AqK`'LF!=7JE']\'2MF-=RplCT47HAms]# +;c3mX3#.QB8AqK@LGBInDOdjN9K_]D3HJ0L1p\lUegW&$7%B-*+XH&H1tnmfdt8/X/e`6N`p!_-e24Kc +ERlQfKLD>f80K8<<)dMn`p)f80K8<<"q0,j7N:3DO$''!?Oq9 +U8F?4M6frK+XH&H6jb(LVkOm;2bjlJS%-r#SDT=T.VbDTQoODr'LF!=7ALJ-E@OT1h`*b]#S15gT#Zi> +.QW)M++Po1*ZMF\m9i`+F#1(c/mO.D*iB]HIW-?]:`oePCT%)50R_SfTTU_"/Y.O'S.Lf712b!]J=hRVK& +XeJBm^3ob+WDi]oI^:_JegW&$7%B-*+XH&HFEkfDS?AI"eEqG2g:;3,7?dSi:O[?PgpnO,prCF`SNhV< +=7R3S/52RV8dZ^RV]o"EM)Z4j[S\!A#B`(ue[B=bGp6.#n8P$e!L_N0":.8+4lZKhq0`uE22GUdX@q4QbYJ5P\ +h04Wl,$eg>kF[6Qg`Ku@-I+XuKoh*h&LiB$S;LoKR>B&%gZ`fp-K=-T]]6AV-;s5e^3o`ss!qYe5'H;F +b:gUmmQWE6'5*l!6:f%oL_N0":.6t;=1`HulPWCPmcH';S6"%5/mc28o&Ro:hKc$so?Ea`c^d/lpu@Fm +^3t@`pR?knZVF(8,iVck$6^"ZU7#"uS6fB&)P2Wf+&"d9)lH[mWA=0R\od2hZ")=>LnB.ml-DTo]]T+9 +_SfTTU_"/Y.O'S.Lf;][)qm87ipjru,+eMJBb_Z4qYL&D++F"02rEutSRup^fAZX/K`E@H+@e;@&+='p1gR`2T]kb"u?TEOsolXu3t6>").A$PR0DP!V^XWJD6T,#1Su +@*HXT_$:XW2S!g2785QG'5*l!6:f%oL_N0":.=baf>d%uAKkGuB&g7URV!<^c8m8*OGHgI.>1*ZMWW9< +NRK+(26_((785QG'5*l!6:f%oL_N0":.=cSfBY"A0:0e)bY4P;EEYe*1CFk/SWZ<1`2SP,66]/no;t^) +A`2rt3].RjI,hSkRV!<^c8m8*OGHgI.>1*ZMAAStMS%\^bsYh9mH-\n:91=-Ams]#;c3mX3#.QB8AqK@ +U"!nKIe[=1aYutqW+fjPiiH'V#`1MUO[;UWWFua!_S[sZ&bf4?329d[GS97F2+VCUr;@&+='eucu`SGFf7,714mG'\'U8F?4M6frK+XH&H6jb(LV]nU2 +h)J\'L2$=s`b?/Fbq)PYF\2ua&Z6gN#`1MU;.n+ml+mT<0/"u^XK5+mL!D]b0QE-HU_"/Y.O'S.Lf4o_ +;I(X+*e\`%SG:0f,McWEVb(D7-I1#1'LF!=7ALJ-E@PE!gCs,*ddCiEiFV$!g,i&N0P4bQ*:6<@,iVck +$6^"Z+stk+oub))l#^YeioT:`X[b72`%4TPUHL&Z7%B-*+XH&H`.=1f\'2KB'=!PG=j4b$3SKZ`8AqK` +'LF!=70Jm4q!?\?2&iI^5FC)7iW-;=EK9ag&/&t4,)),7;\=#GU2_-MLE9.%kq_d[R"^BfL`SSeOL8:.:ri&ofBFDXWJ*7(g+B=`^"@)N%fI*lBO&S>/4rKLD>f +80K8<<(,LE(%$.3fTV[l1(+cYBMSsY&Z6gN#`1MU&N=\u@kJE*4e?nDH.c#!0aeZXBMSsY&Z6gN#`1MU +&U3`%b##a`]X9hIf.9$@'_`C?^=-\&iZ.>W+XH&H6jb(LV]t,p'igTW]A53jnGS3Re*3qdl3E3k_SeIg +P/4rKLD>f80K8<<((!?'ifUYLPFg9:FMg`U"Cni +S>/4rKLD>f80K8<<(,N8SSeOL8:.:ri&ofBFD@.,/4rKLD>f80K8<<(,Lu/)'/_r89TSCMR]aH`7$X@H&9o8KfA=<(%':&Z6i4Atl$5L>no)1::mG2@C0W +'C1nV',#:7,)),7;\=#UC9oU6ZaEPB/Kk_(,#S]'3#*#aUD44H`I"'DMoB:: +ib!;'dPaE9:.:ri&ofBFDUp?'or@0h=#Zf/cVV837*j:dC_e@8f%2?&+XH&H6jb(LV]t,(<)KjN>@(Xm +F"!WfB/>s0M/1L"AX3XZ3#.QB8AqK`\2IAe4fZ$HmFKP!]:W4gV2N<)@H-"N:74C7,#1S&&/&t4,-KH2 +osP<8/DfET`J6VnRtZ]7of?Z-#`1MUO[;UWWJJ'pWMmC14EM,!4m(`k@2:2-DUp8c,p_JL6jb(LV]t-_ +Z_G,S=FC/#TeHif2kTE#6RO/=<(%':&Z6i4k.IED'X+WU/h`9WM[tMER(,.`V]6Hq&Z6gN#`1MU&[t"? +m@K4HKiseQ"^7f\8P$e!L_N0":.<)QBLUHVHmm4U`%C16-(C!P;\:I37%B-j;c2#f_SfTTU_"/Y.O'S. +Lf4n*.VbDTQoODr'LF!=7ALJ-E@N/-785QG'5*l!6:f%oL_N0":.<+#W+fjPiiH'V#`1MUO[;UWWJEMK +mHN(q5Q0lJYD0d$Z*Ei8#9W=3qJKnRiiH'V#`1MUO[;UWWJEMKe[otieu;TGY$\q-pr-<@H0+hkj%$RA +o?9#"Dr7_n'?n>3=f8&,&ofBFKoh*h&TK;#EV&>;1M>!t@$kXOI/3=XO$*!_;bmkI_G<;a`3[cRg]-ZqDnfSlU"AUiqkMBP`*'"6 +&/&t4,)),7;\="!)X6Rk^OGOSa+!Q:?^-$WS;"`Vp=o/m2r8eSs.*_9/mio&p".7_;.a7rXA`"&M)Z64 +6:f%oLc?-/<$pD4GOKEe&&j1-n9aW;=+:%l47X^nPi%d`Gjp&TSilhc$SRJ9'95hdg[2]^4.STcIbHH+Gp"Bl<(%':&Z6i4(:g/Ss*?pDZgb[V +D]%kA5I2PdOGHgI.>1*ZMMP3YeZ2aV0?`4_F(b""%aDj4I.2\MdMtI:PS?G.:.:ri&ofBF:.;X0h7>dX +@q0$f80K8<<(*76RV!<^c8m8*OGHgI.>1*ZMMP2.e',\I=f8&, +&ofBFKoh*h&TK:8RTZ#fDRV^pQbY]p&ofBFKoh*h&TK:8RTZ";'p1gR`2SP,66]/n`2T\Lre?8.&LiB$ +S;Ki\,iVckS;NctDjWL!O[;UWWJD6T,#1SFWMjP1L5Ah@.>1*ZMF\m9i`&=9MON[GQoGhC6:f%oL_N0" +:.<+#W+l6cM,P!8KLD>f80K8<<(*76Rc\OU3#.QB8AqK`'LF!=7Du1(C&WjD;\:I37%B-*+XH&H7%B.' +k&6VH'p1gR`2SP,66]/n`2T\Lre?8.&LiB$S;Ki\,iVckS;NctDjWL!O[;UWWJD6T,#1SFWMjP1L5Ah@ +.>1*ZMF\m9i`&=9MON[GQoGhC6:f%oL_N0":.<+#W+l6cM,P!8KLD>f80K8<<(*76Rc\OU3#.QB8AqK` +'LF!=7Du1(Bh&1(!+9D4HV+JBzzzzzzzzz!!!"tZa$e*_$;'0p!m-mINc)NqYGN;kd/T!S+[4u*o+JXq +bM_=(]g)Pmci9='g16q!mB7[ +ls?,1Z]Lmf*B(SPadNrY/i&9\oQ(mr[+gT]mB/(]h^ifUms>*s8;K;I +SmJrV+[/t;Z6R_IpX]%ieoJ$h=sN7F<$MR;tc&&fR9LS8pEJOVKn<:A;[?:H\O@Zi/dqrV#"-n +%@9<:%&hE1@+8la,V0ejcrpD?R_nDV4quS0u[3_Hi<%ZIjr:YKaS^@_Ap@PIe9E,kKimPqt]EI5PE`>n +%\o%'OMJi<";4U,d[O*\))G3]W^"NaI^OGdH/QjmlPWR^1hgSf/!oJ7_NW*#%? +ZPtbl`\&e`E,L?gqJ46\%hn/(LMR;s2r@$7]GV75QCNn?PP/8n(t`"rpY\-qq9<<;91<4V!d*Q>7Nj3q +q^_2.p?[r%,@upTJ(V_Bu0K@$2j_"P4B%fGma^FW[hi=CF*p'[RB?@M_3J,6'm\o[%p=dT;9pYC&:_<8]H5:ds@q;db>plGHbZ +EiI'GoT(05rsJmpj`4^J,IXmr(f?K4FR(u^\l9i9`%9+!bK6^HhZsjp,Fif`Alsks2J'GRoAaJ)`MZ!^ +VHQ?MOZeSnq@ldR+=p)m6:C1UQU_"^i08qJ,F:DaHV04$Zc<_qq^^565M7ZGj;9+hK\(?TE"iPj`'jE+ +8iq1UcEsjQ'J*TI.)F>qqL$-2XOR6Rg`"G::WB8qH;H"GFX@YY!;jC&#W0nqU(@QFQ^r?BtkEek3h';h +u2tes6IH!X88r$Qim-NDgu!Je:.21+81KIpYUIMBO;tMa%q3]e&NMVXIOmFYHQirH1Ut0o;>BV2@d'CA +ms\6AmqUm.B<8^g9d,\=kG0IQKhuWDnc&0cr^,NSOpNmo#ml"T +De+hds`IIe[*RcHZTs#%/]ePB:kH$Y$JXtpr18pHV?k%V#$e-cm?>Sro\e1ktcdiXd;HA$r&HO\N,2&Z +`mBr>j'D'Hg\H-qS.0*G7NR(f3^2a%,U"b-FL+`Ys.*4^\m1>TmV:B09%mSF?5$rT)/$$0AWUm8 +Q@uSq:2Ztec3eJ]6DF1Bk:jeMQ_n\ffd;6j^qE&.rre'Y'TU3CTkEpn(ta=5Q:H%R59K]'__1<(LNC_K +^X?XHZ/:Nh#Rfl`oi%9R,@i(2s!d$jd0=\?XLQjldjN\5@*-t^A6o\Btl9(k2O@_&C-1F/$PtpSJr./9k*mU)[e^7<&S>G]XMf2Fe>_^uo +]233hRn,Tg96>+\T?rZ$ST/3m+ATBIAHo8Va!oQ7F@!P+gbHrG3&AE,]_$:zzz!!'f$q>UJuAP96~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 33.71863] CT +[1 0 0 1 0 0] CT +N +-1284 -69.75 M +-1284 286.5 L +319.75 286.5 L +319.75 -69.75 L +cp +clip +GS +0 0 translate +320 287 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 287 0 0] + /Height 287 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WIqY,?hoG8OWe;(N#3ajLkLEb@^8BI&2TF\6>2(lYTuV)L8867 +7]aPH1l$HiU^X+\[<\qWW^fLi +e(hKTa)4Ud6sX)hpF;h^<4"a7Y9!Qc6hHj(qF-/&2eQ.Jn&:2$cc#bRdnbJlop:*3h;-mj<2FflSNhW' +`f1pIZuA,'burTk]5#lr\fqRm%AuslZ7P_KqsT%-eQ9ZMldr=YfW_(1?.lf8p$226e%b\;Mm6B/-KmC$ +[F"BlWDekuI/NNT1M>"_NQU4O(]3?aDe_;kZ>*CG-1B"'KaS\3L1aZtY@9]=PTGNGm^g +4d2d7oU@i]n@,g59pmcun])`L?c3[tnC+9CXfW90leoV?2d!BC5QCX[htYp5CW"]rp@a7`IX';:8bMcL +ldi1rT4"6PGAbNc-#,sE2E!H73H?D#^1,'=GM[VC0`2kc%?#PJd\TUOqWb-V?0MaK_bQ^]Z$#B`qsM'l +pGOldl1DXLcfitfJ(8%Pn(t/SoS^6=%Go[5)^joPn](l,p3ZT(@=@2)^]2##Dqh]pQa^eadb3:k%^"p< +R<.u^:#0shp?`_RAj#hCF#rU;]rP5`k2`E\].?rB/5Q=uuqtrBaiHj.X=gRa=opYC7 +Vk<7[,1SIbs,8f6hR[j10H;kH,-D^XeZ!H,*JY+FHL8,l1__DcF`dTYFcCf1@uVOZn`%OOd/)hFPIdi? +_d,Vs6Q/3'r>(9NT;0$H(TrP8>q5k'5p'MXDD`j%<#R,JN+nmd:qb7cTbbR +50VTFW$-E7VG4'M4uekWDu.?DYa1T@kk;r177m-0K]3HD;b6Z3fR*VGaa6@rj6)5YBse,oC&CGkRHe<@ +>X!Z:]T/U3:S+YCkp0?.bQ@qLL%>(7?[1S^9_=6i:n-o<7s%/$/Wfb;`T"jpeSP.!NP)8\#L@_cRPejf +jn5+WE;HD<],L->EG5gIfs<';V8'cPUTMh(Fns7L1E%e(Dau=kVP^4WH2XTnS:9_SY/^@(Pq,r$!?*JD +L5&[__M&A?c5YV3eiC$rRhBT)C'(^W;L[Vn&)^?Jc'MIZYe6T6!K:a:S=4N.-m4qTToV,")!l1\sOpkVm/H +M[\!OcKH&^U>MKg0/>r13NN"*X(M?5XnJ_mVtB@e^>o^MDpGAsh^Y!Xp?'Vh/M/R%LT"k1RUob"YsZ8d +X+c!MqY[V!=0J2ZIJV?d7u)hRqYL&S/mVXf?Z0*CYsZ8dX+c!Mo_bsTCt?\>F6Cj4Q5_c#B]XI*g,2@G +BL0Bn/$ZpkCBE1G5(Dq7^d(C[8,19ei:cQm@8>#:I_rXihjftai70]9>ntR*S$7,*?7g5oaeF42DpE*k +hl<)/[P7W"U"9X2h<"T[o1$JTX+c#'B)Ynl\^RHP?at&`(r=69qTW0"%:3cp5Q;W$jn6,M^H&@kI`o\-Z'h9BSC&uF7)(aW?Y"tAF%3pc&H1aMIZYfMbo-I( +6hHj(qF-/&2eVc@%+0"=kSG,2hji(I1.8l;X879DAomA)lK[d(c1^B+"pWAC3AWWSR-eA'BMR:*d;R=1 +^>G1.>c1;cQMIG7NupTh9mZBkal9oFe'(k24t!Jofuln#3MYJJT.ZsIb;>KR2JkKoi.,CX`cRBf#lWnE +I^=I61$[ANI]HB:#![P4FDHR[IF/M46B'As-M\kj:\$'>W-)[.oHM"/=l6#jg2a``Q6]oY:[D1'=05[BEMm?LGdF\@*SgBdc?XE]B`B3k'=:/b-aN0Q$Qp^O61 +m>"?#/3.n?f\s`'m-O*&kg74H61cOU.g9jTR:u>IO;r?S` +927:DB2PI>7uc_uQBi:<YkB`kWL'EnX9f;4QF:hqb*()B5-\sP`Qk&DDj6,Lt*gWFk]eLEpK4gg) +2XIA>^LW6)Gf_C-&iBJ\>Zer\/92A?ENcN$B[:,ZiidOg,28#<@I-SYVO#jO_ +@`@t6WEGcFlgh>mbG*+$MpZIgliZ$&VnFg681BOXNJ[0aIEsR*gi'.U_M&BF?/]Vi*r=ECVY+*!BT^Th +_\CR.W(loRZE!H8#]6f:bOktR?N7Mo,V@@1M_=$-kMu-4Oe\T'fh%bFO+Io?ZqsCkLB-28*gZ!\"agb*- +[F%n7!MePBeO%#n__X[FE3Zm]GJSk71M=uAT5T\'ru>X-FnOP#F4!3K&bWfELb]4(%!`c[:I%ke''-ofs524 +UcY$6RP\pI`&$AR?!TQpjC[9a_NSTKp;XA&oKc0i8TjQI"Y8@%h*W:;X?eEc0(]&h+rHb/Ef[6l=qLosgHD+]u +dB=A_KcU,$>+BVCMW7k$BHLTk/0jC1e6GKb*W8G1RW9)L+:QO2_Q]6H&QV"q(4[KD, +s*hAa(7FoVKo*?CH$,P1DiFm8N+]5c\G$0paBoB=$s^UL4B\ZZF8oK*/$ +(t7O!@LgBlmf#6fhMrQNX&A1TA,0-8r/'%o8><'OFC!0PotBuZeuoT8TB2EQr9ENj"Q@g=i?8'Vn8W\4 +\^ot)*k";VBDIkT=4D.a:XB%*Z?+[a_fS/EYFapKqru3MolY]N>^cRsJ,V6tJ%dJK\sHdsj)8PHH$;5? ++$NM^KN$^F=`AGE_VJRFE@;OW)#pU8qU/JpX5MZWqZzzz!,C?`$c)b2s56`'e]qsSt1p8Q:Q?[T+h^K7UFeHTBmFt +NZ%,Un)fb:gWcdaAb6mHa)-5C`YkhgFIhRT8SGhga8O4E05//en&\Z^$k`HKhQ@hYQ;s:ZrT>)/1bPR& +d9YSXmKq=2jgSWJt."rXfk=gYUfdbVRT#\oip[O^b-"kffGN]))C"heP_c^3o`T:HbNVl+t2%f9NI5`V +of*_[g29lSAF5*/V@",Hn98j@dPD*??0h^AG(Y`E''B_7S'^.mENLqWXp8HgeXeQ$uSj`*RQ`pi0Ti.9 +I:cc?sbm>4u1@lBKrl4*Kt8ie]$XSN?GoYd`M=qiOAid=k5[0);Xt`jY#IGf ++%YW``fSY?SK=jE+pKH)+!t79?WsdFDaINl<(rJ,XihUPGgo3[`WGV@L]ZYjJqDqBpI[;4B#H0(;[M\b-]H.-aZWtPBJY2iobSY +rHd.@bl>?bX1^\(>Eg!8N4#TqTYr042JCh0VQjzE;%&'Z?jq~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 0 0.07987] CT +[1 0 0 1 0 0] CT +N +0 0.25 M +0 356.5 L +1603.75 356.5 L +1603.75 0.25 L +cp +clip +GS +0 0 translate +1284 70 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 70 0 0] + /Height 70 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0W4c^QD)?sS.r.6biY#7Yb,R!3ErW*]^ncLFrO:XRQT^dLs6DTIe7#D[-"^<0*82ONp6j8:6_s%`d +;]p`+/X)UH0^GpMpN^-#@pbQDTr`6mGP6L1hOY6b>lap*zzzzzzzzzz!!%lSo#i]$s8MoNNNZ[%]"#7P +]H$tP!;c,mhgTqPrV+)*p=o"p?[r%I]mKMA<^-BDUW^j(I6B^n!!#RUf3a"j4$+r#Dmp+HT:_IZ]Qiu+ +p$:3os86q`LX/0]Cl_@)!!!"^q"sNp^\mZGqtKPDHLtmR$\.s1LS&tb8c.U.hgAAZ@5aUWHDnFU!!$sl +eo]k8rqPN+%mG7/j@T0&]:CSPf3a#m?Tru=]\Amu>Fn!)[\aFN:qg?Y.3]'a,#4"d6BI"e,3#D3WNtL^ +q<+AO<@R?Zi?*ODU&=Jnn%S,Eq8%[g?[VC_We[m6M3B-H&1$82La3+[3%6%HMUn9__V]kCIJII-LqED, +n%JHZs8;IgO0J$.lLB,s(p5BAZ1"U+0b>ViUkg9!M)Zq.mZ^YWZS&o4IgFVe,*EK_ihVAU"Go)e,#4$H +S*Rp-(Di*oB(r*W,Qrr`.3]'a,#4#OPG7a4\o<(oXHtSI[WeZgl!@)"N\*qp'Tn%k&LU!m+\9OC&TL^U +hHUjL4ad%odn`2F^YIm+Q*NS@:4X+AKHLjS73j$I`(:P\;RG:i(Ht&J05l.4o]b\nYCHE5VmE_9DDba2 +$POmV,U#^s8J+N"&ogf;S.r*7fS)t*IJ).(HhZgK5(EM#a-W-ZCEC;--;KFh6BI"e,*EK_ihVAi.Cu'O +Y?q2&j,`M1E6T.F:5VS/OGK)EOq8nuUkguZb0:\K:5VS/OGK)EOq8nuUkguZb0:\K:5VS/OGK)EOq8nu +UkguZb0:\K:5VS/OGK)EOq8nuUkguZb0:\K:5VS/OGK)EOq8nuUkguZb0:\K:5VS/OGK)EOq8nuUkguZ +b0:\KDEK!/q^HIm"Go)e+pgOZ:5XjkU>0j!iZ:=5]^Mc60b>ViUkg9!M)Zq.:5X)@Ko*-28OAMpP9Q/$ +,iYVU3%5bFc9#+FTeV]*s.)5uIh(TH7Z`XHMU"nbR4QRlR;F$qWB5=lbhY$h>W";V +NOr,J-KRokdrm(5U7BVE3dUDDH=k]4R1l"#GQ5/Hk@"-M;Ind.asl&,_8$mtN1$/<1W<`UX_-Zaj$F=EAc51c&#oeTeOJ'@h)skj$3"HHSq?4':E;l +hYV@J7kfP%mE?o@Em!cMT6S!-537O$c@I"MRBhFPZYe=[rnU;GqFe_[,Do!.!UQ=,4;g"hm$>u+46?'@ +SGHGoC-3Q@pc$GUR8!UN132chB.2>Hk]X#t>$JFun2Hoc5Fa^?lADJfk\lo%$XF+LMb[tc?X2HHeT5ck[0q1r( +.B<+ab)SM7$[gXgRm"B?]'tTL6+MEs+YQ@(8J,r?Paa:!S97F:Ji'C.]k%N(VDE'naG.rGg.=*Lk$["J +\)]0D\%.Fa/aP&X9kA5"b(';S7(%q5hLu4%:8UASqlNL(mLUkguZb"W[!c8m6X6(1_QX'6:8X_+j' +[QV*t%Q$VtC3!1bmkAW3>W076O1*f'qti028-^%YH:<^IPG6iS@H+@eOuVtSeSV9@I`D6))C=1,&@d[\+bAFJD)GMZ>[+@XJ]7p0c#Tc4Ig(_5pg?K5^O`"#?NEDi$j/khdX8eQO\ +dZ*@4_6uH"k%cX9oeAnEFAk9X>ht>4rV[_%'+,B*8.fi>Paa:!S97F:I14O^L#_;JCi=5s+&eCtI:RJ# +NU+K^-eH[(^*/qfpq5Q`3U%ZKL_LFK7Ch["`*&u`dA%hlf=BUS[p/#(?TWZ,l;WT_X\HI=D?5#SM,T7%=tQV@+&MSWZCT+DoJTDskKbD_H>q8njddjL_75 +1`H%8B<`Qk-UksF;/Ws!ERlR1A.$c)TDUcacMYB,J*Y"DICrEaGWEpCdu1+CIoK?rO.[76ihVAi.EY@$ +-I+XuM6oPuIrfOOBAM3i8*r1+?1=l_]H$<*Faijs4>'*unRfJEGDf(TLm'%BUaS0-QoODr,iV,To\UTP +p?5][mG%*oXQ8JVf:$$YIV82YX/l!R1]p#f:5XjkU>0j!iiH(A\6Y1so\Us]]P[OaHfhO2H[NIGmF,l0 +RnT^0cJg-=Gk!$!%_*2\&ogf;S.t(^$PR0DP/J\5RT1a'DU;Sm-BlQ?]hGJUbLV/=NL-EXZIpT^?!FRh;2PO63%6%HMK71"M6frK +@P14%iKfZB=+S*E[qQ(3T.DWcLTB-3]LaP9KT@Su,iYVU\5Q/M58)L<5Q~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 0.07987] CT +[1 0 0 1 0 0] CT +N +-1284 0.25 M +-1284 356.5 L +319.75 356.5 L +319.75 0.25 L +cp +clip +GS +0 0 translate +320 70 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 70 0 0] + /Height 70 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0Rd;?`c&4KGtj#ST"g[Z/WUmn_W;F)#_/Nb\VUFBS.RZ!7L%fcS0zz!!(s5m(gTIIhb/3c'*3;/N- +Dme.j"Jo=Ohl'=aPeLB#RmY^(8lW5[o@\Y9k/-g-@jCn@.IC9`&)Y,K>%agn,]Rj[BV>&9e#.r)>7Eiu +@[k/k0.(7Q]7MHXhfS1A=lA$hlDo(:[W*(Tl4/5O#4qB`&s(B'EFDi9(dl*j*rjRh3$?ZQ![d4[NY[cj +'JITuG;:;8CW-)]W9rK>WJMgid=lM#HXdq7LPlYeJXc`)B&bntMqdB>:jNdcsjG>@gX^RJpn``N*JB(b +]m\]+;UEr'Y#000!>ka.fg>P(Q`^Ff:.Vr&9gP1+?-I`^i`7DIpUgS/%qqJFV53W6DMQ^iM/oLhro/c$ +ckh\Q0Rdr1.nam$9'^Z>%AU0hs;c##/bs)1]J\Pilk^ZkL3oZKZ!I51[UdI[55!A>Agq#~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.60069 0 173.19932] CT +N +0 0 M +0 286 L +1283 286 L +1283 0 L +cp +clip +1 GC +N +0 0 1283 286 re +f +GR +GS +[0.6 0 0 0.60069 0 173.19932] CT +N +0 0 M +0 286 L +1283 286 L +1283 0 L +cp +clip +0.941 GC +N +0 0 1284 287 re +f +GR +GS +[0.6 0 0 0.60069 0 173.19932] CT +N +0 0 M +0 286 L +1283 286 L +1283 0 L +cp +clip +1 GC +N +0 0 1284 287 re +f +GR +GS +[0.6 0 0 0.60069 0 173.19932] CT +N +0 0 M +0 286 L +1283 286 L +1283 0 L +cp +clip +1 GC +N +0 0 1284 287 re +f +GR +GS +[0.48 0 0 0.48055 0 207.31862] CT +[1 0 0 1 0 0] CT +N +0 -71 M +0 286.5 L +1603.75 286.5 L +1603.75 -71 L +cp +clip +GS +0 0 translate +1284 287 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 287 0 0] + /Height 287 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0W6&8h.rAX4^rgS,Z9f?:g$7(9s8>$B%@4>JQM^V,m1lI7pWCRDkpg8j(64&'EO;<[$LfR,5L]j]e +-t4EYOCB^aV,W(Lb*sME#Z2q%@>;Fm\TPR1bWY^Uqg6UKcZ@Cp_kA?>M-`umcaggZ4QkRJo4AdK*&u`M?AOGK)EihWMi\o>3#BYdWn +55T/#s(KEJh]QXO_r,Q'&qWNA'G2]]D:=23e9kr%*c6u+egX2O&>\RMWaB,`+0!02ars1^J05FO7Dqbp +gN;D[jLKDESWZBA6)ms^I3#a^S>WGd7(EGW3%6%HMV=p8QQj`k4Ct(H6uG:o\EGd/%-O[lX4\=]PUaD('*R70H.AAeR7%=r'rYWV[,DVDo#ATp*fD?3h0` +;FHa%gcf"'Xg,:l.9CkZ(i#.K&9hie.AC=(7%=r'V$jb.(J\P3/U5FgSg4L[,TF[m)/tJsOrt>a77?CW +mF-cQW8I=er2f4!:D/9jOq$C\$pI+%6]d+f,,02FR4.?^MWPY^'.%"4hX)*IZG#kf)GP^o/Zms*uf#- +-Sb0+Obt7n-UgEtFQ''5Ci!@kIf8E2;V\&U06llb_m.^"SJ#=H\7pRT9SuA-OGK)EU3,>o?.dR'n_r3U +Z`pGC-Vj=4&@+!XS6oLtE<#p`pKV@]f;h-<^8LFTR40R/#sfb1M?s()NL(l]Z#sJFH&&"p&J2_F%>bPR +eOU9D#SM,T7$N,YJE=B3p7!1co'iC3cnRVc:TRJqB5H5:.u77L73j$I`(:P<'4#j*bB;c@T&/_%=Yjg\ +)tt^+2.`>ALp:Aa2Md\D73j$I`(:P+\9OC&Q*0,!*si@Kc_1K +06fM..>\l\lId:t6Ae<#OGK)EUHiBn("Ogj(`O6r6+i9nOb=hh-UgFkYraY"dq^VH7FioE +(`OC!6!Qd784&DoP9QaFfGth*l*V>_3pW"uN"+%b+J))\84&DoP9QaFfGtgsl##()7lrFPA"Ad=Z!gcn +Lj,%,Oq8nuUkgETFpEbHHF;[+=f3NSCfl5tiZ4hN,Qrr`.3conh19"*?7iYlegZFm)cgR'GafD0KHLjS +77"o$5%,nXWSgqjN[_-[MFLa3+[3%6&oN89&J +:TkP("m_C@N"&?8q$=M3?P92k,Qrr`.3conh17=WY83W?l]aer%1/#;K34"%6BI"e,,3<6*@U=IC;JT. +:.`CVOOcBMLo#nQ"Go)e,0Gl#JT=Mh(7Zi>PXLH>D&D#SC.T"/#SM,T7$JS$"!sID/N@Os.>\l\g,#=) +VPT(o"Go)e,0Gl#J\4d^(0gk*PXLH>XW#;5do&RHJjc+C&S8uM5d%"d$SI0V8g;90%Ldf==GfX9OGK)E +UkLa3+[3%6&oN89&T:9PF<,jU[_N"'&2C*T#gOq8nuUkgETFpIRt +]ioBkXA]`d2KZ/%QK]#h6nCbP+\9OC&Q*0,%eP0q[G^%IV^,_fkf(=qLo#nQ"Go)e,0Gl#Jc8EJ(-E/Z +.>\l\H8M!Y/4Cg-8An(3;.f/)oPo2bi'FVC8]99.])a`t.3]'a,#4#O11PO$gXE2,&!1p+,0#@21jK[Q +[T@/l+pgOZ:5Xi_@s=THe#NW_Q?>eD`eJl*Hc;9pOq8nuUkgETFpH_c^#dO=1h*#=Lp8*^-!n9]La3+[ +3%6&oN89%C:N))2'MGc-8]98CVm3@j3k/k%$/8An(3;.f/) +UcuJgbY'3kSW\f6+b0;piMD>U"Go)e,0Gl#JTReKru$Yo=JqoO?1Z=%74[9J:l:dHp/49kJjc+C&S8uM +5`4$[o3=]LXOC%7mD&=0Ibn(4IPj#APU4X+^D)f`+;#ti7%(;A&3IRNc9cWq3ZWk?$G:3TD,QA.]K-lK +9%'XOH-2Wm]DSr4:qe[@1').4X,YnO`V* +@JD)S5pB']Lb`IaT\8S[JsjeC*Kmj/Qm_ +opVa'7DmRO?Mc#D1457<+;#ti7%(;A0`Uc[_),Vl%`#s3hVM/frNDN]+^2;dY8fL=-V4RVEDf2h)7out +SR*n8-!7(AX5=ETAuSGN3%XaU>YSOc^74)F,Qrr`.3coV[&VBqbmP=?>e+ldn[EuGoP22nbrRF[9bHf6 +WCtX[/Gk"Kbr:OiT-PRN`(:PtnSI1bmfWCtW@/c5@o +$TEtQT-PRN`(:P +]im'q>Plb\(3*LdEDf2hl"EXIDVV1Zmn5=I[/H8LNK*3RB?m$8qfh1H@4dj9B%Q;65)gfM,HE#9e(($Q +XL;9E0DnSpN8:VsICQ`:s+T0(p`W(dki#GuQLsn*Dcb3Xc[YrclkdG0X`$B%pu?GqcWK3UR%P67k?gRZp;[-$4%Yl:H@t`<.2dL\.rhlXVf[%lHOWU9`Ie:5s]K8Q2njtW!p5<;1pJm)o +^[T9b*)1]VF#Y-W*i>\:/mPojloieSr9"#S#72%F.sg.XYD=Y)aC4U?&&ZqhJ1AP$Du2"QoA1$V,A+46 +bE4a"E!-["OX#=&Pp0"0%8>Y.leK$l42*KIDH],$J(i"3A&q]_N<-aKd=hmr/FL@n0oNR^Obi7X3%8%^ +h07cTi.DPXs*!@6.d=gg=f4Y*5)Gb#dJ;NDP=9DsV%L$mQQm+t*>'YfbBij3=0$ZEqqqF&CMW6g%mDt% +r:k(chG"e5c8m8on4DE<'MVq2]W`!K_gIHe&W)m8Lm+PJ4T4p$LCP>n^?tO6P:*P>]2nOJ\hJ-T.8bgq +io[%M@3`3Hbh'?EObi7X3%8%Uk2th'n%W5eJu<^!iiH(Q%%kJgVFVr/.@27l0c^iR7;^M-M6fs6140_d ++@T!CYrY!j/k70r3[.=Vg855kB:TZHpa!"^MQ4+#K:'2SN_%*17%=t!9c#/%3[Mr<8_c'MZ9c]>/k70r +3[.=Vg855kB:TZHp`sbQ'\,-O)oNu_E^V+K,N>MtD7VE@egXIN:Z>DLdDB+be_tLf3?f'a&TL^u2I2\0 +l]`g8-ZO\Ofc]E-/k70r3[.=Vg855kB:TZHp`qJ^+reJuLW^9dR#ZudU:0='`*'!+)*WmMOWka_\/^Wg +l%h;JC7?hLS97GgiKLcn.C)6%C+`"%@QG].MV=p8'5*jKAb[N'Bo3[D&?E^$j`3a5VBb)rW,9+"ERlR9 +L/0":(Y;&(WnAM<^[tpE*0H'ALc?huRk@C)F\7nWPL[n3^.jq<)oSN3E^V+K,N>MtD7VE@egXIN:KC;u +CR[@Roc(j7n=[92Obi7X3%8U3/khdX8sJ:uV:9G7[Z_p0994eM&W)m8Lm+RAl,(AAVaMCdBs.G@T%cr$ +qkZg!jbQ;u8&RtrgN6l`XAbi%T/`M@nF@;W5[7qGac8m8on4C_Qmk2EgW +HE^Y78AoUM!9^T.;G>)9Up5tPi7fh2;&Jrm[S^$aSjNh +jDmX4VBb)rW,9+"ERlR9L/2u.\/i5aV\H,J6fW2T,,QUEUo8.A0QGYm;2.kY/\M+.cWB3$Q_KqhlfH%G +EB,3Tdh-Rte2CU"39ueW_^AAUh%[Oih^Pis4:loGM8:kd&LU"adtNXb:5L`REc_&GU3F[$7I'@RA.U#@ +_/r)8'X^XO-I+Xub4%E3OmV(DH)*tO/m]Sb@K9(l`(hn*Ua0!cZt0%1DP;UdU1QoODr.)Y6#,e5@ML\t'2Id&'<(F0?! +3[.=Vg855kB:TZHp`,Pu2b!1sAW#!rnmiU`8n9t,:5[c&$PR0D&nUhXM)Mep\)j&&Fgs-9#)V?,Neimn +[ctZI=f4[4%\M3e6*I4,QmOCEpj[V0'umk"PpGB4;&7UmEDk:E?'mV;Pc39o;^icZQ>VT:+o;W,h6b=d +I?5k2l%h;JC7?hLS97HRSm>GI*e7:0MVb%[$KHU"!gF6AMI8Ih:5[c&$PR0D&lmhCm@TZBK:ATZ.&=_Y +_mq9C8EA*=7%=t!9c#/%3[O&lDu+EiXfa^!`!,DfVW]&CWA*UVf#e:3R55iq-Uhn$Ko*-28`Ds#RVjJ' +mjG\d3bMaT'YVDEG@8TU(u@t;?b.qJR#ZudU54joqWQ(e/+qep$PR0DP/Pt(Ztq0l*dZH::!l&h\C80F +8m1b'>1l.6iR3EO`,nD;'Wp`MV+X=>*e""[fB^1G(FIEg-&KM42&@oP4F[3QeT5kA3aeMA6sYn?C;`_aB:AbudTNQ=pW6[nLHus+M_7[IVBb)rBNZ8n)c&WieD\<# +n%JI%?'oM3V^/N,88asC9)T]>FoVJ.ad(:E%qe9H-5"]=EDj0FX&lJG4*KudkF\r,TaTt]N'i3@Cfm

alNC!rL`P(NiT?bJ(jW!*5;H#d.s"U^%um/%u5b)NeeWqMAEYVNK&pu1KNq\$i`Xl +Y=Vu-TkKO('=T6f2oo1`^F:XXLXem*pWU?*M3sB!>M +nuEH>?7ANr-a:JP_B`SO,#4#1>e5%Aobj6gS$RUE$e$!ZPU'-2a_*:r1jm(+bZaMcc4lOK.8,-V-.@Q> +`,nD;'Wk%FVDHdP8Ycl[cX9pWq7Gp=UoE&eq;JVmM/W^dMUcjq:lZ!rbboY0774/o,s:nLke\TS3[.=Vg855kB:Y2Rf0NS`S%+tP=D)Rl_)j2=;9>*/jMtR@?'n#R8&Rtr +gN6l`XAb;G-V2Lo@F:orL&]BVrYocYS>,l+>0?_,>TN6a/kdId,N>MtD7VE@egX2_*2M`O`3Z:"n*2`q +VE^hiMMc89Kn!oZ$$9Sg0c^iR7;^M-M6frK,)[QqS1Q%f$G>;\pdC]UmV$P8(E!(FIEg-&GghN!%ZOh.2q3hLBg_4=1H/AH2_SSO=j3NR6ITI'Iddd/khdX8eSZ>.6a0gDT@*ijbKbhlp4^&2#F2^0EK(=;PRGoe2CU"39ueS7N/*!ZCFdC.7:BT +eJ-3n]&d#Yh\EcdLYVfNkdKC3XoA@Ufg?Q&@&-S5,UGlrdtNXb:.[d6LeF/1L%e7'qSS3WhH[YN7W=]4 +Fl)U2l,!RJ;Bnqog855kB:Y3=+;'r(7E'-UB2OGNC;J_uab:7$(FHq])KA[)2I2\0l]`XtM7?Sa<9=C) +T65D3gS+L-HSn%Ud"MeqUdgjg[7qGac8m6X5pEJN'G\,DgquVmB6ZL['D'M6/kgdC2<(F1D7VE@egX/r +&om<9W5&l%mbV20o@orTg@J#&_?>*],>O-MV@+&MSW\XK&_BI/(2a[rf(E4M_kjj#D7e,Y/kgdC2<(F1 +D7VE@egX/r&oeqgBOUe]XS9,#LE!rU34IY9l[ARNp#4V.0oq`-Gu>k^MV=p8'5*l!KHLlYBo3[T9PmOa +39dGGuU*Gd?dl(\US'j-+nN +/+=*Sn5M#+U1@.ig^$icrVY=X?'r,6Y#F$s8AsVTU88cJ+4[[n\,H65AL_ZVrOk"4"c5!+&TM;RdHhBX +]:fTG2n!j$9*C*]*)kAbNMehlDr#jcE,H1;)`\+ZdRXsiUIrpo]9Tt$$PPJ!F\6u`M7@q3eGO`nG&J/: +)sD,6D>kCGmJCGODj7XPR[s3EQ+_eKtEQcG3$_/kKAA/q:kmQJTq,e7b*,2rg!U3T10(T&=-?`/!5OGGDB7EaOOSbDjT4*T56-)90:/i#t.7Z*!@E/Nq!P4Cfb'P,#FPV*7T +EFl%]eQ;FH?@MY&mT#$\Q6%=B+@X3X2+@161gSspU^Ihpe9+C("GsWSV.e`OJ"(Q@H*8l=2IWQ%K*i5S +OWrchRA-dS@WZ&<#.[LnSfeV(MA4UR7om4I.B^4.D%(Q3'LAI);FK1)]K_4/mS2Hj,Y"* +V_1Zu^t'r_&L?A3.'7bZ]c[0aBaGDl;FK<%;Uis>dHg,aO$tEKk50:0ieFg8l&d)# +-Ul-gFYd67"Go)e,&T(`lKkM2O[gHQHM$D?DnN?_[<;<9jiM%RqsCk"\o_ZCpZo]7%;)0Z00pdWMV9c$ +3\3h?8J,s[85X"q+r_I?#7hl'k*]kj^N/GYQ)a48pY9i]re`=%gb@;.]b;[NUo5SLX2BNWS.lQ:HA_"F +H6W0#D6@0Vp=a;c?+t]3q^\/*RoS3ko#W9Br=rV*\C/tXR1LY'Uo6EsO#6eJ,iYVU\=uod_[fUOI.>1U +mCrJc]CWa&(FH7Ru6#6]lC.3bqM']ngpnc&FS+$"B&Tna\hq47[]RS5'S_Uk>;Kps[0uWk5O@EHT9]5CN:^GE3e.HJa/F +Xfnq[GMsmV)JV*c.kDr:`(GpOROGK*pcIBLSGQ@J2$PIGW6sNkDlM/*W9:%9E5%AYTF8GRYVb^A'pPC8hB^u\]Ko%aHlXc[F3IFCF06m7BX+Lm+R= +A35)D&ogf;>\>K(eU>iOFCF06m7BX+Lm+PGAN5;K&ogf;>W4)MgO7JUFCF06m7BX+Lm+Q"jgIH+8An(3 +EG_U%[qfpVFCF06m7BX+Lm+R-jg.6(8An(3ENQ)dT1a'_FCF06m7BX+Lm+R]/UTpfDT4Iu,#4#OCG/+d +^+Xeu/khe94\5nlEDeUnp%Rfq1T(NlEDf20)_#f7oIO:83*1Hi&1$82BJB;=+;Q6^UklPA.<8ef%_=?6 +Y4a+a8An*IOS$%K/4d]N&TMM`jM'j6FCF06m7BX+Lm+Rl=a3#8)]KZH7%=r'QRYGlMk3ET-I1/5,Qrr` +.2o4?[nN\?j91jY*LOGK*p&Sbg.=HJ?&,3"n\Oo(kSTF2FrC/5Io +7%=sN;t:B,5pB']LhiS+pI28T(FIGXSg4Gq3%5cPK^Yld8An(3ED9?l^?>i.QoJ/oOq8nuUkg9<\g0hb +8J,qM;rk[V+C1?o=*p)A,iYVURjg7O"c52f,-F*umYd+SKo'lY-OE'_:5[[>fcV%UihVC?Gq!c@F=OjU +EN]!\+\9OC&[PNp+;Q6^UklND;rk[VKQLY^>jY*LOGK)EG$AC-=HJ?&,3!dDaF2HMl,(BLg6714&LU$6 +C"Wr)5pB']Lmq,$qkBRlG4"!Fn%;Ttn&"PCKo'lY-OE'_:5Z!tI"PO_Lm'%B[Su8$k_=!1\FJdXNun)E +:Oi5iqF7Oo'Ba++&qWNA'N)'m`eklN-UksJ;rk[Vk'liY?eg,-m;K]2(Z!m/k2r@)LRrnaamH:%5(3:c_1Prr>P%iO/khe94\5nlEDf1l +oc(jHpO@(t,fo)'T^""+?&RJS]p+M9NA&$@@f*W70PkZ!a5ABB +YT:B^Wr-28G4!MA1ImHFq;(Lg=7_uo0QDhCOq8nuUkiU4^S-t2iG`=M.)J]kp"!?rpWiX7pV6asJ,d.C +3tElV17:64?[(MJM7t&56Qeq<8J*J?9[9iDI5p\%7#/\=aPj)#;7CF$38aHVZQfhcn&EAeeJY]C<;lO1 +N>qoma$9"(n%N;PNn)Wfqng9/M(:,&8An(3/$hP.E&b-dC^9EPp?^Jc*S^8[p"eMHjiWj@#7mCeF_]bt +6l.2qn4=7E7%=r'0muEkM-#!a;B/TqL`bA#;M98+FQq6>1H%0NY?nnGrSl:%5Fqb],=dbVr:%VqrZSj, +EJ@8P&1$82La3+[3%6%HMO%/Jj/UitpY9iE?b(R[EqP^Trq>NkG2MS(4\q?G(OWh06')XaTorBCiiE(FIEg,mcj]:5VS/OGK)EihU6jlg*kt4S$SeMhpi4kFR`! +rj_+fF^a:2;j%\;ihVAU"Go)e,#4"rF5t9"$PtF#\T29?GO!&`=f3Mg8An(38I,rK;FI#h[7qGac8m6X +5pB']84&DoP9T"^W,9+"ERlR1#SM,T6kY)>S.lP_7;^M-M6frK6BI"e,*EK_ihVAi.;G>)9Up5t&qWNA +'Tn%k&LU#c8Q"5a@H+@eOq8nuUkg9!M)Zq.:5[c&$PR0DP(Xqi-Uf:(8An(3EDk:E?'mV;PU$Bg3%6$X +5pB']Lm+RAl,(A5-Bl.c!^e)$`(:P4#SM,T7%=t!9c#-OMF^'qLm'$G&1$82Lc?huRkma.'Tn%k&LU!m ++\9OC&TL^u2J8C:.3]'a,#4"d6BI"e,3#DsD9ahT;FD.L7%=sRKHLjS7DqbpgRM^3Ukg9!M)Zq.#sfb1 +MMRIj[Q27D8J+N"&ogf;&qWNA'G2]]D0(GgP9Q/$,iYVU,Qrr`.3_NEg?&eW-Uf:(8An(38I,rK;FI#h +[ETR9:5VS/OGK)EOq8nuUkguZC7@"QS.q*=+;#ti,U#^s8J,r?e2Cs,3%6$X5pB']84&DoP9T"^W,9g6 +EDf1;Jjc+COb=hh-UksF;;7ULihVAU"Go)e+pgOZ:5XjkU:*)"`(:P4#SM,T6kY)>S.lP_7;[+#M3B-H +&1$82La3+[3%6%HMV<4R!!!#)d&6uh +jm;ILO>MkKn;Jg8frUZZ]r5V&$;>m6Xa$RV>cYK/%qJ"gtKHbj:d7:f=CEkc2feZ&dm^/R2k*\Sl%NW( +@rql/f7aSjk&VX@p?[q^q7h6Y'3).d@GMH&td(US9AUEp_#7hn?h"RS:8?]c(lIstGoQ#'Oq!kiNI_5& +=7$2rkX']^.YMF9G4W6%J\TI)adA'3=J,T&n0,hB(b3fr]\Wa(+L?_I(4aV?fC[:G=s*HU]4S6ufI6T+ +eo>i/;<(lnD2r:K2FSYLha^fGhmC-0_\*q@+WN%IHF^Lmf0B0!Zg)RQjN%p;0J)P +#kFS`+o^^0Y=3kXu04+SEGJALV?$Gu?TI<9pR;/J!+uJ%`N8,sqcP.8-PP`0,Idk,T%rD:>O+7(;Fj<5 +IjHKQa&V\ojfJn-Fi%r\AZi-/(m&X)a%2(ff.a%FfJ,QDt0.0Pee:h&AIJ;QAil$]@hu=5DDggs +A`ujd9+Y`sM^A)0&X*(M3hh^%GEKnTjT:pSo@lFk9pVq9F1ZSN>jIH*!Y +WO:E9lo]olaqCd?o9/V+"Xf_QgB0Y_Z5uE04iEj9JrT:4C1YZAtgb^rC7CsGJKAM"Ic0>H"G[HRX7uf_ +*fOK=m,YIh1qsRSune)d?nA,>O9T)U;CL*;Br97",WZlQUjN2c;^%\@i?@)1a-`bG<4nmalh5"2iWDf] +)I-Jp@!U +2]_:&peW\\tJ,$qKo)$]on*IP;&Xmt>iJ3I74'%?6)]K_404$b\il'R)RQ=,`\hJ+]?.d5h`:X!dh690 +XYIsEueBQ;s4-*A?L +OieoIi/(/?bo:$dC'kQ(G@Z9*D?sXX-Ei1[@g&AO'kB;6lO3h%\l-lQ2j?2tN'7E(V9(ft%%ij5[(.3- +bJ,F;OR9*aDFnUa6NZF<-Q88E4b)S'd+92,V%mTu2?Or"QltA+CDH3*&)1I%If4S8765S +V<0*)tZKuH`7W+O"4%2X,jJF$srVPLPIVW`bK+C.*If0!-3e`8??bTc>#^>-Nk:9muI0V$"NRnQER[7B +1\U%.8IJWTU`l=iJQ[\S%+'$X&?[VB4hiE]4r8]4iRD*";RZ=DG\Ha1#i:boDs4>$bebA*u(qX"2Odfq +L89KI0hu;4$K;'WAE7XSk2th'n%Wd4!\aUY>?`1to[2dDQhu4SP\iH%H2D7f13*H +szzz!&,o&+5.R)MZ~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 207.31862] CT +[1 0 0 1 0 0] CT +N +-1284 -71 M +-1284 286.5 L +319.75 286.5 L +319.75 -71 L +cp +clip +GS +0 0 translate +320 287 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 287 0 0] + /Height 287 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WD2;/&)o-G:,X`iPOGFHNaKY5fXHY5nR+[7N$n6O5M*YZ(()%@<+RB9b%h#XCCa$J'b9A.Y +)Fhm_;c-DkbE=Ee/A2ntLrEE<4I=pNF1?F#N\c%<1Y6pJs-O>'1M>n+F#s=]pDNX'.Nt0gZ"Q9'Uu&+O +X/q)<;uQ[nejD^fdB=;]Kc^1rTjR"@eo.7t/_'008&qGfLCQ3-5:poKZ$mK@iYM;9#m1Q(^\!HVU0mac +H?&q"E*Kl9ILu_?59#\rknbMiY6"Jg+S9H"ILuka)PCF?6GE`g(P0r:!W#5-oP8u+&IA=RTO.gg^BWm< +J^CS$qF)P!COgjG#lP[7?N`^1#3ZkSd'!KH73M5M>9"@Bj-kSJfsY6"Jg+S9H"ILuka)PCF? +6GE`g(P+EmDm:P)Q2B.M6%TdXKiJRshM235j7nNtkgoh5+qXT.5edSXILXXW!his'oSYuu +f)Yan&Ge7L^BfLA%F?a0TjIooMa6LX!<")QqDCOQ#_[X9cn>Ho?N]qY5j6f"r?;gL2*en^KROBW0*7hS +"8%L:kgoh5+qXT.5edSXILXXW!his'oSYuuf)Yan&Ge7L^BfLA%F?a0TjIooMa6LX!<")QqDCOQ#_[X9 +cn>Ho?N]qY5j6f"r?;gL2*en^KROBW0*7hS"8%L:kgoh5+qXT.5edSXILXXW!his'oSYuuf)Yan&Ge7L +^BfLA%F?a0TjIooMa6LX!<")QqDCOQ#_[X9cn>Ho?N]qY5j6f"r?;gLD6ZH`8gdYcrN9CN.:I,L(3H>/ +QB?3!P=r*7(4#k!j/0=De8MTom)O\l$7E!gmQYTidkA1,2ibX)+@f`ulpb3MI^t0Dd;Q@V`@JF7U-k*J +gb,-'>G"0#9D+9nRjU8UXo.+A#LKlS0UVkdMG4(pBT>kg=?g,n@7\b$:+8nNeIMZU)F(QNm6B?R3 +@)6nr+8nNeIN,,O1]-APHLtE+rLDP2^X/b53X(p-qreiBoNRAQF(QNm6B?TUKq1$skSJR;)^G-Jfgig( +UYf7D0k^4-0D+J;;Y0%p55KsSrK_0_SCpEId%arTZffOrqLp!h3j"f+qreiBoNQ(hSCpEId%fK!cC'+Q +$b\[sg\Nq:O+*dhgO;lZbWblW?9\7oRPXj)(OCAmf65I+UL36HWaG?XZ]BR/Q_/_j0PC+,0D+h^DfY!a +55Kt>k5.m&SCpEId*$UI8XhO5kSJPJm5LGSAfpt<09c>]G0]HL?g)()h^$O9IImo\/G5M13O=cqTpM0r +;__qYd4b-td;N4NbWblW?J>9Nf::Ma^X,Vr^T!\YqreiBl0UEhF(QNm68+>sVK^>PUL35]Y2<4)R=4]8 +]l`q:p,TI?I\E*oILYJaMh!)CGKts>/Ja9C((,a/f3S-CWo_C`*?D%hJ`a)JCl8=KA8b^1TCn#C^jOF$ +^ISjZn[HIMni\f-,!"*"DfWR)VI(T=.f)#p1]-APacZ(A'/F4od4^Y-ao*Q!cKq<5,Y)>@:"5]dQhc*N +`l:cG5$di\dF$A3naWia4+I8-ace)bAnFBCTRMtW>9IVmfP^iSbeD:Q0+\$(rk*OJk2G:XpYUJ8Xf_!QRrA;lYJ3^$du_:S;`sZq +1Qp;I_hVeX$"8"#2L:K#.opK?[-=?H5'l\2pZ0&Am.Pi&A6?KhnLLfU,/5OWaL\DF4#/Q8O8II#cKj)c +^Z*uG613F47i(FXm?PY$8po)^2p$DdOU;sno^'B/J;eIEp?a/E"sS?8>EB[!pu@Fs6gX-B^R"!Cm6j=) +(#=&fD2msM!L`\OME/!r&,f+dj$oqe.qf6qH?Z`In^\2?&;c?Wc.rmBa/`tp5^4#n>^5T2\7HE&Hn;A)9qI^@N +o4Rl`Lh6g.)"'q3`N\56c'a!*kdTpV;d=-b0fU48"Oj]\JOMqlAAn6ns&6I)**f#*BB3M +:W]lFl84%N1LchH@M%n853IgHn`/!F)G'?sp=S<2=e +p[$S>ns!Z5pLWJ%W*p^J+OpbqfV.Os8D]>;spHeek=-LVgNTFO,s1]`36l@6`03g@Vji0d7o/I6/4^(b'_h^ +9OmoN>s8_dm-Jg;%h9*#g&eD(idOfeBD1G\?eNPr+"&E`AOh1/NAjHEVj=r=muA0I6`M,br:AgGrCS2Q +7qSIB;mj>hG2@Q2/NM,!MWDuJX +7*CJcn"NO`ZJY<"R=0AE=5K_%+YunSnB&UKg2VVWdJmsj]=ZgGTd9N>"=6Q0q=0qm^560lC;4e=a,V22 +3lAkQEajCfkg:>e\07a,g"G%)99r+j]tM,Yj"Y?D#J#9[G54uF`3M#;H,G@GbEa`HBp0h.e@_, +p:Ke-CMR^,hf&CEQXs^pP'6JQ7'c=Qjicc%Z<<'AQM$a43O:@LrQ9"2F(TWAV)<&>6rQoH%11)R8W[.m +`JPE0>VrgZfFP#cfj',Rl@rD*VK^kT*`mM +>4da@47gkId71T^E%U94"*8']k51-/10=CC$$%__+snW`)LZTSCM[f\3WH1%mBRL1QiGZ1l@7BAr`n3' +p=X([Y?p&KBUb^KrFTQbm)r2>W(N)t14MK,i.1Jc/no(8R@,l.kVp!381g$HRC#J6+jF8UqT[Z_fgif& +[Vt';4aZlr:JY1*jF;55I]g"Re:5F(QNm+uo_uS)HB6O+*32U&*%-SCpEI8<+hkAq&%lUL,:% +ZJV1rR=4^cjO!OgT/j52oDPQbqQUFWN42ib)4.2MoUDo!DC"iPVZ$@6$e('D2@e.7oeY8;f#?dK[IuaAb^T_S!egj`sp7&O99DRd1 ++kMd79M\I-n*\i5,J&\$XfK4V>SX]mX3S^<-LWI2O&m<3WCFYm(Uf=VHBg!\rqTFJi[s9Pqr`W;5IOZF +arJi8,j3lsYMHEk6aRfa\ccTgV((`Cl>6B-PojluK.PR:2u^\&0jCjP9e$,A7LnORh]uGk<_aKCFe,(o +EZ-R:maD"`^=KmlCWodelb)M!r*j79`Xf@SUYkhSgW"'Cb42k*qK83gLOPG+rE)##N(tY;JHH.Oh72%d +?Vd1O;D\]Y0^#A&'.NslI,\HQ_R +rO(5:nRJ`nXd/Q`cQK"+chcBArkc,9gH9cF2^-e6mHs;SlMoSmgZ98%kFp;.[FWl8CHW_'juVC'jnWim ++T9L0qV*:p_RB*k4IPXsP(`/AcHa_X1!Z=n<`SJNY;'+4X`M_Z^U5R%ZL%.goaJ-$o\6>BoS_e*haZ!H +P(S3&7DDA'qJ?rF+uqLY(5p02r1RICL[:#$k-H++da9_2KDBS`('."dn!s#cV18J/)#tG&I]^sMo]Xm6 +rBcQoXjA`nkgp1?6B?StcnG%Tf*_ICO++4X0D+J[$N3;PI]^sMo]Xm6rBcQoXjA`nkgp1?6B?StcnG%T +f*_ICO++4X0D+J[$N3;PI]^sMo]Xm6rBcQoXjA`nkgp1?6B?StcnG%Tf*_ICO++4X0D+J[$N3;PI]^sM +o]Xm6rBcQoXjA`nkgp1?6B?StcnG%Tf*_ICO++4X0D+J[$N3;PI]^sMo]Xm6rBcQoXjA`nkgp1?6B?St +cnG%Tf*_ICO++4X0D+J[$N3;PI]^sMo]Xm6rBcQoXjA`nkgp1?6B?StcnG#0lF0kHp*5[%XtK#`+E7aB +_Q!etn&#/\qDnOANIJ"V0D+J[$N3;PI]^sMo]Xm6rBcQoXjA`nkgp1?6B?StcnG%Tf*_ICO++4X0D+J[ +$N3;PI]^sMo]Xm6rBcQoXjA`nkgrG#:p:uB;NH:/YiVS!?=\aA%mBV1.r9LpYnpPOb7#+T7?k9l`\&=$AGm'f@HDQTi$=>rV+-\#Go\#*dXc"^LtlaPmtHKk>(kB/MVV",EFt8e^YE53& +s"0DV_nM5QBMJQl5P:++MB**#KNS4-fcefuh2C5Q&A+0>.2M]C_"bC@+H1b`s92*BRjp]F:!":>*^bbP +qkuqsE_8]B>c4/mc1]^PGa&004CLV#:#<='s(0Zut]c]C*7'-IO\+1T#fLVTOA&rUsI)n`;t5U)mlmOW +8Z.7lgC.H1g.6LL5K&t@h +ti_ZDueH7l^N;4Y$1MR68Y;I=6P7iIC:N\]5b + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 0 173.19932] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 357.5 L +1603.75 357.5 L +1603.75 0 L +cp +clip +GS +0 0 translate +1284 71 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 71 0 0] + /Height 71 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0W^M4I0*6)FU+ZEdT"9KdHdb/pM2ATNL=_]>@Jt6:7&.;]6@k"iQ5\r#'h9J>19i,kbZOm%uh9=1A +rU&moo.\-L',-,HDbaUs`j7H$zzzzzzzzzzzzzz!!&\32#mUVphO\^$ZG/00k)W,KTO9SL_<#uV]p.2C +<[bGV]n_=M4BGO+XD(X,,_0dggP4QU4eWLWJD0R,,ZW*.Vd3K-Dr%[#`5(/-m9jV.O(dbf%a\S.\_TXa +Jjt.66`F=4)iSh40"i`eujA\MR+d#\83>Jr6$^5X,.3TsW.\_TXa +JjucMH[??aZ68`&/$u<;*mh7<('JMXkCSPS5W#cM4BGO+XD(X,,_0dCghA0.4'X8:.:BY&ig\h;c.>=0 +KJ<\&jde?,"`,tS;PCeW&7eHS9%:/+d#\8-%nZ]7H@FtROq4Y3MhCjaJjt.66`-iq)3N&)Q&ig\(6:g0:6r$1Qftug?;b@=PS;J^<,]Y@YV +kVaY@<0XB"$D'^2OjYc*?9H3r($Kc0T=$a-%nZ]7H@E)bj"BV]6E^-IJS'M>M?sTS5WJ`F7V#eX&mWM> +e0XpI`ipI(lon6#`5(/aJiiY-RU8P*^&*2h7`NsRl>8/UNjc4gVW$A;\h!U]dl#0l>*Y\NFLJuEC:*VO +])iP's6g$rVQKhqet?(q=3LcHp41IB%O4ns8;]aZF@;saZ674<',I(N+.^45!4iR+XD(X,,_0CS=Z>?m +d<8eqXj\e^3ob)XkdX9Sh5:*>F:q%3ar3*_g0ng^%;j-1,43%*)T$njA\NB7;M_qp$:qqYNPNQq6,2Gr +k2OJNupSmp+Ed-M8`:Ps,fgSnQk7GpVN!>L"'C68:<[lQ\ek]QOT/j&ig\h;c2btM\k4'4[)&9p'.rZ_ +^ni-U[O%^NSqBep9#I@h#m]TAa#^='3iEQ`g7.!&/$u4F&ig\hRrUsV&3`9AhV[5*IJ``[aiWg"* +.B$-_e[(%^K,`;F,<,RHTb^_p)5[Ko)F'RR?4A?,'#.Ok32#BDf>+4h7K_CnI]_84mMXY[P4cTfcW@XRfWbgMMGGN'Ybp^.$6Q^20HqON=DWS;PlQT?m9*p28]tFnDa/n)#dF(L*7kXh-H\; +bF,+P"!TK4H:g5,]Y@YVkUT3HM-R?+9)3-iPT6q@LMe6@Jdo%V8RnG/7O(gEC:*VO])iP't%W]Z]Ju1k +EHU36aDM.kA`lr+d#\83>Jr6$^:#bkEHTf8/=nIZT;/-G'7 +&,iiQ>[7oK?"QMKLAR(jAaWt/Na3=?QF2_.FBuJ92C*TLr[?lL_<#uV]p.2C<[M8\'9;]W,kRf%>87(O +.OB(-%nZ]7H@FtROpX&S,Ab=c7(%t(6V*K@NJ%(&/$uES0]o*TNYf@Tt#K=iBIl^V]#e&jde?,'$Vbk +W`KG?*+~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 173.19932] CT +[1 0 0 1 0 0] CT +N +-1284 0 M +-1284 357.5 L +319.75 357.5 L +319.75 0 L +cp +clip +GS +0 0 translate +320 71 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 71 0 0] + /Height 71 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0Od:pKp'L]cT>a7M&QE#'g#`*U_17>-"ES2SMhZ*WVzz!!!#7;nRX9WP8f?PfpD>U5I.#Z_E?#Za6 +B`bHnOLMT`?4U5I.#Z_E?#Za6B`bHnOLMT`?4U5I.#Z_E?#Za6B`bHnOLMT`?4U5I.#Z_E?#Za6CKH(O +[Bpj2e=>h;t?JZl!/MLO7C\"[5QqQ8tJSUN*cAZ+FCIbEtpU0i*?Xlu+BIOk8+Vr*A\g$,u??Zu:Jka. +ih/,EhThhlm9l*mBoG5A?)Q^rRUqIQS^MLO7C\"[5Q\,*f5SDuTo-h'+YH+n1m]8m'/\GUiEl*mBoG5A +?)Q^rRUqIQS^MLO7C\"[5QqQ8tJSUN*cAZ+FCIbEtpU0i*?Xlu+BIOk8+Vr*A\g$,u??Zu:Jka.ih/,E +hThhlm9l*mBoG.7>H!A,)A%f~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.60069 0 347.4] CT +N +0 0 M +0 285 L +1283 285 L +1283 0 L +cp +clip +1 GC +N +0 0 1283 285 re +f +GR +GS +[0.6 0 0 0.60069 0 347.4] CT +N +0 0 M +0 285 L +1283 285 L +1283 0 L +cp +clip +0.941 GC +N +0 0 1284 286 re +f +GR +GS +[0.6 0 0 0.60069 0 347.4] CT +N +0 0 M +0 285 L +1283 285 L +1283 0 L +cp +clip +1 GC +N +0 0 1284 286 re +f +GR +GS +[0.6 0 0 0.60069 0 347.4] CT +N +0 0 M +0 285 L +1283 285 L +1283 0 L +cp +clip +1 GC +N +0 0 1284 286 re +f +GR +GS +[0.48 0 0 0.48055 0 381.51931] CT +[1 0 0 1 0 0] CT +N +0 -71 M +0 285.25 L +1603.75 285.25 L +1603.75 -71 L +cp +clip +GS +0 0 translate +1284 286 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 286 0 0] + /Height 286 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WIq[X3IJE=t$)JSLN0Z69.%u,-/3F/G6Y?rt?!;u^j#JYbg=;/"#SA<4@GH-XGSt6&U9p#*'H8". +j>?H>F5iu2Asa-"`-"qH-?VJTA2-Os,f2*RL+mcj7>JWrI,>n[l0e3(p&=0(4W]+;55OL8M0Qa!^/saj +F16(kLCG1\XNU(+S,N38^M`]fcjbXrS;Q<fLf70ubeh;$Vdpqri`*9gPn>uM\18GJ]CIE/\qEJAMMP2. +dEKJG=f5dR,iVe1E[uDZ\2",pqFFgU8AqK`3#*1Q/52RV8es`;:.6\3JG/7%B-j;c1rd_SfTTA0E5X<)hEG9u6'uSd94#8AqK`3#*1Q/52RV8es`; +:.;X]:;Pd!]L"q/:.<+#W+]dOiiH(a&/&tG?;ZnZ@sL*,Wq:O,A>(4,<)b]\0QGYm=U9koSup'JS6+$k +6q/XM:.7T-$PR0DP(f!RlbSII^EVC$K%Hk)6R"T,&Z;@tR>$L(:<>gn`:[(u9s,)![\rT&q>`TZ:PD2& +<(*76MImVNc8m6Z+VE$L(:<>gn`-$JsBaQJX8uCO@FaZf^!u2EG +U8"'0M6ft!6:f%;ECFRKDKLF\;fHnc*"qR,7Du1(BP(]4XAcD9&ol`2;3NH]eZk"YXWas@<(*76MImVN +c8m6Z+VE=S(!XtHe@e,5:J**9pP$Q^;\="!.[jM-39ue[KLB'(j#/[o#i\5CN017glQ1k.O%VV75G;bB:Y3>OGN5@ +MIpI4"pYCH.(ZO&@S!jF'bR@ZA\L7Oa#=heBFO+Q-iiH(a&/&u">EPh9 +4%n=_6jHR$E@ORuh7Ajueqo6?lB_8Aq6]8Yn`*8dIdF>[*dQh/lHNt5Gp_o=4$23\cHX5E=f5dR,i[Oa +U:Qs;m-3GOet+&4=]@eZMNW&DcD?Bjm+J_Q)`M]lI.6(1\i]ZZp&3eR5PX=nIsLn_l##1`IJ_dVDK=oP +@H+@eZ4IXgm8f@IK0*&EKg[:d&TK9mVP^6=`0uG9g5Z(0rD;W)+^%^B!Ep"BBWDk>f +KhpF9HZuM$JSlSUinCE,rVQ>=p9UAs1^0d/BmZlkNFfIs89?6p&_G2@X_ej1[r:0TX]o.[n\t>"q9,*X +Va'+JD;1M<_k%Ykm\p.u71MX.Y'he"H^Uth$[U1Fg*\.,Q\pSt;)19t]u&AlVr;jIqhVF_^Y[SopVS*P +YgK#2Ko*-2a[/P:[6mB*?Pi+c_4@DC6DDr.Lc?.*rqK)g-Vp==[&*J2=qr^(o[;0#OMCIjDsc;gYL/o1 +Ko*-2a[/P:[Ci6FQcVjpEGLVmeS9A#F9**gVkT&S]6100%smB3g%l'E@N/-72;#MPA+\nG3i>A>eYIQikW>pFYl:3rqsjYaJDOr.Q8Gr +m'4_1L!uX"Za7Qe_tW&#g^:7<]WI,N;ZjS;Oc^\6As:%$R`9Up5t(.'4J,o)E#O1S(dQZ5&1:.<+#W7Ji&_M&@6 +W`/DmHT(m\V$aO_ERlRA#`6(aY:.Z.9*\m$#Br5,,N;ZjS;N29(+.< +o]p0BV^(2#7%B-lAel`=3[G.W&Q_dtF^GsP%DlDpl%h;6&Z;@tR>$L(:<>gn`+?-NmMgi.QFstdG2m[4 +S;N,$;:3V)`*'!K+XH(<<`Jf&_PAZfOYE\,X_DiPJV]t,"<&Cp8ERlRA#`6&k$L(:<>gn`7;!2-)4TpV^(2# +7%B-lAel`=3[G.W&\#-A;Q8_L=fdq<&TK9E:.7T-$PR0DP(f!R>?'"u.qPR)\5gR=#B;dK:.<+#W+]dO +iiH(a&/'!5MHhp*#cAp,<(*76C+Utf9M\Gk]68&E4j2sX)fNCZ]ANQ>IF3FPBLf4n*.]Q&"D&QSRS2a@uQS2XUPU>1JOcd5%:/=Z`4ibR^DVi&%hL"^V8u;Odr[(DeRtZ^*:<>gn +`9lHsh]PU_dh-RL,#1QA4*Ks-*ZhK@4E]pgRUKi@AsVl\kbF4,hS$OIoBj$EhR[jqq=Ebgh6U7O39ue[ +KLF28cVAN&B\(2fLc?+]VkW8'X]oLKSX>eCDOI,h:Kri$5JCgWRl>8_m:X_7=o"VXKo*-2a[/Ndq!97] +E]PC>7Du/R3HsmrRTRn-4^5O$l:#9$#gFQ#.egX`- +M)FnX8`\uT7%B-j;c,;-23fN>7@1gTn*`J[i4u'Mc^["Zp)FthHMHHS-RL13I.GCdgHuK7eDtAm)ceCN +\i:%h[!VQ8+NUb,MD;q4$l+$[JNbEg;B4*U,*I/.fH +]/9s0B:Y3>OBC)>+!Rd1Z4IXg.O%VV[2'Mn/mPp5r:>Ljb2r2`Dn\4n41jjNAms]#;mHrIbq6V>o]YN& +U4$!/(.'3?7Du1(BP(]4XAcD9&rkE>m%j1AnYLT4Lb+3IS;N,$;:3V)`*'!K+XH>VeV=F2Lb+3IS;N,$ +;:3V)`*'!K+XEARq]Wh9#3";d+ql+3V]t,"<&Cp8ERlRA#`1tgI>Dj++&NVQ#`1MU&Z;@tR>$L(:<>gn +e>bS90DeZt+q#P+V]t,"<&Cp8ERlRA#`5SOnaYb6S^`IQa?iG9WJEMK(!S:'S97F>6D@q2FEDAPn8/o& +M3*Nl&TK9MRTZ";l]`rR6rGM"((J,pbK><>7:[Pei`&=9MMc!]-I+Xu$R)eIZ]djK7osgD.O#6D&Z6i4 +<)b]\0QGYm=U;!nebp'OLeZP%hTj)+4'gg<(%Kg,#1SFWMjKB@H+@eZ4KnMX#gSW5!,_U'p433Lf4n*.OpliQoODr +/;2NTdNEqh&k*5G[oGgC66]/n`2T\KAms]#;mHs4=/u-@_?CCc[oGgC66]/n`2T\KAms]#;mHs4pSg4[ +(]#(N6l&*5:.<+#W+]dOiiH(a&5ni4+!30"6\Lq*&QoBr3#*%'U8"'0M6ft!6:fpCFEDX'#N=De+ql+3 +V]t,"<&Cp8ERlRA#cVU(8u4t/E8%T]^KO':+XH&H7%B-lAel`=3[G.WFbcfcSMWAg\o,8g7:[Pei`&=9 +MMc!]-I+Xu$R'Z(\fW+Y5!H]Pa.OW^&/&t4,#1Qq1CFk/SW\\g3a1?*\@Bj[C.(L$+XH&H7%B-L/M&GH +:JY?0G&;s1ccs_Jp=a<,pG!$hB:Y3>O?1uSIu&%W.O#6D&Z6i4<)e#$aH=3N^(#;Qfs<'N\]aunhS"7p +D;*Ke+1!Y@egX`-WC+)>+FIB^A0N;Y<(*76.OHMje'NF#`//NFI-K(UJUrB7OcecjP'0Sb@MWPr=Jo[Q +Ue\;h6\No2gqr)K&QoBr3#*%'U5BsQFpnll=)XZkFXkY?1G^hHp4)D1\,-"!LPCQ-_Q3k*PUqL;EE`#Y +_G-tb/;-E]MMP2.EpM;Y1pKeL9N8LFcd/L@a,_=G]77@rIcQV]*e4+X["DMKF^Uc'Koe>g$U7%h#o/SV +OGHgIE@OT+SNE/bf!B#8eo'9UH1Sk)#OCf-kg6$,IeBa#DVQoRZTbHhZ4Kn=C$gZ]2k_G$&/&t4,#1SK +eC7Hd=OTZC]4p8HJO?182fNA!Z@-KJaXZiof +:ISe;,iVck>VB0cL0=<6c'o5+nA(*7r8YpocO7'CNr"6+j<18l2`!72f+P3sA9;*,+q#P+V]t,"PY=kK +YOFEt:H\0cQbN*g[-,pZhu2teqtg0;(N6tV7\`%($PR0DP(f"O>[)W";BmY8$R$+[,2uRDqr92Ja/Bl^j +qWXn:D;(5g8D>*>ZWWYTl]`rRe@+*#Z]c;)&QoBr3#*%'U5I(7aY^@G4*I]1/ml89EF<1I3Z=VTIstp= +jO0kt97P+]KioMK.9QqU4Y=?XFP@;B[oGgC66]/n`2T^#nDV95I=7C44:_l1c-=L5[\#O!,&Na:RTfP4 +Ams8GF\3E9C,[q)1N!$B8WB[)/;-E]MMP2.XbDI_$PtEpVr0,M_SfTTA0IbW;KiZn+!5FoE@jOHA0E5X +<(*76MImVNc8m6Z+gmB-Q],gkcVA4C7:[Pei`&=9MMc!]-I+Xu$R)p7Nqht:7T;bk66]/n`2T\KAms]# +;mHs44'6gNkVNRSqOgkT7:[Pei`&=9MMc!]-I+Xu$R)o_B3d:(/esM&OGHgIE@NH,=dV27PUqL;6?TJr +<@X8;I9`hM,-hamE@N/-77B!?'5*l!KofIa%DkcAPh#c"N35fBA0E5X<(*76MImVNc8m6Z+gj`$?8B)E +'p433Lf4n*.OpliQoODr/;1D0l$L(:<>gnl_\I#PdQa5a?iG9WJEMK(!S:'S97F>66HZGIhB9IeMTA+T`2SPP'c"tE9Up5t(.-0BGMXITLl08?8AqK`3#*1Q/52RV8esb9 +V=#]:GO$3$(JtcI#`1MU&Z;@tR>$L(:<>gn=cAE&pXC.8(JtcI#`1MU&Z;@tR>$L(:<>gnED'XTh=Y[t +?:74m+XH&H7%B-lAel`=3[G.W7J,pcKGRJt=U9jD'bR@N>jfWp)G%l9LEf`]/9s0B:Y3>OIE-FFE$7(i'gU5 +(.'3?7Du1(@WHKE%BV!QS1'`IQS)P^(`4)-)6(72rr)`'Ct\C-9/!,)B4kjMV:,>:huE,Vml%aiZS6CM +.9QqUOh-n$lLF1/2khM%&/&t4,#1QA4*Ks-*ZhK@4E]pgRUMOH$C[TZhmd[dOX!Ar>HV8DQM,^kWM^Zj +ZWWYTl]`rR<0u3*YDS4Y6:f%oLc?+q[r1"o'C3TT7!2.kH./)>a,_n-F)Gm`o]ai2Za816$O[>VcR5?4 +ZI,54Ko*-2a[/OVbfn;dGMdg$PI2ki+q#P+V]t,"PajgZ/krE[c^q8p\9[].K*Mo>qm0'_rH.nh='pB` +d10bsiiH(a&5oXA:BqC?%^u5Dg7=,B6:f%oLc?+q;c?V/@SIMUmDf/)rW)SNJe@`'[\ +8u87\82E$jr[S$ka#9S>teVD]V<(%Kg,#1SFollX*p!"$ST/sC"&rQTqUV$n85Kc3EW1idGlB-qU?dW +a]arNYD?G:7%B-j;pjunYEX2#jN0hpC9OL7ld2=ml+[ +.O%VV't\YVg:MQIok'uF<(`/m5G#Shqlrc$L(:.E95g$Sdo(rhQ2P"KLD>fLf70ijQ'hi +>)s[c<\B^l?G&6O0MidLc_!Ed1,A_29Xm +OGHgIE@RtLI/%Yf?XMo(c9jrdF)uDfm3bZ!86_sgVUF'D:S+Y7n`M7f/2dkLB:Y2S:PG%1h5-_am-3H< +SuRV+#`1MU&Z;@,$O[=Y/mP>M_-*.ZM6ft!U.7P=R@3SeE,g3",)R]mi`&=9MMc!]-I+XuMd?[gmM,$P +i/DuU,1_=,Lf4n*.OpliQoODr/@mp=7N\&ZZ\.l7mYY+*66]/n`2T\KAms]#;mPW(()?W@KK.r<\u2.#5Y/hmLc?+a +bq)PYF\3Di*E&(MfScKU;b'nWq[aB[.O%VV75G;bB:Y2SkD%Js$ML4XFk4)9#(RXu2OE(b:^7C43]&Z6i4<)b]\0QGYm=`d\8VVq0t=V]>mKLD>fLf70ubeh;$Ve"1(+Z5[>#6tKH +AnG4pJ3C#5.\b/oM)Z4^VkToRKo*-2aeI$IC3"GJ;fMVIo8;`G66]/n`2T\KAms]#;mL)kOIAt]/ed&A +g9r1dMi``n&TK9MRTZ";l]`sS0I0S9a(`GKkX7`]:.<+#W+]dOiiH(aBWI6C'O3,Q9YhaIXX^&d$&LVV +&Z;@tR>$L(:kB'*-66]/n +`2T\KAms]#;mL(.8BX1/SA++VJiee;&QoBr3#*%'U8"'0M6ft!@\#kip5*0UE$oZe+q#P+V]t,"<&Cp8 +ERlRAXA;C1Nke5c<:Y(n%cqe#(.'3?7Du1(BP(]4XAcDQ1o+\i$gif/mbi1T(.'3?7Du1(BP(]4XAcDQ +,,CJd$[gQslXGj7O(\L[X?WU-Z4IXg.O%VV75G;bB:Y2SY)k.)mn-&W:BYk`V^&JY&ofBF:.7T-$PR0D +P!q(#ap:*h34Qg;fK4\sP1("G#`1MU&Z;@tR>$L(:G0jq:>o-CRgF+6:f%oLc?+abq)PYF\3El6`LX2V,D#]_f',c9uF:2!r!h8,I.jnE@N/-7;K66 +YV84'II5arAbS"h'5*l!71-"Tq6'"NhaL@I +nu.MM[79I2eJS3dAOI!Q\]on:o.S;XY^n?Y7%B-j;phW#\ofMt^(V.neLgCao4cDt[20e^nc.Soh?`nk8+rr'g.-L#Ol +2NWWSLf4n*.U&+:WMq]^Vhqp,@t0".JHH,qrCEt2$No5OZZi5:d^F#I*kW^l^1l^M)]LlM`9uHnQYqIV +;%Zq:M)Z4^f?4o2cRf!@^\<)-&e&..$Ec&j'5*l!Koh*h&QoBr +3#*%'U8"'0M6ft!6:f%oLb+3IS;N,$;:3V)`*'!K+XH&H6l&*5:.<+#W+]dOi_$%FWt0c!+=,rG6l&*5 +:.<+#W+]dOi`&;]66]/nA0E5X<(*76MWQQcS;PBS8AqK`/;-E]MMP2.dJS]T;\<.&_^@RnT)`LeI)B9_j/%!h37 +;(AeGOMD'Rp(4SFJR%#a_fe@CB=iN7:OI7%FsjS +RO_BAl\+sj<8_j4*Ks-*ZhK@4E]pgqO>gTbd?eokV2W"o,BW+4EBLRF\@&5R4:f>,[,FlFKW+0H7KFX6 +UO4Q@FjAa7j$R#H[#/FgMaj?FmIWMkKgX,OQ]*s'U0YL_A_@,Vc26TP]=m86":O_kuo^CDL%mR^?M +Xcdt'l$^1LYUS=\ofP%!@K3@Wa!mn3Ggd*r-/U1MU!t92g>,jl.ObClB[-XKiHH`:HmIKUS:,@bN258H +0"M9+&?MmZS8G&oB+;>ni:dR9WJ\WNq_19O/6npp#\'V4Hn3nrKe#ZqS3(-^TC_Lrl`(S9DYB+MXcdtQ +"s?]LYURR4*N=U!RI?#>J"nHk04,A*c0@Md06+jqWZM[X097kl3!aO*'/3*X'bhjN>jh#_Q:R(YIp#n5 +-Ma#H4"BLcCJ>Ans@D:`k3OW2+S7>qYL&;n:Mh\ns@*b%mII>g\1#QJ%O5970c?sm`h4[Dr2FFC8VmZ\ +QQI4'eSMjGL4jh<;H\L\unSRJ,b'%#?l7@FLhhr/u405"bnnEGk#6SO@`fKKis$aB?m<+L5(F(Ie_lYM +2FFJ]O4Pqrd]f45ZjO?8BCoesKkK.L>RiIs,$$k3YKQ)qe8:H\0D07>:?Ni)7>mWZG#f@QA'GiOcB>(((+N +0djsWH.C`g5R.jZ<1XZe`pqmjg'qJp`']U>qCX?`1p5hA&b1lVcSijPsMuSLVC)o?W. +$aE!j,^\G5j21b_o!GY0u^A;=0>e"btLl-eo'9SFfUC%Q-0,+=nEEb\%_O;IJ``GlB(3hMl%=%\QOQrZ +`o5?H0s=nC[^,neXJ2\c5IZeIQV1?H]<5OXbDI_q&3$nrUcs]S'i*eH`I[::,4dg=Sq6[X&lL9;CeeJq +4B._4S)6hbKZM8dhuk9Coi=\7;#aa`H]JKC+ZR/6gj:j+8gQRfWfJ-I.?48JUrC+FUH<\SXiK9&@QN7r +k^$_Y(-Xjj8Hirc*P_[S,Q8HFQh*Lr;=1q^AH/nIP^r7G5_:1J&/B+r,bEg;-B]m[3Q +S2]`ob#SsDVVaAi4so')`Lg$,Q6>3YI45"kTk:Xhc4T0>Cm1%G25cd0n^0&>LOeZ7"ZpK[R_s8:4C/A8 +S(55OKq:9J5o:&0-fChkd`'#k2ZGN0Q`l@ +G\qsMUFr/8>bMtc+YIr2q7!!!"^YCHN:Bu'Z$^\unDiMN)cF*%BZci8C=4nj?oMdNQG_a!t=:XVH,oj@ +`!pZC3-c/8HDk%=X^%^C\cpJ=4IPh**!57`s5Q,:71Xg0PB_sH3nV^ +1kl;MD%XkXm6)>Wp&5@+6UU75r)nlb``ro?khp9h)(DuT(;rbFRWs8MKe%NYTM!!'^s:]L&_^\Gc$f)8 +XK<(c3?s8MKeIf8S>s2#SdOM:_:=2+7D'2L0jRJ-RGDh%ZIJ,\VF3_gXkqtm"4m^_VRUq&?WZ>'2K54b +2UHhXCaX)&ju*PM4(Hde%O4.2P+)QDogrpK7'Sf`@L6(31^*^*]?cOW8<0PrglkYQh[(B=F8\l?4FY'o +kbOYkL`On8D3TDsuPplFgs\)2W.hra@^>? +VSJ(d(@0p.4Y1`*&]2LT@eH?sOLn=G!p8U'aN47Cs/c[GQDQhF*;S*jg-EjGDkdUYKt1fXB[#QOjTDY* +l)n#%o3TDn)Il@-2tK`:VA5J>nF2:=.lpgVr/%DnC"BtbW0*_s%\RZW+"pO@\]hS%I3\oQn)m5)C*I#W +6ZkO_^;?tqWt+hH&,%fcS09t^)C4))q:hY4`cpU_rGKg5@jK0T:O5Q(HB5JM-o^,3eTrG5Ps.$jfY0ITE"_Z%mKbrjYMtGp7\1RpYUIM@U^P;9H- +4p8UpD7IoZsJ,BKA.ogNq>g`IJ!I/cOU +NsVpTY5Siu?(oYl_A^=_XNf?V6-Y+8S';V&*_a/V@+fi!/S/H>bN=Lk((r9'?mFj]o4s7_"=g]-4Srh4 +A=aXmA4/$F?^.po9)'(P?N6hHZr>@qM\5P;!OrSp-A@s.\AldsUWX*qa%dbis^Q[egteXJa$#ljsUTWt +c,1g9n3TDdI7cTe$+gXE&rVbsq/V=LGOmA@5Z>Aq3?^.u$"47Bg\/sjnS3HNM0p\b!Is*aapnF1B8LXY +bid75:Td5^NWDZ9@=^THA7h07cTgiLfTrV#!jO0J1im2u;j8*U#&orDHUHgeYUUG2`K!3AJTJ%'7IEnA +@[Ykc!$I4l&$eK(*n7f$a^qq3(knK1h]2GLf1p?\aed:ia?[r5X8IDj5D^@6jAjectRq,HA"II;/jHgP +mpNBHaL'@m!5^4#nUn%YLX^Dm4RJDU"YLEHNnk + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 381.51931] CT +[1 0 0 1 0 0] CT +N +-1284 -71 M +-1284 285.25 L +319.75 285.25 L +319.75 -71 L +cp +clip +GS +0 0 translate +320 286 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 286 0 0] + /Height 286 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0W9k[en)Sg>9PV,@]i'L\)\-Q'G.4K_.7AU_8(CI"u#7N@Y&Yup95nk$/],%5R0d%2s6!B22cp]D7 +;DeRp?+?!M+9ZCO5u^1u@Vs27Bt-OSSBRPoREUjgI_XFWSE]:-2pZtc:?]a8!e&O62RAac\i2Z2R_=@` +WmPKj07e7A^KL2%S:7g.QT4qUd4]M9c(\S)oUA:a`9B4=IYlNlV:ui[m-jX/VVb"#C1(k#KRPEhWe%G* +&c/V?W!:7B8*IFFTc+bP*MM@_L2(+4FbG2o)6/7meIhY[A>f^P<_)A_dY8dBWMukbR@.ra3B]P(j,ZFE +J&`#1eU=.K8fMrPm^V;;rVQ>5o?=i7]'K1TT9'#4)g8:Z6GJdDlqlqjIF2u0%6IPc?!m5.Bt/r`qXs/m +]^a#?pYS1j19tWCVFM\QjQtR+MhdVl]6E`#aiVYk?[d:l/`lDs9:&g0=mWVfVq`]`)&jOllDq,fn+k]I +pK"IUrDmYTW\;*]U:rg>nA,@Q^6Vs)G3>E?*^+iAbaC77:7TtJFmJG(hgXtH[=s,(>Je&Mm^o*=o#[l1 +W=n-A%mG6qIJ9!b>=V>X4*U*DB/k)$=K/]uoC'HomX5"O[[QXK[o3*"^%Kr\KDE\MI90I`oF%(ZTAR>/ +pNuABf6ZN=ackh#Vb`pkB^>ELHgbeT4$,N.Si/;Xd5kI">n"/aP*1+Ro67OkFAKZ:g4sEVqH`COeZ5TC +SU07K(Wt4LNJ4fiQX'uc&'<-]qeYS3H(Spo3d:!slQdLrhp#3N4oJDr+0&c7\(PS`cb8G_ZlIo-A]nSE +4a,QerP&=2qb)FtIr8s@?2F/noB4H/:=A,!h/"t)dr2)VTdj-+fb^so;RpgTqLr1cFK%Yh5!D.j3VhEJ +^Qh;]=Y'1Bat'YHrO!/!o[(=#qcZK?qsAe1DRQ#%l*o(P&(Rppa):e;e``\oLK<]L]QLZSG3-l3Ocbds +jOV`$IQO1:h%4Mt!9go?&.d=@e5Z8/%NIG^J'1>(I8iDiQ:F]A4LrhiDgD8gf3Z(?5VPg=nqfff^P<_)A_ +;W%Ke!?G^#\(<^.EZ,_M).S'lo]9b +.#XWDc4jipo>I&k/9[UE;j>8H'5*3.fQlIM;&25hS12TikD:u`=mS7jVC7@n-a'?rlLeM=#?KUE]f5ul +zzYeaVXGk'BmJ#tgi2`LKu\).[?4fh/=;`$^'J)S7u++F!YgdkSud(=]$o%;UIR58J*O1t879A?ml)t9 +"mG:KM(EcU`u7iu%7lO;h6j'R92A_-F,e]c62g"iV0S[[B+(LQ9Fod?AZEqo +._E\4_Dmp854m^r0g5.c"*HM?6>([pXUDCh9O;lmkQL4T3n%A8]_[iA&HhQ +5HDnl8E!tRLjDHs\j+a9KYA]pt7o?TWSGDo&WkqJ+%8L=rl'J+:Jo/,qUb4&6+)VWaqMIO] +Oh-RY6EB?-#QVPrsLmJP4u2fC8;iJ/M@cd1]BGs$;AXC^c`7G54mkCE^?>'I/V]iq"(0#o_J2pK]d*grC_-nkRd0401r\`^uQa0/d\QFP#0UgN+2Vl1$Mf\"j9p",cuHY-l%ZBban$hNu](GB ++-Eofpe63$uczzzzzz!!$Dtq(EY1K?s~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 0 347.4] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 356.25 L +1603.75 356.25 L +1603.75 0 L +cp +clip +GS +0 0 translate +1284 71 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 71 0 0] + /Height 71 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0W:InH%)o,lJ+sOlmX]gA\^(D(lKh+a*[$-OV$3c=hN0X-r#.SFQ)1bhUDaJ,TQNzzzzzzzzzzzz!"*rDm+IhrR\?FK$J1 +n3G:m)a3&k%(]`J06JDurM!<<,PB["hY/c#6[gU;6JG*_#n4psT"n=[J.4ho +\(g=kmO5C`[FXSi2#!'h,c7Rf:ShOKS7f!+h7In"rr) +^g9hj<,oB4Gdf&pi6lK[[#l`X[1IeW9d!s]I*dE=o/@&!.Z8`4F(uHqk*WLfop:No]];'FoErId*O +I15+_drH@#GOdA,C7QS2_.>OjWV%j%7.R)lc7q!hkGY$K`#dS%KClk]X%!/`Ha0[SS/4(i%er'#K$XSc +i//DS_';nfu\^H^Itl-cF+l@Ng*g=j]a:ofcX!WW3cEFrfpL51PjOnR(k4(lj/WN3'MT3LL)_B2!k/H> +C"M2?%YCMR^72.,tIl-o2\(G8t62ElEWV"4Hc!!#7r^4-%7dEthf!it&/g;_.PqYL'-BAptSampCmY%A +XImbO@>?1<=nc'a89fe3=*!#4D1M%eS;H2RI-^:q>?iSj%cl(>_FhaM/9dKb>E$be7+paf[lIK9EK+M# +nIdIPn19Ci+L[)afrkg?0roa?4TG`c.=_YjN9!'kQX?G+?kc_dS:nr:tf5L85r4>8INDj`ft+$4YI[!l +V!-N>.OOcbcRbEB2NL&2#R!.a.90fK&fmcDWY#A2f%EF\=cXZLapbVhY6r&A%AIhp>ehV@#Gs7#!bk2t +gmC.Ccal"69PKe(q3!!!!5iUuNgq1&(^AKtqs?XG^NAs]]-]pc-m57?A_ICl2H+odfZ>IN>"H*dE,/,? +hs-2RiG!.a'fNfI_Hle'kBOt4`=gh`S,#3>\tYDV0i!!!##Q3CXe"TSOQFj)BF!!'f(@ho7K!+;Q>*?? +.=)B'\>?gToVzzz;?$Ur!5P%#[9:"#4(94/&P37b3#.R/OGHgIE@NH,,>=Vb84#kcWJDgQ7%B-j;c1p^ +@H(6S&jdd;73j$%i`&=9MMgO%';m%;&/&t4+pfD)V]t,"<&@+43#.R/OGHgI8I1/4'bR@8I1/4'p402 +Lf4n*.Opl39Upu26:f%oLa7XAS;N,$;:-@li`&;Y66]/n,U"Gm<(*76MWP0XV]q98&ofBF#pBnY,2uR$ +1e3om'p402Lf4mW#`1MU&Z;@t3Pr_6La7XAS;Kj(8AqK`3#*1Q&LL7A,U"Gm<(%?c,#1SFWMjKj0QHLI +mAkXO=:^'QS;Kj(8AqK`3#*1Q/50;mGP>k0"kEc!&Z6h9&/&t4,#1Qq1CFlZ4=(:W&Z6h9&/&t4,#1Qq +1CFlZ4=(:W&Z6h9&/&t4,#1Q=Dr//&o&\'SCWsZ63DW458AqK`,_SRUMMP3YMLG9hiUGgDK7ef70/EtL +k<($s+VCUrOq87G.O%VV.l0(Af%f&Nc+.FpWk`mP&jdd;73j$%i`&=9MO&$mC9">8C]FD4Vb`pC$WA(k +;j%\)E@N.=+VCUri`*9ihnFM#Eo]be:JZ/M/511G:J!lD`2RDpGl,[6BDjomo69T:CK[P$g!Ohi"m/Vn +E>uH_Ps%B+9hg'9rr)$H:i$oE3^!3`#pBnYU33+ckE[IMI$h%>YHRc.`IA61h^/%o;Y_lV/D9&\2uKh\ +X_kK7!pbE!Lf;^YjjpP<=0>g(c`HIn`qJfS(Op2,j8o>4LT8V9_&YhN(Lfp$8AqK@/URBgD>mFO92!HC +5KNt79aa/ER"_LX:Hh?:8AqK@mE"2MSA31VT]*BZQdY'?b!.-+\WD:kPPof]/)a9'7,187./4Wi(8bh/ +q'67i&Z;ARQ#QLM%Cr=72LB2'Ip#g\Q_OKk+VCUri`*9oAmq^ZGtJ]9,#1SW=.4V?4S+jChL+%Z_Pk'l ++VCUri`*9oAmq^ZGtJ]9,#1SWZ/YRYJ(O0OLQIo2Z2b+~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 347.4] CT +[1 0 0 1 0 0] CT +N +-1284 0 M +-1284 356.25 L +319.75 356.25 L +319.75 0 L +cp +clip +GS +0 0 translate +320 71 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 71 0 0] + /Height 71 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0R5n1^s&-ThB$'%82>(-XT'+1YB1g[^"_.g:DLX-V6zzzzzzz!!!"L-[GkRe,CgZPi^#tU)(q9F%% +[H-g-@j/5OP+[90#j.r)=O3EO^>H#g'd`U`(p;2aPX\Y9k_PB0/EQ7(jQ=tEIp't%/8S1A?Z4?6Km@X3 +!sW+E*]IKJQo\)fT0p(J9=^Ff:.Vr&9gP1+?-I`^i`7DIpUgS/%qqJFV5\ZLj&kLq[&4jeaEmU'E, +dQqLuJgqYbH*[9!/2N9C4^MuV,ao\6*IEr'Y#000!>ka.fg>P(Q`^Ff:.\(0pX4Q?4u~> + +%AXGEndBitmap +GR +GR +%%Trailer +%%Pages: 1 +%%EOF diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_case_2.eps b/moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_case_2.eps new file mode 100644 index 0000000000..772e51f015 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_case_2.eps @@ -0,0 +1,1548 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: (MATLAB, The Mathworks, Inc. Version 9.2.0.556344 \(R2017a\). Operating System: Windows 7) +%%Title: I:/Entw-Technologien/Studenten/temp_kai/blend_case_2.eps +%%CreationDate: 2017-10-06T19:21:34 +%%Pages: (atend) +%%BoundingBox: 0 0 774 521 +%%LanguageLevel: 3 +%%EndComments +%%BeginProlog +%%BeginResource: procset (Apache XML Graphics Std ProcSet) 1.2 0 +%%Version: 1.2 0 +%%Copyright: (Copyright 2001-2003,2010 The Apache Software Foundation. License terms: http://www.apache.org/licenses/LICENSE-2.0) +/bd{bind def}bind def +/ld{load def}bd +/GR/grestore ld +/M/moveto ld +/LJ/setlinejoin ld +/C/curveto ld +/f/fill ld +/LW/setlinewidth ld +/GC/setgray ld +/t/show ld +/N/newpath ld +/CT/concat ld +/cp/closepath ld +/S/stroke ld +/L/lineto ld +/CC/setcmykcolor ld +/A/ashow ld +/GS/gsave ld +/RC/setrgbcolor ld +/RM/rmoveto ld +/ML/setmiterlimit ld +/re {4 2 roll M +1 index 0 rlineto +0 exch rlineto +neg 0 rlineto +cp } bd +/_ctm matrix def +/_tm matrix def +/BT { _ctm currentmatrix pop matrix _tm copy pop 0 0 moveto } bd +/ET { _ctm setmatrix } bd +/iTm { _ctm setmatrix _tm concat } bd +/Tm { _tm astore pop iTm 0 0 moveto } bd +/ux 0.0 def +/uy 0.0 def +/F { + /Tp exch def + /Tf exch def + Tf findfont Tp scalefont setfont + /cf Tf def /cs Tp def +} bd +/ULS {currentpoint /uy exch def /ux exch def} bd +/ULE { + /Tcx currentpoint pop def + gsave + newpath + cf findfont cs scalefont dup + /FontMatrix get 0 get /Ts exch def /FontInfo get dup + /UnderlinePosition get Ts mul /To exch def + /UnderlineThickness get Ts mul /Tt exch def + ux uy To add moveto Tcx uy To add lineto + Tt setlinewidth stroke + grestore +} bd +/OLE { + /Tcx currentpoint pop def + gsave + newpath + cf findfont cs scalefont dup + /FontMatrix get 0 get /Ts exch def /FontInfo get dup + /UnderlinePosition get Ts mul /To exch def + /UnderlineThickness get Ts mul /Tt exch def + ux uy To add cs add moveto Tcx uy To add cs add lineto + Tt setlinewidth stroke + grestore +} bd +/SOE { + /Tcx currentpoint pop def + gsave + newpath + cf findfont cs scalefont dup + /FontMatrix get 0 get /Ts exch def /FontInfo get dup + /UnderlinePosition get Ts mul /To exch def + /UnderlineThickness get Ts mul /Tt exch def + ux uy To add cs 10 mul 26 idiv add moveto Tcx uy To add cs 10 mul 26 idiv add lineto + Tt setlinewidth stroke + grestore +} bd +/QT { +/Y22 exch store +/X22 exch store +/Y21 exch store +/X21 exch store +currentpoint +/Y21 load 2 mul add 3 div exch +/X21 load 2 mul add 3 div exch +/X21 load 2 mul /X22 load add 3 div +/Y21 load 2 mul /Y22 load add 3 div +/X22 load /Y22 load curveto +} bd +/SSPD { +dup length /d exch dict def +{ +/v exch def +/k exch def +currentpagedevice k known { +/cpdv currentpagedevice k get def +v cpdv ne { +/upd false def +/nullv v type /nulltype eq def +/nullcpdv cpdv type /nulltype eq def +nullv nullcpdv or +{ +/upd true def +} { +/sametype v type cpdv type eq def +sametype { +v type /arraytype eq { +/vlen v length def +/cpdvlen cpdv length def +vlen cpdvlen eq { +0 1 vlen 1 sub { +/i exch def +/obj v i get def +/cpdobj cpdv i get def +obj cpdobj ne { +/upd true def +exit +} if +} for +} { +/upd true def +} ifelse +} { +v type /dicttype eq { +v { +/dv exch def +/dk exch def +/cpddv cpdv dk get def +dv cpddv ne { +/upd true def +exit +} if +} forall +} { +/upd true def +} ifelse +} ifelse +} if +} ifelse +upd true eq { +d k v put +} if +} if +} if +} forall +d length 0 gt { +d setpagedevice +} if +} bd +/RE { % /NewFontName [NewEncodingArray] /FontName RE - + findfont dup length dict begin + { + 1 index /FID ne + {def} {pop pop} ifelse + } forall + /Encoding exch def + /FontName 1 index def + currentdict definefont pop + end +} bind def +%%EndResource +%%BeginResource: procset (Apache XML Graphics EPS ProcSet) 1.0 0 +%%Version: 1.0 0 +%%Copyright: (Copyright 2002-2003 The Apache Software Foundation. License terms: http://www.apache.org/licenses/LICENSE-2.0) +/BeginEPSF { %def +/b4_Inc_state save def % Save state for cleanup +/dict_count countdictstack def % Count objects on dict stack +/op_count count 1 sub def % Count objects on operand stack +userdict begin % Push userdict on dict stack +/showpage { } def % Redefine showpage, { } = null proc +0 setgray 0 setlinecap % Prepare graphics state +1 setlinewidth 0 setlinejoin +10 setmiterlimit [ ] 0 setdash newpath +/languagelevel where % If level not equal to 1 then +{pop languagelevel % set strokeadjust and +1 ne % overprint to their defaults. +{false setstrokeadjust false setoverprint +} if +} if +} bd +/EndEPSF { %def +count op_count sub {pop} repeat % Clean up stacks +countdictstack dict_count sub {end} repeat +b4_Inc_state restore +} bd +%%EndResource +%%EndProlog +%%Page: 1 1 +%%PageBoundingBox: 0 0 774 521 +%%BeginPageSetup +[1 0 0 -1 0 521] CT +%%EndPageSetup +GS +[0.6 0 0 0.60069 0 0.20001] CT +1 GC +N +0 0 1290 867 re +f +GR +GS +[0.6 0 0 0.60069 0 0.20001] CT +N +0 0 M +0 867 L +1290 867 L +1290 0 L +cp +clip +1 GC +N +0 0 1290 868 re +f +GR +GS +[0.6 0 0 0.60069 0 -0.40068] CT +N +0 1 M +0 286 L +1283 286 L +1283 1 L +cp +clip +1 GC +N +0 0 1283 286 re +f +GR +GS +[0.6 0 0 0.60069 0 -0.40068] CT +N +0 1 M +0 286 L +1283 286 L +1283 1 L +cp +clip +0.941 GC +N +0 0 1284 287 re +f +GR +GS +[0.6 0 0 0.60069 0 -0.40068] CT +N +0 1 M +0 286 L +1283 286 L +1283 1 L +cp +clip +1 GC +N +0 0 1284 287 re +f +GR +GS +[0.6 0 0 0.60069 0 -0.40068] CT +N +0 1 M +0 286 L +1283 286 L +1283 1 L +cp +clip +1 GC +N +0 0 1284 287 re +f +GR +GS +[0.48 0 0 0.48055 0 33.71863] CT +[1 0 0 1 0 0] CT +N +0 -69.75 M +0 286.5 L +1603.75 286.5 L +1603.75 -69.75 L +cp +clip +GS +0 0 translate +1284 287 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 287 0 0] + /Height 287 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WnVbokS]C9tCIARD']Ju+5d/rRV'JSjlZTSZbg+GurL*J1B-%T]6+=]!kE1[E8DcJlU^2^2Q*,KTO9SLn'?+Z\?L]V_$cZ27FCMPR2.6s.@&T((P4jT:Mlb +N[Q%rE[i92U=O-hEm?,?S+LRB"+/+J#pGF0&NLT6AdafD:-$hR$#C!qA+i^I7XhXJ +N[Q%rE[i92U=O-hEm?+4/A-S&O&>h>b7Q%R6r$23<7I?g9[5Y0//*7c2L?.M*)T$njA\NB7BP7[jIB/g +)YXY9j!X=;+VgJ/L]@)J`7e'#-%nZ]7H@FtROq4Y3G$]neMUqB+!@@+VJbAc>Jr"cKTO9SLn'?+Z\?L] +V]>CNaI+*A/#9U#%,j&_`@@U8ON=DWS;LLVKul?Q)lr\SN.nVYL]8(_OK"$K66`KoI-10kruMF\;*mh7<('JM$[D[HkDt#BLECt)l()["EmEo1RH9R;NTQ@bqV[IMqrg0X;*mh7<('JMoD8%$ +0=uLVq=o_u9Q3TkMJB%XjCbGZ:%ouFEE!VC^QX,%BT,,ZW*.[ntK)`P?R4(\=2?ji0>:5A/> +f@X6G"PtN%5&0`-iQ\=i;eaKTO9SLn'@b +p%+gUr9W+C5Q0hBO$7^Sgq!=Vmn\6/,P/MShpl;HlC5TJVLF$`4'$J3L"(V$^J2B+>PEVH6jY$!;\?Q7 +Y%Y'lr5&gp*'\n"CMW7eX]sD[?0hK7qXj#*^A)0[(1-?7"T&t[Q.BPr/`7@k(\h-")Nq(LX0TUsV'8M; +M4BIEWG#TsDVVaKp[8#&5Q16'DXG12em"?ph\IR%SG(+tB0>JLK3O$d5Z8bA^QMfs,"`,tS;PCe./1V$ +rp\pdMj+-A>F:q%\oQ-"OJ2$u;*l2$WBY[BjP-CQ8dL9DMTDc1/e9$f]RB\NJL?TJ[d^+dQR;YU[P0`) +FB,2#ld^M4n3/!)h3@)2>M:K+&LE)u:.=5C1mbmG6smKFAcF=m*]uE.o]XlWetdf6(+/470%9I'EF9.b +MicN*iFt3I,"`,tS;PCeBO2K.?9E5e`6Fc1]AMMXGOOnOZS/u\_P9V^-G@/G9[5Y(K%VL?;SN66:.X\] +F:q%gjI-kj,Fe54h!T@<0Y-X]\s3G]!0C-m>^nn`dK-.)1Wf+XD(X,,_0dCghA0Bo,u!!dH:En3/"t +^%#=:F;1d3&jde?,'#/Jbn_YhS1\XO(BRpprB!VB)e/^V/m?1CU4eWLWJI(%>-iq)3N$qdnnkWT^(=0c ++`3_Rl)TUQ66`"*@7Kj`'e[<.2>]H8E<`<:.;;<_W3WESBg[<^aAQ`2D?Cg1"Y;< +WJD0R,,ZW*.Vd3D-FY/]FI&6n[XSr0&eYSAAJ(u!&jde?,'#/Jbn_Y8hWK"#(BWIJ_Q1DU_m\DF;.ZnK +'>n9aNl\2US;LLVKupIS3ShGGIHW`Qn)Ln'?+Z\?L1qOAW'E(fr)QY+SfZ!)q\"W#>(jbTFaaJl*q>F=4(cKSd7pH)THV&-dkq"IgD#a30ImRVSVH#JG +YJulQ)]8XB,B>7XVkVaY@gmaTrLW;*/^0lu +i0.BHU;O/iC`&K`E[i92U=O-hE\5T$$kq9Ae90f':G/WfeV8K)8*!W;:.;;<_W2'Mkq"IglqZfVEks,) +;UP8TNX)4n&sjh`.O(dbenec8iAmIj-%J_J:#LV!Y4Sp[->[+KGQYGqO])iP't%W]P?[YaoF?-Q@/G/s +\DWQ$YA!hF[YWP+b7Q`LO],+m[P58FcfrZW"`+6Y+r>WI%4h#/D4AK*Ln'@DWMh[YR,"CuFQNnBSD-\4 +\_rZU7R\q<)o1QkS;PCeW&7eHgt6[/r?q!fH/r*\puI`BOc.psF#bGB,'#/Jbn_Y8Inln(jct1N*6JGW +gp/H!qQ'op]d8n`3?k@FE[khK(+)!=R@d!Y0MLGW:Ms_Y9mm5]e_DDO/k=u%6r$1Qfto:PLAgFe+S0Th +-b&)mVS4V:.W6/FE]G>A,'#/JbnanDZb-FF4+8a#"eT$A.WSs&"+:H3Ti2O`'t%W]1Q+V-!nc%5d0N'6?n+IEj8f +KLB\h'ch>VV$@2:&j<-:E[khK(>]UXrlePdGK`(DKTO7aX.nfr+_bXm+jj(8,,_0dCuI60_u;eYLDT!@ +;F3q8L0B^.gbV;,M*=cK3>Jr6$a5t$?M:=6"94X-8dQZ')g4XcEGl7I,l0eqjAaWt/\D:"I+b:KrB&.^ +V1arOX[>Mu38F]&&/)%@,'#/Jbn_@pfjFHOdJ,l?3MhCjaK8H2;m5Gd^2[q+X[6Jc<('JMXkCRDY^bPC +c?bk[&kf,HE[khK(@J(lO)$rOf1J$#PRnJ<[B4+F5P)a`[1.s=;@to( +[:Tg@`:T\hS\BeZc8h_SON=PJ7>HATTZDG7`,_f4S;LLVKi_jBVg9E?_L:I7;F3q82PD=QGR68O,[++Y +3>Jr6$STc;cgs8lq_l_K-%n[(UFI2M=,m46W/t[\7H@FtRP!=9!mgI#gq,;d.4'X8D?DDXpdM!N%jW'L +%1J)6.O(dbenj=#ZZeS/p6nLR3N&)Q'"O"(B]9f9L_mA%+]1d!jAaWt/Ng6$hohShf/dnH.3TsW.QZXk +&[N&^3>IZT;/%K.Q#9 +#`5(/aJl,GNS;8@5)aci/\LBK\5dQE.3TsW.N35HIV>X8ON=DWS;J)gZa4`9cCM/QqWcH%>e_l'n7.hu +hnlGn:[B+bPS-;,VkQOPrDL,i)qQ<$,,ZW*.U#+38NV+^fTE((LMR[_M&BpJ,J5W&%]/qs8Msgn)&!j0B`5@F+89ME)%i*,]YA +O]0Y4^A6o\DVMo&m^r@7g"tTRhX\rRmnERJqR0D)55nGDhu#_%PS-;,VkSkco!Nb\#`5(/aJii*[r:0l +QLE(f2b2bMr:oe@hgBLn5I.;kRXG%6oZXjek>m!E=9h/:VkVQ1YL'>aFiu!TE[i9BaV?D3Kl>eYeSX8_ +&WaZr`/,.G]^a!<[dX@ueZ@P8\\\A6,,_.J^/>>qS;PCeBJ.!P_JB_FPS-;,VkR@Mg^.(i66`i9OSk#6#E_\&,,]YALiK1ec?UmF,V]p.2R`jPDA\IipHO&C_qJ9=?fYZ^>;b@=PS;Q#\jH3m: +77cK=6r$2B3d^SeCTkF[s2PkgV@oB93MhCjaJihj2II4,M4BIEWG#ViY@$b\mFuQo]t:oRaX<^N3HJeS +)F)C\-Kgms6:g0:ZrHA'LkS5l7H@FTJ?>rUA&jTMH0Y>'o8aqURe"b40KJ<\&jde?U(peN74]^).O(db +`U)sXI/NNTdoZ#[>F:q%8dQZ';pi`]I9"6dhmg3'M4BIEWMh[YR%/4i#pGF0dHZ_G_Ll(266`-iq)3N&)Q&ig^"b1&`4lU^?&FR@Y((rVBO],+m[P0`)PS-;,VkTlR1l#-hMM4Gn +7H@FtROq4Y3MhCjaJikBqQYj16r$23<7I?g9[5YpKTO9SBMGRS&IXGcMTDcq2-ZH[ +^BTm`aJjucMH[??aZ68`&/$u_Yp74]^).O(dbenec8c7(&m6r$/i@d5'g(r\fcV]p.2C<[M@kF>F:8EJr6$^5X,.3TsW.b[SXMc`O2<('JMXkCSPS5W#cM4BG]g%Z`'cjLKpM4BIEWMh[YR%/4i#pGF0&JMYC +4H!<4jA\NB7BP7[jIB.@#`5(/fJdCJcTI)=6r$23<7I?g9[5YpKTO9SLb\%!`'PZG,'#/Jbn_YhS5M[E +jAa&co.4>oO])iP't%W]PB0JJ+XD(XiXiFZE*>fn<('JMXkCSPS5W#cM4BHje[R3D:IsPG6r$1Qftug? +;b@=PS;N][KIsk+$PUEAQQpN#C<[M@kF>F:8E3E[kO,PLm$9bT^;P +aJl*q>F:q%8dQZ';\:12Qms^YjAaWt/POGMV1arOWJD0m8/F:8E<``O5c!cNt +WEbJ)WMh[YR%/4i#pGF0&L@p?1iWn-`(]<66r$1Qftug?;b@=PS;J^L.AS[cfI1>5QQpN#C<[M@kF>F: +8E<`F:8E<`9L/D.:M)3?kAq +enec8c7(&m6r$18=>6PmMqH3,D'5/iE[khK(+/47;F3q8<()QkUiAcS$PRG$QQpN#C<[M@kF>F:8E<`< +M1Ug9Cgi6HF1<3P;c.>=0KJ<\&jde?,"`Q(2"n>6NT*[jE^WYkXkCSPS5W#cM4BGO;&dsU3G];2/!hK$ +.Vd3D-Kgms6:g0:7#=AV=i;8ujbTFa>-iq)3N&)Q&ig\(U1m049tVWSNl\2u2-ZHJr6$^5X,.3TsW.\aj:6Q3^nNT/o<3?kAqenec8c7(&m6r$18=FNg$LTj30A1gC5<7I?g +9[5YpKTO9SL_?`saWb%-/k=u%e=%s_c8h_SON=DW&uuOWas&a$#@d?@0mkHcbn_YhS5M[EjA\O(*ee,: +%p"`@@^&h]ROq4Y3MhCjaJjt.]aJPk*;1:EIFc#f(a'R$AdafD:+7>3E[meO:ICSTKe;;5l=iZqMMbTD +Kul?QPRnHf'iC^o+[%W7NT)#EHUS?oMH[??aZ68`&/$u<;.:([9jY^QEA%`p,'m!QXkCSPS5W#cM4BGO +0qaUZinbSM7J)n'>-iq)3N&)Q&ig\(@W3Jb?c5G(8dqjHH:UK,ftug?;b@=PS;J^Ld#cK1?5[EFoSSN0 +Z\?L]Vj%`*3>GD#kTPp'_HrUSl%WLVIA!;<4TG?N8&"<,%mQTVcF,DekEHTG,,ZVWX@Gep\$/<6'^JU. +X/2P9IJMukh7UFKq==D-\i3B1Ip8;1F%Q`^O])iM(-;Cn3%bF: +8E<`(rV^SAEm?*[KLAR(PZ[O=/E3L.o86WW(!Z(-5QCQ4ZY+da +e"7\0lJ/pkp[@"3o);/AG87imbA>]fJTW(\E[mg%-A43e&[2&.XbfcNLt4JpU;aS1$ST/3r:ofaXfYg: +DI'ktXo%/Ce#0tUieo6iGd2`1lruGN(aUGJ.\aicKf!ZTHPr[n)cREoW+_(UmHoZRp>1&S`f7TSn*[s: +Vk8FlXkgJCH>Cq6Z%^:[Vj%`*3>GD#'13\IKoP*1-<#3V7<@./7.c`p=8(P"mH(*5O)AfO:&7@r@<0XB-%nZ]7?eA3[tcPEU\IY8,,_/\?+bFP +`/,-dDr0i0J+)7-ZY.UunA5Qo*^,tarjFL@kEHTG,,ZVW#\fo"]J((_;pi7hg&(X3Y9,oRFRP!@?[:au +cT_5Bb59r1jIB.@#`5(/-m>C!:#*TlR!8ZIO]0Y:[^W_1qWO]X^]+)VpU#Xr3N&)Q&ig\(6:d;6gqjis +1K6b;7BP7[jIB.@#`5(/-m>BRN>]SKnTUsgS;LLVKul?QPRnHf'i@:gZ^N_+NFEW"5t.p/_W74c8dL9D +MC9XD\QQks:_>]&[:Tf1F&"/-,]YB/KTHs[&W]a#3>Jr6$^5X,.3TsW.\_TX,*Ni57_K"iMTDcq2-ZH< +F%Q`^O])ibPt-<:^='t%W]PB0JJ+XD(XU4eUXN>oa(Y_Z:I:.;;<_W74c8dL9DMC9XDH5!aV +)D>P7O],+m[P0`)PS-;,V]n_=WKF04GhkioMTDcq2-ZH=0KJ<\&jde? +,"`,T3S&NhX,*:'>-iq)3N&)Q&ig\(6:f9VIL$JaKo&et:.;;<_W74c8dL9DMC9XDPo.8i#Jr6$^5X,.3TsW.\_TXH=X8; +-<:^='t%W]PB0JJ+XD(XU4eX)BP<<+7H@FtROq4Y3MhCjaJjt.6L(ao>I^:Y_k\Js.Vd3D-Kgms6:g0: +6jY%0h1RB8X$s*6E[khK(+/47;F3q8<(%$9%E@$:-go#',[:Tf1F&"/-,]YB/KTHCKl5F!j,$#:9 +'t%W]PB0JJ+XD(XU4eV_W,ISr7H@FtROq4Y3MhCjaJjt.65m$+I%+5,jAaWt/POGMV1arOWJD0R)S0We +GZc];U`sh/C<[M@kF>F:8E<`<#pHF1M-ILg,$#:9't%W]PB0JJ+XD(XU4eWZbkN@:GSI37S;LLVKul?Q +PRnHf'i@:gCMV'4XrbP3,,_0dCghA0.4'X8:.:BYde[aoLfHi<7BP7[jIB.@#`5(/-m>B\ES.aWPNSK; +&NLT6AdafD:+7>3E[mf:O>bDF/\LR'0r]u!MH[??aZ68`&/$u<;*mgCCYTJ-m,a((6r$1Qftug?;b@=P +S;J^=0KJ<\&jde?,"`,t;2^EC'p2El +CUPoWkEHTG,,ZVW#`5erftuWp4XLo+;c.>=0KJ<\&jde?,"`,tl)&=V^]%+C3>Jr6$^5X,.3TsW.\_TX +R*h]QI..q'`3lO$>F:q%8dQZ';\:=/`7tin_aZBPF"M.O(+/47;F3q8<(%$9Z+/IVnWYDoL4-3nXkCSP +S5W#cM4BGO+X@C7[Y56?<@2Z:C<[M@kF>F:8E<`<#pGH.:.8*jY[,HuY!oJG_W74c8dL9DMC9VnEoSZ2 +C^V3$N,gLbbn_YhS5M[EjA\MR+d&7#d0sgC0#k;t3Eql@F%Q`^O])i`2dlKul?QPRnHf'i@:gjJj\u +Ba`\7CWa&`2-ZH`2dlKul?QPRnHf'i@:gjI0.,gD9LIe:Zmee=%s_ +c8h_SON=DW&jdeOe;@kp_PZk-\/)Ja$^5X,.3TsW.\_TXaK;J:H)C(<(U5&=mOQn`enec8c7(&m6r$18 +&/)N;<&EJJp,$%Qdt`h3Rk7=Z3MhCjaJjt.66b%!MWPkpeo;5mYbF!b$^5X,.3TsW.\_TXaS!$-0KJ<\&jde?,"`,th!cdsF:400Fu'kf=4,IP]6E_EYJ*'e`grZk4*U*Tqt=[U_W74c8dL9D +MC9VnEpHP!Y_C+^#+IWT6U`RiGjsYPaceZ$g_bHLpIRGim+@Gu?@DLs7un]cq$=D_3TlV>66`HV8D[_'.up[6l**A1X/2!'AB_W74c8dL9DMC9Vn +Egom&jVFHTqp)8A04)(]W+Z4dgY5f4>^>bJk?`W5jTA`^`>;moE8e\5+$]PYKC0cJhnMD?6eT?;S5W#c +M4BGO+XD(I>>`j$]ZAYFZAku"\q^e%<-pRBP^r671XFFS]4h08VNZWk]1>MaYgSOjpG(+/47 +;F3q8<(%$9O]0XE/(qd'r\-S9P`E>/qrGk_DkE'Ld4KbCp?h:/2fIOmIHTY2O2(MQS!-%cOni::mlG[\ +go>8olTe#%<(%$9O]0Y4HFUqAr7-8o=oNI'^_XY,lW3c#D@qrDc\W;_hK\(?.9h%_Ih>@oe_baP5tL'9 +6jY$!;c06rgj20`+WpNZmHs:r,7]B8$e#?`p66+$3>GCX8Er3>IZTd<#W%E9HT@Z`h(9gAW2-V@lP[S5M[EjA\MR+d#\83>G9_lk[r3>IZT;/66`GCX8E<`<#pGF0&NLT6jtf\+7?e>r3>GCX8E<`<:.;;\%$OU%-%nZ]7?e>r3>IZT;/8A5 +jA\MR+d#\8-%nZ]7H@FtRa3ZJ'i@:gjA\MR+d#\83>Jsa1JCP4PRnHf'i@:gjA\NB7BQ@oP>`&>KLAR( +PRnHf'p2ElCHfYs<(%$9O])icCI%(IJ)-jD[6HR]tN6%o]`9GY53mW%N[cZoVXqPC"9\E +U"\>YrUZZ]r'15Q5M^6YI9RPm]ru3YI.>1UD[:u;n(t`jmom?Hc!87hj=YYYX&lJG4*Ku3;m3q3C3LJ9 +e[L?cH2RI-^\l9i*'JUiYG1K6msEjs?1j1dfNrpl[HF-.DUl4J6+VODqWZJ,pF\sKcCDFnqt@%.&VK`, +>ArnY?2N$1IUj$HQNn$BS32)f`f1q4Dfh>8\NF)Y]A2MZq[D:no%LKe]=Y\!n)!I"2I*h8C"5/"JU.4e +f=RgSLHk^1X6B0$5QBE_IeN^2cZePre[LI1lE3\6FibD2!StG@/tU7Q00aaQjNB3kln1dU:7Uf*)!:Ku +s7K`)8AG,jDnE2gp[6l7rqF2-dRu6qqF31V>r1;"l7SdX(#po*EuA2E]A2LSI.>/`(G>(SnUh?9kW\2( +n)%L29k%55\$qD>4aQedebut!G<fm^4*cno#h8=N4[lhBMq:eEgQ[cRr>l6i4JHl]Dn2b +PMEk5STipniN6Qk*^+iA]ANSTo?TYYJ'6-_:05iHIeB`VhC8_EGB`f%5Q:1+J,.:U.V&oCY:!,;F;LS, +s8Mbn^**pA`JYPECXN,'J+K/eFD6_`V1Z#o5(%V?e>ZgTqUaPA7TYP\grsY67IG2_]7'R"pBeKXoB,6U +NupUck*p:ll6`b?hL>@hY,aednW0`b+Ul]Jf%*(bj$,_Vr7Dcs!IJ2'55OKI[J#4Se^8S/GTemW(+q8JOD3?1-(A>IV1>i.:&+ +3H=&s)fNBoWggrRIJiWU>s`uCL';tqaX;F&VYe%YbQ<7nqqlT(SNhW'jd0>'pYC%CorDGBQ_PZ$kXV4= +RKZs1I/1ijrSRoFq!uT]=+,uDOom5S?#CE3I1*[1ST?KaouB;rn`7fU5P`Ds*^>+dlJ'1k4F-MYqqqGQ +J,\V\metNKAc][Dh=%p.C-V^fO8$]`LECtii,OT-MdQDA(T1$!lL'7ADf=OFGOO=tF/Mg+2M[]k/PL') +(3Z%V`8:*&HGB_2hLGS(DS2K(J)7/8!WVk3s7Z2:s7b@2kgi]4qQKpFm+AT22h1huT3$Hi(lU]Wi=C:] +rB'jFpGSF@2gu;8+Qq?`J)+Cmro66B@thCL@6(Q$guW,KPI@^-gf=&sD#_3ChE13BItc1\[^NWUEdmi- +?`s6[0N8i@>W=L!'uTB%rUeRARHrJ.O1t/6WDb9U/pi)IEo:/Hs7B+eoS[)S@T>@D_)\`/guW,KA%/\S +gpPG!4o1Z%GM[VCb@^B,hI0_P4$21AhL>@hkFR%'qb?hYBJo3AYtViD?.rrcr\u +iE,tpC'Ts(dB[t@Xe4/hf`AV[^NWQ\$mGAGjrj+YB4.'^Adup + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 33.71863] CT +[1 0 0 1 0 0] CT +N +-1284 -69.75 M +-1284 286.5 L +319.75 286.5 L +319.75 -69.75 L +cp +clip +GS +0 0 translate +320 287 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 287 0 0] + /Height 287 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0VDeN2Es2XXaA;!JZ+VDU26&]7/YR=r48hIXuO^_l1)%fc!)A3VtLkuP>5Y=EWKTI)f.nW3FR+\+( +_&*b16R:-V(e]V)@"h&#`V"Ya&"_\K>j"/[Y.ZL7Hb4Yhkf.aNkNn_bFZRj>F"V[-;@3B,WN"!d#WGR] +=4`$-$S"m,_Uf;GSd5]q#!%K5GXB'r`?l0[rr]fUOOI!f0hgD=1@6'"g54K2iP +V+[/LWCj?j.$Uat2gaN6p\X[=Demd:YJ"!.S'N,Rk3lpM=#OmITG_jQ//F-nDT.JJ$PtE8)]R8%hgYGs +Vl]48Xj^3C4b!==k1m7R9BlB];]WG(RZ,=bpA>Jh`2UQak[4WCSCA7S)(28ck>gCf]*(1(Ren%S[:;]8qu>;se95em,1 +m!c"2/)9+BiQIQ@VbYbS;o^uEPHfdjrqU2=$Z@<_Rm6a<^!L]skSNnY^\OX3e-l6;O+'qZoUA)A7D7&d +rob0k6GN>k?doJ^k)Xsg0D(_uqF/*EDuLZehr3PQ`&E2j6UO6(c_%E0l6[i):7aR.3B:7"`Fcc@=bV=r +f@^$Krld?>_1Di5s"!*F_*Mqa'.6P>:V(f@@W-2RbSH]go08b/[sN`daGFMrVH$V +gJV1h#7hk\\o_Y-F0k"Vm^_N??Ph-d*BSF\gU:r,(G=2GKgJ'A\^AnI4*E/YZq.C(>.&,6hS#oeC7[NT +\3g@#]mB?1hg?*'H0!$Y4k1'XFeu&j)ep+3hKc#*R5]%j7n:U$?[WXui/K\PW+N!s]^nmc1k5N&c'pYI +S*cHD]ejk9!*']pm-3bkDGuW6QklX@naBfK@U-*i00:Q.DuLZh?gWW>SXlC%qWUKlIAApl]'HNg*Su%U +]6E_pMI(VnV;oUW%h&k[2H:<:,u=tP]QirK%m4gpd%Lt6pcslTEnI5]RmF1Dg9jR?b=>=e^&X#BoC^.F"i9*PE8+ZmAA2<;Jg@Zi_f6dGca.n?ahWlND+Z=d:='\6qhf%Kj +bP0nDYI!#'YM*3!]lh;O($5C+$oRr<8R6IJmF0qE2DHo!.5e0lANaA+AkdAgh/`.W^P;29IS)'4Q7Y`L +J$\nI;WW?p9kVbAM'dqW`>SqTWBbpT$G5H9+)JW]`%@Ak)`RlbRQ7\NkpL*G+6^^T%13Ni).2&6nDjkL+JNL3)'f[2ZdSk*tK2 +Adig&E`/*Em+;nE$J4P"IJ7#VmF0qE[_1L:0s1mpD7#9!JC/<7)SY++WB3K4FRf;)o,ShlXf\_ami1;Z +5DQj=WWMRXC.'H%H9*f:&hTp-]cqTaWo`H;=Y(>L*BSHAmC-0^\,8.jnP"[lL@g+eV`7,c31WD%'nqhg +5fQXnj7DH[f<56-iUlB`iFCru[:eCL[_,tl[V4&4/Ko*hPK]:Hq4lj#Cg^X9(TR#OV=W)3A]"a'Y4]Y8@%h*W:;X?eEc0(]&h+ +rHb/Ef[6l=qLosgHD+]udB=A_KcU,jg4lq +]6sHdq(.$`/t[Sq50KS1bNJII0783P48SV:^TaJ?0D#W6qXm1iYbPPYoF!bWog6EtUL,\H$Tn4X6GKb" +?SD$Z48SV:^TaJ?0D#W6qXm1iYbPPYCjF[<(O9H4_iDFO$X4ZqlpY75nuuUWo"p]J*IEnb[QNp/MnH:U +@E2^8Ke3fsp*)/+H.]A97tS7:+X;Y[]?W_NortH]],Q4RC^Y]WgL+a'Rh\/J#I^p7aGF +ZcnF+jT#8\zzz!!&C]cCI%@q=19k]5o#+k+'r7kigEhpYC%#pc?jGPq0WJp04`Z2(JRMe:uN9:$q]8O$D2@qF.jB]kDY8=KfC:qW +iY0p"-$5Q_&[&l$Mj/Vp]9#C3B47e\->(Wm)o_GTsQQ?[r#S)uSB%T;>moP-GgGF`hhNG=PG!7n8n!?T +p;'j>"j_1bg_Ym3rN7*og2_\gp#:H0CrWp?^HGT$f9lOk>RUqs6+%eKn<3XKHsDMH]]m@q/,Iq40TkG'%hRrU +neB2l3^]Don.gH>rTE=l44.2G8l7T@'s829"X"j(VpR][&og#_XNYAa%q55VO558N(Df>8iI!f0Tk]4mWFH%jEoB-D2^S +jWt?DNct]s;S655k$o)]RPAET>3,/-#D)&'$so,l34#l<^9WVbedpl`[^3f:G'Jc>.Y)AtW6W.bij1s4 +r#Ez!''itABo#@~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 0 0.07987] CT +[1 0 0 1 0 0] CT +N +0 0.25 M +0 356.5 L +1603.75 356.5 L +1603.75 0.25 L +cp +clip +GS +0 0 translate +1284 70 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 70 0 0] + /Height 70 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0W0l'_b+3/@CNC1ZNEU6%(*..m@%_=at/-I,Si8>^`JfPk">WRbPF`;@8To4`6GRsNJ0/60sP((-[ +F40.Bi]GqKgb^sN +eYeP\fIer^$[;4C^hS":/hd-$NmFr-m4?1%Mp?gW&!FNTjmFd2[>.igA.\_TXaJjt.66`+Q?ba1AY?nn'I:TfEGPAatq=;1rnd^j^&LE)u:.:BY&ig\h;pek+LAUT*cTcoGiosb +Dj2[5:c1g\a:I"XNp$5DF4?;l00(=Gb"TG5)8dL9DMC9VnE[i9BbnVh:'[Q-_+$P)9DKZuhoODdo\FK@ +aj.9P$R4e\+<(%$9O])i]'W.$$`Jjo66`< +O8dL9DMTDcqhom^#nscrA]QnSpJ

WJ",!tmk?a:;*mh7<(%$9O])iP(%n'LKfaMHgj/\aiTX'dV\0) +.&LE)u:.:BY&ig\h;c1<9]C=\6??a_R(GCf0O$A-n]Xtd;]c*O)*@@[.8dL9DMC9VnE[i92U4-a!iQec +BcZXJT:B(6fqtKP$*Zk#;K6N]QMC9VnE[mf:ON=DWS;Jr]kih6ZVbd7qn-SP;3>GCX8E<`<#pGF0&NLT +6jrGeH,"`,tS;J^<,]Y@YVkVbT_rOcb#pGF0&LE)u:.=5Ce=(TKS;J^<,]YB/KTO9SLn'?+o+$s_&LE) +u:.:BY&ig\h;c.>e@<*ilKTO9SL_<#uV]p.2C<\h6DDIW=r=[`c66`66`66`66`ik,qY+iWn$C1 +L-%nZ]7H@FtRU);NF3;&EH#),=QZ7e_ic7En+d#\83>Jr6(FJ=8'%t?kC_5@-i@`IS<11#SX[["]-N^f8dL9DMTDcq27kP&kEHT0KXB.mT5?OGE^U3WO])iP't%Wi-Kgms+q!S_mYZ2 +E=tW=0&/$u/-?NcJ+f2&LE)u:.=5Ce='[1S9%;Z+[R)pmBlQsbiOWn66`!u2M.%3WJI(%>-eU#F&"/=A4Z` +)?Pbk=Q!JX6*LYJ`N[Q%rE[i92U=S\JjIB.@1_"0uR_%"`pihM,i%EgQ5D],?N[Q%rE[i92U=S\JjIB. +@e:s3(WYbS3dV#30kJ;dl3MM1gaJjucMH[=oPB0JJ;%hdDr7C7@=.N@>`L3U,]Y@YVkVc/_W74 +c9&q.$pg`'a?Zl&18'%_pf9O<^J-B2<-m9jV.O(dbf'L97S5W%es'0g$ht+MWQ^R`=2(NZ,U4eWLWJI( +%>-eU#F&"13AeuM3s#pBn/MlSXn1;iGL_<#uV]p.2C<\A)c8h^hh(H>EbAZiB>\OeY&[0.7L_<#uV]p. +2C<\A)c8h^h'%4A[^N6Nk%U4f,E]KkION=DWS;LLV$^5X,.5;jk14.p?>CLp$MMnta;*mh7<('JMXkAE +M3N&*$$#,feDaX6U\X$QZa*s^tb2nEl66`^M!q%!P?%q#~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 0.07987] CT +[1 0 0 1 0 0] CT +N +-1284 0.25 M +-1284 356.5 L +319.75 356.5 L +319.75 0.25 L +cp +clip +GS +0 0 translate +320 70 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 70 0 0] + /Height 70 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0V5tEJ"!!i"K4s&0_\u>s(N1#XT^r6kBqN,/.h\6jF#/O-#Ie+KdstF8c-k_mZn2mPo]/Am]I6NJNCHLkpkCLkpkCLkpkCLkpkCLkpkCLkr"7 +Iu*J96-Op?.e]nNkNLd +Cj?Z6?=Xk\4GdQ$Z3sm.`3C-3Ke6*[fSf+5Q7$\=7W<%>;TEcK=,HHsh)gt^]:^C_A)*DNA.,1R/3%*[&DlheY10cH$0/<]>hn^6Ce +>[CaFUN.fN?hGD2hqm5H56`J_-XNtm#8)`WX'K(>7m6]4dYc7,/<]5rrdJNo#TjiR91BBF*61*a1I?Qf +qYEleQVOGue_Aj5;B!oH?g09'hqHfLl00'))e4?=U^Qekp@a6A?].#tH$S)Q^s$Ds +PEV3O%SH\KIlne(O3c%om-a:N#KaieL_E+Kd*9gpZ,jLsS9B$t'oU'-qtj5/#R%@oDtj@H]Y*0mrV_02 +0Y^eHGKr*_?'jH,M[Ne_naS@-2`E\#^Tk&+9IBG3ouP3FV,BTV[9=Rj*1WId_Q4]QiG]WHhVI"%L.,u, +PF7f*^e5eN:JXd?hs4X-b&NlrkJQcJ45oPm%/U;Z?Ld>oJarL-oi:kpo$>X#CEFGc/$M#r^KBcmIl]_U +?!1=H:l$MC8&\pL@inaQp%.eNI!oaXI=7*'KNBh,eS5pd:&3>Rbb+2ies5:&iSe4pW>?_s.)LdVd;PH1 +cWB(;g`2nme'2NaPm[s-qTUO=+P%c?LLoW?oX+q/[S=[((MEe9DNT;_2PRrELt1q=F(4^Mt/-\QCVRb@Rfdr*!0>qI_/;fC&CiWOb+)Qr2o7 +9n.%85!G"N)NS:e7;=N%`lX-sMct2t[BA;aq/,L8RGXlMRU62emro.rj?XHBc;H[C[UdWdhl +d0g'Y>''MIY+5;F@X_P4c2!(HfiahqZ*IE2+`Y>+&8PVN:,:DAQnr6_MB>]a9I=cAg=i"hGP\&]-rLqD +`s[TQWQ:fSk1>FbD-<4g([G!nN*S'&IWs!(pD`Q\,n^Nff;f_H*))ssorKlrfk_Egie1DbAh(*bSG>$O +ITtt$r&+j3ge9&IJ2AgrLm_#9)uel6S]-):YccbQQs]NR?]p-=RI.#eQa(!9cGW`fM:`mNEjBMHY&&>/%\G~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.60069 0 173.19932] CT +N +0 0 M +0 286 L +1283 286 L +1283 0 L +cp +clip +1 GC +N +0 0 1283 286 re +f +GR +GS +[0.6 0 0 0.60069 0 173.19932] CT +N +0 0 M +0 286 L +1283 286 L +1283 0 L +cp +clip +0.941 GC +N +0 0 1284 287 re +f +GR +GS +[0.6 0 0 0.60069 0 173.19932] CT +N +0 0 M +0 286 L +1283 286 L +1283 0 L +cp +clip +1 GC +N +0 0 1284 287 re +f +GR +GS +[0.6 0 0 0.60069 0 173.19932] CT +N +0 0 M +0 286 L +1283 286 L +1283 0 L +cp +clip +1 GC +N +0 0 1284 287 re +f +GR +GS +[0.48 0 0 0.48055 0 207.31862] CT +[1 0 0 1 0 0] CT +N +0 -71 M +0 286.5 L +1603.75 286.5 L +1603.75 -71 L +cp +clip +GS +0 0 translate +1284 287 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 287 0 0] + /Height 287 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0Wd>Lueh$nd[EDf2p'U>O'&(N3G33+B.VaD,6P)K>0g`Yju +j('-l6BI"e,3#Ds1gP>[T'a)"0T/JI8Tg_F;Q't=`1pc]O[>.cP9T"^W&.eiFYbp_?'mXjgS6Ap:Q-Mr +#SM,T7%=sVV@0kHhc;i'.na9@%a%US(Z)JCN.c1=$:,k2MMRIjdWFGKbkmjt10LNmOVjkh^K$sMl,'3) +*0ERLg9\RVjD;7f>CF_idWFH:4h(&Zr[u2O*L*WZc$s^^g4a=Ub)sn-,)%/IVtV*@)q%arZ`#]d\3bPn +@f;583ZX7QCsDR"ap"cQ,ss]4&Ldj^0tgX9gVC74Qpmk9_NeeUJc:FI3Y:O!S+@R7%8tG$Ld]5p.0QV) +]iQT9^p\!F7A]7crL.:L\]`Oq-S;@$01WgrNUe/0VQ-!baUAnf!PXhS"AVaF:`#g`EcQOosi(E0V6N^tVj+b>M2&qZ;-1J>Vp*mcH?OB+P._tN$D4+ +;Ic_slr)=M.2jL<36Nkt\#-QuaZ:FD?'mo3N^tl5Te'.D-lJbcM%4'hhB+Z<6)d6,)%-sVTP;Z7?*G(ELNrafkgP& +f'*`.=*!m#%a8Ip0QG)E.0QV)O'T^OtRTJJ<^cQmtV:'K&@;`i67V]X1gVn!MBjL+5[uF'.-PGgKgIf>&3Z+`Z7% +$:/E#Q+%r8e/0VQVokV$>l45"YQ#qj&mM7AMsu8,D'4NT25\MV/k(b^U2d4"),IMc5i)RU,gL#NQML1; +_Na5lJJ<^cQn%:/'K&@;`i67VHst>Zge$sa*lR$gUrq*$XEU9j@VG2u,,TKo'm*5RKel9U.tMMAd^.j&F\fI\8j-n4m]39c[9XWZ3&'C<99/eA&0\JM4tE +d!LWe#!lutQ+%r8e/0VQVokV$I8,!rZ^64>kL?uAQPY@Vn%uBc[,+a"0F1QdWZ9noe/0VQVokV$h7Np& +%A&;tp%$m4r_%S[pjtU.]r-Zp&>[Dm.3]b0e%!FQ$kgF6dR3&Ha.HNN$rA +92T2pBUgPs`kDD_D4[>r/cSshTaT>P)H+KR#Z>04]G6R'`^nK:p%443r3bD]gcSA4]D?jA-N(QB%"*nL +=sYVlFb8,1.L3Es2+EJCBt;RbZR'hDqk%Y]+]DB$3]L6&:Rj%20pSPjed55aWZ9ele/0VQVt/1//?f!& +(HlBmq.l3I4IK$TX.C$Q1dPkMPuCnE)C%]2<9>'jnbpcqO/-2aNXcPr$Vr,!mA_O&1ej&M;ruMpU;faO +39<<`#JU5Kb(pYlH#6Nq:Y^DKHW:/TXrCA@MJ/>!25\NY/ObY]U2^N)j5'i#G+RV]l,!Z;m2"6<+rVau +NN$r)92T2pBUfid`b0]!F%pACN%.=&#LeA;,2+WK/O_KgO;_'Z]U#;38C;s(DJn=EHhY/@^,u+`1I'p+ +^]1jA"Ata<^.#_"CFsYe`tb*lk#GiIBTXDpVTN=!7?*G(U$,8*b0%lu:]0KZ^O#P9dBlD>IE#o9^6POL +jV!.\@0XoJ7Q$cL1fnAIAh5Ff5RaU@46cBc4nYG6#')YZV-/o,=V"spV6aa2;\p.pgE88)]KaP +=0>f=1@`[QH,^A2^,:Urb09P).(0Jl)Ns\[[0+2$o<\o6B;>4ng2&\%Suip]?I[V7n'SQ1g#dMAcCM-6 +If/`V]>+-9+8tEj\)3eV]MI78kP'$(G3OLQfOA&2iTYfc[j-lH\QAqRr)f=:X']` +OaHN,VuHFi*;,n6gWh^l]6E_hq]>"inI,7`Ya]@QJtAQYPm8`lS#\BhnP"Etm"/5.jXHo=Jjc+CWZ6dEM_c8+gW9.P[gleFOZp,RNP/>8Ppc\]aA#n[;-s8Rb,fR2nOB_ +q=(=8ZZKX8XA]nd<#:!GN$"cOf6r0%bUDpM_5(`F(GB*"=]sGW +miS)`HhPj^7oLJ1$PR0DZFDg)E,uiEVp'JrP9+)m\S*0Ue5)0^PG2A?pPIhmUhDKPS"'0?h4*8Q\*:cJ +=f4Zqn?]HE1jrA0E:83]R#qt+ihU80)Z<(nFAc),/khdX8sCs@*"*QkY7!-AJjc+C/^;#5!^E:Gn$m4s +U=+-liiH'FWiT1K27Uh*/A0m;rkU)1JoO0c5pB']MAj\dJu=g,dWApWXA_G(]QuHFb>0\%a1:r<15F5S97GU7XfO3NqTWg_**8@O&pT6g.Dt-&gZJ4.,?"1&NlTuQ)4p&B:Y2N(G8DuL7&>\ +EDi$7^n1n(:5VZmKo*-2M5mj]*N5gJNpj#$ba8YKEDdK-WqShU,"8?m_SfTT7(%;cCMBtp@@2fm&LU!T +S+9nLRP$SC+@W-k_SfTT6oB=RCLbDkp@?nGVU]n[`XsX&M)Zqf^ngO*drf9%Uo6+UQoODrW%)$%N#L>m +>o;]L8An*I>UI-#\u$uO&#?-\?'mV;Pc0nOGn',P/due6,iYW`5X#d-+=Sd7(FIEg-*$Kn?e)c\\9#58 +UEN1H8^S59&Nh9e.SU^+c8m8OnOm9?]:ZfY45ZsY_`!NG+\9OCdCsuPGV2lnRP%:(F\5VuX_KK]m^k([ +o+ND/UhC:2#[W#qQ)4p&B:T[crY;]p,KS]7lJKs#*0ERLLm+RR4qSb]7A]7c`*'!+%H>f_QXQWK&@9Aa:&N>jeq*]1!,=tanFCF11;kaJ[g!mJ29u>_Hm=er1hO#SM-08Wia6pLl60 +Wg582S97HR5VK0$^Fid`S(DsBA/p^uOGFi@MPe$&\u*;.A-5A"j`FqjXAbjnCfPJg*KA[)+\%QLCH=o@ +$XJUd;q(qUQoODrW.A8dq`1b>r2mB`)];/A&1$8(9@nd[EL!HC-\@ga +H&;ek(FIEg-#1fYi2%LJd`uC*G>?-i.0PL;$<-"!_9Jr570B:m'5*jK2=ugsZKq"#<;EU58#-\Aii5V5 +:BWVVWY>o*/khdX8qK?9Q'Z]6b<1ba5%V_G.0PL;8lF^`_+gsU70BCp'5*l!TZU`/BGh%6oQ)u"j+nD$ +6sRJURdseK&RQa9@ht?,$PR0DP$eD/BjGriN$D4+&okU\aEsTc`[iT6(FIEg-,Bkif#8/>"R#8>`XsX& +M7=k08.-IaZ`#]dQoODr'`SuFTjP#=iR3Z0;@!nT91tBS4CDbuBt?!f@'lje0rSN/SuZ#SM-2;WPO&4@!7o+F4o3u3-=B2mZ[A#GMdO[pV$=XS+K3m +@H+@e;Z%n5A%Laa*:'!;fR\u+;@!nT$`$<$Ae24]/rq&:\om>ilK[Z[=#Mur]=.V)]C/Mk,J#RKegW%; +hLub1gbGA)!uXV)&1$7I:QZ".,\Bp#jia"&[en`jT1sXIoCKQs:HNX[9]*It&8VScpDlNVHaF3.mWfTC +%V%S1dhtZO&1$7I8^[/G]S)iOEat\0nKNALhRt.(NkG2MRo:BgF^a9-iX2$lpU]k&kRimEN(m_#O[>.c +S!"sK">_:/BSqe/NUM)EoDa:5fk3g9*e!_3=4c$SVL0%_QoODr'`T8N;;Ms;GdsM2=&Tr+U_"g2p.^Yb +bZrAd.B[!j])/VQ]0#J@)`J6K5(*(jg$(s#YqA]Sl]`)Z"_iAY":O&o\Vkd&EC:.",&VU^<+$JO(/=>g +iPU_"g"bBG!c9(L=nkF47iiH'Vke`85(V-)_RW1_&5pC2.79VAWB$n8o>e.0=j/lp@]IlmJ +F\7OR^IS.j!lmIT'/bJ`6jc4(8-L>o=YuJqe^_Qm&"bt0o#B.mpu73'Imb)"c8m8jhUdHOH.+J)EKBcD +9jo$(6BG<:(/,pYBJ.o??f1UmK(SckDbp3S\hJ-T.4KAtD7X\>EC:."@U:N<-(%,tl,(AAVkh[nGKfe> +Bm)4k80LOJ:(*p=Z`#]dQoODr'YT@+N^tMf(Ilb`6K +N^tO''5*l!65P*:/j(fIL_PHZZZc?^jXfkSQ6P=aW&.eI39ueCH\8-[*Va72&YGI_ +N$D4+'"dNP_R"_9=GhouU=+-liiH'Vked5Ns/*u]RD:d+KconFr'R`bLc?h59c#/%3[McEmuc2rT%JB: +S='\B,>nfqaA(p6ZO^=j,#4"fdtNXb:._,e:\WA\E+UFNN^t`-h&TL]JRP%:(F\3!HGS[m[FN+nA"DK-5T*V#`MMRIjdWApWXA`"j%$JW>a0'bHk@P7b +L_PFtGU]6jSkb0!PG6KI@H+@e;X>JNYCSn'kq;>plt.6"6BHpOpCkBl8J,r?<15F5S97F2?$I^B']GUd +4n]N"EC:F*)OP/Eq(:1#R./aZ1QG!L8Ae:#'>`-h&TL]JRP%:(F\3!HGU?A8`q5>/V/2DQN^tqjh+m +7%=sVV@+&MSWZ;U51j\L@`i?C#2b>u,>neFF"//1;FI#hQ)4p&B:Y2P(S8`2-_YVu[b5K*b-rG&4!IFW +9%/KNZVF(H/P)/^g%6n9*dYRG[FoB)j_U"Dpn@QPNeimndWApWXA`$\_?[%",kQPPCU;]1;mq"^4!IFW +9%/KNZVF)c$Ql%UPL02$YK^[cD/U/0G=7r8Q)4p&B:Y4FJ07j@e$C$(55*YH8#-\AihVAi.4S%.-I+Xu +Ke@`QB4(q`&Ldj>3%6%HMFu?OM6frKTaOXPo#%)fEC:.",#4#OPG6KI@H+@e;Wu!HN;W0XAfQq"OGK)E +ihWM0?'mV;PS=?-C!;!Ebf;mXj+nD$7%=r'-Ujlr_SfTTUsOf+0[?GbPArtt5pB']Lm+R]FCF11;c;hr +'92_$k@Ycs6BI"e,3#Ds1gQJ.l]`*pn3j$7nG*qlU_"g2UkguZ.SU^+c8m8jX?db5+4Q!WAfQq"OGK)E +ihWM0?'mV;PS>nWBsb!]Cra.9j+nD$7%=r'-Ujlr_SfTTUsOhi2o7ol0TJ[I8An(3EDfc)/khdX8d\jK +Ij7):!98kLJjc+C&LU#Dl,(AAVkf^?o>79fL1<=%(upDdJjc+C&LU#Dl,(AAVkf\)8E4End[ +EDf2p'U>O''5*l!_X#)9(tHH70TJ[I8An(3EDfc)/khdX8d\jK+/:mL%)rl."Go)e,#4"fdtNXb:.[1t +H_a0[&BAjf8W4ll#SM,T7%=sVV@+&MSWZ;UhJ4BlRE@K5KcgsT7Dqbp`1oh`56(QPl&X5GM6frKTaUq!>@$8[]5+\9OC&TL]*`Q#p; +pUbNS=^PNcl(saGr9$:_5p![C*F"s8MaWrpc%6rqPML +T(q.1I^cVgdf&1+YJ-It9lsh'XA`"J&u;4E`h=GTH,^FF"Go)e,#4#mGkgde8%WSTDOrq6DVn7bSj.^R +dPoR-M6frKTaO(rGXo+T`XsX&M)Zq.:5\2^e_uKn/ml>?q!d81(Z![jr=N>&39ueC]'t1Xnt;;f3$O&! +&LU#c8Pt/e$aUi(.4KAtrtsf_/W4U:$:,k2MMRIj#[NhZYYIcp@#tTG*/AVeb@MZU6BI"e,3#Ds1gQJ. +l]`*A#AH`REKJ_"M2WZW#SM,T7%=sVV@+&MSW^kU_Z+7VLU2*B&Ldj>3%6%HMFu?OM6frKTaUmmJK<%a +)+UJ6,iYVU3%6=O(FIEg,t04QK5$@WE/\d)$:,k2MMRIjdWApWXA`#M4tf$Wr]$8Il&TgP$:,k2MMRIj +dWApWXA`$\_S\BqrYS/$&1$82Lc?h59c#/%3[I5e4jjFGOi'/9?5Z8/&1$82Lc?h59c#/%3[Mbt]C5e1 +T`W4G.0PJe.3_NE9%/KNZVF)c$TEP@'ekY=+\9OC&TL]JRP%:(F\3!H\G8LjJ8msa5pB']Lm+R]FCF11 +;c4kDWTb1t$YM/R80LOB8J,r?<15F5S97G]BTS\NP"kCm9oL;p#SM,T7%=sVV@+&MSWZ;UDKY,X@N:Ls +OGK)EihWM0?'mV;PS?.HO`%O'[_(^f0oedJ8An(3EDfc)/khdX8rB,][Fcc?iB5*l.0PJe.3_NE9%/KN +ZVF(HhUdH#hE&Ldj>3%6%HMFu?OM6frK1"%]0g^_r\ +3$O&!&LU#c8Ps350QGYm.nd[EDf2p'U>O''5*l!+tZ?&[EH#P[X,q*.0PJe.3_NE9%/KN +ZVF(H`\-&nXu=-V,)%-O-UksF;/*TqERlQfFCF0f,>nd[EDf2p'U>O''5*l!+u;clFNdeZZQ7$t.0PJe +.3_NE9%/KNZVF(H\h;dV::A/%,)%-O-UksF;/*TqERlQfFCF0f,>nd[EDf2p'U>O''5*l!+ur3e2pM3n +YX-8@.0PJe.3_NE9%/KNZVF)S+/G>eVBT9"EC:.",#4#OPG6KI@H+@e;N0paiQ?AJ=iM%&"Go)e,#4"f +dtNXb:.\=DFl@))VCl,.EC:.",#4#OPG6KI@H+@e;O$I`(&#meGH?54&Ldj>3%6%HMFu?OM6frKTaMNH +*0ERLLm'%BUo6+UQoODr'LdUQBBuX?Y6Mg&,)%-O-UksF;/*TqERlQf`mTPkgnb$+N^t.cP9T"^W&.eI39ueCV1MZN*Nj7/L;c+rKcgsT7DqbpBt?!G80LOB8J,r?<15F5S97G];0:d;hB6*iEC:.",#4#OPG6KI@H+@e;A9O;ojQgA:*8YQ"'QIrrGmr^^=^39ueC_sbI-m)G\98#-\AihVAi.9aO3Rl?BM5Q:Qo-Vg2AF6Ci5#OB7F +=f8&D)l+BuBFXhmFN+nA"Go)e,#4$XFnb=[Y23KpE++0CrS)8*II4GoNZ:(Mh07aNHFtk(S97G]JTp)0 +G@2DL,>nd[EDf2p'[>so='n+3k02+hs7NRF*BSH2dn`3!oQXZ/39ueC\hJ-D&Ldj>3%6%HMWV4Y^>="e +%mTu2p-58Z'5*l!U3MdrD54]3;A_p"&1$82Lc?iPbFL_=\o.Da(LLF[Gk':_;a:*":G,n^nEA8p.=^FS +q-ATMSN1bgmp0<,8dB'S)_Ln&n5pB']L`:Dm(?iUWIe[@'Bkt_Se#A=4h"#60ddT=YC+8MfD,l5pB']Lm+P^2E!J-hkg4mX]r9GDL;6Pl(.DBl)1.s?g2n, +Ui2t8'5*l!@^'-?&RH[AL_PG/S.lP_78mI)H?JsdQe0g>DVr1arSlP=CV([3jN*JTkKcs#-FtmNegW&6 +'VshL;dFX)N$D4+&ogf;S.n]fnDV9GG1k[+I.6&[f55H_]XdoJa,V1hKdk/*-,oG,eCTVq\o;r7&Ldj> +3%6%HMWXTkM_Dg?k*nHIrT9Sf]!ctIb*>PZf7f'f:.[1af7d5_jYDie+\9OC&TL]*YA;amFnPIf`JYZS +)\4#Sr5C=e +4BNCHc8m8j!5#HN]QD.*.0PJe.3_NE(:1EVeQ(PXe^XaDW='APSW[I861Uc>&/e!6&1$82Lc?h59c#/% +3[MaCK=%/7WWb&HEC:.",#4#OPG6KI@H+@e;Y9IiE7$`57H$EI8#-\AihVAi.4S%.-I+Xu7A!jF]rij% +4Y_sf+\9OC&TL]JRP%:(F\7N4JtrbbNc@Go5pB']Lm+R]FCF11;c<6$UdCnX$grjk6jc4(:5XjkU=+-l +iiH'V%&=8X7CZF=&Ldj>3%6%HMFu?OM6frKd9D]QgT)s^/)uF"Jjc+C&LU#Dl,(AAVkiN486H*s&al-. +6jc4(:5XjkU=+-liiH'VoGjZOHS,)HWL8`c6jc4(:5XjkU=+-liiH'Vo\Y?I2-(*fK5j9d5pB']Lm+R] +FCF11;c6TEL$.j0MJtG3,>nd[EDf2p'U>O''5*l!U6Zoj\hJQ5,t0XcOGK)EihWM0?'mV;PSCM.Bn9`o +#Zmde'[\m+,#4#OPG6KI@H+@e;Uc>T\[o"h7ouRR'[\m+,#4#OPG6KI@H+@e;H+@+4eEaD[c\_,!.%O? +MJ/D#&LU#c8Ps350QGYm.I%8gZYap/7Q'I'&^:q6ihVAi.4S%.-I+Xu7?'Uem^Xfd4).G$%2'rGUkguZ +.SU^+c8m7?NBu!H>>o$hBTO>K-UksF;/*TqERlQfWXb1-gk_t/6otO.3%6%HMFu?OM6frK+\9OC&Ldj> +3%6%HMFu?OM6frK+\9OC&Ldj>3%6%HMFu?OM6frK+\9OC&Ldj>3%6%HMFu?OM6frK+\9OC&Ldj>3%6%H +MFu?OM6frK+\9OC&Ldj>3%6%HMFu?OM6frK+\9OC&Ldj>3%6%HMFu?OM6frK+\9OC&Ldj>3%6%HMFu?O +M6frK+\9OC&Ldj>3%6%HMFu?OM6frK+\9OC&Ldj>3%6%HMFu?OM6frK+\9OC&Ldj>3%6%HMFu?OM6frK ++\9OC&Ldj>3%6%HMFu?OM6frK+\9OC&Ldj>3%6%HMFu?OM3B,]#SM,T6jc4(:5XjkU=,Q?ihVAEJjc+C +O[>.cP9T"^W&/.S3%6&*+;#tiU_"g2UkguZ.a8hX:5VRc8An(3.0PJe.3_NE8oo`DP9Nm1&ogf;$:,k2 +MMRIjd[Xb*Ukf_:7%=sR6BI"e,3#Ds1hW18.3aHg&LU#C&1$82Lc?hebf7ZBh7ImGq<".K+6a1I-UjgB +,iYVU'S8`C'G2]]$i%U]rc%)JU$&%mq;ms@2e$Ee3%6&*+;#tiU_"g2UkguZRb)oT^"8g^CY,_+D/J+D +J,c@3?935oe3%6&* ++;#ti`(A@h?@VqHe#-"1r:^*`hs\kLlK[Z1a#h2W8J*BSM)Zq.KcgsT7DqdF]^FRcZa-n-a$9RnDh%Z= +X]r8p+$]bj?iPGpj.Dt$-$YkXO@#%bP9Nm1&ogf;gmD$IE#lZ3iPJ?.4aHVZ\)2Wr]aHLk(Vr!Y,)%-O +-UjgB,iYVU3%:;*@q4Qr?+.NCem!&54*KtcO$;k.hu!0:T/guTq!mBClEE'Xgd/UoM$+r]J'7)ff)?;\T;&fFD5;tjnU9QorDGB\"J0<&WKpt>Pmf+Is +^D+U$WQ-pu74f$LN2>?cUWqqo$?L,\";ZgXHZ0u*P/Dn;ckqtBD07BXl$keMcOs6WLHPl0FR+4$G,_3\8Yl)IJqo=^[9%gOX!B/"N.n/HgeX#8Ct"Ml`P$tn)&WZV3 +arJ3nT\6h&UVSU"qjgfl^ +E#CEhMitk^WTpJ%Fst/$HUkVo?1-Ak%t^jH_m`^]49$mKA"._$<&/ktZ9nPq,q=oXIu0jjBhn[r1#*?! +Z:^b3%huQ_J]]ICI81U/>-!>Gk8hIcm8G\gaE_1U$KEoksPPpu.!Vmg.0brUndS=g[eTpYUJ8Mq7;H*U +N+hn%V)1m+>\EnsAb\]3C4uDItgV7;fZbh77U)4+SK'r:02.rocj:HMd*=qq<>#i:?!Q?*6Bgm'FEMK_ +AZ`Gk%[rrTW%iRP)ec[P)B&I.9WAUf40drT#=j\T$MZ:ZSd2/k[]F.t@KW+92&D^NDK-a,_>Boril$pJ +0+dY2QOeYIFjT-hea/mPpUr-t8"H1K^.^[6B/BZZh]j-H/<9^fi9\` +557EddZ7B1J"(IJ),lf@JOLhA7*:^:sTp9/$8>c[XgNXY.g!DV_nS?.;WA5.smD5Q16'4mu$s=hOFY>K +;aElY]!I2E(!\^OPCiRH)>KX2E.V(FF#l(O!um@f,>*HG]q9DVVbLQ'\gicWZSbi:k"drJuI+j),ibo# +1!GpUc]UQ0oGqIJ$Ut]1+SohnHf&Z[[1KdG6/@lH8Re%s%[=_[kQkqU;)9eDjl_Q9?h>/N4')e:l_!BA +*::rq5U/pO'qETeim1(GBsRH0:`BqVDffFme%qkP(aj0Y7Q#*d!g\H1U1d0-32u9T#4\p-5SDGmWr+^\ +m1tDnX]Q0%$1P/]KA$$eVor]B.?2o:Q'\NAo_Hq5kb.c2t.R\^JH/pWn)>H#7G:DX;E>o&[cE%sPeP^> +AUed?5;QHu\n9VnVuh)aCp8#b]G9Pd*_og-Ep=g2*SiuC(5J^U-?ba>D>? +cLYL'V(PKlu?7HM$Fp+?FZ1eG]:=qq`ROZaR;crquRZLCW_L*9kd6s1IfkU*Z#[hOHMi2` +L3]]4X\:0E><]>?qD=?!ZiE7qgZNh2rd$9d7(%zzz!!!"Xb5VN/E!_L~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 207.31862] CT +[1 0 0 1 0 0] CT +N +-1284 -71 M +-1284 286.5 L +319.75 286.5 L +319.75 -71 L +cp +clip +GS +0 0 translate +320 287 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 287 0 0] + /Height 287 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0V>Gt6o+33oBoY6K`>e#k'2u +0^\m!X(OhU^9/ +\DOW*cc(eYa.;\V^\?s>A(e/!l+tW"n@n# +:?#^;H2[S^9Z!5UCXRDQPItVYVX3"%-rKS6Ci4-nm>VRJiVQ>ME[q'ikKTLJ;6\-fS2h7HY[PG(1Bldk +jCQG.Ek,GdLWD8X+0R\Rr-7#-HhVFS<%R^Jr>'_Nk"WL4d@s(O:1DDsX&mdIKdps>jd<+HB^rX]chP[L +G#[]"nDV8RP7WHZ+$P,Lo^(6]rLrjfK8/hR4cC_b9UV%pX`T[I4ErP,TmQP%s7q/NB$EqlP-!2%\cVWn +gD>(n.%*9lp?gU,rSG,.CYZF>nPeEN]mB>i2/6+%N0E^]dW\^Frl[#tq9_gLgbK)e;5)lX'%/S+`/GQi +i_Z40H_hgAIV[="r>(tfL*8p='HNu)1.c[fFp0484F$?^oATu\UeeUJfo]X]#:7[9KmZ)dWN6*h- +]Ut"$g3?8emCsW^Pom-,hsSiti;Dr7l!?GCqP[]`f<,6--krVPXA1q&o6E?]Zo +4Op2sO!lEJ]mp(]J,oa]W#=?ra'@^r/*aU45t773*>2_3Kl]"^cCFZdE?L9c7F#o(h7In"j?+T4p5748 +%2ut<=C#plh"9(R_1U2m]u!2ZCO=U30c"*932TbHbRfZ(H7/hGq,"qCu(Od=+*sGX:$M)2#"'rRTn6dP'l- +rRQLJ;((S:#5!g76,,:M?doDYXTABp:=*ngRXhtHgD^&MpZkiO5:6OjTO/N3KoUUfkSH;VFeN1+kgtN; +Tqbs2qLsrY?0E(cqK8K=kigWPI\END(]&iGIU2.R3r3um?g-_*Kmo_j?PiQmNdb9t(HVD8TjR$If7e[I +UL+i6KoUUfkSH;VFeN1+kgtN;Tqbs2qLsrY?0E(cqK8K=kigWPI\END(]&iGIU2.R3r3um?g-_*Kmo`] +>ea!-gph@)T,[`Lj7`6(ka*6t^\:44gpme>S9kO?43a>J7GeNpf#mM!1AZ-e?g-_* +Kmo_j?PiQmNdb9t(HVD8TjR$If7e[IUL+i6KoUUfkSH;VFeN1+kgtN;Tqbs2qLsrY?0E(cqK8K=kigWP +I\END(]&iGIU2.R3r3um?g-_*Kmo_j?PiQmNdb9t(HVD8TjR$If7e[IUL+i6KoUUfkSH;VFeN1+kgtN; +Tqbs2qLsrY?0E(cqK8K=kigWPI\END(]&iGIU2.R3r3um?g-_*Kmo_j?PiQmNdb9t(HVD8TjR$If7e[I +UL+i6KoUUfkSH;VFeN1+kgtN;Tqbs2qLsrY?0E(cqK8K=kigWPI\END(]&iGIU2.R3r3um?g-_*Kmo`] +Cqm+I9lde7HO-Q3c(3HTh[ITWb4-9'qK8K=kigWPI\END(]&iGIU2.R3r3um?g-_*Kmo_j?PiQmNdb9t +(HVD8TjR$If7e[IUL+i6KoUUfkSH;VFeN1+kgtN;Tqbs2qLsrY?0E(cqK8K=kigWPI\END(]&iGIU2.R +3r3um?g-_*Kmo_j?PiQmNdb9t(HVD8TjR$If7e[IUL+i6KoUUfkSH;VFeN1+kgtN;Tqbs2qLsrY?0E(c +qK8K=kigWPI\END(]&iGIU2.R3r3um?g-_*Kmo_j?PiQmNdb9t(HVD8TjR$If7e[IUL+i6KoUUfkSH;V +FeN1+kgtN;Tqbs2qLsrY?0E(cqK8K=kW7I:.t3[e0'=8Wl:uE`FjW,MZF+`NKoCIdkSH;VFeN1+kgtN; +Tqbs2qLsrY?0E(cqK8K=kigWPI\END(]&iGIU2.R3r3um?g-_*Kmo_j?PiQmNdb9t(HVD8TjR$If7e[I +UL+i6KoUUfkSH;VFeN1+kgtN;Tqbs2qLsrY?0E(cqK8K=kigWPI\END(]&iGIU2.R3r3um?g-_*Kmo_j +?PiQmNdb9t(HVD8TjR$If7e[IUL+i6KoUUfkSH;VFeN1+kgtN;Tqbs2qLsrY?0E(cqK8K=kigWPR>6f& +jMK,.a!u+a$Sr;6X2p!_LQ5Bq_TYBf.WSt[TjnhJ0_t+R:rm@K2%j!ih4-i`$]XG8WQBmgE(G:r#G5:^jK*De]_aD:JVsGloH1L%;OX$(): +,lk0QttmG#)X(G6[gFD.N"4ET/`Dr5a+g +_jtSSis]%^Frp+L^@FoA-r4/P)NBtDr/-3/sebLq=XqTtp'gU:sWCU'9`BC]9jhlcUqBB$jd4*Ks]* +mu^A;7)3UT0=8+itBfNu0V2o&\'prFs`X9`kV1N'!(A4n=UHorMgA?+P,,* +ZdIj[.#qm#[Y2j[:=<ZLB`hL(.W-rH:Ucs5V.\D[#k&h&GP'E +@82Aa,,+CqHK3Sj2\?*Yp+Vkk09B?6!TF17b>`(rr+psoe3=B\r,M.3O\;.[4AuhgY1BDc_!F6ba8n_4 +r=OXOQ[LlZE#Ah:J4>REr@k4g9`5'T"'L[TEb4>5-fV0lBQ]=z!1<]qK$Uc=~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 0 173.19932] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 357.5 L +1603.75 357.5 L +1603.75 0 L +cp +clip +GS +0 0 translate +1284 71 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 71 0 0] + /Height 71 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0VY>/>J*6)EiL6*Mr\,p40!)ZUG_Lh,++IeJB<7GE>o`u2?!@6\Z'c>A2Q7N?1%eJl-H,%)qB:^J\ +G4uR#_rl6t2a]YJ!rr<$zzzzzzzzzzzzz['BuGCX8E +<`<:.;;<_W74c8dL9DMC9VnE[i92U=O-hEm?*[KLAR(PRnHf'p2ElCUPoWkEHTG,,ZVW#`5(/aJl*q>F +:q%8dQZ';\:=/6r$23<7I?g9[5YpKTO9SL_<#uV]p.2C<[M@kF>F:8E<`<#pGF0&NLT6AdafD:+7>3E[ +mf:ON=DWS;LLVKul?QXCPgNp.Is;<(%$9O])iP't%W]PB0K%C>Sr&5uS;PCeW&7eHS9)8ZSd/us6sU@e3D;pa8!FPt3>IZT;/ +Jr6$^5X,#Oeklfk +cIfhnnEY+j=aD8!FPt3>IZT;/FYZIgY7&p`=&iXKul?Q6e,lVf?M]C6SaFBal +A0i66`r3h.h66`nKaC&ig\h>N^n7+ae]d]s +G%dG^-aV)Xe'_`Uh6>qF@^i]Z(>.b]rEa/r=\\G`M^4(OU6-U?#BO&/$uR:g$T:X==rl*[=;:=o0Pre9im++J`o^i(/?+XD(X,,_/acHa_D\$lkX%MfT6Yq=2W?4Ng"dqNQ732 +a[D@pVk%c0H + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 173.19932] CT +[1 0 0 1 0 0] CT +N +-1284 0 M +-1284 357.5 L +319.75 357.5 L +319.75 0 L +cp +clip +GS +0 0 translate +320 71 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 71 0 0] + /Height 71 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"/k;+.!_*68)B,eJlSb]NBssjD>ssidVMc]kP,+#3X(7A=-:sAe +bTo"5^>&,F3'FtD=e4`$4&=3"rRf*ZR63n`f&4-XGKFgHU+bUCn#U+j463n`f +&4-XGKFgHU+bW7Ca+TP9iVKO8Ts3X8J(TZa_3QJJ@4uX)>FtVF]uUq)H/]q>,$2#1M1=09>eu^Rra@I# +"^@SnLV:bDCjG"^p**SBjb\K>Md4)a-iRO-EWo[=pkQQ('l80T+8-m[YiU^kfSa"NQ7)Z?06.5#T(n)S +a;&N:iZIk<=,`)s\.4)FGr"(1rs/o?G'u?frH0+^+b-0"(=6D$''QM&oTt46qJ--1,p@j=>!RR/8>*^5 +csICukcY0^Q\5Ms182$`ZJl5oNoLCsZMsU@%FJ +qtF;u>*:5g]6CH\XY&2jk3(pTSkD^L5o&TJ8A,1eNfH.]3eE/'+b%2)'6 +Bn?7e5^rk]K`:8`hro'fd;\+5rpt[.qXWak2fIR6k2tgej>8\M*$-.nP"1MRaiT^/P,t`9jF$Xce`l=t +9#=R9$O]*\4o+pLaA>on=GI#(6W]dkT`aGbbD5C]]VYu8T0K7efPrT"`e^D95o +?hEOHlKYpj\Z)R-==dKP<-3SZ?:A8,9*MuNugI$]niHa0rWU,Yq\Z!eC9`0Ag#G6 +[t"NmAnLNDgYCRPIb]qj#o,UKo#.71"U4k4+S,Lu2\?hlm-NYZj[[?`%@DqP$_s<)C4C_?AWoI=e?<5o +jA/m:&(u==3O=JqZOQP\;<P?8g')(`RT1mPi5^3r?]1rM+\c<-@TH#r@&8?#6V,Qt2cZ!t\'4@t^e +C[`.f_HEt>EW#b1F",6To[e]9qlA$m6"t&4B4s)CIT8p:Imq'&D+s0b_Ka`2>E[9]*tmEX;$dE-RVj#_!OC:/Vq'SkiD$TK7a8Je.3Wb,d&[MH[:!;2@QQ% +N:cd];L]hq%PS8j8ZCQ2$fg:-(hZ\Xsj +$O[Id4>?PWEH.,1Rg\Jl]=[b-L>);CS!of8-O+&0"e@.n.e<3&eV^c0UE_EF&+akd7R#'e.bk`"6.BL6'A@SYY^sM)Z7R.:fon>6@ft^bu8W3 +L^]lY1`L2]K>]!*9UBS*.K+B)$A"cu[CWqQ4rr4,a"p"Ed+!d?c?sJGmA=_>3:tgSB`"i\1B78a!X9kd +Z+n&'e&#PEqYIeLq<'VN7kLZ4s*Df[;[)j)[aM&,`MKEV,$1O+:g>fZ8kB`!/.pQ)^,*Ok/S*S]"_rbOm-rOqOof@c:H>>&5XIb)lMf$Ib3k\ku> +gL'pBL\eHd5s]uPTYCMj3W>lXqJ/B[7WZ;#WbKJ(TL8;Gr)U9:2 +^?2QV^1M"jCMIUG,es@:"R4Tg^7(,t`o/@T%aq]^X?NmDDes3&]qDlt^V9e1nU3M~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.60069 0 347.4] CT +N +0 0 M +0 285 L +1283 285 L +1283 0 L +cp +clip +1 GC +N +0 0 1283 285 re +f +GR +GS +[0.6 0 0 0.60069 0 347.4] CT +N +0 0 M +0 285 L +1283 285 L +1283 0 L +cp +clip +0.941 GC +N +0 0 1284 286 re +f +GR +GS +[0.6 0 0 0.60069 0 347.4] CT +N +0 0 M +0 285 L +1283 285 L +1283 0 L +cp +clip +1 GC +N +0 0 1284 286 re +f +GR +GS +[0.6 0 0 0.60069 0 347.4] CT +N +0 0 M +0 285 L +1283 285 L +1283 0 L +cp +clip +1 GC +N +0 0 1284 286 re +f +GR +GS +[0.48 0 0 0.48055 0 381.51931] CT +[1 0 0 1 0 0] CT +N +0 -71 M +0 285.25 L +1603.75 285.25 L +1603.75 -71 L +cp +clip +GS +0 0 translate +1284 286 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 286 0 0] + /Height 286 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WcYHL(s8V'TY7VY7&eXCQ$S,Mm:dg13RtV+SQn4-A]$a;%=D/;h%02jcJjD^-^P<;imkhdQnp6kNS=/\HRCSBhL[]O1kLoe0pi.tRgUD)srdX-Df<8P"pJ[_(#V#1+ +s(M-?Bc@eL6:f%oLc?-7bn_YO3@0B@K)X5nh9Vp7<(%':&Z6i4<)bb[QoO8n'LLN]s/a];B@Jgh,)),7 +;\="!.[r"`S9%:0+mmSO+`%NROH>8s&TK9MRk7=(F%Qc_m=GYWL5JMF,iVckS;PI$$PV]nP!V]$AI,K; +,#S]'3#*%'U9`Ih`&X`k&COps;+VCUri`&l8>F7D5PS?H!AIIse +MF\m9i`&=9MTTN='BbmK6:ah*n?/aH'LF!=7Du1(Cpl$;c7(2qe6iPPW/)-S,#1SFWMjXA0QGAe.>7?@ +&.VVN.>1*ZMMP2.fkb*VS5W;kl(]gMVBSnDM)Z4^VkUKM_SeI4U_&\4*2auY#`1MU&Z;A/fttZfVkiPH +O::(^4^J_'KLD>fLf71(Cgl=n;c<748@EJp*j:AN66]/n`2T]clK[Zigt^YnDa/O/b0!=rjm1O%5C'(W +9Up/rMI$e7&C/_I'p2$X`2SPP'f?^JMH[-jmr.C8T3kc*g?ctSIemdYrr%g,:S0haocghuM/uE`dBau6 +_MNTI,'"!H3#*%'U5#YHWFE50:/9C+onA*Rrr2nZOc^*Vr9^uNMCWW%]NJM8m+J^Ta,Z]QH#ei;C^Up> +ScCJabH2I=&il^H1T5XFpD.2Fo +;c<7"8;;)dhQ2NT66]/n`2T^)iPUF[Ytdtd1`ok'=XbC0+!4j>nV%>ecC?oDI.P@;)o\)#Mi4(,Oc'pXrDrE;I=4iQ!rgOW?H7^D7'J;bVS/'ZtU/m[2GIt.(Q83_FmBT%(M +$PV]nP+iaZ15*j%$PfoOKLD>fLf70Oe^`4Gq>'.[roB>Ks#-\X>F7D5PSCeBOtBqI?DrZC+=,rG7%B.W +Ad]:8Sh5hB)Uh@L<>.O%VVA[@)IF&#=:3#*%'U9`Ih`&X`kkjFOKiP!Xp +'sVD)7%B-j;c24a@H*eU;KQnLL@Cf!ielA]66]/n`2T\O[P2^H.4Mhf,[5N>FE'b9,p4S#k,%$XGFP; +,iVckS;PI$$PV]nP+qh?15,C.pJjUc#`1MU&Z;A/fttZfVkiOjODNmhf6nC](.'3?7Du1(Cpl$;c7(3R +/0mTm/\8#-g-nQNWJEMKQ-C'kc8d1>Q\ArX[mcW`7(W_]3#*%'U9`Ih`&X`kkbaFMiHFI_MJ+4X&Z6i4 +<)bb[QoO8n'\sId/_hu7<"Wsm,iVckS;PI$$PV]nP+l_Y15+D\CFZ'lKLD>fLf71(Cgl=n;c7^38@EIV +F\P<3Q]R#%&TK9MRk7=(F%V>X#g!WqYO8?F[M'9n.O%VVA[@)IF&#9Up/rMCo1V(2g`:W/+1k,iVckS;PI$$PV]nP+q4b)8_r;l4q\i +KLD>fLf71(Cgl=n;c6RU,X](/<4X87LQIF7D5PS@++aUmks?dISkEH[G$crtJ5aAC+c6O[p<(*76)N&fEN7Q+maa1Y7YcpqTgl[_]%Bl:kRk(YSHM-Ro +o(&8/DpFn8f@SW``M\l9@H*eU;H,7o>IXc8Xs,ojOGHgIE@P]_ET4p`cqs>Y4*U*,)tq7/([J7eHhQgA +^d.M9^]+)qnDV9kZa6.7B3U`_kEH\2$HWkI9\$/!N[5t1<(*76$6MHZ-l2-e`'j3ZQ'IWoOn%u32-2C` +0,K],]6A2jn(\[*c8d1>[6h0Q4&`O:U14Ld3#*%'U;G-u9X.\A4F#6Li5($N042H+iK]HG59:gc4aHVZ +(LMQ0p$1'Z^9dUphck?'Y/A!`$k0N?.F8MR'N46.DYJ52?Rf"eSP2SmWJJ&jY,F?^Vl-GN"hNhd@.j3c +?+P,lc*4m*mp:"qi8ENp?[Xdd0lcU7[GnL@Vb_7$e"hCuR(2J]RhZej'Tu6!GH;-O6miW\E@N/-73?`Z +L%!m3>?lI9baIVgSXlHY/$WfZM=%$$oM)Z4^VkUKM_SeI4V!-m$%,n5MjGKlI+VCUri`&l8>F7D5PSBZ. +OtBoRSQlaA+sc/I7%B.WAd]:8S(f;6MMP2.fkb*VS5W=-Ce2!RKlh-"E(+nK79#V8 +Lf4n*.Opo>9Up/rMTuOM&?`1]WJF.[&ofBF:.8a#Ko'kG8^TOAftu:i3>GD*66]/n`2T\O[P2^H.4I;' +,X])i3i!t":.W=&Lc?-7bn_YO3@.+LKObHl>)-'FeHq'l'bR@=qkQ4'p:.<+# +W,/mrER$!^3[#bQ\EZ,K,.`;dLf4n*.Opo>9Up/rMRJ:N#^:j.=%%6D&ofBF:.8a#Ko'kG8^[6nCuI"n +p58&D66]/n`2T\O[P2^H.4NsiOs/U$gl=oK,iVckS;PI$$PV]nP/7t]cL$E%66]/n`2T\O[P2^H.4Nsf +Os/UdX5-hK";EQ]u5/-"Kom6S\R57pI>U_;0L"QRR.4OsG,X](G\K-f!8AqK`3#*0?AnHq>qV]2Becu^, +4F$\mjUJC8*?G+Lb:hbfJ%s5[]MmG@hZa8hgAM`L#(%4clPA?`s&8WAgCYlf7%B-jlfF"mF*2eT\lbWE +,&Z5@I=6O1/mVYqD4`q9;I'.pn`/WT4tk.:\F.+7O^ZR&nk%dmk&s-"+VCUri`,Pi-X1h@H26*tA&&$> +CZA,nR(_IKP/7t]cL$E%66]/n`2T[h2`J4jYEAhS`udPGr:Apjl+d2d_[j.YXn]f_Vb]6ukI*'ac7(49 +-6tsg]=ArE6:f%oLc?,tr9#G=h7@`Ebp0>T9rh]9BP>fY^ig`qFfYYS;*K`ZZ`2SPP'fDLB +F_Z/G\G>9!^JeihF`jP"f\"i-!sa]J'T[2+So%oqS5W>P5tH`Lf5j"tKoh*h&TK:8R$sHn7Vf8Glh1+< +-VsU9qjZ&ZG'8%>A7T+W@K#*SrPIn1kEH[h0QCu#U_"/Y.O%VV9r"JY[9B^&2:$o-K1ej1NQ3Co-]:Kl +Vl//H'jI'=iLH(*m#VY7?Joup$6^"Z,2uSOC3=ZAIX]#AJlC==`&X`kY_@pT4!KB?Lf4n*.Opo>9Up/r +MGcesKR8C,&LiB$S;N,$;;#boig`qFfYYS;*K`ZZ`2SPP'p[#Z-I+Ut7YN^t<=i`&=9MTTN='BbmKU83kZiL]%P6jb(LV]t,"<&RsJ39QM?[P2]=8#-\/E@N/-7:ifZ +M/uE`;+=*2E3F7C,)),7;\="!.[r"`S9%:0>F7CZ,>nf(3#*%'U9`Ih`&X`k8.WfRmQk_\U_"/Y.O%VV +A[@)IF&#;8$PV]H6jb(LV]t,"<&RsJ39QM?\KMj-]ufYt'LF!=7Du1(Cpl$;c7(2Y@H-(&80K8<<(*76 +b%;"pkF@\Z0dK,rB=T%F6:f%oLc?-7bn_YO3@.*p8;;(:F#tS"OGHgIE@NH-/PM[U8d\di34C,1#`1MU +&Z;A/fttZfVkciiaUml[DF^K6&ofBF:.8a#Ko'kG8RVu?kB96#+VCUri`&l8>F7D5PSEYL$t7qO80K8< +<(*76b%;"pkF@^P(+.>oL_N0":.<+#W,/mrER$!^Jfu#KHuqFoM3*Nl&TK9MRk7=(F%QdDQoMQ";@&+= +'bR@F7D5PSC_>aUk>km>)HC,#1SFWMjXA0QGAe.;WGPgl=oK +,iVckS;PI$$PV]nP%&VY)8`b$4!KB?Lf4n*.Opo>9Up/r$nf(3#*%'U5#YHWFE50:/9C+onA*Rrr2nZOc^*Vr9h2c%NRTPs8MuVb/M?=F6Chsp=X)^?G5(Z4kmil +3N&[WKo'k4,)),7;\="!C,g4m`6ck-o?B@@mM$W6`JYOJ/mDI]ftW#dlNchEgUG.e^]!l\B(+Cg-I+Ut +`V)YSK\;==&LiB$S;N,$;;oEJ&&i"KR$_PN;Jb4LOn%u32-2C^/`"*eGB%W-q8hjdC2r@CCY(IkkI*'a +c7(3N)3Q/e(>Op@+XH&H7%B,A1G^i+@X[b(60j..%j&B2q=5p5mb$/onTQ'=I(7i5qf_Bgr7f$&5eEWi +h-c]q[;Os/T+[FLG!lZ\&Z6i4HF]d4>b.IX/f&-*Lg)fS?XM]e9:*(._XmBj`FYNeB5qu#Ir\B'eunmg +(aQ_SeI4V"eIkL+o7\G!lZ\&Z6i4<)f6S +S(m2Z8Dh.0qnRabK7ee\&)iSX0H$BZ;V8k)\K-f!8AqK`3#-l>k9jis\ohf5,HX1)X4?FtB^riD\T27C +n(\[*c8d2iefbpJCkpaW.>1*ZMMP2._l6S4L51PRDf581PmZR3j,G.![E\G^$PV]nP%'?2$t6Tdm>)HC +,#1SFWMj6?C8r,Q@q0$AHMtsL-iO#Bc"T:%4$,2QZEUQ0r-<:%n\B\Xa,_=WrGR`=5Mk`igVUlhVkgPN +M/ta&Koh*h&TK:8)BBj#eS:*$C,@n0\?rWmG^OOPZ?To+HFinCX]r7mr%1HDHtT]99Up/rMTnICK\8Pu +,>nf(3#*%'U/n=qX7PrSbnZbc(+.%m>)HC,#1SFWMjXA0QGAe.Fs/_#dXnV8#-\/E@N/-7:ifZM/uE`@1*b3G!lZ\&Z6i4 +<)bb[QoO8n'WiMr_X*<;&LiB$S;N,$;;#boig`qF1da$Ofep5`;@&+='bR@F7D5PS?PWL+ko28#-\/E@N/-7:ifZM/uE`@1*b3G!lZ\&Z6i4<)bb[QoO8n'S\;]DF^K6 +&ofBF:.8a#Ko'kGM)0fViH@Tr+VCUri`&l8>F7D5PTW>\/8dtR&/&t4,#1R9Up1H0!,*$BH[tc +,#S]'3#*%'U9`Ih`&Xa^e:uj*/0s4S6jb(LV]t,"<&RsJ39QMHg$FK*$&LVVO[;UWWJEMKQ-C'kc8fJ5 +[eQ!466]/nU_"/Y.O%VVA[@)IF&(DcXabb^OGHgI.>1*ZMMP2.fkb*VS5ZlVPJ9Ui8AqK`'LF!=7Du1( +Cpl$;c7,CXaW^RZ87YO/.>1*ZMMP2.fkb*VS5ZlcT7>VT8g+eE,#S]'3#*%'U9`Ih`&X`3B)=sjUQEQi +,#S]'3#*%'U9`Ih`&X`spRcRlq,`5;S;Ki\,iVckS;PI$$PV]ndVA^fhTc]3-mURHL_N0":.<+#W,/mr +ER$"-]3E)\66]/nU_"/Y.O%VVA[@)IF&(EXF29pV_B4J""r37e8AqK`3#1i+lK[Zigt^YnDa/ND/PM[U +g<3ApE.a7.;\:I37%B-j;pd33+1,4R[dS.tc_"QJ>2%tF>F7D5Zj1G+JTnST)h^VLMF\m9i`&=9MKW`L +C9!Z1PEV4'H@941Tte?lA7T5/lYU(iSC8Oa`Vti-iK$;LK8N2C,iVckS;MLT`/,-p6UT*Wn(bHPXPF[G +?>Oeu/PM[Ug1@_!GnVQEPE:T!&LiB$S;N,$d>iVLn=eLC',)&(7oiYkMFY\,a#ElG]6M^2d$/b[F2KA# +7ALJ-E@N/-76<7\1K,j^#7hl_5'ZST_98/uDt[8drAkjqV!B1*ZMMP3YNnD36>l",oNOe!]V]o"EM)Z4^VkP3"S"&0s +f1>el=i<=uU_"/Y.O'S.Lf4n*.b^$):Wg7kldhLp>(>c7(2q7%B-*+XH&H7%B-XlI;e3_o'C: +2uQJtp4.3V$6^"Z,#S]'3#*%'U7IaARO[Ief[s<>?@VP,8Ul5>lSMqo(+.2%tF>F7D5PS?G.:.:ri&ofBF:.;e$]"0pe5JQjuDQnhOF&#:M,iVck$6^"Z,2uR$ +2HuP.kEHZI,#1S&&/&t4,#1RF7AbO[;UWWJD6T,#1SFWMjVs_SiF0 +'LF!=7ALJ-E@N/-7:l'&-;I"*&/&t4,)),7;\="!.[uJQE@N/dOGHgI.>1*ZMMP2.fmJI0;\:I37%B-* ++XH&H7%B.Wjs*QiMF\m9i`&;Q+VCUri`&l8+(=/.6jb(LV]o"EM)Z4^VkUKm#SX*[;@&+='p1gR`2SPP +'p[$6QoGhC6:f%oL_N0":.<+#W,+Z7`2SP,66]/nU_"/Y.O%VVAb-K\:.:ri&ofBFKoh*h&TK9MRu]7C +.O'S.Lf4m7KLD>fLf71(I"[>T&LiB$S;Ki\,iVckS;PJO,>=Vb80K8<<(%':&Z6i4<)bat@H(6S$6^"Z +,#S]'3#*%'U9a.g!!%P0dI*8.zzzzzzzzzzzr-tcJX)i?'Dr89GpCj7;<`W7YMOm%^hX2aX2cs6eHM$D +u]:T7,EjHu0s!K2Zpi3!]R'89d%NhAs8IB2K3iT),O6lNOult>R\BLI:/4R8lh,scL#Q[]aN-oaT+i%3h07`k8+ll +[qaEr3Mi6cDSbqc[c\h>KmcR#='mHJ5^17VX$cT/u,+bi:Y:_I]^NoFJ\/k88p%]:148%?H^D.pJ]Qpj +YGO=(iB?-#Q4*gC-]:Te&;)D4aU+R'n>qoZ+ZQgDij<]#]'.6N`%1P2P]Q<72nM,O`i^FfY'%O:nZEeu +[rp/1>2]jJTFqtf-0-o9HXJi:g04,LTAT2V8(1nB.Sio.h0[P4=YJ:&tI/*3tltdW5&lhodJr1A4br9R +u^0UZKjsq)?UuFhjJ,fE'inprC^A;ThMXck!D;)'80=fP[q!b!P!)?3]1`n/1aMfCaj5Y!(<`I8jdaHs +`G8D&3RuaYRXqhaX]6:<9c\dU[fB[(pS@N\%8oYZQL"WHejlPLaF77u!G!?Qgn%sbd`P&5Gk)C<=MR6R +eV1T6Umsk@!I/*42rSRViIqW+B??3B#RoSMqGIj31RGn>Di5(&s#7hk?pda`Aj2XSZ-Vp?3ieoIm?G5Vco%8YjV-:"po?TZ$n])`jMpEVXlh!Sd.HsPnGundF%,s%qCZ'be?5];e]lFd(CBmQ(j=l[P:)>5;uG; +aAf'mk]2p773&p]`='nZq9O,2QXgfCB5(2-\P@bW6?G3r=+30EaJ+Mes]:T[8Z=_(#aiuGS]nO/\NcQn +rp$gqX6\c/B4aZo$qtKK,/l^'co('%qa+"![f>a;g0Y;;umbQkE[52I@1ro(Om-L1E98)]BGk'eP_hX/ +:TIVNCc^m9=(`55QjG5h?p=[=$D6\f.jA++tH(2NUK+te5h_)pli8C8,aY*Mdj,]g^rcrKFRf;%P5Q"? +YeVZRRIJU>,:QA*LRW5Y!UoBlq"T)r:$^,MLRhUS?!V/!2E#a:^k(JU`T-?7C/i=&UISP +'H0Y(gf7$UJ44X+e.Q;8#BKi`7]Nj6SY$Sfq`b.`JXC!\gEjJ^1/+Sib?/l`N(G@l9p%jk":\stc>L+a +Gdc07qnI"7Mn`.+YXmm'd@!@"50Y;Dtk0;m-[F*CLQ'IV9Y?lYUp".0tC[^,nC\RFp@P1oqd.i(Kimgo +rceQmoctAu!p@@=gG!@W0A,V;TP+/"G;j!F%,q3.Ve7uD2QQltM%f5i3m)Z;5[l404DY90^m9 + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 381.51931] CT +[1 0 0 1 0 0] CT +N +-1284 -71 M +-1284 285.25 L +319.75 285.25 L +319.75 -71 L +cp +clip +GS +0 0 translate +320 286 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 286 0 0] + /Height 286 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0V^M@-:"39r[_+@n%r!,"@U7n;j#Ciir<(,dk%dIG7'a-fjE)I7@E#1ge5uB%2"VhUa8o[[H&8Dpo +M'=-t#V$TW^(1\1;"EXUr$6`3_s91EHd9/^IId#UT6!f$=^>Uj9W-A5&@QcGd%U.Ep<_79dcHg&Ie1fC +^]!l\kKfbBHes2Fh=3(X5KE)0keRKG>^PY!='k^dUQ8aX[F\c8rEXX'[=7cIqsRlVoZ8JQXIWnqq)8[o +HXU>+q/ZHlrDpT1qWm/\I/j0>fCqE%giM6CHdb\JXhX8$T7/hKq!`P"qU$nlSULL^oK/uC>B0N3l1#3( +5CS"AU/tZHjbbRk(jk+cl`J]3rJpi;5Q:GMJ,]9BpYV$9l;^nk[Cj/bIWWb^B:jZ0rQZkj[QO)u'8QU+ +EH1NTcT\u-ZHJhclD`<.rSE##mGeY20"Uc1CVTlFlh-HXfC/(tDl2DPV;J#^rq^Ec.+b%d\$KE)2rB!= +Sn`KJr+kpdVt@UID7ILO&cL!(rU+b'AHr,$F!jbT4EKZ/?N2VRSQ#Ar%AU0hs;D:(!srO1pVS:4]792<5RqB`&s(B'EF +Di9(dl*j*rjRh3$?ZQ![d4[NY[cj'JITuG;:;8CW-)]W9rK>oL^JfkP",^^hcsD?XikK +d4[NY[cj'JITuG;:;8CW-)]W9rK>WJMgie4[me'mo\6*IEr'Y#000!>ka.fg>P(Q`^Ff:.Vr&9gP1+?- +I`^i`7DIpUgS/%qqJFV53W6DMQ^iM/oLhro/c$ckh\Q0Rdr1.nam$9'^Z>%AU0hs;D:(!srO1pVS:4]7 +92<5RqB`&s(B'EFDi9(dl*j*rjRh3$?ZQ![d4[NY[cj'JITuG;:;8CW-)]W9rK>WJMgie4[me'mo\6*I +E]`Z4atB)U-LDt\mk!h\*aKYNDWJMgie4[me'mo\6*IEr'Y#000!>ka.fg>P(Q` +^Ff:.Vr&9gP1+?-I`^i`7DIpUgS/%qqJFV53W6DMQ^iM/oLhro/c$ckh\Q0Rdr1.nam$9'^Z>%AU0hs; +D:(!srO1pVS:4]792<5RqB`&s(B'EFDi9(dl*j*rjRh3$?ZQ![d4[NY[cj'JITuG;:;8CW-)]W9rK>WJ +Mgie4[me'mo\6*IEr'Y#000!>ka.fg>P(Q`^Ff:.\'of(m#oJ$dN/JecGIlod?T:9VXD4;o\6*IEr'Y# +000!>ka.fg>P(Q`^Ff:.Vr&9gP1+?-I`^i`7DIpUgS/%qqJFV53W6DMQ^iM/oLhro/c$ckh\Q0Rdr1.n +am$9'^Z>%AU0hs;D:(!srO1pVS:4]792<5RqB`&s(B'EFDi9(dl*j*rjRh3$?ZQ![d4[NY[cj'JITuG; +:;8CW-)]W9rK>WJMgie4[me'mo\6*IEr'Y#000!>ka.fg>P(Q`^Ff:.Vr&9gP1+?-I`^i`7DIo,g@(83 +17:hi6X\eSfXX/V1,.J4rKin#>P(Q`^Ff:.Vr&9gP1+?-I`^i`7DIpUgS/%qqJFV53W6DMQ^iM/oLhro +/c$ckh\Q0Rdr1.nam$9'^Z>%AU0hs;D:(!srO1pVS:4]792<5RqB`&s(B'EFDi9(dl*j*rjRh3$?ZQ![ +d4[NY[cj'JITuG;:;8CW-)]W9rK>WJMgie4[me'mo\6*IEr'Y#000!>ka.fg>P(Q`^Ff:.Vr&9gP1+?- +I`^i`7DIpUgS/%qqJFV53W6DMQeY@5S[(m8P=^*,loPS:[msL(At-C3'%:cWI`^i`7DIpUgS/%qqJFV5 +3W6DMQ^iM/oLhro/c$ckh\Q0Rdr1.nam$:Rb`fAj>0K)hX/O"]PI$-MbWIndW5ZuEZ\hr14?9I@`QXOP +MH\4d3NK*tb`fAj>0K)hX/O"]PI$-MbWIndW5ZuEZ\hr14?9I@`QXP#d44u/^DnIGU^]P +*PGMRDrIEZ3!/mPpUieoIM2XeBWmOe>7m^qr-KKo+U6i(@U1KMo:pYJ!"9\).Ppu-uQ7uj*'IC_/W"6f +[Yo4'skHKh9r@WT(\mt>i0>882l.E7N\))Gsp`R8_]NcKD_6gc10>IF*D=Y__rUNa#=@M8q4#Y-sfD&VLg2! +lTs8;KK=mXEqn+9QB?+9WncY^/Ip;.1jXDR6hIq$;FHKUiC`o_LK>7Ym>q2RV5jk^gbV@>?]bVRT#E5N +,,IItq-(Hq`hdoTn)oltKMm+Ledg!;RXU(9KdE,<8ak*q^OBAA(\HgJ#WkROm-1]Qs^%r_:0"O0%bCfj +-`If&Nb4E]r=V=-EbjG6gClScubhgbZSi=[fYr:9X\4C4!Fh/T`mD>l!,/[sMUr:ogTc(BLbH+[QJN\s +:MODXgbkB3AGq'S)(U@I2floB(F`45Rq/M5e&hgJ"U*rYK8hhm%KORu1`b>gA7cf3sDg@Nq$A&llc44b +Aln1UlEXGgtFr:.i$5QCcazzzzzz!!$EPr""0p]0Z~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 0 347.4] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 356.25 L +1603.75 356.25 L +1603.75 0 L +cp +clip +GS +0 0 translate +1284 71 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 71 0 0] + /Height 71 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0W:InH#(r0RBLkp$!W^TH$&JYn?85r!aEtL]($]0[Y'.mAk&J;-sB][BrZk/'0+V>;%/L3ZWKsViS +[#g(L60&e26hf@GGF4k3U[Rs%>kE;B1WRg_L6(4X?cG;pIK0?Jzzzzzzzzzzzzfpt?W^9+MSI!iTCobT +5c.+Z.\q(h9:!WW4NI*BG-!!$glAmkZ>!7mu][JJKN`IhM]oXe7NIX]"5^[tLuZZ'om\[f8IkA94j!!! +"\ah)ccH@'utD;*M5;t8eiR5<=@e$TAPZga51=13&)rpf$h'.6P>laL`cG5M"#q@f1$n=rL7/mc1mT!l +>G]f>2A04.b&>lXj)aC0+0EqAG<`HZai`f8s9iIQQ2mdBLP1-KmO?u8X:/6pK2]6I+Z +os;]N>iku)AH\Yc-sUU.;uk09Cin)*$;It)I6(nXlP>lXj)aPldUdn>2iH2$a_`PKlm5F504cGEjm?*g +lDj[U+'(QTOr;B1)]p2,)N>]\i=J[r>%o#URohfnMD=WFNV2;H8q!<<*BLU"+hiSia&%[P$$X&lLiT@V +?*6UO66lUOH8Mh>*7?7hd%];Dd8YPo&I20)t&!!(*<>-1On9GA`=]mKM!SNGHNd8<-;/tI\\IJQqCl#U +oe`PLEfhXYBkk5"W3okQ0e^0DY*p?YrBf*)-SJ/i05B);E%COa."]tM+k]=YDUF6-PLIX]$1,fS6li1< +)Yb,Oe/)5/VX6a^S6)Bg9n2XDV_n3FmIU!4*D;CT0@[,/mC@EQTs=h3]d-4n`-B7Ntt +Ogqtk0,rSoHai,o&#!$I'kn)'K3e[JM:W$P=Vq,=J;qQ"$ig:C7T69c`lH +,4B4kHI63$ucz!.a]b!rr>:s$kILiT=C$F\G4L+XH&H6kVg1:.<+#-oX4]S;Kj(8AqK`,_SRUMMP2.DK +_C,'p402Lf4mW#`1MU&Z;AYlnEE/+pfD)V]q98&ofBF:.;_H@H(6S&jdd;73j$%i`&=9MK6&@`2SPf84#kcWJEMKj^s:);\;S,M)Z64KTM!g&TK;CbmkDb,*EKME@N.=+VCUri`)/3*@=NM,U"Gm<(%?c,# +1SFW@0\e9Upu26:f%oLa7XAS;N,$;/UQE3#.R/OGHgI8I1/4'bR@6kVg1:.6EO,iVckS;M?n_o/O1,_SRUMF^')`2SPP($0%_M,P!X#`1MUObAgP;\="!b0:D0V]q98&o +fBF#pBnY,2uRdRiNhnE,`&307id]8AqK`,_SRUMMP2.DJ!>:gnuD@,iVck&jdd;7Du/R2mY2XmSf8[&o +fBF#pBnY,2uRdRou+M)Z64KTM!g&TK:XR$sK?qXs0sCWsZ6\PGd`8AqK`,_SRUMMP3YRS?RR+$ ++N-`JYN_0/EtLk<:0u+VCUrOq87G.O%VVCGRh*FmRbc@a6h=dff);Oq87G.O#0B&Z6i4<4#g:$O[%="8 +hfZ4+$\&=d\>jT9=khLf4mW#`1MU&Z;ARR[KR(I/*3Xcqs8J/51,p:J!lDs%dJ3!6qp[Dd!nl(;>4op> +b=4gu'`r>(cF&3J)(2,prD*#i>V.mdkl^6c6EK9[7%(1ec>dK.erCj=dZ'@_N9G4R] +4hEiW&t-/,4OQ=dZ'@_N9G4R\9I`N1*F/,U"Gm<(*76f$#[=e$r1F6:b7]^Thuc.O#0B&Z6i4<4$7L@@ +G2a8eOJ5ADPSHoi+ + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 347.4] CT +[1 0 0 1 0 0] CT +N +-1284 0 M +-1284 356.25 L +319.75 356.25 L +319.75 0 L +cp +clip +GS +0 0 translate +320 71 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 71 0 0] + /Height 71 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0RYt?6<'F%qWfg8(0$S)gY74`;ob!N>bb0E=)`7?m:,uRhNiWE:bLffIhL]e*X5\qu&ln'bVAhOKY +2SnaiGKn7fpJjfQjjkkj>05%FImlW.#Q<6cP/gqH1I +At.(d+'d9hIYPM[d:S)46m/*CHbDj5^rDtI-+7c_%UjHi2^CJ0+*jL;SYQU6.:97A>N\$k@aU:9rX\\1 +baj\-A\P'NqcQVLmHY-c;5;tVG]=qeJ-?K`Pkg8i8>`S2:[)"H0JYM@^iD%h^J'M1T_UAI=5 +C)>&#l4jXWhk8*QDie'k$9^QXkFAROuqn'b],4$2P=b3XI_b9ACthYs4sUDq\q?WNOo~> + +%AXGEndBitmap +GR +GR +%%Trailer +%%Pages: 1 +%%EOF diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_case_3.eps b/moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_case_3.eps new file mode 100644 index 0000000000..d80c371859 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_case_3.eps @@ -0,0 +1,1567 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: (MATLAB, The Mathworks, Inc. Version 9.2.0.556344 \(R2017a\). Operating System: Windows 7) +%%Title: I:/Entw-Technologien/Studenten/temp_kai/blend_case_3.eps +%%CreationDate: 2017-10-06T19:28:14 +%%Pages: (atend) +%%BoundingBox: 0 0 774 521 +%%LanguageLevel: 3 +%%EndComments +%%BeginProlog +%%BeginResource: procset (Apache XML Graphics Std ProcSet) 1.2 0 +%%Version: 1.2 0 +%%Copyright: (Copyright 2001-2003,2010 The Apache Software Foundation. License terms: http://www.apache.org/licenses/LICENSE-2.0) +/bd{bind def}bind def +/ld{load def}bd +/GR/grestore ld +/M/moveto ld +/LJ/setlinejoin ld +/C/curveto ld +/f/fill ld +/LW/setlinewidth ld +/GC/setgray ld +/t/show ld +/N/newpath ld +/CT/concat ld +/cp/closepath ld +/S/stroke ld +/L/lineto ld +/CC/setcmykcolor ld +/A/ashow ld +/GS/gsave ld +/RC/setrgbcolor ld +/RM/rmoveto ld +/ML/setmiterlimit ld +/re {4 2 roll M +1 index 0 rlineto +0 exch rlineto +neg 0 rlineto +cp } bd +/_ctm matrix def +/_tm matrix def +/BT { _ctm currentmatrix pop matrix _tm copy pop 0 0 moveto } bd +/ET { _ctm setmatrix } bd +/iTm { _ctm setmatrix _tm concat } bd +/Tm { _tm astore pop iTm 0 0 moveto } bd +/ux 0.0 def +/uy 0.0 def +/F { + /Tp exch def + /Tf exch def + Tf findfont Tp scalefont setfont + /cf Tf def /cs Tp def +} bd +/ULS {currentpoint /uy exch def /ux exch def} bd +/ULE { + /Tcx currentpoint pop def + gsave + newpath + cf findfont cs scalefont dup + /FontMatrix get 0 get /Ts exch def /FontInfo get dup + /UnderlinePosition get Ts mul /To exch def + /UnderlineThickness get Ts mul /Tt exch def + ux uy To add moveto Tcx uy To add lineto + Tt setlinewidth stroke + grestore +} bd +/OLE { + /Tcx currentpoint pop def + gsave + newpath + cf findfont cs scalefont dup + /FontMatrix get 0 get /Ts exch def /FontInfo get dup + /UnderlinePosition get Ts mul /To exch def + /UnderlineThickness get Ts mul /Tt exch def + ux uy To add cs add moveto Tcx uy To add cs add lineto + Tt setlinewidth stroke + grestore +} bd +/SOE { + /Tcx currentpoint pop def + gsave + newpath + cf findfont cs scalefont dup + /FontMatrix get 0 get /Ts exch def /FontInfo get dup + /UnderlinePosition get Ts mul /To exch def + /UnderlineThickness get Ts mul /Tt exch def + ux uy To add cs 10 mul 26 idiv add moveto Tcx uy To add cs 10 mul 26 idiv add lineto + Tt setlinewidth stroke + grestore +} bd +/QT { +/Y22 exch store +/X22 exch store +/Y21 exch store +/X21 exch store +currentpoint +/Y21 load 2 mul add 3 div exch +/X21 load 2 mul add 3 div exch +/X21 load 2 mul /X22 load add 3 div +/Y21 load 2 mul /Y22 load add 3 div +/X22 load /Y22 load curveto +} bd +/SSPD { +dup length /d exch dict def +{ +/v exch def +/k exch def +currentpagedevice k known { +/cpdv currentpagedevice k get def +v cpdv ne { +/upd false def +/nullv v type /nulltype eq def +/nullcpdv cpdv type /nulltype eq def +nullv nullcpdv or +{ +/upd true def +} { +/sametype v type cpdv type eq def +sametype { +v type /arraytype eq { +/vlen v length def +/cpdvlen cpdv length def +vlen cpdvlen eq { +0 1 vlen 1 sub { +/i exch def +/obj v i get def +/cpdobj cpdv i get def +obj cpdobj ne { +/upd true def +exit +} if +} for +} { +/upd true def +} ifelse +} { +v type /dicttype eq { +v { +/dv exch def +/dk exch def +/cpddv cpdv dk get def +dv cpddv ne { +/upd true def +exit +} if +} forall +} { +/upd true def +} ifelse +} ifelse +} if +} ifelse +upd true eq { +d k v put +} if +} if +} if +} forall +d length 0 gt { +d setpagedevice +} if +} bd +/RE { % /NewFontName [NewEncodingArray] /FontName RE - + findfont dup length dict begin + { + 1 index /FID ne + {def} {pop pop} ifelse + } forall + /Encoding exch def + /FontName 1 index def + currentdict definefont pop + end +} bind def +%%EndResource +%%BeginResource: procset (Apache XML Graphics EPS ProcSet) 1.0 0 +%%Version: 1.0 0 +%%Copyright: (Copyright 2002-2003 The Apache Software Foundation. License terms: http://www.apache.org/licenses/LICENSE-2.0) +/BeginEPSF { %def +/b4_Inc_state save def % Save state for cleanup +/dict_count countdictstack def % Count objects on dict stack +/op_count count 1 sub def % Count objects on operand stack +userdict begin % Push userdict on dict stack +/showpage { } def % Redefine showpage, { } = null proc +0 setgray 0 setlinecap % Prepare graphics state +1 setlinewidth 0 setlinejoin +10 setmiterlimit [ ] 0 setdash newpath +/languagelevel where % If level not equal to 1 then +{pop languagelevel % set strokeadjust and +1 ne % overprint to their defaults. +{false setstrokeadjust false setoverprint +} if +} if +} bd +/EndEPSF { %def +count op_count sub {pop} repeat % Clean up stacks +countdictstack dict_count sub {end} repeat +b4_Inc_state restore +} bd +%%EndResource +%%EndProlog +%%Page: 1 1 +%%PageBoundingBox: 0 0 774 521 +%%BeginPageSetup +[1 0 0 -1 0 521] CT +%%EndPageSetup +GS +[0.6 0 0 0.60069 0 0.20001] CT +1 GC +N +0 0 1290 867 re +f +GR +GS +[0.6 0 0 0.60069 0 0.20001] CT +N +0 0 M +0 867 L +1290 867 L +1290 0 L +cp +clip +1 GC +N +0 0 1290 868 re +f +GR +GS +[0.6 0 0 0.60069 0 -0.40068] CT +N +0 1 M +0 286 L +1283 286 L +1283 1 L +cp +clip +1 GC +N +0 0 1283 286 re +f +GR +GS +[0.6 0 0 0.60069 0 -0.40068] CT +N +0 1 M +0 286 L +1283 286 L +1283 1 L +cp +clip +0.941 GC +N +0 0 1284 287 re +f +GR +GS +[0.6 0 0 0.60069 0 -0.40068] CT +N +0 1 M +0 286 L +1283 286 L +1283 1 L +cp +clip +1 GC +N +0 0 1284 287 re +f +GR +GS +[0.6 0 0 0.60069 0 -0.40068] CT +N +0 1 M +0 286 L +1283 286 L +1283 1 L +cp +clip +1 GC +N +0 0 1284 287 re +f +GR +GS +[0.48 0 0 0.48055 0 33.71863] CT +[1 0 0 1 0 0] CT +N +0 -69.75 M +0 286.5 L +1603.75 286.5 L +1603.75 -69.75 L +cp +clip +GS +0 0 translate +1284 287 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 287 0 0] + /Height 287 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0Wd>M9(IE(7D2+#@i,9a!(hQo1HVNhgDa;7ueQlaa](gp?%i_ +pAGP)#Q$jahY3oH!se\Z'Y7^M^93Ss&NLT6AdafD:'p:tQJIX79OO?E6iC@\e$cK2R%(9pjA\NB7BP7[ +jIB/7F6I/>Kiupn(>f#Qn>]k'?eA,'#/Jbn_YhS2+g@YW-"lmh$2CALa.H=#Q#\&NLSg;c.>=0KJ<\_nP)O +Y"9c^E`#9sHliH[_<$KCMTDcq2-ZH=0KJ<H8G"Dbj8Ln'@DWG#.9I.9Wa +D_GJ3r8*+pNRQbA(+/47Nnk]PG@Ck;,:%:[X(^c62N$+`Qn)Ln'>ISKU]6:=RmHN)t5QCZQ)-_?rrt+O"3`fLSqmCrUrE$c>&e__U66\A8M?`ZNq93QG+YbGr,,_/h4FHqnp?gW3Sj^0E_Nul\ReEr; +_W769^5Au_1SLQO']MGFkXT>$^5X,=6\)d +l,bM>/j^a@r/*&b;&FaQ%%iEuWG#-F04$b\il'*22nNGS]6E`1fsB!fpY;N6O/BV*/POGM?%Meun@7q` +Kg]fH's6RH?5k*rM8<(%3>F-GS%Z#>qWcJ'7sA>?kbXVPqXi64B=tu29[5Y8B:bFi?CREs+d!^L70fIH +Oa_5h)AugO%$6@fWG":r>?`1upu,:]IDhCBN)&894;/=0Y%WQVt7P(YWL1LL4hrn)d\Xq +>\1f?U4eEFWMh[YR,!"[dlCb@G]sPirF!Z_]gH6d<:nGZ7I3&#k9MefHDSlYsd")t$nJko-12)bGH8VBK,7H@FtROq3Np#gGfVT]0L)_UpH<)dOpT3X`RjA\NB7BP7[jApG! +VqmKg^[&]>T:Ce]D<<#X&ig\h;c.>=0Y+(DFS9S(^+IR-\_rZM;'Uj'Lt@QHaJjucMH[??agF++F%kNb +]E-bt0)4L,eCoZTM566SWJI(%>-iq)'qWm"?38a^?<8cSjA`K);n)8-/7Kcb;\;#)[:Tf1$d\'"0*,kj +DZU`&E[k7hK88r"/7Kcb;\;#)[:Tf1>OJ"&q@^U;n"t*@-`<\fXPL5Y$]1C2aJl*q>F=4DkB-.D!]GTg +OUF?5(%lBK(9rtBWJI(%>-iq)*I:KDT"qCP]F:#44uj>e_YC>*66`-iq)c$ngJr6$T!i2?NPI32_^2W$U-QcNQ@1tZ&m&+Ln'?+Z\=fZSsKEu_As#"_Zc[&MT0>\ +*:E(WMic#ZLn'?+Z\=f(rsJj'mU,.A&jde?U@F\`L&4uj66`a!8hJk+C>/8E4-%nZ]7:UQ2 +&75/V((rVBO],+m[dXKinXX>$:#J1[.4'X8:.8qCqQ^eK&ig\h;c.>=n:ip`#tb]]_XhhD.3TsW.U#2f +/7Kcb;\;#)[:TfMYrVOHr].V2kEHTG,,_0C[G"&#,]Y@YVkVaYiAEF;b8upci4j;-.3TsW.U$noqSm4m +O])iP't%W]YCS]@p8E07:3')Y+XD(Xg(Z?Xi8l%e8E<`<:.;;<_IGG&b8rMZ^\^!gPRnHf'lB8)J,#L\ +?m1Y2&NLT6Ada[:hA>khs&mam:H58:&/$uF98_nJ5@ +M4BIEWMh[YG_Xo/_n>1Q?=V80-%nZ]74_jCf5)Um;\;#)[:Tg8>4+n,B5HOdig`n58EL +,B>8KD54Q/U>Nu'ckc'Hs'21d;b@=PS;LG*bklq)*us>$E^WYkbLtb/^2rJ_QX>2ek^0Ji(1-iaR-3AD +IK*Xo*9WP!66`0E\ +]5@Gj47DOLASZ(^Hct/^^HLsk);8,nqY2T:I.RB.;b@=PS;J_7?q=)NYIO+1#+$QT.U'p\gUFfVHh6CE +aYt8*If/lj?_@%qoX.\_O8gO/F7.ho^)mFB5Y0s87#;d)c+]$;jb%+%>`QmBE^`W;iENd/F^)@[`05+% +ET4oPYIui[/\K%%CO3HpY-5k%;*dVY):TF6F#^(^&/$u<;.BNd%_4r9K=Mta;pdr" +gpscTpIGh[H))<,kEHTG,,ZVW//lq[Ip9]XE]G>AU4qqt;qASL^:WhcPL$,6O"F&N3MhCjaJjt.bD0U? +o2dP7jA`LbZY.Uuo#`J0^[:PKQ.R)%.4'X8:.:C<6h4/d\/\@37>na+rH^D@hg4UjSXl=45Q:H%R5:&U +ph@/j3TlV>66`8;_UY\gNu^<*jBLfnT7?Lsd>W:XKul?QPRnHf'iC\bUmWmB;>D;C +86h1rWG"F:8E<`66`Jr6$^5X,.3TsW.\al(6F)F!R*-(%'t%W]PB0JJ+XD(X +U;VpVo%1fqalS>KMH[??aZ68`&/$u<;50D=Ao1stG_B=^aJl*q>F:q%8dQZ';\:>P%I)e&m"L;:`oW#H +MH[??aZ68`&/$u<;.9eS*B]!,ipdjP7?!dp>-iq)3N&)Q&ig\(@Q5N*h80rti!lS.`_/b&ftug?;b@=P +S;J^L`/or;Yo.">N/`]uZ\?L]Vj%`*3>GD#cllQ1,;JD>(^UqbAdafD:+7>3E[mg%#XXuoLqO#A5`D?[ +##@[iftug?;b@=PS;J^LRZOC_@BW9c"J_rP!E2j2[P0`)PS-;,V]n`l0;PM#nFqn$^5]hW3A$(P1;,M,;0KJ<\&jde?,"deTUmZkf,$pg;=2[A&W&7eHS9%:/+d#\8-.X37 +fo+K2?@au4Lu,,02-ZH# +2-ZHM(-;?sP9lPuQ8%/POGMV1arOWJD2Q*R`FhC_<";mtt3V't%W]PB0JJ+XD(X +U;Wp^1i3^A`>(;-,$IlACUPoWkEHTG,,ZVWCg9LHE<@.]&Ik\;2-ZH3E[mg%7Y`g3%XSY^7;[-8'N%_C[P0`)PS-;,V]n_=l2Ma1KtT21r)?'Z7BP7[jIB.@#`5(/ +-m>D$3G8\&`:He;3>Jr6$^5X,.3TsW.\_TXp6iXL/`Na/6r$1Qftug?;b@=PS;J^Af)o%2/6r$1Qftug?;b@=PS;J^C4Rl?4)6r$1Qftug? +;b@=PS;J^=0KJ<\&jde?,"`,T'rGg+ +[2Hq5,,_0dCghA0.4'X8:.:BYd`Td=_rG(A.O(dbenec8c7(&m6r$18&CTjGh]c)53>Jr6$^5X,.3TsW +.\_TXqQ`kG9roOZ.Vd3D-Kgms6:g0:6jY%0C[)HPeS?kGCX8-, +[:Tf1F&"/-,]YB/KTHE"i#t5X7B@\R.Vd3D-Kgms6:g0:6jY"Ge>O.fMTDcq2-ZH6LG]epH +7H@FtROq4Y3MhCjaJjt.6=0KJ<\&jde?,"`,TS]kEYm7+@F:q%8dQZ';\:=/ +[!l%?LK-`;7BP7[jIB.@#`5(/-m>BDG468bnA<*n,,_0dCghA0.4'X8:.:BYdb6d-#a[/Q'p2GB&tXOF +fd#DI_$;&UHY6QMS9%:/+d#\8-%rWKVJb@M7B@\R.U(=D2G'RA8uP)GBK>Hr=E'966`KeXmFntiDd@hi +q!iq(p7i`.ki0R>dlrR>9[5YpKTO9SL_<$`Rd"U4rutJU3>Kg.i5($b'=PBZ+$P'sqtBE*:EnV3iCfLi +:&?'A0KJ<\&jde?,"`,tfk)nsh,16tE[k86mWV'+\T29M/_s_sHM$FOX&l4t/%.,lkEHTG,,ZVW#`3iN +Z\Td`>-t5d(GD@>ET6-*S)(::h7In)m+LQnHg]:V8(6>P(+/47;F3q8<(%$9Z&kqhGc;K+L-;\.Ms=pC +X096`o]X]Y+!Q0uV3aCEo[=]HD[VbM:+7>3E[mf:OBBBL/Sl$*/D$WXCi+$;pu.!8IJ)-amqE/nF&"/- +,]YB/KTK`2dlKul?QPRnHf'i@:gjQ1Aum9[5YpKTO9SL_<#u[p2?;0p>k#>-iq)3N&)Q&ig\(6:g1SMC`5N +E@kqO(+/47;F3q8<(%$9OXmEpi$%H@M)U0);/66``2dlKul?QPRnHf +'i@:gjB>N)n.mp>f9^8MCUPoWkEHTG,,ZVW#`2g@MCdc3i*+X!/POGMV1arOWJD0R,.EGe/E1g8>1Aum +9[5YpKTO9SL_<#u\%7H//7PB!jBRUHZ\?L]Vj%`*3>GCX8E>)qkb'NoAXGs3[AYreR%/4i#pGF0&LE)u +Y.':cCgi6HN*M9EZ\?L]Vj%`*3>GCX8E>*"kb')8&W_rf;/66`3E[mf:ON7m8,,9C)#$B9AZ%^:[Vj%`*3>GCX8E9tZ +dB"qdAXE[6YSF8L>F:q%8dQZ';\:=/6uMc7:#3Z%nR)d?U9V%YaZ68`&/$u<;*mh7`_t4#6eEe.L9X]7 +?FDOJkEHTG,,ZVW#`7?H.[mc!/`QbgX.h>SKul?QPRnHf'i@:gj@3C:;*5[?Y%T(s@<0XB-%nZ]7?e>r +\^=Jh&J)\@.iLNSR%/4i#pGF0&LE)uDLF"'15EOUdgE0P771VoPB0JJ+XD(XU4eWLX]n6C\$/`bcFR"4 +4LQq(kEHTG,,ZVW#`7?j<]"@n>Jr+pD+0(c$^5X,.3TsW.\_TXaK9YT1Y8j.>\:Z")?O-1S9%:/+d#\8 +-%n[(6RjjKS(`s]H=RDIF&"/-,]YB/KTO8l<(2Sg@F%-NP`;]A(Uc"XkEHTG,,ZVW#`7>Kr3>ERM-si!m>-iq)3N&)Q&ig\(6:g0:1s=*'lj9WbW2MRXR%/4i#pGF0&LE)u:.95l\V6#P't%W] +PB0JJ+XD(XU4eWLWG""B\+%E*@MQ:_$^5X,.3TsW.\_TXaJii5LV?aX7ZCjl[:Tf1F&"/-,]YB/KTO9S +-tF$AUS@Hu@<0XB-%nZ]7?e>r3>GOSA-fC3dnm*D2-ZH%Ia#9T +a7AS$.Vd3D-Kgms6:g0:6jY$!;c3SWhSOp$`@>WI(+/47;F3q8<(%$9O]0Z3bVt312N:_dROq4Y3MhCj +aJjt.66`>%_-1X_p\G"t.Vd3D-Kgms6:g0:6jY$!;pd!E0SK=JH>42&AdafD:+7>3E[mf:ON=D7N#(9e +:]2tfmGh&@CUPoWkEHTG,,ZVW#`5(/f"p?M\Ft]<IGUUIUAWHj!Z@S9%:/+d#\8-%nZ]72r15$hsBX?))K0hRt^Xc?*Q>EXQ6hI_C*O[;4B;G'<<1^"^6< +V+[.eHk9MLS?"e!KLAR(PRnHf(%G#t4OoAi]lW*2O&ob*C[9-./'g?Lb_n-g\8Ma>s8;I)/mR'+mJH@e +hn?r+qtI":-sN(/X$%b^6r$18&/$u<0hp+K]]@ZClN?JI1Gbqa%j.B(Fm@SnrcRsnaY!G`f3`a:IHR/F +p>3,[c.uU\If&MH+3G?GkA!d!+d#\8-%nZ]74b4;/Ng\,5N@sW/_h^LSp^.s.%]52[r:0lIXC\Kc,k/n +If0!,YJ39g6QK=bS+'_HcCO:u+g;H06r$18&/$uISKm^[2g,jSPH,ET4CX +?CS3RkP5Y)$uc!+:FZX,S;J^<,]Y@Y2h+9^\qRW%[N82rp]&q_AdDZ/.3TsW.\_TXaJk!Nl7*_;(;=tZ +g>quU5CWNTnknl1_KYG'=lOe(X$;kc**7JZ#`5(/-m9jV.O(db#7hm2R'=9;4o)k\gVUSKPkFIVn*[m, +mTV$19kthTR%/4i#pGF0&LE)u:.=5C1u#_rgc9`Tlmo9PZM.S,WPf-'Vj%`*3>GCX8E<`<:.;KP]nNXs +^YZZcXgd0@g"H2rj,_NV3AW[TT4SIpF&"/-,]YB/KTO9SLn'?7H[6'DY$Sefm+AT!T.`BXrqrN]O(NbB +>F:q%8dQZ';\:=/6r$23<4&1_mHoruqIoR0hIR(YF&"/-,]YB/KTO9SLn'?+Z\?L]Vj%`*3>GCX8E<`< +:.;;<_W74c8dL9DMC9VnE[i92U=O-hEm?*[KLAR(PRnHf'p2ElCUPoWkEHTG,,ZVW#`5(/aJl*q>F:q% +8dQZ';\:=/6r$23<7I?g9[5YpKTO9SL_<#uV]p.2C<[M@V]n_=M4BGO+XD(X,,_0dI"obBL_<#uV]n_= +M4BIEWMh\H@<*ilKTO9SL_<#uV]p.2C<^CYS;J^<,]YB/KTO9SLn'?+o,/mQ,"`,tS;J^<,]Y@YVkVai +L<6EN&jde?,"`,tS;PCeW&:2UE[mf:ON=DW&jde?,'#/Jc"EE6MC9VnE[mf:ON=DWS;LMA)()7*8dL9D +MC9VnE[i92U=O^Haf1(/66`Ep[11mC[IFWKcF3W>OG[5^A6or +A&jUWlfFI?mVY>fIRK.=j2[5\j^8#Kkg?0;'n-,ZhsXA +V+[0OISc!IX097k*S!CPi=B3_T7-Fd5Q0%q4o=TPh>-I8EA:MM'reetfto;6].<+)\U=5DP:'/?pu75" +Ecgl[]mE!=_%0jsiJ"uf'Vj&5e(mlF#u.Q>\(iOq^l$ofQ[A`-k:^)M +YkQoHhg`E3cBbe2?/pI3d +mHtX4oB+<>2]b24r:SZKn*;.%#2X[lXfe]hrpc%t57kitlIDs8n.5Qgq!hiuQmM*J;>]k#&%dp0Gi=@k +s80RGI/1(?aC>N^9?3&5qtGU?p](6]s6abg:S0iLciM(NOM;@@LoF2b(Gji??]('h?r->3'-2cN4rS-6.h;<@AUKcXPf73bNA&jUP^\IDms4m?9 +@l42SLHk,hp[@/^h/0HrDZ&r"6-c[JqPq.OrPsEc7ur^gES7g1giB`SBj94AGEpu+gOJtRGPAei+/-$> +X&lKJjo"\9^[1iK0NJuB>W?a8.u*kJo#W7b1Y8g;T7#[u;lqd[FL>ROKaFA +=r5N,P:(Q-6nc4B_S( + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 33.71863] CT +[1 0 0 1 0 0] CT +N +-1284 -69.75 M +-1284 286.5 L +319.75 286.5 L +319.75 -69.75 L +cp +clip +GS +0 0 translate +320 287 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 287 0 0] + /Height 287 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0VDeN2Es2XXaA;!JZ+VDU26&]7/YR=r48hIXuO^_l1)%fc!)A3VtLkuP>5Y=EWKTI)f.nW3FR+\+( +_&*b16R:-V(e]V)@"h&#`V"Ya&"_\K>j"/[Y.ZL7Hb4Yhkf.aNkNn_bFZRj>F"V[-;@3B,WN"!d#WGR] +=4`$-$S"m,_Uf;GSd5]q#!%K5GXB'r`?l0[rr]fUOOI!f0hgD=1@6'"g54K2iP +V+[/LWCj?j.$Uat2gaN6p\X[=Demd:YJ"!.S'N,Rk3lpM=#OmITG_jQ//F-nDT.JJ$PtE8)]R8%hgYGs +Vl]48Xj^3C4b!==k1m7R9BlB];]WG(RZ,=bpA>Jh`2UQak[4WCSCA7S)(28ck>gCf]*(1(Ren%S[:;]8qu>;se95em,1 +m!c"2/)9+BiQIQ@VbYbS;o^uEPHfdjrqU2=$Z@<_Rm6a<^!L]skSNnY^\OX3e-l6;O+'qZoUA)A7D7&d +rob0k6GN>k?doJ^k)Xsg0D(_uqF/*EDuLZehr3PQ`&E2j6UO6(c_%E0l6[i):7aR.3B:7"`Fcc@=bV=r +f@^$Krld?>_1Di5s"!*F_*Mqa'.6P>:V(f@@W-2RbSH]go08b/[sN`daGFMrVH$V +gJV1h#7hk\\o_Y-F0k"Vm^_N??Ph-d*BSF\gU:r,(G=2GKgJ'A\^AnI4*E/YZq.C(>.&,6hS#oeC7[NT +\3g@#]mB?1hg?*'H0!$Y4k1'XFeu&j)ep+3hKc#*R5]%j7n:U$?[WXui/K\PW+N!s]^nmc1k5N&c'pYI +S*cHD]ejk9!*']pm-3bkDGuW6QklX@naBfK@U-*i00:Q.DuLZh?gWW>SXlC%qWUKlIAApl]'HNg*Su%U +]6E_pMI(VnV;oUW%h&k[2H:<:,u=tP]QirK%m4gpd%Lt6pcslTEnI5]RmF1Dg9jR?b=>=e^&X#BoC^.F"i9*PE8+ZmAA2<;Jg@Zi_f6dGca.n?ahWlND+Z=d:='\6qhf%Kj +bP0nDYI!#'YM*3!]lh;O($5C+$oRr<8R6IJmF0qE2DHo!.5e0lANaA+AkdAgh/`.W^P;29IS)'4Q7Y`L +J$\nI;WW?p9kVbAM'dqW`>SqTWBbpT$G5H9+)JW]`%@Ak)`RlbRQ7\NkpL*G+6^^T%13Ni).2&6nDjkL+JNL3)'f[2ZdSk*tK2 +Adig&E`/*Em+;nE$J4P"IJ7#VmF0qE[_1L:0s1mpD7#9!JC/<7)SY++WB3K4FRf;)o,ShlXf\_ami1;Z +5DQj=WWMRXC.'H%H9*f:&hTp-]cqTaWo`H;=Y(>L*BSHAmC-0^\,8.jnP"[lL@g+eV`7,c31WD%'nqhg +5fQXnj7DH[f<56-iUlB`iFCru[:eCL[_,tl[V4&4/Ko*hPK]:Hq4lj#Cg^X9(TR#OV=W)3A]"a'Y4]Y8@%h*W:;X?eEc0(]&h+ +rHb/Ef[6l=qLosgHD+]udB=A_KcU,jg4lq +]6sHdq(.$`/t[Sq50KS1bNJII0783P48SV:^TaJ?0D#W6qXm1iYbPPYoF!bWog6EtUL,\H$Tn4X6GKb" +?SD$Z48SV:^TaJ?0D#W6qXm1iYbPPYCjF[<(O9H4_iDFO$X4ZqlpY75nuuUWo"p]J*IEnb[QNp/MnH:U +@E2^8Ke3fsp*)/+H.]A97tS7:+X;Y[]?W_NortH]],Q4RC^Y]WgL+a'Rh\/J#I^p7aGF +ZcnF+jT#8\zzz!!&C]cCI%@q=19k]5o#+k+'r7kigEhpYC%#pc?jGPq0WJp04`Z2(JRMe:uN9:$q]8O$D2@qF.jB]kDY8=KfC:qW +iY0p"-$5Q_&[&l$Mj/Vp]9#C3B47e\->(Wm)o_GTsQQ?[r#S)uSB%T;>moP-GgGF`hhNG=PG!7n8n!?T +p;'j>"j_1bg_Ym3rN7*og2_\gp#:H0CrWp?^HGT$f9lOk>RUqs6+%eKn<3XKHsDMH]]m@q/,Iq40TkG'%hRrU +neB2l3^]Don.gH>rTE=l44.2G8l7T@'s829"X"j(VpR][&og#_XNYAa%q55VO558N(Df>8iI!f0Tk]4mWFH%jEoB-D2^S +jWt?DNct]s;S655k$o)]RPAET>3,/-#D)&'$so,l34#l<^9WVbedpl`[^3f:G'Jc>.Y)AtW6W.bij1s4 +r#Ez!''itABo#@~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 0 0.07987] CT +[1 0 0 1 0 0] CT +N +0 0.25 M +0 356.5 L +1603.75 356.5 L +1603.75 0.25 L +cp +clip +GS +0 0 translate +1284 70 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 70 0 0] + /Height 70 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WZ"atg(rtT?NCCcPZ-4L"(1)QbL%\R(Kcm0'/1^oi0VsJZ9hH#0'NUMDU_/^lc`!AB;sIJ`O'E*[Yu!!!"6*?6'cm-Jg%n*D[>\$suFo&@WHj5]0\+$Xr;E<#q9Se#iJ!!!!g +UM#/Vn`.Zb7uo90^3o7tX\404_DcAf\9muFn!)G2A!pKup-`P +fj4C/]6E)#Dr/-pIHN+^Xuq+,n@T:>`&FcAiGY`hKTO9SL_<#uV]p-t\Y:6?nYoghmG#,+S)$Orq`\)b +?@D>$6-h/Gj:afi'i@:gjA\MR+d#\83>M4n$Squ:U4eWLWJD0R,,ZW*.dD4m(Z+',?fErkD=8YbJ;P`u +,]YB/KTO9SLn'A!S_Aetr1pE\041<`_k1.FJ""q;XtVjN;*mh7<(%$9O])iP(%jYr$[6LF]Qru&]otDR +RnBc4MC9VnE[mf:ON=DWS;R0fn%sEuHeg8LT0>D%55t'1_p6QQltSZ/'dfh&8dL9DMC9VnE[i92U42^G +E9HcOa4oA'J,]DA4*U*4*Zk$&"BUt\MC9VnE[mf:ON=DWS;NVRFEI0SrVQRGp^^GnS;J^<,]YB/KTO9S +Ln'?+F+q`8L_<#uV]n_=M4BIEWMh[UR%0$^+XD(XU4eWLWJI(%>'#D>WJD0R,,ZVW#`5(/aJl*q=.#M8 +-m9jV.\_TXaJjucMHY(Taf1(/66`Jr6(FJ=8;F3q8<(%$9O])iP't%Wi-Kgms6:g0:6jY$!;\;#)[:U4%kF>F:8E<`<#pGF0 +&NLT6AeufWS5M[EjA\MR+d#\83>Jr6(FJ=8;F3q8<(%$9O])iP't%Wi-Kgms6:g0:6jY$!;\;#)[:U4% +kF>F:8E<`<#pGF0&NLT6AeufWS5M[EjA\MR+d#\83>Jr6(FJ=8;F3q8<(%$9O])iP't%Wi-Kgms6:g0: +6jY$!;\;#)[:U4%kF>F:8E<`<#pGF0&NLR`\$]e+0rA?W[eATV@uN.^XCZdY@>lq15FZ?R(Y'@4N%pM; +?a:MYN;5?kYkH7JN%r>>$SoH+0ub(%O7@$oN%r>>NLSJfZa7aKHi91rHq8%&gA'8uaP-+4$D%JM?P2<@ +,]Y@YVkVc/_W74c8mK`)c<:8c2/p$pq]mE?@B3Y[MPqjIE[i92U=S\JjIB.@#jFaP?$MK;HX%NXE%7T8 +ON=DWS;LLV$^5X,.C#iqD(WIkNaNZpq\0^KW>2[I66`OpYEH'EKc=KL/jiS)!l?IiR.& +W#GA8j$iE&cgK]EKIUHTKLAR(jAaWt?'q.'8r789P^IOp4_sNE?W_b1chqj7eX0B+N0]RHWJI(%>-eU# +F&"/=XcV7R^>lNKYG(Er1cDIn(bHnn;\;#)[:U4%kF>FZ=s6lt^Cq:L_QERlBiW)b$&P10aJl*q].c8. +PS39hBq`4V1,!cVNGKDKYnVOEU4eWLWJI(%>-eU#F&"0hifFAIA!Z!U/@u]7h?=E[PRnHf'p2ElCNa-, +c7(&?&CS@:biW,;n6T@Hm5u@c6:g0:6r$1QfnIO.Vj(j2d]dXbDHVEml.q850<9jQ8dL9DMTDcq27kP& +kEHUe+V!:X(L)Pa2?'od%nDiq&ig\h;c.=R@<0XB--AS)fmd^LWP*PWpNOTo&LE)u:.=5Ce='[1S9%;Z +3Nr6p>b7uO])iP't%Wi-KgmsilmM0 +ghuJn(Rh1fp,oO@;\;#)[:U3Z7]:g?Z2aCIMHG7agW`dc:Wp7;~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 0.07987] CT +[1 0 0 1 0 0] CT +N +-1284 0.25 M +-1284 356.5 L +319.75 356.5 L +319.75 0.25 L +cp +clip +GS +0 0 translate +320 70 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 70 0 0] + /Height 70 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0V5tEJ"!!i"K4s&0_\u>s(N1#XT^r6kBqN,/.h\6jF#/O-#Ie+KdstF8c-k_mZn2mPo]/Am]I6NJNCHLkpkCLkpkCLkpkCLkpkCLkpkCLkr"7 +Iu*J96-Op?.e]nNkNLd +Cj?Z6?=Xk\4GdQ$Z3sm.`3C-3Ke6*[fSf+5Q7$\=7W<%>;TEcK=,HHsh)gt^]:^C_A)*DNA.,1R/3%*[&DlheY10cH$0/<]>hn^6Ce +>[CaFUN.fN?hGD2hqm5H56`J_-XNtm#8)`WX'K(>7m6]4dYc7,/<]5rrdJNo#TjiR91BBF*61*a1I?Qf +qYEleQVOGue_Aj5;B!oH?g09'hqHfLl00'))e4?=U^Qekp@a6A?].#tH$S)Q^s$Ds +PEV3O%SH\KIlne(O3c%om-a:N#KaieL_E+Kd*9gpZ,jLsS9B$t'oU'-qtj5/#R%@oDtj@H]Y*0mrV_02 +0Y^eHGKr*_?'jH,M[Ne_naS@-2`E\#^Tk&+9IBG3ouP3FV,BTV[9=Rj*1WId_Q4]QiG]WHhVI"%L.,u, +PF7f*^e5eN:JXd?hs4X-b&NlrkJQcJ45oPm%/U;Z?Ld>oJarL-oi:kpo$>X#CEFGc/$M#r^KBcmIl]_U +?!1=H:l$MC8&\pL@inaQp%.eNI!oaXI=7*'KNBh,eS5pd:&3>Rbb+2ies5:&iSe4pW>?_s.)LdVd;PH1 +cWB(;g`2nme'2NaPm[s-qTUO=+P%c?LLoW?oX+q/[S=[((MEe9DNT;_2PRrELt1q=F(4^Mt/-\QCVRb@Rfdr*!0>qI_/;fC&CiWOb+)Qr2o7 +9n.%85!G"N)NS:e7;=N%`lX-sMct2t[BA;aq/,L8RGXlMRU62emro.rj?XHBc;H[C[UdWdhl +d0g'Y>''MIY+5;F@X_P4c2!(HfiahqZ*IE2+`Y>+&8PVN:,:DAQnr6_MB>]a9I=cAg=i"hGP\&]-rLqD +`s[TQWQ:fSk1>FbD-<4g([G!nN*S'&IWs!(pD`Q\,n^Nff;f_H*))ssorKlrfk_Egie1DbAh(*bSG>$O +ITtt$r&+j3ge9&IJ2AgrLm_#9)uel6S]-):YccbQQs]NR?]p-=RI.#eQa(!9cGW`fM:`mNEjBMHY&&>/%\G~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.60069 0 173.19932] CT +N +0 0 M +0 286 L +1283 286 L +1283 0 L +cp +clip +1 GC +N +0 0 1283 286 re +f +GR +GS +[0.6 0 0 0.60069 0 173.19932] CT +N +0 0 M +0 286 L +1283 286 L +1283 0 L +cp +clip +0.941 GC +N +0 0 1284 287 re +f +GR +GS +[0.6 0 0 0.60069 0 173.19932] CT +N +0 0 M +0 286 L +1283 286 L +1283 0 L +cp +clip +1 GC +N +0 0 1284 287 re +f +GR +GS +[0.6 0 0 0.60069 0 173.19932] CT +N +0 0 M +0 286 L +1283 286 L +1283 0 L +cp +clip +1 GC +N +0 0 1284 287 re +f +GR +GS +[0.48 0 0 0.48055 0 207.31862] CT +[1 0 0 1 0 0] CT +N +0 -71 M +0 286.5 L +1603.75 286.5 L +1603.75 -71 L +cp +clip +GS +0 0 translate +1284 287 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 287 0 0] + /Height 287 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0Wd>M70Sd067)@6_&,QoG)H#R=9A/PskOki,.!sqYS>m0gl?Xt8e]*PPN#`'%Z49ugh&K_2hOapt. +<+Hi-+aWp4e'h;:6eoALma[aTZjeG#JS^O<.E4$2ctkbF3Ajm+V57iqL' +1&^h6++l1O\l@Uo0RDE(<,.#h:>&N5UBHE5.3_NEC=@l,@_2K'/]'U3.>;:?OtPOaCal)UJjc+C&LU#T +l,%k6AWpu&nCMqYrVQ1F^Yp*(8OR+US+W'.AB[k7%=r'-UkH-_O[)p +GcP/jS#6s_3Co$H.l+#YL'SE3;FI#heYW^uVVVgecXEDC7-5W&45>_;.A@u;7%=r'-UkH-_B#$86c&(s +Sl.u=+F156.l+#YL'SE3;FI#heYW_`lX9`5l<<"+V2-IMU^JR%7#K&]OGK)EihWM2?+<>rILF_AbYsC4 +,"NS`*-3s!,4ZBmihVAi.B6)YDGGp*_>BUt'[]=1P"[oKBd-",-V20e9[Tr"8;C^FUG'2t/,%E#08pbm +R;oX46*19hh[Q7aXe^d6"GsXI.2oig3BB.rU'i@CaQsuUc6M@a:P0Pm;U1]O:/`Sc1I33;=,I28:l`h] +?Kf7?9kS>#gY(Xkm:fU*60`GWkWrE%+tZ))/m!o7Y>1,'NaCqd#rS']>cU$4C+`'!-g!BGQQgG_,iWj@ +.0%gCLQS=bFQ#@Eo\\_db;E(0r[I,>54fL3HEACRal)5>+Do> +CG\Ij,=oc78s,+59i=r[/j-5t?4MC^>k=1l[2u.+AoMQIXUkGBt<@Tc"]C4h9>)[[@SS*&1$7UV8sG&-7Prh(LETq?\Hs. +&`1Vf:MEi760`/j2l_KEOb"VeQRbMuV`%+DD7]4_FRsP:6fjc71om)gFYgF0e4kf;Q66d+.n0DBI?&po +eYW`+1EDd6DtbO/4Jc3:"KBGTU)Dd_Lg^T&EOetXB53VEeYW^UdeAaZI<*S2Rak,o`\?`-l6\q.99=tQ +Pp4s\S"uu@?+?t'IjfQ>pX`+$R\r!C^EE24nT3tK71;MELs)'X*a?i*85X68E'^81(Ha;$4Jc2O"_gqo +5TZJmLnP(eEOetX:MQ(-eYW]Zc2"'kn]3R`Bi]^Ll>b:oY.kZ*#XKXe=,LfbD3CWL)`MZi^3tA-a6:B+ +j1Gu::Tet8ZapRnQrf#.FI=?(:QUCUPp3h;S"s_/2fIP8ET4o,++6!G_fXiPN:VgVkK#MVBi`8?C1Q5c +6,tE`SHOeZ>UaEf`NVjihj"B.!UbWo9:ODCH9XH%q__X>g.N`3kW#nh6g;IgkaP8#V7cCI$E:S)ssSTcE!/CK5b +hWAo>Q9$->f7I@ul*;@YVhh_m,iWj@a`rH>IjBD'=0O8E46]+tJ +5p@p_MJPLoP+n3nf7h7>[gOos'U!7JYJuO#C*Y7&2F/N>=,Q?-D3CWYl,!rgVuMd"8640g]HFOc$[uZ! +9I6H+&bQDBEOf!.C9:3.Znbp3NkNU;(lX_!"1?K9J +O<>.%.n-n72G$bgNB`rtqc$bg0FW:%QG";$s"ilULG=c\)0:Z`8bg/bh[eRGt#u+pUctpZq6.TCZ45GT;-bLl#\p=fW"f'NHO1tbblR4U'O%/ +/m!qs/o?cGlI%m:589WYB;J8/T@UpBF05[r;!-6LUkg2tM7?e>EjaIF.B5#^_jPWlR#JVH(F-D\D`f'8 +._->miV:,oKG7::+;'qj7J+$(%KHLkn.n0/s2G$bg3?HJ[ +T*!mD7oJYn?B!P[:T40-#FJVoOWoYo,iWj@aJRB4.B7:LLNB^"p,C!^o:0r8rD0?tc"9M4Q0Y`,AdK)i +\Pct=D3GZ62r);2oNq$ICVT"R3A3j;W+T%d%V&I=OR'3'AdK)i\Pcs.Bp0622pfJ46c&`jr:NGo:<((# +/(\>7bn;;]Ei$j#dO$ECDN,1icl9gh"ZNX.Gqi%r5*]#&QVgmjY0.$<,tPu98s+P19i=sH=rtu*rnHIOS4O7<)1MMEfRNpEq"3hH(ic:m:cI!sfWpX:+BDN5/HQ2s]bBYfTH(MW1B@7%f +2G:3r#+?i/`8sURD50g'<8H>bj$k^5-Q2?,(jep?gTF +s3SY)cG:I9mKGCF47e%/UjD#uSP2*RfKm&#)ebN[&XP":p=V>qd0_4QG4b"G7t:*q?iTujh7N8BqS:!g +0::il8Y]0HEN)^1*QIH=>aGmV99=tQPp6*AS"s_#++3RoU]Oo:H?FR]qbM_Z?[1O`H%4eNLGSmr +g^%LP/^+S4Om7crFY`>GLhgK_;4e%q1PP8=mEb4Cj3UFI6/7I,1l5cuH +).Yh$VAQs[\LnhEXH3pI,MtdKEc#RUK6lq=[7TugjHEB:htaUNrTr'9?_.4iG/)t1Mn&s$)Lb\1XEk;G +S\IgB8e%2;8r#TsiLMuMB'<0<^u0:hiG^dM*CI#g/0W-42P$N6AT`9jIer<)X%jT'oK/*U5Q8eUYKZhn +PE0)89>Qjd=*;P57k/4KX:`Hjc_W@G$f0c\39D2;.*8@[5`QI)G-rs8_A@e/%)0A9<]EuKHXc@rKY*CP +2Z2Che(io$3;*h#2!h)_G`ECapA4IJbJ$GL(FCcd`@!7C=bdm3?+H7GcUtNa"c5-/&TOe]E.5F6.I4\A +hV7drl//AGO"O+reXi_JQJ/F!i_HrDaA^Ng>X>)Y;FK:_.;J]:"]%A]o_J+Ap\ss7IoAoT-I-@%<20h= +4pEdoEod%0RuDpB[2aHUR[#Bo +Zq6.2>A&h^^)]?'il-gGNum-UpQ*Uk4aZqkh)QRY$PR0\-`Vfa2iWq1A?P#bYa^n.8@1sGL`G +l`75'Rbr^@l,(AAm>:+?nP*EP".$/)BU@X<`]TQtQ6X4`G5!1bdkk?t33,2>f&\q^p^3s)bL+s3^E^:@7%:!.\:Q.Ji?c;aFCF11p-`&SWu9[=k$!eb2YnH9 +'dVKY7Dop4dIcha]g&eq(FIFB:R'!ue#5_pf5`^JU$kXW+OMMb+tfH2[tEkmKo*.i'4mT7BiLjsCH3<` +d.\hfOD'gl&Jn$$gVJfpKo*.i';[H`2P'rp[2b0=gq/b#8@1sGLg)l.D?hgc(FIFB:R(O`^6+@oY2s=B +KANA.6)%(O7,5'sR_B0rG46\t@H+B^7&^UfNF[uh/Oq$'oH**$&oEdUi`>B^G+Q\;_SfUEM6_*(9D;qd +CH3$oB&s@4D3?+&(/3,i$>eI"S1[L*eXcgnheUXJjc*(Lq)!H0T4D6M6ko7L3:/Cm`.<= +En(&,pFB=,BTj,BpWsVb*?:j_'5+_NLqa,8C0k9)A"7][\X'"N#J,,iJjc*(Lq$S:E\Fp:?'mUP4[hK[Krsf$FZdIMQD9HF\p(]:7%:!.\:Z7$:F;@' +$PR0\Vhi7&YZ8Dt?3`IAEn'D'O$Kijd3^:dDI89+*u1[]'5+_NL^/NBXfnqO1![0HFZID#O=Nl/8W&>Y +99IuFQ0?*'=m[YIIus;YqYD/e>g&6<2_.skBTj,B\!nSNKBpp=M6ko7`$%FPkZ??m`gU['Ep_;V>X>)Y +;FI&0_6rOE`*)IVip\()'/fIWXl`m3;.kMC-Fn^rS"tk5rq>Q/FCF11p(T6f$h*jcBLSKZZalBsc3AJd +EWq:X8J*Io4*YUa@H+B^'JV733^lb+NGbo\W2GauR9W%P9iAoEg^[XLMUj_4L; +naY+O1T]VH?R&='=Ot=C_,=7%/khd\8eDR?P$1^c+%*[:E\s>i6bDgp"!k7uZEFif74`?-DBhTXl,(B, +V\J[j+K6)5oeF%Y/4XcMDm0`;_TfBi&LU!uB]!,N]jjT1`/P]pDVr/ks'p.Zilk>Y==?^T75]M+%XknL +BNEY8?'mVCPTlFW_YQ\A*=V%BGf@9Z,Y24jKs'%Pm&!NYEbJ$H9'J[ejhh[PlASl=& +^@g&]a,V0ep=X)$@Fi=YV2,jj%&GgE\r4;6?mf"PFlD31f8,V7%^je:P,)boGOF6HH1L#Xn%:H%6Pj>t +bYsC$r?j`WWp-3_ijY$T+5nE9Vs0lp2u=M5;T(aLCdCt+XNf#7HhZsqr)AOim)$rW":mP7k022M5S'.i +ddBS&l"!8$HD_h\>a@/n7Je]'ia6KqPK`i%A\T5NA7$QVMV)QK&ROP%N&a>C;XD+OCD2aZm)8o]*(k!d +;!4[R7U"r(:AJ^lI>p38@b9HHYel,;7<<9_DVgeen,M[iXGqKt&^`54DA:Xb\1Z9bbL2)kA7$QVMV&ZS +<0?b=\ +s&U"KD9Pq9.+![5NXFJYdJYLtcRT64I0m/pQ@4`P.2oRr.BEW3%5cD]d:G7_Cn>.dtLpDo9:Gn6..j[BPU!X8C9KiTF:M5^.+V,NQo0V_*uq(.9`,lbhAG^ +'N$2J8k0$o,ct^Sba.5:4%(0&.'9 +)KAY3&iFP3mua?uFCF1Q;i3!\Kb]]DRMa=;]'qcJqmrNS/Gg?*;D\UN>4=-nW_F9Vc9.qZ_ElU68o(0R +4j\o7:D`GQI>p38lO-m[[o?_MJCUoM).pV +U1+qi6jh%"U)D6P([cm'NArBPd_Qb!<$au@l,(B,V\Dul8=E'QGm?4WRa?M[1+DM( +i![(0eYW]fB:`!hh&r[B'dTf*s#>X!bL,77:]r$N'$ZT6Fq&m^G`NQhV@+&MSl.uL+R(5LV&7SbcQLVU +P[\`:;5,2\/1G>]_1)SQ([dbF9UpB#&aK^#T'`Wr!tXRG0:uo<'"4)P$51UHU?:OI*P=n"C=@ln1J]H/ +X[,Rba`TlcSk0`9Y(a_d62noR!qcZ<&VC"SQ:5\U8?A*Nu +W'4LS3:i@YL?udF2o9a>D]i\B--Hlh#SM,TPZIe<_0_uV2I2\0o9:FsFQ(G*@LI9dqB/>I8PrY#D>R41 +Rk@C)GtJ[d#:]J/fSJfo(NZcfL//Ce&1$82.%;!eq(5%Cl,(B,V\Ck5OP8D2Z`6*E&,Y_2Vhcr2&ogg6 +9liaJ7uHT\Ko%T].:W&p[CAr.<,j%'@Fdc,Lm+PY>.blg7uD'1Ko%T].3_EH>21\#WH-Oo^aIBi+rVh" +`(eYW]fB:`!hXrqkkKB?!B+;b#.\Pbi%"Go)e)G17DKD.o6D7VE@js`a[$Bd#H +aPJdGoX!buXH=V;-Um>[h1GOV^nmtf?'mVCPTk,OWMcjTJ^A?go9XNpLh6r+EDj/UICptS+"=3a(FIEi +V2/ABl>K$1eEWAK9E)>(.ABss7%=snc+Xu_pU"j3;/NluETS]=j9h&&>["'60.^1^BU0bQ-Um@KjmCth +;RDn;c->S+YCHH:[h&F.?'mVCPTk,OWT0Ol3(jeIo$9Y*'[\Ht,#4#q3quJtFh(dNdBYYg2I:k.jWd9U +4Sk8^++JZ9MW]B"/khd\8eJUcU^PeJ$e#5E,#4#qlMGbo*[t:D9/!u#il$\75Q5nSHi)Br>JL$bY9&&W +Z(![jcMDckQoO]%,'!j$$sW'0Q5J5=Sq:2rU03(9S.sMXY6&p_92!Z12E*RU*'#c;BX_p;T![=_hgTq' +?dXRa1J]GD=-,nWb77sSTj;g=F/=\)#nh5U<5Wran1H.nb2'[R5Q(#g>ISM;]k;+rCXRC`GiOcdImk/# +c9.qZ>X9:Y?FtB=G2_QE8eK;\,iYVuTMaMQSgHllQS2^;[,'%ms*WB&4M&0un=VRMc4#+.oH7.qVK^gh +c_XG7Y%jj6=(Lf!V20:$&ogfKd$u\_DduO>]Ej#[eQ9eP++N7'(Zp+(qng8dM(@WodKmVb]QQ*GaWDAt +>UcCMJjc+C'f""g_0_tkNm5hn4&bkOhp4Oer5=F*cThI-`l?#g:SJ41B:`!hXrr^LlWq.$@iQ?Z>UcCM +Jjc+C"\o#\8Yb+$V.bmi=0GB6FEtIh^An30a,V0%HhQh(,.sZY;hB9e&a=m(k1t6pr]/EcMk5#>U.p5- +S.nDNr-%QN.@T;Zc'oeLg"P06IK.9E(FK[d[F\_hjHJfE`0mM;OY025iHL6S9[^= +fn6(.=/$(dO!##^7C0KE]Jq@?9c#/%4Jdl#6*bQ513Z:`>r"Qbm'EUG7L0WH;KS#T_98"9g2pc_bYsC4 ++@td:=c8:&oMs@-a1d*=d/lTX:5Yo#qi+GkH]r#Nk7H>dd`(?(8 +*%+1_l,(B,V\INVODO;MYlUA9IFV5Q85,,$)fpo1rK7CijiYT5U@lleM).pVU89!ci$1jQhQ1(_eP_8q +9TY&LD2R*Y/nhU@=rUb73:i@Y)@M^FIV"4fmbiMKajF4Ja@_PM)e"W$QfT7&,HHJ0VJ+4r@H,L0MJ+b9 +G5>d8rZ8qm)\ASSigO,487mN(Z47[0_A',?/khd\8eFc%ad0]+C=c%4hBRc?27X]hb]m$m\)+\:>hjR% +1_a5_3:i@YRLGA9[?Sg.ojAU0bcmN_QQqY2:PsNAZC^T^BILGGETS]=1`7Q?!/k()5TT]aC!R42C2uO+/XD=&D;fqN<9RD4j8up,IR<4rChf;tkN`20q/khd\8eDL;ajn0o +Xg\Z[qIR?TR`..s*0E^o.C/!9;m.Xm6Ph)p4JdkrKB0=GQ8Mu/*DFk^=&"%QR%sK=L]mQIObIoUqFa[D +\hJ-d.7LTa,Zb2VXS9#7..UU"Wh5aJ#pS=Zcr:=c*j?Ko%T].AHV\\O8F,HH5*?.<:oF75Vb! +O[(iSZ="0@RhV]q$PR0E;FDluEeuJem8m&@UhELDp?]&bPN@TdooUGVjKSJO;.dBnETS]=oFN:7$e'hI +NMTOK'JiAmb7R*W4[iDj$sHG(I_%4Qjs``@&gUNeHd[,s?1[Bd-Zbe==cO=ulR>_b1MAp?q<>c7RAUbH +:QSgEljWSNJOk[\h^0E9P;tu./4U,Hd1dW!9nNkQd1eH+(FIEiV20SPUco5H!q?sF]J$>uO&/'a&]8<> +797'#)GO'rFCF1Q;i9cg8?O3BHJes*1oh"Fr.uGNY*L::dT28!I05QVg.G5#FCF1Q;i9cj8>C#rK0JcC +.It@?&aF3n@L-hIaNBfI>:FH>)O)0uW.&$P4n%\ekbE)Y?J,I?:b\tG20QH5( +7J%InnQ]Vc\>!/>MItZkV?;6!8$#eS'Y,7>MTdNll1NY8J*aG\Y$JXtH2Gc<^H?Z(e>*T#q06243:i@Y +\dd(YC/U&s3(Sq^,OS@:b7SNS1I]$1f9VpU8o&3Xlfc`kDnPV[hKpk]]QiMYOmVQ'=arjV-I+`MLn95U +L22ehO)Cm1\OYGCSsL\Q-"2\d%W5%Y'IC6!\bY9H5OSJidYfL?=;Rhao9:Hq%oTSI+.;EOi$k,fbI&<" +LEkP>IY2QRNLH*h]6E^M\T6g,n`0ZH^]-CY,9L4J-$[e)1M;G+"a\O>OJ]3GL-Crep0Ci2I6(M/2#&B" +_r5RY3egr`=[J9GD%Mg^I-oXqh;8"3s8&pKrTdhRGN$UZJfWaTU6,A,[!NP9R:HgX:Po@kgiYRrNe7RR +ag7rm[(3_mB?KlHRf)^TrVM*Do:MY)rqVa*:X5rW\hJ-d.7K1>83L7@4Hf64cEa9[nEXD9_r960BMQ!1 +/X2iSH"1@Ei5aWeIJ_*J,8Vt;R.X$m@H,L0MASdD*dQh=s(u&a$`m4$M#%723%6%HMWVEooB&PA +[^NX4gpo4dj88;[TDl(Ta,e"1iet-,M(VJlGtJYn$<#"^\X]`3@72Q=-:&hNMMRIjV+fV5Ut`W^p=jr_ +\TR5hj?7Fqq<"cnU'hWISl3L_K%0Xtee4VQLf-W8Jjc+C&LU#j3e./,n`.YSrUeR\gGa$*Gl$[&:RsQ> +_[euUqKQ;53:i@Y7Mhl=NUe5*TD@\K6lgkIS.lP_7EaE;fQcYWQhGlapmGcdq=`Q]kBsop9UpB#&Ru5I +i_hd8mW0FZMPre%Lm'%BUhDX[n)(m/rVGp9[ibI/\hJ-d.7K1P8@be_"'Tq`pIJ4NBnAaC'G2]][HYQH +RAU`Rl6'Z?QN,H$&`+CNMC:uVLm'%BUo61WQoO]%,"Aab\NOWU.A@eJ,#4#OPG6cQ@H,L0MAUJt +pAWn,S:+ ++;#ti`(L6S9[^=JonNe+5ksjWC?+;Te3e9,.o-h'I$)d8J,r?<1>L6 +S9[^=K(KTXHY[g?G`NP9KHLjS7DqbpD7VE@js`_)d_ef:(LFPocFOD=;%_ZI+pno-ihVAi.B6)Y-I+`M +#XMY2r*m:fd2+7+#XKY0MMRIjg2pc_bYsB1Uuc:+LQNd<&1$82Lc?i`9c#/%4J`(mai+=X#j5pB'] +Lm+ReFCF1Q;i2-^W3Q'RBi7>2Jjc+C&LU#Tl,(B,V\C:F`(:P0#SM,T7%=tAV@+&MSl14a&LU!]+\9OC +&TL]JRk@C)GtJ[#7%=rgKHLjS7DqbpD7VE@js`_)&ogf;&VL6S9[^=Jjc+C;1p&(-UksF;/NluETS]=#SM,T6kP#=S.lP_7CDBs +`0mM;+\9OC&Ocsg\7. +""BrM5pB']-pj#OP9T"^BE]2*?MqbqI^-/_Z!\ASeg5R&<)A5j&LU!]+\9OC&TM;Ud:u,Fl`\'p%,.%T +IQ;].I::\oMC:fQLm'$?&1$82Lc?iP@rl__cBQFtmbPML`"PqZq<"0Y+.s"J*`>Br2fIRN +BZeoWf"#kb%fH^k='g/`egE2h`(:P0#SM,T6kP#=S.lP_78'&uiQWg<04-ndm+CBYano`L'dHDB'N'N+ +&LU!]+\9OC&TL\_iTGnt%k44Y5pB']-pj#OP9T"^-pe_^4f!lX"Go)eU'O%/:5XjkU=tP[EDf1:Jjc+C +;1p&(-UksF;/Jdi3%:R-5pB']-pj#OP9T"^W&>koS.nhR+;#ti'Hp#c8J,r?<1=IH:5UGdOGK)EM@_&m +UkguZWpS/_Nu.is!!Y0"9*P@rzzzzzzzzzz!!*"4CMW84p$9)*h]DV^B\;J0js3CQIf&NZ-UJ@3hS&g* +(LIT!(:7h'Hi':N^A7Ams#bR:k]op87&uUFaJK4:Oi5ijKd`u(L@sTUhItF +0>031WZQ`gnK^Q4DVb0>YC?/s@uj@Hn'L5dX!T@FA6mW;=i'1!?kT%=(G=LTGOL;/I[DZVa,_OeA-$O@Dr8fTXSNF=Ta$9L\&!JaJ +b?t6(i$m'>c-=KX7ugicFD:2,PKV6CMC',P".g7pqX1ua-KX@UfsA7D.sV'hkKfYYZhMMTrq3HB:S.LN +Zd/h<-!E-.JgM;%H[gGCrV%]:RTCd*:m6g3\))FHZ@>%7m'HRmN(\%(1b2!I\Vn(Ls8HO/hgP7T^%Y2) +H1IOW=0;sVZ\+\[b[C%k`d2R#:1#Q3^W9s!>kFR%g[F\`SX?sKPbIVodhIQ0Piue:\ +oSLr-hu)UqPI5)mO2(SJmj?GNhW`rpGOF6HH1L#Xn%:H%A%KXhjCWD<;WO"Q\80^!9a:*N:Hk1qkKeVN +ZWCL^Ff865".(ZJT&f2.cT`NJ6tjocM\gm5MdL::D!8a;@!>QHo#i[66$hgqVuGdbroM"N$[s:\'hkoT +o]X^&rpTmd^]42Gai3GB;lBWd5Q>fgPG/)AL3rCG]q(e\b]Jb_aj&gWVp:iZ`>;lDH1L%W&p/29o>Zb/B?m#-Fm>2Pbi3_QioY>kQeY$rrk;)[ +fV"&phg^,R?I#-*CK@`mhu<>Y5QCQ*-d0o85C*5#f8gt93dKbTDn[+ce7ckB++Ls#]76a9l"ZDn:!2q= ++6<@i`ucZZdf96krsX-QZt3U&EQQH4Ap%OKgnjB:f`$6d]smGn^4jkd&M0Mc96Ij +/V_5mqsCkVb^Aor#Li-(H1IaFZ'='_WpI?Op[A.]mk;EMi_ZO@F8!!YQe\\#cn=[J]<%p&Ies!ApmT\\LU"KV(a +_Q;no^]47C;nI;Eio]Ccc'pZlmGIn[ZEO6%j,ZR"(QJ78Dgo%io>6]lUWGED!f*k01*o26)in:YNrUU[Rjh:EF47oAOIKYB2?'pmO_K4_TM;'cB1.)) +2E"lejcq&\NpQ]ckqBdG@d'#M-*pq6lB7XUm7WR7mWu=M[_DV'.oR(2%W$'%:Fbk9>IT>N&_a[?Fl_.E +;ijXizzzz!!%P0rBH8AK'W~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 207.31862] CT +[1 0 0 1 0 0] CT +N +-1284 -71 M +-1284 286.5 L +319.75 286.5 L +319.75 -71 L +cp +clip +GS +0 0 translate +320 287 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 287 0 0] + /Height 287 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0V?\lu&+33nCg[@J`VHgWu>e$10>VHang@aW$aPS>8UhqRH6>gs>85cUPPaWO7$6dY:J)b07dY9$P +G,7#GBi7;crg`-FcF@.^]*cD+61Y%%j-N:+22@3Re0mH+$WM-QL&/+QneDa5'_DDjN2Z?gpqJZ?bRL< +CtQ15gX8$`?b\dr\od17d4jRnZY.V@]mFt7V5pXI??tMHL#gp]!Q:%:D/F_"qK:KYrVc]JA$5Bt`TN,l +`G;IkA6?*G7D'q;PB[pgSiqE9POQaK^SL:nmBSf[eVSh]&%Me+]?5jAc%[GB@p8'J/g] +B@"RCCu2i#Ck6ghH!.G:>V;B2+nCTDa(nG@3Ycl,gprV4'hc5V^P/7DIie(WiJ/M3R4qEo]bb_H1)moq28n +Gk'd8-coOdUatrm_1Q_TNfrX*04);ieF.=jrV#&kho/BJ(OYi!2q+Wu9:'Yh4])!X9%uQljsiT!l'GVo ++9sCgRnQ.pL6G`LE+'a/ZY-K66d]fmR_I[rZc=b._M"Y9<(85!:q1+p53Li_9p9;V$J*HRJfXf1.D5n6lX2jo?VJ,d3$cSK1WQoAqip?\')LOSR9o_ld5 +8fp6FqD9hUP"WH0OXF4L)`MY.?P\FH3.)EHs-?rAZ/FZfY$JZfVtTK1;mr%R,W!,q$p/Y!8=+='?XF4L +bEaaEZcPYqeZ2cpDSLJgB(hUmr+JOtAe/pT6GHB8d3QZ@G9"HNX]q,THNPSX[gl-iDg]?&^i=u#`ufe) +R51VH[5E7J-s5P=p$1)4c=9kp!A;rNS7'CT]6E_@4/oRgisIO7'*kUd5(E"U\P]+kQ0n>Bp$8l2mFnuD +:C\C+'PF>KV5pXIGsOPMI/*1Z.%\+rn(sEd@q)ASgU"q*j[Uid\!fTPR.210?\=&RZ?5?Zpk`u5Nd!q; +ERm9^`/*J:+a`p?cu0qn^>E$uER*A1anYDddke\S7365krVH3/F^GtKH?A*Ib?0>c`^i(HLb5mLrVQ=j +3a^^I@Df=a[C[es,qiYpuo0soSWo>^NH2V1^Nr["9"r[cu0rg(CbtFld,\iN;D,p^U[^TU48[Ae:E'SkSH;V +FeN1+kgtN;Tqbs2qLsrY?0E(cqK8K=kigWPI\END(]&iGIU2.R3r3um?g-_*Kmo_j?PiQmNdb9t(HVD8 +TjR$If7e[IUL+i6Ks'!U4#'9H\X\!PBK0k:)kq6TAF&=O$Q8oScnBM5lU&A5dBgoME9"s? +EGkElNSBeHUL.oo^>'\+EoZlThY@&7$bsH.Ndb9t(HVD8TjR$If7e[IUL+i6KoUUfkSH;VFeN1+kgtN; +Tqbs2qLsrY?0E(cqK8K=kigWPI\END(]&iGIU2.R3r3um?g-_*Kmo_j?PiQmNdb9t(HVD8TjR$If7e[I +UL+i6KoUUfkSH;VFeN1+kgtN;Tqbs2qLsrY?0E(cqK8K=kigWPI\END(]&iGIU2.R3r3um?g-_*Kmo_j +?PiQmNdb9t(HVD8TjR$If7e[IUL+i6KoUUfkSH;VFeN1+C@/JDK-Zf,\VG]idoO((qIW"$:6*)NdBbe/9.BK0k:)kq6TA7Obq +@hlO.o?ab">aTg#=@Fjd4ERYK(M4^L"*T3 +j%KG?C?WAOzzzz!+2ZpNumufp6L-,YHREGX]thpGjm"/]8H1Tr54:#n)(l%G:]M(H9FDSmHs9W04$4,l +q]kE1iD*YIs=NZifm_;h;-mcVbTtcF/8'LVuQVZYHHhAX8'u!M2gaOg[F[ma5\WF7CKM&kf/T$Z"\Eab-GU%2Jq/iq!__g74"4";&jZ;iVE*.]u+Vpn]_r84RhTrTX'Wn)cB?nH5\-,HWN@Wo=&hX"#fURh2IbV;J;l37!EokGn5 +MF&@s#tsm-gQF>lUN:V +5l">Sn#t#]mJe_^SduBq= + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 0 173.19932] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 357.5 L +1603.75 357.5 L +1603.75 0 L +cp +clip +GS +0 0 translate +1284 71 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 71 0 0] + /Height 71 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WZ"m;8+3.gi)@:R8.1R@=`C6:X34QIH#XZ/fio4"cThst4crh/4EKGco.+H@-3_9DtV,3j^8kXZm +kInj8->i>QS48_*iGd3"'5`f6n!AJcYrOfFzzzzzzzzzzz0#HK%hY['9]DioE#6Fl*!0''"3*99b\GWN +8%j%*o!<<*:DblreR@^!V>?gFmG]RqIG':;U%ZgI=!WW4NVApTs?+FueEH1O@OennN?tNO\(f6$5OW[U&4?: +Lr0Jl]+XD(XU4eWLWJK=T=-UqGCMR_CkLLS2DLDH]\c44Nr'kY",)QY_S;J^<,]Y@YVkW/:md;,9*.7\ +ZEGf[^lIDq``aMr9S;J^<,]YB/KTO9SLn'>h4$,O+]a.GPD\p7W&LE)u:.:BY&ig\h;ph93p\3k6k>1" +8kglk?>?b<[c?FuaWJD0R,,ZVW#`5(/aJii4#6tM"lg$Vo4(k/L$BnC#-%nZ]7?e>r3>IZT;:AcYE[mf +:ON=DW&jde?,'#/JRO_',7?e>r3>GCX8E<`<:.7luKupGCX8E<`<#pGF +0&NLR`bnVS',"`,tS;J^<,]Y@YVkU'!_W4Za#pGF0&LE)u:.=5Ce216oh"(%,W':F)JWRsPL_<#uV]p. +2C78:mS97F1+d#\8-%nZ]7H@Ft1p\krl]`#K,,ZVW#`5(/aJl+PAmo`2.4'X8:.:BY&ig\h;c2#f_W7d +s8dL9DMC9VnE[i92U8F?4a]YO+&/$u<;*mh7<('JM9f!0@ZVDqm,]YB/KTO9SLn'?kAel_+SPhdFjA\M +R+d#\83>FEr/54>MV1arOWJD0R,,ZW*.VbDTR%/:k#pGF0&LE)u:.=5Ce24Kc3U;nB66`)BA,,ZW*.VbDTR%/VdO>8!FPt3>IZTd6J0P%pQ0eNu)YGB;[iYY,n_sHAYjmS9=]&lMhVj(OV^[2C*L%-^3qR&jde?,'#. +OaPPe1ldr=%S^-IE7n6)*Bm4Q:Z.Dpu_BdFu!a3\kmNupS +MccKd-qDd[:7-g'MURHm2`8edZ6jY$!;\;#)%;L$.p%u5-3p6[)OtkTYYHWe_''\Oa-,hG&jde +?,'#.O8>jq)R[Ug:rVESpg>(KMob=_d58iH&Q^gbeb^d^RFPG&jde?,'#/JRTZ#M^A]3 +`$F!8S1%LE"`+*39'epb_6r$23<7Eb2n0IUj5Q&Ho!!!kHrrM99Z).~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 173.19932] CT +[1 0 0 1 0 0] CT +N +-1284 0 M +-1284 357.5 L +319.75 357.5 L +319.75 0 L +cp +clip +GS +0 0 translate +320 71 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 71 0 0] + /Height 71 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"/k;+.!_*68)B,eJkXA^\Oj-IYC-R3_$/P"B+0>pPPCOr6iS>sr9[]81!\R4`*7,g#BsYHF%!-BUub +7$;*Ch08bp*N*Q=H`H["n'9DRIQr#G][&Ua3PXbDI%GE)o=gc+Oq9qc+bUCn#U+j463n`f&4-XGKFgHU ++bUCn#U+j463n`3j$"V3A@R(?ih%1_U'VGPBR/2QOO1i6pU7l'-iRO-EWo[=pkQQ('l80T+8-m[ +YiU^kfSa"NQ7)Z?06.5#T(n)Sa;&N:iZIk<=0UeCJ(TZa_3QJJ@4uX)>FtVF]uUq)H/]q>,$2#1M1=09 +>eu^Rra@I#"^@SnLV:bD',)%^6Qik0D"dTf6:-<1+3nnV?&(\dDs4A.oTt46qJ--1,p@j=>!RR/8>*^5 +csICukcY0^Q\5MVZaH[C*8:JW;3dEtgJoA70-BEZi^q=A60`kd]X5Leds.HAY/hHn?R +ndhD.(.@"do]Q)IqYBs_g"G&'4C22pH@C=7]W;>869Fi6pHttl+$Led7(Bb::kb-uPgn76IJim1rVQ=K +L<.g7nRT_cboI`B_hAX)Ff"_SARu&.FmG`BF`mAB[Hg*g%1OK8^q]rU@7jd0>`="A8HE9sWDc_oLp4:p +26"hcTI4UX"b-=?#nO<6ol]?9mAQ+Cd=VZ7/@nYScsI/)mk8br@DUR!?ZEjO8&n42R"tbNURo&3B4j_G +P="3Wc_!G`,:l;67c`Ui@gMu&j\'_>FA=cE7MlssjVYlc/sPqO[AtGEp\/Y6(:,K[grmd[#`]LdV\!)C +_9^EPoG*$lrf!b.RMA@11/b`9r`TkYIm**fr*M[6ng(36+cBB[D@7@RQ#'>h>?dRH!I>qSnmETX!E)L+3t(XX(0r*Z!(BlJc8gaq=ds^ +/Nt'l)l:k22:-Kn#S8KS1+b(0WY#+TR.;&W=<+7W/AQioS\MeK]1@O.36'/[X)^4=Y$D2[FfC4NJ@-t0 +X>l:h8]l>grZYN*M`!AP+$Foq76-&#=qGt/oiWT>W2T1oD2-?>$;'KcW401BV35@dRB@qh5OmsihVQiT +QtuFYA3@WFW3*1e$*XitqY6!EYRIB5J!5AJiAEJM,4`t%9Y)#72pbn>,4@0G\b`hF[tfu)5!GS9CM>dg +32j,k8B"u4YCBLI$UJ`^=f=qbp\nWB+ar>m1OU4`qbb*2'ZOc^s+jjQ$Gt$kElL<*?$# +Xf\#iSXZ+475QLBhaKVXr`TkYIrU+F"#E^]I$hF\*Vk,YrbApCX%QbITasL=N032`Kde +\@g_MK1@!4%^jiR7*$@+`Gj6]95t%3[35&>U>'2'/DHqbQ^=a%W3-?CO`,gs>=hDC4r6*OM[Q5_Hu4N< +0uBBWii!G,4?mOI' +)u==NrQS(k;Iaa-8\=gbRWI\r"nX`h)&X;0)B(Xr3,fnZs3P*\kV!5Ks2NrQBL.,>8<@2,KDRUJFmRDH +^Eb(DrbMW6,p@j=>!RR/8>*^5csICukcY0;p@l#a+)=@nDTtNq[\]h8(.?p7gV/0.*LXFFjQ5cA%1R(^ +rO%1T#"Z-"ec5PDhj-/KkcY0^2aF[hhb6:b/P+9&c8W!8D?Hu%llV_po/B8i+Wc[hB5VU)F`mB"b)2c6 +jmK=,o7iX9H#'pn\[f8*L'ApFhu=UHoP?am[\X]I)r$fcmrH1<^Hpf5_*Ir._u?p6XfW%69he>*($1[F +Q(b6c\bg0RoB)FDH#'^h-7":bGY4?UoP?am:Me5ogDX6K-uS,70A:IAc2~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.60069 0 347.4] CT +N +0 0 M +0 285 L +1283 285 L +1283 0 L +cp +clip +1 GC +N +0 0 1283 285 re +f +GR +GS +[0.6 0 0 0.60069 0 347.4] CT +N +0 0 M +0 285 L +1283 285 L +1283 0 L +cp +clip +0.941 GC +N +0 0 1284 286 re +f +GR +GS +[0.6 0 0 0.60069 0 347.4] CT +N +0 0 M +0 285 L +1283 285 L +1283 0 L +cp +clip +1 GC +N +0 0 1284 286 re +f +GR +GS +[0.6 0 0 0.60069 0 347.4] CT +N +0 0 M +0 285 L +1283 285 L +1283 0 L +cp +clip +1 GC +N +0 0 1284 286 re +f +GR +GS +[0.48 0 0 0.48055 0 381.51931] CT +[1 0 0 1 0 0] CT +N +0 -71 M +0 285.25 L +1603.75 285.25 L +1603.75 -71 L +cp +clip +GS +0 0 translate +1284 286 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 286 0 0] + /Height 286 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WcYJd>*r"Xbf8,BA7"i.m_BW?r:dg13Rmdo%0Nf*`bt9pkO@"k%%KqH*5VNQhU)7-+&IF&b+=\!2 +,,.mBLrb,Q"pl10\Y%0rH)CCKP0`=:bWU#Q.l6?HB,Ft4ESaDFBf("NSiqFDjo:*BG5:^j:>Z5$JWSNq +J,N=3Fqp-+8AqK`3#._'(+.63+EeeU$73iHXE@N/- +7:ifZM/uE`+f'RN5(jk),)MD;;\="!.[r"`S9%:0+n^mO&JB(5,#1RfLf71(Cgl=n;c3n#L[E@uDQ&@:66]/n`2T\O[P2^H.4Kr"PBPp^U>)Z''LF!=7Du1( +Cpl$;c7(2qe9c@a#WG^N&g7jb,2uR$2HuP.kEHZIl92aAKGuBbM3*Nl&TK9MRk7=(F%Qc_ooeJ4h;og8 +:_?9P7%B-j;c24a@H*eU;@'77m/E?(>?!ut+VCUri`&l8>F7D5PS?IL-+gpDRoDc_+VCUri`+EFAS#Fj +DXQ>mGFuNgH$Qs1o$*X_T=iSf-I+UtKogUG#JVJ[#6tLS`l?TCo%.5u/Zua8 +rH`JFoB4G\*^+i/`/.2PZRnk@F%Qc_&JB(5,#1R\NupS%MtPf3CTUg,Q^B/>GZQb$`.]9>],2At<;@&+='bR@<`\t(*5W."O[MaYWJEMK($=Z@[eN#6`VSiIJS&)E3M3Z+$=d%2E!HX5MuD.gpqLNT,0,_>Zb)F)&YGRi4uBp +Y;Z7$[P2^H.4KpL$/I^s)_*%gOGHgIE@P^kS=H\2C<^sX*ZcA/>[2+%5!;&7gbLrQg\gQYLC`G*j*UOg +D7u#&UIUA'q6[RaER$!^K[ft3HjDZ16kUXTV]t,"e8Ai/jiN]6XVLcU.l[KF8kl`JER$!^K[f+pIg@u4 +6kUXTV]t,"<&RsJ39QM?6L&0J(r?^sO[MaYWJEMKQ-C'kc8d2)OLeImL2]LK,S:Z/.O%VVA[@)IF&#:M +V!_3U+l#m+8VBL%MMP2.fkb*VS5W;kW=)^A#WG^N&g7jb,2uR$2HuP.kEHZIl9_p5rCKPuWJEMKQ-C'k +c8d2)OLe0JL2]LK,S:Z/.O%VVA[@)IF&#:MUomV7+l#m+8VBL%MMP2.fkb*VS5W;kWI%Td#WG^N&g7jb +,2uR$2HuP.kEHZIl4VVf_@76B6qG7qLc?-7bn_YO3@0B@\j<0JE'm&>&JB(5,#1RF7D5PS?I<"hd'P)_*%gOGHgIE@NH-/PM[U8dZ`, +XlkIY6U`74&ofBF:.8a#Ko'kG8Kjm-otq>YW/)]c,#1SFWMjXA0QGAe.>1YM>8XeD8AqK`3#._'(+.b.k>[^F77u!qrF%8HMuO'B7KjL8+DAZYI'"?F&#:MUltAr&8nG&,XN\M +7Du1(V0FD'[G%4eS3;4BEH,un.q`I+%Ndmi]Q.t1nG`C`Rs\CDQoO8n'LF9:?ObtKMF\p:i`&=9MOKEJ +>E%.tl03N-5!M8=/DRM8Z$!7?S!tq2S=#[G>$?7Lp?gI=Im#J>YfW5pD.2Fo;c3n#%(7kVJ<5Rc&TK:8 +3e%#%aN-p<_csTf'cZl.bEm"J4EKZ/d*PVT_a"2!o?a0u%j!jckVLu1`&X`k&5p)g)o<%!O[MaYWJEMK +'g@*E==i$=f<2N!=^GDeDOHr^>'8rTdSb)^SND&(rlK"cig`qF#Urgs%cN/"80T>=<(*76$MX#H0,Ele +HhZ64gqS@=KaS^J^%1^Ra-2^N-Vg3,pV6_k0eorT:DPngg;;Te)?+>`BW0C(JR0Ip7.!@Oe+[ETWJD6T +,#1SFolER(\N2f6>:e-$Dh0c"0JG[S^1uM^qSq52@-l%j!i8p&3FAfYYQeVkal%QG+BV%2G!n8AqK`3#+=M +IV\/LI#mpU]6B/`Y@#'$IcJ#?\]#=2c8d2)OAb`B&8nG&,XN\M7Du1(nb5+Vh7.H7eLbROgABmKMrOGu +R@3af%im]A$WAP/d'p1mT`2SPP't"bI[T9FdJ#gudn8R\P,u%02(UqW6cF0mGR[Q9^n6kk1 +'.6O;J,XhZ:MU=OkF@]%8.gSqPDVmS,iVckS;Q%&XK4O0nmq@L(Yhunf8BsJYd!W=.rA_SS5W;kBu^Y@ +();ru8AqK`3#._'(+.F7D5PS?I<3^\-:.O'S.Lf4n*.Opo>9Up/r$6a8K+hS*rO[;UWWJEMK +Q-C'kc8d2)OLE4GhLpbW+XH&H7%B.WAd]:8S@@eU:.:ri&ofBF:.8a#Ko'kG8Kjm*15%k`7ALJ- +E@N/-7:ifZM/uE`+f*@#_HW]X;@&+='bR@fLf71(Cgl=n;c3m8'8Gul +WJD6T,#1SFWMjXA0QGAe.>5&?6[7or6jb(LV]t,"<&RsJ39QM?6<]^!]IbTWKoh*h&TK9MRk7=(F%Qc_ +XihL:();ru8AqK`3#._'(+.k`,.>1*ZMMP2.fkb*V +S5W;kBbais#?4(u+VCUri`&l8>F7D5PS?H!B*dsbMF\m9i`&=9MTTN='BbmK6:`\_n;aK('LF!=7Du1( +Cpl$;c7(2qe78hTW/)-S,#1SFWMjXA0QGAe.>62]$V..O'LF!=7Du1(Cpl$;c7(2qe1cQn<(%':&Z6i4 +<)bb[QoO8n'LFR.j&ADR+VCUri`&l8>F7D5PSANeOs-?icRU2tOGHgIE@NH-/PM[U8r>eCaVIY!k7s+J +8AqK`3#._'(+.6oP!i3Cgl=n;c<7)8;;)X +^9*2r66]/n`2T]3GUR=7g7H'L4aXWi\Y&dMUSFU]p?gW4)I&RgkEH\Z)3Q/5X$8*YSWJY+&TK:8R[KQm +7dK^=FM2"QT:[2F*#on:g\e5h(DhS?(1n@BVkiP&ODNl\rE0`sKLD>fLf71"n`.Y[7RgQ'hR[j1fW[#9 +^>.rK=0Gp>$k*OT&)4tf!p>d^I2J+jS?=FcE8AqK`3#*1rhnNMLepI/Z[GSKDs8EBB0!'EujQ,CbT7?k!_hTg] +iU+2bs"lPheEOS10BfHug4sXFmn6I@X,8CTbt.c5$ep=N'SGG$n]cI!g>/[XJ#EBlW\' +a,c-CqmnJnj0J\s7>AM`aVTY(dT7/\*[),n,2uSOfZk7=>$T7g_\Q`;\="!C:CLSo&RoVed>/\$PV]nP+m_!15'jG%p-\e&e]16,#1RD +,#1SFWMjXA0QGAe.=*Wm6[8@u?:AshOGHgIE@NH-/PM[U8r=YtaUmlr*ik)l&JB(5,#1Rc\,g7G>QUb6tZg_3#*%' +U9`Ih`&X`kk`(Z4iQg_JMWd#C&Z6i4<)bb[QoO8n'Km"j+l%'#:_DMK8AqK`3#._'(+.tA.*Td +%obqU&/&t4,#1RF[Ip;]16uoU8nQV3#*%'U9`Ih`&X`kW+\_VE*'#P7fLf71(Cgl=n;c6RI,X]'L%,pX+r=r0966]/n`2T\O[P2^H.4Mhm,[7eU +FalhZJrkde&TK9MRk7=(F%Vb.k>[^F77u!qrF$cbKIki +04)fLf7/ZDJj@(h]mR@k08>Op'hNCDa&gn[P/Sh;c7]q,X](#GWI%& +OGHgIE@P`$rD$KSDVS?:9Dc>8[@<\V/H47Z(GB[fPMLf4n*.VbE?R41VkPq,r$p%m.8:Bq+0>LWA`K*Pmr +A+T<``Ldq^(A@.MGO3teS,`-Un`,TmZRnk@F%V>G&'4tB4e@[)+XH&H7%B-<-7:0V[9E12)@[2f0.nk8 +DkEVm/oI)JSLshgj2R($Iga[O5?Ve1'BbmK@[BIQjku`kl%g$?,#1SFWMnXqb0#nq:Kf8.Ke5ugF%V>G +%-_.!Zto]VPg.Yh.>1*ZMMP2.fkb*VS5W>P>"FBe&+am2$6^"Z,2uR$2HuP.kEH[m'9X*cgH6L=6:f%o +Lc?-7bn_YO3@2WsKObA_4ASJC&/&t4,#1RF7D5PSBsKA-ho9 +:Ih2l&ofBF:.8a#Ko'kG8PrebL2d1^F@6HZ&Z6i4<)bb[QoO8n'P2sY/Yi3&V^#(FM)Z4^VkUKM_SeI4 +Udu$<&FMoWN^t<=i`&=9MTTN='BbmK+u^c7\3G7",)),7;\="!.[r"`S9%;[`/kDd^?+U8'LF!=7Du1( +Cpl$;c7(2?6F)4?S>RT0#`1MU&Z;A/fttZfVkf-(A-h5[L_N0":.<+#W,/mrER$!^Jfu#K1cue@6qG7q +Lc?-7bn_YO3@2Y)6i,CQ\T`u>nT7/++VCUri`&l8>F7D5PS?1eaU4o9V^#(FM)Z4^VkUKM_SeI4UtBQU +^)Y@#SrQ>b,iVckS;PI$$PV]nP%%W=)8`Judh+$^7%B-j;c24a@H*eU;J\'5/!s%U3[09>Lf4n*.Opo> +9Up/rMGJu6Fp/i%XQ&K#'LF!=7Du1(Cpl$;c7(2#&'5/j.m+i76:f%oLc?-7bn_YO3@2X6+o-.4>Nb7, +'LF!=7Du1(Cpl$;c7(3nL1CIo?(R'I+XH&H7%B.WAd]:8SF7D5PS?PW +lV:hTR'#t%6jb(LV]t,"<&RsJ39QMc/!q$BN^t<=i`&=9MTTN='Bbku@0Mk9dh+$^7%B-j;c24a@H*eU +G$pL?C^%.TSrQ>b,iVckS;PI$$PV]nZ?7KJV=J^r$6^"Z,2uS/1Fjt+F)uEkhS&gIQ*rAdc7,7;I/gWU +Y`OZ>&LiB$S;N,$d1-j$>-1i[o9ZdrcRph&DKr+8m`Oqb5 +T!$]2oCMR+K7dZDA"-_A$PV]nZE\H$D^nJTOa5&i%rKoh*h +&TK;SQM^FF(X)R0]mK-*mbbeZ_M&@:rKU-m7L"1cjW,3W)VWkOKGG;b6:f%oLq%o:BEqadG':=H_Sm^: +^N!Xh@!m@W('_pfKBK;CG4rQRm8QI\+VCUri`*9:[P3fGr26^t`tLXV.O'S.Lf4n*.b^3!\[h*VO0nZ, +,0i1pKoh*h&LiB$S;N,$dC(mh.I5!5)lmjjIlFK0Cgl=n;c3mX3#.QB8AqK`3#-;^ace)B7n6c*qOL7F +!p>d^66]/nU_"/Y.O%VVgGLcC;p)c2qc'd3N&Ya&ofBFKoh*h&TK9MRk7=( +F%Qc_&Z6gN#`1MU&Z;A/fttZfVkak:E@N/dOGHgIE@NH-/PM[l80K8<<(%':&Z6i4<)bc:0QAQdKoh*h +&LiB$S;N,$;;"(K`2SP,66]/nU_"/Y.O%VVAb-0@V]o"EM)Z646:f%oLc?-7bp,oPMF\m9i`&;Q+VCUr +i`&l8O"bQ',)),7;\:I37%B-j;c241_SiF0'LF!=7ALJ-E@N/-7:l&r';m$P#`1MUO[;UWWJEMKQ-COI +S;Ki\,iVck$6^"Z,2uR$2NKP3.O'S.Lf4m7KLD>fLf71(4Mo%9L_N0":.:ri&ofBF:.8ac#SX*[;@&+= +'p1gR`2SPP'p[#g9Upu2+XH&H6jb(LV]t,"<&TdkE@N/dOGHgI.>1*ZMMP2.ff[-iWJD6T,#1S&&/&t4 +,#1RLopt9C?&O041m4C4#r#p?^Jl-"s4F +&Jaor_h[]pqeklZ^!2Fp*'$oecq`IIWblj"FPjf\S\>n>d`fqZiPUG?:Ig%iKD4iln+8c;P(*?!a4A"@ +VbWegLtS*GY?rA6Gjr3"IVZ^G95_1LD+.cOV^l(0'T_>IoQ7cQT:_`/?8db%NHP(m;)-sWqe^=Pn(t`^ +<4&m6nFbC?+#n5435;#u?W:%qN)Vnmfu!)@nZ&7=ZBkci!gUG/NdD3PJ0>Xku^]+(F&^p@N*;Ei2!Jr:n@S8F+/t[r)qAq9,*X4*[*jQK@5i]mKK[ +^3mJ69C]dW\pF/@@AiQ" +eMB3Gq>'3GJ,&NL(1mf?s/8)0r4!$s`/,0-rqF/T-78XY*]m3*<3+PuqWXp8J,d3,nTjp!iGZI+VUKaH +$7H\XdaD%RY;t(G@_Cc6lSbbV/MFYeAnPb7#B85jM@9n%N/s$Dl7PqV:S'Zt'(R8$m(h)J:Ra_Kpp2Qr +%c"U9VatKGGkd1M^:8@Rg8.H/MPm4JVbVLrBm*ln@Ud[@NZC4Tp?gU0h]o.3eV`m[RiU./$[]u9k?sJ= +iPUEU%j!iSk0/Sk+$+gWW0jEXV5$PArpn5cbn"Z"G2W)]gVlBlVb`q&NSasO*j#4P7+dCgkKb52FJsEj +]"G]Rr;#rXTqTAZ&"CIQSLmOj-.@'ait<3["Z3ScI2Wqr>R\5 +XLcB#6>*nW-RXgm/mc3CkrV43NJrh_=cX<8f"H=uU1e.NAu>OH6\c/NLi$l*8!R(]_Y`W!YKib)hl44U +jfDW???3@SlY^,a\T=<(H#e"K[.U+OG\78YVP]5eg>Cp2[VKGcA\$'N.p)H3gK4r^8`5G%KmhOBYG/\^Jc$$4ka@krCc!UBS]^2`OlVF-:*?6&85H"!B +$O[?].thEQNnsW2juX^%cM2ZnG38Yolbu)'PEV3RbKI(r^]*fI08k>3hS4Qtl2*ogS3(qtq=DJBX/"[H +\WN#:!s]=KHM+;epP[0r]4/G6B"M)Dj<]"AMUr9E>-7VfLr7-JIf0E(EoY0!Fhb?7O2)<8$aX>349lB< +Cd&H%3-!sRoB2[Y7o[fi%j/g3a7o#XgNjt+7un^6qG'm6)guq2QeZE5Wf"IM0$h\_b*+2K*(^-V5eUJW +-Lemh6Ds8Xe^f+jjR&^6j + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 381.51931] CT +[1 0 0 1 0 0] CT +N +-1284 -71 M +-1284 285.25 L +319.75 285.25 L +319.75 -71 L +cp +clip +GS +0 0 translate +320 286 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 286 0 0] + /Height 286 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0V^M@-:"39r[_+@n%r!,"@U7n;j#Ciir<(,dk%dIG7'a-fjE)I7@E#1ge5uB%2"VhUa8o[[H&8Dpo +M'=-t#V$TW^(1\1;"EXUr$6`3_s91EHd9/^IId#UT6!f$=^>Uj9W-A5&@QcGd%U.Ep<_79dcHg&Ie1fC +^]!l\kKfbBHes2Fh=3(X5KE)0keRKG>^PY!='k^dUQ8aX[F\c8rEXX'[=7cIqsRlVoZ8JQXIWnqq)8[o +HXU>+q/ZHlrDpT1qWm/\I/j0>fCqE%giM6CHdb\JXhX8$T7/hKq!`P"qU$nlSULL^oK/uC>B0N3l1#3( +5CS"AU/tZHjbbRk(jk+cl`J]3rJpi;5Q:GMJ,]9BpYV$9l;^nk[Cj/bIWWb^B:jZ0rQZkj[QO)u'8QU+ +EH1NTcT\u-ZHJhclD`<.rSE##mGeY20"Uc1CVTlFlh-HXfC/(tDl2DPV;J#^rq^Ec.+b%d\$KE)2rB!= +Sn`KJr+kpdVt@UID7ILO&cL!(rU+b'AHr,$F!jbT4EKZ/?N2VRSQ#Ar%AU0hs;D:(!srO1pVS:4]792<5RqB`&s(B'EF +Di9(dl*j*rjRh3$?ZQ![d4[NY[cj'JITuG;:;8CW-)]W9rK>oL^JfkP",^^hcsD?XikK +d4[NY[cj'JITuG;:;8CW-)]W9rK>WJMgie4[me'mo\6*IEr'Y#000!>ka.fg>P(Q`^Ff:.Vr&9gP1+?- +I`^i`7DIpUgS/%qqJFV53W6DMQ^iM/oLhro/c$ckh\Q0Rdr1.nam$9'^Z>%AU0hs;D:(!srO1pVS:4]7 +92<5RqB`&s(B'EFDi9(dl*j*rjRh3$?ZQ![d4[NY[cj'JITuG;:;8CW-)]W9rK>WJMgie4[me'mo\6*I +E]`Z4atB)U-LDt\mk!h\*aKYNDWJMgie4[me'mo\6*IEr'Y#000!>ka.fg>P(Q` +^Ff:.Vr&9gP1+?-I`^i`7DIpUgS/%qqJFV53W6DMQ^iM/oLhro/c$ckh\Q0Rdr1.nam$9'^Z>%AU0hs; +D:(!srO1pVS:4]792<5RqB`&s(B'EFDi9(dl*j*rjRh3$?ZQ![d4[NY[cj'JITuG;:;8CW-)]W9rK>WJ +Mgie4[me'mo\6*IEr'Y#000!>ka.fg>P(Q`^Ff:.\'of(m#oJ$dN/JecGIlod?T:9VXD4;o\6*IEr'Y# +000!>ka.fg>P(Q`^Ff:.Vr&9gP1+?-I`^i`7DIpUgS/%qqJFV53W6DMQ^iM/oLhro/c$ckh\Q0Rdr1.n +am$9'^Z>%AU0hs;D:(!srO1pVS:4]792<5RqB`&s(B'EFDi9(dl*j*rjRh3$?ZQ![d4[NY[cj'JITuG; +:;8CW-)]W9rK>WJMgie4[me'mo\6*IEr'Y#000!>ka.fg>P(Q`^Ff:.Vr&9gP1+?-I`^i`7DIo,g@(83 +17:hi6X\eSfXX/V1,.J4rKin#>P(Q`^Ff:.Vr&9gP1+?-I`^i`7DIpUgS/%qqJFV53W6DMQ^iM/oLhro +/c$ckh\Q0Rdr1.nam$9'^Z>%AU0hs;D:(!srO1pVS:4]792<5RqB`&s(B'EFDi9(dl*j*rjRh3$?ZQ![ +d4[NY[cj'JITuG;:;8CW-)]W9rK>WJMgie4[me'mo\6*IEr'Y#000!>ka.fg>P(Q`^Ff:.Vr&9gP1+?- +I`^i`7DIpUgS/%qqJFV53W6DMQeY@5S[(m8P=^*,loPS:[msL(At-C3'%:cWI`^i`7DIpUgS/%qqJFV5 +3W6DMQ^iM/oLhro/c$ckh\Q0Rdr1.nam$:Rb`fAj>0K)hX/O"]PI$-MbWIndW5ZuEZ\hr14?9I@`QXOP +MH\4d3NK*tb`fAj>0K)hX/O"]PI$-MbWIndW5ZuEZ\hr14?9I@`QXP#d44u/^DnIGU^]P +*PGMRDrIEZ3!/mPpUieoIM2XeBWmOe>7m^qr-KKo+U6i(@U1KMo:pYJ!"9\).Ppu-uQ7uj*'IC_/W"6f +[Yo4'skHKh9r@WT(\mt>i0>882l.E7N\))Gsp`R8_]NcKD_6gc10>IF*D=Y__rUNa#=@M8q4#Y-sfD&VLg2! +lTs8;KK=mXEqn+9QB?+9WncY^/Ip;.1jXDR6hIq$;FHKUiC`o_LK>7Ym>q2RV5jk^gbV@>?]bVRT#E5N +,,IItq-(Hq`hdoTn)oltKMm+Ledg!;RXU(9KdE,<8ak*q^OBAA(\HgJ#WkROm-1]Qs^%r_:0"O0%bCfj +-`If&Nb4E]r=V=-EbjG6gClScubhgbZSi=[fYr:9X\4C4!Fh/T`mD>l!,/[sMUr:ogTc(BLbH+[QJN\s +:MODXgbkB3AGq'S)(U@I2floB(F`45Rq/M5e&hgJ"U*rYK8hhm%KORu1`b>gA7cf3sDg@Nq$A&llc44b +Aln1UlEXGgtFr:.i$5QCcazzzzzz!!$EPr""0p]0Z~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 0 347.4] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 356.25 L +1603.75 356.25 L +1603.75 0 L +cp +clip +GS +0 0 translate +1284 71 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1284 + /ImageType 1 + /DataSource Data + /ImageMatrix [1284 0 0 71 0 0] + /Height 71 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0W0k_5M)o1uA6q!i/PCjRCLo?,cV21"b>6b`S*/]PC(NFC,6q!OJEU)&M30YTs;FEpQ3#%K!%`L/F +E@<"TKb@^g/]%2NGf.4ls-VsE?0]1R5#ZP$oe%6A9DX_srUBsizzzzzzzzzzzz!%?\!oB3`s\u)C'>?l +[:_M)h)bEjkT]iP16!)O`C0E;(QIiG^J!!!!<;QX!scVN41^O5@>B&TS_V/1S?Y)9Q)[^U"Zg:5I0NXG +ge!$upbmbQgZi205<\phf93-46+r;:qj6#d[SEokI;mFsjSr-75>M1#91D;/sc^0TN&4psT$o]Y;RMtq +8&]=YCtIeiPG9udD;!.ZiKcH^=a]K$pLDqqiW5!D.c1=G(;T1u0f%j%gU.F,g+S@`RgY.]2V5'ZSTiPU +EQ!s@5B9:%9]fB6pqH?smaHZ.cRH2mmBrVQ>%>I*dE9udD;!.Zhp5(1$4n"4gmhOSN]r:tD_ZZ-cKlg% +b[>g0spZEeN3aH:TF=at;rcou^MM,LhcI!f'lO +k#iN]Ymiqgd=a_^"fX&nn^X0*TF;29$cBm"oae:lmdBN3n*fZ2D*A=\/M.]]P24>?mb+ +oo^U`Y0<;L/ADWSA.!!#iM;lgq*F`,rM*ET0.Bs>efS$Kq$<'/KP].!!&1/oB&b*HO^Gm'Km^6i^VLH+!ldjXh>BfGdO_oLBoP)%@E>Hk"]QnOW/'hRL +CV"BnY5h7ZS6C%;j%\)E@N.=+VCUri`+F!\[f7\a,X_PY$%,%E1N/FOGHgI8I1/4'bR@<[9?mC*Z5jK[ +r:0WZY.P"FGB+G,_SRUMF^')`2SPP's6$'_SY9LLW@ESZ7jG=FGB+G,_SQja"$?U!(t_sZh*bYo!`PpI +f(1C>F^E!C)$[)d*U-chZYn>+VC':U@j!7#CsQpHa@[^f7iIV;(q*pJrke(US@F1[Kce](&WKq/54)$@ +7W^U`3i^pH9]:L!6kXr+#")O0h*"C&/&tW.f,p3U\VfQ3$M*d`2T\PAmma?F\395,-J0pF"V>!E($4RL +f71*beeI\l]`ZJ6sRDLP:mLhNegUGE@P^m=dY4hSW\YfLhlNZT\''Ynu)(u7%B-j;c2;n_K:b&PU(oMK +_^sf4<+s2,2uR$2R>)WY#CJp&oBE+PEptKi`&=9MTTNH#2nCa#Rg\PaaX?B+4)k~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48055 616.32 347.4] CT +[1 0 0 1 0 0] CT +N +-1284 0 M +-1284 356.25 L +319.75 356.25 L +319.75 0 L +cp +clip +GS +0 0 translate +320 71 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 320 + /ImageType 1 + /DataSource Data + /ImageMatrix [320 0 0 71 0 0] + /Height 71 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0RYt?6<'F%qWfg8(0$S)gY74`;ob!N>bb0E=)`7?m:,uRhNiWE:bLffIhL]e*X5\qu&ln'bVAhOKY +2SnaiGKn7fpJjfQjjkkj>05%FImlW.#Q<6cP/gqH1I +At.(d+'d9hIYPM[d:S)46m/*CHbDj5^rDtI-+7c_%UjHi2^CJ0+*jL;SYQU6.:97A>N\$k@aU:9rX\\1 +baj\-A\P'NqcQVLmHY-c;5;tVG]=qeJ-?K`Pkg8i8>`S2:[)"H0JYM@^iD%h^J'M1T_UAI=5 +C)>&#l4jXWhk8*QDie'k$9^QXkFAROuqn'b],4$2P=b3XI_b9ACthYs4sUDq\q?WNOo~> + +%AXGEndBitmap +GR +GR +%%Trailer +%%Pages: 1 +%%EOF diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_radius.png b/moveit_planners/pilz_industrial_motion_planner/doc/figure/blend_radius.png new file mode 100644 index 0000000000000000000000000000000000000000..889411ede8b1c8e4c437efe6355a6bb93ae2ab93 GIT binary patch literal 56819 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 image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"-Q5m[ZK&4Jl8OV0*_(+G@Y.C0eEKu^JqF`*XtIa8)r!'`0W\G*^"53L-Mh`kI`mCg8:"TSN&!5Q@u +T)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7 +!<<*"!%@'Wz!#5'>S8!!%P +$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\ +#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!! +`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!! +&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2 +,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT! +!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol +!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*" +!%@'Wz!#5'>S8!!%P$rX8c +,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8 +-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)h +o3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56 +Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!r +r<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$) +#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2 +cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'W +z!#5'>S8!!%P$rX8c,!!#8 +MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii +""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!! +B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!! +#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!) +V%7!<<*"!%@'Wz!#5'>S8! +!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:! +.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF +!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5' +>S8!!%P$rX8c,!!#8MIg,l +Q!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW +'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7 +CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT) +eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!< +<*"!%@'Wz!#5'>S8!!%P$r +X8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ +ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`* +B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[ +b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,u +L!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!! +3$)#sX:!.]\#$ig8-!.`a+;ZZ.&$Pj6eoOe.(!!!!+qD/*O!!!!&r>>S8!!% +P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.] +\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!! +!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ! +!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'! +2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT +!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eo +l!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<* +"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[r]/+NCf:N +'D!!!!Ikg'5/!!!!5oOe.(!!!!+qD/*O!!!!&r>>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)e +ol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V>(F3` +AjzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzJ:DhF +b7^kp~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 921.6 112.8] CT +[1 0 0 1 0 0] CT +N +-1920 -235 M +480 -235 L +480 940 L +-1920 940 L +-1920 -235 L +cp +clip +GS +0 0 translate +480 940 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 480 + /ImageType 1 + /DataSource Data + /ImageMatrix [480 0 0 940 0 0] + /Height 940 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlV]TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzi,?jb%4q~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 0 0] CT +[1 0 0 1 0 0] CT +N +0 0 M +2400 0 L +2400 1175 L +0 1175 L +0 0 L +cp +clip +GS +0 0 translate +1920 235 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1920 + /ImageType 1 + /DataSource Data + /ImageMatrix [1920 0 0 235 0 0] + /Height 235 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0R5n/K4!!GS<83mS\ed55T$<"C?^a1"AS#Z3Fk2#b@zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!!'f4k+$?sz!+8+I[U +%MXp'Uj#!!!""UH\h\!!!!qd%:==!!!!Ikg'5/!!!!5oOe.(!!!!+qD/*O!!!!&r>>S8!!%P$rX8c,!! +#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!._q]rqp&^1! +2QXz/E0NVSoa>s?JY\_!!!",&c+9`z"oT;=!!!"LK)Q/Y!!!!a6%9(=!!!"lTK`MY!!!!qd%:==!!!!I +kg'5/!!!!5oOe.(!!!!+qD/*O!!!!&r>>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"FC +rV8F5o/qMI"TSN&!5Q@uT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii" +"onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!#jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B +&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V%7!<<*"!%@'Wz!#5'>S8!!%P$rX8c,!!#8MIg,lQ!!&[b56Clc!!# +jBT)eol!!"G2cN!qF!!!`*B)ho3!!!B&1B7CT!!!3$)#sX:!.]\#$ig8-!'ii""onW'!2,uL!rr<$!)V +%7!<<*"!%@'Wz!#5' + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 921.6 0] CT +[1 0 0 1 0 0] CT +N +-1920 0 M +480 0 L +480 1175 L +-1920 1175 L +-1920 0 L +cp +clip +GS +0 0 translate +480 235 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 480 + /ImageType 1 + /DataSource Data + /ImageMatrix [480 0 0 235 0 0] + /Height 235 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlYNTE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzJ9M*dVuo]~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 0 0] CT +1 GC +N +0 0 1920 940 re +f +GR +GS +[0.48 0 0 0.48 0 112.8] CT +[1 0 0 1 0 0] CT +N +0 -235 M +0 940 L +2400 940 L +2400 -235 L +cp +clip +GS +0 0 translate +1920 940 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1920 + /ImageType 1 + /DataSource Data + /ImageMatrix [1920 0 0 940 0 0] + /Height 940 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"-:! + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 921.6 112.8] CT +[1 0 0 1 0 0] CT +N +-1920 -235 M +-1920 940 L +480 940 L +480 -235 L +cp +clip +GS +0 0 translate +480 940 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 480 + /ImageType 1 + /DataSource Data + /ImageMatrix [480 0 0 940 0 0] + /Height 940 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlV]TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzi,?jb%4q~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 0 0] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 1175 L +2400 1175 L +2400 0 L +cp +clip +GS +0 0 translate +1920 235 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 1920 + /ImageType 1 + /DataSource Data + /ImageMatrix [1920 0 0 235 0 0] + /Height 235 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlV]TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzi,?jb%4q~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 921.6 0] CT +[1 0 0 1 0 0] CT +N +-1920 0 M +-1920 1175 L +480 1175 L +480 0 L +cp +clip +GS +0 0 translate +480 235 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 480 + /ImageType 1 + /DataSource Data + /ImageMatrix [480 0 0 235 0 0] + /Height 235 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlYNTE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzJ9M*dVuo]~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 0 -0.6] CT +N +0 1 M +0 310 L +955 310 L +955 1 L +cp +clip +1 GC +N +0 0 955 310 re +f +GR +GS +[0.48 0 0 0.48 0 36.84] CT +[1 0 0 1 0 0] CT +N +0 -76.75 M +0 309.5 L +1193.75 309.5 L +1193.75 -76.75 L +cp +clip +GS +0 0 translate +955 310 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 955 + /ImageType 1 + /DataSource Data + /ImageMatrix [955 0 0 310 0 0] + /Height 310 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlSlTE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz! +8q],& + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 458.4 36.84] CT +[1 0 0 1 0 0] CT +N +-955 -76.75 M +-955 309.5 L +238.75 309.5 L +238.75 -76.75 L +cp +clip +GS +0 0 translate +239 310 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 310 0 0] + /Height 310 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlV]TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzp_ +u9P$uu~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 0 -0.12] CT +[1 0 0 1 0 0] CT +N +0 0.25 M +0 386.5 L +1193.75 386.5 L +1193.75 0.25 L +cp +clip +GS +0 0 translate +955 77 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 955 + /ImageType 1 + /DataSource Data + /ImageMatrix [955 0 0 77 0 0] + /Height 77 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WTS+'TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!!% +O*SPYH+~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 458.4 -0.12] CT +[1 0 0 1 0 0] CT +N +-955 0.25 M +-955 386.5 L +238.75 386.5 L +238.75 0.25 L +cp +clip +GS +0 0 translate +239 77 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 77 0 0] + /Height 77 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;! + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 0 -0.6] CT +N +0 1 M +0 310 L +955 310 L +955 1 L +cp +clip +0.941 GC +N +0 0 955 311 re +f +GR +GS +[0.6 0 0 0.6 0 -0.6] CT +N +0 1 M +0 310 L +955 310 L +955 1 L +cp +clip +1 GC +N +0 0 955 311 re +f +GR +GS +[0.6 0 0 0.6 0 -0.6] CT +N +0 1 M +0 310 L +955 310 L +955 1 L +cp +clip +1 GC +N +0 0 955 311 re +f +GR +GS +[0.48 0 0 0.48 0 36.36] CT +[1 0 0 1 0 0] CT +N +0 -75.75 M +0 310.5 L +1193.75 310.5 L +1193.75 -75.75 L +cp +clip +GS +0 0 translate +955 311 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 955 + /ImageType 1 + /DataSource Data + /ImageMatrix [955 0 0 311 0 0] + /Height 311 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WDeR\qh>d"3DiENij!)0V0m8OSW$BS;+gNsOLi)AcZ#^7If.E5>"B!*gUj1_ZUq.>(NCc3g==@IO +#Vqt<.T/\46]-uM207&'ru`&E60a%i8XcL_r]WQ]oN\<7S%6I_YEBrGd#Z4SFXK%s&k-1k?@b.QU,MC7,/t9ln/EARVW!ZL(YY^V$XC1#.`eUQ$ +@9$kmVlWeHi_FB!,X48F,G)pdi^?e>We,r)$t]YN7lEP1<=#WTK/mM>WX9NA17/e-*81*`I25M\B*AWX9NA17/e- +*81*`j!reFf'3a7lTo]4rrhW^'Pfmo@](3AY:pRl5,` +oH=WT"g/XFW[`[%Q,/uc]QSWWnSbJZ9(*Wi&U_Eb"n.dA,7\`aDj*H;U?86SLjOb=JWu<<[*ejnI#G[i)qPYZ.;mGRJZZl06=e+[h-d$=QqWT99!HqXT(LZObfB;E[LO\nKFk5<>@&aAM>W:33r(JW^9ff +)9gX]pd/QhYJ-B$=QaE18?+pT"UeC(Nq95ZIsq<>j!f(633YW2^D0eMILe;`PNB\JbU6.Ss-]6<+5rJqYEg+0$fDl-:fumq&4ifd<%!W<-'7/6$17.p+d:nY)sL=B/iObY7,%KQXF%JYWWPR$l+A$gV%,!_F-*Wh?CR4["5`il)9A0">7f^F+Y:Ja5`JeuBZICj>U"8$?41k18HX +pO2Y&hqYecCMWqAYc7mgR,%sY.Q9#^F#=4KQla+'6!/K37"@ +)p+.*rqQ6&s8@0!IISJb$AFM#NffHd9(usP.r`0M`*,#;bYL@k`9?DuG0?4ZIeiWb:V.SGns@+is7EOq"uM^8b2.hpXp0HQ +$<1#%<*d1`F\be/n[I,R?XL<^iT\gh/)?i6XMFM'&8Tg40Yd5)4/FmMs8Mo``f1orWrM^qWWk2Fh$3<4 +]#7SA0!'+O#UEECWe0uFj5]0;!$=@M[.Y#=0Iq+U.)]:H)pH4;_kf&>?Fn]B;A]15AIkuiFH$AV7*foQ):ka8+$lT +DL"IpY_@5&#(`QW<)k?IgAG>BEo`&R$Y@kgqXeKGM]9uB#'9Bc0$8E!ROAhbea+195Q0hBV)L=4 +)Wjg[rH.AVXmTQ%Gk'eN=+4=/XK'jC@HKZK=t-Oo2$bI-TW3VhorDfK.RAj7U%Dh%XgG0Ah%i2')5B)Pg0iueflIDqQ!$=CP\Fddp$PtRc>E%l:+kE[H@!8,ip=]2tJ,bRZr*sqp\,5RH[;1]p +H1]KSh;,+2H`gYdp8r7]bP`Alr24Em(CC=)S)+)rh4.nR2):P3ICXB&gE!/sG@@&C5p3-.<>?3Jh-VQL +2Jaf@p?'VhDA)Em\$+6Y)9`Fm0++sbbm*d"*BTj;ie_J35Oul?^\ZKa9(+S%@/f=Rs7u&#J(oBfV88ZN +^.uQtkNm=0@9(R#0\?*jObpgSGkpYEH*/)?i6 +XMFM'&8Tg40HWB"bl.D,J,fD]^qc:DIT^id.YIPT0>;BEp`&,c`XdOfK38G#VY#!L5PicgRf@l2ATAd7 +FhIu(eoN]U<:u9I$<1":Nf?%mTsXZ\K&5rkfiWnG)%)5OlZ*T7?k9^&-,0O,].T]>'m%*R+9G=+0R\ +)J6C%0K8o!,dErAq4am5,ZUM;Jq^35Ad&Q42EnBHX`6%EpUf>-(:*P8J,RQ=86M%/#BTTs=b!#t"g&cg +c+FW[XQO?4W9PBp'r\-?Tdk[t_8;=o:TRPL?+MjH0Mq]g3Se*2mHlL=ja5n^hG8Xte'_Hh*6^j:I\)8t +XVo@-s2_]PcddD?eN8pD:fY=u<k\3sd\TTdr8SlchVr<)B5G:W6TpfbrH..ccW)!c +H:Lj:W[_,Lb$\8SE+J!mE`G&cf<8OgH:pauLZfW<;V#0PTc;4)hhWQ>F&e!qhN:cgWX9NA17/e-*81+_ +>h';Gd^K:jIf9,\%mU!SRr=VL7kpBhN4_nQ1mi'(\T2!%ZDW)Ql;6"mOt':._*V-+Z\!lU)kW@q]#!aQ +n1T:ebKiEQr5t9T:HeC#GJ<[>ZBm^I#BQdHI +*6\l,&P9Yqgt6"P_.taIE3:ZeeN8pD:fY=u<uuroo>gT<)p/!Q,0P0iQ0#oWX@1SQ!UBI7di]O=6!nqI5'hAPr"r2$<6\YU^C($YY^V$ +XC1#.`eUQ$Xf5Lt3fUFHARsR\Sb:l=j'_T[7O7Zd>ZIGsG9g1]We,r)$t]YN7lEP1uB!*nVND/FBkGeS`]d'KX<>@&aAM>W:33r(J +W^;WEB!9IX[$HW>g"gMb&"dhqS!qJ;c;b%JH:Lj:W[_,Lb$\8SE+IurWS5]5-\A2\Z.npmmsHD<%Q:KP+` +K3+pOS%88]t$m_mud4&ePEr#nghJi +YNuE0%m@;pTncC3HF`U*N)YcF-:fR+JU^C($:fL`- +B[QbRo69Z[IHo=]!s]=Ghfa-bh7S$>df&@QVGJ\RKfZcJ;t>AC&Yc:WfrBbCaf_d>D/FL2rabU"%;,?q +g`>2+np[Aj0O$DJ<:u9I$<1"RX6O7M+$4Z4r;#s'hd4!BeW&E+4*FR@b[19RPk&rR;2V@\#-1f'+W16/ +0\^tU\Wjq1&YQ.J,ZUM;6>NSR?+P.6\oj;;.>(cSlU?B)$J)6&p-pgT<)rEo +p%Ie-!s8X:59duSjp`7f<;I.1ZNAa:!`^!%<3>8[.mNa[iiQE\k5@h`B;]KWnrk;JZ9'7WbrdMp%>`%[q@qcil)^@]RKg*Q2]d'KX<>BUU-RU9sL5,-Q]fYOC)9`Fm0+(ZYaJJ0@K/mLBoo>gT<)p/!Q,0P0iQ0#oWX:>Yg>l5Y0UPd.j!f +(633YW2e3rWa;QCL;BB8Wd705"fa%SW6/LKY]+.56WF;4eQQ:^>l,J&0UPd.j!f(633Y +W2cMklLB_m+pN,2W9PBp'r\-?Tdk[t_8;=o%oj>Y<>AFm_dH4W5e]-I%Ug=JlPYosmOt':._*V-+Z\!lU)]u(0GcBEd)j/X._439\ +H:Lj:W[_,Lb$\8SE+Iurj!f(633YW2`Ze<=;_c_dH4W4%W9RIX`,]):SKOeM +L;BB8Wd705"fa&.WqQ2]5QCZQ@q0!Wk.GZH-rAH\+C;35,6i53W9PBp'r\.*W-[me3OaQpL5+KeCE1RK +'afZ(:oBnVT"H.3KW*V;6K)HVf;0tC._C2kmbmN!pEQ5sqi'%Vf9c6,QlY@i!`coYW<-'7b,RA7QH.%d +T6p":2r8d(q^p,JkJbWl6lE!_al",#e;It,;asdU8?+pT"n,GuJ,T$^rpY[j:7O:dhmRCVk0BO`IW=o; +`C_5h?rl33;4q[A_L2k_)$Y0)W9PBp'r\.j^$==ZCM/#t`TGF7.t%\U=b5m-JZ90HFXjl.h$IO?B,JiA +UT/M`hn>UZ,dqiTH\_439\H:Lj:W[asJnf$Z' +E4mYr[75;P&P6)))9aP)Wco^gTW/'G3EBB<$<4,r/`55_qAPC$(1YKN4;RS2.*j7oBMj.TiXl?rjLNAE-&-#;uPQikh_< +?qqS>]d'KX<>@&aAM>W:33r(JC)J[C6kWO##'7qcl5`G2W2a7!.YCm?_NBfgj!f(633Y'!Ed2Hg@o9172!0j!f +(633YP-%p>)j/W#XJu]kPYosmOt':._*V-+Z\!lU)kSsff)%o^oa7`LK/mLBoo>gT<)p/!Q,0P0iQ0"d +[AotQ@$Ctu.YB`m<:u9I$<1$0:mJku@,]2H-_79>RECr%W\Tr?7TJnJW^'Pf$WS(g$5SY_U^C($YY^V$XC1#.`[CV_?J^L6?=?iF0W0l0hN:cgWX9NA17/e-*81*T>da6#//O"?Q,/tG +Wd705"fa%SW6/LKY]+.5'4o]6VfF,cWXS$S;:Rak.Ss-]6<+5rJqYEgT?+%p5*[p4b*fK6172!0j!f(633Y_Q@Qo.VHVub$[s^V?GMX4hhDP'U96 +qB,u`b,FSG8JS2(TW:+-0T^_3hpS>oY@#%NjdpO*;^`@:6CiFKHLcLj&[GQI:cR.YFfDM1:8OrVrfOgF +]3F-QFCmG3r?u7oZndgGun)!X]r7a +h4MNb_"FF`A(?rQK2EtsF-XS319,Xj;?a'M.&r;eNV2u;'n=6BMA7YE?G0P(rXX;B$0ti-0W0l0hN:cgWX9NA17/e-*81+oZ>-mf +6rL4mc;b'ib,FSG8JS2(@%f'&=i%t;NDF>i-M#)q;-gT<)p/!Q,0P0iQ0#/>rB$hS-eLd +AMC$@Wnrk;JZ9%mW\TqV/0*@Wsn-T;:Rak.Ss-]6<+5rJqYEg+%=`ThM@t6@@aG-k*/`n +4-D'igT<)p/!Q,0P0 +iQ0$:RB#Ma&P9[Q3`d3C.ANne,ZUM;Jq^35Ad&Q42Em+#jb`*a_E(a9bUK_-%-EdO +eN8pD:fY=u<3P]tJj>II?P?\"'MST>@VE +oqIOJjb[Q`_E(a9bUKi5LPLWmKu/EF$Z=b0;0//m2 +ZcXj8f"&pZbUKK/mLBoo>gT<)laoh7%+Vn@X&ZE/QWXS$S;:Rak.Ss-]6<+5rJqYH(HFg)G8[GF#=B-6_.ANne,ZUM;Jq^35Ad&Q4[[#?@3KmXs +ed/<+K/mLBoo>gT<)p/!Q,0P0iQ/GsCSl,!SZ8e+<`K?Fb,FSG8JS2(@%f'&=i%t;]d'KX<>@&aAM>W:33kTIT?HchsVf,TZ9%C/!4-(CD5T``$7EHs0"M"i[G@grPMI7bHb'`% +nUkXUl`6m*XK(\E;IVGURX"&`^AQ8>_U^C($YY^V$XAJ$"(.U,A\R$&S +QhZ56Q,/tGWd705"fa%SW6/LKGjrf*qd_HDq*>e!QhZ56Q,/tGWd705"fa%SW6/LK-luN7Z:>\5QhZ56 +Q,/tGWd705"fa%SW6/NAc4/U4Y"S+lmjq]snHl6GK/mLBoo>gT<)p/!Q,2f[1J]@(PA=UcHAPF"<>j"0 +UT/M`]d'KX<>@&aAMD`:Z'!7*DOuRJ,sGa;AMC$@Wnrk; +JZ9%mW\TrWdJQOI-TBAgob*n$W\Tr?7TJnJW^'Pf$WS(gPr(Udh>c3_mP'g;ZZ*Ur-`jqOG3!H5%.H&0W0l0hN:cgWX9NA-9dei(NP]a\b+!S$V**=<)j4).YB`m +<:u9I$<1$0:c6)*gs"6g281Wp_NBfg<>EBNb$[s^,G_SVFp%oj@]Wle^E)-+?pW<-'7FB,69V?R817n,s[]r0Q"r89JN +INJB7)S$3X(BpfgKN4;RS2.*j7oBMj.Yt+mfs>>ZgpqLo>I.qdkic]F46J\mB3`Ei[df"A\7P+S_Y'Wg +E1&)qn4TW1=\<>j"0 +UT/M`]WcSHg>[$8r:!'4M*Lt2dn9AE0 +EME*Fq=Edao#`JJ5,>;t=6g*1mAnn=2P(N4MZQln_Q(ad:)R'F,H1`E'tdU2Fm>21b\f>*hUp6'Z$Gs' +8fuL(_;*UbVlT,]V>h8;-f9eM:JXdC%j=8=<=#Y*qu#$sf9c6,QsEfo6U=`@8?+pTKsI_p%H].d$-2R( +EPoF/9pD?O6gT<)rEoF`;<(hNqdNpOE3]?)'@'!F.:\(BpfgKN4;RS2.*j7oBMj.X8.c +I>d!V6\ig%.K)0?11oFR,\UF9$<1"2X"&`^AQ8>_U^C($:fL`7I/3X3l\iONraY%d$a(9LW[`[%Q,/tG +Wd705"fa%#Wb-0So'X-Y:/=ZX4*Rj>]=W/L5D[.W_"FEe@Y^2lU?B)$=QqG0W0l0hN:cgWX?>;;c?V-c^q7&Pqrh\"g/XFW[`[%Q,/tGWd705"fa%SW6/LKY]+.5 +6WJiEW\Tr?7TJnJW^'Pf$WS(g$5SYgT<)p/!Q,0P0iQ0#oWX<07 +AMC$@Wnrk;JZ9%mW\TqV/0*@<:fS[?WXS$S;:Rak.Ss-]6<+5rJqYEg+0$fD +]d'KX<>@&aAM>W:33r(JW^9ff)9aP)Wco^gTW3TtWXNJC$V**=<)j4).YB`m<:u9I$<1$0:mJku:ad%K +IL$O[W^9ff6Q+*V<=K+3]d'KX<>@&aAM>W2m.Ss+gXJu]kPYosmOt':._*V-0O!-\dDI45ZIuf +.T"YWOt':._*Z[4!!!!a+S+C7zzzzzzzzzzzz!._XT9hc',%ZZL,jS_=fFSYK=_Kn%!3U+i>X&lLerBR +)43]_T`oP+&Lo6qeoE`G@"jHI4u"]3V=o^p+\(GB%'i-pg_@f`UO#/JKQ2tM=qHhQfo4*U+_qpqiO_dA +iRh7.I"Za98UZ"&&DO;Nq9NP58\bO+]aft"\=nR?_$jSba'2_d&GWm:F_`f1r5%,fb6p$:ecS!WlELr= +lK$g)i-qa)t)#8O\bLC\TOF_*;>]=U<,puB"/;:s0a3AY:pRl5-+qk413a,V1Z!O-%PMUp*cGHnYBqS7 +XamRtapkKgd+A]'63/Ue,5\oQnilfmsqR(__LlZ6E]*'\o-SZBZG_hCFnrU&j`,g#q'Kl,SQD(aka^ju +=Td*RmOX4(qJ]H:*8go"3I)1]Qi`Fkfkk$i5c^AWZsm`)m]=25"F#IC5dj5[Udh/],e4$#Ft:SQ*Q)*d +mWpG\Fsr8EDQk5EZDp@d6Z]8Qt**cqM"NN;66HZ%NBAM&?>0>-ekg9k^S^NITH4etke-$6m"J*t^9l\%B2A%5pK?=[FVdo8O",6M;c@c#cJ?$PBCV;erdNIes"`oZ[;4CLr93P8AMA +Ji5*#ORjIKgIJ``GlnLomp?gW&)L:M:GMFhgb[-6gNZL3$`-q2*hVuPHCKijnciA:3hn=BGpflA!9kX +`Po3B15X&a)jZGh5QAMAJ9CY,`7cHa'E76JT1a5*Z?UIUC-rBOi#B$HcWSpA=mXh5`HnCF^Gk<>XVJ,A +)Ln%#d6F:tO#r:.hq:HWXV7-T^&kKeY>Puh/_(o$(\M#1G!n,@?>0T5;R]@XGRF660Q%jV?sh7511gpH +D2k]l^D2tMJX1$J)pJ,]9,a2Z+9be@oK\8h?8jY+=>;Ytl*4[&_`ct3[p%(K*,6UO6/>[=dSRG2l=[r: +G6(d'j%l4dTgpu;#4gpqKUrTdhjq9OOSEo]bm=4]*SnV^F3JF$s8]u]+0NOa?+k#O[)LbY8ccCR2b:/k +Pj:M;EF1B.E\h@c+j3M6F;W6YIIP&XDLV +6Op9Ku!7Rfl$gY:O#np*H]JA(sYlTb=+&)HF!;tk.`[VbHf\aC7M04)m"TuCX.d\Z9\XipT=K^/@&j4T +J6.(taUb^=^/eQ3P<=>2TiQ1kB;JQp3,hd1O$mToR4of'Y]:!4SFp+:`i?NF`In-,[B$td9Nqtj[F/R, +[ErBMRcc;/Y)QMjlFnRW!Fqf\KGQ3<:$P2)R +6o@di0eoB+;=^YlZ"An:4FfMRodhVR\7LsGNfKl6G?`MHp]\?DJ!0j.gf]691+^$JU>q7l[\Hc9 +4/a2d$!eJA2*d-Q`bhL5.Sl07GRkK\3oGF.`11l9'8M]6^)l<(?&8_MFCcb?Ri%s3G +$>/*Ib`0J%O_L=qo9ldiUf21#d@G-3H$["t@>d#']%aFd@\Ttl:PK(V^Z8\L-^>ETSIh[ +8;(sK_(^RO#h>'t6n\*j%ZeE4=5Za6to9=erm1A@&)hN'&hqtKQ'4l)GJGs@C8\A,%%Dr+a3r0Js;o#W +8OjRPj=VP_Y14j-e/dPN[50fV/6>N3L`2aW7RL3OK`UZq%-bEjlkni\+G`aiSErrrf1zzz!!"-3rso[G +'$U~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 458.4 36.36] CT +[1 0 0 1 0 0] CT +N +-955 -75.75 M +-955 310.5 L +238.75 310.5 L +238.75 -75.75 L +cp +clip +GS +0 0 translate +239 311 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 311 0 0] + /Height 311 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0VH\bAq+33nY8Wk>FIn9F5X@R)1q.&0djA4C%UeR>SZpf"J?/cqT;0(?>KTHJ5?]pRQC&_!^M[bN] +-J'Meg\forIa`[Wf,-U@niF+KO/1HMNoS@H4Iu;89d5SY"KmR-ag2)R8%&"s4PAd`'K ++D)!jf'8b0r&[o5G?#S_Bo,5&i0l]n.SF<`Fs%&CX-thhRtRL^(e?:QBmiheaKXj?>F?BM\e&;Cln-"9$G8A +1M9JG+"N9g2RPh`kc4eZ2d3NGm[d\Kk[P +'6D:7]P,ck9mum1)*`R41$?s[^":iT_Qs+4cTb^J_(K6so]];enHB:9Uqb]uHhYUD,CB+KeZW>pKaS]/ +:J,Q^]K']SU^/F#<`W7m4F&]qI-/Y@>ISL0(Qhj*0OoaWP:'_OHoZORrgh)AkKfc=Cht(NE+#cLWiCq* +I@'-\eZ2cVc1^PZirq1#nTW!#r:of,j*UOgNRo+-Cl$\Yf<2f+iBhhp11J1Xp[@"[Wc-e/%3@WVlI;df +3Jk.bkK]&=Y@#&9b*j0fm9XXHD>Y-rf[H`o;u`FFkLk,s2Jh$Mpp9K$jQP!dnN)Pe^TmB7Lb&(P%j+\6 +WrCa^^38mI;o/HfQt(Gim/IP;5.kFJP.4%P[c)B"=>sgY1@:1Q[M20?3<+3PDGfUE_Cn3AIEm +9f"Q*o'\\!)a8Xolnc=)P)`O^Xj2!"$]MXcZX7bGp%9'7P3:b]oJa^YoLc +I?bBs3?J3j:_IKMjHZj-nRnra,V1.--r2JO6^c/X5e>DF)tSTZbO$_*EH0?V$`,@s3?J3j:_IKMjHZj +0RNN[fH@>kEA&+'F`=8MWpZEc7_QL2na1IHp-9s9Fk@ZHSB")"NVoB+?Y4)Q7ge/[Iib7X'L/f3$ZcL?cp.TdRs9@-"[iDi?skW;7M:O:guoQ&q30()21`Y#pj0t0&\1BQr1AH +T2;+:LYni,V0G*+e=qetJ-ljo"YhM=ZNW'6&@2Np.hK#j0e3gA"YhM=ZNW'6&@2Np.hK#j0e3gA"YhM= +ZNW'6&@2Np.hK#j0e3gA"YhM=ZNW'6&@2Np.hK#j0e5eec]"KqX/g:`6M^.8T,BlB`0FJUQn=+sJXA$F +=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2ql +Lfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r +/VmP\Qn=+sJXA$F=b5`l>O[%&DW(?7aje7o=b)kkLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+s +JXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F +=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\k;-?3I-,>)q96t1 +`0FJUQn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\ +Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+s +JXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:aNEbnVnS[8nj2ofhQ!&X)/VmP\Qn=+sJXA$F=b2ql +Lfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r +/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\ +Qn=+sJ`egnn9jA9i;(U=eARVTJ=%pE=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F +=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2ql +Lfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo;l1L'?rk&0,QbfSAQQ!&X)/VmP\ +Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+s +JXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F +=b2qlLfo:r/VmP\Qn=+sJ`egnn9jA9i;(U=eARVTJ=%pE=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r +/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\Qn=+sJXA$F=b2qlLfo:r/VmP\ +Qn@UhleR?C!thjC_lgeR=to:MN2d'!Y/$u>0^K.*WWg;C^o1EjljA]O"iILYW*1nA$B1tg_lgeR=to:M +^H8I1HpB;l,l2-Tzzzr*^[2Ht[5.H2mlWq`oI`qtKQoIf2TnWi2kPhj +5p!p?p`upHb(RB@!/L;GVOR(^4#lJNujkk:NZ3kcY&=Stc-=KfWg>>Dat/Cq_=Yt)GZ86(')hUqA*QS7feHjEE[>@[_q;5(f<&7i36IgC`] +lX&(GB*b=`WfWW>KnmFN)=X3W8Ia8S;s?=]lVd.upCjal6ebL:XOjmbkp6ldr>DY-+?N@n(Xupg(gS'_ +g>Sp%8tG:0b,;9m_6aZt[uiY?pT[W%sYPF50JGc*7!BrHlbV\Mks,:<_tW]pQQG2FoLC^*Q0=eCN1l3, +g#3jbXWu@[s&QH"&n3EgIG\Lmd"l7>ip.nuXp7jia"24SeF$];ZmY]5clND;;YKI8K%-F3NkjR`%XiUS +Hl#X]mY?2;)iA<8P<8[p[%(oT*-bK!An1QC)Br&$!9bN]HIZZR>A)lkj\jS?3H7HfN*T17!gVNBnn$!! +!"l8H/eDbXls~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 0 -0.12] CT +[1 0 0 1 0 0] CT +N +0 0.25 M +0 386.5 L +1193.75 386.5 L +1193.75 0.25 L +cp +clip +GS +0 0 translate +955 76 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 955 + /ImageType 1 + /DataSource Data + /ImageMatrix [955 0 0 76 0 0] + /Height 76 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0W?UtlH*6.MVOV%%LN^S+8LVQ5,7-[+6$`P7:9U7*D,SgtHJjc=7YIY"%Ul1$]"Q;mL6kg@[&s>P( +@8IY+ajTbKo>bKeQ\T#)?!@C2zzzzzzzzzzzz!!!"+8Yo +>,A?siX!<<*"F$4d;?sA@^-ra2He^`1bNCGenleK$lC?*dle'?EE/GA/HP?^bi7Vcf*Z"(h_EfU2#!3h +A[R&d9g_uFLjDc\g%ZEdBQ0/#!Yq!k,^IAL$)p[@"?NH]SjB3i)+qYU0?*\#;5!!)NH'P:?G2p>'o;J4 +:F;2\U]>'0-^R7scbXJd_Oa-2^NC?+Q43IRm6jlPTf-Vldidj`K@!!)MMX"Z&2^3jp%>RsOepRPCH@Kc'jj!8_`2k"hU5*B8"'/aDZfF65Hk1_1'+\msaiq#:6he]aGL)>1A4UdT@WoSk[d2hs^C[41 +9QH6pkL-"B;NcFZ/^Q2:@RT0Ih:A#cT1eP,FibUs5Y!!!#33JH.s28\J3"ec:go('()[^*35Wit]^)ci +SuQr(\"\QrDmb\Gu0q0@0u,*>F2WOVH7>fc?g/@>TJ-HJ!5Mgi_RsO-So?Z:lddZ^mUa +p5e!m@1%8cZHGkJSMYKs3$%1Nc5041<=RG%'_G_Hsr6?_Op1,UqSCG0s1QiR0ei6D.kr`gLOC8'ck<)b +iZP$VDdQ84.]quCeQGJkicuW(1*C"mOiRGXP: +jT_@-DE!,i#VB'&gXj(dZRqtJo,WDr0PiPTE-g5,>@F:AZgR2^@b#VNG;GBJ&=K/XKMn(hP\`FEL4'P7 +=F!-g$,0WRfN;,Io4Ka%_c-71&\5CVD?f][_QZ89;lZ0CE5B!k2&iS1h[n(=n?['V[Uf?2@acT?=qX3U +Y@q=D"QU76@NRB(SVb_<8!k7*bS +S#'$4CIGB[1kaYbjj$8VY^!45s:?<22*rV,m2-'QI&Y@"=2L&?&6b0#UAfibd_i9gRFzzzzzz#_Lk4!! +%NqMH-%%ZH4GO\-`r#puH__D1g],SDR"+nuVJ9!BgG>7.]BWS2r'[3JQUUaj36<%6$(7Rfk)I0 +`#)WY4YjeX"'g=/r\O^9LtGc/AZuqlT_0p_6-`dbX"^ug(C:e;O(WVWYB%O-Ce6=+]ShlV+P/+1/cY_80s@t"; +=\00M=+Ybk_jL9!BgG$?M;kWcgc[JQ*q_O=GreJdH)@In3Rk?)^_hK8`d;,>niD.`$d;.EiDu34&TOWY +4YjQ,4MOUoGGt8g%+?-DX7BQ=.RtocI(s?rs?BjrbmKm>+^CWCeif<=6&8'@*]ZOK&Gq;Pc&P)6%@@U_ +63uJdJDSQmJ,=B)RKa-.nJ4KfR4Fk8<=*iF8mr2b;Updu-'5,0'2kY\9/,>Kq@BPtYU`]\F-)NaG!mg2<$fV^]"5I62`DP2`U]%b0MC@&,( +W]>fTdq?3QO`k4!KqTWY0t_*?#irXf^Em/fY@Jf4GAr"PtdE86(7IWD]+9N)[20;@0-K5pFk,d8AGF+$ +Fq78u3:=(60G!HK)jLO7^,Z=$sm6,mo[/4rmHsB\2V5:"nj!i1bGeZcl<=*iF8mr2b;U+g+hj +Kq%U;+/]'<)a+<@qfqBC"jJDVVblk09C;aiUEWVMc6DHAnaU9AkG.!i\er.ocptO9I#^bnf6Ps'FHgNJ +T)LP:hK?K=h08daI^ZlW9.`]CUkI+sYa9cHa^E++b#cWW]q3V?)^_hK?WCUZZbB''P"Q"hnCb.8]sN%>EJ-BHh +$*L._rBsZfs9lSitichk+[!$F9l!5M5?lWY4YjQ,4MOL8;E"h0;j%=AA)M$>2o*5!u=_[&:LF\>Tc(q" +V?\kJrW*qtBCr*$!21$ADUamhZ;+.`&8e.Ek(YXAh,8AA-eYD]dh8!T#A6W"MX$JjcWP]tM]Sbc+QVBk +aQEVl.8Crq#=!\].R8-1HAG5cPI`8sR75A6Y74joo9I%67KE(@B"bnNrL+WY-RT9dC?QY$>sr)S;iBjk +[Om*oe]n&pV/^+B8_kV+P/+18.[T?U2ojNJh#"F5_g&JQ*r:V>BN0Y7D^=G^lEWK>K0jpPT/PQ!d[n'] +pOeQ)_iYCf*.:MAN8q;O(WVWYB%O-Ce6=+]ShlV+P/+Z9Lo<]d.B0a;/pYXE^F2+B8^e;Z.-ZZhqu~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 458.4 -0.12] CT +[1 0 0 1 0 0] CT +N +-955 0.25 M +-955 386.5 L +238.75 386.5 L +238.75 0.25 L +cp +clip +GS +0 0 translate +239 76 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 76 0 0] + /Height 76 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0R!K"\o'L]d;3=g6G>EMrD4UlrpYGC@U9Ue6HfgH:5F0]bR$!WLcHX@"YhCC]HH?iQl!]2&G*ch +R#f.5i1A7rrXAP5X"cg[c@+r6g"kf/lu$mYR?R6e]JtBs')lJoLcHX@"YhCC]HH?iQl!]2&G(L@'4P:X +)Y61%Nn`^~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 0 187.2] CT +1 GC +N +0 0 955 310 re +f +GR +GS +[0.48 0 0 0.48 0 224.64] CT +[1 0 0 1 0 0] CT +N +0 -78 M +0 309.5 L +1193.75 309.5 L +1193.75 -78 L +cp +clip +GS +0 0 translate +955 310 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 955 + /ImageType 1 + /DataSource Data + /ImageMatrix [955 0 0 310 0 0] + /Height 310 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlSlTE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz! +8q],& + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 458.4 224.64] CT +[1 0 0 1 0 0] CT +N +-955 -78 M +-955 309.5 L +238.75 309.5 L +238.75 -78 L +cp +clip +GS +0 0 translate +239 310 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 310 0 0] + /Height 310 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlV]TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzp_ +u9P$uu~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 0 187.2] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 387.5 L +1193.75 387.5 L +1193.75 0 L +cp +clip +GS +0 0 translate +955 78 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 955 + /ImageType 1 + /DataSource Data + /ImageMatrix [955 0 0 78 0 0] + /Height 78 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;JH,ZM!5fq/l + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 458.4 187.2] CT +[1 0 0 1 0 0] CT +N +-955 0 M +-955 387.5 L +238.75 387.5 L +238.75 0 L +cp +clip +GS +0 0 translate +239 78 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 78 0 0] + /Height 78 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;!=]#/!5bE.WG`:P'EA+5zzzzzzzzzzzz!!'fe!EZk263~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 0 187.2] CT +N +0 0 M +0 310 L +955 310 L +955 0 L +cp +clip +0.941 GC +N +0 0 955 311 re +f +GR +GS +[0.6 0 0 0.6 0 187.2] CT +N +0 0 M +0 310 L +955 310 L +955 0 L +cp +clip +1 GC +N +0 0 955 311 re +f +GR +GS +[0.6 0 0 0.6 0 187.2] CT +N +0 0 M +0 310 L +955 310 L +955 0 L +cp +clip +1 GC +N +0 0 955 311 re +f +GR +GS +[0.48 0 0 0.48 0 224.16] CT +[1 0 0 1 0 0] CT +N +0 -77 M +0 310.5 L +1193.75 310.5 L +1193.75 -77 L +cp +clip +GS +0 0 translate +955 311 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 955 + /ImageType 1 + /DataSource Data + /ImageMatrix [955 0 0 311 0 0] + /Height 311 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0W?\h_F]t!TRe!kFE9eObW0HuC5:b76pKO+dK0H^[q&dAqF`'R#"(Eo$i,18ek)&*0!-QrVG#neGU +'T!DjYbVjC$)o*Q3JNV<@RQ>eAH,ukr&3#lfmEFbpK?gohXu8Xi+sdPGi#jZrpE"WG,J8kp$:5]n]r!= +?iTt(h4)bFs80R%s7r;4J,S!i?g5T&7pT.A=I%763]jsr?G10qer\ZgZSO&HWe:XX*LI0%^ADg(S'WFu +9ZnHW19=+3@b$;Zh(h((I%7Dj_5`0bd*!FmFV'!+]-=`qfP;)Eh#C3CpM=HsGkWWP%#_TKkWl3LfuJlN,X?*+1EjWX7Q0,HdoIbsPq\l21\98S +=0j\3_5`.oTfiY@_EFJlN*hW]DgI,-5TG'>>)r/WZPn0,kojU9M2N=+[T06AjV09%3jgGBN?E]PqZrQ0/PTrpXSV(9!Bcg +6<+8&6A1V`+RdLu<[Ck50Lf&Tju']QAnP"n<='8;3\V3kXDA#b0/dTGJlN-;"Vhl6g['#q*>#FZ(Z^7(Ta$!&??W9V/lLp42X,+^Y3CgFPdA@8rta/Xe!X#`&?b'c-/P7jrhLeuWQR1Ne< +COt?i\$dd/WeAKp3]!u#^7(Ta$!&??W9V/lLp428U[R3s=dY3/?Sba +?F?JAorLc9Wj[:eG$iM>U]d_2,#i\m-:Cs=<%W=L`E00q<=)p\2UBV8X4`o*?r]OHWXd7+#V4)tlRog9 +WcbQr!Nk)0%lA95c-E*fWtHUUF^QOa=BS1S:N.%R[741CcrJhGTfMktlqC$U.Nq,Y#A-;UQ%d_4H)lOt +f#XkE$ECORAp.P+cD1TD&gC:t?m\9D=[KgrdA9mGQW4@B<,LC6m(SpZ8I8ED7&]Cd9SfpYg!tQ?>\)C= +=d;fdeQ.*kM>M%2-7)cZ&>?*+1EjWXk#M;cgaTLC"BHgJbf,k'e5m*AKC3CpM=HsGkWWP%#_TGV%g9fWa +U1uqo-.Gr&m$ZOT2*7!7X@e:FeUa,"@:^f#n8_M4<"6pKKGpm,4>XUQAnP"n<='8;3\V3kXR%3AhWHf1 +C.qYSe6=fgUYRKV=0j\3_5`.oO]drGHds4d$pf94CeN<='8;3\V3kXR&IrEQ?eCWf:Cd6Cb'l?T&foS>sO^.D`$;nZ#p1If8]j +]=GAdJXOldj/!@:Ei3VOS&21Y:fSb?@)>H$<@rhp$!&@2;>&5*44D[-B?m"bn3*7"DdNI9/mc3Cn!b>b +#n8q%RPHI=)HF12X@e:L[>^M6>1E\AP[IM.W)[ck\1ocqP=F=."7m$fr/eYOaH7^>/jhEg9k_c^mtBPID^RAGo6j!6;ro2B&/5#V/!>= +Pn:9:K,u&:.V@4#1F^/?K]/ug]6A2ZeueDSpKm^@i.3o5e^N!r_f(/01SGE$9=(MW:.)$>N`?B?X#B2? +=0%3][F%Z?YUX(WB:'c(HIR4$3=d0u%im^*mp._#7*C##NgpqLtoCM4iD;2LIs8D]j^46)bAnPc6eVMZ6Pe&e^OP/;? +eueg`jdkPBD?$bcdfp+b[@sZoLg7@FiLb!]IoQ0n%2-3d6^a0H +U]d_2Z4G182djkSc1PtbF6CiueC:a5a85ag%a9TVa%OmZj\Ems"gBJM.92ip1H2.FK:%m2.BF8P[up[@#.pD5kE'*94.9tpgH-Y1a/=I%7+WXYDb)cX3o9M2N= ++j7Y`5saf:$V?*+1SMgR/Tk7b`&M)G@oYkEX2^ZtRpIrpP7jrhLeuWQR8Dqd2W^+%@u,*: +PfKeW!icGeP8$hN)Ntf88r-l +NgK<=Pu)kY>%ZpVX&dQB"KN.Z<-;Rq5V!f7C8c93E4hFUWe<90XaXl"6e.'^P[IKXKW5O+"CbqHGZfu: ++ri8tYpuFn<@`M(hib!>1+C&>KEtQuQjMGIenMZ.j*3#6<=/&l>326lg/GC7-7)cZ&>?*+1El503\>PE +3*sa;4.5d]TgI:KXOm_AnGpbeI%\.?r]OHWXd7+N%NWr1NR?4E_K*0.Nq,Y#A1i+/)0V*.-W+r +nPUF/'&$TUS!i#9'k1'm<='8;3\V3o=]mD9d8,GUV*%d)[(Im\OMBmW#pps#Pn9Xh"#FBPQ$$7O+N!YH +*ifpT9"_.IWnEf)?r]OHWXd7+nQ+4TH*@Rp96mU2Y\FE1RB;pK8I8ED7&]Cd9Gh8NSX.kAiHQf4<=)^n +au_C`2*7!7X@e:FeUa,B`le,Y-#8BW]TgI:"KV6,4L80J4-L;Y8r-?*+1SN^K3\=,O_XUMFWtMMFVD6qqB%?6A9!Bcg6<+8&_Q#-PZok#fa%L]Z9!IS77\,sLR[m"V<[C/4 +lG-(q\[#O^H#aLWQh"7D@+?E[1c&>n4-L;Y8r-?*+ +1L]Oj3\BM-iHQf4<=)\HacJ0k=Z&:)'!+]]:t:,bcs'YNjbtB'0BKGg_5a7Kk!qP8R[m"V<[C/4lG-*W +Y,p)m?4i3anlV/beM4-c1Ku^uP7jrhTW;D6If8]j]7[l=JXOkj=[/Q)0@)rfWtMKpT#!4h]u]m#Z`6RF_h/OBG+OBn +<[CjjC]iP9QHlORDd@)4;$g8L&60M^(?XcA2K%<[CY(0Dk$"Porjm5:3A"n,=bpHcJlO2GDe;c-Tm\g8h'%!Yr&'T[NcHa/)+jA5\Z1=G&h3S`&+4\&I-.onXGMS`b+KH-VRROuTlF(R0Y'\V) +iJpO7.UcK1\d%<0s)'poA4Qm0+!^&QQ!r3J]\F(@*L1#4!a=-*\M?q'eaP+XYU[Jh)*'KogeeAY,rdTF +_%.rnL1_Z]<=)^NbF'7-N_6N*_1B,sX.IGHr"6cO&Ab@LX(LPd&d3DXJlN*ebY?^XGn2R4:[fo'YU[Jh +fr]RKHY;II\YBe=8oS0UZiR?CHFsfj9!Be]We=A:6.MBK'(2\$WtHUUF^Q9:i"%5mYd3Aq.`&+fWtJ<1 +J&46"G>s/o#na0u0TTYePBMVE/WWm<<[Ck5d&lT2WFk4O9!Bcg6<+9Q;%<+27td-ZO&ZKe-!6GZX6N,0 +EcFSq=HsGkWWVi`L3u9@_TJ1bWW]@8X@cSueX8E*G>s/o#na0u0TTbc9,g<%g%&71?r_eY$-T>01Jc:: +Q!dTYKW5O+_]/UQ*+(k]99gXX@f]HTjLf4k-;Il'!+]] +:t:,BYjkK-&QZ>&<[Ck5?rb'oWm8iKECV`jjfp;OWW]@8eu\.jk!nHm9!Bcg6<+9Q`fOgq/!X@e:FeU`!G +'40NO_TJ1bWW]@8X@a>8W\a89geeAY,t+]s^qA+VkM$7m>99gXX@f]H@JHjOTZN;N;$g8L7&]Cd]M+W( +-R,X.H)sWB.`&-'\<8r- +ROmKZ9!Bcg6IjWsbilAB&QZ>&<[Ck5?rb))lFIP +_TJ1bWW]@8X@hEN[e9etgeeAY,t+\8r4lR\ZNh(C[QIS:=I!8o!`ue;(X6nh-!6EDTk`6_F'YuW79J76 +=I!8oJlN+jeTT6^m\g8h&gC:,G[R]EW^.4t[QIS:=I!8o!aW3f1UB.m_5`.oW'UgPpgiUJlN*hWYRBEa-i5T0ik_F<[Ck5?r]Pd40=2g%&71?r_eY$+3_aHY.Fk-!6EDTkXT1F20;=7Te@7=I!8oJlN,"<@rH-G"3i\ +Pn9X(dg,$&Vm6RY>99gXX@f]HTuO)5T9dU9*L1#46A2@u*ggG4bFKJ#>99gXX@f]HU#)fshY*ifnt +<,Lj7*;kuj&QZ>&<[Ck5?r]OTWkn.P7M6t\@B<(W:pl,^F8X)R&QZ>&<[Ck5?r]OTWki'"*(c6fKs<*N +6Ij'bbjhUm:5kGiO&ZKe-!6EDVeRqBF.B$PYps23Wf)dnQS)RTHhVEtD.qM9gk][Tj71!j.`&+fWtIa! +/RrB&Q*_B/-&bgr`/,-H2JcLqe=JgMmbbe:mlNIHhRrhP?+bEeh`!K-?uF>V0Ki_J<[Ck5?r]P#WWgVj +d?9g3WeB?3Sj%Q`9t'Zbo1tr?\T[Aobfn;IK*PKVc6%N1+arO9,=aq#,2Lo?Df3_5goOG<`s]_`"KN0: +8dJP,5u6OB.U^[+=HtRfeJDP:@GeeI]e;VKo[>Y\hR[iFj`d:VF!gk5J-gLh7L[McR[-#V0+=loX@f]H ++_K9%]MWWJ0p=Md<=)#nIJik[)J`-?4P@>X@::>8o$KrLXo.=l\[gthl/B)prkR=!Bt<9o_QYN+WW]@8 +_H(OAbT&NTUKNj9ACV&(/u5cGm+J^7jR5o<9k-?IFaK"FKSP*I0)Om)M\7NjL_hSc+r9!D$\#3C*q!mD/s-fRP:LA"o[dEt\ +^[Lo`Y@#K>m-M@Wfs^;*/#VKOl[G:nrM%<6>#Ta;;YMLPaJoBD'!+\2?F>Xa9`OS/UIPOtbl.O>Fq&lDhXLUn_lWnLB^Q.:f\kN=nU4>9>eLjA#12-G3n,$ +^YbZ<*LNTYNraF[]6E`Aq=Dc^Oc]k1Ib17Y +6lhX64Y:k??5Q]h=I!8o66iKgCM%HPd`/OA@JHiaGO@S4i'?bSI[?>c^&__]DQ\3,SND%mVP]@o44`k= +%QH.$rQ:EHNu*ON$!&?SQ-bbq%@W]SP-eAn8f59WpOc,qJ,fHp:S(h)H?Eh3VDg_H]Qiu)_1TGq/aqT3 +J'4-0h=kjC\8``fg=s)T+7QOcd0A_;SSAAuGTg1S?r_eY#nkcE`q\sId0f:i=rQ\JOIJ*=$gB7H/:]kbVdrNLhKjdu5<=)\P1ok@9hH8F3UeP8t_PgHN +(Dj8[\ME+-igtjXL!,f95Bu[*c0pTI0GcMsGGDN`2)p+Pn9X(OF_\#[[_'B'4YUs@o\+\$!&?/ZteZK[tZ4=cDlO'i)jCM6XAJYq!Si"KN0(>;bckgt\]f=d9PlC:s^jOje=u`laUf +WW]@8X@d/JeX/.6UQ^FD1^P0nC3RtKU"-M +<=)\P=Hu]JeS%_l'p(6pWtHUUX^tlmHWojU=P<7IQ!dUD<=*59%J<3/16P+:*PqA%s$!&?SPu(B/+>\(18`R$)+[X_:#Nd.A$!N"I/WWm< +<[Ck5:fu6RcQ*ad1^L,p,#k[b?uF)ngki;Ajfp;OWW]@8$EG*(h2-h3%Do,u#ZWAoR+jDKG@IXiH)sWB +.`&-(i.mO&ZKe-!6F/ACZ!=js$#?cDlO'<@\oRCOZn$]a-,m*ifpT +9!Be=e>bC_7@'CL?0E!&Pb#06<[C/4aplRsSX)>l$dJ= +DQ;ei+]]mWW&i&9m'PPDKU"-M<=)\P=I%8(Wl2Lk>FlO<&<[Ck5?r_eYQc_'>S!7;\6A2?`%Er.! +Gt8NJ[QIS:=I!8oJlS/*HtG8c_5`.onfkG^E&QZ>&<[Ck5?r_eYf/2b'*1<%!@_5[X='!+-Q +O_/3h'!+]]:j(<>fafL!:kY)cO&ZKe-!6F?eKGAd1RjV:+ud%<.pF'q'!+^0.`&.&)tI,b +P7jrhLer6I_!JFu7>-pXO&ZKe-!6F?e_pu5^.OS%X@e:FFm6^.[%'dBPqA%s$!&?SQ!i.)$o9]/P[IKX +KW;_:fafLQ.)O,ma/T9C'!+^0lDW:(R8$;X.Nq./m_J1#1%L4+ZK8>@_5[X='!+-K_0>;o-!6GJmFnt9R@/[4%hAC6TDe-VS +fDX=-4N4G*GC:e@?r_eY$!&?S2&Dltp/f^m:%$H+9;B3Ij-aP/f6p#BDoTl>'0F%1"KN0:9!E&"koS`+ +gK*o`>CR5b-eJ;/^Jh%*/\>TYNr^l^qe0eWjGBF8`1('!+\JWcgV:jSei1J+D[BeZ2baAnI@ScRV"0'0KS,<[Ck5?r_eYZSO&HWW]9cn`.Z: ++-!sXn(tl&NU=MTn9?*YQ!dUD<=)^NcD1TD'"Fs"Mi1Z>>T#XRG<%>j4C/:o-!6F?&<[Ck5?r_eYZSO&H +We:XX*LI-F&<[Ck5?r_eYZSO&HWe:XX*LI-F&<[Ck5?r_eYZSO&HWe:XX*LI-F +b*YU[Jh +"KN0:R[m"V<[C/4)IXT-@o\+\$!&?SQ!i//9M2N=+[X`POsEUs6e"7\99LPlOsEV^,Y=.E8Wk>jOsEV^ +,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8WlQO\@?eJd\XR"n(,/q"hK0]\m[Bu=BJ,klHPeWle[_t +gqS@=il-i?^NFHcJPt%%^A=ktXcWC*o&RnOhgG%gf3bH5e@dH^+Pd(VqsV;'CBI>%33co0L@n@0fsA^\ +c&D)G\MHB3IHJbA\i6Df%j+"5m;IJ92)Wq?=.ap7flZ0%]hsd`q!mBDFoD>akg1L!!-oSEE+%_GNHK/. ++Z=8q]`(-l#C:N2<3r,ZIc<"-RdJ9O^KeOBf3a$@mS.K0UIUC=#(W%HHE$bG3?9[8 +T:V[I:Cf%\?+ZD_Q\,MRm%=T.H+BXF%Ptm*__'h5$)Q4o4]h+4Ef(bEa`o +,W^dHnWX!;m^Z6V:I"fbmS.K*^]!P<.HAGjJ"-^n1gE3+R]nU3B6kX/EDj+KBF^RVm+bEPmM?n%A6en!7J(Nht%817Q7lhgV'7 +O1fo73\Y3/:8I-9G='U=Puh;F]mFtlbM0LEDr&"T-g`_dm^qpcdQdZg%s;e]j/!E'H9g*Z1-H7AB7h\k +SGDsMj7G!r4F+5V9,^IO/K]E5;.\KYUjMk(V.8T"pYJQXEF@)Orr)_dIJ-f)q=JPr_d7)iFP,%ZdNSYK +_1UU2WFm-C*LJ4@)SZ.?bAY)e<]Zd40P<+!2`El_?2%Baj3aVlknNuTJ,H)0%4Tu%4aVYRb?q,LX6pF2 +]`%a%V_`)Vb7?i80^ZPH7fqCu$Q%7+GkULWV)N;G[->gohlLW5MNijWF=ui@SX^^f+Wl+$6#-;YQXA=W ++XK\.?$]&)7_:6V[f#g%J$"'=8oX.LZ![Ip]Hq9DnRTDFaf^Pe'rTTsSr9%^bIC="I[bq#F2cX`\G;Y`#aZnTk*^4t] +b0;?%"#K#\Pq-Q=p&4TpFRM8S*BSH"^4!W]c"Xhk=0Hd;On'Yo]$mbN +kN/0c%q<'>FD8 +bN\9U='g16iPUFnDbD8%Nr&P@j0-5s3`Y"IFfR=i,T]*po\=N6rT,\^l$hm4S4bo*?FtB_pZ9Yh2q-IQ +kg?._DGm6Xp=X(-i6*dggmaBY?G*f7?()[9HG#bWSiV"omL:V`l`\'pm[MWr?t!L&`f1qLGOJ:fQ`HXE +]0@J)>;A/Jbh7F8aX:g#fXl@2dk]nMh7HTa;sAj\h&FdMJ,J=KJ,]&3Vt92aVqun"m0t!mUu-Rkbr9c` +>%r0HfWfr+rjoS5WBU@[oBp/pQJUg]B"@j=pV5UuH1U%T@bhu$Ji"W(qsh6&%j%Pp:L&be>`G +Cu)#Q:S0haoZ"";\%8>HnV^cP_@pW9h$8/Ih@B)A?iR^s_E2u04E04Dmn5;aQ^7eq7d8<3MRiB%Egk@G +4*QurRd[lW^.Ys-hG0^u/1rP-/FgO]+)K`B1&],TRO6FQmcNZoHFK]`GA:kB4c$7\X.&J0B:iK+La,'+ +p+fcRI/EePH+AnGZ>r2^2b0^"T'\TDpUs8;K3 +XpO"a\LNRj*Ud4@CcQ_->j(@p?Ki&D`GZ/8T'p+5AcMc.Bj^8ALTnCoDVr1aX#`r6j,ZE"pJC*?7s[Fe +*e:p"lDnV'=F-N0NT]b[s19(eat"M3h=iUI5IkUf^3uJ0Db^g:.c--Ea,fsY)LLr0]q0^/Ea[2Se>ZBI +^!+k[)u%X[t+X&0'U)!mAmqH`_FpQ5FjjG[!thH:Nr#:pu74rO\";4<.^;]:Ss`J +@7]2n;N>j#FnkIbhVnM4o?VpZeQ9.pal;=>Pq,oUQ)/YMr:ofY9:,QI>fE%aONWtDq^cDM:S'\ZIf4SX +T)g*pV`V!V)Q4oQOsEV^,Y=.E8Wk>jP,'#p5:N-Y)Z~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 458.4 224.16] CT +[1 0 0 1 0 0] CT +N +-955 -77 M +-955 310.5 L +238.75 310.5 L +238.75 -77 L +cp +clip +GS +0 0 translate +239 311 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 311 0 0] + /Height 311 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0T_1u%j+33pNR\;"TCqc<+m5%qQ*4_5'ZmdFqdB6J;RS@N/0smlj,dh>@M^7gEM5X.3OcmrPGC50# +VOoVU?G2ftGW81e\7Rq]o=XgFcJ3mH=9fWp>Zd&*_dDBkq/).ONW&Yp\n0'N5Q=(Wq0RR[XdId8rd7'4 +=!_IUVl/9BfS%1J+m&n^=,8k&bS=S^&9EPm'?"-!jodD?LcIcF'k0oLF+otp`*=JJ">Nu63C1k(@SRJU +KpWOl>Tr540is/k6-L'Q:(VK#QkRDC+m&n^=,8k&bS=S^&9EPm'?"-!jodD?LcIcF'k0oLF+otp`*=JJ +">Nu63C1k(@SRJUKpWOl>Tr540is/k6-L'Q:(VK#QkRDC+m&n^=,8k&bS=S^&9EPm'?"-!jodD?LcIcF +'k0oLF+otp`*=JJ">Nu63C1k(@SRJUKpWOl>Tr540is/k6-L'Q:(VK#QkRDC+m&n^=,8k&bS=S^=Dc9g +Za8,^g!nMNHO1Y;BJ^Y)S^>Q5?^UQ4*$FAN0dhdf6HfaFXq5Z+Qn-+F+Qa"c-]#<"bR%a]&9EGj/&[r# +jpEgjLq,jr$"C%KF+Tc0`1.t4$8Eoa\O+LH@]g8`Js\(,S06r$0dhdf6HfaFXq5Z+Qn-+F+Qa"c-]#<" +bR%a]&9EGj/&[r#jpEgjLq,jr$"C%KF+Tc0`1.t4$8Eoa\O+LH@]g8`Js\(,S06r$0dhdf6HfaFXq5Z+ +Qn-+F+Qa"c-]#<"bR%a]&9EGj/&[r#jpEgjLq,jr$"C%KF+Tc0`1.t4$8Eoa\O+LH@]g8`Js\(,S06r$ +0dhdf6HfaFXq5Z+Qn-+F+Qa"c-]#<"bR%a]&9EGj/&[r#jpEgjLq,jr$"C%KF+Tc0`1.t4$8Eoa\O+LH +X,VCJG'9<3S!od\04ElYNCIEm'7-)9$e*t#"2nFfjodD?LcIcF'k0oLF+otp`*=JJ">Nu63C1k(@SRJU +KpWOl>Tr540is/k6-L'Q:(VK#QkRDC+m&n^=,8k&bS=S^&9EPm'?"-!jodD?LcIcF'k0oLF+otp`*=JJ +">Nu63C1k(@SRJUKpWOl>Tr540is/k6-L'Q:(VK#QkRDC+m&n^=,8k&bS=S^&9EPm'?"-!jodD?LcIcF +'k0oLF+otp`*=JJ">Nu63C1k(@SRJUKpWOl>Tr540is/k6-L'Q:(VK#QkRDC+m&n^=,8k&bS=S^&9EPm +'?"-!jodD?LcIcF'k0oLF+otp`*=JJ">Nu63C1k(@SRJUKpWOl>Tr540is/k6-L'Q:(VK#QkRDC+m&n^ +=,8k&bS=S^=Dc9gZa8,^g!nMNHO1Y;BJ^Y)S^>Q5?^UQ4*$FAN0dhdf6HfaFXq5Z+Qn-+F+Qa"c-]#<" +bR%a]&9EGj/&[r#jpEgjLq,jr$"C%KF+Tc0`1.t4$8Eoa\O+LH@]g8`Js\(,S06r$0dhdf6HfaFXq5Z+ +Qn-+F+Qa"c-]#<"bR%a]&9EGj/&[r#jpEgjLq,jr$"C%KF+Tc0`1.t4$8Eoa\O+LH@]g8`Js\(,S06r$ +0dhdf6HfaFXq5Z+Qn-+F+Qa"c-]#<"bR%a]&9EGj/&[r#jpEgjLq,jr$"C%KF+Tc0`1.t4$8Eoa\O+LH +@]g8`Js\(,S06r$0dhdf6HfaFXq5Z+Qn-+F+Qa"c-]#<"bR%a]&9EGj/&[r#jpEgjLq,jr$"C%KF+Tc0 +`14'cQq&CA3ZS1to5B$dS*sHrbZhM8*.R2rB#gc/`9c,5LHT_?Y\-]NrgH^CY8IXUXq5Z+Qn-+F+Qa"c +-]#<"bR%a]&9EGj/&[r#jpEgjLq,jr$"C%KF+Tc0`1.t4$8Eoa\O+LH@]g8`Js\(,S06r$0dhdf6HfaF +Xq5Z+Qn(Y$;0rV=OI.PW4i()JN'5!V.uZX-<%Enj_,MqD4i()JN'5!V.uZX-<%Enj_,MqD4i()JN'1UW +;]UM*=Qj;tzzJ(U)@?_0B*o(hn?p-LZoQS2]pr:k9Nanbc.@E:[*B>&]ip?hM:dp';!*?,q:^7I<(@W$ +(d]r6qXh7ImCG3ukjs8MSQfGl,/8e_iQNY^:\Q"\3:C8L9"a&fQ4qXqmY%Be5K:E2fIP8GOF8Sh7NFMhnM9l<_L +Y*_nGbW1toQcn!PtEhS4P)3B;B]o]c(D2R!oN%sQL2)&;c7o>@0Q]uaHZLjAN6DqMfV4^mm)nlnH3`L] +5>DVVb,oPeDSAsi2E[r70tg?;SU4;`6Z7un]sHK\.G+X^'W*;7K-?G-('hsPB0I/Np +h!VQmA0nEei7M2@)ND6mR2k2m-q5.pYFl`e48Gk'dtdqCCLA,A:K_:>SfQTi\9#4CO*r"J2R0F_3" + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 0 187.2] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 387.5 L +1193.75 387.5 L +1193.75 0 L +cp +clip +GS +0 0 translate +955 77 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 955 + /ImageType 1 + /DataSource Data + /ImageMatrix [955 0 0 77 0 0] + /Height 77 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WIq4iC+33n+a^d.Q8Wp"lQ"9o:B7D1hR7rd,aYAWGJ#%mL8WlX;7oEjn0f=ek8WpHMrlETrdN?Tt +T;c.`l?"B(V">:2B2\gku1A.34<>;%U7lOa,f'4rr2ojp3 +'dNYH+^.^OEl"V#^Pr+F,"lHt[YEp$1*'#-;%J5p@\+36d(cI.t3'+$hMH\aRJ]'Xf(!(nDJjLI-QE2?smC6k07Jp;4%@a!)V>,_h +Y?Q*^>+$r'Mi,S?RdoS2iD)Tu"Q2l`oL5:KX!dmUifY$-*jgb_VV&I-]@c\T?rfEnmp8$8VY^!"/&Vl* +9*TGk'e`&)#0@e#%QioI64b0JK_Dc^p#O$?p`\.J8L;"k4eTC:AB8sD;&O$EUVaI]1l]W.#GNsC_OS_Yk09B.GHIWH]mBADl-i[fmB +0IHB`+2M?`^uQ0s.R[eq)XUU3rtOqs +BI1R5o?NS2kYb6a(CQ_M +&Am1%nFTAS";!75W"uDf<,=BjKHKN=,:Hn8NYuH.70cp[@"#+1S`q[:SKj\nn4P[C+Pu:uT:XWd_Uuf@ +8;PhmR-'bT!H6!rr=o852fQefGnrHK=M&[C,+D'@<<8S4]V]rl]^EE9"rtDHKl*XlAK5dG\1d[eWR_/f +jhs5=1#4-XelJ +dkJF`gD^DT?4?g&30geA*hr+Rl@P7G>)EL!!'f13.Lq?(! +*hl[WCWWfaW/a[E.Rqkd5'QWiE(>c=-/,lYC?SNNTJt'kV[$KferOc5in@Z=Ss+>Oc"E19D2D'AXH2-S +Q!4Z#"V`l&7kFkMB&QpM\s']mB?dHdnW%/bAr.d2B$hN,^Dr(68esYPG._Bamm%FKI?_.g_)#sX:5Gb-M_gR@php:@dBld,)'cLJb6p>^t98Z1&-Kt*o2(GB+mWV9%o"onXR_U-Y+a* +0Pq:X3T\@)*\!r$V4/NTom!Soe]?U=j?@B2S?pou19e)#sX:pnRKUpQq55n(=n?e11S#!!%]6o&\&sXf +_$S[U6du?0]r@!!!#9&tMi>s%u)_!!!!o='&I->FYT#e11S#z!!!"L5LC)D!!(q9;6%K" +]A>C<mtaqo<#%_j22$*C*`>u\<"]A>CC<"]G#R8/4Zq+bWf^=GPr\<"]A>C<mtaqo<#%_j22$*CSod#!l;^@t;H4i>"]A>C< +UY`CJQ*@N8"]A>Cu\<mtaqo<#%_jQ,9U6_Nmn;;H4i>"]A>C< +UY`CJQ*@N8u\<mtaqo<#%_jQ,9U6_Nmn;;H4i>"]A>Cu\<mtaqo<#%_jQ,9U6_Nmn;; +H4i>"]A>Cu\<e!i[Xt;B6_sgqS>g.[=3.h:f8PXZ717:LR;^o:eLM$Da[eWX>Qe*K_h5We)GFIJ`_<='%V3n +mlia1m?%We*3,J=+9r6+l@MOZN?a8"]A>C<NB[5eeTfWsV +u#]/X&Z3$2)R6+(pda.l#aKS5H1?MU"$-)&F&iEZY'/7o&dj.oP9ZX]s\Ha$r*AuU8/4Zq+X^:)D +>D//(Y.'d>ISJj*#pM7R/O`O`qTe9-WdJKH]5,gSVN&9.MKjjIGsXpG=8GrWX?=:n(taiI/3?(4*MHXb +@;5u%6cFD2doq!3@-mQ2.70]0`.Cfr$NPVfaIe^H:Ob" +d^^0fe<&!mtaqo<#%_jQ,9U6_Nt/fUskNT + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 458.4 187.2] CT +[1 0 0 1 0 0] CT +N +-955 0 M +-955 387.5 L +238.75 387.5 L +238.75 0 L +cp +clip +GS +0 0 translate +239 77 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 77 0 0] + /Height 77 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"/k?USsb*60-VR3[nIP%'rtmEo-Yh2U!@CNAmuH?!S=^5n]*p*ZcAE.]B\BPWA1@%hIE2[\p%$ +bT`Cs[648_cS=n%dFJ[,TI:a='&JWcBXY0%/_XOK5m;*himm/p!rO* +Q^3rG[^K(GI56TXo4Q55r`ak-#m:;Hj6c69G%Z/K]@QJ2NK*)_k)tl?]A5Y755t?P.#ZMa``:C4d"%Qr +ARupD8"7>L66X_^MC'YsA8X1W0X/'s#U'd`iFG_[cggN[.V%N+m7eX^e/E\^q?bN:b0%k70Sg1\XAA!J +Z,kSl2u_=YB,MiaJ7&`m$ZZaZ1.Ej5rEsnr)'>cSV[j7I[^NUUal+N)Td\I6m.:$L'?LPqipb[U>,Tgu +Ug7/-P!s/%CXZKC91-#+Xpj!cac&KD;2KnT!t0J1O7QhpRT`4"k6!k?NJ +;6_]0sH$amBgP>iTCk$qa3#kC"%a97mcXb$9!EY%I +BlHSX2BoTT8l=`@A.IMc[m'K`h@Fq('h$@4lKXe*RFH`T2e'%Z."Xn_BX?AaIqJnlpcY]A9WPh-Ri>hp\+;Ker@"LheZibM_aJ7MOYe9./#MY]j<@`i/h$8#W[j]iFm"B'1YW^;$Z[0F8>f0 +j?M:rIa7b6h;.W: +[$2FE#e!U1]b02PfFs*0EqZ+\k76$.b`'U&3GZLdBJcaf@c]+/');`9JB-*X`l?p'm:WB(RZtA8 +5kIO7&I\m8eY"t(8XYJA`,HtUaDIGBB?jjOrAs5F-=neZ!eGmJk=['5H#-EMeYLF-+R6$TAL7UYB/P0? +k'mE1;fQ+~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 0 375.6] CT +N +0 0 M +0 309 L +955 309 L +955 0 L +cp +clip +1 GC +N +0 0 955 309 re +f +GR +GS +[0.48 0 0 0.48 0 413.04] CT +[1 0 0 1 0 0] CT +N +0 -78 M +0 308.25 L +1193.75 308.25 L +1193.75 -78 L +cp +clip +GS +0 0 translate +955 309 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 955 + /ImageType 1 + /DataSource Data + /ImageMatrix [955 0 0 309 0 0] + /Height 309 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlQ&TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!! +%P-!Re\u[f~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 458.4 413.04] CT +[1 0 0 1 0 0] CT +N +-955 -78 M +-955 308.25 L +238.75 308.25 L +238.75 -78 L +cp +clip +GS +0 0 translate +239 309 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 309 0 0] + /Height 309 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;!=]#/!5bE.WG`8*TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!!! +#WfDo,d64s~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 0 375.6] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 386.25 L +1193.75 386.25 L +1193.75 0 L +cp +clip +GS +0 0 translate +955 78 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 955 + /ImageType 1 + /DataSource Data + /ImageMatrix [955 0 0 78 0 0] + /Height 78 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;JH,ZM!5fq/l + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 458.4 375.6] CT +[1 0 0 1 0 0] CT +N +-955 0 M +-955 386.25 L +238.75 386.25 L +238.75 0 L +cp +clip +GS +0 0 translate +239 78 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 78 0 0] + /Height 78 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;!=]#/!5bE.WG`:P'EA+5zzzzzzzzzzzz!!'fe!EZk263~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 0 375.6] CT +N +0 0 M +0 309 L +955 309 L +955 0 L +cp +clip +0.941 GC +N +0 0 955 310 re +f +GR +GS +[0.6 0 0 0.6 0 375.6] CT +N +0 0 M +0 309 L +955 309 L +955 0 L +cp +clip +1 GC +N +0 0 955 310 re +f +GR +GS +[0.6 0 0 0.6 0 375.6] CT +N +0 0 M +0 309 L +955 309 L +955 0 L +cp +clip +1 GC +N +0 0 955 310 re +f +GR +GS +[0.48 0 0 0.48 0 412.56] CT +[1 0 0 1 0 0] CT +N +0 -77 M +0 309.25 L +1193.75 309.25 L +1193.75 -77 L +cp +clip +GS +0 0 translate +955 310 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 955 + /ImageType 1 + /DataSource Data + /ImageMatrix [955 0 0 310 0 0] + /Height 310 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WIq[C,q=jDF.AMhW`le:B1&B]JK$l(kL!:4JXW9cF43Q>ph4t/[5m_EC2tr*nB"K6uK6AOh$Dhn$ +*+BkCZ.lS=CiH?J"j1H(FRQ3HqV8 +54OL0H[4Y2G'r_(^&7HEm662L4T>-UgX:+F[&DeN;]U(I@&a?.%;2I>;^GsFe\Y#4]QnS1&"t$[AsBo" +0NE_(L,2_ZW=gt^C1/H"Qu"W2bU@\#@&a?.%;2I>;^GsFe\Y#$0\L2CQr39$_,L`<)U:k[VFnpkWeHk& +@C"Ff0VdE'JuKAV24TdA9U1\_<=:T+_dofV@7If."B-V6C,dFaQms7HWYT25L<3K6_MiM:$)U9OK+#& +OC>HFYV;j-pYjf_,S;i.D\si),djr'/E7i)AZqL +]1ObWJuOJ\;M(k\18JYn-=iK[2(Zs"GElR9"B,bBU]aUBA4Y7f9ZSp@C06j#mOH%P$)SWd8-u.caH3EU +R?1j_eZ^a&gf8s*&kk0QOV1?QO7Crrb$?<\.`#*%)(EC$#oQXK0G?38[Mfon +Pe0OAZ/-"KQs_G&$)fkOWV;=5pM/^/kVPHBRn)*oU6-7Crrb$?<\.`#*% +)(EC$#oQXK0G?38[MfonPe0OAZ/-"KQs_G&$)fkOWV +;=5pMZ/-!XELRl5,P4*U,Zo9M%:Ie)RAamM0=rqtFk[V*pX +amNtR-@!6-Z7r'/IJG*qU%D!p\/lTG#&&S/Be7CQTuusV+[03IJ;Q=cge\Y#LHjO=l7_,Q&;^IfG3$T`:.UedF +2L`S_gU:r4DJB&(^kNLM:@-]BCVm9r."urPha)J3_T_Ls$"RI6\Z5j3-(&F,,:/^,@JZrU?+P.>b*C5P +PPn[q`X=Ksqtlkl*'&%McC?m62JecI,?pNAShGXGbU@\#@&a?.%;2I>;^G+%e]&[`fs524q"XX`rVO4< +\siSCc^m:JI=9Al/[&9]U8+KYnbS5t#7m,t]l;rI.K1lkKpglp'$.qKE`WRE8hee77S5@7_F:<4ET>($ +T>p<`l"P>!_83s.bOG"?j(c,Qp$1(Kk0.Ppo<,^n3dg_l'HboC9^mE9A77s9OK+#&OC>HFYV;j- +pYjf_,S;i.D\si),djr'/E7i)AZqL]1ObWJuOJ\ +;M(k\18JYn-=iK[2(Zs"GElR9"B,bBU]aUBA4Y7f9ZSp@C06j#mOH%P$)SWd8-u.caH3EUR?1j_eZ^a& +gf8s*&kk0QOV1?QO7Crrb$?<\.`#*%)(EC$#oQXK0G?38[MfonPe0OAZ/-"KQs_G&$)fkOWV;=5pM7Crrb$?<\.`#*%)(EC$#oQXK0G?38[MfonPe0OAZ/ +-"KQs_G&$)fkOWV;=5pM/^/kVPHBRn)*oU6 +- +;^GsFe\Y#$0\L2CQr39$_,L`<)U:k[VFnpkWeHk&@C"Ff0VdE'JuKAV24TdA9U1\_<=:T+_dofV@7If. +"B-V6C,dFaQms7HWYT25L<3K6_MiM:$)UgJUur8USFUGQE=B#:A-:U +AqCQ[JQ`Gf(GAk.V*)2qqn/niO/oN$/SbqY%&h7H\Vg!BAq>A%@S +jo]rQ$aZ0MnPUE0(!FYJ5i(8`5=`A2\`Crq)]g%QKt5^qef-\33nCB81YKCar]&`ih4&PLQ7Z=lmR*pF +GP;J^5*5PE^O=dTMe0*G3"Qtd`O +1Wiu4eGA_Z$Zdj8PsD/!pqnC^[VQg'+5ah_Iof]QCOc=3$T#WjKj^n`;[m8G7_,RN/Bf(MPlRYlET>($ +T>p<`l'_BD@p><,ShC4F-(&Ei$T#q2%:io0\>TN_eZlBaIJ`_4?'Q?[bQQ6.JuKAV23Z=%E<%Z=I%$RfSW=hl^ +OG+S6Xp20cF'M[2L/]bKKFF'HO/Wac23Z=%E<%Z=I%$RfSW=hl^OG+S6Xp20cF'M[2L/]bKKFF'HO/Wac23Z=%E<%Z=I +%$RfSW=hl^OG+S6Xp20cF'M[2L/]bKKFF'HO/Wac23Z=%E<%Z=I%$RfSW=hl^OG+S6Xp20cF'M[2L/]bKKFF'H +O/Wac23Z=%E<%Z=I%$RfSW=hl^OG+S6Xp20cF'M[2L/]bKKFF'HO/Wac23Z=%E<%Z=I%$RfSW=hl^OG+S6Xp20cF'M[2 +L/]bKKFF'HO/Wac23Z=%E<%Z=I%$RfSW=hl^OG+S6Xp20cF'M[2L/]bKKFF'HO/Wac23Z=%E<%Z=I%$RfSW=hl^OG+S6 +Xp20cF'M[2L/]bKKFF'HO/Wac23Z=%E<%Z=I%$RfSW=hl^OG+S6Xp20cF'M[2L/]bKKFF'HO/Wac23Z=%E<%Z=I%$RfS +W=hl^OG+S6Xp/Vmb`>!Fm\?b>Mb;'PWeHk&@C#P\IGXPVb>4]l3S?RYc_!H!_tNHM1YJ2/CcjoZdg\/hC:Sj2R)? +]`n]HbLHb((*#DZCpFR8qr;dBGAl&$.aM&II0^QC\mgi)B(YUi'?o!TgOUXq`af5K2WKHakigd[b3$q!)k22C*::/N,hu%q&O(-Mb:Ke +We5qVXl&&"IJWTWaN4!\P4;CBQ7Q1D@`;kr[4i7V?O3N$0\&E(AsBnGaMQ/@;$e%4ouN7?6S6hQbN +frpZV]E"_A^V>%eWS_dZbh94/_djkB_G'HH+daaqW@cDVWnB +e(?fH4j=JlGg5jLn8RE&\UF/9eT9lsC#&<_]C%_-q!\t>f"t,MHm+k,_,LM>Qr39d+:C!G73u2TWafOK +qtBEHinMFHUSFT2p[11elIQr39d+:C!G73uJ8e\Y#$0\Q;i.`#'d=dW(SC*3m? +a$h:b8CbRNa=uQr39d+:C!G73uJ8e\Y#$0\Q;i.`#'d=dW(SC*3m?a$h:b8CbRNa=uQr39d+:C!G73uJ8e\Y#$0\Q;i.`#'d +=dW(SC*3m?a$h:b8CbRNa=uQr39d+:C!G73uJ8e\Y#$0\Q;i.`#'d=dW(SC*3m?a$h:b8CbRNa=uQr39d+:C!G73uJ8e\Y#$ +0\Q;i.`#'d=dW(SC*3m?a$h:b8CbRNa=uQr39d+:C!G73uJ8e\Y#$0\Q;i.`#'d=dW(SC*3m?a$h:b8CbRNa=uQr39d+:C!G +73uJ8e\Y#$0\Q;i.`#'d=dW(SC*3m?a$h:b8CbRNa=uQr39d+:C!G73uJ8e\Y#$0\Q;i.`#'d=dW(SC*3m?a$h:b +8CbRNa=u +Qr39d+:C!G73uJ8e\Y#$0\Q;i.`#'d=dW(SC*3m?a$h:b8CbRNa=uQr39d+:C!G73uJ8e\Y#$0\Q;i.`#'d=dW(S +C*3m?a$h:b8CbRNa=uQr39d+:C!G73uJ8e\Y#$0\Q;i.`#'d=dW(SC*3m?a$h:b8CbRNa=uQr39d+:C!G73uJ8e\Y#$0\Q;i +.`#'d=dW(SC*3m?a$h<$WP8B.lc5&.TDC_eAqK1R_,L`<)T]dSE`W?GQoQcK!DW7.OX$EfSO5b3;r>j: +9^mEQQn#pO"'M!gmV3jP1WMp1E2am@Gd+6LX-@$#F'En'&58?sWdu_F.!IP1Kpgtq&r9LW7nU^HsF"AD4$.*m`c^[":mX0)a0Xlu'$c,dKVAeZP(YW5F]Qh!>MhO0W&#oahe`dn4WHEE/ +Dq7?\[VT*Y&"u=e8hedt\)-t%g\[$J0@RZe=Rbd&T/$Q)V^=^c4O*(cXeAj=E +JuOK/\#qir*aQ/:S;^GP5CZY@Y +0NE_(&knQuWo8o$@&a>;F0.Q3#c:3JjOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk^[f\"itaN3o3a4l"b'mfiOf*sXbkic^5 +eO,*%[JN4hEq8;54aZmes0hei.TB;ojcrp$I2(,*`lH."orilDo:Q%6s(M/385j4:J7HW[[HdfND;$gj +mbHLY/RQ6I0:IHP*')I#ff:lGeF!F<_Z\B2m^o[@\80^!o'a8=pQdJ'V),UXT^#Aq>0A.@KfR*+DnfSp>ebad1G-b/m67['fZ;-),LSA\ +cFibo468c9USGa,-$hRDN6clRq8u](IdXc0g3mX9[RVEf[)Db#P>@JG:s.<_2r/T1D7@dZ1#-fm/\Sj2 +c)YEQjcJ>Dj,Fp?N67*>NqW5AQ`lQrgi8+'3CJ_24LNtOBiFVhnu,m#/LOC7O6T=r2E!I;mbER=HDl,4 +L(,(ocMjHh&9#;YAuQk84ZsSC&ESJMSFST!5i;P.GF'mcf"?>(nDP=)][:ZO#9?Jhj[r.bAA#Rh4'.:p_o%7H5Q%)o'6_$8aElX1\jh[j? +9.>36gX`[.92JCZ;l^3H*TV +AcC$&bHYj7Y4<.8GOOCoX1-o.>Np:rf<=p=(]k-W&,VS:9'NBtkKa%VYC?/R^\r#iNZAKC/GS07IlNVs +d$WsK(\sE$Qtt9SRE<@FR"ZE`Dr8:7W4q+P9&iQWZ"1t>_hSc3qf&]_qtKPt<0?`i$ZhPd$Q%*X2fI`r +NTD\Bi8A"R>/"[Yn`T#;FJ['D/a_fe\`8]3"pP8QHK_'nTR-M&\,/CWU+AI2h+(>'nq=1A6^3KF07N)T +G@pEP>F9+?B#71o^!t`gq;(Lgp[m_!m66h.PXR`^p?Y$Dq9P5hNAo^-B>,?ucCDH0VON&+S)6'*>*u(L +#LW\Z%Q(@13cq;_\j#oIK5E`H/)$"(4%b%\q9F2Q%=-9k4VM.uWCp9`0:+B%D;3Y0"0'4%pY8]]2O+Mu +dF$?o#7iFk[]DSuT#o:5p^()1P/4CWLO80OB1i-dl05H)'94/!5%i02njL4J#BBupi.2-Ir8fSua49/? +m^qr%\T?r"J,JV>s(_;%eRlpd,qE#tB_PA/WW)hY5<"&Y5jODYa"5@dIdr?loB20oNOAXKC/>i>KHIBZ +Fm;qO>lF?!Im%;^d.e3fen77->C;#?`PNU1_hJUHc[5,o\(q9eM6`ab3@F`#mID"@?Q"/MH@'ulpkr8A ++d\tjlE4F)-N&a[;ODl(GiOc9C5B'BorC9<7VOuqS+(HS+8k%%1S!s_V+Xmm>hQdT +YEb#W@1H8.?'[0KJ$YXtdubkF-N%VmUIUB2>FI2mcm9MJ)]NYagY`#(L)Y"Ys6tA0Q_VsrqYU/Z\!69N +1M9I.'&CR&]$`06[&EX87sXOhYK7.Ak*p;c]9`UW:B05MmWZo[cC?mn*`m"LItfl\E64Ct>K4_(p[@"s +e^`4(T66PQbY^up.qco^`JZ,A:ADiTjNR$UgK)]as@?+7"2O.Qbrb^H=mel>!b?+DD +Za6tMl#!oc/TqhSu@0JH>o/5JXeI3A22?`M\Y=joM3(GB+mat'[&j[dD2`qJfSB2t8s4.SN]G%>.% +5DcH=8dX1_GH]m-%5^74rqbracfEu6O=j8&XSVr^,tX7F8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>j +OsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jP,.0qJ,fHf4*D#@$p=L\dmoH?rTG8^*BWuE;br[f^A[c[+2']; +55=&gSND&@fVaoY8WoOnX]p"o2:m5M`V7+@^"-qEnDM,YJ,7WR2nf(QWtVXBg*\J[]W\MWRWi)QIf7eu +?etL9hu)UqhgP7T9DbNJ,Y?G'](=3/9+,%5C/q7Ljm'sO-QdWpO__/6p5<;U@^@lbp\1$Or8Sn!\DYn1 +F8+L7?[(=Ke%+W`rpY^6koP9FdIHbsQX>2eeuW#`hgYIaHtl69,\`^=GiFS.78!ZQE;O#BqU_dN\uKl+ +`mqf;^/'4KPKgR3\9_kd?^SV#V(XE'ZD;d=pV6`V3Tbhkqqm`c!0SU!d`;4,=2+7E07NGCDsHcY/tMf& +s7t!3GM`.L079JkqrXAdIc,b^-n^Adf/QO7#9m-*YXlD^\M+/G.U;Kp=Of3ECAb*=L#7r-no +DV_m,ZY#JH.3E)FGe!3/Ie9BWQ$^7>hKu(?Dr/.;q(^cVs8?u]L(,*;>U2n(UiY_=a2_E!NBBMk]qq&Z +rUeQgqU;&P04'&!eQ8)e^\HfH''0/>f9Qs4gn8'H[:#5KHs-PoO%"AGMauXo]JI= +q$#[0BW=ijn\hse?]m-#1fWmDg2c4g.H.tR]qmEL,5nK:I;7ldQ-K%aFQcQepPPmEP)SsobBoM,Bt^c. +mE'[g,Y=.5jfQ#K.UD]GqsV;X>GkVkhg=h*c[=k2TDRF,m^_MP;Jo-'DVX(s\ttDTBMjZTpV-C8`Z6VS +OsEUkY47[6A]pBFn?%]-:%@SVc^t$D+8Ym3huA/kXg^3;m9@-7Vl/_6GMaDX(arJ/NM$-QDh%Z=NV@0> +bh$.AXBDmPRs+5TktWHhlH]L&&tPh^nd[L%_XXhARIXJ,]9,YJ'Y`TD[atj\)Oo+"^6,idQj +TDe]N5Mp_C;Mg_n?f#JMV'k/AcTTN;C&N`=I%gAZ1sVZlmEO6gG?qbmot/S7H/O5YRNH24il1n2Ce9d8 +c+Nf.J,_0Oq9-$Qa"Hc8hg4Uj^]*o0c/4]3Hd%SQFkqkVRq8ad*,?AAIOsEV^,Y=.E8Wk>j +OsK;7np^X\*>L[~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 458.4 412.56] CT +[1 0 0 1 0 0] CT +N +-955 -77 M +-955 309.25 L +238.75 309.25 L +238.75 -77 L +cp +clip +GS +0 0 translate +239 310 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 310 0 0] + /Height 310 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0VD2;/&"3,=H66\aLkX.`[!]Q>pA0jj60F@SRRT'hQa<7c2Ma\JZAhW3].AT?_(W%^S,Uk1I#f4G% +Q<5P^`FL^!,^O#6HZe!o4?SDJX?5J-?k+:7>FL8G'T7$2\7WkB<^:l$pVCZ#a +eGVY!?@(l,ji]%G5*$dMY2_1=??Y"5VI/DRDn_W'IJWBf]:4a>[tM?(]$BuA`hb&)ddQeEp\3QplT)QD +[bEFGkb9/Jpqcf/NgQ*7!\UZ?o#N&Z]^j5+5(n=R`>;T\EJ4a6*qQog7*Lj+qtBFR`=EtM1j/*5%3%3- ++6u.IH.)ZekFXfm:7F0/L)Y#Dl^6RZJ$`O#f?6f?S^hYlE8eYQDnJq3/7-!alDq++f_aZd0@#tA8"F"- +aX&H=Xup^`7*AjtG3gWc?[VC_.orbHl)1/rRoEm812P'q-#^KieucFIRAJVQ5%?d*_:= +^V:Vbb]L^$Bc;BW^k(LRj\'X;Q7^]nF%pY-]tM,0pDj]ipYC%9[khX?d"(QPmXk`TSoK4$?lH@kj$s!o +ehLqDUhssp3Lf-"eq*\"?[1N5rN(J?o=fYMb.Z+`o8L,Z?+]gDpYOZ5D4@-GHg\GBq6"A&I9,*(X]hRg +4*U*lJLX\J\)LG"bftq-9WKb&A"gDb(D0l,>k`EBis"pP8I/6JRWnoWoT*/$?-UUn]tro&T$!WepOJ[dVtc96 +mO38CWg_=lYoMQVhlemlqF\5ClD^](@=#WNcAS_q>'kCpDDG;3I"B>>1X^^Gh,dp2i.2-_^p.CioX!Ct2'I>@ +mN$YTnTJW)[d++&[mC,QHgeYeJ0O-A_c0h8F4L$BJ$5!XQ7].$qAEdlrUnc"k2VLeY23EA?7i"r@63A6 +]6)=?n!>W6Hd#Z:`g=F&I*mP\\`+JHX8%-8cW\5dUGUg[/Jtj#Vtt--G1U#D'a'>\>7OSGe^'))K7d>< +BY84?IJWU3oB3TA=mHESd:0_6GZlK\,[VSC0GU-!F(`rOp[ZK\hu.KF?[ocGiq<:TS3O(#YMT#3Fm4._ +Re0r8@W"3-)RJj4\*E5Bfs>>;0>IE?pi"1Z*=/iUQ5's6&c\pESeU#K,7 +[i*GGe%$9Wcl$\gA^#_%i4J8d0Im1+_AmBLGc0$f@18_Aa=/W;]YhjY!)4WV"6bZm3k_OMtLEs+3Z&9@t/3tQH90foqf">MtLEs+3Z&9@t/3tQH90foqf +">MtLEs+3Z&9@t/3tQH90foqf">MtLEs+3Z&9@t/3tQH90foqf">MtLEs+3Z&9@t/3tQH90foqf">MtL +Es+3Z&9@t/3tQH90foqf">MtLEs+3Z&9@t/3tQH90foqf">MtLEs+3Z&9@t/3tQH90foqf">MtLEs+3Z +&9@t/3tQH90foqf">MtLEs+3Z&9@t/3tQH90foqf">MtLEs+3Z&9@t/3tQH90foqf">MtLEs+3Z&9@t/ +3tQH90foqf">MtLEs+3Z&9@t/3tQH90fr&ck/"mMI[mlNXd2/(p/A0H]36r&9[H0lB4_6TNZ_p=@ZDRC +#@`]9Ad;e*+D(jfNZ_p=@ZDRC#@`]9Ad;e*+D(jfNZ_p=@ZDRC#@`]9Ad;e*+D(jfNZ_p=@ZDRC#@`]9 +Ad;e*+D(jfNZ_p=@ZDRC#@`]9Ad;e*+D(jfNZ_p=@ZDRC#@`]9Ad;e*+D(jfNZ_p=@ZDRC#@`]9Ad;e* ++D(jfNZ_p=@ZDRC#@`]9Ad;e*+D(jfNZ_p=@ZDRC#@`]9Ad;e*+D(jfNZ_p=@ZDRC#@`]9Ad;e*+D(jf +NZ_p=@ZDRC#@`]9Ad;e*+D(jfNZ_p=@ZDRC#@`]9Ad;e*+D(jfNZ_p=@ZDRC#@`]9Ad;e*+D(jfNZ_p= +@ZDRC#@`]9Ad;e*+D(jfNZ_qhM8hY;37s;`FpDV:Jn]F:<[3uT#A,iFBm3rc,FEWZAi50SG@4GrR!&^H21fOd +R-:W[r'/d66)KtTzzzn/j`;o&RU%^ki^PdKe2D^AdupT7?jN@H4=cV_lM*[pu`An])`P=0J2QCK=M#*'C5ZV*oh1mC1Kl^]dI**jr@gS1RV)4'-t +3\7BC1#YI`j=PXBDmlq!mC&(+i_'H?K(Wg/p_dqD?GP,N@4P;d)!Kg#RN;`*@]Fe,$0d:i*+[,fHK\Y[ +G<@mG#gb]6Vk09Ci`"PqB&$!=&NOehZM, +"s6,9rh0qIr`$:UP%5QJpf]ji`u,IqI44A,Z8s>%scCWkFCO=e:-Bq=;kbRW/7rmA%5jjHEB\fLjVn8L +@pIzzzzzzz!!'fFq$/E;B\*~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 0 375.6] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 386.25 L +1193.75 386.25 L +1193.75 0 L +cp +clip +GS +0 0 translate +955 77 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 955 + /ImageType 1 + /DataSource Data + /ImageMatrix [955 0 0 77 0 0] + /Height 77 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WEF`)L+33nk:%lhB^,*kVYpPa[1B"IB-BX]A(!1!L81)e-OX->_dN;'#oUVCAA29R07?[T^P9ar7 +jf2#*Zg"D +d]RAHJY!!!"J_:>SfMi*BIREV-ZDjFo8#7hl_#s0dM,/!6@WMt=Cp(biI0EV:T/0cN;S?N>Z1c3_9g1kj"hS#C4G^= +\ilK,c%YgB-Q($;-+cAM%f:S72Z:=%+e_>/dFiFS33*=XNpCu;sTHhH[S[V9qNS&,R6!3f_Pbfm.n\T5 +r`20OIoGhBU_Y$J[1LJ:H9*'\nbUnkpL+K_ZD\om=>i<,sSVQ>bIO02j)^9b.%rq)_tr6t1:o#o5"a2Z +-MX]oE?.P!$Ug$IMldIO03VW-TEpI)X"GOODP`,'d$BkaQK?a4'o4l+B0]i;B'naZ,o7ul5PB[bS:?dI +X%jQ'imF0jUt-BgH3kg95$mh9`MC"Q(h?UcHf!!!#B868lZ4!2?lDVDJ>(14h**?SeQd)qr^\(90eh0n +D-'e@qF(ffSV!S2_/CtW9U]6E`3l05JPkn^%Rc@'&e$Q8Dne(3$u<)ci`fWi?&4u[t?Z>7H3r?af*8M`*P-e(_?M[uK++g=t@fBJtj'S?9 +n'#GNZk!!!#BLt+WRDkj)&DXl/O90(PPS2tf8gK;L:7`7,P +_m523GeA%*9iAfFdlGh6+\3]c81"pYB[H?sVgUO2+$mNrW[S%lZ2kdQ(5It,3BYh+_mn*92\hb&Hdg7U +,%!!"PdB@!0Wnojs+nV8je=Dh(DVl-GV$XWCSZ*?$-$:O(Og=tB<8Jc8H<1"%5molbLjSUT5diKPO[Xr +r'o&TrY%]ijA.UH["$F>R*j+nFa>@1ZA*?RL"0G#>t9@p&90EV:T//OS:Psl(ZYHN.[ZIu<@Vg"gN8KQ +enkX$1,)r7`s0Gc_JLBVg@Eq7kfA'nZ]AMT[b\iTReJV=g#KF;JGqQdE4KM>C4!<<,JB5hgoB`=(E3qK +k2@e/NtMn/WsFR=NU;q"(:PioP4&KE=E;U4SWjU3Jq*2UZmHko8*d/nhkF=)c:m_Il#4,*+F*# +X8g_&\KWiC_H;j[Rc!7L&GJHJ?G.p^)a4F,?rC2Ig1M^@t8:+E]t=^>>#rX(;e^p@\"MMmCpJ`f.ac"= +T"]:V32iYLS;0GcK.^S$UINk09lEo'GV6UQEYfpu=[SU(lf#JD^lKf6Wkb(WZZ!<<,:2_d%La^e":9AO +%/*7f/4e?)uddTm.?,(LGP$AsVaH:.0r2"T(g1C#*H[DMXD>s5$p$poj.*MYk!5F/e=0GeEZ_G(YJ=;oF)fX +iW%D2Z&bo:H5GrTQ[aTJj%X?Gj/le]=%\$*!]?2r0h6s!uY(Zn'(k8.*5[dJ8![^N +W\H0\YL:Bsu,DJX-J*mO`:GWGfgn#,2q=AYVQHfhKBlr\bGlL$83(Vd8_4!&9C>$C +K(ar7ZLV!M4F5(EQZr;7*51B7CT(,@a)AY!dNAE;VWq"!Oid(Gl!2D=,ma#g&kUG`?-n-NUk"[@G3P]N +:8S9lLNJ'S?"zzzzzzzJ<\^e!!!!M'2)>mQXm_m7]HfkW^*QkUoH\[h@Z^gW@ER_C'\lO+&Z)]<U<4sMS"]A>++k7.dO +?TJ?5cP0eW^*QkV!8t_.ZgYs#cWP4L\)`i"]A>C<Q%5cP0eW^*T@&ZGi2.YNmu#]iNY;H4i>" +]A>C<Y.tk->dt^m;86(4?'hHk:,#oacKb..Y0Iqg\B +@DW8'hD>U<#%sS4!IZIY.tk->dt^m;86(4?'hHk:,#oacKb..Y0Iqg\B@DW8'hD>U<#%sS4!IZIY.tk->dt^m;86(4?'hHk:,#oac" +a-iK?G64)iC!/Q$F9fk(Bm]:+B8SCr;#sI\bYAm87=,#il5h\h#@6C^OQ:Nr>Y@?j(Gt*W@F"0G=8GrWX@0R.EpSqGMB@\>mJ#WDJieG. +ARNS.ZgZS7&iMP$9>(`R(730^,7bBrK_td+VLTN5cWZQW<0%K85oJ`_VEQppX`d-]\Qap*\@+,;KK/T- +\Y]YTBuu]W^*T@&ZGi2.YL`f+$@nEjEJQ:`?X]m'P8@LWsYZ&5cWZQW<0%K:mf^hmu'[MAgopE$Da[eW +nn>e!i[YGR+$r]ManIn.6ad>UoH\[h@Z^gW@C`3du*UP7hfPa5-#$dW^*T@&ZGi2.YNm5KioRP4e!?(A +gopE$Da[eWnn>e!i[Z&O=Gre+bW"J)AHd45-#$dW^*T@&ZGi2.YNm5KioRP4e!?(AgopE$Da[eWnn>e! +i[Z&OK.Uir5W6\6J/WD6"-)=Z`69j$Dcr-OXcHm63sPgQk_s?Z`-6!QK#6N5cP0el5c!:OK(WBWrE&%\ +V`?~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 458.4 375.6] CT +[1 0 0 1 0 0] CT +N +-955 0 M +-955 386.25 L +238.75 386.25 L +238.75 0 L +cp +clip +GS +0 0 translate +239 77 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 77 0 0] + /Height 77 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0VZ#,+i!(G:/PGos4MfgG0HWQ"4OEYY9GEJWpjZ25]%.O(=\kmF^!rr<$zzzzz!'GYG$Z!L!n&Xi% +FSm^(UZR8k__X%S0XY>*R<@c:b@+>Uj-Wmdnlj6^p0RJCO/*;+p?XZ3/Y#q!dI>%]Y\O+LH +@]g8`Js\(,S06r$0dhdf6HfaFXq5Z+Qn-+F+Qa"c-]#<"bR%a]&9EGj/&[r#jpEgjLq,jr$"C%KF+Tc0 +`1.t4$8Eq+2!0L)R&6j2L&YeWB0T.=6&RC;J=%k*SRhllZ20n05pk'J$~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 574.8 -0.6] CT +N +0 1 M +0 310 L +953 310 L +953 1 L +cp +clip +1 GC +N +0 0 953 310 re +f +GR +GS +[0.48 0 0 0.48 574.8 36.84] CT +[1 0 0 1 0 0] CT +N +0 -76.75 M +0 309.5 L +1191.25 309.5 L +1191.25 -76.75 L +cp +clip +GS +0 0 translate +953 310 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 953 + /ImageType 1 + /DataSource Data + /ImageMatrix [953 0 0 310 0 0] + /Height 310 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlHSTE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!! +!"LhZ+\G + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 1032.24 36.84] CT +[1 0 0 1 0 0] CT +N +-953 -76.75 M +-953 309.5 L +238.25 309.5 L +238.25 -76.75 L +cp +clip +GS +0 0 translate +239 310 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 310 0 0] + /Height 310 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlV]TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzp_ +u9P$uu~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 574.8 -0.12] CT +[1 0 0 1 0 0] CT +N +0 0.25 M +0 386.5 L +1191.25 386.5 L +1191.25 0.25 L +cp +clip +GS +0 0 translate +953 77 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 953 + /ImageType 1 + /DataSource Data + /ImageMatrix [953 0 0 77 0 0] + /Height 77 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlN5TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!!" +tq=u!uW~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 1032.24 -0.12] CT +[1 0 0 1 0 0] CT +N +-953 0.25 M +-953 386.5 L +238.25 386.5 L +238.25 0.25 L +cp +clip +GS +0 0 translate +239 77 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 77 0 0] + /Height 77 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;! + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 574.8 -0.6] CT +N +0 1 M +0 310 L +953 310 L +953 1 L +cp +clip +0.941 GC +N +0 0 954 311 re +f +GR +GS +[0.6 0 0 0.6 574.8 -0.6] CT +N +0 1 M +0 310 L +953 310 L +953 1 L +cp +clip +1 GC +N +0 0 954 311 re +f +GR +GS +[0.6 0 0 0.6 574.8 -0.6] CT +N +0 1 M +0 310 L +953 310 L +953 1 L +cp +clip +1 GC +N +0 0 954 311 re +f +GR +GS +[0.48 0 0 0.48 574.8 36.36] CT +[1 0 0 1 0 0] CT +N +0 -75.75 M +0 310.5 L +1191.25 310.5 L +1191.25 -75.75 L +cp +clip +GS +0 0 translate +954 311 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 954 + /ImageType 1 + /DataSource Data + /ImageMatrix [954 0 0 311 0 0] + /Height 311 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WDePF!rQ"G[K2T/+#PrD(;Q(hc.NuZt&qXo.#@`f$Y+8j[9S,[N6#l[-Y0;&VA;.'g?9Ph\,p'eE:3=qH)7'&0$c^:fW(H$<1#uW]:S])f&WKeS`rIm**bL^cojW2`*_"fa%KeXVDj9Zsc3FbDZCW#;2-kM^`D$qV24W^'PfW[^iqS;3n6bI&jgW3(ee +-Kd-H>VD3_W<-'7W2`*_"fe$_OHaJ49O`61e(S"&r63X8AU(^k,"#63W[^hFJZ9&V2$qV24W^'PfW[^iqS;3n6b6kSZD#M7m@o(AkY*[4k<.V%V<)oTk!`dKj8BS<@:smE4LM%ss +$@''e,"#63W[^hFJZ9&V2L1dDnP7@N +Y*[4k<.V%V<)oTk!`dKj8BS<@@(ER:c?FNC?6Va7"fa%KH\[c'*4OSoFCB]gRUN$<1#uWWH08 +W+sUF;Pn#Z/6B:Zak?"4m,<8I$qV24W^'PfW[^iqS;3n6b6f:kp+*OFcn<>DI45ZMkHOtnU>GZ`Y)Er1Nrl`0bK;?a'M:fW(H$n<>DHIc9kL,AH`Sp/!p+bg^mK7 +78a;h.Ss,rWX;]_k92;'Z@[js9i"r&F(83E"\BH-W^'PfW[^iqS;3n6b6f:k2?VsD\O!8GO]6n3$<1#u +WWH2FGt?)bXPdMuZ_SJ.)ni6O8JS2(5ZIuf.T"ZcLSRVe$6E7!L"aQ/1,C^dc&ktVWX;^*TW/&nc&%T9 +?bUpXh2WRA?LH*4b6hK*V5bH'b<4d7"7WI!]A?*b2jV'?e$9#k93HCr +bu?Pj;?a'M:fW(H$n:L(-kdF`qr"5C\-Bq_KfSE3WBe@Uh3o +`JLT[<<]BP:fW(HjqLDAgY8&H>IJbEhP$X:JUrCA@;BZEjia"6h1+sB]"5IZ8!UqM.9R`Z?6-_mj!+Et +I,Vqfa6%?5_OZa.QI^^&WWH08W2`*_F6OrU]m=fs:J\P$Q"aBPMoATU)k5NS;'et:"fa%KR +i*oRY\gfculu8[K:fW(H$<1#uW]HYHK' +B[i"TTGe$'r\,t<<]BP:t;'gl."54M%_6`-77lg-e#@&(X!e]Zgf9$4EB=q_X7*s_0N&d6_estW!ZL( +TW/&n'rYlm6W0dm"V3-L7$rsp*^(ERj0#PfjAX*?$\.6o:K;+/G%aj6'30U`$<1#uWWH2FGt?)bXPdMu +Zdm[Z=8?Z;af'Tfg8aMdVuS3F!`]u6W^'PfWg`O@P\F::_ocRA9Y@c-bP,mU/ul0+4#G+?6rfn[!`]u6 +W^'R**g/91.sP0!%glO*]=PR'*0nEl4i_39[jjHrm_Oa[5ZIuf.Ss,rWocDhAQi.(Yd1DGFt_1TFaJZ9&VZ]<1h4S$S,0WO&B:+kj5J_R4e'!0) +%A2@S%CniY'30U`$<1#uWWH2FGt?)bXPdMuSHomLaX^Y]4L[HAG3,H_W]&98%8Kk+W[^hFJZ9&V2o)8G8+-gc@?aToXBQ0[q:fW(H$<1#uW]:S]R?eRMXDEWK>EidV@ZgT1^8aA6 +2H?O/U!_dGWX)T>W2`*_"fe$_OHaH^_8FE-jkd*U8]a]MQ2G0";T;^HgnE-:-`RYV'r\,t<<]Cko8o2N +=i&"uVQVZ[Y?\VYNn8k5DHa2d<5.IlC.(-?]HiIE<>DI45ZIufRe)W*Bj&9ib,2/JojZbq\?K[mNjlKh +K:k:C=B:fW(H$<1#uW]:S]R?eRMXK8tL5)PeY7^%8dXm1.d7UD;T +7TBVl.Ss,rWocDhAQi.(Yd1\EF7S+i%]>W]W\/L/j?'>B<)oTk!`]u6Cj +RNkDh$rn%@W^'PfWg`O@P\F::_ogQ6g/j&.MkfRhI(W^*<(Yo=WWH08W2`*_EupK"/Lu'JffE]V7L/'3c<<]BP:fW(H +juao#>#t-sZ?,X2l>W$X?Sr:i4#BL.5ZIuf.Ss,rWocDhAQi.(Yd/?>^IJZ9&V2u$L"M5ig@"fa%KeXVDj9Zmd2YAEW5*Ng$C=3W\c +]::"#'30U`$<1#uW]:S]R?eRC?eK+a:JT'FC(/agTuW"i5ZIuf.T"ZcLSRVe$6E5+5#eq3HYi]HVu52@ +@>tq#JZ9&Vn<>DHIc9kL,AH`Sp)]u)KX$%mn1s4iHn<>DHIc9kL,AVD%'p?'VhPEV2fK8G>< +lQn:j8_KeW%o-(-W[^hFJZ@ip,\:.[W,Q=WCtZ+-d@q!b0!&[?* +n:ZVW>P)&?L1;]gr]L.;bS)G(ldLB]-+!`]u6W^'R**g/91.o\AX?b1>.H/li]7(@70 +lID=jb:sOZ94ZIDg.4:^3)LEhW^'PfWg`O@P\F9oWbM:kc'ufo_h[3jVPY]bU#hYslQn;(,]/&P)P!`5 +<)oTk!`dKj8BS<@:t;p80eng'Olr%RnSl00-Hi4Tma0l[n<>DHIc9kL,AVI.]j`fU12gHYFQHSf; +]gO4EUbV;aaM)DJW2`*_"fe$_OHaH^TrMh;]tM+(bKS1(iAE@hrU54PDAa<03HO?,*1uju^G7)i*PLj!GkWYuJL.Ss,rWocDhAQi-5C0D+=HKqK=hgYGUJ,)`A>?glAe##jYq^bpX.,8[j +5<^eVdFm3`@)7H3-[GLGLVqb\o7+P%&(aHb4=8>Q%LnJ!o8fmY<)oTk3F1(tl04=mOfMQec?i?aAVI.] +jk[Om5PE`>Ko,PT#9J-cjd22*R:BELrqY_!HK_&HhgK]\AnGjqlpj;:dC6mhm0a^_)#PIpM2*3pIZro> +LPF]dGt(d;W[^iqS1*X9IJ]<]=gIh2N>jelht^_^9ZmcC:!80AKAlS)q9OPFLPNYBo#m3nPadtWhRpC, +_1Gt)Fqnr+EofpgCp1MB8f\0))@o-rEf`,54#CtS22A-15ZIufRStIpI/%XtJ-Q8_AnGXMT0D)^f!]/5 +Q9"BZ[&d*AZs6@nQCi[+q%m@^iIM4T\GuR*f(grNEuNIr&r&GgA'XLX5[p?i@"MK6N6/ ++EMg#R\(T=H)d;T<)oTk!`dJoP!8K]1W`q+n%JI%R"s"[5@_TE"iP7j!0O +Z,[p_ieoJX^#s17]bWfdnF1CV#ONQC60@a)1_3A>kHAVA:fW(H$=@KJ)oJ45;G"bi.DQC?+[PR"3q&kK$<=9C#riGl;';#\>j%<n@LW +d7Ikn#Vm2`;L^bb@]8Q&<>DI45ZMmf8V`%T_XndZk2_NHc->"PD_LiT(=/nZX6Xn-WO&q[l;N,o45VL_ +Cl^g[q"!OiM]_rrk$JnJcPJ4(GAIc`$26P3HXr&3W[h%K +TW/&nc'9R!C0Ie?mmRPHeLXh0B[PteS!1=7"YDpIr:8#aQb5M'`!i]@+MsoaSna:iWWQ4#TW/&nc']q" +)&Zj1L'P09Eq7KS`l?"6/6MDqCTiHLn(G#pN696YOc(.h60=n9Rd&!Q7p@iL<)oTk!`dL5-S>6ihk5GiH?mrU0IUGSlq=^]4;1VPaC*gY`&1GH8L4)]jUT`LeuF +f?f>gC)3bJ5ZIufRStL!kibS:_`b1GQO2D\q'SE&8TSroiQ_?CJ,JgmB?l1b%idQJheYo6,VUQ-"IX%u +Uab`YBV;@SU8e8p'rYkBOgOWG,[lq+R@-'Xl;Utl>KO&"&kpIUMNo2&*DO6a8H[rqaBZV/9kB)L_c9D7 +<>DI45ZMm"UjMk(/\^h!GBZ"7I%DI45ZMkHOtnU>GZ`Yo:t6OW93LW.TW/&n +'r\,tDI45ZIufRe)W*Bj&9ib/T4:k"%OoRW`?a%KD,>c;b%J.T"Zc +LSRVe$6E5+5#aC0dRmLq2LiG[U#HNh)]\%@!`]u6C#t-sZLOWg3KhrAQ$55S''H7r<>DHIc9kL,AH`Sp)]u)K,AFiUmrF"*c;b%J.T"ZcLSRVe$6E5+5#aC0 +;D[[d&E@"qTW/&nc$;k&[&i1oA`H-XF!NVdHY,Ijg#t-sZLOWg3KblA;O&7@oANqSTW/&nc$;k&[&i1oA`H-XF!Oba +X"$1fb2?N)TW/&nc$;k&[&i1oA`H-XF!Oa>W6,U0HZ6,;:fW(Hjuao#>#t-sZLOWg3KbjolS>uur#t-sZLOWg3Kbl1?T!b.CQ?/E(9"5uGZ`Yo:t6OW'cO?WIYUB;?-N[$JZ@ip +,\:.[n?B4gTrL,9.T!NrqKFqc''H7rFr%apnk*S>uur2$A%U3 +q=Ee4\3JHJ!Z-arC[Is-F$g4(K_gTBb_loh4HtDADL%Y?p&6 +do5[u0J+eoYp`H!*(^mDWfUuGL=r9:\Z.npF*/hCGk'd$_Y!Km[;4BKLPJN/&0jll>IJ>spIUa<'t@?[ +W+q?g$<1$HVJ>J$Tu":>5ZMmf8IPDJH@(!s[tKULWMsUXSiu37#h-'\(Q/>pc&ktVWX;m0NH^-^kGeS` +bpehLo^jt!2]k&#,lE+5FL7gBm]NFdm"YH"k#W]=A5WMuj1-Vd?/9[%iZVI]o`('U_,,H1`E +'g,OArsfL!#t-sZLOWg3KbjgrB*iCG(%2/bQ5 +nkh8_W+sUF;Pn"/%kAS@WgY03!`^!+<&Hm92Gt?)b +XPdMuj$Qgf,ZUM;6<$t@4OkEO1P0W[^iqS;3n6b6f:k2Ek(t7oBMj.T!OS3d,15GZ`Yo:t6OW'r\,t<udrZTu#Ad*p9O`%nW1T'g/R6 +I&Le?U^C($TW5lqW([f.FYSSLR!i0#t-sZLOWg3KbjgC;Z+WS?(d7,\:.[n?B4gTrL,9.Ss,rWX@I[236!BT:@oC +c$;k&[&i1oA`H-XF!ObYWWH08;QtjeXVDj9Zmba<]3-@2+LOJW[^hF+oA8s]EXr(-_.NH)BB>[ +R?eRMXDE9_C6#(s<)oTkK!21s52kj?EqWKj$6G?c/Lu'Jg%\Co*(^mDW^'PfVc@MZ_V*17%B!4tbX5:* +AH`Sp)]u)K,H1`E'r\-oK;pqZ_Dqj$o>X-qVI]oA.iTS1RNnd5<>DI4OJf,O5N/-`jIE-J3T2,1e$=R\ +Q&Q;Sc&ktVWX;^*aD4f5PB1'23p%S7e$=R\Q&Q;Sc&ktVWX;^*LnSR#>;]#"B@Gg"L8rOD8BS<@i*g3W +6WJ1Qn<>D7.>4WEQek\@tDI4ck'4CS=HX0g:8B,VTV>)VI]oA.iTS1RNnd5<>DI4cuq45UpI)ni8%LSRVe$6E5+5#aC0;?a'M:fW(Hhl-Qhk<$TQRFYCLD^cM:%jrjUZ@[js +N=T%6O]6n3$<1#uC0C3omn!fs?Z^RL*IY@E6U,";NGZ`Yo:t6OW'r\,t<<]BPPZBA]o%@c,/iQ,;3(9=,W+XGJ]mB?d +ac4cudj$(^pYL?PVI]oPJeY.uNhd"]n<>FZ"WgfV*SYGF7;(l7gf[A2'3&m;kP,HZb6g?7.8\P78JS2(5ZIuf.b%AhhYGiPKUu\2G!AaRH(p=ZNjc@'KlK%3/K[0(38?8C0JG:= +F8GOnE/-#L[`n85R$JJ3#Z@=q3Kbjg\7WMuk4$&WH- +r%O-L^$b/ib?.Tk*(^mDW^'PfW[^D=Fl"LE;h".\2?O$`a_,oI-RY,XCWWqG1,?^A$kFPp=<+!63Kbjg +DI45ZIuf +R]AYeag<%0FED?U]Xde\Y99/DI45ZIufRSuo'Km+n)E8\OUbfm%bVqTkYP/Hn)R$JJs +=;7]KNhd"]n<>DHI:,+=*HhZq[^@QJkG;nun<>DI45ZMkHOtnU>GZ`Yo:t6OW'r\,t<<]BP:t;(kUeJr=*`b0_<&I0D"fa%Kn%oj@CC6#(s<)oTk!`]u6Cn<>DI45ZMkHP'T*BpeXtAWocjP +5ZIuf.Ss,rWocDh>mp]5!9?GsK/3K-zzzzzzzzzzz!!!#W0%8:u,9nF7Y?oKM5U(=Dlrh1DR[TZPkN]U +!kH[:5G`7]E+$Y3:r&G8J$jY?eaurL#Z +N.H.HO(`3P9<1Z:%3a=4?[VSP2(h,?`3Z<=!]M-Kq[Vab7^@h9ZK+Gi0HKikSY-+qseMDS;P4`hVfLmm +2'H.Gl%u9&73,p-id0p+uecuqNn@0AhJ#6cj=0>d70mE$=ohIi`1$dlB[ulf86IkDRYCH9!BAl.a\[e, +X%'<%@ps.^4=0<,1^%^C,qTs9L:Oi4>B_^._DhYCo@Bt4Ul)3.7=d/D24S-cQRl5+5IM`hW*7FZSk>OR +'a@o<&p%J*6YEJ5&X^bNm&X%n;/,/Gc=1fhAUkcD;,0KDREc$,KHHD`LSpRWHZa9Gcf\"i6'e=OKhU&)lQU9-Xrqk,`$4\0fS897/ +\N>jgnhq6iD?b@]/,iP&A#7m\T$rOTZm97"bp@$l\I`&O/@XNS$rV,1[O$(Bc_QXj1-AO``.pVNV',/= +q6d.5K1G.331jo#MB4$&V`UI!PZtuJG\$r31-0q=^b4Y)P_aEYFrqF.XfN$Yhg0T +p_BWgc_`-J#1Ru%uGsLcLZ")a24EBLRo#>7aQL3>0,IM$;;A_a;"4=7*@l)T>a;]'1&__^/iJ1PX8FD2 +Z/poGfk.9^;k1F_aK;a+b$BRVqHXm,[%hlSL^d*$.FBS2_*Uf/7? +pKV<;8Y$LtdJt\m3+hf$Q&Veg^9:#MTpV6aK5Q:3PqsV#&[f58&^I[qr$;4O-X$;!NgqJ2`RYMJ0VIbm +R-VoI1Ps+gf$=>WBeZ2c4NK%Lt34X7ue>^:r&q806Co+hYIG(o;HhZq;?a^.C#/Z/S.qXN#*?Thd`J"u +5]=WFG\omuMrNEs3C3WQ\]65e+\n%Yt[]GN6'&d'*if?d9>.*Y%cTY"nDeE6S@p2q.nA>c@>$@MEm^^H +]afLOL#2q,HET>'Z++G8nY#qr\J[liRY?ueUl)4RNLHcJ:A6QDS*^rks5$e*UgpqLbTlp+th&.83hS&s +gqk;uTcTYPQO,kAI?EuR)2%/:pLRIHlIDq09hjSNpoFuOa+!cphu2I<56qe"6asc$dS!6!/.')eo[?UB5.&tD?G3qJV^Lf +*aKZ7>pn7+;"3DL-]$/<8Ie0&jbEl"#:M5(u\JN9GP+SYAR$\/?X092,8nuCCpmJkWpHF:8pt!k#e$?) +=HhN,a0>@3jecuh?E,p[hZfL#L_q.Le(UP6Q2JnoUeQ/)'l4M=liSiaY(W6U.14-:k;0[QhnDV:,)cs+ +C_7==?aX<_AZ.)2#gU`PR&3p'FcVi'CdF#4EoB,%f]RlY*VI`-R>K[R6q''jXa2NrQ94!5=d\TUqQJsL +ue6mTKH7Im52r7ZJFD:LZ:GLCp0\?!kp(hQQB5^^I;u$&H_kW+)b*=K@hf4>uJ&(TrcuX&bLun9a,,WDK('Yr=U#%h0! +(])Ag1bc93*4khgN`gT3kb4;>N%)3pnf9`6PmH;=hfE6QiWAR.Z)mWoril +,-(>Mk1GNZUbK&Pg`>QBjkf2/CcrmmOHFU),SK'/eb8CbMjOIDET>'[a9Z^.$ie*=ET4nCT)>rQ1Ga+Gm+F5QlN*qM@8c2o561`azzz!2Su]! +MNt&`;~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 1032.72 36.36] CT +[1 0 0 1 0 0] CT +N +-954 -75.75 M +-954 310.5 L +237.25 310.5 L +237.25 -75.75 L +cp +clip +GS +0 0 translate +238 311 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 238 + /ImageType 1 + /DataSource Data + /ImageMatrix [238 0 0 311 0 0] + /Height 311 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0TIqVjT+33of&KA?9N)T +XT+PFGjo*>;cE&\n])aOok!$+kFK+Xo(C_ECS-%KfntQ^`L8Z"SppP#rr2oenaYqsYJ:#+b>1:oe>!44 +`ES?g:B=;[3p<5>=`6l$%[e&\.:E9BVJ,I^G +f,(pUigtMkm`",AHgeYi5+oX=fBcWa@k`Rl>7l>VeAS4ia8+936VUie\>pR^f!An:9)AP+RQt&LB@u/5""Ho>s(kjQ;uN=gVki +U6R61(*5"ni]\6hjis8R8'e"jbfQ)SrShg#/se*V0728L'_gR2laM-/ioI7+fa"l"R4:5iGAYh'G-CCk +eOoNC%mYSPq/;%GH&LXbd\#qEqP,hs&VNPFT&k?F3O8X>Q3NK0H*1=bSm+J_C\EB2c +IYg.*XJH:8?HqO0=o(ub7+g)An@F_AXEC/GFj3:Z4(TYnb)^h7E +`*,3.csp2tho=&pJUoe%bEa`6LHFkjmZ'Kk/R.dK=m;V0(S>6[EQo=f92!IELCF\%CYpdNVigQ?INKo&]X):>!!l>M5]"(S>6[]tM)gPnZFk013k]ENp,t +*Zi%8j$q"_E>OU]@.b%Wn(bJFmk-f;-lL]'aiFZY7Q+'uZ@S1$%?uffpb.tmN1!9KoilJ8lKRP)HO(KW +aaTJU5fnJ>X?amVPcR-lI[$p!aaTJU5fnJ>X?amVPcR-lI[$p!aaTJU5fnJ>X?amVPcR-lI[$p!aaTJU +5fnJ>XADj;,9nErR'KsLQhD!U:HkChIN71m";UTK:DTU65>"tLA3W[eTO^8Z"tLA3W[e +TO^8Z"tLA3W[eTO^8Z"tLA3W[eTO^8Z"tLA3W[eTO^8Z +"tLA3W[eTO^8Z"tLA3W[eTO^8Z"tLA3W[eTO^8Z"tLA3W[eTO^8Z"tLA3W[eTO^8Z"tLA3W[eTO^8Z"tLA3W[eTO^8Z"tLA3W[eTO^8Z"tLA3W[eTO^8Z"tL +A3W[eTO^8Z"tLA3W[eTO^8Z"tLA3W[eTO^8Z"tTWT92( +OWI2!/sf4X#k]R;cSn(KmV.91HFP=1:pM/h.o_-&NA'PgVISKeBk_:!DN6s=I.PTe[r/$*W;?5ZcTenH[1*TUQL< +PCJ,bE[^6niM\97,g1!.o4mC1u5J<(^42Ej>(_[etRG':#o]/K%BeZnSXs*i(Q-';tWaeqq,N]kK0J+L +oDEC+knGD_$sT&5"o/S=e,:HpH!M3l36'/+qdNiGk1]mKMFcTbd@@)3e#]MV`#MA7YQ]"3dVSiV!D::P +K7=ph%KW,q.I`K\B7V*!^+n<6X38S^lilfQH]mHs:JIedQ&;-J"AhrUZ*&Y]/RR-.^,GMp8fmG#*'?G-'@f3TtE)muF$[)>&lHp5;]fs5hZI&jo!!#9drW2ZJ&B"~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 574.8 -0.12] CT +[1 0 0 1 0 0] CT +N +0 0.25 M +0 386.5 L +1191.25 386.5 L +1191.25 0.25 L +cp +clip +GS +0 0 translate +954 76 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 954 + /ImageType 1 + /DataSource Data + /ImageMatrix [954 0 0 76 0 0] + /Height 76 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0W?"apb)i&EA&IIG_BTODrP_+ek:kDS3aaluK8e_`B+;.9P,)D&"TRrbg,,J*u#XRhc@[B?<+BE:i +&Ku(,HOu(-[#.6`O"@!CQ69l\f-S,P_`M[Y2m_!*rkE_6\UKd+R@TD`2&,J5g"GV(zzzzzzzzzzzzz=9 +(rLk5/Ea!!"-J(GB*";PR&:XBN$3\$pR'FO]hc++F!Y*W5'ERpg;QD!]<0/$lphA*;[WDdQFA;tsp2Hg +S5iVba?h$31'VKd]XT76XYlWf_HnEnu>mGKn1epUQ]QX>3Hrt2IKg$ +a1Rgpt/5^3/bmfqSGKJb6ST!!$,W_R+-CC=W0$\\)S$*dd.bpYPL&=/f/fR[UN,gX"KS?*f/b:`F*?,s`mHk?5_]?L)cC@Ha/sT$V:7Q!8D@ +Wj.2)QC6E+"'@4PAZN_1O%V9GB4]K.aCnH0fA=$YQrO'8LHg/tT@CG(*GH]9eZi +.U>Y?h[9X#)dqB`$MQcWUbX!!%pEb-X8l3bg<"?bSWRrquB6iJufuY-)6=q!"]KY$&*N(2[Rk)]UkY`" +mRbgc7?(a,V1Kps(ti,R7$29X\"a4$2imp$:5ambnq;Wr&)$ShA]m]tN5+l/TgFT/q,[NAo^u2-[P-rC +7IVIJ7%%lh^;?s(F%c!!)*:Ct%sgHhTF8g12iW5(#>k$+DX=r:.hL2TZuS_o'C#\9-t5)dFm(Z=V4F6D +7eB$B(2@E:'25GjQ6]::+%A8Cp +U+?.@Y[$&?XZ7BP>IFZcRB:Am2Wkn)(mP]K/&5=a>dAp1ZP1l&o>0`F@pe@Ed$lClPJsYM.`KDJjpqkY +[Z5!<<,(W77B(f<&9/e^`4-hk/]/Cr9oIR$t5gCqX\(59E(:36^#lD/De(*ZZ:CY50hXp1ZP1l&o>Pm\ +%Z#,eEU1ceFcZqu6*&%iJ7G!!$ES8cP#^,39CP[_B;_3W+:$o]bl?ikPcG:HnS"feWH3SFL]D#NLclEg +Z5qY?kN1a)D"Y!2*60C&.VulaBr?GB_U6nAjBCCXuIf*$$%_J,]A+*BOU^K"X3)3#L4ZT9_:)DJmpDWD +j4s5^`Ir\$OuK$ig9X74@3'4?5E)Gmd"agbSE9#9SnaNS1"gceeoF@aSN<]6A0qbW[U;4C.>,FcTI> +;JJbfOK"!<<+M\h[%(B%sb2[cNi_I[R8dQcgBi*OaB+&fs!`f%*lKnDp!U[F90XpJ"^`\`p#m]1^;h`2 +Q\5QHXaDFi3)Q!!!#?4tYMOgt^[i-koFH3&*6HFSYLhp@e4LJE=#OqsV:ToYhMI)Gq0IAf!!'f^H2-l;7n8>o`0JgBd*RlV\TI(6\QljqpTA@pHqdLECB4D8J;# +-CSG`<\o7;ID2rB"(p[6jQs#r#QhnFO=rr'suf3a#E)a&TI3+Z:=IU6PQ<<]D6,H1`E'r\,t<<]D6Rrd +$8If"!Rk04\p>d,;"Vr^/Cr6lE7?G)YABlg\aq;R;cgtr33:fW(HmRX?C<<]BP:fW(HmcL%hB&MQrs*] +3*Cp':o^\dF\>9"\*Y2"9>L(,M+SofGm83p5ZWk'FS!`]u6W^'PfWk/*%8ZS`MDnc%e(2[Zdgnq3UmF\ +[R.ISEc:J];dn./[2q0i]36reFVn<>DI45ZN#.8`skmT#5i9NiEFcF[o=5W[^hFJZ9&VFm&b5jcP +Z;m_jn^<>DItNhd"]n<>DItc@&k+TBZ7nmCiZ8/?K&gq9;[!`e'=<.V%V<)oTk!`e&*VWI=7,fO5t>V?'Oj,Y3$*L4OKi]WqM<>DItNhd"]n<>DIt:,+>iZY.T2hgE+UhnJ`$^?2^N:fW(HmRX?C<<]BP:fW(HmW;$-]QeGZcCOSf=oBBWZ_!b[q0i +]36reFVn<>DI45ZN"_,\:.[R+q34OcHI08?+pT"fa%Kn<>DIt/r$/qb6ft/g&.PD4-D'iDI45ZIuf\r.^\e$;:K=#PQ,lAhYI<)oTk!`]u6l7Rge9Zm +bt>hT%KW]Q@n:fW(H$<1#uWk0+21+b#pE+SWrWpWEX5ZIuf.Ss,rWpX=eb-\5]_j/IgWk'FS!`]u6W^' +PfWk+*3.FYRh$s,?:W9TD=$<1#uWWH08W9Q!iUeJr=0jNE0TrL2;.Ss,rWX;^*TW5U@OtnU>`,K;ZLT9 +c5W^'PfW[^hFJZA-I8BS<@&AsdX+0)msW<-'7W2`*_"ff.l+XtmG64?pRJ#MXmU^C($TW/&n'r^CML87 +Md$8Gf=r1U,POt':.JZ9&VDI45ZIuf\r.`rnX!USqn:-1_9Volh/J[OO$Pg]/"8b&F[o=5W[^hFJZ9&VFVdEnJ+ZJD)ar^.ZY( +5QPuDc5=#PQ,lAhYI<)oTk!`]u6l7RgeoCE*qN+9;hT%KW]Q@n:fW(H$<1#uWk0+27fC +!]oV#GC908-[0jNE0TrL2;.Ss,rWX;^*TW5U@P"%SdVb/c1.)"hIf?PL)r>'!mj2U;W^' +PfW[^hFJZA. + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 1032.72 -0.12] CT +[1 0 0 1 0 0] CT +N +-954 0.25 M +-954 386.5 L +237.25 386.5 L +237.25 0.25 L +cp +clip +GS +0 0 translate +238 76 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 238 + /ImageType 1 + /DataSource Data + /ImageMatrix [238 0 0 76 0 0] + /Height 76 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0S0kpbe(kp@f>HkOE\0DBDl!;\Q`Zg[0&3&MOXK9Wr9cu``n\:hPk>]=>j*CG'_.FEFe.F3YK#]>XIX?JW +9!4iJ4=+'*Eh8FE-ok)F'pP5dj9eN);fW$fk:*rnP4OoC6-4CEY40.OJ'a]?4hPpZ;dY)g;DN)c12TiC +D, + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 574.8 187.2] CT +N +0 0 M +0 310 L +953 310 L +953 0 L +cp +clip +1 GC +N +0 0 953 310 re +f +GR +GS +[0.48 0 0 0.48 574.8 224.64] CT +[1 0 0 1 0 0] CT +N +0 -78 M +0 309.5 L +1191.25 309.5 L +1191.25 -78 L +cp +clip +GS +0 0 translate +953 310 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 953 + /ImageType 1 + /DataSource Data + /ImageMatrix [953 0 0 310 0 0] + /Height 310 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlHSTE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!! +!"LhZ+\G + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 1032.24 224.64] CT +[1 0 0 1 0 0] CT +N +-953 -78 M +-953 309.5 L +238.25 309.5 L +238.25 -78 L +cp +clip +GS +0 0 translate +239 310 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 310 0 0] + /Height 310 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlV]TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzp_ +u9P$uu~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 574.8 187.2] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 387.5 L +1191.25 387.5 L +1191.25 0 L +cp +clip +GS +0 0 translate +953 78 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 953 + /ImageType 1 + /DataSource Data + /ImageMatrix [953 0 0 78 0 0] + /Height 78 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlQ&TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!+ +#lt)s+F~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 1032.24 187.2] CT +[1 0 0 1 0 0] CT +N +-953 0 M +-953 387.5 L +238.25 387.5 L +238.25 0 L +cp +clip +GS +0 0 translate +239 78 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 78 0 0] + /Height 78 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;!=]#/!5bE.WG`:P'EA+5zzzzzzzzzzzz!!'fe!EZk263~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 574.8 187.2] CT +N +0 0 M +0 310 L +953 310 L +953 0 L +cp +clip +0.941 GC +N +0 0 954 311 re +f +GR +GS +[0.6 0 0 0.6 574.8 187.2] CT +N +0 0 M +0 310 L +953 310 L +953 0 L +cp +clip +1 GC +N +0 0 954 311 re +f +GR +GS +[0.6 0 0 0.6 574.8 187.2] CT +N +0 0 M +0 310 L +953 310 L +953 0 L +cp +clip +1 GC +N +0 0 954 311 re +f +GR +GS +[0.48 0 0 0.48 574.8 224.16] CT +[1 0 0 1 0 0] CT +N +0 -77 M +0 310.5 L +1191.25 310.5 L +1191.25 -77 L +cp +clip +GS +0 0 translate +954 311 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 954 + /ImageType 1 + /DataSource Data + /ImageMatrix [954 0 0 311 0 0] + /Height 311 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0Ws(bSHg;iaHJ++P)IM*j@&0`Z.,e0*;5qF;cWK[iI'Tkq*Td]k.A1>-Hm"0%Ccf +)H$W>g]f3*qC'0(,`!b"<$Gb.CX[=pC+,l1Si% +WnI)%0Xo*?b/T4:k")L;<<]BP:fW(Hm:uF7EhcL\6dj!'1,$c5NJEdY%opl:<.V%V<)oTk!`e"'p8FMV +8D8;l:)K@FiaHEY6WJ1Qn<>DI45h2EJ1+FY8OuAks'*dUeH!&bp:t6OW'r\,t<<]BP:j!#fB$4)O +g#):\[+2OR0JI^m_ofuSWocjP5ZIuf.Ss,rWi^A#< +?p,dkH!3s(IYA(jXDE9_C6#(s<)oTk!`]u6g/nlhn<>DID?-gj) +H:ZcC[*0gOg>cUQj$Qgf,ZUM;!`]u6W^,+d=M-3$6dj8Wjb/2q/KRqN5#aC0;?a'M:fW(H$<6t`d7)SJ +,jfh[:)K@Bk$_i]6WJ1Qn<>DI45h05oc&*R*Fu(]t>_IA-*`b0_<&I0D"fa%K0#/s4P=LR!i0n+6$=9h"+_aa$ +El,WIR"prd%opl:<.V%V<)oTk6IDh@/iDu=Bs6!+_F9h2n?B4gTrL,9.Ss,rWX;^*.!/J61T2@X)GJ=Z +,3'+R<]3-@2+LOJW[^hFJZ9'rXX\\&JVU$*drN=@]UahCN=T%6O]6n3$<1#uW^9"P.USP.+fW_nS1lY3 +`l#s=LT9K-W^'PfW[^hFTnl^foDYcU1URBfY-X97Gi. +A`H-XF!ObYWWH08W2`[qWi8*Tl63.s[%))0\X,F[Cj`0rNhd"]n<>>j?26BpoGXuR6/LLtN/ljko +<&I0D"fa%K,bI:()BqPj=Z%cYKmqX:U)Y`KU8g5:.Ss,rWX;^*-q)U-T+Pp)l.99l +*QHgtl05=PXTo@Xm,,R-@Uc(j4eFla(@HJ9gprns_Muh>A`:"$i(ISpia>=uDt*4PiOe/LSLXR,^D5Z9VE2,ZUM;!`]u6WXsI+/7)uD +B%"rKbqRUQ^OEk>9=\:;[p6OgmEI^g:/29.%CNq[g1`PrkeJ26_3,D1RNnd5<>DI45ZNN*X(HI=i&6dJ +o?B4&VS.'6:Ap0!p[11ck00<=5'c_[kih6XUIY2f)&jN1p_7h0Hs0:&GS0)*&!lQYeJq-qW2`*_"fa%? +>;a#?5MJjm4$+Bng+Y>7h`*STpsDSR]m8e'Oc_=g?bCVn<>D70g2MpBD33M['UPH +meQJ;>>35b^1=<9f9ElelU/ih;:QXX'r\,t<<]BP6s)>4Qddoe3^#W3s4$JV`l>m46Mmt)Ggi?RLW7BT +Rsd0-BfRWh^`;=LiW*!'O]6n3$<1#uW^;A=Zb@Q$_kbK!b;48jPtL^nqJP)u;7fWsQMTM9X'/_3S"#o% +G!V'@/N:;s>a"ZbS7LM>*>'>D%T([q8JS2(5ZIuf.`>B<_=O2a-QO3J4`TILmF,ZKOK6+`@WHLpG"\49 +qtg/dVP]g\b@sbq=[/ONNn=gW+/iq7U^C($TW/&n'r%_n?rTl^Is7(%5Q?+HC[8V$^>$DPIr0G%T:_aC +R&I]!H$k!eE,`&XZAhA8*ec=qA7VLT)ul`t/LQ5hR%l]Egn:Z-Ot':.JZ9&VpRaQndc-nD?s6=b+.2(K=?N:W3Kbjgh.r7SG5XDrNr(_3&#\]g%\Co*(^mDW^'PfW[d);Wn1*.nWD>?[%,).XsG,i +2Ek(t7oBMj.Ss,rWX=$Rl?Ea/OOVI\m.`k@(Hed8I&Le?U^C($TW/&n'lmI-pQ,)4,kWoE-W(>s*`b0_ +<&I0D"fa%K[2(^2<%*Tbn2Ek(t +7oBMj.Ss,rWX=$ORZk4on;u/U[%-2hq-*9lZLOWg3Kbjg[4"Vg?*gf*lCj`0r +Nhd"]n<>E/Jc.f1epdj[r>#&=00"V8t.iTS1RNnd5<>DI45ZJ!V0c)ZTZ"mn`eUSV +8?+pT"fa%KUcFg.PPbm6*`b0_<&I0D +"fa%Kf8[A)SSFDPlM@:Wr-6A`H-XF!ObY +WWH08W2edYC9F.ECreul4AF!jDLRi.@:eIdDI45ZItXn<>?KRc/GLa)tK(IQd^!7I37s_ZLOWg3Kbjg +PSCj`0rNhd"]n<>@9i)X42jpt/GRR$JD0YL;sFZLOWg3Kbjg +o'W>c,U^C($TW/&n'f)^+or+C:P:eLA%h/umbfmH. +>DI45ZNNF +X1ESJ:e-YT>V8fI:A4GV+$P(^LsrYjT1a[F2+LOJW[^hFJZ9&+<6]U'8`-tPS^,.7Ed=c^ +f@+cn<>C0e$TT[aDI0fRgBK,6?cBu\&N>-)Eu8SQ6:Yd3emW]?4l:fW(H$<1$0XBO,3?u4k37kNN'S>>[B%1as.+0(bS +W<-'7W2`*_"gb4fb.mMOUD@iQ:?2M`LR!i01?1q2rnC;/ag!9#kpe!.iTS1RNnd5<>DI45ZIu?WeJ1n`\nl]e3ZsSZCc5`=P*Vt\%3B]B6;Pd]C1-b>ZLOWg3Kbjgn<>DI4ct-30K$g*D*L1@7(T*8X4KN@HW+q?g$<1#u +WWH08\uEiNgldF5Q"g%QG-;_QYd3emW]?4l:fW(H$<1$h\149E:-@mA9ZsUo)ON[hCj`0rNhd"]n +<>@Qqb,F)"%m)8inobcNZ\Og*%opl:<.V%V<)oTk6>';D(Qp\$fMS'&)sDS9ortalTrL,9.Ss,rWX;^* +kb'EWMeeB/*L1?LJY%?HiaHEY6WJ1Qn<>DI4cu)iQjgKHe;43^hlYU&'Yd3emW]?4l:fW(H$<1#= +X"'lb-Tpao9Zp0'0JIiUg%\Co*(^mDW^'PfW[d@?Q$4D9OG=jABt9LH#A+Js)]u)K,H1`E'r\,te +UB_i`<2Sae[/Iee_ofuSWocjP5ZIuf.Ss-=5ugD9hK[[MR?fq]p5=qnXDE9_C6#(s<)oTk!`]uD=(PA! +R>2fJBt6%e%Eoko2Ek(t7oBMj.Ss,rWX>q0jjM9e4RB"?b8kA.@.ph1nY)sCOt':.JZ9&V@$TobKJ'r6UNXc1G/#N0JKa.Fn>4rc0if_ +glj&eo3G\<0>NG#*(^mDW^'PfW[dr(n1^WCX\O)i7un_YhnMD"[k4K=B@!0'4.JBVmUi#/A$c%g/bc9m +7@8S][>X(^*%,oN,ZUM;!`]u6C@ALT?4Hsob,3nM;9S(ljQ'j$J,eKFLKdQtiCi,>/]QgfR$N*r3IiFc@%59K6JePaVOt':.JZ9&V[D]!p +e'W6[04):^?B*43Vra*i:QCHq*^+hVn!1/_Z,_nI\+l;XQ>J<0lZ$Am7oBMj.Ss,rWb-Jl&u@4(e/bIK +Ocbd>HhUjZG]@nMG'\HqHoaAPr:K7&B(t2rP>\B%)/Zlf.Q)IYd]:tRhkd$#nB`iS9o'6M'r\,t<<]Ck +i4HbX[N2b:^6Zt([5sjRbMc))*^$BL]!SgYmXP66q%hG"ZS/"^4M"M'bgR]c8?+pT"fa%KeGqg:en_dj +:/=[;5IJ,.Yu1PO*N/!X*BJ:UI!iT[=.,A6n]E-q:@.+6W^'PfW[^iQ=,b;$BXjfi0/(Z$WDkA??YqqX +LTf"Jc#('87[TJh-750u"4OP=/g-q*M;9.C'r\,t<<]DrUrfRZ-"P8CZ(nb!QE.4$R%0\Jh%F>g^:q=\ +WMsM0+OdV_j1"Sf@."IOG&np/TW/&n'r]iM7dme$gQO(R9[!&!o+McN[FZmhO,je]%c4a;-[GB&-DR?2 +,9nH!lg)gp6)J4IQRghO3+?:`)CK]L,ZUM;!`]u6g:cXP\tl>dPA.T(3p52Lg$5JD0KsXE<*s!>ojuJ< +^]4:s-VmqDK1sGq03=I+1Ki`PA<*Gm<)oTk!`ck^ne[OhC/1,&>V7Z^/j=daI)gRh/M$b)Z4+sS3!G]p +W<-'7W2`,5DX@#-r)>Q:+XtmG_J^sJ^hh'/nIc_&.Ss,rWX;_m=<#kKV5cNd8XYkZ?<^Pb_JI0.nIc_& +.Ss,rWX;_m9RBQb;:V1lUeJr=gK0]!0O+$c]L7LM$<1#uWWH0^d.U7mWG9^G;Pn#Z"tRm4gbTJ]94USn +5ZIuf.T!NYS\1naWocDhAQi,J]Wqsi^%$'S7#%KE<)oTk!`e"'iU7jceXVDj9Zmc;=-eaupV=]:&fHi^ +:fW(H$<5hakJ+#m$2'lDL"3J,"#63 +W[^hFJZ:fqlLg??2XA4W^c<<]BP:plR+J(9@Tjuao#>#s:$AJpjskM^ZB$qV24 +W^'PfW]&DFDrjpJS;3n6b6i*g/FQcj+V2UdA4W^c<<]BP:pmRb^,o9DS;3n6b6mX>/D$-PKSSS61*fkm +WWH08W7jM_5P_.U3=e]LQ5)G_=U+#sGrT+S6W+)f.Ss,rWnU[h8U&30*fcT.OApe2$<1"R +>h)f&>[+_

UWUQ"6Bj&9$AJpk`*&!EtW<-'7W2`[e +W[V8@[6Ra@U.\ZBQPUDQQBmh[]I216Jn/F#5;7-c1.P4GW[^hFTdWpirU*gQW[Ugkh:U@>IJS%m?f19Q +%NIG>`o\'2B3J>4*A#0Yf+LhEk")L;<<]BP'V]@-:G`f\C:Y*N:RsO(1c0=Op?euaXd,0:;Q2K,0X/4& +h!G#6b6l+=V81]IitQ$aU^C($TW1?Ve/;LY:qOYBFgE' +%a:Gpb`PkUWX;^*Lqd[?QXGffC?j$,Y-5%d\ohe"AYjQCV,@Wkn:_5dRf*tuAHhnG;TOEW;ij#&.Ss,r +WX=kic0-*XjAiOJ6IMo9YD.>thS"9\m_H32ON,+7]QYsd'P*6"$<1#uW^=p0Z[5Frk,K:r-bY$0rnu_m +`5G'%qs<02WDpHf%ZQI-WW*WU9;S8)m99c)@/N<7MHL +Uc32HBR!g@1M=uiq^Y@`$J?CMYn,'KK$9?VJZ9&Vq,,sjaLSRVe$CS#tVk6GHo5M?1L85/UY(k[<<]BPjL)#J;)ua:!^kVI]oA/,Pbt +r:F_om],Ck8JS2(5ZNM#g"c.gcFo2.AH4="KADI4OFsPnI$,i^D#*$V?`<>DI4i4B2STkGE!COApe2$<1$p +=>f9:EoOE?c?Vt'[&i1oA_WKBJN6M+F+U1p<)oTkK"J%.^;alH];k\i+XtmGJqoWY5Y_OGS5mf9Ot':. +JZ9'kWoiA(d>iTSNIlq]9ZmbaGZ`XZ\UV"h0!"h< +;?a'M:fY>)eVH]V`)"p>GY#uaXPdMu]A\*Ec>-G#8?+pT"fa&^W#F9dS2dJd(Cs**Q5)N`CmQ+PbW2ik +'hK.=W^'Pf(KL'Mjo6@3W#?H_8XYkZ4KNAn]Ulb+?.C6a.Ss,rWX@E\Fo;/2fV+c4>p?6L<>DI4OE&ef8*)#fW\O(+P\F::_oh\kjhRD`WrA)ZJZ9&V1$kSL,qTb6n[c91qp4gVC1t&BVcJCg`:!W[B&lTW/&n'sah(loU+c +p/Q2$-f*G-3.:XF?XM^Y"WHAm/5kk@!iP$pZpTh&rZu<>DI4O?qFL8*,DP +-o\nMX(a$F(U&4pL0%W]ECC"fa%K +FjRp/QZ%PHM*mhn!rGAS%]]9;PMm;so>I(Z)grjQ,CKcqsVo^pL0SiPFM]@#hI+ejuf+<<]BP +Ufu=7Q2Jn3YF=cduPh,:dh[;R&L@p_+&/ST?T/XOXrFg_agp[6iV)B(YW +jN,?\7`4J7AnL2AK*Se[Q^3rS`-_L]q%hG"ZS/"fQXbGWRHY+*U90k)Ot':.JZ9&k<%ZP)b#Rf/jr,S; +St<*7C:AXA^3T<^It.L'A&k$tapf@PFD-&L]\-ASQ5*jm=L&m5A$274Ot':.JZ9(JWh-@ZRMtm"Et+QeOU +p/Q2$-bX]j=r;&@0-]"EolV(7PEWCY_X-+1f,#e$Aq,MK=X!cs-&WkJ`EtKF,ZUM;!`]tgDD5Bu\Uc.=O"/r$RTcd,B\9[mCL4?bqm3&l0GcCOIf7un^NNfK-YN3'4d2uCX`Q5'aHYbXH: +(SYZU8?+pT"fa&NWYThY:=rVOg.ZhQ`f5^SX#P1_9_.N8S7cJIX*5&+nYoHbC@@;`rql.KH1IcM5L-X; +:m?SYh1<*bGZ`X`V"cc5JZ>T$U^C($TW3Tle`'jfmS3&Kjuao#>#t-sZKXqr?nPL1<01(1WX;^* +0WrQsr!N>$3=e]LQ5)N`CoUANQjZtqO/*+^#t-sZ<>TabXJ]b5Z.cc.Ss-= +VlG]u9sCgio8o2N=i&"uAk[/pHE*DYW<-'7W2e3Ce\]'/8Mf_6juao#>#t-sZ5F<n<>E*Hb,F).ql2Xe8XYkZ4KPUlV?8VSc&ktVWX;^*kb]i) +nkRh=c$;k&[&i1oA\G;eR&Oh\U^C($TW1?!:sjWYQ/ +@:(nT+XtmGJqoWa`SuYs<&I0D"fa%K&FN66!I?T%!i.FYSSLR!"[kCK&$k")L;<<]BPZs/em\J+>1 +juao#>#t-sZ6&Zs0N6LA8JS2(5ZNNHW\Q&JLjdgDLSRVe$6E7!W?*[*:K;H]n<>F5fb.EaWLjdgD +LSRVe$6E7!W?.Y.TW1#8.Ss,rWX:ghja(p;@p_+V+XtmGJqoWaX4r2nWocjP5ZIuf.dTus;7S4DX6)Mi +AQi.(Yd1ES2)%tZ*(^mDW^'R<<`L$&]>_L!c9kL,AH`SplWrZU1KD\^<.V%V<)mU8Q$4D9!W/lW%nW1T +'g/R6%Wlq^VQ)Y>.Ss,rWX=`dEY48eYcjMeOHaH^_8FFX6RP+bUT->;.Ss,rWX9381+N$WIFXjCUeJr= +*`b0Xg)cW\C6#(s<)oTk_Y1!gaqiW2c$;k&[&i1oAb2_2JXNP#8?+pT"fa%gYKE],/[2FIo8o2N=i&"u +k"H_,Br[UHW<-'7W2f>jGZ`Ys +fkFikW]?4l:fW(H$GTPO<&V_0C/1+;I=6NmIQm\uNq['f8HC2`DQP]XYI2 +4?OSfjqd](>#sQhkt.(iq>Z2)Zei"?YbN[E?b=VrX.,[!XDB%)@anD:[FUh9sLHC:fW(H`jiC]%/[%b7FH4er;?B^g8AA"%eDL*Elp@D$oIk#P>[5J +X,iTCf4Vc+nU46!W]Bi^<0gqm0W.P^`oHabokW0^%1WmIo:Q&!EDNHC"V):ec(=mlK+C0@i5>8@;:u3W +J2po`\[f99DttD7FQgi1-S=bsHRGXfkqY:V2E$lo-:HkT'2"[B'B+QS559s1j6'^[mde'J#QoUfD+Qf0 +M9G#O>+PLCKhjWd2o#Clq]eUkm+]"Q`PB]=b6hOV-5tq/ANonIK+I2OcRPDn!&3#7dcp#\qBphQ2E'F) +cg'e1?XM^$F6B"j,>?8f*%[DmBq,tlC-G0\e\$9+:S0hQ^Y@]) +i.iD'f^'\g>#sQh;4spLOt':.JZ9&V<_lDP@f;uBj$">7=hK$8?+pT +"fa%Kn<>DI45ZMm:UmmjC$O[?CX/e>=PA+0NK11?kk")L;<<]BP +:fW(Hjuao#>#t-sZLOWg3Kbjgn<>DHIc9kL,AH`Sp)]u)K +,H1`E'r\,t<<]Cko8o2N=i&"u`eUSV8?+pT"fa%K>H%oj@CC6#(s<)oTk!`]u6 +Cn +<>DI45ZMkHP'Yc8peXtAWocjP5ZIuf.Ss,rWocDhornnqTrJ/oc&ktVWX;^*TW/&nc$;kF@2n2n<<]Ck +,H1`E'r\,t<<]Cko8qJ>2T1BN$A:1pjp.4>\lO1Gb6fL;[ +J0A)m4GdsZXmeU@,+JHOlHaa0`QD0'bS,i/F"P:'.HptIiLi^A9GJ(@g9M1L5/h6.3Io!7,Nh#$s6YD7 +mgX$-4GhuCq[hdjDhq0)5`^"nZqpu.!2Dd'lG5C^E@h>c;ThbAT4%S'.d:JXb^LBj(T*]s]5bJ_=eb1d +K.7un^FSfoc9ZADMX:5+HE[r:.6qs)>H8uYbsh`\m;OfZ#Ba$0Ltj3Va_DD(j4EH*^\dgQ>"ef,?bE*a +!/5LZopB@!0'R-2bc]3-N:R.YXagVUfo[H`Yd07Nc^Vf5NS*$"$pTtL^LDn[iOk6d?dqWb,_2_E(Q>e( +IcIei)liOaT,XPS9hX`rWI-fo2iqsCkR+$X*/1b<=mUrSN<%b"LN9du_dedI2G!ECR@B\8iP0X9qXrPo@3u;i>e>/2[;C`Jg=f +^i5X,/=e*mU>AJ=CqlaLcf$>5sa/Rd9>D1AQguH3B9 +)V1mIZ67-2CG(Z?))msk@!lOA^(#9S?_LHk\[bZ\.f8A:(EO,#N+mF*`&p`f(9p%*^f2rAurrel!ggo8 +&.n(t`jcC@IC)kn%$ODlC9?B*3'b9C#k?4Cc?h7K$HL?)YXmD=L<0\6aD%fZ'ls3,e1@PBYsouB;rEFW +L2C"^YNP:&jj7un]Sg@rbBfGHgTmEs_E>W@Ei/hVn7opp<`#t*OZF6E>C"[fW&ZTK9`&Veh!HhRC9msk +A`J,XNTeudoiiBRAdt>?Wpd\!/jEXI1AX +Vo>7l_]:p0LBP6VU>r9:,Odep:)/ZUTX/)7a\DeNhJaH7\d)]Mpu9+8[D]",BIrV,3)V#0lQ@pn`DM\e +&'HL%\/55D#N.FYSfE#*lki'HbZV5:#-C-@(GI"n,TGIMJG$4Ym>n%IG"4?l'FmDYLW>'R\"@c"V7,O5 +eq_1s+](qqq_PlB(Q?AYAnZu#0mc'r/>3-OX*UU%G\e^_CJ^@2[tlOCt@^]! +P<^\cjU_F\nDQ&e0/GgDsEi=A0Nn3bcr(7R[H%ZQO1B>#$?G5M"#l?*>nI!U$(+8B=$HV(keG9m$ZUWQ6!\@Ea@$u*'\ +nbiRLts5^F%9e[`6$D&:+rdk\,Gl:(CAq6.R4])K]tqt@:uReZjMJ'Y[T7.k!E[T>cmktce$3Uc1qk_T +s#C7fMM3Eo2#L;H=$&@;?[Ep1L5o('4^n?&dnKNi2p,!ZqoPtJU4eZ2dKqtn8QG`&I:e[]Rae0eHT9K3UAs%N[aBmDA>Bhk`Y`_SJDq3&iu]S%ST3=*X)%nr(>Ya6T%nN/s$TIC8p__L9:uO]1GX*&dJ@tp]qdB]-^T&Qjo<3ZBMb>rG$AX-(Fj&>0-9H\SpqX[1GY""gAmDunZ1c +Jpa,V2#r*tOsfuf9n2]D[GS(HfX%CRL$Ohd*PUsl9" +II'-?b;B+$NBi]cM\V<$t[pq?[-%zzz!$GkQ&*UGn)?~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 1032.72 224.16] CT +[1 0 0 1 0 0] CT +N +-954 -77 M +-954 310.5 L +237.25 310.5 L +237.25 -77 L +cp +clip +GS +0 0 translate +238 311 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 238 + /ImageType 1 + /DataSource Data + /ImageMatrix [238 0 0 311 0 0] + /Height 311 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WH\bY_"30jQKSW#a&H*aa,.M%t6';d^_P2O3ZD*#.72?J$QAX&;DC,Q"78u\&Jr!!P,UFB.&V>gi +/@!PrP*3cqPGKdff[XP[kjU[(AoFh6cZ=9Lmg#!21M:=W3W#@khD8Zda9\6-^V@PO+gdr'NfL]+E7*q; +mB(^@D2=AH.+s07o-i:CP4L*TJWfUQfn#=X.+s07o-i:CP4L*TJWfUQfn#=X.+s07o-i:CP4L*TJWfUQ +fn#=X.+s07o-i:CP4L*TJWfUQfn#=X.+s07o-i:CP4L*TJWfUQfn#=X.+s07o-i:CP4L*TJWfUQfn#=X +.+s07o-i:CP4L*TJWfUQfn#=X.+s07o-i:CP4L*TJWfUQfjRK!p\4FV@bSE)]':>'lfmj*m[/t%@=g6, +1++#;EZQMg:i[U'4&Br=,s+qD*[NnTHHH1S)jsG-D,>9/6U5]hEns)JF&6o56U5]hEns)JF&6o56U5]h +Ens)JF&6o56U5]hEns*%3HF1OIt.Kc(C^ia*^4uHpYUImoG3H/5fNGlK"L@4a1//tHnEp3WtetPL;nak'k +?Z,\uLEAADQX4uPbl'!$EKbkEg=V:4[VTZf.pKK#eK*.UghDSn%CBenA:JC>I9cc4aXUaeO,*%BkMkapYUIe +=4_Ir>8kNWb:gWsg9mum;-20$)=Q73OrH?f;9?tR@9V,ZXLh_"j3&sV]V9>rY@%>"`ucfNc/B"-P@8HF +[H,T%2]!3C:L3qaX05j6?pRYk-HYhQmG#*WEQ&YrLDSPlf#\8!Nud'1SiqEqSN?GsB:iosZXIL-]&K*4GJ'+3>bHjAZ'*LU +J\K]?4i+o[D=L.WE8\O!5CL2-[Dl7\>'Q,+qlHLGRG`:bT<;%*[g=f2U#bIorKa*fYb(:U +7<`sb-IQr3`"A#/8hQQNG`UmN>AhgqTpXK5F0\gSjTIYOaeJ*EG'4Wml`>0?0bc";3l.?YDGkN26a/)l +[$m*>baDCXH+@&UC?8]9JTh%bdn`I\/:$^@ +]u\=c;>bqdRmjM\h^-J@Z>H>$c=*D7>c`24#WTd@madC%Wo? +5?_:2.s&ak*Fo)hHK2\A6cjH]TmiFOQ0#fs^nc<,g:k;8lFSG,F&AoaV7N>k:eeK!*US)"\aCVGUbm"* +Fn,%G0/r2$.Cnji>]_fLCYb^2c%6*,-N0:-kDtel*l>m0ldi2-2fB`W*,OVO;KCS\5]]bBh*XGK:ibAZ +5]]aWg;\5,B_@Nm&c]%0#>3::A-Y`PULXU%cD+nT9$X2B#>3::A-Y`PULXU%cD+nT54(:i:]%g*I+n#t +eB=@u5fn;9lp/[o`FV#WA@@(F0Yfmk>AMe +-0J.2""!,-Z3)E9;6g9Mk>AMe-0J.2""!,-Z3)E9;6g9Mk>AMe-0J.2""!,-Z3)E9;6g9Mk>AMe-0J.2 +""!,-Z3)E9;6g9Mk>AMe-0J.2""!,-Z3)E9;6g9Mk>AMe-0J.2""!,-Z3)E9;6g9Mk>AMe-0J.2""!,- +Z3)E9;6g9Mk>AMe-0J.2""!,-Z3)E9;6g9Mk>AMe-0J.2""!,-Z3)E9;6g9Mk>AMe-0J.2""!,-Z3)E9 +;6g9Mk>AMeTD"bpVu9p%54*Oul=E^KT]A4-G+dnY8p6lg4A'dij?-%XT]A4-G+dnY8p6lg4A'dij?-%X +T]A4-G+dnY8p6lg4A'dij?-%XT]A4-G+dnY8p6lg4A'dij?-%XT]A4-G+dnY8p6lg4A'dij?-%XT]A4- +G+dnY8p6lg4A'dij?-%XT]A4-G+dnY8p6lg4A'dij?-%XT]A4-G+dnY8p6lg4A'dij?-%XT]A4-G+dnY +8p6lg4A'dij?-%XT]A4-G+dnY8p6lg4A'dij?-%XT]A4-G2UhuoD#]M$c&\=c9T(eaTe!"8')7*S4C[2 +Pak7c%[kB)eUDb!b(n])`@2JlX-E+)7,L]1VpIf7X?:u-b=D;TjCrCo6,FPsrclGgZ!u7`hoUAk#TYLd-2rIu8/\GuR*)bRj9c9'X\?!DciDr3bGE8nfm)FiDW%NRU+6`Ro%)t +bKOieoJ@25Jgrl`\&U=gDT8p?h^N>-c^tqKCJn?0.Ym?hpEp!cntN3Z1Bi9T(ciJ/L-[s[u0LH=e'ihiKEjPl"l4]hA\]Qg^,;! +Jm'gXTOem!'@ie]$XT0Bqt`JRBZ2Ussh(=l +aalfV#YBf3a"jo'_HRac[sr55T0PK5,7u9.o'=d>TeB4T+<-?ZpU9P%QNoXS*7Y:rqY_6Co,%MK1s/_!!'f6r + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 574.8 187.2] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 387.5 L +1191.25 387.5 L +1191.25 0 L +cp +clip +GS +0 0 translate +954 77 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 954 + /ImageType 1 + /DataSource Data + /ImageMatrix [954 0 0 77 0 0] + /Height 77 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WIq4lB+33n+PFYD09JW.acH/[)O\YU?'$8G#reP**Rm^k/6rD&OM'SLq]6[Yzzzzzzzzzzzz!!!"Ld#F +!RmBZcm!'n&oWiGX\nerDbZL-#edUG;feC71`J3.r@Yl4%I^$Fnca*-k(AI#krqmO,if@SX2hEI,*g(A +MshHa5cQoAp)OsR#%TD!9%!!!!iR[Z6Sg;LL=h7@DaCtuPJG.<&%r\P-6SX-n"]8MQ(CtARMU\4BUQ^3 +rk!@oWL/mPn_?XLQil-_6]hZ3]W!.6jt7n4@J>\N/,:J]3=CE/tl*Q5p"TSNfZ5blF,\)@`*'\o-m[A6k_V;PO;-3p[4$$Bts<2jic&b[C*Cg,pd_"qk9seaEFe_fbW>_`d% +AhihC3-Veu=gJ,_\%0C%cbL`bDdD/H\u*]eCVMGaES!;ImXfW`33`X[C!<23d&Rl@Cp5pDm]P62fEMcG5KqAC'1\e82Sdbl^$qpMM_ +c<\ZDmVNf[#6h*R7SX&m>;qsE.I2W9m-VR\nk!!'_j,9nH)k09A[It"btf54['G]C*Oh,RER<*37iZ08[1^"o +P[)l2<7BNcGu*mW*XO+uL^B4klTP-t6d4(cKQAXdpK>?fo:auq>g3Bo^CQ^=&nY\dnGFT1ciNXjgS\@? +e3AK(UL!.\!P>AIa3X]r9ic*k'hN48esjiq@JAPN3ch?d:e=m:*fVIc681DY!j2Ak3BV+[/8NN\eTT/U +W@PiK]&:WkZHc^d.AiPL<:V@C5I_p4f7Vt2:JX3`.=,oK?P!!!"L%,Kaq2EFl?=1ark2fI!fc[Yc]A[I +)ZI^@_5AW,:pR[/#BIYDVl/hS4Br!@N#[Va3-@_&DuZ-OpigtE8Xn)H3R%f>teZTW0LNj%FB!!!#)=g` +"pS2kYFLPK_;[SaT0U*>'T_hSc#S8?5Te$Al-PA'lS\80:U,<,l4#Mg2Mj>c(^drIL?[Z*1$gWrNY/1E +/&c$b&\iO3FOVo4buhI1gY:K:g);PTLo+ +amb/19jLi_1H[r:0lDAJ8U32Xs@jB&C,Q%l!&,i@:#.ab9R;E$\$suO=EensUSFTt]tLGG.W>6cZ(p +WlnS-Y\fAbfLr;:q(>%_L2eZ2d'X]oH4g7tBP^3K1bNZ%4oUU;*o5!R)cjeknH\i%el0ZOtW];6`q=72 +,PIeDukqs/(-M@%S"4Zh\Q!!!!iZEC>_pTD2GT;Z?(o9Lt4U,Vi"N4O)ncM6\^N:6>Dq:8hFG37)@>@1 +a0Z0n?aVoN'YG&2D`?YYTsb@@0J7@R7+'gIMdNd]m'KcGT5qlm\KB(CZ0!!!!aA8#YTCL"mB,\Jne0OW +r/_hSaYk2_BrFE_q)Gr5DpK7edoLT7ASRf:>Y!rr<$hi>Fb^ARp,?+Y:)p5&bL!!!%6DJj?/D0=a5rV5 +pCffgDV!!",ad3@lNf+%i^!!!iTs3?k;[Pn$OCnCt5zzzi1lnE!!%P!K@u]ZBBAk7)c[WOl5`G2W2`*_ +"fa%Ke[lBUL2[XE6WF;iH:Lj:W[^hFJZ9&Voe(on+e1pj:fW(HhN:cgWX;^*TW/&n]aGut#j7:3<)oTk +G9g1]WWH08W2`*_mm9P`_DrkP<>DIt*D%!EW^'PfW[^iq]+C-[E"9uW<<]CK7oBMj.Ss,rWX;_u/qg#D +S3ujD#kpfR8"a&H:Lj:W[^hFJZ9&Voe(on9Zmbd4L<-sK^d24%op:fW<-'7W2`*_"fckb6;j[lKb0j/jIrSt,ZUM;!`]u6W^'SQ +6:f8+X:W6)Rlj[CNhd"]n<>DIt>mO#iQ5)`2As8"MhN:cgWX;^*TW/&n]aGu4e$;:GcYW/KeN8pD +:fW(H$<1#uWcoU3AQi+?iL*C]Wd705"fa%K:iLBiJtFA\V,EsuYSj&*(d9eI^Qnq#oo>gT<)oTk!`]u6l9VkZb+>KlF?9As.krg*JUuJZ?7ZF_oo>gT<)oTk +!`]u6l9QmWacL<@Wi(!_mQH!MY$K6'&qAeGVFf*hJU(jPYp`H!4-D'ik%\:E9,;!PccUnso!FEI0$5Q<8f096Xi'-1>^ +@.M8[%*UNCMa`2shN:cgWX;^*TW/&n^L!5,b("(g[-deeo?fL(n(ta)l>OD^[[NY9q.oM0;4sq5,ZUM; +!`]u6W^,+agPhs."-moh)Z~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 1032.72 187.2] CT +[1 0 0 1 0 0] CT +N +-954 0 M +-954 387.5 L +237.25 387.5 L +237.25 0 L +cp +clip +GS +0 0 translate +238 77 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 238 + /ImageType 1 + /DataSource Data + /ImageMatrix [238 0 0 77 0 0] + /Height 77 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0R!K"\o'L]d;3=g6G>EsAHH5aZ*0.!1J$OFo`KY61Bzzzzz!!!#7Vu)#UG4kb&F_nd"eXk#%XP1#V +JlR.U?a+:kjpP5WfmLW94e"*,[:f(7X7gAD@+Cjn(Tc=PNoTCp\030m?E_u2O)RHYmOWOr'A<;t>O'HV.U@E_jdb9("-R6-2890.=B/j96k(Pe<[MSrsnSgf*cqP']f-:i]@R$VKh9 +H/W#Ma5R#I^X)*)cZ$W\=7YD1gh34Ah*"NTmN1OQ\NeunMt?D3kMO71P']f-:i]@R$VKh9GsTP8,qg[W +VrWP1-3"!sjhMr~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 574.8 375.6] CT +N +0 0 M +0 309 L +953 309 L +953 0 L +cp +clip +1 GC +N +0 0 953 309 re +f +GR +GS +[0.48 0 0 0.48 574.8 413.04] CT +[1 0 0 1 0 0] CT +N +0 -78 M +0 308.25 L +1191.25 308.25 L +1191.25 -78 L +cp +clip +GS +0 0 translate +953 309 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 953 + /ImageType 1 + /DataSource Data + /ImageMatrix [953 0 0 309 0 0] + /Height 309 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;JH,ZM!5fq/l + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 1032.24 413.04] CT +[1 0 0 1 0 0] CT +N +-953 -78 M +-953 308.25 L +238.25 308.25 L +238.25 -78 L +cp +clip +GS +0 0 translate +239 309 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 309 0 0] + /Height 309 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;!=]#/!5bE.WG`8*TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!!! +#WfDo,d64s~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 574.8 375.6] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 386.25 L +1191.25 386.25 L +1191.25 0 L +cp +clip +GS +0 0 translate +953 78 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 953 + /ImageType 1 + /DataSource Data + /ImageMatrix [953 0 0 78 0 0] + /Height 78 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;0`_7S!5bE.WFlQ&TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!+ +#lt)s+F~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 1032.24 375.6] CT +[1 0 0 1 0 0] CT +N +-953 0 M +-953 386.25 L +238.25 386.25 L +238.25 0 L +cp +clip +GS +0 0 translate +239 78 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 239 + /ImageType 1 + /DataSource Data + /ImageMatrix [239 0 0 78 0 0] + /Height 78 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0;!=]#/!5bE.WG`:P'EA+5zzzzzzzzzzzz!!'fe!EZk263~> + +%AXGEndBitmap +GR +GR +GS +[0.6 0 0 0.6 574.8 375.6] CT +N +0 0 M +0 309 L +953 309 L +953 0 L +cp +clip +0.941 GC +N +0 0 954 310 re +f +GR +GS +[0.6 0 0 0.6 574.8 375.6] CT +N +0 0 M +0 309 L +953 309 L +953 0 L +cp +clip +1 GC +N +0 0 954 310 re +f +GR +GS +[0.6 0 0 0.6 574.8 375.6] CT +N +0 0 M +0 309 L +953 309 L +953 0 L +cp +clip +1 GC +N +0 0 954 310 re +f +GR +GS +[0.48 0 0 0.48 574.8 412.56] CT +[1 0 0 1 0 0] CT +N +0 -77 M +0 309.25 L +1191.25 309.25 L +1191.25 -77 L +cp +clip +GS +0 0 translate +954 310 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 954 + /ImageType 1 + /DataSource Data + /ImageMatrix [954 0 0 310 0 0] + /Height 310 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0W@;+3SrV,j^j$3QVHglNr4p`Kj&gE9n&1hB'MRK<'/[?KbJjb3Cip_eh[;:Y8:c?b;Hs4Y>< +rUncB5D9/A24R5E<[Cj*dbVN2rp.=JHmk4l2:AX559Ag"D= +C*_DOdC`TfJlN+XNT=7iGuc0#QAanM6Ek2aP7jrhY\GH81agGA1D\dq)_jQ`scU?$!&?S23MaCjB7K'=tZ7&$c/k%9M2N=_5`W& +b9YDK,hI(a]NGM@%;/Rj<=)]cjB,]WtMKPagFh5X@@4^(X8G'@+B3C-!6F?eOZiSP%QY8CUn-8/-N#.1F^/?"KP"4 +/X&;tO^-'uo4B.J24R5E<[Cj*P&$KH=cKd;C\d\kgN.FWCVPjERGc=VY\H.]'!+^0C*_Cdag2nB?d#d^ +ZX$jBj5]08^R8l*i6=TmC,hCiX@f^3,hFfnZPj-Vb;1q14ZtrB$+lKRiQX]nC,hCiX@f^3,hFfnZPj-S +bI(MjA7T6*[V^BcmWC*_`LDQheSli]=I!:E8?QNeB/L=1QKRGoGOF73k007c&$G#oGd@s_)U>,]WtMKP +agFh5X@=Bu\%K5\puL[UFtHe7RtY8#E$cl5Q!i-5Y%P"M:p$XnEeQS"3pZdSW=u*/tcD1TD'!*"ncRk>CX-%H!gbSDc7WRH.M1jB=1)2[dI%iClkJ.`&-I>g"D=C*_DOdC`TfJlN+XNT=7iGuc0# +QAanM6Ek2aP7jrhY\GH81cU?$!&?S23MaCjB7K' +=tZ7&$c/k%9M2N=_5`W&b9YDK,hI(a]NGM@%;/Rj<=)]cjBVp@7JlT^VP[ILCn.>g#S-Ag(86S4O#f-!3$fCRO6dNT=7qRPtVjWo6WDYU[Jh +O^-'TcYB9,[J]!='g<5]1;TH6@+B3C-!6F?eOZiSP%QZ#/$7oZ]fn;22)dH1pdAB1"E,'-jZ`Y/JGd"#Z_CI;M%mT-4)sF7.hoBA[rEA>H9,lfFapCRO,*6Ek2aP7jrhY\GH81[qtIQae_f9ageU3p\X!QY/-N#.1F^/?"KP"4/X&;tOk-k)-RL1gVG3Pjop))=SO\_^IJ/YI +H[F5'*ZZ7qs0&]4Z1MLLGP?^p%p&SPgKnDu@,SEC.=I:Uoi!9#D2n7EhG24R5E<[Cj*P&$KH=cN&G5Fpm%fsAlFbI;BFlKRPINp"O+al24;k1;'n%1RH'FuI'N +@qK="c0Xc7WRH.M1jB=1)2[dI%iClkJ.`&-I>g"D=C*_DOdC`TfJlN+XNT=7i +Guc0#QAanM6Ek2aP7jrhY\GH81cU?$!&?S23MaC +jB7K'=tZ7&$c/k%9M2N=_5`W&b9YDK,hI(a]NGM@%;/Rj<=)]cjB,]WtMKPagFh5X@@4^(X8G'@+B3C-!6F?eOZiS +P%QY8CUn-8/-N#.1F^/?"KP"4/X&;tO^-'uo4B.J24R5E<[Cj*P&$KH=cEQfja+U(2)R6M2tt1uF=e0= +=U8%;B2X=]$!*&H=seMq,EZd;e>Z@e*?Aum*B8#rdA'3I]Wl7?i6=TmC,hCiX@f^3,hFfnZPj-SbEjhe +8csODIM=seL#`;AVZIs-&9lc/H, +pFrRH\&uUgOcS)>f=@3B3<164[&iA2DArh*_ld:WQIbMi.p#n]\UFAKA&jV3p4%'6'>.J"IIbL@pPTP( +5(*-]HFT993<182Y3"eU_^6]WdeZ\-\b25YSXi93*aS151@hcDI/:At.iZgNbf"^sgP%trnbn@!u/P"SCC@\#1X@f]H_5[X=L*MlTp%9=dFK##p$bq=aCRO,*'$7P? +nXpMr9!Be]WW]AW,Eas63m$']B:"sODr&"Te'lc,StEp.%.IkcjBBQJ:^L/K=I!8oJlT]S8Ol9@Rm6^p +E,]d`T7$$0-?ujbE\1c`W!'.6X@f]H_5cJ(V"K'4k09AKfZ=T*AUl^4,hFfkK1`?t_5[X='!*!(MkmLe +5SdG0(p7G/#F/[sJlN+X-!3$0(.hfTJ1Rj>0jMm=%k>Dq"KN0:9!E'?/<[T1!Ei[\@^q^Y*`R_k$!&?S +Q!i-]=X8,A"1#GB`GdD=4K&C`'!+^0.`&.DZ:O7a#%V^bMr@jZGYe]I-!6F?7B+=`e-mf.`&+fWtMKP/rQO. +AO%#4[MZ/YN!GVUS]n:bCD.HCb]2<(_8+4WW]@8X@f^3\1EfSQ2t,nfj_IW0cj;G<=)\P +=I!:EE*4H//H`;gZGgc7@m$[mWtML+YU[JhiNc#>=pAMWAW,MN`ct;d<[Ck5?r_eY_e"t[[1(.9aqhn& +N:EPRX@f]H_5[X=L_5[X='!+^0C:GgX\shNSrQ8'F[JlN+X +-!6F?eSnY:FY*^$\?a(m/RpoA"KN0:9!Be]Wo:6Sl<4C&EFk'e>/ke`$!&?SQ!dUDaXK'!+^0.`&+fX+neAWGa>!8R9Mi/?WeD>g!rp.`&+fWtML+Y\L]@-EYnc;c?V9F*!I>_R0gA +Ar5SP`ct;d<[Ck5?r_eY_lYHRWDf]U3]bud3cO#mUIUAGHcmEkG-q4tjQ,C%^TVDji6;nV[>aXK'!+^0 +.`&+fX+kusUmE]>8u$THCi"BBH$XeJVl+0PGkegfq=*@\oTmOY+9/'(HKD0A[;-Z4ZtBf.t.2-'E$]j$=tnQ!dUD<=)\8pQA+7QBor! +5(EQZo/3pZ/\U<%\T?*2n]8dB='+!7SqLksi6;nV[>aXK'!+^0.`&+fX+kuCUt;bT9AB6aPq/u?gqJ46 +Z"(hGIH/5#&,5bimGG[nrMfeqro\_;qF@]"J2^+Hf.t?u9!Be]WW]@8X;^LQP>4eFUpZ^NF6b><4$/KE +4o4Lap\+_5[X= +'!+^0C:NFR*?,r5rRC8P_SXgPeB<=f`j9jWhE<\P[-BDq"KN0:9!E'?k9cajSK2WG +YLa_CVshKV$dH.p]VbAjrADgFcX4A3Fi?;X88ELYD`@DDY%<,B9-i+E`e-mf.`&+fWtMKPmcBZ+p%9=d +FK##pC>V=[nT>Wm,9tIbV![!phL>%Va]3h+f.t.2-'E$]j$=tnQ!dUD<=)\8p[Ulp5Fpm%fsAlFbI;BF +lKRPINp"O+al24;k1;'n%1RH'FuI'N@qK="c0X7B+=`e-mf.`&+fWtMKP/rQO.AO%#4[MZ/YN!GVU +S]n:bCD.HCb]2<(_8+4WW]@8X@f^3\1EfSQ2t,nfj_IW0cj;G<=)\P=I!:EE*4H//H`;g +ZGgc7@m$[mWtML+YU[JhiNc#>=pAMWAW,MN`ct;d<[Ck5?r_eY_e"t[[1(.9aqhn&N:EPRX@f]H_5[X= +L_5[X='!+^0C:GgX\shNSrQ8'F[JlN+X-!6F?eSnY:FY*^$ +\?a(m/RpoA"KN0:9!Be]Wo:6Sl<4C&EFk'e>/ke`$!&?SQ!dUDaXK'!+^0.`&+f +X+neAWGa>!8R9Mi/?WeD>g!rp.`&+fWtML+Y\L[!P.Hq[=^9Wh\<\ij<.\*V<[Ck5@+B4!,]t[@ +ZFI3ZE%PQ^W!'.6X@f]H_5cJ"8Es@_A8u1=iEF6G:^L/K=I!8oJlT^"OjpcIaPt>X_mPHnTG"=uYU[Jh +"KR9PPMX$%HZ!`h"`NI*#'dIBE\1c`W!'.6X@f]H_5cJ@UpID6?!Uarj5Ve;44c7'RjF55)<4"/=I!8o +JlN+X%EBccR@3=(l"OpKF"LJ1RjF55)<4"/=I!8oJlN+X%7_\GeS6SV1C8?QN_#F/[sJlN+X-!3#EoXX)&`Pj3#Bg!rp +.`&+fWtML+Y\H-Sl+5I:l`\"Q[YfWeJ^[f#rr2nsT0bQPId=,u>5i/YGL]Ke-lu?><=)\P=I!:EE%@*S +G7W;?[J:RW=j)833S#]c9s)Ra/RpoA"KN0:9!Be]Wo5k'FDPcpoom0!$Oa)Ol<:?P2bPFJ1<+r=YU[Jh +"KN0:)K(1!B4kkt>L`!3emEPO=3-jW;Hh/EAVLGT?r_eY$!&?S2&r(7[9OknQ:S/iN!GVU_5[X='!+^0C,jgcWOu@X\X"rk<.\*V<[Ck5@+B4!,]t[@ZFI3ZE%PQ^W!'.6X@f]H +_5cJ"8Es@_A8u1=iEF6G:^L/K=I!8oJlT^"OjpcIaPt>X_mPHnTG"=uYU[Jh"KR:#,,o>qON!J:L2.[e +5p]Wu?r_eY$!%M%78h_m+H%aS%+d8SK1`?t_5[X='!*!(MkmLe5SdG0(p7G/#F/[sJlN+X-!3$0(.hfT +J1Rj>0jMm=%k>Dq"KN0:9!E'?/<[T1!Ei[\@^q^Y*`R_k$!&?SQ!i-]=X8,A"1#GB`GdD=4K&C`'!+^0 +.`&.DZ:O7a#%V^bMr@jZGYe]I-!6F?7B+=`e-mf.`&+fWtMKP/rQO.AO%#4[MZ/YN!GVUS]n: +bCD.HCb]2<(_8+4WW]@8X@f^3\1EfSQ2t,nfj_IW0cj;G<=)\P=I!:EE*4H//H`;gZGgc7@m$[mWtML+ +YU[JhiNc#>=pAMWAW,MN`ct;d<[Ck5?r_eY_e"t[[1(.9aqhn&N:EPRX@f]H_5[X=L7B+= +`e-mf.`&+fWtMKP/rQO.AO%#4[MZ/YN!GVUT`DsCL1GdBeY/RpoA"KN0:9!Be]Wo78JBrtDT)&_,9D;3p\He2TIl'Kg;X>Q&? +BT/#`5CE%D-U+7G?_pV$olDPEZ"o\A)<-!cJlN+X-!6F?eSm16FFJ[fkK]W2cC@K+YkD6qUUmM,CE63F +\O1c>aT(4&%cr%[JlN+X-!6F?eSsjNh"'Iaifg:HH0r"eq!d7V^:sRCpUTpCj5hAc +j\WZm-WlXA3]\uM0fCqU?L7+JIdl:3WkW'*qo=JQQ[=,W^]/XaU!cH[ +]0Aa6\-b]J8'.6h-qg\Pl&='rJ'T='%?m\->JeUBCSDD2#okp:V]&?HeqU]d_2 +X@f]H_5cIcRrigsG.^8W?>oem[F]HqeZ2cTY5!_gBe9i+&$P[H>g!7g(4oQ(R?V)ZJlN+X-!3%[.jSDI +/N:E3@Us#Fq3n\(gY:IYSijR;Ds1@OGd@s_)U>,]WtML+YU[JhiBl,djQ,Ckn8Ru7Q%t*K3]fF,>e0Fd +kta,"lg*m(m="Wjd;$FiCRO,*6Ek2aP7jrhYU[Jh"KR7b=j)f.F.SbdBY9^enW>%dg=t@$?hV-NhnFI3 +m]H!u\sNF-!6F?hS[M24R5E<[Ck5?r_eY_r[!0[7n[#b*L)JiClkJ.`&+fWtMKP/r-7*AO6l.[QIS" +B2X=]$!&?SQ!i-]3@&`!'6:UgjfrP[P7jrhYU[Jh"KR:#+fT7F0JG1Woi!9#JlN+X-!6F?eSmMoc/C[Ia/T9CL,19pWW]@8X@f^3 +\/^[on/TS\MaU:`cYMX;]B[ +"KN0:9!Be]Wo7thR_s1pO&ZKe%;/Rj<=)\P=I!:EE&f1\P9`__[XtN7ZQr,*,Y=.E8Wk>jOsEV^,Y=.E +8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Ws'?ea)n-WN!G=\Z28mJSsAZD:h+]=tQ;q4*U*lrC"fukg?0I +aiX1iri5(>"q=(V`Hk"g7C?Ei.-;j#+D*R +mHWsT+!7]_M3MCV@H"]1rG?n.HfM3qg9iHe3)r2BX_hcd.4&j.\&3t3Hi(iEFQh)[D;2(>(5:DG@n59L +V2t2IISsD,V+[/d]=T"FH[:"@?+X/11YUQc?bbIk4R^&bIaq52CHHOq7.X4SGM[UXo/Ca%;prF,ChtYN +:cU[%SSjbPiSdL[%],V^R7TP??Is4R,=dci%m@Z)o#l,Un)(lE0JJUfoLp?f<;jJ-0\< +16VX$gq.d6CH4dTRQdl:Fm;rt2B9&2.'$!K;A5GS,!5U91qqB +hg#.uq;uJ@-:tC$GOF7`4bk6+cd/L.jNO#JkoX0R+W`dmFSYLhoU_uVRPa_9gX`X-oh+uUj2[4M0;b+N +5J*4?/iA%Nh02*Yi.L[9e?p9*A7VL:X/kMu;3]&=`UkeTmsk@aePDuO#7__urUndkeuJS'Ci)O,6g6aK +o>T$>q^`cDeic:1G3rK02dX%8V=g,.[r4KSm+A0uLE`Q,P26d6GrhF#bE,LarA:pqIf4TC:LqXAdk6&& +P'1,DBBNY$ns?AK:'j[e4Sc$brG#bL_6k9EnDV95I=;"emr*]U^VA\+#.d*%Y?jrl6>tYhOcJb^Dnhi4 +h=9OGrL41G-71);GU,ZqWuW3$J,J=Ks7)/">eYTr]=[r!^\Q,d5(U_M>k(hmktfNu7uqQMdjUT!)05?2 +c#ce\)Z()*5;\S[]6E/EGH^;0ZfU#SFfR5`dQb@0U\+9RDVr0VFEBAWSg9 +K7eOFmQH(!r5Tn/SDL6Zo?KGsf;0mD:K@?E$B[N:C]9U@2rB#SLECutb^[6?RH@[">eba$X/kR"pYK+V +=K)),PTZOFV5:#,^\p&:h77U)K6\[W(DktRj,H;'q9P$:?-?*nHdV*Bl/mnJmbCD&>#1YJ;;kI-l7QGX +S/T-=m^p_h4?5F4ieoVcb0n>R.HZa/l(()A;mWq(XigkYr$N2`K@FhOZoaYPO)l@=S'i++EarPn(p2a1fX.S +fYYB#o#o&I)/+GpT.Z&m]ANR)a,V25HG/SkZK7p.]]/D/4b!;g]jL`eTDl33c_9lQqH?,WBtVFr/YfhA +A">`-1A1S'K+Fu2+sfd81S)`)s"->2=m>Yah2$[g%mKa"Xh$bU,+[8b=0Je%L)=VVqmBNFdJ3Y;V+[.Y +?b(7@:=![2?iKV_^+TrCponYT=$cc\f>$2']R>3VLCP>>^?Bd&Mre+PPWlHJ0jDDLS2Oi"G':j6i4FL= +IX4`[WsJ>)lLfJ*`M]>W\o$31oFHD.Bd4P.DId:Rq3lDOgY:K3LX-]!WrhYA[B&sFNqBT_h\7TZpYUJh +pK3I(\G\Yhm'Ghi()Ie9qpeF?c_-8i:3-'pg#_>W>ISMCo^oMNB5N`G3D(31l0`ffbr8^Oj7gRNV:)D9 +2g]1MkJY/.,6?HqC,p,B`t;kS702nj1?n[$=I*^$rBa,]d8aX063dF$A(:VIki*;'2*+P1Xu$PtEXpHNWo2>.uo +YcuLL3E+0E-b>`'n,5J%CH5#`K.3AAk)[5N]?\0O)Bp3LY-+ose[OFb4+/APoeS)6q=EcJch&q_ePDtP +l&Vj>7uoQHs#8h_o:'[4WT9Jslh-`+Dn;./s$04M92ebfrjZ1o0?oOs2fAE4cWJB6bI;EIhTVVb+MEBH +;Y@eR8s1GkOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E +8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>jOsEV^,Y=.E8Wk>j +OsEV^,Y=.E8PT3qZZ9$e~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 1032.72 412.56] CT +[1 0 0 1 0 0] CT +N +-954 -77 M +-954 309.25 L +237.25 309.25 L +237.25 -77 L +cp +clip +GS +0 0 translate +238 310 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 238 + /ImageType 1 + /DataSource Data + /ImageMatrix [238 0 0 310 0 0] + /Height 310 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WEG1U0"35CI66[V,k`:Q!#W*<"a<^W(#a6B_ZD)r,+btjr_]k$pZPiuZ79#)n+O%bjP*-H9&53LC +`1X2&ClC\QU9#2@ANBJ]j?jI@D0L&=T?lnbpPU8>ch#rZ\aR6#H+nJMD05Ddp%J*NosVZNVV',jq=CM" +:TD[.29U!KBOatWL6=8Y:i^Ut4*GH?rr#(]r3Q8:*B8"GE,a2#/,K/?%j*ttm<"0@nLX5J,]9, +U5LY8q<"0m47><+@G+M`\lHH*eOL[+AF%gKds1oeh05L2kPb/4*uPqVEob;92r/Sl"W)RdrV,>i9Z^#9 +A]kiPdXqc8lEKmHZd2g)=.nX=V+HAqjdBbQ.@98;Y2O^+q<,fS^1Bq9jHIt`V,]0e]J8il>e5%Ap"*QS ++)\jlp+*;UU1WfYYJ7eZ_#cch3Y8DrZUUkH$!1uu[]NY\rqY`\?G0O+nF@n`-.goBc9(LE0i1A)XjV5A +q=Dos2f.->h:!"-41)oE.DE:#pX2\fSMOo=2Vto]?ZFicfAi`&S$'Epb$l`"X]e_rFL9^k++9s^S3(qt +eol4[lCGfE_>3K-hmRI\Y![3>7&M_mZ$uZJEq'km%Q%6mf[d;e[2klFm.0qh +d3S`c`R?bHnWg0#f/8bO;S?)!,\X^unoN)uf3NS8)jDX-hGTcl]J1BC(skrAgZqm/:(rqpl%HLm"M=MZ +F?%h0I<<\gFVC(BHdhE=Em$$D1*1;+P1tn,[[16>aj)\JHgS4%Zg4u&*&aji>b1;@\S/ZV%H9%*,ra\d +VI\MhDV3Li[;4AH]`kIiJU/UY0:&&F8T)&sL1:!9WKK+^d998ulTMB`-0H:1G"d\$2/Cdm/DmsWUE6r- +NLKKSVG[:f@Z&:gB:jTQDq0UbI]2?I2Jae.lNj@ti7NBeQ\jPQP*;[3_Co( +9hKR$i5(&bXf=UtBWu&BaTi:qd&uXmNh!OpgGVb[ZpaB[MET>sl_RQSn#I,P8OpNm#A;jb@;AUnGOF7k ++*!7j03S%K8OZ->a4<%\Qc:%G9$UYF@)9L$o>Y(4Vc]".E,\X5WKZn2g8.H/QCl4K>G^El558M?Te4"5 +Xj3]Qj9AhKSL:UJ^OGm+3]fFr!`WRH8O;l^Heh&/KWe-MPN:`r;Z)E+$Q#+I!7.t3ibPaRA$=J$1IfY[les,UlL,I4F,_iokrDis/-k`UHMF/g&iXr4]!of"!s^*:bpbBN%Gp7 +XJmIX.N&\[?U/*>;0!^(4&Br=,s+f#jFMl55"o+'GB^B;U%MA7Q2)*`]hC,_5*!_hPak7c%[\<,PP.@s?Kp'!Ra+\eZrk^eNET+6^4?gArT]A4-G+dnY8p6lg4A'dij?-%XT]A4-G+dnY8p6lg +4A'dij?-%XT]A4-G+dnY8p6lg4A'dij?-%XT]A4-G+dnY8p6lg4A'dij?-%XT]A4-G+dnY8p6lg4A'di +j?-%XT]A4-G+dnY8p6lg4A'dij?-%XT]A4-G+dnY8p6lg4A'dij?-%XT]A4-G+dnY8p6lg4A'dij?-%X +T]A4-G+dnY8p6lg4A'dij?-%XQrM00!s3:: +A-Y`PULXU%cD+nT9$X2B#>3::A-Y`PULXU%cD+nT9$X2B#>3::A-Y`PULXU%cD+nT9$X2B#>3::A-Y`P +ULXU%cD+nT9$X2B#>3::A-Y`PULXU%cD+nT9$X2B#>3::A-Y`PULXU%cD+nT9$X2B#>3::A-Y`PULXU% +cD+nT9$X2B#>3::A-Y`PULXU%cD+nT9$X2B#>3::A-Y`PULXU%cD+nTreai"J&Uaon5mhGTK\CX#*bWJ +aUXQ*8')7*S4C[2Pak7c%[[1j^%m&1-Kojpm>b*b4WRW9,hs%ZG-DA+%.2jtZ!.N+sDD +m_Gd`1$/t)C*$mQ^o6BMjpm>b*b4UlWDT5UIk_0bOmci_zz!!!"fm_jqqrVc]8Nur<6NjOX]^]!lX?[o +1\GjG'J8AffRanY.EnuiZAl:=L! +HDSotW/r3-7ZZ"(hqaN2`Td'@6+Q7lV%m%%m"K7ee^?!YU\]&[//G%jN&aBsGq[5R75l"T-P[\$oUq*c +P+dRu6Y96=@e&tK/p\5t9In%\nZ\8gQZ='pCMh07J8I-[oDY$/65]_]GL+)$;q^AG&>HeG:imG"N^eUO +V9l6Q/[F3c^ZQWi#0^]2#]dA"mT2sZ7aOu7aO+tHhWh!FS[M"b>$ +cm(8X4ppu@F_dn*W-r9:,OedSihF3QS'4n_tkp9ID,n9$Y%s8Mo=-1APASq`e=gf2df>b(T=F7hF!(G= +3!P\08fgX=bOj4rJHrT9Sf55t?;M\e%\j,Q4$gW!c$EjOu#Fer!Hn\uLiIItp^7uo9,[VXd2Fj8dB(04 +A>hEEa-a?+P0Pig*#)4?ANP)K'YR^SJ#'MGI`"(LP]/6T8ibEh_aNZC2I8(kP>=Bqm%%m.@nSGg):9%+A7XcE0>Hl=lDb=5dpdQHGid)5`ODe7=$6 +HRe!aZ$H`('%fTP?]='d>jXk&$oD7,3)p5:T[Y6LDL!<<*"zzzzzzz5\p0[Q'>a+~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 574.8 375.6] CT +[1 0 0 1 0 0] CT +N +0 0 M +0 386.25 L +1191.25 386.25 L +1191.25 0 L +cp +clip +GS +0 0 translate +954 77 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 954 + /ImageType 1 + /DataSource Data + /ImageMatrix [954 0 0 77 0 0] + /Height 77 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0WIq2jZ+33njeO7B0ar_?SUPmccMG.hS7?sm/Ff]Bm'fFO!R*$MGVIH8dK^877f#\ +M2>5L;cuN!g5>)L&Qp\?q7b\2f5YtOn&`-=IU9R_a7J9hOaHNZhXe:]HZ-Rboss7'D#jV:zzzzzzzzzz +zz!'nP@(0#Sq!!!!I_kg"mWiE(>\_P)X%kBDdO$$;gd*tQX<5CVC2IIlSqohIaMo[E +*jlDfHf?@2)!`J`/-!WW59QabgtX1#If>25HOIT_d>lr[K+HhVDP9oTn>@*9%ejlPUc]mKM-?J=/g042 +HKf@SX$csUK^S2d4s.0'>J]U51XZf^uWkF^AVe^`:'s7=Q$4$SK@CWkUbs1ReJgm0lX2uimSDs=t'l04 +&;'3SODZZdh+EHZM+[pK+8!;ul.]=Y2R9i"Qs;E$4X<%\6`"eJW& +9'bg"/r3Z,;Be)%]\mn5=I'H&ei3bgJ8lg'JD/cYkO.VNmEF8,+Y

fC/mC/C3O3!,^f8U>MaP92>fUap+.aG]_^oo2P@du5+g/>'g=!`Df=O@CR;Z-rUI +]/*s@M,m92A)27D>PX'OQ+d+q[*l_UGS'.6Q-J7-tr6USi)?RZ[uAn\$g[Ti@1Nd($Q7CNU_BRoUTXSTM.#9=g*=0G +r>?s1/N.K]C9">84*^7fm-J?pWX.XXT_83sRQ52F'?-DAB?.u_D2E"b'FfQY%l]r +VWIdCZaGJoZTE8cE!IQM=t,J/F!h03_62PpEPIM\GIUTEMe*BI`_\oHb"=k<]T!5M@8Nb=o"IX^.E*>f +WLoMX/mgM7bSSN@X(ali9-G3sV;Puj+W3-44Uj?qFp:S0O(2qu>ZIegs"$+K"Aj'?6P^OO"&L>e07pAX +sX(GFrjhks[^>&n86=(6j;ZCAl0oB1a!K*B9De'jFbgT5u]G#)sbbf@m=DAe2b8Aals!!(YsMi3MEfih +Q_Jh>P'F1L(t4aY&(D!UBOWiN0FMg.`]7`NHfgp!.HemiK1C@'BiWnm48ESIl9@s9hEb;LonGZS%'LPN +cWVP^5n?G.8fO7&n_9K=:i3aiR*n@(-djJ*"h_@:@!SHl2[grr.AUf"qk(g2b(#Y-M4o0&EARm+L&pCY'@T>W? +onfZPq_*:C'dD:sSHEPPbbD/X*$#`k%JTLaMK3kI%'db^&_o[?Uj%L)n55R#]if2n6ag=ki3jR[Z+Njm +Mt`"-f%[$2e*NjrL`>>@0WRI,*-A``!pPJL>uEk,FJ98iZc@$7rIMXqFECIsf"E>9h@'AaJ4_hFlr[9O\/&N@,LE$R*d> +'(+L7*]$>2^nKDXA.b^b'7m^Y3dO\>?etQm$JkA0StdmL7Fs8dcN=.I+B:%"\n(ca>&L;?9he>?i:?!Qp@lI[&$>\3]0:T8m,[6'Pt?1QiLh74&'3 +r*G,b@,G@G#jI!j]ilHRG?N-baGG^F6CiZ+'u432Cg`Qrr)_3&[E-`=/!Mj2*X +OCg];bKJ?[_TIR1C;&E[80%prDhI^ZDrlph.%aHhZs=UFSE,SuoK6j1g;/+RM?!2dK]p`A_@Ng3o@T=PrQ4lO, +?R.CUn@A)EQWm;HqG!!(qGZ+@M]L%+Nd]?`Fol-lQZ"d(#cQW!6rB7>ArPR(g=f_@Blo`S,BI +pI0k11`zzzzzzzn=k.J!!!"D&QGb^=(K)!7]Hfkl5c!:OK&A].ZgY3WHsnc8CK8Jllf@4;Y?&@'hD>U< +#%r(JQ0n\Cn'Vb])Wm,EU +oH\[h@Z^gW@F"0!i[Z2Wcr051_"NI*`>u\C<Qe*K_h5WWK.LOK&A]HC'@WdkHRD+]S\Do +o;QX86(4?'hD>U<4tplUhQ2`p2kG"j3\J&?0tGU^Eot5 +cP0eW^*T@V'/ajZ9fHNg$Bk^mtaqo<#%r(JQ*@Te[mY+8m>=e_]tX6V!8t_.ZgY3W@F"0!i^L4L.H%%$ +>F`qZ\MMn,>n\Cn'VarD-8"kO)4NOWcpk25cP0eW^*QkV!;5(,,HkAUu@H\*`DZk8/4ZqJ +Q*@T"]G"G%?]))( +"2TmAe1ke8#-KfW^*QkUoH\[hPDAng9O$`*nfm'9*N7ksqs6K].k +K]VrK5&L9]N>k=eN4sT+B8SC$G45ho<%bjlL%mE;oe2s+K%E;WDK7$G9IT8C]dG< +?P9F;H4i>"]G"GH))Au)hWcqDnc&0LECs^hj3XR)\>r/,A>7-]N>k=eN4sT+B8SCk +<&.F1HIR3J&Jg-/(Mnhc,o-6>?9\$U-Pa8&ZGi2.ZgZ[[r+@;!moNe6 +>_a$b<8!O7un]SIf+G#6"ainK*MorDOIr7^cuuG;Y?&@'hD>U<'@j9CTFIm';lZ/eCRdQ'7AQCI,Mek\ +)2Z3l`\(;IJ`a2ldtOjHgeYW['WeIr9N,%lKT9WRI!X?V5KD@V!8t_.ZgY3WVTWjo#$;_RA\0`hZ#`cI +C*Rtkgs0k%F-RY0&$)OJUs2sS7KA_9>X14AKb(BLfAq)'hHlQ#7i<@HoQ*qqt/,lae.VJ[cLucmHpfHS +LSb2D-;F>ljBQR*K_h5WWK0r'PY`k69+d&hYCCGf=aS-V[fglRiAH#D4Uh*^+7SC`F?3.WpBNAHcBk$Dcr-OXcHm!ic#a>?9aolBAukI +-8eGmdBLNXn&GiVja'CVPg?$$GU1no]X[)#7dikQ3G>J>Rb\ +o#!+qmJS%`ONCd\$<3c*RWm,O$CqQo.`0p>?9\$U-Pa8&ZGi2.ZgZ+Zt1PTX$/[b>>AjAA)laEIpQ>`g +NFiZ=b.BI!i^K9U^Eot5cR#qQBc]tqBTt%ajHChGd/ZYWcpk25cP0el4\#;M?9aolI3)nnp^[4c +)&h~> + +%AXGEndBitmap +GR +GR +GS +[0.48 0 0 0.48 1032.72 375.6] CT +[1 0 0 1 0 0] CT +N +-954 0 M +-954 386.25 L +237.25 386.25 L +237.25 0 L +cp +clip +GS +0 0 translate +238 77 scale +%AXGBeginBitmap: java.awt.image.BufferedImage +{{ +/RawData currentfile /ASCII85Decode filter def +/Data RawData /FlateDecode filter def +/DeviceRGB setcolorspace +<< + /Decode [0 1 0 1 0 1] + /BitsPerComponent 8 + /Width 238 + /ImageType 1 + /DataSource Data + /ImageMatrix [238 0 0 77 0 0] + /Height 77 +>> image +} stopped {handleerror} if + RawData flushfile +} exec +Gb"0V_$u#N'L]c:PH$UP/QYS[5fp0cR4/,aXWAHB:B1@pzzzzz!9!;%E+>s+O2nMNJlV\aSm^)4RjV=G +cfPO7mB_(i)UZ[%.&qeVj3e\3cXl4Z(OjM!Y;l4Z(Oj?=k;.(N-q#tjVaEe9JO +PanE-4s_R)\PL\K`D8nJT+Ae3.L +5LSu3,Q~> + +%AXGEndBitmap +GR +GR +%%Trailer +%%Pages: 1 +%%EOF diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/figure/ptp.png b/moveit_planners/pilz_industrial_motion_planner/doc/figure/ptp.png new file mode 100644 index 0000000000000000000000000000000000000000..b57a9282868512a0a689d083e067ed2e2f393bc9 GIT binary patch literal 16444 zcmajG2T+qu^e+sAD!mC(#7LJ;=v5Iz2dRRzfDn4`JyDP%9RxxV1f(ly=rxM;P^EXJ zN{JL9Xec+l@B7X7zjyA;9VTp^eNJ}I?m4@A%5UQz>uXToV7oy;KtQdfscu9-KqQ6# z{+pZ>|3C4({SCe#wb#*5C%C%)E9xlEz}HZCYg+gb5HNUNe+bc}Uv2P}Wd2%ukH~(I z($I*}C!Cav5fI!V&{BV35lgyAu$;xR=jA;>n|<@xX_e$vLR|rH0391dRg%^?n~37wOfRHm9BKR zIsxapQ+L!AS)?$ROb5E*OXY9uyWyRs9FjBHbqmE&=wnnCMn$=EH0jym4b~egH}OpJ zIOnDs9?DOkTPHt8uAFhKVSc@?>nhOXmbZ{FW_s+WHhIn|PkKH13{raiNj$Mjw}IeJ z-gB$KQHsJ)iU*UNv-iZHJ9N@(Xm<~3LOh+?b7-0mHU+NuV>iXG8cPm867&wEXtTUA zTcRS7!6=P0-sKU-li@}8s7&tfrxL_Tzpz+to@XGIB!M>Q3i807PsnxgLi)ef$|_l@ z+iCp?!9+Q8N2qD}&)nBPHhlA(Pxt;z&rAoXkQ27Gc%fx|@4EBMh9ZiD67g=d`z_bw z2xourwRAiljy2;PR_To<+Dc%bQL?210@t*0p@P+Ojl+9%tAlisuLzr3a2UNhTQV7M zY^b3^@gx=reGXyu|SQtQeXZT!s zpm-&&toExQz2vklCk*<@K!NYW{z2yJfy%kaQeFLP-F)=zf$8IMHP6TDi4DCUXX32X z)Z(&QRYirPVU^DOwSBk<~@l0&{XrN)VV3vJYZjz_`P0x0Hty6f8z z1zymLJiC=x#2lt-gXAb^b@ryp=4EOBWR~+YA;jEk#3RczKA;Ua+eULNu58a;fhe0$ z8T4wD(vbUJ;b)Z3q{6YRY1>n(Go26C@uvfqC{M(%QNk;-@V8a;3{oP;MZa93Zh3PF zQ0PfKA!xUYe76lTryv0esoa_xMgN`p*q(t1X#DE>=UJ`=7szr3eWOLMt#`{FIxT

Y(5X zo!YpHy_dN}s@A2rec39J=cnDz^m>p#!Sm${&H53=H1I-C-oD14T+G z9V=_rH8pj5)UM#%CpzcimxO~Xhb9`9c?rc@Y$Sv1MsUnvk-4*Om~U~RwNa{5Y(r`B zH1^Q=9~`S5XVYI3v5xB3_D*)+ufMLHsd;>|TD#37RX{si=(21I@@tX#YVNYK&M@o8 z;(){Ci>c|Jb|EvzOgd`{EN9#poep)X#*7^?x)=0-RF1%mT0NC_>2-Idnm$__?dYBN zQ{F+^`9e>*0`m&mZ_rbdHbZn;T8^p|qB+-9v$5inj#?l^ARtrdvA)BzdApC&HXTXD zNvg`_$5>E+Vv`3U<&-smIpn?bftA$CIwi#2?ez!}2v;Ajg*WPpp#%oX`x}9VNWp8O zS-RowFt64qgqE4S@_Q;Ceb6JmGGJ_{jQiZo+V=UlU4&x<=~?&CmA>h5oDS>kv|aXL zZ9DCJ!gVj`tQO{AL7~@W^b$$fKO)>we}o z=7-b$PoB~*R_jW=UH|QkEE~F$ET)*;iJ&arIG2IkpOE=OV zSPVAcu~QaNAs~Bd_FJkk&y3t&?@n^xgRH`2!1PsjS|M%jus3lnR3Ik1V+V|Eg@QhG zy9{3eHkOW+ma)@?xgLOGt)}JCvTkdR&j(LJ14zl8Sqiz-l#84dat3~RIb$`w*% zcYyUv%g`I@BFm&xjy(42dC}$23c{))ZG{Ujw5$T9Z*?1=Uz%aIf65Sf4Gg?aN)6(@ z0+__&CFQb>3mluU4mt{Q3!EK>=+!rLoUirWrP+f1GUtRI%LK>nVl!Lh;-p)vTJ;0S zT@7n%hE|*@X}B{5!HaG+Q-1+ZM=gRh}&3# zJ(*X{_hQi3iduKEqS{pH2J@EsfLQ|OFruE&o z0ta@bL1)Q|DvtpVYG^c{iO8B8M$UA{o<9c{gKJvs?(W&HPd=B*8(Ze?l3XuofjeiD zwau~|KWKN*+Zk_pA(e?a2Z_cR1ON4U>Dc0mz$dEX#2_PC&Y-!jhq|f0;&-QG0<2e; z9C*5O3z8(K@XovzHzw$hato@lqP<=NmILPqk=woDlEw#UPr8;bElhQOHIrZeo_^b` zhup=UxJaZ`Y7(<)s-soQAhC?89W5>RXj5|NgVJY}E_zoB@MSkiwJnD)YFbpV+Alcm zJb5?3_xN(10Y$TgQK~Q2JARcziZ=A(RW&iE-hTN)xI2D3H2+(w>=6$(h6WJX;4W?D}3EFk%{)(qr?K&foMB9Z|e{YAZNq}W73kErt=kjveq6C9R zR*618FA>2B%(a*v#$6#e;qxbwNVy(1Y*KDQNbIZt=F7Eoool|r#wnJURK2)m^IP$_ z?x#BYyQQ6mZ&N--*a9C<$cpKXSHz1do5$e4JP-ttFN6TE=%9f&kM|b_MCi@ET;j&_ zFlV!MHV{D15CC=X0u8`GOnivfY(O)*0c@gT;#gvF(UqK4&@+U)i%Xa;P0f|iQr|Pl zHCDSplU$a+}J?0V|g%m!pWI|YuFEY$u z*H`5ml5+))yjmMk`jeB@GxcEwF~BVmOrC-31I-qx#_?Qw_?nn!U~|MT1q4Nv)__9* zkn5Mz^{3Iy_uH@k2IE#$!>ZK(lDpAKWc*;ut zJ8;B~Oqol$;?7LvBuHnmNriP>?a^NgoV`k^(7Fc8lDdL7n4f?I~@Br7%xr* tAi-W+ABDaJ2KzRq3}0(pkf$=3p8RPd`M~RV3G~lbG;}T&owvU8e*oMT{g(g$ literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/sequence_processing_overview.png b/moveit_planners/pilz_industrial_motion_planner/doc/sequence_processing_overview.png new file mode 100644 index 0000000000000000000000000000000000000000..2b82cc09bd5725d2da07ead00780a01834fbbd43 GIT binary patch literal 187694 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 + 5 + + UMLDeployment + + 520 + 155 + 100 + 30 + + <<MotionPlanResponse>> +Item_1 (Group_1) +bg=cyan +transparency=0 +group=8 + + + + UMLDeployment + + 520 + 190 + 100 + 30 + + <<MotionPlanResponse>> +Item_2 (Group_1) +bg=cyan +transparency=0 + +group=8 + + + + UMLDeployment + + 520 + 230 + 100 + 30 + + bg=yellow +<<MotionPlanResponse>> +Item_3 (Group_2) +transparency=0 +group=8 + + + + UMLDeployment + + 520 + 270 + 100 + 30 + + <<MotionPlanResponse>> +Item_4 (Group_2) +bg=yellow +transparency=0 +group=8 + + + + UMLDeployment + + 520 + 310 + 100 + 30 + + <<MotionPlanResponse>> +Item_5 (Group_1) +bg=cyan +transparency=0 +group=8 + + + + UMLDeployment + + 520 + 365 + 100 + 30 + + <<MotionPlanResponse>> +Item_N (Group_2) +bg=yellow +transparency=0 +group=8 + + + + UMLClass + + 510 + 125 + 125 + 275 + + << Vector<MotionPlanResponse> >> +MySequence +layer=-50 +bg=light_gray +transparency=0 + +group=8 + + + + UMLDeployment + + 855 + 155 + 110 + 65 + + <<RobotTrajectory>> +Item_1 + Item_2 (Group_1) +bg=cyan +transparency=0 +group=2 + + + + UMLDeployment + + 855 + 230 + 110 + 70 + + bg=yellow +transparency=0 +<<RobotTrajectory>> +Item_3 + Item_4 (Group_2) +group=2 + + + + UMLDeployment + + 855 + 310 + 110 + 30 + + <<RobotTrajectory>> +Item_5 (Group_1) +bg=cyan +transparency=0 +group=2 + + + + UMLDeployment + + 855 + 365 + 110 + 30 + + <<RobotTrajectory>> +Item_N (Group_2) +bg=yellow +transparency=0 +group=2 + + + + UMLClass + + 850 + 125 + 125 + 275 + + << Vector<RobotTrajectoryPtr> >> +MySequence +layer=-50 +bg=light_gray +transparency=0 +group=2 + + + + UMLDeployment + + 1240 + 205 + 110 + 65 + + <<RobotTrajectory>> +Item_1 + Item_2 (Group_1) +bg=cyan +transparency=0 +group=3 + + + + UMLDeployment + + 1240 + 280 + 110 + 70 + + bg=yellow +<<RobotTrajectory>> +Item_3 + Item_4 (Group_2) +group=3 +transparency=0 + + + + UMLDeployment + + 1240 + 360 + 110 + 30 + + <<RobotTrajectory>> +Item_5 (Group_1) +bg=cyan +transparency=0 +group=3 + + + + UMLDeployment + + 1240 + 415 + 110 + 30 + + <<RobotTrajectory>> +Item_N (Group_2) +bg=yellow +group=3 +transparency=0 + + + + UMLClass + + 1230 + 90 + 130 + 365 + + <<ExecutableMotionPlan>> +MySequence +layer=-100 +group=3 + + + + UMLClass + + 1235 + 180 + 120 + 270 + + << Vector<<ExecutableTrajectory>> >> +plan_components_ +bg=light_gray +transparency=0 +layer=-50 +group=3 + + + + UMLClass + + 1235 + 135 + 120 + 15 + + planning_scene_monoitor_ + +group=3 + + + + UMLClass + + 1235 + 155 + 120 + 15 + + planning_scene_ + +group=3 + + + + UMLClass + + 1235 + 115 + 120 + 15 + + error_code_ + +group=3 + + + + UMLDeployment + + 1595 + 215 + 110 + 65 + + <<RobotTrajectory>> +Item_1 + Item_2 (Group_1) +bg=cyan +transparency=0 +group=9 + + + + UMLDeployment + + 1595 + 290 + 110 + 70 + + bg=yellow +<<RobotTrajectory>> +Item_3 + Item_4 (Group_2) +transparency=0 +group=9 + + + + UMLDeployment + + 1595 + 370 + 110 + 30 + + <<RobotTrajectory>> +Item_5 (Group_1) +bg=cyan +transparency=0 +group=9 + + + + UMLDeployment + + 1595 + 425 + 110 + 30 + + <<RobotTrajectory>> +Item_N (Group_2) +bg=yellow +transparency=0 +group=9 + + + + UMLClass + + 1590 + 190 + 120 + 270 + + << Vector<<:RobotTrajectory>> >> +planning_trajectory +bg=light_gray +transparency=0 +layer=-50 +group=9 + + + + UMLClass + + 1590 + 135 + 120 + 15 + + planning_time + +group=9 + + + + UMLClass + + 1590 + 155 + 120 + 25 + + << Vector<RobotState> >> +trajectory_start + +group=9 + + + + UMLClass + + 1590 + 115 + 120 + 15 + + error_code + +group=9 + + + + UMLClass + + 1585 + 80 + 130 + 385 + + <<MoveGroupSequenceResult>> +MySequence +layer=-100 +transparency=0 +group=9 + + + + UMLState + + 1125 + 230 + 85 + 25 + + halign=left +valign=top +*Build* +ExecutionMotionPlan + + + + UMLSpecialState + + 0 + 235 + 20 + 20 + + type=initial + + + + Relation + + 15 + 240 + 70 + 15 + + lt=<- + 120.0;10.0;10.0;10.0 + + + UMLState + + 245 + 225 + 130 + 40 + + halign=left +valign=top +*Validate:* +- blend radii all positive +- last blend radius zero +- only first request has start state + + + + + Relation + + 195 + 240 + 60 + 15 + + lt=<- + 100.0;10.0;10.0;10.0 + + + Relation + + 370 + 240 + 30 + 15 + + lt=<- + 40.0;10.0;10.0;10.0 + + + UMLState + + 390 + 230 + 105 + 30 + + halign=left +valign=top +*Calculate* +individual sequence items + + + + Relation + + 490 + 240 + 30 + 15 + + lt=<- + 40.0;10.0;10.0;10.0 + + + UMLState + + 770 + 230 + 60 + 25 + + halign=left +valign=top +*Blend* +*Trajectories* + + + + Relation + + 630 + 240 + 25 + 15 + + lt=<- + 30.0;10.0;10.0;10.0 + + + Relation + + 970 + 240 + 55 + 15 + + lt=<- + 90.0;10.0;10.0;10.0 + + + Relation + + 1205 + 240 + 35 + 15 + + lt=<- + 50.0;10.0;10.0;10.0 + + + UMLState + + 1385 + 235 + 60 + 25 + + halign=left +valign=top +*Execute* +*Trajectories* + + + + Relation + + 1355 + 240 + 40 + 15 + + lt=<- + 60.0;10.0;10.0;10.0 + + + Relation + + 1440 + 245 + 50 + 15 + + lt=<- + 80.0;10.0;10.0;10.0 + + + UMLState + + 1480 + 235 + 95 + 25 + + halign=left +valign=top +*Generate:* +MoveGroupSequenceResult + + + + Relation + + 1570 + 245 + 25 + 15 + + lt=<- + 30.0;10.0;10.0;10.0 + + + UMLState + + 645 + 230 + 110 + 25 + + halign=left +valign=top +*Validate* +Blend radii do not overlap + + + + Relation + + 825 + 240 + 35 + 15 + + lt=<- + 50.0;10.0;10.0;10.0 + + + Relation + + 750 + 240 + 30 + 15 + + lt=<- + 40.0;10.0;10.0;10.0 + + + UMLSpecialState + + 1015 + 225 + 50 + 40 + + type=decision + + + + Text + + 1060 + 230 + 35 + 15 + + Action + + + + Text + + 1045 + 265 + 40 + 15 + + Service + + + + Relation + + 1060 + 240 + 75 + 15 + + lt=<- + 130.0;10.0;10.0;10.0 + + + UMLState + + 1100 + 565 + 120 + 25 + + halign=left +valign=top +*Build* +GetMotionSequence::Response + + + + Relation + + 1035 + 260 + 75 + 325 + + lt=<- + 130.0;630.0;10.0;630.0;10.0;10.0 + + + Relation + + 1215 + 570 + 380 + 15 + + lt=<- + 740.0;10.0;10.0;10.0 + + + UMLSpecialState + + 1785 + 310 + 20 + 20 + + type=final + + + + Relation + + 1710 + 245 + 95 + 75 + + lt=<- + 170.0;130.0;170.0;10.0;10.0;10.0 + + + Relation + + 1710 + 325 + 95 + 260 + + lt=<- + 170.0;10.0;170.0;500.0;10.0;500.0 + + + UMLClass + + 65 + 80 + 145 + 310 + + << MotionSequenceRequest >> +MySequence +layer=-500 + +group=7 + + + + UMLDeployment + + 90 + 140 + 100 + 30 + + <<MotionSequenceItem>> +Item_1 (Group_1) +bg=cyan +transparency=0 +group=7 + + + + UMLDeployment + + 90 + 175 + 100 + 30 + + <<MotionSequenceItem>> +Item_2 (Group_1) +bg=cyan +transparency=0 +group=7 + + + + UMLDeployment + + 90 + 215 + 100 + 30 + + bg=yellow +<<MotionSequenceItem>> +Item_3 (Group_2) +bg=yellow +transparency=0 +group=7 + + + + UMLDeployment + + 90 + 255 + 100 + 30 + + <<MotionSequenceItem>> +Item_4 (Group_2) +bg=yellow +transparency=0 +group=7 + + + + UMLDeployment + + 90 + 295 + 100 + 30 + + <<MotionSequenceItem>> +Item_5 (Group_1) +bg=cyan +transparency=0 +group=7 + + + + UMLDeployment + + 90 + 350 + 100 + 30 + + <<MotionSequenceItem>> +Item_N (Group_2) +bg=yellow +transparency=0 +group=7 + + + + UMLClass + + 75 + 110 + 125 + 275 + + << Vector<MotionSequenceItem> >> +MySequence +layer=-100 +bg=light_gray +transparency=0 + +group=7 + + + + UMLGeneric + + 240 + 65 + 765 + 460 + + symbol=component +halign=left +valign=top +layer=-1000 +CommandListManager + + + + UMLGeneric + + 760 + 100 + 230 + 335 + + symbol=component +symbol=component +halign=left +valign=top +layer=-100 +PlanComponentsBuilder + + + + UMLGeneric + + 45 + 45 + 1710 + 830 + + symbol=component +halign=left +valign=top +layer=-1000000 +MoveGroupSequenceAction/Service + + + + UMLGeneric + + 1365 + 180 + 100 + 125 + + symbol=component +layer=-100 +MoveGroupContext + + + + UMLGeneric + + 1375 + 210 + 80 + 75 + + symbol=component +layer=-50 +PlanExecution + + + + UMLDeployment + + 1595 + 615 + 110 + 65 + + <<RobotTrajectory>> +Item_1 + Item_2 (Group_1) +bg=cyan +transparency=0 +group=10 + + + + UMLDeployment + + 1595 + 690 + 110 + 70 + + bg=yellow +<<RobotTrajectory>> +Item_3 + Item_4 (Group_2) +transparency=0 +group=10 + + + + UMLDeployment + + 1595 + 770 + 110 + 30 + + <<RobotTrajectory>> +Item_5 (Group_1) +bg=cyan +transparency=0 +group=10 + + + + UMLDeployment + + 1595 + 825 + 110 + 30 + + <<RobotTrajectory>> +Item_N (Group_2) +bg=yellow +transparency=0 +group=10 + + + + UMLClass + + 1590 + 590 + 120 + 270 + + << Vector<<:RobotTrajectory>> >> +planning_trajectory +bg=light_gray +transparency=0 +layer=-50 +group=10 + + + + UMLClass + + 1590 + 535 + 120 + 15 + + planning_time + +group=10 + + + + UMLClass + + 1590 + 555 + 120 + 25 + + << Vector<RobotState> >> +trajectory_start + +group=10 + + + + UMLClass + + 1590 + 515 + 120 + 15 + + error_code + +group=10 + + + + UMLClass + + 1585 + 480 + 130 + 385 + + <<GetMotionSequenceResponse>> +MySequence +layer=-100 +transparency=0 +group=10 + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/capability_names.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/capability_names.h new file mode 100644 index 0000000000..61737ba275 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/capability_names.h @@ -0,0 +1,42 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include + +namespace pilz_industrial_motion_planner +{ +static const std::string SEQUENCE_SERVICE_NAME = "plan_sequence_path"; +} diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_limit.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_limit.h new file mode 100644 index 0000000000..199791f76c --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_limit.h @@ -0,0 +1,159 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Set of cartesian limits, has values for velocity, acceleration and + * deceleration of both the + * translational and rotational part. + */ +class CartesianLimit +{ +public: + CartesianLimit(); + + // Translational Velocity Limit + + /** + * @brief Check if translational velocity limit is set. + * @return True if limit was set, false otherwise + */ + bool hasMaxTranslationalVelocity() const; + + /** + * @brief Set the maximal translational velocity + * @param Maximum translational velocity [m/s] + */ + void setMaxTranslationalVelocity(double max_trans_vel); + + /** + * @brief Return the maximal translational velocity [m/s], 0 if nothing was + * set + * @return Maximum translational velocity, 0 if nothing was set + */ + double getMaxTranslationalVelocity() const; + + // Translational Acceleration Limit + + /** + * @brief Check if translational acceleration limit is set. + * @return True if limit was set false otherwise + */ + bool hasMaxTranslationalAcceleration() const; + + /** + * @brief Set the maximum translational acceleration + * @param Maximum translational acceleration [m/s^2] + */ + void setMaxTranslationalAcceleration(double max_trans_acc); + + /** + * @brief Return the maximal translational acceleration [m/s^2], 0 if nothing + * was set + * @return maximal translational acceleration, 0 if nothing was set + */ + double getMaxTranslationalAcceleration() const; + + // Translational Deceleration Limit + + /** + * @brief Check if translational deceleration limit is set. + * @return True if limit was set false otherwise + */ + bool hasMaxTranslationalDeceleration() const; + + /** + * @brief Set the maximum translational deceleration + * @param Maximum translational deceleration, always <=0 [m/s^2] + */ + void setMaxTranslationalDeceleration(double max_trans_dec); + + /** + * @brief Return the maximal translational deceleration [m/s^2], 0 if nothing + * was set + * @return maximal translational deceleration, 0 if nothing was set, always + * <=0 [m/s^2] + */ + double getMaxTranslationalDeceleration() const; + + // Rotational Velocity Limit + + /** + * @brief Check if rotational velocity limit is set. + * @return True if limit was set false otherwise + */ + bool hasMaxRotationalVelocity() const; + + /** + * @brief Set the maximum rotational velocity + * @param Maximum rotational velocity [rad/s] + */ + void setMaxRotationalVelocity(double max_rot_vel); + + /** + * @brief Return the maximal rotational velocity [rad/s], 0 if nothing was set + * @return maximal rotational velocity, 0 if nothing was set + */ + double getMaxRotationalVelocity() const; + +private: + /// Flag if a maximum translational velocity was set + bool has_max_trans_vel_; + + /// Maximum translational velocity [m/s] + double max_trans_vel_; + + /// Flag if a maximum translational acceleration was set + bool has_max_trans_acc_; + + /// Maximum translational acceleration [m/s^2] + double max_trans_acc_; + + /// Flag if a maximum translational deceleration was set + bool has_max_trans_dec_; + + /// Maximum translational deceleration, always <=0 [m/s^2] + double max_trans_dec_; + + /// Flag if a maximum rotational velocity was set + bool has_max_rot_vel_; + + /// Maximum rotational velocity [rad/s] + double max_rot_vel_; +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_limits_aggregator.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_limits_aggregator.h new file mode 100644 index 0000000000..796dc01c4c --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_limits_aggregator.h @@ -0,0 +1,65 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/cartesian_limit.h" + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Obtains cartesian limits from the parameter server + */ +class CartesianLimitsAggregator +{ +public: + /** + * @brief Loads cartesian limits from the parameter server + * + * The parameters are expected to be under "~/cartesian_limits" of the given + * node handle. + * The following limits can be specified: + * - "max_trans_vel", the maximum translational velocity [m/s] + * - "max_trans_acc, the maximum translational acceleration [m/s^2] + * - "max_trans_dec", the maximum translational deceleration (<= 0) [m/s^2] + * - "max_rot_vel", the maximum rotational velocity [rad/s] + * - "max_rot_acc", the maximum rotational acceleration [rad/s^2] + * - "max_rot_dec", the maximum rotational deceleration (<= 0)[rad/s^2] + * @param nh node handle to access the parameters + * @return the obtained cartesian limits + */ + static CartesianLimit getAggregatedLimits(const ros::NodeHandle& nh); +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_trajectory.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_trajectory.h new file mode 100644 index 0000000000..9d7b70431c --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_trajectory.h @@ -0,0 +1,51 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include +#include + +#include "cartesian_trajectory_point.h" + +namespace pilz_industrial_motion_planner +{ +struct CartesianTrajectory +{ + std::string group_name; + std::string link_name; + std::vector points; +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_trajectory_point.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_trajectory_point.h new file mode 100644 index 0000000000..4a5a57e55e --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/cartesian_trajectory_point.h @@ -0,0 +1,53 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include + +#include +#include +#include + +namespace pilz_industrial_motion_planner +{ +struct CartesianTrajectoryPoint +{ + geometry_msgs::Pose pose; + geometry_msgs::Twist velocity; + geometry_msgs::Twist acceleartion; + ros::Duration time_from_start; +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/command_list_manager.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/command_list_manager.h new file mode 100644 index 0000000000..ae2ea66387 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/command_list_manager.h @@ -0,0 +1,225 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include + +#include + +#include +#include +#include + +#include "moveit_msgs/MotionSequenceRequest.h" +#include "pilz_industrial_motion_planner/plan_components_builder.h" +#include "pilz_industrial_motion_planner/trajectory_blender.h" +#include "pilz_industrial_motion_planner/trajectory_generation_exceptions.h" + +namespace pilz_industrial_motion_planner +{ +using RobotTrajCont = std::vector; + +// List of exceptions which can be thrown by the CommandListManager class. +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NegativeBlendRadiusException, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(LastBlendRadiusNotZeroException, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(StartStateSetException, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(OverlappingBlendRadiiException, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(PlanningPipelineException, moveit_msgs::MoveItErrorCodes::FAILURE); + +/** + * @brief This class orchestrates the planning of single commands and + * command lists. + */ +class CommandListManager +{ +public: + CommandListManager(const ros::NodeHandle& nh, const robot_model::RobotModelConstPtr& model); + + /** + * @brief Generates trajectories for the specified list of motion commands. + * + * The following rules apply: + * - If two consecutive trajectories are from the same group, they are + * simply attached to each other, given that the blend_radius is zero. + * - If two consecutive trajectories are from the same group, they are + * blended together, given that the blend_radius is GREATER than zero. + * - If two consecutive trajectories are from different groups, then + * the second trajectory is added as new element to the result container. + * All following trajectories are then attached to the new trajectory + * element (until all requests are processed or until the next group change). + * + * @param planning_scene The planning scene to be used for trajectory + * generation. + * @param req_list List of motion requests containing: PTP, LIN, CIRC + * and/or gripper commands. + * Please note: A request is only valid if: + * - All blending radii are non negative. + * - The blending radius of the last request is 0. + * - Only the first request of each group has a start state. + * - None of the blending radii overlap with each other. + * + * Please note: + * Starts states do not need to state the joints of all groups. + * It is sufficient if a start state states only the joints of the group + * which it belongs to. Starts states can even be incomplete. In this case + * default values are set for the unset joints. + * + * @return Contains the calculated/generated trajectories. + */ + RobotTrajCont solve(const planning_scene::PlanningSceneConstPtr& planning_scene, + const planning_pipeline::PlanningPipelinePtr& planning_pipeline, + const moveit_msgs::MotionSequenceRequest& req_list); + +private: + using MotionResponseCont = std::vector; + using RobotState_OptRef = boost::optional; + using RadiiCont = std::vector; + using GroupNamesCont = std::vector; + +private: + /** + * @brief Validates that two consecutive blending radii do not overlap. + * + * @param motion_plan_responses Container of calculated/generated + * trajectories. + * @param radii Container stating the blend radii. + */ + void checkForOverlappingRadii(const MotionResponseCont& resp_cont, const RadiiCont& radii) const; + + /** + * @brief Solve each sequence item individually. + * + * @param planning_scene The planning_scene to be used for trajectory + * generation. + * @param req_list Container of requests for calculation/generation. + * + * @return Container of generated trajectories. + */ + MotionResponseCont solveSequenceItems(const planning_scene::PlanningSceneConstPtr& planning_scene, + const planning_pipeline::PlanningPipelinePtr& planning_pipeline, + const moveit_msgs::MotionSequenceRequest& req_list) const; + + /** + * @return TRUE if the blending radii of specified trajectories overlap, + * otherwise FALSE. The functions returns FALSE if both trajectories are from + * different groups or if both trajectories are end-effector groups. + */ + bool checkRadiiForOverlap(const robot_trajectory::RobotTrajectory& traj_A, const double radii_A, + const robot_trajectory::RobotTrajectory& traj_B, const double radii_B) const; + +private: + /** + * @return The last RobotState of the specified group which can + * be found in the specified vector. + */ + static RobotState_OptRef getPreviousEndState(const MotionResponseCont& motion_plan_responses, + const std::string& group_name); + + /** + * @brief Set start state to end state of previous calculated trajectory + * from group. + */ + static void setStartState(const MotionResponseCont& motion_plan_responses, const std::string& group_name, + moveit_msgs::RobotState& start_state); + + /** + * @return Container of radii extracted from the specified request list. + * + * Please note: + * This functions sets invalid blend radii to zero. Invalid blend radii are: + * - blend radii between end-effectors and + * - blend raddi between different groups. + */ + static RadiiCont extractBlendRadii(const moveit::core::RobotModel& model, + const moveit_msgs::MotionSequenceRequest& req_list); + + /** + * @return True in case of an invalid blend radii between specified + * command A and B, otherwise False. Invalid blend radii are: + * - blend radii between end-effectors and + * - blend raddi between different groups. + */ + static bool isInvalidBlendRadii(const moveit::core::RobotModel& model, const moveit_msgs::MotionSequenceItem& item_A, + const moveit_msgs::MotionSequenceItem& item_B); + + /** + * @brief Checks that all blend radii are greater or equal to zero. + */ + static void checkForNegativeRadii(const moveit_msgs::MotionSequenceRequest& req_list); + + /** + * @brief Checks that last blend radius is zero. + */ + static void checkLastBlendRadiusZero(const moveit_msgs::MotionSequenceRequest& req_list); + + /** + * @brief Checks that only the first request of the specified group has + * a start state in the specified request list. + */ + static void checkStartStatesOfGroup(const moveit_msgs::MotionSequenceRequest& req_list, const std::string& group_name); + + /** + * @brief Checks that each group in the specified request list has only + * one start state. + */ + static void checkStartStates(const moveit_msgs::MotionSequenceRequest& req_list); + + /** + * @return Returns all group names which are present in the specified + * request. + */ + static GroupNamesCont getGroupNames(const moveit_msgs::MotionSequenceRequest& req_list); + +private: + //! Node handle + ros::NodeHandle nh_; + + //! Robot model + moveit::core::RobotModelConstPtr model_; + + //! @brief Builder to construct the container containing the final + //! trajectories. + PlanComponentsBuilder plan_comp_builder_; +}; + +inline void CommandListManager::checkLastBlendRadiusZero(const moveit_msgs::MotionSequenceRequest& req_list) +{ + if (req_list.items.back().blend_radius != 0.0) + { + throw LastBlendRadiusNotZeroException("The last blending radius must be zero"); + } +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_aggregator.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_aggregator.h new file mode 100644 index 0000000000..0f60b353e5 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_aggregator.h @@ -0,0 +1,150 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/joint_limits_container.h" +#include "pilz_industrial_motion_planner/joint_limits_extension.h" + +#include + +#include +#include +#include + +#include + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Unifies the joint limits from the given joint models with joint + * limits from the parameter server. + * + * Does not support MultiDOF joints. + */ +class JointLimitsAggregator +{ +public: + /** + * @brief Aggregates(combines) the joint limits from joint model and + * parameter server. + * The rules for the combination are: + * 1. Position and velocity limits on the parameter server must be stricter + * or equal if they are defined. + * 2. Limits on the parameter server where the corresponding + * has__limits are „false“ + * are considered undefined(see point 1). + * 3. Not all joints have to be limited by the parameter server. Selective + * limitation is possible. + * 4. If max_deceleration is unset, it will be set to: max_deceleration = - + * max_acceleration. + * @note The acceleration/deceleration can only be set via the parameter + * server since they are not supported + * in the urdf so far. + * @param nh Node handle in whose namespace the joint limit parameters are + * expected. + * @param joint_models The joint models + * @return Container containing the limits + */ + static JointLimitsContainer getAggregatedLimits(const ros::NodeHandle& nh, + const std::vector& joint_models); + +protected: + /** + * @brief Update the position limits with the ones from the joint_model. + * + * If the joint model has no position limit, the value is unchanged. + * + * @param joint_model The joint model + * @param joint_limit The joint_limit to be filled with new values. + */ + static void updatePositionLimitFromJointModel(const moveit::core::JointModel* joint_model, JointLimit& joint_limit); + + /** + * @brief Update the velocity limit with the one from the joint_model. + * + * If the joint model has no velocity limit, the value is unchanged. + * + * @param joint_model The joint model + * @param joint_limit The joint_limit to be filled with new values. + */ + static void updateVelocityLimitFromJointModel(const moveit::core::JointModel* joint_model, JointLimit& joint_limit); + + /** + * @brief Checks if the position limits from the given joint_limit are + * stricter than the limits of the joint_model. + * Throws AggregationBoundsViolationException on violation + * @param joint_model The joint_model + * @param joint_limit The joint_limit + */ + static void checkPositionBoundsThrowing(const moveit::core::JointModel* joint_model, const JointLimit& joint_limit); + + /** + * @brief Checks if the velocity limit from the given joint_limit are stricter + * than the limit of the joint_model. + * Throws AggregationBoundsViolationException on violation + * @param joint_model The joint_model + * @param joint_limit The joint_limit + */ + static void checkVelocityBoundsThrowing(const moveit::core::JointModel* joint_model, const JointLimit& joint_limit); +}; + +/** + * @class AggregationException + * @brief A base class for all aggregation exceptions inheriting from + * std::runtime_exception + */ +class AggregationException : public std::runtime_error +{ +public: + AggregationException(const std::string& error_desc) : std::runtime_error(error_desc) + { + } +}; + +/** + * @class AggregationJointMissingException + * @brief Thrown the limits from the parameter server are weaker(forbidden) than + * the ones defined in the urdf + * + */ +class AggregationBoundsViolationException : public AggregationException +{ +public: + AggregationBoundsViolationException(const std::string& error_desc) : AggregationException(error_desc) + { + } +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_container.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_container.h new file mode 100644 index 0000000000..fac49e9106 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_container.h @@ -0,0 +1,163 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/joint_limits_extension.h" + +#include +#include + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Container for JointLimits, essentially a map with convenience + * functions. + * Adds the ability to as for limits and get a common limit that unifies all + * given limits + */ +class JointLimitsContainer +{ +public: + /** + * @brief Add a limit + * @param joint_name Name if the joint this limit belongs to + * @param joint_limit Limit of the joint + * @return true if the limit was added, false + * if joint_limit.has_deceleration_limit && + * joint_limit.max_deceleration >= 0 + */ + bool addLimit(const std::string& joint_name, JointLimit joint_limit); + + /** + * @brief Check if there is a limit for a joint with the given name in this + * container + * @param joint_name Name of the joint + */ + bool hasLimit(const std::string& joint_name) const; + + /** + * @brief Get Number of limits in the container + * @return Number of limits in the container + */ + size_t getCount() const; + + /** + * @brief Returns wether the container is empty + * @return true if empty, false otherwise + */ + bool empty() const; + + /** + * @brief Returns joint limit fusion of all(position, velocity, acceleration, + * deceleration) limits for all joint. + * There are cases where the most strict limit of all limits is needed. + * If there are no matching limits, the flag + * has_[position|velocity|...]_limits is set to false. + * + * @return joint limit + */ + JointLimit getCommonLimit() const; + + /** + * @brief Returns joint limit fusion of all(position, velocity, acceleration, + * deceleration) limits for given joints. + * There are cases where the most strict limit of all limits is needed. + * If there are no matching limits, the flag + * has_[position|velocity|...]_limits is set to false. + * + * @param joint_names + * @return joint limit + * @throws std::out_of_range if a joint limit with this name does not exist + */ + JointLimit getCommonLimit(const std::vector& joint_names) const; + + /** + * @brief getLimit get the limit for the given joint name + * @param joint_name + * @return joint limit + * @throws std::out_of_range if a joint limit with this name does not exist + */ + JointLimit getLimit(const std::string& joint_name) const; + + /** + * @brief ConstIterator to the underlying data structure + * @return + */ + std::map::const_iterator begin() const; + + /** + * @brief ConstIterator to the underlying data structure + * @return + */ + std::map::const_iterator end() const; + + /** + * @brief verify position limit of single joint + * @param joint_name + * @param joint_position + * @return + */ + bool verifyVelocityLimit(const std::string& joint_name, const double& joint_velocity) const; + + /** + * @brief verify position limit of single joint + * @param joint_name + * @param joint_position + * @return + */ + bool verifyPositionLimit(const std::string& joint_name, const double& joint_position) const; + + /** + * @brief verify position limits of multiple joints + * @param joint_names + * @param joint_positions + * @return + */ + bool verifyPositionLimits(const std::vector& joint_names, + const std::vector& joint_positions) const; + +private: + /** + * @brief update the most strict limit with given joint limit + * @param joint_limit + * @param common_limit the current most strict limit + */ + static void updateCommonLimit(const JointLimit& joint_limit, JointLimit& common_limit); + +protected: + /// Actual container object containing the data + std::map container_; +}; +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_extension.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_extension.h new file mode 100644 index 0000000000..84bb1fc79f --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_extension.h @@ -0,0 +1,66 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef JOINT_LIMITS_EXTENSION_H +#define JOINT_LIMITS_EXTENSION_H + +#include +#include + +namespace pilz_industrial_motion_planner +{ +namespace joint_limits_interface +{ +/** + * @brief Extends joint_limits_interface::JointLimits with a deceleration + * parameter + */ +struct JointLimits : ::joint_limits_interface::JointLimits +{ + JointLimits() : max_deceleration(0.0), has_deceleration_limits(false) + { + } + + /// maximum deceleration MUST(!) be negative + double max_deceleration; + + bool has_deceleration_limits; +}; +} // namespace joint_limits_interface + +typedef joint_limits_interface::JointLimits JointLimit; +typedef std::map JointLimitsMap; +} // namespace pilz_industrial_motion_planner + +#endif // JOINT_LIMITS_EXTENSION_H diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_interface_extension.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_interface_extension.h new file mode 100644 index 0000000000..4791267e92 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_interface_extension.h @@ -0,0 +1,101 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef JOINT_LIMITS_INTERFACE_EXTENSION_H +#define JOINT_LIMITS_INTERFACE_EXTENSION_H + +#include "pilz_industrial_motion_planner/joint_limits_extension.h" +#include + +namespace pilz_industrial_motion_planner +{ +namespace joint_limits_interface +{ +/** + * @see joint_limits_inteface::getJointLimits(...) + */ +inline bool getJointLimits(const std::string& joint_name, const ros::NodeHandle& nh, + joint_limits_interface::JointLimits& limits) +{ + // Node handle scoped where the joint limits are + // defined (copied from ::joint_limits_interface::getJointLimits(joint_name, + // nh, limits) + ros::NodeHandle limits_nh; + try + { + const std::string limits_namespace = "joint_limits/" + joint_name; + if (!nh.hasParam(limits_namespace)) + { + ROS_DEBUG_STREAM("No joint limits specification found for joint '" + << joint_name << "' in the parameter server (namespace " + << nh.getNamespace() + "/" + limits_namespace << ")."); + return false; + } + limits_nh = ros::NodeHandle(nh, limits_namespace); + } + catch (const ros::InvalidNameException& ex) + { + ROS_ERROR_STREAM(ex.what()); + return false; + } + + // Set the existing limits + if (!::joint_limits_interface::getJointLimits(joint_name, nh, limits)) + { + return false; // LCOV_EXCL_LINE // The case where getJointLimits returns + // false is covered above. + } + + // Deceleration limits + bool has_deceleration_limits = false; + if (limits_nh.getParam("has_deceleration_limits", has_deceleration_limits)) + { + if (!has_deceleration_limits) + { + limits.has_deceleration_limits = false; + } + double max_dec; + if (has_deceleration_limits && limits_nh.getParam("max_deceleration", max_dec)) + { + limits.has_deceleration_limits = true; + limits.max_deceleration = max_dec; + } + } + + return true; +} +} // namespace joint_limits_interface +} // namespace pilz_industrial_motion_planner + +#endif // JOINT_LIMITS_INTERFACE_EXTENSION_H diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_validator.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_validator.h new file mode 100644 index 0000000000..8b95269266 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_validator.h @@ -0,0 +1,153 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/joint_limits_container.h" +#include "pilz_industrial_motion_planner/joint_limits_extension.h" + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Validates the equality of all limits inside a container + */ +class JointLimitsValidator +{ +public: + /** + * @brief Validates that the position limits of all limits are equal + * @param joint_limits the joint limits + * @return true if all are equal + * @note always returns true if has_position_limits=false for all limits, or + * if the size of joint_limits is 0 or 1 + */ + static bool validateAllPositionLimitsEqual(const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits); + + /** + * @brief Validates that the velocity of all limits is equal + * @param joint_limits the joint limits + * @return true if all are equal + * @note always returns true if has_velocity_limits=false for all limits, or + * if the size of joint_limits is 0 or 1 + */ + static bool validateAllVelocityLimitsEqual(const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits); + + /** + * @brief Validates that the acceleration of all limits is equal + * @param joint_limits the joint limits + * @return true if all are equal + * @note always returns true if has_acceleration_limits=false for all limits, + * or if size of joint_limits is 0 or 1 + */ + static bool + validateAllAccelerationLimitsEqual(const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits); + + /** + * @brief Validates that the deceleration of all limits is equal + * @param joint_limits the joint limits + * @return true if all are equal + * @note always returns true if has_acceleration_limits=false for all limits, + * or if size of joint_limits is 0 or 1 + */ + static bool + validateAllDecelerationLimitsEqual(const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits); + +private: + static bool validateWithEqualFunc(bool (*eq_func)(const JointLimit&, const JointLimit&), + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits); + + static bool positionEqual(const JointLimit& lhs, const JointLimit& rhs); + + static bool velocityEqual(const JointLimit& lhs, const JointLimit& rhs); + + static bool accelerationEqual(const JointLimit& lhs, const JointLimit& rhs); + + static bool decelerationEqual(const JointLimit& lhs, const JointLimit& rhs); +}; + +/** + * @class ValidationException + * @brief A base class for all validations exceptions inheriting from + * std::runtime_exception + */ +class ValidationException : public std::runtime_error +{ +public: + ValidationException(const std::string& error_desc) : std::runtime_error(error_desc) + { + } +}; + +/** + * @class ValidationJointMissingException + * @brief Thrown the limits for a joint are defined in the urdf but not on the + * parameter server (loaded from yaml) + * + */ +class ValidationJointMissingException : public ValidationException +{ +public: + ValidationJointMissingException(const std::string& error_desc) : ValidationException(error_desc) + { + } +}; + +/** + * @class ValidationDifferentLimitsException + * @brief Thrown when the limits differ + * + */ +class ValidationDifferentLimitsException : public ValidationException +{ +public: + ValidationDifferentLimitsException(const std::string& error_desc) : ValidationException(error_desc) + { + } +}; + +/** + * @class ValidationBoundsViolationException + * @brief Thrown when the limits from the param server are weaker than the ones + * obtained from the urdf + * + */ +class ValidationBoundsViolationException : public ValidationException +{ +public: + ValidationBoundsViolationException(const std::string& error_desc) : ValidationException(error_desc) + { + } +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/limits_container.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/limits_container.h new file mode 100644 index 0000000000..79e9d3ba00 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/limits_container.h @@ -0,0 +1,104 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/cartesian_limit.h" +#include "pilz_industrial_motion_planner/joint_limits_container.h" +#include + +namespace pilz_industrial_motion_planner +{ +/** + * @brief This class combines CartesianLimit and JointLimits into on single + * class. + */ +class LimitsContainer +{ +public: + LimitsContainer(); + + /** + * @brief Return if this LimitsContainer has defined joint limits + * @return True if container contains joint limits + */ + bool hasJointLimits() const; + + /** + * @brief Set joint limits + * @param joint_limits + */ + void setJointLimits(JointLimitsContainer& joint_limits); + + /** + * @brief Obtain the Joint Limits from the container + * @return the joint limits + */ + const JointLimitsContainer& getJointLimitContainer() const; + + /** + * @brief Return if this LimitsContainer has defined cartesian limits + * + * @return True if container contains cartesian limits including maximum + * velocity/acceleration/deceleration + */ + bool hasFullCartesianLimits() const; + + /** + * @brief Set cartesian limits + * @param cartesian_limit + */ + void setCartesianLimits(CartesianLimit& cartesian_limit); + + /** + * @brief Return the cartesian limits + * @return the cartesian limits + */ + const CartesianLimit& getCartesianLimits() const; + +private: + /// Flag if joint limits where set + bool has_joint_limits_; + + /// The joint limits + JointLimitsContainer joint_limits_; + + /// Flag if cartesian limits have been set + bool has_cartesian_limits_; + + /// The cartesian limits + CartesianLimit cartesian_limit_; +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/move_group_sequence_action.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/move_group_sequence_action.h new file mode 100644 index 0000000000..543c701579 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/move_group_sequence_action.h @@ -0,0 +1,90 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include + +#include +#include + +#include + +namespace pilz_industrial_motion_planner +{ +class CommandListManager; + +/** + * @brief Provide action to handle multiple trajectories and execute the result + * in the form of a MoveGroup capability (plugin). + */ +class MoveGroupSequenceAction : public move_group::MoveGroupCapability +{ +public: + MoveGroupSequenceAction(); + + void initialize() override; + +private: + using ExecutableTrajs = std::vector; + + using StartStateMsg = moveit_msgs::MotionSequenceResponse::_sequence_start_type; + using StartStatesMsg = std::vector; + using PlannedTrajMsgs = moveit_msgs::MotionSequenceResponse::_planned_trajectories_type; + +private: + void executeSequenceCallback(const moveit_msgs::MoveGroupSequenceGoalConstPtr& goal); + void executeSequenceCallbackPlanAndExecute(const moveit_msgs::MoveGroupSequenceGoalConstPtr& goal, + moveit_msgs::MoveGroupSequenceResult& action_res); + void executeMoveCallbackPlanOnly(const moveit_msgs::MoveGroupSequenceGoalConstPtr& goal, + moveit_msgs::MoveGroupSequenceResult& res); + void startMoveExecutionCallback(); + void startMoveLookCallback(); + void preemptMoveCallback(); + void setMoveState(move_group::MoveGroupState state); + bool planUsingSequenceManager(const moveit_msgs::MotionSequenceRequest& req, + plan_execution::ExecutableMotionPlan& plan); + +private: + static void convertToMsg(const ExecutableTrajs& trajs, StartStatesMsg& startStatesMsg, + PlannedTrajMsgs& plannedTrajsMsgs); + +private: + std::unique_ptr> move_action_server_; + moveit_msgs::MoveGroupSequenceFeedback move_feedback_; + + move_group::MoveGroupState move_state_{ move_group::IDLE }; + std::unique_ptr command_list_manager_; +}; +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/move_group_sequence_service.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/move_group_sequence_service.h new file mode 100644 index 0000000000..54c0af0f61 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/move_group_sequence_service.h @@ -0,0 +1,66 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include + +#include + +namespace pilz_industrial_motion_planner +{ +// Forward declarations +class CommandListManager; + +/** + * @brief Provide service to blend multiple trajectories in the form of a + * MoveGroup capability (plugin). + */ +class MoveGroupSequenceService : public move_group::MoveGroupCapability +{ +public: + MoveGroupSequenceService(); + ~MoveGroupSequenceService() override; + + void initialize() override; + +private: + bool plan(moveit_msgs::GetMotionSequence::Request& req, moveit_msgs::GetMotionSequence::Response& res); + +private: + ros::ServiceServer sequence_service_; + std::unique_ptr command_list_manager_; +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/path_circle_generator.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/path_circle_generator.h new file mode 100644 index 0000000000..b2f13f7a84 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/path_circle_generator.h @@ -0,0 +1,101 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include +#include +#include +#include + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Generator class for KDL::Path_Circle from different circle + * representations + */ +class PathCircleGenerator +{ +public: + /** + * @brief set the path circle from start, goal and center point + * + * Note that a half circle should use interim point and cannot be defined + * by circle center since start/goal/center points are colinear. + * @throws KDL::Error_MotionPlanning in case start and goal have different + * radii to the center point. + */ + static std::unique_ptr circleFromCenter(const KDL::Frame& start_pose, const KDL::Frame& goal_pose, + const KDL::Vector& center_point, double eqradius); + + /** + * @brief set circle from start, goal and interim point + + * @throws KDL::Error_MotionPlanning if the given points are colinear. + */ + static std::unique_ptr circleFromInterim(const KDL::Frame& start_pose, const KDL::Frame& goal_pose, + const KDL::Vector& interim_point, double eqradius); + +private: + PathCircleGenerator(){}; // no instantiation of this helper class! + + /** + * @brief law of cosines: returns angle gamma in c² = a²+b²-2ab cos(gamma) + * + * @return angle in radians + */ + static double cosines(const double a, const double b, const double c); + + static constexpr double MAX_RADIUS_DIFF{ 1e-2 }; + static constexpr double MAX_COLINEAR_NORM{ 1e-5 }; +}; + +} // namespace pilz_industrial_motion_planner + +class ErrorMotionPlanningCenterPointDifferentRadius : public KDL::Error_MotionPlanning +{ +public: + const char* Description() const override + { + return "Distances between start-center and goal-center are different." + " A circle cannot be created."; + } + int GetType() const override + { + return ERROR_CODE_CENTER_POINT_DIFFERENT_RADIUS; + } // LCOV_EXCL_LINE + +private: + static constexpr int ERROR_CODE_CENTER_POINT_DIFFERENT_RADIUS{ 3006 }; +}; diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/pilz_industrial_motion_planner.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/pilz_industrial_motion_planner.h new file mode 100644 index 0000000000..13ae41e67e --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/pilz_industrial_motion_planner.h @@ -0,0 +1,139 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include + +#include "pilz_industrial_motion_planner/joint_limits_extension.h" +#include "pilz_industrial_motion_planner/planning_context_loader.h" + +#include +#include + +#include + +// Boost includes +#include + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Moveit Plugin for Planning with Standart Robot Commands + * This planner is dedicated to return a instance of PlanningContext that + * corresponds to the requested motion command + * set as planner_id in the MotionPlanRequest). + * It can be easily extended with additional commands by creating a class + * inherting from PlanningContextLoader. + */ +class CommandPlanner : public planning_interface::PlannerManager +{ +public: + ~CommandPlanner() override + { + } + + /** + * @brief Initializes the planner + * Upon initialization this planner will look for plugins implementing + * pilz_industrial_motion_planner::PlanningContextLoader. + * @param model The robot model + * @param ns The namespace + * @return true on success, false otherwise + */ + bool initialize(const robot_model::RobotModelConstPtr& model, const std::string& ns) override; + + /// Description of the planner + std::string getDescription() const override; + + /** + * @brief Returns the available planning commands + * @param list with the planning algorithms + * @note behined each command is a + * pilz_industrial_motion_planner::PlanningContextLoader loaded as plugin + */ + void getPlanningAlgorithms(std::vector& algs) const override; + + /** + * @brief Returns a PlanningContext that can be used to solve(calculate) the + * trajectory that corresponds to command + * given in motion request as planner_id. + * @param planning_scene + * @param req + * @param error_code + * @return + */ + planning_interface::PlanningContextPtr getPlanningContext(const planning_scene::PlanningSceneConstPtr& planning_scene, + const planning_interface::MotionPlanRequest& req, + moveit_msgs::MoveItErrorCodes& error_code) const override; + + /** + * @brief Checks if the request can be handled + * @param motion request containing the planning_id that corresponds to the + * motion command + * @return true if the request can be handled + */ + bool canServiceRequest(const planning_interface::MotionPlanRequest& req) const override; + + /** + * @brief Register a PlanningContextLoader to be used by the CommandPlanner + * @param planning_context_loader + * @throw ContextLoaderRegistrationException if a loader with the same + * algorithm name is already registered + */ + void registerContextLoader(const pilz_industrial_motion_planner::PlanningContextLoaderPtr& planning_context_loader); + +private: + /// Plugin loader + boost::scoped_ptr> planner_context_loader; + + /// Mapping from command to loader + std::map context_loader_map_; + + /// Robot model obtained at initialize + moveit::core::RobotModelConstPtr model_; + + /// Namespace where the parameters are stored, obtained at initialize + std::string namespace_; + + /// aggregated limits of the active joints + pilz_industrial_motion_planner::JointLimitsContainer aggregated_limit_active_joints_; + + /// cartesian limit + pilz_industrial_motion_planner::CartesianLimit cartesian_limit_; +}; + +MOVEIT_CLASS_FORWARD(CommandPlanner) + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/plan_components_builder.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/plan_components_builder.h new file mode 100644 index 0000000000..a89b3fbbd3 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/plan_components_builder.h @@ -0,0 +1,158 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include +#include + +#include +#include + +#include "pilz_industrial_motion_planner/trajectory_blend_request.h" +#include "pilz_industrial_motion_planner/trajectory_blender.h" +#include "pilz_industrial_motion_planner/trajectory_functions.h" +#include "pilz_industrial_motion_planner/trajectory_generation_exceptions.h" + +namespace pilz_industrial_motion_planner +{ +using TipFrameFunc_t = std::function; + +// List of exceptions which can be thrown by the PlanComponentsBuilder class. +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NoBlenderSetException, moveit_msgs::MoveItErrorCodes::FAILURE); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NoTipFrameFunctionSetException, moveit_msgs::MoveItErrorCodes::FAILURE); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NoRobotModelSetException, moveit_msgs::MoveItErrorCodes::FAILURE); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(BlendingFailedException, moveit_msgs::MoveItErrorCodes::FAILURE); + +/** + * @brief Helper class to encapsulate the merge and blend process of + * trajectories. + */ +class PlanComponentsBuilder +{ +public: + /** + * @brief Sets the blender used to blend two trajectories. + */ + void setBlender(std::unique_ptr blender); + + /** + * @brief Sets the robot model needed to create new trajectory elements. + */ + void setModel(const moveit::core::RobotModelConstPtr& model); + + /** + * @brief Appends the specified trajectory to the trajectory container + * under construction. + * + * The appending complies to the following rules: + * - A trajectory is simply added/attached to the previous trajectory: + * - if they are from the same group and + * - if the specified blend_radius is zero. + * - A trajectory is blended together with the previous trajectory: + * - if they are from the same group and + * - if the specified blend_radius is GREATER than zero. + * - A new trajectory element is created and the given trajectory is + * appended/attached to the newly created empty trajectory: + * - if the given and previous trajectory are from different groups. + * + * @param other Trajectories which has to be added to the trajectory container + * under construction. + * + * @param blend_radius The blending radius between the previous and the + * specified trajectory. + */ + void append(const robot_trajectory::RobotTrajectoryPtr& other, const double blend_radius); + + /** + * @brief Clears the trajectory container under construction. + */ + void reset(); + + /** + * @return The final trajectory container which results from the append calls. + */ + std::vector build() const; + +private: + void blend(const robot_trajectory::RobotTrajectoryPtr& other, const double blend_radius); + +private: + /** + * @brief Appends a trajectory to a result trajectory leaving out the + * first point, if it matches the last point of the result trajectory. + * + * @note Controllers, so far at least the + * ros_controllers::JointTrajectoryController require a timewise strictly + * increasing trajectory. If through appending the last point of the + * original trajectory gets repeated, it is removed here. + */ + static void appendWithStrictTimeIncrease(robot_trajectory::RobotTrajectory& result, + const robot_trajectory::RobotTrajectory& source); + +private: + //! Blender used to blend two trajectories. + std::unique_ptr blender_; + + //! Robot model needed to create new trajectory container elements. + moveit::core::RobotModelConstPtr model_; + + //! The previously added trajectory. + robot_trajectory::RobotTrajectoryPtr traj_tail_; + + //! The trajectory container under construction. + std::vector traj_cont_; + +private: + //! Constant to check for equality of variables of two RobotState instances. + static constexpr double ROBOT_STATE_EQUALITY_EPSILON = 1e-4; +}; + +inline void PlanComponentsBuilder::setBlender(std::unique_ptr blender) +{ + blender_ = std::move(blender); +} + +inline void PlanComponentsBuilder::setModel(const moveit::core::RobotModelConstPtr& model) +{ + model_ = model; +} + +inline void PlanComponentsBuilder::reset() +{ + traj_tail_ = nullptr; + traj_cont_.clear(); +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_base.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_base.h new file mode 100644 index 0000000000..14143a0ed8 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_base.h @@ -0,0 +1,181 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/joint_limits_container.h" +#include "pilz_industrial_motion_planner/trajectory_generator.h" + +#include + +#include +#include +#include +#include + +#include +#include + +namespace pilz_industrial_motion_planner +{ +/** + * @brief PlanningContext for obtaining trajectories + */ +template +class PlanningContextBase : public planning_interface::PlanningContext +{ +public: + PlanningContextBase(const std::string& name, const std::string& group, + const moveit::core::RobotModelConstPtr& model, + const pilz_industrial_motion_planner::LimitsContainer& limits) + : planning_interface::PlanningContext(name, group) + , terminated_(false) + , model_(model) + , limits_(limits) + , generator_(model, limits_) + { + } + + ~PlanningContextBase() override + { + } + + /** + * @brief Calculates a trajectory for the request this context is currently + * set for + * @param res The result containing the respective trajectory, or error_code + * on failure + * @return true on success, false otherwise + */ + bool solve(planning_interface::MotionPlanResponse& res) override; + + /** + * @brief Will return the same trajectory as + * solve(planning_interface::MotionPlanResponse& res) + * This function just delegates to the common response however here the same + * trajectory is stored with the + * descriptions "plan", "simplify", "interpolate" + * @param res The detailed response + * @return true on success, false otherwise + */ + bool solve(planning_interface::MotionPlanDetailedResponse& res) override; + + /** + * @brief Will terminate solve() + * @return + * @note Currently will not stop a runnning solve but not start future solves. + */ + bool terminate() override; + + /** + * @copydoc planning_interface::PlanningContext::clear() + */ + void clear() override; + + /// Flag if terminated + std::atomic_bool terminated_; + + /// The robot model + robot_model::RobotModelConstPtr model_; + + /// Joint limits to be used during planning + pilz_industrial_motion_planner::LimitsContainer limits_; + +protected: + GeneratorT generator_; +}; + +template +bool pilz_industrial_motion_planner::PlanningContextBase::solve(planning_interface::MotionPlanResponse& res) +{ + if (!terminated_) + { + // Use current state as start state if not set + if (request_.start_state.joint_state.name.empty()) + { + moveit_msgs::RobotState current_state; + moveit::core::robotStateToRobotStateMsg(getPlanningScene()->getCurrentState(), current_state); + request_.start_state = current_state; + } + bool result = generator_.generate(request_, res); + return result; + // res.error_code_.val = moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN; + // return false; // TODO + } + + ROS_ERROR("Using solve on a terminated planning context!"); + res.error_code_.val = moveit_msgs::MoveItErrorCodes::PLANNING_FAILED; + return false; +} + +template +bool pilz_industrial_motion_planner::PlanningContextBase::solve( + planning_interface::MotionPlanDetailedResponse& res) +{ + // delegate to regular response + planning_interface::MotionPlanResponse undetailed_response; + bool result = solve(undetailed_response); + + res.description_.push_back("plan"); + res.trajectory_.push_back(undetailed_response.trajectory_); + res.processing_time_.push_back(undetailed_response.planning_time_); + + res.description_.push_back("simplify"); + res.trajectory_.push_back(undetailed_response.trajectory_); + res.processing_time_.push_back(0); + + res.description_.push_back("interpolate"); + res.trajectory_.push_back(undetailed_response.trajectory_); + res.processing_time_.push_back(0); + + res.error_code_ = undetailed_response.error_code_; + return result; +} + +template +bool pilz_industrial_motion_planner::PlanningContextBase::terminate() +{ + ROS_DEBUG_STREAM("Terminate called"); + terminated_ = true; + return true; +} + +template +void pilz_industrial_motion_planner::PlanningContextBase::clear() +{ + // No structures that need cleaning + return; +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_circ.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_circ.h new file mode 100644 index 0000000000..f9e69f4791 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_circ.h @@ -0,0 +1,67 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/limits_container.h" + +#include + +#include +#include + +#include +#include + +#include "pilz_industrial_motion_planner/planning_context_base.h" +#include "pilz_industrial_motion_planner/trajectory_generator_circ.h" + +namespace pilz_industrial_motion_planner +{ +MOVEIT_CLASS_FORWARD(PlanningContext) + +/** + * @brief PlanningContext for obtaining CIRC trajectories + */ +class PlanningContextCIRC : public pilz_industrial_motion_planner::PlanningContextBase +{ +public: + PlanningContextCIRC(const std::string& name, const std::string& group, const moveit::core::RobotModelConstPtr& model, + const pilz_industrial_motion_planner::LimitsContainer& limits) + : pilz_industrial_motion_planner::PlanningContextBase(name, group, model, limits) + { + } +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_lin.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_lin.h new file mode 100644 index 0000000000..d0990c3913 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_lin.h @@ -0,0 +1,65 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/limits_container.h" + +#include + +#include +#include + +#include +#include + +#include "pilz_industrial_motion_planner/planning_context_base.h" +#include "pilz_industrial_motion_planner/trajectory_generator_lin.h" + +namespace pilz_industrial_motion_planner +{ +MOVEIT_CLASS_FORWARD(PlanningContext) + +/** + * @brief PlanningContext for obtaining LIN trajectories + */ +class PlanningContextLIN : public pilz_industrial_motion_planner::PlanningContextBase +{ +public: + PlanningContextLIN(const std::string& name, const std::string& group, const moveit::core::RobotModelConstPtr& model, + const pilz_industrial_motion_planner::LimitsContainer& limits) + : pilz_industrial_motion_planner::PlanningContextBase(name, group, model, limits) + { + } +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader.h new file mode 100644 index 0000000000..bb0839ed1e --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader.h @@ -0,0 +1,144 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/limits_container.h" + +#include +#include + +#include + +#include "pilz_industrial_motion_planner/limits_container.h" + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Base class for all PlanningContextLoaders. + * Since planning_interface::PlanningContext has a non empty ctor classes + * derived from it can not be plugins. + * This class serves as base class for wrappers. + */ +class PlanningContextLoader +{ +public: + PlanningContextLoader(); + virtual ~PlanningContextLoader(); + + /// Return the algorithm the loader uses + virtual std::string getAlgorithm() const; + + /** + * @brief Sets the robot model that can be passed to the planning context + * @param model The robot model + * @return false if could not be set + */ + virtual bool setModel(const moveit::core::RobotModelConstPtr& model); + + /** + * @brief Sets limits the planner can pass to the contexts + * @param limits container of limits, no guarantee to contain the limits for + * all joints of the model + * @return true if limits could be set + */ + virtual bool setLimits(const pilz_industrial_motion_planner::LimitsContainer& limits); + + /** + * @brief Return the planning context + * @param planning_context + * @param name context name + * @param group name of the planning group + * @return true on success, false otherwise + */ + virtual bool loadContext(planning_interface::PlanningContextPtr& planning_context, const std::string& name, + const std::string& group) const = 0; + +protected: + /** + * @brief Return the planning context of type T + * @param planning_context + * @param name context name + * @param group name of the planning group + * @return true on success, false otherwise + */ + template + bool loadContext(planning_interface::PlanningContextPtr& planning_context, const std::string& name, + const std::string& group) const; + +protected: + /// Name of the algorithm + std::string alg_; + + /// True if limits are set + bool limits_set_; + + /// Limits to be used during planning + pilz_industrial_motion_planner::LimitsContainer limits_; + + /// True if model is set + bool model_set_; + + /// The robot model + moveit::core::RobotModelConstPtr model_; +}; + +typedef boost::shared_ptr PlanningContextLoaderPtr; +typedef boost::shared_ptr PlanningContextLoaderConstPtr; + +template +bool PlanningContextLoader::loadContext(planning_interface::PlanningContextPtr& planning_context, + const std::string& name, const std::string& group) const +{ + if (limits_set_ && model_set_) + { + planning_context.reset(new T(name, group, model_, limits_)); + return true; + } + else + { + if (!limits_set_) + { + ROS_ERROR_STREAM("Limits are not defined. Cannot load planning context. " + "Call setLimits loadContext"); + } + if (!model_set_) + { + ROS_ERROR_STREAM("Robot model was not set"); + } + return false; + } +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader_circ.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader_circ.h new file mode 100644 index 0000000000..b1760aac2c --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader_circ.h @@ -0,0 +1,68 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/planning_context_loader.h" + +#include + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Plugin that can generate instances of PlanningContextCIRC. + * Generates instances of PlanningContextLIN. + */ +class PlanningContextLoaderCIRC : public PlanningContextLoader +{ +public: + PlanningContextLoaderCIRC(); + ~PlanningContextLoaderCIRC() override; + + /** + * @brief return a instance of + * pilz_industrial_motion_planner::PlanningContextCIRC + * @param planning_context returned context + * @param name + * @param group + * @return true on success, false otherwise + */ + bool loadContext(planning_interface::PlanningContextPtr& planning_context, const std::string& name, + const std::string& group) const override; +}; + +typedef boost::shared_ptr PlanningContextLoaderCIRCPtr; +typedef boost::shared_ptr PlanningContextLoaderCIRCConstPtr; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader_lin.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader_lin.h new file mode 100644 index 0000000000..f3215fd869 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader_lin.h @@ -0,0 +1,68 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/planning_context_loader.h" + +#include + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Plugin that can generate instances of PlanningContextLIN. + * Generates instances of PlanningContextLIN. + */ +class PlanningContextLoaderLIN : public PlanningContextLoader +{ +public: + PlanningContextLoaderLIN(); + ~PlanningContextLoaderLIN() override; + + /** + * @brief return a instance of + * pilz_industrial_motion_planner::PlanningContextLIN + * @param planning_context returned context + * @param name + * @param group + * @return true on success, false otherwise + */ + bool loadContext(planning_interface::PlanningContextPtr& planning_context, const std::string& name, + const std::string& group) const override; +}; + +typedef boost::shared_ptr PlanningContextLoaderLINPtr; +typedef boost::shared_ptr PlanningContextLoaderLINConstPtr; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader_ptp.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader_ptp.h new file mode 100644 index 0000000000..52ec4f6af7 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_loader_ptp.h @@ -0,0 +1,68 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/planning_context_loader.h" + +#include + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Plugin that can generate instances of PlanningContextPTP. + * Generates instances of PlanningContextPTP. + */ +class PlanningContextLoaderPTP : public PlanningContextLoader +{ +public: + PlanningContextLoaderPTP(); + ~PlanningContextLoaderPTP() override; + + /** + * @brief return a instance of + * pilz_industrial_motion_planner::PlanningContextPTP + * @param planning_context returned context + * @param name + * @param group + * @return true on success, false otherwise + */ + bool loadContext(planning_interface::PlanningContextPtr& planning_context, const std::string& name, + const std::string& group) const override; +}; + +typedef boost::shared_ptr PlanningContextLoaderPTPPtr; +typedef boost::shared_ptr PlanningContextLoaderPTPConstPtr; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_ptp.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_ptp.h new file mode 100644 index 0000000000..842c350f19 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_context_ptp.h @@ -0,0 +1,67 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/limits_container.h" + +#include + +#include +#include + +#include +#include + +#include "pilz_industrial_motion_planner/planning_context_base.h" +#include "pilz_industrial_motion_planner/trajectory_generator_ptp.h" + +namespace pilz_industrial_motion_planner +{ +MOVEIT_CLASS_FORWARD(PlanningContext) + +/** + * @brief PlanningContext for obtaining PTP trajectories + */ +class PlanningContextPTP : public pilz_industrial_motion_planner::PlanningContextBase +{ +public: + PlanningContextPTP(const std::string& name, const std::string& group, const moveit::core::RobotModelConstPtr& model, + const pilz_industrial_motion_planner::LimitsContainer& limits) + : pilz_industrial_motion_planner::PlanningContextBase(name, group, model, limits) + { + } +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_exceptions.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_exceptions.h new file mode 100644 index 0000000000..5dfc44da29 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/planning_exceptions.h @@ -0,0 +1,71 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include + +namespace pilz_industrial_motion_planner +{ +/** + * @class PlanningException + * @brief A base class for all pilz_industrial_motion_planner exceptions + * inheriting from std::runtime_exception + */ +class PlanningException : public std::runtime_error +{ +public: + PlanningException(const std::string& error_desc) : std::runtime_error(error_desc) + { + } +}; + +/** + * @class PlanningContextFactoryRegistrationException + * @brief An exception class thrown when the planner manager is unable to load a + * factory + * + * Loading a PlanningContextFactory can fail if a factory is loaded that + * would provide a command which was already provided by another factory loaded + * before. + */ +class ContextLoaderRegistrationException : public PlanningException +{ +public: + ContextLoaderRegistrationException(const std::string& error_desc) : PlanningException(error_desc) + { + } +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/tip_frame_getter.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/tip_frame_getter.h new file mode 100644 index 0000000000..e173bbde37 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/tip_frame_getter.h @@ -0,0 +1,90 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include +#include +#include +#include + +#include "pilz_industrial_motion_planner/trajectory_generation_exceptions.h" + +namespace pilz_industrial_motion_planner +{ +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NoSolverException, moveit_msgs::MoveItErrorCodes::FAILURE); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(MoreThanOneTipFrameException, moveit_msgs::MoveItErrorCodes::FAILURE); + +/** + * @returns true if the JointModelGroup has a solver, false otherwise. + * + * @tparam JointModelGroup aims at moveit::core::JointModelGroup + * @throws exception in case group is null. + */ +template +static bool hasSolver(const JointModelGroup* group) +{ + if (group == nullptr) + { + throw std::invalid_argument("Group must not be null"); + } + return group->getSolverInstance() != nullptr; +} + +/** + * @return The name of the tip frame (link) of the specified group + * returned by the solver. + * + * @tparam JointModelGroup aims at moveit::core::JointModelGroup + * @throws exception in case the group has no solver. + * @throws exception in case the solver for the group has more than one tip + * frame. + */ +template +static const std::string& getSolverTipFrame(const JointModelGroup* group) +{ + if (!hasSolver(group)) + { + throw NoSolverException("No solver for group " + group->getName()); + } + + const std::vector& tip_frames{ group->getSolverInstance()->getTipFrames() }; + if (tip_frames.size() > 1) + { + throw MoreThanOneTipFrameException("Solver for group \"" + group->getName() + "\" has more than one tip frame"); + } + return tip_frames.front(); +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blend_request.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blend_request.h new file mode 100644 index 0000000000..450f89fea5 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blend_request.h @@ -0,0 +1,59 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include + +#include + +namespace pilz_industrial_motion_planner +{ +struct TrajectoryBlendRequest +{ + // The name of the group of joints on which this blender is operating + std::string group_name; + + // The name of the target link on which this blender is operating + std::string link_name; + + // Robot trajectories to be blended + robot_trajectory::RobotTrajectoryPtr first_trajectory; + robot_trajectory::RobotTrajectoryPtr second_trajectory; + + // Blend radius in meter + double blend_radius; +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blend_response.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blend_response.h new file mode 100644 index 0000000000..880f2b777e --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blend_response.h @@ -0,0 +1,57 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include + +#include + +namespace pilz_industrial_motion_planner +{ +struct TrajectoryBlendResponse +{ + // The name of the group of joints on which this blender is operating + std::string group_name; + + // Resulted robot trajectories after blending + robot_trajectory::RobotTrajectoryPtr first_trajectory; + robot_trajectory::RobotTrajectoryPtr blend_trajectory; + robot_trajectory::RobotTrajectoryPtr second_trajectory; + + // Error code + moveit_msgs::MoveItErrorCodes error_code; +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blender.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blender.h new file mode 100644 index 0000000000..ce647b5479 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blender.h @@ -0,0 +1,74 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/limits_container.h" +#include + +#include "pilz_industrial_motion_planner/trajectory_blend_request.h" +#include "pilz_industrial_motion_planner/trajectory_blend_response.h" + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Base class of trajectory blenders + */ +class TrajectoryBlender +{ +public: + TrajectoryBlender(const pilz_industrial_motion_planner::LimitsContainer& planner_limits) : limits_(planner_limits) + { + } + + virtual ~TrajectoryBlender() + { + } + + /** + * @brief Blend two robot trajectories with the given blending radius + * @param req: trajectory blend request + * @param res: trajectroy blend response + * @return true if blend succeed + */ + virtual bool blend(const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, + pilz_industrial_motion_planner::TrajectoryBlendResponse& res) = 0; + +protected: + const pilz_industrial_motion_planner::LimitsContainer limits_; +}; + +typedef std::unique_ptr TrajectoryBlenderUniquePtr; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blender_transition_window.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blender_transition_window.h new file mode 100644 index 0000000000..233bdd3e31 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_blender_transition_window.h @@ -0,0 +1,178 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "pilz_industrial_motion_planner/cartesian_trajectory.h" +#include "pilz_industrial_motion_planner/cartesian_trajectory_point.h" +#include "pilz_industrial_motion_planner/trajectory_blend_request.h" +#include "pilz_industrial_motion_planner/trajectory_blender.h" +#include "pilz_industrial_motion_planner/trajectory_functions.h" + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Trajectory blender implementing transition window algorithm + * + * See doc/MotionBlendAlgorithmDescription.pdf for a mathematical description of + * the algorithmn. + */ +class TrajectoryBlenderTransitionWindow : public TrajectoryBlender +{ +public: + TrajectoryBlenderTransitionWindow(const LimitsContainer& planner_limits) + : TrajectoryBlender::TrajectoryBlender(planner_limits) + { + } + + ~TrajectoryBlenderTransitionWindow() override + { + } + + /** + * @brief Blend two trajectories using transition window. The trajectories + * have to be equally and uniformly + * discretized. + * @param req: following fields need to be filled for a valid request: + * - group_name : name of the planning group + * - link_name : name of the target link + * - first_trajectory: Joint trajectory stops at end point. + * The last point must be the same as the first point + * of the second trajectory. + * - second trajectory: Joint trajectory stops at end point. + * The first point must be the same as the last point + * of the first trajectory. + * - blend_radius: The blend radius determines a sphere with the + * intersection point of the two trajectories + * as the center. Trajectory blending happens inside of + * this sphere. + * @param res: following fields are returned as response by the blend + * algorithm + * - group_name : name of the planning group + * - first_trajectory: Part of the first original trajectory which is + * outside of the blend sphere. + * - blend_trajectory: Joint trajectory connecting the first and second + * trajectories without stop. + * The first waypoint has non-zero time from start. + * - second trajectory: Part of the second original trajectory which is + * outside of the blend sphere. + * The first waypoint has non-zero time from start. + * error_code: information of failed blend + * @return true if succeed + */ + bool blend(const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, + pilz_industrial_motion_planner::TrajectoryBlendResponse& res) override; + +private: + /** + * @brief validate trajectory blend request + * @param req + * @param sampling_time: get the same sampling time of the two input + * trajectories + * @param error_code + * @return + */ + bool validateRequest(const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, double& sampling_time, + moveit_msgs::MoveItErrorCodes& error_code) const; + /** + * @brief searchBlendPoint + * @param req: trajectory blend request + * @param first_interse_index: index of the first point of the first + * trajectory that is inside the blend sphere + * @param second_interse_index: index of the last point of the second + * trajectory that is still inside the blend sphere + */ + bool searchIntersectionPoints(const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, + std::size_t& first_interse_index, std::size_t& second_interse_index) const; + + /** + * @brief Determine how the second trajectory should be aligned with the first + * trajectory for blend. + * Let tau_1 be the time of the first trajectory from the first_interse_index + * to the end and tau_2 the time of the + * second trajectory from the beginning to the second_interse_index: + * - if tau_1 > tau_2:
+ * align the end of the first trajectory with second_interse_index + *

+   *    first traj:  |-------------|--------!--------------|
+   *    second traj:                        |--------------|-------------------|
+   *    blend phase:               |-----------------------|
+   *    
+ * - else:
+ * align the first_interse_index with the beginning of the second + * trajectory + *
+   *    first traj:  |-------------|-----------------------|
+   *    second traj: |-----------------------!----------|-------------------|
+   *    blend phase:               |----------------------------------|
+   *    
+ * + * @param req: trajectory blend request + * @param first_interse_index: index of the intersection point between first + * trajectory and blend sphere + * @param second_interse_index: index of the intersection point between second + * trajectory and blend sphere + * @param blend_align_index: index on the first trajectory, to which the first + * point on the second trajectory should + * be aligned to for motion blend. It is now always same as + * first_interse_index + * @param blend_time: time of the motion blend period + */ + void determineTrajectoryAlignment(const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, + std::size_t first_interse_index, std::size_t second_interse_index, + std::size_t& blend_align_index) const; + + /** + * @brief blend two trajectories in Cartesian space, result in a + * MultiDOFJointTrajectory which consists + * of a list of transforms for the blend phase. + * @param req + * @param first_interse_index + * @param second_interse_index + * @param blend_begin_index + * @param sampling_time + * @param trajectory: the resulting blend trajectory inside the blending + * sphere + */ + void blendTrajectoryCartesian(const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, + const std::size_t first_interse_index, const std::size_t second_interse_index, + const std::size_t blend_align_index, double sampling_time, + pilz_industrial_motion_planner::CartesianTrajectory& trajectory) const; + +private: // static members + // Constant to check for equality of values. + static constexpr double EPSILON = 1e-4; +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_functions.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_functions.h new file mode 100644 index 0000000000..f31bbada01 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_functions.h @@ -0,0 +1,219 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pilz_industrial_motion_planner/cartesian_trajectory.h" +#include "pilz_industrial_motion_planner/limits_container.h" + +namespace pilz_industrial_motion_planner +{ +/** + * @brief compute the inverse kinematics of a given pose, also check robot self + * collision + * @param robot_model: kinematic model of the robot + * @param group_name: name of planning group + * @param link_name: name of target link + * @param pose: target pose in IK solver Frame + * @param frame_id: reference frame of the target pose + * @param seed: seed state of IK solver + * @param solution: solution of IK + * @param check_self_collision: true to enable self collision checking after IK + * computation + * @param max_attempt: maximal attempts of IK + * @return true if succeed + */ +bool computePoseIK(const robot_model::RobotModelConstPtr& robot_model, const std::string& group_name, + const std::string& link_name, const Eigen::Isometry3d& pose, const std::string& frame_id, + const std::map& seed, std::map& solution, + bool check_self_collision = true, const double timeout = 0.1); + +bool computePoseIK(const robot_model::RobotModelConstPtr& robot_model, const std::string& group_name, + const std::string& link_name, const geometry_msgs::Pose& pose, const std::string& frame_id, + const std::map& seed, std::map& solution, + bool check_self_collision = true, const double timeout = 0.1); + +/** + * @brief compute the pose of a link at give robot state + * @param robot_model: kinematic model of the robot + * @param link_name: target link name + * @param joint_state: joint positons of this group + * @param pose: pose of the link in base frame of robot model + * @return true if succeed + */ +bool computeLinkFK(const robot_model::RobotModelConstPtr& robot_model, const std::string& link_name, + const std::map& joint_state, Eigen::Isometry3d& pose); + +bool computeLinkFK(const robot_model::RobotModelConstPtr& robot_model, const std::string& link_name, + const std::vector& joint_names, const std::vector& joint_positions, + Eigen::Isometry3d& pose); + +/** + * @brief verify the velocity/acceleration limits of current sample (based on + * backward difference computation) + * v(k) = [x(k) - x(k-1)]/[t(k) - t(k-1)] + * a(k) = [v(k) - v(k-1)]/[t(k) - t(k-2)]*2 + * @param position_last: position of last sample + * @param velocity_last: velocity of last sample + * @param position_current: position of current sample + * @param duration_last: duration of last sample + * @param duration_current: duration of current sample + * @param joint_limits: joint limits + * @return + */ +bool verifySampleJointLimits(const std::map& position_last, + const std::map& velocity_last, + const std::map& position_current, double duration_last, + double duration_current, const JointLimitsContainer& joint_limits); + +/** + * @brief Generate joint trajectory from a KDL Cartesian trajectory + * @param robot_model: robot kinematics model + * @param joint_limits: joint limits + * @param trajectory: KDL Cartesian trajectory + * @param group_name: name of the planning group + * @param link_name: name of the target robot link + * @param initial_joint_position: initial joint positions, needed for selecting + * the ik solution + * @param sampling_time: sampling time of the generated trajectory + * @param joint_trajectory: output as robot joint trajectory, first and last + * point will have zero velocity + * and acceleration + * @param error_code: detailed error information + * @param check_self_collision: check for self collision during creation + * @return true if succeed + */ +bool generateJointTrajectory(const robot_model::RobotModelConstPtr& robot_model, + const JointLimitsContainer& joint_limits, const KDL::Trajectory& trajectory, + const std::string& group_name, const std::string& link_name, + const std::map& initial_joint_position, const double& sampling_time, + trajectory_msgs::JointTrajectory& joint_trajectory, + moveit_msgs::MoveItErrorCodes& error_code, bool check_self_collision = false); + +/** + * @brief Generate joint trajectory from a MultiDOFJointTrajectory + * @param trajectory: Cartesian trajectory + * @param info: motion plan information + * @param sampling_time + * @param joint_trajectory + * @param error_code + * @return true if succeed + */ +bool generateJointTrajectory(const robot_model::RobotModelConstPtr& robot_model, + const JointLimitsContainer& joint_limits, + const pilz_industrial_motion_planner::CartesianTrajectory& trajectory, + const std::string& group_name, const std::string& link_name, + const std::map& initial_joint_position, + const std::map& initial_joint_velocity, + trajectory_msgs::JointTrajectory& joint_trajectory, + moveit_msgs::MoveItErrorCodes& error_code, bool check_self_collision = false); + +/** + * @brief Determines the sampling time and checks that both trajectroies use the + * same sampling time. + * @return TRUE if the sampling time is equal between all given points (except + * the last two points + * of each trajectory), otherwise FALSE. + */ +bool determineAndCheckSamplingTime(const robot_trajectory::RobotTrajectoryPtr& first_trajectory, + const robot_trajectory::RobotTrajectoryPtr& second_trajectory, double EPSILON, + double& sampling_time); + +/** + * @brief Check if the two robot states have the same joint + * position/velocity/acceleration. + * + * @param joint_group_name The name of the joint group. + * @param epsilon Constants defining how close the joint + * position/velocity/acceleration have to be to be + * recognized as equal. + * + * @return True if joint positions, joint velocities and joint accelerations are + * equal, otherwise false. + */ +bool isRobotStateEqual(const robot_state::RobotState& state1, const robot_state::RobotState& state2, + const std::string& joint_group_name, double epsilon); + +/** + * @brief check if the robot state have zero velocity/acceleartion + * @param state + * @param group + * @param EPSILON + * @return + */ +bool isRobotStateStationary(const robot_state::RobotState& state, const std::string& group, double EPSILON); + +/** + * @brief Performs a linear search for the intersection point of the trajectory + * with the blending radius. + * @param center_position Center of blending sphere. + * @param r Radius of blending sphere. + * @param traj The trajectory. + * @param inverseOrder TRUE: Farthest element from blending sphere center is + * located at the + * smallest index of trajectroy. + * @param index The intersection index which has to be determined. + */ +bool linearSearchIntersectionPoint(const std::string& link_name, const Eigen::Vector3d& center_position, + const double& r, const robot_trajectory::RobotTrajectoryPtr& traj, bool inverseOrder, + std::size_t& index); + +bool intersectionFound(const Eigen::Vector3d& p_center, const Eigen::Vector3d& p_current, const Eigen::Vector3d& p_next, + const double& r); + +/** + * @brief Checks if current robot state is in self collision. + * @param test_for_self_collision Flag to deactivate this check during IK. + * @param robot_model: robot kinematics model. + * @param state Robot state instance used for . + * @param group + * @param ik_solution + * @return + */ +bool isStateColliding(const bool test_for_self_collision, const moveit::core::RobotModelConstPtr& robot_model, + robot_state::RobotState* state, const robot_state::JointModelGroup* const group, + const double* const ik_solution); +} // namespace pilz_industrial_motion_planner + +void normalizeQuaternion(geometry_msgs::Quaternion& quat); diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generation_exceptions.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generation_exceptions.h new file mode 100644 index 0000000000..8348850687 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generation_exceptions.h @@ -0,0 +1,121 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include +#include + +#include + +namespace pilz_industrial_motion_planner +{ +/** + * @brief Exception storing an moveit_msgs::MoveItErrorCodes value. + */ +class MoveItErrorCodeException : public std::runtime_error +{ +public: + MoveItErrorCodeException(const std::string& msg); + +protected: + MoveItErrorCodeException(const MoveItErrorCodeException&) = default; + MoveItErrorCodeException(MoveItErrorCodeException&&) = default; + ~MoveItErrorCodeException() override = default; + + MoveItErrorCodeException& operator=(const MoveItErrorCodeException&) = default; + MoveItErrorCodeException& operator=(MoveItErrorCodeException&&) = default; + +public: + virtual const moveit_msgs::MoveItErrorCodes::_val_type& getErrorCode() const = 0; +}; + +template +class TemplatedMoveItErrorCodeException : public MoveItErrorCodeException +{ +public: + TemplatedMoveItErrorCodeException(const std::string& msg); + TemplatedMoveItErrorCodeException(const std::string& msg, const moveit_msgs::MoveItErrorCodes::_val_type& error_code); + +public: + const moveit_msgs::MoveItErrorCodes::_val_type& getErrorCode() const override; + +private: + const moveit_msgs::MoveItErrorCodes::_val_type error_code_{ ERROR_CODE }; +}; + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +inline MoveItErrorCodeException::MoveItErrorCodeException(const std::string& msg) : std::runtime_error(msg) +{ +} + +template +inline TemplatedMoveItErrorCodeException::TemplatedMoveItErrorCodeException(const std::string& msg) + : MoveItErrorCodeException(msg) +{ +} + +template +inline TemplatedMoveItErrorCodeException::TemplatedMoveItErrorCodeException( + const std::string& msg, const moveit_msgs::MoveItErrorCodes::_val_type& error_code) + : MoveItErrorCodeException(msg), error_code_(error_code) +{ +} + +template +inline const moveit_msgs::MoveItErrorCodes::_val_type& +TemplatedMoveItErrorCodeException::getErrorCode() const +{ + return error_code_; +} + +/* + * @brief Macro to automatically generate a derived class of + * the MoveItErrorCodeException class. + */ +#define CREATE_MOVEIT_ERROR_CODE_EXCEPTION(EXCEPTION_CLASS_NAME, ERROR_CODE) \ + class EXCEPTION_CLASS_NAME : public TemplatedMoveItErrorCodeException \ + { \ + public: \ + EXCEPTION_CLASS_NAME(const std::string& msg) : TemplatedMoveItErrorCodeException(msg) \ + { \ + } \ + \ + EXCEPTION_CLASS_NAME(const std::string& msg, const moveit_msgs::MoveItErrorCodes::_val_type& error_code) \ + : TemplatedMoveItErrorCodeException(msg, error_code) \ + { \ + } \ + } + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator.h new file mode 100644 index 0000000000..09055fcb81 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator.h @@ -0,0 +1,291 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +#include "pilz_industrial_motion_planner/joint_limits_extension.h" +#include "pilz_industrial_motion_planner/limits_container.h" +#include "pilz_industrial_motion_planner/trajectory_functions.h" +#include "pilz_industrial_motion_planner/trajectory_generation_exceptions.h" + +using namespace pilz_industrial_motion_planner; + +namespace pilz_industrial_motion_planner +{ +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(TrajectoryGeneratorInvalidLimitsException, moveit_msgs::MoveItErrorCodes::FAILURE); + +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(VelocityScalingIncorrect, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(AccelerationScalingIncorrect, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(UnknownPlanningGroup, moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME); + +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NoJointNamesInStartState, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(SizeMismatchInStartState, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(JointsOfStartStateOutOfRange, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NonZeroVelocityInStartState, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); + +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NotExactlyOneGoalConstraintGiven, + moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(OnlyOneGoalTypeAllowed, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(StartStateGoalStateMismatch, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(JointConstraintDoesNotBelongToGroup, + moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(JointsOfGoalOutOfRange, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(PositionConstraintNameMissing, + moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(OrientationConstraintNameMissing, + moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(PositionOrientationConstraintNameMismatch, + moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NoIKSolverAvailable, moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NoPrimitivePoseGiven, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + +/** + * @brief Base class of trajectory generators + * + * Note: All derived classes cannot have a start velocity + */ +class TrajectoryGenerator +{ +public: + TrajectoryGenerator(const robot_model::RobotModelConstPtr& robot_model, + const pilz_industrial_motion_planner::LimitsContainer& planner_limits) + : robot_model_(robot_model), planner_limits_(planner_limits) + { + } + + virtual ~TrajectoryGenerator() = default; + + /** + * @brief generate robot trajectory with given sampling time + * @param req: motion plan request + * @param res: motion plan response + * @param sampling_time: sampling time of the generate trajectory + * @return motion plan succeed/fail, detailed information in motion plan + * responce + */ + bool generate(const planning_interface::MotionPlanRequest& req, planning_interface::MotionPlanResponse& res, + double sampling_time = 0.1); + +protected: + /** + * @brief This class is used to extract needed information from motion plan + * request. + */ + class MotionPlanInfo + { + public: + std::string group_name; + std::string link_name; + Eigen::Isometry3d start_pose; + Eigen::Isometry3d goal_pose; + std::map start_joint_position; + std::map goal_joint_position; + std::pair circ_path_point; + }; + + /** + * @brief build cartesian velocity profile for the path + * + * Uses the path to get the cartesian length and the angular distance from + * start to goal. + * The trap profile returns uses the longer distance of translational and + * rotational motion. + */ + std::unique_ptr cartesianTrapVelocityProfile(const double& max_velocity_scaling_factor, + const double& max_acceleration_scaling_factor, + const std::unique_ptr& path) const; + +private: + virtual void cmdSpecificRequestValidation(const planning_interface::MotionPlanRequest& req) const; + + /** + * @brief Extract needed information from a motion plan request in order to + * simplify + * further usages. + * @param req: motion plan request + * @param info: information extracted from motion plan request which is + * necessary for the planning + */ + virtual void extractMotionPlanInfo(const planning_interface::MotionPlanRequest& req, MotionPlanInfo& info) const = 0; + + virtual void plan(const planning_interface::MotionPlanRequest& req, const MotionPlanInfo& plan_info, + const double& sampling_time, trajectory_msgs::JointTrajectory& joint_trajectory) = 0; + +private: + /** + * @brief Validate the motion plan request based on the common requirements of + * trajectroy generator + * Checks that: + * - req.max_velocity_scaling_factor [0.0001, 1], + * moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN on failure + * - req.max_acceleration_scaling_factor [0.0001, 1] , + * moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN on + * failure + * - req.group_name is a JointModelGroup of the Robotmodel, + * moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME on + * failure + * - req.start_state.joint_state is not empty, + * moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE on failure + * - req.start_state.joint_state is within the limits, + * moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE on + * failure + * - req.start_state.joint_state is all zero, + * moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE on failure + * - req.goal_constraints must have exactly 1 defined cartesian oder joint + * constraint + * moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS on failure + * A joint goal is checked for: + * - StartState joint-names matching goal joint-names, + * moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS on + * failure + * - Beeing defined in the req.group_name JointModelGroup + * - Beeing with the defined limits + * A cartesian goal is checked for: + * - A defined link_name for the constraint, + * moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS on failure + * - Matching link_name for position and orientation constraints, + * moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS on failure + * - A IK solver exists for the given req.group_name and constraint + * link_name, + * moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION on failure + * - A goal pose define in + * position_constraints[0].constraint_region.primitive_poses, + * moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS on failure + * @param req: motion plan request + */ + void validateRequest(const planning_interface::MotionPlanRequest& req) const; + + /** + * @brief set MotionPlanResponse from joint trajectory + */ + void setSuccessResponse(const std::string& group_name, const moveit_msgs::RobotState& start_state, + const trajectory_msgs::JointTrajectory& joint_trajectory, const ros::Time& planning_start, + planning_interface::MotionPlanResponse& res) const; + + void setFailureResponse(const ros::Time& planning_start, planning_interface::MotionPlanResponse& res) const; + + void checkForValidGroupName(const std::string& group_name) const; + + /** + * @brief Validate that the start state of the request matches the + * requirements of the trajectory generator. + * + * These requirements are: + * - Names of the joints and given joint position match in size and are + * non-zero + * - The start state is withing the position limits + * - The start state velocity is below + * TrajectoryGenerator::VELOCITY_TOLERANCE + */ + void checkStartState(const moveit_msgs::RobotState& start_state) const; + + void checkGoalConstraints(const moveit_msgs::MotionPlanRequest::_goal_constraints_type& goal_constraints, + const std::vector& expected_joint_names, const std::string& group_name) const; + + void checkJointGoalConstraint(const moveit_msgs::Constraints& constraint, + const std::vector& expected_joint_names, + const std::string& group_name) const; + + void checkCartesianGoalConstraint(const moveit_msgs::Constraints& constraint, const std::string& group_name) const; + + void convertToRobotTrajectory(const trajectory_msgs::JointTrajectory& joint_trajectory, + const moveit_msgs::RobotState& start_state, + robot_trajectory::RobotTrajectory& robot_trajectory) const; + +private: + /** + * @return True if scaling factor is valid, otherwise false. + */ + static bool isScalingFactorValid(const double& scaling_factor); + static void checkVelocityScaling(const double& scaling_factor); + static void checkAccelerationScaling(const double& scaling_factor); + + /** + * @return True if ONE position + ONE orientation constraint given, + * otherwise false. + */ + static bool isCartesianGoalGiven(const moveit_msgs::Constraints& constraint); + + /** + * @return True if joint constraint given, otherwise false. + */ + static bool isJointGoalGiven(const moveit_msgs::Constraints& constraint); + + /** + * @return True if ONLY joint constraint or + * ONLY cartesian constraint (position+orientation) given, otherwise false. + */ + static bool isOnlyOneGoalTypeGiven(const moveit_msgs::Constraints& constraint); + +protected: + const robot_model::RobotModelConstPtr robot_model_; + const pilz_industrial_motion_planner::LimitsContainer planner_limits_; + static constexpr double MIN_SCALING_FACTOR{ 0.0001 }; + static constexpr double MAX_SCALING_FACTOR{ 1. }; + static constexpr double VELOCITY_TOLERANCE{ 1e-8 }; +}; + +inline bool TrajectoryGenerator::isScalingFactorValid(const double& scaling_factor) +{ + return (scaling_factor > MIN_SCALING_FACTOR && scaling_factor <= MAX_SCALING_FACTOR); +} + +inline bool TrajectoryGenerator::isCartesianGoalGiven(const moveit_msgs::Constraints& constraint) +{ + return constraint.position_constraints.size() == 1 && constraint.orientation_constraints.size() == 1; +} + +inline bool TrajectoryGenerator::isJointGoalGiven(const moveit_msgs::Constraints& constraint) +{ + return !constraint.joint_constraints.empty(); +} + +inline bool TrajectoryGenerator::isOnlyOneGoalTypeGiven(const moveit_msgs::Constraints& constraint) +{ + return (isJointGoalGiven(constraint) && !isCartesianGoalGiven(constraint)) || + (!isJointGoalGiven(constraint) && isCartesianGoalGiven(constraint)); +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator_circ.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator_circ.h new file mode 100644 index 0000000000..080239a581 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator_circ.h @@ -0,0 +1,107 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include +#include +#include + +#include "pilz_industrial_motion_planner/trajectory_generator.h" + +using namespace pilz_industrial_motion_planner; + +namespace pilz_industrial_motion_planner +{ +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(CircleNoPlane, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(CircleToSmall, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(CenterPointDifferentRadius, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(CircTrajectoryConversionFailure, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(UnknownPathConstraintName, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NoPositionConstraints, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NoPrimitivePose, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(UnknownLinkNameOfAuxiliaryPoint, moveit_msgs::MoveItErrorCodes::INVALID_LINK_NAME); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(NumberOfConstraintsMismatch, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(CircJointMissingInStartState, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(CircInverseForGoalIncalculable, moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION); + +/** + * @brief This class implements a trajectory generator of arcs in Cartesian + * space. + * The arc is specified by a start pose, a goal pose and a interim point on the + * arc, + * or a point as the center of the circle which forms the arc. Complete circle + * is not + * covered by this generator. + */ +class TrajectoryGeneratorCIRC : public TrajectoryGenerator +{ +public: + /** + * @brief Constructor of CIRC Trajectory Generator. + * + * @param planner_limits Limits in joint and Cartesian spaces + * + * @throw TrajectoryGeneratorInvalidLimitsException + * + */ + TrajectoryGeneratorCIRC(const robot_model::RobotModelConstPtr& robot_model, + const pilz_industrial_motion_planner::LimitsContainer& planner_limits); + +private: + void cmdSpecificRequestValidation(const planning_interface::MotionPlanRequest& req) const override; + + void extractMotionPlanInfo(const planning_interface::MotionPlanRequest& req, MotionPlanInfo& info) const final; + + void plan(const planning_interface::MotionPlanRequest& req, const MotionPlanInfo& plan_info, + const double& sampling_time, trajectory_msgs::JointTrajectory& joint_trajectory) override; + + /** + * @brief Construct a KDL::Path object for a Cartesian path of an arc. + * + * @return A unique pointer of the path object, null_ptr in case of an error. + * + * @throws CircleNoPlane if the plane in which the circle resides, + * could not be determined. + * + * @throws CircleToSmall if the specified circ radius is to small. + * + * @throws CenterPointDifferentRadius if the distances between start-center + * and goal-center are different. + */ + std::unique_ptr setPathCIRC(const MotionPlanInfo& info) const; +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator_lin.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator_lin.h new file mode 100644 index 0000000000..2d17768cad --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator_lin.h @@ -0,0 +1,85 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include +#include + +#include "pilz_industrial_motion_planner/trajectory_generator.h" +#include "pilz_industrial_motion_planner/velocity_profile_atrap.h" + +using namespace pilz_industrial_motion_planner; + +namespace pilz_industrial_motion_planner +{ +// TODO date type of units + +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(LinTrajectoryConversionFailure, moveit_msgs::MoveItErrorCodes::FAILURE); + +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(JointNumberMismatch, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(LinJointMissingInStartState, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(LinInverseForGoalIncalculable, moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION); + +/** + * @brief This class implements a linear trajectory generator in Cartesian + * space. + * The Cartesian trajetory are based on trapezoid velocity profile. + */ +class TrajectoryGeneratorLIN : public TrajectoryGenerator +{ +public: + /** + * @brief Constructor of LIN Trajectory Generator + * @throw TrajectoryGeneratorInvalidLimitsException + * @param model: robot model + * @param planner_limits: limits in joint and Cartesian spaces + */ + TrajectoryGeneratorLIN(const robot_model::RobotModelConstPtr& robot_model, + const pilz_industrial_motion_planner::LimitsContainer& planner_limits); + +private: + void extractMotionPlanInfo(const planning_interface::MotionPlanRequest& req, MotionPlanInfo& info) const final; + + void plan(const planning_interface::MotionPlanRequest& req, const MotionPlanInfo& plan_info, + const double& sampling_time, trajectory_msgs::JointTrajectory& joint_trajectory) override; + + /** + * @brief construct a KDL::Path object for a Cartesian straight line + * @return a unique pointer of the path object. null_ptr in case of an error. + */ + std::unique_ptr setPathLIN(const Eigen::Affine3d& start_pose, const Eigen::Affine3d& goal_pose) const; +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator_ptp.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator_ptp.h new file mode 100644 index 0000000000..09048557ba --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_generator_ptp.h @@ -0,0 +1,94 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "eigen3/Eigen/Eigen" +#include "pilz_industrial_motion_planner/trajectory_generation_exceptions.h" +#include "pilz_industrial_motion_planner/trajectory_generator.h" +#include "pilz_industrial_motion_planner/velocity_profile_atrap.h" + +using namespace pilz_industrial_motion_planner; + +namespace pilz_industrial_motion_planner +{ +// TODO date type of units + +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(PtpVelocityProfileSyncFailed, moveit_msgs::MoveItErrorCodes::FAILURE); +CREATE_MOVEIT_ERROR_CODE_EXCEPTION(PtpNoIkSolutionForGoalPose, moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION); + +/** + * @brief This class implements a point-to-point trajectory generator based on + * VelocityProfileATrap. + */ +class TrajectoryGeneratorPTP : public TrajectoryGenerator +{ +public: + /** + * @brief Constructor of PTP Trajectory Generator + * @throw TrajectoryGeneratorInvalidLimitsException + * @param model: a map of joint limits information + */ + TrajectoryGeneratorPTP(const robot_model::RobotModelConstPtr& robot_model, + const pilz_industrial_motion_planner::LimitsContainer& planner_limits); + +private: + void extractMotionPlanInfo(const planning_interface::MotionPlanRequest& req, MotionPlanInfo& info) const override; + + /** + * @brief plan ptp joint trajectory with zero start velocity + * @param start_pos + * @param goal_pos + * @param joint_trajectory + * @param group_name + * @param velocity_scaling_factor + * @param acceleration_scaling_factor + * @param sampling_time + */ + void planPTP(const std::map& start_pos, const std::map& goal_pos, + trajectory_msgs::JointTrajectory& joint_trajectory, const std::string& group_name, + const double& velocity_scaling_factor, const double& acceleration_scaling_factor, + const double& sampling_time); + + void plan(const planning_interface::MotionPlanRequest& req, const MotionPlanInfo& plan_info, + const double& sampling_time, trajectory_msgs::JointTrajectory& joint_trajectory) override; + +private: + const double MIN_MOVEMENT = 0.001; + pilz_industrial_motion_planner::JointLimitsContainer joint_limits_; + // most strict joint limits for each group + std::map most_strict_limits_; +}; + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/velocity_profile_atrap.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/velocity_profile_atrap.h new file mode 100644 index 0000000000..2d71ccbb4b --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/velocity_profile_atrap.h @@ -0,0 +1,215 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include "kdl/velocityprofile.hpp" +#include + +namespace pilz_industrial_motion_planner +{ +/** + * @brief A PTP Trajectory Generator of Asymmetric Trapezoidal Velocity Profile. + * Differences to VelocityProfile_Trap: + * - Maximal acceleration and deceleration can be different, resulting + * an asymmetric trapezoid shaped velocity profile. + * - Function to generate full synchronized PTP trajectory is provided. + * - Function to generate trapezoid shaped velocity profile with start + * velocity. + */ +class VelocityProfileATrap : public KDL::VelocityProfile +{ +public: + /** + * @brief Constructor + * @param max_vel: maximal velocity (absolute value, always positive) + * @param max_acc: maximal acceleration (absolute value, always positive) + * @param max_dec: maximal deceleration (absolute value, always positive) + */ + VelocityProfileATrap(double max_vel = 0, double max_acc = 0, double max_dec = 0); + + /** + * @brief compute the fastest profile + * Algorithm: + * - compute the minimal distance which is needed to reach maximal velocity + * - if maximal velocity can be reached + * - compute the coefficients of the trajectory + * - if maximal velocity can not be reached + * - compute the new velocity can be reached + * - compute the coefficients based on this new velocity + * + * @param pos1: start position + * @param pos2: goal position + */ + void SetProfile(double pos1, double pos2) override; + + /** + * @brief Profile scaled by the total duration + * @param pos1: start position + * @param pos2: goal position + * @param duration: trajectory duration (must be longer than fastest case, + * otherwise will be ignored) + */ + void SetProfileDuration(double pos1, double pos2, double duration) override; + + /** + * @brief Profile with given acceleration/constant/deceleration durations. + * Each duration must obey the maximal velocity/acceleration/deceleration + * constraints. + * Otherwise the operation will be ignored. + * Algorithm: + * - compute the maximal velocity of given durations + * - compute the acceleration and deceleration of given duraitons + * - if limits are fulfilled + * - compute the coefficients + * @param pos1: start position + * @param pos2: goal position + * @param acc_duration: time of acceleration phase + * @param const_duration: time of constant phase + * @param dec_duration: time of deceleration phase + * @return ture if the combination of three durations is valid + */ + bool setProfileAllDurations(double pos1, double pos2, double duration1, double duration2, double duration3); + + /** + * @brief Profile with start velocity + * Note: This function is not general and is currently only used for live + * control (vel1*(pos2-pos1)>0). + * @param pos1: start position + * @param pos2: goal position + * @param vel1: start velocity + * @return + */ + bool setProfileStartVelocity(double pos1, double pos2, double vel1); + + /** + * @brief get the time of first phase + * @return + */ + double firstPhaseDuration() const + { + return t_a_; + } + /** + * @brief get the time of second phase + * @return + */ + double secondPhaseDuration() const + { + return t_b_; + } + /** + * @brief get the time of third phase + * @return + */ + double thirdPhaseDuration() const + { + return t_c_; + } + + /** + * @brief Compares two Asymmetric Trapezoidal Velocity Profiles. + * + * @return True if equal, false otherwise. + */ + bool operator==(const VelocityProfileATrap& other) const; + + /** + * @brief Duration + * @return total duration of the trajectory + */ + double Duration() const override; + /** + * @brief Get position at given time + * @param time + * @return + */ + double Pos(double time) const override; + /** + * @brief Get velocity at given time + * @param time + * @return + */ + double Vel(double time) const override; + /** + * @brief Get given acceleration/deceleration at given time + * @param time + * @return + */ + double Acc(double time) const override; + /** + * @brief Write basic information + * @param os + */ + void Write(std::ostream& os) const override; + /** + * @brief returns copy of current VelocityProfile object + * @return + */ + KDL::VelocityProfile* Clone() const override; + + friend std::ostream& operator<<(std::ostream& os, const VelocityProfileATrap& p); // LCOV_EXCL_LINE + + ~VelocityProfileATrap() override; + +private: + /// helper functions + void setEmptyProfile(); + +private: + /// specification of the motion profile : + const double max_vel_; + const double max_acc_; + const double max_dec_; + double start_pos_; + double end_pos_; + + /// for initial velocity + double start_vel_; + + /// three phases of trapezoid + double a1_, a2_, a3_; /// coef. from ^0 -> ^2 of first phase + double b1_, b2_, b3_; /// of second phase + double c1_, c2_, c3_; /// of third phase + + /// time of three phases + double t_a_; /// the duration of first phase + double t_b_; /// the duration of second phase + double t_c_; /// the duration of third phase +}; + +std::ostream& operator<<(std::ostream& os, + const VelocityProfileATrap& p); // LCOV_EXCL_LINE + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/package.xml b/moveit_planners/pilz_industrial_motion_planner/package.xml new file mode 100644 index 0000000000..d69a541779 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/package.xml @@ -0,0 +1,55 @@ + + + pilz_industrial_motion_planner + 0.4.10 + MoveIt plugin to generate industrial trajectories PTP, LIN, CIRC and sequences thereof. + + Alexander Gutenkunst + Christian Henkel + Immanuel Martini + Joachim Schleicher + Hagen Slusarek + + BSD + + http://moveit.ros.org + https://github.com/ros-planning/moveit/issues + https://github.com/ros-planning/moveit + + catkin + + eigen_conversions + kdl_conversions + moveit_ros_planning_interface + moveit_msgs + moveit_core + moveit_ros_planning + moveit_ros_move_group + orocos_kdl + liborocos-kdl-dev + pluginlib + roscpp + tf2 + tf2_eigen + tf2_geometry_msgs + tf2_kdl + tf2_ros + + + rostest + rosunit + cmake_modules + moveit_resources_panda_moveit_config + pilz_industrial_motion_planner_testutils + moveit_resources_prbt_moveit_config + moveit_resources_prbt_support + moveit_resources_prbt_pg70_support + code_coverage + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/plugins/pilz_industrial_motion_planner_plugin_description.xml b/moveit_planners/pilz_industrial_motion_planner/plugins/pilz_industrial_motion_planner_plugin_description.xml new file mode 100644 index 0000000000..3a6f16cf50 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/plugins/pilz_industrial_motion_planner_plugin_description.xml @@ -0,0 +1,5 @@ + + + Pilz Industrial Motion Planner + + diff --git a/moveit_planners/pilz_industrial_motion_planner/plugins/planning_context_plugin_description.xml b/moveit_planners/pilz_industrial_motion_planner/plugins/planning_context_plugin_description.xml new file mode 100644 index 0000000000..0ff208f2a2 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/plugins/planning_context_plugin_description.xml @@ -0,0 +1,18 @@ + + + Loader for PTP Context + + + + + Loader for LIN Context + + + + + Loader for CIRC Context + + diff --git a/moveit_planners/pilz_industrial_motion_planner/plugins/sequence_capability_plugin_description.xml b/moveit_planners/pilz_industrial_motion_planner/plugins/sequence_capability_plugin_description.xml new file mode 100644 index 0000000000..9daf67146c --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/plugins/sequence_capability_plugin_description.xml @@ -0,0 +1,13 @@ + + + Motion Planner a sequence of trajectories + + + + Plan a sequence of trajectory via ROS serivce + + diff --git a/moveit_planners/pilz_industrial_motion_planner/rosdoc.yaml b/moveit_planners/pilz_industrial_motion_planner/rosdoc.yaml new file mode 100644 index 0000000000..119e416808 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/rosdoc.yaml @@ -0,0 +1,6 @@ +- builder: doxygen + name: Documentation of pilz_industrial_motion_planner package + output_dir: pilz_industrial_motion_planner + file_patterns: '*.c *.cpp *.h *.cc *.hh *.dox *.md' + exclude_patterns: 'test' + use_mdfile_as_mainpage: 'README.md' diff --git a/moveit_planners/pilz_industrial_motion_planner/src/cartesian_limit.cpp b/moveit_planners/pilz_industrial_motion_planner/src/cartesian_limit.cpp new file mode 100644 index 0000000000..3d67a9be13 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/cartesian_limit.cpp @@ -0,0 +1,119 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/cartesian_limit.h" + +pilz_industrial_motion_planner::CartesianLimit::CartesianLimit() + : has_max_trans_vel_(false) + , max_trans_vel_(0.0) + , has_max_trans_acc_(false) + , max_trans_acc_(0.0) + , has_max_trans_dec_(false) + , max_trans_dec_(0.0) + , has_max_rot_vel_(false) + , max_rot_vel_(0.0) +{ +} + +// Translational Velocity Limit + +bool pilz_industrial_motion_planner::CartesianLimit::hasMaxTranslationalVelocity() const +{ + return has_max_trans_vel_; +} + +void pilz_industrial_motion_planner::CartesianLimit::setMaxTranslationalVelocity(double max_trans_vel) +{ + has_max_trans_vel_ = true; + max_trans_vel_ = max_trans_vel; +} + +double pilz_industrial_motion_planner::CartesianLimit::getMaxTranslationalVelocity() const +{ + return max_trans_vel_; +} + +// Translational Acceleration Limit + +bool pilz_industrial_motion_planner::CartesianLimit::hasMaxTranslationalAcceleration() const +{ + return has_max_trans_acc_; +} + +void pilz_industrial_motion_planner::CartesianLimit::setMaxTranslationalAcceleration(double max_trans_acc) +{ + has_max_trans_acc_ = true; + max_trans_acc_ = max_trans_acc; +} + +double pilz_industrial_motion_planner::CartesianLimit::getMaxTranslationalAcceleration() const +{ + return max_trans_acc_; +} + +// Translational Deceleration Limit + +bool pilz_industrial_motion_planner::CartesianLimit::hasMaxTranslationalDeceleration() const +{ + return has_max_trans_dec_; +} + +void pilz_industrial_motion_planner::CartesianLimit::setMaxTranslationalDeceleration(double max_trans_dec) +{ + has_max_trans_dec_ = true; + max_trans_dec_ = max_trans_dec; +} + +double pilz_industrial_motion_planner::CartesianLimit::getMaxTranslationalDeceleration() const +{ + return max_trans_dec_; +} + +// Rotational Velocity Limit + +bool pilz_industrial_motion_planner::CartesianLimit::hasMaxRotationalVelocity() const +{ + return has_max_rot_vel_; +} + +void pilz_industrial_motion_planner::CartesianLimit::setMaxRotationalVelocity(double max_rot_vel) +{ + has_max_rot_vel_ = true; + max_rot_vel_ = max_rot_vel; +} + +double pilz_industrial_motion_planner::CartesianLimit::getMaxRotationalVelocity() const +{ + return max_rot_vel_; +} diff --git a/moveit_planners/pilz_industrial_motion_planner/src/cartesian_limits_aggregator.cpp b/moveit_planners/pilz_industrial_motion_planner/src/cartesian_limits_aggregator.cpp new file mode 100644 index 0000000000..30dc95ad41 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/cartesian_limits_aggregator.cpp @@ -0,0 +1,96 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "ros/ros.h" + +#include "pilz_industrial_motion_planner/cartesian_limits_aggregator.h" + +static const std::string PARAM_CARTESIAN_LIMITS_NS = "cartesian_limits"; + +static const std::string PARAM_MAX_TRANS_VEL = "max_trans_vel"; +static const std::string PARAM_MAX_TRANS_ACC = "max_trans_acc"; +static const std::string PARAM_MAX_TRANS_DEC = "max_trans_dec"; +static const std::string PARAM_MAX_ROT_VEL = "max_rot_vel"; +static const std::string PARAM_MAX_ROT_ACC = "max_rot_acc"; +static const std::string PARAM_MAX_ROT_DEC = "max_rot_dec"; + +pilz_industrial_motion_planner::CartesianLimit +pilz_industrial_motion_planner::CartesianLimitsAggregator::getAggregatedLimits(const ros::NodeHandle& nh) +{ + std::string param_prefix = PARAM_CARTESIAN_LIMITS_NS + "/"; + + pilz_industrial_motion_planner::CartesianLimit cartesian_limit; + + // translational velocity + double max_trans_vel; + if (nh.getParam(param_prefix + PARAM_MAX_TRANS_VEL, max_trans_vel)) + { + cartesian_limit.setMaxTranslationalVelocity(max_trans_vel); + } + + // translational acceleration + double max_trans_acc; + if (nh.getParam(param_prefix + PARAM_MAX_TRANS_ACC, max_trans_acc)) + { + cartesian_limit.setMaxTranslationalAcceleration(max_trans_acc); + } + + // translational deceleration + double max_trans_dec; + if (nh.getParam(param_prefix + PARAM_MAX_TRANS_DEC, max_trans_dec)) + { + cartesian_limit.setMaxTranslationalDeceleration(max_trans_dec); + } + + // rotational velocity + double max_rot_vel; + if (nh.getParam(param_prefix + PARAM_MAX_ROT_VEL, max_rot_vel)) + { + cartesian_limit.setMaxRotationalVelocity(max_rot_vel); + } + + // rotational acceleration + deceleration deprecated + // LCOV_EXCL_START + if (nh.hasParam(param_prefix + PARAM_MAX_ROT_ACC) || nh.hasParam(param_prefix + PARAM_MAX_ROT_DEC)) + { + ROS_WARN_STREAM("Ignoring cartesian limits parameters for rotational " + "acceleration / deceleration;" + << "these parameters are deprecated and are automatically " + "calculated from" + << "translational to rotational ratio."); + } + // LCOV_EXCL_STOP + + return cartesian_limit; +} diff --git a/moveit_planners/pilz_industrial_motion_planner/src/command_list_manager.cpp b/moveit_planners/pilz_industrial_motion_planner/src/command_list_manager.cpp new file mode 100644 index 0000000000..52941969d2 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/command_list_manager.cpp @@ -0,0 +1,315 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/command_list_manager.h" + +#include +#include +#include + +#include +#include +#include + +#include "pilz_industrial_motion_planner/cartesian_limits_aggregator.h" +#include "pilz_industrial_motion_planner/joint_limits_aggregator.h" +#include "pilz_industrial_motion_planner/tip_frame_getter.h" +#include "pilz_industrial_motion_planner/trajectory_blend_request.h" +#include "pilz_industrial_motion_planner/trajectory_blender_transition_window.h" + +namespace pilz_industrial_motion_planner +{ +static const std::string PARAM_NAMESPACE_LIMITS = "robot_description_planning"; + +CommandListManager::CommandListManager(const ros::NodeHandle& nh, const moveit::core::RobotModelConstPtr& model) + : nh_(nh), model_(model) +{ + // Obtain the aggregated joint limits + pilz_industrial_motion_planner::JointLimitsContainer aggregated_limit_active_joints; + + aggregated_limit_active_joints = pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits( + ros::NodeHandle(PARAM_NAMESPACE_LIMITS), model_->getActiveJointModels()); + + // Obtain cartesian limits + pilz_industrial_motion_planner::CartesianLimit cartesian_limit = + pilz_industrial_motion_planner::CartesianLimitsAggregator::getAggregatedLimits( + ros::NodeHandle(PARAM_NAMESPACE_LIMITS)); + + pilz_industrial_motion_planner::LimitsContainer limits; + limits.setJointLimits(aggregated_limit_active_joints); + limits.setCartesianLimits(cartesian_limit); + + plan_comp_builder_.setModel(model); + plan_comp_builder_.setBlender(std::unique_ptr( + new pilz_industrial_motion_planner::TrajectoryBlenderTransitionWindow(limits))); +} + +RobotTrajCont CommandListManager::solve(const planning_scene::PlanningSceneConstPtr& planning_scene, + const planning_pipeline::PlanningPipelinePtr& planning_pipeline, + const moveit_msgs::MotionSequenceRequest& req_list) +{ + if (req_list.items.empty()) + { + return RobotTrajCont(); + } + + checkForNegativeRadii(req_list); + checkLastBlendRadiusZero(req_list); + checkStartStates(req_list); + + MotionResponseCont resp_cont{ solveSequenceItems(planning_scene, planning_pipeline, req_list) }; + + assert(model_); + RadiiCont radii{ extractBlendRadii(*model_, req_list) }; + checkForOverlappingRadii(resp_cont, radii); + + plan_comp_builder_.reset(); + for (MotionResponseCont::size_type i = 0; i < resp_cont.size(); ++i) + { + plan_comp_builder_.append(resp_cont.at(i).trajectory_, + // The blend radii has to be "attached" to + // the second part of a blend trajectory, + // therefore: "i-1". + (i > 0 ? radii.at(i - 1) : 0.)); + } + return plan_comp_builder_.build(); +} + +bool CommandListManager::checkRadiiForOverlap(const robot_trajectory::RobotTrajectory& traj_A, const double radii_A, + const robot_trajectory::RobotTrajectory& traj_B, + const double radii_B) const +{ + // No blending between trajectories from different groups + if (traj_A.getGroupName() != traj_B.getGroupName()) + { + return false; + } + + auto sum_radii{ radii_A + radii_B }; + if (sum_radii == 0.) + { + return false; + } + + const std::string& blend_frame{ getSolverTipFrame(model_->getJointModelGroup(traj_A.getGroupName())) }; + auto distance_endpoints = (traj_A.getLastWayPoint().getFrameTransform(blend_frame).translation() - + traj_B.getLastWayPoint().getFrameTransform(blend_frame).translation()) + .norm(); + return distance_endpoints <= sum_radii; +} + +void CommandListManager::checkForOverlappingRadii(const MotionResponseCont& resp_cont, const RadiiCont& radii) const +{ + if (resp_cont.empty()) + { + return; + } + if (resp_cont.size() < 3) + { + return; + } + + for (MotionResponseCont::size_type i = 0; i < resp_cont.size() - 2; ++i) + { + if (checkRadiiForOverlap(*(resp_cont.at(i).trajectory_), radii.at(i), *(resp_cont.at(i + 1).trajectory_), + radii.at(i + 1))) + { + std::ostringstream os; + os << "Overlapping blend radii between command [" << i << "] and [" << i + 1 << "]."; + throw OverlappingBlendRadiiException(os.str()); + } + } +} + +CommandListManager::RobotState_OptRef +CommandListManager::getPreviousEndState(const MotionResponseCont& motion_plan_responses, const std::string& group_name) +{ + for (MotionResponseCont::const_reverse_iterator it = motion_plan_responses.crbegin(); + it != motion_plan_responses.crend(); ++it) + { + if (it->trajectory_->getGroupName() == group_name) + { + return it->trajectory_->getLastWayPoint(); + } + } + return boost::none; +} + +void CommandListManager::setStartState(const MotionResponseCont& motion_plan_responses, const std::string& group_name, + moveit_msgs::RobotState& start_state) +{ + RobotState_OptRef rob_state_op{ getPreviousEndState(motion_plan_responses, group_name) }; + if (rob_state_op) + { + moveit::core::robotStateToRobotStateMsg(rob_state_op.value(), start_state); + } +} + +bool CommandListManager::isInvalidBlendRadii(const moveit::core::RobotModel& model, + const moveit_msgs::MotionSequenceItem& item_A, + const moveit_msgs::MotionSequenceItem& item_B) +{ + // Zero blend radius is always valid + if (item_A.blend_radius == 0.) + { + return false; + } + + // No blending between different groups + if (item_A.req.group_name != item_B.req.group_name) + { + ROS_WARN_STREAM("Blending between different groups (in this case: \"" + << item_A.req.group_name << "\" and \"" << item_B.req.group_name << "\") not allowed"); + return true; + } + + // No blending for groups without solver + if (!hasSolver(model.getJointModelGroup(item_A.req.group_name))) + { + ROS_WARN_STREAM("Blending for groups without solver not allowed"); + return true; + } + + return false; +} + +CommandListManager::RadiiCont CommandListManager::extractBlendRadii(const moveit::core::RobotModel& model, + const moveit_msgs::MotionSequenceRequest& req_list) +{ + RadiiCont radii(req_list.items.size(), 0.); + for (RadiiCont::size_type i = 0; i < (radii.size() - 1); ++i) + { + if (isInvalidBlendRadii(model, req_list.items.at(i), req_list.items.at(i + 1))) + { + ROS_WARN_STREAM("Invalid blend radii between commands: [" << i << "] and [" << i + 1 + << "] => Blend radii set to zero"); + continue; + } + radii.at(i) = req_list.items.at(i).blend_radius; + } + return radii; +} + +CommandListManager::MotionResponseCont +CommandListManager::solveSequenceItems(const planning_scene::PlanningSceneConstPtr& planning_scene, + const planning_pipeline::PlanningPipelinePtr& planning_pipeline, + const moveit_msgs::MotionSequenceRequest& req_list) const +{ + MotionResponseCont motion_plan_responses; + size_t curr_req_index{ 0 }; + const size_t num_req{ req_list.items.size() }; + for (const auto& seq_item : req_list.items) + { + planning_interface::MotionPlanRequest req{ seq_item.req }; + setStartState(motion_plan_responses, req.group_name, req.start_state); + + planning_interface::MotionPlanResponse res; + planning_pipeline->generatePlan(planning_scene, req, res); + if (res.error_code_.val != res.error_code_.SUCCESS) + { + std::ostringstream os; + os << "Could not solve request\n---\n" << req << "\n---\n"; + throw PlanningPipelineException(os.str(), res.error_code_.val); + } + motion_plan_responses.emplace_back(res); + ROS_DEBUG_STREAM("Solved [" << ++curr_req_index << "/" << num_req << "]"); + } + return motion_plan_responses; +} + +void CommandListManager::checkForNegativeRadii(const moveit_msgs::MotionSequenceRequest& req_list) +{ + if (!std::all_of(req_list.items.begin(), req_list.items.end(), + [](const moveit_msgs::MotionSequenceItem& req) { return (req.blend_radius >= 0.); })) + { + throw NegativeBlendRadiusException("All blending radii MUST be non negative"); + } +} + +void CommandListManager::checkStartStatesOfGroup(const moveit_msgs::MotionSequenceRequest& req_list, + const std::string& group_name) +{ + bool first_elem{ true }; + for (const moveit_msgs::MotionSequenceItem& item : req_list.items) + { + if (item.req.group_name != group_name) + { + continue; + } + + if (first_elem) + { + first_elem = false; + continue; + } + + if (!(item.req.start_state.joint_state.position.empty() && item.req.start_state.joint_state.velocity.empty() && + item.req.start_state.joint_state.effort.empty() && item.req.start_state.joint_state.name.empty())) + { + std::ostringstream os; + os << "Only the first request is allowed to have a start state, but" + << " the requests for group: \"" << group_name << "\" violate the rule"; + throw StartStateSetException(os.str()); + } + } +} + +void CommandListManager::checkStartStates(const moveit_msgs::MotionSequenceRequest& req_list) +{ + if (req_list.items.size() <= 1) + { + return; + } + + GroupNamesCont group_names{ getGroupNames(req_list) }; + for (const auto& curr_group_name : group_names) + { + checkStartStatesOfGroup(req_list, curr_group_name); + } +} + +CommandListManager::GroupNamesCont CommandListManager::getGroupNames(const moveit_msgs::MotionSequenceRequest& req_list) +{ + GroupNamesCont group_names; + std::for_each(req_list.items.cbegin(), req_list.items.cend(), + [&group_names](const moveit_msgs::MotionSequenceItem& item) { + if (std::find(group_names.cbegin(), group_names.cend(), item.req.group_name) == group_names.cend()) + { + group_names.emplace_back(item.req.group_name); + } + }); + return group_names; +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/src/joint_limits_aggregator.cpp b/moveit_planners/pilz_industrial_motion_planner/src/joint_limits_aggregator.cpp new file mode 100644 index 0000000000..5c800573b5 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/joint_limits_aggregator.cpp @@ -0,0 +1,181 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/joint_limits_aggregator.h" +#include "pilz_industrial_motion_planner/joint_limits_interface_extension.h" + +#include +#include + +#include + +pilz_industrial_motion_planner::JointLimitsContainer +pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits( + const ros::NodeHandle& nh, const std::vector& joint_models) +{ + JointLimitsContainer container; + + ROS_INFO_STREAM("Reading limits from namespace " << nh.getNamespace()); + + // Iterate over all joint models and generate the map + for (auto joint_model : joint_models) + { + JointLimit joint_limit; + + // If there is something defined for the joint on the parameter server + if (joint_limits_interface::getJointLimits(joint_model->getName(), nh, joint_limit)) + { + if (joint_limit.has_position_limits) + { + checkPositionBoundsThrowing(joint_model, joint_limit); + } + else + { + updatePositionLimitFromJointModel(joint_model, joint_limit); + } + + if (joint_limit.has_velocity_limits) + { + checkVelocityBoundsThrowing(joint_model, joint_limit); + } + else + { + updateVelocityLimitFromJointModel(joint_model, joint_limit); + } + } + else + { + // If there is nothing defined for this joint on the parameter server just + // update the values by the values of + // the urdf + + updatePositionLimitFromJointModel(joint_model, joint_limit); + updateVelocityLimitFromJointModel(joint_model, joint_limit); + } + + // Update max_deceleration if no max_acceleration has been set + if (joint_limit.has_acceleration_limits && !joint_limit.has_deceleration_limits) + { + joint_limit.max_deceleration = -joint_limit.max_acceleration; + joint_limit.has_deceleration_limits = true; + } + + // Insert the joint limit into the map + container.addLimit(joint_model->getName(), joint_limit); + } + + return container; +} + +void pilz_industrial_motion_planner::JointLimitsAggregator::updatePositionLimitFromJointModel( + const moveit::core::JointModel* joint_model, JointLimit& joint_limit) +{ + switch (joint_model->getVariableBounds().size()) + { + // LCOV_EXCL_START + case 0: + ROS_ERROR_STREAM("no bounds set for joint " << joint_model->getName()); + break; + // LCOV_EXCL_STOP + case 1: + joint_limit.has_position_limits = joint_model->getVariableBounds()[0].position_bounded_; + joint_limit.min_position = joint_model->getVariableBounds()[0].min_position_; + joint_limit.max_position = joint_model->getVariableBounds()[0].max_position_; + break; + // LCOV_EXCL_START + default: + ROS_ERROR_STREAM("Multi-DOF-Joints not supported. The robot won't move. " << joint_model->getName()); + joint_limit.has_position_limits = true; + joint_limit.min_position = 0; + joint_limit.max_position = 0; + break; + // LCOV_EXCL_STOP + } + + ROS_DEBUG_STREAM("Limit(" << joint_model->getName() << " min:" << joint_limit.min_position + << " max:" << joint_limit.max_position); +} + +void pilz_industrial_motion_planner::JointLimitsAggregator::updateVelocityLimitFromJointModel( + const moveit::core::JointModel* joint_model, JointLimit& joint_limit) +{ + switch (joint_model->getVariableBounds().size()) + { + // LCOV_EXCL_START + case 0: + ROS_ERROR_STREAM("no bounds set for joint " << joint_model->getName()); + break; + // LCOV_EXCL_STOP + case 1: + joint_limit.has_velocity_limits = joint_model->getVariableBounds()[0].velocity_bounded_; + joint_limit.max_velocity = joint_model->getVariableBounds()[0].max_velocity_; + break; + // LCOV_EXCL_START + default: + ROS_ERROR_STREAM("Multi-DOF-Joints not supported. The robot won't move."); + joint_limit.has_velocity_limits = true; + joint_limit.max_velocity = 0; + break; + // LCOV_EXCL_STOP + } +} + +void pilz_industrial_motion_planner::JointLimitsAggregator::checkPositionBoundsThrowing( + const moveit::core::JointModel* joint_model, const JointLimit& joint_limit) +{ + // Check min position + if (!joint_model->satisfiesPositionBounds(&joint_limit.min_position)) + { + throw AggregationBoundsViolationException("min_position of " + joint_model->getName() + + " violates min limit from URDF"); + } + + // Check max position + if (!joint_model->satisfiesPositionBounds(&joint_limit.max_position)) + { + throw AggregationBoundsViolationException("max_position of " + joint_model->getName() + + " violates max limit from URDF"); + } +} + +void pilz_industrial_motion_planner::JointLimitsAggregator::checkVelocityBoundsThrowing( + const moveit::core::JointModel* joint_model, const JointLimit& joint_limit) +{ + // Check min position + if (!joint_model->satisfiesVelocityBounds(&joint_limit.max_velocity)) + { + throw AggregationBoundsViolationException("max_velocity of " + joint_model->getName() + + " violates velocity limit from URDF"); + } +} diff --git a/moveit_planners/pilz_industrial_motion_planner/src/joint_limits_container.cpp b/moveit_planners/pilz_industrial_motion_planner/src/joint_limits_container.cpp new file mode 100644 index 0000000000..7bdb1d983f --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/joint_limits_container.cpp @@ -0,0 +1,182 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/joint_limits_container.h" + +#include "ros/ros.h" +#include + +namespace pilz_industrial_motion_planner +{ +bool JointLimitsContainer::addLimit(const std::string& joint_name, JointLimit joint_limit) +{ + if (joint_limit.has_deceleration_limits && joint_limit.max_deceleration >= 0) + { + ROS_ERROR_STREAM("joint_limit.max_deceleration MUST be negative!"); + return false; + } + const auto& insertion_result{ container_.insert(std::pair(joint_name, joint_limit)) }; + if (!insertion_result.second) + { + ROS_ERROR_STREAM("joint_limit for joint " << joint_name << " already contained."); + return false; + } + return true; +} + +bool JointLimitsContainer::hasLimit(const std::string& joint_name) const +{ + return container_.find(joint_name) != container_.end(); +} + +size_t JointLimitsContainer::getCount() const +{ + return container_.size(); +} + +bool JointLimitsContainer::empty() const +{ + return container_.empty(); +} + +JointLimit JointLimitsContainer::getCommonLimit() const +{ + JointLimit common_limit; + for (const auto& limit : container_) + { + updateCommonLimit(limit.second, common_limit); + } + return common_limit; +} + +JointLimit JointLimitsContainer::getCommonLimit(const std::vector& joint_names) const +{ + JointLimit common_limit; + for (const auto& joint_name : joint_names) + { + updateCommonLimit(container_.at(joint_name), common_limit); + } + return common_limit; +} + +JointLimit JointLimitsContainer::getLimit(const std::string& joint_name) const +{ + return container_.at(joint_name); +} + +std::map::const_iterator JointLimitsContainer::begin() const +{ + return container_.begin(); +} + +std::map::const_iterator JointLimitsContainer::end() const +{ + return container_.end(); +} + +bool JointLimitsContainer::verifyVelocityLimit(const std::string& joint_name, const double& joint_velocity) const +{ + return (!(hasLimit(joint_name) && getLimit(joint_name).has_velocity_limits && + fabs(joint_velocity) > getLimit(joint_name).max_velocity)); +} + +bool JointLimitsContainer::verifyPositionLimit(const std::string& joint_name, const double& joint_position) const +{ + return (!(hasLimit(joint_name) && getLimit(joint_name).has_position_limits && + (joint_position < getLimit(joint_name).min_position || joint_position > getLimit(joint_name).max_position))); +} + +bool JointLimitsContainer::verifyPositionLimits(const std::vector& joint_names, + const std::vector& joint_positions) const +{ + if (joint_names.size() != joint_positions.size()) + { + throw std::out_of_range("joint_names vector has a different size than joint_positions vector."); + } + + for (std::size_t i = 0; i < joint_names.size(); ++i) + { + if (!verifyPositionLimit(joint_names.at(i), joint_positions.at(i))) + { + return false; + } + } + + return true; +} + +void JointLimitsContainer::updateCommonLimit(const JointLimit& joint_limit, JointLimit& common_limit) +{ + // check position limits + if (joint_limit.has_position_limits) + { + double min_position = joint_limit.min_position; + double max_position = joint_limit.max_position; + + common_limit.min_position = + (!common_limit.has_position_limits) ? min_position : std::max(common_limit.min_position, min_position); + common_limit.max_position = + (!common_limit.has_position_limits) ? max_position : std::min(common_limit.max_position, max_position); + common_limit.has_position_limits = true; + } + + // check velocity limits + if (joint_limit.has_velocity_limits) + { + double max_velocity = joint_limit.max_velocity; + common_limit.max_velocity = + (!common_limit.has_velocity_limits) ? max_velocity : std::min(common_limit.max_velocity, max_velocity); + common_limit.has_velocity_limits = true; + } + + // check acceleration limits + if (joint_limit.has_acceleration_limits) + { + double max_acc = joint_limit.max_acceleration; + common_limit.max_acceleration = + (!common_limit.has_acceleration_limits) ? max_acc : std::min(common_limit.max_acceleration, max_acc); + common_limit.has_acceleration_limits = true; + } + + // check deceleration limits + if (joint_limit.has_deceleration_limits) + { + double max_dec = joint_limit.max_deceleration; + common_limit.max_deceleration = + (!common_limit.has_deceleration_limits) ? max_dec : std::max(common_limit.max_deceleration, max_dec); + common_limit.has_deceleration_limits = true; + } +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/src/joint_limits_validator.cpp b/moveit_planners/pilz_industrial_motion_planner/src/joint_limits_validator.cpp new file mode 100644 index 0000000000..66c5b198a9 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/joint_limits_validator.cpp @@ -0,0 +1,157 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include +#include + +#include "pilz_industrial_motion_planner/joint_limits_extension.h" +#include "pilz_industrial_motion_planner/joint_limits_interface_extension.h" + +#include "pilz_industrial_motion_planner/joint_limits_validator.h" + +bool pilz_industrial_motion_planner::JointLimitsValidator::validateAllPositionLimitsEqual( + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits) +{ + return validateWithEqualFunc(&pilz_industrial_motion_planner::JointLimitsValidator::positionEqual, joint_limits); +} + +bool pilz_industrial_motion_planner::JointLimitsValidator::validateAllVelocityLimitsEqual( + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits) +{ + return validateWithEqualFunc(&pilz_industrial_motion_planner::JointLimitsValidator::velocityEqual, joint_limits); +} + +bool pilz_industrial_motion_planner::JointLimitsValidator::validateAllAccelerationLimitsEqual( + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits) +{ + return validateWithEqualFunc(&pilz_industrial_motion_planner::JointLimitsValidator::accelerationEqual, joint_limits); +} + +bool pilz_industrial_motion_planner::JointLimitsValidator::validateAllDecelerationLimitsEqual( + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits) +{ + return validateWithEqualFunc(&pilz_industrial_motion_planner::JointLimitsValidator::decelerationEqual, joint_limits); +} + +bool pilz_industrial_motion_planner::JointLimitsValidator::validateWithEqualFunc( + bool (*eq_func)(const JointLimit&, const JointLimit&), + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits) +{ + // If there are no joint_limits it is considered equal + if (joint_limits.empty()) + { + return true; + } + + JointLimit reference = joint_limits.begin()->second; + + for (auto it = std::next(joint_limits.begin()); it != joint_limits.end(); ++it) + { + if (!eq_func(reference, it->second)) + { + return false; + } + } + + return true; +} + +bool pilz_industrial_motion_planner::JointLimitsValidator::positionEqual(const JointLimit& lhs, const JointLimit& rhs) +{ + // Return false if .has_velocity_limits differs + if (lhs.has_position_limits != rhs.has_position_limits) + { + return false; + } + + // If velocity limits are the same make sure they are equal + if (lhs.has_position_limits && ((lhs.max_position != rhs.max_position) || (lhs.min_position != rhs.min_position))) + { + return false; + } + return true; +} + +bool pilz_industrial_motion_planner::JointLimitsValidator::velocityEqual(const JointLimit& lhs, const JointLimit& rhs) +{ + // Return false if .has_velocity_limits differs + if (lhs.has_velocity_limits != rhs.has_velocity_limits) + { + return false; + } + + // If velocity limits are the same make sure they are equal + if (lhs.has_velocity_limits && (lhs.max_velocity != rhs.max_velocity)) + { + return false; + } + + return true; +} + +bool pilz_industrial_motion_planner::JointLimitsValidator::accelerationEqual(const JointLimit& lhs, + const JointLimit& rhs) +{ + // Return false if .has_acceleration_limits differs + if (lhs.has_acceleration_limits != rhs.has_acceleration_limits) + { + return false; + } + + // If velocity limits are the same make sure they are equal + if (lhs.has_acceleration_limits && (lhs.max_acceleration != rhs.max_acceleration)) + { + return false; + } + + return true; +} + +bool pilz_industrial_motion_planner::JointLimitsValidator::decelerationEqual(const JointLimit& lhs, + const JointLimit& rhs) +{ + // Return false if .has_acceleration_limits differs + if (lhs.has_deceleration_limits != rhs.has_deceleration_limits) + { + return false; + } + + // If velocity limits are the same make sure they are equal + if (lhs.has_deceleration_limits && (lhs.max_deceleration != rhs.max_deceleration)) + { + return false; + } + + return true; +} diff --git a/moveit_planners/pilz_industrial_motion_planner/src/limits_container.cpp b/moveit_planners/pilz_industrial_motion_planner/src/limits_container.cpp new file mode 100644 index 0000000000..6ee51df0b6 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/limits_container.cpp @@ -0,0 +1,78 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/limits_container.h" + +pilz_industrial_motion_planner::LimitsContainer::LimitsContainer() + : has_joint_limits_(false), has_cartesian_limits_(false) +{ +} + +bool pilz_industrial_motion_planner::LimitsContainer::hasJointLimits() const +{ + return has_joint_limits_; +} + +void pilz_industrial_motion_planner::LimitsContainer::setJointLimits( + pilz_industrial_motion_planner::JointLimitsContainer& joint_limits) +{ + has_joint_limits_ = true; + joint_limits_ = joint_limits; +} + +const pilz_industrial_motion_planner::JointLimitsContainer& +pilz_industrial_motion_planner::LimitsContainer::getJointLimitContainer() const +{ + return joint_limits_; +} + +bool pilz_industrial_motion_planner::LimitsContainer::hasFullCartesianLimits() const +{ + return (has_cartesian_limits_ && cartesian_limit_.hasMaxTranslationalVelocity() && + cartesian_limit_.hasMaxTranslationalAcceleration() && cartesian_limit_.hasMaxTranslationalDeceleration() && + cartesian_limit_.hasMaxRotationalVelocity()); +} + +void pilz_industrial_motion_planner::LimitsContainer::setCartesianLimits( + pilz_industrial_motion_planner::CartesianLimit& cartesian_limit) +{ + has_cartesian_limits_ = true; + cartesian_limit_ = cartesian_limit; +} + +const pilz_industrial_motion_planner::CartesianLimit& +pilz_industrial_motion_planner::LimitsContainer::getCartesianLimits() const +{ + return cartesian_limit_; +} diff --git a/moveit_planners/pilz_industrial_motion_planner/src/move_group_sequence_action.cpp b/moveit_planners/pilz_industrial_motion_planner/src/move_group_sequence_action.cpp new file mode 100644 index 0000000000..d0ff22bf3f --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/move_group_sequence_action.cpp @@ -0,0 +1,293 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2012, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage 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: Ioan Sucan */ + +// Modified by Pilz GmbH & Co. KG + +#include "pilz_industrial_motion_planner/move_group_sequence_action.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "pilz_industrial_motion_planner/command_list_manager.h" +#include "pilz_industrial_motion_planner/trajectory_generation_exceptions.h" + +namespace pilz_industrial_motion_planner +{ +MoveGroupSequenceAction::MoveGroupSequenceAction() : MoveGroupCapability("SequenceAction") +{ +} + +void MoveGroupSequenceAction::initialize() +{ + // start the move action server + ROS_INFO_STREAM("initialize move group sequence action"); + move_action_server_.reset(new actionlib::SimpleActionServer( + root_node_handle_, "sequence_move_group", + boost::bind(&MoveGroupSequenceAction::executeSequenceCallback, this, _1), false)); + move_action_server_->registerPreemptCallback(boost::bind(&MoveGroupSequenceAction::preemptMoveCallback, this)); + move_action_server_->start(); + + command_list_manager_.reset(new pilz_industrial_motion_planner::CommandListManager( + ros::NodeHandle("~"), context_->planning_scene_monitor_->getRobotModel())); +} + +void MoveGroupSequenceAction::executeSequenceCallback(const moveit_msgs::MoveGroupSequenceGoalConstPtr& goal) +{ + setMoveState(move_group::PLANNING); + + // Handle empty requests + if (goal->request.items.empty()) + { + ROS_WARN("Received empty request. That's ok but maybe not what you intended."); + setMoveState(move_group::IDLE); + moveit_msgs::MoveGroupSequenceResult action_res; + action_res.response.error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS; + move_action_server_->setSucceeded(action_res, "Received empty request."); + return; + } + + // before we start planning, ensure that we have the latest robot state + // received... + context_->planning_scene_monitor_->waitForCurrentRobotState(ros::Time::now()); + context_->planning_scene_monitor_->updateFrameTransforms(); + + moveit_msgs::MoveGroupSequenceResult action_res; + if (goal->planning_options.plan_only || !context_->allow_trajectory_execution_) + { + if (!goal->planning_options.plan_only) + { + ROS_WARN("Only plan will be calculated, although plan_only == false."); // LCOV_EXCL_LINE + } + executeMoveCallbackPlanOnly(goal, action_res); + } + else + { + executeSequenceCallbackPlanAndExecute(goal, action_res); + } + + switch (action_res.response.error_code.val) + { + case moveit_msgs::MoveItErrorCodes::SUCCESS: + move_action_server_->setSucceeded(action_res, "Success"); + break; + case moveit_msgs::MoveItErrorCodes::PREEMPTED: + move_action_server_->setPreempted(action_res, "Preempted"); + break; + default: + move_action_server_->setAborted(action_res, "See error code for more information"); + break; + } + + setMoveState(move_group::IDLE); +} + +void MoveGroupSequenceAction::executeSequenceCallbackPlanAndExecute( + const moveit_msgs::MoveGroupSequenceGoalConstPtr& goal, moveit_msgs::MoveGroupSequenceResult& action_res) +{ + ROS_INFO("Combined planning and execution request received for " + "MoveGroupSequenceAction."); + + plan_execution::PlanExecution::Options opt; + + const moveit_msgs::PlanningScene& planning_scene_diff = + planning_scene::PlanningScene::isEmpty(goal->planning_options.planning_scene_diff.robot_state) ? + goal->planning_options.planning_scene_diff : + clearSceneRobotState(goal->planning_options.planning_scene_diff); + + opt.replan_ = goal->planning_options.replan; + opt.replan_attempts_ = goal->planning_options.replan_attempts; + opt.replan_delay_ = goal->planning_options.replan_delay; + opt.before_execution_callback_ = boost::bind(&MoveGroupSequenceAction::startMoveExecutionCallback, this); + + opt.plan_callback_ = + boost::bind(&MoveGroupSequenceAction::planUsingSequenceManager, this, boost::cref(goal->request), _1); + + if (goal->planning_options.look_around && context_->plan_with_sensing_) + { + ROS_WARN("Plan with sensing not yet implemented/tested. This option is " + "ignored."); // LCOV_EXCL_LINE + } + + plan_execution::ExecutableMotionPlan plan; + context_->plan_execution_->planAndExecute(plan, planning_scene_diff, opt); + + StartStatesMsg start_states_msg; + convertToMsg(plan.plan_components_, start_states_msg, action_res.response.planned_trajectories); + try + { + action_res.response.sequence_start = start_states_msg.at(0); + } + catch (std::out_of_range&) + { + ROS_WARN("Can not determine start state from empty sequence."); + } + action_res.response.error_code = plan.error_code_; +} + +void MoveGroupSequenceAction::convertToMsg(const ExecutableTrajs& trajs, StartStatesMsg& start_states_msg, + PlannedTrajMsgs& planned_trajs_msgs) +{ + start_states_msg.resize(trajs.size()); + planned_trajs_msgs.resize(trajs.size()); + for (size_t i = 0; i < trajs.size(); ++i) + { + robot_state::robotStateToRobotStateMsg(trajs.at(i).trajectory_->getFirstWayPoint(), start_states_msg.at(i)); + trajs.at(i).trajectory_->getRobotTrajectoryMsg(planned_trajs_msgs.at(i)); + } +} + +void MoveGroupSequenceAction::executeMoveCallbackPlanOnly(const moveit_msgs::MoveGroupSequenceGoalConstPtr& goal, + moveit_msgs::MoveGroupSequenceResult& res) +{ + ROS_INFO("Planning request received for MoveGroupSequenceAction action."); + + // lock the scene so that it does not modify the world representation while + // diff() is called + planning_scene_monitor::LockedPlanningSceneRO lscene(context_->planning_scene_monitor_); + + const planning_scene::PlanningSceneConstPtr& the_scene = + (planning_scene::PlanningScene::isEmpty(goal->planning_options.planning_scene_diff)) ? + static_cast(lscene) : + lscene->diff(goal->planning_options.planning_scene_diff); + + ros::Time planning_start = ros::Time::now(); + RobotTrajCont traj_vec; + try + { + traj_vec = command_list_manager_->solve(the_scene, context_->planning_pipeline_, goal->request); + } + catch (const MoveItErrorCodeException& ex) + { + ROS_ERROR_STREAM("> Planning pipeline threw an exception (error code: " << ex.getErrorCode() << "): " << ex.what()); + res.response.error_code.val = ex.getErrorCode(); + return; + } + // LCOV_EXCL_START // Keep moveit up even if lower parts throw + catch (const std::exception& ex) + { + ROS_ERROR("Planning pipeline threw an exception: %s", ex.what()); + res.response.error_code.val = moveit_msgs::MoveItErrorCodes::FAILURE; + return; + } + // LCOV_EXCL_STOP + + StartStatesMsg start_states_msg; + start_states_msg.resize(traj_vec.size()); + res.response.planned_trajectories.resize(traj_vec.size()); + for (RobotTrajCont::size_type i = 0; i < traj_vec.size(); ++i) + { + move_group::MoveGroupCapability::convertToMsg(traj_vec.at(i), start_states_msg.at(i), + res.response.planned_trajectories.at(i)); + } + try + { + res.response.sequence_start = start_states_msg.at(0); + } + catch (std::out_of_range&) + { + ROS_WARN("Can not determine start state from empty sequence."); + } + + res.response.error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS; + res.response.planning_time = ros::Time::now().toSec() - planning_start.toSec(); +} + +bool MoveGroupSequenceAction::planUsingSequenceManager(const moveit_msgs::MotionSequenceRequest& req, + plan_execution::ExecutableMotionPlan& plan) +{ + setMoveState(move_group::PLANNING); + + planning_scene_monitor::LockedPlanningSceneRO lscene(plan.planning_scene_monitor_); + RobotTrajCont traj_vec; + try + { + traj_vec = command_list_manager_->solve(plan.planning_scene_, context_->planning_pipeline_, req); + } + catch (const MoveItErrorCodeException& ex) + { + ROS_ERROR_STREAM("Planning pipeline threw an exception (error code: " << ex.getErrorCode() << "): " << ex.what()); + plan.error_code_.val = ex.getErrorCode(); + return false; + } + // LCOV_EXCL_START // Keep moveit up even if lower parts throw + catch (const std::exception& ex) + { + ROS_ERROR_STREAM("Planning pipeline threw an exception: " << ex.what()); + plan.error_code_.val = moveit_msgs::MoveItErrorCodes::FAILURE; + return false; + } + // LCOV_EXCL_STOP + + if (!traj_vec.empty()) + { + plan.plan_components_.resize(traj_vec.size()); + for (size_t i = 0; i < traj_vec.size(); ++i) + { + plan.plan_components_.at(i).trajectory_ = traj_vec.at(i); + plan.plan_components_.at(i).description_ = "plan"; + } + } + plan.error_code_.val = moveit_msgs::MoveItErrorCodes::SUCCESS; + return true; +} + +void MoveGroupSequenceAction::startMoveExecutionCallback() +{ + setMoveState(move_group::MONITOR); +} + +void MoveGroupSequenceAction::preemptMoveCallback() +{ + context_->plan_execution_->stop(); +} + +void MoveGroupSequenceAction::setMoveState(move_group::MoveGroupState state) +{ + move_state_ = state; + move_feedback_.state = stateToStr(state); + move_action_server_->publishFeedback(move_feedback_); +} + +} // namespace pilz_industrial_motion_planner + +#include +PLUGINLIB_EXPORT_CLASS(pilz_industrial_motion_planner::MoveGroupSequenceAction, move_group::MoveGroupCapability) diff --git a/moveit_planners/pilz_industrial_motion_planner/src/move_group_sequence_service.cpp b/moveit_planners/pilz_industrial_motion_planner/src/move_group_sequence_service.cpp new file mode 100644 index 0000000000..ce6f789eb4 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/move_group_sequence_service.cpp @@ -0,0 +1,105 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2012, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage 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: Ioan Sucan */ + +// Modified by Pilz GmbH & Co. KG + +#include "pilz_industrial_motion_planner/move_group_sequence_service.h" + +#include "pilz_industrial_motion_planner/capability_names.h" +#include "pilz_industrial_motion_planner/command_list_manager.h" +#include "pilz_industrial_motion_planner/trajectory_generation_exceptions.h" + +namespace pilz_industrial_motion_planner +{ +MoveGroupSequenceService::MoveGroupSequenceService() : MoveGroupCapability("SequenceService") +{ +} + +MoveGroupSequenceService::~MoveGroupSequenceService() +{ +} + +void MoveGroupSequenceService::initialize() +{ + command_list_manager_.reset(new pilz_industrial_motion_planner::CommandListManager( + ros::NodeHandle("~"), context_->planning_scene_monitor_->getRobotModel())); + + sequence_service_ = root_node_handle_.advertiseService(SEQUENCE_SERVICE_NAME, &MoveGroupSequenceService::plan, this); +} + +bool MoveGroupSequenceService::plan(moveit_msgs::GetMotionSequence::Request& req, + moveit_msgs::GetMotionSequence::Response& res) +{ + // TODO: Do we lock on the correct scene? Does the lock belong to the scene + // used for planning? + planning_scene_monitor::LockedPlanningSceneRO ps(context_->planning_scene_monitor_); + + ros::Time planning_start = ros::Time::now(); + RobotTrajCont traj_vec; + try + { + traj_vec = command_list_manager_->solve(ps, context_->planning_pipeline_, req.request); + } + catch (const MoveItErrorCodeException& ex) + { + ROS_ERROR_STREAM("Planner threw an exception (error code: " << ex.getErrorCode() << "): " << ex.what()); + res.response.error_code.val = ex.getErrorCode(); + return true; + } + // LCOV_EXCL_START // Keep moveit up even if lower parts throw + catch (const std::exception& ex) + { + ROS_ERROR_STREAM("Planner threw an exception: " << ex.what()); + // If 'FALSE' then no response will be sent to the caller. + return false; + } + // LCOV_EXCL_STOP + + res.response.planned_trajectories.resize(traj_vec.size()); + for (RobotTrajCont::size_type i = 0; i < traj_vec.size(); ++i) + { + move_group::MoveGroupCapability::convertToMsg(traj_vec.at(i), res.response.sequence_start, + res.response.planned_trajectories.at(i)); + } + res.response.error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS; + res.response.planning_time = (ros::Time::now() - planning_start).toSec(); + return true; +} + +} // namespace pilz_industrial_motion_planner + +#include +PLUGINLIB_EXPORT_CLASS(pilz_industrial_motion_planner::MoveGroupSequenceService, move_group::MoveGroupCapability) diff --git a/moveit_planners/pilz_industrial_motion_planner/src/path_circle_generator.cpp b/moveit_planners/pilz_industrial_motion_planner/src/path_circle_generator.cpp new file mode 100644 index 0000000000..503a1a3c89 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/path_circle_generator.cpp @@ -0,0 +1,147 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/path_circle_generator.h" + +namespace pilz_industrial_motion_planner +{ +std::unique_ptr PathCircleGenerator::circleFromCenter(const KDL::Frame& start_pose, + const KDL::Frame& goal_pose, + const KDL::Vector& center_point, double eqradius) +{ + double a = (start_pose.p - center_point).Norm(); + double b = (goal_pose.p - center_point).Norm(); + double c = (start_pose.p - goal_pose.p).Norm(); + + if (fabs(a - b) > MAX_RADIUS_DIFF) + { + throw ErrorMotionPlanningCenterPointDifferentRadius(); + } + + // compute the rotation angle + double alpha = cosines(a, b, c); + + KDL::RotationalInterpolation* rot_interpo = new KDL::RotationalInterpolation_SingleAxis(); + double old_kdl_epsilon = KDL::epsilon; + try + { + KDL::epsilon = MAX_COLINEAR_NORM; + auto circle = std::unique_ptr( + new KDL::Path_Circle(start_pose, center_point, goal_pose.p, goal_pose.M, alpha, rot_interpo, eqradius, + true /* take ownership of RotationalInterpolation */)); + KDL::epsilon = old_kdl_epsilon; + return circle; + } + catch (KDL::Error_MotionPlanning&) + { + delete rot_interpo; // in case we could not construct the Path object, avoid + // a memory leak + KDL::epsilon = old_kdl_epsilon; + throw; // and pass the exception on to the caller + } +} + +std::unique_ptr PathCircleGenerator::circleFromInterim(const KDL::Frame& start_pose, + const KDL::Frame& goal_pose, + const KDL::Vector& interim_point, double eqradius) +{ + // compute the center point from interim point + // triangle edges + const KDL::Vector t = interim_point - start_pose.p; + const KDL::Vector u = goal_pose.p - start_pose.p; + const KDL::Vector v = goal_pose.p - interim_point; + // triangle normal + const KDL::Vector w = t * u; // cross product + + // circle center + if (w.Norm() < MAX_COLINEAR_NORM) + { + throw KDL::Error_MotionPlanning_Circle_No_Plane(); + } + const KDL::Vector center_point = + start_pose.p + (u * dot(t, t) * dot(u, v) - t * dot(u, u) * dot(t, v)) * 0.5 / pow(w.Norm(), 2); + + // compute the rotation angle + // triangle edges + const KDL::Vector t_center = center_point - start_pose.p; + const KDL::Vector v_center = goal_pose.p - center_point; + double a = t_center.Norm(); + double b = v_center.Norm(); + double c = u.Norm(); + double alpha = cosines(a, b, c); + + KDL::Vector kdl_aux_point(interim_point); + + // if the angle at the interim is an acute angle (<90deg), rotation angle is + // an obtuse angle (>90deg) + // in this case using the interim as auxiliary point for KDL::Path_Circle can + // lead to a path in the wrong direction + double interim_angle = cosines(t.Norm(), v.Norm(), u.Norm()); + if (interim_angle < M_PI / 2) + { + alpha = 2 * M_PI - alpha; + + // exclude that the goal is not colinear with start and center, then use the + // opposite of the goal as auxiliary point + if ((t_center * v_center).Norm() > MAX_COLINEAR_NORM) + { + kdl_aux_point = 2 * center_point - goal_pose.p; + } + } + + KDL::RotationalInterpolation* rot_interpo = new KDL::RotationalInterpolation_SingleAxis(); + try + { + return std::unique_ptr(new KDL::Path_Circle(start_pose, center_point, kdl_aux_point, goal_pose.M, alpha, + rot_interpo, eqradius, + true /* take ownership of RotationalInterpolation */)); + } + catch (KDL::Error_MotionPlanning&) // LCOV_EXCL_START // The cases where + // KDL would throw are already handled + // above, + // we keep these lines to be safe + { + delete rot_interpo; // in case we could not construct the Path object, avoid + // a memory leak + throw; // and pass the exception on to the caller + // LCOV_EXCL_STOP + } +} + +double PathCircleGenerator::cosines(const double a, const double b, const double c) +{ + return acos(std::max(std::min((pow(a, 2) + pow(b, 2) - pow(c, 2)) / (2.0 * a * b), 1.0), -1.0)); +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/src/pilz_industrial_motion_planner.cpp b/moveit_planners/pilz_industrial_motion_planner/src/pilz_industrial_motion_planner.cpp new file mode 100644 index 0000000000..a7e592b204 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/pilz_industrial_motion_planner.cpp @@ -0,0 +1,173 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/pilz_industrial_motion_planner.h" + +#include "pilz_industrial_motion_planner/planning_context_loader.h" +#include "pilz_industrial_motion_planner/planning_context_loader_ptp.h" +#include "pilz_industrial_motion_planner/planning_exceptions.h" + +#include "pilz_industrial_motion_planner/cartesian_limits_aggregator.h" +#include "pilz_industrial_motion_planner/joint_limits_aggregator.h" + +// Boost includes +#include + +#include + +#include + +namespace pilz_industrial_motion_planner +{ +static const std::string PARAM_NAMESPACE_LIMTS = "robot_description_planning"; + +bool CommandPlanner::initialize(const moveit::core::RobotModelConstPtr& model, const std::string& ns) +{ + // Call parent class initialize + planning_interface::PlannerManager::initialize(model, ns); + + // Store the model and the namespace + model_ = model; + namespace_ = ns; + + // Obtain the aggregated joint limits + aggregated_limit_active_joints_ = pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits( + ros::NodeHandle(PARAM_NAMESPACE_LIMTS), model->getActiveJointModels()); + + // Obtain cartesian limits + cartesian_limit_ = pilz_industrial_motion_planner::CartesianLimitsAggregator::getAggregatedLimits( + ros::NodeHandle(PARAM_NAMESPACE_LIMTS)); + + // Load the planning context loader + planner_context_loader.reset(new pluginlib::ClassLoader( + "pilz_industrial_motion_planner", "pilz_industrial_motion_planner::PlanningContextLoader")); + + // List available plugins + const std::vector& factories = planner_context_loader->getDeclaredClasses(); + std::stringstream ss; + for (const auto& factory : factories) + { + ss << factory << " "; + } + + ROS_INFO_STREAM("Available plugins: " << ss.str()); + + // Load each factory + for (const auto& factory : factories) + { + ROS_INFO_STREAM("About to load: " << factory); + PlanningContextLoaderPtr loader_pointer(planner_context_loader->createInstance(factory)); + + pilz_industrial_motion_planner::LimitsContainer limits; + limits.setJointLimits(aggregated_limit_active_joints_); + limits.setCartesianLimits(cartesian_limit_); + + loader_pointer->setLimits(limits); + loader_pointer->setModel(model_); + + registerContextLoader(loader_pointer); + } + + return true; +} + +std::string CommandPlanner::getDescription() const +{ + return "Pilz Industrial Motion Planner"; +} + +void CommandPlanner::getPlanningAlgorithms(std::vector& algs) const +{ + algs.clear(); + + for (const auto& context_loader : context_loader_map_) + { + algs.push_back(context_loader.first); + } +} + +planning_interface::PlanningContextPtr +CommandPlanner::getPlanningContext(const planning_scene::PlanningSceneConstPtr& planning_scene, + const moveit_msgs::MotionPlanRequest& req, + moveit_msgs::MoveItErrorCodes& error_code) const +{ + ROS_DEBUG_STREAM("Loading PlanningContext for request\n\n" << req << "\n"); + + // Check that a loaded for this request exists + if (!canServiceRequest(req)) + { + ROS_ERROR_STREAM("No ContextLoader for planner_id " << req.planner_id.c_str() << " found. Planning not possible."); + return nullptr; + } + + planning_interface::PlanningContextPtr planning_context; + + if (context_loader_map_.at(req.planner_id)->loadContext(planning_context, req.planner_id, req.group_name)) + { + ROS_DEBUG_STREAM("Found planning context loader for " << req.planner_id << " group:" << req.group_name); + planning_context->setMotionPlanRequest(req); + planning_context->setPlanningScene(planning_scene); + return planning_context; + } + else + { + error_code.val = moveit_msgs::MoveItErrorCodes::PLANNING_FAILED; + return nullptr; + } +} + +bool CommandPlanner::canServiceRequest(const moveit_msgs::MotionPlanRequest& req) const +{ + return context_loader_map_.find(req.planner_id) != context_loader_map_.end(); +} + +void CommandPlanner::registerContextLoader( + const pilz_industrial_motion_planner::PlanningContextLoaderPtr& planning_context_loader) +{ + // Only add if command is not already in list, throw exception if not + if (context_loader_map_.find(planning_context_loader->getAlgorithm()) == context_loader_map_.end()) + { + context_loader_map_[planning_context_loader->getAlgorithm()] = planning_context_loader; + ROS_INFO_STREAM("Registered Algorithm [" << planning_context_loader->getAlgorithm() << "]"); + } + else + { + throw ContextLoaderRegistrationException("The command [" + planning_context_loader->getAlgorithm() + + "] is already registered"); + } +} + +} // namespace pilz_industrial_motion_planner + +PLUGINLIB_EXPORT_CLASS(pilz_industrial_motion_planner::CommandPlanner, planning_interface::PlannerManager) diff --git a/moveit_planners/pilz_industrial_motion_planner/src/plan_components_builder.cpp b/moveit_planners/pilz_industrial_motion_planner/src/plan_components_builder.cpp new file mode 100644 index 0000000000..175a7deca9 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/plan_components_builder.cpp @@ -0,0 +1,137 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/plan_components_builder.h" + +#include + +#include "pilz_industrial_motion_planner/tip_frame_getter.h" + +namespace pilz_industrial_motion_planner +{ +std::vector PlanComponentsBuilder::build() const +{ + std::vector res_vec{ traj_cont_ }; + if (traj_tail_) + { + assert(!res_vec.empty()); + appendWithStrictTimeIncrease(*(res_vec.back()), *traj_tail_); + } + return res_vec; +} + +void PlanComponentsBuilder::appendWithStrictTimeIncrease(robot_trajectory::RobotTrajectory& result, + const robot_trajectory::RobotTrajectory& source) +{ + if (result.empty() || + !pilz_industrial_motion_planner::isRobotStateEqual(result.getLastWayPoint(), source.getFirstWayPoint(), + result.getGroupName(), ROBOT_STATE_EQUALITY_EPSILON)) + { + result.append(source, 0.0); + return; + } + + for (size_t i = 1; i < source.getWayPointCount(); ++i) + { + result.addSuffixWayPoint(source.getWayPoint(i), source.getWayPointDurationFromPrevious(i)); + } +} + +void PlanComponentsBuilder::blend(const robot_trajectory::RobotTrajectoryPtr& other, const double blend_radius) +{ + if (!blender_) + { + throw NoBlenderSetException("No blender set"); + } + + assert(other->getGroupName() == traj_tail_->getGroupName()); + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_request; + + blend_request.first_trajectory = traj_tail_; + blend_request.second_trajectory = other; + blend_request.blend_radius = blend_radius; + blend_request.group_name = traj_tail_->getGroupName(); + blend_request.link_name = getSolverTipFrame(model_->getJointModelGroup(blend_request.group_name)); + + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_response; + if (!blender_->blend(blend_request, blend_response)) + { + throw BlendingFailedException("Blending failed"); + } + + // Append the new trajectory elements + appendWithStrictTimeIncrease(*(traj_cont_.back()), *blend_response.first_trajectory); + traj_cont_.back()->append(*blend_response.blend_trajectory, 0.0); + // Store the last new trajectory element for future processing + traj_tail_ = blend_response.second_trajectory; // first for next blending segment +} + +void PlanComponentsBuilder::append(const robot_trajectory::RobotTrajectoryPtr& other, const double blend_radius) +{ + if (!model_) + { + throw NoRobotModelSetException("No robot model set"); + } + + if (!traj_tail_) + { + traj_tail_ = other; + // Reserve space in container for new trajectory + traj_cont_.emplace_back(new robot_trajectory::RobotTrajectory(model_, other->getGroupName())); + return; + } + + // Create new trajectory for every group change + if (other->getGroupName() != traj_tail_->getGroupName()) + { + appendWithStrictTimeIncrease(*(traj_cont_.back()), *traj_tail_); + traj_tail_ = other; + // Create new container element + traj_cont_.emplace_back(new robot_trajectory::RobotTrajectory(model_, other->getGroupName())); + return; + } + + // No blending + if (blend_radius <= 0.0) + { + appendWithStrictTimeIncrease(*(traj_cont_.back()), *traj_tail_); + traj_tail_ = other; + return; + } + + blend(other, blend_radius); +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader.cpp b/moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader.cpp new file mode 100644 index 0000000000..9a071bba58 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader.cpp @@ -0,0 +1,64 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/planning_context_loader.h" +#include + +pilz_industrial_motion_planner::PlanningContextLoader::PlanningContextLoader() : limits_set_(false), model_set_(false) +{ +} + +pilz_industrial_motion_planner::PlanningContextLoader::~PlanningContextLoader() +{ +} + +bool pilz_industrial_motion_planner::PlanningContextLoader::setModel(const moveit::core::RobotModelConstPtr& model) +{ + model_ = model; + model_set_ = true; + return true; +} + +bool pilz_industrial_motion_planner::PlanningContextLoader::setLimits( + const pilz_industrial_motion_planner::LimitsContainer& limits) +{ + limits_ = limits; + limits_set_ = true; + return true; +} + +std::string pilz_industrial_motion_planner::PlanningContextLoader::getAlgorithm() const +{ + return alg_; +} diff --git a/moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader_circ.cpp b/moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader_circ.cpp new file mode 100644 index 0000000000..0234b989dc --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader_circ.cpp @@ -0,0 +1,75 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/planning_context_loader_circ.h" +#include "moveit/planning_scene/planning_scene.h" +#include "pilz_industrial_motion_planner/planning_context_base.h" +#include "pilz_industrial_motion_planner/planning_context_circ.h" + +#include + +pilz_industrial_motion_planner::PlanningContextLoaderCIRC::PlanningContextLoaderCIRC() +{ + alg_ = "CIRC"; +} + +pilz_industrial_motion_planner::PlanningContextLoaderCIRC::~PlanningContextLoaderCIRC() +{ +} + +bool pilz_industrial_motion_planner::PlanningContextLoaderCIRC::loadContext( + planning_interface::PlanningContextPtr& planning_context, const std::string& name, const std::string& group) const +{ + if (limits_set_ && model_set_) + { + planning_context.reset(new PlanningContextCIRC(name, group, model_, limits_)); + return true; + } + else + { + if (!limits_set_) + { + ROS_ERROR_STREAM("Limits are not defined. Cannot load planning context. " + "Call setLimits loadContext"); + } + if (!model_set_) + { + ROS_ERROR_STREAM("Robot model was not set"); + } + return false; + } +} + +PLUGINLIB_EXPORT_CLASS(pilz_industrial_motion_planner::PlanningContextLoaderCIRC, + pilz_industrial_motion_planner::PlanningContextLoader) diff --git a/moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader_lin.cpp b/moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader_lin.cpp new file mode 100644 index 0000000000..85cf3b6fe9 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader_lin.cpp @@ -0,0 +1,75 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/planning_context_loader_lin.h" +#include "moveit/planning_scene/planning_scene.h" +#include "pilz_industrial_motion_planner/planning_context_base.h" +#include "pilz_industrial_motion_planner/planning_context_lin.h" + +#include + +pilz_industrial_motion_planner::PlanningContextLoaderLIN::PlanningContextLoaderLIN() +{ + alg_ = "LIN"; +} + +pilz_industrial_motion_planner::PlanningContextLoaderLIN::~PlanningContextLoaderLIN() +{ +} + +bool pilz_industrial_motion_planner::PlanningContextLoaderLIN::loadContext( + planning_interface::PlanningContextPtr& planning_context, const std::string& name, const std::string& group) const +{ + if (limits_set_ && model_set_) + { + planning_context.reset(new PlanningContextLIN(name, group, model_, limits_)); + return true; + } + else + { + if (!limits_set_) + { + ROS_ERROR_STREAM("Limits are not defined. Cannot load planning context. " + "Call setLimits loadContext"); + } + if (!model_set_) + { + ROS_ERROR_STREAM("Robot model was not set"); + } + return false; + } +} + +PLUGINLIB_EXPORT_CLASS(pilz_industrial_motion_planner::PlanningContextLoaderLIN, + pilz_industrial_motion_planner::PlanningContextLoader) diff --git a/moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader_ptp.cpp b/moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader_ptp.cpp new file mode 100644 index 0000000000..5c72e69cec --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/planning_context_loader_ptp.cpp @@ -0,0 +1,74 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/planning_context_loader_ptp.h" +#include "moveit/planning_scene/planning_scene.h" +#include "pilz_industrial_motion_planner/planning_context_ptp.h" + +#include + +pilz_industrial_motion_planner::PlanningContextLoaderPTP::PlanningContextLoaderPTP() +{ + alg_ = "PTP"; +} + +pilz_industrial_motion_planner::PlanningContextLoaderPTP::~PlanningContextLoaderPTP() +{ +} + +bool pilz_industrial_motion_planner::PlanningContextLoaderPTP::loadContext( + planning_interface::PlanningContextPtr& planning_context, const std::string& name, const std::string& group) const +{ + if (limits_set_ && model_set_) + { + planning_context.reset(new PlanningContextPTP(name, group, model_, limits_)); + return true; + } + else + { + if (!limits_set_) + { + ROS_ERROR_STREAM("Joint Limits are not defined. Cannot load planning " + "context. Call setLimits loadContext"); + } + if (!model_set_) + { + ROS_ERROR_STREAM("Robot model was not set"); + } + return false; + } +} + +PLUGINLIB_EXPORT_CLASS(pilz_industrial_motion_planner::PlanningContextLoaderPTP, + pilz_industrial_motion_planner::PlanningContextLoader) diff --git a/moveit_planners/pilz_industrial_motion_planner/src/trajectory_blender_transition_window.cpp b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_blender_transition_window.cpp new file mode 100644 index 0000000000..94c108ced8 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_blender_transition_window.cpp @@ -0,0 +1,301 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/trajectory_blender_transition_window.h" + +#include +#include +#include +#include + +bool pilz_industrial_motion_planner::TrajectoryBlenderTransitionWindow::blend( + const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, + pilz_industrial_motion_planner::TrajectoryBlendResponse& res) +{ + ROS_INFO("Start trajectory blending using transition window."); + + double sampling_time = 0.; + if (!validateRequest(req, sampling_time, res.error_code)) + { + ROS_ERROR("Trajectory blend request is not valid."); + return false; + } + + // search for intersection points of the two trajectories with the blending + // sphere + // intersection points belongs to blend trajectory after blending + std::size_t first_intersection_index; + std::size_t second_intersection_index; + if (!searchIntersectionPoints(req, first_intersection_index, second_intersection_index)) + { + ROS_ERROR("Blend radius to large."); + res.error_code.val = moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN; + return false; + } + + // Select blending period and adjust the start and end point of the blend + // phase + std::size_t blend_align_index; + determineTrajectoryAlignment(req, first_intersection_index, second_intersection_index, blend_align_index); + + // blend the trajectories in Cartesian space + pilz_industrial_motion_planner::CartesianTrajectory blend_trajectory_cartesian; + blendTrajectoryCartesian(req, first_intersection_index, second_intersection_index, blend_align_index, sampling_time, + blend_trajectory_cartesian); + + // generate the blending trajectory in joint space + std::map initial_joint_position, initial_joint_velocity; + for (const std::string& joint_name : + req.first_trajectory->getFirstWayPointPtr()->getJointModelGroup(req.group_name)->getActiveJointModelNames()) + { + initial_joint_position[joint_name] = + req.first_trajectory->getWayPoint(first_intersection_index - 1).getVariablePosition(joint_name); + initial_joint_velocity[joint_name] = + req.first_trajectory->getWayPoint(first_intersection_index - 1).getVariableVelocity(joint_name); + } + trajectory_msgs::JointTrajectory blend_joint_trajectory; + moveit_msgs::MoveItErrorCodes error_code; + if (!generateJointTrajectory(req.first_trajectory->getFirstWayPointPtr()->getRobotModel(), + limits_.getJointLimitContainer(), blend_trajectory_cartesian, req.group_name, + req.link_name, initial_joint_position, initial_joint_velocity, blend_joint_trajectory, + error_code, true)) + { + // LCOV_EXCL_START + ROS_INFO("Failed to generate joint trajectory for blending trajectory."); + res.error_code.val = error_code.val; + return false; + // LCOV_EXCL_STOP + } + + res.first_trajectory = std::shared_ptr( + new robot_trajectory::RobotTrajectory(req.first_trajectory->getRobotModel(), req.first_trajectory->getGroup())); + res.blend_trajectory = std::shared_ptr( + new robot_trajectory::RobotTrajectory(req.first_trajectory->getRobotModel(), req.first_trajectory->getGroup())); + res.second_trajectory = std::shared_ptr( + new robot_trajectory::RobotTrajectory(req.first_trajectory->getRobotModel(), req.first_trajectory->getGroup())); + + // set the three trajectories after blending in response + // erase the points [first_intersection_index, back()] from the first + // trajectory + for (size_t i = 0; i < first_intersection_index; ++i) + { + res.first_trajectory->insertWayPoint(i, req.first_trajectory->getWayPoint(i), + req.first_trajectory->getWayPointDurationFromPrevious(i)); + } + + // append the blend trajectory + res.blend_trajectory->setRobotTrajectoryMsg(req.first_trajectory->getFirstWayPoint(), blend_joint_trajectory); + // copy the points [second_intersection_index, len] from the second trajectory + for (size_t i = second_intersection_index + 1; i < req.second_trajectory->getWayPointCount(); ++i) + { + res.second_trajectory->insertWayPoint(i - (second_intersection_index + 1), req.second_trajectory->getWayPoint(i), + req.second_trajectory->getWayPointDurationFromPrevious(i)); + } + + // adjust the time from start + res.second_trajectory->setWayPointDurationFromPrevious(0, sampling_time); + + res.error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS; + return true; +} + +bool pilz_industrial_motion_planner::TrajectoryBlenderTransitionWindow::validateRequest( + const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, double& sampling_time, + moveit_msgs::MoveItErrorCodes& error_code) const +{ + ROS_DEBUG("Validate the trajectory blend request."); + + // check planning group + if (!req.first_trajectory->getRobotModel()->hasJointModelGroup(req.group_name)) + { + ROS_ERROR_STREAM("Unknown planning group: " << req.group_name); + error_code.val = moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME; + return false; + } + + // check link exists + if (!req.first_trajectory->getRobotModel()->hasLinkModel(req.link_name) && + !req.first_trajectory->getLastWayPoint().hasAttachedBody(req.link_name)) + { + ROS_ERROR_STREAM("Unknown link name: " << req.link_name); + error_code.val = moveit_msgs::MoveItErrorCodes::INVALID_LINK_NAME; + return false; + } + + if (req.blend_radius <= 0) + { + ROS_ERROR("Blending radius must be positive"); + error_code.val = moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN; + return false; + } + + // end position of the first trajectory and start position of second + // trajectory must be the same + if (!pilz_industrial_motion_planner::isRobotStateEqual( + req.first_trajectory->getLastWayPoint(), req.second_trajectory->getFirstWayPoint(), req.group_name, EPSILON)) + { + ROS_ERROR_STREAM("During blending the last point of the preceding and the first point of the succeding trajectory"); + error_code.val = moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN; + return false; + } + + // same uniform sampling time + if (!pilz_industrial_motion_planner::determineAndCheckSamplingTime(req.first_trajectory, req.second_trajectory, + EPSILON, sampling_time)) + { + error_code.val = moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN; + return false; + } + + // end position of the first trajectory and start position of second + // trajectory must have zero + // velocities/accelerations + if (!pilz_industrial_motion_planner::isRobotStateStationary(req.first_trajectory->getLastWayPoint(), req.group_name, + EPSILON) || + !pilz_industrial_motion_planner::isRobotStateStationary(req.second_trajectory->getFirstWayPoint(), req.group_name, + EPSILON)) + { + ROS_ERROR("Intersection point of the blending trajectories has non-zero " + "velocities/accelerations."); + error_code.val = moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN; + return false; + } + + return true; +} + +void pilz_industrial_motion_planner::TrajectoryBlenderTransitionWindow::blendTrajectoryCartesian( + const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, const std::size_t first_interse_index, + const std::size_t second_interse_index, const std::size_t blend_align_index, double sampling_time, + pilz_industrial_motion_planner::CartesianTrajectory& trajectory) const +{ + // other fields of the trajectory + trajectory.group_name = req.group_name; + trajectory.link_name = req.link_name; + + // Pose on first trajectory + Eigen::Isometry3d blend_sample_pose1 = + req.first_trajectory->getWayPoint(first_interse_index).getFrameTransform(req.link_name); + + // Pose on second trajectory + Eigen::Isometry3d blend_sample_pose2 = + req.second_trajectory->getWayPoint(second_interse_index).getFrameTransform(req.link_name); + + // blend the trajectory + double blend_sample_num = second_interse_index + blend_align_index - first_interse_index + 1; + pilz_industrial_motion_planner::CartesianTrajectoryPoint waypoint; + blend_sample_pose2 = req.second_trajectory->getFirstWayPoint().getFrameTransform(req.link_name); + + // Pose on blending trajectory + Eigen::Isometry3d blend_sample_pose; + for (std::size_t i = 0; i < blend_sample_num; ++i) + { + // if the first trajectory does not reach the last sample, update + if ((first_interse_index + i) < req.first_trajectory->getWayPointCount()) + { + blend_sample_pose1 = req.first_trajectory->getWayPoint(first_interse_index + i).getFrameTransform(req.link_name); + } + + // if after the alignment, the second trajectory starts, update + if ((first_interse_index + i) > blend_align_index) + { + blend_sample_pose2 = req.second_trajectory->getWayPoint(first_interse_index + i - blend_align_index) + .getFrameTransform(req.link_name); + } + + double s = (i + 1) / blend_sample_num; + double alpha = 6 * std::pow(s, 5) - 15 * std::pow(s, 4) + 10 * std::pow(s, 3); + + // blend the translation + blend_sample_pose.translation() = blend_sample_pose1.translation() + + alpha * (blend_sample_pose2.translation() - blend_sample_pose1.translation()); + + // blend the orientation + Eigen::Quaterniond start_quat(blend_sample_pose1.rotation()); + Eigen::Quaterniond end_quat(blend_sample_pose2.rotation()); + blend_sample_pose.linear() = start_quat.slerp(alpha, end_quat).toRotationMatrix(); + + // push to the trajectory + waypoint.pose = tf2::toMsg(blend_sample_pose); + waypoint.time_from_start = ros::Duration((i + 1.0) * sampling_time); + trajectory.points.push_back(waypoint); + } +} + +bool pilz_industrial_motion_planner::TrajectoryBlenderTransitionWindow::searchIntersectionPoints( + const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, std::size_t& first_interse_index, + std::size_t& second_interse_index) const +{ + ROS_INFO("Search for start and end point of blending trajectory."); + + // compute the position of the center of the blend sphere + // (last point of the first trajectory, first point of the second trajectory) + Eigen::Isometry3d circ_pose = req.first_trajectory->getLastWayPoint().getFrameTransform(req.link_name); + + // Searh for intersection points according to distance + if (!linearSearchIntersectionPoint(req.link_name, circ_pose.translation(), req.blend_radius, req.first_trajectory, + true, first_interse_index)) + { + ROS_ERROR_STREAM("Intersection point of first trajectory not found."); + return false; + } + ROS_INFO_STREAM("Intersection point of first trajectory found, index: " << first_interse_index); + + if (!linearSearchIntersectionPoint(req.link_name, circ_pose.translation(), req.blend_radius, req.second_trajectory, + false, second_interse_index)) + { + ROS_ERROR_STREAM("Intersection point of second trajectory not found."); + return false; + } + + ROS_INFO_STREAM("Intersection point of second trajectory found, index: " << second_interse_index); + return true; +} + +void pilz_industrial_motion_planner::TrajectoryBlenderTransitionWindow::determineTrajectoryAlignment( + const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, std::size_t first_interse_index, + std::size_t second_interse_index, std::size_t& blend_align_index) const +{ + size_t way_point_count_1 = req.first_trajectory->getWayPointCount() - first_interse_index; + size_t way_point_count_2 = second_interse_index + 1; + + if (way_point_count_1 > way_point_count_2) + { + blend_align_index = req.first_trajectory->getWayPointCount() - second_interse_index - 1; + } + else + { + blend_align_index = first_interse_index; + } +} diff --git a/moveit_planners/pilz_industrial_motion_planner/src/trajectory_functions.cpp b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_functions.cpp new file mode 100644 index 0000000000..5d37a4d4ea --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_functions.cpp @@ -0,0 +1,584 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/trajectory_functions.h" + +#include +#include +#include +#include +#include + +bool pilz_industrial_motion_planner::computePoseIK(const moveit::core::RobotModelConstPtr& robot_model, + const std::string& group_name, const std::string& link_name, + const Eigen::Isometry3d& pose, const std::string& frame_id, + const std::map& seed, + std::map& solution, bool check_self_collision, + const double timeout) +{ + if (!robot_model->hasJointModelGroup(group_name)) + { + ROS_ERROR_STREAM("Robot model has no planning group named as " << group_name); + return false; + } + + if (!robot_model->getJointModelGroup(group_name)->canSetStateFromIK(link_name)) + { + ROS_ERROR_STREAM("No valid IK solver exists for " << link_name << " in planning group " << group_name); + return false; + } + + if (frame_id != robot_model->getModelFrame()) + { + ROS_ERROR_STREAM("Given frame (" << frame_id << ") is unequal to model frame(" << robot_model->getModelFrame() + << ")"); + return false; + } + + robot_state::RobotState rstate(robot_model); + // By setting the robot state to default values, we basically allow + // the user of this function to supply an incomplete or even empty seed. + rstate.setToDefaultValues(); + rstate.setVariablePositions(seed); + + moveit::core::GroupStateValidityCallbackFn ik_constraint_function; + ik_constraint_function = + boost::bind(&pilz_industrial_motion_planner::isStateColliding, check_self_collision, robot_model, _1, _2, _3); + + // call ik + if (rstate.setFromIK(robot_model->getJointModelGroup(group_name), pose, link_name, timeout, ik_constraint_function)) + { + // copy the solution + for (const auto& joint_name : robot_model->getJointModelGroup(group_name)->getActiveJointModelNames()) + { + solution[joint_name] = rstate.getVariablePosition(joint_name); + } + return true; + } + else + { + ROS_ERROR_STREAM("Inverse kinematics for pose \n" << pose.translation() << " has no solution."); + return false; + } +} + +bool pilz_industrial_motion_planner::computePoseIK(const moveit::core::RobotModelConstPtr& robot_model, + const std::string& group_name, const std::string& link_name, + const geometry_msgs::Pose& pose, const std::string& frame_id, + const std::map& seed, + std::map& solution, bool check_self_collision, + const double timeout) +{ + Eigen::Isometry3d pose_eigen; + tf2::convert(pose, pose_eigen); + return computePoseIK(robot_model, group_name, link_name, pose_eigen, frame_id, seed, solution, check_self_collision, + timeout); +} + +bool pilz_industrial_motion_planner::computeLinkFK(const moveit::core::RobotModelConstPtr& robot_model, + const std::string& link_name, + const std::map& joint_state, + Eigen::Isometry3d& pose) +{ // create robot state + robot_state::RobotState rstate(robot_model); + + // check the reference frame of the target pose + if (!rstate.knowsFrameTransform(link_name)) + { + ROS_ERROR_STREAM("The target link " << link_name << " is not known by robot."); + return false; + } + + // set the joint positions + rstate.setToDefaultValues(); + rstate.setVariablePositions(joint_state); + + // update the frame + rstate.update(); + pose = rstate.getFrameTransform(link_name); + + return true; +} + +bool pilz_industrial_motion_planner::verifySampleJointLimits( + const std::map& position_last, const std::map& velocity_last, + const std::map& position_current, double duration_last, double duration_current, + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits) +{ + const double epsilon = 10e-6; + if (duration_current <= epsilon) + { + ROS_ERROR("Sample duration too small, cannot compute the velocity"); + return false; + } + + double velocity_current, acceleration_current; + + for (const auto& pos : position_current) + { + velocity_current = (pos.second - position_last.at(pos.first)) / duration_current; + + if (!joint_limits.verifyVelocityLimit(pos.first, velocity_current)) + { + ROS_ERROR_STREAM("Joint velocity limit of " << pos.first << " violated. Set the velocity scaling factor lower!" + << " Actual joint velocity is " << velocity_current + << ", while the limit is " + << joint_limits.getLimit(pos.first).max_velocity << ". "); + return false; + } + + acceleration_current = (velocity_current - velocity_last.at(pos.first)) / (duration_last + duration_current) * 2; + // acceleration case + if (fabs(velocity_last.at(pos.first)) <= fabs(velocity_current)) + { + if (joint_limits.getLimit(pos.first).has_acceleration_limits && + fabs(acceleration_current) > fabs(joint_limits.getLimit(pos.first).max_acceleration)) + { + ROS_ERROR_STREAM("Joint acceleration limit of " + << pos.first << " violated. Set the acceleration scaling factor lower!" + << " Actual joint acceleration is " << acceleration_current << ", while the limit is " + << joint_limits.getLimit(pos.first).max_acceleration << ". "); + return false; + } + } + // deceleration case + else + { + if (joint_limits.getLimit(pos.first).has_deceleration_limits && + fabs(acceleration_current) > fabs(joint_limits.getLimit(pos.first).max_deceleration)) + { + ROS_ERROR_STREAM("Joint deceleration limit of " + << pos.first << " violated. Set the acceleration scaling factor lower!" + << " Actual joint deceleration is " << acceleration_current << ", while the limit is " + << joint_limits.getLimit(pos.first).max_deceleration << ". "); + return false; + } + } + } + + return true; +} + +bool pilz_industrial_motion_planner::generateJointTrajectory( + const moveit::core::RobotModelConstPtr& robot_model, + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits, const KDL::Trajectory& trajectory, + const std::string& group_name, const std::string& link_name, + const std::map& initial_joint_position, const double& sampling_time, + trajectory_msgs::JointTrajectory& joint_trajectory, moveit_msgs::MoveItErrorCodes& error_code, + bool check_self_collision) +{ + ROS_DEBUG("Generate joint trajectory from a Cartesian trajectory."); + + ros::Time generation_begin = ros::Time::now(); + + // generate the time samples + const double epsilon = 10e-06; // avoid adding the last time sample twice + std::vector time_samples; + for (double t_sample = 0.0; t_sample < trajectory.Duration() - epsilon; t_sample += sampling_time) + { + time_samples.push_back(t_sample); + } + time_samples.push_back(trajectory.Duration()); + + // sample the trajectory and solve the inverse kinematics + Eigen::Isometry3d pose_sample; + std::map ik_solution_last, ik_solution, joint_velocity_last; + ik_solution_last = initial_joint_position; + for (const auto& item : ik_solution_last) + { + joint_velocity_last[item.first] = 0.0; + } + + for (std::vector::const_iterator time_iter = time_samples.begin(); time_iter != time_samples.end(); + ++time_iter) + { + tf::transformKDLToEigen(trajectory.Pos(*time_iter), pose_sample); + + if (!computePoseIK(robot_model, group_name, link_name, pose_sample, robot_model->getModelFrame(), ik_solution_last, + ik_solution, check_self_collision)) + { + ROS_ERROR("Failed to compute inverse kinematics solution for sampled " + "Cartesian pose."); + error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION; + joint_trajectory.points.clear(); + return false; + } + + // check the joint limits + double duration_current_sample = sampling_time; + // last interval can be shorter than the sampling time + if (time_iter == (time_samples.end() - 1) && time_samples.size() > 1) + { + duration_current_sample = *time_iter - *(time_iter - 1); + } + if (time_samples.size() == 1) + { + duration_current_sample = *time_iter; + } + + // skip the first sample with zero time from start for limits checking + if (time_iter != time_samples.begin() && + !verifySampleJointLimits(ik_solution_last, joint_velocity_last, ik_solution, sampling_time, + duration_current_sample, joint_limits)) + { + ROS_ERROR_STREAM("Inverse kinematics solution at " + << *time_iter << "s violates the joint velocity/acceleration/deceleration limits."); + error_code.val = moveit_msgs::MoveItErrorCodes::PLANNING_FAILED; + joint_trajectory.points.clear(); + return false; + } + + // fill the point with joint values + trajectory_msgs::JointTrajectoryPoint point; + + // set joint names + joint_trajectory.joint_names.clear(); + for (const auto& start_joint : initial_joint_position) + { + joint_trajectory.joint_names.push_back(start_joint.first); + } + + point.time_from_start = ros::Duration(*time_iter); + for (const auto& joint_name : joint_trajectory.joint_names) + { + point.positions.push_back(ik_solution.at(joint_name)); + + if (time_iter != time_samples.begin() && time_iter != time_samples.end() - 1) + { + double joint_velocity = + (ik_solution.at(joint_name) - ik_solution_last.at(joint_name)) / duration_current_sample; + point.velocities.push_back(joint_velocity); + point.accelerations.push_back((joint_velocity - joint_velocity_last.at(joint_name)) / + (duration_current_sample + sampling_time) * 2); + joint_velocity_last[joint_name] = joint_velocity; + } + else + { + point.velocities.push_back(0.); + point.accelerations.push_back(0.); + joint_velocity_last[joint_name] = 0.; + } + } + + // update joint trajectory + joint_trajectory.points.push_back(point); + ik_solution_last = ik_solution; + } + + error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS; + double duration_ms = (ros::Time::now() - generation_begin).toSec() * 1000; + ROS_DEBUG_STREAM("Generate trajectory (N-Points: " << joint_trajectory.points.size() << ") took " << duration_ms + << " ms | " << duration_ms / joint_trajectory.points.size() + << " ms per Point"); + + return true; +} + +bool pilz_industrial_motion_planner::generateJointTrajectory( + const moveit::core::RobotModelConstPtr& robot_model, + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits, + const pilz_industrial_motion_planner::CartesianTrajectory& trajectory, const std::string& group_name, + const std::string& link_name, const std::map& initial_joint_position, + const std::map& initial_joint_velocity, trajectory_msgs::JointTrajectory& joint_trajectory, + moveit_msgs::MoveItErrorCodes& error_code, bool check_self_collision) +{ + ROS_DEBUG("Generate joint trajectory from a Cartesian trajectory."); + + ros::Time generation_begin = ros::Time::now(); + + std::map ik_solution_last = initial_joint_position; + std::map joint_velocity_last = initial_joint_velocity; + double duration_last = 0; + double duration_current = 0; + joint_trajectory.joint_names.clear(); + for (const auto& joint_position : ik_solution_last) + { + joint_trajectory.joint_names.push_back(joint_position.first); + } + std::map ik_solution; + for (size_t i = 0; i < trajectory.points.size(); ++i) + { + // compute inverse kinematics + if (!computePoseIK(robot_model, group_name, link_name, trajectory.points.at(i).pose, robot_model->getModelFrame(), + ik_solution_last, ik_solution, check_self_collision)) + { + ROS_ERROR("Failed to compute inverse kinematics solution for sampled " + "Cartesian pose."); + error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION; + joint_trajectory.points.clear(); + return false; + } + + // verify the joint limits + if (i == 0) + { + duration_current = trajectory.points.front().time_from_start.toSec(); + duration_last = duration_current; + } + else + { + duration_current = + trajectory.points.at(i).time_from_start.toSec() - trajectory.points.at(i - 1).time_from_start.toSec(); + } + + if (!verifySampleJointLimits(ik_solution_last, joint_velocity_last, ik_solution, duration_last, duration_current, + joint_limits)) + { + // LCOV_EXCL_START since the same code was captured in a test in the other + // overload generateJointTrajectory(..., + // KDL::Trajectory, ...) + // TODO: refactor to avoid code duplication. + ROS_ERROR_STREAM("Inverse kinematics solution of the " << i + << "th sample violates the joint " + "velocity/acceleration/deceleration limits."); + error_code.val = moveit_msgs::MoveItErrorCodes::PLANNING_FAILED; + joint_trajectory.points.clear(); + return false; + // LCOV_EXCL_STOP + } + + // compute the waypoint + trajectory_msgs::JointTrajectoryPoint waypoint_joint; + waypoint_joint.time_from_start = ros::Duration(trajectory.points.at(i).time_from_start); + for (const auto& joint_name : joint_trajectory.joint_names) + { + waypoint_joint.positions.push_back(ik_solution.at(joint_name)); + double joint_velocity = (ik_solution.at(joint_name) - ik_solution_last.at(joint_name)) / duration_current; + waypoint_joint.velocities.push_back(joint_velocity); + waypoint_joint.accelerations.push_back((joint_velocity - joint_velocity_last.at(joint_name)) / + (duration_current + duration_last) * 2); + // update the joint velocity + joint_velocity_last[joint_name] = joint_velocity; + } + + // update joint trajectory + joint_trajectory.points.push_back(waypoint_joint); + ik_solution_last = ik_solution; + duration_last = duration_current; + } + + error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS; + + double duration_ms = (ros::Time::now() - generation_begin).toSec() * 1000; + ROS_DEBUG_STREAM("Generate trajectory (N-Points: " << joint_trajectory.points.size() << ") took " << duration_ms + << " ms | " << duration_ms / joint_trajectory.points.size() + << " ms per Point"); + + return true; +} + +bool pilz_industrial_motion_planner::determineAndCheckSamplingTime( + const robot_trajectory::RobotTrajectoryPtr& first_trajectory, + const robot_trajectory::RobotTrajectoryPtr& second_trajectory, double epsilon, double& sampling_time) +{ + // The last sample is ignored because it is allowed to violate the sampling + // time. + std::size_t n1 = first_trajectory->getWayPointCount() - 1; + std::size_t n2 = second_trajectory->getWayPointCount() - 1; + if ((n1 < 2) && (n2 < 2)) + { + ROS_ERROR_STREAM("Both trajectories do not have enough points to determine " + "sampling time."); + return false; + } + + if (n1 >= 2) + { + sampling_time = first_trajectory->getWayPointDurationFromPrevious(1); + } + else + { + sampling_time = second_trajectory->getWayPointDurationFromPrevious(1); + } + + for (std::size_t i = 1; i < std::max(n1, n2); ++i) + { + if (i < n1) + { + if (fabs(sampling_time - first_trajectory->getWayPointDurationFromPrevious(i)) > epsilon) + { + ROS_ERROR_STREAM("First trajectory violates sampline time " << sampling_time << " between points " << (i - 1) + << "and " << i << " (indices)."); + return false; + } + } + + if (i < n2) + { + if (fabs(sampling_time - second_trajectory->getWayPointDurationFromPrevious(i)) > epsilon) + { + ROS_ERROR_STREAM("Second trajectory violates sampline time " << sampling_time << " between points " << (i - 1) + << "and " << i << " (indices)."); + return false; + } + } + } + + return true; +} + +bool pilz_industrial_motion_planner::isRobotStateEqual(const moveit::core::RobotState& state1, + const moveit::core::RobotState& state2, + const std::string& joint_group_name, double epsilon) +{ + Eigen::VectorXd joint_position_1, joint_position_2; + + state1.copyJointGroupPositions(joint_group_name, joint_position_1); + state2.copyJointGroupPositions(joint_group_name, joint_position_2); + + if ((joint_position_1 - joint_position_2).norm() > epsilon) + { + ROS_DEBUG_STREAM("Joint positions of the two states are different. state1: " << joint_position_1 + << " state2: " << joint_position_2); + return false; + } + + Eigen::VectorXd joint_velocity_1, joint_velocity_2; + + state1.copyJointGroupVelocities(joint_group_name, joint_velocity_1); + state2.copyJointGroupVelocities(joint_group_name, joint_velocity_2); + + if ((joint_velocity_1 - joint_velocity_2).norm() > epsilon) + { + ROS_DEBUG_STREAM("Joint velocities of the two states are different. state1: " << joint_velocity_1 + << " state2: " << joint_velocity_2); + return false; + } + + Eigen::VectorXd joint_acc_1, joint_acc_2; + + state1.copyJointGroupAccelerations(joint_group_name, joint_acc_1); + state2.copyJointGroupAccelerations(joint_group_name, joint_acc_2); + + if ((joint_acc_1 - joint_acc_2).norm() > epsilon) + { + ROS_DEBUG_STREAM("Joint accelerations of the two states are different. state1: " << joint_acc_1 + << " state2: " << joint_acc_2); + return false; + } + + return true; +} + +bool pilz_industrial_motion_planner::isRobotStateStationary(const moveit::core::RobotState& state, + const std::string& group, double EPSILON) +{ + Eigen::VectorXd joint_variable; + state.copyJointGroupVelocities(group, joint_variable); + if (joint_variable.norm() > EPSILON) + { + ROS_DEBUG("Joint velocities are not zero."); + return false; + } + state.copyJointGroupAccelerations(group, joint_variable); + if (joint_variable.norm() > EPSILON) + { + ROS_DEBUG("Joint accelerations are not zero."); + return false; + } + return true; +} + +bool pilz_industrial_motion_planner::linearSearchIntersectionPoint(const std::string& link_name, + const Eigen::Vector3d& center_position, + const double& r, + const robot_trajectory::RobotTrajectoryPtr& traj, + bool inverseOrder, std::size_t& index) +{ + ROS_DEBUG("Start linear search for intersection point."); + + const size_t waypoint_num = traj->getWayPointCount(); + + if (inverseOrder) + { + for (size_t i = waypoint_num - 1; i > 0; --i) + { + if (intersectionFound(center_position, traj->getWayPointPtr(i)->getFrameTransform(link_name).translation(), + traj->getWayPointPtr(i - 1)->getFrameTransform(link_name).translation(), r)) + { + index = i; + return true; + } + } + } + else + { + for (size_t i = 0; i < waypoint_num - 1; ++i) + { + if (intersectionFound(center_position, traj->getWayPointPtr(i)->getFrameTransform(link_name).translation(), + traj->getWayPointPtr(i + 1)->getFrameTransform(link_name).translation(), r)) + { + index = i; + return true; + } + } + } + + return false; +} + +bool pilz_industrial_motion_planner::intersectionFound(const Eigen::Vector3d& p_center, + const Eigen::Vector3d& p_current, const Eigen::Vector3d& p_next, + const double& r) +{ + return ((p_current - p_center).norm() <= r) && ((p_next - p_center).norm() >= r); +} + +bool pilz_industrial_motion_planner::isStateColliding(const bool test_for_self_collision, + const moveit::core::RobotModelConstPtr& robot_model, + robot_state::RobotState* rstate, + const robot_state::JointModelGroup* const group, + const double* const ik_solution) +{ + if (!test_for_self_collision) + { + return true; + } + + rstate->setJointGroupPositions(group, ik_solution); + rstate->update(); + collision_detection::CollisionRequest collision_req; + collision_req.group_name = group->getName(); + collision_detection::CollisionResult collision_res; + planning_scene::PlanningScene(robot_model).checkSelfCollision(collision_req, collision_res, *rstate); + + return !collision_res.collision; +} + +void normalizeQuaternion(geometry_msgs::Quaternion& quat) +{ + tf2::Quaternion q; + tf2::convert(quat, q); + quat = tf2::toMsg(q.normalize()); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator.cpp b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator.cpp new file mode 100644 index 0000000000..8069004d2c --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator.cpp @@ -0,0 +1,332 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/trajectory_generator.h" + +#include + +#include +#include +#include +#include + +#include "pilz_industrial_motion_planner/limits_container.h" + +namespace pilz_industrial_motion_planner +{ +void TrajectoryGenerator::cmdSpecificRequestValidation(const planning_interface::MotionPlanRequest& /*req*/) const +{ + // Empty implementation, in case the derived class does not want + // to provide a command specific request validation. +} + +void TrajectoryGenerator::checkVelocityScaling(const double& scaling_factor) +{ + if (!isScalingFactorValid(scaling_factor)) + { + std::ostringstream os; + os << "Velocity scaling not in range [" << MIN_SCALING_FACTOR << ", " << MAX_SCALING_FACTOR << "], " + << "actual value is: " << scaling_factor; + throw VelocityScalingIncorrect(os.str()); + } +} + +void TrajectoryGenerator::checkAccelerationScaling(const double& scaling_factor) +{ + if (!isScalingFactorValid(scaling_factor)) + { + std::ostringstream os; + os << "Acceleration scaling not in range [" << MIN_SCALING_FACTOR << ", " << MAX_SCALING_FACTOR << "], " + << "actual value is: " << scaling_factor; + throw AccelerationScalingIncorrect(os.str()); + } +} + +void TrajectoryGenerator::checkForValidGroupName(const std::string& group_name) const +{ + if (!robot_model_->hasJointModelGroup(group_name)) + { + std::ostringstream os; + os << "Unknown planning group: " << group_name; + throw UnknownPlanningGroup(os.str()); + } +} + +void TrajectoryGenerator::checkStartState(const moveit_msgs::RobotState& start_state) const +{ + if (start_state.joint_state.name.empty()) + { + throw NoJointNamesInStartState("No joint names for state state given"); + } + + if (start_state.joint_state.name.size() != start_state.joint_state.position.size()) + { + throw SizeMismatchInStartState("Joint state name and position do not match in start state"); + } + + if (!planner_limits_.getJointLimitContainer().verifyPositionLimits(start_state.joint_state.name, + start_state.joint_state.position)) + { + throw JointsOfStartStateOutOfRange("Joint state out of range in start state"); + } + + // does not allow start velocity + if (!std::all_of(start_state.joint_state.velocity.begin(), start_state.joint_state.velocity.end(), + [this](double v) { return std::fabs(v) < this->VELOCITY_TOLERANCE; })) + { + throw NonZeroVelocityInStartState("Trajectory Generator does not allow non-zero start velocity"); + } +} + +void TrajectoryGenerator::checkJointGoalConstraint(const moveit_msgs::Constraints& constraint, + const std::vector& expected_joint_names, + const std::string& group_name) const +{ + for (auto const& joint_constraint : constraint.joint_constraints) + { + const std::string& curr_joint_name{ joint_constraint.joint_name }; + if (std::find(expected_joint_names.cbegin(), expected_joint_names.cend(), curr_joint_name) == + expected_joint_names.cend()) + { + std::ostringstream os; + os << "Cannot find joint \"" << curr_joint_name << "\" from start state in goal constraint"; + throw StartStateGoalStateMismatch(os.str()); + } + + if (!robot_model_->getJointModelGroup(group_name)->hasJointModel(curr_joint_name)) + { + std::ostringstream os; + os << "Joint \"" << curr_joint_name << "\" does not belong to group \"" << group_name << "\""; + throw JointConstraintDoesNotBelongToGroup(os.str()); + } + + if (!planner_limits_.getJointLimitContainer().verifyPositionLimit(curr_joint_name, joint_constraint.position)) + { + std::ostringstream os; + os << "Joint \"" << curr_joint_name << "\" violates joint limits in goal constraints"; + throw JointsOfGoalOutOfRange(os.str()); + } + } +} + +void TrajectoryGenerator::checkCartesianGoalConstraint(const moveit_msgs::Constraints& constraint, + const std::string& group_name) const +{ + assert(constraint.position_constraints.size() == 1); + assert(constraint.orientation_constraints.size() == 1); + const moveit_msgs::PositionConstraint& pos_constraint{ constraint.position_constraints.front() }; + const moveit_msgs::OrientationConstraint& ori_constraint{ constraint.orientation_constraints.front() }; + + if (pos_constraint.link_name.empty()) + { + throw PositionConstraintNameMissing("Link name of position constraint missing"); + } + + if (ori_constraint.link_name.empty()) + { + throw OrientationConstraintNameMissing("Link name of orientation constraint missing"); + } + + if (pos_constraint.link_name != ori_constraint.link_name) + { + std::ostringstream os; + os << "Position and orientation constraint name do not match" + << "(Position constraint name: \"" << pos_constraint.link_name << "\" | Orientation constraint name: \"" + << ori_constraint.link_name << "\")"; + throw PositionOrientationConstraintNameMismatch(os.str()); + } + + if (!robot_model_->getJointModelGroup(group_name)->canSetStateFromIK(pos_constraint.link_name)) + { + std::ostringstream os; + os << "No IK solver available for link: \"" << pos_constraint.link_name << "\""; + throw NoIKSolverAvailable(os.str()); + } + + if (pos_constraint.constraint_region.primitive_poses.empty()) + { + throw NoPrimitivePoseGiven("Primitive pose in position constraints of goal missing"); + } +} + +void TrajectoryGenerator::checkGoalConstraints( + const moveit_msgs::MotionPlanRequest::_goal_constraints_type& goal_constraints, + const std::vector& expected_joint_names, const std::string& group_name) const +{ + if (goal_constraints.size() != 1) + { + std::ostringstream os; + os << "Exaclty one goal constraint required, but " << goal_constraints.size() << " goal constraints given"; + throw NotExactlyOneGoalConstraintGiven(os.str()); + } + + const moveit_msgs::Constraints& goal_con{ goal_constraints.front() }; + if (!isOnlyOneGoalTypeGiven(goal_con)) + { + throw OnlyOneGoalTypeAllowed("Only cartesian XOR joint goal allowed"); + } + + if (isJointGoalGiven(goal_con)) + { + checkJointGoalConstraint(goal_con, expected_joint_names, group_name); + } + else + { + checkCartesianGoalConstraint(goal_con, group_name); + } +} + +void TrajectoryGenerator::validateRequest(const planning_interface::MotionPlanRequest& req) const +{ + checkVelocityScaling(req.max_velocity_scaling_factor); + checkAccelerationScaling(req.max_acceleration_scaling_factor); + checkForValidGroupName(req.group_name); + checkStartState(req.start_state); + checkGoalConstraints(req.goal_constraints, req.start_state.joint_state.name, req.group_name); +} + +void TrajectoryGenerator::convertToRobotTrajectory(const trajectory_msgs::JointTrajectory& joint_trajectory, + const moveit_msgs::RobotState& start_state, + robot_trajectory::RobotTrajectory& robot_trajectory) const +{ + moveit::core::RobotState start_rs(robot_model_); + start_rs.setToDefaultValues(); + moveit::core::robotStateMsgToRobotState(start_state, start_rs, false); + robot_trajectory.setRobotTrajectoryMsg(start_rs, joint_trajectory); +} + +void TrajectoryGenerator::setSuccessResponse(const std::string& group_name, const moveit_msgs::RobotState& start_state, + const trajectory_msgs::JointTrajectory& joint_trajectory, + const ros::Time& planning_start, + planning_interface::MotionPlanResponse& res) const +{ + robot_trajectory::RobotTrajectoryPtr rt(new robot_trajectory::RobotTrajectory(robot_model_, group_name)); + convertToRobotTrajectory(joint_trajectory, start_state, *rt); + + res.trajectory_ = rt; + res.error_code_.val = moveit_msgs::MoveItErrorCodes::SUCCESS; + res.planning_time_ = (ros::Time::now() - planning_start).toSec(); +} + +void TrajectoryGenerator::setFailureResponse(const ros::Time& planning_start, + planning_interface::MotionPlanResponse& res) const +{ + if (res.trajectory_) + { + res.trajectory_->clear(); + } + res.planning_time_ = (ros::Time::now() - planning_start).toSec(); +} + +std::unique_ptr +TrajectoryGenerator::cartesianTrapVelocityProfile(const double& max_velocity_scaling_factor, + const double& max_acceleration_scaling_factor, + const std::unique_ptr& path) const +{ + std::unique_ptr vp_trans(new KDL::VelocityProfile_Trap( + max_velocity_scaling_factor * planner_limits_.getCartesianLimits().getMaxTranslationalVelocity(), + max_acceleration_scaling_factor * planner_limits_.getCartesianLimits().getMaxTranslationalAcceleration())); + + if (path->PathLength() > std::numeric_limits::epsilon()) // avoid division by zero + { + vp_trans->SetProfile(0, path->PathLength()); + } + else + { + vp_trans->SetProfile(0, std::numeric_limits::epsilon()); + } + return vp_trans; +} + +bool TrajectoryGenerator::generate(const planning_interface::MotionPlanRequest& req, + planning_interface::MotionPlanResponse& res, double sampling_time) +{ + ROS_INFO_STREAM("Generating " << req.planner_id << " trajectory..."); + ros::Time planning_begin = ros::Time::now(); + + try + { + validateRequest(req); + } + catch (const MoveItErrorCodeException& ex) + { + ROS_ERROR_STREAM(ex.what()); + res.error_code_.val = ex.getErrorCode(); + setFailureResponse(planning_begin, res); + return false; + } + + try + { + cmdSpecificRequestValidation(req); + } + catch (const MoveItErrorCodeException& ex) + { + ROS_ERROR_STREAM(ex.what()); + res.error_code_.val = ex.getErrorCode(); + setFailureResponse(planning_begin, res); + return false; + } + + MotionPlanInfo plan_info; + try + { + extractMotionPlanInfo(req, plan_info); + } + catch (const MoveItErrorCodeException& ex) + { + ROS_ERROR_STREAM(ex.what()); + res.error_code_.val = ex.getErrorCode(); + setFailureResponse(planning_begin, res); + return false; + } + + trajectory_msgs::JointTrajectory joint_trajectory; + try + { + plan(req, plan_info, sampling_time, joint_trajectory); + } + catch (const MoveItErrorCodeException& ex) + { + ROS_ERROR_STREAM(ex.what()); + res.error_code_.val = ex.getErrorCode(); + setFailureResponse(planning_begin, res); + return false; + } + + setSuccessResponse(req.group_name, req.start_state, joint_trajectory, planning_begin, res); + return true; +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_circ.cpp b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_circ.cpp new file mode 100644 index 0000000000..6e1e57f0d1 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_circ.cpp @@ -0,0 +1,270 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/trajectory_generator_circ.h" +#include "pilz_industrial_motion_planner/path_circle_generator.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace pilz_industrial_motion_planner +{ +TrajectoryGeneratorCIRC::TrajectoryGeneratorCIRC(const moveit::core::RobotModelConstPtr& robot_model, + const LimitsContainer& planner_limits) + : TrajectoryGenerator::TrajectoryGenerator(robot_model, planner_limits) +{ + if (!planner_limits_.hasFullCartesianLimits()) + { + throw TrajectoryGeneratorInvalidLimitsException( + "Cartesian limits are not fully set for CIRC trajectory generator."); + } +} + +void TrajectoryGeneratorCIRC::cmdSpecificRequestValidation(const planning_interface::MotionPlanRequest& req) const +{ + if (!(req.path_constraints.name == "interim" || req.path_constraints.name == "center")) + { + std::ostringstream os; + os << "No path constraint named \"interim\" or \"center\" found (found " + "unknown constraint: " + << "\"req.path_constraints.name\"" + << " instead)"; + throw UnknownPathConstraintName(os.str()); + } + + if (req.path_constraints.position_constraints.size() != 1) + { + throw NoPositionConstraints("CIRC trajectory generator needs valid a position constraint"); + } + + if (req.path_constraints.position_constraints.front().constraint_region.primitive_poses.size() != 1) + { + throw NoPrimitivePose("CIRC trajectory generator needs valid a primitive pose"); + } +} + +void TrajectoryGeneratorCIRC::extractMotionPlanInfo(const planning_interface::MotionPlanRequest& req, + TrajectoryGenerator::MotionPlanInfo& info) const +{ + ROS_DEBUG("Extract necessary information from motion plan request."); + + info.group_name = req.group_name; + std::string frame_id{ robot_model_->getModelFrame() }; + + // goal given in joint space + if (!req.goal_constraints.front().joint_constraints.empty()) + { + // TODO: link name from goal constraint and path constraint + info.link_name = req.path_constraints.position_constraints.front().link_name; + if (!robot_model_->hasLinkModel(info.link_name)) + { + throw UnknownLinkNameOfAuxiliaryPoint("Unknown link name of CIRC auxiliary point"); + } + + if (req.goal_constraints.front().joint_constraints.size() != + robot_model_->getJointModelGroup(req.group_name)->getActiveJointModelNames().size()) + { + std::ostringstream os; + os << "Number of joint constraint = " << req.goal_constraints.front().joint_constraints.size() + << " not equal to active joints of group = " + << robot_model_->getJointModelGroup(req.group_name)->getActiveJointModelNames().size(); + throw NumberOfConstraintsMismatch(os.str()); + } + + // initializing all joints of the model + for (const auto& joint_name : robot_model_->getVariableNames()) + { + info.goal_joint_position[joint_name] = 0; + } + + for (const auto& joint_item : req.goal_constraints.front().joint_constraints) + { + info.goal_joint_position[joint_item.joint_name] = joint_item.position; + } + + computeLinkFK(robot_model_, info.link_name, info.goal_joint_position, info.goal_pose); + } + // goal given in Cartesian space + else + { + info.link_name = req.goal_constraints.front().position_constraints.front().link_name; + if (req.goal_constraints.front().position_constraints.front().header.frame_id.empty() || + req.goal_constraints.front().orientation_constraints.front().header.frame_id.empty()) + { + ROS_WARN("Frame id is not set in position/orientation constraints of " + "goal. Use model frame as default"); + frame_id = robot_model_->getModelFrame(); + } + else + { + frame_id = req.goal_constraints.front().position_constraints.front().header.frame_id; + } + geometry_msgs::Pose goal_pose_msg; + goal_pose_msg.position = + req.goal_constraints.front().position_constraints.front().constraint_region.primitive_poses.front().position; + goal_pose_msg.orientation = req.goal_constraints.front().orientation_constraints.front().orientation; + normalizeQuaternion(goal_pose_msg.orientation); + tf2::convert(goal_pose_msg, info.goal_pose); + } + + assert(req.start_state.joint_state.name.size() == req.start_state.joint_state.position.size()); + for (const auto& joint_name : robot_model_->getJointModelGroup(req.group_name)->getActiveJointModelNames()) + { + auto it{ std::find(req.start_state.joint_state.name.cbegin(), req.start_state.joint_state.name.cend(), joint_name) }; + if (it == req.start_state.joint_state.name.cend()) + { + std::ostringstream os; + os << "Could not find joint \"" << joint_name << "\" of group \"" << req.group_name + << "\" in start state of request"; + throw CircJointMissingInStartState(os.str()); + } + size_t index = it - req.start_state.joint_state.name.cbegin(); + info.start_joint_position[joint_name] = req.start_state.joint_state.position[index]; + } + + computeLinkFK(robot_model_, info.link_name, info.start_joint_position, info.start_pose); + + // check goal pose ik before Cartesian motion plan starts + std::map ik_solution; + if (!computePoseIK(robot_model_, info.group_name, info.link_name, info.goal_pose, frame_id, info.start_joint_position, + ik_solution)) + { + // LCOV_EXCL_START + std::ostringstream os; + os << "Failed to compute inverse kinematics for link: " << info.link_name << " of goal pose"; + throw CircInverseForGoalIncalculable(os.str()); + // LCOV_EXCL_STOP // not able to trigger here since lots of checks before + // are in place + } + + Eigen::Vector3d circ_path_point; + tf2::convert(req.path_constraints.position_constraints.front().constraint_region.primitive_poses.front().position, + circ_path_point); + + info.circ_path_point.first = req.path_constraints.name; + info.circ_path_point.second = circ_path_point; +} + +void TrajectoryGeneratorCIRC::plan(const planning_interface::MotionPlanRequest& req, const MotionPlanInfo& plan_info, + const double& sampling_time, trajectory_msgs::JointTrajectory& joint_trajectory) +{ + std::unique_ptr cart_path(setPathCIRC(plan_info)); + std::unique_ptr vel_profile( + cartesianTrapVelocityProfile(req.max_velocity_scaling_factor, req.max_acceleration_scaling_factor, cart_path)); + + // combine path and velocity profile into Cartesian trajectory + // with the third parameter set to false, KDL::Trajectory_Segment does not + // take + // the ownship of Path and Velocity Profile + KDL::Trajectory_Segment cart_trajectory(cart_path.get(), vel_profile.get(), false); + + moveit_msgs::MoveItErrorCodes error_code; + // sample the Cartesian trajectory and compute joint trajectory using inverse + // kinematics + if (!generateJointTrajectory(robot_model_, planner_limits_.getJointLimitContainer(), cart_trajectory, + plan_info.group_name, plan_info.link_name, plan_info.start_joint_position, sampling_time, + joint_trajectory, error_code)) + { + throw CircTrajectoryConversionFailure("Failed to generate valid joint trajectory from the Cartesian path", + error_code.val); + } +} + +std::unique_ptr TrajectoryGeneratorCIRC::setPathCIRC(const MotionPlanInfo& info) const +{ + ROS_DEBUG("Set Cartesian path for CIRC command."); + + KDL::Frame start_pose, goal_pose; + tf::transformEigenToKDL(info.start_pose, start_pose); + tf::transformEigenToKDL(info.goal_pose, goal_pose); + + KDL::Vector path_point; + tf::vectorEigenToKDL(info.circ_path_point.second, path_point); + + // pass the ratio of translational by rotational velocity as equivalent radius + // to get a trajectory with rotational speed, if no (or very little) + // translational distance + // The KDL::Path implementation chooses the motion with the longer duration + // (translation vs. rotation) + // and uses eqradius as scaling factor between the distances. + double eqradius = planner_limits_.getCartesianLimits().getMaxTranslationalVelocity() / + planner_limits_.getCartesianLimits().getMaxRotationalVelocity(); + + try + { + if (info.circ_path_point.first == "center") + { + return PathCircleGenerator::circleFromCenter(start_pose, goal_pose, path_point, eqradius); + } + else // if (info.circ_path_point.first == "interim") + { + return PathCircleGenerator::circleFromInterim(start_pose, goal_pose, path_point, eqradius); + } + } + catch (KDL::Error_MotionPlanning_Circle_No_Plane& e) + { + std::ostringstream os; + os << "Failed to create path object for circle." << e.Description(); + throw CircleNoPlane(os.str()); + } + catch (KDL::Error_MotionPlanning_Circle_ToSmall& e) + { + std::ostringstream os; + os << "Failed to create path object for circle." << e.Description(); + throw CircleToSmall(os.str()); + } + catch (ErrorMotionPlanningCenterPointDifferentRadius& e) + { + std::ostringstream os; + os << "Failed to create path object for circle." << e.Description(); + throw CenterPointDifferentRadius(os.str()); + } + + return nullptr; +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_lin.cpp b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_lin.cpp new file mode 100644 index 0000000000..a91c6e943a --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_lin.cpp @@ -0,0 +1,203 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/trajectory_generator_lin.h" + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +namespace pilz_industrial_motion_planner +{ +TrajectoryGeneratorLIN::TrajectoryGeneratorLIN(const moveit::core::RobotModelConstPtr& robot_model, + const LimitsContainer& planner_limits) + : TrajectoryGenerator::TrajectoryGenerator(robot_model, planner_limits) +{ + if (!planner_limits_.hasFullCartesianLimits()) + { + ROS_ERROR("Cartesian limits not set for LIN trajectory generator."); + throw TrajectoryGeneratorInvalidLimitsException("Cartesian limits are not fully set for LIN trajectory generator."); + } +} + +void TrajectoryGeneratorLIN::extractMotionPlanInfo(const planning_interface::MotionPlanRequest& req, + TrajectoryGenerator::MotionPlanInfo& info) const +{ + ROS_DEBUG("Extract necessary information from motion plan request."); + + info.group_name = req.group_name; + std::string frame_id{ robot_model_->getModelFrame() }; + + // goal given in joint space + if (!req.goal_constraints.front().joint_constraints.empty()) + { + info.link_name = robot_model_->getJointModelGroup(req.group_name)->getSolverInstance()->getTipFrame(); + + if (req.goal_constraints.front().joint_constraints.size() != + robot_model_->getJointModelGroup(req.group_name)->getActiveJointModelNames().size()) + { + std::ostringstream os; + os << "Number of joints in goal does not match number of joints of group " + "(Number joints goal: " + << req.goal_constraints.front().joint_constraints.size() << " | Number of joints of group: " + << robot_model_->getJointModelGroup(req.group_name)->getActiveJointModelNames().size() << ")"; + throw JointNumberMismatch(os.str()); + } + // initializing all joints of the model + for (const auto& joint_name : robot_model_->getVariableNames()) + { + info.goal_joint_position[joint_name] = 0; + } + + for (const auto& joint_item : req.goal_constraints.front().joint_constraints) + { + info.goal_joint_position[joint_item.joint_name] = joint_item.position; + } + + // Ignored return value because at this point the function should always + // return 'true'. + computeLinkFK(robot_model_, info.link_name, info.goal_joint_position, info.goal_pose); + } + // goal given in Cartesian space + else + { + info.link_name = req.goal_constraints.front().position_constraints.front().link_name; + if (req.goal_constraints.front().position_constraints.front().header.frame_id.empty() || + req.goal_constraints.front().orientation_constraints.front().header.frame_id.empty()) + { + ROS_WARN("Frame id is not set in position/orientation constraints of " + "goal. Use model frame as default"); + frame_id = robot_model_->getModelFrame(); + } + else + { + frame_id = req.goal_constraints.front().position_constraints.front().header.frame_id; + } + geometry_msgs::Pose goal_pose_msg; + goal_pose_msg.position = + req.goal_constraints.front().position_constraints.front().constraint_region.primitive_poses.front().position; + goal_pose_msg.orientation = req.goal_constraints.front().orientation_constraints.front().orientation; + normalizeQuaternion(goal_pose_msg.orientation); + tf2::convert(goal_pose_msg, info.goal_pose); + } + + assert(req.start_state.joint_state.name.size() == req.start_state.joint_state.position.size()); + for (const auto& joint_name : robot_model_->getJointModelGroup(req.group_name)->getActiveJointModelNames()) + { + auto it{ std::find(req.start_state.joint_state.name.cbegin(), req.start_state.joint_state.name.cend(), joint_name) }; + if (it == req.start_state.joint_state.name.cend()) + { + std::ostringstream os; + os << "Could not find joint \"" << joint_name << "\" of group \"" << req.group_name + << "\" in start state of request"; + throw LinJointMissingInStartState(os.str()); + } + size_t index = it - req.start_state.joint_state.name.cbegin(); + info.start_joint_position[joint_name] = req.start_state.joint_state.position[index]; + } + + // Ignored return value because at this point the function should always + // return 'true'. + computeLinkFK(robot_model_, info.link_name, info.start_joint_position, info.start_pose); + + // check goal pose ik before Cartesian motion plan starts + std::map ik_solution; + if (!computePoseIK(robot_model_, info.group_name, info.link_name, info.goal_pose, frame_id, info.start_joint_position, + ik_solution)) + { + std::ostringstream os; + os << "Failed to compute inverse kinematics for link: " << info.link_name << " of goal pose"; + throw LinInverseForGoalIncalculable(os.str()); + } +} + +void TrajectoryGeneratorLIN::plan(const planning_interface::MotionPlanRequest& req, const MotionPlanInfo& plan_info, + const double& sampling_time, trajectory_msgs::JointTrajectory& joint_trajectory) +{ + // create Cartesian path for lin + std::unique_ptr path(setPathLIN(plan_info.start_pose, plan_info.goal_pose)); + + // create velocity profile + std::unique_ptr vp( + cartesianTrapVelocityProfile(req.max_velocity_scaling_factor, req.max_acceleration_scaling_factor, path)); + + // combine path and velocity profile into Cartesian trajectory + // with the third parameter set to false, KDL::Trajectory_Segment does not + // take + // the ownship of Path and Velocity Profile + KDL::Trajectory_Segment cart_trajectory(path.get(), vp.get(), false); + + moveit_msgs::MoveItErrorCodes error_code; + // sample the Cartesian trajectory and compute joint trajectory using inverse + // kinematics + if (!generateJointTrajectory(robot_model_, planner_limits_.getJointLimitContainer(), cart_trajectory, + plan_info.group_name, plan_info.link_name, plan_info.start_joint_position, sampling_time, + joint_trajectory, error_code)) + { + std::ostringstream os; + os << "Failed to generate valid joint trajectory from the Cartesian path"; + throw LinTrajectoryConversionFailure(os.str(), error_code.val); + } +} + +std::unique_ptr TrajectoryGeneratorLIN::setPathLIN(const Eigen::Affine3d& start_pose, + const Eigen::Affine3d& goal_pose) const +{ + ROS_DEBUG("Set Cartesian path for LIN command."); + + KDL::Frame kdl_start_pose, kdl_goal_pose; + tf::transformEigenToKDL(start_pose, kdl_start_pose); + tf::transformEigenToKDL(goal_pose, kdl_goal_pose); + double eqradius = planner_limits_.getCartesianLimits().getMaxTranslationalVelocity() / + planner_limits_.getCartesianLimits().getMaxRotationalVelocity(); + KDL::RotationalInterpolation* rot_interpo = new KDL::RotationalInterpolation_SingleAxis(); + + return std::unique_ptr(new KDL::Path_Line(kdl_start_pose, kdl_goal_pose, rot_interpo, eqradius, true)); +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_ptp.cpp b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_ptp.cpp new file mode 100644 index 0000000000..45b2157e4a --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_ptp.cpp @@ -0,0 +1,261 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/trajectory_generator_ptp.h" +#include "eigen_conversions/eigen_msg.h" +#include "moveit/robot_state/conversions.h" +#include "ros/ros.h" + +#include +#include + +#include +#include +#include + +namespace pilz_industrial_motion_planner +{ +TrajectoryGeneratorPTP::TrajectoryGeneratorPTP(const robot_model::RobotModelConstPtr& robot_model, + const LimitsContainer& planner_limits) + : TrajectoryGenerator::TrajectoryGenerator(robot_model, planner_limits) +{ + if (!planner_limits_.hasJointLimits()) + { + throw TrajectoryGeneratorInvalidLimitsException("joint limit not set"); + } + + joint_limits_ = planner_limits_.getJointLimitContainer(); + + // collect most strict joint limits for each group in robot model + for (const auto& jmg : robot_model->getJointModelGroups()) + { + JointLimit most_strict_limit = joint_limits_.getCommonLimit(jmg->getActiveJointModelNames()); + + if (!most_strict_limit.has_velocity_limits) + { + ROS_ERROR_STREAM("velocity limit not set for group " << jmg->getName()); + throw TrajectoryGeneratorInvalidLimitsException("velocity limit not set for group " + jmg->getName()); + } + if (!most_strict_limit.has_acceleration_limits) + { + ROS_ERROR_STREAM("acceleration limit not set for group " << jmg->getName()); + throw TrajectoryGeneratorInvalidLimitsException("acceleration limit not set for group " + jmg->getName()); + } + if (!most_strict_limit.has_deceleration_limits) + { + ROS_ERROR_STREAM("deceleration limit not set for group " << jmg->getName()); + throw TrajectoryGeneratorInvalidLimitsException("deceleration limit not set for group " + jmg->getName()); + } + + most_strict_limits_.insert(std::pair(jmg->getName(), most_strict_limit)); + } + + ROS_INFO("Initialized Point-to-Point Trajectory Generator."); +} + +void TrajectoryGeneratorPTP::planPTP(const std::map& start_pos, + const std::map& goal_pos, + trajectory_msgs::JointTrajectory& joint_trajectory, const std::string& group_name, + const double& velocity_scaling_factor, const double& acceleration_scaling_factor, + const double& sampling_time) +{ + // initialize joint names + for (const auto& item : goal_pos) + { + joint_trajectory.joint_names.push_back(item.first); + } + + // check if goal already reached + bool goal_reached = true; + for (auto const& goal : goal_pos) + { + if (fabs(start_pos.at(goal.first) - goal.second) >= MIN_MOVEMENT) + { + goal_reached = false; + break; + } + } + if (goal_reached) + { + ROS_INFO_STREAM("Goal already reached, set one goal point explicitly."); + if (joint_trajectory.points.empty()) + { + trajectory_msgs::JointTrajectoryPoint point; + point.time_from_start = ros::Duration(sampling_time); + for (const std::string& joint_name : joint_trajectory.joint_names) + { + point.positions.push_back(start_pos.at(joint_name)); + point.velocities.push_back(0); + point.accelerations.push_back(0); + } + joint_trajectory.points.push_back(point); + } + return; + } + + // compute the fastest trajectory and choose the slowest joint as leading axis + std::string leading_axis = joint_trajectory.joint_names.front(); + double max_duration = -1.0; + + std::map velocity_profile; + for (const auto& joint_name : joint_trajectory.joint_names) + { + // create vecocity profile if necessary + velocity_profile.insert(std::make_pair( + joint_name, + VelocityProfileATrap(velocity_scaling_factor * most_strict_limits_.at(group_name).max_velocity, + acceleration_scaling_factor * most_strict_limits_.at(group_name).max_acceleration, + acceleration_scaling_factor * most_strict_limits_.at(group_name).max_deceleration))); + + velocity_profile.at(joint_name).SetProfile(start_pos.at(joint_name), goal_pos.at(joint_name)); + if (velocity_profile.at(joint_name).Duration() > max_duration) + { + max_duration = velocity_profile.at(joint_name).Duration(); + leading_axis = joint_name; + } + } + + // Full Synchronization + // This should only work if all axes have same max_vel, max_acc, max_dec + // values + // reset the velocity profile for other joints + double acc_time = velocity_profile.at(leading_axis).firstPhaseDuration(); + double const_time = velocity_profile.at(leading_axis).secondPhaseDuration(); + double dec_time = velocity_profile.at(leading_axis).thirdPhaseDuration(); + + for (const auto& joint_name : joint_trajectory.joint_names) + { + if (joint_name != leading_axis) + { + // make full synchronization + // causes the program to terminate if acc_time<=0 or dec_time<=0 (should + // be prevented by goal_reached block above) + // by using the most strict limit, the following should always return true + if (!velocity_profile.at(joint_name) + .setProfileAllDurations(start_pos.at(joint_name), goal_pos.at(joint_name), acc_time, const_time, + dec_time)) + // LCOV_EXCL_START + { + std::stringstream error_str; + error_str << "TrajectoryGeneratorPTP::planPTP(): Can not synchronize " + "velocity profile of axis " + << joint_name << " with leading axis " << leading_axis; + throw PtpVelocityProfileSyncFailed(error_str.str()); + } + // LCOV_EXCL_STOP + } + } + + // first generate the time samples + std::vector time_samples; + for (double t_sample = 0.0; t_sample < max_duration; t_sample += sampling_time) + { + time_samples.push_back(t_sample); + } + // add last time + time_samples.push_back(max_duration); + + // construct joint trajectory point + for (double time_stamp : time_samples) + { + trajectory_msgs::JointTrajectoryPoint point; + point.time_from_start = ros::Duration(time_stamp); + for (std::string& joint_name : joint_trajectory.joint_names) + { + point.positions.push_back(velocity_profile.at(joint_name).Pos(time_stamp)); + point.velocities.push_back(velocity_profile.at(joint_name).Vel(time_stamp)); + point.accelerations.push_back(velocity_profile.at(joint_name).Acc(time_stamp)); + } + joint_trajectory.points.push_back(point); + } + + // Set last point velocity and acceleration to zero + std::fill(joint_trajectory.points.back().velocities.begin(), joint_trajectory.points.back().velocities.end(), 0.0); + std::fill(joint_trajectory.points.back().accelerations.begin(), joint_trajectory.points.back().accelerations.end(), + 0.0); +} + +void TrajectoryGeneratorPTP::extractMotionPlanInfo(const planning_interface::MotionPlanRequest& req, + MotionPlanInfo& info) const +{ + info.group_name = req.group_name; + + // extract start state information + info.start_joint_position.clear(); + for (std::size_t i = 0; i < req.start_state.joint_state.name.size(); ++i) + { + info.start_joint_position[req.start_state.joint_state.name[i]] = req.start_state.joint_state.position[i]; + } + + // extract goal + info.goal_joint_position.clear(); + if (!req.goal_constraints.at(0).joint_constraints.empty()) + { + for (const auto& joint_constraint : req.goal_constraints.at(0).joint_constraints) + { + info.goal_joint_position[joint_constraint.joint_name] = joint_constraint.position; + } + } + // slove the ik + else + { + geometry_msgs::Point p = + req.goal_constraints.at(0).position_constraints.at(0).constraint_region.primitive_poses.at(0).position; + p.x -= req.goal_constraints.at(0).position_constraints.at(0).target_point_offset.x; + p.y -= req.goal_constraints.at(0).position_constraints.at(0).target_point_offset.y; + p.z -= req.goal_constraints.at(0).position_constraints.at(0).target_point_offset.z; + + geometry_msgs::Pose pose; + pose.position = p; + pose.orientation = req.goal_constraints.at(0).orientation_constraints.at(0).orientation; + Eigen::Isometry3d pose_eigen; + normalizeQuaternion(pose.orientation); + tf2::convert(pose, pose_eigen); + if (!computePoseIK(robot_model_, req.group_name, req.goal_constraints.at(0).position_constraints.at(0).link_name, + pose_eigen, robot_model_->getModelFrame(), info.start_joint_position, info.goal_joint_position)) + { + throw PtpNoIkSolutionForGoalPose("No IK solution for goal pose"); + } + } +} + +void TrajectoryGeneratorPTP::plan(const planning_interface::MotionPlanRequest& req, const MotionPlanInfo& plan_info, + const double& sampling_time, trajectory_msgs::JointTrajectory& joint_trajectory) +{ + // plan the ptp trajectory + planPTP(plan_info.start_joint_position, plan_info.goal_joint_position, joint_trajectory, plan_info.group_name, + req.max_velocity_scaling_factor, req.max_acceleration_scaling_factor, sampling_time); +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/src/velocity_profile_atrap.cpp b/moveit_planners/pilz_industrial_motion_planner/src/velocity_profile_atrap.cpp new file mode 100644 index 0000000000..f19da41b8d --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/src/velocity_profile_atrap.cpp @@ -0,0 +1,451 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner/velocity_profile_atrap.h" + +namespace pilz_industrial_motion_planner +{ +VelocityProfileATrap::VelocityProfileATrap(double max_vel, double max_acc, double max_dec) + : max_vel_(fabs(max_vel)) + , max_acc_(fabs(max_acc)) + , max_dec_(fabs(max_dec)) + , start_pos_(0) + , end_pos_(0) + , start_vel_(0) + , a1_(0) + , a2_(0) + , a3_(0) + , b1_(0) + , b2_(0) + , b3_(0) + , c1_(0) + , c2_(0) + , c3_(0) + , t_a_(0) + , t_b_(0) + , t_c_(0) +{ +} + +void VelocityProfileATrap::SetProfile(double pos1, double pos2) +{ + start_pos_ = pos1; + end_pos_ = pos2; + start_vel_ = 0.0; + + if (start_pos_ == end_pos_) + { + // goal already reached, set everything to zero + setEmptyProfile(); + return; + } + else + { + // get the sign + double s = ((end_pos_ - start_pos_) > 0.0) - ((end_pos_ - start_pos_) < 0.0); + + double dis = fabs(end_pos_ - start_pos_); + double min_dis_max_vel = 0.5 * max_vel_ * max_vel_ / max_acc_ + 0.5 * max_vel_ * max_vel_ / max_dec_; + + // max_vel can be reached + if (dis > min_dis_max_vel) + { + // acceleration phase + a1_ = start_pos_; + a2_ = 0.0; + a3_ = s * max_acc_ / 2.0; + t_a_ = max_vel_ / max_acc_; + + // constant phase + b1_ = a1_ + a3_ * t_a_ * t_a_; + b2_ = s * max_vel_; + b3_ = 0; + t_b_ = (dis - min_dis_max_vel) / max_vel_; + + // deceleration phase + c1_ = b1_ + b2_ * (t_b_); + c2_ = s * max_vel_; + c3_ = -s * max_dec_ / 2.0; + t_c_ = max_vel_ / max_dec_; + } + // max_vel cannot be reached, no constant velocity phase + else + { + // compute the new velocity of constant phase + double new_vel = s * sqrt(2.0 * dis * max_acc_ * max_dec_ / (max_acc_ + max_dec_)); + + // acceleration phase + a1_ = start_pos_; + a2_ = 0.0; + a3_ = s * max_acc_ / 2.0; + t_a_ = fabs(new_vel) / max_acc_; + + // constant phase + b1_ = a1_ + a3_ * t_a_ * t_a_; + b2_ = new_vel; + b3_ = 0; + t_b_ = 0.0; + + // deceleration phase + c1_ = b1_; + c2_ = new_vel; + c3_ = -s * max_dec_ / 2.0; + t_c_ = fabs(new_vel) / max_dec_; + } + } +} + +void VelocityProfileATrap::SetProfileDuration(double pos1, double pos2, double duration) +{ + // compute the fastest case + SetProfile(pos1, pos2); + + // cannot be faster + if (Duration() > duration) + { + return; + } + + double ratio = Duration() / duration; + a2_ *= ratio; + a3_ *= ratio * ratio; + b2_ *= ratio; + b3_ *= ratio * ratio; + c2_ *= ratio; + c3_ *= ratio * ratio; + t_a_ /= ratio; + t_b_ /= ratio; + t_c_ /= ratio; +} + +bool VelocityProfileATrap::setProfileAllDurations(double pos1, double pos2, double duration1, double duration2, + double duration3) +{ + // compute the fastest case + SetProfile(pos1, pos2); + + assert(duration1 > 0); + assert(duration3 > 0); + + // cannot be faster + if (Duration() - (duration1 + duration2 + duration3) > KDL::epsilon) + { + return false; + } + + // get the sign + double s = ((end_pos_ - start_pos_) > 0.0) - ((end_pos_ - start_pos_) < 0.0); + // compute the new velocity/acceleration/decel4eration + double dis = fabs(end_pos_ - start_pos_); + double new_vel = s * dis / (duration2 + duration1 / 2.0 + duration3 / 2.0); + double new_acc = new_vel / duration1; + double new_dec = -new_vel / duration3; + if ((fabs(new_vel) - max_vel_ > KDL::epsilon) || (fabs(new_acc) - max_acc_ > KDL::epsilon) || + (fabs(new_dec) - max_dec_ > KDL::epsilon)) + { + return false; + } + else + { + // set profile + start_pos_ = pos1; + end_pos_ = pos2; + + // acceleration phase + a1_ = start_pos_; + a2_ = 0.0; + a3_ = new_acc / 2.0; + t_a_ = duration1; + + // constant phase + b1_ = a1_ + a3_ * t_a_ * t_a_; + b2_ = new_vel; + b3_ = 0; + t_b_ = duration2; + + // deceleration phase + c1_ = b1_ + b2_ * (t_b_); + c2_ = new_vel; + c3_ = new_dec / 2.0; + t_c_ = duration3; + + return true; + } +} + +bool VelocityProfileATrap::setProfileStartVelocity(double pos1, double pos2, double vel1) +{ + if (vel1 == 0) + { + SetProfile(pos1, pos2); + return true; + } + + // get the sign + double s = ((pos2 - pos1) > 0.0) - ((pos2 - pos1) < 0.0); + + if (s * vel1 <= 0) + { + // TODO initial velocity is in opposite derection of start-end vector + return false; + } + + start_pos_ = pos1; + end_pos_ = pos2; + start_vel_ = vel1; + + // minimum brake distance + double min_brake_dis = 0.5 * vel1 * vel1 / max_dec_; + // minimum distance to reach the maximum velocity + double min_dis_max_vel = + 0.5 * (max_vel_ - start_vel_) * (max_vel_ + start_vel_) / max_acc_ + 0.5 * max_vel_ * max_vel_ / max_dec_; + double dis = fabs(end_pos_ - start_pos_); + + // brake, acceleration in opposite direction, deceleration + if (dis <= min_brake_dis) + { + // brake to zero velocity + t_a_ = fabs(start_vel_ / max_dec_); + a1_ = start_pos_; + a2_ = start_vel_; + a3_ = -0.5 * s * max_dec_; + + // compute the velocity in opposite direction + double new_vel = -s * sqrt(2.0 * fabs(min_brake_dis - dis) * max_acc_ * max_dec_ / (max_acc_ + max_dec_)); + + // acceleration in opposite direction + t_b_ = fabs(new_vel / max_acc_); + b1_ = a1_ + a2_ * t_a_ + a3_ * t_a_ * t_a_; + b2_ = 0; + b3_ = -s * 0.5 * max_acc_; + + // deceleration to zero + t_c_ = fabs(new_vel / max_dec_); + c1_ = b1_ + b2_ * t_b_ + b3_ * t_b_ * t_b_; + c2_ = new_vel; + c3_ = 0.5 * s * max_dec_; + } + else if (dis <= min_dis_max_vel) + { + // compute the reached velocity + double new_vel = + s * sqrt((dis + 0.5 * start_vel_ * start_vel_ / max_acc_) * 2.0 * max_acc_ * max_dec_ / (max_acc_ + max_dec_)); + + // acceleration to new velocity + t_a_ = fabs(new_vel - start_vel_) / max_acc_; + a1_ = start_pos_; + a2_ = start_vel_; + a3_ = 0.5 * s * max_acc_; + + // no constant velocity phase + t_b_ = 0; + b1_ = a1_ + a2_ * t_a_ + a3_ * t_a_ * t_a_; + b2_ = 0; + b3_ = 0; + + // deceleration to zero velocity + t_c_ = fabs(new_vel / max_dec_); + c1_ = b1_; + c2_ = new_vel; + c3_ = -0.5 * s * max_dec_; + } + else + { + // acceleration to max velocity + t_a_ = fabs(max_vel_ - start_vel_) / max_acc_; + a1_ = start_pos_; + a2_ = start_vel_; + a3_ = 0.5 * s * max_acc_; + + // constant velocity + t_b_ = (dis - min_dis_max_vel) / max_vel_; + b1_ = a1_ + a2_ * t_a_ + a3_ * t_a_ * t_a_; + b2_ = max_vel_; + b3_ = 0; + + // deceleration to zero velocity + t_c_ = max_vel_ / max_dec_; + c1_ = b1_ + b2_ * t_b_ + b3_ * t_b_ * t_b_; + c2_ = max_vel_; + c3_ = -0.5 * s * max_dec_; + } + + return true; +} + +double VelocityProfileATrap::Duration() const +{ + return t_a_ + t_b_ + t_c_; +} + +double VelocityProfileATrap::Pos(double time) const +{ + if (time < 0) + { + return start_pos_; + } + else if (time < t_a_) + { + return a1_ + time * (a2_ + a3_ * time); + } + else if (time < (t_a_ + t_b_)) + { + return b1_ + (time - t_a_) * (b2_ + b3_ * (time - t_a_)); + } + else if (time <= (t_a_ + t_b_ + t_c_)) + { + return c1_ + (time - t_a_ - t_b_) * (c2_ + c3_ * (time - t_a_ - t_b_)); + } + else + { + return end_pos_; + } +} + +double VelocityProfileATrap::Vel(double time) const +{ + if (time < 0) + { + return start_vel_; + } + else if (time < t_a_) + { + return a2_ + 2 * a3_ * time; + } + else if (time < (t_a_ + t_b_)) + { + return b2_ + 2 * b3_ * (time - t_a_); + } + else if (time <= (t_a_ + t_b_ + t_c_)) + { + return c2_ + 2 * c3_ * (time - t_a_ - t_b_); + } + else + { + return 0; + } +} + +double VelocityProfileATrap::Acc(double time) const +{ + if (time <= 0) + { + return 0; + } + else if (time <= t_a_) + { + return 2 * a3_; + } + else if (time <= (t_a_ + t_b_)) + { + return 2 * b3_; + } + else if (time <= (t_a_ + t_b_ + t_c_)) + { + return 2 * c3_; + } + else + { + return 0; + } +} + +KDL::VelocityProfile* VelocityProfileATrap::Clone() const +{ + VelocityProfileATrap* trap = new VelocityProfileATrap(max_vel_, max_acc_, max_dec_); + trap->setProfileAllDurations(this->start_pos_, this->end_pos_, this->t_a_, this->t_b_, this->t_c_); + return trap; +} + +// LCOV_EXCL_START // No tests for the print function +void VelocityProfileATrap::Write(std::ostream& os) const +{ + os << *this; +} + +std::ostream& operator<<(std::ostream& os, const VelocityProfileATrap& p) +{ + os << "Asymmetric Trapezoid " << std::endl + << "maximal velocity: " << p.max_vel_ << std::endl + << "maximal acceleration: " << p.max_acc_ << std::endl + << "maximal deceleration: " << p.max_dec_ << std::endl + << "start position: " << p.start_pos_ << std::endl + << "end position: " << p.end_pos_ << std::endl + << "start velocity: " << p.start_vel_ << std::endl + << "a1: " << p.a1_ << std::endl + << "a2: " << p.a2_ << std::endl + << "a3: " << p.a3_ << std::endl + << "b1: " << p.b1_ << std::endl + << "b2: " << p.b2_ << std::endl + << "b3: " << p.b3_ << std::endl + << "c1: " << p.c1_ << std::endl + << "c2: " << p.c2_ << std::endl + << "c3: " << p.c3_ << std::endl + << "firstPhaseDuration " << p.firstPhaseDuration() << std::endl + << "secondPhaseDuration " << p.secondPhaseDuration() << std::endl + << "thirdPhaseDuration " << p.thirdPhaseDuration() << std::endl; + return os; +} +// LCOV_EXCL_STOP + +bool VelocityProfileATrap::operator==(const VelocityProfileATrap& other) const +{ + return (max_vel_ == other.max_vel_ && max_acc_ == other.max_acc_ && max_dec_ == other.max_dec_ && + start_pos_ == other.start_pos_ && end_pos_ == other.end_pos_ && start_vel_ == other.start_vel_ && + a1_ == other.a1_ && a2_ == other.a2_ && a3_ == other.a3_ && b1_ == other.b1_ && b2_ == other.b2_ && + b3_ == other.b3_ && c1_ == other.c1_ && c2_ == other.c2_ && c3_ == other.c3_ && t_a_ == other.t_a_ && + t_b_ == other.t_b_ && t_c_ == other.t_c_); +} + +VelocityProfileATrap::~VelocityProfileATrap() +{ +} + +void VelocityProfileATrap::setEmptyProfile() +{ + a1_ = end_pos_; + a2_ = 0; + a3_ = 0; + b1_ = end_pos_; + b2_ = 0; + c1_ = end_pos_; + c2_ = 0; + c3_ = 0; + + t_a_ = 0; + t_b_ = 0; + t_c_ = 0; +} + +} // namespace pilz_industrial_motion_planner diff --git a/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_lin.md b/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_lin.md new file mode 100644 index 0000000000..4f2abec293 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_lin.md @@ -0,0 +1,62 @@ + + +# Acceptance Test LIN Motion using the MoveIt Motion Planning Plugin on the real robot +This test checks that the real robot system is able to perform a LIN Motion to a goal state given by the user. The test is performed using the moveit motion planning plugin. Note that before you can apply the LIN command the robot has +to be moved out of singularities. + +## Prerequisites + - Properly connect and startup the robot. Make sure a emergency stop is within reach. + +## Test Sequence: + 1. Bringup can: `sudo ip link set can0 up type can bitrate 1000000` + 2. Run `roslaunch moveit_resources_prbt_moveit_config moveit_planning_execution.launch sim:=False pipeline:=pilz_industrial_motion_planner` + 3. In the motion planing widget (lower left part of moveit) choose PTP in the dropdown below "Trapezoidal Command Planner" (see image) +![moveit_1](img/acceptance_test_lin_img1.png) + 4. Switch to the tab "Planning" in the moveit planning plugin. Move the ball handle to select a singularity free position. Click on "plan and execute". +![moveit_2](img/acceptance_test_lin_img2.png) + 5. The motion planning widget (lower left part of moveit) choose LIN in the dropdown below "Trapezoidal Command Planner" (see image) +![moveit_1](img/acceptance_test_lin_img3.png) + 6. Switch to the tab "Planning" in the moveit planning plugin. Move the ball handle the select goal pose. + Move the robot about 10-20cm choose a goal where the configuration has no jumps. Set velocity and acceleration scaling to 0.1. Click on "plan and execute". +![moveit_2](img/acceptance_test_lin_img4.png) + +## Expected Results: + 1. Can should be visible with `ifconfig` displayed as can0 + 2. A -click- indicates the enabling of the drives. + 3. PTP was available for selection + 4. The robot should move to the desired position. + 5. LIN was available for selection + 6. The robot should move to the desired position via a straight line. +--- diff --git a/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_ptp.md b/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_ptp.md new file mode 100644 index 0000000000..732ec8ec4f --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_ptp.md @@ -0,0 +1,54 @@ + + +# Acceptance Test PTP Motion using the MoveIt Motion Planning Plugin on the real robot +This test checks that the real robot system is able to perform a PTP Motion to a goal state given by the user. The test is performed using the moveit motion planning plugin. + +## Prerequisites + - Properly connect and startup the robot. Make sure a emergency stop is within reach. + +## Test Sequence: + 1. Bringup can: `sudo ip link set can0 up type can bitrate 1000000` + 2. Run `roslaunch moveit_resources_prbt_moveit_config moveit_planning_execution.launch sim:=False pipeline:=pilz_industrial_motion_planner` + 3. The motion planning widget (lower left part of moveit) choose PTP in the dropdown below "Trapezoidal Command Planner" (see image) +![moveit_1](img/acceptance_test_ptp_img1.png) + 4. Switch to the tab "Planning" in the moveit planning plugin. Move the ball handle the select goal pose. Click on "plan and execute". +![moveit_2](img/acceptance_test_ptp_img2.png) + +## Expected Results: + 1. Can should be visible with `ifconfig` displayed as can0 + 2. A -click- indicates the enabling of the drives. + 3. PTP was available for selection + 4. The robot should move to the desired position. All axis should start and stop at the same time. +--- diff --git a/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_lin_img1.png b/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_lin_img1.png new file mode 100644 index 0000000000000000000000000000000000000000..c0a55f478f5b837e3d93f7bd4d0563b925d593d7 GIT binary patch literal 229896 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
k2U~srxdnu8J4EfJ@G$rh06O z*5uGSW%rmQOp4YYh)JuUp_8;r?rg^>%f*v^-wZfknYK|6ezYDxF19QK$x zTh(!4>t@_C>+0csT7i(~T5mZ-W!L@nwT1Cj%O%RknC-s*ulNHH7BFJ5H5bT?AWufcSvGd|9><0S-Pt8 z)(t>ny&0ybCWpQi_BXA?zEG#hB=_SUj$^R4KO0`rFW4qpH;Uo7zC0klk4kB{J$`$Ll$=@st>_ycJ(@|z{Z=KhoDR1!z z#jeb&a9Z_X>6}?rI3t;DnFz?unU4;e7wB=+7pPn*{rt*8=0e#y2#DG+!q&=ucqnyN zPnSFPW8uVaF3101B6Z_X#?k3pT>g7)Hv4{#n&&t@dKn4$U6vYDmy(wA7v}=&Qfj@m z*FyxxN7)}brZ(?o0Fw2jZEoQi>u$Y8rRP?{&vu1^e>!z?qAS|=c!f=u6*HysXOudo zuJNBa#RJ>w=$l?!Z!rpASz*sb_~GfIH~v4$-ZCt%ZRr+<5Fkh(xCBXp1$TGX0D<7{ z!Ce~~cMI-r!QI{68h3Bp-M`M>``mNBd+&Rm=lanEIORdLYyd135!VgBe@lU4!A>%@JKt16zd`-5da-8}fWveKM zoht|i7X2o(ri<7=COQt3>{%rio(zTfRaAs1D-}W|(6u}7!n!+kBVe=8Tw{;X_T>wF zSizml!R?zkP2zv#ZF;>$lU{q@NwN=UzT@C2YVWHk1LDd)_hc^+PacL~Q1|irMl!~G z#^2Q>t|g?uN$cSDFCn-$L!1gkCZD@-bvWbhYsq3>Aev6P zHJR>7u<4@P?Ob~MVfZ}HdJ51fN>#f*JYNLFEz|B%0AX++lD)h*a`&$+F<8jIcSoKJ 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

0=Ojy_60sTt3EQj-PkkN&5(F=n*iHW=_ij9ag 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 literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_lin_img2.png b/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_lin_img2.png new file mode 100644 index 0000000000000000000000000000000000000000..84f533025e9c2c01733930dce723e8484befbc2f GIT binary patch literal 280710 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

-qtt^WPjW&X8Eha>Z|SzQ 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ïW?1mF7iBwkt5i#+K3Ry#(b!B{_3?6XQKd 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 PiwGCe24&4aTuS~Egy!>m literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_lin_img3.png b/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_lin_img3.png new file mode 100644 index 0000000000000000000000000000000000000000..41804fff3b15b9b58ddafc7595f936030dccf7a6 GIT binary patch literal 253603 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

pi*Iz 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%0D(Qs;3aLah5=Pk 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

jJu_hNZC`G%tSO2n3B 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 z

  • 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ɗd<) z9D_6JX;jh{p*f4IIQ8^v!M}#FBqUJcf@8d#4qNsSU|bLnZs-9GE6J!MnVpsZxa?ox zt14kY>5?)d-1Z%1lFS$EewW8yRnXEjf|YRbLGY+X*ZY%Ecr4J71;<0FH}|-sZFf?0 z5_jvn)r|@1@1#!yh@ai7IP1Mx3~G0s*_Xs^Djj7BGld5ajER0f@K`60ZZ}k-Row?` zTVkJ{Wc{;9XtE&hBr(8~fK2HFEZT~Qp_!Fn(4~lNE-hrV4Jj*qCys6O{`j8*K`~-w zgN-hv84aXUjp_6K1;j5bmj%-NzJgoJK`8>&g*LZqe;qRSaxB;oXi#o-zkBeY_pxU~ zxcop`&6a1*KlIBCr;MuMV)vPcUb`{tc$4|Cu`_*%>N(AK2qTr+=(Sbh@^?-2@uFLl zxBq_OSHM>$ObHjVk9{3J6H5*ZKR(kE^VT&qYMr>!th`5OHh5fWYq#b$o+j(^%mk=S z7(&53hmiQQ3=PEE=ljuePd4$AcZ^|f83ovHNS@3_9bCyX(^m; zuk7t!UV5!L|LhWOkD|l7NbzbC;0UR$PhDf%NtZbRXtl5%Wpz64YX5^N0{7;^kdgWT zG^y7Dd*@$3*k@NWQ>sTI&teC)fDu1gmI_pLY$IeU3Jso4F390LF;pF9C@Ko&_H1q9 z`e0g0PR?|>$q`~gJ-nj|?C1#6S2vy-1q{?%k1X&{W-jaY-`Fb<^eSs>JAhL`P2@aL z%e_>VT7p=}cU5LR{Pg$w3a6gOc2i`x=iNO;?$58nmNm};Q)Cf5FIV$6V|M+i2V7H> ztU2HeJ>!=tDZa&Xmt7rQfOGK@^#~moCI+qu-a{sR71YDAmMh?ne)z`~1Ezb8E<1vt z_CO%M@o#&d;52oL_nYn(pJ5MrDIJ^>Ao6YRXmi|`V3=L?G(Qnzda)-DugfgH_HvG( z*Gu&lN}|1`*|#3M75YQ^EwSH+V#@0_PvH^{lty4b)?46dR`_xLWBEQ*1WE{%V^A2- zq?X~EHvjw#!d}}fnXO(_i>NHNxG^?uDtV{uk{Xr;IkR}UbHu_zy54_aWsR@wc#P-{ zLa6n;u>yWKk(>gg@w#xKk9ntmQSTHE^_`#eThG~_rOa0RaJGj{|1#HOsxZ14AhXFl zkmMmqZ@!QW8^Vx1`b*7FNMfHfi1VgXI2nbjKSp7 z5|5**Pfue?1FAxJe$tO=5KogcS!p&nv+ce^XMq)ZDV#~O&YKGfCfjtt_9P5;KlAhP zOE+K3KHzz3&rU0;EjH|}-R3PJBPnvOwbvmL-e_WyebtkK-$&Cu1bUT1F`kHEX-eXmj3=9tO8K}OWihI6Z z;9b>y!kM<$?u+!Hx|#`6e^+yYP-8i6dQhFI{Yg{yHYSIA{Btt!wD;1v!_4fgnzXC` zowSUu76)Q~`i-Exb|jDHA*ar#woA3gGCr?Ql*S*FNm>)eStya+d_m)Fh*M0q-DyT* z&U`0c96_3E)mPt=)EpT(tzz=L%qC~s3VWOt0eF;t zhvPMR{b?FaN*d6meE$1~7@h0cYVj~R28?=l{??U~fU&jclkFNJV!r3kg3_7%DMq{V ze&a}IQqv*y&Da4_I8FT3RjNq+V=2&fe>+k6bnVlt(KWY-X zn_Vj1Qr6`uZ^fr2aK4%LX!YK07+X=Z{p~jV4JpBAp8K^RV|;mO<=a06h%dOXi{0z= zi;2{o0u|ILBJuEpq_|rf0&mFEuG%C(pmC}NAC?cXhu@Pclx8zunYPv|LAdHkhF01% zPRT_N2?ICZ?-ILqW`%0(*E;^%_;Utls@=ORJhZs!pcz@+M zn|!JE3x-khfmlb{9u32jmKI)z9$sUY>e7ZJWGXS8(EHqngn&`&fbDb+Ye`vI`n#=5 zHwN?FQq8)ypTuKF62`pEIb-&neVm)kB{CvL)1hpnH$K@uCPdY4C7C%P%y6aF7q+7aii0+e_xYELzUI0t0`aO|r zq0U3SFcu{6AB%hO7B<#KJ+42-zp!RjAb}ptX1!NGO{RacI~8JA{GE>(t%Jh1m=16IRDW(bv z24aTPE{nIjtHF0HKRr@??h+6#er0`1y|}a?@kZ~7XWW<|e)`4P!m3*G*BB_N6~F;G zG^4+ACXW6ZGREN2sV}}xxlvl=<5Zl@Qz3Ssg-RgD*U8naPeNcM?SYSL@SXz4e2>EDLYBsin#6&Fnvk=Ktyy zE|QKZ5=k_`D`U&b#}7$Mv~37?K9U8cY7On!HEa_QRSv{%fJIZ71zJ^VIBGGGR`d@H zwD7I^`?T-hD?4+Rz1ArK?+#J^Rk_7)PX-&9w6UD6MAap_%+|nPaS$P;03!0^S(Q9@ zs7Qyc|9T?Nnd`p z%tu{0QvHhId9O1wH7jUwn`h4qIh@p9W7SE1a1=P@PP|FoT85O0q4N2U=P`l|5J_aV zxF>h+#q>JcBHh)nyYq`YfXL9~zwqW!EPS)MiXSKMn$ru4a>bsrs!>ZtRO?gk*!`yN z`Lwt=6apaeFUSQ;0SC2W5UJ1oC-(Id19Kj!~eVN&v38uv0H2Vh zjE#XS{Ry6!$0_yv+@Ty0$LcUYrAigXPuC7E>2M1eg`{hjL2#J->0;I6<(b~;VrvP5 z(+%RN&{TSV3e&i;?&z2-!CWA-{TcA@4^_d31FkA#J70=I2V6P+ECYS0&&Q$x?D_Y* z2Xg>xL|zi)PJ+_y!zuIL6wdfW@wYB!S9jfbqvqHzA$^* zHQqkEE$w3M>t0&H*8V$HWrgEV8xNx8M~2RCh12D>L}vf`-g|O5V8@8ZON8&o6ro+q zRbvl@=T>W}Vh(a8-o0jz?z!Ze>q7~!zNC(`ia-AAYvCbNF`~My1`L=KaV)1yOYbc? zIx(-Pk&zJ`N!rK&jR^khK{ZUhUJsq;iz1j0ZD*uvb_Gf3B6f>+c@jXg zzxXY=M(~%~Xz{UetUJFlrM^6=2a(`C=8-z1;p4s>k^6&(ou$&FS&1I3t@yZ^ql-W= zM^4@Xr;%5*@!~p`usmR^YkWep)`YUr$Hl*&X<54T{BRlS&&et-Lirpom59opSbgb; zJo)~uaeW-P!HqTsOEy9!voyKF;q;Z}IiLj4uf05$rNWKh23?J6?K1g1ba`bpGUswM zSM7SDH2?%CK)Of{->vUcnta_C>V4;5alNmT0|WCqEV#BX7TZded8#woeOGwdwftIj zmya!sDS6^WhraqMkuH(ml|E+f4A^K^@H11mwX_iuRidhBcP4eawG_ouJRd!- zr$u0lR|g~lT-oH*iL!{54n-?JS=#^qyGyy;8I>s$X5B}Gzq5?VY8-JNUp=53ZzTJi zc0IVxFQ3KQu6CG+=-_*-r<>#y>~e13v>)wMTTZz|tq6w9A<FrFffU4h1Da|jrTkWEf zryTcgBsET%7l5}Y8#{)l;)W8*(sBNb5TIb4<$im6yUKP+4UTp*fsZ)B`@lWlKq=pe z=%}BYX#!UPzVz{ncT%gv)B{)vT86p7u$(b_SAn3EGRT7g!mLLJ2Mu0dz_K|4Su-;# z1JQ&MO8D22?Td{3-0btaCf&5+}$;}yKC^^!5xBL+%B%ud4A7- z&dl!4&c4_)yyV60KHb&zt&dcdvT|^^R?q(KyW2E)U~kvY2uG){6Is?n9c;%w;a zR(}c&cBH*I`(rJ(H?5&eWli=f-a3ks61skls^#N{V?q?L()eDK=k8QvG_BcGdr5lN znRg6^(vXz|>qkfCp!lf~Nc_0r+tjnYfaD*#-kXWf2CTG#FV4tdO1Z*?3dWUO&SUiA z&0Dx!@!LNsjx96Q-NERBo#Q()JzwwOX}gY-w=5C=U!kF#;N`Xm;sc8*Ml3^XnrQuU zrdnzcYTiRcX+LEfjwb@H7a$Z)&km%W%fCq)m`pSt?+~vgaYEypl`aTBL zHn;(&_vUn3H@sD6e%W=4oMi7UHfQ=$7>BMlD4%dy>Pfse{Q?x6XItNj4nNpfynW;% zye0W46YJ?G9oTs~rqxUyU=&Ho+Ng%}JD!8N=jwrw`0A{hxsY>g>koXG^?EYH=_;D( zchwSG%_FuSVv$%G|I9zzhSk-ZK*@3+Z1fAqoaQev1nmYBt0GJo{xZd$O;o@)qg}dbX(oqnbJulX=Z8~pPnuSn#>;4AbA)Q z4$}Bhy!8T#*uEE7JRFTD4Dqj-qW2&pr-;$!F_0Z=#CVNgXtD8uvS6VNK9!M;D*|dFa~yT-x)cZp zJy`JV7bCQT#YVI)$NAdu;0dodbJN4=s&AYVq295^b#71E38A24Rv;bmdgvagTl$uW z_Is(@8Vg@^Pp1zhr;k7P3oLTJ|GCRiDdj(Vi4*`8`Fr(#YQ0Kwsw%m{mT?|&>SPU{ zdIw{CL}^S)_2e)G2!t@VlklF=ofYiUB<57>G#{ciOuo5oNe=Ie?AqiP3yIC^)Eq< z#H}>~w-R!$HZD^!G=B+$ZgB2cR30#34o(+Qh8tP=$(op2&-sHe8&AS;GYSd+hYP_S zoiQ)Y7>8WY5E+`h05I@f)=btecQI(hCS+SUV!aFakHsV*xWvh_bNK?ARViG_kR{RY z*tv5ZB(qSh)oaZP5XZEE>EIK7UBzPc#=jM?ayAB^w4CEJ9k<^CG7P0*^8RV)vFwEi}0`U-_`YfF)6w#IGsjvp@+l5(WldaHA?ntcT0OMmmtp9#ig zHyhMwwDBUrVo^n9szWzBTB={9d0eVRa`k&=8-Se*WgCv<&$F)IS@4bdK zr$sCM2R{sKmnKw9n37mvbkM%W-vxtC0xBcKjtad6_mFBb5ww$FB0}N{%trHSdDVX& zgmc<9-y-6ipITw%UpeFaSebn;guNE}=vfLNOsy9xNtl`Iyf}!^mi^w&YibHmydiEku+epuACk38c*R27$xeyjP>Hxi=d8~X$h6-us3|p!B6?t{H;Oqb zduikL6};%b{4hoByMt)D@62oP}5)iPsaM`-H4 z-byqwJ730qC~}t(Hw@1P)ON+#^5jI&(Kg~*~hhWQPCBgoQ$-o zL`M4kI)%u0tkX9cvqd8OPbksk!9N;uKRay+tJ8TUHF*koK$b1aZXZ=-7<0SE*%H%l zS3xghK3ThVII|>%FP3cIxcjsy$dal-L^!6bLRSSN3#yMytSue*0vM^JcMekR z8v;g%q*Jx&x&&gP!ZN(~XE)`{e|G8M z)LyIE*;n(3ef;R33M71K>4+A0k-{~B%?svJUVV@K+w$ZZ=A&k23{0%A{UP&KgJw<2 zHciT^nvzO?;VTFJKLEBZ3qRyTMT+n7@^QV@ay2i2v4_;Zwzq3Or|FniGF@|YPRAg&dI2PJE$pr!fq%qlP7QYPJwl%nw|u|?@dZ%o)VwQMnsZ%{6&t%nX(si!a3$47s#j{uv%6F& zLATW#cA1qzGm&(1kF3U8{`TiE@8StdE;jr-yRd=Fke;PWziLkT^r>E@!W)!ls$Nhj zJI0_ZTJ2~%XT@sq=tENg3}#Dp6n0tE5rEsNK<~)YXgWm86DtrHjkyjL&W+AiYmeU4 zmBF3-{>uNs&G&rxNsZR*Mo#bJ$#b2bnddJAxN}h({N*XH#AswN_2!3x2-C|ZCWty7 z6VRXnjf2E|;w#?l1MHi_IjR}qs+$u@=SMV?Ps-cJ7W<@{j4=JTp9S{HdD>_e)BeK{ zTzcNpNG9?pH7+wj4RU05Nza({!OZKETfPrK>m-^eKy(zk1cXS=`u6qA< zIufqUo4KLJ9w$#w=x>P1*l=WChIHvw7^M{Qm$Iq36KT-|Cy>rFruCr#k`k*`QL#l# zg=(;2>EFQlJ+OqJU@cc@)rv?t#)CekhOhpzDN}gWnLXC5KP}Rl6UGVJlkF{=^7+!tPfJ|jN zd4s8)5|Fslll6}%tyh-M87W)2oNw6r-WH^}cX|U6&5lLti5dOq7D)-R7TFHxKDmIG zn5;BS*33yEhm3^<&4xqP3|*aeNg9DvE{zFF{nMQZ!w-^;E?wy#g_1X{A>@{phoB(m z*HIvPvpccv0Xy5?$CLS3%)K=`WqLiaa(zqIOM26 zN*p+FoX+y#gf_Bs-;X6Xum|B|urK{4kH<{H25MzY~NsK7C`ku*E~`R=@O$&vc5 zIHglvhhej;GpH&aDV)bMNQ5$CO5kLGVY5B@CF5Io~B6m z+}z=rI}YbhD5Pk-tX>O=Yp5;hskv$WM~rt4Xsk^cuK}<*>B5_j^XkHX%Nqy^7Sb%@ z?oHV-^(uIH=GE1fltu^Fpm>S~+{BUbNkYNtQiPC74QSxYV((uJL^B?Y1JrhjOM~w2 zjl##$$2zmJq6*0y2b~iCoB#3x%!jyw_wC<#D;~Due4?ipNgf5#MMZ##xH!zy-MRVW z^2~+xiAb2Fp1~{ zqrp7<=O*{(vEXNLF4Jy$MX7m6zVG?f^OL6wu|J~`*vx_Jm`y#O8T-s=BFJ0wq97%m`OH>l8tQ6D=ha7Ox|G}dUX+GH^;h{ zkop@3Q66?HAF7kz@`Hk{ZSRdS(N4lHlM_mAp=H;sjn}r3{>DbIcTSdU=)G{v$p{I# z{NK)qup~VT3o6%qq+Owl)h|Nv4i-|r!VX3zQVc8=tBlp7%F4x28hhZc8dWSgk}<8e}VI~J(IVL zol@Dglh*|H|0W(Ev4kY3M?^+Y(eX(w%;Y*N?jT^6^^d?zV1B*0+O4 z`UCfQ_D;9Euj=O~6YI7S%U3H-ZfrQ?+c|O`_I1(gu+CJ)4A85o4K^~6{a6ZS78Oi+ zpKZVT?SXj(cGvZcCG9OY8;j)8wHqxQ-9k*_UurIf^jaHNp}FKwmt(R!WIP3H3@=-- z7`(q?q3EKyyHyw7_&*>2vMkN~ayN;~)+Dsb2IN1{(JIpl^^=vRNY2Gd(keaJ3<^$i zo^q@4$C+dXGlKcblY$z>=qt)%(8XuQxz zmID1RTn2d{d*3||r4Vx@<{AiTdT_zJ9{t|>j##SF5!2;014|8@C|Z*wQl<;pfVfhQ zg;wWW$vn(++0s_sTYP<6!P9$otlQ)g?93SP5gw~L#!}6fkF}b67>uJsO`C;5%?sF6 zb((E{1Ys9rxHpKRrcdSDarc29S?P@oo{k0`ZB03Oaj2vEc zZmUsiak8mZ`ziO_+F*Fod#;y2S<>cxmVg@qZPK`=)xX@vC0TZQ=>Qegj&sL4=f*l2g-#B z+Ve_YpyZ?p7L^7O$XZPn-j%&r{c)~jl#tB7O+Y))Z8EAFG0y1Xxw5%G-~(Yc-iq>F zT76n>u{RKp!U-7sO8pl2Ing3HLs|p{+MS~U6JN2`o;96qXHp63V44eqOUg|T5#;Jt zB~=WE*IWf_?>EwH9B7fG_=x$k061{PsBTC_Ake1?Ls-d7-}@WbQy8BZYD>IpcCZTm z;x{RU0RO}7m}B4yUXUo-++&z0>y8c@*bnvRx^DLNU4t&c>gK-|;j>O%7PfBoE_=VU zvDdjw+Z#l6+WdCQ zKx{NIMv}{v-!J`DOa{HW>s^J1MdP)AwV7zVR9z8?vEc1q3Xvc?OI1T@kG_`ZHre-C&xG7Ra6IXa0yaEdkhzCfB2^YhzCH&muP6e~}? z%zp=+s3tQXyBz~0m!67nj>`Go^);#BL{f9l|Gzj22HrAluoIUY&h%DHO-6W!AsLFk zVP|Ukh4xnM8&ydpgv|d^PhTUDS$rbeeU#Y08Z9u^vWh60|8}Um08GR+5M|*Mc;VYZ z1c6r~RXk}?#+fJD_TyD~UM?6A7wJC@BWNBacs;!EapbpY^nic|LAp__s9flUQ$d(r z5%?D~bv|UW8rZM30(4-DXyGGOS|y*FptKlZk-3MmZ!xMu2AUgotkL1ci>DU+O*#tA z?d{J)-zok&!wzA+GSKrlyKyurttkr&Q&luGqoAgy-q=8jcY5;aA8tJN*h*g|_P-!H zJmpCmk6`P_BKEwEP51ToFR|4Y|JS^Gcze?0FiZnvv3Ck!qSG%0pj(%i1p^)uvTeel zwo&as5Lor4^fpsjD<+q=>dPg?9iTlv-S4+@{k&Y6SJ!%;`2R#7DB}FJ+@bwerKVQq z$mtu7P>1=KZBerh_Xww&SkC0)jy-yNbN)R>2O=?~rJ0;^?hfvk+Jp;=bBgWqye?aMP{w`{pCBlTCG6U;-Cx}{;!75s6s^@Fb-H~fS;nJ+=~v7 z)YkS=9A`$mWFNwE8|ryEB(pg@)o|7QxCwY$mDPvdv81ims>8Z(6)xo8^Zql|jg(YC z=tm(Sj)RF_isTlTo6>%aqJCs_M5gdWd=f8}tXLUO`ct!!`NM$_x2z@G>#DqWCL z-8%wQV8GAG4K*EjFgiUy9ejnjgbl!z)NZ)H8uYA;Y)hBw*GAnxeYwm#_=R1m+myYF zFYaX76^G}&(HEF|F?yU{xaoqZcbsN@;`tYs4X_R~##vh8B9IT7<0$m4+QSZqdkkAU zHyPa0tTB@fF6o`$CVD?#`4=6oaYvMxXwdVmccHdd;5gR(iZU zct}8JgmPST-u}z5OwCSl{9?jK1MP2?d-p?HQQ03yul=*}fpMb1pFI!=^ArE&rIPRK zZ==*xqo>~XO@{yHE}HnDNxXWl=>gK}XbIb6tx5_M`9aJoLj!U|Bovw1;`gT(1A_)L zB*4jB-D5$!uX@WY*_lI~$VeH_7eo9UenXqeuv8fhpjaJ|sXp9~((!(*qm^MQ zJCcac0D_@g!d5dd)A5CS12%fAaK}DA<4>{>3o~>4bb&;J-8v5o3(KUB-&hL$_37%O zFODU~dQcQHp#=`)?_{FvV`sxZ1`iRC+nh#W3&=8G`@P<$ zH%YK0x@NE za@P259t?W_C8IYmb?EjDQV-*D83Eg**X2Xqdg?D26FrT+IiQ7H63;%gpMMc|t?FNX z963*Snkc$OpB(+6ndGp>DkynZQ(rpkrlx%V|q zHiXPy-@iRB_AK@I3&O+0o0ys^X=?ro`}mork^lb;K-C&qX3Oj#dQA%vA^LNegT(c6 zYCZ1dNHB}0&hnJ;xP;ufr_|?7FB-u!~As)l)=OpAY)2Lu>r7SW7nOPMS(GXz^W_x8w6{vs@hXGxP4`%e(-S3_TVi(4uM#z} z3;sXn*z@0SrS|KRx+h^Gu|@-e=ggz5RZx`H@uOWyjI6=yW>`W zwt({B-N^Po^=qGFtY_ak)=AV=o-`mc3)FQ(_sT(&Hfgt_A`=4rR9 zXRXu%U90+;-xf+#xdB=3-Fmz0XL|Z*xlE4fA{p$zl-MooTYa2SDkGnFhZ~-M7FU2b z?_!_oE`cPL(?vtkxXzV*_tOm%Wf*DuZv@*bs`|E#&Ng*)y@(|XIf@?o3u)(nJ>WlItZ=Y3<+7Npdp=Ihaa>GjVEzettz0eNz(pu#iu zHrBOoB$ew`kAM=+bw<4KYON`cL18b}n4YIOJ|)F(vQAaB6X>ECleg6@qTtqGhXRdf z&v}=sCTT!PeXBDb2KF2p4#g1abi;Dsj7LdSe`4nQo)#pUa3qRrMv+r-(UL5i)tIE> zdv1CKl`VWZl(I2J3?I=1U|>Go(<}%H%)^?6WN-BU?O==$PbF! zG+Dz2<&9FN>M0YVo;qBmt?7Y9g?u}DM2dH-@ZDKA?;3h6MlKv#59di^w%2RGzoQrl zr*x}9+~+rckDah7=8%N)fh&I?y#r?LH)a^(@)Qi<^;Qtm`th;pv!UYSm$1`pi_Fd3 z_y7s1yRTIs`us;su9Tk8r@bwpg_fE+JegJ_A!)Z9VLI>^nRZd}%x^se_@&C*iyFgC zGZxFC>;jnI1&&k>2`BAXlgB68xJF2po9_iy;-w_}$E4t$yG2OkcsahC9zPuUbN=QU z>5t)suUY&)H@A@0GLrwQ3bt%`oHlt>%Ikm8cF^qtpa$f$3R+(K|uWkg+p+ z`)2R7=E_}vu6B^lm+}DbN}APB%tt4$#fAN^ZG`4^=+a*g7Ib9x`@GaiAQz6TBCCy| z>#Q>zg-EBDHPXvz1YIPZc?-^8r~VuKIVL13o?dE7>O6nXQSG*Z^z$J4{nO4(ddGon zPR=vJU|QLHA#VYXfy81vNgBEr_?HYxC!amDwVAw0JSJRZiDO4jW2suek(derc5H6% zubv6>iN+^Q1jC3=)k?e>DK=9Hd|{zyYrRpa=HNfxs3|V+{%1=P|L9M4oVaQ=*|g9A0c2Hdg5-cqoDJf~6U1^H zbVO6LzNuVW#~MeWG08 zLUsx&3}-GqKVA}U*c={}3$Gbe^ox~eI#%ITWDz=3V#>n^{0lZ9Ojet#5XkwNa@guO z)$ge`KAvD|LPL}6?l(I=+OVNY*xB*-^~qc16sEq{ewr^g)UC;jgctQmH`e2cF;eqo z4yfR$3{WLuP*x#On?#O@geTY{JMiT|{dZ0aJQD)>RPJA7LNTS)8w@Raw3D+cGJ&|UE`*d39i380?mXtmBRCk>x>xV)wNZ0@bt96p2<8#CPBjf#zq9}`3IQc&3z3894-?$d$LWsmz6_ONf)UZt z_Iy9{yuos%i&g53XXT!qR*RT_fZm^9=&h&cXBB;aXO{@@g_@d=?R5+~Yd#;td2O2T zyd6WQSNeKlQli_LcnoW+J?5D6CXe_FJV%uZ3?{F{ych6?Bafz>Ic;%e(fh8G7lPl` zHgqQdGH{sq#_SPA>p5--M4v@YA>irt)yS*X`{)m9LpokIE_OWqt}POAPh*@4`A0T1 z9$*csHfgr`1Y2mjb9)H^oVXjk3JV^WcXuxp+kCKRDl#^CXtw?z4sKcf9Vr0qk8{7xaVJ;fBI2iYt0vj zLKc_pn^9QUhqtU?PC4ushc2=M#s?aa7hi=MlbR1()XFRsV)zq_L z+&@`X_ZOk>&#)~bU^rjAr1L$T^Q`fJ?N~_Pso>mbhiDk~e{96%&Ky+h>|ke15?_=z zJ_|0XgADHJo^15ojQ2Y)_+U*0lNN5XREppiHa?*5!ib2i<|T6VcCzlNt9tV~e7SgX z@+p!u|Ic^Qu-5$6;uO7Ew#CZ1vx#>4l;k2yQ--qE zqWFyM5XeBLe!3pPkN~5!0HfqRun(WdPaAV&plZrGfASG9APGX9AD7 z^S;QTI``Z@DnI+rce`0|YK|+3oloXUzElgHkV9a+y4t*NgvjU|U?n$7FU1|6$0qn#`TMk%Pp+MMORdNx75iYb7i2O_?Y^(PA7O-u z{Lk+oOi`3))w1rwvqAI6ZZC}eMi41nho8?fU05Ex<|2i zzFmk{_GWiK@}h9(%_&f_>1Klaq`Jx*c+8WNwuN{LLB0de+9Y3PNh#79FPw zVjXmJ{8#z3G;SO2mlyA?-Zry(zC!p|%vgT9<70`(H}+A2)bPt3s(RxYX>A&7rBy}( zI<1cJ_PZN$a$h^6#10iA@pJc1DHGr;$46R%Q1b<93maU|oIAk)XHyI^g!ak2GaiV; zdIq1SK3@-8)?XHRzCC%EjS@EAHgzFt*2i82XTEgo&4otwSVL?m`1SSm8a2Ok9byni z_e8pj=x---R+9+j_WAF34UWpeN^x3SF1?DMzVnT`A$z{`w3~MH#9T> zXZJ$fq;0%f!TqZZ7|yrP*7oE0A+Hv{IT7)jN0w{_r`!rVCAvk{TU`FRr*!?T|M+oD z&3>pcuI2?r=c;d~fHRI#xr?8lHxFXB;IHs&T_GtURZf`L7r~($`-s#E?CFHwTdlX@ zC^`RlOGr~gna7x{arFMxE#H;F&2fh`Pxtj<4ZZz_twT{0tkFjj@;#w1yqTkXsI->d z61bw+`A$oqp|S|u*79Ybp{&IS`e}_K2G(PeUI(J{sz;a!&-wT9jjNr2lsow9mlVEh zBv26eb)n|_5J3Ifw$-Gq$sguki?h`XTj|&1I$Zlv(p@%*I->-9J^Y63S%#}AA`W91 z`lp-k<>Wa8Cc1>s<)=Qz&bEDF5-4VKtIV2+FgHW*c*XRB=3yKZ-mh`?xJW+_!@12ugcb3&In1d819yBCU!wE>)@vdxPPUIp;a;6=>`6P5sJR_r^wt-D65A%$G=Cm6H( ztBe^MZ3*j*KPBtfZJaa&`c z?w)Da-9SEe8iLo?2v6|-l}#dYWd?wNEuZef$R0%*3@6;FP1cuEg`hQAZX3weq)x)z z-lxge`;C4c@A(}HYv2>+QIqJ?@W)mEH8rEyn&P8@^p&a9W*;qjj#0x~6W_&J{{Tz| zciSP-zRk**C;GsFZqG3L9L~M-0~wK)SA2Cr2@`E^YGV~`y5J6kypB4vv*PDieU{ll z-)E;ep(!a=oH^OZ*Ynd#e|v#gg3j^nJEA<>*GCMaX`0h+# zA!V^8AH2B7iZ_Sh!B+Z2IO@;*I)@@)zk)QDPf>mJZG5&+Bh-SgwK%@ zhU!kfAI4W3Gb39*kjkcy83+>huDQG?#7m;T9OG|HxpTKX;03D@9b$%|Ngkn27JZCu za2h0Dd(;JePyZr}?mb5MErv4>jp7s~hIpmYz7zL2bSomielOhXb{?7U&GQuvHv`wIy9bR?jS z@X5d0!)LOtUM+2#w|*9e*0i{tdKzEebN)cZLCdb-$KpOjOHfarfA<@}l%vEE69t4Sa*yA&*@64w_wn~HS zth`Wv=J5^+Ab|q`oc>Pg)YazYT*air3qgg#QVVsd9bf9y_)n|8e1+!sq5PDUyQT`Dh3?tN zjfHz+mT~T^$D8+T__CpfC{SPerTpH;gqNbF*cjkW=GabV0x2quKvGcs8LbcCa=hu| zl;+Ntg|~bD7cVPLuAc@D-B&%=fa~aib*2zVf=X>x;@}{;``YMO^I(EGe;92z zP-WAav8tooo=-#7P=1~8>gMwZ-mUh0z8n;wyNsRvJTCnh8~W>0H2V%rZSgNwT5i|2 z#tGTUaoT_ZuHMMBa!|&Ui4Yw7g+{Tl`lWyy$>1=KTC{6s)EVVhBdC! zaQ25oVujj{J3%!nJs`4M+?@HwwE5!L48AUgf;H0Wfux(Sb zhR|Xo>P-Cmggv8)?bPL1RuD)%DvK|%n;wdp_$kbiwK??y2kzjF&v~esW(G~}2Rx~; z?OxD40)mD}>RBkO3?Fvm0KOXA340K-v%%ghA@)J)J?-iw%xr=EEGa0@tIx`{E9G|V zOhY6<8N!fSQ@n0Zx-0}$SQR%|I}{I*0+>KiDO98sF!&vF>h?UNc+pX14nf_1O~R~# z)@IF?#L>!KI4RDo36egI>DV7@u!YyqE^3Ye{w z#+)&#srExLU-|p|*Fl7|DO=+m2u#A9W9ct}5W$eO?LPL-U9tw-!#({&5UUS9FWLfW z%<-5NAy*515(m3irpkGWdx8>m?plbT9>1KC$e3BzK9dbetB9#&emcJ^`V-+<&4JOV+Pieq8BV`RgQ(Ig+77Ko z^TMZbQr;3fgk~=FRv+Hu4mVfDs3kN%kj>84=*}z7=-m{IXVQ-T_ji??uv)t?KKho> zYJI4k$cqa{5vE`ZJAY_XNyf9I(}_7(g9ch-R?5JqE7dV&ifbBiF$WuhFFwO5 zNwSZ3wM~spX2fP=M(Evo+wjir+t#JSRU4h7TJmB_5B<%K1@sS;d^CDx|@=}HKn#( zU?8A3o3va1^~F^}{{$`R?WqjTZZ_o;M}y~->7&8y&;CuFaC;Yp5QVee2~Ikb>%e2p zCU?5*1iiKSgx=m$N|F<^e4peve?IFb&3B(m?uaNEZ9W-?>KR)bXIkggVM7Oy9ZAB( z9Q>SFKEB_&Q@4?`AENgq<*Qct*rXywuW<^Md;4$z2?=Sn+nbEq$2v*>spj^!a?u(L zB{j@6v%0>n=OEzGtReNCKWXkb`TjwRraprx@kl~R&+1AFMp#u<&aPiOJqrqHSUs+u zA5qC0aC{Rg2zO{($-o^-LXKQ1hW_SRiCi<#xau_{=O^{8%i@{9bidPJFMMk~))H`q zPAt*F@t1)mbrGL@^G$(yu`AFi4LMjHO6YvW)c1ZiWr%K1Su*@3*&z&uc(Gh*{4A$A zno*RC=B8)-!7?@cKrqe^-OlKta8Ne8%xpUksGu`7`QA{!K$$!F24y5bN@2XZbRJXm zQFKmKj9tOCdD2vkW=KHl+n$@rZfkVj^s)636H2wjeeiqpATls(GV3c9^`Wjz;Jcdc zsAQ*@B^8?LR=~P=C@Nlac8Ba%ylzrqH~D%0r82EPZ8(?JY4gu5+l=m(t~eZjwXH;+ zOES7}7!7FTl~9%K#2b4Z3)qu}NV41PesEx4;dBwxli6Y1V>T_5nC^RP_t=Q=eO#q* zzY%oXOCRBaNF^^ZM)En#KrmKoiteX_JtHZdKX@nAAL>-br;s!c@os(oyW?2NrS8xE zwdsx21|5y7TV!Y{mCzY!SOhspPPaMW@ZVLt3&l^SbXZqp{;JM@Ql* z@vyzV_l(Y$=1<8fWce6MpGzpVxM#}4-O23PL^zU$Yye(BjJ-TcSNdRq{vP|*fyhDY zBF+7~T<%FPZ814g7nrL942OFkcVKY;k=}igX5)z~ds1m5>unDT>p4r}`E6ZZhLEc3 zJKT(>)Wa42Z4;qre`_&S&wWTTJ`Yo;@#oH{VJ>?IA7SzzU1vYeJ4ZVCt%-+99d&01 z8n|YzrzoGjpZO-&nNo{ln}%VTvLA!|*EwUsf%|nf%DkNcohrv3KF`7o8=4;3r2?4g z=XJHG#(dP&>`$M>;kNYU5LggEF?8Wzh@6D);Yk7cwmO6rWT#a+vp{8>ERb8MDj1QG zM`1f9tSV}2^EYgDzARiz(~<;P$E;QvSGYcz4;+;SxozYwH2anTC(aMJ!eMk)9PkR? zf9!n^{gOhD0%h_q{KXe%V@T;8E}!lBx)4~UpED>}n~&*T5Y>KIc|b9C zR+wC_?N$0&qA!1QH}R*S)Dwv;5QbBt=UeNc#dk5@{b|^2|KU#z@2X<0#-gb6VwU@be(kp=8G}DyT_J4Y z)m{b1ojj}q>E%>w(sPsjOql)gx1cr^L5jr+W?NE>Jk^w$>D9=#$AE2z}c@uq18sUGToAOCKJ^oPA(fZI0YmK9dl$Kx+| zl;Cl1M9m8sd#sInx~bf>!Th_D%U`_jq&x9N<1x-uF50P|d6}&&SiAMyzBlhw53VQ8 zR<~JT9y>j^IKc)7TVui#ug5DYhqd=_5KTJfEFBdt!b0{wq!Q4Q$yl!IM;WiGKh+~t zkdcI5Ula88gCqFs=?Wi}=1kCJBUXmy1)4Yj)0^zfj9OTGZ{2*muK`FC9x2(qFQ5W- zrW?5_`s;DZ#6phmqrvG-sj<`2O&=-+A;D;b+K#1?@l)Pj{o6!Gy34)3IwOwo4o!yO zsMiBNQTu}!#;l-u?>C`zJZ0cC`vT0Xo}Ql8@Mfn`A{xeuH5q?P@BkHzG}20_`D^Ju z*y6Rk9+T}XFzi%If(963=k^NP+-+sd>^;NjxEEBQp5kO{5M`lI1H>DN-dpY_9uKKY-@ozwWH4 zjkMn!ddnr#EuzN+@-&ZC!;I0M8xCxAs|iby9Kj4L*0&2sH8z?pL5>I^KuIB?{&7(N zHCGltGfIH67;=l4lExwAf6Qz1=P1+z7eobFhjX4@vlSt7|5?H0V~LpxBS3-YJazfq!IO+#_Ih^VA@ z8}$GNRtUE|BzfIh25{;h7J$zNoMI&UzQ*Vc&GFQGP$!IV9I%~82;?XpC9 z2vNnygtMMTK7DGriNDj@!)spQ^A?lt@$LoAW0EWR&#&$qZB4BE4|!~0YSz~Yo;+1@ zp5;oOHe!YBg z)hs9`?1Hu^+jSjx?&D3S^RdK}J3N!9S{z`9713@-P-^*GL(q==xZv+}pv$wfJD;gn z1Kvw%pq0y*x-(WuOfE%-2Lx2!K!p+81fIpNN&1m$;46h|lWB!Hn15j$3fXd#Ms(d| zvzf4>hBi>2ILCkl{`dId0&2-vIS^D>KM%f+Oxo%|yo#61LZG7NLA-t`nVoK}i-?M9 z5SmzTK~Ta(5HwePZKgjWw(Qq-UfOJcSZ)q3g*u^hYqVL8`1VccL&)0q#E({wz_RLQ z0P>;cyD2@OTJl=x??$mN13+GOcQ zZ9(x)mu*YBXd@h){OKf=k1Pp3EGoZesVWCfO z*$l9Oz2AD{WX#N9U;+d3lM}nYaf%xwA0Ar4lZ$nkR(u_+Z04BAzjgZXsR+q>0@P_6 z`1b=Wb{3fKpO@;swOyU`o5|zPY80$yh?^Gs`+RbkGG%pJ9b&3)<`pCyTK8SE#^yDjb!RqI^txF&@N9b;;^JwTzV|&q=QfTOEYkyqEC-2+wGw8RmoBg$6`d{Bp zlzc*#FNij8SJ1tr=}f!hs8nj>AP!7Zj*O+N8wH!EbDbZ+AG22$p|ES1n5cxn?w=g| zj0%hwp49^mu&@xH%GE+?v1|@guGZRSF6Ik3xIY{NcBRj#LwzP+@rgeeL~Mrd5?<(M z`MiblNvleWM)eq9WRhbVSc(%$jZb8fc=K)Iz{7F4YegcV?aXl&cmlK8D!dt*Y7FXU zDXQ5g+^c8DQ|ym4HOahr%4n2X9|GoAACm3-z|(pM+C<4L`|06p{F&kBm^?cr%&xU} zxM36TattQ9U@-HdwGB#EX8~AfuaRUufyg9dB@$77(^}0I`*Zx}HRkqNCN!ZU<+#-X zP8n>*ir_}{{CydzxNmr||9s;(bHinWwsQ3Xcn{J7*91|iOZtmaiosinONkE~*XqXM zewvrx2tyTeAye#U9jYTljHVw+ipnr}z?TW6LD#+00GeN$17X$9GB}bo2LvFr5UL4D zXv}l2{~WLRSKt{kV!wJn1E3deA&Y#`x8p;u`_Ww|U#+SM&Bnc%)09|U<88a7(M9WB zh7j7U@%!TYN{4Z(arzttQaO@rAyVo%I41W%2LuMgB~v3)e2fSa0@v1LlqUXwm8(wD9{J25Wgx7CJl10ByW+lTDig?s<0{|EO}7L%P^WIMrAaD zQ~C?4QyUWkluTSJ(U=)x?tqQ@!AHf&2a@6N2aR;mut*UL&#O&!^6l`4BLX?8U%}H! zar_fmkp0&llQktrJoTqYbpvh^(XTASp;klu(92~9~pqcMH=y~*vy9tFjXj>|4o~JnM8kZ`1EN*`> zc{#ayRGyIP)@ubU;fGfGPve1AazIz!!wr;^^{lt4?I&RL@&oneZyrjlQh4f0>i1{5 z|BSx?J9(hfA42)%CEl#XKB*G!6^{;NvM5SlGrOi}{h6Gt_w&xDh5NnW*PK&1J>~rv z;~LR-ynkQLf8#(TtFx}2b6 z-ltQ7fL-5&+a`oZ{qT(?Zb9RwuNHyM4SoGgKtG2&GL-dyPW3@&|BqB( z)ET!Ua?R#c@zbs$k9c>pC5x-PM||y?e_WmuNnlN!kTQ%?+Nrs|G!?bz+WulMrp>p4 zw*yiMeO$&)$kFtAwj*jgXNbTVcGNb;%Slu>duIbE7-j)K zKq`0BQx3Pg;-V0-yaWLNwlEWOwgP3K;o&gBn&g%oVTFazeNZ?|~wvMoXC zomCV42A=OcXj0ZRd9rdwG3T{)^0e?atz-69e+ONBvngWsbw^ArjE&2KfU9oN! z`?Tn^dE&4Z`U{qBp?^>8$DtJUIC2LO6cel5L7U&8g-vU=cwM^6m#?re5B{mg)Oeci zhW^{(Kcv0P!zbAu)3KF}3M%--$JCD4GuY?V>P9_7G)`f7r`q-`a-R*!$7Tv~o6!wI zH&*=R)8~1?HwJ;NZ@iZ<1j*{hhQpPme+$inQ92_3_9J4vFa7zivs=!#@8^Ou=aq*QZaPo+yd? z3ufFMP8XGs2!?lWEfFzfnWhn#Fx=ax4g;oeHjRe%Y~c*r%cgDSV-pJcR#w!KOkiRY zKF9;9qP%03{fEj&^oPto7;H7gOhI$gjTC{H!n$&e+`zkY*9j@dlb?SPQpWT_pAhto zv}D~dJdG-sY=6fJUUi`LUipma?$GP0tMIWagh7US(UDWB(sVU56cQSvWWQZM;FXf~ zclM#!UPXj_GE07{b(Qy>G}(rz=OpYcOs%uG$vdT$k_O{#iymJBg0i{x<61Ib_zwU5 zN+Ge5h*ThVH-M#lK=M8a{k7JTndrTe>^_f7Sk=9#sxR|X&y!53(WUo;J*e=Dz}&}4N65UM(b#uglkFPNt%i*{4=KOOl2Mr zU4%WE@Mly_$P+M1>&bRW?UJr?E(l_;=5*Nm>y_#DFjFZzLXU zpAUSbk~kgu%Do5O_d^ky&OF*Jxi3@wgIl`^a8e|qYW4`^dkEGfR-76En~GeTaq*71 zhBe~V$c}C%R{;zKQ+Nf;h4|J=%R`FV_~m5qt?4poHhH_Hjujy&cPStyYBg205kQ9J zNv>l{gn-SS0}5&gOvo1~jUXxH1%y*Cp7PG4yjm9!Qj;jmhAblJE&{PHFvc1HPMjG-T(@{dJ`U~s_!pVGpWzcCWh8- zFE0=#i06X_I!HULhIITcmD?|gbU#i#A}{Xuri^sWg;xn(&-RvjI^Y>;NRN28ir>`@9_OY?TgFNH}v_Mo5DQeSh}RI zvE!swq>sgRTFnO}%akwioyPoKyMs(ugBH3R$5&E@w|}_^^#tO+dsdtNC2(aa^yTXz zbh)cNM7}=qch&s3A(1b_n|!wVI}nk{XMKc>B^>G@4E}Gw9T3RBK`{oFAmT%J+otg2 zeV!N{-CZzX%vWt9VPPTm1?!vRm*Gh*mxK-mIG~=$N@&{{0q@`m;0cdLLT36O91xt2A-H_LC=F4gOg1nP0 zH^KT`q>;8(NehbCUDYZQ55klQ<4zGNDqxAMT4?-gH$u!W^@h+GW7;sT}t0x1GG429x*(&g%ukB&Sv!B&%j4z6|M1z;cuh}wJd$JKQ$IwY9^S`z~ z$n}r{PFQCbV0LZAy;TG=EK*V22*E@WJ-}l5%@+StM1?(SYfyildVf2`|GTw9+`=?fU^f$PO4QM#j! z3IP?{qXo%(alzg;Dm>Tt%G^T@LZLJOu|u z`q&ec-$$Fu3zLFlLdg@#{7KwZc_mtK%1-QCa&yM(D>>oaf!MXo*osjhwros9BZDUq zU8BH^7Y;3>$SXu)7jZ8q;>X0#l=o<>M313QY{*ixwR`xStL(RA^V#dl{woqP^-W5e zA26=~$nb01a`^ZhOj%W{Zr{KwbxAQD;ac|59K%^2(OA*Kl8pRu`0diTrXdQTB}Ct< z@B7CQ4af095y72Qbqe*KJD!Co{kerOY=y~npAnUsR~0s5at`iFK}^vn66hjuc-U3j zPW?>TM@!xFp}&+Ee?<6ZERA&b|6V93d!)URX-TWvr_{Ws?-!U)LA#NJhP!BrOc#hV z7^E{A+Ejumcf#_oKy83?1c!a+lBE7QVW6;O(MF(-rhp~0ig{TY z7ZsH0F$LCypy*_Gnl4culo;u9Ar3Rk)0?sN7QL;4jJ>=|#eHMYRu zG?l zysqo6sL5w4twj{XQA$r*>>ZjGh~QF}T#n&TTU@TE`Q%Fs&D7#nQ7Jt=aX|(gBkg?z z9LZ|DVI9}MGi3R9h7bU$lTv=x`SsYH*m9r(hU{?IOd#!d^i3<6wy-w2!^3R|&dLzB zn7HK#n5m>-ww8&}Rb~;L*RhHt=BI{3{%lUdu8_|gua9!L;ul*|?H#^ELn3Hb8b5m( z{Z>4lZ~7i=aptR)V9&H8W;lq3Rg5{AJ&vp^THU$PwNpBgj$=Q^8zI&2oKY^>Ks9{t zzw-=yia{u<Wn!dzNb2g}c9UcU0lkVuL0fK3`2tO>k71 zC1MbYa~KeFt7er|`P?Sv7^$|1u;O0$;_jB;ALOhW5cm?mgSeTp#;{jd>j4&JZR;)1H);DO&y>g z(6cB|+@0S4R9|}ojvLB@bK$Gnkpj%&lkWb5X&>xP$}R|ioh{SZmagw*_6GuQAx#g8nU4o@|E?3 z%h#j~i65ViK3#GypD!$1>_#>{UMu`=k%v*@J_RYv4cPYr&;|Dqt9S67d!X}eMIjk2 zpQh#6%jTsk;iI+eb|;yL=JwG;p9B!y2+tB(HGb*(3D$OZ=-sFx2BS0q&>zGM44r>B z3sHc05R+4pb^Lx_;&5uCg3+a;=}ut9_5M3w{7)^SfGZ=gWIj@wB=FheUPYFijUh?x|@YNEzpo8(xBKJDX$y8W$f$V`#TBC%C)(|cM;O3C{(pI(Dqv%O~; zMb(2mJ>pAu;CO{Z(Xc4+v*y_8)7t#14e~j(fZ~$t3ChH`hr^7JC_Wd%iTY9fLJ&H6 zGBj;9H0+B6OBF|SdITZ4VF$()UG-sU@+ev{f@?5=wZ)>metG%M#MNXx2PO>;qC-XxJb)PV-mZF{5-7HkLnO*_#~1hLHe|}3c}7J+3GFfL zK5;}cEIJZH|HO^8k`=jG6eN?Xgez^mbBwsVI6rgBQ^6-P03qc{mW$B~8b8CYR%iP6 zZ(DeP5*bL7DtD!BXBg_2y*5z*00PHC$ebaI6D3ZEHBkl+yc+FFq$F(t78nwmn85h_ zsauDQ|5;6m*6GUcH&#HeRM|xqSYcq| zr1b9qC`T#Ku^BRrPm(XVJvk8TGibmiP*LR$1uvn#u)&lDvttO)Qld$RFIQEm3MTj4 znwoHjlS4$Qr<W2l9jc7v;N=01c8Nh0m=)xA2bGZ zAB;!d6!r?4FRTpK0qqU+UNr(qO|Ba<%JxslyJZPiz_T>)2p9P9N!0HdHcAOX5q2B5 zV5_mCs6y=Am?e!V%~7%3`Orx}6_G+V74F9aG($;+rk89< zB#kN*y`ht)Kk|KYWm8TB!$wuUTKqf4IH{Jt-mRE{0xU%kmFkq?v>HHfI{Am9-1z~Y zw?Y<(LF{KzTG1-;WHSbZ!EB6+3msnGA&eR8>WE%02#C2?#FGVM8}{Q}46*;rT{*=d z7M79rwAZgJ-R_WY6FP&QW_bwlnla`?Mp8jKfiJ!m)*M|EUk1>-C~x+|hsfs7ZM0xW zh6jvl?YCCB|1r0v-^qST7kzD&uuEpp*F?0Y3@oW8OT=JT@-FeAi|ULZj8@$LTvfU* zd#$8nxX3m#>TsJHg=oWBmTQr!2~X8kYVR^9*UyP9Fgx43;6?ZUKK@Y*VUfTDI;@O}{G9EbRnyOuU)x2ItzVO2m@yBEVAjU#*PL?hb z-us4QS*%)WbvMK%9J>5Zlii~=$O5 z(qjl@frMvC$${n-JHhEv!jeky|9iso=W2OJu=;h~^bkclGb`oHz(nYKFYLWnYrJc* z&E921xm%urWReC=a#q?+hPnO6t=&-Qao=QEpXJJ5_`aZ>(=}(Lf_%r|X0`8c?j8=l z$md658O$I}b?OP4K$J!et=_-keB!``7_MbcKwtMJj;${9Yz$AXozrIN7yKoi?EGyFd~e-r-IX zhMG?e-~o1qa+WeG3l?t8Te>{oGqG;}LxP1nT)dW{ z(gv$+T&-tZ)Lt#9=qf>>g2tE#vz<7z0-{cRj*x(U8;tM^3gkWTe_tXVB%+MGd%ZaL zvO=+AU2T{jBA)^mx$)fc${7bBr|Z1GhJ6ClJ6hsJ8qq_4eB3dRy5J2}G?hBp8a*G-;h=<)ziA|QJ!73T<&fc#`;0wbJ!VX> z)Z~Q)*hLxk#=L3P-76V6|0E9(obMQWMef`&Y=f;H%);S&XC}m1#J7XAHzkV5anGt& ze&6?M!nMC^#s+S^*gxt)4hY;z-~c!UW0 zi29Ito-AyudRX6tFghEMq_(O$T^UXuXzfqstw^#nF%t*@58&( z+nWSK@fT}Yk|4@sZ{kweC=%f-Tu;Hb zU_taBc}dkLICL#D_Jo}rU%E1lz3#?^%>=i^Mvw_f*Wu}o1h0o7W|q)+QbP>VMGLP` z@HVtYjgif3EsjLBbKu-KUvv0=orR8Btk*}7pjEooO9j35`hz6-Z8gPVM{)AxlJId4ho zwDk{f=i1`0D)w~*^zES!>l5?TE00IJBK?1;xUQCrI!EM9j$c$-O7qYT<%&j~(I zWtw6(@A}{SX$-!vbdIc|V}`$9VnrADC9Ev^x|1p8c_4i}QV!3@pb{xMu4T;`k-hZ7 zzArYUB7dl(y(prQl(j1_d>{Y0`AROz{MhN)!mW%*Hq%%Xrev&M>-h4S$H033#q~o( zd-kou<6b|XUC0r8xkMS4*$&nq=6tvYWks2-N6vDot|((?f^S-R{3lN|gPb$N#iv+L z3;K(T=}Fi9a=vL=6!O?vl1v#=Li4?F!Irz$@$5HLczt|`qXQ6e1Hq8q%9Jcbt;3J= z^gCXe1$@%o`=HSl#vT{V)kcC(#Ua& z@8tn>hM^2Z9wmsU5O6@s3KA1lxaB`Em5F@Ic&Vi#dQ@Q(&i`-4>+IxOUiP?)ujl20 zw&%bNrah|U@{-8V;1@yp^m^vKjivm%UX1jRXMZT2%{0B^8P!7R>6l|!va`0syUb7W zGE~&ZFn``$#AxRA8h<2$0aThC&_)6gmPE|7?7@%BA{2)y&9vi>y~PPd=i{r2ew!V& z43xmwiNd-NI(E!tQ1jQs4enx22=~HsKG?Az`6Bk;A;YS)SO_2%YP=ULW#4#MYS`P~ z-ageqx$acchg{(@B@_Nuzw(yG;&kC3bbYzDV6I{%`4ORbe|@^S9)z6~cbj!d@j*C` zftXfQ6;KOMveGMs@Mo_Ymn-jVksY9?H%9pHoD@?nxm-$eeGL2-yZD-Fr9sdAyk)mg$K&X}91Z0a_ zz5@NN%O#ynI&&*txxdzDM*AVORK_|veb!(V-*0uRfs`GG?x%q(qpa1C`2wrdXX;B} zRu7vn6e(sshD=T}V#82tN~>BSJx!#OtEHaJ-b>E_4}?=!oL{)l4kVJ*0_MMc>q=xoT9((ZM|F z3#K}qI(9QAL+z!6DUM#Xwb**RT%oSbU&gKsOTjxHD4qH1S5D|wlvi}#`U2dk4w7@^ z4DJ6rs`rX(BtQ$PQeDTTL^U_peq46p;m#&5mxS#XiH-DL468d?v*Vh_+`#J9QY4|`h_Kwh=EUIh@kwOvSm+PFU#*0Ig zId3VIt+1<;O(eF^&i!pKU0&})>MZFSk~xFqdwrd3mUF@LwrH&m$K{bf95OK{=uBLb z2l|}t2Y|`z^r!RI7IBL>l??InQ*h%S_js1>_b;j3U7pY%lZo8aBopK{n=m~@abE^P@EQbnRIo3P}-vKX=5 z?{nvGiS7_01TqJl*P$OR*1kJtofp8`Dahy{K{pXFwvYXHY4>OC=aFB4iODDw28hCy zMgL-1fP<;NFAJqHBkGQhi1=4!CAN>o?|e)K06JOeVL$&5Sf$om)F3~TTU1g4mt7R6 zsnbsO@>-jbE}<%ss-vR-J#VNff2?*nvqbkM2#u_&PXJ>AcoP+i?1(=Y8gY@0Z6Z<< zs2=>N&)4%ha7yepn3A8w?l zXQKap;>CLv_KqOG2>;2j>Z$=hNS`wZ`h*OU@H80zp*OU`i$NwwAWcgUyR)<*0z+bj z-Y6b0VDzo@_Ou`VADavS$9^@6qD%U2C|vSb$suRVZS8$9?C@Q}S}m z4!jJZ;Ng;NeZ4DYmn7_wR%k1w+m`?BY3qdp;bZ~OMpq74W+3mC)@I;z+_KNFwr9dt z${0X9OM*)=hb&#)C)jX6EHiCC^Y^|=1W(W73HkXJOSQAI#&SofU!QV%T!xWZK1PhT zRbwM2f_-wzxFu`m=S)#!e9gcN2Q&KN8)oehSU^4fF&mLgx^Cn=D?z7sBPigtBU4BJ zlOopaiob<_0^wLPcvL&oYF$^olR2o--OAti<;EAD!oeJVrKdn+#WU6I?9)Dd&d9Iz z3)aD->q96c1p0Qj*A0=F0AVXvs)~k>HoTSi)(~c`VMS$GtI6eNNc0^MPi^K4p#Jkj zlb-)UK1Kq?@~|^EFJ3LtEQXBA@S`G-8s6Jk<1fcP7$TfbEY@$0rI_x9r;(vL%^FSF zk~ypP4lhMEC8K^#D=Mw^rpl;Ndu*MU*7BeR4QWCoq-1w;u}1ra;6{$qEd>lj&PaoH)D1gUh<@E~B9) zUkh!%C%CwAy2Y}}mx4v~D#chA4kf|>{65Knht9Im!)RohDs{G!y_I%0Rc8Np*n^Mn z1(58sUmIHytxfHbC{Bzr#7RU4W|Nbvszm-i*D_)^M*J%R_{ZReYX5OyC;^0_j`Mby z4jONo8s%ok5Pz8Ja6)MQ4n7$Sl#$bFVf}0^6jFrMw8^u8eXZRq7!S%!`z5O=EGmS) zVv79|eyu9?taRsRqLp%C$2Lt)A4Ml9h$PckXrIRbsNG=>y7MT45drPx#9C+XRnsvU zupv?ZV?(6xAwF7KT+pP|(Mo+Pe&g#j@X#oezz&oV;z9UmPwsq8W!qE=Dy+Vjem@jJ zQuNZd(z!IF=Ej)iF<`>_Edyi!#jXy-a(SnYMaMUjDD^{~Aun9v6SE<WX@G#T|Dz|P;Yxr@69HVOrUW4K_itBVl&qzw zw0xA`G<{pj!`V)BZ>614S)L)@c~)#qE0a}mZEu9F7%XcZOKK+2E$7m}80oa(aeyw@ zs5&K@vea{N(ZU3bCQ6DdmbaXaN898G2Z)DGJV3ow_$i}21ZuXR9MDFWuKZfv@EL-$ zxcKIWo11A>bP4%?WZ(aI!Cv%#sfn5zmIvIAiS?{MtxA(0M84z+vK+q?PUmcYubh4A z$fe)2XvNq?xfJbzP!vVN6oq`v|5?&%rpWSNT7XdK@XfGLxWDw_aQWNF$fB(_v<<`( z@bnTgF*Yk_X08dRW~>=fKEARPX=DjDF25gqvSTC&m*gmh$mGlu+$Roh;!u=jDbRo+ z)Bj02P_V(0(~{1`sHn7JRR$lUNMd0Vnqf9NIBTnq1;tvaibOwWgK{YF&^R_YIZ^?lw(+fglrW{z!IE{7d|`h6ChXP7WZ^lRK&t9j5RdHP~9 z`yzL|NSYcq#=LPRKGIF>XkzB=>8HYm?*u+*vT!6crW+imwm@@fk^vKPzug*UnCgz4 zmv_!6l?iv=v7POtGs@eCjK?JqeCuVz#dmeF6B87lXV=viU34Ozi_hsDq#e=!?c$&E z!;;@f-4#&H<Qv7hXXuc& zVExsi>CL7CdVYv+NNND+-H5Nra!m$!afCrd?KWu`>R5#Agz!LYsgipNkFu^5uC|m^IZY z;d9$ho;k1_@LTf~<^T!oHJ>2KMoi(hPbU`3KB|3DWzD-t;>OqO~Kfha+l z+HK%V0iVeOF;t>H$M+NUfhN!XxmD8GK0g(BcX_=)$4P{evKvftDzI zP}_*jX0(yT84hROc4M$@^iEv}R`qrnDJ3s3OCH2To|x$-J?8g$sWS#UXij0i70BF# zDp#C|SfAMJPZ)IfKvxr^9sTO?<^%@6ec5S5H*%6BPUAR4bnS^$X*nLDWFlRYaeMI~ z?6~;R>2iLf>oF0-)mW!rY@GiwCJ1`5B9L1ezPQjI38@l@-?X480ZyOdC)o;7d%TR@ z(jdu!?m!THKA-!E!sGq`b^3X0Vt`fnhkYU1+HI>f_twY;Fz7QaKyQ`3Vc3U`r2jKY znCN27R*@9CwDes;i6}X}wnVsZ0TF$fVhFdvG_|C)I&at@G#u&7VYslWniN%sd!1(xz~$ZYQCt#S0#l(26{ zw%vMTxEycW5p+8uy!%OM&UQX)j7i&@dxPMphWrcb?>^X)w7xi^wouw}et+=+FQoG7 z-=Ws;wP})QtBp6@`=gAGOGhIxEi!x!fIF_8X%5@ixIsH+-q^D~=t$DW#^>N1jxb*v zI{V;GAu!_#;3eQ4$U{Bv@!=%YTH%F$LV$(Ka)*k%E z#69U?Oc~O*$_LsnsfeJOp#GO%=ZV9FN?}^Q=o+&w3l~WPo z^k_;d;n#sL=T+JW(a)Xn1M3|9P|p$4*Xsj=eSiK1&_hae;rw!f_2Dd`4~N0quB@)k z#~6WNSN4RHy2FL5eBn^mX5(+hEl{(w{ozsyXzdgGsn_ujACED}K;;Mfv)^VW=c0R) zBX*nhGOwH0io7GOS^8EJDyuJU;RT&n49P?dq3CvUZ&u zi$?u~1JS{CGw0Oi$Zul0qjJ6zP>eX)7_xreQ zmTh01=djQy**6(mqEOew*otDKPbpS86M|{Dw?!kfOzMc#=%@4-2brL%!ckQs_!9%K zv?>+L-pU%$g@g<6rvrLn$R*u;ul*bIzqso?;SnRS`ihB*~v}{FK zbsLUe%!DOigj=TS9lZ4A!;N}4PoUrM{d}ZT&&)3iOvL3Usr5tJVRz=(W5&7Y&SIfY( zNaUr1&Xx$t`y_6khwut3+4|t>O2=+5$GmzsU@Xnl>fxXTJ%%HN+k_*le0(>>*Ej9( z_b-)`YnGc(^qS~$KEu3}M&GW$gB&}`R-2~w(m)iWOeyi@!(YKch@GptCJM3p#J8vC zq6)_4)0{=mDxU*vS6#M_R>5b_KYj?fFAcQYeV0>WFG3-u{}MI5$YoEA8}ks|yBr#3 z)*ciOp&>XNZK=fV31$ZAYn#eSkmto^`5B5Uw9hiSFs8k*qNc6J;*I5?c64moCm?iQ zO4>WFQO`+!J@ui4VL5Pm5%L75g>TZ2a1xdgDFuOi?Cj5TxCo>t z6YQzl+^!^Kyt=hP8YTC2X48Z6kwBxWvIBi!>SN|0Z7Osof~^iwm}ng|rSx25stp-$ zUAqHmF_EY7`NOY1u9M{vF4qs5P&>o5eGIt^fyjLu9Tnsmjm{vg)sbaeSb0z;Yw4t0 zw{-dwJ!2r67t_0-{#m)v(bNqniRzpunW!Gw>%zDFi<~L=5ZrCYU=HD`^vO%tKt2r^ zBWMG}BXj;v{qXhx!guuY4&sgM80ER9A8o(;G;b@z)$Do4R%iGtMD-8hHg!o+g89Yo zIGvAIw(9d!ilcHruF=yIMi5^)U`Cl)138lCLUe~Zd|T0!y-(LK?R@S6P9A#>@@L=n zzeL-{N-9TIU1lR4pWrDbPG595(TLG4^M_lLQ^eQ8kpm_(ve0qPEdY*ErqPz5Tj+aX z5u|3hrP!y`U$)Rq5VU&gT2=5I=um6MH%0bSQ<$1?XG|dk9G&ADZUG z@T*$bX7O)&6)X0D2%=o7#vmBuO&fudY)3cl#_vgI9bka(ON|WX4Wt_=Jzjo)5DN_x z2bYo=vDAIJbDcCf-Q2SCjS{@&1YLfbslEPF_uFwqH%-1+a;GwYp&~0atVPdiH`!0hq zY~L%Wkn9gJANxg{GS81c^ajt&b+AB#ud5-I6=8b*Q@E4Ds|;W3cvKhhJhL2+Sw~;5 zRW(_Idj^4rJx(p}bvyUNJ^g6!^3!&-0_(w1GZ&i`@srF}D(NfeOjRDamX56DWe*OtuphyB!{PWfe?*WUz1I$K# z9mp@e5q+b&yq7j&*5-yq^_G=}(`D&4gwP-gdNgSyWI((HCE_ndLeVq@M_0w8^-=W#Y9wztFZE;Qg68wBCz#XCU<6$91{C_@m4C^V1WWOV= zUJ#$lJC7`e-oc`*$M^R8PuQ6!!^X$7PH8uW)oaI1O178PJLtT87DUSp9?1gk`zY~4`@;1 zmKK?V6-yxUSPWA{b6_Mxj8O#wMI@aGGG#!jo;(Co3wJ!Etxi^;YLauhxMXETxMN8} z)R$+Y`d$aSB5F4+iy%V(r}1GmX~5#|k<4ArDVm=9h#3P5#)0R8XM zYQiB4;Eth8|I>Vhl`&TB8!zbpiOJ@QwIf{VcR1*Z;bm+MqOH2SJaVP) z@7N<+y`Ir1;XTq`pV}tD+a2Jz8BH%fsyzDVXdO=YGc3Ix9=N^-`;TBv;QlDzzNvYroc$ww%iuw2my@xgmwBu? z@HTOH`tamh@A#3nc=B0!M(}Ts;0KTI`-s{20@~rZhqYwdpx8V1%o_-|BJ<0{ zGF|r32-~iBbwLjwS9y@Agk4X-sKI-E25)PKAJ1+_&&Z%HLF8=--&ZW!IX%Aj@~#^5 z`S(%F%gN>&v3H+?j?-D7SrYl2@taLQ#;#-QqTLWn`foF!={kpt&4x5j(%^|oX?eN% zd+*yMc#`Zmn$cli;SB23{fZ12wRqop;J*lu*rdwCgTob?RR)xB z;Yi8%6gsz}7};o%6uxaHT)A!j=ZJx@EgHkDeTRkN`9$Jr9ocScDM_Q|I#%ZKsj>0( z65ACtN6K9CW3OhWYsfi=FWjTqJ!5$wq|WJ%=KS#(`w*J%4nW853!tk%(Yf=8iUYkM zpHYP}pV6oX?+nKE>|V|tq4m2W1N*JttUX3^XaZMrF|}`P8;)mt$U=9z>kb1t+&`)q zS<$Br4|b3*g{=e``0K)Yf0>>yi*P*|GHQIBebX1XfJ^SUn8~br_Bj8Tx^P?ho|5{p z86I=a?s{42*^9GoN$2^n_j;O-Zc%1ImfAb&YA`UTQ@w-j>J>EchTk34<--s%R*^i6 zOA?5a(mwh=>H75T;_melD7*{O4;nPR*ePG|iVk4Mjunr25V5EDh8%ltJTd>_xKVv! zVvc_~TRV|wZhvPk*rRmEBB&ghwcO@mb#na2gT0>&2(dKl%`jz>>53YiU8Yj*l;>i8 zs`iF5qfg#_&k)mGtYT-(EPUk?CRbYJ@uc&Y>mfQM4#XiGC)w>^x|fmBU`B1p z_IRDT)!A@))vOM|!GzU+zrxM@=yzCs&WIRuDgPHc7SZc8G1;xR4`a!n?e-{S4~~I+ zx*-e%6Vp-kSV@LoCeS~Op1#r6b$y(~bzMihc6Dv9bUnV-pQe<0;r+1V-Csm)HDGQ^ zrqh!C8kgJQ?V5Hh0ZTNn2zSU6(bu;SuWdIqr2|I;=iJTF%N)zij(rP0H^0AKU5oVf z?DnTXiz3TUTyd;KY%6Q_2Iqj7$BL}ffKo||DQES5qiA~F1;p)IZ01LrA(U3EP9?Rh zX|?!!Fl9h?eU&?VfJ)MTnL(8lD`F}*`3+EEZ(a89#GK8Y6#?lvlEBpM>8Sg+h$ucYnMdub0sf;r7fr#01lQ?T}?2jfV$kYr=bDnH} z$%rp%^=CRGG^nE5MzqEvaAadHlPAz>^tj4u!btSG&?*G5BGyaGW-sn#YEnFaSHE8| z;-j{KrLW%##L-9ZKyzdQ*bnKsLL8a@#-piZmfurVJ?)?tu3py)!7x81T6Jl2LD&q% z7kv(BydKbvq$R}^$7-^nr-jQK#UJ7q5}sKsL2Q&d{Ht6*qb*4~ubhurR>^P8U5hCK zPfpTxm#-pYL7CKGPhX_#xuz_Plp=Sp6%SZyS z35zj^UVPubWxxKr4**(n_;dE{mq>Wn<~3~OYoI76&`i zSHN}M8QV|jrv=+Ew|Nf#d^y>mV$oboQoN#aBsS^#FSUtGxcXxMrb@&2)gtOsDYn>5 z;_qr4iMsf-E7^^ii{Utkc^&0A4bU*ab0e_tES&3gcAyi_?X?>Ewp+1pocOyMR+k)5 z8V{(F0Bq}?6bv^P03jkdVE^S203xj=S-#kzRTpeDM=%F8E|8I7*BS&rE|~Llb8tXU zNzt6AE{GHy7;jV&wLJQlYLe^HNGDyb2|qvIR&|mi=206FkG?RkdU6Uvq?}_`$LSW! zySj{w{vNAp{$kH&mJQ3C1}j9TH5K#~xHFKk#K1yk|1E?YO&BQ#7&Kf7ArORv^xt{c zP=}F9s@uDPtC#ZnlrdmI)}43sv;G9X-rAy9=*L1RBetr1@DX6i2Q+aTnb4%0%^DkR z-!{Gq>ZOC*BDnwB)|{TV4AcpJ_dt?JDm1Ox>KP1%!V2j#6&dOok3smpKe-oqKqHj~ zK`qJ*OEI9T_Q?6|oe&|Xw@ixmH0dnjKMRp~#(TJVTWPv!V$>Z~LaZ}Z_;*^yA~WC( z%@=0lneOf>*uimNYjF%-J|9$-X*fTEJ{6i)XrJ3I)(E^n>UO$COie3)&lvx%l5cCR zA@p6Q-YPhbiB8Sm_#0xWg*CeoZODBal6g|$Kp9(!$qU+a!xVf8D|nl{44t?n-V4}r zDUJTV5Zu-%b!r0xwo#ou9LcwLib%2-4$&q?BQ8l|?w?K{gdA0#LH)g?Ts5`VDb^*; zcy;|0K378uHO;=*M8f@3<6iwl+)*;HK!d^OLb&5>`2J&#mX{2Px(1r+a6|3^8 z%gUCdr6>ckh?dm19E~w00qa2!Rpv%Qkb@U#Zy-!Ds%ZwfSI=yM&Wqmb>T zY~eu%?rG;l)e543f5`oRU|f&!wy$}r-%krNA2RgZIWv3)ZD056Bf`V!198gI#^_Hi zH^y!z`1|~ziH>okzXbQ-Romtd8wC7<{9{NzAT+3Rw__+t1z?$Q&B&ytmEawUt#>gSFIFy0dA02uYYEP9dsP z1iS$pGfTx;*yjYJuXP%K0|H}rq5yR2X*>)aUwW>l>pA7jrw_s)`sgiQ?3xm(uq9+G^?oD%={~CRA{jpFS9rGJ zsJC9*dgf^9T6?BizgO_EBiHAvZ7$Y#Nzf>6FVDIak9siKjW_I!WzhQc3dkS?Ydptk zJJYrr0M@5cExfEJ>U#}yqVep~GwWk)59;}Maj_^)x{MbRtE+iHNmCC4^M`JKrTGgA zHD9oftZ3N#e0Ro&_ZRG?+Hh*puCe8*EcgHRp)AWN`yScKHX{V|us848+}w49beuzj zZ#H+t)2QzxJngYQV}VX{GWHrU1=7}&*R8BInA_09vLFW3*?|_3`M1GL$QsRriOVqZ zZ@rhAU8w+yB3#;U3)sLLWv40?}!x+pBTm9nHE~Ia(&j zV_A)0I2KhAu>9~Ut!O+4QsLLrJT>KolJ6gA`;$D8&*VQ5r?g9%7mRB)35k$G5Zyu-(zC#yH9UUeP*>= z&tiR#$%3-eo5bBd3OF)p=p0bF-OmFNmYrp7bIU-*%#FOlw2xS=i`w#2K|$H4SPXKq`HTi0jXTkV~5JjjM~I#SQD<{ z=qq$~D;RSW0R&#F{LW|NO)kK~p8qUN@~aFRE>%#5ZuzNVz~&E4la0TeVP7?u;Zo1k zHaynpG2MMF;HSSC)5FE7l|DGK{#lrDLH7W!LH|b#NnObJw5NS@SM9VjlkVeo_CGM-uBp%?|}rXA=YU_Dt&ZjNF{W7S)D2g}cgSl<8k^*KfvMlbd`LQ0@g!_gsusECF^Q5i~8u!nB&o&x`r=X3E6+Oa{&gD6;=P4_7(BgP8*X> zjk>4|n;GRBN!{6)YnUJnPh%=!Y)~@_2ztkkPh%E^2F3z`E7kIl18{@VV7==A&z4Cq zg>ueM!R)qNR)i7Vi5gyL+XfcFu|{yaxqw#(CQ)sl24P?&rwrOB2Nz-zqppaW*E{ zP)j2#^8}->K9)pQyYg`6kk@Yd*@IKDLKt&I`8_c$!c`t5+mxCa-sB5DYNTPJ85O2+ zcgVGbh={a?6#=;ino8XRj+J9$xeJi`d_iQ>k!Ga}33NuF^Jfr`Y7?E}-9suUJXELn zcPRnWt++7<{cRMv1^D5=>}Pe&@j3c8ahR4$XPt=IYXBP4eG z?is3F5F(Dz5N4ZLAmJ^a@7uqXN@0a(NKC5QSrW`q7sCl{qfWq(ka0dVJmRyx9XAXn z>hXQ>5ls8?{I&khM-cOy_|0kG^M?;GW3kwx@`iA3Rl1{gi`4>C~~w6GPnipyGxW36zp0s1?yd;caVmN^=3|P$opk{^*H|WE2v| zDd)f2|8sk{DP+<{jaT<7K+)rT0(v9WreCnY&MtFw@E7YU$&w5erssSxYs*>E#^pWK zWdIICfc`7-w=2E3g&=+o#NW@s7=e^O3V^1XNX|oY#z)IHY>*qym@6nogBmmLIf*~l z2FMiF`*nv@8wRTw*Vk2#6+So~$vkSZ#o$!`ObLmlTk;tc?uej8>!*=oFaAnD=wQ%6%p^va4 zCQCss3N^~I$W~&YIF{qugnzgIk@Y>6Ke=x-0>|Cm+1?Rbbbvs%us;}5?V`tbhciIo zi&cwdbWR@YRHp1?yy9he-uj@rq%J`|Fyg2l$_~y~*qvUYK5yN%#Ti-t zjTks?2Iir$B<}T}7{SaUUQ^44_J^)6n^?bi-gq@?nSnEGboE#>At25@x#E3Ano>>dTHUE!JBAdExOm5;E%Ayt6u7{d`mw$?bL4i*1Ut#N zRdKS}4_a}h-QY?(3xUfoPr}j?=ZjP7k+=tdvZdPpjd{~0` zx>L=+nl}gqTFqLI#zrbcys;Vbhu7`sPcyMx;@E>>qWe{V0hHR~H?!3c5Z?zH%G*v& zxo*V#FUAUcLp~cV3YbZ5_Lj+tGxy@gsZty3%!=ucJJlc*m|j-tpF1KC?{^hPdBKNQ z0rvqKDaC@_MoOU~c0GYydv5yCgPc;BeGZ9$RhDV$pnO9Pwt8**$^$^QCms;{Pg*i% znk_ih_E_vw>7ytgP$tv+`_=x^!WY&pcyP3iS9UtE z{?_}GBl1?Of_D-WDNlz)r$>%xakdBJ1(m<>`iQW-Q5nCMD+x=|@(OD- zR#Q7Su^44xs#K8{BAtm-Sm09`asj%ArR*&a=DV(Qfkdc_YQS#msO z+>k`$XE|$Q2epa@H3;;Y_~rYEa-1#g!uy_MWnWh=Hu~j- zSVZc5=oN5&i>rxYt+lE`X-VmzmK8(LXH9%0?OjX+l*+DC+KV=E1U2JXD&UD$t8&82 zzgzTpVDVp9`fb=h%$G;?1r)-=sOyG*dcOznF&z0#B`!s=?)*v&{jA@=a&uc51%}1d zIq7o`;_2pGeLl|%3QYTqv!hIu;w76NGX7-|vq;CLgaJ8oAiHuRAA@if4{Csml1 znUSYPwRYNR8FXhucKj3fksY>!-(ep8{(^p%^yXt*+wK$p!~Ws}zkkcK=S%$orO&NR zam~ajy(ihdyJd`1YuEUcGxM+V5Ikv;Gs7e~{J;9g*-GmmV@dguy@s*C1HvB@oux<~c|jvo$}qrIDa?sYG9&-GdO|7=EYUSbUF~Vh>W*g)R4` zn%!D8O8pGffL>E&V4H-~qRA0OJWtcg6#8qrr$I56efy1+Eo_~&WczTjCJPeD6^ZAbKIZU_v`NbPIS0j$B zD8Kx98=ZYTKS@mJhG5L|(c~b$#p9*Y{c|^&VeV<-+S$q)^X{izMqw-e@N|d9>`$Dh z1^M$({4=9`VOWB9Y>NJejG&|FRG*~E?0aJ<{o%@Wt~KtI0sqs@tk8z8%WLBL3z#}D z@|Big|Ca-1zu!OQ>Uw{ywMK3VedZ+df8+-l#Mt_W>pA$u6my0C#FB$n{@{z)pM6d@ zCIFfB8BtF_^>6>K_fi)!--4nHveNZ{PB!qxebmAcwE7EjuwioA#?VVw-yY=_9C@T? zgtYKFkz3PCEb1-a6zkI>uEWOtY@g+VQBh_UD|_9v5a*g=r{Cg|SpX)n+|D(nORtjM zMTv%Q10i*9zB**HwNs9$H`C6dXRN98l`Ho-21}& zgy?@mm_07Vs-6DK6Dw_|=l!l`ybMlT$EDJOl|VvcbVx;^jK73&9)jaknbH)`6bF7G zv+UQSb*As_6sDUU(iqGr=SmmIIO0;Oeo67nLVQR4hmt_6QA(8^oxw92oG>9C)~40S zRMV_IaASGL0~fb{vg@%fb1A1j{m8P5T+BECaZBZN;OQS_a8CwKd1a((AOy#b`XdXP1t1ss=-x+?^r@&qoeejc*u8?@BAc{pouJ zWt$o=zDxD2k2Ei*opGZU7uo%40y~!;YsrmIfyk_vExtSlrpcR#zDW+1-)bKxJ1!0g z@TzGqcx~oSb6`3T#T01v7Hg6o{m-D&z5E8aR@o>|Uu+Hz&YNYtZ9&xk&5 zL@DeP+czL@*s+}dwtv8^ynPBdZS}|9A2{TH-q5^(@)+qqT59_e>hFX)R8GY09~+&8 z=dhdZ{v1jwoIWXQM=$R^6Yg5#UqN~q1D7j3C_&vS}YY0tT3z2FPK4jgrds$by>++slHd->h9L#^?$azed6 zilsu;5Ffr;oM4x!!a3?QVJfla;7fO6eN~t_U1m}5hzb|@I#8saWa(xPQqk`tq>EGF zr8}+>|1ip`B_XlT@Y6UK+A%co!a_005SS-E$Dk1}D*xd|mKu@9831Ri8+xMB6p~TC zEdW9b%{C=pSbL$*JcX*Lwd!^qgb$!B=}`gEfGkVB^$1&Dd=87v6b1 z3#o!{|EACGC08}%^5gP-r5g9ya}#>}m(7kbJ3OY|r5EnCrn_SP>05q(4=1kvjK#>` zo#U5>@WRn zFD|x3diiv?=9T&byAJo94)Zr>J*Zk|ZN+)5XNN*n`zgo^T#rK}UFKX1pQH)5qU)8g zynhM$)eb^gI4-((bob*HdfuNfG;KuNwO+KWRloH7HvRU@=J3qf|7f@kk!$bDUgXn$ zo^cz~sY7q$6T5<%Y0G42_kRU%#jGlcl>862mzTzrRaDG3AW1#*IwzFm^kBe|72UU% zLAN-wgesL!EFjuDwd;hbleo<WoEJaF2S6Gt zJhULT=fkLinUs6*E2=FEEnT5x9e;tC%xZ#&RFOg)d0e=J!X4?PGQE1y!7ghVZ~WA^ z!LgiS#hacKRM%$yoUCD3Qpf5le0Ha(u@j1ZK@yWdVrk2St*8U zb3FpvA`rQsIakEU7uSB&yx`3*>f*nTuRI^-65%@`T6R3&*jT!0AFN$^^+bGe(w%bR z_#?90^YlVb=do^V?zi2$^OxtEVFp7M`_AdQxOm(q&z)dwzK;tMLeoDlw@CE;hbdbZ z0zgf{-7z*!x*NWzj@={9a1AnfYz1WQJAgLf9niBrN0Ben#jE z<*c;T13TNOU$qysY5BZaxv=`k%W`tk02`NDe=)wZ&O`b#lSQ?-8u%ss!Cb2P=QA8p z3+Xl}T4?yCzdap2`-WL_jJQ!&{V%kPz$OR)p!-M*@`ZH7gVt0eSrT^ja^`BECfo{p z^2r6^y0X}wF*wXj)Fy^$`=|YlRJ!jRpUUvyv1AFeR`xVhP{zr-3PJQ|WC*WE`WYvq zW>Rq;Bz_$BmQ?hG^-to!e#n#@%s?uoNW9zNzOk0>-TYDf;KbrYNtK7_~!Txls*kjyN(-y&aRiz21l+)4~i#CRo52@(y#)Fw@ULXwU_-6+`}d zdf|YxdjRvwi$q=7ePNY|ekZ+d>O2E-FsN-;Wc|KWBwAeoi48}--bfXA-F+-T7!8d3 zlX2J-l!xct|5fP9H<5fI*ZYx0AEwV|Yzoe6N`Lj(EgtE2D3QHKkd_+KW7eI@YK#8| zz85zlbX!?XpX61m%hX?AKl2VJ_b*I!^ zs-GYl7}`mT84sKaUOXTcKlhNPiKlV_h zIItpqjNEzo3`Nk&CTLRYLU^aflu_LFTT0Gn&SWPf=wth&33eKX=|}vV_Y=@4HAc)| z`G!PcYAL^k1VF;|6V0ewB9HhCIchT*TvI`Vq^R{u5(+4VvRVjiD)Kvjoe~YH)qb-( zaffx|Awa!_PYumI_B-=lK0AYR>mL>SiG)tVFxtn+sjK!E1b+{nOr0VE_jyjYLa3dKis{wiZ~Y{rznm|G&T$3Z zD72n`WH_Y=UGi7#N};z6L`i34o#AReKRo*QYp_5~M|tB#T%0WC2&IO&WQ_jS>1GZ9 zEsRuZeSWkVovV~2B62?zCd^;^d`En2ymN8CQ{(Uw@83Qr$Gg&9F`P4?X7-t-7z`K*o_;}hI(7>+`7f%8{HA{r^CNoz%7$3RmQi$wK|#!dx3 z7%-Ihv9IEqQ)Okz{UP-CP4?jQ^QQ}!3;8Z|5|P$23Zcl??1PN)r&n}H!Pjor&58!! z0w&Hp!fXf~nZEwAV(|rLJM`N|5F!M8LaPeP8w>@d0duRw*>=_J^UM(TZg;=RbbfA{ zFc8^j_rzZ{e@zrsQ16O3oi`07y|=?Zu)0bbY4#pZ5?A$y?6ocM;G(xLLSnU%oOBpgwBvp?yw z(KL;K1;OnpnSN$0Gq4ZWr21Xs0VewV%N6wM`FZ~RWxdkW^BU28PpH2n zgiPwpa*WrHhIC1*sG`IFdu`TdtmxZxJdVsB9w~)<`uY@KP)^$^s{KQU+`W_ys;^!? z4F63qV=a2P%dArmZ1!dlS9`zE65rkU@!FP9!>$m_e5=}B7Xk7m+EgG{ zl$J)Xzdz9rIz0!%$3e#lL)V3c;3m(3|KPZA8Rru_D(`y_>ckjPd3!}BgC9>(Tv-hY zrnzR>*hHd1?O!f+AzB|) z4jt9Je+ECD4bj*)-M-0MC8Rz^V|Cw_$+-RoNcVz~&)z?G;v5mJ_S_h#Y&gPz(te(X zxjW4*oEkUnKx;akCku6r+xw>!Hyo|cYC*NW{xr7T30uGO#YrOC;E8|vI@Iwzx?@}f zU9eM3=_y*FWfN#wsbk!k*jybZcvo4lpoM=($H94z(C{wT8VbE7*N*~5c-Nz)|!X|!U zmH-k&d%`discGF7o0iSC6a}GOH_|Fkj$u-cXjEYO!LKakzC*S{3Y6vVQ68{i4W=i` z-b*3BYf$Bk1l)~m6~KNs%>L&|rcH%x_?|A2}2<-6E@yI|c}^>W(>7%Q!`g1FQV zY1Z#6BRO+tQkU?lW0vOXjQjfCzL}Agsv{i$(8BV)YO7!vbLoRV$?pire0PSb8V^HI z-D1N{;9^l;6LloE34N{LI~~3k@a6f%J)kB2vTg8**yoExgLjJ^`@b)110a%sDu8@?2l%y_l?@QA5vCr5DDqu7z9j0oje zt{L=RKuA?YpCXr|1OaQzk*0>*%&f_48}?+g4W_bQs~!E)D6vE`^N_DoDLNfS{;67K zQ0AgC+2cM=Ka7|Jv!j7tIi71ESVn6-ISTsx^ZW+t!E;Gvx-@Pc2A{+g_*q!1hu_IN z+=lM`g-RAN*KfnhULV2k_1nhKh63}u|_pN5JP*(`Xt3GP!m}Y9r zd?nWUPXb;Xy~PaDIzCioEvoAU@a^N$f?`F(fLc2i7*r7ZLTnx!b8{UdD@_rUS?4nP56uavS5P2Q_jlw5 z#fp_i9I9cv(aO?ABg0XHfC7_dbF?k4J$lbAjXAZ)2q~_Sws1vA(_b zXtO}jHLzRlq#K#y7*NlfT1t1X5F{dZlYXsw@`{0)=`V&MYHDai9%xRz?|Y|dkBP;H zj*5ny!!c(bcox}KX1LVBJiS@kMqbu#DR}0QpheX5_jm-8ypfif1oCsd@bOUJUS0z~ z?Sy2rx*xuYcV)2Xly*VD+h3&zf@4EMc49TbqG1tzkwejoAx-x5>QmQb!;S!fvp?PJLI)`~F=?%4zSyfi=X6aK=?c490i5 zDEAH?f$|3mg7H9Zfhp0POZdQ*HD)eGqe0WzByXj-DW!|c)*7UP?BP*m(PwY;Tez4^ zn}n3ZWUWSAFo&JN&b!Ojnt=D#e9<@t6$C_>bLGK!|O?o!eu=!o=xq(Q*#_i)qXZr!QVN7li|c(db7u=?zIL3JzZfI0DY z<;CgBb+0~&4z|nFT0uF|@@UoUoe*2d+|1H(oXTUWYpRvm4g)pTC64dXzK6n8)Or4RV%~M(dpKU5nD2Yw`jk$m~t?b#SaSWOWbsuk-A)lah*iA*6lQGQu1%NL}eUau5+DkPoVQ#&?rsd;w$>92&izYzDi%N(P|UR zTQpx1ictDT6=>AxDbhq15V1!lC<6C@0^gdI4yc%zaB$aWKz8I6A*cTTFff44z5_OE z3LE!IcsS!!0SeIq!3y8{X1PYzt_Usjp%r6`Mo;Epvw@ z@@j};(o0SwyCG|<^K)t>b9LP`gqAOTd&rA6K*4ImSvf{mW}w?fi+ z_q#H_d|Lo%fa5q+5vtvRQ9gk`$b~t>5-?N|*wV_6r_Aj3>Aw{G~_exS8*e;)cfc+WgYOR>t;vd^|6h_86%De7%$$A;$0grGpoR&XWI5 z9_-v9QXk@oLG2|-CA~Gtq0Ax_LSHC=)TE!kK9V2ZHqW%zSEz>f^V&I3rke@p% zU8V`JcIi-PmX_SHzKL5}TMy|0icAze+NtGC20#PD-#|AE(F6zt{?sazogzv2W|DGX zQ78i{9*F~`hv`4eC)IN&*yigq>KHAbgDYsuU^ zj3)ELag_B;3*4dR`_L}50%J@vi-ITWFq%n)=V3g575u7CCQ3Vv02^{mWVUb@Vk(H} zxjDp$Wv|xws;F_q7kye1Y=t<|47C;$FICWBBE}6;kw(8GVkP?Vik|xi3WfJTNUTes zCbco}2JT=3f5^-AkSi!mTiIo1qS9=$Ct;ZIr^^3--=gQ?Eq(6RPfLQ3g)bHu3tx?2 z2cV4@miB6vjY=fDmeTum=M0sQFXuJ}+f2+3LT?i!HS!_Ct3EaGrZ$kRD)#=v1@Ng` z5v!Rrc)z<`WF@XXn?bZcKC9=Zi6NPk0b>OlW*dTnJK8|BzOirZ2(>!DOdnnn64oe8Gj~q$apn&C!v;0}OK|fsrkD z+RRv!2YSoAqfR#~D+;9p#7yToB{4S1-tsd#cpD5z717!DBWY4^J+uxZFVzEm+8%6^ zdd;%`$Q)x}MFz#07JITl4?dAkVdkilHw{t5ytcf2w2JC4eV>h!B(NCiQKXRmrPBYROVokX?+U}E4l$5 zN-*3TfTs?yvSQnfnB*OX(qRBb6pUv7tC_j4dBW7gnkEiqR76C%`IM(7h4a}R84aYH z+Xj2i4=TI7p(TIe0m_g2#fl$;IZxTHRvbjue9b1WDUjC8sSA+Ds=EfJBIl#v0RNk* zUtM(koI3FO6u7^&c74k48D_;uM`M}*Ak=0W90NdC03zmCi1OA;5ufti0~~yucniEqO^rge@9{2tb^c5xar$dNEkj&jjm;d$1Kf476d*$b;V{w>^EM%| zxD7z2N}VW^X>$dar5^)rSnH%h zK`}Y`PgGs-9~k(<8I9uhrGrc zeJ~FuWV87RR}nRWS16~UGK*nvM-p+ZFtg7KH}OrU>8E-6=}&;@xwceYaXu$i=GRi)AED0COjNA`;eKse+lL#a z1dLmr6XhFG-dI3)k1ZBkQ=#k5^8dQH&wpH8Ao^S9Jo)_Z0yr8{y6PXoiv)r|X~sJi z^);;hU@O~Mjsx$d!NW2uystmMTAO?z9R2>CmZ_FCP9{z=E;GCxuav*z&_a5i~3!I+CNwioVkO zv@T60TEHYakzSg#Jf|=u4RBs4dIBUFf?WOxxR~S-DE;5ZEF&yB7~4=IUt*3g=;CV# zd#n?o(;KFu-kdPhCC?s)k_*C7fMvAOvSBLiBLd#?PdZG!V zgzfoUo$_DMmI$k zf{=U!BgLU9&2t*rbE$-f_v-94yftPFYwc_(3X71*g%adr@i26u0h?UFy3|`E+^G?@cq~U`0 z*x>R))Opw5kY5)?Ta{veS>+CiEntc5EGf+uT1GeCqfn?^Q_9ZUS`%@t*BP`#KO1ti zo;)xE_{-hKyZx`KvXYl5a-DNRir-|9o!2jY!rDwH|QdWT!Hu5GSNgK9R4i1xyN(74EpIgP$%HZRM)u*68?d zf-yY%^bq!Y=u(KmB#)v`{x>Jr4Y7=)myfqSh@^(%stv6&i3gC-cCPQe@Eh)5fg%cf3`FX+a=+hb zV~O2K@nVCX6lM!*m)yViCvEiAHOyL8;P6@apVW@YJnPTn9I~SDEuwUjL<+n7+7t=< zt6)OczO#KCL8L@34vu?QZz(V)p(#U%1;PglINx!jsd&djsooOp`N3$h1jl(&7hRI_ z5gHG59CA{nC$B+V-J-S_+v=i0DAKoNLCE0~lfZyIv#afM)vy~%b%kHG0CPV_5(z?P zN;=1OT-@()2+NV4t6<}4{QFn8R80v>50eXt=zwRGpucNhGBO~Or|Fl~e3Vr2pItD* zYTtdFh|;EJOHk=o>e|Gp{(5_Z0*OO@6>NJx!c4!Fc!f7`4D%J&#flk@}Aj1PPXy4}r; zV&g|^5XPd%8vwv)XlAqV-i5(Kl0sv*t<{OX_H%UD8a~dw+56Imf}+Dm`TmXi?&)y5 zNAiPrM@st{PfB}k(_)4Cvv@!PRrt{m#sM~ zxyEsK7erYzyMLw!kw;gp3l~ymmA;#)m+bdFGm_%dc7A$U{)KeY+mhm~^bSujxc;%Y zp(@j0Cb`##qM{P06B9q@j3~TsDPaL@^+t2kz%Ii-v`vf+IEGbWLC=fWpt#+ucq*Pk z37gM8dUNr+vbf>GH49HXqdUd#4BZW(5O>R1+4Kqn%3*B-_-N}5NA((crzMu=_GiDY ze$>ZDq%d<~ew}F!D2vtVg1P1(v!kmYMal1J%6*&qYEK3D&UvFLEgb_Q+PhFmN6{%r zV!jN$HAzyA{fZFj>3(2c1aDL=mo#{8SiyK=^3g{~|8`Z)gEy6^3E|K6dT9PmvE{hc zB#+>@^zTp*46Y1d(G6C|rA)ebspy`%wD&Wu=$(s;N^BN3C$5TVF!#+PNr=u=uO3;U z3v;Cq=AA0i7;&XJ33Kz#^PpuAmI!x_#Uhf*cdh!Z4fA;&S5GtH8`YTXlq{DXih%!v z_2OF)8A4A6#z|qof<_|gl>Sij-e-2l0R35AL61#_9LC*G9jTS}`W^ zkaaGVsqOF}*P*q*#{qYnQG5(5D}Bl(Xj}mv$RAZN`~UOtabuJ(d`_s`t2Eh&xR`N8 z#}0Nrx(DnVm1~jJK=?@{Axn0P$J^)oGS1{5wRmD)ujis&Qpp*ou^U+W+$Nx=I!aIn zzM8SdbB3>PZ?rQoTbjc|y$VHLmOS0dP*^ow(hS%sdwZ6yPLF$Ug`DGoAc=8UDUIHt zB!9QWL?}9z78G|$_R;+g;d$wFN*;Z@{an9z`q$;SP<$|Ob5a&CFvHQ`40Lcs0nBoY z4ak4#JbOe$>TwzwL5pp2ST}?>ipk6?&aY!@i*{uRYb9K6ZBFWzguOwiHpSCTRrCY# zDaWeRX2fEF%96L=v-Itoa}-OWIA}(q7|nnfA9Q`*!1G=8*NqA`#C?%*P(uInk|q@A z<+NQ?ot@*V3kFsKa1$)?IWergVT_gIff?il{oqed`Q>7E99KxdmLj(IE@X-+P)Axo9X(|Zi>cB?$v_+Bv1nq>Eu+G$@&=Svy;%UrP8*jz4QW`{CvAfH>v zAb5K2z{dB6#s^_+(EP(|Mxd}KK%`dE42oTA_;?0;nb)7!e17!9tlZRv7|UjK$U2-Y z^yzY*#O)*{RIw z=(&#Rv2PI~YB|}AIKghrOxwxkj|OHMd$o1R+u!e=XosTLspYjP|Hz^x4~?f9%v07H z_IqnEbaTjrqNg`C)0B~7YdaMT#X|bY(-2Ek-~B&7$E5CaU?@6hHD@13CG-mS8<7$^ zjVZ~hn^u{I3-RVu!VFKVfA5bUq)`4IXHXRbo2LnB>KJLV+$&IUzgoe5G6K&(uD&f&XN8$1eGOF6t&s(?AO zxnd62RP=MbNC|sOhW1WIBqE@x6XO}CZaLfh%H@YEdQqjfe%YMPHvQl{U|bUyAv7`w zy0s`z8IQGyk)3uVXq&K;lX9Cw7@tBZty2JT%u9v|v3+Vt7@g$i0DA>i6@`m;Qf z3r?X1L`OnIiptOpPkBLLB5z~G|9OEG#Ijw-wy>N;l38X`A+z#8TPPZnRVBQ5r@&6V z6L|jP!~JX5bI8@LwOLxUOk-rL%gS?d}&1uAbBIR1MqDmTyuS zmyy{*gJR~>)dP_!Dk%T;j-ty4%I{?axm9Vo^hgL6s}w^y;-N0Mr@{J%*CeFuE1gb{ zuDYRy(9f+=kC5#4&k4|;gJA)tz(#N-V#NWrrzS={%Ms0m| z$g?}t(S_h@#PTf$*u28+bEXU|wlE!Is%*dLYEzdBUy>IcNCz6zD0*Dq{u^B&tlxyh z$xOW!XIl!oLIBNj%F&M?F@nfLyD?5iAjSd)5w6qQlmh%0@n8mQ=|x&m|Jfd2@1hJP zIv_XQr18V=Eb@Vjj2WU*C>l_rZt38)%s5!vJOW%n&Qx#DWx<2%{Pc%y!so{|c?TjW zvc-n3bVjt-xad?3Da#*rEp`RnJ}FkR=+xmg#0JGQ1pbME4u${CXkeH&FeS*x#b9e( zhIhCvsem<`8g7+PT5@IIACsVF<7(7>T4B{H7bu*K}TTjt}j`c#n_Tnz7D$C-oA_uF4MtNIRU z%6f@s8**DM{}>+^-b|w3{O|0^5Gfp3{%GuJ0WvLrXH^j>ik3r^YgX)G)|aETbxPk8 zhaB`O?gsq&EN$y<)nX#KPP(mZp^_fNIz@~nX;^q54ON4(;t=G-1IwT0oT(D7x7y8g znv1Tv>rkwZ!!x|tG#mWsrdj0E8(uFV9QyVON@uF?UyMuNyD8Fo>Hu$75s_+GBQ|1j zo@{%UGj$|bzAN=Mp ztMqKLQ&ULo^5$z2PVN@`ig`UnS>tzm)T7EOWR~Yjrel}p*Lu@>Mg_5C zmbqp@eUZy2W_oR*#l>rSEwtpau!_aY%tnL7W6tB7i@R=4;I2ie6D##P(vbB4r;7OB zscH{sAW#n@*Ih1FF>hQQ4D@!DF5Hw)H(UBT4Y_PvNI&?@87Jk!%K`Jb){$Y!SO*g` zy4x@L4u1PY31g0FQR~zhUi)DR7wvD?nHs3K`I$vg8Hge^at2K9kcfTv|J)Xw?L7cc`v-Gofyb&_wI+}HQ zZB|l`CPTAvN?AU%KVllOYbmJ6`_nuahQ>YrfOY1;|DNgCR*l%;CB)bup?>?`&0ONn zhvW=hw@qc=Q*afp1(}Tczf*v1T3-cp$o-h z1LPAtGu@-i^4Sb1cnC!rkPn%+R$Pttw-kPkMx-rqS9|v1)?IcFeDg&;ql?e~?ZXtE zKAJsk>*rOm)UFV(d_k#`gNG*y+`+^@Q^gt?|2tRi+6WYCmORwMUfM-9njm3JQEr}* zvbRiN9*S*G{a)br!~(G9kHrZ{y@}kHg0zZ+pi7N+xL{*&Fn1P_U?07hRJgXe8rN`Z ze^X=vLS;o~oMhASk>%^hM@#J1^p6nO2PLJ-n7VY_T35Dy@k8Pt2QpvGkbh2&KD8`Z zCE&3~T=T}jdO5za5c*6>QP4QFR&7qAp5N^wTnv4l8<^Qq3hUEc#0Cu z#*WG$CQZP|n|n$)xXY22>H2WIdmn5)1yeW7olxg4RP1-B)$dS-Ko&71_0bw8-CPYP z>cg>>mH=UB6!vQ1aOJ6f2)zEz`Osz!_HHPOZ}3R;8R){R!?_HWk8iibmsAqh#pJUB z@*`S%7|p8_qR(@}7mchn`lwH8?0R^u2D~dqu|^lono?s(<7)8yK6iWIv1y!nsW+lY zfA2!^kAAT}_J61#V+k;dkcqA*^9EysnF52ub4`7Oq9})P>kF2YkvWF1gHGB!Yq(N} zBNa&OgvJbs%J(S`{6Xqc@R&Qf1>R3iPN}z>tjkk2Do z!7wm^(|R85Ocor3@ZTQDC5wl-+0|fmw<1Z<_0~a4ds}0vw;J^IePXuPi6c15cJ)ZtD%Ne&;%|@;nc(CL90(TCXP%=mAD= zDeq|+K3=Eff|xdl8_@Fl2L~AHO?I8J{J!WQ^cO-TU;B(x0HM0YIx>(G6}|L~->Jm_ zY4dgLR3EuE+nmfk9?g0maXuVzVQ$EhU9bi6*;GBhqsUmkOMEp(nq&xZB;WT%ShPh- z#G)r@=&X22;{Ak7rKK?BB=D7XM#78caiFz-ytIO&nno2v>P={O0^cz`x+amh2fiZx z6B;}vRGdgj+OiT2lYD)Y<$h$+;NIe%C2LdI+c5o{51=_ORXW{~)r|Ouh0)q^UmudO z`n_8r+Tc^B99i1kjEb}8g;+OmF&%vTXCe?yVdAf2pdYhwG<>)DZHx~9BOH&`RxZ)W z)o65mlRm$YqIMdwVXgM;s_S$t7{9>|c4Qv)!T z?(Qx@gS$&`cMTex!F34k?hH2Qoqgop=YE(UFwa`6ySlo%+6Au?ebH_c_{ZIV*#6k( z$6Z#DdThVF9$X?Sh`gyt)U29^2@7wt>OotrJt$6w_Vm_&L%x zDY&3GAv&F8&RU-gtYyOd0SGDBVO=bcyJ=6jMkb>Sy3ja$|5cun(-y55z05CNVgVq> zPMT_od?uX$NTJj#AyA2{pKa#y#V~$~{h2+fY|Y(fU@EXA{@dgTkc?)ow1on(Ttc58 zTW4E2HwQa~qw~ykT@xPu$GSi)GK`TQzELaT{RPza9bX%jqT<82QB~Ud3iE*ob!c#a zB$n$vNtW-OaIfJeVET~E%-|zH=U8wiUWaHRlg@fIZ3@j(`*|c9P1aDeY15Jijq(ol z>KsFjo-Bc}$D-W|Ew?7G8+#3vESUfY(MS``V?Hbr&I*oe5s zCv2mhlZPDz#84y?+oWD-u@x9oA|5mTo=gC8cn!%b5wwRxoB? zcM-H(`9=QF(k=+%w& zn5gw0{$wB-2G9y9$IkwOB~v<;JQ&8;wL(!pj8eyM;l?4#&;o2J1J^cTUR<Du? z-tEme>CiGlt~wh?Mt|zmR2GZWlb`_bh_-dL2C2pPvGv1W(~J$OXWnOBy)M3-?>jSk?tgL>EE#c7=`{UBW-&fROKKbwysQ#w6JfqV(ovSz(+9cg;`x#jjSs5o&6tiGH=)*2DHwbZ09K4D*bpGpV7F01Mn`wFX3}Oic zCv{YrUJ_$k;ne8LmqdBY_m`Dj-tdCxDWmZdWBn}lv|n<)^AoagKD_N?)kSTB%*3Fqnk zpe^HFOS0E0j>WYF{owDu{ae{2@k$Q@8J)Ul$Ii-#JLsEFhsIe1(pWS`^oa&SUkGz(T=g&Ry%&_UBVUx{sQIR7!vu)2B zeP8Y@4rEs*L7Jvh;faI_NUSyXvu#X&pbz<`qW0XPC99~YVsdD4Hq6=HPO|)oA$q3B zXc`Dbs;LPc;2nC;PUnKx{ZHs^m;4_>GR1bne!$1g6nw18+Z!@oG$L!2X}+b0T~nw0&&4XOq`Ye)a4uO@Ey~+N%L48~{I3D!gV*isbH4H8FNyv=e=k8BA>1m(kjr!^cnA5Esp71F3|?peQ8DCdX}Z_qkvUrPODBYZ z+oLzMCqKu5Z#7nFCu{?Wro3Zb-ZKMq;?qp^p>xMy%fy?O2i=qr-#h-`{@DdcdVpT+ zb#+6-2lkcfU*Cvx7+N2Y+6M{?_NFIxGv#rr(o$GmdTva*)Z}~oA;n#L&XOqEU?_x9 z&?A;!Z8Ug`aQ;sb5J_lfKnPSS14%J_WoAfGP!Mwoyk?zKC-zttE15RBTZ-w~AUoOH zo*+nuV*l7^$_-66txcaxvykV$oxv|NTrk6%5`%C#N>P8Qb*3Nf?LAaU`Rwn(fDJVv zQacw|k0OsR2&_Nf0=v;3?}Pwib3YjdO%n;9iWXm`;?HkYsAS}+8q_JE zkgTTAxkHKw!NOu(G)=2yOH>_no|sSfr%#P!1d;7cU@aTTY?dC)1{r7d&4>|*4f$sm zrijsH;FBVLJzn2IfRc83J+EM3nFK>_uV-h z4KB6^Vpv2rjh^L)cg3WXXeQ@cxn7agG&~#>D)COBw^D7Ip6)ZsFyqF`9d}aLW1BQY zPgWb}-Dd`=;CEc~fqtWsGXK#P@l2RQ7^1ppR4UA5O(`6*9hWyQ>E7iLbz;t&PxN1r zFX}oaMDlT0CLoHB9CJjrY3m#w3FoLNVmO|=I6*M0@wtfpEIoi%$}w9u)hw+~3U&gG z%ANl;!s-a?5*z8N2rKnqu}HWsNewAn9mt`4PhOz2sK$_0Ugq7VUy`Kbw1p}(G1x#Z%0|T3AvCU9Bi2&5tjM@1_~({mD3f3HjGCfZb&y}p z=wvk6f+U@;PzIw6KUJ%tko-btq{%_b6HC$YXkY#pmJ~Exh`siam{6wL^}bI&8igawX?eww;L~93!fy1l^0zJ!jdie?Ff;3_4H~ zotobdJxHCMz-1jHP-`Ti=Ql>($DTWTSgwIAuF{@}p1AQ&B1FnU4G=+GvOAAoNWP5k zjaQdC5R$7vhowJ4QBAYq7{@5WAShQOKcPO@kc-`5-QRx;dZXQ+`Qe&3#X7(ctC zp{V&F?c^xCa+Qj)w`@Z?^73__e@0~tBQ&72#qN#1k0$M6>NemZcsKMr5L!KbmX>C><;o7HG3|;%*>{^>yH4}c|ckPlJ1`p=?`+e`OLn^t?SB8*8&h&KuA zd$ZL08;>!!Sz6dU&J_iGV5E^+-w^zF^&|r61F{?8d@}q>x~7Tmb;HPKw~Ql+@wz$Mk_J*mdXC4t< z{CG}|C2?c@=9y!WUF51!3+A-_`)C@cYtBNgFC+pH#6CypGCJc@Ni&T&&sb;FM!#%n zo((_Ptfu+@%I9rF33(TbAWN{kawd_=Gr;CMef)Ow=usn$|2;HO*Ya;0ZL+rwt|@nD zXj|_QeJF3|4!G_yAy<$E$vI$X?PO=5QgfS2<=b$Fz?H?GU-qXLA_ka$#=iTq`MBm@ezRtFhZmoG&Vje~$86FR<{N~OU zDO(maTt6f6$RX@Y{MB>wp0_6kVep=%<1@43zs=0r zUoKGIsSseJdEF`KeKXr%uqS407RJiZ=rT5(^-H$ju75;8qL&t0HaYMZ+!p;Sy3|(= zdvEY1YNP~tVw>H+DSqmP_1Mb8+r0YxqS5yd^+NOX_A*eYA_=)9Z2NQyf$=YkNZH0S z8E3!giJ*k{y$>&*@qA1NVxQTf)dkBEzBliYwjMX4wXOyKw`Q8qq=*n?@iCy%<><6q zF{`sgmBZB-M{``_IAqXb3=5r}(!H3KpZqxfaX-EDWoy+|f_^PfkQaNU-6E6b^v*aC zx3?)e4(t6+ny~AkTAto&rC8OGK(R&VacbK%&3 ze^O&R94752KS*s!F+I%+#Vq${*q=S+L`^XiFCWiLuOw?H$%TDmXD;c@-qO)uV=??? z$OSlI)1LoYJla(z;zov`mh8j^%G05;*f&Vtm`OCx+hC=_k14%(yq$m=P3m#aV5IDD zE-uGc>?ZhLV?~aAFXVz>yO4){Q#pb_j(w4=8YNf#xbBfYF%Z9@D_(R(D@ek1R^;KK z(rsY1?(=uQ&n7n>N<^We#pcDkyB`$tVby=AsoJf%8R}Eb%d{Y&91x*k&+3rsdQP9* zl{2N;BbgG6XUhZT1*54o3PXwSI5(VVyMufi6{8LF=4#b-ntSk#$*zMud^01^NCEu< z^Vp=C6?Zx4JClhlVi|>plj?@qwhyAozR5_R}_PsX{|kKfkc2G4QZYE zRDK|ut&MSN^`v8jv2E>7XYi{Ff%n4NjtC(zepRw{ssp}|AY^G&E?vsw0@Ycy=6+8b9q81(x4$Txz|8)%K;@M%8JpS*`$l z;yJ?7!Bn}&-OJEqdXR4WeN0hXr~I1TXP$v?fR=#N&Q7N4ZWup6{Mmb7$13sWJK0qd z2{!R(uvWfcOyeiJ^eNnTe;X1~U&4wgzosaUur}{){{RGUUjx!GbP$9o9lZNQ{^>vU z?;xQ|^1)Yw;$$&^nRhVj4P;vYNFvmsI*L`f(M$8CFZ~K6m~ac8cERy-57$rFFDsh! z7K2*Ma&<>Ybp$%7UTU%m3XN}U&~o5iZHd_SXm3W?VAFde*)c7gk`=?Q`5?3lCh*4# z3z~7BeY0=-R_g3FVDpmi^voC}}`QCJ#I$qCXwwEDE9v1r^;pHC^s=jJ!#8|un*|6v>zDqhZ*GSsw6 zF4b6A-es>t&CQlb0cUmd;BmNCSuvRv)(tc|4Fm?zt0y|jdT+l%*p#}(!d-6}1iDbI z6xie)ZlA|13^Y>Vj@EVPf04Spiwhy}^zPugaq<(SKn&em7mVprmeC)x&}q(-alIvW z%AaBQ{^8-CExUJE_?aZP`a|d+OKwJfjS8ejBC)hdr32gNx5U#kht}EN$45EM!o}VS zBldV=RB-|=HR=23ZNIl}UF8`8#T-!kM6yL5)v6_A+qW8Hef^7XZO2%8QZ5(Y=cNakF zF;XPao#ocZq*T>#5TG-(z!>{?UVgiNrvX4o#Uyre<9rYCKoNL_BPLC5jGaphHyDAA zUz=i!|1s6uZ|Zc^;ijM7<1outV)A*bV%bQQM_cXOp`rDD{<|Xs^Co4=%h51X2V|3U zs24Hl2VlpA%;Cq)>E4oI;1Esz%bERViR-^=N9M?8V}GHcwPqS+;hp!_bs9?BkWB4Lo3uv$uMP-#u#InSdK&F&i% zJF=pf=XUUF0TNz!Krw&g3|vovTsq0Vb@9(rcGyZtA|#7p4E@%)yw)+-_h|2yTp0{8 z!4lJJzHy~wU7S*lJUz0~1)je1)BUGO-UVkp;M2gLi`x4*xrzCjS(>GWUyEEeFe+I| zj$QDL5&E2yIm?g>Ug2ZXy>8l5AGZ(IyyCdAS-^7z{phlNsVg^0?R?f5`KC(1N?7aa zz7ajGDweNOl46n>2U>Wo2J7-m^Uw9QFvcuWIh|-*?X@Sku4-`~nQojSit@p%DCk3W zwYvBdVrYEMlWhjoZ*^ff^{ld#md`Cy<(j4>>r5o$vb5!RmXW*T(I=x;yrC*`DYxZ< zfm3q5A&MMbaS+njTDhhYyps*Xy+p94TN^@rQ`8CfW)5G2l}G-F+(bvyZC-XNf;|&S z?uM;Eq(aDhpJxlV&INp8yIc_mt_6{8$w@0Pi4eCF3y+pER7HdiRPZX!{8de*41M=U zz0s%zi2?lAvydobkLT>(;7oBUQE(hZ8`=ZbaaJKK3n6X7rs+gTH%tbi-Qu2371LV+ zCqzen5PpV`r2ZoRJ-&dxqhr;!+Ppfx`yKMRuk*O`RTV4OUXMs}xBK>-^$+$cM^(|a zXEb){%V3lE+RmKDQTOxay%0q!{EKXS@a1C28&b4qSn%(?cezOPuPg~)Eng(h1t z2yzcwg2ZK^Y#T29W&IDuO>(EztF2OgWX(P@_Vc4LqYU7~i{mY$%Xpwh30IM2RBO;s zCAAPN+@!21O9$rWNlHg~41~(b2qMFkGl~=6t3(K?rHRhLq!;8!m&DP67~LNt>9e9V z%nY{uB&hCmeIu>d&M(*O&$VeC7J4@;bU%@)5ZLx|>3zsaC!k znLjIPWO+Ki7hS?Z7TsG>FWp8KQYN80%3tSby=1@Ai)bQ!;1P&q929w+9dUdX{%;E# zvcXiYIuzS$I$LeEZZC)swjOREm5fDzr5&+%U#wJxY}0?j_nIDQbwlIw~bJE{WN)mx+o`6 zjMWe~Bd5Za^*7GR^=8Lev=|;PNY(X0k(QKvn)MU5ZcO5m%y>5DO1m$dm- z6LKo}I-QsgB6E`b$Z41Vlw`aoh>y=771=@qBFm|MM8K3jdmCSRc{E(#y^8N5(JE4M=*nF4`_dEtNi=Ad2o~ z-r^ndcnqips*KRb&Wbma?C7~S7&R^kG?|0OMn5uIriBy)3(dgOXv+6fX85h1>t*M2 zFDrT&!%SGvrMNlFIbd7anGfFi)3XiUnSW73s+3XT$y%_Tv+L-#{w;7ip@tte1u^n)qv0iN|u+=`-7*KHr$iAsVNwkw!dG7 zoTiLFOkdk&((r1}+&tamFlJkdzC+)^ytuz}z(DUwD(t8BbTu`J@_$g2gOK&W(>)bh z61vpJI7>Mc3f>7Bi{U|P(q3RZ2W+BG@obUlN-K`N7JR5n3$h-CUY#xS=_@*vHF06i z?*g;gs1~&&E%RX3#{B#X44r-{j&x-@#~SUY9?2v>g`^-hUGNh3a93u~oEu81ZN1iC zxTeHD0Sp}YSK){XkjU;XpSLYgDOe(NHbxYm59XN41_?X*5Fr8fn zzqRv3%hHVdDJLCFz|9g0>%9)iZ~mVZqS{JcR+f+59`};-yZ3!>E&ikJYj-b3IbBQ= zl#%JlRp=j;dP^mQtSh|f6JoVAJmZcCf0Gk|P1vt%oO`G}7yG7Fc$Xkk65|6V7AU|z zeRB3Jo;K?&*}7I)*#EME@Qfco=+)*{G<3pPvp%>YE5Bp`Is_k=eOiC(%Fp_>n(qCeg$kuqB|citTW!9(fH!UQ?$VE~JlY-Ef_YC&8^OAoC0L`p4AxoWaNs46|)IEn~h-myjP4mBOla=sw=s2_LvpZvB) z3HiD_``j(&LO=hP=!?`9U8y%vli+&#s`qi3Wx6p2KYjd;vz))<882B_>eO_1fb2z>ZY&eX);ZEWBQ!rY>wbQYzU;^2CpBA)9ts zjzpz0?(8;vVRE)4uJEr*g+`xc9&cRvAO`dJ7uj#2P_8v6-fDLX*U0t~ZD^@lDtB3F zb@j=DMx*&x`GI#Vex4xR-GD}tnK4tS{Q+1&LIm};Qs-3(=e)6*D9mwjq^e{THO8cu zL>iw(v@{vk9rK5X&~KkNKaKdSP3tzFym)$Y-X#QZR;0Zs*fy(4Z&=~}9);|6N8c$; zHd58YK_oBx_ckVuIlldKAyXLB`$v%=cx}RZoWC|D2Uji)dbHxwb)?lkcYupntNxi_ zUc@JRSEs#oCPR28-uRcidVm!cwqE3Gw0E0mVSK$eJqP$9oxD)E4{5KT|xB7S+PNNE? zwQ^GelsQfckZ`k5t|GbR!0)%>wPu4@u*G3QYAK>Cy=AS#PNY^u2t9}-l}OBh7;IQA z{+%woV#mB}@(;fUzkJsTqw%``J(|du4SiBvImD{YFlwCMtWjTGUfM>*0mf=0^zzld z<)g%O2qfA9zG_i~m0s%%EaA+BYqG!m1iW7%SJUjjOM@w~AEV&^)KzN;5S5k^&bJbz zo5}`7`I`aC(1d-QnzD%qBGd@K*E`KM{a)$L54j;zv-ef58F>Z0f}USZXW(zd1T>xN zVZ_VWTrI9d5vW=qNew2wdS)dA=$wrf7F2z~sdc)ft&XA*4a~x@gSlMUyor92gin(E z+b(qHpJb<`Z_Aw_X#0(?P0nSrX{B1F%8EN(P=pg+kkI_a8A?uCVpgGM_ZON+(8?wZ zmW4k`$)B3)9S&vgG7}fS&d(o_&-NTkQ^cgBQAN!s2!$@hrC}B31%js#C?vQ=QPEsMxy|*skezait^Y-}Q-n_^_Pr&c{)8(R98!RTX&@7K6OH0#O0N>KVz}&@SK% z6%Y`+_Y2NLg4?Q|gwKPsYeFphFDIyc6tiG7N7^>*kgY+}Ob%mTJ$=9{Hjm#Zy-WY( z%oM5k?+xw3FSi_GT)9fD9ZuLdU})nu)kpM#lzu7svlV)-aL$Ef$L#Bc21I z>bBt}iV@tkWC@|)sOW+GKRKSeWx zEj{G8K#Q7&s$A+lptomE0(oPEE_BC)hdhJJgc`@5gVVaanR z0{q<+Kh3!7e5e3gzz-4$*h@rm(BYsQFp>P-PI&Dm=J)Mv*3{f@$JUG@>fGV)7~R!a zBN~BhIk%?p%sqSa!tD`9pg8=PSk`RFgmtdFdOq~_R;D34g_lM@afE3higOrk5ApqQ z#}ztjym1M;-9p`5JpHboFtSXa8@LqE_Z{Tb=eso7`+4fKaNZDQx!ngsu(iwpdeF{)!{znO1(3zMzmnif$o2fU*#8SR3I!|n*a z_M(NnJsJzfykkKv+H9kt9`ztkBd&)CcnO%;wvF_x{=uvy>n8r7>-FSysm%^iWQF@M z4fuwQ3nr?Xd69nbI^6WqqFWM{Uh3SIJWE4#X1(+MGKky1Lo_^iMgo1KZSBJdugTTE|r7M|;otJ$Ub8 ziov7?eDO>QSrFI6D88Ss#)!37Kto9g6nxT4w#5=L~J?Jyxy<#Z?X*ohc_-z zZBIRw)}-q^Ws1o!*1Dw+RM)IhNQ+`NLz8+dP+lEx{GTf@$%YpuGI!{d_8BOI4M|jx zx>$rKYua5Ogjoy)%Qi1(tr&CL(fAyO%o9vC^`sql+Oe0G0QOqu+qe8HuN%zwKf?&N z-=8DVXRxpnEE&5*5v^&H{+Ai_K6;lBGofI%VtZzNq`45^3mOx!g? z?>JzTmNXu50mV?&#b=!`*sBthh{2}5y%yt}R%aO6mMnMF>W^(~J+xhZYNM#8w{wwM zvz&?&reKCEM11$O7}O>@4$_VyocD0RYH{VukhFBvg3uQr;a90jENg=-d^$-MoswyK z$^1=|9~Kx_-XfV5)+0;w7Xs1{%ByqN#s+^F4twZ(G&g}(tybX)87m|s@*eSd%*AAB zsx?~-79%{wxl*b~V2Cn*2uz3?)wRDD7YclCd&h-HkP+J;)-Ea>^^!Uk?<5;vKY}}@i*TM=e_R3T|OQ}fm%||U}FvTnrz!zMA;^1Zl1y~(G#iQX+{w#~ z&C&o$TR2P>y96DC)igA=Z3?zjsR)}my9Qb@8cQehQI0rU%Pp$m$1)m#>%Zjjfa!#f z`3*)U-Z>B@4MDhAJadV18;l{ejA@UIA=SK zaT|lq47IJhEA?_v-c5h+UN-M~X^@+;&mU1NKhaortxbyq9{1#AV~36EZAW2GvQU z4ZsvGlBwJx5fekR$w_Wk2pI-P4s(!#0x8ffxN+8Tuss|pC2_w4!>yCUgHxgW}Jd@e`no>)rVZ}BF zCQozX4=jClglUD;B9Kw{^urH(-Zlu)MspcVJA=aJ|lEk_2 z-fSIzxJx@jR4IP_h~rej`Z2t-`Jv&*Hw=7w6!9yZNtWvwG^MM1|-O`E~*30 z#WB~58b6dH=Loouk1te`bYas~6#h6XO&!1oqgaLGeJ<#`sC;KZRvz|{NA{N~M-+rxX-A)HEfwkQth>w@@fc&?(%Wrv?-{e%6!#dJl#I53F zVMIvts(;h^8$2En>_g9-Mv>&+OvTgsN5;}x7*uzd0s17J1GaD+ln2mot|k_&Fq|_` z9kcrS`qCCX4=*F*6Jxa(a0H$_SHh7}>gMJa=H}gF)qa}~uWv+c&`Tb~x{0eZ4#b{m zEhbuovEi|M;vVd>>z>E9|tRgD9(8)*1Fll7C@qe&17di5DPgsRHr}la_O`PA{(+-tXl_MOu zJ|s%~hUXS4`B3p@PcAWIE-{4cgCQR>Qyr9ExmyWqke|2&MS{3~&u*YqpoaQY#%3Sl z(6+9Khmj<|;-tjz4N*STAkq&1$f#G!7VihKZcH|r*!?d50x@dD?y%FyY|Z3}mWF4y z4~O<~0;7a&?NUQi|ImTUQmvfZTbbYPW;Y-`5ZvbFqA04$_AuA>cn9@)=lLw?rL#9P7X(Rs4qdCH4rzjKXl+;F4si27g0j-uMjR3-bBA z$hLrVI^We0%gxa!9D6x%2%U$SeU*`|#XquUskzBi|GpfT#!3?B6s1XVbnl%0Q|L;2 z`R+>1uEp+3tto@c>1xgH{jP}?@sb!*Mc-%0cKL_mm`EEH77cgUs={i?O!bSgXk3i>qJkVq zs|vr*)_bKTEMF$y5>bSGEs;f)Li>?9Y$cv!f>j7n-D z%%+$3PIh-IDPJj1vHs$cfDUa?5ynm23{;~;E*&#!q8+rX8(0bPNv14V)GwU+QsNSH zO{Ko8%TqRoY&DQX^Bc-d<8PpEXd8g5q6jr)5sKIo!C!XESK? z)Wx+?jMS{2Cs+m})mj!DMpoVL6g{ARyE?x(O$#f#s9ayPo2?6#{_M4MN4HiMPN@)N z+lAAlN=xoNCH?%2Xcm$2_;k|!s_!Azobx!;wryZfKH_$jGfKd@@zNH1C&S7)e>q>k z^*ZU55=ZtIgvtSh4bPwm(v^XuNr#EJ7H9hhf}ea3O^%>5>23re3?SZWYcxEG@L=uJ zqUjD1Pp~c|GPIH44xF@WLxREr86(uE3SSp)cV&yLAsORfRNJUj6oOWvv{TMPF~YOx z5ER`CTGy}!FOC+1`043QEVi39>^!uAl9&5mKayMQIkO4<7qfNITkFwuS=@Pm^Yr-SJ+cMJKUIwyC<_P4ajFyo zn8PT4fm-TqL~ELY+3!=-N%2h#&W((>kp<+~j5SqQJloX_$d3nMr7%mMj1>DG+0p-~ zrn&<#VV_D<1+6?+Vp3sJuryMT{nI)T-H|~((uFQ zCVwwkHNyTRe-$gFk|RusQdvo$Rn+6AtW<33mXJpM)m*^fsIGSn-1qpI@XASmqLk;i z{@V}2D(%A2A|-E`H1H5AMRs*pN7*R~q1`)gP7F=u`8KYOaPr>Q^^SvoA+x;o`UM^! z^#0x*BTlx+h4{#u*0N6POFDtN_h$NN3z|Ia~e&XFhm8A3=Vv@z-EW60<$(`-nQbq8~;lYytc7Rr#HX?vDGd z`dH)9kb2BOBTfq^?7fcf-bKD`)twbF7d2FX^zb{{0)}k*{iUq zOcK-H#T#jpZ@I*PvQnwY*a0TQ_*!oC%X~aFjk7#dz3^P8ZZUoVG1em6rv_Tp1iEwc zC$_rb9FidP=C=o`Xq7=R4r(L@r%!8%Fg-gx9VUhJ*M1+VzgmX?solGgVxTAh>lJyh zHB^g95&6xLF;dNh5(X&5K*uL;2daw{gx@$rQ*MW8ZoEWsr$xO=b(qwbjF4->QSBy! zBj5^jy~QRVKtk$MbzKaXvX ziOQB7nlLJdJaSqzasx@0aqMv1PPCBm35ZR}VKa=Lr=FL4L3o?b%T+J8kGzHfZm`Oe zu4e*)!xOcJ`%5C+cJOW^hv4hB0J&#V!-ME&cys{KNWQ@Ev#WeFCd}gkwWsTmDVpoM zlhH$BtNk=>n92{cd+)dN_;jzw@!qizE&-Bu|2HNB{x@bz+zvbp_U1#x0PrZM=q^*h z%REnpJyp=ipTSqbr@^8#f`p*PPLFN#x5szi<(}@@5pZ<=rg#`?lVi^WgJZrq8FVlA z&|5t5cH+4@w=z%Q3Rs1A(0o+`%k*Y@!TQgynpDr&!l^XJw$oqL8C#kW_@s)ExjOFF z)O2tWuJZN8nkWe=2x{nNIhjZxAj(x9G1T3I$S-DuG^dy`$SiItPhj{MOr_KCLC|LY znU5F4_5PJZPb-Rb18N>kcIz1L zi1R|FFRPX>#o4DBM10~r5A73lSleS^;)SLLR>u%HC(+`ZZ(~7>oSn2^Q>6Za{y2<* z%J}>**qNwkW6!o5%1BJ7f2BLVWA`d&r|E7w5c9zQ6Zz-OE&vL}c2hdWE~#I&%f*+i zIDzqw=eO$y!I`XPzRi%yqM`{s|1@>M8M_;e8Yw*H{R`P33($vOQdo;muw&ViTu6!d zrJl0slC4P_NN{Wx0zb&0Qd&6<$oS_B$ZEY;bj*`;J~XvX5I%lxncC7IgZ-(hr*-s= z4m=3J3Q2vY4I{}*;ap{NPTEU9f;+vLNK$4f;h-hn1w3RB{r+=E!Z+BO_{qvN^0Oq5 zhG2bB42|dY_AJjaC8F8~v_d!Hd8W<|SQ#v235}GP+9IH2**rCZAAJebE~462L2Lm( z`e&<bfCpJL=DOUh-7$GuvzcO{5w{%l|jIB5r6v;N%-%*qqs#w>}2VnWWtqBV^L z$RP<*To>nF_8qC*Fc|w@WdY+|oHr}w`rbbAqA7fwr4&R^PM&3dO{CxfzU{rkC zJPdqteE;Zp`SkhyI`9s5UT^F1;SIa&YW~$)%L~HW3B2EWpX7t>-!3?O5mowdNvIsh6V5_ut7|a#m&kA1$O^9!prQ16C#9;0uRJ< zG$h8Ew@idB!?|qk3O02^uYVNwIduxhO^vbF%$SI}m zY2_;p3oT)u^coN3Q$s9pP4qP2@0-OviFv;ZDf~rzrF_*6p`GnZW8X(YD_u|j zPW?~8hDZst0xpE&oX_kceiz6v@T9v<@n{Kpe$n~)k95-Gy~CE5b>s`|xR!*YFv>T} z=jOLJdjSV{g*JeK78_r)P+9-EV?*N-zA%N{<;++6Ir?pK>Z7S6^9JN^ugj zag8bXe2CHe6ef*N+#8Q!uyZzq8gZ%)o4}Z}--y3=rS@@!)a74rW!#daN{|~{b=;)PMV^99 zx7E_G-a?*yZrp#+Vd_QwNoFz+GR63U=YtevgPQ0QNsRY!B|AKVT2u+j`@G8KVQCO45hsoz#K0;O#y}Y&HRHhM z#k!#giWYwCVXuE%Z&xr4NS2W;>zsY}J3e2@sO}y#r;{o?oIes8W*4qM$_{AOM zy+;Ne+W5+9I$1CNS z{C;EYy$8T+mtcoeoQ>9HOW|7u4leH=YODEHJRWy+A>D10!8PiWPCD)6QiYSgvP<8i zdngH`U& z)&b@4F+MpWub9j^hEj^ibAIozq(i%cZ($T?HAqH;$?ik>FI&WM`2wSs9!d?qcm~4$ z!S@?NY7+e~$I+B6uL@{?b_i+s7(77BWoR7OP%&3#heVs+uR_d2^9qI|qj!@*ww;7U zk9o~;$J{Kg2eC_;ra|x?sN}PZJ)WuDJ0-+UFqjIC*@N)Z(nk03fql}rD}q|2UnALf zAI>KXZF%*!ZqbBy{JuB%bFRnzni_1Cl@h|M8}W0y$8#Am@Ni_I$oK_(ip<>QU>tnL zM_AE(7q;(<-?M1Z9U0bQ2ydbJ>aa1T5&@$TmHdZ3xRGuCm+(i-fn+_sj;~}V7K%?F z0hwxeT_ovycae$O=%<>8hv07e)mr{QyeahXOtdB%HSTQbn`ccNdPlv;iEq~Wl7FI- zHav`IbUr0O+XGnzeh`}$ik6`ApH}LDv->xE2?ta!Iwq80mc2z0MCq>na;xsUG>u!; zn3;+Az4o@81E$WS;oNhU$x~d!?q1a5H`+q34hmNmt0(=tQ-vmVV23TIWJm8t8x|~0h_71*%NM1@Gb%+HX zUGOR8g)~fyjMmR+aYOGLqc>&@IRKGL4s3JqkX(=(g#Xm|wAWod(!EP(DrR-(>T>CmE zQCZ-kqzWagNxt8IoqJ5ctm_%d1XG`Dp+6$I`7}5_tuY<@xA^^({8*#eGfvvo=;CkO z6fGyswCUYQwhBhoxwfOuBAj=PKD+}VJzvYM37vZo&rNsV-J?D7bTQ}?&=dKUa#;TyYumi7Xt&QExFG_2+yhJY|a;5}3^**I{s(7C{~y+Z2`rIh1| z!;jfTskO2Hg@C(s{8Am?x2w7VsdOYS3p8F<5+(`~yEgX4o=)e)Fd+nYpC?+$Q!2=J z$GaX@oHzJ9GcBaaV1D*fs1TS+bWl<2!*6L;c-1dN&6I{ppsR_qvgK--4#M>)XL}5e z)Ht@qwa_6YNUjZK?K&8x`hK>W;4W`7F60CZWvZo2gaUfhMgv4Y*G^M;3#rsVNiJVi zfj}>_M@JnXgP%I*THA@;o0p}bu4`Wj&gnUq|ICRZM|=xYxTt<>o`oZu??@VA2)eE1 zrWRq6F`j!|q8^_3BH=p3H4s&cXlgiscSIdkz-rdj6T=NxV(emtUxPvsqR7nDicgSH zWYChYN~0?AQ;KlFrIY9X5%o{ek+;qFI6Sd4nb=M`n%K6TOl;fc#J25ZV%xTDPHa2> zp8NTI-*>HEeb9Zy0>wLh%n3Wwi zD5Z6GsI;MbCD*UqC{!+o!vE6(@Ecxp`^j2HkxQbu#S2@48fwSu@5Gr+-p+Avsxff- z{JmJ8*gzmQ;;RDN+_hu3p}lPJaI||MVx#kBA!Q0NBLDN?WA@}qScNKec`HlkoSpN2 zBeBN{MB_iIA9-F(y`HkV2e!TFKmJ-XOIkX){7AYGtAyJttlKNd0?WG8bzFvvcPY82 zMOTH@N@J?qW=U%tr&g#iHE9rqPGggrJ?fdzp+;F~mOf+Arq#6)U>D%2!4eg;qMvKZ zF_67n)N$#2S>PV_y>*lg@_ZRk62q*7)+o_EFug+6HJW4rjSrLaN|uYn_$~m7rJ{gtTdk zVDaO9uH@>f)e|I8&e#!S&(ZqHgu(8&9A9HZxcP1GwC;{JPtSpyaZ$iq`g$n;;TzB1 zdu`73+zSzq@&K$dX!X%_^gHr($A=6JWmdAg7E{xFlD0Qp%^&W#G-!&&Je>0PEnT8I zvsVc#WJb3A=nb9Tx_EQ5JxpvY1(~Q9%+->L{a0n8T1c3h#D0jS%S3M$ru&|?Qbrgx zQodO#qZ3rCcF%?C!|$8%#78LbU#3qSF;U}1V+Tk>-MEOC1&`Y%r@aoP=PCv zJbpIKHg#UI)>t?*!tUl%SrKT=KB7f=F&l7noq1*wWJil@N{kW?I3r;FIyzHmxfwgG=e> zUo>;w6(W!)J||QZXtK|Kfe>->SX3y`z4FKNm*lZ#W54ggSx7ZjoZXUs=V^p#u;r>C zwrp6HGywdj`y4M z=bB$gnvWfF*9&O1_A9ay%3~QJOWf~SOyBr^uANq3>}=?E=4gYU;>EjkZ$CD>uB(@i z(>rph)kj&YDvC!k<3w9cF8!o{&WMd(K&95|ES_;;Qw5m#PF8H)KTg0zPh&wMZcNvh z(yx_Z^SkPYiN~y%@e29eSm8;px;9_)?n6xd#C{Lcm&`w^TSyaP^pyyR`!xi$Td=C0 zyhuM7pHST1qlF_%z%lWmM5IT75ENw1CaxM5n^_wP!kz!k4pEu9zYosi$E93C) zn5zqmQD6{p1&OgdETxH3$*Oai{M72hr5*8v)uTutI5_w^_|)t626Ef;2BX8yBGvS9 zF;*R?eS=@wmGQVzCq#WQdigoK!VcaOUUp$8%2Dh5+>~${J$54((ER?Iv4w%NmIRk_3^6Gh~OE#UY!PE1OC!OP8OchtZ!eB z^pt~1J24aPEh`6`D3AE&aC$8bdruaX&;*H|CWnk0k2F7r9{$x56~t>E0gn3{9s#m@ zD;jF~pD!zZT>d@dkacU={@)aTC(0CyRd~?+KBt<6O@_>Z)t7vlf>Fpn847n;;i6ol zuoIs5!nhjO@zAsBYr=PXPdkN!g6mG}k=lfsqyAuFLpPcPmMypGoR56Cjj? z7+5l#gw#@fH{5=TX@+yOv8|-_*zsm_O+*rjdAJ%WMvVtdz9)Uf7^KUR1T7exA~;cy z0J*M9&gp+N9Qj`0XjB|R=xCMm)uZF3N-*dfHEpUMH7@J!9{~{FhQ>yoiLGVi1|+tZ`?vsZQq~3dLld2@nNRI3 z`0VuIw(w!Pbxh<0P=>F;s|GSOrulYYJ)B^8xTFI|0pG zJ0E%gAu@sHA0R#+@3HWa-}^$Y?q0e2&++_a0eTk8q#=(8*XLYfFKMo+AM21X(ji5~ zM(bO6@K%aYF|(X#zs`f|or6}78f4d7b8|5^q=22`ZSyjU+!z=Bewa4jLF+QGgq6zG z+Y(wD+TJD{v4mXZ==CTyq-Z3%UK*Eat(2zCWc$i3p;&-7@`SA3Oht6u*Q<&nUgZ`a zx_>=u(tJNZ3bQU!PK8P3t_ipv2Drb}O+U)n6hvzK*iC~;cith>ecg-XL%A?${1~Vt zYkSz-;KR0xSKE!+UAt^lL~5OPp|*Is8yKFx>olahxm{JrUQ_7uz&WvOK3OTSf)!1~ ztnwtSx4k_Sqt}L`pZq(Kv#v?5*)?+?v0b_~jvBM7`pj$n!$zdNGeu46H#iXgw7XAm zzT|elru;|lv;mBT|5VdFTQ87t^iSH0p>xbxF*;_=RyL=j^%+B_LkMo0=He<=2QQ3) z95MJZ*i&!-`QTALW)WZ1K(aRS|;g z>r?1^9H5huD^WOf%~a~i%sggbc5jibVhF3F)$AmyoL!h!MpShLiLH4?zKL^Fi-Xe8 zPAHWpW0k6wLf}_c3BvZ*1aesa!3wYi|JzfbczaW%mwQmJCHu$4tBfpXe3CWlt^}HU zlz-KfV=42|!ps^9&fG8+zcfEee|V**?4z6Us3+NyVF)%#a&?>Gq6*C^ieZAS?OP&P zj7@%NApQjf(S4;jmRr2T@oX5e#`w506y(whmus}=uRyH`gQHeQDNbC(;Yt0U`ivPq z)$y%FXAeYEnJ=LQVma;e83!xhEZIrx5x4F`USVA&ua2(6-(GxOi7s4UKJVb*@!f+r ziv))WzJaXsy`b)If3o_%-f?8VCzU+QeL=-of8FA|pYXkjz2`yt3pC-mWxkbx8iFtO ze-V9cZsY8Ky#!p{`My{CN`tzA?QeXI@Io4YyK(Jt;mNYI+$B(xE#-5h#8z_X!C zq(`7ah|yt=;8LB88QE3|(j7*1c4tKJLz02g-X6~8+>rlPHLx=R;-S9&U|bm2YHCJn!}{*<52`s-`P9_p)P3F*oCKzuX?8 zp4?xK*D=8btiy#8o|t}7-2)dV+?P2&@c<;b-1h2Y9QPL4*l*t7NCOv|3HDNWU1Ax! z*{b>KaylF5JL1j{{le&TXsO!WUmg9IW4Z^|hqD2YM&_YeF;=G2BZugu+UuQR2kTUS zww^EvxIVmfJpPhm0C;;37T3gUwX0Tbgo+6~!-ePwjy5rTEn=SB0>KOy-ap-!)#Sc7 z5l$H1sJ2UF#xBg7UAfMHJS526ZVRLO@YHVqcl+CeGgUMaCf2?94t$1Ni;eT+CCyPF zZ&+u7XA?FD6ahSei{d2CI2i^2DtA_*8l49yJ+o3pIy86~&thtxP_nYvJRFQ}xO17^ zTN5QI!jNS$SB5|0Y6pkcfbhtVq5wUEA|!KeOTd(cl)qxIjn$hhXWU+Ime7fFIT{%V zGDH#d&=DbsvTyyZ9wkfS5E*+TIOn3H5QM;KJiPkPOAuw)rZH$U_Zf+Y)^C5F=^b|& z4IilTt{5=gkf@P@lab&t1!Qm}{lqx#p}jP_6`*m7G^pPes6Zmde<)x(a_P|3uSCkP zAyIR=eQf+iAL^mo>J$bjp5qeaF3PNMu=3|unzb7?SlAAi(KHZGO|2WFXDH|-C>0Tx zFt}{SF`5r`k-d@;xC+NQPRcqT%UUhwthY-AAZrT8x6`uTWRatoT{Iq)jm9u`G9w^p+uahtkaq>|Z2j4-|lP6Eelyw23&!^;3x`fwN?)91j^-luJ=bpzZGZxl#~YSry;v3Jb*dz zF_NBHe(XuABm=1g)S(__{+txk5Mt$ImMSWFbBBGF=Lds##k@xbXVkPzA{yg*+@x=4 zlC~%%bs)LqQ6o=#SiZ*Xi6|^3;Vh&df02Q4CdKJuY>|p^B{C3I!OC8fXmv0Z9{m*H zmksRTTxDpQHQP|iI{b%>m#bUKpKgYie{bb@zKO~1%==rt6U(f}oZ8?bhaZu|fjc*Q zs=iR%Z_hFZ%?E;+(H!i|jY$expWm!uXc?;=AT)v>T&TxTe6ec3fQ{( zY4CRiZry~*T{~1KGLb*lSloKW_z);`Lf`vO=v2OTp<-Hzxm2Mv9R=;oZjX8 z(2keH;ZzW;N2zz!%u+K4l{?Hocv+rSYBkdSede4*6Qw^mBGuVEi`Q^r(g61tT2qRV zO!g~06xm6#Tx6^Qo{SfopfFI8@I=_(qO2zxy7xD;n_r4;JD$@e3RQcxmmH%!tlA}c zBG{Q79sy0|N{EC9P6@4K)+2%OycN&1A{Et|yOotqTjknT3S;Fe<=n+`@Jz}AwcqB~ ziVGo>Bt_*7ckka-Citjml6S_W(@G5Th+4ZU-o-|xNV`dVu7B#4q0#7))td(!ry?$* z+e?EWLJ90e3%odUBa^Grq58%|g)DroF$S zOSa(;(EK*LmQd}Q+4bVUHEd0>O5?5xaiwl&RTx8 zG@Y%4Z=AZcFWNCwAP!#?VbTG&xrddzxZsvAx^=8-v3!W;Yc%WjcVx6?8;Q;P!O9wY6Z}QF zOmZ__yfFig9z-Qy6p<+*Alqv5SECfh2#Y9MzOhJ9<%`tj<50KN7NeLWO0RD$N+%vn zs=vEriZx?{IST!TT2$848VeT*=7-T_V)S;LCCrp7&zmG2t%ne{#DNx2gnv~-!ys}?FW{^`(vlI&;`mkP3pP0dPwVK?c;?BovGCJmV}Om zgz1l=DXva5%>*3@>^J(T!a~A7rkMJ3Bt;j{=FJ+<*~5!=7fbe1cGkMuCYR*xm42>k!kGdLM1~r(QLVn7qcw&qa z&bYoOQckq~9>}wuA{IQQ=EA1<}7ZqyU-hJdd*~-VV1`B5-AujaYgs2q+iH-akZ!=dc)OQ|o$L*x|J*7?cN=yw7 zAh_jm&Z|9vm!R2NzX3#9SxGeAzlpp2>~K8trj6U7H4Y+dH9Yd}aKB}j<9(pqBR%;T zkr5%GB*l!)ZZJ^vg^EKV!?UbW;i8mfLJb<#!MWwhS(fV<^Y(nydSC$}G912_G*1^@ zIi%5}4zA#7ziBI##75qUi&cFFTBhuWv5mlJ&q+u|)@6ud%aO?5pM;XM86X;)f$?-F;NikpUUGY$ zjA-O68qjMB{)wRbenXt3Mdz(p^$Eh=n66}rtX{9ztodrIoUv<#f(22i|0vr^Fr^ZO zirQ1MdnZGYiVC;YFl5eJgI1JzGZC*F6fW^ZqD*bU>}G3WL$+q6P)%z@L8d?poOjkt z9BL~)BKv0H&jhLx6oC@9LrVyeR_o4f715scaqD2n@&Q347=02Q1o-bk!r24;ItA3$ zv1^13ZgV?tpxY?mT?0;|XM#)RewA3}9^(S1ZqiUF#*L)b5`?!Jv1zgD=Uj}zUOA?B ziF4~#n|ZdD(I!_cZxcgj#`$Urh&&Cf4Q()Be}6k3O))VjANB`}c^i3Ubq+pVan&)f2PJ4 zycqTB#LkM7=6Ph1e*okmSMf#Iw770HAVv+nW45vJjLj345^;Y-M5^i={1M!N3x<>g z&(6hl3-lA)k)q0LM1m!Fy^{IP}*Mq2{n0>hgb+dH|E8Vrwpc>#L zW$GDY5`*0dUE zNMnA>s3ny@6H7`?nvW>dlX@I#KcF%u*P|=cXcQH=WSPgcJ= zC68#28{H}1Z{G<6J6;7>;BsDCBeb$JNTT;OJCYEGB?FP3eR@V#C<+Wwa4s=jf!Vdh z{=e+H<uLFpqTZ&foRp4@G{mJG}qnMm!qr1KF zHf+6a+K_OVWt3o!t9u|$;bO=V*9Si5G#`)5$#7DU%Onr0cIEVTXG*`T&NJ`^ZrpAB z$I;vcjm`Rje3~I(D^IBzQR15<{hh?0?s)*IXipK#fJm)kY{Ll(wdo1EO?%KuR$ti@ z?%FU@%!L7w;!A|llt{p+rGv?oNS5fODJYP=1Gd+!!4$JrIHkxXZ?YI#kt)gyFKzmb zBdLpf4R;tRGJ`TbW;jRbX4-1iMAzVr4!>n{pxUQ1E})6P6)GH{tk{;E42}8vtM+ak zFck0&hO0Vd12+b&hNAx+!4{lV_+d?eu#I*Vsd&|LilR{x;R%pN2DZGrb{plmZ-We7 zH4{}%f+eOCIv9NL9!#SYD(H9w_RY^R*pG^6=%uqv`tKzTV z$+@SR?e32^pCDWdJZT9LzBA(_6tYUis!(&6LPG79gIyE~((u3L)?!s+nePK9q$3xo z@o|tB9mP$m6JT-&F_&ph8=unR`3T&Qr!oErAB|No1XC=XV-oCi-XZJ>Yl<0F91n%t z7?HT9aKQk_*{F$*tE82nUD{JU#@ry|3-?4lj^^oTmuq7>w5#O|2cK_&h~z2 z`wl6Fulsd6r2B;R&k6s0v5!v_ZP;}aWqZ5jd8K_J)Z&0B_d`N2BlvS8on9T zWk90}tQm~Rjs&vxS$v96|6h}otbH(XqUYl|#`R!oW{n>y*xKn?slAfF6a9-+0+_C{ zOx+9sNvAz!E(a^PMh{bn1U@URWdHDZbj1n=m}XX9E)+g(!QRd3r>-yWEgt9a?f1!T zLTLYA(_8{`|8q~jy&Mylr{DJ1$2Qc?=i8Ir`*Rre)YZS{&okz~iU+8olH{f5^PN2F zTKc2X;!!y^NhR4d_{}j&R2G_L+AIerh!bV{#vc`5SfG=CQell?goQ!Cvq;rzteG4okgM$>{6&^F*w1(^&SuX zqF5=(6dW-gTq>Z+ric}g!}WL`46e{;>JnX`K|su`rDA6f{nm>hXbHdd4u{kQwuL*= zx|jR}O+wvdGT+9(%ujm$p#jr`AlL~n^#dM!DJpHZ$QjVcAWnH*;bB2yBhs`D4{H9D zLTM#%=!6Qn%>P+3L_qSS^k*YHu*LA-OQh za&d?-QlN@r)8I;VoEO+E6uCrR!GJgE`~g_Q+h&?k<;k(Bh*P@V?yv)RJERRcL}9N3 zd+xxqrpS^T_4N|G`EYr{vkv6=J}3dw|M1qIq+DHFR{C{n)h`oiG3*}qtvKuQ!^!`7 z<8T72>+`|4&-UxlwmRI-*}w4rj#YNis@3g7wQrVWQD4<&`wvTYTSj02NTwt3|DP7X z3;|@Wl@RF2pz^SIDg6=6f`VmI$t^2aqqs>5N$lzYEv^A(&enYe&>=SpLkb9dAnKe! z0q#%XCtG3VWT~NxT;X^nY19bcUK?e}!?kSiq>NA$iFObeWnG!f{V2VpW+mF;=o05@ zf}PpDk-zxM2}PtmW9EDyvWZ2vO!e+zy0HfX#*l^2mxr=&@fE(oP{fj7V4N2}`Pyc3 zi_XT~>Dzz+*H1U}1CCfJY6$UfcxwkLzcsMP1u<9qMj_hlM3t- z^X5l_j0an%#^v+I5(rG0m^FtRLpw^`m@w*Yu9LL}Nd9wMWr1#L#})`txuNU=7ULp{DI{u@ z2bcgApQVeeT5`7@8*xm_^jD822?Dv0xa*{Sg%$Agp*SNZfXWBxB4MSU>z83Ry+rDW zR^C9$dw?GULPbt%Hy!-8EksX*%8y@?+5(S*K6^PhGM_ZY{@2>|=L;Ec%Z!mro^^qi z;h+N`4+TKeWN`X(aJ%e#wFg1{cs#%8LOIbAW@%huej%ii28o6XjM;CBaNr^~Yyyxi z*{50L#B};BPFx9F2L`44>9t>n- z=0501R-kfJ7|Wmt28_;`$7J0Wh}V1b5MoeTXUY0W@P$a{-bXEKE*bS1G2H$-xE$*_ zTPz~2p&gs;MZOpbFVx@pA)*pWvma+BLmB(rRk$fL$GTXA`>Lg8#iWctKQwdxJM!@O zHwqaW#~`A^|L$;T$^olMBd({mw>Z@A+4KkuTKQ7tXB^*s+X{~@nE3zN0-(suGrhD_ zqU*8o>%5GGbQ2<}fA@D%K50dC{hArisOCvD&26hcdz-qj1m1#rXfKUxPmerHPlCTq zAq9jERl2%8W4Wf8C1F)0j&_{s+86c^(y)qNrnVUqt6Dw|rEu9wV;f98+)tB3vQ4$w zXk=vLP=mofhm;~0X>Sg7rN{~P?L=@L!J>ns{6c=hpq)MOj5#lUws4SCtaEEdlOj7a zczG}eXc|BKhAbBB*b~nQaQ?VzQtz&o>@Mf;QIViK5`K!1a${P7sHGm}w+P=z0xOBa z&}hBE;}qN!i39Ui!)^+D#!5Wtj{OTZyQKGNRV zM&e)J#bZS(xDFE+O?=h;1>*U1>C8e3EIR)srsxM~|KHuWs-KL*KK7BeUUwO;9*)4n zLT*ZufAFx7umP=FPSA=U!IR7}-7KJ6SLJF}dBnoYFVkJ5Mg#lTd zna;9-T#B|v%l&nwpQ!QBzyPlTD(Ocm8$sPvKpOK74y+af|2Q~}tU#5-nwkyc!pfI* zRU{G+WRf&<(sQhO(CprD^OWKC28BcmkgONw*a?>x4*Gx!Bt$0dMJupcqY?yGxamqV zNt3s@q|4EK3Jx9ye^eFzNR+IISdoxY`g`1j)D3S+GBX6fBmGF?S$bsz7;p1IRck9$ ztJ4PN6G&{snbMYHoU=mZmm?4#T5i~kA5v6`CM?wR2zP^$MXQB{#m6)p_}-JaIN!VvQSJ<0!(hV|g)?4h&iMHx{1zrY}s^-5U zZNp~?lb|;^a_$Zg=KR+697Jb#a6@v&djj~fV}eQWaZVN0Dz2X?)Cn(D1s%&1BfI}6eauCn9LxJvHRdN)!3-L@C>da+ z(k!ochOnj)6wH&rBAaE21PGQ*Ja{1CQV?WQ6qcMnC3hkQMze4M+6^UWm;4_rce1v% zqjSN&DSbW+vZLWPXtF=SoeH~ag*HQEZz&P+C!#nNLUXCSPe!}ZJ#9j&;?Cq*Vio9Q zDI{n3s4FchAR`NCl#C)O;mSSI+M)Nv_F%e5WU!PFJ! z!}TT%wK}xla16y^L5*t>jUN%~JQ9nqIbeyddE($Iz>ITTjDk*Qp5)i`3P*#M70bMm zyAP&s?|Fbzn)g#y%(D;m1u+&Y#kjhv_+iaj6^0nBJwYCu#m?`qeRIOdzS4FJ4LT06dzGuRJcJzyHX zq>`$*cD;{s#KF}(kzFc~$ZGCXLM|ILVpE}hIRMPnRB^jX`cVqI4E;kQ`zGi1J`zmY zPimRR8UoXp9r^@Q4|^KURIF7xms^8(&t z`-Zm3$6)PR?bK=b)94n#$e)1+P zr1j?Ht_oDvvHr@>=MvRxzvo=C)y%2LsAWy}iUAOc;?gj0FZp-I)OliwW?oo&kx`&k ziC&4(rK&>o^zAdbs}=I=;FtQtLnmSJmdg*$|B+XDe90^*L|KNL3PvQ}l(MnF3wZy} ztUw=dw#HMm>hO$m{f$01tq+a=##vF11Tm3e9E`)z=)m82u5`!pr+;uG^gT(fy|r zxT4uw$hqmy-!6p|K_Ei|FJ436mY<;wDx#NQ>AhWgmyXX; z1*MVDd-AT2OgN`i5~2_zEPdSGQ;%5jx%z7abIjX8Zv8=*2r*#~X>DxH+{ zn=8!81%T@a6fT(KjnNb@R)HB|FXOy66`Q4o&uicq6x~g0LQCvOaZ`pON3pVw{elx3 zZ62qz#-xA(_EMF|GpAIvbd$jB3s)ESYVyxWExc7K1P+}Ps;;;$6(K19zr_3BcOckN zkYX{s!$6L;76>(#3y&H&ojtUX?5>@O*(hs_8fbk{pc$H6#!~DDp(!8Rdz^DGGFoLw zROG55m^-6L`V}rV)|UGL7>1Tmnaw|XBE`)U=fo-1EQT?`?DHiW$bpxBE6f{69%Yta z#_~34d{wQC#s}4^J+=F25_>%zb^B) zm4Bq=n{<+{sMk*6(!=H)h=#=*{S<+mLT+fn(s6-&0ZX8Uf+auCEU1`7jCK~&G@oN=cD6XNW6psQJ8WisOqtVA)SnY? zTxd*g_`ne)NQ*!54yJjc)L3w?0cLdIxh{W+b1!&z!7j?{AR%edLy#T6?pI~5sjnZ{ zo8>pu2o^n9k~BsP2CV8RqFD;~A}3#nEE1eGaLTmLD!?yU=V+KEPEQ(?@C31At2V)m zng+zGZ4bOwd6XcKhhT{}`eJH|MQNd?s}ghKB#gW;h)R}fT)aK&q23pj;u+aVyVg;lc#r{3MOF=TqsIFV^vx>JeUlL zjHrpZMkSiUA4&|zfv`MuoSd#o0ICB>5Jhf5tf85aeBc2wdHbcLh9VO9ZeMCO(4241 zEg$V#5kc@0;;{d-B=EhD%z%nAO`>zX=IVzyyf>FEVuPChlyRo!G@~`R=A0vuS(oJf1EisM^LDWE%uqe<*;vWZn~uDCtv-fJ)rnwt+-T%7q4lpyH=oJQsq|(bG5@ zfk?Nos+szIqd6G_Qq)nfM4t%9LAB2Sw4D|_R_U+OU&EBBQbz<#`m;0H3vmsFKr@{i zEsskYKl=+G7?DRvv`Pq%AQ4gizkmdqF(vk-@BqOcKH*h@77|@h_K|0Kct=C`bO}@D zJ=*50Co9V-)3WB~t^XiqNdeQJRo&&Gl=yU3ztkjK zXQZH-;%&H5FH9sHDIV6!?3nq^Tq`IU>NQF3=moFVB`1b&YrWsM*vDmX-n_=@E1k;e zj?-Y6<}6cft^o@+EVAAL>Er__9uffE5Re@~A*1>lUkhVz z0MkGW%gh3?iT7iOb8kR#Dg+)eD^Grdelrdk{l}apFyQn(>X?mGRoTR1@b#ZAOXyyB z*E}W19@M`5i2q;U_5BjhP0F##GC5?HQo&?<*avnJid3EuM&iO>$8Fzh<^aAkd zSS}nKWKcoqV}1B|Po5%(utO>MG|4x(C&E3VTyg(^*6eC!aBDe!`fMq}0|q5!X{&At$BnZruz*mbGI5sC2m)drBoMLIeoL; z%YY?^N{9B7mX$`gDY8Dm6yyr)!9J9$w{VUjg`A9uC~Y@0B`GXOv8u6xk_;r%_ww{} zk{v3m2zNK;tBT==#}KDedaM&a!|n7UXOCKl%zT{2 zi*q0U{wd6wVE(&HrTu}BOrt)n!xLD4X^IS>)|;*@l3eOhJas9HDA1*>)@viYJ#`F>j8IDsgi;8hRRJl2 zk~)84J8)q}U81M!Vx*Ou;KpCJ1d$PhaaXYGA;bVbbpFbad^cs6w*>Jh%N&CO2ei)> zapZDN|8QS3HsS(1S=Jy_N54*M#?S}%_^zpvNTO1q)nCeFD&ORXcO%F!gAyZkgQ>Qe ztO3qRY`4^X`$%e_BuTZ>;Lh|-KNq?&f2$_4q)w*1snB38Q;|g}#lk>Cv9XJQhi7Q) zQqYr3bu0)M=q3QWb9V7Zg!pCmeh za*g2br! zZC*hPdXh^+`lZBA>m2e%-u-oelm3l!*y=-% zJac2wRcTZ?v@9~YA7n5^hXVpl?tOB9!!2*{^M~f^aOgI0^DJNZi7i`dtNO43C&Hrj zFVSsI$qturzOJ)Mf}AeiTSmseS_raH8V&w}r4i{5Z;mHOb;1V8(G8F94F-#DFsA07 zG%{#5TODC%thRz6gA}B!$@L^Gna-H|HA}vYUsjd+G`fxI6sYNt8$m141Y$q8$RR&O>;Cd?{`n#noCK3*V?mvo%kKt9CW(q=WD3pHpuxm z>!tvkxGFNn*_2JxX4k9ia#7Ky`K@k7oNBuZMoYol?akTosO~pRK6gt#-s4s`%cNcVmciir;qw2a#u*srS+o!l$2F9tr>`3;MQj695& zy^`+!vYgLftcjY&ddgMO+qZv@9c;E-^DKw>b>0A++m>pE8#Vv67hkGAvw9Oh}mAZ5)Q4nu3PSaZ&2U6da0|=k9wg9 zz;hQAhDc#JC+JpEf&cBW&q-o*UtvHfAb^SYN$^!n2c{0T^zKJm*2%J$VvYs-@XC)# z{_Y0}v0O4d5C?k3MS}jL?d%P#-isdoFX-Xg)KAXdIM86KK}V%-NI8*vYPe_m$ecCz4UK1tf_s&p4L2@|?-!gx;aGX(|=0 zJ7y3|PJ*aLJoq1mK@Q(>SYMrtcrkL(l!pvX5x^+=zEzAO$CWu-dQd%zkLP)qAC0{0 z5D^$uSY84$u3D_m7Sn*#pfye;ECDu@D9M}`)MC)d@~(9Bcn4Zj*xU8jZrILnWPEEvv9>p=QlF|De@mo5*DVia1> zHinZr0!t72sLk)Q)6;CiS9CBX?UeezeU1GUf)45ecTl!hJ3w+7xg2Z;TdYTlBz=1Y z>dRzUYd${Otx!<9uU9N*XYzvJpzU$2dQ_t8?EwQ5Dm)207}5WPl?BS_NEZK*8@VZ@8^-*@|aY|I7gh}12}ECJzj3k zOCJ~|P=hH9`08|~hd@G=oDaGc0sSwrME|vnh8xB{dy!i{wKn={S%q_EB{42-g%2g| zi$EWVUP77I?s7VK0q+di(MoP`+@xnAl%cUASy2i=P;pU9c15FD6tZd^lQ)hO*9 zResKnl@(Z;vh!BeC}u8?I?YuK$zrqV;|T5hO)nq0gd99v{}kV^1`XC7$M1f!EKP2q zL8hXFmB#Mote5I~skVt5v5h>b3v5xAHIf;1IaX=T!s)Qr>6f0oGRqpMeY}gj!hUsg z1ocO#ARK@OIl|6+#S5KOY?NQ&sLP!PE*Kl&D$wc`T8uzoTjBxdrrZVhYM~a^o4;@& zCqQ4?S)&7OBAuz5>^uz`bKGZ+kmQ`~*GeLnA9yF*`Vb@xqOU%1xd zdpo&5ABNpOqXZ0o89YRDwSIZK*0yFo{$Ov+p!0fBN6f*`xA^wU;O}GmbKFyR)~CVx zh0}|1#d;0V#rM`AoT@XUXFi{xBj6H}X1wym)b0=Ms6 zo?vzbxX(jJ?gvRInRpMr^amcSx5;n3J>FcNA28uD*DGJI)H<9l$&#A{X}4_|El0gi z_Q0Jt;+W4vU;Vzm#!$Xb1YI#Ky|_&{--+2ZuyfF#_ z{$H%ZTSm&Uf`b5LvyJTRknqg9o{Q+@XDN7Vq@y!*;|kB5vu(77Aalvc9@l8D ze9g}9wd)Jk-AcYU$)aFMql6dB3a8o35go~Ii(6kuEhY}IHyt<@54ztXVVZZl@P3sEl>H?-uuHWh~cxHr8LtinxB$J z=hYdFB=W(Z5hYiWQn{SPu%6U%2x4?p*$tndY;N<%4~ujdnG_hQjHJp3O-oFvL^y!; z;_lpXuAoe&TKoWCS<+Q!X(HX~n)v$@#RBQjv$7Et^To8o`YNn>!kW*{qwtmlsJbEPs_-GQ3x^jqL&CKEC-T^2Q93S&d`@3wH=bd1yzUh~Pv<#Q zKIXtGGH_w+99N3*_FkqxT|ZB+9c(Y*_y&JAZ%DFEu6jfRCyYHkPRbXpH6@3-#E$ez_W^!=+rR-z9<(s1YfX zx0QFM_No6=NwYK1^Xsx-8fQIzt);P2V&Tv$usv!YBqiBqV(Q>pwRSF1DyYG=%9l((R0C#U4K@4bKs4TN8yi=U%*-&q zI4d4tMpxML<&`WkYjie({Vbx(F(HIUH>Qj1tY@;vR)OOi3tKB4G_VLZ(hvif)TPIw zNFp*g;3R&th&*>@`~+UzjK+DDe4l-L&oY?KEMu@4I)*lR9WgJBS|Hr+Z)@Hhel+DB z-={-#*v#rw*7fu^rM7&@bG0r$io-Q=3v3JU`XH3!_70zF{-ojiy!6Ql?XbZc%=;R^ z$aV`>;@S?FCb59+q*iaOOG?Y6AVo0sy~gxB!*RR5;v3OyL#+vtp~il{@m-(XuihFQ zb~Waqma15-OZw@JUA4}Cl(zgl&qL=(wKXZ|*Rcd=3{L^863QZ{) zPHC{w%2p*tTkL5BACdc!(==iISazC!r9SSg*@_&Lwc3yEYhQK6(=M<*`H6X*D{)zO zdg)BE$N3&3`gTpXW9+l{O}*LTl!SMlb@FDD+g-l)p`T!1%*7@5+q`|?9?7r?d&vL5 zgcJWJ*H~vJ5M^cR7i&xmY$ap>$?Io!*z61; z48Xq3?d~-+kL}2w3@!4==%-;0x7Jc6-H1A-slXa`Ix&?-!dDQ(Guvy_{j#JFX2v?1!LE4l zM$_eHA1T`+HVwAiaE+)|&lr`c)Yy|N;vurHTrgU1=CD7XV0XRJ=&xlmv{K*yo+w53 zM^2&XFumdNWN4y{)l<5-NDF7`RioKW0Lx5-X=6k&ukHn zU)VR7OGaj!C}9ii*r}4^fjFV3oPCV^4wz|vC#F~~wu>bbu?bL- zH9>_PGW05C0vwK_mK&eOo^M*i2t=ELJbm4%;E2^Jg1!U!?Pz~wy+TvZ zrjaLv>#4~j;fB)2aLEmU>|r|AJzM~J-?3wC=31fNB}P{4h9;M3ZSrHlJ!~}-Q<%vk zW!}SSj1SFpjVsk0Dr)GM<8wAFcI#oa11t7_6)=PP!7ZSwf@8ZQ%I5tbAENs&)t5b0 zm~%1c97~P5#frsasBY~}EDa$2UOwsE3F@SqrFr1e ze}3;`*8K&RIIdqWY>rY{0M+W-1%NXTb0}*XPsjWll!lc6QJVNp*8r(92253bEba%k7gA zzHjl*^}FG|`)i>5_!IXea?Cv-6yS|Mdt$ebovOd7l%g8M3$(3GzS$kuX#it}zF*+K z*f*Ffw&X=CI$y;I87YCW>@|dn9MV37jT#m8K6i5{!i7~IF_WX?1yDx95t#EtQ`U`3 zovA}cFLtXcpYNjtaKNn`yBr~*7;xp6XlrhEkz!s4Xs&#|A%@<5%PI93;=(fPl1trz zsoRcmr2Nw6SKe>d;Y5%>uXEELLQK)fN}uHh7YxQ5o`kl|eM~~l-H%WiX&qM_c zZdY0jgpo>?j`FIswv+1A7%85`yZicdY7ME)v0vJH!+2U65)G5bI_ZyTHEvZapq=v<#6Da{CVhDhj->t}57NFO=%~%bLpV7_<7rGji1?xIcJ| zl?q9Eu3t%r1$jnixXhm+bv?ad`y|i9hA%x+Clw<|3NB$uwVUe!S!z!oY~G?=oBo{s z?55YOSi;IXyii~%(urDnBx*GhB!w^=Jo#rLZ*t8EN>eq27?ivS7})_WR=<{r!b#9} z!AZ0wG4D54<3$0=@IJa>C2jKKUX|4m2C>`lVtf9QT_h51w2Gr?1SmDXH^nI>yL7E? zKYqV~*&}~vWXMo*!{6(RPPp5TOYeBF(W!I333|~N)%9g_I-cV4-C_VebnJ9|T>D*# z;XXtN_Rs^p^(S{>090iiA|A7{mwA3az%lontlPhBKpv`ko(V^~h5mz#4L7#|XC%Jo zkC!yehLsHNxL^Kg8+*T4oo;jmEs&h|&TSrq?y&0M@|atH9Y4GsACm*Uv2LuirkC}c z!+CFbB4m$p&>8!OQhezPic|W>{X=MCHBixVi;4h)0z)6)&SB}bxEh>SYn*;>XO%2Z z<_gSJ4$&e8)kkEiD8Qhmj6pwFSjl*l2*0D-P_RSr1_7E$5??qDp0f+M7?$`V;|Zs@30lS@cfn=0jh72YqA2?m*$`4NC{R9x##>8o4&)1` zbD82VUV-!AQzVQb3 zfBoB_`_Or|3I^oPu+pt6w#+^g*z2V8#KwF7J`|(+86a4H*dcflcnG9wNb@bP7!7N<%b8MdeeZ8?|VK*1NDU6Y=6BMym4kL-$UTIl}ET%K}Uh$X>2L z@^gUS!I7DK6ca4#pl7Jv4z-|Id{!&(Y;oI^T3yxA*ozWy_825WM;6f8e3^SbS>wAu zIAw#fYZB8tc*lodbZu{7M-y6});J%rdvtiRS5}jUXlrtVL1nVG+?;IMQ{z<6%c8t` z;oD}q?|WQRbNRzj4tJLgWd3w7>GRN=I6F^79Rp5GL3cN2jVI|FQ!iwGA8+bJCi?Qc z2RFkBaQ+x{rtV1UybafEZ}i+?pEnPEf33h|JxH>vI^m^RzjEvT` z82g^LGRqKCt=!urJ*i~#c?L^H#K{{Hrfg+msd&@ar$GR_Egv;O1Q{k`bSx>6mbLoY z=nHSjgxhRX7&KmG{nD}Os}YGBoV&F)!qha=SnRRZJ0Llp%?8NNQj^dCmOd0L&WOk* zQ1Rn#qXYei=jP9r%s6|xxxf=M&e7({Xyw+5Pt;)3oVU?a&Cxi7!?qd^<2D!tCi@)| z6MXtg4>l(37vfs}GNkLlJEo1jhU`x=kxQx^5{@Q^^fctMu# ztjG~^9^Ykig{smFttjYHxM(liEDrEOXfP|vvC|!}oI><@_K5mA@tVHra6Dx2blyR~|r%E$tGlHGRSoYD?*GDn1&y)mR z97EjYQpUP4xgvB=cqjMdaJYhIZ(KuA_lQRK$kN6=!GMQcNrrw;QZQOzbbxsGCPagR z8t*%Uel%Kv4o=~_5*)uAuWGk>B6#zzALIShKRn=zo?Wde)NBcKO6mof#wxS+^#lIa z#@dwJ_tl+RdN?I!^W8MqN!77IzD}}1kg+wB^$QzlSPbhH?#k_1>P2@Wn`#o) z-oRuc-XZIqdB%SzSdbd++-PZ6u`7C0Ep;d!rX0_<<4r_+S9AS>O*$&Fb41#iI9Rt` z&4=*$&rvu1+!C_jdO53FH~Lh&&q%5<$o^wP=nX3Tb7-idx_KE&8Ufwwpa%Ssy@3>m z96PoVT&rFu@K+!T0e@qp#l$czNP%a_Rq`QZxsl&5!cm+PppA345zM{Ky}#`((e@ZuExpr6+}rr(2g&(~Ym zEH-6EN35a2vw=CzGMg^zIhP7$UIbBSntDWWS{@jP)dET!`$1e)S z)!*jr4HwsOf-`~hf*x`Db@Cb0LBWAnBGlZ#_4?1OL<& zo~Kc+ssz-O9kPvi51K(rfPC-5+RKH>&S@xV_1x1bfZr4kT>OP^Y+H;!4qZ zIhm4#8gvC$%;EJ8ICfgO@MEXH-7+P5_qExb*Ugjoh~aYYKotF^rDY#Dm;pHALy3vI z#gNtx%9p?x2M%|sU5;J3S2*(W@oE~IfcCJHO)C%-M1WQCTsn4YBm~8P;RZ*2gc4tI zPX?$0P!?{7QTJ=gA+8kvc^{+q;ddNU=UqLk`qMT+N^8VIF zwocIxKGj&)QjOh(_x!HjF;9*cJnpNS$p+0{!%8YDjE9wTqO&J@$F0doL!;kgG%%s( zf_;8zUd|x>HsPnS*`r2n9Q%CC0(Odqz2W9WG{RJpo?_p=Gl;fOTEDa$^N!;+&6T85{ zyF_6!ZI;UwaWTV1Qq%gf;pA)|f%#QZKYKCS_7;;D9C>2AKuUEjny5jxzXM89(Fa#v z&@es%xtd4uV4OmCyB7*)wO@6k9(_tG8t~hxnKv-aB0>^@Xh`vYrMZ$F}Ixt`zx24d`IHQ zCi?TBSpmYqA?vZwgqtxT_CwxdG{pj8X)$$)47h*i`yC}E9=7W`s4+yy)86C{$N%pV z3SvjQN=4Hw+kMb*Rb$x& zbOEhDu1{6?-0pa*PIFpyZVuWNe*6fIy#V5x8I-)kPIvnLfmEVVla9e;^fgO_Z&rP%$o22qoPz=lU%spDr#6?``T zPYwPPI7?dE=CH5^d;OD-YtW>SgEl6(w6WQ@0!m7cpEO0YDN*Z4jk|twn=np}yl9*$ z@gqxh`&?l4U6{5ZjryXHLs5nB_|A#w^-i3jauAC?v?1>GlO_CQT(D+8TAyCc@2F3+ zQW|Z}T|e;uNpI|D}|FpKV5nc_<3MpfGuuicLE9^03Nrwi4d{)Z9|?9@|?j zZtut8Sks^jrnzL)z;e77Eyepkg)|ha5i*pcu(~>OFrP`f#o2;yOe-(&jY=Y*k*xy5 z>{6diTA2fnd#ugMj1$jBQbb(|-hgMIcn&$Wlp$3kUw(iRx>qI5_oQ*71vt;w-G=`( zKTRoZc=#dxMO`!Hy!0Pn0l5L{ACnJflLA=Bv$=_)6E;Bevu%o&>eIa^gel(ruU9U| z_28sKWplrdS-~s@1<2O)2&S2NIUj0H_w0~C+jnT`0@_fJ2;HH!!I9YnC_J2ao09&_ zYW!Kr*!c7RIf}iMTV}-;GMXx-J)8cKik-$$7M5vAKm!?C)XM!XQu_}b{AIeWBBhy8 zTNO3$l8g7W_DcQwGl*RPf?^EINDpnwk~=ii;xE^qF_AFPK41HlIHkD&i~*qR0*~+Qo{ofdCwX8Mj}VVpGad@I(KRvVg-6Qbiu_i~{MNpWbQ6S32`5%QEK0ePF}fy@nhwe!J)&8`57kvVh9(c}d(g zNwu^uU-6?|Y)5pDH7E|-T+G>2LB7B?(+avYmu$7R%SpX98QZ)y;~r3+f~6jGNCW^D zT7A5ky$Qy}CB;lmNBCcR*+2YVFV}{n(U@~PTbl{|+aV|51$}Mg^RnX=V@f$)>Hlm^ z*ue3W2<-B{>pskKJG;OWZcc^nPKIZ9So>2+WN;3Z3&0+E#0u*YxGAG4*-}P9M-ovb zA!B7>J2Ka7Dr0Bvo=!O$I(=u^kNH(OMRBYRe)KNg9W-Cj?4S8f)WwDcU!*x>9{K0j zV=-I0DEa+o!MlyUfkqwVa8=f@!1OHjKhjN#V|8F6(eNtVkNmzR< z{!_|nMId5W00qJoq#CSyP$C-zHmjkT&XQ!cxlQMuOw^MupYu;r!2EyjzRWFprxO?rkYH5(^fF8*-gYl_`cQRf#WK{$mn;}u`Dw~c`)UX_BR%-r3b zpvX#}OJY$4qfK71^z4Zr`?qGcTDTi^!0|pe1wrZRC`UmnwXr1D<7aB|ns0FmG>$YB z)~<;ancW7K7BcfQC?wr6I;xsZ{VdzzR2(4RDm$j#tef65mrLDS6haue7vR|QTjL{sevQnbL&U7-g-hG(1-cr&Kqt^fPXXFzlkpGy6 zuYW`W&i_PHC;^a`E734L+el}tN&%v1Mvhfng*Rajl|y*B8Bfe&IR_#VC zDl)pVf$qM-Id5QM1=g3tG8tOHkLEy!>vwpethu5wamb3}2B&+HRMAjFo!#9rlV*3< z2=Y+xMp7D1NLBVNsE(2{bVLa^*_9-Zi1PpB4%5V0R+_p{`2_wGA_0*FFGuyMdzdh+Ib8K7E(Q4aT&QZqEG@ zlOFprCiwk%AKPAUMk1ewspE2DzIfzOs-rrf*lu*VUvDSuViQ}jCJ|bpA&T+Pszfs* znG;zxRKsB9(BBbBCX0R%WJQe5WJX(FSeTe8l3nV4It(REa!#Gw(A02b&m{SO;$4Jo zdQ$y&MVSdP5&>;8#W8yXpbBC9C!mv6q&yam1I4G6cmqb4%M#IJkB}CYZq5Nq}uqe(q zK#h*IKR`XLQ@QYdCA!bHzgR;J`S~{I=7p@vB?ychN~yx^xls=T`NcnEohvwuaJH5a zH&JG>+s_@KQccB+i!+biQ;kcM}?5D{z2?f(r)kYPuE%T6I%qou?OP7|;cI zX2_c0=R*UaD8$l2mZBIxbWc*5b^3FG%3OjdX6DD2h8Rg@{Ku4$=5wy_p1c!wAjNK#hEHC4ohdLBno#V-OV%EeFf zJRqo{`LU_O!aKhc^3}c^{Bj31{Dln>ejejx{iTi~^ezNN$ZadQvKUQC%dwKP`MwD_E`gFiG3jmti3dmMOZYu5`RhoQ zh9+7;9tGi4|4ARt>i?psX+wQR$sRx>$-mpO|AKQ8FNtDn&PxKL6l*qt+G7)Ymio|p z2q}nA-93)He4??n@A^hNqR>uCaI)X0u4ygc*g){oHk_;^i_e$|&g5akl=R{EJE)KT z0U*wS{D(f|pW}5Nr!WD)NY?bzLQ@I8W7)*DG2`dt%-ptR@tHscJ6NNN2+J;8gz|TZ zt-SN(U3g4vddk*Vlg{xgG0`!84WC*9EfpG+Npi=iYNJDyAkydx1WV)`KizYBl-}p_ zm%kn5T8z=BS*(bDHIqmeCvkuc@?lZN6rCO$qf)gCQq`}$!B zLQeS}U6VDBCQ6WXYk^rb4lOQ`8aMq8Ng8-X%eh}5#Ou6%qyoCFR#l`eAx1aJ;^8EO zkR$O3K=Go0M}U0Qrxk{3?Q$U7MWx2WAx%+%h64tDsK%EZycmTC3VldD*er&utPeUF zQulwo0O=Mre9tg&T9u$p>zYKhDx#Ph5hmrnyJF%B9)1oj%ZXAn-DiH3UfW^sfr(zMa`uWvC;j($CI^8d263N%|o zJ1C%*5#1}5zXOu(zG?jE5xcnri&q+#%sDx9P$wR39G_a9ER;O>CbYMloP6zeQfz#Ve|DocMf$14_+|b<2^gqu1`GyX zh|u^E=*m(czY}vx+ShEpe4*7=(Tss{g?9VIePAEt)N#sJqn<6Lmg@PGmSerabf9ASQvMXJ*~kY_+p9OK>3d`hYz7HMlF14R==^*qKAYY z;=is1>p)p*#N1muLFO9JZ)lx~PBr(-OIYmn_03GgE{##H7K5~^2^rV`T8cRlOJv*L z?`12yU5qyGV(HkqYP&#A(c zBtO40d}3nd5{rkfp{oaBD2>{?@`BFaOdVyvd2AA=rC@WP>N~^}k9GC3rKU2ZS27^; zfVMrG*5|BK77i?cb^8yyUq!{p(<3MJ|wZVs} zAs~#7#Fk>6&i7@|wI&JF!9UhaLfd7h{gitD+48o%nvm#g!(#42Sc!qE8nR3!6#JmY z4nXnSq}JEHPF?Iz3h5VmP;ft_n7WN*`36l~5!c~3xG2j!z6_Bg0!Sm?H8Q%oA7lBA zFKxvk#IgLPokN=yhvyUXp%o)>F9hxO~v{QE?y8955*0`)4AQ z6zaVSaz@hc(r^X-mWVL_amkI<=#O-35r}C(iS;GJRRDnHN3}{&#RC&)_Uxg4|0GX z*J=1;uJT%AZc2=??T}^}m6id)ZgKqvl^#;SjDtUo78Yjz^x3aKwHoL(JV;P~3y$|^ z8RTd@lQf_BVj4J8EGV2C7`5Q=Vli2TtVwAgWKr7!CL5RutD8eiYn#P=_o|1VAV)OW zTIp^-`4g{N+o0>a9wVgkhCo(y4H|a06fD_O6S7e1avbUW zVoOX|(hMrVs72jBnkNh9a^oi3t!|2t_`?;`->%{}dd=BLA(83v$tXO5I{lI9u_axq zir>;GT?-_cY^X~K%t@+-VzjYc3vNZI=ltLUWy(aThz8AoG#p6a#|u4(4K=R0gMo_9 zj2!a@pjD#IlT8!`jmre=lDNi+rSdC4w46jLMn z|2g2%8Z^)KJ3;Lx!7TarBCC(4+s9%DYZwdiVkxG$#b^wN75idd!Wo~s8q0& z3}A5gpL7Kgz=2J;$Hb8h_{ZggNZ^MP-WbcS+=SxIs+*9426!GKjlV{2((z^F0HoUe zNIQuP=!jcZsIaI1U+(_7*m=UG<`zA-DZzb~$pvQFVsC&Hmk*RT^#)<%e0??9cXApt zDV#A9X)BFSxtm&u0~QU$0(<_m`ZV};7eUUSpzh-pK#fMD$of0|UQ^YpI}qr{@84Kz z11KXgO6-DGxjPy1GA(6P;SA~6g*LXxBOPOybhyqF^A!5aU@cJg|JdB~ZnMx{Do`T8#;@^UsOjwY5 z)?=E(Cpjw-w%z`83y1V1=o98j6_jWQH@llv>_S!yzl}W35%N^8(5kJp>mmm*u86T| zF@E}X=I{M4^rffUDJxAH$x+^owQ_Ci0s8xMsz|pxRYjx@bCBAY=CdjNgH>P8-hyNo z-xzzIjy-4H3bY*$e$RTnQ3D?*%O0Zrh#o3b*ZM}k6bx~BrcDZDA@`l<_8i#NUAw-8 zpIQu13OW%ijz1`>TwbS>ZvU+%+lO5hVr@fQG}~R_4@gVYCEeb}L+N_z^K9}y<-y1O zv^dzFm1*~Kg9Odpy74JM1xXl9TH?atVi6ieak#t``ys`j59uzc8a2rkJYDZlwYcz? z`%B(3D}(HA@54`5`u{E69-j;+|2KT8A`X&)1W8tMR2*o;fJlCI$$=UmPHskB_xz1~r`UkI1>Uyu;ZnZa=wvp} zc3{@s7U(de270~P2|xcOS-S`n(i2_q>MVxraRSCzFQ3~jBKYn=5?$N4EjP^hiLvpQ z_vs*sX2|=Eo*M4f-XVTZOw}MuyfHkb545PDdk<27d!bhUbEE1k$m*Y7 z<37tr0Q(gy-rid?)8pG8jh8ZUsKGI^K~2L|6w8$pyJU}_U7wTSfNNsg_6)7tU9q`^ zi(6+%PZrv7$>Ho!F+8tkbvQCY)`P<>rs%sBhX&<)&~EKkf9DvD--;tLT8G4@GyC;Xj$wRk^9*XlI2W{Qrsn4}0f zQzX|KB?ANqQoq|zaq$MzB-LxKRGtBU%zd{8 z9a;S!t4EIm9)zA>597~QJHcvgT30TyMZ(YFJyUm^7j^d^vxN@$-{+=zXEHFF9-)2| z81;M=e!KsD^WjE)lGH!9F5tH3k}X$cu;<|<&)o3It#1Cqm-;Y-*Ab_SU#Uw@ZmUgQ z0pkpy+kjV1Q6oRLo{NBhm}9yrMmoCt$DS9l`}y{#`<~Z6)uw%o5P6UO#)V_OrpDkk z8X-i-*+pih|32ba{mH~=fs1jxhbuP!?DY6pvmd>U%4^rB@mHRt9l3E;oTF9*elHB5 z>wVe#)7(B(9`Zkcu{fw(H{Soxy8ZDaD`oA;6Zg{4ressXEvWomVk-%|1cE!|MZ$4zTxxWKmZTEXY>^aYlKVQ%dNFoB4b<<}f z$@d)&1>^<1Z1xOARtD#%*W5jS=(+biHJ6f*@DR&;JbCL)u0wPFwzm1Q?DMkz+%I5 zI_;0`wP=$ARnZ4s-?J@t_~Ew%eM9KILQfB| z2s+J3_Cx1adD~YABzu#bX+NIcmW9sl87r?pigC4;;3Z8bO-msa1e2E|@@mybcXy^W zSJ&2BdairuHavq{YHOpr&0$drm(;|g%FDG9H|%~~?`;UV`3H>Wth#E_Qy_VfiDgt+ zPXgTz#@iu6XHOkpRVp|5S2!O_eFz*(_Q{*e)Yitmi}f{E?ee=8WQ;tt+K(Jazk9>K z8q>M{UOKht=>EIWmZTgR+4fPL^bRe!*K6uBJ`$yTm}E5LYG|6`QxqSw)q!;#*LLRs z;Gva>V3~Fr4Xo{i(5{01&E(s!8@$}s!RoPk2ziH?4vpB=8Z6s|)bl%)&TD(YvO}%E zfFY+&4Y}!TGoos-=Ec0ci8<2k#5>O!%lT!%Tql}~45pz@jjUpvY&>g|40CwaQ%_iD zI6MK~yrj8^UHBydPxeIRnI;*cN`eBjmAC5ZqAyoddFgr786+NvcX~Weqf1$PMIzTE%AA)i z=@Qe+F@bTb+>xtwSr#mw?MVS|H}tbwn2KfHlf_fGjSWheiyeGJIROIJXv4n_*ZXC$ zUng-U_g;JAXolc6ZqD4!#6Z-?o_B6nfww_y+ti(W`w3KIZ(GWEt8b7*H#Zk=&qn(h8KAlU)Ozr& zI*ncC!(g_OFL@mL8z|_MG&rd_`o5+d8}G%1*=VQB{%v2%IQKc=x${Qz*+C25d!9!- z$Chz4y=TuEjm(Ad?Q~&;QPRXz_ma*wav7k}1#uI8~Pe_g>#-dek`Si`7c?w2oTHrsr>=}!Hh3BA30PdV~S@A(2o z&Ex(0XV(gcp}<1I38BrPAd6Z!n6qRA*HepD1i+RJ^iGXN|gC>N-dgo#UxbqD`zH~ z%jpFcdUJrfrQN;jERj-9YZ~R8bX8XoKjiWXe`6z7C+{&xa5kcUjVm6{SWjH~x8>Sf zc;ZqARd5)`WqGc!*OX${<+Hu_rU!H8t(5vTO5JA9k7lAMcHrS2npmtN8~@-VK6yv? zJd+r_PnvJ<@tN;PZ!ArQH>H5=OI#=GR8y^P4I5FQ-3_Gc`G^~|sTb8NWtGR(esX|q zYohDq_u~eli(J0f8D6(5^iG5SmhElm)B2i6i^yAx)Ax&k!{^3t2qpgHC1Q(jyE0)V z1b?3|q>R0s;GKOD`|8w~zjq~-A2wi-I-`(ejL{x`~_Wn3+3!(eFv9OQvH0yLhIM@W5MUy=E4Erb;bd}M~U72do{n%UK@5k zkJ0o-)i8fuAK)tY{<5;V3!yQ%iL zxg3lB$mOzOHHtc&m9mE%e?(3 zK={`^`lO#zI_1Ag@lXCF>4z68_o%pDyFzLlnMk_doV)+JkAm z8cHS89Oe-|6Cs%XiIKny!y=>tEws{%mq)vn@(YdO*p_I{e;b$Sa!9b7WrDw+agJ z4$`jY3dor%9KVkB{u{Ziv| z{Zm!q*M9w?7Na>%Z|I;;cXQ&8R3T*(O7k5pu28*HIu38!E!X*@?#1QTsRy#)nw-&f zR(#{8Umw1k+kgx_@v8a1k;K>@BW}b;G4`D|#xNUBYxuA~cG(eR=ORk?Ts%}IdmSv_ zx_A3f69g7jwRZPLbX9l@i;e0I*D3Pt@}DX=p5%ow8chK`>8@sX9bHK~>Pa0P?W(A9 z_JF)?`jdQ3x-*azM{3!rWunge$B`#5OAqv-$@bj$CxDc*+I%A>lKss=YgOTXLmvdr z*E`7ULQ{^HQ}aiRZ^lFXcAvV3Esl9o(_~K@+%SmGWKK{F6 z+vm#}yzxyJoU#_QzkGhwHv~gG)|UAWFS#E#{6diiNJ+bF=?~RUq!%*Dqz9tp*Y5tH z&i|NeyBx1A#vl0W(M(rc3L0+>I!_&(o_z&s)s|-me*&RWL@bymB3E9v65!q-^NegMWZA{`4#PEny>Q>H!ACHEu~?Zhb-e zyg;|dQrYgV6E*`u=M5uWjfDI_s=#Xg9~j4UX0snwYpt3C@77rl5H=e_aNWL~_BAIAooJwLgL zuHcWy3)0`^t5vpuK&38$`aVxWjBzD(A_E9^-fpify3iAR(eP?+mbC2&h$>ko=lH(kb)D^a`GBc2U!=UNUM?zJwEtDKFoMA%X zG{gB`eVyfaR%SAhoI9W}bfgr#d6rDBKlhyCIb`rHah$_w)_LB2eC4pKXKiFF+i550 zRo+Hi;tn3pLV7MK6H(ioZCDK}Y-iTI$@$&78*%mXz6!bWrw-U3&Y__NWT}r1FH4u7XlS_ll`0gl}J6x--o)1&!s{*v1ux{D} zoeF4bD$^Q=0v68Xp~8Z6j$by!K<3NnWUwcjNk}InXPV;HeAlPTakJ6^`!DTw3}hQo z#Wu(Dzq}2M10Fw77pRN(Y&cwO+~8=I)gCNWbq>|r#C8qny@JtVYuD1&VWe)%L$QPk#vLeV=e60B2xB>@?GL!DXnQlIU-#*JyBK3NPrH+n zh1!0Qx_7v8iEXz2SSFe(wOjlZ*gOxF{fulwm}*6l7f)eyNkzDfI8Mjpt?tnK8zOi* zeWz*FFb{+I{nqFOI|D&*?k*1dw~J*Q0YhI@CS$6TD?2Xd+GEIQ1C&jln!ay6YErQz zYDtfSVxl;|rAnBEi(VgsBl*z;!?jhVztG{$^}jz1v55 zBKu9X8%V*^eKxdPm8$g4Rc zusuQpUxWQF4~w0)kVi9-5^&%bt#eWgbLhW0;%Td^e zTtSY8%9?PY@?7K7+Kc2HrfLj*coOA&+u)>!hwcHEQs?2s`-GtB^Ck0#(pw6J7jwC+ z&mVZ=m&zoYOdH}kmOHIJ4OnosDF)r}kcj)r!hdr=KUvYndGwwg6$LCG^4l(OkbpL% zDohI25*HiT_E(#eCPe9h?szRjyxILH1NYj7#QZj%YuZ4bv%0RQ?&RmHvoBwwtc+ws z?U7R|<7rS#VYfO0wy5LpMOyQ+6oEpyDKX3jG=jm_(n2v8PPv19Z&{K9GwCjUsSg(I z(fap)VU;RbG|}kYo=X15njn+z*zQzxtTp5FvMs((3RMLs(t8u-i&t~3GOz0d?ZsD2q5JR(3$Ja9 z+Ojqb*8)!}uYR+%xKnw3)tOG`zlJpb1pHR z5B(heyllKD#b8ZxW2t6rO}HIoC&!L>#?*_H2JQY+mGr1eT&cm+_xvl8l%eBi8m$w|A#_^0MncmC(PW}3+ zj4;a6sweEm$#aMDc3sBsgsyVTxZ(kN)C>H^4H12j$ctcq=&Vknt@K7>@HiFgHW}<- z!!6{&SICYQ`|aU|u-0N&g|o8TOx`d6$D*HMl_w%XOer zrog^>sp{nJb+*&q^(hiXXWRMh-umF|MAS8Aci&3BiuaW0Pb)#iR&5u_swF?QoHOmZ zktl}*eFmLd?rjY%-?tzp{#pU`coE{<4O7f;r>)58R{Hg;>q-%9JU&S6jHEsN7^2xR{ zwQrL5a-*DLsB`*PWrmjIRfmKWEd^T!y|g5?)>I3Eok|{F;~q>3IY|$7&U(yHTuV#> zDhZ#M!q8ixn_*ZFqrP*)#rh$h+eVrDE=_VI7Vd))xr_QTn>;5?4E{lTr~mZ=7zh`< zg7W2+G*H6DC_f`h?qa-BD43%p-{4WFMpl?jsR_)w$?fWbYuS1?d8oo-a|v+9QaCxZ ze-f9$99ET^<7D+kU46*_`*ZEwt8L(*djnh%@F1b9{XeKUV6DX?xNfVzjG#|nG##zx zE%WT*bCQH8hak+>SbNRmc~+sjAA>XXZfzyv=>oGa91TZlUEBYxCF8Gw-)q(LtrPSm zU1ID^78~M@8#V$Zi%=ZysJNvZP7r>X=qu4UVy)#Tq44{;3%=dkU?nG|<)eWjw=)SV zDM{n4)N~F8*wJu%9_i~?Mz{B(oxZ54U=5bC-JhXEGjD4ja;!v2x*g@C#)$i9Vh)A0 zigBs&1=b0qM%rf4E5o98g<;whSuI(B2yCKFkG1W*?q(nlf-cl}CO!;C8a&@70&>eh zr_dWZ6Z$&eb(BqNqE9&>NbaVlXD?eL1J9P zs0aMa@j9Z)n(vo^H)T}>7~4H+RIGi$70(`EJdaY$Tu+3<9L_HrwEpXdC7zD%x)AHd z(O9jSD3uywQ%f@a4H-Q@9Xqz0;rLIoG&((4oouilb5uKnhY;ATZgumxULFuK1W))K zJMDzKvFzT6w|*U+)d4YRCBtTyH$g;*YXLh6RqYM{$IowN?McJ4%C{e8>mTpxuV4b~ zy2z}NbKvvj%6<>Ij6PdGtX{EQX`C597v!k-wTG9Z74m$4@mjgw%V_d;y&frg*!mrQ zf4*FCo#V_})4LJ=`xa-$U&?{KO?$v*(e$C>rMqL$J1|pb$?Kb8gySND>&JcO%I5zZ zmZq1$rY)FLKl=|T)_x<_d7^!rqJMicJvT>};xJ$Hs%F%tR&v|lb{p<^=bpx++nV#y zTvC}bFZ1N>Tc55oAg0PNW?Nh_Ten+o(UI+BFQcFs7pUJeq%YZKEc1xcV$Q81EoBc* zfq}&X25H`rMjw}77SKG{JH2*~)|9nX4l_UygH5o6xkg%49?XNWRE8-yiJVL#U{ehu z#iBadm68&*6A;*dgX##q{xd1G6`_52cEqNB?9`IQ&ZEXbMrGPa^HyYjQZXmz>=Jfd<8IO7HRzq06fcKzu2|HyjFsJen>T{HwI zxD(vn-Q6v?yF+j%xVt;S-EH9-+%>qnOK^g{nZ56M_q_4OSc5hB0kgWgyuPm9aD~gD z-Q0byZP{U!Po9f#7BQ2Cl%Rjad7tJW3}@fo#9~u~qgELFo3Yhk+=66rb_p^f%~gC) z453wTG@ty+fsW$}%-rSDcK)3K9-;Hd^WkO3v&E=2q`2ihaL3-H84dxHs)&DZLd!T9 z6~z@Ml7ZL|$DcxA7M0#Z9yLpOgiQUZW*(lAQh`%ah&sdoFb|99I@ya&cf*{fm@?_7-v0?mVzIP-Pu(%3PrYS*A^i569%=ozZC{wcb4R?I3shWM7q7~ z33xk|E^LoJZ@zd#d!;GCkN&o9?M}n*p)^Ws$Xi%$N3Ruz6~T1Z z+lHtox&);kvuB59^(q=uNz zz|FBS%R}RM+Rk=oO+p(SI(~Pme(h$s8m_l> zIny>rm znc*AO73+qMkee}NWp_s3dE#O;cRee?yqFnMvEpmogvYZy%MfCbPvEbI7_)pf`Rk$~ z(H-MM27$nO{*Cu2?fIP2d{4u+b-X_(_xk(tS9?^F2PF zB}NG*rX-p2=KuWs?I@t4?~$nCmObMClZbg`l)`s*eEmg`bl7X5C3 zhW_3rw1&ejv(JcpNMej^#{Ho8qD@!ZaRaGU2#z%)hK^>tCG~-$FPtB+Ku7SL@Hka20XHPM7vh__XPI*&^TF;5^?6SBz4ZHrf$w!N^87=?$VV?w!5G zJ14?7zl!u+%C131>5Y?F;v~~F=|4lc=>i?t)q4>j_YAJa8_UUI@4q{A%5fvT8k#bT zdBpI1Z&W1$?_eLkT1Qo+&ND3x+d=M2N!|ml@RKtYO=pIPyJudtB`n8xg&7Y6Yy>{5 z!x^MM;!kRf`wyM^Ui!hi!vdaN@9w9Tr|0TASJw<8(-52w>zJEJFI4bUZ4G`c!bwTp z3wdy#+vr_9Ho8IR@iYl%HTuW(oDRWm=(CYqk_H79~HIxSt8Mj0bTH0W&C(GcoGd>lt*K*|1euR()(#1{;#sWv$Bbf!}0U zO!28}v`zNZ7$V0yf4LSH2n?yGE+Oy_nF`4*)iBS1TNk=kUHl^D!yi8rh39887N(Yp zc2?HbmQhw#&R)WR$T$B^i&LM9ju?DurNrpTaU^Ri0ceRi_$smPG) z!x!|N+c`8r^9iebWdl3?qJM@J$MenB@~W$!(*8Yd`VCQ;2hsTT;)tm|yHWd`bd80D zr6f&aHU3N6bqkiK-&o^ow1UhgwiDFR?DK@6lkDz~&W}k`im7XGN7Mb7qWSOu(`3fo zjYo|H?nB1tk>5%(lt;l|u(^*MOXTz?dbjRLKRTmup4U6PZ~9cI=o8jWYR!d&Y4O;j z3q>y{tZ^)du^i4S?U(fHwDEw5FsW4Gi|whydXpU2AIuY0$j@5^gHyOFF4$Y)$9t}>Vo9~ax(qNcC912pF5A}WEw zMQ`LLwim+#I@*x2rt7~nP3@c{bEk`i>hLXre(^UgqjS}yvRai@=x5gBMdV4rn8_OzHz zoHu>!2;dwjOlR^nBokdjlo3}6T%m^Pe3NjJ%$c@xu^bj%EtHr~ob`X);MydvWe9l< ze@0~wAt82KJ4?aLXaUMwVuFGL9wpW#H9URUfvZe$)Qw-tzxk6!xNS%}jW+FJCl};f z_QP^+g#NfO6?nOZH1`x%w44sF{5!|kNKd)x&6_i-^7Oig_1p~SP&{Y#G>FGtg|ARe zaDPxn8*|LZYsr32b7{*T7AKf7$Z5}*H-O}2jN6VR5GEMQA4*Uj+ski5cKA>rdt+Rp z@QUQyoA6V#r+$g`y~rCid{+N7A$MRC%VEj2yz_oXPXFbKGQCx5S}-OSoM)ax!XR~{ z@{3JR?pW2M4AUom>MY+u;>!Mzm>L%asHZY|j zf&bTJ)yeOQX#aY}D#wPpitb=Njj~^AxjkaKfA7BgY{`=AeM90*`)R!hbRpbBhZW2} zoOhihrF?+o{dT!@Ucbf6-NkiM!HToC;Y7Ro9IeyF{)fM0!Xxd&X9wDXMK87^CxD-q z!vohv6_Z2mErTLf6^j>B&g7la4BHOwyK(dyowLp`(ZY0L~QIGnkIPBb?-zac&jAAzhtJQ6+5xKE|>LdZA0B`JBAB}*h) zn7(cl0paYVB-(*kKW2zS)X{W?Je^Q(jPllkP zmxm8eWT1Pj_Fcbp1zD?o9JAA-gx#>zxZ{y}HANsJveWNZuwz5B5b;Sw#qIPJ6Ws5u zs(w3QEvvdwQ8(MZ$F=mIhJi^c>0_$aybZO2jo0tLf!pV-LMrw4J*!=^-({8S);=g* zzv5aJCx)TVaZmz)YQ&g8nWAqejQ_GF_vrfFZ*jsNk?JC7ub~OjIBhUsDE>PEcCxMh z)Vcdny_+INUcyW>mZaW`JHuDqMr_#p8!N;MN_1#NNWGk9vP@BYcDRbfY+Q~;lQ+7< z3%A5IQZx&E27Fxb@}9$(-v+n&@)i=7Zm$!Tu7=wJZmgg#D3g0ia+jd;aegZmZf{K7MJTfLutmg5>J31? zB^KyLaG(^uXL2h0O@^g@(+GQc17NNoWW-RQFLaAR?yjPpDXgrV&}v-`-A)@zW1z;A zENt2-Ws?=EegSS9LjIynI~zbL8f@QO#Xzs5Jpb8|R4M(JW-`ro1^YRP+gD*DR6Gw9 zpltj#_S=U6(PAP!-kP{yI6>pZr-S zODMV6nI;Qjzk*v(GIU-sGr-$1Sw#+#{f`_5xAUxDDFUbA9Vphd!MLbMOxY$?lGnd@ zfG;M9_>|q?K>UP(G>MTMh*O2ba9H|khmTV&DshE0d@?iZz1Z3>v$blMnXniSCtC#? znEj?*0;gB2mYB6W2i|EVjBHJ=9?gtGp#!x;$Zfj{N_f6K;&4la5atSA_IV?2if5A# zQDzY~LlY3fJe62goR>T;^CbPhq$M%~M+-!5Nm5~8*~$h*o`UayTq!feRZLmg)5IcQ zOX<}4+sQrJQNu3F5Gsb6VIgL*$f7YGY=8?W?@XOmqBtMDB>yvmVSf$EW%~k%U(Ip> zkB4liO$b6-n2T)r3g_hwxG!%<*0lwgC?QG)gg^{0mc-O(svPvRq5JP>IHJm{iYgNS zU!qXI{5w8VqG%ExKfAm%G0kYn0T>!T8XpNmY4L$5vN1Iq`CSvef}$F$<8~7p3K-uD|~oj!mgIc0z3tJ^V||JV09}Q<9U>fe1@lS{m%DWN@^E z*l2&+4b6C$?URKj&9xuBHNk-DHVhWRFLfsHBTEz&%7=m)9a%R%sbV@5-RaEs1Q3usFy=(RpeR!YL$UAGrw&Hn%$@E9xhilW;{_4O?>s5 zi|QMReh2XFP2&E)D!j0;zOu#Uh8ajkPCj35!^y(ZaQ)mFlZ_9sOEi>TU^OXdaBxuG zF7O*bC7P(aiuwU1`!57dx5V}m0A;`I*vwuCm(FdSss7@=)||D}TR|?cnm_?N5D6a< zlZsr@?dwjfP!-h5ajEE&D{8Gm(vr3 zj5u@oyQKh;@QN`RD_($I0B(=7n0yfZa(%Q`Hf^TS9gLc~JSLkQAP|aNJ2<$+zL*G* z2g#J_-XkO}G8#x4855x&I#=C2;2RGG#7i3I+y33epaf#A?icj*-7a z&7TygNl@se7;j`Q++7IP)&D~pI?Pzb0y;?|L!j@G5=E06P);|COadvDrMVW4%xLrO zzm|U{G~#M=z0O1{$2vhWr`^(QWr>oS+zvIS0qZsAyIxHM1DzC4r3IJ``FJ4sPUCQj zg#hmB3QzL+?;wnP={=_oX=!=01N(7YURr=p&?(o_!j`_kd)42g#FF{ssAz7DGvVZs z23(3LlvwuL*+B`~dM&FRx`-Q2khqvZEZ#j$^kd?cpV?%~*uE>FhC5@cs&f_r@{9u0 zl8Vk*BM%;dL=7XN@=x>rGkqg}w9x9Sd8;5NzrHQ$r)ikg-}2lg40>35`k(IIt$6NLWmGXrlk6(x?l9nqn>pg(xYPiga$! zz+;0IN$SHS?hj$wnIQqHh%oZ7DF5r=c0O1Hy$C@!!(5-ZbbX{%&eJPJi84xRR3^O) z%}fM3d5Usb-F+Q@{_RDz+v`YgU=1W46F5ns6%Agyxt<{1+ckQ>s0@wSg<_<808C=w z%s#Ts=#VhrOOP{3{)2`BWbEIkPq?HwB7QbFDv?N?c@kj*L(-}ksdkHO>HwzE9EAD( zv6_c?d?a29o3w^Z{ajLSop%HAs&XTGoW-`GfbnD|w4y3T9 z=J%FOKwkIv_s4$ZgGotC!=_&C9ESi5Jd6Wq`Oka*{d7RKJo%5vaM;Vxdi#@;@vzZv zw>Pz$nO3DIQlvg%%ez=g>n%APYcnCdpsR#LC2BjYz|h1KgZ0RkBfGoCK%r`Fgc}t?I6NkL5l9yQ&&Nm*1*O4FEcttP@)Mr$0;A=IR8by` zm?odZccj;ta1I;_Lu(#Gf6=8Gc7%C&J=#~idA7>oDzPtUzzuElCo{jwK8IO+*l7Y5 zLZTIS2~Zm2(U#nB9d&@Axc?u93J{U(cM}(w-VU5`GAF~q`f2tRDvw1%mxs_1T$uE^ z_FwPy!D5l)w-azNzxvO#TS3(jHY4WAVbmq62At_28tmyJ(o6<9J^~RIoJc{@0Ny5+ zSU4b|Z6tyJYmme5fbe+e(D1}bq};8%f-$10gI>3+3dkxl+o(~giZw+V9eMcU#7z7k zsIYhy(91lKEXzgb_Y3OnYz}cY(>&QmpF0G;v zD+7BK`@i=J861TeiGf6hgRvs{3rrGDKcsND5w}&X7WA2tdfbEK4i%(=-Y`nDXrqaQ zwRSIlRcN`K9BUopwZZjnKu?J>*)aFY1@E>F7NBW$Td+HUS%wKoNwNwGcFUUoLLB5w z%Kyzp5r2m>a3QggAUQzQ0C*g^U=JrZcN@#jdT{wo#uNPbht&)Z%TrpOkd?SgbaOO> z+J=seDZDg-EC}?08ctZQ#Y}9gQRU{<{DkeY7wP&_nOJYG`q{rVNcA(oSL*?77O^Ku zr7R9x)A!f5|5{dXiT}}gKx*>E(PV=m20rJ5X*GW@4^Nc;3D+;|nL-GoB_`1!zrcop z4#7@8N2W|&ohfe0mT9h~eCl;?65~&U!ypuBMs7vJx-GB>Uj&ZGHiydp{r2*a{!8GD zSe*bA4GB4U(_j~6MTc2RTmiszZ)6}|`X52HbPR`Cc?zdm0Wr&kOxr^(r6^O$i+(|a zwiO*coh2oGl>GjsF%d#G8dNs{*Z`DEz3Mx9S~);s*HvkbWft>oo)AK|bii64kK6!F zH2$x8tQ%L6lLPq$3_TbM87_QK;=Qa^r!{MFhA4N90WIEtmj7Q0f-$4RZ1$g?;~ z;It^M!ED5Jgg|0_@yC`l7${#*VH$JDtUJhMR{M%XmmGp2v)NKakj@)78bV9+Ap_M< z+e3|LT-bCKV$P!>d{>lYjE(1n>3|gKYmx(JjT_!z|4A49KVwG^7&}}zwXx~xjp?Kw z;lHCB-0J_hA50P4XP`ckYKu|iK1Ht8(t>-Q`9^r@=|ylDf7W`Hssu`%()q`&Om?7T z{0Sw=hls>fMMP}0BqG0UMMXKpsKVMfzgi5+L~@mxXmSKQ;o;A(on}m@$*&A7JTCl} z(&eAbXdEm9JW>Lx7g|eID#bi1UX61Tm%_)j}0!%%sT2l&PiTuu9hG2uS4K);lvhyvs@txIA zA7erm-FwAKrxO+3$GDYbZs_YHtV?sD&aUC{R7k;wan*1Buvh`>M&a3UM{ozOs;$v!}b`WC1aJ zq9q`#DRhS^KdvlRhej0VXud4{nU6M&<$g>KZLK2u9Z{h^f+p)12Jud-?h_E+$02mSGQRK^GyL8lZ!E ztN(EpmUxKWMCCG1C&k0yNkirEcz)~_amNZBVnO`48g<_#b)ZVLxBAs=v!{R5c8;eB z+7_s`jUF@qbi~r@8|6=$RYL!`f%@=t7O3RB$Qyt@E_cD<$TYG#%V2jV&Km2@UWuB; z(w{DtY#MCpIimBP<=*o^ecbJ{a{Rvo<{c*&j9CIUQ%y@=fy)x;H6h zx_+q8L|~fYj&oW z;7OWtoR9m!@@O>w92SBxvjhY>+igdp-B_7@H{1Dr^mJ8fL;dm$N$}F@A2vNP)Uyv; z^L(UB^ZiRjE9xO;z6ROjS!;V%_L&L)gCa9soNyqd%1ywd1iUxsQ)W<8(ZBpj zID9|vMP5x@@OI~?@+TIBt|Y-6*5u2JIcbH_BGD_9Xq<%<2!v=oR?qV(;KbJsg-l8) zIAaKH_s&7jMt>G9tx~$`_t%KrCGEa~{)^9z;q1;^N0W+}4doL7XxEq8Q+Jev2TAn4 z%eBsIy0OO1mk&wtnF`i;su(qr7dj#uo{@6H8?2aGWr6chCzcp0-ba$2se~mz`f`Pa3{_=T!0A6!FykYUQYQ z{(4WF^R~7(LB}SfR&TU;M5k*TkgV_=oWIkecMBBcz$14i z1BnFO=T8;Klmb6>po9*WdE4$M0`^PD6O(5{cCa>oO^Q~BnH@zdYU#mBj9U9@cdww5 z>JhAG<`&!wUjIUKznMu}V=kCel#-?7=g)q~a9q$;1lwL4`2BKqm@!Sqth|(GyoOrx zabZJ>XQYO>Ih7Nl9~Z%qiWT!GFwz?1|sltv1kj4@+xLR zW=Xycas8|tPGuqFbbX7~iROngf4vVdK*YhrI0h_L^+l+hxqg^>#{?ZG7kDw7KhX&Q zaI1zRO4t;2`ZK^+5y?)dU~EJl@5|@sYloVo|ALj~G9N(i{d)L_9ulX%mJ7_%=^1L| zydS(NT1m0V^$g;q*c3Cs>h(ITrHa7YzU=4z<72-w*rIQ?Yl3v$`@!Ff!H+LQEsJSK zJ~zS~hx`6QQ`_StXu=8xr^V!srcd*9QK+~KG4tSZ`QsU3GyM*J$t{Ko$IX5j+}~ox zmG63FkMFJT?DZ-$hdnvLq3+L>?vxjy5T8%%iLi0&O&;O-{;ps+jjS^e7s2 zzbA?>w7nUA^ol)qbkki=WEyUe6~0EN>)9xMlBcj}9`}7(;ANV9 zKV4J4H3dBPsDlx}Nw|sLNeS0oUuX|0q~GxK2CHXB{LYHXl6M?U&w_xvc9lg*VtS#yQI*QSz8@0;bW@l}Y!V&j9wzUvB;t{gN_kNu)E|jSo-;aJ{hctV3?55JK68!(M;d(PS>mr2!FDT^b=y+{{`Qzsdb~tdnF7O*Kv|fA_ z!73lrkiI%y%RpOnp+X*!n&hpE;XbzPFV;myV_Ehu?AggRkRYhMz+D+MV3024A{5O- zsz#$%`4+c8^R#Dzpn)eCmVqlj=lZLK{@(?e@`?#u=ZUJpqdCr{h7#HhtxzNMdh;%J z(rk7Y2t72mnV%jcRr4Z>f3TsJ^BJnzN$gsQ77VIZQQZ1 zOT%ia9hQ!j4P&JMBrQu;nZcyac1nyz|zp^aJOGZYt{dqf@i18b6gGOXv~OD zbx^u;M!f>^7bo{GWgNbjtC~(CgP{+qn=Wm#MheAjRx%no1!Zf&ZWevvzrE zAC>v1(Pxx~28;)9`nU$xQk!H$f>4%2=-E2;@=lGna`ngOY|y4;LMgbof#a6i(x0VL z!R=DLg=t`h0x|?~aCkgDE($qruFQOd;PnfaF;z`~xqW?zXc+~Gh!hiOaN-&S@^32a z&)@s)>XMze4NF`(d=2t9>>Q2PEJvAPiE!qXispSni3Ca(f0y?l>NfG+yiY=h+;D0C z1-v2`cy}n7tX<$Zy#!;L-43j3&wAD^pWxkhl+u(k=kZ4z4Cl0*w-LjA&E@|p;UA^{ zIK0^^?KW&W$(wh?a&Vf4X!d?5A*_ieCl7IG#rG$ikJUk5zI^=3EG{=Q%5@sYmw88> zB>0qEn^tSKxlft?xZy?Md;PgRJi|0-PtH!3=9?G_ZgXnk&AO3b+3UG}M?Y#)wv{Ob zm(Uk)XRD{{!S4o<{zqT&+DN&|{b)tLf+Un5<*e@q%1W6Hv#S0@pw_ob$f>fxdfrtaqseSvy>LZg3g7}nrSI9;N_nsORtwCw zaa1Zo1v(H<9hL8X^sV^PJ-*T=m8%FC|NXg8mHteDH2IuBOYp{93QB@S`Y|6Yfk5?*m7$k$jKQ=aNli}b} zWmfvFAR*Qpj3ZKnf6WOX%jT(iJ^fTN?64D0ak2aw+HhoE)k)3;-|6cpP69)Z@v@PS zYcOM2Pu@RFyCYHt*!6F$&>JGkif7};1nLdEf?nyAf=>yq9Wqq3wB}2p#ooNY6-*Uu z?T>Qcc@9%pbkr-r&%MbyHaB+4){@semy!U)EUP37>f4+3{25q!l` zl-HS9+=Ux^sM_mjAq2wF)DW+sk)#vMSs&adc*u&t``d04XdzvO?0Nj-Khy(Y*gDU) zVOZa=yEO@uxvW%>k%c(DN23=GsMLlkYI}@Wg}kx6%ogkm`m2`Z%?`f}ee4M5WO?99 zQha{Ln9x@5^egzsY9c&|aPp#WxDR4ZzP?uyQ_|ywV=l_tC!`bDEK(qBEBdud-9i&y zYbrV=rMRcA%D!0Q{RRw&<9upbewjOv`$;BdT?Kq&m1;aDCFyrz%ah=!VCeZ68<5T- zP{JRBW(Dd@_xsyfrd$nN5AEaWevh(r73=+hoP_4TvUZ?N9kq`rTd(hKk2#%5dd{CC zp?x{Qp=q|Anh+>+1%ufTY;IZu9L*o{k}POCDi*KLbL~td+&-t^nxrrNjtuK$og)5N zOVdLyd|=F<18FJ+uMEp{6~ z_T-zMg{?cE+2irk#j$;GVET3VyJCD=`RO*A0GboF;fzMHrDQeJK{0s0g)<-iL2{PN z)t>9h!GF}*S3BtJ`FFAHb?M-9F4Do*fsN^n(cX5@#S;Kts;6hAwC{%)0rtLK8t{hU zLb3mz(ezKM1A==y`ty4J;|PxakDi3EYwnc!`}YW z5wQ#H)P%{ZZf_jA^`uFjtjH|!oXYG6ju6R;?e3s>Be2&qBq*{{Mg}li9e0RBuxMWi za*cL5RhK;$8jMxJ%$O(QnXwg>QNl06focsHG4uDCDx2UwdWZq3u$mp1fpXQdygDly z40Jj*v9C%IP|eiEQi@KEHFtSf!1(gXc+1DF7g~bVJxpGNXG0la8pxKFKX&5wm_SBH zZfn?h?3HBL@A!jo+G2kGFhcPqt`JfiHb1Xx3WbyTSPyh4g}IK{?Sh_-X>xv~js2=r zzVx%pPJbhO6~|;d^M%Ni?=m|5v?IpiE{C{2yIV=TnI#~C7PjnGi6UR9IQ)KaI z{H+BYuLNtM`Aaol3i`$B)RZ!oRd$%uCVr2FW`&$M;a3-BXoF#&r8u%Ruyd`cb45Yp zQ!F4s6Nqzk-|TGW2-Bx-$cnoKZH+MVxNj0d0O%uv`;;rK+-;f?fT7s-M^T0iwI z)*=2kLvF&+M+D_nPyDNO$snS(nO9lWXFl8GAFCIyZ-I6mpXl@bX)jyD^V=dUpQvhQ zq@*8IFvj^CY13FQGkO;a0nAVRfRv)TVr+-?XFp!jG_O_3U3XBaXhqUZ7w?L`W&kB? zTteE`Bu3W(=|88Me?XKP-xpx0_$jJ*KfnKole+vGYF8w*3jLmmb@&=P4vcg(PoYe$ zF&X5xQc$c65h6*8Xi9}y|#G`mp@hC0CU{oO%yUQsB=Xi;QeX#0WMIs92w>{c?1@b8G*{gqo|}U?Rv5NAl=N zloFA)A0kZRWEbmc-X~Y(7^k=Tqb+L3isajuzJP7LTR6@w_81W$Ok8>4R?ndp=AtX3 zVl?^n$_+30cUfY*pP3Z*YBg}?XM`;*HJWGNyGc_idVMmVSoEk0-cpOtw>#(GL=qB_ z$=b)F&h%poHrr&y=$Yn&@prh9ku-wh2Lcbtszx-l4;{*ItjLcWY}ID-pulgL0k&{9 z9Y&hNIH3h|XGc*f0&*KcK*+%L&|1{m+Ny3N&Ffnqtp~7FWFqr<5-i*ATCW*SgjFaC zxSV09G)b!|uz31a?7+U(dDt~~w%mj=RM&}g@Am7ead|Z1hbwp--5+C*H-CwvMh5e6 z7|Q=v;QNe(T6I{3*6ZP*F&wwNELU_+2UX!Lh!9P=GB3I@gaS&|&S*>#abhm|7Mfeh zkfD{A9C(1z9zrfy`WT#T0iCQ&F?xv=eO5^yOsi{C=dg8p^SGw`jw82}1Fg*9H=u+} z6&V!;luxOF$}K!D$4~hz4ycgP>$tMMY8s#>7#tJ?lPL0KNO-Yq&9iF3r9>`kQjr#z zJ|zB`R0T0$TD34(PXM}P2`N^6Klg^$j=Q?Mh7kC>|A^KJ%D?h#fsiFK(DrdbSJ$l3 z(IeoefE8{QL==g1ZPE-h;JEiz@@( z{uK&^ECe$)s>*k-wRx*m^oN$D&d~bpXA{H=HOPGN?Mo+|j~_=3LsOyuJRAr{EExSO z8VWfQLNSKGYpB_2Sr`t#_TOA`Zfh?hBC-Vaq-NPA!&m7S10n)bsdP|t8y=4%1GJie ztixRvg-pP-#qK@slYGdQy)ncbryT1s!Q#bVzlTdcftvQskEgR2{-cRh(>c&d_iT2k zGKba}1r>=G285EB<6Axq3Dwxat`nytm>6=Koj*}{U_qe26Gn=7o`0{IRlwZm;+IUH zX6LELmzTYt8FF(jidoVxo;OtT<`hZx=5wQ?k3IsqaY2=?2hJQzze492d@O^JMRhr{ zVm{as{Qd zAX(9o3zESgkZ;A)LSoyDVg$CDRTgW)Q9}}!2aD=xNC78bybys$(bd8!gm_y&-;%YMOPJwT@c92Mm3#cKO6S2ld^-0wrAObkPsc#=D-r~xwPmtnFnN}^-*T9k6> zQj(G{>TzZj7P15Y4JnTy$Rg)_uw=m3f41ursz_vhb*It#9E+sLC>Z)FL?y=|w?kxg z`)~EnW2dt6$uh>#)ey-Ck&^y1+Eo!cjn*N6C*w z=_b~=8O0KfZbIK{OC;Y?rD5ra0$Yh54i80-!HIL3D^@v_f~(i4s0lqkJ~n)R9d16` zE8NR{kQporP85Nuza@)D|36~Xl^z^#tVoi-Uo)!*4jaOR5PFXLw|QP0NUi zg7;5`jKbl>C-I_32oIMlrW#G*n>I?_;Z!vh8-RGkucI|JaRzNXa(wO z_R9eP`P0Pt`@L&3T10G^NHoqQwry|Lmi3G3ed2<3Pr_1`1#R)Z$ZAZO;G+511$%Oh z9ovOXeXCU8*oKs;#4!@{>r)~DiHLItMT#g%?u9{V(0+!@sVr>b&b%}h($Pq$35;V# z_+2{peF9+@oHBUX7K$bOys|x}QdJg?cp$d&L}*TXJoNs|(#Dn?=Cwi#(%636i=aQ0 zow>l1O#AGYzCs8Dt;lym*qcE^8caA)Q**=j73KDhjyegEQCs#JnxbX(nlt6C86i<0 z@DsVvvDjkd0`p|fvxb!++ss0;fp6r%`e4-pFGa8hiO5nMK4G-jK$^fC>7ty3QDlPQ z1Z#c~7mQ}O6}>5r2gD<}n23kqOEehnWD2}I2wD}9LLSfDx|&Hst;r+CT*E82#1tW? zvc4OT=^;(sY6twu(?vemC8IehNK>fW9W;@1;|^ejvgZGmH&wp!Z+U06j1(DCEM|XQ zSTfqjG9HYlEvm`W&de9aFgoA=0%*%@CD!SWG{$bzx-=rOLHF8D?|%=IaNfDii!q(; z#~2SA_K5vqaY73-unbL?3mW>n@uG3dhif`EqesqFy4}&PXNxSZt8#rz%OSMrBHt_D zMMofmy6A}AxM9hm6_7P}Qd2BMQ-ekd2zQ}Fb*TXpq6e9qNZ6zmv)YttSz@Xy4r>_E zH*$kKHlvBIgsWaDWF!8=9afU|rnrtJssUY0xa5pRw;C2S=*s46DAk(TtEmhdwxsU< zE!WMl6E#0E7D43PYHT60;{~Gf)Os{E_3ilhINnehhPYX25-Ra*spgj}UWr1kR(Ukr zkZNd2TFO=}Vr5Zc!^0f{+W54RAF;`EyIe`^39EVi@j=LU&6ddg(XvdT6Z2@kpv2{F_}nP^&Y1@R5XxHrB+_2_`@r5;#_4^a*; zKH}8~E&Y7xOBs0^FJijIGg<(&H| zpYSLuVWxs@;Ehrj zz7w_Cy=j|Yu6?ePUe?4HQMXULN1zbDSW!-2-@3J^Hd_yl==^&l%Z?_6dGq{BKM?s- z(VSKHkAnm6=UrK{Wb^`H>TY{SyQTG4fo0j1v*;|Qguy6%qx~}Gpe}Uc2O3lnxY?fA zSVT+)ZzYk@?7U8N{5I4fZS+~X;Xp#jIB`KT4Y-quXOJt#pS|sG!nKzdGWQS(2iahd zE*ReG-$!OM9${nhJ8icuW11-7=u!&4!R@{H{~6^~<*FW13bHZQGKk*B7H>;cLskY?gE)A(JrjXUc90}PPOo*7xWuXSn`l%sJRl?VJ#c?vRg5p?1hxc~FxvwxP+kxt z-fThG)UR55d?&38{|z!>Vd)+r?L}QV^yVkrEF-WYiMUm-TTh=hHQ2lbyhEsiyg9Y88(fuY16UA#OLxLOtNEk(sGBu6{F?#mkYJA25pRBj0O{QeyB`_bpi_dPE} zfoDyM;+K~b+tHqP_e(EFKFS^oOjpr+=+|$HN7$9$M-$0kr;+?dj;46ytmgk_Oj8>b zA%iQ3ND%`=Sg2rGZf$g|7zh7Ok!%cp%2V!I&WKwDeYKg@77s&I+c9yqS)A&e9*g1T zaTcKZrfn2c%zxBqZGu>wSI!Voh*480O<8CV3xF9gG^B>;b(CgbM~T>!kgdSzge{pC zjRuG8HZ|8GnwUC?#gE-@{uacvjJ>Ia@{GM zFsRGy`{bRmXm2*!sQ5?OrWMUy*>r%FCp4i)4u07?KPzgHkf2=n%QDzH53;PN7V=-#=A#iR=IXkm*u6vM1rO~aNPkRCG zY}C9F1Uer^k;KzlnaLFVV8&$7Wg_D|4lctu_}0*=Mb|uqgdl85^-L^mcuWJ~vhSna z5&2})8CD-MB}vPMItFMY8?kl)G#HUp?;*3e>I$AnFvxfEcC#Sk>4zM34ns{8s` ztlFQnf8Aqzp*MKGv88($Pb0I+jddA+L=c8PxksoMuD>En%Z!fw^O zt@y+{LvZuv%Vl;?ID&ZZIE(M$&d-MxMW^#R&bF6|@#iDvwA&yn1YV!RKL08!&~(9C z_aKIi;DoC)W&Gx%%-meBFMX374S7pZmPL;{@mA*6?Uxu8&dBnY>Aj-I+%e`P)*uzV zTD((<7>m9qbC!+*9-c?^kLL*574NqR-`6vQ+z>K5%auXtj|ADn;84>h*v z{Zeb;@0+uWOK{#AZ%fM==A}qBIHnIN_B-@r_+WnQsw3#JBi!^_Oly7Who0j~Ht_z7 zmn4_PlVb04o2Ank17t#KEmYt|sLJ7bV!)!}9+Z<`5#fBpnNu%C{>6+_opFWii<(vH zZ_VHJ+K7iMnspCu5V9dTTrj0uGY^N*GlFG#PPQ#Wjx1|^nrr_D3os{*B}pp>MBlCj zD+zYG+&Gz*p=Qs2qZ#4?l!{Oh$+rwKOdY6GMMO-19I4G%N^dOcP#KeV^gz}H)NY!U z>AnR{9b5+Zt+O2WP8B`+mAQtk`0BraB@9q*3@BnRac9@tI;-U94(-ECr*@q=?Erbd zZarN`llj)9U`z}4*4n=_=4d*>F6nx3X>okqUpnrNX?)ssXjl(z;mNDwBVfmqTAlK{ z>Hm0wy=4t^T3xYV=^7<&d0^Mq=ZtRGe#647*|XnzWAuF=!;XF429oT0f_C*r4<)RA zH)$FcWSg57FDwy}(aDBTZyjj1o}e#NyqPHIC)zE+&ySmvR}7imK@?dIk9qlV6+g9p-O(o6z`0u-A?H>h58|J)~W{TS-aJ}`>BKzAXf^giJAw#;pnuB|Z<@$qXx z)O>%DZ96U<=XydjI9fl+=5u;$dVPcpO=!^{2ylg4yN6%W_rQ5H+v*QV!C-Ex{# zWY`5xXE{#33@u&?FR7pZ8733??f)(!CB#t`ygW#jye~%EYe}h$a8w|bEf9wxSwIeSc10>TtKi85Rsu|v*m<-tK`Vit~Vz;j`t z*z~OC7b83&3f-6^>%N&hP^3n^@o1pX<#}XLMfHvEeMLMchYpLI;b^4g({L|q_S3-Y>U4QlGr{|O;x0|;UEAAfw zo7^Y%rH`BG*R2Y^3Okap?#CqWLmy`vH4cuR+}5Syb3?IG{Gz2TZsMEw38$Ibj?4zW-{HH zdDZ0yUyY>S@3(bFR(Xs0lcI$1MR@9Me=R*(*^t-s{o$16+77uO!w zpFO4P*?CIv_Gor(e)^zvi!bNzf%|Q?{l@4mZlq9R0=@lSmGkuO$Sl9gC(bwRp}kOB zKEKD9b*HN&x{HRQA-rCo`-Moz1H$3doet8_orp^%{Iyi`1pk7RzvGH3V<&8m$7(Sh zYtck7qJxP2tKHdeo1IdJhte(F9)&bb@A;#)y9iJ3qg6$w$&J50pPy`U zwwE|JrVMiQgj*o934RTvqCKr+ZA~YiGWJ^;=Dt0|Z8lebF9V-|Fu&>%Bpt)}u|sp& zeJtY3`hKSSQT!(Tc6&;9+$V*PP~=Em}L2>(}U_q%5-{?4{MSEMKDM{hq;&*-rEMDLk* z>KQ}#Pm5B&oJt0s$P)Z20r(EiM3w$@jvof*@~dOSN=7I>ZTI4+_HT$E@8yM-st(Kh z3i?mSldtEqicXUe{ma)Q)2;UXrc>|l;y*c7f=rI$wQj%|x(*aDd(LjpJF;jGp$86Q ze>ETM1taT_5f>ph2?IGg8pN!0A5gHt7A%OJ(q$7>rv5fNk>WuX6`6&vrLQ%sP=lP8 zTtKR^d(W;HJyK#h;Zc;tkW&cM(s)q15b~Nx@S&3^HVGZ@0+dtU zz$IyuBQHs-*^8N~RKKNu4kE-pO^j!RO!gM-Tj0`8P{8KXnBQC&RH;ulT@l{ z{HMZ%DhEgWAk%~^rLHz$Ylo@i%AQ|Q(^@Iqyw$=!8V%hnMhr^%b(OMK29I`>J=G?O zWbywH_Eu4GHDUK>5`t^6K=9!1uEE_x;}YE6-5nZtXo7p=?(PuW-QC@$-|w6M%vy6Z zcYV`qol|GkQ@i%Fe^u(aL)Q|vJ4KD!zur0ocQZAlUK`XNI~Qc|J?_cz1t-Wmy#yLJ zoDfr({fTs(;6$hsP65aocdkz|#e2yW=a=3%74IW5sC*-Mweo+mJ1SrU0jm#ZADhYZ zy<8`erp&C(5fV1dpc4j19M5sewB})$`ht^YyvJog4C`}y_O@kc^v{p&wb$EwTSvK> zdatv`Z(LiNgiY79uTE2B@~@ZQ-A5n4uAMkW;cW@y`3~3om`%|`or121LJDC@@sP& z`?JhRMTU~`iViDOjB?5%ikH>5$YhPzZ#FmO>X+zc>GC^0j;6nf8m^~5)_ZI#n*#=h zQyiDwQvRM{fjry$aYW?3_BYl3)yHV( zU>whrE0ld>D4WnTa6A0vdLS>7iBw^~s@i^}wC2?H)yZwwTz3(t=3?JlHlR-I2Xi94(pzun(BUiikX_O(KFU9JCt*$ruwDj8oqB8G2s!Dy8ye$cd#CSSQ4@6)(?a4~GkoEaZy@ z^IU0bMTSF3OK2&F7X!+HTK(AGfq7UEBivp);NNCwh{{h3*b~^0mc-CJDB(Q&`a(>c zI#n_qh$R3UsjE5I6#k;9w_!VqMAC<{xDq(jF(PO<5)=74_D%Q{!g$8k&EN8(@p};c z)mBnlIm(D`+?PGX_!^;nz_adl&iML@YN_;FA(tGnAx|6EtZM#K`hFm={3}f@1ux&n zrf;>~mPbIE;Z9|%e+evM-)BSoRNjm&TF^f2hg%RQ0&KOO1yjfLSyAbPMG)vIe##iT zATu3>EGy1-rw4I;w^gtO6e)Pes|n=y$58Nqm5?3Z{?y;^detf>m+A0yz~vqRTgPX;5r-4HW_!d-91Jm+PjAW?hssfQQ8W+{Y)!; zb8}tfqEG-usomw2T-k0FUtRICQYw3Fe*^oxBRdo+;DLyr0rzQio+w^$!-)JjhKdKJ9+QKUU|aoY_=tT@w$c0^xihZ|Fbd7 zP|0^A_b%XzeBu4!25h~h0G{~Piv$G4zg59tggpKNHY7#5y}EK zY2j#m!xW?J!-Y4-S#Ia|22ZwYw9BX7M|M|-UQ(zRMe=l0$F5cG{Ip&b&{iDneD%i) z@Zho<1-}ZlfRb=;*;KFaENa-O@tJ3VHx6kzd1{1-0*RI=B++a|-LEhWpU)M0hcA^Q z@0nCPodPK^*mn9y*I`KD)2qVy;!)+)V~CXt7AMFPMiBakX=g?)V~1aY>8v%2Eytm{ z7_ajfj;?b}P=>J;cFRJ8G6JHNww|BDbUA`Ebw;KvE+q{@R5pVI3wNnx6)EZDnWz*&4qw$*e z1cl3{GQ|ObF5LG=d9SSEr4YZ#GXvsGRWRGP#()I>`BIrzl$^O#pfw^4-#l^(bnhg| zBt-G=Ix)PBNkvT+PRsXcVnEyJ^CF(N2kY@);@g&=k;xY3d>Vg3_h(L(_AzG?|IE-^ z6y^7^CKPJR#H&SKt3{Q#TnFsYjGUjkn_o@`k-!t?#XPgA;k)q2ygxDdew;wPZf^LD zR|2_XD!uQ`W-TkHhI!6gc1c&~PIfTMR-ibZOw~2Vd$6ztKfEUdc3#>m@#@oo#C>|N zEY`ByVYpgp?F||cyZNq{!52iM61qMCq3`c%=gr$PuNK#>O^38ZJM?Me-kFmvMLvV$ zt^$1ldw7QwV#|$8^^#RHdrVpyzi0LZCX}_WP<`BQboe^V$Sa^jTa4ge2k61n>W~EG zbJhF)UH{n;v}BcA;M=^ zmH5IfYV~Px0VHNE@2nF7$z^2}q8QnqKG46T+xBiAaYuY(am`;Qn3+d3CqiQdPf zdU*pfo{A$%Ke~uu(*hay8ax@HfB!k_>AZ<7V>l?i;l;f#8|AWb%NDZ6(~Lb22l&q~ z6Yx+MUtFc5dE!BwQk)jZhN?}Gk}6Rcp&(Y9S%@~cX7eviQgqphL%GfPjzxb6_-9Tv z+dR417#R&9&c@xus9AV=z~8W^-&w`jw$GVuSmlC7s=%q>$8XF2!vQvFF`|o57zxXO ze@xD@P=@I&kPUVORom&vi>wux^r+$bd09THnr!te7^B|ax$Y+$_T-e6dM$nhMSMva zUcQ7@SWb!dUCKB|jn@;){-m!}Rf@_C#5x<9Bp~Tq|7-HF5>2lrx%~L24qsMygT50q z%GnN96*awcKYbXM;d1l{5pD4=j3YI>95H=M8%gt3BF3${f}lnF)}yH}IUj=sj)Utm%{Rc!Xq`U=G6NF1 zHo83RMYG(}&3A{#GXyF?d|YkJ-tE$$-Sx2VHr|H^>%#l%A0IE>k8q=^ZQTyXJ=wu2oT?BK$h z@M)sKxm)kEm73C*I&2J0yVW&K-@?qV3?YAO%!2QoRHjhv)f)>Ingt#Xj4#z?)-RfM z?*D!a0v0->DG8fmJl`+*89E$ch+0lJ+&>b@{#@P&kg<@t^nVBcj!M5_nD`h`Cj6Ks zSiMmO?f{Ry#oJc6fZ{D0wbeo71nqTS3ChodTBzm7GBHWhe_u}1EQ{dmd{RfiTZkha zU9=h}bg+*58ZT_c`=6ojC`r|fi`{}CkOfU77)FDd6!As00xO5PTs^zjk-b7kETTi- z$S}fbnmoyFxDODAj9baVI_>=5h96IjKbaQa6CkB}_T&a0nE6rg>l<`f4!fW5ptT0X zSA;YtAa25PtM@B$KIRWTiJ5twpGVxY1==l$zwo8SE$#792bG%anVLQNmBpho$dVw> z6ezb+!+^7kg-p+)r3_cySiH2x{2Lt024lI+RKv#_v5u#+_o*yd?8JEpn9);5y?5Db zP{vs?YHbmSW*JfLek2#LC2{kffMRU%g$f%dEeHUJk#X99!Gn#TzYR*P&)m9el+yq~ z{gAN!WL8k^F~}hT8`B&1hHA{GP_sWSe~gkY%zxuvz&~0-ADuBdID+@GZe|h_JgBP$ zB=p9_Xp^&D<}yaOl32JyFPwcsQEbHyuFZb?UohU+)Kd}^)(KJN+z8 z4lq6u!WC<&)THnHrM_DK%R!W0oUv?mBYX>!Zy<_yul zQ%W+07*f~x2tJZ%nvjkI#1)5$a2kPz2Ii@gpJ@dz{!ByVwks_o*V4RC82k-aEm688 zRD)lhCOtaO^*0El$l}x5DO58*F^1afHcmmdx;g;TQV6uvxc(>TW9ml{vnFZ!Icv^a_bA+NQrFT3!#X1S`rOI_?LkN!a?{G&l!zg|CKvtb}H zd42rjwIhl8WzxXF5hh8iHvsm06HtTC>56&BD!-Lzj_SCA+A$onklnNOVw7XaK8pC_ zFnxs~^>-MlGSGSQ^0L;}cs6H;`xoN#ioKo6KyBaj$PU-L`LBwL< zh0FPwbk*aou~_iN2qjBJVzGmebq5Cpk0bafn#A{I-1f266)t+sa!A3QRwDYMifT8QU3fh)95Em5jPLgNwUDD{IX(>Go~to zkul+MI*Sr{ac44gC6-wxZzKh*)j_Sc>(w3~@7s;G^OO?XndF>NRY<6hJ>$vXq{*~h zO3(54$BhhIL+7_E?SJu~5!&4PVYwdsp_-q;wwK9cvI38B*ym5(jZLS?j1JGYD1^_$ z(R9{6sNV_L@uPE}78M+(6*~K(^*WOW9D#*4Q(4+?is5gamp&$BjV-z9WLWXSx0Njf zX=7sO29xADMz-RV%s$_<+=(K^xRuCrlo1T|_XhB-b;uQ&YM8|+wx(n6FSX@bN`+aH z>?A2YAX_(y-ziSjfFg!gAjQ_5ihKyb^NXgEd26D4(__wOEa-&!03y*Ba!qPQr3b14 zOrSDO*VGhY5Ij9lc~eM-riExw$qDO=w2vgk5lb$K)XTts?e(e9uW_yN3RK(@|D$v> zAxbw7L5fB{KYabjHQA`Lk@lmEevZJHvsEI+X6tqab$5B=Jwi{w74E}l%=Bq>B-?)Q zqI1%?5z0(?$^LXBQy8$JFt?J_xzuxj`*lx`u9P%OI@XH5Vb!N@^5%!&8M`)#IebYG z^9R+##;XJe=4ZZi3ZgD*y+3(bvjWRW{{bi)WQmTdGL{;ZC{^m^#{c-wQ~xWWkDrp6B$7l%7iezx39#|8;BYBv;eZn%pDY$Vq0sPx+IX`43QnKxQ@8G6Qy zfbX{eZHME3SyC&Uv0jEp$~GNO2N|p97}<|pFS4N3lbxW&nOh=ZXS;6h>0c3t_r&bw^I4P<;Mtc2+8J)^*Gu) zLCzbZLBUS|1*$4}s#6i6SOheUhAZ1Y9*X7|;;8dUZ1F@8M+wB_VdUGUPeLJk`RLS;*J~PUgXoe8^PmD>HWPe3B`_2)stCs&jpQojsQDsg#O@=ZdOp z6rtztuk|O!BE_Kt*TM8pO&>A7n|ksBNy;UdYsM!w(qWu=Ls-lHhLex zZh{yMq)R7ewtL}&M0*vsf^k+2_Al6Gsy8pSf9`U*g^}U;udRKs;CMS zs=Q-~3M?P9+;e5@h+nhrv~0=oL}#o?UqsNveIeP!98Bd)kru?yPX>NOKOp^2jSZ#0 zIqq#L(h=>-cUQ4r4O{hY7fts}W6^Rc_+I}7^4?vsd-nKTAV?w3`_@k_F?W=PNrL*637TE`+L0Gx;FN;mW*N z#$2Cx&a=Fp4KkUB1;u?@&wsca&LiC9UHAaGYQKLoDSUZ(vL0^tqFfL>c34&07=B!H zn>FD5eslXgmFYC~?rDspVN%hZx?T}MDWBPeYwG2vW!oMd<8wHkHK(fUWqQ=0vvG0L^ekaE5-N? z|GkmMO|}I^iV;MPtG9nh)m2Ud%5N!&KM*CL$FHF6HdK(Hr_$dB%T9U87+Mz?mjUei z$xB%RYhEe0%;~TvqeD=F+_Rq(C8(Lo)$d^-9ik=YmLV!Ol=1Fb1PR zNed6>P@j4Q9=t!}fpq8nQMr&YQeVJ`&4+=tlF0Yl4WSmBn+m#Juot?Kt-;xA^LT^b zh@QU`jaO`VVeK*e{SmWY(+cc5T;^9KFNG7JxDztvpUIqTrSr2iz=`e79!JAw0pY5AC{b$((QfB> z&|y?nrrEeG5JS(T)I=bCeb2ngx9VIa2ZSnnATNP2w98%iqp;3++z_v1kTn zWlK673o`%a=f!!lz!rB{$Y&8Sg?Nd|>V`^JzGwtN^UJHbF}~XgTJ7VLwjJi2LBS`}hPhq98!w8&btM5g}p(G_IzA{H4sVI(4uksTy>k?(Mt;;rjP~vH$`C-jo8N^SnOFkuJ23HV>*9h-9Df2bWHrpM+5s?(!2l zip?SUI1-m2D;TI@ap_+u3(RifwFV-7^&R81q<4u}3s(zx9tqUr-=ACIrXu3SaJTE`xRp zzK~{>E~chtmm_-)wE;cm7m+`7&eW)4D#6VTZ#->AnwpIf{PADoL;}Ykp(`X~c05V> z%r;a;Mlb(f6hU-BIFFyDTy4|RfzW4%O~?`#E#aC7$f<{9@9t~taF9r@g|3m# zbg!f5Jrp`vq-X8ct=o|uUhUyHevY+=vNZJ+9y{-w;9iCW#&|@OfOt-QL<_5!sZ?Gb zsKN|!MD$D>;Do|=6eNT8B!IyTC*`43e{g9Pe;<7UNmY9$UPlSX5<3(ZgOjby zmlQypBz>_;kgL$gaBCk2Nl~vK^H5n^jZx%!GazNtO2IiR(?yW%&ih>@o5E|#O;P4# z0J*Jh6S{}V=s8NG)jdi0ROdM)9_nZewZm5ELLtn0uZ01F@~oE@QI9NPn8{%l2Y#?2 zp*}ezc63&_W?DbTUdn0CI@p1T0XoS4;>TCDsC1r8{e z7^v*w#!2gAaZ$W$@y;Qq!9{n6qyCNx?ot;vCV|VFke80TWlQ_l-`8z9;&?Rn{qXoW zUQrpze90==s-gP&2ZjIqzgZ0Fi8u=>$has%A}Kp9_@1jPZg)v3X&;YyyN=D>y77zA ziOTt`xR6lsM3lyhjj}#<5RTiP;&sajnBd=w_w80E^5GkNb%pk%;qKuS*>5TAj>j)L zSurU0@ga%!7!=pXxhaiL_tMnb3k41Y~^aLqcC`1Zzp{0hk? zerv7KI3sr(qvjve>RKi7bZW8|1zq7hM(T(#h&&*fBPuV!V~FcFuvqME$)+&ko27-4wj2-JkBh=*huK|CJ~QY+JLA&o)MrN= z!0925Wl}zMc?*t(P;`tziv{=diqkTMN5>90>zkX+=}!0z6l=vlShAut8#EC?WyO(| zjaSyC2NFGnN%07ZJn2Lw^%1?j*Ut8~fUY@yN78C+L2zG?nG2a;O$57+7|)Hs8gw=! zM_bjkxP?0n9|~-ntZ~+90_N^&Wj@~gSb)4J98!*de%TcUN=bZg2r}NE-C}{wr`6-RnQ3 zm;VaUC`s^a#oFb$RFnioPM5L>PESS1=9->RZyoFE8#x1v*e9o&0M=Ud$~Y^(nM;y@ z2g1p;6!Zf$+DJLoW>{+!OfV9(6w&2*Bxn8+Jp*3Ue-#my7B%t@GpPJ#u?6eQFe=0b zyNzhRdDE};`{f^OHly5`$7s89rnR)_++89t6O)Clw*JQ~Z+Tcp)WN$u(MSNGZ3 zruasQ*=CD$SV~|5y8g)WaZalXW86Qtf%B$Dwwr$lvf&u!C0BqUJVv}!GiJd{NbxTW z3Rxpa>&MBdZnSz@7YyM;AhGZNGQ6{x|L;>5*}}m)gmj|i-k(9__Z?zBUalfD#$@O$ zO=-Ya$tL-NYvwJnq_{pn0_bFu8!}PrRmn2tdLebL33%+vP(S|{;6#K#!%9J)d^kgs zcnr@QuGI*mkLmEEKoQu_j*!Ge-)}Y zgW`eoaks~i*j^6vY!RO_JOMz8LOWhp#Xa>JKOT@23qMJ|bzJrLZwY<0XU(mAN~=vsKa4B+G5(V9_BxFQ)>?Vk6nR@{(qkH7oa@{ z=D*1n(!tN2NQdQMwA~!1DY2yu=r%0Cq7|*sEZYEsqnxrj^z-|j@wJOwht$AsPEMH0 znpz+tjkN~$mWn(TOg&9SX^cNre&YJkVwP1TN&~pQQO9@9xi7cc&`pX6RL>-TAo0hb z6U9prKD8a5^g9Uip?{r7;Eof#sLw*Ad|G^LA!WWp6NH2GA9#?};dMnG*#4D-=09fO zzaRHF9eQ7gFTDeZyEJQ)V$i&)3+(W}FWk^rFY_@n50#UZIr)W0@;7-6vHrtpqS?{!;5TW^hCxFP@aB zM4q4h@Hw|~)S2qASeXTZA$XCWEDRH>0AE(5YIUDJ~8WID(ykqSxP(-#Vp*9oLVTvgd`Rpn?HLQ1t01; zonqG4rw}V6Vg5IFkwX4!+typDcVZ9Psm4|(oS|KKv=1h?~dI6^9-B?Hv)gQKbaRT+7QGPXybSg7C*c1k|4Q(HMVGwWY5$D$atXGaQBkX^6wmdpN&hH>;efiEHicGtEgD#E0>=)2=FwVL0=RWgo z$#kR+!k>*(O`0rYA324XL(n9*snK%1#*lC0c`jQcqVx$6-Av-Kk{~>6KoaVl$22vC zVAy33D9BYRX`-1@M-K=6n-De*F>>}--EO6gueG390Z62cdXH4bhfAsKks&=j1od7yqzxhmYuu)2 zAtK47D&?mODWpe-W-xl6s5tGsT{_5BN86}D9~!r}6shT7=D9EG0R*ea3E%oSN6r^J zpA>#BP%TCOSt^i|uZ&>qd5;}+X1=goyY?3@Df$6u<>foIu_ve+$im;A(bME@$xZA` zAeVy~jV|qu0)cYTG_|SYF`-2FMItm6*9M&b@8#_w7tKHjf==PWd>$4>-(b|=fwUlg zM_=RnN&8@ZRC@ilxudf!?Gg_Xx z03?$OX3~mvEPeTx`U%A#VmN3~z*Cs2B&kOjUr5}Mtn5KQQ=nZ{#88SHKl4#^7foh4 z(r1Sqn@!2@$ZXD%OM!d$RHlEeCik+|RZ>Hjh$o#~BaL2T9T2g?Mh$J&<(G#kzVv8F za%3iKec9{wHZQtWnm3%Xov=?25!L^MTwT9AJKym>6-TrueT~b-P7;BjcHGMJ5RtFQ zp5d;JN5CcC{_1?|!fmCZ(yoU>?b#zqil@h3R3uchT2_DTu*NDiZBV5Ourb&%0rS@2 z^5ie_Rle>^tX{LQb?m^&6BG+gW18#L#z&uX-Q%W}$CZ?YG!)tHP&U#B+7oS`QC^r4 zWFAj8xLu4&HhE>I4KkWClPnkW1prVqNZ|1(D1BK(O? z_<*zvvs@EZF3oT04#q}orb@H~jkW+T`!F>Ss>Yj4>aD;r>s!8}W0{85O^PfvjUof(x_P7uh%!Dxt;`PmF>CF-KApkT4 zJmLBQPuhZ{Qm``8Z~wV8~gA7r#iu?-tsI9kcmKG zrXX=ZK? zgqVo7Qrv=7_%+UeiYhdA?sE%-=Pph^lfowGQw@RnW9_w^bzG8JXa8(=*o4-Blmuk279lln+L7WHfIL;AylONp&`2 zi0E--6ciW>YHHpaLW&oiUPsi^4Ur)vF;?SF0pSP#{tv~imtSCvvSj5_l~Ow%Ro$ei z*26`4?x6yXj{?Wg;L8CJ%N!)ibZ-dDe5Tmuw-1YZYCI7CIO-cc3FM*u?!S2G5c~uH zSeX0k-${w1%CP2=h)vIxTaVuC=GN1>)g}?wC4seaj&S*ZgEv)Z1SXWG-oC%B-Dd>i z^o$IuNZ{L(`Qa;slN7yre(L&<>Vl_)6nM`$EB)9CS>lVMM+I#;HJdX1vI#d@qKai* zqS`W?7TqV-2fme#BS5$}*Vb+?E_ZQE`DBYJ(eBoHbKAp5t?T-g65t8X$0lveC|*{Q z^eegtvgCI(YRf@}h?bW78cPw(m&tPjy;B_}wFR)HUTZF#GG-!r$uvBg@bj$a#nYSp zg)9ZhXO(!_O+F%K*2eKP-m}#k(8Jq)VGiYXPEXvuowe|@s zE!FdeOxx=eYB?RN;tUVVZP*O=MPIiO_XYE}<)JZ7z3nVpAAON}=<^1oOgs7o!W|$% z;bSx{_ZhOEw*2b?ROWm&_+fPMQIOEfMPSaaY(?pHCzBL+l^a8?IMKP2!NjrkbG|s9 zIiUJBA?0aOqE=n?hq%GhK~P zm0g~E*r?MU*lD5v-tVry*lrJf;S}$ONq#f=*IWT}Kl z|KwrPev3Aen$K5phiouOk39c9#&)2)vpXWiDW5v`> z0ISF<#u1A?*O|t(Qtp1PIJ%G~HCGianuil0cDeM5oTv&TB|j}S4Y;mpa~hKFW}>G% zV5XP*#cZuc#$}E1C$(YGA~hL9q1AMv$mqgoP+c{Rfy8`GbnQ*4$ky^{JYJG4T*Lq| z{!gURVox3x#!t(}+T5((;)I&!WmqAeH*wU$in0dSQZvHo`eav_u%=G>wPZJo!49$0 z`r3;K^>$b#Q!Vla0VO4V0aGTPt`Ksu@)OA2MYpmoNJCN9hBhzBur_W1PoKMHLO2qC z*WA*AnvLzpBR|iZ4S`T;% z>ETyi%ot`B;pf&d*`k&Wo2Q2)=ep;Toz&iF3z;khK7!akJ^N@oooPf3+llwAogH$w z5%BM<+>XetzUo)sxFO_vK;3Nk#_Dlu4+N^kkjVVDGf%>_<-9C3{Tn(`Or_K9%D9gF z6l1UPp@W=DOIF}@+fq$||<3)%XDg1|5|!T zAZnBmR}7n^R7REgC9l!_b~!k4RWLZ=S~FMQrUm4L@xVDK5>A8N_C~FxO_=%sqi6eL z44we}jvzBtoxLpWYM%}C{?J&?ne(pZYWEZ=+pz@*fYs|cQ`=R39X8~1UYjFpzeGB4 z*|=&|P?V6kC*TE*2qTIJ2+H+NM!I&Z!0I$Q`#Mpz<~+Fxo&@y zDbW^il-@xXG}fgvdAUeRcFtI3q(CAj2@y`_8rx!0lCNBRVh_Y{ygZFg^;FJ*5QMmo9CTMUxr4!GRPQMr z2Z$flv9}yhMzs<94e$r&(jt|B9f=aVD(P)_G-KTVEGkeYZc46QA+3* zMZ&Ioszd4k1c11;^+WtXv1NHa&dtj)oKv07LYxb%a z_hjXBFsf-1({pMf0njpOe19({!k-S<=1p^OFE!A4NlhX56hg1(-B*)Png4RV;BGC2 zGqnBh1`|Dd9dSRLkiH72E1A z=5h4^b#g!2Cp%&?fEEgW-ehbbjTh$0}k{;C7rpk*o|Kw`^MX< z>eBmfBExSl+9Fv?9om9WcImBgr;h&$JxWy z%d9dg!ct3f_%-tLzuc0jLE#Mj`>c_u{rWZAyB=sbS^Qyaqs;O~a_*+jkOB3j4yh%E zJ2-NZKNUy_UGCuHwe?FERGYqi{r3!J;%Jn_w>6Aae1H4P&l7>&oI$|?GjI4gn7@Tn z=8sp}c3aiA@&G?3TD{aEWJi=uki$Sk4mMvP!jo6MUgU`%Q$3J_!u9%7cFw${d(P~J2_h3yvD;x zq=N&00M!cHhtxjaU0}x+M`?C*^u@MX zB%})6Vq4ZK><;6}=Vim{yZEjy<7U3lrkp*t_YH&fU`2}sz3X(@j$L1fsR7_`KSnBHFs=1!-P6g zWdvHXH!d0$2y1XBZ3rqu`p4U3N2sazd)Ie8uW?S+l&ZUhqqgT0rw&|KR@bb#WUS6) zs6Uwe;{`?hI;Ib2CnHRYS3fD*j=s+$_$doC-{A{{>)|ernfQjy29I7sVdD4OL$RKr z)+Jj>2)=`O!mDTS^tz#hJKKj7c}>3kMf@&c&uJLp+pv;%6X_f7QA91KrM+ff*4PWD8~ z<19XJr{wGIhXT{QYop-=PEps!uQfbl?*}@)i}yU;(U2v*|HF>+iO;8hbD3(Fs?}b$ z%m5|kZ9~PR0DowMK`;_*4%5#H+G)n^tXcc}?H5bm@uYx>&ia%#a~09^)!O5&;6?T3 zt+06EAZISC>ADX!RGVM2Fc?-iT5aj8@&CyJ&~Y|S?rvoenz~;kG~Xt_KaTk9j+^TK ziAWpGOMprEL7ii^<#C%w;jr@$sXRX0?PlpAts$RR;`K}zXmgS41i1tGWgn_-_JEn; zEF&r`v1&Kv?odK|%vppb#{#)_!!xVs-4@xuq|sj1vtrAo#qx14yriw&;ghMJE4;TC zOhNw~W`6&h+51uUw`i9^!JZe&VyZ1HzALNtxh>=|T7=Cr!4U9N`1SA_&dg-5r;Lx$ zZ#NwN<2H_8^JCh;BuD(-Yy1+8tEq>-=S(}4*w&m!Ht#(F%E5%NchUVPE!QEebe=!5 z$23JC)7>NB8gvjtK~HvBc`qPWC!p~vge&GCrZo4j zrG+)Jq-hqpXjXc%Xv$!;Lh-~-T5=a=162tPLUL7#hM)QJSp-giACvh2vA0wJI^&Qe ziE>TlH!N~3t=lGu#=%8bjjb~+n9b>a-bGq~G zdra$&IH3dY^B*yCtJKly2oc<*tCw~7t4bh%Ba)KvB><2tejp;hGqkSD;r-5cQOWdU zt@GC`CJ(Y82r-msve`J&?FLNU*4mJnX6rLL{6ZvhYQc8i`sFJ-qTXiCLkb#kic%4% zt1F77!}m$f2Z$koC&0Lk+Ad%5nOb^)gpO{8%;1rFqb`%^{pCw%s(BQyh7kJ7iFNtr z5mO=*FPEz)HX4XE5cWH`TQJAZ$<$tXr2~nuj%Zlu!zMuN!!4c&JIUTF6yFq)NCyVR zdjZag%;DvKf1WwwFJ~W_Sr=dLPR2^l2i#qC2I87s3ullgQ+aNWNI>bm>6c5d`s=B@O%Hzt^C{R@{bspcp6Rr7ugchcdOKvd7X z%4h!NtsUWC*6H<=_WSeqayTT4^s3A$Lt?1sf}DR)7uUF}e4V_$+`FGzC_nS-&}G_F z%J?iv=i3&k7m?LID25=(is*k5fvKZ(dU|WSId?#5uT$tf!!%B`MHLoTfO)tO^Zf2~ z^3B?k!?$@0`hEKGXvrJ1{z@}X9IGE|bM&U)8SLbB=EY=+fdw-=)mA~g(g>X+=Q(Z2 z=odiA3d7AI=H_meV%1i)1>wQyF7pW8rrn zDYE!v${gt7RAz={36-zv*x1gN$U>`DO(ynI;yQ6I$iu5vAG&x#aVYJeFc(-(=2^h7L~{(6wXP8f)$5 z5mxzMrt7U~82E$B%Zp9Pg_5@NJRz65=|yXh96DT5N1bhofBQz$pc*^Nfu~bqZ(#M6 zJ);pFjbGAoAqHh^i_@a`7J2It-dk#+>o%ooZj5Xaa@8#_(ZXPX=)7-tkyswLVW$(@ zx10e~-AdSOQkO*Vs!%i)F#(2%*`f15_?nY|6CJmnx1^L2iGsX0@>`D~?(|e+ue*YU zV66NIDjnA7({3v=5_c)Tf4?465k7Ik`kGhRwX;?ICm#F9AVV%L+Ma1Wy`48KK=lq) z`i$R5bYjR?g4>o0zA_8wTI`Uc=}OqMnS_7wtV7as{%~Ju;WcU2oeqYrwI&L?ei?Z{ zhnOqrXv=;gcE#L@;SB5^^{2T`E~G;vZrsfb2? zXaRL~%|J1EC@r$MHFiV+#sUvcoiXQ_w6W*ljK6P3NMq}357}Z*3PjflI77QR@_j{> zf`bI90~Og`z0bW0d9{{mgT)H5a$*@d9;_dH2dy3_P7P1=E=-xZ3F{NE?Dms74{-@! zWJccDDBP(#1fq^}nLPIpM#co#xOVgMS)F>mIW-*^gPR~{r|@{;OAs~)X8q2%VWshL zy)aB!q3p8FE>^pFdN`#t=l)+sTahtOEZwp?4AGj@gx~dhBj(hiQj>pkP6PF$2S5Qk zikM&cDTJ5fD*jAj)mPaaXVyX(c>-Sy(`65QQAxCVE3cXxLU5ZocS2lu^sfBWCst^Gz7MKRAz z%bC-sr{$C&nT1uk*eOELR2bJZ&U>k+4DdjY?@DHRYg`lgy1v`2`pV{>y~uhC8Z}zoRT;T zQ68Y$*&gd?5HK<0E$o3v_#4Jt!qi=JCheM7A(CwS#darc?x@}PXYi9Pt^^njchD#c zmriYCcg7#vc}~%(N9+YM`p#qD4NPLiJ!f@ditiME`^-RZ3Gm$>`>)Rbnh1=CpOPlI z8cICozul&*&Klm=nAw9({YHusYz@Q7=S>jQ4gB*k7FvKBEso?o{LVnw?FA?$`pclw zvo>RYwJ`&AWzoi#7!G@(;2T#?=}PR{M~%Pufwi@*Iwkqp6&HI4U?YnbIG4!j?jYI> zbq_GDgk|)I`!?&BQB*hb3y(;`L z$!Q{c!;{|Hz35LWG24(!@KOiaBY=xPBTuKGiOw-+PWvHE&*ctzTMx}86>d*Vwv-_~ z`y%Vp(ISJL|1~L`u^bC^_B|hxg3jW1yoS)2Jkf;EmTh9E6(Qj8@`m3BlE)%b`Tpfz z&UF-oG}^t#X6FlUqJZIF-dHcsPhe zxRcT9eZ5TG>Y$uz1~)hF`=@viG&{v=I__(7CM`)ff6t2nW<^*PXmX^sYzXWH8{t}pJx}BO8%4Ib*A3f!VT|dcB&2SaLOGfalhe7P?Y0r^w?Cflq2InHayQ$UR7oC zaIS@p`2ZSiNWA;i^-GETP&hI(y^9A1wFtP-=6mwOK`1yba(%1p6!kB@NNP$<`xNz(`|1cX-_uj*jkN1e zHr)V~XlGX15NaxQ0}zAA^{^W#3#3Mx!3a^m@6Hdo784+am%@^y++sai|AeEEnMPNN zk(P@N99oJ)H=NIuC?ECc8U4!fHCM1#L7uT`x9BoY{EV_TAN-^f(ZOW)F3wv&7R6o? z7>MMKT0w0<2qtAyZdA#$LL(Qp4l}N_L*nt1uKd|{;JRLT zN`oy-s=ncuBRj7eHF5DZ=V??{hJ3i1_BhUcy()*P{6mluEMsPtq6SHGO*mQq^QCc<$oS5!pz|M#7og?{$zdO z-B%$gm*W9i;eKIg%hZ{{7Ollc`W_X387=Q}$CHbofF%EUB*=ZWBk+gfiv+gHUX~IC!kZFOcQ3+jL~P+w6R0E; zuUzI3oliGnz4hZ3?33xjPbIYWqtl?VIUyk4g!ppyNVq(xQjMq8ZUcq)#xU>H$(ol* z@a_D>nIchvPz0KBXJ*wfPk)wRWTof1DdGeMZk(GR+w-sM+ijJ;2bjhYtgiR2W=Dzj z_pjG@`aWU~_dJPbvv@MGQ-DAn^+ua#ZJIlDCmy6CCY3L^f{ben`ji^4yYRCMB<;Lp z50f^@C^h%u+Oi`5;a zdV~{r+qRegW5XJkG+Vbt_!ebW$CFV_`1BJeD#+to*e}1ZaT!7$qF)5AXZVM9F)LAG zkCUs;J&>YTjdS(RW(Gmn^C#fnG4vonhIoj)*3Y3a%nYYNQQ05K8|?%gsnm6+2oY z3y$RcNk#Hclz5Xisd^`~*E^#ao6}+i1~Eas(su*D5y@ul6n;nP@D59bIb)oX_ov8$ z@0#jWzV&v!;e?bG_G|I=CFJK92my6{bvEW8$Y`V)7;cEdOkV*JPa!awAV$2l9C>9v zE|4PDV0}J2xflF~kSGP9mmJ9OHiAe3%Lfyw-z1sy0v~8NlhSr`S9J{@CwQ>WSmNg2 zK|UbYaaiPz!p(`6^+{@Y8eI%$C_K(g49($)Lok>Eu{J)4cuC@60tD0<%}F?dn&@uh zB;u^Fs?Rrn+{u><zV#`}3kUVr)+q=tE9u%~(}vi@ZD8bV;Sunx#8y2&60} zJhe432TsmuBlp_AU$~|m=)(L?ah9?Wo=^4$E7kJ^E4^@`g;MCZnCUQNGiPrRmv)cI zaUqgah}0=Ft=o1?t>1S1Nu(urHXM(&ITMe?zQQGu?ao^`v%c8ahshI~Gd7e@dFjJT zpY1oQu(!33XNz+3KH|LizVAMN?DCT9Lx7aMvGXO4*?}(=VPpIQOqwMdsWZtNsnaD) zZF5v_LT}$qm(ZB<$n>ao;Y0WBx>C36HievTo_ZCgB6SMAjQS;}y^@!u%9hc|GirAG zIpIyTb72I-#CO>4u!;i*=)&`c?dA8^J}2u1HUCC*yqSa9{Y4_r{mXio=KFz5O9{gM zJWBVm_9(ty-!Amw^}*-I=qyGMPW*DJTi3X^y^rwWaZ9ia%{c#e_-tIQt>?N#?5AEz zPrnJW-&t&-gz2~+)p%ueT;YRWAMM8#+X7z6NYVW+vekwsrHr?(;)Im=%TXqM7G?Zo z50dHc?AGfpg?T^a9aK;tBt#o1f`KLly&yjY6}`A=bUxxAf$Plt8ii*zoA)V)vs ziO%9|uGgu6B8a7y*mjFI{$K{*pO*g9l-^VA(cXtNC7W+BC!g5j6MtJhuh*Gg^&C<8 zH^BJ059~vHo{sfoJx`=5Tx$QUmzLIZykb)jrLEF6P85l<|3sVx?sk zzyWUZ`y!KyK=vp6d(5&td+O&;KjP7y;UdwREuN zwBY2kBwQvkwL8_aycTt7^qK^}Q%79%W!XLll<-WhM z(smNc=57Swv+<=H_~}gtu1=y*wJAHFEVO)Uw}Tp9h~G6f93LpA%WTbo$t!jHuDFg^ zM0vzwVIuhC$^Gr9syRqgPk*gxy6+;qb^JL9Ta_htIO?bl7D~a5ah~^2+@d>tVIpR| z$0Dg&Z37sAy&ESBk9%JEh(-SHg!bGIy>;>Y-@XXo;#|W7$WGr?NLL4?lp4T)%ZBDM z=itQp^f}uj8jm%PI^7FOd%jesw!P|jKQtar=iNF`(lmzjq}+9pwLcs(&34~WGj6;x zlep`2w5SOwoh8kK6W0aKnx(|Id>Wia#Dg*XmHY`f3VM9@xa2_OI+tR2UAO0Zd0@MI z$JFH(<*K|E>NwzR;JaefbxobHX8cG+%6S6s1)E-u_%cg4L&C4}k)(NO^u>Vx6Jr?s z+6{Xk7>~h3gmWFKjPrNSR=1QMPj+gLcZ3yq8_TiZj;E|ZJ{g1bMG(i}*};h~A<~AW z!(*X>^FEg0#zm;p%O^3DfmEHQLCKjm!zim_P_C;qP?%wgl(7nvi6h`dR)n8 zBa-`hdg!ukVdWpM9y^OV?Gv@}i&tEB8BRDs%9$j!$pld2?AFVF_o6 z#K?rd&I`ZAG+)<}b>Hv7E`82Lyf{?Ghf0K0{br}J_ySohaozFLmd*vwk}*uDo((CC zk+|`58GU1k1fOoRvs|9xX1wmX<);-^xDA>8GB`5_dfsnd&oCkNI^F1NyFWlhi*i*B z4d*ojg<_Q~Y}lRq62&GH65mI>y3wJXAHAXNjpi&)cLonr;GbZ|BOF)8oOB`+!k{f6 zT}`F_AEhz?e^?S6IX*2#!MgZ!w0KtrD6)*M%+COpu*owHbh8}?=#c|kORLG-+1Q3_ zkjg9I?DWWZW(q5Thz&JgD*GQP1mxG}$T_N-WMREm!x-x(Of$&FCbSTu99j z7ThFpOT>w7P?>E?O_+>OBhyr&$v~L-`%2LOQOP`!nT!?~f1%yBR~%xomQY+Wi1(|#W^uCC*jTtqfyJ!vciIt(?8CWbq!!PNyHG_BSc z<8YiyMqpF)*IBks*IkFflZJ{@8RdJkX57HbWF&ZyD9gVkNM(e1w3-yiHGpbnatb1` z;jkz_Z-XtEf#kT&!m_g!`+0E`<3kiLr_?a$!##m@1}d+~QCl(esLl68094=tvH18> zh*oo`L628d?ve&7cvF+l3lVq3c!DBEI=>z_0qXf#*ZJN= zmq8=w>{DuU+!u#hL>iQt{yfG>6%?iaDdf=%Sgs!3i0m-?mN*phgjXWI!ZfG4h>1n7 zlh#BhoFLRvTXO7)?Wuy1cJM3tK_N!(a1uiB8m)d^?Z>2QA8wv#V`Nu6w$F2tXBXZm!HRSjUiZkZ`R6Ruz8l+g=Y}Lf*qGu_1cvnTKj+dGaE-$P?VD-o7@|j z6bJes2_~aGVdqncHKkI!RLu3QCc0q7U+k|H2Ft3YC4jO>A?H2qi|6s?Al^s_b=zbt zbQ@+RMeS&4W~>gq%D=0g+VHUAEM8SwcF(m6CWzxzb^#oBtgX03j(atK$TfQl)p+mxnXx@+s%9mrULs@D+j0KWH zrqpHsoExp9g@7du4cX;lZB>UXr>iMwVhK0YD)LTLL=Ook6VOfx=O&|lLupBQ?WY|c zTax}ALT>FO1Bi%tZ?7s-F#wgP&a(kk#OVthsoUxd<`<{QP1eic_R=)cXDk>}xa2)n zqJwAjlcYP3jdu4m!Q^8z-D8CeE62~`Tchso-s%M>y#N5C48n;}x%f(s< zMlLFTcJqGy-Z#5MpNTT?als*HoGTc1!+P_7TaHPrvT756U}I`f<= zl)qFSP0fm1sO74>1Ufo~OS5_w8$B8uhFUejn-V&d%1XUfi?g!W5##8oly*uP>m0Wc z9CFJwHilTCD-FWJmj8mA;1=L#m#jTq%A%VzuKa5s6V!TTP!(-CMOAS^)}HMP8uhC2 zkOJg-ogsgt`K;9m1&DmlR@BnMd6i4F14fu!ksCq*)znUw3bEE(?947Qw!?!5={EsD z)&eRx1`SlL)m4*L+g8yk5Dx;1Pu{qj2c(poSgoUSb9>^d8q+o>6wOo@x8F4DeNOD` zYpLKmY7*n)fo|)%bPF5i)B5eO%ao_~Lw5&XoXOV936>A9|mxe>ZVSe{f-Y`Hq~5|Dq#?K_RU|=uMLC4wQVA_}%&)RCxJZYDRIqQ9I5Jc)VzOfB z5L0bD3IC`YZOs%iUAO>KVY^I|0Ti7d(Jl0TxqnZYhE4ri)IzVJ$pFQZRu|PF1jbqi zVoVW5>?lN_9VI?b!IV^+^dRE&R)?(28owRp!o)UtRFU*~(x|vvM9QSAopH_NIbn3SAawuO2? z1r2ryy$~ERKC^M45tC6=dz>^0Hw=j}&(* zXW8OR_3R6(&XTTrN4U#iVm>72I)b z6w{1b7zsKV>XJr9>J%v2WK1Lt5o>T)d0k&p=m71rdJOvi*=9h(W?o&L{do)i6G(B1 z3M`nPFDRPaHz|A<{y$m(awAAB4P{ZeF=Ez5Ij&XlOjXVlCMk6nm;4_P9VOp!Fe_9< z=gYAzCEG~rg7>4*Tk^^(EA*h1g``#>OjMbgg6WNLl?+jtWTV2V%MiuNU~yGn27f~$ zK%k&4G@W0_=`>AEOO-Uyhz-?^P2MPCge&eMp|Mm+IzPVxIa2dDLr;bUndKKdhMo!&{Wm$aIdtB6c9ZlN7|YaGj*yFB zRdlGyhBCxed7%GT9}x>osO+0zP@Lgtdqzo}UUG`VsicUX8yuNe>p|l)p2G=^-dgc4 z67GXD%Fc~P=KUMc4Ww#aN^$&@2Gs~hKM>0-Zo-`+#Qu)P1^&B-{I~1|JSpaXLIXf` zL<%aoS}OE{eSB6?{3)=Xh$S2wbG>pv^_i>BKj9Wex zoL#EK3X`LyRh7Dlst+V6?w}823Vkt5tTQyy3ar~5s)7rEsvlGLj@Q#rhOx-pHB?Nc zgJd#aRcBKpp`8|GviYu=(ij^qJ|vw%^v@CF*~Cmu$w4eyk&ZH{Wr&pUe~bG+h7B_F zqGBmpn}ARyIR-c}?jns1`1}Xb zaD+wm?XstACCP!}%4aY#jJdCRMy3FiZ5>^IL9=OEN#Dgh7>q>Kir)aYnWjVw2d{EC z2-kLs`b1Z{$bioK%fIvfw+c%&vBJimQjmj8$RdcSUnbm{|Iyyuokp(3pwDGS(1 z0yK%pUN~vAC0fI|NwfV^oMpk&AmDgg4DSzVg!1L2QBej-v6+oW-Q8LX^+Nj27ss>lPt!|> zB1F}JryLA887Z)<<@=hkK&?_IsYAgA%e|3&p;J_Y5=YS-K*7Y2Omhhh2;L7;P1;^= z4Zl2cJ$nlJ8Ul5q3JvcxpI8oi!8L>4ZO?6Fbyr(t8PSnRLreP)fr0d^AP6=v(DS!b zj1;H{(wd-))Y-jzB_t#qZ?v-##vZx5^O09$kwEr;kK5ZbTB0#(i!Q zDXF&R!+%ZhF4tqHrs&YQ9Zh2!jaF;nSN(_V>=}cJk*^yq2fd`FTjrZ}6l51H1~C73 zp3nSjrBvl@d@v{@byaD3=BuUzb8I1R=c=I8Bb;AE8ct3J3c?w2hMgn??nQlWG9q29 zsNt~5bJ!Z*?Z`Xx7zr*2sU-;)&V^KP`mJ`~qEm>`%X#DJ55rwPa7!?}!6s2PrGy)( z|9@rtf9&u>YfbJy^MaKcfJ-PYF1E;!NM+E|?x0S<6jDM@NK8CgYo@JKuP$h6N;*G3 zPq9n+@BF|9!|UueabND%V`ua_nq8b9y!;eI#GM*a?fAXwot~9jl5I$6J8jWgWdHN> z@vGu?G2rGwe_f!^JB(^+P9ZW(ex5ZPfwMB$HNa9#HVSl0g8@axx?oU_rLi9H*l-Q2 z8$dxbkVXxN1KQysrI7z}#fX&=RYTW-cU2vEaU~9^(@QTQF|wQDIm>>?ND+6Ep2!gt zer4hvY2YxhRf!O5ut&a1Nn)-+1scWI1^#K7SN3{1Uj^|205DHa&nnG&k^ki@@N?m+ zj8iKX78V`QcS~608uU#ZOpaNu*A!>|FGdv+-UKy?i$`Sw=4a|44Gj&`T3{?SG40sE zN?QQDPl$4oKC<&5s6fIx{j-Fs%qoj@oh1XrG4ZkE$5?bwT1o+7m~kn9h?A3(45w%U7=V%zEkaDY1LvRT z1DQ-@tryT-ncnmh61&}Wt#yks{)?gsL!g(nbTn6LfnvZ^UYx=X^xdH%h_n=_7%Cj` zAy@Pyo=Nnhhs#1L|Dt`RPT!{Nl<;19se9?LKe@ti@u(3+O@il2hJBxpYdFvG z5@Zt;fti?SQPI*5u*7w8P@k`ub0x@S%;refs$VJc{WvPf!5vbm#9T$O~_W=vrE zisUr(?s@$%jsRtXJOZ=M4oU)pk(%v6~+x-K&ROXW1&QjjF&g_s6=l6?RIus zILStCli`0U#x+AW>GvkK8JBu0^A>1Q1sRS)Qy4+-)9kckLoBAhZmi5;Vo_s78|r`1 zVULh@i@;KHio(0wzXbdh9^|GBmb;ih5a8M$>Lma6?Nu79Rct=G$w+wKWIeUj@nleN zKbFDi`S_PJlRx(^+X#|z1*1A&qrmY`;K2B#OI$ze|20mElrUhu%{P{ua* zd2~PgXMnx#B9_8N$IjZU=i654lgAtfDRnlE_lTOV^NY|tnjE(s-03@o>)Bdz=Vh03 z>H2@jiquk%ErhE4l#tX6S>}hKwx&p<_?XxGR~Z<#;u=<`<(q1Mo51fOf+Ch`FklNC z^`Azt<{~Nkalc(S31h>)Gd*<@SsMubtDgg^)3ucv{>v28Vgo-(BvzY=$--4rcT0ct zZn?mIQGtIu$kgI_r`Keygw)$k3@TGYLW-E>PBTGEm8fl z-PV_$-3kHY4gYyVYVzh>$tWugkei+vx(VHi6@lSFcQF~R6|a_#JNJJ2p5UJWs?#pQ zuLy2=+SR|8GCnO@jRpt7Whg{L_Q@?L+U^EGT=4r?m6USlxQ(z6o47&dJ~1 ze!-KGS&M5Z^}o62i)nk&k69TEdj|y?cy_&iSEcn z;8humQy$K^3ZJh!OPO(6_T6PUvt)@S*Y#J}6mmG?rxWfT$0y?(X)ka{*>S0D+2#CV zXRlBx|84nS$vUXwNPY_G43Y0jwG4#^bZ8I(4p|8h^lPH-RnZ6rQE$(htm_{g*$Vf`t^0*J&lEZ1Y|cP+dh#`%gA~!H+*_Z9 z^lAg5`d9L*;O)HLYg-R@r^~T!_v?T+I!`y!W&f1XAxitB>lWMsFA@b^H!|n1+cW!U z(1|6%t1M^iIX)-Gerwo5z>Bf#o6nsF*mq-jBoxi*R7QbGJOf4}8RQM_FWm1fI$ZMJ zu@P9^;;Fm_dutyp?trE{$C+L;fiQtLz>$mVTKyq61K%$9tJ^H_?bRSG!7};gmREuK zqMJxlh5Y&t!rt*MrPIiDmR=8vPN66ZKHTp8(tRZdKxpJML>sGEY(7a$P~~RN_>D)c zy4iQpf7`2@I+$$N%<3eEr1)|7JeMa^E0?~&>3D3-L#Z*i-Js@2AS?F57L*zHx9!{! z8KP-Z+vdInJ21(tXQYn~e>bvil|Y9Zq^^%QJfCM7X7EMH)LlvE!}ig7gUn;Brtt@Z zt^JTspMj0$WKAnL0;G&FTmP%k6f8=o!K^QBNAb?#U-eV`JP1ntEw*QP@9k#v+@aku ze(ueTG8C1r`%Oirx86R61!a8>>EY+-y=sSWPM1=}4gI2JIA{`{^C;hq{%PN!HaxFj zuy=rDR`25tNzNUMa`+@A<#gsY?4zB%mb2MvU_=r$eQsK)s(2V)YfHk6( zXJe{S<3iHuJ5H^OB2~tndh1J5;l~KsY#(AA{~=#&-5DK5MheSw{tc(CfFfF^Diw^V8K3wg z^PEZ1F!Lqn+zgv{BN`RKN2fc4R;BkTTOSSc?%@`k*;_|TN(K)P7D_j#{xm-ijqE7| z#_s6}GRk>xdxr8=DTMLOHHH7c7qGIhp&_B5VAxwMY055BGS7pzguIT9iS8R`i;VKn z$083wVa?DB4CI9TMqFe=RE;DVZ6T`3xjjKxNnaD)TGRN@{ta8xt3ZSv(R|JuBZ!j* z6*EvUND9#yim0eTO`qNY#9Bz~5lH}IWa4?n+=b-9Iy6QjA+N9Fhw6Sl`;J>}M~+^6 z{$zs-bQOND>87T7T(2)^$Ct2;p8dRhuOsLmi-NiY;kK zIX)4uM8{HBoul!E7b79Z}QCE(}G}D=M;M zh~FrCj4a{{UTNp}-C2L#@&X(F^!uTJGb%WXCze54rhSdRyu}~1af9VJ3f>Nh*)wR& zxIN;FGwU#FxN0$iDUj*J9?N(!6mM=Ydi@5lYI#11D;9mW>p}F~Z$Ib=8lMxo`4d+I zsdbZ!*Y?bhC8_K24a>bj^QO1d({6&Gi0_7&66^e}dIf|!D#4*mk~~Nn^2?T%o_xrw zqe6qno?P#T|GvmeH#T=mCVDg3xqRLBeZcuPA$g4@c>-#+Ih0d*pfZ;SKb>wi|I@x$&N$$(`Ki6d1~i4&t)@%iR=J1*%tejS#e| zJ0J0z|6;{?6aPFc;T0Uleny`?ZnBQvi(;QRK zA-y|4h6t?sbVN|UjK8Z%#i}rOqtJMcGyqAdGW5gdS9Lyx2daD@5$!w+lX^yT2HD@8 z^BT|_b$D=TEcr+NE>9v-E|e3nS9 z2(G`t!c3yM<0@kmI6CS4|8`zjLf~G+_y<2KC@KxmdhD&fNWwRm9XeHI?PI4LHDFN- zyb%5-Fnb#+xS;61eNYtegqT+ZxyR=J?H*?U{iHWm`FPMBdn(d}ZufUQ`pq(iBbw{} zL%D${ON;Qkoh?~JbtfuiVa?Ra`^);sVoTGVs^W$94`1$<#iQHZ+v3r$$Ho7yzz^yL zz3%_C18f8!r=YH*`$A@<*l0@-)$5s_>Ibs9!7=ClikD35^gBG)Jm=E5OUqv7_elHa zcCG=3QB$C_k3PLY;GE_T1wki-_fj8ezTcJ{5kC!g2TSC?|mt?=rJ9)_+N`?z9(P5`}Y)C?JV;7TwsyZ=Xr z+DL4z?Ed<1SXq2fDQl0NY}n`Zfime1)II!C!m-{i=W(j%$>}mp$gklF=`zYqt-WbJ zFPA!qSo%(Bf4$nJEJ2hL6xv^M)oa#m4VL&gD^mUv-zu;rcEn0_5IE>O_hT#DC1tud z(ca8{cO{YMH*ZOQNv*!IdL9zi<|h*3xN?B--6WFZfh*C?%iDh2Gg#1St*->|!;;VC zz=Nl4@6mq6w4&8gp;SIQ+>XZUXL0NYva{dX#5e(Oo@C4Qq?6#u7wGu2iq6^;XQo63 zgVEj`pA_qvSH=)y#DiPgmB^BPcHQO-@N@y^lxzP&NYX#mIaCdk7Ad(K5*H3V15Hc z)IPe#SCvHwW_t_v=Z9qM(MnpfP}Fy0F3Wyf|4&auT_JW=*-w8?P2m>%Zz7owMWa0w z7<}p69$I3KA>iKi#IO(~A7e+p22?fwS`|^pw`97gVBdDZwI-7vKF_n=eb7xmMz>kl zW!x6LrKIwMw}ginzF&3c9<9za=6boOG`i2~3;!mr`Y%Q2Q1l`V*6km+U9dJ0+|BYD<4<%OiycDsd=Px;`AobRmS@W(DO2OLFqP3|0iqW8m zueC_x@k**-2x>}-=t52j*#)B2bfXt4brSd7R&1EF=7&wIbh?e%6JH5960v;hJ>I3i zXLjo4V%ffbwHh~3ZGlyTeIZaIzjmnlx`g5i$wtnk&3FK5*Ums1R%AlKjhM8<6YXj4 zxEUenFexc$Ecgd;hMo<2Xd2zFYW(yQgtba`AeFSD ziAvIS3xqs10=wq6VuBa@K>rE7);K2Pxz{s`yxpNd{Z-jOVNn=wP$s7U0C<`bXksEY z)#CJBqJ5T!M7FZ^4*JliEyEa5FuQ(JI8N0H)V@X1i@^02>Q@(@=YEOKGtceU5BJ-r zAAMW++Z>0}FKI7NXxyf8dM@!-p_tDA(FL-SkmDHt#Fr*fuAc9hjJ_XViY2o|LOVig zd#U?5K9obb0dJWajf>C+tTnsmICGP0(t1>ESO7d~eSL@%NfxS>lL?lRSQEvmFgm?< zv@0s2$yTc&B7vkLvpqxaczn?`zM-+gZ+`jbL-5KK>Nno)KS}l*EpVuR3r!47dU%|l z*gTmEZ2P@qC~WgYwSrz5_pjkf3T`0f@RGg5TPO{|h81vo=L^HR@|~U7gF9t1zOjru z>+e-?XHYyhn;M(8X{oHxbx-1yf6|BhP#-y6O>zcIJxTPJ@mtb0a=p} z@^mf=x#%p!qN~0T`BI5^grD55w&=kZIU}_%de?d-)Y_t9%_(Gf+_nNW7TCtDb)zLJ zDk@)uKr~n_3Wd0zRDcjM46&0893+84Dh9wEi-GA{4im^f%}` ziTjLxt~Gh)F3^wlP_FB?uXY!eNd5W&OZdk1%M%M(&Aqor2=!P(L*F!Fe1Q-$M`7L~*cagK)8vEpk2h-E(j*m=fXTl}(Z- z9DEYOc|ux=N%D7YX?Ht9D$BmM5OHbr8xylZoh;VTePvXh z)CthAd^Bjm#=-s~I!aIaq2!JZm?LNTNMi2#xaRBG@}e_m^XY$!1jO+95v#-c{0NO1 zn7rI=FngrVrbi+B^{WOUq`UY>s5I{=UXz+c1FOd=6&;e#U_pX0m(!q8OZrzwdAs#? z8-OVOGnzc9|G-UF!w#&S&kK}3zChAC%NHCE?ZMu6G(sN}4unJo5T`&5m^(H)k$Jpb z%6)E}JBgnQ{Gz6cj$!g{w-HY8V=Fx-k;hHlYpxEm<-lD@`&&zoBle@)enWb&7;6F;SS-V_;KZnJ}h2?|v$DdL9(2&7G>@Nqkt3#)7R9yFTG59G8xdOi9S7VvBNqI-6Qmfci6VP^7Vryn*7KdvM&qb4&y?wYWT^xp67}avqt}=F9zt*I9LyL9YOl6StB6Z|3t*|3qRG z);|EmSjMAFB&^1r_mH+%!pT1Z;GH=F^+Z};As2XjL*^z4={R1dahO;zpE&0#&rR18 zTzg1=)OyAF9p8!TUFT1j4FUnI=tx|^z)UrJ+)6B+D4DhYs>Cfk*VcS8dgAbJ))JNu ze*>qN2QtnYpv||*s(fKu?Lo@1A1luyxgEP59b(HQ!>v+XaU7 zK-kslHtEOU^eoutF;hX1l!cKA=&W@2{#6QheCKk9;SSotLNdF=VXryKW3&T z@IPyW&WfYLfzw+iG-)sI1ab`TFjGLkT4Xq}h5lkww9KFqm;G!Mlkkj?Rl97$!HG}p zOZxz>Ob0ytsIWY*x+#Dfmin=>q6sETfo9kGI;&CkZO?&=iVhzgQASg>N!g|48zh7< ztB455PIufsG2tKsQ(RUJ-$}q}08-5^(iL(@r5Q^jK^4K|Gha<*p8Zbp0Y77k?Mq;1 zuNt3spd*wl)tlzC!AE6O$Krl*!1^KDQh4zu@F(h0`n-P7^)wU6=3=L3T-fz(RBhST z&ZfDun4`~_uYG<@Hky{QFfW6v(UwEf^}mQ+XdipOyQ$N^2F*(WwXj4Ve)MRz_>L_! z(&G5OXGc%Eu-siq-b`*Xvb>Lq)DY#41+yaUZbEPG_k>~0@L3^KQ!pm4Pddt{OU7Vl>qqsq5n@E|;P%%(j| z;QN6ZH;tqKwY3riFX1ni9x|9Whm-cqSFxzLCeXg4xqafPIYYlR3G(W0Gmkus9+Wv! zJFX!T$Z`i2c%s`7wr@6T&&sc*xcAkZ&5}^=bqvR+3 zos-kJ^>^gFnYb{%@oCL`hYvXP>iR!gfL7w5do^i~&(PjmyTfeRPERUKp>q9^tW<-8 zeWKRArKzHa*#QIq^y8ccUuvpAx%r=@@#qUY(b*K#hnRaj4kq6h7gRK~bPikG)Qz_4!t) zj)qgCNzDb>{2Y}=iNdTh8FCaI<2tn&@qK_~3I_@|@JIS@(3nI6_{kT@4W?QV2!5zylO!$@Q z#C^D8BjA6lrLTqn-)jq2eGP%Y3 zNUxw@T-e z6C1Itv$TKqORtW$mTQmhe6Y5Axqi||j5-evd6?j8-CX17J})}tJnaxl=sY%wqz{QQ z7@o>-vRpirI_Uc`wKQMd3_a?H>bm1XdDl9)(FTjMWPs|nk&)_dZtVX+6*1S&d9_MI zM@L3xO3R0sZOHxkS;ml{{k2E&4wS^T+ zqRHz)CBi`@@oJ`-IGdDS>5-9eET8_rP|+Rb zv`FGBa)C(ISEATLkvNF&R684)40(QQVO<_q8$vx|K|g~x;#UC8zGn;M&Y)K>M(<|M zx&&YSeKe51lX4g{6)GbH9FV#LzcCmH#F}4bF5CFOI!;IVmwqI3C*Ad?=}7PjE!Lsu zj2nzF{HZ^=YVaB}z-HRB-|#kuU^Vj{rj6~24GgBY1(YHP1m?@bx>({r)_OB_-S7}~ z-$UN=5wACJy{*kfOGobSSbqRlqgbEr4kVx8`;Lj5x1}2B0)gyzS=x{VM~O|JGknZo7^m*5Cdzc}Z6i0by&!*1rp&X4`W07-_tT=D*9 zOB`!!r}pcV#BtX4)$0S=t`E@EoM_%m=NiE<&8x46J#Q2WpNwGvNcead>YDP{Gb_KB zJ^XjIt&oUfMIok}GsxEge-%z+^%9uR?F2IkMloynw=vDO-wn1Hh=zcv+XKHKiH3W9 zCNixvCa5#O+n<~XyHDiKpTitBA}E+K>H>~({RzQhN5Awr&kD{aYv=>@ z^$C%={PKIJE}uAYge3oxm@~O84Zd0MMlMKlWpr=>zP-FPoda44GJvZz#^!mjZ@H8>{n2pF}01{=YWAfh zYj6p$pz9Bgul{-PQ`R%j5;p^KULZ0t{%l)SJ4!)m4!ZU1hT1~N(HLH>X9+Kaot-^x z+RVz@x?cN{E2CNl4Q}$(fs2}9Yb1d@ilMFGQUdRj=wtE#?BR z(wsJcY#dFD-s+Oq!>I;NZ#Sd+x6f|-3FvnKQgJC@!T@7Xe;;M8&p^_6B5%DLxZk@c zvuIeXmB#AuH!O$WNybWQLpGmO-FIl;frVXQVyKVa=OpZbj6j~5nRkc}jW6XG2F~jTjNhL|X*Zn1(O^RoknHy|((5<)-sMNci&wAf zpFe93O4@zfFN!m@pNZTr%|(MOpeN(OReXR1~}|y10Q8pR|CD-+??A(?)yZ4 z>KhxF&pjh*Vzp;dTlI#cpVmDNQc#*&y+_qlhGV0!oQ~rY9l0LnE6P*;ei+RD85W3T zeyw3%dFYt$4m0rA7un6r|Gm5{F1Oua`pv%k9nr0mpmlwk+dNm?Ef^d2d-EEVc6+q2 zXy`jIpgkh=g~w03Aufo5V2PP_13E@5rqQb($Z9Vt* z_vdTPQKzR?8+M%O>FKZg4wvp?|M3Nb>sop1*h^vTkK6C^%Ft*bYO3o;8L%sNRlv`e#Mv(dUK$NtfkW4ZRZmJ2zr%dx$;5Yf zX+nXIeEv~9DPxfpx6t5s2#G3N*WHELiyMRpYh6I_+p7Zat!$~RZJ>yNFCq!)@bBgt zj|BX^%H6b8lb^q#2VGf(`Qt0jM6I;S%v{O)!|qxgEN6Q36!ZVZ+FwRx!98!lsFKp4 zbazN2Al+Tk9TL*rAc%CgbhmVaba!_*lG5F0>+}1cb3VKuU%%nH*S+?=_rx_b*USVu zxCXraVcOALOd>-goMe9{PnppWJ(lkNea@J7K-GZ|g(zcksOy)MgyPWGl6*5LQgrA} zYNs*$m=)9!>7E^f<*Gngy_U|e$G*SL=J{4s!!9kK;@vDpjB+VH&&^aG?V{Ya$*PK_ zr3e0gH6vK8GgkhaMy5qS2$gI}aD5dg?eYUHZEQ8z>icmuaR3@CRa{loIFu!M_QMGp zLxRPLs4YNBsBhefMMY_I&XL7HD>75c$gA6@ZsLuYB%fH{tWO}?K9X;+ zEmNqKj8dj>WceBLcD|L|J3m{*j}UoA+JfX*)Q<`|Es26@?jP`bo) zGGg#CxU1(gbdTo_JEIT5rRJ15pEy$9A%_T?6H+$xz2lIRJ$f>3uqU%`6niEp;#IcX zv%i(TJ=kAzEyp&vm)qQ2dKv6bd|KkHev$vV)S3)^!eC$+2OCw9k7 z)*NrZjp^na6QRoSWTb#jKphP9moLWl7qTBeGhu6{tr5V!txb?0MV%P`tK)(;1@sE` zF8Z>uv9X1vrC?CB(x%h*KkbSqVzZLy-B8)~g}5R;qrtPZH#ll(Se`QQcz7~DW}#t} zBxC%>c7+vw*ggq?r#I3-ZbO8DL_$KEKe|?(TZ=;#`kPY1=g?-rVn~qQjz@p9D41{* zK6Q8nn&k|uYmf9y8I0i8n=eL}jvkXfm=I_dr8Y+!ZKw2BP(sQ@k_fo*GSaw1SB!xm${*R91R9WUnf)%Z#il$=>G@IV`^elCT%lxOF+@--W z;o;%nIVxhA>}_)fj5-gmApFu|wQwOI)+p=4A;fvB=$M(xDuoZ~iv>T$Ep^GY#Y#oK z)_(Q+Y~nK$lu+aS)2r^D9{&V{8BTJsgDdwiF~bBbGRQj;g72uL(4eLv@a`??hY!`j zO^_dVK?u@1Y6!B>(uS%Ot1>(PnLm|aGu3HdjQu&2;(AzG&(#D^Ahee{SS6#NfW|pu zujB+{0VR3#r0K3tCc{``EKjQic4=I}KCZmS zGkLDBR1_4@d1(UEdJ`MQ&Iie+&QiJJ(NADn-5$sWV+w40n7E5J5%#`DUn%{_e1r2d z6pA{_Qw;+>?~9G&pPz=>-D!jHLjVSliB}?1jX3ZTEOJnuDD{goo%^m`zPzw2-rK(6LShC_L$q0$7>y?>Ssu?5TE0*EY7u6nr?mla^ z5^Pih$?Pp(l8*ao*!TmC?`z2zuoM+#Zs0SMAAg{BYz%qU)P84Y?$|Cu!r^7$#Y;OEQyQC#ti3A;VB_gK2f$=Wm>R}!Ok+IM;cg&%fLdxjz}(&4cUBZfZ#W#-dZ>Q4sptDgFb}InrV+{Gmnd|tzBP%Pbysj?t_Yq?<1_tE%C0P{}3>aVU?QNsM!9n$tbLjfd z*}ZWv0j&4AmvA>IqSx#JBl~>&w)Wr34aDnfs5$>DYzm-~0{%efFL)?fiL&Ga-s?U_%~JxU z2=3tCfB;B^0;c5rO6wIacFSdnuGgz|nGVt9aG^ay)@!Zk=;)3(%=dE{SRWig9X{^K zeRUV#Ws}CWWi_8Cl0@NcwjUuI9hBfnTt8Hr@Vbq~)Q;?M;+bY>gIB}0!Tt3So@La~ zo+ArPPV^^!_YAVg^u;oIx`!tH zTO?xqbjzt27}C49e|$zZ#PH2B>@52@J$E)0y=hZ(XEPzT( zTa04uV#P6+Jz{J)o+)_i!B}h z-@c=mXL(_vS#=3`6=r6%;u$H>X+jwb2cE~!kPNs>)8qhf3o%K2qw z5dcJiQgZ*;7z#HRH)J%?Uu|#1N=nk$poYkPqTW0HKjiBqA(UxY4AlJ+u!XCONm2i> zO(09sN2x1J$*a)gLw}&-Gxw(R+(1o&=cf<(seOpWBr5`$0?$|B>8od$HXY*l(zaH0|Nebki5kasjHX#<1=B#mewzFpyL9> zrjj~30(%JloJdFv$ic>P1+m@TBH-9RfBpnF0N=C{(PIEtPR7ZZ1ehvdr`ylsV&VAT z71-F>^sguP9bw3Lx<6MhRA`o(CSziX5Fo>Xh!!A0fG5HK0mqXycX;-oCFUIDC1G zZ3MRe3xbGoQ%1xL4MC~Shg|ZnQ3X2C@wwfgk{FCdl$6ZP%Tv(Rl`}J=v93?~^^4<= zGdGB~T6819gR`?^YQ%SCDN#t8s|1Ax2fv1Z^uZ8)-M)L_536Xs{0l8%$bV`-H!I6K zF%f%mYO3pw^y!1QX41^mEtBNrEvv2#G;q>G8XpVdvO#Pa+(>AB~Lj$85 z{4aM{Fuqv}PIwG*Dqk?fa`wN^s{Iu((oPB*;8h?5S&geX>2CeIc{9cW>4xSl*)t32 zNhRNcNe4zoMt-6LR!b0V;E%#rMqj@8FZE@m-jHA!8JQ>SplJiV7m{6J*oXWI7Y|QT zMuwb>3^I10JDy&vleCara-%~zi!1OATr`P-V)+GV&TBEZlI zqICSW->`20kNbbWvA=)Vz-hw1H-h_3#@ZVBJ`^5T6}c}=m7MiNB7`3`&3t){bBlle zz9SbaYp#3_&!*<|;bn>T8LS2;Cu~XC-&9B(T$rs>ketvzbo3oaD!bL9pDxj!H9VXf zWh_k*(&VFqm>7(E3$U#Vbyj#WtyZwaQoLNae=5}r5{&K~W zj;A{~wfY-dXI=y&ZsFp3kS_l4S^bVm4(;~n7(GvzjSBNc#j$9?Gw49ur)6>&_J^kR@oR1c-c9F43`Tte7vsYqB z!-_Kt$o?IYRFdTm`e}f1Z|#3K1~dtkLGqt;5R;GqXFPs*MGw`# z`Wj^X^=xf!4gAvE&YCH+&DOwo6ifwod=AnCsTlA3dw10`ZJ=g|*7aY@573fmW&YLQ ziA^JHrQzMVbTp%;S;M(p=#j3RHqb15R(<6Px(sUdtNVgZqyC<3kHr-iuduAhV5yFN zdZuAwI-N!;A6ER!F%nROuQG_t*VuHbwBujDwf%pe3D_#2I_MZ>7^WohVy%IuvYE>n zH7Y2;=1rK2fRLn7+u50&f`S5MCuJy=nxH_1V{*e*QM)-Du%Vvr2>zLvNJ=KtJW8G@ z(V!TgbRiJmv&rUUHzTIWeey71p{#CjgL7A+Qu`#Dy)R=vvg5`}XkJ8HIIkimq*#SY z@z?!~@85dz6&1hNsCPz!gh8U@<9ogTDv*F%zC^1!M8UAPzNtCijFok|I>!~S$vG}M zWe!F3?4%FZncnX|@Z6F%J*^zipcArUje-zb+CZ`N7LrZ2>+s5eCF$DYp^ctdxg5nY z`p$z70925U0?#cT7akfaTrgD$>>CUUVe`^a4dT#y7<#zB3jOp;n*r34;DI8DPke!v zbSXv9h>?_#5mI@i=F?-E;4n26#E^!Uiox|Gq^|w>Q4mYe{F>y4k}mxFXifR}ALQdT z0+VhUF%l9o`5tOGPRE*mm?I$d?Ec9Q>FI+fNRK6X`vyi$eFUD~L14V*nqNhOPW2rA zzWUpd`Jl@YISI2H|7^)2iS|FK+bhKm@2!ZMPq!^C^|y)pk_4oMRkq8#w(jdv47q=X z+T#7PDuJ>}57r+Wh`-prjfW5gfV`#^!rB(#$_@?>gTuq~fM|<){+D?}btI40*A~`q z>#+&VY?}NMc-eGlZr9tF^YdF2IjeFMD}>+#dChm0;39u0x^d<4Hy&cmjnmS?@Xgcf zZt$`wp7FW1cC2idaH1-<-MyR6b9K!Ue}OGAM>|yKKvQsN=$gZZu8g}eCUEr|$OEfF zx&I4vRz-w_AXHRT`m4g|hV(l=0WqURv@i-%j_jKPAKW>-xbv8vnVFcM$HpY{kV1!hW*nL5(4E446hDm^wlV!zP$iz%6W)ZRUcl7?2ynxZ4 z_~3iw8QdbST_*6}cy+lBTdWko9gdU@ljsNMmJDGD+8kivD z58WR{-9Qy+@CG2qHKI3H$IeY!eo{wo0I&zqyK9TCM{B$%;Rmo|9bX-0d_vayb=FrH?A3@|F*LV0y#wMRT(ectMbXsHxukj4e-Oi#ea)OLE0K9 zGDyj+c=UxpZ^gR;87E=}ms!Vpki0M}+f4CSPyi<1+}{g9eS^#c=z?EcR#mz8iBauK z>z|!N|0h%7>U8m#Ze(O>F(Vh^V%bys*)Ys=Gc#F5=07aX$3RKrXJKK-*4dxB<;|W@ z$xolC0O}3x@#!%D7+9_#=hv^qoJhXpF}{benPRn^BB{XXzt989hZhZ}lkHN6cn{gp zOpxXDHLI*>jFW`-e8$F|Vs{fcG!%VJkcYodnQ#p<&L|0vv##HTw-hRRatf5mU;KtC zJN2`us9QzHH~Y5dYDNyAMdZNP`CBL>jb*bN_}Y*>o3YQ{N6KYfG> zA}kCE5KxJB1Iv4n!}N1;u>dC|H1m{(73);FUB0=(%F5`XqW9pDmRe-iT0INP%li(m zK>6hU8?7H?XvaeT#_4xr?JQC4YCR_6Ib71NASCQ%m{U zQw3`eYb>SXwv6g3|K=usxLucs&tMt3ObUBAz*)LU?BUXkEj9ks3rk+L|K~>jMnFKN zxm}LCt?L6tC5ivUSboyom#9=!xL&nV*VFq10woY1eQlwGf*QC6xsOlw_AH{JqUv;* z$||A?Kad@q{sqP3x)2+k7M&52BvSB=EIL|Ih!kj0LZb~)IdU*Ps+2?uVP)cP+^&&;2(J{+JCvc>v8`Di!E6D^DRQ5i8XDe1!RM8Oh z5ZZh$-}@$Dp+0~x_n2U_ozw6zFoZqtOrC!n=t4`xca7R6;~rE%1}(WDW8hASL&N-V z5~z2fSY?FyVf87VKg2@em9zn2S43kFtsKtx(k>BsIA1dVFd0a=9fqGJMKh1=7y5)L z4d3aVU}6H&+v7luXd)?pg)Vo4KD|$PZgq$emUoQ%BXTD`bGhA60?)%Zf=6RBeg=J@ z@K{@P${0b!g#eO)x%0`;(8%xShvOwH9Pj^944E$LAo^0L+h96wLKs_I#=*&MP^TGU zsjaQ0KbK&)$?*5<1Iz~C8Mv(r7K6zpu@Pb9`0kAO9#4fm_%gt40YM(8`Tu#sp{ZJE z$u~g?P=4ZUbRz6=N;BW*MB>S#av7*ZA#R7fb`M1l6_oBj7|4^drwMsFak7b#alr{~ zJ!?9UT(Wk`!pb6KG_|XRM-di^#$k|XK@)%x^w3W*=nyricx0me{T5|zUG-Fz+-P;R zPqVDyVI_PeS}N1B(31Y={x%=lW_<)7A~g8Z2af_N#tldINiNM~8um%@|MbbSmU;Se zXWT-(tZ)4~{ozfX!lP`d(WUwou^0L2BDw;lA?PdNLBEqT`nQm^ws1V%#oqo#j{oh9VKSXw~IHHO2n-T9wRM33d&j%J`wae9JRn2>hY(% zw75dP)QxR>Q56tG!E&A@j%TBSO^+=dMmWD+EO+0DmwAsp@_k;M`+mf zR)@oa#2CrEZ6yu=_$b%Z;UvCQJ`aaX;MJ ze{lTxVAJIPuKLnd+RJFR_=M@C{%AUg()QsAuRNY;nuI&fjS*8uD61sBWUBp{zsx{A^zl5Bh3iFSLSoxDSd1(9OscZaZ%v+$ z-bM_we?*8lF7UWxDWYCKdHEG3Z0PIICl~U5W~Xw*(r6#SK8_oK^2bIxn9HL z?QE&m#xa&jB+3xR0++VEOo&q8~s$)=>;br1CVBm{F% zV5jH|og)}Cd2UcV+Sq%1IMd3qTs7pm&Wqc!ZbG<`c46i>Zx-yVz60V`AQdOqqL2t1Mbo zZF3A)8nUQDXO@oeg$JMB?w@JhsHmv#GxGG)t*AJ*XDv3|ENJ9`RG$0^tL*$@+_Am^LNFDD5{qWIt$p; z4lqo$N8t*gTGu`9YaDudt1~$>{lTXG6Ss@qSf6`D z_s8E}6-KhWWDL#GIS-m=jTHA>MvnI#GObLpN}GS=b-;Fp=AM`If$TLMakTRiE-Ia& zQYvEufllm%u!!@$5nAq~o6|NoH&2E>U5^iBo8}s4`*<=xGxb8oo9qp|XxL@WPrSUAsCV&C8=dYysuM=={U7 zoht;3ZryN0%1g6SZ~GSG#?A%}wnZqI_OL*=q!`J?N8%CwnAG>i>yGGAl|;ezmKeW7 zD~QAj-|$@lv&)1rPwZB31ZoM{Rc^uUsS(aVQ^c;Wb!)E}J0s{=cO*5O^6{zO{ye^M zSFx@Zul62MVyR8PUP2q;}GCt zMiyd)tFp7R4V|+wK)PkV#_XM)o!!@A+N9* z)H&WH3{m(=3KmR(7*aMAwIq2AGAg&CV!Sq*DL-;E^R@J?T~ED71w%StL&Ns&muOQs zM^c#UPmv@0-2fREZZ6jNShb3X5%Gp-7enR7{E@$XEOw$}-0vgN2xzZ@p`zI@>^}TH z&H5Hm@2n>z&Jrh4=vyDf(V~qXH0i7CuHyi5)4w$ebj=Do>_Ne$REZ8niycHRc`sS1 z9!8JTGcJ}-9IYCZSpiT8-4I`A*Gxu%F-K{lLk6myc2Oz!R&9yV({ zW^?;3mGh=$slxSBRl3u>xPB!(#1&(iMAgA4b;ddQ*65pxkiJtMt2F)^vg)ct!<}f2 zVPOES;0u&A7Y#OVa#kVQoS+Qh7NuY7cC2z`klyNZ_|a;P1fr@mQHmVMPHc>@A8wsl z-UeyVUWI{a`3dzHz(p85se&AXMJr-i```3iL z2qV>na17S(e+3n+HvaTnGKXv{_QSPA?@md+{&Ye-^4jT(iYr?MYg@F0{n8C)ZS>%| zSdeTVPAe4o@R_8#hMZ(L(RDR34mN%rqt}Vfdl}&Z(*KEVu%Afp^V35tki+xeLtP50 z&Qu}+-Giv#+S+>7#lQFV_Ci)*$@&SES})cF%ciiumeA%W95}fhh`+8j3itaH*1RB$v%a=KJvu z-kf@+&R-VKYb!;CR)UB<+75cOf&q0f2fJN-WK=U~fMj60CZmcsj(iJOYH*o4sZuaQ ze_a4NL}Ff1sj_UoeN>a*ZMMul#MeXy{={-xoBj_Nl_VE%;cqSkBo;q9OKPdHEL+<< zZ9EgKZ);CQQF9pHDEQzU>60t=bRAbRzi-qZR1$B{r#nuXVdRP+J0;}Ur_d&~kK$3a z*xTWP(#i0;QKUD6!)K1@C9$We*FlD5xIHRDi;hZPYLFy7?#CRBz=t>$ ztf8QbW8=kOt=pr(liT~^{pIIpt+3WxJ?*bDm}Tsd^qJEYo3V4QhsFH!+Nz-jRRUz> z?Dq==w6a9va#hH+MKNL+!%ZRc+sqR$nLLXjnM)*p0@sR0pRcBpe|xN^{Dyk{f1Vnx zg>QV0$)NiUNcK|G(sqI147#uXT2%{q0Q8*UInSvgOpK48Qr!?IgCZ5E@}psry{@XR zzEO|N%_R>LBXigtrQqWONpvkIkN*O+BoNk$Vyg+7OsY&5VT$ZTO)Fza#&osVE7CTs zk`mcAnPVkd+Q+2x|F~>^{_%XxhVXprk5nigwbHQ^?PHBlia-!tQG+&1rc%@I7t?_& zEvw+>8!L(|DcF}?WbPy>i{_<3|B{;Wa{cz+qTpgZ ztMcLar)7xAGO~A0I$Qb52;>*6)6Q`jx(Czv5O^iLKd+*ajROh-`CRw~Cx_z8+ddbo zj?6AGt`8YI@IP3?il-$J4)4>}W(!+1wV;^2lI*iRrRW`{DNVVKQ|h%j(kn!RAL_tN$`3Jp#2u#lwJZ|`+}%=(ntEUyMCB#e-g zC+n-gvB5)yRpExmHT~=pOg4Ps?}ZbrGW=iO`;rwPGe}tEZc|pV1{^0YonlTh?}`sq zcQvz6JZ)=hJ9TWbONJ72Efmbm(WP4TVzNUcBP%&u6T27D(b0ldR`gYLhL!4|%(qlp z{2xDIG#eB>7}R9vnQ25MJG}FU5MnxxhipyU#-W1pB~3Mz2qjD7JZyBZ$j;0v_t@i= zRx+b<=14YjCJM4~gdVcUCrRHZ6Bk4`QDw<0#{Eo9FSBLDhL~zLydn!wt)+d{L z?~-OX@rOj0Y?^68UIj@K`S+{vVGF8S+fH~WFHBjL9Q*9rH*f@;>sh5vBFz>f`SrD{ zEk%ZS8B5j6d^R6D(Iij5;UR|-kjMwzlsCb}ARQ(?=x_!rS#Jk)#hOkcdRnGGy&Cg+ zqDYZz{K4n>V6bZvU*hzErxWGqDn#Pu%KfwJ%_y^#L-r&&F8OkXEJDFdjU;sguZ@a+Rh>YQUl+6UWJ$Su5chYb?^M% z`pnE<=HMW2%U^pR{`gCwgC+O7UxX`H6u~84Z0K1rDZ5IMjP=F*J+)Q~hSwwcD2KHN z@pe(4bX9N#F%GVE?(vq5Hwj53`km73Qzhg{l=ijSO%$IUb=M}_j;ET)5!yRjiFMki zqzvZ)beVqRPYX<129zd3eCIcyIcxv-<%!{|5z&boJmP&0n3M9TQ8d${fJT&@$J&*` z*%s9QsG)+Nx{O%Ru(0|TYb`(yOP_>A(b1CL(jr$Kj^4lT+K*=?12oJVe=x320@WDy zp`S$|fG2{oSoAju%A(JNo!vR{pK-vjYtTjqsaR`(c*cK2OR|oW3&j2{U8kr_O$!i8 zvW-JC!g7yj(XH+OoVI!n|EKbMjfK3}h7V%zux*_Tv@UVnJ9tl zh>oS}`TCs_sgSXC(rBEC42lQCuVgb6e8E)Bkt!73otemQMxk0=sa#=(42>ZUy_Cmi zJ49je1bi?XPw<4Ho)`gK2rd)a@zeRXe$dH}?v!x`TEM0c)7&Ar zZUsM7W;l=<-p|XM4=Nx~GMk^{grz>vfkg>)WlB^rc(fa12njYv+*cWBYXmwt^5ex=Qmn!_iC)~9DG^cbApQ<3q}2fIPJy>NOYNo2;M{RW1U)Xb5aw||Ioq1P7 zoQ5-=5Ok;Bh!x;5FD-G^!A^YSN7`Q^O8ihCwFN_EaBZE}iC4Kc>so?dY1$zrhW`<& zPj?21yzh-1_w)cS5%1s!W-MFfR*bpia`j_tchvKe|Nqc<^7`oY!2i1)N5^cPBnx)` zm-uyCxK5Nt-|pwH#f_Yf{7JsdswkfsGiziv=YXfiDU2 zp@3i#+B0eJ&4J`CghB3%c@Lm`-K?G5AO!v^05tOamj<%U+}rdqQu@}tt}O5CE#XUW zWv^8D25sZJn#;|ejC_kfM#|xt*>_8FO6G*-&Tp+&PSC9+&E%! zVwUgBH8eOIs5siB6;#^@rS(y!Yc=3Ir|bH+7e$a~wT?Oz=- z4b-tpTmK?f#*ytas_H$Lu?g}6pCwt|V6PQd>R_&@;oxow!r2xlZWm9Z^*!mAo-dxt z>>khX<$R9(vs6So)59xk&pFFc(S12_Tk{0!*LOCo`Kj&QHSuX^@sC|NU$oj|#^Sed zSt8y&douRU>1}n@XM9eFHPXTq*ZvsK+=aYx|3JQ)d`9Syt}6ifSuUmhOIPm{)ftm@ zv))cAj>GLS8M_A>Vdax{jDXxL$xE zv6f{h6;a9@agRBRnB>e?yN@Z1na^=3ZfC6x)UROh;M~Z9Ctk;-Z6s(9Y*Xoe8I8SR z)~cFvIS3CU!X#=T)OoLD-GFyjtCsY1?(4BVhnC`k3ff`d`iyJKyC`unhAT}|TJ?9- zntsl`(m}-W&A06Vt%dTbh(TyE@T=i6>imOe4Hba$t%Vqkr)hpjJTi#&Ch61`vW`dv90m~?mY z^;hMz;6urWUk<%9h#_Y$#YJ?*5H2iNM|I|*1ie?Eo^f`4$Cxf=>rX|UHhv8eZp{u9 z%2uJ(dl5I7T^JjWxEIbIeS27v-doI*4u6o8Es8-$i=NFbDGAg2cISV3YI}XWqDAId zLi@d>SP@jP)YaA3MaJ)yCD@I?fD>Ip8XB6bR!<=zq0*rPcv5;$wiFQ)GpJv( z<4RLjR-S%n5D^g(@-~*1QmS$bfk$!cHa+WPOtL*7AH;Jrz3q7XH{7ml&lSeTBI+kLbWSTTp+it`a8_=vAI)xtctR%ATjKZclT&AC`~UD)OvpvNr(GGETL{HwGq&8~S=Z-y z_9OdhUB6WNUJ?z>3sH2)KfC8IDK13XSSI4RFP-hG#tWWx$y;U+HDN;?8FH zPkFO}^7{Ef0m26Gu0IkI4C|L5^;CmQJ-vv*Eto*xD>zc`b}LdcGG;``z%K6-CS#jW@Br||nk-~w(lask%6^u_aLPoN$mW=) zixnz?Fy78Sb;EK_ z$bxOJW4jqP_RN~_=^NeZ-T|cN1IG`iFHdXY(U=`2^m?e=rFG~aC2)DG8Usj+EBz|3s_^<0g~7~!|ujllLBK$G+fob%dq28?9g z@_NB~7p^q#8;D15QyCeV79wF05%OuMv3O-XH8V?+uOh?NEToUJSP6uE;4HVESDc>{3K9<*)&7%`lJ&5P#aj2 zG~->}_E=j|!&+g-XrGH%EHnv^C|iAhqIo1W(CFfG)a`QUH+1uEfgj_8set2^o(+-P znpYPiIZI6r?dk0^EX%bDdc4(U6Fp4yQ{&|5apzJ!S#!f#>D$x);{yD^aC;|Fge(RD zy$K$xI=J?3+~GhY?2srFDfZW8;z8gQf8d8s=r5u_+>nM3esjHbk2$!kH1otc+iFBp zDITBVSbvlbW#g~DpML#PT))74yN9{459GWsIk%ao5GJ=Haaty{{R} z;TM#wqMje#J~oWVr)gI2t*;WE#G%8$ZnGpH^nfheW@HvOd~hI4Chw_5Am7<4Uv)p` z1Raxa_IBY0QBJNg@`fnwwMqJL<_{(wJj{#Hul(=guef{j=AXC$!(=W0MsGJQ#5=d| zN7Zrc++Anv@P5HH`LGF<+wub9!=9OL;+YGNNko>KPizbuci}6<3~!tyA+?WmuDeLB zVfd2nVQJY%U%lTTf{kQjf`NQ#74-M14MfiR9wvCu&r=;!uG(Eq#L7ii0 zZAfsKCZLPri3$pma6Va-1khleIBz=l-#hI~Nl5`r&$d|FsLjxopOd+o2v^36z#2yvDnH z=Bp9~$BMbs!viC3z0v2GwBM+4EI|VwpW-ETx*j?8mMgX0GJLnycF!gpKHQbR{$(I} z%=Y7w8qZjrakR-A{!8`h)?FZf2kd%SzGuC6_k0KIQFr7$Z=22q%1-k$`PwFN*%*!^ zUmX$eSWD=Vfv)~&!OPA-WQzb4!F{?+eP!R|L__(L)9GQY3TzZ5`^(Al(<;iLQ=yRJ z;`@RrN%!5dk`WD2Wo2}52UteGmB;RDt<5DrR+^j*lAp({Gsc#R)-t+&pSjvL zZ2^EpN=hnjG?vcmc)ZM6v4)O`8PKIrP4L|Do)GY24-ld8G;z%KXG`(EUT;qnDp3Ki zaOjarhD7=rFtdOcv*my&cbO~G0et`lhK48)cA^02so3JFsYnk-zgZBNw634ZQ6oBc zJ~6t;&nPU~D&aJ1v1A9yFzh34$4ueA?XFc4w1o_>>y6fhTyLDb2NlVC8!a6xojwoA zrY4jEnWk8!{G%7d+OCmlxHY)TgDQrI*GxxU`K>Z8Hs4?RQArTk(Emb z?an3dB9Ytgv zL=uD&hEUO%1ydR=HrrnGfXTQ0`!~VaRtWH~TqE&6$S|tB$!|Z(zl&9rkdZPw&I^*D zRj3x4gqnIa)y*Vx{o8K#kGNOyp1|QG47|0tWxxS3+tmDA_6$>zUIEg(ciime?CtDK zvMKM$^G2!xFY_cy!k}+^97od=9h;Bn`l$#Xx$yqRx4h9_0NHY>uGBk?0}U-YzMl#4 z{QO)(S{m~4A}>vj3UK!mhE#U7`=2!Eb?H@2ao)X~GPSTQA%6R~BlLc2vH2?NUUBb7q`RWS z4xzmvcPlaZJ@aH3cFX6X)4)Pwr`!V+ME4I1dc<_7QUJca~XCP)?@p49&Se#p_7%R7(fcS+ZW zMW1VhSM)SAG+O4=R8#LKDXK(9u2Hfcy`DC8VKI5ilms7cY$ zc~6>!^-*O}=xAn^a%$M%g`YpDK|VA;H{`RYAaz~VuQDTfbtx8`6*|HEp=fKV(H*;( zEWxVmiC7=iAd470D_FHEC#Q>6&R$=lx{gtHuPqoa&;KMOJ9mf=JeOO%%$dK% zmpSIvTG+R(a-TuTbpe}H4#9mKu}Uk7h-h+^&q-TbGXUNno3ZHPkuwkghz@f3tufv5 z1khx~wbV@XbL8;)XlZ{kPr9_va=5PK0rY*q4TslUrvTfJE(YXXx%%2<#k&65=65E# zM2JMnWVH!nJl%5$MJVPtBU$LJAM*2o_^_vn&-5yZ^~kl?O5Iby=G{_bGWzz(M&AtW znR|=l$!c}58VxB}y)O0lTvdaEQs68g*r4L)&p;;Nf`X7NCY?0jfPX$62QaNP{iA0l zF*7@RUGELx9=>usoTay2m_R1gVZZ`F8O+=gn8};kCud|V?=2|-U*^HLrl8>qT$r@} z(NvM9BC?owZcq)4bD*z6U$}nPeMZ0Tql)iNRLvJa=?LnVXmmc5i%f4pcI~YS3Sv$D z_rQ5YB_)V{PJjsh3hcBnOg0W@FHz;d;W3;{KEc)|F;h_`wB$cBg^gZE5y{EUeg&~n zsE-Zoup%(yzjT0w$P6z5@z1p7R?(C8LdM_6bg*RS=KXq=Wm3*J(t?hLhQ^Z)6k;;v zpEVBzOl5NU33Ua9j?px3z$FH4a17&{)8>`tBR>#Zm*F2i>k%iVrfP4I_k->%N;uN3 z%}v{;mG;&_af{h6*4EbHcRxS?&(;Y-JhTPzYKlCD+5$hIAK)HhD;HZeUG+R_Mhe=2V-j0%ztQ4ZJwub;6ca`}Bes5QsKN0{|`@XcYkk5^{2K z{5U3-_wPdh@7(=zPw)Yx7$NA@Wv6m~{tNufI9X2_oR%Bk>E40SU!BP114MJ$19M&cm>S()|o3rJv{?M8S_{rUv^GT za6|+p3rkFYzl6*bV$GMUI}h)1(7CNBFE0SzCHw)5`U4dBh_0{IAf#F(w($D+FFvwL zg^(;9pflXswK;D)pU}27#{zr5dBHhJtpsf2jD%52fc&$<(gs1jc#8qnTOcyQU)VYv zRSluvTDN3K*F+Fg8X7wx@tDsK0HBK!b>b5RoZ-Gd_Z|&bpV3 zeJb9ZG>5YY4hw^N{6LM=^~Nt!l~(<*5ioB7mz^(zQJ%(Zp~)P`$yP0?dF# z!eft$i}N4)4L@vMv)C-OvXOh$VwUX9ZmasnOoa!gKD5?H9JK2G45`^s1(KC;er^xI zVJY$3&meVBt2qTOO`=PkB)66~OTNl#Vqyl=eg=lkrZg0FABv6>o?>A?nXi>}adyXD7M9-DcksQ2N^!Zs z2Uqz*M|XhxRd4m+1m?{V7%;Io1JKn5avI}l89KeJZ8D{H54&gN=JVG9FUxclOwBBT8n(cIiTFlZm^vkU$s zIdaCB`1Phgo#rV;fh|BU=6_2J|iUXfF{(C?c9Wh~=PVhRgCz+2{X+BYo-2@N_@RjI_?vq|%RTz%Qh2ei zO}QeQ0=_by^aY4Nw?j5Dt``Q%Q4G9Jg!ZuOV|_+*eph`=Ajk3Q3tj7r0VX7B-!0B3 z=291qoz;v){zK6n&)RgMjL>V(KISirqWBrO5lETlAEkHs`ihBO+9Ozk zebt1tx8r1SQ~CF|zRq&q%llF|R#9Rz`HDRS>ql{hchBcoqlc5pn>uE+%71eSS?xsu zj!j#Dr%t=D5Q=hWS7*I4I9saq7ksZYI&rTbmDpAR3xFyG;0tsSjukuJXeJuGQ>}fi zk2CtEN~&2BM~a3!4l(+Eu+^ zH*bYHn>6+R;q5GgstWr6FCro>-65@XN~0iMN=i3~bT=2In@cw$B}mt$FWqqI?(Xi~ zgTC+1?w6hYu(Nl@864%FbDrlp|M>l@B&l^IMRzs-GJt&*hs9cmH}WoX((ZEWg6Fs1 zeX4uXLvhS;!a^tc2pYG?-SY}E*PyK~awEF}-;vaWnp2-^0#VpT@9E9!O@{2|IC-PS z$i+GW)_pSO1449ex`Q>=ql2Y;#6x|j78~Y<2NAcxL%rp_O_%QhzOhhk>BCZXJCnt> zEOJ6r!OeHf2c)9goiq)Crt`zDkAN%T-L~BPC6aZ-z?p}LBqz!EkLyPA?bVzY)}^p5 z;XNhs)iVjD4!(5gHuJ_|Ir_>}(B4pZKPEQMW?`8_q*YH`7`N5|wc@B&W#qS>644nx z6{(OQN&Ecy_$phWP~ebu1Mq8mI191S{ZeSlvQdWxP~j!>a$ZRgqTkLAo=?Z`gV_VoQ~UDg6!O0Mkd;gu{2A3lmqhCU3E%geXIo$ap} z?K@)}iCr+uXOMinFeeA6aQj2Gg_FjJ5J-*BwbEh|vj-ivu`p}04F)v(HSuBDfyFCf zR?HN>2cWs$@>%@jjt!Kpxbh$Gg=a-q2r+E$dFNljckjqo zc?^bZIpX0+tgu6k4n{a?%`Hv`iHci(|NPxey)o5S^AO9qw@&6{t~ad)c16yq6Sd-?cg^6^RnBG7Cfg{DH8X&U)$l!f=yu$t}Y+glUK znN}=G6u&@bMLL~M-ID23d{?r(dp4VK^~;nh^Q*BBIIZDfP9EU5zeP>lclPw4(-*g71BC7eTXgGOxi@ zHe>KTy#xIqds3vl#hwmV4%f5r$Z0+|WV9W!?>H43zUmEUg9a1$H?Iy8JAyZLdJzmq zf{(0L#&@lj?<+N34lXi3!FQ&^YF2wUgPXS14+zM7(R>>sfdqMc%Ind``8Hd}erwdj zsTi;Og4rkxqQRf&wOYrQ3Rgy_)XclM=*ng8+gjZ+*Bg_Kf z$?Kb30_ZlGOh=h9;+}!i2t0aev}`XZR!F_SbeH3kZ?5M6T}Hn~Ao=YoE;XkGRC2k1?4Y2D~wO5rUM$Fl5$m5JFc zjOj4p`nX$IL&K-T)fwcQ(0^(inB;|7Iua) z=`E?N*=S}++9eDaUMM-2_NDeP(PgtzGsHuhGzTw2GSAQh%jNo}ekAfYL%~+e!eO7a>?A%=0{QFGx5> zSbI8>Ko?Hfi!Hh6s_&llvc271(UV1|IDNo(RC)k3Er)tCFByv)V<=vaxRw7Toi_3DSn zgVSW_-TkWU!L=juAbO*eb5ma@8ZLF%q14zzSAeI~nT$^dgKE_7{>On;pqC)Fq24-d zufRL@H(&ZJZg41IqBU|I;7=A2vl&%XcMq(E)o8TjBuym@7CWoQ+;imIbC{RNe9Fe< zE5MBw7t)2Eqirk^6Q=8Rjavzrp1Gx{TYGkm^$%D6={i)mKa}2RYD{v%&b424^$dDO zFqM+1t#;g=iZRW;LpdUGMs*jeQrLYy!avY8VNCqnPGq?Ncg@uuyffQ7x%*BkDN(HT zV}jKR!)2-asNDkSTJznUAy1|`4}tqvflV3dms)*P_z|>&FVEz2zIUt(TyG-_70JA3=6a`nWZs! z6%vlWoG*b=p$AkJ>#e~Kj;>Lfo<1&96Z_ph*wOS-ebSKavrSpqm558S<&tG39^=n+ zzdXe5%12v%B2h`%Iq99b(j6@#>KfkkOAqpwk&~tx@4byM?cQ3*4hN=!Uka}!nbz4Y zPaV`)A{4SbFNmz?o15Pv++00 zyJw{7s!JOoL&s?HY%^^*NpsO92r(7k<|c~sS0n#jB&lW>F$LuaG6@iff}AoeXkri8 zUYcSV!jq5^*mhEwz&sLYYN@UqyF`T}oG&9S3SZ^Hjs{=fTF78g*T79y<;YIg4Y=y70F@9bUqB#tg8w1jw{?rgpO!}-#aeBP9D za*j35XPBFQQEJdBrl6ees?AkltiiA=&86XW%Y(%yC&Boz-`9nM({d`LKH0U-@Z``F zWOByY=D}amT3_Vfy~=AfS2S&ea-nuTWg>mw^#-Vwr#kBzbyj-G;O5)CB}Tia(e8D*`4B zjZDU7OU|u!B6l3!f%L|>8Zb=LnrvN73cdLwgoAl=4R*LZuGVDSj@Gs<=*Z{XF}SjL zYI-^qsPch2m=JrL*Na+8p191Hd9x)2+hzGY(sg6`J?pEi`{uW2M8hd#=}K3pmB{Hy z{0VgBp5AHQ7u%?NlM9dVsD~ZbYL5YFu!b&Svb)!mO1uvtnPIYWh9hYlL5cV5hy9*E zU<}@+E^ZO^(YA)8NEQC0fW7KUabT?Db*Vy@q6;?_WU-j^kr3&o?+s;9bek7}k5S`+ zQqKlV$RJd`JHDQIW%a)JeyLBF0A%GRI0GW1NJTLS-R_%el25<;j(eRX#>lYKy0#i& z+Lo75!D@=(X%Bt#-iw|}2}7V}#B+{o&d!Y};zx<=1Ni;aa508@&$5pxw@)G%v{Gze zH_ur5NHvOBmD#sg#Wf8`ch?t zlG~pzM0so9wpWYT*fYQ~-mri-9ohF_&77c)&ojfOcjAbe=~h3( zco@gMTUS#fS!!}xd8yMZ_}K9CLS?uy(PjN!w&CQ1b9m-uJ42FJGcf>1nI(!u%J=Am z?${&Iv4Nye+u)BahPWvUE>R$_3pQf9`*fZ0gk)83lXblSA0!^^+Yy>Q?Fpt?X|cxz zKlsFs!g~|qO5tGUVeZn}9-@rk)gFcGvkJQtz6=o)1Jmfh&ZFtPjAN-``I$&QALbUR z6)&x0Gl#f-WxJ5cxc-eQ_> zgE8fRh)Og7kv=0+Mxy%zKT&4BsR=h17tgJB)_Co1&+-AVQ{VDxGo!9HpF7=hpu*q2 zftQMjPQ~b9mS4Gwc{%#W-MJ32>4w#A<@GO=rj@p;oT=7T8-6(;Lc=hzrlvoWB^eaZ z$cu92X2>Sq|7?(7FzpV5Tz>tJpmryiR;qj@G(Zzayykel~~BT+XW-mJo-qu9%tcN%o5)<)!M8vZ;U5loGf9VUh!Tl7egN} zQG+fLJOeJT(C{PV4Mst_M*3DbqRdcm1qVvfW4q_wb@gn`YH-PK=^gRBEt5HtvVX~4 z1Af%pjrT7`4{uRem}k(u=e>S!)INEXPcYjEq&mxv0G1Q|E0wqYg9YH8&x&HzS)~7J z6-C$9XgHFgP2~$dDc>kIe2t08>jCihf)M11;(^RkipMAjWOl!1-qr|>z>k3u^;9p@ zh*+t5#8W$523D=CCiW2nSTmZ9eAMDCXO9uzW zzX>{^fqz@Q?XY53OTcdNVrqwwBZ)RZpFYf@s$i;W4ZG=mwB-I$r%F={E}%2u?-S$K zRSDj{5v>4%BQJK6G4iohl0&;z-_V)Hi2&pm{2Eh0)2=<}3o@-}6hJ6}$ObS#aPyS( zCSZg+F>b9`vsE*rgsPA#BN82Lb#bqP*>xc)!;|-4DOlwz>93nf!4o_7 zQ33eIp`}IDcdh#oD9WD9mDZ;2%Vi{Dkyp z$PmDpEIhF<9EOyD@be270Wtxy$O0PCu%{aWz7g-QJhAlUg6~;6Z)=E zW>^@br#yLXr^}-9o2R>^9QpAZI4aqW0M1Z>E^5A0c~S{}#Y^9%s%(pd%{8mo|g&Z>R8U$_|Owe66vb8)a)75L2VAg%sO*zBsX`*{WfN)q9O_00r0D= zWRZvv{^Ht%H^5@*rRk#=04cpdjDGS}1`s=-uDpWuggoc?dG0E=)Y#plKE5^krvNx9 zz{kwz$u_~dDMYTtq!NewO<9iC+oN72{dey-tRV*(%kvX|XgJu}ftv=x0z&U*{~!aK z0(>+m5P&n9$xy?@@WJWAKt-%tADQMU9<6IbJh?Q8XX!J$Zvq@0uGZ9IykfK-`shaO7BkrCe0Ih0a<62!(v z*d~?xu?Qa1RrDxrno7yD)6e}QRSnm3{IT*4@hG=`zF(T1OJD~2XGwRqiuhU*cc_#j zcu)4p+ExYn5+HWCW?X_v{;5-@&`0XZU(La0O#7#^8qV^A1t$DS@*KdfWe>2T`U<+b zh7oXWMCnrlv`=sCHyaQW_ZgU=H)rjG9H0L(wxBOYfA2|C2-9gjvCJU|KS3QKXy6xG zDh_2?UWjyFhWF@5xnADIT~kF^?ER@X+;(TRGtfV+<>)QJce06>k1+sbwDP)LWMCwv zHP&>HdPff#snBk5XaQ>7_*F3@37dg(=oKoY+IZgTJ-}X5swx8CJ>8rf5XRuy!4%in zLq|jlryM9B7qB1j^so{RzRjo!^8%xJcxUw#8cAGencQ!pculE>VF3Km*9R!W4e9X= zwo08l|NUp?hSquhf{6GzuO83wb|ayH6V~RP+q3;h8<@w9vC^& z?d(=j;3ZLG%Vun9VYqu1`|hG^WngQ?W&5JJG#{_)5^6V( zBackddOKonhuIo_2&PPy)6mA3;>CI;sgNQ6Nj0`LcUB|!E-z(Q>!P-hq)lv;5N_Hkl};^n-_}x);x7e=&W@uF#KMy zkF?FOR6pwScwg&Ugc@`Mb?0FolqPCiE7JN1*I08i6Uv*ZeZJn-HRj@Gf2h!(aZY*K zq@j=r6T59%O=RDvj8H)9GQla|>*#WI-3IC!;|-rL2PfTq-@(=5dDkNhUjYOM9_|%% z9*nqZUDp1b17Mmh+H)8unuIW9qdY9w?1iQ zAU_$H!0O*pewpC`2jX#0g!T>>>h*219QDs3+$k^l0-jHX9fz~-Pz) z^?;mI>E1*5Wa@D6{Bf8!NLU!e?+J2??K9b1ngeqF!;BEeR?qiuRtVEmA*pip0?N-n zIT;+iO|a>h_6>6OR$r|(JhpO8fC>s`q!!i2y1==CL~%yoL!E` zF#uy0Q;0%9C~m>f3x=jt5oGpJzk)=_98vVinhxv|1_B08M<5T7u)vFkTpZuu-TgF@ zc-OSn(N5dGB#Ze;aA(Vv@e}EAt3BQ(?rGnnXW(9}ujrbx*Q^;uTRp^HPCNwsDc_le zR7K039&8@eBA^QFB3tcZOC6NE_IvH1J0)?{uKVEx7>W7Uyx(!S^y_IB@E|LiG@R0dz!Wf{(h{y33O7 ze1(oT=oOJ?!XtS-n{(#$f8=S({MWjI1K5X$%U68|dLEbbz4p#4yEr~*tjN%fZT^SO zkt^dgwx z;_3i_mFcL zMNgKInNq}e|7AQx8czp{{pSCofcqBi9H$wrLW2`N^!6uRmV!WVFdex>#s#y*hmIRaB7`|z3PZbta9-=f z%lXHeIAaLQO6UOoP<`MdxRuX@-Q_cg(g#jZR#pC%PDT}v^(|L=`JISIF*W;3)8YC? zc(=0xFE19T#|2Sn-;Het)##OqJ3nhsVI^`g^juKq@c{LJNSky{+*yC9)aUFKfBUWR z)zNjqZ^l96QH%`M+s65+It2=j>Zm=a=O?S3YXPqTqmk6+pKxcT)~h=SI;Jht@PyF! z2?mtgi=fv@f`()V6Mpto&)+9SsoBVompP|WPD_-?V{_+h~p z3L3fjYfXB6hZw6|QDuJo>v;6xYB5d6T59?Jp%it!eWNU{5e!g=;4DJP8z-+0ck^Go z2bHoQvE(dxszCxj&-Hr7p7ZftwuX9;k)armXMpoXAov;g`}+vFzy|VZWdp2nd(?X^ z{wotlxTb{tDWt*!r+>gqJE%Mnhv;%C-R7Nuks3;fRk)hd|aB`SJwE?dP&R zgoC=1cVrKG*z38Gtr?))M6HE7$9J2l?#xerl&l}UJp}d`PbO+jG?nQ_=1YOOwy3Gp z88+NqwQ474T$88GDC9@;EXLz-y1cWh2j23cJr)paZ0f>MJ$6G+3-!jn#n#G&-mmPd zih~*KaiJ{Gi296&*hcul4HzU{B%~}RPE!`^C3?2ulAKM{5QtUE!mxuS&d-_Op93-3 z<9zZ@?e=iOwSyyb93m0EI!oa7P3p13{#G;nVBXws*s0%ern~!8eIOS3=UQJ}P1zMh zv>YW-4S1P9#`||q8WKoh2@C80pxK|AI?m@KDiWbGt~cO?1^5&39niGef=($L2^pKd z%g^S+b;3`Ewq(jmDY-a>ddaPF`E^C)lmTA(dU5EL3)Ecr>IA&psRJ#~OEF25YN0iSaDbpsn*_9#S(`R3N z+{GhHJjWr&xIyVkri~hmbuTfj;ddc*qU8Ss=SW&wv0CY?e>Ex~5y+->Yeb8U2Wr2y zhW7fNKDPbrBU_7)*(tuCy>uf^ep%OjGoO((!+@;zi4lo(7JIkAtI)3EKmx@}s+d#$ z`ji7zy~_LguyLT`vat`;HP`G5BKcVVvUqI?{rtvaD$R)%Z6{9RIeH!`E1O(1=MkZv z^9;uEdx;t3Cx>oKwVqNDN={RmulQHdR21Mws#X~tU0BLYtA6(XXKMU!?1}|+&wzo@ zlxx3UO7HXpuNZ#(%HKI+w(-%|dp_9SY8h`TukAW&1!Tr5@W&#<+WH_?yWdh9&1v?JGw0=5U8HJ%8UG@o})f?JLF3->p1@S z7^OXmMqR9P^%EiaIWxhn=`3PxMgBb$D!5j~Zs`gz)BvH@r&XT(`cIQ7ep!`gIYI$BW)<(X`LRr})9>3{PC_uoJw&tnOA){+~kDeXL>2xD`+BitV zrSDDQbglRLx2)iK4$mB{TvstoI<@*sZpFb63o;gF2-{JJQh}&A@j+n>;g*}9>*4IS zeFt0nY+JCP{)=Jq0Yf3FR9^11nRBp^ljj3!iG^e?NF0Flsmce}!3frjS?nIKMfv?P zF*$;z1o4h`7Ri^A8l*^O$I)o`r&Sjcf>%d&F@F={6g~KfT}wGA1a~w!W1Bmm%6IZ8RyI1RPt#uL zjlQhJJ9|OuaDjArE~|Cws(c+?RtbrS6al|lg{J;C*fj5B%^=UID(j;ub~MrBcDC`; zCRG|+L5KmL+ATsJ3~ZO!zwO!``dUF#gdGR?)>So@TL1hxAP&2-iv2aEB1DK#JrMPO zfomY^et6dZz_n4rG)4ZGVSBt0Z-!BN9`tC^HDB62T>H9O3|itzM3CwN^z&s(VM6T02>IkmG8`OFOH+e#=_v|`X46l&{6Tua*L0q@?^2z zq_1|_LojK#<#pB*VPKm_Ao8t=hZ@J(k81s{`YgTgKhJ`@j&1CEBUt(71 zZlu*J9JwOA##4aVs3^P$%Tj!a#yO8AS6RLmWNo` z#mi({^YCPa?9r%eE7nK0&WosRu396_EX@qMv6C-+dif{>6MckNTY1eqNYJQDfpkIZ z?#Y!NcQrg|W8D+laCERMaNd@(Nxf#c@qKDV{3C`=P!ZzYd%u~V*Y_7QwnSnI~da%HrDpw9wklPIcu zX_=|w#lc%6Ke+(%up#^rg>b$${{H%8jIlUKG~#6Biw_beG;@PcE7DKO_9c0kv2h3M zyL)0`L>$%A6E=591DA7we=_-b0A2wGTt!VFmJ>0%ulkn*AOoG+5j&Ad-sx3V!zH_G zI=4JF3H-YKBLc|I8C0OBa^Jc^cPZvry+uDK8>*;&wqIoklkQPZ-77_<8SK@mz6tAv zmALRPsJ!)v;DJUSGgTmd2%eDrm|e*gsQCrpJ(QVrH5w-$0M@my4YZ|wcd?86S6LY( z(+Xvj07z&g$YXE5DZu|xy&r~v>mB}k4K*Ug2?HP9F)O0TGQ~tHMAAH)LUE?tGt)>l zG?f%cW~Su2hM0zaSC$poQWoQ;{YPV%l70QaY9~Y83@Pq!uzo#pqauIDsLs{5-&GJz zJ`wfuea`>udpMT9qZkF?#s5Dj8j#2@A4m_Q^}jG_CiEbZ8{cSgN1j${2zEVkV8qurOKgX49J% z6Paq||1v3FKt)N)WL`&6qGkPagzN!sWn?stOjdMwUy;S3*->5gWE}(B&;0@LoUnRv zK8277`9A?CrWg>X&+X5Q#aoe{nM`AutPj900nXH4sqII(OMyxsgu{#V01_7acMH#U zjRYdQluBX(eE-mB+7YY$PtcegPz6s#Ig(lk&-w%z@1QAw$YA(@$t&{UoBRjJn@4_e z4_pyT1Hge&GBU!2pNH!dY@EUIpK$-7FH66th2ljZ=K(rh0N~AP12?!*s3p@#rYIeN z&t~C78n~_$6Q=Gmh4IS&fsO%B(2UR~b z0KWh1gk{jv1@eI>G86jyG$Nt^5pDjmi#`%6=Q{E!3>{rtP0*ERD8 zwC0&)T1-IhK4JOn($mUk%N@Hm0$59*pvi51!3wf!=f7;TL#6ad0|VHP?qR*E&=Z#s zkqe3-NzH%TvJF%ctUA>bSBaT>?xE0#+Q(N$6hGNm%l~WcC~?N&P^OWz9dcI&PkK#_ zi|nYy50#K0PPC_8HZ1+`A#xkj_!8W`{ExhG7FrrUnp&UknIo#n1ZWVeJw5OLE9hpa z@W1DFCcE=eG6et&xh6Sg)mIQh{7EDUS6U;kKhsX{$vUbkEua+5Q3^U&x3+`?wwgj4 zYw-b8Iiif(rl+7oMkOB3YeawqOjaP^{f-Kx_Uf6Z{_JC1?3@gZFUzdqn>&ju6>>-F zgTxtd_HvLIn;_JhL)T}~I^I+)6wDody*k%8`J>$OZshZXdJHAy`Fe(b3?a{Na7+as zHF`}@cc%I{Q41XoKwi7SWz~^BQM26DKuZkqFoN;DjK?Pg4Cd}wwpscuL10$KPr}I= z!r7;K+Rt@)TzgM_09s+c5#v6Bi^wgH>rdrQqgk&i+3}hdc0J0zKor)@w?nZOzIff& zDbT*?-d>%^k<#C*?Qy%HweVm-Xzm=RztWyI6PQV--P{2^5UWIH$O%7j5dcu-KqD%q z8QgcZPXU8Ic$j91fC0`W&j=i9aGRkc*|!~aFdFV$XBDsT<3C9@62*FQbg)WgJ-o|E zAJJ~?)ial4YBxD0>gO>);nco_ixNTVO zQQ+aCi~inTrvCa<6P-;DGEY7BH0{r2w&;-g3pgn?*xJVOL(0DEr7E+_w|;1@9K9LKDlhwy zv3VcPyF1JFa1mHz@%i%>-;LTw$Z5IhbxOlgZ=gp-)e8>3xE4CyX7WKY@n0yc$m$m> zs|^hfRQ$+&Y(Brwz^Pt#rcTT^(Iu06zryH8B+|Ra)nv2Xv-gh7Xr zIUZ%@Ofp+-Y54_F{ZsbCzleJ(RLoqp;)PrI6ZQu(Kcy7-{)#)x5Fp)*sQLd#x*5Em zRsc}D31Lb7zsTV&IDrcyKBcqbr$WQ$Ze8JD`T67A{=oRAUcOV;jTj{Pe(LBLrQdDs zak~ESDtG5Ta4*A9e!fWS)E|kfVE;dnxro7ne4}pJ!a%3fHmVERgrY zr0wH5TjD6*aR)FYxBa2Zb@kxj1u??j*ZK%;eKq!#g%{65olC!syvUXRDz@1dU<-?S zHN}<@oZ-=*XoA#WtIb&*<2q>jz=WCq{V7B0_iv_M4VFmBPX#F=fVKv&ZZ>^`>FjD& zl12Jv8V&gW4MJsq%%4D(n)LF@I7Sq|4CECY3o9D_z--A86U-6M!FY^HL@EK73Wg-J zm|A5GU&Bt1xb~0Ww?^WBp1Bk7JEG6tqSC#~hi`%w>#GF#R)gggALm4ZamyzP4N9`m zn9}m^n#vM4eEG06dWJ3syrP#Y`sOj+-mrw%gL%kH#kAY++u~1-)&Tr6-m+3S>bkYP zz{#Ajp-x;y!FQwQZL;>zqE_LI#c{`EC0Ozn@26*F99p05(&U;0b1h|SqrM*JyqnXT z!LC#3jsxB2l-pyCe{LTln0mC2Un}8T(OQ2XXrX1moFDvohWm}&(D?kv=2wW9@SxK` z%a9I50NvEf8aOLxPK5SF@)dhtny_Pub8v41$d<7T8 zI){TGVN$aJJG`dok9ifaUuyO!4#Al&+XkIQUlk^}hK*MRGdIV&(rXpz05X-WKY9Zg zQU6vy>y(6Lb8RguS`oxN!=THgj%}&+S2p`9ruk&sUs5({l6NP;XzJQnWO$?!oK{EK zDz2EQf>Dx5ZXHS7Cyo`sEc^1->*!Q)vQB(wAwPhQW#`@>Wj%EHrgSzVtCCQyl40ds z9n?CuLWH`HJv03+oV-VLf9$EYJT)q$A2Tt8R>{a}kCup{X)``k_Vu1xRFXKbOftCy z!MrL)wih-dk_->ssuP+Qf-i0N+eOJy=F)sC7}NRDCpz0X%a(fQ6f#kM^q34d zXB=I_7^ds!@bgN9aYS4);V0R2dg&YW`J{=o8dAn*(L`W7A~EGi6|ZOV`Q?&&3eq}^ zeT-bII|p7FFx;Z^z@a31n33!tYL?U6h={Ex(w&lklYul&aDc?e>>!uF;phCsym#e7 zZRkX)Fk6anMHZoliE#DZ9SVxl#jwyS20KxP_+fn9`)3>CdE5WZ1vp2t z6iea8EqtTin^c<~SKkumi*_1cb{XcwSw`ad?Ij+Tm3#Uu-&I`wq#q3{NrrTW$})eu z1()w~tAD5`%EFp|&+N9{yrsZ+4(|iP?$upf^I-UD7REE$k!fTPOK@HiO1+0LzS%1kkD3lz)v%^nwxyvU9DTH#}uF=QzBOs7qSNZ3_`C4oPxT)dKQ z#uShEQ8wqdlBNe-m=^aP_@(|P7U{R=F=-L-*kxh2Ng11X<&bfIYVpcn(`Fz0?_HT6 z6B<)Wh3R+Rf=!vfMT{G@Exz>U^$%30(`cK; zGEVCd)(m+?N}$k;sjqV^g`VptxC>c*wcn?LPgAQ|hle}bo>2Z_q>%wW;mgPDP5iFf z#vj*~3(6*zd#yuGa1t9~LIc|bW(LOvDn>jj-^>tf%0UCV*`q&BQ_}W6g^URTaxEYF zG^xv7a$73S0s%~^m>C;e^+{ZO+XcvZBI1NW{m=D_y0O+9LCr=c6;M!d789#*IQUj9fI9){AhW$M{a*7Bu$3z}RImJe~$M&P{MmM}%Z$c}{fFF|7UMmMfMz4H?m(-LLN zMlhB`HZvLXfJLsTt?C5(#VFdsj59L((KJ1@Jnc#r*B;%Yft9$z8+$nW1mh*toqiSH zs(%n z*k?|qM#~x_q39?ya&Xk>^`RB5&g_P3Sq*1B78@+uohQNxN2g(tuI|0x(Gx|sJ?B5P zjtH5a@mEOdR3$G$K^eo?5WPcpru*bHmmtsb5N^-b`^ouc4tpnC=}}s{=s97BsYXFm z%zP22`o_W)Bnnvm;U``=sJsDA$1;m4o~R1q%xS-MS= zI(*knFeLoI==Oq{`ucW!?XDhWQfD@8GS90w8|ucsv-jCeTR72wwP_usn=T*O<@VZr zeNDbo;6Um~zC!#S@6-;i@jOWZdnNb!TJSt?O4^yjU-x*3v5|v*aR1+Wdy5Zbl zOlrNFrg?Vd-!YP}YbvcpOXS=T{N)jS0~7<@I2UtWT1+j*7jDO%Oc(EF(}1W7!k=5? zS|8t)8bfA@_b_xQ&;4i0L%Q>i9OOPf0aZ?%1J-iGs>*joe|jOda*~n)>ysSoMy8~v zv6IpMr#z3p`sf+ydDck*$JiwlXls%EI|z+fvAcH;)V~k3j&yQ=Mau8owz2AKTM78P z1u7rC$e?sAxeAMLI>e&ThlN>Zxf4GEH2rW?@QoxO?Ui#*7J&kJ%JVoni_v5IbxNwN zM0VGaw~Ybso*d&AV5lH4$JxDsz>*8jH#sSV^ z(=mx?g7ueoxPL;fzdX70Xd(Ipz>G(04AD>7s;8+QW5E*O8Q7>I8y%hI)1^_K+!jT0 zF>!Hy$gCr(wl7fG{gh_Y{RZ&b73*D#*Q#elfi43yysp8JKx)eK)F)dipQTq#Y-h1D zIp-hV_!RLIP+c>d-PMIR9wCwgU!F*eV_IIlq;xNlw#P2QIaQQ{N%{8!7~`X zdk&k>0vY(}N|I^0Proa=D;fgi96SMnonI$iqdUwif+p4&Kc#W+1wAFE0$L> zC;t5vm7`P#9L&Sg*?pik8HNnZF@OXB&ie>hT^&bG5079>l14or$Y3UvKpCOW%`RB@SfmN!Co429^UVe3z z?1+5xK;S-6L-u7+Cdz&1v-jwYZ2Bmq6%$G=6p-ZE)!D4EuLbKczc!@AI$YZSsux=c z{5V`}lb)%bwO&Yz-GT?d5~CB9r$Y5)Adll~xf4fzl9;!DRJ*yW$){aW z#N}RU*E^`I=NIl5XG_HiH&tqT5ec zm^wRQzFfivFt3lA?S0PtD+nA;x$Vif&W8rDpsRedw4?*ZOEhR)OPXluvn6VNWAqrI z$MiKc_qVMgHhb!G=W9i0sBB*NjZ z=vCe`=?g18cgznmb&#^v8U75m$i|kibu$uH*{}2_ivg~(9&Xf1+_(nM2Jb<~r@yL< z^|KM^Y9qv7X!fEt)9am{CAb=X;Z8KHJ;}f2{gWSe$3=cTlHGBawohGZM$JSd>Qsyd zLRp%E)fuNu#cBKbV0dxUFF=wylq60MAqmmzb_#K|Jid)$LQ}-=DVx_Q+-DVYo9^(S z#&yqp;r|G41e*#QKLj-5=(n0UM%OQjm1YobE?kGX8ZcHo%t$rqQW0I_g3G*^$$`qA z(@V2?nJ0Xf-}v+*p1;!|XJ=v>pKZg!3va3-&+ ze@YPRdfj9N^*g3?GoP%&atQUpbIn&R@8Zg$#b%L%W+3qn-kqe|1P4opQW+HuufGXI z(dpL46?^6P-y9ms&NRdv=H9h*C|uI~w4k%B+4TK_`pxLGqLH3sPVB-V#eG7V0OZVC zi_>&yRl!z;7$jTMt*|IX_Mw|MjKGsW%~!T2m01?AdD&H)STOxAs;fRx>UP_hETuGH zjwa^%IOISJdtG!6ZS{KPC8F!}^xAr%;Yh`*dNRZ($4o5M47QS>0HTC1rMU~mC#w(o z3Zfrm>0HrlkB8-!Hasgta%Oc}{k^X(8~b96(+Jg8qBXgr zlXvIa-0@5^vL(NiQJbOnW35zJEDt*h}QaFg37ad95|y+7ZIid3?}cWkgzT%Z3<&8g^I2IE%g{5&35G_3oin z>kjr3%Af;xk-cyq_(bSZ>+<1ENh!#k7X6>ZmfT;@k5=aA2FGMk08h^USFVrtk{j-t zj?a`3J(t36A$7xU<9m3k4s+JEqQhlKL!`zcjrlm1H!G=qN3*Db@l18*!YrKp8ZpC) z0Qdf)=Gt$Hevnyz^X%ATeqX&f;J`I_ur>v_3o?i5~xhpeiXwNk>YyVkl3g1PpCE(XcR*aC`O>DP4)F# z%JcNUYUpkHs>Qv#lCyGOl9J4-JayGGdcDp15KX%D;8_(W=YVf_= zRZ25jk94%|o4*NpJnFk4K94|SlLiU0Fn8~AOwyIA%X!=a{ zrLG(L{q4msxuX`rlsk>+q4xW9H4lg%sn~&#k<}-UU5d*`Q{wh?Pp-B=j7{B1 z-9F<@w3Q#DR0ULoc$naKYyI<`y^Ct#FLqn^H1&9=`>96N_^ItGoH_=vM&-sGMiFa~*+`!m3-u{`<8wgIOjE9ByBfMg-EE8j@y(4luD zj%f4A_Vx`bdf}D#m(?PHyDz4c7I}PR__Zls#xs@VU&~F1)oHvzJhr5;rE=nu9OqBx z69fDl8^;q{gr9`(g-D4qcA8|T_Tq<)v_E@QSFq$gR!oeyBQ!6Cnafc4;&Y3AL>9 zr%Ja~wW)Cw##I31&Grg$4cjm|GKSD3odD|Tg6D^4Ozt|ZOc32qC=5eZJdulgOId`_ zvbXo-+}ZFGA1EnjqhEiAWAr=s3{vyR<1o7^DV$0clR~6SG_CAuDl{*+7K8R>6!`}Hpaoj8Ea4cuG8|pbM9CG ziaWD)y!PnQ@COQ!pr)i$>FGA^;eZ^8KcIzyt|^n_@z!fEV5>>>3vWD!zI856`EeZz z_GzLh@-Dqlvf-3USnMUmhfoa}MKvx7&+&PUwoFz!t@a=(40(;3&vEZKd$j%NSxg9R zBaw9|>8m-fmib2RU{tr&tJS@AyI^2B7v69;hVbcHIrRe(g68#lMPw4UH7O8a^Q+$P zTOxk!xIXqt^p4)Ia5>#4my{Y<@`mT}fQng zU_@b4iRlFq0-o;z&XqGQVG!Z9yzxh1I@xoX7x3vG;qEiJ$J-SpM{V&I($5|@=4*~} z>uUU3S;opq+eJMnCks~@K< zyi!h>V;-!T2s`x9B21d^VK(mgx=#Hb@m)~Hwbn0LghcLIo^v_rZ@Xcumunqo+x*Su zhFg=1?zhF3SXfxNbwNJ?wX^2pQlRee9H=*t57D{q(o~f6zJawiS2!5_s5`X6#qPXJhw22?cKq82fZAkc~<&jWGr&T zF$g|bc=P3;CH4>VOT}ETJHo8swSB~T`){<{MvI4w$7;3&_>bm#Ir`Lt4iATMc~>^} z=FAPpU+TC9jR*FmWC@a_kIf&~N8-6j)QP`dE3gS#d&NF572+Ix?Hvn7yxfJHx-YnZ z;3h&3R+2b03SgawTj=L{GGrjl&HOHf&Kws0*H@4e zICGvnZ8wy(z3?MvlhV6gjKqhV!1l(|SAxD6APjjsNU?#T6Kb2dmaI9{U_@=uXyr_e zVAe=LAp=*nZhrX|QVtrP4NGf`^nwU>G*7_cnCx{L+vi&UovJxz^o-tM-$;u?qszFDG@fw;YjrI z{B_hK{RzSmL_c5Y85TE=l5RMEbI&u&#n3pJLHlL+6C$aHl=GqYXDpb2?`X36PZ@Wj z9H!NLvCwJNv9wRn6L_1bGBb>?Geh~V>ndJinoa9{RjSbs_tsVdOa$0NIifG7FNI-~ zqm%Xr_i56QO6=Jxe(eIMBOE0v>T5?tIR0l!rI`m^G$S8z~wS!_wjn1AUx&~NS8qkP!anT&O$2%sD_cc>4b zUL!4!7-ns}&U1rkY4B{k73!z+bRG|<($xn&9oxG)hCB^JKD&NSE21tI^mjFp@PlpS z3`Hj#q?VbIbkmyL(Q*uKRcP-}5afJ{w#R2$8<>cv54S#j6T7t}eJNb~KNx%KsH(!R zTNn$Zr9nzsI;Bgx5s>cg?go+W?odj)yQI6j4jj7c0Egz=_`C0WV~l&p=NSIw@tkMx zr`DQtt~H^D_?{%f%@2M3jH|=f({K)*?*jIcKYTS7O%*rXvIZB9^Kae@G*t4m;A;9M zl6p})5SR}Bu487FrE6q?D((FU!_U<;pL>=Xd$^?swV#q;qZ0JI3mE&Y8IGYTt|4L( zRZO1$ixaqwp2osMG9oU1k^f`gX}0#oeiz@}iTl4m9R#urTe0_J7?Q4 zYo8k%O5z7s?CHBGy~|a}1^KN}T=&wOb@!(R-n3y`&jg)GmyG51&ARhp`E^m5lrj_7 zzyk$PGDRyRG+KJ=fkJ@AbH_;R`3!5-27k0;+`8ZmcC3bka-8CtxwiybZ1F#xdK6$M zjwZM&aX?+u00$7`iiQuQA)(P!4D4YA#`@%f@SbzF{b)K_raU_r2XvBoF zT3(2+qaEL4aSuJo)_+@qc0>j1687_DhN&?_R9zA>hQ>tlxZMH%{{RDMrwW8+v9St( z;wLVyTID4o#=7_!mxX`}WP-rIDk>7!nU(E+w*#K@N8;JdPKu9q&%7gg;~zs#pWfv~ zRWCclwVhD5O=%OEM**RG_FtT2!3AyilN)cLM&=$UuG-J|@?O{MsL!Uz$yw8pDNMQ< zO`bQN+8_0C)&|_qlkJs*-^t)YKcaEyh|P;Nm8L$zLr{8HF2hi6Hq~3I9mXOAZtR-^ z1{NsaHdZfGa^aUUzr9bXyy-&+sKMll_6=1{RH2J0>X2jk?DepM0_LjNcFeMewAAp? zOS6;cD$j9dsP7C{rE2YSyVFS8_{O8G`6@52BS>ZL)L!r#*~2JB-st~w>1f{GrIRYw z04eZQC=Dr)3q;WX^kX_%t)eGP2>_8vm z1Ph{jg|=^*gRE`|l}w+yN>O*?ZDHp0G-{7K-=W~BrP)6jj_W^d85a27ps#V$v4tIW zM~<)d1S()PxbtO@?b;@drS$ga7g^{*7__b@2rp~X{n)iUPq&YJPI*9hd~gq%Q>SCo z5>ln>fij(!jgR`}59=5^5s!@1uVmWaa#)Lp|Bbh*UDup^YMG+3q!92rr)oi1fnZL8 zy-wO5tw`xAyP0TCm1#+J^6SX+8Gx>!3&$h?#vdCWUk2Q=d9W`sHS+~toVUd^)nKN7 z*yJVXzp+WqM346`&_QgxQcQOL>0tQ&w5#8I-$X?R^jdqFg5qlOBe7y(LPgNX;NYaB z9U2;=w1mVAv?@g6%|=n!%sYSQ;UBjUx&7PXm;{8xghpBm0tyPCtsTD1`maez<7&=Mn}zvF+os5lHUQqi$tUK?kxE$?)|Ue4mXg%alJMLq7SI_@ zQaKhm9q6<7T|u8jJvBA2z=n+R6edXem27ytn$@aB9Xcj~jNLb;r&q81_Wvwff@lkx zpiyZlt^f#fKQ*N&DRq#G5u#{G9fFBg^!P&U&)5QcC4bo4tZX1i%0KV>fP$is%8n1a z^@`wqPt?z#AbpnXEe-vvfdb^iy-C*n#s&_gfFD1+Tnh5zVylAZ?5*v&2@`E9+$%D6 zKs?2sAOLNB0+gFGVgUOja)A93cU~z0ThcG-&TJi1LMo6T3ccQTO)5AlGbA(;a&2cp z*v+{!Rbu?`_$I`1I%*VuzJ`M=v+|5G(Wb;*fPJ*h_4|Blc!9 zm+>3^8$U6?0stu)u-y-Mw7=a(e}C!fib9ZMzxmA;H6LV#hS&S_c+X6ne;^0Z;bVh> z?0F$TW%gBgA%ITeuTb%z125%GV@121qy5P!x6wjFB$Qu} zaEa9|F8*<#iwuQm|BeGtyBiz-O`TIoODiHeT0Ss3b#x~l!FlT&@Ff$#GY*_jX~Zci z)$#-X@$uzk&a(l!8+O?=9NuWrU>m%vq{P#c|J<_Drf+P?HGZw z2YmBvVL{Nb*B;}omv@%LrV5ePQv z4OU=Z49X8gL}SmCGJ23CdMq2NLNUiv!Zcu^aVc0fd3YE znjranLps@R-52$IjiIpb%q62@xnhyMb0=5CnOPE?`n)i5xhu}%>wO*|1zY~ z0D?b|NZ6tOz|rC8om}(2q#E)AWvbo%2O4qS)MH=l3Rd=T7i$0c$|D0QWn|7Fn&f#^ z0|yG7>B^hj6zh%@pofFx#Lj-}?bG`#gtU?LWR41FUxhXdeKXKk$5Z+%l6qF80NB>&s`K-=Z{HfQ%!c~Ph#b7_W*Pt*T+WXXK0wAzG#YGj$JO5Kz(*Xpv~-biQEzKP zwzszS-Uf$+z`U^F7KpClD$1fmp+(latp6cG` z{%1pnl!>qgcCVmbFut4pmT2u~fm~6|+pBS{G}HrGM0`K^=lc1JiI_y*r(U)8{cFDnKS9!E z3WAknvdnDVtgm76wnSbV7E5>Oejm6|txyep^_{O_VA)(^*dgjf&($%A;*ln1rQ?H- z=a@EIC6bnB`_Jg|YhJJ>n4PrsYC?2+uTLcVEvhEC+pX1& z^M<#(j93U2srPT6FTRG+Q0J3y^U7R$q0k`U@kPIT`xbqzfDnJau#(Xb6)c;k@+_D? zrb=%i4#)5@=jw#%1Rbe2)mWZvW&LkqwVe&{Yz7y5DamSc#K8| zV%kxe?q*fpk7wuIHdZLr2wGD3?(q2K%)2O1`Gz6#t1{88*?0mL2^uF5pKBk>3^`m3EH&9*7 z(6Xac6^#s6IAM*GjdbWvWv&@9B9)B3BZOqd-6xz($tc$^Qn$V5z9h||H{NxUY9zis z?R~_)jN`nEN*-3Cjb(;IQM}=)l*$q7fd%-w4nbC5KHS4-lWi}y!`%mF;;$svGvT4y}i9^!Ai47q;}9k%CJs*u(YAI;Onwex$SW( zY{+5#uUczO?mvIcny-#Fe2x(~s}%?H&|)J|(oM2ev>Z-n>D=6Ce9?L+Y!M^D2 z%vwHB3ObJi#J-68fQZD%#;riaE;O}7(fhXkk4 zXMXHFo%IKOzla>DP6`fYt&Fi-hOEqWR;;v9()okGYt@={y@;?J8m!9bPT7z?g&k&j z$4sLxHsL*=!Q^Z;f`SLJ{UZ4=396gEcJ?v48)|$ktMK+;mU-SB9A7hXfX+8kFrQ73 zq&|f59k?TDXv7>6zwN=Kca%*vc>XRWp?^;j zefijnd()yjAKQJR^*+LS1blnQ+|Y1?hJ6Be=n{MU(*zsJi*+*oiI`{fxbCo`sG%!0 zi2pRF37T|=F7Yw{w38_Up#yaoE~!ud(4?4O@nc>$e>ax*Z@%nEVWG#VAxUBXyaeFH zbaRt40n(tC)HtKH2WYB;7V9AhfM60=XIdhE>PYj8XUcs%h{-(d9d^Q{})=(mqok9Q@dI@LC! zlwa>Q_Cabr)pdd|cheeM$vkqso6Iv8OnlVW?BF4R=7S_5H*fh`fPgBNp&yMf{<2NY{ zg{72?m8`1B7E;%Y6&F)I#F9^zUrLhbH-Z;CVox})8DJ`drWux!Telc*OwOfL9-I7{ zhFL1>n<9oc!qlJU5L-DcnTJ&?Om1zT`x`n66un;Cc7FtAvHQDQ>2%=00Ub^Y%xxi$ zAhq%q(+~94er4|hPVl6>=Ehqedp!^$3|q~p$y_PoDIdP-I|*<%J(*k`%$Cx${h$X@?07M*k`&5lD;j@Ndsz8`IHuRPMu#d06SQ>CdN`3(Wj?aouD*6jn! z#qe51x()KBNy0r677mW#_u9HBj{maj3&*^X z)&Q+azQ#;>yWe)o|EX{~p&{+4RO7xnlnDjPFYAx9vbd2d`P?MT?7$J82k9a zS;VtX>bA~A5GsgGrzLflFKm|fL`FO&Rd~Ce+*G;U>HN8jerz|2)(1RkPJDL!H@S(j zc_XN18|zeJr$UR#!StdJkrmZ*MrgjD>g+oQoTaaNFzXX6HwVj`v8ni<{ajB{iy_Sy z6guO+fy_!-V6YdWJ|W|_K<-JtW(+*jXNJ$OJXu#VsiN!nQhs<|Of*teMfpTCN00u+ z`!Jf?&^BfmpgGsvkr&)hvC?dfk3r?*(Br}Za(lx(IT_4*I>UDKpCrW=RFVXCAk^4b zzAkx%Cjgmp)NkcIumB(?EGwmVx|yWT+UCyZJEQ6D&{fx_`;!)+6^~=Z7xkr+g~!Of zf}}FVthqQVH6Yb|RfY;EbG}F&Yl@1<6{5b@0wYFQW zoByEAkn#$+RmqKyY0!C`i`W(?T2^o#l6?^`6!-PY=2253bS-P1U7Ydx+1 z%?2im+&zcw%6#~T_*Y}vBW^eR1#IqN@>vIRFnX8|-7E4`XWJEr3z`NLwb}yZjr*{$ zb?^?p{n(|Z7bT~xw$mur+dQvmBbP5X(^_o6D`p*2r(pD{_`-|MEn>B*8W^Q-n1#9? zh^{CnA`-_(nx7O+fNa|9a#H*)99(>Q`Y=7mnv9p1*W$bPCN+36lmKo7*?AJlX1!Nk zY)8C+-0-XwVxVSVlzD8MeKDZZNdS%{~n$)Y{I8NiiLiitoWc!z+>u5NkOtxK4EDoB9Ap!mvxy@aK<2dD9Nf_37I9mw7F~fN2YD8CUE|C2R)z zZ#B)#xeF+4m+(e*+x)!RY=74B_Xgv)a`TL?W-UAIaTJ1OcKegF)-!JzJXRlYpWPo^ z?iQ0Sz)HC(sVYBSHA=Cl)j06XJ-ME5P0K@i0_LYkAUGiWFR78DCl(_siNt4HC61pt zf$|<7Fc(o1`Huu@MkbT2mNqEZa9Xxu$zi$G81c0Io&m7H0sJLi`tyU_q1x=$Ag=)z zB8x?u;AxGxtN22CO8^pv0hoTAhAIg5E?_E91Omh;bF2}=o|_}91Rh1_{A%FK25BWkFQ2+1TEm?@xLh3&Ugc8)@*hWfP^t*VH^S~pjn@9B3n$` zC8Sr7)R}}k_v_Xq=EWAf*|U$JBKjZG6}R)$Z9fOC_;0VWN9H^tc2*@s8~@aeBp5+Ja*aMEM<-rpVWgPS6f}6d-{A$17|FD*2MI77hoOq+6v74vpT7*iJ}p~ zwb~{4t7K>TipOkvFiPd1O?9|7TQ!N|a4J)3)Po*=kpJS5&k7S#83{EO0Jb@2&jkaV zYO@Fs1r5aVD#zaGB%~DxD$*FSq{1V;H+p{Z{>f%>bPS%M5l1wo+1%Y7&$?U%U{Rp6 z--@M`vLM9A=>-8CbFYwO=vE>zUw0^sfeR2_Ih`~{0bgpK?q-PV>aB>=@16c;D|G^= zzII*MD?(u%$~tvwvTIs-wq-$qjbn&^r_|K1E%@#9-t8hxZiHO6&>S=Xp8Qx1UpJ^kn|sinWe5+?#Jqf493Te@?gKJzTre?1YeO5a}SBH=@9M zh*-pjJz1p56jaxd$>w+FFBz1EQxxry(8;RC0wF80$_ROO4$2Qz=;i<9c@~c&%)GgIK1{Iid2*sXS19 zfk!KDj(Rt97m+BZ8}8U(zCDy};<>sI~g{SkWHT)Yifg6{x$4610-qnp+CXVe4IB|nC zme5p;ex_x867qVS?kCm^h~|=%Zp+cTAs^p8Z^|DnpphEXpUi-GMaIh!TTbRJ+u_i9 zPtD%UpPe1yEj8Zks0-cTthv&Y@uP`7w$DxSj>)9_@vjQ(33Z880?Uu7dC0m=2ym$`kisdMF^1aWjY(4f2|f?CI+>U;(!Dh#H-V6+i#T z(=|SyTp3KFGJjNNrBNpo}#VQE(xT_so>Y~p$jQy zHm&-cO8nVUcHcfU!J#l&?KuOsKM5s4F8a8X$`V8NfJ_UyEWDDxh~8iYD#(MO7K(LE-M-aVYlxSgq%J7 zxN=-^amVOnyr+M@Lad+G88Bw43;L6x2!Fph_m zA#eUtY+B3tQgX_A=TT&p12$zz6~^&F`2SsLKw1|DoC8I}yf}o#kF_)J5MJc`U(J>a z2*a_*HXC{o_hKeu`+k8>4#Xp>hbjWBsYLTyy9LN7Q4ncgAq9*)-m5jZd;u))ZrG14 z+!7R3i=?VO2o{r+{VM?7yfHu_NoXg;#Jta8QUrV-;}n0z#Tmf-hpU4&TRJHI7gMLA zqHa)g`@OO3zlpjwO7&8eJ7msuS^T;9hh+nV3rHIud8|jT5eu0318}{b*P72ig&;`B z<|-r_%}xS!e59mQFZ*H!3y=*Su1RI)0T+$(cQpxs5hyBJ9vJ5F11kzn|GwNB3k3=m z-oAswAi#|96@;<7#HdY!h5-a&F6B-eWvYzHQoVeR_5E90R6w#jq>#8(r1WxTIvl(_ zkM*ujRA+gyL{a=dx{ZRu$oRx`x(~Tl{z$^iOl^@{0eSKNKbt4Q`<=qwftQM0@a3+N zP=2vQ019&8;X?s76(CV#H98$%{l4#le;grqj(<6+yA`^wk2UuvsxX+V>_J3wWrn!@ z9b*|CzA*OIOI7Zh9@i#$7}%h^DeEt%{V)9F!3%AK77d&oN7o;0QFG;hq67e@Fs72k z5&q*@m|96# zSc;t_5zDZsUz9NaPm)hU_WZl#!O!fM*gSSg=w&^S%PSi>T%a>Xi{x1pVg3<<4SaqW zNFe5L$blWtZ*iDEf7}(QY5TKtO-*ZL*{sz!|MZi6i2?VtNkvz>UccT?KI9CfzRULXh-7kEnoA2lv0KnIx z147Kl(OPDV8;U0d25ubJmd>>G0i$Di;){5$EYuRLgC{efLoaTYR^g z&@dKeq40exm_75T0==$tv~E{*mLXM%p2XC|4$n1+X3pbkMCSaN_fHVkMXY1?KLX=z zo>Uwtmi>>!@&#-}7VxE>ULAPs8JJusT#t6S>_mds^$r`3AQp+|98>`ir zZ?SZ;TVt%<*-5!|yR_w3Mw?>W^YL*pZSF%GbbX>1OQ4GAxWdne#5IKBs(t%1a``8>J2@%Mg~uK32<{!7@+ZV!Pdl_iN$&NC68=dGT@(N_OChWh-T zSJthn>W@dg0eVxG(|mOqIsRm-yP#%IFt-cDH+zJF$K^9eHd>JGpfT^$8Y?vekE!jq z#$(Su-v_w%w!4WblTOesjfcEX79PaKekUfW?gDjSKy$dz)@w9tx*U9t|NC6>IdUA7 z+NJaizX^esQ(lC8<&n7Gffw_Nk%HojJE(dwAPNxlJ3?DRQrLc!`%^}|8ODSD{cN(# zxZ|&2ieBr^ZQCyJqwohMWM_NSa+TMO%w@8*1vo>66>?{=qvFu3S)euMo3Kk%F63-% zNbybV1vk!X|F45_mQ$$c^uRN5EA~+MVC%&pQ~RaZs`v+hv#%=T{rUs&imyI{nlchz z6U%v?5tScefAg?qyi0x>8&K~V(CpXu(0e_e2^K$?LF47+d#qG7ANyjcvpXb#7+8du z!V8w(DKPqG0RPK5n`Fgh_|wLls8)*(BUP60>EjF+TgwNS%E^NbxJLWiZZBRN7Czk; z|31gHjp<0R*2Tj&^f#*&Xe-XR9L~1^4g8N`b*r|8N;zM5rsQuAvMIH=JwDKv`PEUM z6Q(5{4<|MyoZCKpwJ+3k1Mk=@j0y_!n!2JIfxFfg9ryJ#)TAZSZ|S0a)dvD|#aP+q z?ybjV{IzkJ-MLND>uOJaQPI0R_8m|A8fq%M1IvKL+S6)bv!58xFGo#382p&dbyVl` zA|}d}qX7X z$!2LO>0ue_T;qgl0y-?M&nNUJSB{6y(T8oEvEWN46WEM_> zBWiJ0x=w#8*H=oEyyIP!WKH1q;KtKCGWf@RXUg^m{M#=s)(Vw2@S4`EcvG{CH;zu= zn~q1~0EG6PeJU!*&1Ibv-=Rt$G;(1&WMt02ySz2V=iS=HMzH1Qq33`G-TT0hs(A;K z3XQnHYFV%IOU#|Xi0v`Ws9b5|`F=a};6|pWJHv6qhSE>8@+_6Au&jQ{UFFs-BqV`9 zHJVkEb{{%zd5{#NKKj*ch>>UqvC@IMivtg-f2CX@s_0W9nWos1B2m4Gk_tNRsAQX; zCO|C)mA<)g)myp-C>#E7uQ^Uhzo;kmp8R-iV7U334|6fRyj%ou)~PD;P)6}%{Nu=- z`HDz#(~dh+nTDE$HJKVPd_*$`dwn&s|LGuJ3btt(iTY9@&w!l&M?ea0zG+$|itnT=h z>Ajgv`>hp<^x^Pdva!uOM~ua`8%q@&luM|N;l&+RjUN}lQKz!bv!;@+rt|qDN0xaw z1SRcW5I)Eqr%1|LBR$wy{r-v(Xk)Zot}HDv^y;F{+Imo{Tm}U63*@+GM%X zJKU3Su*K~kyysbH#!xUXRClmHFLVhfkCxT91!M?ekUpZCr6ph`eU*6oYc|?3$#!?Q z$&&e%%gAm?1gj+fg8DJ1=KEE-)>z2S+E_&XG3UccINnsb*vG*WV_V2&KNnK#0kxcL zu{xjmPq7a|)Peb(K1>}EWovw$kN*;6IL7$wIg#J&NKlK zU4Spw7EkC49G%AwvY{>x!-Ss_oEm-~O5wg`P9Dvh%DThXeLUViAT11Qf4ZKwoMe3$ zS2WGC?{-I~#rCO~<#R0zy4?DyYh-@>s_(9TPoGLOx)mp>P)=z|HBJA-(86Uerj9Pr za3~b?b%P3eG3EFSo-no17rD2%f4|>#hNhhooA?*}SOS-%heZb-Ez(tTJ6mf6@5wC` z4bspSWPBhM4rnUPi5Pv(9H>Km7CJa)y!dM_`GrQzn}At6RG&lBQM&4nnWN^3i8Q~+ zRRqNhkzDYNomzV;FRD}h8#T;bo5BxN+8Lc!Y{*ue(=NM&Y*7E-g4Oz^U5Q?oLsXbi z09t>?{$!9N+vXcfbD$>da=cW>``m@NV)uA;d7?e6k!5{(#VFhD>Q_NgTBhjeJ+Mw( z1BAG2C~KZcGc&K~H@w3`*icVH!{h)LVT~EdBvRR5fk0vZwEp@pr|#~#NcR~t6Selx ziY(9Iy4A7mq?&m6ijniK{iO=Btx^+D5gaXs`7Ga6^pN6MSnd$#UZE%5t)!EtTDn74 zN_k!BekI$Thgu>6=i^xdg91nwZTP}sjN#>+4NF1CUssA?htb*K$zSzs=;0fLnxC0A z_OOk9^$=l;rdBxgckf@eU){FBvcg2&d_{_?QG*DZY&T~bYhpvDUGS;N;@^{H5Rt`K zS!?#lYYx$zbjj{y)Wz6+Ft3yU{#UIaaQ~d`Cfk^3uXC}U51>|26aJ2R4jW;aLZ*LY ztEaEAS^BeIJ&8Wd*0Ud_)mh$-msFq=6Oa4qcqe|boVP$$H&>+BrDlWMDBi1y-8ZoaUsK%@ZEjL_1(qbo{k*))<&Aw=y)leWqm~$j)%T^7c|D8ND@l<&=b!toLyJ{9 z%|5JJ!oX*ps#iDt1XJsOs}E(&_D#Nmr-GcRW9gd)D`?&NLYi)ylHDJ7zuORED^*a$ zNzILHtgW4pgHwb>$Zv(-mJF^G|) zoXJNC+C9PA?3CJnBOk-mI~O2t6%5% zDTmjc|J&rX1qhNQPP83fPyEEbP*&OoYya~+O|u45pb zU2OP5fzAZPxcBBm`n4`Q3_j`np@jwGhTSJ0&|x#XoS|CdYN~{crQSBS3awyY-shWe zuXeWJ>OVvgO?xgUt$Od7>9=aj->4kdt+c2z61m@i+ib|D7Jk%8Rhx+Bp|Aiuq1L$= zkPYi9=kb$;e8)=g&kHs)2*W;`tz}$Lc>O`hYD!P8W!qp(GQ4L1y4D<{?3kp0lGnlH ze>pTvhU>g0y^`ia-XLIL*jI~syA?=GUHkV$W}{L%*ik0?&qsPC;pQkKqX(;<(bc~c z)PtCGUYV}*TwHgc8i~-e-Y6Gt0+)9<-rk56?cDL3)8$5jTkWKSEcH*#DaSBt?SH%1 zR65!@=G$+W`bA2&gLM)2SZr_!y*mhp5y}+<;^?p|&i|e?G#(x_6l;As^B;G6O8F)g zKJ<4H&obYOR}~LHD6p@@ydx`?SH25trZAARk=1u9d&gW z=$pOgJ5r?Ot)oghyt?&Jm$c0@T=m60*$OT*x+(A;4%_hcwt6uF*UuUouimu3SqdGQ^i``WVRyAGDColvh6 z-qds|BDu>nbs3+1_9r~P%)vrebBvCPbq@+@O)M)*NtzerEVd2kurS4b%TEOurng;- zTA(HLPm;z(fx|q3zs>A+L}NXv!KzQ32c4-AOT$lH82xs)ZHA4l{H{b(nVWKwI}lfs zs+*A(F0YZdAUvgEmutBQPczs}3oUTYvbvJnbLmH(g8Lg&ci#ul$%;`wYE6pnO!hNR zv88CB%zr|K=|k2V6Lk9zs9s;9;SQQXD_udzfg<_Hx#<--)7ZnE$$UeX!w1c=U)`qQ zS8g}pR~84lt*vIeQ%^!ewLAuUN8F%%fMYxL=g;d8kiKa?=BgnVID)bN<=rd8AM$66 zcv>28-knA}j(%lU_DIS;=qO4Z4`VDi@1sIguNf9r>t~DNhdMBDl1^$;*lt4(!%@$U zR_G9T^=hRJdiGTvMhCr%VqKN>KY*wMYvr)W5bk5Y3GGktM1Fm|{(h=1dU$(%Jb$|$ zyuFpc6>{kK)>O*{zMo39;$W?NsV%LdplvJ|GG952Ar$N*ZvXTJhqYM~7naE7;RbfR zBYSMJa0lr zMR65E2|R|jwY)t(GP8eHe}r`fK?$ppdHdR^*c2;OTf?AhL!X>R3|Cxx^?Puc=%};v zapX7a-X*i%HZ~Tw9YCABJzYjTBgb9I?Y9$_Ia#USiWQQ%N&XIZowmW&&_D$%t{1s+p60yy1jX&Y3xo{J? zQ*ZLOB%7Z;jIAG{{??9H9d%1}7l7=f?s9e8E~5%Pfe@%d`TjZ$)g)F>J;tlfU2gOYpBR~0@#AH8^p-$P6z;YMZJ?Hec% z1qEMa2zRXIoO2_?#iimtYF^hjv~c78Y>O+DbErPPi5#)N@vv!kU9I#%AeHrzP{)HU z<3x#}P(DRee+OU2?S^(lcxi)52bymhTL0KdNn>3J<0&dNtA{O%rwa zD|rUN6kRs+hi9Lv|Apc+XbRIL|igXOjKHM#g(}BFuyqjAjv(I(wTgFT;%1pme(0*}Ly8)qMA~lCn zFuBOP8A*a7fz`yJJ>SC$l*B<-;*)eo1TrTyrp~?e#r0@PEVaiH|f!SJO%FxQ>Cte1BiKJ?-3IYxHPw;a-Sy~e+*b50ea~aBU7Q-~a>_mS3 zl_zny?Zho9D@(@16Ml45Du^mhzE?Mvy9+n+iF6y2LE0STS=W!WbvX>newuj_s9&Rh zY@4I!Si2+~>m0}m1GK0bI}8g$wC5DMR%ie1UXi}T&y?l?N)G`1>T$(J8||PK@^%o& zyNvriZ-P2cF5je|ldfv6wz%+mocjX2XgWG$cdx^<<`?1tBKE;?5kLaskqqtzmiKM=3llok7;{@cxtA9qbH9=lQ-lQ$oos zibnE+u`Z-e7JDoCarZuvQY*g{z}jP2W@Kpf>g(Bn5|p$(3fl{F+H zg8Y}^t{)siXIC}dQk~<8XE#ExXrR?{^Sj~d5c$2I{YpB!S{5LvoFg%=EZ6BMWh+O2 zq}|0P^z>r?;A_Sj)$h59@z{yzya{>rD@SaKH}`JKxf-{nS{cZMeQ}t|WA#}0)X_XY z9OXWOt$j5VrTUp@-bk+b(AWI(kI1}ki?_cZ3s=EmI?%HnRw=O~44-ok!A%i@6Tf;~ z4&7gjH=9yV-Q9|qN%3fipkJ+yutIM-%djVyT13IDqMduybhYwTg6huIKTtZUvaOY4 zm7q?mfdOB$u-op7=oce;g7W}e0@L#=)YL6vKJ>y@|1%A$;!H1nk9 zl6Dak{cbFRYVbfEy7J`^J}avIC&ry<90U^F`jpg7XnT$%1FSL zcLQv+67E)&)sWakvI-kU-Pgy=yO*?nA(yB7yDRFaKHY(cf-RGScvn_oFp zI2p6q@BI$$<+&oKJ;sgiYEU5tW9CSw;GaL}jc}lbD+-~?#Tbu)PDj#Ipk3dZ_D*Lj zmSf?t!68e*Go$F;%5%e;^+`P5ODF2h=o9(Y+z`UsDgrMxgxoQ_QMl;wjaVw#F+TQ0 zxnKEPHbW#PTlPqybxPHD$S19*JO+&J5uWmUQ=GOEUH5h;fkj?-M`SWy5S1}G7uMZ; z)x{6KEDeO%!I1_ml$qVmYe?YKMO1rtYqv50l;l z7HKnsCN+~J{Qf_qGNGW(N@Qj}BCBgyl^!*{G|H@t3lGAa+1B}&O)<)RI@*iv$fPRo zk-$&v^*0%^W-?R=QYj!g=AJyv36Kn{eWicNd(Thw-Z#=bn}59fH2r5Eba&v8(qS?d ze!>4I*>fMgZ(GkLYSz}%J`8)8VKZ}{VWTVI8Sj_c{=>_ zd%k$UpLNB(<=VZ+4BSf0`II;PnSsV4ia8Y6n=?b14e_D^40OhzM%cM$}+17!wDF)nQAbOGx-L?Q)Hd zIlu&_4kt0`t*?tAW`-lULX_@aixJuzZ64VPL=a&#-Y2DbfepOJzRmq(*3ly{okHF+ zK97F@u)Xs%p55R#&EA@vO}ao+w70ar$Q@fw1}oNYu*Bx#jZ;%hW>wl1V$qNYQu=H= z9>>tc3BF2%WX8p9d~Colx3~h@K)vwkq@6N}aipDt`%ZCbX<{xeD%*$OMNl$cWEN=V z7!fJmshpl~3uJA54@%0vkdu*h;d%GyFC4Q=g@s#cbqE~Fg&jpV&&6Gqqwbfkh`~XD zp^&QqoH;y0QPCTiOAk!**W9EpZ42qc{>2sR#*S|DcL^Rvv@vgO_x9EbW_1Ik>r%e2t@L%pSeK2EVP7tX4HH7M}t=ABCM0}? zScR>flTQWSRyo1b2gmd=rP6M0Z{HIN!22ybMR|6Bz_@7M3_*mtwhnAsMbVn;%m@ zJq`~?SgdzOOfp8xo`8=o)aoEMXL&jlwpnY}hC>A&KCc&oN>S&MDKQPH2rF$z`WeE; z|F8Uf%79ZyNMdg$wDOFJg*8brrsLCuuti;SGrD@4g=ia4bNmMQT`Mbsb3z_{4_>t- zk9w(12r8*JN!}?7p~wdyolhDQNO-X_WkY+paDh++cs*0Ufu@h#JybChRjj!FM6!p* z9=r=j*FmcT7v=Q()QqaQ)RE=&pQieK=_Lte{(TF;n@UWdKWqKM_$Zo|{GXX-77`LF z(a9Mp8C`eCGiJ z3=SAxeWO~{Y9K`C1R)fFJ%kgzO}l8jAz2=D-=<}KCB=%-B7l6s>uj*pg_;x8^(=!Ow4V?;Et z#3kMzFZWN8@V`ozjpXbpG0~hW5a0yfTQA_a>*OZ~3|oUfFpkvorkJ!&B~QZcpEZf~ z4`cO*+ue^{Lfw0*88X1Z5v2dtLyfd7$XFc{`@{sIn|=cs|8jYd_fLX=s|1klzF#ohgvIC3tSi!4u65GXd?{whm z0wdZFfo4h)a{I%@SgA(~?U6T8nQ1;b=uWQ*MgCdJ0md?~1LLMtxH9Dwm8NTf!6N?F z(Ey&D(rSEBOjXs@@1uV1>FxnI4-kT!9{v@GSedu%sip(g{9?PeW=*8Rj{vCO->d+A z;BCM5391I>?cb~o1JvVo9#ibxSchmymqct5P}~C`lkoWz6o4W}xv8`qf$15hk8N}Z zFGnJVS+-^f;%i$Geo&DQ=-s5GrPF+3(Cyma=mLf)2*sbK{xvZPsl@^$TJ&d`Z{gq0 z?gH(ji0iC?ego{CrGI{wmi!)u*43+&y?o-L4co$V^rj=J*!N2Nbn>u386vQ-{V(Ii zT}PW8Js#`ccRJ7ue8EaRfPw#iT>S-99Zl0U3_}PI+}#p9NO0HS?(XjHt|1WI-QC?a zxVt+93+`^;kmS1G=l^G&6<9gLOm}s4b@i_5+7y)i3QVMBVZ(7j)BCW$s}Tw9bpE7_ zrRXSrBZ@bawFhr4_RTX?-5@AuoW=y}rO@bvq#4UU>rrp4)pp4YBW!f^}(z9 z>C2_8q3z)mvcCwyx{4yezCuW78NerMO8qn+Jmc;f6%Y6-Z&J@Ub)#(e@D;Pn+FmO+ zpOm;z_8cBb(x&y^hj5AmMLH)&VE1DvZ}dTOT6azV~#2&CcdXmNuQVyh#2+#Pcd3R*WF59iLNwT(}74MPh3lSdSJ`4ja2(@1v%s{^3he1-6>o#xEpqw&JphsYSR_!cx^#q zw9VX#*(z^d)q8i@kBiy&@LEl)uGH*7S8t@2Kz9V&W$2k4eWXUB(SdRNyXeJtIYcQ5 z{p+pwPKKf|Nv3vyL7Z77`p8JyIL!EH&c|!$^!8f;WPZ;GQ)1!tjpe=y`kDFqdL1V1 z_7@6*5%tk8(jU&BBX<4FX$(UtVZq3kSyKWD(g&kckw1oh1MRmPgu}2`DL|}Tp-MWZ znrU*^m@u|g}2|vz8AxR`TFDbv3yTb_k!&UZhp#6M#tD8aHCN|U}ZQM z+ivUYR`%qNZ#cY@(D^*)ggm8dJ>h&PA960glGzRUtWrH#eZoqCrtN08oxozTnN|g} zSppdzrJ-5rk7ZLub@^$M&@;eLzPTj-h-}Hb*eC5`bbvv%+L*SA|B*4BJ4b3aT3niN zc9H#%g_>e6@~W&w?YymGwQ5nW*fKA=0()vd^b-e1$!yw>(!V1f@;2hXo;iOhgeXNR z0rfcERP5!L=&-o(vZC=)o1kLnqSAA+;7JL4{BuHBFPhq;es!_8_6tS^H@z>56a3z< zWuQv(g7%2}mSH~kcINO5w>qm~rj&v1xha{mTiJUyGwlf*sXa ztEMXst1|4E0jT{>eX=|4RL}{MTLcK+Kj;qlteP4j>q}inTn=qt(jO7ho6dDog+AjL zasA|3AN_P(OW9~H^X@xG;KlaM!T{JuqpPx~tt$aOpNR#j1@fJ7RRr42)ihY{N4JxG zjLw_h8W;V8^+i3&%~Rn%eadC2J_6NmsSXUc_}C%FkK?VkQ^Kv$QC*E8<(sI=AJ{_H zHg}veHo|7S?YDeB&=QK`x-!q>;R`=bAXj5Z?Cr3SA+4T*m+#{UEsmi*-57rk)UYKJ zc7(~YnXd5Q*2hLs+B?5P!HB}0bLiONEs}%Vzn#T!Eip77maU;SKjf6j`z!YnK<<^7 zo}_>aMTWLE6+o5o0^v+acs5cwNhn4w5Gdn%@_d!+XRv(XhiZ zpRo?|(?Spdd+=TG<9>>P@gTx0Ap=9;1-B-}?u6*6KfIBMF$XMu*MyeMVDvKX_F%nJL-g;u${!cs)y7|c!r}Yt&M1A3jn&yH3AUij5EWRW|7)RD z@>zneULorOqvH+hgPqDYIvGK`AMXx_0wtzdFi7)Ng-(*0wrkQBowa@*QK(~Etf>Z@ zvXd_|W?)To@AfNtSJf;?DFB{zugn1*9p&6%Pc^M%jM{1a9ZkGNZ4ieU;yLsB0<7Nj z_o*Kds?|k_RmTZc^~9mE{2Jes)+3tsZuh(i4AtrHYu^43<=F~Fa$WbwnLFv>3V!o4 zWtZtRhY}dhF*`@r$G|6glxfg~r6@%3VJCDstKl1lxzVbxfuV`2BhGrW|Jt)lC2b}lYiU>U)=m5S`XNhz3W;l&kq++k4t5wrBzb}F zNGE>l9K0dlcNIQ=zmsuzFo_{4u)vt^H(*KAziI}NYmK!?OX$~}zC7P*BZ=s#E>Lvo zNNZkB5V{bIr-!b+URM>URlCjRstOC1zYjkh(Km7bn#=RoO;pd9k@NE%j#D{L*Dx0h zt|j?94QV~mqS1U)3{_QB+PTZ>>N70vVSgcTM{8Mk^uDfX4pcSZeQj-vAN4r480J#R z|Jss^FHjQ{=Q^3XM3b*pA`3GfeqA~eunjZ*tI+qDwlYXG^hV1(d2NW*x@-TrsXmL1 zJ$h+WXEU0_g685CzeAedZntwnD&3jVuZS3wtv znhUtFHhzNUK(D?7ZDu*nj{&qGlo4nlEMHgX93m2 z9$tjS_T!DIZo%g%lgr3S@L^iqxJ!K%6yFHut+u$7Q#z@iBw-7WY~IZRFS2}UuTyH1 z3~!5AHd?5(h*ztJfC88br?LEj94TNgngahnl}Q6sCKpK10Ld+&fjtuu$Zh)khg7Vy zxGQq0N*mfR?~?%U6b7Q?ej& zoalvz{m4)2);mtUr#fZ(9;-!WCpUiIdi$i`+Imb3FKWlvsl<$St9yirk%grBd-GdU z#>lV0peSOY<$>i|oDcn1E@v*BYi7K|S1%feKlNCzQi<+?dL)Tg*`0Sp(Uq2J10(x~ zHsQ?yvgbPVJ`DX%yS_B(8&Jz^p^}FJE~@w~e2)xfyi|ifvOF%PC5#X__Xdd zxf$aaq#fvVZx|%PIWx8%1R^gF$y%Q|U|a2|R*&#G+ifPU!e@W__j7CnpKp~_mb$>= zM|`!Y7{jzjKigFHWXtk~>>6UO%t5WBz^^dXJ;zudPnGP+YBSMp_ibX}(K8=0`9gpi zwqN9l?zgDL@7j&SqZYqIomP5hmIM($+M`ar#HY{zF>0^xisvI8HZr|2b=}j=01_``(*ck^BeQQ(AwES8wU~?%B@a z<>y)uVUA{E1YL_HNJ_%EnsNND8C3?Cy$Js%YY7&q=0ol- zHq)?Ny24hx=DyZ~QFZNmj`7^PUoE%Zt~VrI2(q!J5=XRz>4Le@on@D>?lv{t-35>( zS_(ut97*D`v!>@xzl`zlt?NA`&@k-t$4tO`vONtwvb_emSj4a2l@{xl;Z{^^S6t9@ z;DtBF)^*DoCeB)@Lr{%`YvEzY1TE;j(sUeWl35cfMaItDU!i5mPW;!V# zIb&M8jv%4zb{p>MI;*!WyIDFP&7vR%%b~77SVVjyqC!FfqV=Qw4IbarYJ+PnzjIj6 zb0b7ir{03~XEP-*(e1B`eW>3wTa`Bi_wBN1(I}e~zdfCqv zHXhuGW5rK^MYrUeg%*XOLZO10uBG6RQu-bd?=09l1RN-O+|ZUcud7E~roXKvD#*%Jv zgsdKqO+!9`W!AlIg#}sx7fAmcDCYTSfplKL3uyJydtnjs7N=vNgIzSV^qGVPbkryS z1+oN8&M)r`OMcV39&nI6)c}OXDCK-`H`K6U3~oKeTK(%ft2!#!l+l(j#l_0H3n%nS z24}J?-OW+frTWg>&b2>IZ^+eE0D#Yj{Ow*87pmBhuiT?H(jv}Zmw=e`T1RkK?mHZT zpsMSA`du!eN);A!e4&XrVK2yRzLvz%a- zU}nIO2In}Qvo6HA`ItKa1Mh!0k|`-bq|o@U%}y_G zC&H@3&Z%j#C{&Ty5dV8tqTfI~P!SJM9zsWX^2M7w@9@bBWJ0^lH}L}(BNBKNb;REe z9OTPX9|JkTX48~}VSjc#0BA&H$DYQTMu&D-vi&*8LiewCRP78+qTcbg)R|3E{GWTz zD!x0kteTn5_%*FsrH*0ZdA#+#$e(X;4yc((I2HTvt+*g{hL)ZHj)qC67YpC@){vus zQ{qO(jtI;mrlo@z}^&iBnl8hQyyH)O+gmkL` zg4j1Ud*GV!KkaT_PAdo=VE*eP6J8gH4aRr#a4IPR>E#&z-6juY@G1(_fBHLurkILi z5IhN#Q8P2OLsmc*@TlP1ZV`|h*KexRdSHCte(xrah1CMI36L$IAis&lkxZTb4UoV= z=G!C}$lXL0gTN@59t03Jo0ipsJ3>Oxe~h~V1~dSm3Ot7~m2Yrk!;a*a9Z7UjQdT() z06qTqn47LYm=A;-=37sx!}$h(+OntR=EH-?0L_07{#OEogzlRhE`La8fj0sI1SOBP z5Na=1AfZ~;|0Ie1MuZGpVZvG4?L`y-)iT(B zkB9r$kiHz5YO62Ggn*mz)+O{mAk^DHgZ-P1wx455KmY%9`+xTgc>Q6$4-(muBi{#d z92P^}tLMn(*M@xy~ea{f001b@Xdb?1?_4JgIZ_9GP#Xa!VlWCRun^G7ND)3l%g zFQBH-+uOG;%Muckljn^1L<^=>Rk4zjnk1;z1aoJLls}r*ERqk5n;%pGH@*dks(}=X zueoph*>BSY+wyblm7?GSehq*UD^&2((^CYe9xs2Uq_jLZ|MM3LvPx=V?aPu54lO`B z?f?73GOk#KH}R2#KUmD(j#Kh(f+`XA{0#8xm<)9$jLh+|OXAodC|g z#Q^~nc)~vcjxXB1I>0%Dq$I4e-RJmMwWzWkAb@ow+4gP_9uN6{_m9Q^vWu~Kx;dor#pjPu zSak&{RjDHUne#SQ|6NgYrFq8kFI(0Y@auTBq#@pF3R~54H<*8x!hcUEX05%lD6T(e zAq_mm(f(zsiq7G@`)e&OuwOph5ZqZ;|1L|(I9|K{ za9n_^uuc9!Nl7R@HD2-Xwmkzu;hJ``VZ8YZB#=u&m}kwS^hH|;$hu*72;$kW z{U?XNKi-oew8VS#3|l`XtT&*7R)sbn(ph2R3RcD+D?$<5+dEG*Xq%Jmug*_9$(NQS85DRQ{q-k z31kqy)5{Hf1m`ms-l}Hxc4RB{nkEKUXXPhQe)G_TrGQ3Cp>`1yYq>I(bB?#Mf6WEfI)Faq$q}X z5$k(?8Jje=FQv@&<)|bd6Wcokr(Cqiv%P5wL^QUJj)De3H{_VFvAAbvPH@@_qWdf` z4;a10KF*1C`|f_#>U#wAr`F`rbna9jI8Lj~6?KW2$kLXx zMdhNydU4@iL<)1sH`Aj@RnS7KDs&dd8IgV4M99JHU{8Gq@6Z(^mJ`)NL#nS?a=RaY zXwrYn@6wg>KQT=aE}D2xxN5jYp6>bPexv&2d6Dsyw5QAa4X@NAUcx)z6&=5;mxW-& zyTGG*o=eS8F!mhdbk!B>6m;X4Ujc!^Lh-!oNzVFWB~u3dPo!yo{|K&>5Gg!9NJyXF zlUePH1M`e(6Mb&uh68WQpYX|=~nDc(Qr{~8i*c9UB!8f`U(~&NaAD0 z*>dTG>auxCBk?yO~5d7`r7-S$kPd5YODI%?w$_jvj>Alh-n!>;<)dEV6_ z%{Nyue*9*XgLW(CH|`>4?~B_SI7vxRsA&Y9BS{bLbjoDi`)H+eHEx$}S?-~euFuZv z-L9TQbftRCPiOGc+{xoZczHSzS>vCbZN}NSDlvAeUB!{AxHJS<7#*y74<6i=+IKoQ zpT-d?GhS(LahGL%EB{SdkrG3>R_d6F4z<9x{z2Fi8C&838@qurdA1qaGmBT6*OK{m zWY+VW6ihs8NOeqGJe|V~tkOYoy{GlQNrvpuqLl+#mq6b9jgvEc=a2-*&xWU3|v#b?CKDjZs$hPM~jMkVI%N& zM0T?inIjF5sXZXcj}sN7r@FS%?xRG%oNM^|^**<)wjaIR)0MlDg2iBlr=JnO&aYQ= zRL2QFOgGS7&m;f#AdSK2K}pC79S!j&>aX2s$XHNdPyV*F%mNv3k(T7~c#iROW>1Ra z6#wp1t#cl&%{EjhkD<&cPVCNEKaIDn(brvR^Ff|LK@Aj^)GuR+L)Q^6LKm~rcDIQK zv)|Cc#kDuX`*)}IoA+Ed&JvAIyfw$-U%7`gt*wl<@gnSxC!El3t*a@YRZm=;K6_TU zr!K?a5;(J|qmLTO_aJ^bsS4O{SQ*E-nRdOZsu3-gSfmP$?-)Bq*^6;Gj#=>(z^&V1 zQqqN}kn;F(b(DsxgzAm6S=9)T*&p0ZW3tqu=nA2{+-B;~A!u_1NDL27B1r5G#XcN2 zkZ_(BQy8wQJJW8KnDj|MU=%o(;0MN6TlH~C+>MO6N^=htX(qE#R6Eh_z2LZ-S{^Ik zw(3D6;7w=E?M-<&M`!nMy zwJFB_K}hDQ-<^D8wU&lo3BDf=M3>d zNMfV>cHMXr3yk$kvrp<%}u!A+5RwrINWTx#0N;%X>^Vck zP}SqUPh*AmDty(&B)53W&3@v3!My2LLyPNuFAJN)lp`*(e)me!SV;v{AEpH?!cVp|5+ zDr5LMLP~$785oZ2w1qmvYo4<@6U0n>d*!O6#Zh=#lS_A=bsbobN7%lYyy^{Y*GH}L z>OdW@XOnpJphV;!vqE5WK2Am&ouEA3SzGn;)*jJ(y10SysA{4Kyf$yRrA0<)f=S<6 z^L~~3v7TqxQmuONsMM#e(E-)qjNLt}+?dqDCdZ-A9Yxk`hgxm}9}3 zXf&6V+TLMY_ZFj&7cc!O>k&KJWDYkemLaX$Yn%R#=--ZXoGA|{tRnEn>JZ=%u4w;r zF>|4?#(jN{QwM9Ir1dzRF!VW?cA`!Z+2QcSo*rL`^u@9I^R72T<=rkP z0ugL3hoW%ZSI$H6q9h)TSnsrqhv&EygV2O?iCQLE>Ui)hfBwvZ#lh@6W@#PVyJWFH zT3oe}>6^Q{b-6#TxI3;O4E-(eJ?+6;!+n=m&w_W68NL0Q)B1_V|2S{MhSc_o8o_Qf z(gc<&xMufkZus?LvsgGFh#jhYOB*W^+-STkG%P;t;XNKP=4>#`l?E3ML7@GRjdy6R)Ah@7w?fybT@?5 z(bzu=(tx>_XwfZJZIEacejq{-(i$)%Bao=LqZPBSR;i+h(DEcIIxe(Y++`a{e1>a! z5{>Ad!dzVgDT(CqP8__F#)xdH`w*0S7zERJ_&`*=x|D73+|TK73R%jKwJiF&?Q73b zdAIoEX)nQU>Pzy^Ou3u9P*=cb_6BJ_R7VMZpt_Aq9LO zRI2nL1ojPuDjVPml|JBkqNitIxx(zoDhxJ5#4Ovq5V3K(JK) zET)$X8I~T_0|%vtZ>)0#+Me7I8w1xbnm+SiEkbDG0@cYV(*X7hO3%JX0rE1b2-_rvuzv+~(pDu&Nio6S~T%4X}3<*o=gRzuae#2KhMa9;RxowDU8TZbagT@s%)tq4op2 zW@I-U3Z~y`W2N5bel-N5`bsG47m~SGj}I*w7zPGWaRojpIedIC*KJhkZQn-w%k>pq zk&xEoK*0!d+Zn(noh%vF$25ee0vIL0eVqBVl3D%Gxt**|wEJ#hSZueG(FWV-!GoML*+gg4n4E=!N7MGrJdaQyZtoV-@- z<3zuQEav~<_woOIypxASbX-tW(y$y<8}Sw%kN2q@Ii9^{nG|h`L#?_`r&DS7%4s8<6UA zuL|0X8)MEh2CZyS-nqR5N}Q*SaU4GnESMNu4=0Kmgr+qWZD(p zsl=KnY3B9C*Oau*08JQ|*W|9;bFL56?TwQ-+HKHRpqPri)};sM7fjhg(mt}s%}>eC z5H0iRKOqp;GA8+3WEG$$x>J6B*wZ%`>`N2As7AnSIjX+YFr5@bpDIhoRMh#>zIeqo z^3;PAdS!M)m_tzF-*Wx21%6FPY2){aePYYEwU(9A+|E^b1aPGbLm!VXWp_bP;tZx| z0}P?X`+cMQlu5Up46n2Ss6_k7fF=~(=Hx%k9z>78nk3JRtVwByXTz3K_l2PXj@ zJl@#&O!;RHlAcW!HO5CqeRtNZ>NPAhp+ynKeV^hzZczx(-qRiDsc@b&BRGvTq<#IG zgHEMtq1_y@roXh2R_~t|SekhwU^(6yz8HnI^DC1)KIVyW6NcHCRk)}wGX426!FDiy zC|P>Vu#=5Lr)PdxsIN}HH01?<(JBTL`*73FN>!@DaF`mzS*`Vg;#nU$;j*X3mYgXK z2*KI)X|;Pi!rUa|c9hhaSzs;xUST3>C{tnU(1X@K8iG)K-?ok`w5-$EYDqBY%6s4i zp9lAGuEga`pfA^i1p^N>=xMlA+u^-uN`eckB}9#NQd-r$`)G|! zvVeQl$xrSt>RW~SAV>SSJWe>CX+{E=7pxs;V5H@<6J8S{>BWThn+X|-3_CoSJZV3> zbq$HWQLN{4GBEy-l{ca{bo-DHj=6s}hmz-40>Uikbn+`-8Rfg8v(S@*S1smB#%PY0 z!Q6$D$I5ii69K~J+@>Xd`HegOJF^v!cW0krNhx*=vjz>0?t>dT76PGU9u){BQbZ3% z9m-Q#hjv!_L%@kaQ$m$sn9Z^K=cSFStLRbO6OOjXo7}f@6k6BNfL#VM8TzV)LgG~!zu@}`d&k(LZw0q33ccw^*&QjkfFmON#9H!zWPj4=iJ#X@neRpYCp96r z`TJDE(^>>~e(P}ZnIYl)GDBe|PQxZy7Z}RgkzjtLzdpWsAB#7HN8#+z>L}8Ta?f#^l%r^axaX-DL+?o^;W0 z(-CYHgV@_6U>?sW4mXdrB)WIJewQ?rJ9~l>9_u6D5D3VIKI(QjhI$&?{Sd{J3jDxg zL5hZyj-0Pw_lETtBgXr$i2wU&*eg)fEg$WyH3Rz{gLLjr zNxywm1s89v0J_potARa}?bq+tFgtwXIlej|RBpt`%tqyMOl}&Z0*X16T-QwAwGNa<1cgGwGCyzjhw0I_3JXBQW(mT5TyEZ6{gB*y&MT)*EL72hU=WP%ok4 zOWQ-G3v5GOYDpn{eq+0=V0K>h;xtW_^2CA4Y#}-9ak86y2r|`j=x#AmgzHBkyI9_b zJz|0}pNscO3!^NFx06{7rlYyGGg=Zrj&w|%N4MU!u%faR8Y0_^j@tSVu3$EuP>Bb_ z>S9KcBLB;z(v&N~w-|vdbnl=Ew;@H8WjL04wlLD(fn=E;m0wnh3c`p@*G30GNkUb-q?1C2Ax=p>N71dW^9v+1_z0%uM9pm`9*VbAc?Q2aT z^n0qIxba@5OWd!YB1mC9t;x$M_9HK;2H2^c4|vdR^dB8aPsD}tk<+xj{nuo}y;9>i z;I^Z1)Ejr#gYokirYrRaD}B@vnb>)Rw%{_VOoX+u9T56FT(DBClnd60uA!b(g*(e& z?F?zR*WA+;Es??=>vN8z1`DKO;oTo(oeB;LmuaB=_gTf~wQ~-9K6B2}ePEI)3I5Iy z$Zgo)j>EY?Inz7phNcCVv9WkZoPX33RJC}>sWjeeJK8Z4zPf+c)9@)@gPKNe~Rz$#t*U zlyIwpN@tnBm@|hF`CMZ~ZENi@SZKl_${<8<+K@EUCM@FJNbg)M=zjjQu;}*pr+e#k zXCXhc)_#B=X))Dew;p`usbr#Al0&JZA@#LoCKPnmV60S2(oP41+YGtuCJ#EnI_dLI zjQcLN`1Bb>o(m=jW``^EuyQ=!Idg&Izg4|w3cj| z{-_ILyJr*=Ywy>a5pGcB&KkDlw3~%rR-{@CRp}h)oWz{VzKfSZ`;-#1ApJUIdI|P^ zW#`JBhc>uqY(xp<5NZ!hl8Q$1%OZdED9-vse(LoCbpzd&kbn%XW=p`??owRp(cQbr zB?V?`uHg1-%q2xhqXNC%_(8hM3ZMj0`idGS$GIu~nKCHdOiAi^VZ(eCc@c*-)2&na zYDl3FoT-dTg1XdRLN5m`3ua#lSnB)~cGg08drv5J|De@$y}FL9qnTSRx z8S-S0U|=+l9R;OQdfqdPW9ocDb%wv#4Lrtuh1QUl`Nvgt z#ocz6U0`!mz4NKI6f20rl3;i@tsjvk6#c7Nr6!T>^ye$2&AUU(6?P{i6bO&i*9Rp< zl9M*d>Z1==gTV|Ndm=HhXd6=&->*|VjdeRr+``<_+h=PBnv~h1igkw5`WPalD4PN@ z4-IyT3RjwGs98KauM&hJ7ph=1TR3?&3UQFp<)kzqryWUQmt>7xSnQ!?Qo}}2RfXy~ z`p89*p`j_zK8lh@`&}4=MbA;LGDF5V0;&7GScjfY0RjgB7W+ZjfMCytS;wSjLN|@P_=>DawrmSg z$f@m1*@07JP$4=>_B;k5XFmJrI;a`E0!-wXvVx#;O@+1 z^P`5F@%kFgN&cFr5K12gD0#ozh0EhBOXvB14*M}q8t*2>?^X`m*W#d5vlqQj)pm$J z7bLu7{c9tck$FV(XBC5LX2?!d{U+|x`$YS}5yx4MvA(hzWjx_VG4bT@zauMiCX2lH z=*v-UwhXF?ZuHiMXLQ}gIZJX2BBPq)5!R{j4K6Z|8$VxBnR%4NCIl(a-AG7fG{X64 zmjs%q4a$nim9fOLBSRNGN`WCxxxa^^(-I^Jp7jFq=I!|B50x(ln3rXnTy@T@cr(hs zhHABaXDDm2H!?+DLbskG6%j5j0R3VdP3dn8zN;!=z=7>fYG<;aXz(o0 zb-6fi=#v@L;l;aWFTByNE&N(sHlM_ng46i86h%hu&WxLi_U@Q4FdI}WDo2&FqErbm zTEx|MQ0`*rZ4$8)0mj1jE#v<8C(rjsrg{D;uZEZ9jEiDMUocx?F^LFrm1mUDskkH> zI+fyy)qc2^!)!t@Xh95&4hZ&1-2~Ja$Ohc$`6>^pq>&<-IT2@&v}NLFQL7`@x`A$9&+AuxRcr)^J(+Y0sadcgv=J2YQje;J2;ev(dyw( ztJc*dAsVnQP5U1X7ZMul7*sCI35p>~b-G8*u3U4_@gE#uRR%`lKyg0zSMZB)9H4W2 zY>repa4RL<--f#gc^93xU0{1q>__bk!Jm;Rd(rfh(GL1&gGx_B=DYdy;xA)AwiQFr zk&xYKQi-~?0)Il|L79W!lsFvg@ow?Yeq^%yz6FDekEH2B>_)>Q=@mB|#xap6PNp^s zMb0v;`hTs)UC4k^_0)K^apSUb~RXmV}GpR;nYPA%;|;2zaurc;6D^lUJEw`>0PvsD=dWelcSl(_dGy zuEi*ywi)X^@3C;8-xaA(V@Ph=`3PSoxVA{U{CJFyo(uU{7dq4dP9t3+nV^}X(&ENV z@Vbtym+|5wo5qRDQUTU{v0DiL9<61oRD}J>gICmkZB^-LpgNS;mx@wEPIrezIDR{0 zG*ZC;%lIh9r!UPETjA;KccI2U{yn+i?beQ+*k|;dbCMN=8|}apVJVvyYt~M0Mi9-! zUJB8|6Q>;6i=M)5ohtn84If(;GKVnKTHzGe4n+}ani&Bj;NwfAbu&^95R~l@JP3w_r&+w4c|(%(iJy! zc|}TfDT)~{W(aMx6#-C+%Y}sm6OHVv3TXch978l4%W35iHay;OsOLh>^Q$EeeFg=> z`eBqFCoG@+C%1gBN+0>Ttx^^5sCs|OI8Ch_M+hIZ?R8DYF4wi#^;7;P6rC& z3Y7<^3;mG`wvlVr;NpFerT0ZqcB^zEP9sJ*!67Fj9U<@VN42)g)<|C0{rX})COAr- z+8*1A@=-jEi#28V--disD{Ho2snd1v+_L{AMOEuG8xl!03_O2@4Fg-K|S_0@n^&JHFgoWb)G8B64D1g8{V z7YH)`spy{6swtjZgHJ9r3yrbQ)*M^;9)%B3w^;glbDhq6ZH0q}ptfHcLt;993_>em z_j12f5?6firvY7z;})SXinATXa1=qIEa-wrNBl8;W*%HQ{|6ttct`b^Dsm8dS5ouA z9ZE-|?K9@PcWmw*215tK;jo+}3ESH3dpxg6z0C~yb|)pp=deX$bwOq`r|h9f$6WWv z1>>rYbOa!hypqMgOH;WVcBBLaNdl)KjEJp;4)s~D3 z@vdust&ZI-4nF4+&U|#t9?4)1S*0L2$3pMG=;hSlhCl;iDBYOaw=T7!#we?7ImrtQ zA~JF!qkWZQqE4Udi64J^`q!n|+B~PWcm!QB9vuV-%8v|b{mJypm4SL4IzyZ55wH5= zHX-gzIga%gHf7OqXWO~iHHC^@a%@lcd5CDMMGzTiszi(4gn7Bsq6SPEd9Vw?c*&P^ zu%z&|+I8-pU;8ol7BBc#3t|~yB}5-hX9z)~rTHIfFF(5O*;-V!nW&4x6;5E)>5P&p zmv3k8fr^u6|=3p$iA|-W(;}u>)nh{!Nk49nA@Y+BKk47Rw-cXwm#51o3KCeaIQyX7GxM|Z@-t%u2P-sNt*Ubrd;Ta0!F zWBY5tiC~)Z^!V$V9<613o#{^dF##Hlo&$ejPlcM<*WyO3m0Nk*dM_1WC{F(vecY%R z)+G&Q;%B-@68+STBeK#ICBMYl-0wz|)mLKn9)D#+qMj_Pw?b3*(;be+NLMYjN6iLq zX9R4{{3(1hg-XQ{$@ybB|g%T06Tt1BA5&wkJm1nF@vIUcS8o z-0Y$3XqiN<_B02{(RWNtkz)w+otp0y*jH+GM#lvEcvV()8soR0S{(*DyuQhkGR2ug z#$_xN!R0D_NQ{=31rLaOf`z)FKsl;dsOt|{8OCiU)Gw67BY@lSNRPWAyD4E5m9}|? z=REH#kT}o|SpHGMns^UvDq;RF=FHct5Yjv?P-yTymyn~{eESzxbO1{^Dr(Et_iWNe zu5Jjj^M_LF`z%vQt?*l-c4hH+Db-Fg`Qt0kO!%+tI1LqRU6k!$bnVECWDS*+3_)g{ z_=Qvnte!O>oUL@3ou|ISL0UW^izvoAZn-3~US?D*@`F(3{DIgfg`6eG`-aBLz-cZ; zmY!uh|CJ!6+7Htl)rtzN;=@W$r0Qe!P@HvTciI$_hg%5yGZjcFMz}q8dieSoDS=8Q zT}CmV4%m!Bo!?(-$Zu)$#DmB+#kGYYXf6258g{o$yGuv~*-Rdai>usX{ElJt&BHj- zSiUDBIDV??K~{vE+xC|N6@cihz}UPQR~n(+*wJJ#P!@ksjpSKBQu8T&K9QMkTp>=1bypt@>T94 z^J~|z1J60Wc!wJQ)~&nzYz}Ayw@MP-aKU*~KM4E09ntfKm>2uI$#JJo8jxnEANpN2 znnRD1zq_bf>4cel4I4nrJ#JC0s)AoVe8_3g+;yr_2|1jvBW&lV$(|qI?vH5iSt%i5 zdSX9DGF`8Idct@XThV zDRl9QlAx`~aHSw3K`q9&FrDki5>tk~>JJH=^dPm8POBPu``-?0mKqkao@mW&7q|u5 zuhIUCEq4!(tl2`0r0&zW@u%%j#9NEGpZJ3#RL6+O5NfT|_E?Cn6b|Wv0!zuDJZK?= zeK#<@*423d+^b|`80TU;;mn`jTUxv7Zd#GWXyr#&rC=`#R4yB|=! zjSKr~?|x3yqk2QVo&{Gjke4aGMxD(B zI^TRa_~zPvfP*E14yFEA+8L;Rvx1%Km-?V>p)xIhlVsMows^+5m)bP=Q-`jCE4w8M zhXciouyy=?I~~#r9)?Tj&_Ya4!(Zm6i{2xB_lp%5SA<|Ueh09RN7Tvgac#U$?t7Yy zngG#wmH6dvcCU94aR-JJdr1SrA?mt#;*uYZGmeI@HPx0HY+`!_r#AAH`NQ?`-2`qj zosR{Kq%->bzH$ZK(AnxeYd9qmx|AwY<7!*VY^`s9)!X$PlZN?Ou+=i-2vG(r%jHt& zMhMgX6sx+=6@+m6ULO0iYu)dadWBJ!M@z3~T~Om0N0-**q?-N+40pMJF&;ncuT4j( z^xu;{pNGDf1l1Ij$3%BeW^`;0cbC6g5Ykf%u526nUGU{;W@cAG zuTJ{HJ?Z+mR?m-S{z8mL)UCirI^%t2uf%$64&*+us;lDpa0u>5&mHoVcv4#~3|?v8 zGI&m&TsSWZticKrnur7yPHPf#+4R*N zkD|Ay;}}=9fjJ|e9z-0BS@?9y!0y5=&P=ea;l|C}0>2Id7#VR0LU*{G&F9m~izP*+ zktKl==PlEWwK;MPNV%C4?dhvrwi%>?XOHe>FXw( zS=>6$WIh^nt4Nhx<5#!Nx)-L*I*O8f#tY|c{7DR?paL|&r-ap&K00s7~8#<$_1}^k5y&bF-GYYy~T1yl!ulA zO&sY$9iumyB0~gNltrQw$|ZnM@A3@?MoNWmYz9G6vYO4S!T_{EoMkry(wiZ9zid zdM04X!xg8J_S^B*TxK@PjEGCt$}&yvp9-`Ns#~5WG_^hn1A{g@6$kYS9>n{GEKh{a zw&@+iGmKLn+2y_1$w;_*dB9lIZC#PilWAZGlwM>dc4CeNo4~`8Qs9RZj5TY}HDp_`D8&58M z`A4~Dx^!;CcSC^V`Vb1c9&v>QIcD*uaWoez*`-8|&V-(nPE<+n)kPnJbdyTHiu=?0 zW++^gu(){VXxG&Y{vs*)W9V8_&;$2*68e^*7BwS?K!pe8R3q7oq%F#U3NY$3|vAMQHsk%<}#!#|vI(TiXO-Gx4ImOIHG+v`wC_=`734wVeM@ zI@^(g8Z&+NRAnAY_Bp#g!Y#gEf@c328i*g$t!&h zgHz0(iU}gF53x1jvfs@0S(@Pc1{P1nh^vn0M#K3P2M1;MQZm~<)=dkTMT1yvr8+Pv z>VAI>$k8Sj=z#nL)eWeb9z&c^l|>>$t={c%(k1ON^DD?L=>_c)(c(~vYA=7Y0^c-; znUqc7--zZsMwo=AVr7L%+}rfMd7AptLdIkrCzgEemzr2qANQ+y_qarIA27QY%2^SE zj~-$_XM5*Yv_^Qg>_P0d^2xbQmL$sCuRn)Xjn+{rD>%S2!IaDaFL`m4JR~}tHhLL~ zNIvj2J73i;3TjQTGpFwSYTloFAjCIAmW{D%r5gAFWA6NMpHIlf?QS=?bW4A0C`6bI z?IIYrgN<50&)9$0$)%tm^LkF3d=aN^Jf8tuJHLy*S2V_% za+XNO3K2p2O0Xs-%yQ2!o(Nu}vgm$GA=g0unl~bv6MQwgiIdixu2n8i1{+91C7tAG z36C;wd&DbcYJ#aa^Aay@(g{5;rO}D3BR=^ zCoNM`K1OLyP1{jc%+yqaj?#wE2NIXVbbbnCzFYXs#&NW%S|QA8ii4{fF}S-oXQB^- zDFUJzk8dpRTQ5VRea#ZT3 HK_~wQFp}&O literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_ptp_img1.png b/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/img/acceptance_test_ptp_img1.png new file mode 100644 index 0000000000000000000000000000000000000000..5ecad9d06d1ce29c5c6fd4624a44c08f50137216 GIT binary patch literal 163741 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 dxq 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⩔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 z zFcef&AuG4Dr>o^liL4Ce5la0S*dO6g)rkLiuj7=XGrW}paQtB#v}ikVuaV5YkZ+TZ zO0CP-Xjy$GoG0JL1aSbqn}v4HSXktkYREOp9H8f)!iYZT?JV?5)eSI}@Ve`qV(S5Y z7wVD0@oe}QpF8mZ9Ig0-*mrzYyW<*`)X$1x|C=>%EGBsQ^hgnA2?QJ#pS{o9?J~nK zFfdG&=s^bV>kXz}Yend%`&~GVhjY*jzotxf*><{o46K==%S!Ev9y-8# zj5r_$%RmoBe3#%Oz=uqVsA>Y!0w1P|y85@uN)MtnK=yhG717ET6JJ*jKO-?$Z5W;) zltTxDW(Hy3@q?tf{nJm*eKj(e9Wc{adfLY%OG}fX=HDfF2TbhrJj*X0LDLr{HUAdL z4`L`WrHuPAFm@B2n9u@I;L|xAAYBeVEv+j?golTF$SX6XxVNiF^pggcm)F-f&MXKy z-PXoqQ0;h=mKUFS^mzp{OYOASQ=@c>0zH)HKdlzP_4+~i)TtANt<}yGss3I9j8CAQyi9n#VGO7P< zfuC2YB*>G|LPaO-G4UAIdGc^A*1NTW8(utX>p=IS!Zw|*>b<3v5rRG&Aa!>kWhhc<@#(ILXaT#sL|(yxchlJRmbhrIRD+@WV>xj^v~>!x z9_^fWA_kUYaiah}cpYa?@%^<1$E<8NRG4k#vTmzfQ=7|~uLloiylVb#?u z@^gt4*nu!zUaplKVvJvlT~tEO8Gylk8M4;pBu>@hjHc9Jt!q8Y1rcP=IP~x@>?X6e zP-0!kCgk)3kv_woC6qZj>|q>{Jg$iE&_qsFUr@)50@&rOYA~CTToh^d6hT~+St8*u zCpq>O_fGmAd2ELO$sw;F8VBD|fe~wt4Pz-B``LiXVuQMaJti$~EfDz5e#;O8Y^?wH z;1B&bK=bHli!T3(hvc*GOaN>O`{n@ri;EW&G&GHnez_ts0aEEX&R|e#am0Um3&=7( z7-q3O%G9pJ@S6`#0Mkl^!4KQ;=R$pieMiQGIhMR4)iK>l@8y;z1t{H9H8PNh zsssRdvPGzYhUb5uXqW#+5(1bSv}lrobDV%=jgOF0nOZ&oiH(?*Pl`<40K9czKf{eU zbWDufSX>-BO(7IW+k!&FY$lQ_!~4#+==ZxzXhHYnI7NX6Po;uEg>Itb!O1YUx3_a5 z!VKb}Sahyw->VOYGrgR|(+gh4rsE;8r=iUiRi)A2P}f5WKF_u~#+MII?-wxRR~v~5 zzrLAUUBLWBjr3e{r{R1M{~D(FS0s1hOOf|5j!oVGCOm9fxiTV*nDN;3PX6ln!L==t zJxAsFw`pI;({4~U!pgphH{XvQqrO_`VfEZCvd}6T3~#|eUdxF_x;YF1DJP83K%+fO zV7yQl-VfZX|9u31{#PDW_3zG(;2ux`1tL#uklku&xg1c1*jLaa4Vc6O@P`c~rv9S2 zaXf=6;1Tw?RE^yy|Z>fyFR2lv%OJKqq}6 zIz@(mci4F?sKn^B7P+jBmv*dpxq;aCMpjEszNDh&T9v)e`80R&qhj$PD(Q4Rfj`3c zdpr=}T8$fij%aJ4V_*Mrh<_PRRo;p){_h;vhM{rN3798Jj2h6bgG}jzw+CxI38By_ zT-yOgZ3E&O11>IYWI4v%mn1iDRjqkBlPl-?WI*xzmoZDP4EBEq5b^&VK=6MDFctg+ za84x`-GV`Y(X_%`|9`Be!A3hEn2^TJ{re}uj9bx)`11UGDS)oOXl-Rx%7=y{nWx7B zSeX4u|MOidL=@9LL}Ck<^9!s#j#Z>sC_7D6oEb9+7F7m+mKT4{?DtM2Q;L$DxI+u= z@jPhW(Xlfsksu>|Vz#E(im0J5SGCTKZ%-qtVh|rwjflwpdMtRig%slt~h#`s(JEI?o9lDx8qdwe?rI5 zjlln8Wp(i|k|EJWH-$NgInLQ5&Sl$VAE7u~M*MOSRI#8E8(&+t!csis-iV2<<>{WQyegO@xRy>q*p}KqRw!SL9s0=Y zX^JlK4j9%j?!JoILF`P8bmbWB{o1oI<8gG@GO+#n4`zr#$f`x>_S|Sn!{CRi2-;Yx zM2}s;YPwR-*`Lmmm^e!W%vdO>QKyzccpr4)&4L|21}XyhvkTN@$Yt7ectQLi6tNMk{MB#r5{ODrq)M8nH>c)lw3@MO)9=WEQu}74b19?U} zKue{Xxq^}Sz?oOVXaHF})^`)WWVm~QC4nzB0BiamHm77RQ!XRY-&-~cjr^%!EIrLE zA)?}mV!3&vm%9_NE%rLlOQiLMM)Mk}t2$VhxJtk0y>(ToG}%J=YLw#b`||-~&MA1p z?_#FV?A%+9t?}DazBH+GwP(+=B0@{pCHVgi(qZb#-(9vhXsNvk+P4Wp$t_n zO<2-Twmev9h6ZqvNJ(pLBQ(GX3KY+uIGL+O>p1HJp{S>?2_yaty@o;)D7O{7(*kGp zUm^|xVIzBv7Exw{&(04dP63`9RlGvHoMkz5^i{XpqJCRj1_(oC|MiCTzvBu2++VJC zIJK|U4K#(N;KU@zMO|;FCh?bSHofaEzr0 zPbD#^QUM`)4TOv5L>y+z1qcFJrAqJ*UFSBol-p1?F%+&U#OLk2O?-u zSDt;%!$b!u_>4ho9{EOh|A})T>;Nh0ENO~ywH3m_pY))q=h%S9d1bnKSGN1O)ecrI zDx&>cX!71+$kzkN3J4mCRBYC3k&6iIwPiQmB@yCv_z7tGJVL1L)+Nc9S_hLTo~;7o z0=pYD0(wNua|l~lf=0bn8%IYDCBX)u-lla~G7bYK<(P;j8dQ;kA3Rh=kWhh2Oive8;3czi>!|5=6 zz@uYNvjZu>9hT_F-{M1iYZ20@(iv&*c*tvMfu$K2`oJ~28^s~^xHPWv@}_{YU+9+0qAz-ZEXxyk*Guq(m+9B576?N$IAI$fj9qK z4gx>01X&hE_q<`qsO8t9ufkYXB;4>!zUi10BU*$yyaFW5{)96Q8laZpfW_0 z^uRLNcve?bpvkR7pnVkV=VW*sa3g>tjtnZMg%uTtRg8Z@h9rV39IK*YLJp`e%58%A zE9>bupHJzw-Ak2*fCGEb(3?C>N?+i0MI=H}Ds`gKgeuLYD{sWaCfM>eV+a3@+{b21 z1j(MMnjn?f4;f)w-o4l%-rd((10|1EuObMqH;qbQUx zc45qyqNbCpU^F!`WP&51#OSYSMOCbVI-`4VlBq>GzSp!Qwyy$^s^0Vm~1mer>S0x3uXkcXXU_+`Q~^ z)a}b5QMVwEbHt6DPx@Hg*YP)T+;~o$y!q926l8UJu=Xf>Y=!FU3H28y$ZC?iIxPq7 zIcsw{Yz)_@!L$8X3*J7T4DTUiOtuI42nl1+DjJ_1yDx9dNSV(MyKnNE)oH(9r*zf& zy*+QAkJ|4d1+#dk+j8k%>m=_d5ZwXIS09@)Hf-Eb(B?%+adD^utvDwk4G1BZUT)+W z2z)ZsV&tIQs;W4^P(Xy(6kBox?=vu=x7F!DVOR_cmRO?NRrw@PPAwLQgRGu>4O~gw z1WlYX51eg!HFJt!Lmd$UP zULX~9Rw_xDsi)S%qhM|2GzhxTS4Z^~afE-NMrdCH)N~p~-!~FOpvJCEQ-6&X$q>*c zQ)A7){p70N&6n=ps`TiawsWdZJx|b_{9Ig9GvbEP+I%W4@UrIeN53hSV@d#8aSo1| ztfr}N*SAB0k&$hjSOyc9RwmgOKe0MkF5H^e1XGJvD;(TB7oN^c{WX803x6*gigODwFe)+>UBYI_B0fOs+8kno8#l-ORo-@1U5JzKjm|eHa5s# z5q!p0XfKaY`h3NhJC^Lh?1Z)=mJ4A2|6-+aVnsoDy*er~HB^Lrfs_a;Qy7Q^3`-? zcrltGcO}tSiWwHCoF|ED67Im^C&=mD@pyYpz0E-M7?okQw|F8);eLWy+l`GHd+%;` zGPSn1Kltw?bah{T?o-`IP7Lo~9%f@|rkT4h){4|3or^?K28`667S!>_6pkPg4Ckz0 zzsR0)wj^+ck?7Eb7fTg8$(Kf6nHK66u|IPU$xHg z!XLOz%Q(Ob5z2{k$=C5qo^|13q-6T4t&-_5hKeBIG|eFX%uBAQU*n z5HXJq0|8QWb8~axmsdYw(l~h81YoM6ICs4YIAO>p0K=={S_N%wg8BLRe+vuwCwv;T zU&oGVVCI=Ic?D`CG;5~KuoStj=yNM@(@pYZ#MK zf!p~>`iP{=XiVo~i(#Ec?y>wXVA3N}Z#_LJwghHXeN}Pxw7q0qxCIsb8smXv^X0GX z$cW3h5Px3-+Aei4|DGzV$zs}zrNoE0ICI`y^-JEE*Pw?$*qUg6>x?j$?`y-Ftv58G z(Y^z(wp{3k6APzs9L%4mk(H#;t}KY9=u9oyOd${yq}{f^L%0i6!yXGyIF*n}EPE4% z5m2`^%@889c_}QP`x;VRdwcpfQw#zZ&^sz`vIm%L>yx!()-aE~OtkRhqc{)XXkL~G zzeU8}{~#nhcJG`;7)1U2V;SQsBnSv_L%SnWQ~S=IDTd@AdPEA+amdr~(61O6L&gYu z>px?4tCs{1|D*tYkVPFp+%-3+!I6tbgNjB{q{)Z`hA~&A?6tqe7tJ^&#WbnSw0jHW z=xd`Hb=A^VOY=WnpsDQz>MBFo1Wsq*R%HnU(ZmXuZ6!Mi)r2^r-&5z&!HSZM`m*&@ zQro7AEv*6xW23m#kttMAOh)Y#)tcS4q}x0t|u-5Vh ze4HJTxBv;2d2(VM_9#t+(6X2qY^_K_G$yq^_UI=z<6qZQ;&~@ur(Mc7UrE|PS<^d% zgS5p;IifB%xF$7AEL~MmQDYlJ?23FVt5;7xdd?#>(8+ODPRat1W9;!}un~d!)3wYL zq|0#$)crJn-gap3!s5OuviZ~fSyD+&fw7xuB7cwdahg8Vo}2^tS;B_;lG2#Jp#Oc% z9GJ1x8(t1mI~`>3RQge#W%&+fKi_~Tn0&$M5~why6ZQyNN>6z_+05Sm-LyED2A4$M zuv_dnU1RBZewB!L#=#LHxw+zhvn8%n<0#4GgmtOG?stHZ>C^K>tPf8_`pCEGl@Cqp z_nY70k$%7Jxo`9A!u+EL2Vs-Wg4;pBhxG>9^15Mekc|y1ENUzaG{%@&AEnh~Ptw(P z#>MisvX}}S&ucW*Yx{c6$_im+^Un1f7ud*OFJRi7jXh1lU>q4P$SOU#YvBh{uo*i+ zV2_cX--lk%q(I5vDe#!XoD*DnaRl?2XOD8SInXR66k@8VBv1nv-&c1-><+H~WWETsQBi;K4!<&oEm9s}sXTs}t5hBunT*9gHlLnV0_8$jn*hnre`R$yb6 z0p|+BcQ91Xils&u8Od%^HxeM#rb~XSqkk-g^s2>ll1FGKpb^(0IBovUrc6xy8n^*I zA^bl)eFaQhUAS#=cXu1yt;O976p9yjXo2ExMT@&T6nA$hE`z(f7Iy}H=f5}a?qtX$ zGa+-%+56MA)@N2V{Ao$_k2?c0^tR$Bg1iVYqG?}9R3wF{?>m^^ieLWN=1Y@#+WmCf z7DIy#?bII*j1e?unY!Worr9-OTESBv##{N*_8C8k$wr2a2s!*B+KQ9p*Z1G}2(u^d zm(QXHZz(p$n14?TZ11o&>GzFa;&f8mGrxmAgPpp!Mlas7i<6gnDgCjEZO=|RY8t$9 z%FbJpi(B5>{kE3Pn>Y|-|Czo10RI*^h8uezj_DBG1iyunn7oK^>{RIAB7e@nk^FPK zfufC+y#A&!(S3_iL3$u@By&Nx;dy5(P}ly^uZ7V16_U%X&9vPJKoN%8&+`GlD!So9 z@ME!(q+$Inq{uqcZKKtD=W#c*o!JZaQ~y$-XtKF6A$(ia?wu!aBp@or`is*%tfHGI zci4!q*OOWKG|Il>^h3EryFDj&2YsOt%=m)T`80_55dq2>XS$lxiv;wGtIImj#-gH>&xntE>nriBBEM+kGc#e_NY0Wpr{pr+YC=@&jh_+>{u*CS0%VsU6W})N1lbHmrU%uWn_bYcJAX!w=3#41YG08g^L8j&J=+ zV8lef;tIHHs;1`e?Mnx}<2CjuLi5nftHw^%$}#FaO#4Q->!BcKv9au2)sg%UMAEfn zfnj;~FO)Y5vJ4`ITB=m>Ul)xyTD<7jcJzYmN@^p(!`nDR6q6o@S%M`Th&1c`N1!Yi zQrWa!9vthFijMoewY(;Ug=O8;el1~e!sh}Qf@4$2V`-?GaK)xga&#g4wc{p>aw%Hg zxumLPii6%S4_OJ-F1gH5lZT^WG7Gb&j{X_nQ63`g)YKIPk1R|3|Ly*vg^+*QhcL$0G(L3ZH?M}ma(_{SG+~E;|@4NykjEIy51*y5+!mcG+GXCG#?r>A>G}3FVlqxL2C83FgP|?|bp2>Ok9c3s)B6w)MH{5OkF)gr%11w) zXG=FW)kFFQl$3%a3D zo#$^9wureROUSxX_u;Ym>InRx5#ud;@Lhkf{7IgO(6==gM87sxuUs8D6e<79tc3fbK=z9x zhwVe`DIe;C#`}lg95+XSrPIig3i4Ojsv+;u9`d!x+oy7($h#`c-533znGFm2nXGkN zjEG8yH)@1A6lXe2XfrG|IHHWlu@*#<3vBpg3wC#toh@!| z(*)uTHpEx>UOvBUjcAHdsgqMrccy7kw8trxlC(eq@O8*jW@KUsq%ChTABeF7cL*vt+s?4l^r5j`^C;|b7o9?Z&L zeX%t=(mrKB;$83<4pvw3hbTx(sF^gl?qAA|s?M%U2`*kbBY}Ou#o_drq-u zr`vYad&7h-Diw0g^p6F?|G1#~dM-QoxzSKYLT19bMz|7(?IHH$n5xa1GiELE&-uc; zu|bQ~yzeG>;(iv(HbQ4D9d6-rw2o~eo5xWyUjJ7OMY4PyJ-o({)4<|^s(iZpkO02$ z9bxzD!m9Jjj^_k1FDcm#$6Lk4RfNx#rY8Gmif4M;bb@4|UKCaYC(k~)R}}KJR3DPm z_aptaD?j$y0sptq^SOUstxqcm@;;|OUXD&08$_I#yWj75j~>=W2qT4{qK4OMF%LC+vb8~ZvLC*kI(p*PfOAE+Ova+&h^NrtQ zcT7k*r>re?G&h2mHd#w>_j?mSVa^pW@mY`FT;$S``yFMNs~yP0(i*{8y;OCeHUGRl z83_xF@UKkhO!4;HQPut{xrj)~AgbYcxB;#Kd^oaBHH*uucpVUCdNSsNqh?;EarjUL zRdR7%{zYfgha*Jaf+k58HB2n05KLH3D&yZx$E158GBq@64`-fSwBNrw5gJs!9THN? z#Ap>S);!_SDnk<&_IcCGwYeLX9eHZ00=y1PDztXuuR??a=m)J%G0u`v`g$Q@`mI$& zwFLnIgzCdCyGv~m^F1ADrH}ZNBKGLtir|idn3+n?b0Sv9;?|y+CRuC>&P#AobuYy0 zzS?-~8?rW1B! z={PTz(qNn3Lg@{X_^%scrv5~{^=pa@ahHQ3MxIAw)vvX+;ry9TwY86O z)A#3JH}pD_vQbNVzR{7pBO=T_KR7;?vtHw6C1gG@;|JU{pJo!z$7`%uz~+C<{F@@u z_?skqW2}k5ZdZ_fP5!RIgVgW(IFqNCygJch9S7rD27B(<@Zi%TnQT;Jlx0K3n zKmv*&-_zb-|FiVqI*-#D4C2o)Q+K8%u ziPEgAA3Wb9Nh;;LHW7KdM?7oRw(yU490$7=ZhlUmcRMo^&9cWQ@M9Ve$ezx8oNkNr z`q1bA*DHRx$nCMh^BvEBd5pg%KDv5iuseHmj4|iLkK@yk`_E-L}2_&VexRGn>v$8C0~huyK}6HBa55|7e5Uy6YX z{w{nq#;@snY(HP6{iPpOl=h2gLXZcI%*%PA*B7`8`gA^XJwq3*iC3Tz-wwsagJ_+plC7_i4g-T_fIFsM(O_=DtLB77vJoSkhn5>Z{_ z{eyH?4J=;l6AYfrq;gEB)4G~szt|g?A9to@{VRJGS-`&=FnL*vopSg0ZA_tiz_hzN zqj=MbHcTQyPJz&2DL$V2+M3Y{(GksQyASQZc%fn^ zU~lr&@!ZT=R(GLmHuMtV?))o0Z=-w9OWyj{^Hg1t8;TT^&Vb;(G*RXw|^ZW1z{2EBV#b>FXhH`HhGmEhjeB+K%(#OUCFH8mpc!3Z&oK-TbL)Zou zswX0g=>kS6u_4yfMng-bSb@AIlo>ig8Do#Z4+H+GXV{5%l<{RLa&F4=I|{T)h1i9& za=;W6V|lA-mv48tA|K;N<`PC=BNmiD47m06IA92%i|70lj5W3=Jv92>EEyh}-(nPY zLhbB8loq*GTbbqbU*g>_uX4)l6u)x7h@EtA`>Ar~#86&BqE}Zmqfb^8{6hPa^QoU- zy`j4&9-m@1CPN|kdz`iI=nYB+l4ACFtrPT~fM%^3#7}2WIL>qkLe-e0m1EeCKWT-| z=Z(LgF3xpERU>F@*)u{a?1t(~1e%Z08l7%Dr8UrFCvikp60N;Bd^e}DbO5M>J zIFzX`e9_k1o&5dwuz!1r_}JeMBnQk{z_=pQFKNqNqMzash`#>TA=ntslI`ksn(X}R zhhLHVnnmDonMDAZ3|qXKMft9Mqm1#PHObBX7~+;#vC-I?K?*a_qX^cusrw+{aezQ@ zrFhl5_pym~26oecwl0FlCtl4`>o-Ni4$gL1dx94G`<((U0p0OkjN@wzLA)7h%Gy15 zw6%}gt$g~J{1DGh97u>e#?o#%;-$PeA?Zg!>Mo5lOG}F3`W@-Xlfow5ddhO4VaZ;` zUmejWVW;Gm49gt9ILJ>s^RwO|$awFe$5|Ok>&x${DQ1#&7N19aJ3kXRVOkWf{#ikH zw*t$_bnawwTiKL+B^;oAFdv&{glnd0BUV+{E5zhE(sT@=hY|v zCIi|=7a*E>ruUVh>3)9d3AXnM)n6(i(jTjQcj88Yk-b`GW;60;kUe=3y&i&GOeL8j zI&h4K_z906sOIdP)LZ6ffBfb5cKnm&b<8O?rrhjHjV>QKxLZ53=}q#3hxhupy>ZdK zJx}vXU(YA^lco$0o3mefk7w1KteFM%yvk}NM}Ht)UuckBir0H_iotSeyleNNz7gEx zEIMiZq9=rdf)0aSNTl4e;7!dAna>9tbV;WfxFiG>gB2o4eKN~14vb@wG0H)Z>iP<> zQT`SFXF*yzA7>d6SUnOKzEF+z0dAB}@qnfA->MZJ_lgoD?6Ew;fT(;t13UW=2P#kq>iSv<3_C6h zSv-+kbO9mltY%DS>HWIDl#J_l!qG)d3|>khcmyF9f5evmDW!&z*V9J5Qu5V!C4V(t4Ado^2fm~-P!jw|Wxs0Isj&%r*4{37|pRegGpS`C+!-Rdlh!KSj~sg)y% zW(~jYK;96=C||ew^+YMuDMX z|HR($wlQP&_NnX;#kc&%oueQcpVU0;G-n>mF9PZHU2_xV4{x#WuMe)@-XVz9S)Pm` z>pq3Y49cncdY#(Te68Q7z7HmwFQwf{jETHyr*}yEA$&*M^)cF~sV@|N(0@CuE!ZK8 zPg$8Z*2W1u(DL~7eF3tDJDHMS=q^au1T_7nH&-7nPv|vc|0DyIk%`l5J3!i_ zphE|wj{erEePJznhS36TjFlW_O=#wX=(y0#h7#6Ns(Dg-X zwRdP;?M6@;GYH&$;9S(samS|4OAeG>oR-Jp6o;>s!#&GW_k@0#-GMP=hCMj%VVwKD zrbLBIav>d|_g)K4Y6(mN??$#C4D-f!dO=gg zxBNdQ|47l($Ru{e(D`e!Z}GafuDYuZc2kr|I&w5W3F|X5t-yMXLn%A&$z*>wlX&3?HIiO9qoduD)d<%MrP)| zx(aVO2M)six{3}=D?<1jYiXcU>D=L04ZfHEo?>`@RRFT0v(t2p$r8R!z zwW)vT-Zy*?uLxXG) z8Ngwc9?L^zdMG%SA4o2x>EcRjZpSQfolzm{L8~KKonNz(BE3h-!v6gjF=*S@xYwA$ zgFbC$bb#x$23GglCm0t)x;Dc8>6VD+)6bEJ5ugpyHv|-6Z$dcfCv!p3b9BM>CbB%E zUdRt&UQ-Sz;hBMr5Ywt4{5fQaWP`p6ex(MMCAm;P>>;HvN?m+SHf1mN)a8Mf*V=)? z4D^2a3?0u^6HEbrrZ0ZR6$ou?*Gp(tYl z_hmu8B$?|hcAbCf#Z4^N62>Cke|UQb#0w&t395RyJ>YkL1Xz9dA5|Cv$Nl+4V6pQ^ zX%l8D#X9J7suyj0NvWfgf2Mky&ZJ(7A&u`h;Iq0S|1AM=e*Dj`fr{c7?MF;yK`(eL zxJW64Ga0yo7p_h85hxC5n#4(*Wp zBNr(nn%>zIt-})b(NBn^#b{V~JY?GF}^# zpObaQHRMkc#~YSlk{M0Bl0C&}_Tgn6iTS$SJWND)wV>&cQ}0S{ndwPduq?5<3FxPL z{JxN8T7~$IHe6pzV$^X6q~nPA(IF&Vh&tvmW3Je=<}i!6`E9$HVGsF0-W|3pK76g} z=1VO!9WiWqs7=wHUX!OV@YX>YEFM8~kc)r0;|bnAn-EbfL$Jqc^ASKmO4S_4MkxVFu*)|b={9bGHG_b<5xauI_sA4MHN~s}(GgVBa znOq3*L$Sfqy;~uQXk{jx)9qybv9ju@uD!t;tBqFpf^g4a0gx$U$vq^+{UE|r-r&cS z(SS66F$B=5!T^^5UNU-mbXih1p{yz*1$j7ru7SLo>huIx*_qsyT~K*-ro`op7X@o@^n*>1$*56@#gaK|ApnJ6UqS2u4+>=It5OMzf ztR1WxrQ!jHC%NYqK-y`WWfn_Wn>4;YTT)UdYlMFk73wf{JM*t}m^^^%7TIf$a@AR+ zIGBGAflOhi{zKZoz?l6lrp7;=70(amQy>idD+4+PvD5cnB%e>-`OM30qYD52QJvcbj z`g}ZaTbsHtNW;H17N;9)#-aBMvjhTK)DwweT9>Tp2ruK>j7=G7t^DG!%T7-3aT~1X zdgWYpOZamQqDH>5y)B38K9+|u#ZV^a*L4!wm~Z<9PuR|}S>(@z18?;5$5eIt#+Ly{*N#HtPNOd}{O`;HAzXq{^imU{ z)IX#LQSD&^rt*$UWoA{Ff4Cna)U^0MHX-M)c|oKIs7vLrh83#8F(Hw?{88WYX6A zj{JftdEr$jKwY0JjVHu-FNQ4okwG4NM4R3i!(C%a14$m+M38ELAqzJAr^A0LW(l?5WVkD?x;HN6_@?rXSxRoH^W=j;Y@J*5Li4VPevd-d)Yh{Km`Lvh` zHtn1+UQ~)fod?bt^qEQ<&wm47;Ol|EEts602}xkLH6K#=8mB?z$XI7F?YV(0Q72!) z9NPRSEGZ66?osV$Sg5ug32c{S^;E;9P?&de8BjJSsY^euOfWKyC@o+3F$F|O^zrSO z$2vFq3AEV>Xr=R)gw;T6evBxDEzMF7HPQATOr5RX$uAhhP8Mg6$OTiOzsyWNz8yvz zD>M>d_U0CQqZYj0|LhYCn|#@$*L$h8o_q4wgO@~8qZo~=#g)mj=he#Qi&8+VP!DJ* zM*ZR%+u;|VGjjNry6Jr~OUiAFJ77Wb#SB+1Iu%Tq0~;Sxn$w<5;eF3An6gZ}|5A{8 zHv(?GN{{(k>5rSn;xr_svZJfh{vB-`DN5x`3O$ojVzF~pWODwHR05b$qK-kx zQ{EWra2hEydTr{7WOxUP7CKyg*$ZHFhq66g_CAR>C8ALMD;GZuK}wL$xc2CBx~f$y zo04y|HJbmYBsKqG-qe!2QvxdF%^)%Bl)m!K9-X2v;3u^cM#&O;U*t1N5QRX;d}J11 z9MW!j$r(Ek-eu^DS*#+bTkrHcDVt3sIz*CvO1s+cV?p>#{+(W3;)J9k>}bM=Md zt(EcbTJ>vChFwQ3$GSZpMRjD|76tQfUFZ4&GYue~mGQSss6X2zQ<(;?M1uDu^f zx>u4Mw$tq`C*w+pChY5q6=t37<%wL+t{`LXVx##$pZF7q8~fJrQaZ(i$cwwW$fZ?( z%M<{_hP_~4on!#f2VfrnfIJ5(NPhH?+PS~O#JJjhh9}C1BWUrY@8oV~m877WU70Cq z3?*QHf1h^szbYJ5H(efhDkEee)&62%kqUMcyCjYLk2*%H6vo@xXU5OAQV9sif$3@h z^50mcDY&QdfWZuD@O!X?k8-Y#Av|&K6fXW5j?Pj2Kv(1$y5a#cv=KGTRirk1a=?Vh z5`Ji9XY3NZ0=LbV6VN;|$Pg~R>|&0HFHvl%{G_6+WUH}FzyJe3JPJ0DF`x&3xLD%2 zi9VDNE)J9O#~1YW^u&%I)j_xz!8FJrea6Hj8TZT2Z7nUhgtbK}JIGDRu-ftVN=p-5 zU@qwmaWy%GIw!A^_b0Dnw|gC0r7yB1-$t5Cwpgnv73sl-tNy%pOKopPx?j8&B=@k$I9;^ z@_xh)i!4%J9c^3O1aVaUsHlsP*hE>c3g+)0;a zQ7PiCWec(>JcfUnii74F;i#(L2rgd4dzVu4$B?Msu@FHwHva zHU|XDMDI!=yC{}~{QF71S1x$I{Cmg+6aCj| zG4%%@X2XMdv;zJL3*^R^G)s#2Pf-*(a%ssXpPk*9UQf}S2fcU9=tOV))_iY#{!FGy zRxbCJv)jQHq0fi_C9iHduOkk&EWtt*1{i-j5eIeN_qQQYcWzG(C)x4bXj#ZA&7`V> zGg?|SVWTW*UnjPM(a#rv-7dDk2M(}X~XJRWk`y@iPq#s1?6Oa#jr`bmywZ1*9$ zg>y}e+q;J-yOgZMQ>oe|RBO)@_k+qGY4(~@8)zkSrqbl31`w6Xx$MWLi@fgxg5t;y zQ*f5E&LcUG+mk1)Fa6)XyB)V8rk`!S7$oV9Dklc-=8z2CE1RrdwcL^k1Wq2RfR+Wd%~&zwk! zdgKY|ORn1Kl1{5*YsSL~j06vHVMRrxI#X~ygR_f^s)2zrTZ&{nsKbE0ttvse_$IF( z0F3?*rg2n@gH1+5LnynKHOyHcDt{QD?|WN0)Pko@?tmKDumwtQV%m||-Kf+owhl^% z4DLu`Z2PBzGVE+U3`kKO69Ck?EMm>Mv5 zC*0mKqKe5DCQw{$vHxQ#Bv1)@G(jDeJL7)pObWwcGj#swwWE(1! zk{)>UGHc46^8H*I%ifG~53egaES3rgV>#oHDN1SAU?5+KDH1q^y$BBJ=R7Vo+PwM% zUr527Ig4R)r1XiR*nlDLuj^X0)5ATGSUW@DJ4Gq8}o< z@$lum_1JnQn|N?hE?-;beb?O)?fu)7($Q4REe<>s5Ah+H{M}~G*0ENzQ~wpc!?NY# z&FawkPEm?jxkwO75ye2zAaE$25H}x7$0Q%#g1a~Gk&#dmFA1aDF72Z;NZk#4lVrFj zH(!M+tey%08i*aC~~&~qTmje4L&kqVo5RIa#mOk~Pn^!+m3H-tOO?!%PLH>8_#|) zEBemU!I5O#MP|Y&uP~OE!ah%mT9hyTMuhMMvN3}vclito1|LuXsICyX5cwC8=3Ex= za9yM^p|hLYAxiS!tpLhccI_QL=m@e9^mq^!axfq#CXsBuvuHl0F^^qH6FK5-l4?7)HHz^6F{@m{LyZ(EY|voa@akL zlp_$O?l_skO%d*<*)e_#gAU44UasPjKl5i^FJaqos-`nRQ5n%GZlbbjNx`#5cqc^+zk2)WP zo$(es>?uF3c_Jk|sD^iT0s~mt7k!TL|1e+d49N!HL#&1I&n&K(QTXm#zF?xux_0&2 z#e3esPqdk!5ePlXPW&LPeXzXg=rY5awH%|4V^E@OwVtIT_k6?(=%EDE?QcYV$W6n8 z#6NV4{vE~p$-V0j^N`Asp?G`sFCUK7<5u>541N=4h*Z$~qO%z(v=6BGK~WM%VTVas zSy|;)RYjwbe8fbARlyBbVF;Q$EXd3I1<)I?C2R=c>sS)N`wYy?;Gfmql-h~_q3hz| zaG?K<%@mM)w6z`JQR15ZXrgc1FQ|)Hl!5dQ^9tEvy!zJ{xN5o}F?}|~AUxk~LLSx< zG(@c&8q{w~#)FB-foG01*!YbL3*LrLD1k*9si?Y?JgBOKw5GowV2>1#4~>LivXH1S z=}tQWp_GE~x@V#E9mzcZ*!^`=r-;FU4u1`*e1-j+yp9PQN=^Q-!Y08mE=gEKiTp%q zxBxDdN*4beDEu2>iix4PxV%O*pkWL^=P_dgPd_!q(DTZtQq-hcG3)z4@M5rRDZ^oo zQ|zQxlMB(69JX|CRZwt}8emst-Q7bwuK?;zgQLeq$?3BB|?c+&C|cRx{Cau1!_pH zS}7mJG;IMRUJA(1F+U2Yudct2`3E=dC(Jwl2db4d;Ky?JSdML zP%9r978;N{6q3QHghqwV)Wmo6J2(nUdlrfNyOf-x6Ru1O z5`uBpL6wicb!IkCMT=mD)L~?(T6Sh8 zGMtJ6F1{(=mTDw;AF*injtqC9Fie;eB0Wk{8;aszcFsO~WZftL*7(1sR9(t{O(_=U zKVRiRI!tQ^J)=Vyx~aHKnz-@-_Z6Lt*dlL>-DeHsI+mGT1YR{1JExfRsB7pr1a>_$ zo#yh%tZ&G=R$Otzq0B8UEvIDn7I?cilP)o#Uf3>kNZz{#I3evMUT};;F((vRpE`VE z%_}I(Iy-@j%^1|TAb9_UXog(c%k3; z2|Y+W=n>&nFHpMIXu=i!0QI@n%2BEp@DxbTT)n(YwqlSjPQ-KUo?LruSa z-IQhe|HlGcQ}tmX{_MO<7H(UIWACn!Z9d$oYmNn_`HPBaY0<~kU1wEaQf+mrGv9mq zG&I{5B^GwdYWw$a={ym-*p+07>Rx zlrLIaN#h(|xI9T=-~ZNuG6P7w`fuE25QFBSs7Sk}q0JL8wraZG@t@`|!h$iMS%SD# zZX0tKS&;knGX>v6l zeF7}A`DJachAtBW`;y~bEJFJ`Tr(;fNk!A9I*pF}zTG+h(%UdP0Vrx_h}*^#U6SI| zMiUws`_Qg$*ypIb?-dW&pxuDWqDcXBT8t5TdU+wiLIZRnx`dv?n>>ba{Z_uuY$+r> zp}A_YQpx-JZHxeMwp9=PKOvh08%>+l5f{YEL1y+kyW`J6LMjBp(3?Fn1VBx$|5l0DK(0a*$&gCoM)LUboYwN*WDd;z)tp<0%mBDEa= zrUad0dhh+ct<6eHwhdK%894L<)_Ja)j)t^`(t0id2hh3#mKV0hY)Mt+!0ug*BZOA|nvXtzTzm^>j&d<@sI7PufPVkTb)Nm&K(q>CtU@6oEObM& zjmc{UyXrB42fPn4Ebo;1B`zNI)%RY3Tt*WSL@X6GX)Ns7fTvhYbXvj94wfFjPvSgW z5wj;BjY0YOqL663><0o^rO)bg0R6H^1CeF|zZHQMmVY4hc@#$M=eu&5bGQ0g(?)(99g8yA9KEXxDh1?>0E6FU(7srD3 zu+S+O=(XCB(h>MvK2NBNS=`X}j+McESPND9K;bzbAg5pL4yggwoGEFv9RmI91HeU$ zbywB1uH`%0qqu#3J!<1a7hwCFHNCp}Sy~$I1E2-&Y_qCxlK!d2M7IK*A6ZS>lF{6N5fnUf>U{XQL~S9t$u&&D1zG;iEFOuHl4zP zt)-~+-R@t`UsNvK$<(n&6PV~RSv2B-d;9nLnba8(UhU|KY3Is-iwKPnB^5TXvu~~b zLH7TexDK;afFXyk;yc>;zg4HES)~VHe*2_qDG4K_ZMRL~fFH~QOn(C|5g?cvq`Iy7 z0_;Nwa{ucMqJW*KEQ4a<*Q2)VYAKOK-6@YmP#ECJezrT@aW%0RiX~A%i^P4I!h#q6 zE)F|qM)hG7+nq-+hB80OEEK&wUfYg}JWJx@q}^B@E^%ms3Bqy}X+<&@?0y)8A-O$$ zbb;N_7sguNfGEF!sWyR`pG$+8u9?RXhPxsfERLYRSWT%MWu9UW*XuK+5|A4Rl21%YF(rftF5$oG<6)pZ^!Icb4#Gdp%>??3 zHvvWtg2gK}YLUPQtUbvXRxmNwA>b4C9Qkpjx9<+$6>H0kcVc9_V_7WENF6EM^snZyczl?%asYSh#C7G z@4R^GMWY2wFc)A}j`$Fs>!uQL+2k6zS|Yp_%t2eEIePzD)M$tQvn7BgC9z(fB))0k$bbvLZNJo?D*94woRG3*@loiN=|GRsI z`m_;ZJQZs&!TGi?)j@5zRdyy}FW4ZC_#>=>K?<50W2;-kMrNb$9m$VW5g1KEUsu4 zXsUZ=UeJlJ9hhM#cK@}(sR*Y5c$$v0-9>J3dxoA}F4@L@U{skku&aQ`AnQx!>Hio( z=vd{#qvLZ6aI(_v-9Rlol8=*z-yA_0VLL#Thn1v~=)n}}&Vjn8O2GhCiSh9SA_a(v zpgwlyS`!0B&!QqaAZX%5rMWo2@$B>9c5H9NeU-U}eAcZwOF{8Zkgq6pIa!>EAG;~{-i&4iM&HOJJ>RNL9HhA_*! zEwDDFp}9Q1Laz=rem{H6gG1H9|H8hk^&p!rHvPuGsYvDRDXPIyz_pF z>$hCOOC}o?=^H<`x^Uz{(`kj-0?8(^g(EeAF{ftt;Q)~0_>xZ|hUOcx0)riJ3FIxP zPR|IGZ3sXPq=CnJJ-pf-26PBWx}Z6;%QwIK2|9wNo0_igwhe2HMJ|; z-CX@iR%iBx$NlDUX|da3mdSZgdvOrDg#aZxB?<>WR+xVuHO)7D4mf=v7q z56@8C>IJz4+cU<5CM`t({=Sv~!YU5qFZQWr{X4i+x3*0;X5`(8LeAVf)VZ_V$7{6I)ba+uBMI9&iO*l*{bH3cq zVkG8^yg`R8mHr)J%qBO-y65(+>k{qTmiPll2fbp`Axlx?;o2aNpLcg$l@;M)3AR~HZXa&INU4zubl zg*Nk^e6%Tggm4yFqh2c(R3@ccv<69qqC{vqp=Ls5VmjC^77SE&+|?Cz_T(=F@U~eq zlp2~g)KZ;#6m!zz^mr2S&d9`KutMntnM=r2VTG;meMndAc42|rE%pL3E>keUR;<^o z3g2*)3G!HYlby}JRr0lzdegkZqe5GOUijg}5B+)dL5U3_={T+#Pj7%$n64@(bFvTn zfH<&&;y&!GsQ|*G%F5^G8+ar5N1Ezmqx+&$tr5=4&O8F~VuXNx0(?CZeBj>+99Y{m zyH6p;n8?AyU@*+r<9=YWS4Kuek+r)}{$w#AziGk=Ace?d=$9?0Z0}%Q+SdWx!M~G} zgjL|)0rD9Cy%nb;j|uI{z9XHg3?Joq)SqJgjOc_Ui5SGDf%sEd9S*+==k-IVPL=pN zYzj0(jqE4)pR|f>SgWJAz5WxuaD=r%gU-#l;$;ns=U7(IVCEo_TBaGP4`E1+RB=WX z44TWFrH&@LbEvw7eVm^O=hQE?dyRBhA0zgzDuhknUsojjyhMHFLB|c>960c!uo2C8 z+$$J4r#w&?-SYmp7#mJIBmbH>%oK*3?LHKv4Af?6i?~+@HV?=aPDi2Rrq(OTmfhD+ zED@KPr{P^r0QO9WvLRS(l@^fNtOq|O4VZA|PcsO6-U8lg`^r7uDF=|D)ng;*F~Zc) zNT~V?ME-i4Z@SS^)b5=ddxUGdSD0Z^C8ec#ZEb*TOFU`Dk90ut!qU43UXN*R(8!*E zD)X3b%n(JmPK~xV))8&x^}{-Gr2Wx%CW*|G1Qbrmpzy?luscBnshD0oJf&NL{%vv| zwJOnd|M~e|q9Z3A+5yewnsu)!jywUTpwXZ-1seEm;-JJIQ-$FhVMRzJk}5g~**1)* zuCS-ON&lTPYT%Udq}#)<@JaU+jfTx;90DrGN?`#Lhcm$&&Y^j1-D>~s8#z}LU2KFi z$NnM}4UHy`J_BR(i1yIMVZibt2)&e579b8U*iaLkr=d50RBZ5CcTj3EyB zXS&YHf#{j<1LA@%Q#|8zPUo3BdB+`pg1Fb2dO~7~xp&(|GF{)GaGR3ou&(aBuXk8J zq6uc3!do`QWOg@9i>b}RJ^Osb^s6jSw&e|;;Zb5@{-ma+5miOMCnY~qgcTiRBd~vv zS9Z2D+_2uiIJUEWxWIj$$-P9=Zt4SXafD#tvF9S8_BJ~5+No3B`ab1&|=mvRl0$cM<5!SKtS;asMr9dikBB}bq%F^LfClufwn3&Ev*z( zQee85@-IM5x8OtoK-V^}DgleD21HX}e5Yw#gn7`hpr;`I+s6*vvCdym%W(|qCU>dkwZLQQ zyr`n^eI;&5)_ zeHyQhLZ;D8{N&?H`-dSCqb4E;d$jr-zd)69EK**+geDChbL=MC0*yh^rDe;-flo}=2-0;6HYU&EwP}u_j>gYo%RFEaIf2cvE7qbN+@ad zxgj&NXQksm|Dx7D_JAKR+zMLm7n}(9BI>LmZWXR~re>QJnr^3`XnyE$JTSlDutvz7 z(pwmKpi#KIGdJrCM57laxf0qeMkicfJL0owi&R8NjRNpgW@ey13Fu#9b(wrX2P9&E7%@Qk*A!%uXZ#O`6`@Rm-PTps zXi1dBVns+kIpS6I=Mc^ z7_b)5O2U4}Z?$A&!`M1ZohuQ}4m{o8xM)&4=<6W{O$W79M)ee7_P+$1nJFw9$qpV< zlk!;Em-Exf39udK8-0EiX|i*e@@Q;}6Dv`B>*;Pe+K>)94P6s&ONuti>HD%ZT&sV@ zgx)&x|HyjB@VvSwUbv0zG-l&8wr#tO+1NH4qp@wrjxil z5s5<9(9)FUE)Va~VhY;rysqc5si8z^fP=+$zbV!6v2auFz#zo&T@A}lF_xpXa+u-5 zerq1u-O`@xDpL2<@!CZDDg@QInH|&B^tX%r=+xNmvPXGJB49`0xU>`9w*Ds4y&up;ku*j(T%8k{Qv$0C}5u5^{NQ=&{T8Unr*V zfi5+n8tBa~7yNk5Z0}36(J?OiQaZA?H27K&tv*-Fxo>~gn6XzdYoxty-fG$g(QeXE zpb*EdOtE*^t-?I*!O_~jQy7GWGwE>Ri`1%udV^v;=#x;QfiP^T4DU{}qribw#!i4y z2HQqCB275`;*vyVHpe}56UwZ7uyA}!^6vycDT7fOx7WxTyF|#ebH*9t_f9n}((R4A zx!7L~3_x78jObe|s#;F}lv!*yl1&+Rg0j_6k>!^D-N$uizKhbH6S6jlsa+M2{-gkX zG*KbhRQ(QHi&LM9CJS|CIPVF+NN%FGx4Z1gzx3_=?V7yEIbuAK!Tvxb*}-{V_Wad*X^|(zf<$wyMR>N!p4&EwUZ<|z zm6B@&4ywMiwA3asASdc(r*7>GfN7A%!W5bBIJCwc^|e(|ssv}+^xVc79$0_-B6E); ziv{&Le4aTEcDQjJdQp*}`uH(*-n%)8hNDRe6nuThy^J4R*OtI}sGjReX}{%y{L>@o z(zFF{bYXsMR`{P1=E1 zvdnPOJ|`NK=BAuFL3Q)r>&j~ws?JUw)yfH`a3^V}wGLgs4i_Bw`6G-&h~bPLG6i1g zc#yDcr3?+e6%}C6tZ`xMOh)?3nk`B?PiENpHh0?F>a?iPi;6#DMh;yq9fl^D*H z$1uL#J-sTM?$F{-k`(K7OBvnR8z6qmC=HEvus4d>@;wowu#wSZ0dWcO60V7Pt}+`V zaHcS&>M>qy49uU_nwCMRZ}kT}Xb4`7oNi1YdSFKAdPY)iYX9bym*d~#mB)_<{X#F2 zvU)q<itR`K|QFx5q*#k%^okA1sHrR*_}K zUE!)U0sr)K{>-k$Sxnp4D1i==b637?@yYLR4Danu4DXH?T(>vjOBGo!3X`3*y+0m4 zk^^s4w$!XPgp-2#PVKL+-9sfz?DJ_avHnGCfs5)nf-7v@GiFz5ONdEA zYyVA<-+6SL`s0_yZ+Ts!(t7AzH06~JDWH}QzL{};o9^@_`Q07{$9c={0#oIw=&!I% zyAvrF&)?Cx70wrS8&8IA0}UO8jlQKDbH@mYq?_LOt?iWqig){c(K<}*wfdxi;&J`e zb(WT!Kk};Mse@XWd|WS8GF)xNc=v?D`V02jcl{9+ynltE8V-owv>Z^lb%NWfI5;oXAjY|&oSwtM#kPLPeG!%LxApJHZ#QD@c0ylX6|>MDo#wV7WD7C^ z?R8*+_U=&Z;3@TaV;$HAE0}lrxkytvaWP}W(1gh%$-WKg%LbKOMViK4j`0V^(HX%9 z+%t*61;r%|x_4=|yCCX$G1(S_ex6`L6Uf)naZTg4z*$qK9h3Bd2le$w29KqDs+v5t z|GR=PaULX48}^HVZy3IrS2R21J*M^tH=6*Rp}U%`eAlbp^P{2F|PtI(*S}#pnBcfRXZCaC~XX z{QHH$yU!ReTr_98Z{&&aW4ng?<UOTf3Xr2ba-iA;@91sm2f5wS z1is3tjf3a?_k6k}%zrh6Wlm;=+9d=#&c#nC8TCT zqJrKOXv@z24~~X|OKnftLlM(%QmOH}{Z|QRTdz^pvM+X93$DxprULSvw@z@oY(tS&JRO@x28dw)R-Zc_Jrnc4{=5YeNX~vClB^bdj_7~fOZ2^pIiSJz zdOXr*s$iK{&3Tv*7a=cqB9ea{>-h`CcI^B5`)H16r|H#a-9wv6%W}!QPmCz6O~{8KqWg{sbVV8oT{sk z_l1*6yIU{)S)5koEMY)kKr!i>G?4u8+I~lWp&w0>Q=S9`9ihO{EoB=3_fW?-MXbj4 zU+S%P>kb6_&z06ErI!h9Dc`GUNP~Jt87m@w?o2Yo_U0IuF9+lR_gKxi!NR`wbFYQt z0ib=8mXQ%)kSQx0DVibrO~`vdGs){2fyFm~ULvxn+vGBztpaoH^Sl+59JZ--zJNE2 z@87wPmq;-ar9tC>Fj)U{1Om2A|&7~Sn^yY1{o zQ-*WhZEA7mDT3=!59v8U=)J!w*?3;UvwIgXK0OOCllAq_kEOocO3WjILbc>mB`F~f zm!g)N5A2pax0D+%-i<3f5)Zz#r`YXnae1b<(0u+sSO8?xr%b85S*O#GI|A~DY00x{ z%8+xu@c2pb`k$YtI$NW4i#Nwsps{j3gL`C*)m4A=Nn}?agy!Y_WiaY<&_WlRSuOa! z$Q-uDgVni1tLtq9DHcLB)zZPv*vdxpWU+7L73cm9i*UhmO&D(sODW|`cn8uhMvwN4J5NBK&3RTZ!VzP%z7 zdDr^)#T;cdO+cLRy9K*%`@bF~-Ea~sK#DULP>quNdd8b#5%x5qqj_D8w_DM0hw(6Q zg`Xq-#FJ}h(8+9@sW+Ya+uwf*LI&4yW&Svc!e7egsd|KZ2a@G|Xe>s-gl@y+i{p%* zhT{o%jNL#g1B=-OIG5X~P~-)=DERpEh1>gr-f-%*?YoQghdAG(*T#c>-W&T1CVIL+ z2+x-{*~4YSx~8l6$s>WZ*uHv2>_NY7xG$Txn0i$LsXlxbsUPD!Ry3SxTJ(Hbx;B0& zwH%n6WmqRPKk{2Ha}S!X64Qi~nxAa>lHa1Ob%A8gRjbTGlYrJDhK zJcVEqd2KL?r7^Guwe%GD5sg*C>rZtHj9xgMCG#u#C*v72bAL*jLZ;_@yI|dKNmXvU2hA#(+v*cu(6?!ME8KP^C zDUYcPRT=c^rt;3(Ipp$dseVS->LBga!BfUrW(TPe={P9ol{H^5X}c}+R{2qzQj6zds-kP?250CX|LaIYEMuih(OnR=Tp1Yw~``mRJbqR?C)A>H^ZHLu=3tt zl%?&m$0^@cu;`&m&YoVFKb@u@`5|`q+qB)Q&-5Hsl0IU~)UgmTiX#YX%GBKOgbeo$k?l1MW+_B!=l z`rZ+Hc+ZdOTDuV_!~ETEy4G>+Ta4TnIfz2ANPB;B32icOF!5pz<%RYhytJ}&*-^~IpPZYgeJ66xvCO!t@|SKU#tsv~ ze?-&P{?H{E=Mw8~p$EX^l?Y$u>cdPbpmy)+(-v54nYmAW4kv=GQ>AgJVG(fXU5LR~EA`*)mR#5+NGSU2W$UvxAnmVezSf?T%H z0QP_V&hdm3X&B{uDa3xp4Yakxo-kj5kla+8j?`AC$*DRI{qNM;i`PX4`iFO3H%%VKIv;0T4u0X(tUe~_Ifj_jLuFW%aDRj7Db@e*jwaBcb@mZNZc|F~p&V|sM8y3=SqONu4k*5mGq&>`dkw_r@m3J`zYwv<8lyyZ;UmN7yYRjW6mP|NVF;XVbPv-WxB! z%V3H`x~0qU!OLlD+E{3&wKH-3n(o1F6>YGC^^#PQTk(b2 zQw7~N(9_5K~ziRDlit4ivliOwM~f7_u^yA zeegp~;Q^)4PPD(4<%ybfe4C7>&vCHBMS}5?61B#@$4H>}GNo*PA1o$Fjcw5FZ>5Df^--EGT8K7_*JwompQ{NHQjYhWo3H#G{t1%L zbB^-Ih2`(r*l$cT7?i>+>XYF_B5ol>0~eG?y~t$RIkV@ad6T5dVxX;<0dMU;#fr=Iz!+7) z7}q60o%eb>s?(v^1&y`Q!mzdB#DdJroz{gFMG5QyK@zX`UEKM}-8t#?Pv~_X_oVUF zsi2M|`>%LO1~gsTbqUxfzExyQ{j{U=aa&=JRoeUxxHpID{k|ps;u;@%=gyDr9=?A6>BOxV z!zH}e1{&#efAXkk6+`$>Mb7V6Gv0P29j}-&vCiNLY zw(kQUrU#LX@!DIx z1GxAKo5F-uogB8w>*x@KiRP_*>hRfQHiUAjud7^7qk>!nWX%?&sW+9mYSH@~5V`f_ zmAbiVYO?XpOODy35>bcHNM-w3f5|Xb!TVS9LnWeOYr$<*U{$N(VZN+=)q+S+mB57y zOhhe_G~St@?>~sQ5t15<=dMDGr5BcpyZs%zND8+K%-g0L)&s<6p=>h|deC6xLV_2A z`X)37lhOU;wl0r)`JUcNi22&xL+L#dmkxS|!2||_5raPWP0u(3g2&=y~~3c7`x@bjzF$-HD=rWmj4LeYgl_eh|sZUWf1m(yJ~YEkikN7bw>8LV77& zKsq+5c6`bv8hSa9c)WOT&Fj}-*u5M37+2v+zBz0(3iDYXf02d4{Qgp2eUK>g(F-rO zbhV7xcUgaTd-1sXgZK4ks8T%gPpgZH%HVHKWa?F#0}bYL!&6fSwL^rv6)aN)1qEc} z#yq22YlZ=wpEmjNUEFLp-CunOdxi*;<)pc562}ejIST#Cw>o~McTn0N4%BX;a_+(pph*MuJXbqw;$C z(eJkh@UpkJnujWcY(%yRufn!GdQzL-5c;|=9yp#n+{JOoTmLvl%ys44ecFJ~!7}fqXG=8hAa@EBr<0r$6E2oN z(j(*WkId(wk!-cZ%0CfBIB*hC)_|2cwN~?#cV&%M#_9 z?Up%#kO%-6s>gndX{?k=j3$L0Bjo0t7Pb^lV#(4Kve)tO#BGkop~!8eFpZ~?pIV6v#f%i&4k+L`{z>n}2A z%H~T{VMJM|f54oasW(y43cCz;y4*VZuGPB%l5OWbcl~}fg%W3ghzD-Up{kESwpel}Og=-(;0pqt-^KTbSsdLrXA{y*Y&Nwj*(!7o=w0ch*#LPse4{5EgeYq5uMIa_vS7Ol026PoHK=La*9C{GmBN zUT==pni;0;rZ>NQP(b49-1A4*PHm09MuKy>7&Ee=D!tym?1Ea^Euj=ZHxSJe;ov^p z$Z5hO{=)dT_iucZ3feu9Sj8-+<8=61yjk$JEx(J2JhLcmQ{_}g3Wid4Tc0cPvGoT~ zO@SrGs~$F4t-rYXGr?f+hs5?#Dk1t}!EPx*Ry@O=A9{-^Gx_2fnSna>Hp>BLSHgL) z&Ms8<&&5IC^0#1$U}($iekwWOHdKSj)%}SH@Qc{$IPn0QK(hA;kAO zrUHle?%v79`|IZ_tLL|KX^IRd&g5*39uWrKo~Z25V0lgA5ZzseODaKq7|JZp@U<+@ z07?)+AL5JEg=uvh%aw3db^2rjN7h~va$n1hhe`!8m?*{-p)%HImoF5xcK89mLc{er z28K5Kt#i{`-;PdNz7@oB{DrA%-DZd!$H=aWV+)o!f9I*fBl>#}>I^459ML^kAKZ#Q z-t>T0rW0-B{H~@pz_ImSJ>#%D7)_3H$?;u*bcHY@{;*I61THCGbb6q55@cZtpyGiV z9zd7?hGw+1@PK!Sc^Z&^J^{jEY;0^%t2dl|lBXzW019VsNRFwdo)cl{j!th&9{Z1@ z^#;`agVSAE$>xz($Pv1&M`zx1Fr9uhA5)Dcy zRT2c-S(w&S%~JDl%L0)f$l5<^p)^2}Qlq%wYpMwJSPPYwR;?Z%T5o2=q7N+2-a;Cnk0I7kCXHCjZihEE2S;^xg`SO=na4b{~?M4aP7lBfe_gdktNxwj>D# zEF^Bn8wqXi^SA!Vw(QanC&RNjEXS3TU)r~S*ktSCct~X~wmW=ZyA#$f{uB_xS?YB} zM(7RizrIu*_<5C!UJs>ezxvuL+Kq_38s%lHnZKB-dUdNE@P)oq$6Q}@)+H1CwYgcN>3#_CXWg;e zPQ3@;W%0}Mp4vro8iRS)|E*!_93Rdyqe}A2FT=e6y|ANG$gdWi(LLW=ipQkZ+(D90 z#6Kn`SGQ!u3~lvWQx?oduCa=9UFbM}W^t(AnE^$S)kKvqsA@2O+_auLcK1L8u9+LK zj=Jrg?z)!@S$8fpUt)r4zEx+arnUmOHi2(X(F--nL|9r{mR45Eg-2=atmoNM zj|R*0Z};D{{^CrQ50)qZ=Lji+aW!b;EGacq*WW|VBi0VPcL@HhR~cB06{fr$^cnA1 z*?=_txF=ID0L%@%j`jO2yB!6tOl-|tUAt(Hg22-wN9C3UgBynvQkr@-A8Jc%T@#O$ zyL#E#xujR36?9Q7#%H-cNp^fDCMBg=+&#RMqS>FBfpX+FL+YSOf(MY4ShCdXQ21Msl!8rQ)n;?$f()cwkLQM^ezX!Px^|?uoH9vvLpH z$gO!_H)CFfZUbT4*;M!Gyy^KdcO20Asz?O(F7YxqdMtW9(I~uO=-<|Qo42)8?lD<50 z;uVqUFHf&NzJbiU6X_f(ii&DjlXw8fX4-@|)?17#rQAM%m@&4>CZ?CUw8^leQx+}W zyk_3+l-~;#Stmj)MH6|tm&A*xxzBDU((p`O;AQbEL4 ziI71@W|vN5gBTek`A7ZJKw+-F{-M0TN)D#HG3cD(X7y#PJh zyAnmGqhj5|PO!$1QAwpM%zWCi@>GxC*3f1=MV>j$jAX&gjrCPtmhn<7JIAz|UCN-rL*TA$9+7 zVZ@`dVW8LklBY^`MMNfY_Se058WC311WLhx)~0t=J+M1pp}3p&R)W zSEqUPy)sowJy#YhslnQqq4!>d5nEPwTKcZvI{lzRorl?_l}}YoElj+1$(%cG^B3oRNnOnhSQg?jjCNC{^o9n>@}Zs z-_kBzoc40E=La9hzQO^<_aw2Upo%g!IS%8#WlVi;DyCLrUmgJ*IQmZdn+ zdiNa0Y#8Fm00eN3e>qswDMCeQ>A#O$AZP}_iUAiooh7^k#E^gPfq-2)`CRz!6=zxz z`A}Y%sIY2HzoD^-3EK;I;Hyaxx*{RkQNO(iLSbD;>8xS33@5Zu3w(2MrX50FvHsGx zlCa)nP%o@V|1L!@^)iD(qyk5X7!H%5FjlXAzlNl`i-8IQNo)gG27RwkAXKxtQt8*7 zj$vTy^VG*x zNw~GqK24@|Y>@PdQ!JVCe6F1qLB91Cqucp%nnqwPl%}xmGUtBjpTYe2Nq)H{L1F9d zH&LHQT?XM?svV+*4XlpauN4N6!jkvP@3ZJ@nMQeLv9o1Z=s*u$r_c^$ zgmZK5E!)0LXc3(yYF-u5W?~}xS%hQS84L1-urKAu!_^_(Tqq%5Qou3|zt_DpyG!bL zcCe}8;ng7Qx_Vxdd15=2pAE=WL}Cf=gU$ul8>a8)W*@qONHKU-A!tf)sd?Lbhnxpo zc#PlVy{t->%I2|)Z|(QHHCb8dB>vFK62WjwoV>bwQS56458RP&ytzWS43kSa)Jan% zWvI+5a(G@G>ahOJK3pBo-s$;<`O>MRX6@90>25HygQFu8LjKAhZ~#!OgA#N`+ZYFC z00#h_fis&Jji+$=;z316M-DJB1d3H4)P{DkgJW6c00_NdEjGX24c6LO+)fS_b7%BP zIYkh9=_P71sVKiSUXW1os-mE(|L3QgGO%|?L7LNX#vC$*Z}E%<-jy(fQrI;eV7HON zUI5asLF9i>KP&KtyV>o1GvM2TX5YQo4~+P;U#P*M5lJXHwj63xsFzYZ@HZ%=KHg^y zrQ&RwM<+17K*me}d{}wa7wclr*7PK7ZD%o4;P=}HqaQd1V-XJ?)uP*!WI zc{T4ur6Zc3BV%dy-jZWReRtq%kB7S@^b@iQjeS~|q zsUE^!>ZNDTL1{f77&X5|3la++(En2QTa^ObIMvnd(vxF?M6A{og8{mtE4|#C1gy;4(%6Jxconr@|&Dm*{{B}X9}P5K2{ zP)T#B-_Ub5Tp;BwT6R6D;d6hI#8tSu-E8#2NU7Ls$uq}BLVT-Ef3IIRi3fxk1^ltTpv+@LZtw6EJSzVq24uAlFF zW?0iQSGL^E&IbHR(#_9@4+6~B99n^993>?sbj*+lX{>%TM`AwGE z&9b&#Sn9DtOA%Do^OwcN?iW0`qXdRuLQ+GyB_%2PjFNJ4Q5Y~r$y=$DI&do{<`e`7B1=k*XXCcb(a3EJyRx%g<}}}pP31B&kb0w!%WC_?08NkU zt}~fOP=h_%))8t~-TQ)Jh!HnqJh{V3w7Yk0T9~Q(;h}mRJ zB&9&@(gr>EJ*0dp;_jsn<}j#Cb`s`|kyiqcY5{TUu2V)vQDKwbay1sO@vQ(v!I| zxcqjZR7@D=JQSZQv=Hz<*)Xs01<#rhZ#6u<3-t=jIb_-?`e2pdh!-USb=6Razt;M;by9G5t=%PJLaSqAj8I1ua~yGllGLUbD`U(!>oazY)<#`-JgT z>*1QMWD+E~vE{M0bA$qUWK&Nji|Fpq*D)pS6-ig55)u-wpE{N{a~!bAi3 zy`^2Qbfp0mIAhbfRmdJE?mR&%uwD#c73)-&S4sgZJN`8M|Z+w*HB;QDK?O* zEfRExfnyePXZU_J@KeMd`Gj4ERTZ$Eis*|GDVh^q>@6XN4(Ly`2w~TbN zW)|QEPZrlCq=gPKcN7YiYn}#7pvcD}_z01K#{vk`|M^q@`R^KBQYK9rD>%oB&}UXh zWTvNp^NC&zCNP{dF5H`b`xC1i$)hza=5(fj))+3ut0p{O{lL`G-VmH3&X>JW3SoS0 zHIe`TQzkX{AI{nBJyy+JpoUF`!gy6K4W9g-#a<~C{tu;BkaI`{3O}G3uMe#X$Gl0D!8=$-aQveg2AZS zLh|-s_Y^QibFmP@fHnw1;OgqC@s?1wLWy~iIq-W|ZoDnpRRvnpUobzTa{pv1iD+pY z3uGH;Q_H16c)KxB@!oy+j}4-NJx`$6S*a3I^G~A^MJM%cAuhjS=YK{;I-@*40hSbe z%Qm1y0chjLS@-ZSN?{oo84nNN&z1cH%9U1^ljD~uWQ~&%Km(^9H1qKAcpP~ofa4=I zXA}L3T1G?rqkbO?VDd4hAMGt99sNWsYlco96Z@(D}ruscbjI(%`h<# z8lLt^xUNCFdXB?B0X*{Mn85QFG64=NZWKEeow{1$ z_iw>NU-3J|dgeLT-%Z;;Fml+TgtB2^YsEy=P=&~Sn(ZK?kFr)d*4#^|7#ng7s)gr* zo?BoDO2c~jJC&yvhPIPw9@#R&b~b)wXNb;r9SwKF6jD9@SF`I_BbMa>XBv)(0$_fc zQe=MD%Sb0iomiV1+0Bf%E~yDCy-LuIQ)?I{E-OQd5fwh*C!vOMeci6uW&ZWfxzYG1 zr0ZL>43J?&cZg#{>pkwK5b&83fO`J?d}DV`m3?ihEXSh06U>&!8IdzR|b?`+o zH<%1Zz|O>aDp9)V>^U&;fkwn#2c)v>nPd+k&fYrDtu(7Szw5~)2UH!33u_bfeS$>5 zz`&4WFO#KiB__drN0P}5)i3NGTsA=RAordBF_>{I6(A7FC`!Q-6gwF~v{=mPdp z^HJ}G_n_ZRx9-i(Bq+RK=O0R_ooNU! zcxu0Xo8gXJEF9d$O7^F3*8G={+Wqe}r8A=GXsrH6YUNnq5UuNz6ta6Un*z&CxuF_y zGSpcD6653ByK!l4S=mUozcFXn(uvrTbB8!V8#Vo+WfG{@?mZH_YDui8xF^kmYEu3z z(1I?%l-gk01#xjmRM}n?Ye!#-(Ab(J9caELrknhGt63m@pXJUkyCVVD;nKS@~BJ{DzY-f|&Bs$v_IIqEa#}rpka_g47fs zs{+ycbY^vgZ$%p&j-Q8ga1LRb|Ir`Oe zo|Udu9-wXKht(N0lb=)jY01C_h10!LqsVtp(<@?OZIj&Zp+dq84NTb+u+PI5=NiBj z>q}L&G#-G-xpN*H)-;J1VaSm2z;9QS+td#UuPE3pO#?a99$I!zP>BtreJSUzW2Z$8 zqg-(zfr-2_E;voUE{O9;Qu00qBbiQxUXi>N2xDd79%8ch)1s_w<}T>Ud zJ5Tul=asY~p^oSvlFa#K(~ zgA-B>OC}<7xX!c70vsk=TH|UVpgd7lQHehtT2Uj9ai|EPW~(jr`S3%bT}z!V4CarJ8q|phEE$#RRGZ#Xoy)`&#={}GK=YYUwb33{_Kn;JHMW+X z#}HG#mF7D^xy~E*3J2}cDe*lzOLa$ZOxs7|8a;u8*4)xg`WI$XA;iMsh+3h&b*;si}s3Kx&k|Ci_aw-7eyx}x)~06u`2QiM**6F8P`>^Si$un`Qgp@3^* z_LKzBu$wW%0BXe|b3on)Um?9H%mCYsZTlXcQq;T#Oq5`o6d<~X*dQ|Ivcu^jI&`2g z1!1?8>YmCJLGkgx3ZdWz#|ieWq~3Iy_g1r^D6y=xQc42jbVQjbt&=Oo@PPJ^MLMKa zxr0w@Nk5+a_9Q(^;}|csh{z)D{*pfTx=vkO32j-82_`d zNp*fZ%Cay+v`fetoGdpQ#+VRQmVA+-7Kbu^LIcMCPtm0Gtv)S3n%t^)dZ1~j-s*EQ zs8-UOrpSVaV5U0b@FVKd6W-g0bGW&7eUCne7{5d#?6}PKDk1C#opXoyzi)I(&`Dac zRd28-R#V9B5f*cnJP%)}i#`NYWV-Hf7*%}ixc}_9ME%gxia>h2d0~F-o_m~A0v|SG z5>oCV_?F`to6f6esm3Mue-SmcZ1PQ1uO`ORTdnu;eM(*D+?TgAd>0_`RsYJ_&|Z&u zu5;W8ZE9-E^X6l{WO(6dyc$5Pv>yi;uGTULFvN%;a}}(ZkgWw{K)BLXdJA`a1$GfD zuG~G&ts5^u(pA*cQvlKdBLWZ`K%wOx-MkUFfC}UB>-T|kVZY!8#017(U&$XK-YS}2 zp+jXcoZ2Gc2diPH;(oDq{2!VCGv6!i&C;kol92Z+`>776hI^ij&A4;R9Lo3z0S^Mp z)}pG(W{$XB@RM+p#9KubDDfuxscOuz7Nw zwsWjUy6b_MTMX9uJ2~=C>!wc)i!p1jDF+8c6OAwXGd6N->{V5=U0yWtt~)ZKNdhCz zt{pOl!v+~1^MY+|`Kqti;N>j!mko#6F~a-PbB_=6N$Wqy4CX)jGY*J$bB6>BqL3y` zaVfvQjH+orU*d{q`p_LD&odvywm&WDA#w}2Q-5W~7;pQv?mdIpf%!^+wNZnWN~^as z8A88zJf6D#^itJsOiVe|O&0-t42Cl)VpR;tK1N(J6mTFn0aJ{+=A5xTi)rY2e$Z09 z5Sdbp45l~undQ9;vg_I#)>6-;e%;UsVWk0s(A*cW#Q6+y^Bs1bZwLcoc46B|CIe_A zRsZ8UU)peCtx~n#SZY^c~|7 zqdVvPp!#X&g_-6g58LnfMD(Fc1e+=6w_thNnWkZ&k)ZxXmI{o#3x5+_j2MFyP-AFD ze`l2@{yp=jwy0n5fUaQu*BPW%hHY7Oapq66`1dCWFr5CKTAhYsI@wdKO?MNn))2kE z(!FNK6Pb(JpF2{Vv?>#q3|_al2)fU1uz2}@CWr>FG~S}VhU@f??%%xL0$8<)>L9yV z9S^Dx*E4|1lq$ODH99_&br4vX9%{LAyK-YT$z=&g?oao+d8qcyyj5(-`;Q7QdXorL4ega%{PIik(;MZ~wVP%vF?DS=cz zcxBtXohZ;%2uJ^073F%*8A!wZBs{_`_ob27VMX!P59d7B>x9kx5g7YOe0JiG4-JBr1S7pMGwy`-{I9DjGZ zEQOe~x?}qCahmCxq3yiURJ~=c;@Z@FTX)14#A@MY7U0L~jftX&Iu?kC3QwhmfeNV< zi^MOfgrXRZf&uHVD6$%S3nspo% z3wp?bAX@h(0C~O{<$Vba$Q^$l*Jyd2Gir0fA57jHG~uw`t#{oVO;xLT6L57rn2T6x z;gf~y=I}cz))`-#Oc$?B({W2!VBqWRo1!zmi)PJ1FRL=m&#_)_Wh9iS^!KM>#^^ml zp}**k+A7c+4h2BF`3xy`ISf5;nwB69$piV<%jb4@>-$S7E%wRE1{l((_Cv1a$|Ev@ zLz?fRZ~=TG?-O>`XW?18nc%`es=IhFT4VpG#Q_Dh7~FW}m6TA^iuPz~>UzkUzDoW` zRYY6pWM9HqVlsnWqBAp%i*Wu-UB01HLQ~bJnA?f)<1YbyUGgnKkkGYg|M*KA)qInr zfgzd8!Rj zPBn&ZU~bRb5LG2wAdUtcgL>)z*5N$f9)>prmw__A%^otSg?AKb39pj$`E{<>~u$@j>g#2KHVFWK)3 zu*!GbhIpCOOtb+KV!3*6aox5y+o%4xKX=i-RE9I1MQAw8+6k1F=(|Y@El@aIV?o=y z*rRA#xW9J|J)Y?V;&^X_8Fyy<8uCgf%Ho0{@K@6Imo^$2&{}ifTge@zI-YbH)5OS_WrBC_xz( zv1(8s=jNk6?Z`AbSFmu7*|pOal^<$~KcsqsE_Yh8Zf^o)cad%TmGhati~Fa-ak7~4 zuCjVF(r&H?@XbWq;`W_0pEW zz^ok8>B@?a`=pPqc!_GJGv$0@vTeh5D2qE&>c) zt+9Vcj8$k=<$x#qm_yRO^yIb*tdHoT8?IM{=&e%B|JO*6XYs=El8?p14`ZpMFOA=Te-LCDNl>{g!& z56(FHAttnG>xTF>7SEuN=BlJC(SguZOypGKOR@`9CcCw5$~#au+ZODNx-m$_o$?Lr zNz((|P2_XkmppKqp%eaiQpNS-*h4stG3;L+eePwjQ6PL_4$MplqPg$D{&V$U0Rab3 zGyNC88P-l?cI@n%X|^*2*&A4SA*spj!W$diCVQqa^!Zh@CrJu;CACsOrKL2WShsqH zV~?pSKJI7p;5I)T#s%R{4K+J5IKxlIr_PQpPr20G$nd_MKRZn4QuUKtiG6fGCbGhD z9yQBQ^NhEB<9U~J`HQ{sku0FVI>QN<(@PBmmEHH#U7U+`CZ-XAdd{R~v7V`6xzGOa zl=xx^{)aDqH;0Zf>*}BBb@)p0k2zV^&#MRBU+~6O?cOP=l8?2U7Oj1cq_$P!jyCM_ z#!UJ^EUB%Y{q6WZ;H>r+Gqx+@645m$_49Tn>!WQ$O`EoFbDC^-)ar8~QxN!zO66mvTq~h>n@*O_UIH>;GWxQ5Gr+ig@XH4Ko2SNy zIIJ*B@95)PXATcxS1MzV;*b(m_HYFi(M-DXFB`|cDIfTJCH_n5Nfv<^g3^YIzjzwY zO6V);zkhjGcsxNfTfC@>M}b>`V{ypnH2}e{7Ee(^N82p;{@jBh)Tp z+$jimP`(`EL3?Gz9~M~dJ7hCgrgX+}G#I`cee^hTftTWsR4avC!uDqLdNEjNwMpa~ z;2h;XT&f1DCF51CeJ2{hRZYI#>EM|p5JM@i9PINZ*d(JQd+#}-oz+7GMoJIOTXVO( zk}EZ<6akn3N?t+R|ULofCK9KRVUGth=Dd9VZ+h`8lU53bJ zvg7RdR$s}#Lp#Zsf6~e5J1c3q*xk&fUnFNHMVNUm~{w{;Kb6MBZWeYY#&DnPp_Ce{sKzZ@zSJMUa>{uZoRwArQtAt#9dMn|g zai5f5VZ$Z!jo%1)#e0v=s#fkFZ zK?`hx5c{bNJmdK9KQw_-P8L9VFRj#a5;F*Y`L^J8NQC+A@W}%Xrk*9rfeRdv)2Qaeq z-m$ZCu-NszP#N8DUk0tTxo(@lzwsG}VQ1DiZ63sfD}K=UJ_RL}Pk$l>hwU4cOgYj( zr`)Ff8vk){=VT3OnU4T2>D-cks72Uw=GKkRn^EWeXtf0R!*%;YxAEs?b!#8?F8s1l zP%p=YLwd0FrC$aD%BQ7~Y0e{S{_bn&t+#pIZr;n2>5Ze_mi5~gyN>6dGqTTbKi*8F z*?OO(3A_G+wz}FmbqeO2!*O1Li;b~2D9tBt7b66I=kyoeSldn>960eMGEMJaKUhtHElAQVtVU0cRFg4MY0)k&OZE7J~tSO!U$znC`QiAxqg{gSXiVX!wDu zJUQ9`t6VS&&=~%jA`BByS-A@fstvMwn}+@@Yp?p~)7s*%;FRNwWQ!A#g9_u6<1gw} z*#NvgWbBoJv3z6q+(K;4LOyuI!T%aD+mgN&x7+P7KgK0@idUn8GPENeAe6>AVIgA| zx83H?3I#N-NAin1VO)I3=pCXAGb4%RNNo;I*Dn=msF4RJZCJ@IVN5OrzZb`bCKIdv zb`x93(FsFp2)%4ZH3-%}<9jW1+NaTEUL9y95WSKn=|j$3n;`j`aKRXB<91rmqOuwI z7KYrFDY0F(cy_Nl<5sugfPLM?@{6C5L*SCnse7iyb{rkvX>)aTc;E?F&$}j}QKk0K z>weN=^?JeD`#09d)9)#3&hsgRFZ|iW*Nx^b$y@}|`aK9Z+JJUm!Di}A)rFdN7QxFD z5wVxiQB({Y&c=1@hwo=|<4=T@kAYAZDQWrYv(~JcSX-lIBpjE$lc&52NErOcuwxfi z3~qh`w7p?le7CP+WL7Y@Sax+0-#D6be_DPaK+97+PM{lqxl^nM&Gp9S=Y0> zr+l(XKZ<73DaPzS&YFHT?wUlxA#*t}y`Ii(k2wYCaVJV2d92W_OIt3$MDr;)O3qJG zvXl((rL0;;WE)?RYyBS zG-4YUU4mlHNiha}W=QRI11+X7L3(i4XxfH3>2(HBzU}87q~g$mtqO(HVwr{ri?th> z7*ESdrAm_bWL-UwCX%e`h~ta1xh&2z;F5OEOs}vLdq~2AKHhpH*a|_WaaH0XXTk#7*poB4n}z2 zW??(1>T%O&5$>L!2<-L}{gu1wJA#P3#7gCNVnpVDbY(z%RKfNOnwz8BJQxtren|QS z-Eld25#@tv;TdUu8ATVV>bN1b_=T<5n9KTag~ZKxjNQ$C<=p+HL*Cv+Cgj^QhXB>n zGYglaBuG^Ys@D=TzQf(Ktl#b9me1lfY@QPaStP{IP@JIS*&p*#C*S^t2;B9{xh=R} zHAH_^idgm&cE913$0ZP?_LT;k|NhE-ZH+UiG(_q2QIYa?nAf+Dojd2W(G2=j^SyPY zLYC(TQcBlTVDc`pIL4q~?mJ!`WSo&?fbe-LJF&6h@+1z+(hy4&;mNhioMCra3KVnf zL8)tYT-h<*EYTzP?LXX5GOUxH=gzf>|%gqjix(e~P6Cgxz;4M?28_L?4j_nq-9?=iX)7sXl z540##AZ=DZhazQ-af+io96hl;s11zbY#3E=U-nKF+hhz*geI?XS0LB$J%9H0`B3$} zpN^Tni92q>jy@skd*$NbyVISmg1z4n_%&DBsBqs?B&~>&OyEURw(UgmsP9D;l13zF z@OS5F#!p4|Wws-ldrfLY^2ETbaTeBN$jN;{9e915m~!M#f`!H$0KH8LpL^0Tyx4S1)$A@9&HUE>OVueq;gNotN zsl=zc8}CJ=x3f#)uizAAs$Fz~E67NGzBR<6S&Uh{1aWi%K374An}F6}R+ivjb><3Z zl#zh|e2*=JR7TB-yEb+MBNSYw*rKv%S6zbjOANS*&Nz27H86==Wo~EOF$LUuBBXc_xu?{W;t@yqdH~yZ)HE?pgJC%H8HU^Gs!Y#<^Uw zyDR!afwJDO?dKOQpwpAEW@on>4T}5yo%Zc+16qUc5QCxPw`667+4@vm6B2!!uk@{` ze1|*AiOHhHwFe+dz?nY9Qz(?3p=D&vO^K&ZY#88%fyD z^*ZCA{hpoP+_omUf?WNcu6NO2B1-T8shE? zbhA$rayW6k(@k-oq3VhG5KvBoZl;ch$;QuDGl64-FL(-{wxACE+I(SCrPHR8>$f`3 zP9bB2o|z{fH(1QjOY@4co$gqlEZqK;$xP>iO`7&6PFs(Mva#(iFyi|5WUE-b!}@xj z!TNpaP~ORL0x6m3ZuCg|Uxq@|bww|F&7K!$7(2PhJpC6E7JoS#pql(H(LXud;T>Oe z+nQD(9luejGkHi(jJ;Q?;yn6|r%31NFWiyD5^G-dxx2=i_O!j5LMaOV!Y$vxT2(JjKU|?t-RBVE=&K2p-W03??L8Kh6 zja0+z#-nd{wL!b%ol)RmGF|#?n5E;m^z(-n)4>%DXX5qtvvITb)$v1B-oPF5(dm@$ z%(59WFFCeD&d5M&Di)SsyGhxt=}dOS&hnhsK>og$1pB8y5B7evGfrxs>?i zhW?I>i3DN0*IWo*Ay3bwqe+!~LAx9qk6>k8I(f;KR;s@y8?2%C>h|<<8nDWCe9!v|K3DX1ppJpt zfYX)zFYD*3!XZY4^+W>-9ARDB#t#`B4nxPeYHLD3ih`9?M)-5Fiew#mTdUn4U4aX6 zvy~ev?l6J==gvACOuXqknfgson#6sRSKnAM5+Ahw@$b4{QNANSTi!Y(!8^N|jK2b& zuE4k4RZE>&-Wb|GuWRUd?tr|_2xIf}j-b}NHqvg#2XPFeV@i7IBX-KKGg8Iw6ETly zL9@JJ?PIR$`Peu`$7@GT_IBj?CQbji^b-5#RX->9-0ehkdoQ)_BeE3!dOxkK%c6al z|8O;JXS%e>ck1%wQcL5sduIKeI5-dm;Q#MG|AINia+hkqdY^?|I}Il|J@6KaI>I=R z+Bw}HwW0T2*xF{QZ(YiS+gq{N^|izwe4LmF7Yy<##K-B5?eyJgey|>{^1A#=fOzn% zL8ia%>k7X`r$moxae3lJi)nN|`vwe;0qT`pPRF~<&I@M`FM@pnf|rpcvgxcx{;;*T z8hF=qTH{;Bu>wpiThOt5wI`|cT+QuA2L=32L+6}G0Jn7Oj>BXC0#HC=O6Hc9q-YVl zoJbTD6u{;IEazKo4mgoiRO$|vb<^^4-^_hZXU`8hCF3Cd}% z?D@zrzJ3|YN67#Zj!UiS;1l%$FGQggrNyFGptF2Iuzp}ntqSZ)!(W{(&~(chjn~~D zJF5>?FWZ;+7pgsJKA7^k$TJh2UY)f_yjy2FBWu_w9x>s%WBEx=sBnAy6V9($5nINS zL(2igTz@z-qW0eW=34~QcUGGTc&G?F<@)YJO?>U~+rGHF<|kPoF@OXbr}OCCtZb-V zNFpC5rTkU&fnx)uTBHovs^ZBJbDYBCeVA|JDOoI~<8gAxYva#YmRmJjuqS%c=YKR9 zqldA!BC%0l=hJp3wesj|NL1_hm>GHi37^vt`tH{lF2 z^}gl0(G|;ylwQaeB%{7D6}cQONIjnXRl9bGDHrNtq@E!`5{V{9M7)uny)o}v&LE=L zZNX|ph}a1{Q+@t8Tu0fV_E65572$#7K7ZWn5`HuH{Q*K=+<)A+EaR?X`gKbp2LeCB z#IGTz+W+LxGxZqy<#6%CFksQ?`ln|%KKJhxOIo{Ny zS02^H(aKb7!-19ipV2ON3U@U9ms#}+8Z=hA_NYxgd&k0}92aia^svj)J>MhGURL%# z<_tmj)Pi-_<9)u(^ll%X`_HXLpXkQAoW~;31uA=G)@t7B-`;?puHa(TL@?Pn z65pTO{CwK$vM$N~g6V1daTR^x3OEmt5m~q1#^8x36dK3Y`1keAER3p@Plsc09W)yo zhj27j!dfzLrgQ!-dF^l$o`; z!tkKhx??0h>ei-5%{kc%i6KeO7Yf64yN~yLFamAv8rgV#r75-*d>Uz*~*iQ zc7m=jJkR=0{AiyniNt>ubA1P_fhmBCcZ8h-qh$Vi0+hc-Dxd%$0Fzq4(#Qx>en1nHFhMBv^ETXMHn1;jJI- zjPxSwkJd;@dvS87jW!OiGp8wc4s0n(?a8z&N_(#}NwTbFr8zc4$fDKo!2K*&SDAW2 z+WgO)Lm0;$&9Hhjifgz*hk555xxDJ4;^vF_y2iu$;feOUi)>mpGA!XP!E}$E6wXsl zq}~QIN5`YTyndT<_OlbRRqQZzUP&h(9fZdFY3b^h{4s9dz_vzDh)y~VF`%H0t9_3g zKG19TqZh51=t3$zP8<&VeCNP9-eYgL#+WKa$zGHQr21Q}@%7n;gl}G)6mB!^kb;8N zowXQSe;8_h{b3A6jP;R4rH?-uAp$Wo<6AnN)4xuoX8#`5xA*;kS3W~IW(TgxrfcvJ z-At+E`k0#Ln_t$mi?HzS8kj^wfVX;^=t3WgFv%|R{8Dq!VBtQ{>A#0Rr8paS-jbp zFeOp-*FUXB2JRxISL$?UN)fFpDsjUFP)w-6&%Hyti#vX>2^8)&^xaLeJT?$Rk}A#&t1z4dI-Mw& zI$wZSHiWDadc<@>JXMuBJUlY)RU3v@bzsi!pRZP_^1ZNrc0Rg(n1XwPsuh_stufk1 zD|uh>m4&_H0?~b=pQG>ee|Qp?M%FuW5jYLku;4e-LG3c z8{T}n8-3`v-~T|rQD%QI2_+JUf~)Bf6Zv?EjK(=7{zf50@F?NhRSet|`hY%lKqR!G z()FJq{as|`kk*?cepq0jV%wO)uz-H^kUQ`?V>u)iM(e~4ZJ1=DRnjWQ`GOwa&s z1_caIZWmI+kVsM{l~-o+#Fe?URj*CLcOlV9o!^3iB z)|J%;iv!Pv3RQ)=#6y(*2T5jXdfKAu!pf)x`3RF8d#@uG1agN)FcN2!A#17w;j2QT z0yNwqi!^=U5;ZG-aW;GSmb}3_rbmD*BN!zNFmrEAAUJVe3|F0Vb%sQA@?PX51Qf~Q*M=} zu6p?3uVR-s;C45dt5*^<>Ms!dw$eQFpbwVF#3S9O7 zuZ6qIzcikT24F|4=Oc}Ds%jJ#u#d4!+N2lp=x~^r3m(Wkw7+U85$FTu=dzuziGSB-TCGFXnY`7`kS-D4Fol_0JO601SJwOE^E4d`(J;+&3Qn6LF`{wV4t`h zJL4#2Ia&StLvRECxtBq$l>wY!Ton_2$b3ISJ6vFT7iC&v^ zMw=@Rr?quf+#Y9-CHuEku9YxC78)HVX)8Syk`99WZ8WKW>p``e#3Fw$Emk7s+B&@i zGkkcV#Em%)l)w-hIR6V6=x_BYRPhDqASMesg3oVT%}?`;Tvu+JnJaZkwi}Q|QwK0- zFbH18eYszWk|#+7gX2~F9rp76%REA~QT?zBVrY*k3aiIsJ~ic+(b?q%myMghs-AnrI6w;(^W)>dW5r37$oChfq#bdB^JiO|mH;h@5 z+y`HmgWGpr=Cc(UBC_ym@!`h^OvIsm2?u=ex-Y<;XF7A|$k5I{5I{J-L(xx>+HiBV z8C)p|>ZOn8jz^##@6_((*gZ3>HPg>brxO=f4;QvXnO182{32jE^RfXY#jcHVe z`kgV#qig?FQpF&(07Op7fd!(81yo`K-dhL9aKJ@Z@=q3#@P`%(33pne zWh$M^ios&hy3c+F#wb#;A5=`OQ#R)0ALn|K^P)7#NJD< zbyA!{2bIG^XyGd^=1G1bNem=#D2JIZ;0EXJKxMfmfHtyG5@nLCrk57+A;26F3TI>C zg%RV2QN!A6FkXucYYi4su}Ut!A;Vy7%@{N@AKte}bd6-EjjUg2Ug2o^VVqc5`4w)e z5^2~rMe+pz!!a&oeJdR7xLqII{wXgcUohF&irmj+nj4aCrqm_zCDV=#h{ie1L z8>3p8(n5PqQ&*l}uNoPg_#yP&nFoi23>s}cs@{#{e|uL^HKjv>XsENrO5@Kl-ta*V zye7FWNpS!9J+t)_jQC1)BJBRZMN2sRnFS%d+3M5-oissC7`F*G%!B~U*b#_OJ0u%n=m88mfobgj?i8`bW*un< z_V(d}+xS)zJQmaSUFvvAaQ?@p*}?5xdwj`t+l&SguLy_MF@s*bpJgKRAS2fWYqj7- z7!tIC_fJ2wF(UU1=52|EK;o8%iIwJDKOx|%$;FM>Vn&%3#9@$krB;fbz}HS87L|BG zkr5{xtKE~qmh<~9C{Ayc4%ICx^<{X!%Xx?$eOv+lPZFoVboR$E?|%cZ`2YO(`2Pom z11TX&j}Y-RTmWzqn|#Y~LI7rQTVzs4{==Vura9|Zm`p^1Enk{0A3aTu-R=35{8P@| z@Yn+g#K*iJr{w|6b!WqxEd6kpqOMh50M zv{k7=rQ#d?_p1MIgGiD?$LC_fGz|is{NhCmpi>)Jc=&>7nHhS($r&p$NLqHd?g2X# zIS!9?MyaW8u;8d0P=79)cwv?aCd4*V|3_Jt&7Ua{B1hbLgro#JUsI|68^yS&#UE9c z`E~IsdUI8{a;(h=4Ap`R*zO6aH%pL3qG2hjhG-C>vC^4^8&3M*K%~&xMGS11y&@Vk zk}Ze=G#V6XPYxdnlS4sZ=p2x?ljsJAq5MxNQLJy6VR{@o@q6VdvM~P~s*+M6VHHm{t zP3otv8i*D9=_3SodrAKH>%4F>`FZ_cFgmK>Ii!Q1YPid{IN#HaO!OO zCGTVa=c}7t(rZAY3f!S~^|DE&rQ+MZ_lUpoem8VFw5jN-%`{MDOBxz7&u(i`|MypQ z6Wscq`=u*P2xt*NUNQsd2i7FmHM0xCzq+GuOz5yqYGH4!MX)SY!N9^@*A-J=fX z_@4Yp$k_&~?NU@Rkg&pI8B;ZW#&Fdj>6V5eVzxJWa*?zO3`QG7L79gPLRM;4ZX8%|s){up^O<2g{SD%jy5~bQ3Qa4icL=iuyGs0n3$@ zJ2_Pfx}f-kOGj87>7UqfK;nOI@EJ$(BF#47db}J2JA5zyh zS~kbsrfsyJYj0Hb^x89r%JWxShjSF%m4%4+0|g%J=ek6PZ2RTce=p`V+!%Fryxat{=oh3C@ZhG$s&k}na=f^CJYe*QB%ucdBnlR z!{ZsHy@HnCN8i?bB0ML};Gv?O+z_*CcuK-~xT3mrD#qhC7~rWgmnQl;Rw8#lsQtVE zseU_L`iDfT6u6--GODT5du|0V{*#v!E7Jg@V_R*^w0@idM-4HG{myHoq_(ZH0~U$S zOpFqKAvFwf4I-sN@t>ou6aOksS&(}NGe`!HNu04wBD-tk~5)KY--i2U@$=t?;fzWZv%t?mE^xuqHYb((0-@1!CdEwvrfYMl)movaFfR~jci_iVdFPSw#%1Q zJwHBy*PoB=hs6V|ALns8?@fJ;%*%_k?E)}?NesuM`o3xCv`6;}z<+z?TtXTYB=#=^ z4j14q!H7KoAly=m#vfBy!6<93F<8_Sns0Pt%h&s*ulL)jm{HTb+-(F~n2>}wmM9O&9j&jM+pc%forY|gs^L9?cRHZ6g z!Mn@Ac;qkD7MU6fMgAWaV3{RcnJ=;wZov|zuK=YH7iHiptK5JcHO^OeA0fD&!2CpF zRJ+Ztm{iG5sa9wA2W$25RQZATpWOQ)3^{_PM?Y(sJrITX@;u40a=LQ8?;E~cwn~oO~oolZt?JmR^>VS>o z?$ph<|31jKzegZ*kCN%iJtfck-4|@9FD!2wfwbPj`&q*K9h7M2V{wkNGs@R5HxhR= z2Jh;DGn+lh;s>JlrCZ(2WNA~obuzT1%I8DU)@xeYv%NMxD$aC*na-rT084@}V{dcpIl?3>_rp$Y4+~vdi+**!m_>$n?h^%i;Sr-( zzpLZfGVCS?uXGH5JCH?%uJpPbju<1%dTsaXft{O^Hjerliako*RE1qXh9_L?*&0#k zeHpuh#;n%cbsoE;>8}sG3LsRIztaf!_D--GJtc7GVbxZd&hK~jr@Jk+GKafyR#**GAs;61=Vb8`*b12og zL71^OYxg5-+}2<8R-U%|po2;-BO}l`@A`E5i7(L)g5C#S)}zCH&Uh6WMK>sBi~ICU zhhXB+UB=HS?(krz#StZ2=@X}kukFXHc1j+jY3-(_khe#3j&lcXH=FxB9j1CTruSd@ zx8nE1W$H|}L2}koM|eMn$=BMP`M>F(ImCIrBmiwUCKfK;(M6nq;x3{TJBr$Jk zdeld_SFy7#y*ID#INLv)#`Y_niiVxf2Yi)RX|7#Ce^O0_mYKBW?eC*PgR=^P_P>k! zkl3CYQkVqdKQJH23IO|$QVWe#v2Pi}0JU#w3x7Z5d(YA?`u+ACO4EVaCgA7UpA7hK zt{W$KOPeB6-lp*MABO4TutH^!1(>LgT9SAatS{pGELjzjb!8e62I+>Z1!#=r16J%R zDI2m`-z8;!I`fvsFk+f|8GPfngC8)Vg@r4xZ%cHolya}6mX)yh2Ie0A^LMi1u4sdE zNITM3W+Mm8I>!2I9z9YaAgYoEqAD*^lHNM9smT8wn4IOaLR}GVxgOYNFPhVIO7qY; z;~7O88c);E&CZXdl{Q}#_`4zsRciMq=Lp77Rm>cJr}>R@lxle23`beZd*SeU;peU# z(b+HskQ4Q_#Wn-wle7hMu!%SiGndHUWK_zHn`&@omCa)hp<#(VaoTAQ|LHxgJ(am$GH1+j@4WH-=8y#scIK5|UEi6Mg-XHbck~3p zjqCO6Kasf4kzxuCHUEw7i zkpPYDH3Sm^E&nmi?}Qt-^?|%?nLbkn9C<`dz7%+ggrn2=!t!}&B%?F92#?h!#!H48 zGtAM8eluOPnOt4pMqj5?WH}!(aC3d*FlWqEP<`TlBsd;Vmv0KwG9>af{e{wM$ ztJXekL(0O!NG>ULjgS!Z1=V?9#m1t4UqWR!G`p1D#bb}U{YcYL(pKIM!6V`x*J=dw~%LM?!r;e$*w(2Pgv4zyg8ITJp7#l^dUe zok&er-%0E+Ba19h6C|NLcl;vY3)a#CG+@5rj|nMZ0F?(dH8sFXT}TKN&}A;NHqgP> z*b|F#GYHspl?+twf5^Bs1=ME3Qb=XmqTSl&#c=H|>YNxHtRT8WiwFy%&UEO7$!#Zi z7tRWz21@2b^{tC;X%DUhW(+SGId77bBsVTok07mKlxD)5Q&c0*3|Y1A%Csb|z~5S+ zv=8{9#@~Cs6HY4((J3s!+ zf^6Zz*}P#u9AQakv0sfr5|Pj!K%T`3-grZL{QOPRiWy^QltR^J0u3|!%)Xi{fI;TB z?imh;IL)9g>tF{*V0MxvR2DPxxHaxWgmA=?raMwyKvFIDdDz;;zxFG&5CB{sY=w0( zSRt*uvR0<$@13pD@gQrQivNY#_@qd!f`Cvtvd|!ta?c(oZ!S%S-W5L#D0~;}5uOp~ zq~%?S`3r!5f~t_k0cMWz}|L1!@or^o=Fed-hcrg`TLFW2+HB zQbzdy+JL-ZLeFsF=nqBJu_?Pwrg+=wdE~;Rn;xjN-HfU0n+|E}o2nkGP|=$Hu#30G zgPxxp`?mB1UA6O?epvj|9V8p3YWp2RTEWO%&>x2Rb{MwYZPx6g3Klmkdo=itM0Ez{ z?)RIzM@dWULdO_0tN!wNupVzX>QGn_GSQ&g=PUD0*8%btvmg0tu5w7J`nOu#ZJke8 z=_4hC-@?WhzX_Rj+mhopFrcCt#z4@nQjK_!(s?wR_(RQpdt^IZkbC=AAQSgr4G#px z{eP%a*QO~TRX)sjsD~7m1N^WKfL8J3)D&Q^@}Eut56GG^QeS^58{yq4c+9}!DD6KW zTT30Mz+VHE_r$Ffl(jEv4g{e!NW(=l2#ecABkCdnzlM>nsnI-P)h1f3*`;Y@Y7N8M zLJ78&5F&eHa)M_9GMb+(6+_OyS>MGDJK%?k>lF;($QRjt#Y`Bnb_?DA386Nju$CWF zq_sXOUKM#cU{MZ>o)?b32!2{B@pK>sFVGP zx@2De`9T!x7o2go{+ijK?r*h8=8FtM`niFviBWO5mQ>1OISeCy_z`0`TOomB?i+-y zK7x`fESx!1`q?`mA!mU9pXFRjEoB=zT2BYCw6?b^0&t-9f#<+ zjj+%0s!e)8*WmThfMM$wnYZ(RbHAfI*hq1Gw}Y*BICT6r>#P0ri0*f?+=hKWFxcmG zQlrq&bILiJqZbZ>;Roy6dUG6zY26ly!#^(KII+mvWe;h!QfKx)>bd{xgAxhpf0$(P zUdLwp`Ffj1rxC0j?*f+hmH?VT!QG1QM6Ag8?Q4U<7<@ zA3i=4%YI(c8P8gxza$)74^w0D>r|5iq}ZB|W&=2oV5qL4g^seX>8u9VeGp70S)qbu zdKax@Wy(!zhn~@pozaLWVah7d5X$9$g@f(ESk#Uz{R(k`g&|f@U=LNQ6j=ykt$-?2 z7J_9=%>zey&_>2;1&*2v7L1a-;BPplh#4?fw8zHk9V$$kF?ewH)lg<3?`%uK{%0Xa z$=VXMy_W#Pwc-oC#s9670GYaj18kLLnwt!9vrQIIPgnZ>z4zSqH;8+@qL!vms>I@{yWEW3jNKl-Dj*0=Z4BKGcyqPCqudNp`bjnUQdb>IrF^|p4yW!fj1I?jswJnl%X#u zrvp={s0IsZwFi+ZU)P^52)5kc=RE8U`F7ct(?&*t7h2J=9sqSL8f-S3o7?v@3aQKilmva8#6F7Q3Y@a zL-{Qw9s-ZOhxR~N`o{+tk~W(|4=%$^I#}a1tKj{AF+RR`Z~cFcOo={Yta1wz*e#|Q3C35G{X>h>jBQ!8w5Ns5_KQ**?}u4!t|rTCnHDb=`9mAq-Z$6%v|lrF z_mL%nYckTV zOhyJi_JB!VGlXz6RKX3BTLfIrzqYevgary@ke+WF%Rwd<&sdkSs$j+iJa)Vt5z_YA z9*ga|zY<1c2LYaAAR)*=v_U)aVj^41n;U^4*xsI%xg~jW$?`W}5wlIWMG3@=c(*CK zp^|WxmaK;(qKhXY&D4M$J1VMJvFz&TX7hKsY~?_IBM;cmLw2zgc(oV-Dy&0v$O#RymPXmsn26 zhukdU9}f7|o2i4lhBBF#c0Ge(t`y)?!lx13sl9(-WN^lg&_w`4N&ul595@vMjBG4y zZ7B)k&;dV^XYc=lU!bv*Bp;N?wXBJ>+kP|vwzhN;>7MjeC!y{uOo~w3VS58&D-dJJ zU|#V8`sDTeB%RZgd=Ze;g3c?^zN_5aztLD!!CC3u4UnpGOp@9&NS_*LS~Nc*)Kte- z>X|vi{C|ncd81nOG@1X2r8K$9C+-amR~DY8Hgz{*cG-Z@@)=^LS6rYBt@NjV;$%W+ zvq2@64$_LO$#73Zb(S0Xj?ilN9NhSu1p1IC{trFim$esnA+{C^s9pXm582~GPc;Il zW3k_EvAM=O*4&#HTZ{uVz)DzB>UTdF$x{n-<0k;erkz7Rr0@_ElN^V9Wo>ONEIK6$ zQkcUx@N)ugah}ri{e{JWwRWCLGGS8gd>+Y=3)yk~b@d zievvQO-*E%zM;zO#|bDE?zg3^#!&oWQ#=3%nqQ%qxg{L*C4Z(|SO&hET#6>28mumH z&}zKA@*^1G%bDLHbZRt_KmlNt3)qGHS4?eOeWLWs`}AroTipjC29xc668~^_P^bec zdkGiQ0lkK72tg|=-+^W^&~nsW1=uIx%Fl5@Hswd4GQ9ncqkPc`9n{Iw zTRYf~63kmGXl@=ad%aP-!!@#2))gztrZS39%T!LCu^PQt&wR|Fa0}b&C82UnAmZVT z`FHy#tLK~f;H6&`9C<35C85t53B*{a*j1r3$?9Sqg zO10N)SP=q~F!;SEy+U_MUIvL4Xn^tGRO}^g%e~&Z8udA&P9DPo>-wK%8&I#4u|THD zkfg@gsPn+Y!XgdMuc?VCEu{o%nvQ$qABECwWd>!6iPhn0@9R+fwgJc=0$y%}MC!WN zes3-n;0LOg zkI=8?A)Y#POC47)`}sw`^2JoFlX;9AuHB*X9$lFj-DPzGgs&x+Mw+KHgX2rq4>B{Q zV;r$7gV3_!d{U$9g5#0%8Mz`NhF{?3)AgYQ%}f~(Looe&6!N}M8H`L=3VEeVIq-3f zC~W@T(R^q3J!1Mf!Cs2|AH+9GUTWm8>m22(oMm7Rq~>|J<-OKD7t z$z^tj>-pn88o%=U7O$td>}25*S1g;j(r}Lhy?7bLLOp(TTG|s)peOg;;gs^3l#>lI ztg_IY0pHT0tF~pWXCfZ8f#PU&>#j5DRT#4%I0*PL|9(+JmJB%>omTU%F?28h4ePE> z965>>DFKFd6{>Lh?TA%fpRJ`o{L~b18RkyDBI7Dyc4abY2g?>L5ms-wAz2e`qxGS` zF?ji9!r?7Ea0efO)a&qRAW@QO@+AMk_R>J%C+ORb+ByAEj*~P+q_W{WbwV-eD)^*Cc5J+fnk@QXa zPS{s0;4;NE8vpz5Bo83VpnDIkIM86A01E^d9!7}Tcl`p6+;17h=Ki*ST0qpH14`F9 ze9{9RwS5M3OAy;IaFI;wyJyau!*b0n_4C^)K@+0i3tD)yi(d-x7Eq)a2kIX87rk&Y zGIiHKeb-lSf1@sF5s0Y+qYNM*$IA`r@^@jB^mW9(BPKYv?6IjlIH{_7OJk|H92ABd zO`tUK>2|odk46uH7W-&eC;k3@(9G3;-BxXs=&) zRS)*Dx^j>FNUQUo66p~rrA1jU25yu^bPOz~3MKXV3EyP7Y{##g;YM9{$8WP?F9)~(+Lr#0L&$?(L ziwx3f=+9Fh!h+q^6mSkZo57-82|40QtB!b8V}&ZsN&Vj*4@U8dk3&c4)L{VJf&kB4 zYjyyr0AdXTO{_ELQZz7JwF&*_>-VpaDZPV=l+m+`knCx4GB-SGNz%DkV8nw~1P zjS5AF0N*GLQm z7&#gVRun2+$Um(Sp?4-hcgD)D&G3;B+0pNTJAbrAFo}xGwjE-$3s4G>(ggw5YQ+mf za$oFVzW1Pk#$|`{zYj#t%KURC)nTZAcIPh+o@4ZQJsC@3tq6)}$Lul5$Xl4iriy#( zvyCWcaUVJ1GNqVy#FQQr`lCdo0&~Sc@sVt@YOB^HP)!Q5e?z{8xmfD$m7p{W+>wd%&lyT78*8!+|9|QS@!lcM#i8A(; z1_sbUrI31jgWo_;P-?k=`c&w z_Zn8Ms(9Z47wv#S_`?Gd0Mo0&Me2@zv|-n&qFq&}1uOqQbiGwTU0V}0h`YN>Ah^40 z0tqg`9fG^Ny9WsFA-KD{ySqCCw}ZpKbMJTmnTMG-9uDX1y?RNl?y73u|2uC1-@on* z-rDDS6_j9O4PYMwSTw+v44D`JP995KmbeHi)jgc7$uSd?C!pdKEz!5N)CBoqB#t9} zz(*rMu~JjT<|or8A%3~qciA^+rJ^A3=c`Js}0TNz_hr5+F{=M*hU;;b5%M zgo};qs=@Lgwl&Jp7<`9$}v5RZe{>`}gqcZ>D`!_Xsh%sQ10YlAX`W|mWUUjI7 zF7sQ3S)vvO929^=Zf|dYe4(Vl zLf{D~PeiLA8c7W7^w;T4{qT?pIwMfn4Y;E%x>>nbv+Zo|v~`eUdREtHx82+y{Dvy7 zfgi|vhc>B}nGIb{6x0sV$LxiWXAP)DBR34b{G-?wWCw6J5OE0S4a`si^=%kwdx36f zRbS#81k5Co425EQi3w($arv{$sA)h@`+v>^t0NSIj)7^iWQx}!M>*4bQfpdW?MV?* zedkwIpP!f)E9|dOgk$N5NDU9nrPlCVn4tZI9m8sX>`D&cVI&w@f-O6>VEgj#hFbq%BOZLagC)Ig5<4fQzd-i*I@C{=B?w)7d01bviwLK zjIAFvRZbfWrTxqDV#-vdBT4d$oC3__r+eJ)cvM-t`SPKqzizR_V?}6Mjo{V|b$ zxv*$+<`9`FBPLo+O$QsqZbBrqw@>222@e|#%y;&Peu&CW5MB8hafb86W6??yHQ-X$ zow3aBewUd1c#EG+td!EkscHi6`+BxHl=0%sM05hfKC+6sJ}C39;dK@zm!Y)@d=nht zbczf(!j{(I03^b+v^0et>%Ce_J44 z8-fcbV;0vT^uCy!O3#oJrZ)&-FCR!4eM+_K4Z@ovCRJNw4DY)_ud9GkH#cK@cF(7W zK^(ELvua=#msg15!9iU#((wbdZl`xH6fnklbcVIy}WN=bE4>rVLPiM6VzSMj`m_`bO2`n%s^)y0=kkDf(N?s5f!#VrY{mXot;nUL58tQD_ zkePu;CI!vWk3~kAQL)(sN*PjU$N&>&&5BT`4a)TKxQSu<%L;{xhWO!LLt90Z#?kVD zR{CNhEFf0$fT+$Iu3JB~#60~~rj}RLg}k%ly3_6JD;D?0mGOXQqdhEtf{OlnhGf&l z-j>@a7A?AZw-G_3iGOvR# z@RIh6GcyY@6sKa{A08)cn~v2`Ivgjz6VUHxB24JBTc64O5#&Gbxf5H9X`}e->Rf?a}+gqCogK=D~fLs!FPEd=4e`5 zF7m!?p5a&tF+f=eR{e(M`kk9UV8cy-T*$emtb<`T8_o zN0W;`${2>BB^4jmbhM&B{yU1xN&0rrBt}y=f5hA3Z+Gf+58@UlcUp{2T+@|a*I-fY zde3|%vz-WVvw5?qT(dS3rPZ;Ey6a&-Dyp)ImL2K8d{(pHFyro*`N@f>yTgpS)<;OH z(|@K$B6DP@U)1hf$0ApOCLzeQwak!WgZ zeWk&<%TE@BRwss)KUOws9&h?FFzxam7vQA?&uMkuV`GL{7N&x6DWO`t=kq#9GbnRg zmKt5HkvXuw$N9(N+4D_EJE?3i9J$3TsS-=~ zwR*m{dS5vKgP^Dcd=3G;423A2tq8e1c_LNz*QxSnI1iz>dR(mr^OMUS9WM#7Q*BV^ z&4UeZ)u(@e;PcN+5)>TO>oq;$oOAZ~*ho*CUDH^h$v+emd5&5*m>dZVJ_kZR?~Th0 zk@!vNRQ4~t$#!pw#BR6P0uSS*?k%qtKAz)FFMi9<9~O08xZf_`LM&0?bM$9!UO2T~ zVv}uOHj#<&>3nZzj#GtWX`UVX7nu)I?2bX=F@Id$=-YoDp0_3snlMtB@D!7}5*>Qq zeTcDf%u8WC*zn{>ZR^Nzt|r3SvdI|g)Ul(*CE2j5OjTbSvh;n?BY7AUYeC#9I^J8V z-0V^-fKsTUDf5gDJ$FyR-O!R$MP|F6nr%9YpXDVh1BYp^e9dZo6A1mN!;0YN`-1y$ zaUy55L?v9$Q%ua8b+vmYZNABtY7Jw0=0OY`&>>Rj(!&1@GdIGB5P;m!8a$ zDu+?+G+NB5^oZA6yCaHJbxoK7uMe3JpWKqxdqdiVNSyBqn|LO?7kWUlWr#HbJ73`% zAiB%;dJgys1liR`SO;~*I=Go8K?u%5g)XQGsvF&J@7rH^r5m7o-cKwRFGGKu*9;%8nMn{T3jUR=3*oNl}Ic0{iI zP>zVdt2;RM>^oX%Gh_DJ|1rw`yGHG$_riQuKQ|Mhd{@}@+vdgLwBE~4g+s=S`2vho zXIxi-_0eg)jwDRbP27oYEbEw&Z&PG@x6a~Qz@laB?vCv{EMq_F;~?oPo6pV;`Ipzz05>hVC-TjHR; zZmU*=du6Y7av@)=m^Qt>>vr3(7_ZrVB8-`X@mNFFde}CD!hK!bm$?E@%Ql%T;0zXb z_Zh~%c_0%CKZk*3@&VQgsWZf!B^_Otd9?JcxT z^xnVvr<)&E*ve7lsDIz+%(k@kzzH>hoLC=OK*p;&?H_{*=tJN((Ck+AwBco2k4hcThq z#`D{_)2v1U=e|t(x{VVlE`jro!oQFFmIB;wkDg~u$_}DY5$du8!drX_E6_50Xg39S zxy~PEoxQG7r-|%e3V9y;DDbr|K7n74k{ni}TJY{Bjq-Z`#!Tt*(bF1Vv((+srk^w& zqw$olC>`MJ`M-RT>qHj&i>e{2))#=GTLEJLId*i+Q; zisHe+EK8i}1oLDw3~Kcy%*w9Jge)L76Yl(KO}Y7qgF2}#@wDUtfkZVl1X*aW9|@B{ ztXpck|gxCDL5X_NeY=k_^{_WYD#PY0Md;s0pbn3BDuZM4(ff zKf+@zQz{U$YnUdu~Esd@~I zk^2b(X`gdJZP(@fm)lhAJ%+#~Nz%CA>4TlF;Mx3#L_)3;yxMl-?4Q0=300taOhnk? z5sQAgFJQHwau{1C!q1r0QS*r;-Mm4vtsGAhLOVE0>qH5WH8pIykVIRoGM6c1Rj;=T zTsPtWuA$p{j4>g20m1Y(!rlBXD4o>n;+y99-I$)SBDXPuY+_`NqH7mN+Ogrr z3dDI_p~C`Jq=s;Fz{T4sxUTw=tbyYwBFeCfkgy~pMH~!T+0!+RCTXafj4#n z5~|e&t1}CIl?e}t&7kL# z$rulj9{?Oj_YBCn@;uPw-QmOJ)BZ`NE)|;naR~|(_mJ^VWPZz3QH@er)ako{Joi4> zug|cPgVoxcO;RX;-Bcwti?e~#WS^OOJI)`NJG_g3r~&oz+Zf&TCbnwEwjG) z8mBrte5>5ib(=7;x4x+}9((bOJt_Zci&D>!6L{nEAd3R8njIR^*bR#W5^s+XhpxR1 zSFq%XsNCd@OE7uQEX;QMk)Hj`uH5OxuI6juNZLX-I&FL9ZaXskoB7QT5p=(OJEySt zO+LD|t}=u3VWT8FzBW_Y_tFwY^AcfF@D8f;v6A|6RB`j*pmLn7E!wokSj*D~p`@1t zobR_4+7ywCaF#K6Qn*3D9|hx1y8Ptw<_dFAwg{Z&9 zFj4oO_bHfPoUzpK#tz7j*+%GvD0k9pu47TD3hZiJ>=rHeUiHWTv0}R8kpu)2=JJ9e zcPL3$o5Lo4?nQw{40-jgSX#8P`o7E4#u^bK=trr>5k}x6@L2z8F7AhXjF(Ow=G{&^Qoa|}FbIkv8FYnXCm{>__ zzYH{1>3k3vy-{IRY_9v|6=-e<9y4I?)Z*a9;>!7W-BC^{y>S}wRPFSHtq>r?XYgUA z2G?!7KlK(#I4wN7m)Fq4Z=bnsNLW`x{&jnBiudOR4d+lw;C=6B)KLnm+&BvOs<@9= zWY%YAb!r_UiWm4Ex4(H#@Lb2-y$%=nn_v6{E(EUR7qA5DWUc(`9W}5{o}pCL?@=P- z35a*o8>=%%MXS8A@+6~w*Ouop<3ZWgvlZ)*v)PiYCk99c4h6U_cd<~_|BU(FWG=L& z?6sY?+WgwHeLL|&Zz}=o!}rb3O`B%#i&b@C$s1H_jXd~5K3SofEIrdJKBy}~eG`;s*oX}| z_e`c0q{8|I_c@?Dz(5Ti2iY@w`B%G(L4ldAsqh4u1r*E8SE6F351&cV*I`rd@Q$Ou zv*EYQf(Sx&Vv5af@o0+F=sgx z=W}0u#yDi>%0mKiia$@XQ7?}bXQvIk^**be)@OO4-M^dROfvDtvgV0F5#va|b4K>( z#hO|zNoJDHMCxuw?*jqa`!4jJic;Zot7?O&Jx06hbvx!A<+-Vt;&5D?-z87ZbNs1* z$9BKEP-Q^ZgRH(JJ;2hCK$6{*c(uF0IS__W_leW@p(+@X3aOBFD`%?pry5D7 zbhlvQaj&);gsI&?k(%3Ovhcy8psC$a7}@WI*+jy@;X!94@-?<_<`>vXiL~X)dKk`j zpw*`{T+mes3V|F?vUqlL=H{9McmL#gPJUCAufU}m7f1F0_N+J!(kbhzoCR@crYnSR z^OgMCi!ch4fD4qxqRiXFGb%iZGpA&u8Q!|>^?jrBiX_)IyAgv14(uSDg?4&K&iO)k z-6dSC@C)jn7>i$1nK_SDdH4&q^sv_1b2p_0oc4REuvbHwsF$;wB^jQ3c0__VZs!z; zX|6BZK)yWIA3F#jZfW2EMU&oX(JH*WBd~Ig=p_bZNbuJBC6-)0d+*{0?=5|d*#PmC zt-LShXWb>YcAxM}D(c?rs$zFtMJX*|gP#|BpEx+4aug91BT(I_T6vPeD7 zw>zjWb_RX9>^Y+jmqu-NdW;C^t%s$?DTTb%ksbB$C&HCa6u{LEtBK|x7~~)151K&T znh~;>LDfl}eSyqQ3DscbAr0Zw_Q$T1yO)~SW`|Mlu9#WRq+7PJYu(cBT`HqTyG*-H zMxhue1iw|=2OUwzjdgIkWOpADns(?1XN&xm_yg%}TjGT`Ug1#Jo=~r){I+4Ud+Xob zsdn4=YiL!wg^w|8T3SLj1t0K)vlC%}*!nzaX*-@fi6QJ^l3qRS$~)LrwqxXUIwP2R zos<$0ed9XLa;eMi!N&FKV}5twZhS$^h=#Sl3Zj4s3e52_oUGhbEEe36@=0k)_RR7M z)6yH+DI@(F3PJOSDnUFL?bnJvxB*xC$I6zYdB}%xED3XhYDKyT61+F#NHn{|l~99( zZc2nIHkdRMTlUL!?$dKU=c5t?qVyM#b-TuMicL8)-q@e2y2T2tv15?+ndq|@61%^& zmVAM}2w$+cd>q5dY_u{ozZ=me+(`{dLPAnWTVb>foZmKu}uG4)of+dS)@IZB#*ybKMaR{O+@+y= zq3K$k7R8CV_o5Cqh)0FL$&vpFLZHzk)MY|x=a4BeyD0xsfu2$1hz2@p!r@X40S~+1 zhLA+ja^5bHO&4_A^@` zF;ij@x#QeHUEB?4G%?!fT`5aG|BmjudqnJ`b5GT+|3jbU8+<%wcvDb-m{&kU9nLoW zyT_x^nHJr@Nl+pbSh>Q4K$NWRAEU(#K$oMBcv!9VFD1U$v8V!d^$VC&Gi5$E_HR{d zgQBLfJ*}nka&Xm>G-_yaDJ*fHBTvaOct3W9i21p22AB99oTh7+sg@(BEOu+qF*2im zEUqB>E)rSIx5cQgcskNEF~dRAIlIxQTR&#`sLo4_Kt<_br(a6^p#WjaUc@q5aOk)G z5~P$vNPDJu{UQ!W26$bXiBrG0Xd|xqd=ybqMI3i#lk3v_TI;t)6l#p{5f3x5FnQHS zXAjeF|JLmcvjHi42)Qz0-$ox{@UK$trZv&a)L8wNeRzvgNjdJ%6SqgJgAmNBnb*?>Z|fph|c1ZOb}FK6!T`75xJL zjHu+^D)>-8uW(X5Y5Fa*Jw{)&5jJ7Zi66_V9DE+L@3wJAL5A(&i%BF;GzYK1QAw}~ z_T__x>yq=D){sYl*s0G*uKr^^U)-0|A3qfSNrZ`o38qP`8zkG08YG|n!9*83g@%C% z;^pkJXor?J5VVohLj=4ntvd?LQK@O^QE97Tf`a#*5z1$#;{QPSKzkb6H#V6hr{@<$RAXMhleInhqG{?6lM7(ZuSgK4jd_ePRuG12Ae*= z`(yryh;>!79uCkbmSfR_&NZ(DIHSYcyweRgDOl zq*33iBZKbkQw%dmbqREoLtZkcQc&=wks?s2VhH}QBGic#2u##djgnG0VWxjd6aUoX zZrNGLwB-@$jYbu);1Y2Tl~oj^=RHE8|M>ms0zd>^kfBvFu@;n*oc2CgMaHjv_N=jgjh`tccF^@)69mF|&j%w^l`ZO`Rt>DXdfq9-6S%(Xv!n%zO9t~E`)PXUP*nRh z+^+tv*JLXQ{w1R018qLJH{!0I|4yq$cQ6Nr2a{y1sNj{NN-$eTqsb)Tzcta3(VFOx zsLz7;tJJdoFGeM$29hEF7AwOpQ;-6)`*Ljm+Uuf z_8DTDICYh%7q=+*8*o+$EO0ON6|Y$L;jin;UmnTv7z^B5cn6Bt#Avp8{A8N^rtR@F ztQ4~-End67q$TegOIYuSfjSe?>~AW(UkWtmN286a%XQ9f+e|_f|bsKEuD=_o`~g1Ri@*W3nsAH0lz%6u_3CqXo171NpsdK7KZTuOd=~qXOSZ~WFsGY z4ol1*W65+c5iSaFE_XS`%emP$ptIhRk~Q}7w?^iZdU4U-fM4*0vo0)0mGF);l&yl>{&_RetQc(kR6@y>O zskdNsV2MC!{w-gP%eyn+(_q|*EwsH)ApR7za~aseShR!g1@UQkdbNch7kGOf#_=>5 zWyB5K_XXM{>Nefy_to^(f2fLoCnk4Vrxb~5DkXNRRVqH>m~Dz&cS-zp+_O1_lJ7Tt zc%w*z<#Gj>KUsf(o+4_%YlwGEYktq8uc+HFs(uDqCF& zrvj}_b!&1aB^H}!8(oU4x|9$JX~Qq@LWX@1Z@$H9s4pskxXb)1cmfv)O+q21im05f zhcbcwX^p}T`>boqvX3?mhlB#$BHbIU^n$+f>5C;vl)hk08hVh_VYSPdCIJC~&~jum zH7!b=aVq<*~pfR4h zqLl$OBg2WVd@J>5b!o*D@XFZ=5}CcTlJ018JN_KO@0I*btjN52u(K;zN=d|TkANwE zSzeOW{JoH12sAK6qW)o?P`PUe4w_+UJyH=Oa)_!6Jav9;1R~rLX^z-?8-Th7|MrT^oFlJVeP}*Sy2QIk!W5yEX4=XX!$QHyLnHk;_EXH_MliQ}9DM z9$4+muR}|@y3Kx5Kpj+RymatOYY%A8aNGthrX>_}sI1Itmn(jcQ8*;GR@dA}b|Sh& zq8I>1gk$>-fQ1F{knXrAMm39=b(pgMJZtJBKx zfW;IfqwBqIEaW|48j3|_6P>8hqv!j~%|`8;i8$EO9d!*7zh|BG#nI!>!#o@m>ggzK zdeZQ@x#UB6z5XbJN~`7T_ctIGj^N}=*bnfo{3N!R%~R@zB7B*Et8wR%A0p9LnVeNtDX}6$T zmfg#|1_C4qv$O$&P}0xx@~G(yUUive+PJoDe95Q@`8m^Hs;wq0+h!BH*T^N8hRX!j zr8joUQ4?CnA8}eYO%4d9!?5yel;Ox-694#BX|Kb8m{$O_Sg?Fwv3>u1_52F(HWqNj z+i-{nMr8cz?TIVVE3J}ed)!J2FifSDgWEl#qA0YBKaBBN3|knqNn`*=3UrvM>;gV= z*>|W&r90rgN=j5G#A(|rwUUDWwp|Y?FyFgz*JfIjYn2nnMuJIYG57$0_{8B}3?u|{ z7o7hUt!dvcg};>)RF_xhBVqEaUEw? z^!}?%3hcY|Ub}k+D%N9k9R}U&=K`)!^sP~nzD~rb%r~s(n{tQrhYiZ&5zeGcd%Zy_ zx(iZ3odN}*(WJ1Oa$!=*{O;)RcM|}5MgWR8pyVDb<}a4(S77es;sUrB0?m?vhQCb7 z6xowEx+TF44P04TMzBr==4>wN$i&3Nl#oWJ2t7*sdbwt3^etiihGi>NB@QHj8JrWJ zEYOC0-@yP6CRhx-a5lW8B+-r~c{I0#4q*7$@hGSy9vqnLTs`DW+M32GD8N~vUuw4t&E-zysvNCosolM$#`UShK!zHT}QvS`cuGa zgig-$M8IQ8*t8577+}Y~c9yz@IX*7OPJVB~ydEVzc;564IiR=MEfGH*_sD)BITSX3 zZ@;@~bX+xEwZmgQ5VYsM7ruj`SH{UoqRnucR^z?jf+51Y?Erb6Kiv=|IrYT zbyo7@TOa)Y6j{~3ZoJ*0KJL?(e#Ot3b7I@w?Cet$7IcBb_H`HXIK>rcV;F;9T27o^bNV|aL4a`a)perkyfPXTIH@}^OQHS`BH2*jIh&R8hRq}&>+ z9knnadR-}9CJ@v>sVb@?M@Dh_8?<)s<5=S1)su?vj+(seVS%#qo5!Kirvl&1lh`6j zdI>N%;ydIHUk`pcEbV$(vpo&aCFhG)Pt$t$fZ$7{q%Y^kJ5o6{Ii zq%>+J#okD*35fLZ3{seaoaF%eITLbOb#ci4`SS{(qAh|6*kwx&Li@nVP(2 z5^lR!+|>o%q2hnOWo%>ec)wFOU0gLb>+hfkg59Y z_wKJ=n-|}t+wpHQx4CU$%)Sfp<6Lg z_eZfD%KH|!o@v{3UdyZycg+n)DYZ83+@oHNEGzSrcW=zivt-dGP;VP!JYR9K`>u?G z50Vb%mJ`U}i*DbkHQ!|R_X%xk@NQarjBP9}G6I}MV>Wya*-|K5dbNu0XDjtG89eBI zPfs2p$b=HEuG~OivFTN(rlv&5(8!2T0J0){XfF>D3fAXhDEE1p*)k+-R@nrgq6T=& z#eMl9l@Dlp>gwup%n1M|i_eO5dVekVr1ptMPf#R2pi9J(=oHJWDVCH%jh-z6Snae^BSVArtGE~*ke$usO9S>cK>zL$`_YTDdF;UXz^^sSrzou`Gkgp|OY8qT zV1E^_qNAW3vqGzOJh-ZAu&U~~qEDhW-KQomI`r@oTY1alSQ!h|VBif_?-H%?T7t)g z+aC<@^WF^QJzfSUr!*HO+ppWs=CY@%D^bbD$rNt~2I&BKp~Mc+_^< zu@9cZTuX=(F&bX)4PB2!PjFjN^oDzD2#c4Tj1X=!e5 zp4;4e>TAvo0PP;II$qQ#^?Hr~*zt$b*>IEmHGoie7m8>w3v0cX{}9eC#WRq zvu32ME72Xb1P0!~;Ld1dWHm`Eax{0V%ezvuK4QB!6cZ(sRkl`-Ox=ba^!!@a*l2_Y zW4Tyiyg!l%_#gIGpOL11#KICgHK+WSK55UB`6`5G6>XkYq=gL2s1%uHELW4NEX*1G z8hT$jXeszecK$xikfq~5Vk8j^$H$QLW{DFiNjkYy70W058@IiOa5U7hZ)n)-jh$Hg z^{9Lerzu5w;PEK+8SlO$k7a*GS=v8a%x)%J#(rbONWL_x{Z_<6g`0D5tn2-L&@IMf zg0I0SvX}9iP+0%%tZw|ZJO^?1r+HR+Ca}}vCSNEhC0)H%G zY^Iki-mg*O^`1N{THZcdFu%bsX3o$F7r~Q*)EOBWU+Hd2-ia9S7*=P1&b-G?4iDR* zK#=+k;|!~pm~*~i1uM{eV!?wt&80>Og#@ns026oG%xP%Q!uH|^IR&un;$O!8()6

    zXZOu3^W3kQzr1WeyKk)rHXlFmp|oGhm~1?9``iza6Wz84;< z+E{h^@mE-Gcf)QL9&h>%baGny4Ghh8_JlL9cLn;oMdEJ?1wk@5M`7A_CJ&xJu*TAX zOJuzeo5)yxAA=U&X-Rv2*mbBepuvt*h7)zu&H-$e9+zK;3D}RSe$#T{WP17e}AOs<^lk``Pt840(TU= zTSvoKvcW4~lkH~bIbY7Z2Ol2GINY>&fy(Mmnqwj63U4o6W0#mmR4|%n3*dh$FE5{; z-}EHtT1D4o0a*&)xR}%>OPr~yX;c}t7x zKPfigo~5n?2X#2WbqxSDfPDy4ve8%yYvS3-pFav% z!TpiAwl(Kfe_>~P+`q{o+I_{VaB;e5`(|P|6D8hjDVeHdOOHIQafYgC*KJ?K`_wSjZYi(9q{a?KRO&pN_E>{_d z8%x={f4EFqz$kkYB8f$9*|aX+nLNA!WC1O$t$=L&HK2QAV`JnBXm7J^=aw)SOTZaX zQNaX!GhA>_U8Cz1z(5D|mQuibFP;2DPWh)e5=LCm(Ls_t8eCwWs8H1+W>-ZgRyeC+ z4$C#38y!YkrUYER(IfkZ4sX)EGfGOv(z#=S>pXzWVXW;d08|ecyiOi!G}(a*3a-Dx zBm?(>jqew5u+cO(x?cW`$&y9<#~5;?+bi>?l)&ix{mJJHz>XUJwIonPKS6jD#wS}U zzoA%)C4GEmbyb=v8Bjph*Vji8a@&-aj{<)I7Xp~jUeR2Izqh^W#TEXQ2t=K>%TVE) z+sMi)8mf~oe}yu@H}_Ti7~Kah8m7Ag(dl(qs6?NX-dcONkJK28Xb^(M3~C2yLj84g zbQpA6esWqaAo1cc5RL%Gse`f9XmEBr;ncrQo_^311fv7Pa?xAkg0z zqDokvme0)wK=ML`&gk#22|QbVkPWrLjCW_D8s)j1ld-Z(YO?BN0BY*Dy@;Tl1Iskg18EYfc z>Gy5yR^AIwoCc4o6OTg@Bb!X^O5l#z~e;~rm5=w-j7KuS6X-nnT zeejDmhqOccBM_Fr{DfgDhhosVkKczYI11_O5yC6&F$7etu6dZAyOVi%e*e(pPY=C# zW@qkbO+vCE7$hD}P1f#%r|`CVyf^tbArDvmOotQcCO|?Zm!Y2e4ao`vLlqWaQH|En z>Fu9!P%juG6BeAfLfNlF7pxy*l6anDz#FSiS z&m6SWdU`n`TJD2^*$W0!ier=WC9dAKL-z5WwHdlrJuBF75<_(#98e_sqSYSit%2HC z-Cxd_l#&7@{5L)_J8s@BUJd5+GIWKtjUv|Ks0N542mU50kSOH?rys46wA}`2*eggn zfa>)Qn@nI+q3J7Xi-5D()aEc%A9mY{F4)y*H;+7L0B?T2H33eXv zgf8R60*~jKY*{P@@>%Eo%-88BwugG{HFCfHo$!W}`!|nO3@7ikuA5h~^XrgzoFm8~QnoL*IwN9`-Z|6N@Y^Oea7Ob<~BvDZz&Wz|zB7-`_4s_;SP76Gg z%2QlwuqJ$bd<3Jm=D;8zkTNhJ4@DvVz|XIh77s^0A$_-5zQi7nh#~m6FHhm_iK3u? zyHh!?kpmda>eIb{w>H(Wz@O%A9R`Ctl{rLXe`k6KDBl;^G8W)})ot<2zgqXrG7!C1 z?9jWVR_kN|vmKPfaDT|7MY72?WGgu;`H3>{szM6nL0a13N&3al>6Hno8nJPV10=%uQEdvgsuCA_nxvII$ zhajGdIbR1f+m&1M!0SVjIf~UULRQ~ZQI7?LVpIM+l|bvBRXj}xxy@ZMQO2xtX*Y>OE?-+%U=Ie>jU8F z=fHJQxg_gT-;Iq$s4_Pr{^E_-6^ST;L_VSaj5^u7iphXav}EL&#Ct4G((&4Bp*19! z5sLryKYl_Q6*Dul3>9W@aPW6i)7_I3EyiWo`9iGKLe!Hxk0=QWzV&eF*#u|$ipo0} zSt`u%@bFKcKFvv~t|SD2D05(VS zHDR(=Ykcxel3IEC=v7J&<5YLH2*X_R5>V;2STs;rI8GrV|Jgr0Z}i~OIX1cJW49l~ z(T7Tt>nOC2=O-;6&Fr3z`A9eG*Uh!pgGlY=p5YJEUt^)1y6+FAzX+f0T)24^u zI^>OdqdxrmPo5Z@QVY-5G|l;Ix}*_69odm$upU@K34!gk8uG;ukQt=WI4($Zya{DC zP}uzT6lt$q_K6fO?ZF||s%XQx zSf6?MV@csnJ2Oj3CQ2Es#?y-STOA`_SUp4X^$(%7>j#blA0GcmFR&Y-1xjp(53uI_ zhBaVxpFJ0=@}S7Vg1*R0#SqtG(}dg~hFFHOn2C^Lyvm(wTv>b`WLdS`0KLM*;8|Tys9O)^>fgt2iQFLDSF#hUacb>E{TDk$;FyrE}BC zN^tY7DZJO%^eQGPvZz2nso`}vtL;hsW>3Gd?aF#)iGt~uaM{Aan@slYE@wt94GJgF+Nm^D zkMajoh5-Mq^rJfJaKQE>RoBSXu8K=p?9R0o)7BubuX4kgcorTfZo6*(cZ+`FS`)jw zFhcXrH)Rlx&DJ_K_hptYDivnQ8wAz3cSzO-Fj8hLAFVu3>~+__9W_awU`nJj;j+FA z5aOXZmQ-BP^{)yUjt~)J3Y|+G@lMj!C^>DRCNaH+BeyCIbAyMV?eOc3IUCvR{+bFY z|5Ek6d?(XO zg6I%HRzAB@0jwZSsBc%>!ACWeA4ycgwfAj3YHF3wGGw~%N0U7`)Soot|HRifpXKuvQFA(N0Myoiy=5` z%5umUM;_rwr7m{LxDK^g6B%mApV@8|l3!TTPKmnGRog2JPMb=@=D^P+Sg%OfNtri? z{G$R-N5Pzgf+Xtmjeg)vVF+w}E%0PA>aG!9a-ktjfJZXurZJ&!IihzzclJ&4>d2Vq zpP}JM6*-Z1GnB5w!Jat623UNj;Eon-b!6deen-LbYK=NbT-5O<0uY#XaZZk( zpC4FP(hz(4xLhH|;!De~U%yoAvr0;0B6>?4933s!P1#b1hlg{kra&7X8p|9j^GYV7mJ@g0WZoEfh$!m*u51kG1nePNc%}6F4qgMl~vW+lhBiI z$>HnB6+$2WF5$0?hP{zS?yXK7j=G%@mm`LpmgjW3UYCMwA@W8ODJ(ADmlzjiU-OnA zBJ_~FD?5{)D{Vq!e<@WRxSwY_ZuN0F3%a>%P_B@=1wI#8b+a$U&SZQTBM>%x(jIKT z*Ae&JTuBwO+|Vo#d_rm69R#|TsiB=IN(O&gCii)N!Az=H5pVb^sjv#Z#&Wq@UQTnVZi!6#&S!7FG8*_-h(FK% zJ}%L2((-I`!^iJ0SKzgs8w0sfVsv0gakp&_9H?t^fg+44Co8_%;DosClL7B%RHYD3 zKCDPSr=JI$Z}x^Fl2e*~XV4eQ7=2$eFX#L)!ET)Y(Q3Ia%Lfvs^%M^V#bLc8*v{3Y zHkC=Ig{K88IeC?i<<>(mD=Q1wy>b^%rjMOsV)-&rfb_%6>}+^cRG&VJJ_iA>(-9i* z8A>WD)lx1QIk}4Z&5R5pBpA~8co%dmtWW7&))^$5sg%%Xe<8{<6Em~vXc8k}3f9(c zypoL8(_W_0{wE`gS$Z9~`k6IgwS&ter;N%LMfe|eP`Ksjp@EY~#8|2KtwGyvt-7G> zt}G`gR!2Qe_B!3b)CmQ7DmL4cqr!_zuye42om`DGyzMy_p!c`R-~RUSnG%~wx_B)7 zkWzZlQZ~^?mW1@i{mOel)wn&vDnCn66{bUv%VO(5fNlE{YN>V1dU#><+>PL|e!~&? z!TBfY^4QKJHR#0o7Ix#!4!Nb2WUoI`E0=zPY?U2~7-Y0Cd-sOhOy7-(Mf}Dns4yCP zy?B7tbn27UT=enjS_!FKPz1LpcrhkF(iagaiJ`&g6@7FgL;A&2etNX>z_Log$qe=x z(XiR*WxnpJgv{s};r|f!)=^PL?Yl54D1rjgA|cW((k2(jC%`bTg#Lz|cd7 zv~&*L-Q6*q2jAcOt?#UL&N_e2Fw8vr-usSyUDv+%220vtaT!nJcj@ozwW+t0F%1X0 zCeZ$`OI|~En(u6TE29iU&qRb_PIQ*MeY|MoVwHyMM05-c6z|_7i7OplTu6Z67P}ZC z=TV&oMZ}Jr#u^1fudn= z&#FobO8GnxYm@3$u%7r=7+p(_4<=D-8-^pn zW96o%GtVu_5gp@YzjyW5Pj`1;r2xe^0UP0~wY4=YT-*S)A}6^{m=+X5RLF9Iw)H>U%5043{Vl__nH^=CNn z7|djMuJo8P&CJnV_XbgDnlYq|{@$+=&ck1HD*q`t6j~40uW_KQL=7*nmY?})&t~eZ zxhyQDgLRiKY6mrGOn}?c?B|$ezc&^_srsd;tuN`PaBMCL=G0Ql-=mqF3w&>SYmM`& zW$I%0tqT=Jz4cn$Bt!$g#xlNieId-isele6GJmu2h*~q!0PJC#U=4Nu=}0d+LLL_ zT7yX9^KkdtAl1qkthulmk;}g#deDoV$zSCIc8~WAf7HW zz~yc4mbC5ZMFzA-^Y*pRhNiIXXGN6G`~tf-#)Hd$TJl|;TSDJFYxs$UBkCzaDOli! zs*qvy5GELM;csKw7BS5~*ZH>^&*!^XswfbM;tYU$r49QA2c1=4?KtwX6Gi5}2~A2$ z%H>s5!Yx)S%C#R>D1xu-dVG70=>a!@i;+x0koPS~GA+M-DV<#1+}xBhvS26r#KuMv z2@1ek@uarxctlONP^CjYUmKF>KTO3G@dht}?2^;Na47gGct>KX81?Uj{GJCW#ek%) z#Gi%ow+ooJ2OlkEyh}N|Zjf{JCYZ$77Pcy*Nz9Q$%*QDl!3}Hqmw9at%7WY~7vDSf zJ2~1ab(AE4DgoI49Us5vn;;dejYL@G@qr7=OzM4`n_aJS!bZGVPY%9Gb^}KGm zD)dNH#Xh7d#pKBPhp^!X-TFrX`D~^7TtZS(92l%9B^5#;{2Ojz33@YA^lV=xeE-rC zrse6W(D>R|5hExtkmtgIStZ!=?O$^ts?RL&p_G5rOrSkqQ<9MBLe;Cud^cS{Ui^rl3Wr8SI^;Dm`%P7yn3EpJ;Fzn z8>s}z(>oscrB@k;8zsL~Q5?O+s+)Wn`qhT3ji%UGa<9*D5(m5@Z3ncpIxY?S`&=B1 zt4<65a-^U?7@wXTUgdpi-^Lk<+|6tR>mks7{Uh=94ySfISMl0z!bjtImg@?^LX;G^GTnD++v;K7JfkH8+^Q&bEL31Fe_??-~cWWdhZjGgGry=gT!hnASvG33$fVV3HRO-;bX zvU`gyU{V2hZtPHiW5&hDp8)oP1|Nq3b(JG82?V07r1S%BkzZE!6R48_pk{r29r#de zMuslSEdV43RhgVa9Ne1$uA@MXdbYuEqc_kC1oK8v*hE>WP&jVUKOj9F-px=9jjNqx z32m}Wm!5lkcsqm=2#<_RpPt@oEKpWP=IG?4ZE|u_N!-kqIcLO-mX3~`iz^98^8l;E z%KAo8akdSJy+K!3u2Cd>&p#_Ey%84|H}#YQc!z+100WrT@!1)0M?r){t|2`j1gtjH zVx6LYPX(keGiFL2+8rZC78)Uz=&CAJ8JRGp-R+F}UyPsVZz90CW7|jPr|mhc-5Mm(2{?Al*R7_0F4-^#TT2Nd90u?PS89@0B?6Z^Q zr~yj>M&5GdecZbhsX+mFB1gBuISL{SAQTXYn7H^8)m=3m02TZCHG6dzA}{ahF>81)&Po3zL>SF@4Z%^V!%m#KkjeM z77N*ggh9>MvSjRVd;2p0dGqu0`$!ZiCMmgkco+>}Di$zc7Rt1s zQ2_?4fYz!3Pyv}2o zF9KD7rLC+ZXJGKN2y?yh&09SA6NFbl5UkiCqNC}n)Sm9D;|eo?QHA{KRD%+HR#jyW z3`B9FMk%6aW;VGzm_j)c3rI|s}tAW|sB664ZPjnP{c@mep-5x!ce-cCUK z9#$Ybmk~GBAYs@6L`wiSfLbIN0Dv>FJ>g!p24uW3iHQZ2Y=ED0cFAo{2wkvf3 z+PBiFbpN7+D@Pr-y8Aft&a8XeB#7lpH6V5ekC;(%aVcW^i-edc0!2%DU_CY!9v+^n zEB9fqg}$6-`a57Eq#oxXWCQ3Fi2*M3e}QR#v?Pp;jg5+qPQlK8mbbe9@(*M_z>+tE zi_O8_9%-t^maMK0NIQE|p}&8d0b8xXBM?A{U5m;X5&h7rN?Q+Ccc?9X!xB5dV|BkF zJ7FwC;p<)iQLv@!=>arcG4X3_yxk!Vl;tk3LmwCF$R4oN)MeADsP;=P&#z+R;s6Hn z89)vjEH-;lQc=NoFP>CXR7_QxV(v~r4FSTGbO>sCBg+Ks3<6&fk1%sI(lX%Bsgi^Dkv&a(9>(tqXuFPBx=*VfQP+8AiQ5PAg;o_ z-WvbjIKeHC^l)h)sgy!SpXaaZ&(0yicI8v2#+w-q+=okPJ>ALJ@=ARZ*M#Cst+JH2(ak*z zdU44d_#1P4kx&KnXYFr~yR_%n51xB_@5naKjext|ufCToL%LFjssqQ|9G10|WzPbf zn}S}@2y_h74pkBZ4P0-~51SEB7+g#YPeP4{GjLqpja;72l{dpA#8o}hI2(DLcBH$< z!#7A>eoi%n6|LwE0b!elFZ`~NzuzQI&I3OubNkF)s|uBpn-Vv&c$r=-?wev%hD}^d zP<%>?w228dQiJopMZA}c9}qy&>#Xg+Fv*%sGsJ18@5$eiPkuV6roE%x(CD>MMgvuy zr*2!&8WUe3Xrii!2d@U3&CW93p09!Sk{d%b7talLLMB{)OT@Nh4vd~n%$?lGQxfr) zM-Yoo${&^+Z8JaTABTQ=X+gO@i*jea-`h^nu(Amn{7s<0Qcu6Ts}+8E1m_E%##x9) z7jfEZVqX0K|By~&XV#O9-;*ij@vPjdgBD)Ttn&15W_K|QLiL$c5A?lYPk zZ+XB{kH*ren>{zBqImEYi0kZOs;4H&9f-b{`b%dEID_>X*)lK zX5I6|JN4nEeyJ?=Vh&C1J=L7|1MTzb6R}p2!7fF&%Od$b*`b1`N82A$)oJv_jo=|f zn8)4v;$p8_LZk$I{j&G1`FXza;k2Z8atY|IYmH%>csWD_@GUIeXlRSaaMlVL+TMoJ z;CuGhs1Gh(aAPud`)sa~RfLjVGv52dd@+^wc{8Vyc>MMC^%Y{f#ravc@n?u|-}{y% z!GbkgDk}{>`ac`UD|HPGmF=yw?`4>t04EiJ#$JL>YCt%ZBCIl^mN#mf4WWR4QjzsQ znar69fMGazG>WX~4F0UjrLp>RnKZWMWq&mr=+@xb7Z;R9TTP|WUrE?JSoVw6Phm5D z^CAKX|K!5P#8i#J#`TUz&-3dC%(>yXC89z#hYQjRg6p5dtY>2QYR8n`9XNBONrR(Y zz!4j+7K(;;Gtvfnw5HV*-VZD-;5X2yJ9)u((BH zx&%0^R$`8_Ol4lH9)<491e|}I9gR#dggY=l`DAKqsvRY=LX~k;+9)_Id6w-G5_ta( z<17E_@j9_q3z?-EnY*N_gz#~}7}d+4=UjXaOtm=Y#5S8bb=@SC7bPo@+R2*YJ-H9L zTF=I1?xtHxQfTAzvanQlk=%JVLx8GFLOd=ZVcM)4fG`9iM~v1y4HVI2;;?}Pv7DIT zKas;eD)YYBkg?gRUqUI|`3T;d+Y#j+?7@O5iCz^wQf|AeikOOT<=_gMdG0Pbl5gs= zBH%j+rJcE;44yF`Eb*|a!jE|cIF_P#xTH~mdl9nZIYxom#8vR0I4&C9Rp}(&)jw04? zf=j;6JLsQG>#tp_z^^WMLI8CzvO zDowWZZcg$EEsPm6^GiGtqO+flwKs{HwI*n%6=d188C;0Ei)jUq_S zmWf=H)|V8gqds%>822QR80EBCLPavayU<2!Kd@3~szXB4d&zbD7cVXOZq-|))IBf_ zyU~IJuYAM$+rggD$IG-o6iER}3>jI+f3kubl~wLR$LZ!&1LhI7GB6$pgqJya@XT$q zcGaD1F@6OD+e6(>b8a^URv}VWB13a4X*w1_@~LU#%riWlOQbfP zkK?U*80F(QnSpWsK98hqL-IM0%~g%Gm+LE%7MJb5)mv`H&;uQShHnCv8j}@;bH{uw zVDbzl441zlpV@0#&XAjm_I3QpJKlZFnArVtwy@QcS3L7Qq2gZF)x(_E+9s{ntJlZv zB0Pn0@A|nRAAF0pm@uTF_T3X9n_mv#DWV?HKdF5;(SinX2<*&vvuXH)VUESry#rZX zTf0#0a_0B3NHTx_LO*vJ%$C&sToqr!A&?r-*`n*VY(m92_7mu)E&D7BWl~tL(~MtH z3~2GVPp+p|8l78xv;>cStiQ#&C2$@1_F+4uM-L$}!_)1-aE{@w9y;v9bS)6XVe>3MXjqsvN zDn}s0!amUVdRvN%Wo>Tj{-tw&~kS5wE z@*5`A#HIatkU&bP!jIuhM-1nJ?Sw2XP%(br+eOt~9_rtzZvRaKUPZj(6(#3y_Ctk1 zpdoXpcwNuFXX6w2;G6WwLS;7wyc!YqlGNRoHZxVikold^rkx7IZiNy-Twvdhb&x`= z+PLl5?XQDvAHN<4-he5pSGb=pTHRYdYhiu}a3R>w>nLF0!o)0Cx_sNn`C!U&|Rl4UF%eBe9v-2G+Xb~|elH^J<*{NQ3o>Ay|H1A%0FxN8? z`LH@GG-{|&OFMUQw?q?>mqNGcdc&O*+R<$$ys#dnzeC&%CP zM8@LCqL0bNG0ziTBzL{%QeCV+*xz$1^|~&#fdxZEl&9gBe!FiU&8hnKcElvsrz4x7 z7bM>n)}}ohzOuD=@dla~F>Kj)M^e_SOsaiXRm#}jPcQnf#hJrB1S)}z)NW%j#DK}@ zKJQ&EqM664r}U&2;&)BE$nX4&tLcO*A9R?MHkZ0B54Fbtsj6o2zB3i78Luqj#urKF zG5<8m{phyb;JV2<7(M$Ff|EaI=2iOD@nl?#-v(v0og&r06YD;A?#v@H^XO)fyGR?# z0Sm4UkjeZ07>;U}uHF04rns3v*X-DGE6nV3i_@IRkzgFgV%JVHTw_X80<;X%12Zkn zQdM5fqq-u;e(&+u`NUm6f!oIG2K)M5k!+%PUakv9fjV@RQnzS~W!Ju|GYyfkUHSWU z&S&+Izv+ykxoOYI20HJQml#Hoc2$5no`csY;3OU?33CKmJo-3Z$fr;fLHdEm)3r05nv+KiT^tYq@^A#ut?GSh;e*1O5o z{-Sd0m)9TdA;#_%648g-g|(D-T6Oc7<^yzz!OAKrLJwnFt6dRq<*nr8V4E3f8zlc~ z`rQ@17S$q{J4*a&E}CY`$xL5squ@F|_N%Zs*7Ktxm5^U06+4_fJSmrpKHy+d_YeT7 znVktpP&u(~d1Gy)RgU#q7RU~QDc=|axb^7*QLYOb7pDKqp;lCMasN6EqdP~>^t|EX zmCNiD)%7HDnx{XFS?6c-=7~{kX}?0hA2eGGL~*lPsLd1>W$s=STIzSU5*XyVTxbi1 zE*eeCHXZStv!zC~Jj{u8E9lZOF%>%dSXj{Od)5&GwIhHi)ZJHWhZe?CKGELn%A4og z8qe3x(0m^1F%Q%eBg1yKa_=UfCPzQ}NZ<<9(c;BE-t4x-yHX{tCEBx;+ruh@^%7d-qqOzQy)g2#I!Ye?ckwr@z)&^Ph&enerKCeEk7{#u((o$@B;=gO1W@@qY zesW(Mm2cMF58+FRqT7iO_=%j2)u#JDoMjUEYq`Z6i-TqjWB8mc_xE~-pk05eIM8XL z9VNmyQ!?WX{W+~pqf0@#5vKCBt zd;EJR^c+i(@+0U~DA#Gf*KNwjOO9qK*GQ$%YV*Ip)l}g!ZYTDMd!r+lDW-&DeHXuE zYcN{Zgig@<5~*3wj+tFSHe6+1itdi*qSR&evhebIfA$692>Y|y*uedIwSlPr`$>1h^x z!i!Z^O)pHLpj1z7IiRD-2HRuOY^#FQMj+&#e<}DIPw5uiPgUw0 zy`9#xi!`9rXc&7`;E6NoGv{Lc5b~%6>#Aaz1zBftnh*Og|Mvc3M9abqr3#rhB1kDq zBs0EzgQqerchKZ!a{lZUpMr2;0=|2|cL%gE<=YN55ME^0MXiOc0iXwDsK_)Jd;e18 zKcrh5o%qPo>b|Ir4aO6ur@CI;HtR;AvGuNQZ~yjlD}4EarB(#5rjEnGzKnYW(nPzO zST#W&>sevepgYq=E^mDIiqmx5hC3kp8nu1Y=EY+Z1IlRnj68Pem(=gqV&*8+-N zeTE(2+DOnyj;h-n+LhiJ?a;zhDrCO^w@K)0D$ebjHZN69WqVw7i0VFn$N&Mg3Ne%Va8|B=e&gjaMfCG`KAqL|q+hlJzcA6P^OIRsquo#=%HIaC z91BsiMQlz)S`c*=3)DjGC1k=vnt*&Rw319dzrw#9jW$7AEHXzJo_?K%Cc?0CFEg9?IMwg+dXy(eDsh3H)KO=27;;v2>s~r*%w($qiR3MN> z7Y+yrG=ynDK%j9-yVA6d1r8$KgGgy;F@6E! zXX}jz6<3vhU%_Fc_)&)X2uz%{!AI-w&WeUj9p@X&aFlQ_4>ffBa1@j>jXjk}CJofQ z$=3vxd(id9i^RZpEZd)xB~jcY9gYsY=yadKn8Tv5U~nDvvM&E>t$FL=6RG z*r}GXOS;*Nb-+kZp9(;iXz1v`jCD*m`=G?W#}#3h28vs!Q8RYr-~eo*iC771m%XlH zd~~Ayw|b35)nQcO)1F$=*r5#$kDd_$c!u`+djK4V*$)WAc2*O>MXoX5+qr{m+!BP! zYSBFs zvRZtQwzthkjn?=d6}ZZy%>OV3;{3Ar5Ao_Y|0R(0)FueKACE+gH-Npb5{pWjegIhU zZ2b>VYV1@!wz@9EKqk_Yn(f~o0{W�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 OiIpC!$rZ^w3-~{P2{ +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "test_utils.h" + +#include "pilz_industrial_motion_planner/command_list_manager.h" +#include "pilz_industrial_motion_planner/tip_frame_getter.h" + +const std::string ROBOT_DESCRIPTION_STR{ "robot_description" }; +const std::string EMPTY_VALUE{ "" }; + +const std::string TEST_DATA_FILE_NAME("testdata_file_name"); + +using testutils::hasStrictlyIncreasingTime; +using namespace pilz_industrial_motion_planner; +using namespace pilz_industrial_motion_planner_testutils; + +static std::string createManipulatorJointName(const size_t& joint_number) +{ + return std::string("prbt_joint_") + std::to_string(joint_number + 1); +} + +static std::string createGripperJointName(const size_t& joint_number) +{ + switch (joint_number) + { + case 0: + return "prbt_gripper_finger_left_joint"; + default: + break; + } + throw std::runtime_error("Could not create gripper joint name"); +} + +class IntegrationTestCommandListManager : public testing::Test +{ +protected: + void SetUp() override; + +protected: + // ros stuff + ros::NodeHandle ph_{ "~" }; + robot_model::RobotModelConstPtr robot_model_{ robot_model_loader::RobotModelLoader(ROBOT_DESCRIPTION_STR).getModel() }; + std::shared_ptr manager_; + planning_scene::PlanningScenePtr scene_; + planning_pipeline::PlanningPipelinePtr pipeline_; + + std::unique_ptr data_loader_; +}; + +void IntegrationTestCommandListManager::SetUp() +{ + // get necessary parameters + if (!robot_model_) + { + FAIL() << "Robot model could not be loaded."; + } + + std::string test_data_file_name; + ASSERT_TRUE(ph_.getParam(TEST_DATA_FILE_NAME, test_data_file_name)); + + // load the test data provider + data_loader_.reset( + new pilz_industrial_motion_planner_testutils::XmlTestdataLoader{ test_data_file_name, robot_model_ }); + ASSERT_NE(nullptr, data_loader_) << "Failed to load test data by provider."; + + // Define and set the current scene and manager test object + manager_ = std::make_shared(ph_, robot_model_); + scene_ = std::make_shared(robot_model_); + pipeline_ = std::make_shared(robot_model_, ph_); +} + +/** + * @brief Checks that each derived MoveItErrorCodeException contains the correct + * error code. + * + */ +TEST_F(IntegrationTestCommandListManager, TestExceptionErrorCodeMapping) +{ + std::shared_ptr nbr_ex{ new NegativeBlendRadiusException("") }; + EXPECT_EQ(nbr_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + + std::shared_ptr lbrnz_ex{ new LastBlendRadiusNotZeroException("") }; + EXPECT_EQ(lbrnz_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + + std::shared_ptr sss_ex{ new StartStateSetException("") }; + EXPECT_EQ(sss_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); + + std::shared_ptr obr_ex{ new OverlappingBlendRadiiException("") }; + EXPECT_EQ(obr_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + + std::shared_ptr pp_ex{ new PlanningPipelineException("") }; + EXPECT_EQ(pp_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::FAILURE); +} + +/** + * @brief Tests the concatenation of three motion commands. + * + * Test Sequence: + * 1. Generate request with three trajectories and zero blend radius. + * 2. Generate request with first trajectory and zero blend radius. + * 3. Generate request with second trajectory and zero blend radius. + * 4. Generate request with third trajectory and zero blend radius. + * + * Expected Results: + * 1. Generation of concatenated trajectory is successful. + * All time steps of resulting trajectory are strictly positive + * 2. Generation of concatenated trajectory is successful. + * All time steps of resulting trajectory are strictly positive + * 3. Generation of concatenated trajectory is successful. + * All time steps of resulting trajectory are strictly positive + * 4. Generation of concatenated trajectory is successful. + * All time steps of resulting trajectory are strictly positive + * resulting duration in step1 is approximately step2 + step3 + step4 + */ +TEST_F(IntegrationTestCommandListManager, concatThreeSegments) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + ASSERT_GE(seq.size(), 3u); + seq.erase(3, seq.size()); + seq.setAllBlendRadiiToZero(); + + RobotTrajCont res123_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) }; + EXPECT_EQ(res123_vec.size(), 1u); + EXPECT_GT(res123_vec.front()->getWayPointCount(), 0u); + EXPECT_TRUE(hasStrictlyIncreasingTime(res123_vec.front())) << "Time steps not strictly positively increasing"; + + ROS_INFO("step 2: only first segment"); + moveit_msgs::MotionSequenceRequest req_1; + req_1.items.resize(1); + req_1.items.at(0).req = seq.getCmd(0).toRequest(); + req_1.items.at(0).blend_radius = 0.; + RobotTrajCont res1_vec{ manager_->solve(scene_, pipeline_, req_1) }; + EXPECT_EQ(res1_vec.size(), 1u); + EXPECT_GT(res1_vec.front()->getWayPointCount(), 0u); + EXPECT_EQ(res1_vec.front()->getFirstWayPoint().getVariableCount(), + req_1.items.at(0).req.start_state.joint_state.name.size()); + + ROS_INFO("step 3: only second segment"); + moveit_msgs::MotionSequenceRequest req_2; + req_2.items.resize(1); + req_2.items.at(0).req = seq.getCmd(1).toRequest(); + req_2.items.at(0).blend_radius = 0.; + RobotTrajCont res2_vec{ manager_->solve(scene_, pipeline_, req_2) }; + EXPECT_EQ(res2_vec.size(), 1u); + EXPECT_GT(res2_vec.front()->getWayPointCount(), 0u); + EXPECT_EQ(res2_vec.front()->getFirstWayPoint().getVariableCount(), + req_2.items.at(0).req.start_state.joint_state.name.size()); + + ROS_INFO("step 4: only third segment"); + moveit_msgs::MotionSequenceRequest req_3; + req_3.items.resize(1); + req_3.items.at(0).req = seq.getCmd(2).toRequest(); + req_3.items.at(0).blend_radius = 0.; + RobotTrajCont res3_vec{ manager_->solve(scene_, pipeline_, req_3) }; + EXPECT_EQ(res3_vec.size(), 1u); + EXPECT_GT(res3_vec.front()->getWayPointCount(), 0u); + EXPECT_EQ(res3_vec.front()->getFirstWayPoint().getVariableCount(), + req_3.items.at(0).req.start_state.joint_state.name.size()); + + // durations for the different segments + auto t1_2_3 = res123_vec.front()->getWayPointDurationFromStart(res123_vec.front()->getWayPointCount() - 1); + auto t1 = res1_vec.front()->getWayPointDurationFromStart(res123_vec.front()->getWayPointCount() - 1); + auto t2 = res2_vec.front()->getWayPointDurationFromStart(res123_vec.front()->getWayPointCount() - 1); + auto t3 = res3_vec.front()->getWayPointDurationFromStart(res123_vec.front()->getWayPointCount() - 1); + ROS_DEBUG_STREAM("total time: " << t1_2_3 << " t1:" << t1 << " t2:" << t2 << " t3:" << t3); + EXPECT_LT(fabs((t1_2_3 - t1 - t2 - t3)), 0.4); +} + +/** + * @brief Tests if times are strictly increasing with selective blending + * + * Test Sequence: + * 1. Generate request with three trajectories where only the first has a + * blend radius. + * 1. Generate request with three trajectories where only the second has a + * blend radius. + * + * Expected Results: + * 1. Generation of concatenated trajectory is successful. + * All time steps of resulting trajectory are strictly increasing in time + * 2. Generation of concatenated trajectory is successful. + * All time steps of resulting trajectory are strictly increasing in time + */ +TEST_F(IntegrationTestCommandListManager, concatSegmentsSelectiveBlending) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + ASSERT_GE(seq.size(), 3u); + seq.erase(3, seq.size()); + seq.setAllBlendRadiiToZero(); + seq.setBlendRadius(0, 0.1); + RobotTrajCont res1{ manager_->solve(scene_, pipeline_, seq.toRequest()) }; + EXPECT_EQ(res1.size(), 1u); + EXPECT_GT(res1.front()->getWayPointCount(), 0u); + EXPECT_TRUE(hasStrictlyIncreasingTime(res1.front())) << "Time steps not strictly positively increasing"; + + seq.setAllBlendRadiiToZero(); + seq.setBlendRadius(1, 0.1); + RobotTrajCont res2{ manager_->solve(scene_, pipeline_, seq.toRequest()) }; + EXPECT_EQ(res2.size(), 1u); + EXPECT_GT(res2.front()->getWayPointCount(), 0u); + EXPECT_TRUE(hasStrictlyIncreasingTime(res2.front())) << "Time steps not strictly positively increasing"; +} + +/** + * @brief Tests the concatenation of two ptp commands + * + * Test Sequence: + * 1. Generate request with two PTP trajectories and zero blend radius. + * + * Expected Results: + * 1. Generation of concatenated trajectory is successful. + * All time steps of resulting trajectory are strictly positive. + */ +TEST_F(IntegrationTestCommandListManager, concatTwoPtpSegments) +{ + Sequence seq{ data_loader_->getSequence("PtpPtpSequence") }; + ASSERT_GE(seq.size(), 2u); + seq.setAllBlendRadiiToZero(); + + RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) }; + EXPECT_EQ(res_vec.size(), 1u); + EXPECT_GT(res_vec.front()->getWayPointCount(), 0u); + EXPECT_TRUE(hasStrictlyIncreasingTime(res_vec.front())); +} + +/** + * @brief Tests the concatenation of ptp and a lin command + * + * Test Sequence: + * 1. Generate request with PTP and LIN trajectory and zero blend radius. + * + * Expected Results: + * 1. Generation of concatenated trajectory is successful. + * All time steps of resulting trajectory are strictly positive. + */ +TEST_F(IntegrationTestCommandListManager, concatPtpAndLinSegments) +{ + Sequence seq{ data_loader_->getSequence("PtpLinSequence") }; + ASSERT_GE(seq.size(), 2u); + seq.setAllBlendRadiiToZero(); + + RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) }; + EXPECT_EQ(res_vec.size(), 1u); + EXPECT_GT(res_vec.front()->getWayPointCount(), 0u); + EXPECT_TRUE(hasStrictlyIncreasingTime(res_vec.front())); +} + +/** + * @brief Tests the concatenation of a lin and a ptp command + * + * Test Sequence: + * 1. Generate request with LIN and PTP trajectory and zero blend radius. + * + * Expected Results: + * 1. Generation of concatenated trajectory is successful. + * All time steps of resulting trajectory are strictly positive. + */ +TEST_F(IntegrationTestCommandListManager, concatLinAndPtpSegments) +{ + Sequence seq{ data_loader_->getSequence("LinPtpSequence") }; + ASSERT_GE(seq.size(), 2u); + seq.setAllBlendRadiiToZero(); + + RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) }; + EXPECT_EQ(res_vec.size(), 1u); + EXPECT_GT(res_vec.front()->getWayPointCount(), 0u); + EXPECT_TRUE(hasStrictlyIncreasingTime(res_vec.front())); +} + +/** + * @brief Tests the blending of motion commands + * + * - Test Sequence: + * 1. Generate request with two trajectories and request blending. + * + * - Expected Results: + * 1. blending is successful, result trajectory is not empty + */ +TEST_F(IntegrationTestCommandListManager, blendTwoSegments) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + ASSERT_EQ(seq.size(), 2u); + moveit_msgs::MotionSequenceRequest req{ seq.toRequest() }; + RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, req) }; + EXPECT_EQ(res_vec.size(), 1u); + EXPECT_GT(res_vec.front()->getWayPointCount(), 0u); + EXPECT_EQ(res_vec.front()->getFirstWayPoint().getVariableCount(), + req.items.at(0).req.start_state.joint_state.name.size()); + + ros::NodeHandle nh; + ros::Publisher pub = nh.advertise("my_planned_path", 1); + ros::Duration duration(1.0); // wait to notify possible subscribers + duration.sleep(); + + moveit_msgs::DisplayTrajectory display_trajectory; + moveit_msgs::RobotTrajectory rob_traj_msg; + res_vec.front()->getRobotTrajectoryMsg(rob_traj_msg); + display_trajectory.trajectory.push_back(rob_traj_msg); + pub.publish(display_trajectory); +} + +// ------------------ +// FAILURE cases +// ------------------ + +/** + * @brief Tests sending an empty blending request. + * + * Test Sequence: + * 1. Generate empty request and request blending. + * + * Expected Results: + * 1. blending is successful, result trajectory container is empty + */ +TEST_F(IntegrationTestCommandListManager, emptyList) +{ + moveit_msgs::MotionSequenceRequest empty_list; + RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, empty_list) }; + EXPECT_TRUE(res_vec.empty()); +} + +/** + * @brief Checks that exception is thrown if first goal is not reachable. + * + * Test Sequence: + * 1. Generate request with first goal out of workspace. + * + * Expected Results: + * 1. Exception is thrown. + */ +TEST_F(IntegrationTestCommandListManager, firstGoalNotReachable) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + ASSERT_GE(seq.size(), 2u); + LinCart& lin{ seq.getCmd(0) }; + lin.getGoalConfiguration().getPose().position.y = 2700; + EXPECT_THROW(manager_->solve(scene_, pipeline_, seq.toRequest()), PlanningPipelineException); +} + +/** + * @brief Checks that exception is thrown if second goal has a start state. + * + * Test Sequence: + * 1. Generate request, second goal has an invalid start state set. + * + * Expected Results: + * 1. Exception is thrown. + */ +TEST_F(IntegrationTestCommandListManager, startStateNotFirstGoal) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + ASSERT_GE(seq.size(), 2u); + const LinCart& lin{ seq.getCmd(0) }; + moveit_msgs::MotionSequenceRequest req{ seq.toRequest() }; + req.items.at(1).req.start_state = lin.getGoalConfiguration().toMoveitMsgsRobotState(); + EXPECT_THROW(manager_->solve(scene_, pipeline_, req), StartStateSetException); +} + +/** + * @brief Checks that exception is thrown in case of blending request with + * negative blend_radius. + * + * Test Sequence: + * 1. Generate request, first goal has negative blend_radius. + * + * Expected Results: + * 1. Exception is thrown. + */ +TEST_F(IntegrationTestCommandListManager, blendingRadiusNegative) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + ASSERT_GE(seq.size(), 2u); + seq.setBlendRadius(0, -0.3); + EXPECT_THROW(manager_->solve(scene_, pipeline_, seq.toRequest()), NegativeBlendRadiusException); +} + +/** + * @brief Checks that exception is thrown if last blend radius is not zero. + * + * + * Test Sequence: + * 1. Generate request, second goal has non-zero blend_radius. + * + * Expected Results: + * 1. Exception is thrown. + */ +TEST_F(IntegrationTestCommandListManager, lastBlendingRadiusNonZero) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + ASSERT_EQ(seq.size(), 2u); + seq.setBlendRadius(1, 0.03); + EXPECT_THROW(manager_->solve(scene_, pipeline_, seq.toRequest()), LastBlendRadiusNotZeroException); +} + +/** + * @brief Checks that exception is thrown if blend radius is greater than the + * segment. + * + * Test Sequence: + * 1. Generate request with huge blending radius, so that trajectories are + * completely inside + * + * Expected Results: + * 2. Exception is thrown. + */ +TEST_F(IntegrationTestCommandListManager, blendRadiusGreaterThanSegment) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + ASSERT_GE(seq.size(), 2u); + seq.setBlendRadius(0, 42.0); + EXPECT_THROW(manager_->solve(scene_, pipeline_, seq.toRequest()), BlendingFailedException); +} + +/** + * @brief Checks that exception is thrown if two consecutive blend radii + * overlap. + * + * Test Sequence: + * 1. Generate request with three trajectories + * 2. Increase second blend radius, so that the radii overlap + * + * Expected Results: + * 1. blending succeeds, result trajectory is not empty + * 2. Exception is thrown. + */ +TEST_F(IntegrationTestCommandListManager, blendingRadiusOverlapping) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + ASSERT_GE(seq.size(), 3u); + seq.erase(3, seq.size()); + + RobotTrajCont res_valid_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) }; + EXPECT_EQ(res_valid_vec.size(), 1u); + EXPECT_GT(res_valid_vec.front()->getWayPointCount(), 0u); + + // calculate distance from first to second goal + const PtpJointCart& ptp{ seq.getCmd(0) }; + const CircInterimCart& circ{ seq.getCmd(1) }; + Eigen::Isometry3d p1, p2; + tf2::fromMsg(ptp.getGoalConfiguration().getPose(), p1); + tf2::fromMsg(circ.getGoalConfiguration().getPose(), p2); + auto distance = (p2.translation() - p1.translation()).norm(); + + seq.setBlendRadius(1, (distance - seq.getBlendRadius(0) + 0.01)); // overlapping radii + EXPECT_THROW(manager_->solve(scene_, pipeline_, seq.toRequest()), OverlappingBlendRadiiException); +} + +/** + * @brief Tests if the planned execution time scales correctly with the number + * of repetitions. + * + * Test Sequence: + * 1. Generate trajectory and save calculated execution time. + * 2. Generate request with repeated path along the points from Test Step 1 + * (repeated two times). + * + * Expected Results: + * 1. Blending succeeds, result trajectory is not empty. + * 2. Blending succeeds, planned execution time should be approx N times + * the single planned execution time. + */ +TEST_F(IntegrationTestCommandListManager, TestExecutionTime) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + ASSERT_GE(seq.size(), 2u); + RobotTrajCont res_single_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) }; + EXPECT_EQ(res_single_vec.size(), 1u); + EXPECT_GT(res_single_vec.front()->getWayPointCount(), 0u); + + moveit_msgs::MotionSequenceRequest req{ seq.toRequest() }; + // Create large request by making copies of the original sequence commands + // and adding them to the end of the original sequence. + const size_t n{ req.items.size() }; + for (size_t i = 0; i < n; ++i) + { + moveit_msgs::MotionSequenceItem item{ req.items.at(i) }; + if (i == 0) + { + // Remove start state because only the first request + // is allowed to have a start state in a sequence. + item.req.start_state = moveit_msgs::RobotState(); + } + req.items.push_back(item); + } + + RobotTrajCont res_n_vec{ manager_->solve(scene_, pipeline_, req) }; + EXPECT_EQ(res_n_vec.size(), 1u); + EXPECT_GT(res_n_vec.front()->getWayPointCount(), 0u); + + const double trajectory_time_1 = + res_single_vec.front()->getWayPointDurationFromStart(res_single_vec.front()->getWayPointCount() - 1); + const double trajectory_time_n = + res_n_vec.front()->getWayPointDurationFromStart(res_n_vec.front()->getWayPointCount() - 1); + double multiplicator = req.items.size() / n; + EXPECT_LE(trajectory_time_n, trajectory_time_1 * multiplicator); + EXPECT_GE(trajectory_time_n, trajectory_time_1 * multiplicator * 0.5); +} + +/** + * @brief Tests if it possible to send requests which contain more than + * one group. + * + * Please note: This test is still quite trivial. It does not check the + * "correctness" of a calculated trajectory. It only checks that for each + * group and group change there exists a calculated trajectory. + * + */ +TEST_F(IntegrationTestCommandListManager, TestDifferentGroups) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequenceWithGripper") }; + ASSERT_GE(seq.size(), 1u); + // Count the number of group changes in the given sequence + unsigned int num_groups{ 1 }; + std::string last_group_name{ seq.getCmd(0).getPlanningGroup() }; + for (size_t i = 1; i < seq.size(); ++i) + { + if (seq.getCmd(i).getPlanningGroup() != last_group_name) + { + ++num_groups; + last_group_name = seq.getCmd(i).getPlanningGroup(); + } + } + + RobotTrajCont res_single_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) }; + EXPECT_EQ(res_single_vec.size(), num_groups); + + for (const auto& res : res_single_vec) + { + EXPECT_GT(res->getWayPointCount(), 0u); + } +} + +/** + * @brief Checks that no exception is thrown if two gripper commands are + * blended. + * + */ +TEST_F(IntegrationTestCommandListManager, TestGripperCmdBlending) +{ + Sequence seq{ data_loader_->getSequence("PureGripperSequence") }; + ASSERT_GE(seq.size(), 2u); + ASSERT_TRUE(seq.cmdIsOfType(0)); + ASSERT_TRUE(seq.cmdIsOfType(1)); + + // Ensure that blending is requested for gripper commands. + seq.setBlendRadius(0, 1.0); + RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) }; + EXPECT_EQ(res_vec.size(), 1u); +} + +/** + * @brief Tests the execution of a sequence in which each group states a start + * state only consisting of joints of the corresonding group. + * + * Test Sequence: + * 1. Create sequence request for which each start state only consists of + * joints of the corresonding group + * + * Expected Results: + * 1. Trajectory generation is successful, result trajectory is not empty. + * + * + */ +TEST_F(IntegrationTestCommandListManager, TestGroupSpecificStartState) +{ + using std::placeholders::_1; + + Sequence seq{ data_loader_->getSequence("ComplexSequenceWithGripper") }; + ASSERT_GE(seq.size(), 4u); + seq.erase(4, seq.size()); + + Gripper& gripper{ seq.getCmd(0) }; + gripper.getStartConfiguration().setCreateJointNameFunc(std::bind(&createGripperJointName, _1)); + // By deleting the model we guarantee that the start state only consists + // of joints of the gripper group without the manipulator + gripper.getStartConfiguration().clearModel(); + + PtpJointCart& ptp{ seq.getCmd(1) }; + ptp.getStartConfiguration().setCreateJointNameFunc(std::bind(&createManipulatorJointName, _1)); + // By deleting the model we guarantee that the start state only consists + // of joints of the manipulator group without the gripper + ptp.getStartConfiguration().clearModel(); + + RobotTrajCont res_vec{ manager_->solve(scene_, pipeline_, seq.toRequest()) }; + EXPECT_GE(res_vec.size(), 1u); + EXPECT_GT(res_vec.front()->getWayPointCount(), 0u); +} + +/** + * @brief Checks that exception is thrown if Tip-Frame is requested for + * a group without a solver. + */ +TEST_F(IntegrationTestCommandListManager, TestGetSolverTipFrameForSolverlessGroup) +{ + Gripper gripper_cmd{ data_loader_->getGripper("open_gripper") }; + EXPECT_THROW(getSolverTipFrame(robot_model_->getJointModelGroup(gripper_cmd.getPlanningGroup())), NoSolverException); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "integrationtest_command_list_manager"); + testing::InitGoogleTest(&argc, argv); + + ros::NodeHandle nh; + + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_list_manager.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_list_manager.test new file mode 100644 index 0000000000..1f4eb9489d --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_list_manager.test @@ -0,0 +1,68 @@ + + + + + + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning.cpp b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning.cpp new file mode 100644 index 0000000000..c724595bd8 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning.cpp @@ -0,0 +1,501 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_utils.h" + +const double EPSILON = 1.0e-6; +const std::string PLAN_SERVICE_NAME = "/plan_kinematic_path"; + +// Parameters from parameter server +const std::string PARAM_PLANNING_GROUP_NAME("planning_group"); +const std::string POSE_TRANSFORM_MATRIX_NORM_TOLERANCE("pose_norm_tolerance"); +const std::string ORIENTATION_NORM_TOLERANCE("orientation_norm_tolerance"); +const std::string PARAM_TARGET_LINK_NAME("target_link"); +const std::string TEST_DATA_FILE_NAME("testdata_file_name"); + +using namespace pilz_industrial_motion_planner_testutils; + +/** + * PLEASE NOTE: + * More detailed lin tests are done via unit tests. With the help of the + * integration tests, it is only checked that a linear command actually + * performs a linear command. + */ +class IntegrationTestCommandPlanning : public ::testing::Test +{ +protected: + void SetUp() override; + +protected: + ros::NodeHandle ph_{ "~" }; + + robot_model::RobotModelPtr robot_model_; + + double pose_norm_tolerance_, orientation_norm_tolerance_; + std::string planning_group_, target_link_, test_data_file_name_; + + std::unique_ptr test_data_; + + unsigned int num_joints_{ 0 }; +}; + +void IntegrationTestCommandPlanning::SetUp() +{ + // create robot model + robot_model_loader::RobotModelLoader model_loader; + robot_model_ = model_loader.getModel(); + + // get the parameters + ASSERT_TRUE(ph_.getParam(PARAM_PLANNING_GROUP_NAME, planning_group_)); + ASSERT_TRUE(ph_.getParam(POSE_TRANSFORM_MATRIX_NORM_TOLERANCE, pose_norm_tolerance_)); + ASSERT_TRUE(ph_.getParam(PARAM_TARGET_LINK_NAME, target_link_)); + ASSERT_TRUE(ph_.getParam(ORIENTATION_NORM_TOLERANCE, orientation_norm_tolerance_)); + ASSERT_TRUE(ph_.getParam(TEST_DATA_FILE_NAME, test_data_file_name_)); + + ASSERT_TRUE(ros::service::waitForService(PLAN_SERVICE_NAME, ros::Duration(testutils::DEFAULT_SERVICE_TIMEOUT))); + + // load the test data provider + test_data_.reset( + new pilz_industrial_motion_planner_testutils::XmlTestdataLoader{ test_data_file_name_, robot_model_ }); + ASSERT_NE(nullptr, test_data_) << "Failed to load test data by provider."; + + num_joints_ = robot_model_->getJointModelGroup(planning_group_)->getActiveJointModelNames().size(); +} + +/** + * @brief Tests if ptp motions with start & goal state given as + * joint configuration are executed correctly. + * + * Test Sequence: + * 1. Generate request with joint goal and start state call planning service. + * + * Expected Results: + * 1. Last point of the resulting trajectory is at the goal + */ +TEST_F(IntegrationTestCommandPlanning, PtpJoint) +{ + ros::NodeHandle node_handle("~"); + auto ptp{ test_data_->getPtpJoint("Ptp1") }; + + moveit_msgs::GetMotionPlan srv; + moveit_msgs::MotionPlanRequest req = ptp.toRequest(); + srv.request.motion_plan_request = req; + + ros::ServiceClient client = node_handle.serviceClient(PLAN_SERVICE_NAME); + + ASSERT_TRUE(client.call(srv)); + const moveit_msgs::MotionPlanResponse& response{ srv.response.motion_plan_response }; + + // Check the result + ASSERT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, response.error_code.val) << "Planning failed!"; + trajectory_msgs::JointTrajectory trajectory = response.trajectory.joint_trajectory; + + EXPECT_EQ(trajectory.joint_names.size(), num_joints_) << "Wrong number of jointnames"; + EXPECT_GT(trajectory.points.size(), 0u) << "There are no points in the trajectory"; + + // Check that every point has position, velocity, acceleration + for (const auto& point : trajectory.points) + { + EXPECT_EQ(point.positions.size(), num_joints_); + EXPECT_EQ(point.velocities.size(), num_joints_); + EXPECT_EQ(point.accelerations.size(), num_joints_); + } + + for (size_t i = 0; i < num_joints_; ++i) + { + EXPECT_NEAR(trajectory.points.back().positions.at(i), req.goal_constraints.back().joint_constraints.at(i).position, + 10e-10); + EXPECT_NEAR(trajectory.points.back().velocities.at(i), 0, 10e-10); + // EXPECT_NEAR(trajectory.points.back().accelerations.at(i), 0, 10e-10); // + // TODO what is expected + } +} + +/** + * @brief Tests if ptp motions with start state given as joint configuration + * and goal state given as cartesian configuration are executed correctly. + * + * Test Sequence: + * 1. Generate request with pose goal and start state call planning service. + * + * Expected Results: + * 1. Last point of the resulting trajectory is at the goal + */ +TEST_F(IntegrationTestCommandPlanning, PtpJointCart) +{ + ros::NodeHandle node_handle("~"); + + PtpJointCart ptp{ test_data_->getPtpJointCart("Ptp1") }; + ptp.getGoalConfiguration().setPoseTolerance(0.01); + ptp.getGoalConfiguration().setAngleTolerance(0.01); + + moveit_msgs::GetMotionPlan srv; + srv.request.motion_plan_request = ptp.toRequest(); + + ros::ServiceClient client = node_handle.serviceClient(PLAN_SERVICE_NAME); + + ASSERT_TRUE(client.call(srv)); + const moveit_msgs::MotionPlanResponse& response{ srv.response.motion_plan_response }; + + // Make sure the planning succeeded + ASSERT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, response.error_code.val) << "Planning failed!"; + + // Check the result + trajectory_msgs::JointTrajectory trajectory = response.trajectory.joint_trajectory; + + EXPECT_EQ(trajectory.joint_names.size(), num_joints_) << "Wrong number of jointnames"; + EXPECT_GT(trajectory.points.size(), 0u) << "There are no points in the trajectory"; + + // Check that every point has position, velocity, acceleration + for (const auto& point : trajectory.points) + { + EXPECT_EQ(point.positions.size(), num_joints_); + EXPECT_EQ(point.velocities.size(), num_joints_); + EXPECT_EQ(point.accelerations.size(), num_joints_); + } + + robot_state::RobotState rstate(robot_model_); + rstate.setToDefaultValues(); + rstate.setJointGroupPositions(planning_group_, response.trajectory.joint_trajectory.points.back().positions); + Eigen::Isometry3d tf = rstate.getFrameTransform(target_link_); + + const geometry_msgs::Pose& expected_pose{ ptp.getGoalConfiguration().getPose() }; + + EXPECT_NEAR(tf(0, 3), expected_pose.position.x, EPSILON); + EXPECT_NEAR(tf(1, 3), expected_pose.position.y, EPSILON); + EXPECT_NEAR(tf(2, 3), expected_pose.position.z, EPSILON); + + Eigen::Isometry3d exp_iso3d_pose; + tf2::convert(expected_pose, exp_iso3d_pose); + + EXPECT_TRUE(Eigen::Quaterniond(tf.rotation()).isApprox(Eigen::Quaterniond(exp_iso3d_pose.rotation()), EPSILON)); +} + +/** + * @brief Tests if linear motions with start and goal state given + * as joint configuration are executed correctly. + * + * Test Sequence: + * 1. Generate request and make service request. + * 2. Check if target position correct. + * 3. Check if trajectory is linear. + * + * Expected Results: + * 1. Planning request is successful. + * 2. Goal position correponds with the given goal position. + * 3. Trajectory is a straight line. + */ +TEST_F(IntegrationTestCommandPlanning, LinJoint) +{ + planning_interface::MotionPlanRequest req{ test_data_->getLinJoint("lin2").toRequest() }; + + std::cout << "++++++++++" << std::endl; + std::cout << "+ Step 1 +" << std::endl; + std::cout << "++++++++++" << std::endl; + + moveit_msgs::GetMotionPlan srv; + srv.request.motion_plan_request = req; + + ros::NodeHandle node_handle("~"); + ros::ServiceClient client = node_handle.serviceClient(PLAN_SERVICE_NAME); + + ASSERT_TRUE(client.call(srv)); + const moveit_msgs::MotionPlanResponse& response{ srv.response.motion_plan_response }; + + ASSERT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, response.error_code.val) << "Planning failed!"; + + std::cout << "++++++++++" << std::endl; + std::cout << "+ Step 2 +" << std::endl; + std::cout << "++++++++++" << std::endl; + + ASSERT_TRUE(testutils::isGoalReached(robot_model_, response.trajectory.joint_trajectory, req, pose_norm_tolerance_, + orientation_norm_tolerance_)) + << "Goal not reached."; + + std::cout << "++++++++++" << std::endl; + std::cout << "+ Step 3 +" << std::endl; + std::cout << "++++++++++" << std::endl; + + ASSERT_TRUE(testutils::checkCartesianLinearity(robot_model_, response.trajectory.joint_trajectory, req, + pose_norm_tolerance_, orientation_norm_tolerance_)) + << "Trajectory violates cartesian linearity."; +} + +/** + * @brief Tests if linear motions with start state given as joint + * configuration and goal state given as cartesian configuration + * are executed correctly. + * + * Test Sequence: + * 1. Generate request and make service request. + * 2. Check if target position correct. + * 3. Check if trajectory is linear. + * + * Expected Results: + * 1. Planning request is successful. + * 2. Goal position correponds with the given goal position. + * 3. Trajectory is a straight line. + */ +TEST_F(IntegrationTestCommandPlanning, LinJointCart) +{ + ros::NodeHandle node_handle("~"); + planning_interface::MotionPlanRequest req{ test_data_->getLinJointCart("lin2").toRequest() }; + + std::cout << "++++++++++" << std::endl; + std::cout << "+ Step 1 +" << std::endl; + std::cout << "++++++++++" << std::endl; + + moveit_msgs::GetMotionPlan srv; + srv.request.motion_plan_request = req; + + ros::ServiceClient client = node_handle.serviceClient(PLAN_SERVICE_NAME); + + ASSERT_TRUE(client.call(srv)); + const moveit_msgs::MotionPlanResponse& response{ srv.response.motion_plan_response }; + + ASSERT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, response.error_code.val) << "Planning failed!"; + + std::cout << "++++++++++" << std::endl; + std::cout << "+ Step 2 +" << std::endl; + std::cout << "++++++++++" << std::endl; + + ASSERT_TRUE(testutils::isGoalReached(robot_model_, response.trajectory.joint_trajectory, req, pose_norm_tolerance_, + orientation_norm_tolerance_)) + << "Goal not reached."; + + std::cout << "++++++++++" << std::endl; + std::cout << "+ Step 3 +" << std::endl; + std::cout << "++++++++++" << std::endl; + + ASSERT_TRUE(testutils::checkCartesianLinearity(robot_model_, response.trajectory.joint_trajectory, req, + pose_norm_tolerance_, orientation_norm_tolerance_)) + << "Trajectory violates cartesian linearity."; +} + +/** + * @brief Tests if circular motions with start & goal state given as joint + * configuration and center point given as cartesian configuration + * are executed correctly. + * + * Test Sequence: + * 1. Generate request with JOINT goal and start state call planning service. + * + * Expected Results: + * 1. Last point of the resulting trajectory is at the goal + * 2. Waypoints are on the desired circle + */ +TEST_F(IntegrationTestCommandPlanning, CircJointCenterCart) +{ + ros::NodeHandle node_handle("~"); + + CircJointCenterCart circ{ test_data_->getCircJointCenterCart("circ1_center_2") }; + + moveit_msgs::MotionPlanRequest req{ circ.toRequest() }; + + moveit_msgs::GetMotionPlan srv; + srv.request.motion_plan_request = req; + + ros::ServiceClient client = node_handle.serviceClient(PLAN_SERVICE_NAME); + + ASSERT_TRUE(client.call(srv)); + const moveit_msgs::MotionPlanResponse& response{ srv.response.motion_plan_response }; + + // Check the result + ASSERT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, response.error_code.val) << "Planning failed!"; + trajectory_msgs::JointTrajectory trajectory = response.trajectory.joint_trajectory; + + EXPECT_EQ(trajectory.joint_names.size(), num_joints_) << "Wrong number of jointnames"; + EXPECT_GT(trajectory.points.size(), 0u) << "There are no points in the trajectory"; + + // Check that every point has position, velocity, acceleration + for (const auto& point : trajectory.points) + { + EXPECT_EQ(point.positions.size(), num_joints_); + EXPECT_EQ(point.velocities.size(), num_joints_); + EXPECT_EQ(point.accelerations.size(), num_joints_); + } + + // check goal is reached + ASSERT_TRUE(testutils::isGoalReached(robot_model_, response.trajectory.joint_trajectory, req, pose_norm_tolerance_, + orientation_norm_tolerance_)) + << "Goal not reached."; + + // check all waypoints are on the circle and SLERP + robot_state::RobotState waypoint_state(robot_model_); + Eigen::Isometry3d waypoint_pose; + double x_dist, y_dist, z_dist; + + const geometry_msgs::Pose& aux_pose{ circ.getAuxiliaryConfiguration().getConfiguration().getPose() }; + + CircCenterCart circ_cart{ test_data_->getCircCartCenterCart("circ1_center_2") }; + const geometry_msgs::Pose& start_pose{ circ_cart.getStartConfiguration().getPose() }; + const geometry_msgs::Pose& goal_pose{ circ_cart.getGoalConfiguration().getPose() }; + + x_dist = aux_pose.position.x - start_pose.position.x; + y_dist = aux_pose.position.y - start_pose.position.y; + z_dist = aux_pose.position.z - start_pose.position.z; + double expected_radius = sqrt(x_dist * x_dist + y_dist * y_dist + z_dist * z_dist); + for (const auto& waypoint : trajectory.points) + { + waypoint_state.setToDefaultValues(); + waypoint_state.setJointGroupPositions(planning_group_, waypoint.positions); + waypoint_pose = waypoint_state.getFrameTransform(target_link_); + + // Calculate (and check) distance of current trajectory waypoint from circ + // center + x_dist = aux_pose.position.x - waypoint_pose(0, 3); + y_dist = aux_pose.position.y - waypoint_pose(1, 3); + z_dist = aux_pose.position.z - waypoint_pose(2, 3); + double actual_radius = sqrt(x_dist * x_dist + y_dist * y_dist + z_dist * z_dist); + EXPECT_NEAR(actual_radius, expected_radius, pose_norm_tolerance_) << "Trajectory way point is not on the circle."; + + // Check orientation + Eigen::Isometry3d start_pose_iso3d, goal_pose_iso3d; + tf2::convert(start_pose, start_pose_iso3d); + tf2::convert(goal_pose, goal_pose_iso3d); + EXPECT_TRUE(testutils::checkSLERP(start_pose_iso3d, goal_pose_iso3d, waypoint_pose, orientation_norm_tolerance_)); + } +} + +/** + * @brief Tests if linear motions with start state given as cartesian + * configuration and goal state given as cartesian configuration + * are executed correctly. + * + * - Test Sequence: + * 1. Generate request with POSE goal and start state call planning service. + * + * - Expected Results: + * 1. Last point of the resulting trajectory is at the goal + * 2. Waypoints are on the desired circle + */ +TEST_F(IntegrationTestCommandPlanning, CircCartCenterCart) +{ + ros::NodeHandle node_handle("~"); + + CircCenterCart circ{ test_data_->getCircCartCenterCart("circ1_center_2") }; + moveit_msgs::MotionPlanRequest req{ circ.toRequest() }; + moveit_msgs::GetMotionPlan srv; + srv.request.motion_plan_request = req; + + ros::ServiceClient client = node_handle.serviceClient(PLAN_SERVICE_NAME); + + ASSERT_TRUE(client.call(srv)); + const moveit_msgs::MotionPlanResponse& response = srv.response.motion_plan_response; + + // Check the result + ASSERT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, response.error_code.val) << "Planning failed!"; + trajectory_msgs::JointTrajectory trajectory = response.trajectory.joint_trajectory; + + EXPECT_EQ(trajectory.joint_names.size(), num_joints_) << "Wrong number of jointnames"; + EXPECT_GT(trajectory.points.size(), 0u) << "There are no points in the trajectory"; + + // Check that every point has position, velocity, acceleration + for (const auto& point : trajectory.points) + { + EXPECT_EQ(point.positions.size(), num_joints_); + EXPECT_EQ(point.velocities.size(), num_joints_); + EXPECT_EQ(point.accelerations.size(), num_joints_); + } + + // check goal is reached + ASSERT_TRUE(testutils::isGoalReached(robot_model_, response.trajectory.joint_trajectory, req, pose_norm_tolerance_, + orientation_norm_tolerance_)) + << "Goal not reached."; + + // check all waypoints are on the cricle and SLERP + robot_state::RobotState waypoint_state(robot_model_); + Eigen::Isometry3d waypoint_pose; + double x_dist, y_dist, z_dist; + + const geometry_msgs::Pose& start_pose{ circ.getStartConfiguration().getPose() }; + const geometry_msgs::Pose& aux_pose{ circ.getAuxiliaryConfiguration().getConfiguration().getPose() }; + const geometry_msgs::Pose& goal_pose{ circ.getGoalConfiguration().getPose() }; + + x_dist = aux_pose.position.x - start_pose.position.x; + y_dist = aux_pose.position.y - start_pose.position.y; + z_dist = aux_pose.position.z - start_pose.position.z; + double expected_radius = sqrt(x_dist * x_dist + y_dist * y_dist + z_dist * z_dist); + for (const auto& waypoint : trajectory.points) + { + waypoint_state.setToDefaultValues(); + waypoint_state.setJointGroupPositions(planning_group_, waypoint.positions); + waypoint_pose = waypoint_state.getFrameTransform(target_link_); + + // Calculate (and check) distance of current trajectory waypoint from circ + // center + x_dist = aux_pose.position.x - waypoint_pose(0, 3); + y_dist = aux_pose.position.y - waypoint_pose(1, 3); + z_dist = aux_pose.position.z - waypoint_pose(2, 3); + double actual_radius = sqrt(x_dist * x_dist + y_dist * y_dist + z_dist * z_dist); + EXPECT_NEAR(actual_radius, expected_radius, pose_norm_tolerance_) << "Trajectory way point is not on the circle."; + + // Check orientation + Eigen::Isometry3d start_pose_iso3d, goal_pose_iso3d; + tf2::convert(start_pose, start_pose_iso3d); + tf2::convert(goal_pose, goal_pose_iso3d); + EXPECT_TRUE(testutils::checkSLERP(start_pose_iso3d, goal_pose_iso3d, waypoint_pose, orientation_norm_tolerance_)); + } +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "integrationtest_command_planning"); + ros::NodeHandle nh; // For output via ROS_ERROR etc during test + + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning.test new file mode 100644 index 0000000000..ba73e8b56b --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning.test @@ -0,0 +1,62 @@ + + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_frankaemika_panda.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_frankaemika_panda.test new file mode 100644 index 0000000000..d360fbcafa --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_frankaemika_panda.test @@ -0,0 +1,63 @@ + + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_with_gripper.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_with_gripper.test new file mode 100644 index 0000000000..64fb904bde --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_with_gripper.test @@ -0,0 +1,61 @@ + + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_get_solver_tip_frame.cpp b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_get_solver_tip_frame.cpp new file mode 100644 index 0000000000..0cd4ac3bcc --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_get_solver_tip_frame.cpp @@ -0,0 +1,116 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "pilz_industrial_motion_planner/tip_frame_getter.h" + +static const std::string ROBOT_DESCRIPTION_PARAM{ "robot_description" }; + +namespace pilz_industrial_motion_planner +{ +class GetSolverTipFrameIntegrationTest : public testing::Test +{ +protected: + void SetUp() override; + +protected: + robot_model::RobotModelConstPtr robot_model_{ + robot_model_loader::RobotModelLoader(ROBOT_DESCRIPTION_PARAM).getModel() + }; +}; + +void GetSolverTipFrameIntegrationTest::SetUp() +{ + if (!robot_model_) + { + FAIL() << "Robot model could not be loaded."; + } +} + +/** + * @brief Check if hasSolver() can be called successfully for the manipulator + * group. + */ +TEST_F(GetSolverTipFrameIntegrationTest, TestHasSolverManipulator) +{ + EXPECT_TRUE(hasSolver(robot_model_->getJointModelGroup("manipulator"))) << "hasSolver returns false for manipulator"; +} + +/** + * @brief Check if hasSolver() can be called successfully for the gripper group. + */ +TEST_F(GetSolverTipFrameIntegrationTest, TestHasSolverGripperGroup) +{ + EXPECT_FALSE(hasSolver(robot_model_->getJointModelGroup("gripper"))) << "hasSolver returns true for gripper"; +} + +/** + * @brief Check if getSolverTipFrame() can be called successfully for the + * manipulator group. + */ +TEST_F(GetSolverTipFrameIntegrationTest, TestGetTipSolverFrameManipulator) +{ + getSolverTipFrame(robot_model_->getJointModelGroup("manipulator")); +} + +/** + * @brief Check if getSolverTipFrame() fails for gripper group. + */ +TEST_F(GetSolverTipFrameIntegrationTest, TestGetTipSolverFrameGripper) +{ + EXPECT_THROW(getSolverTipFrame(robot_model_->getJointModelGroup("gripper")), NoSolverException); +} + +} // namespace pilz_industrial_motion_planner + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "integrationtest_get_solver_tip_frame"); + testing::InitGoogleTest(&argc, argv); + + ros::NodeHandle nh; + + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_get_solver_tip_frame.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_get_solver_tip_frame.test new file mode 100644 index 0000000000..6f5425d85a --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_get_solver_tip_frame.test @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_plan_components_builder.cpp b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_plan_components_builder.cpp new file mode 100644 index 0000000000..43f0415771 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_plan_components_builder.cpp @@ -0,0 +1,132 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include +#include + +#include + +#include + +#include +#include + +#include "pilz_industrial_motion_planner/plan_components_builder.h" +#include "pilz_industrial_motion_planner/trajectory_blender_transition_window.h" + +const std::string PARAM_PLANNING_GROUP_NAME("planning_group"); +const std::string ROBOT_DESCRIPTION_STR{ "robot_description" }; +const std::string EMPTY_VALUE{ "" }; + +using namespace pilz_industrial_motion_planner; +using namespace pilz_industrial_motion_planner; + +class IntegrationTestPlanComponentBuilder : public testing::Test +{ +protected: + void SetUp() override; + +protected: + ros::NodeHandle ph_{ "~" }; + robot_model::RobotModelConstPtr robot_model_{ robot_model_loader::RobotModelLoader(ROBOT_DESCRIPTION_STR).getModel() }; + + std::string planning_group_; +}; + +void IntegrationTestPlanComponentBuilder::SetUp() +{ + if (!robot_model_) + { + FAIL() << "Robot model could not be loaded."; + } + + ASSERT_TRUE(ph_.getParam(PARAM_PLANNING_GROUP_NAME, planning_group_)); +} + +/** + * @brief Checks that each derived MoveItErrorCodeException contains the correct + * error code. + * + */ +TEST_F(IntegrationTestPlanComponentBuilder, TestExceptionErrorCodeMapping) +{ + std::shared_ptr nbs_ex{ new NoBlenderSetException("") }; + EXPECT_EQ(nbs_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::FAILURE); + + std::shared_ptr ntffse_ex{ new NoTipFrameFunctionSetException("") }; + EXPECT_EQ(ntffse_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::FAILURE); + + std::shared_ptr nrms_ex{ new NoRobotModelSetException("") }; + EXPECT_EQ(nrms_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::FAILURE); + + std::shared_ptr bf_ex{ new BlendingFailedException("") }; + EXPECT_EQ(bf_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::FAILURE); +} + +/** + * @brief Checks that exception is thrown if no robot model is set. + * + */ +TEST_F(IntegrationTestPlanComponentBuilder, TestModelSet) +{ + robot_trajectory::RobotTrajectoryPtr traj{ new robot_trajectory::RobotTrajectory(robot_model_, planning_group_) }; + PlanComponentsBuilder builder; + + EXPECT_THROW(builder.append(traj, 1.0), NoRobotModelSetException); +} + +/** + * @brief Checks that exception is thrown if no blender is set. + * + */ +TEST_F(IntegrationTestPlanComponentBuilder, TestNoBlenderSet) +{ + robot_trajectory::RobotTrajectoryPtr traj{ new robot_trajectory::RobotTrajectory(robot_model_, planning_group_) }; + PlanComponentsBuilder builder; + builder.setModel(robot_model_); + + builder.append(traj, 0.0); + + EXPECT_THROW(builder.append(traj, 1.0), NoBlenderSetException); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "integrationtest_plan_components_builder"); + testing::InitGoogleTest(&argc, argv); + + ros::NodeHandle nh; + + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_plan_components_builder.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_plan_components_builder.test new file mode 100644 index 0000000000..447c618525 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_plan_components_builder.test @@ -0,0 +1,65 @@ + + + + + + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.cpp b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.cpp new file mode 100644 index 0000000000..a5883e71cc --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.cpp @@ -0,0 +1,628 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "moveit_msgs/MoveGroupSequenceAction.h" + +static constexpr int WAIT_FOR_ACTION_SERVER_TIME_OUT{ 10 }; // seconds + +const std::string SEQUENCE_ACTION_NAME("/sequence_move_group"); + +// Parameters from parameter server +const std::string JOINT_POSITION_TOLERANCE("joint_position_tolerance"); + +// events for callback tests +const std::string GOAL_SUCCEEDED_EVENT = "GOAL_SUCCEEDED"; +const std::string SERVER_IDLE_EVENT = "SERVER_IDLE"; + +const std::string TEST_DATA_FILE_NAME("testdata_file_name"); +const std::string GROUP_NAME("group_name"); + +using namespace pilz_industrial_motion_planner_testutils; + +class IntegrationTestSequenceAction : public testing::Test, public testing::AsyncTest +{ +protected: + void SetUp() override; + +public: + MOCK_METHOD0(active_callback, void()); + MOCK_METHOD1(feedback_callback, void(const moveit_msgs::MoveGroupSequenceFeedbackConstPtr& feedback)); + MOCK_METHOD2(done_callback, void(const actionlib::SimpleClientGoalState& state, + const moveit_msgs::MoveGroupSequenceResultConstPtr& result)); + +protected: + ros::NodeHandle ph_{ "~" }; + actionlib::SimpleActionClient ac_{ ph_, SEQUENCE_ACTION_NAME, true }; + std::shared_ptr move_group_; + + robot_model_loader::RobotModelLoader model_loader_; + robot_model::RobotModelPtr robot_model_; + double joint_position_tolerance_; + + std::string test_data_file_name_; + std::string group_name_; + TestdataLoaderUPtr data_loader_; + + //! The configuration at which the robot stays at the beginning of each test. + JointConfiguration start_config; +}; + +void IntegrationTestSequenceAction::SetUp() +{ + // get necessary parameters + ASSERT_TRUE(ph_.getParam(JOINT_POSITION_TOLERANCE, joint_position_tolerance_)); + ASSERT_TRUE(ph_.getParam(TEST_DATA_FILE_NAME, test_data_file_name_)); + ph_.param(GROUP_NAME, group_name_, "manipulator"); + + robot_model_ = model_loader_.getModel(); + + data_loader_.reset(new XmlTestdataLoader(test_data_file_name_, robot_model_)); + ASSERT_NE(nullptr, data_loader_) << "Failed to load test data by provider."; + + // wait for action server + ASSERT_TRUE(ac_.waitForServer(ros::Duration(WAIT_FOR_ACTION_SERVER_TIME_OUT))) << "Action server is not active."; + + // move to default position + start_config = data_loader_->getJoints("ZeroPose", group_name_); + robot_state::RobotState robot_state{ start_config.toRobotState() }; + + move_group_ = std::make_shared(start_config.getGroupName()); + move_group_->setPlannerId("PTP"); + move_group_->setGoalTolerance(joint_position_tolerance_); + move_group_->setJointValueTarget(robot_state); + move_group_->move(); + + ASSERT_TRUE( + isAtExpectedPosition(robot_state, *(move_group_->getCurrentState()), joint_position_tolerance_, group_name_)); +} + +/** + * @brief Test behavior of sequence action server when empty sequence is sent. + * + * Test Sequence: + * 1. Send empty sequence. + * 2. Evaluate the result. + * + * Expected Results: + * 1. Empty sequence is sent to the action server. + * 2. Error code of the blend result is SUCCESS. + */ +TEST_F(IntegrationTestSequenceAction, TestSendingOfEmptySequence) +{ + moveit_msgs::MoveGroupSequenceGoal seq_goal; + + ac_.sendGoalAndWait(seq_goal); + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::SUCCESS) << "Execution of sequence failed."; + EXPECT_TRUE(res->response.planned_trajectories.empty()); +} + +/** + * @brief Tests that invalid (differing) group names are detected. + * + * Test Sequence: + * 1. Invalidate first request (change group_name) and send goal for planning + * and execution. + * 2. Evaluate the result. + * + * Expected Results: + * 1. Goal is sent to the action server. + * 2. Error code of the result is failure. + */ +TEST_F(IntegrationTestSequenceAction, TestDifferingGroupNames) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + MotionCmd& cmd{ seq.getCmd(1) }; + cmd.setPlanningGroup("WrongGroupName"); + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = seq.toRequest(); + + ac_.sendGoalAndWait(seq_goal); + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME) << "Incorrect error code."; + EXPECT_TRUE(res->response.planned_trajectories.empty()); +} + +/** + * @brief Tests that negative blend radii are detected. + * + * Test Sequence: + * 1. Send goal for planning and execution. + * 2. Evaluate the result. + * + * Expected Results: + * 1. Goal is sent to the action server. + * 2. Error code of the result is not success and the planned trajectory is + * empty. + */ +TEST_F(IntegrationTestSequenceAction, TestNegativeBlendRadius) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + seq.setBlendRadius(0, -1.0); + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = seq.toRequest(); + + ac_.sendGoalAndWait(seq_goal); + + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN) + << "Incorrect error code."; + EXPECT_TRUE(res->response.planned_trajectories.empty()); +} + +/** + * @brief Tests that overlapping blend radii are detected. + * + * Test Sequence: + * 1. Generate request with overlapping blend radii. + * 2. Send goal for planning and execution. + * 3. Evaluate the result. + * + * Expected Results: + * 1. - + * 2. Goal is sent to the action server. + * 3. Command fails, result trajectory is empty. + */ +TEST_F(IntegrationTestSequenceAction, TestOverlappingBlendRadii) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + seq.setBlendRadius(0, 10 * seq.getBlendRadius(0)); + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = seq.toRequest(); + + ac_.sendGoalAndWait(seq_goal); + + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN) << "Incorrect error code"; + EXPECT_TRUE(res->response.planned_trajectories.empty()); +} + +/** + * @brief Tests that too large blend radii are detected. + * + * Test Sequence: + * 1. Generate request with too large blend radii. + * 2. Send goal for planning and execution. + * 2. Evaluate the result. + * + * Expected Results: + * 1. - + * 2. Goal is sent to the action server. + * 3. Command fails, result trajectory is empty. + */ +TEST_F(IntegrationTestSequenceAction, TestTooLargeBlendRadii) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + seq.erase(2, seq.size()); + seq.setBlendRadius(0, 10 * seq.getBlendRadius(seq.size() - 2)); + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = seq.toRequest(); + + ac_.sendGoalAndWait(seq_goal); + + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::FAILURE) << "Incorrect error code"; + EXPECT_TRUE(res->response.planned_trajectories.empty()); +} + +/** + * @brief Tests what happens if sequence contains not executable (invalid) + * command. + * + * Test Sequence: + * 1. Create sequence containing at least one invalid command. + * 2. Send goal for planning and execution. + * 3. Evaluate the result. + * + * Expected Results: + * 1. - + * 2. Goal is sent to the action server. + * 3. Error code indicates an error + planned trajectory is empty. + */ +TEST_F(IntegrationTestSequenceAction, TestInvalidCmd) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + // Erase certain command to invalid command following the command in sequence. + seq.erase(3, 4); + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = seq.toRequest(); + + ac_.sendGoalAndWait(seq_goal); + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_NE(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::SUCCESS) << "Incorrect error code."; + EXPECT_TRUE(res->response.planned_trajectories.empty()); +} + +/** + * @brief Tests that incorrect link_names are detected. + * + * Test Sequence: + * 1. Create sequence and send it via ActionClient. + * 2. Wait for successful completion of command. + * + * Expected Results: + * 1. - + * 2. ActionClient reports successful completion of command. + */ +TEST_F(IntegrationTestSequenceAction, TestInvalidLinkName) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + seq.setAllBlendRadiiToZero(); + + // Invalidate link name + CircInterimCart& circ{ seq.getCmd(1) }; + circ.getGoalConfiguration().setLinkName("InvalidLinkName"); + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = seq.toRequest(); + + ac_.sendGoalAndWait(seq_goal); + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_NE(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::SUCCESS) << "Incorrect error code."; + EXPECT_TRUE(res->response.planned_trajectories.empty()); +} + +//******************************************************* +//*** matcher for callback functions of action server *** +//******************************************************* +MATCHER_P(FeedbackStateEq, state, "") +{ + return arg->state == state; +} +MATCHER(IsResultSuccess, "") +{ + return arg->response.error_code.val == moveit_msgs::MoveItErrorCodes::SUCCESS; +} +MATCHER(IsResultNotEmpty, "") +{ + return !arg->response.planned_trajectories.empty(); +} + +/** + * @brief Tests that action server callbacks are called correctly. + * + * Test Sequence: + * 1. Send goal for planning and execution. + * 2. Evaluate the result. + * + * Expected Results: + * 1. Goal is sent to the action server. + * 2. Error code of the result is success. Active-, feedback- and + * done-callbacks are called. + */ +TEST_F(IntegrationTestSequenceAction, TestActionServerCallbacks) +{ + using ::testing::_; + using ::testing::AllOf; + using ::testing::AtLeast; + using ::testing::InSequence; + + namespace ph = std::placeholders; + + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + // We do not need the complete sequence, just two commands. + seq.erase(2, seq.size()); + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = seq.toRequest(); + + // set expectations (no guarantee, that done callback is called before idle + // feedback) + EXPECT_CALL(*this, active_callback()).Times(1).RetiresOnSaturation(); + + EXPECT_CALL(*this, done_callback(_, AllOf(IsResultSuccess(), IsResultNotEmpty()))) + .Times(1) + .WillOnce(ACTION_OPEN_BARRIER_VOID(GOAL_SUCCEEDED_EVENT)) + .RetiresOnSaturation(); + + // the feedbacks are expected in order + { + InSequence dummy; + + EXPECT_CALL(*this, feedback_callback(FeedbackStateEq("PLANNING"))).Times(AtLeast(1)); + EXPECT_CALL(*this, feedback_callback(FeedbackStateEq("MONITOR"))).Times(AtLeast(1)); + EXPECT_CALL(*this, feedback_callback(FeedbackStateEq("IDLE"))) + .Times(AtLeast(1)) + .WillOnce(ACTION_OPEN_BARRIER_VOID(SERVER_IDLE_EVENT)) + .RetiresOnSaturation(); + } + + // send goal using mocked callback methods + ac_.sendGoal(seq_goal, std::bind(&IntegrationTestSequenceAction::done_callback, this, ph::_1, ph::_2), + std::bind(&IntegrationTestSequenceAction::active_callback, this), + std::bind(&IntegrationTestSequenceAction::feedback_callback, this, ph::_1)); + + // wait for the ecpected events + BARRIER({ GOAL_SUCCEEDED_EVENT, SERVER_IDLE_EVENT }); +} + +/** + * @brief Tests the "only planning" flag. + * + * Test Sequence: + * 1. Send goal for planning and execution. + * 2. Evaluate the result. + * + * Expected Results: + * 1. Goal is sent to the action server. + * 2. Error code of the result is success. + */ +TEST_F(IntegrationTestSequenceAction, TestPlanOnlyFlag) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + // We do not need the complete sequence, just two commands. + seq.erase(2, seq.size()); + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.planning_options.plan_only = true; + seq_goal.request = seq.toRequest(); + + ac_.sendGoalAndWait(seq_goal); + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::SUCCESS) << "Sequence execution failed."; + EXPECT_FALSE(res->response.planned_trajectories.empty()) << "Planned trajectory is empty"; + + ASSERT_TRUE(isAtExpectedPosition(*(move_group_->getCurrentState()), start_config.toRobotState(), + joint_position_tolerance_, group_name_)) + << "Robot did move although \"PlanOnly\" flag set."; +} + +/** + * @brief Tests that robot state in planning_scene_diff is + * ignored (Mainly for full coverage) in case "plan only" flag is set. + * + * Test Sequence: + * 1. Send goal with "empty" planning scene for planning and execution. + * 2. Evaluate the result. + * + * Expected Results: + * 1. Goal is sent to the action server. + * 2. Error code of the result is success. + */ +TEST_F(IntegrationTestSequenceAction, TestIgnoreRobotStateForPlanOnly) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + // We do not need the complete sequence, just two commands. + seq.erase(2, seq.size()); + + // create request + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.planning_options.plan_only = true; + seq_goal.request = seq.toRequest(); + + seq_goal.planning_options.planning_scene_diff.robot_state.is_diff = true; + + ac_.sendGoalAndWait(seq_goal); + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::SUCCESS) << "Execution of sequence failed."; + EXPECT_FALSE(res->response.planned_trajectories.empty()) << "Planned trajectory is empty"; + + ASSERT_TRUE(isAtExpectedPosition(*(move_group_->getCurrentState()), start_config.toRobotState(), + joint_position_tolerance_, group_name_)) + << "Robot did move although \"PlanOnly\" flag set."; +} + +/** + * @brief Tests that negative blend radii are detected + * (Mainly for full coverage) in case "plan only" flag is set. + * + * Test Sequence: + * 1. Send goal for planning and execution. + * 2. Evaluate the result. + * + * Expected Results: + * 1. Goal is sent to the action server. + * 2. Error code of the result is not success and the planned trajectory is + * empty. + */ +TEST_F(IntegrationTestSequenceAction, TestNegativeBlendRadiusForPlanOnly) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + seq.setBlendRadius(0, -1.0); + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = seq.toRequest(); + seq_goal.planning_options.plan_only = true; + + ac_.sendGoalAndWait(seq_goal); + + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN) + << "Incorrect error code."; + EXPECT_TRUE(res->response.planned_trajectories.empty()); +} + +/** + * @brief Tests that robot state in planning_scene_diff is + * ignored (Mainly for full coverage). + * + * Test Sequence: + * 1. Send goal with "empty" planning scene for planning and execution. + * 2. Evaluate the result. + * + * Expected Results: + * 1. Goal is sent to the action server. + * 2. Error code of the result is success. + */ +TEST_F(IntegrationTestSequenceAction, TestIgnoreRobotState) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + // We do not need the complete sequence, just two commands. + seq.erase(2, seq.size()); + + // create request + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = seq.toRequest(); + + seq_goal.planning_options.planning_scene_diff.robot_state.is_diff = true; + + ac_.sendGoalAndWait(seq_goal); + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::SUCCESS) << "Execution of sequence failed."; + EXPECT_FALSE(res->response.planned_trajectories.empty()) << "Planned trajectory is empty"; +} + +/** + * @brief Tests the execution of a sequence with more than two commands. + * + * Test Sequence: + * 1. Create large sequence requests and sent it to action server. + * 2. Evaluate the result. + * + * Expected Results: + * 1. Goal is sent to the action server. + * 2. Command succeeds, result trajectory is not empty. + */ +TEST_F(IntegrationTestSequenceAction, TestLargeRequest) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + moveit_msgs::MotionSequenceRequest req{ seq.toRequest() }; + // Create large request by making copies of the original sequence commands + // and adding them to the end of the original sequence. + size_t n{ req.items.size() }; + for (size_t i = 0; i < n; ++i) + { + moveit_msgs::MotionSequenceItem item{ req.items.at(i) }; + if (i == 0) + { + // Remove start state because only the first request + // is allowed to have a start state in a sequence. + item.req.start_state = moveit_msgs::RobotState(); + } + req.items.push_back(item); + } + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = req; + + ac_.sendGoalAndWait(seq_goal); + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::SUCCESS) << "Incorrect error code."; + EXPECT_FALSE(res->response.planned_trajectories.empty()) << "Planned trajectory is empty"; +} + +/** + * @brief Tests the execution of a sequence command (without blending) + * consisting of most of the possible command type combination. + * + * Test Sequence: + * 1. Create sequence goal and send it via ActionClient. + * 2. Wait for successful completion of command. + * + * Expected Results: + * 1. - + * 2. ActionClient reports successful completion of command. + */ +TEST_F(IntegrationTestSequenceAction, TestComplexSequenceWithoutBlending) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + + seq.setAllBlendRadiiToZero(); + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = seq.toRequest(); + + ac_.sendGoalAndWait(seq_goal); + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + EXPECT_FALSE(res->response.planned_trajectories.empty()) << "Planned trajectory is empty"; +} + +/** + * @brief Tests the execution of a sequence command (with blending) + * consisting of most of the possible command type combination. + * + * Test Sequence: + * 1. Create sequence goal and send it via ActionClient. + * 2. Wait for successful completion of command. + * + * Expected Results: + * 1. - + * 2. ActionClient reports successful completion of command. + */ +TEST_F(IntegrationTestSequenceAction, TestComplexSequenceWithBlending) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = seq.toRequest(); + + ac_.sendGoalAndWait(seq_goal); + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + EXPECT_FALSE(res->response.planned_trajectories.empty()) << "Planned trajectory is empty"; +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "integrationtest_sequence_action_capability"); + ros::NodeHandle nh; + + ros::AsyncSpinner spinner{ 1 }; + spinner.start(); + + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.test new file mode 100644 index 0000000000..df51f007b1 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.test @@ -0,0 +1,59 @@ + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_frankaemika_panda.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_frankaemika_panda.test new file mode 100644 index 0000000000..bc6afb0a8e --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_frankaemika_panda.test @@ -0,0 +1,65 @@ + + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_with_gripper.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_with_gripper.test new file mode 100644 index 0000000000..c45f964dbc --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_with_gripper.test @@ -0,0 +1,60 @@ + + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.cpp b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.cpp new file mode 100644 index 0000000000..bf9198d52a --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.cpp @@ -0,0 +1,180 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "moveit_msgs/MoveGroupSequenceAction.h" + +static constexpr double WAIT_FOR_RESULT_TIME_OUT{ 5. }; // seconds +static constexpr double TIME_BEFORE_CANCEL_GOAL{ 1.0 }; // seconds +static constexpr double WAIT_FOR_ACTION_SERVER_TIME_OUT{ 10. }; // seconds + +const std::string SEQUENCE_ACTION_NAME("/sequence_move_group"); + +// Parameters from parameter server +const std::string JOINT_POSITION_TOLERANCE("joint_position_tolerance"); + +// events for callback tests +const std::string GOAL_SUCCEEDED_EVENT = "GOAL_SUCCEEDED"; +const std::string SERVER_IDLE_EVENT = "SERVER_IDLE"; + +const std::string TEST_DATA_FILE_NAME("testdata_file_name"); +const std::string GROUP_NAME("group_name"); + +using namespace pilz_industrial_motion_planner_testutils; + +class IntegrationTestSequenceAction : public testing::Test, public testing::AsyncTest +{ +protected: + void SetUp() override; + +public: + MOCK_METHOD0(active_callback, void()); + MOCK_METHOD1(feedback_callback, void(const moveit_msgs::MoveGroupSequenceFeedbackConstPtr& feedback)); + MOCK_METHOD2(done_callback, void(const actionlib::SimpleClientGoalState& state, + const moveit_msgs::MoveGroupSequenceResultConstPtr& result)); + +protected: + ros::NodeHandle ph_{ "~" }; + actionlib::SimpleActionClient ac_{ ph_, SEQUENCE_ACTION_NAME, true }; + std::shared_ptr move_group_; + + robot_model_loader::RobotModelLoader model_loader_; + robot_model::RobotModelPtr robot_model_; + double joint_position_tolerance_; + + std::string test_data_file_name_; + std::string group_name_; + TestdataLoaderUPtr data_loader_; + + //! The configuration at which the robot stays at the beginning of each test. + JointConfiguration start_config; +}; + +void IntegrationTestSequenceAction::SetUp() +{ + // get necessary parameters + ASSERT_TRUE(ph_.getParam(JOINT_POSITION_TOLERANCE, joint_position_tolerance_)); + ASSERT_TRUE(ph_.getParam(TEST_DATA_FILE_NAME, test_data_file_name_)); + ph_.param(GROUP_NAME, group_name_, "manipulator"); + + robot_model_ = model_loader_.getModel(); + + data_loader_.reset(new XmlTestdataLoader(test_data_file_name_, robot_model_)); + ASSERT_NE(nullptr, data_loader_) << "Failed to load test data by provider."; + + // wait for action server + ASSERT_TRUE(ac_.waitForServer(ros::Duration(WAIT_FOR_ACTION_SERVER_TIME_OUT))) << "Action server is not active."; + + // move to default position + start_config = data_loader_->getJoints("ZeroPose", group_name_); + robot_state::RobotState robot_state{ start_config.toRobotState() }; + + move_group_ = std::make_shared(start_config.getGroupName()); + move_group_->setPlannerId("PTP"); + move_group_->setGoalTolerance(joint_position_tolerance_); + move_group_->setJointValueTarget(robot_state); + move_group_->setMaxVelocityScalingFactor(1.0); + move_group_->setMaxAccelerationScalingFactor(1.0); + move_group_->move(); + + ASSERT_TRUE(isAtExpectedPosition(robot_state, *(move_group_->getCurrentState()), joint_position_tolerance_)); +} + +/** + * @brief Tests that goal can be cancelled. + * + * Test Sequence: + * 1. Send goal for planning and execution. + * 2. Cancel goal before it finishes. + * + * Expected Results: + * 1. Goal is sent to the action server. + * 2. Goal is cancelled. Execution stops. + */ +TEST_F(IntegrationTestSequenceAction, TestCancellingOfGoal) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + + moveit_msgs::MoveGroupSequenceGoal seq_goal; + seq_goal.request = seq.toRequest(); + + ac_.sendGoal(seq_goal); + // wait for 1 second + ros::Duration(TIME_BEFORE_CANCEL_GOAL).sleep(); + + ac_.cancelGoal(); + ac_.waitForResult(ros::Duration(WAIT_FOR_RESULT_TIME_OUT)); + + moveit_msgs::MoveGroupSequenceResultConstPtr res = ac_.getResult(); + EXPECT_EQ(res->response.error_code.val, moveit_msgs::MoveItErrorCodes::PREEMPTED) + << "Error code should be preempted."; +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "integrationtest_sequence_action_preemption"); + ros::NodeHandle nh; + + ros::AsyncSpinner spinner{ 1 }; + spinner.start(); + + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.test new file mode 100644 index 0000000000..614b5ffe1d --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.test @@ -0,0 +1,59 @@ + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability.cpp b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability.cpp new file mode 100644 index 0000000000..02f4bf5aa9 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability.cpp @@ -0,0 +1,426 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "moveit_msgs/GetMotionSequence.h" +#include "moveit_msgs/MotionSequenceRequest.h" +#include "pilz_industrial_motion_planner/capability_names.h" + +// Parameters from parameter server +const std::string TEST_DATA_FILE_NAME("testdata_file_name"); + +using namespace pilz_industrial_motion_planner_testutils; + +static std::string createJointName(const size_t& joint_number) +{ + return std::string("prbt_joint_") + std::to_string(joint_number + 1); +} + +class IntegrationTestSequenceService : public ::testing::Test +{ +protected: + void SetUp() override; + +protected: + ros::NodeHandle ph_{ "~" }; + ros::ServiceClient client_; + robot_model::RobotModelPtr robot_model_; + + std::string test_data_file_name_; + TestdataLoaderUPtr data_loader_; +}; + +void IntegrationTestSequenceService::SetUp() +{ + // get necessary parameters + ASSERT_TRUE(ph_.getParam(TEST_DATA_FILE_NAME, test_data_file_name_)); + + robot_model_loader::RobotModelLoader model_loader; + robot_model_ = model_loader.getModel(); + + data_loader_.reset(new XmlTestdataLoader(test_data_file_name_, robot_model_)); + ASSERT_NE(nullptr, data_loader_) << "Failed to load test data by provider."; + + ASSERT_TRUE(ros::service::waitForService(pilz_industrial_motion_planner::SEQUENCE_SERVICE_NAME, ros::Duration(10))) + << "Service not available."; + ros::NodeHandle nh; // connect to service in global namespace, not in ph_ + client_ = nh.serviceClient(pilz_industrial_motion_planner::SEQUENCE_SERVICE_NAME); +} + +/** + * @brief Test behavior of service when empty sequence is sent. + * + * Test Sequence: + * 1. Generate empty request and call sequence service. + * 2. Evaluate the result. + * + * Expected Results: + * 1. MotionPlanResponse is received. + * 2. Command is successful, result trajectory is empty. + */ +TEST_F(IntegrationTestSequenceService, TestSendingOfEmptySequence) +{ + moveit_msgs::MotionSequenceRequest empty_list; + + moveit_msgs::GetMotionSequence srv; + srv.request.request = empty_list; + + ASSERT_TRUE(client_.call(srv)); + + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, srv.response.response.error_code.val) << "Planning failed."; + EXPECT_TRUE(srv.response.response.planned_trajectories.empty()); +} + +/** + * @brief Tests that invalid (differing) group names are detected. + * + * Test Sequence: + * 1. Generate request, first request has invalid group_name + Call sequence + * service. + * 2. Invalidate first request (change group_name) and send goal for planning + * and execution. + * + * Expected Results: + * 1. MotionPlanResponse is received. + * 2. Command fails, result trajectory is empty. + */ +TEST_F(IntegrationTestSequenceService, TestDifferingGroupNames) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + MotionCmd& cmd{ seq.getCmd(1) }; + cmd.setPlanningGroup("WrongGroupName"); + + moveit_msgs::GetMotionSequence srv; + srv.request.request = seq.toRequest(); + + ASSERT_TRUE(client_.call(srv)); + + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME, srv.response.response.error_code.val) + << "Planning should have failed but did not."; + EXPECT_TRUE(srv.response.response.planned_trajectories.empty()); +} + +/** + * @brief Tests that negative blend radii are detected. + * + * Test Sequence: + * 1. Generate request with negative blend_radius + Call sequence service. + * 2. Evaluate the result. + * + * Expected Results: + * 1. MotionPlanResponse is received. + * 2. Command fails, result trajectory is empty. + */ +TEST_F(IntegrationTestSequenceService, TestNegativeBlendRadius) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + seq.setBlendRadius(0, -1.0); + + moveit_msgs::GetMotionSequence srv; + srv.request.request = seq.toRequest(); + + ASSERT_TRUE(client_.call(srv)); + + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN, srv.response.response.error_code.val) + << "Planning should have failed but did not."; + EXPECT_TRUE(srv.response.response.planned_trajectories.empty()); +} + +/** + * @brief Tests that overlapping blend radii are detected. + * + * Test Sequence: + * 1. Generate request with overlapping blend radii + Call sequence service. + * 2. Evaluate the result. + * + * Expected Results: + * 1. MotionPlanResponse is received. + * 2. Command fails, result trajectory is empty. + */ +TEST_F(IntegrationTestSequenceService, TestOverlappingBlendRadii) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + seq.setBlendRadius(0, 10 * seq.getBlendRadius(0)); + + moveit_msgs::GetMotionSequence srv; + srv.request.request = seq.toRequest(); + + ASSERT_TRUE(client_.call(srv)); + + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN, srv.response.response.error_code.val) + << "Incorrect error code"; + EXPECT_TRUE(srv.response.response.planned_trajectories.empty()); +} + +/** + * @brief Tests that too large blend radii are detected. + * + * Test Sequence: + * 1. Generate request with too large blend radii + Call sequence service. + * 2. Evaluate the result. + * + * Expected Results: + * 1. MotionPlanResponse is received. + * 2. Command fails, result trajectory is empty. + */ +TEST_F(IntegrationTestSequenceService, TestTooLargeBlendRadii) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + seq.erase(2, seq.size()); + seq.setBlendRadius(0, 10 * seq.getBlendRadius(seq.size() - 2)); + + moveit_msgs::GetMotionSequence srv; + srv.request.request = seq.toRequest(); + + ASSERT_TRUE(client_.call(srv)); + + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::FAILURE, srv.response.response.error_code.val) << "Incorrect error code"; + EXPECT_TRUE(srv.response.response.planned_trajectories.empty()); +} + +/** + * @brief Tests behavior of service when sequence with invalid second + * start state is sent. + * + * Test Sequence: + * 1. Generate request (second goal has invalid start state) + Call sequence + * service. + * 2. Evaluate the result + * + * Expected Results: + * 1. MotionPlanResponse is received. + * 2. Command fails, result trajectory is empty. + */ +TEST_F(IntegrationTestSequenceService, TestSecondTrajInvalidStartState) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + moveit_msgs::MotionSequenceRequest req_list{ seq.toRequest() }; + + // Set start state + using std::placeholders::_1; + JointConfiguration config{ "MyGroupName", { -1., 2., -3., 4., -5., 0. }, std::bind(&createJointName, _1) }; + req_list.items[1].req.start_state.joint_state = config.toSensorMsg(); + + moveit_msgs::GetMotionSequence srv; + srv.request.request = req_list; + + ASSERT_TRUE(client_.call(srv)); + + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE, srv.response.response.error_code.val) + << "Incorrect error code."; + EXPECT_TRUE(srv.response.response.planned_trajectories.empty()); +} + +/** + * @brief Tests behavior of service when sequence with invalid first goal + * is sent. + * + * Test Sequence: + * 1. Generate request with first goal out of workspace + Call sequence + * service. + * 2. Evaluate the result + * + * Expected Results: + * 1. MotionPlanResponse is received. + * 2. Command fails, result trajectory is empty. + */ +TEST_F(IntegrationTestSequenceService, TestFirstGoalNotReachable) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + PtpJointCart& cmd{ seq.getCmd(0) }; + cmd.getGoalConfiguration().getPose().position.y = 27; + + moveit_msgs::GetMotionSequence srv; + srv.request.request = seq.toRequest(); + + ASSERT_TRUE(client_.call(srv)); + + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION, srv.response.response.error_code.val) + << "Incorrect error code."; + EXPECT_TRUE(srv.response.response.planned_trajectories.empty()); +} + +/** + * @brief Tests that incorrect link_names are detected. + * + * Test Sequence: + * 1. Create sequence and send it. + * 2. Wait for successful completion of command. + * + * Expected Results: + * 1. MotionPlanResponse is received. + * 2. Command fails, result trajectory is empty. + */ +TEST_F(IntegrationTestSequenceService, TestInvalidLinkName) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + seq.setAllBlendRadiiToZero(); + + // Invalidate link name + CircInterimCart& circ{ seq.getCmd(1) }; + circ.getGoalConfiguration().setLinkName("InvalidLinkName"); + + moveit_msgs::GetMotionSequence srv; + srv.request.request = seq.toRequest(); + + ASSERT_TRUE(client_.call(srv)); + + EXPECT_NE(moveit_msgs::MoveItErrorCodes::SUCCESS, srv.response.response.error_code.val) << "Incorrect error code."; + EXPECT_TRUE(srv.response.response.planned_trajectories.empty()); +} + +/** + * @brief Tests the execution of a sequence with more than two commands. + * + * Test Sequence: + * 1. Call service with serveral requests. + * 2. Evaluate the result. + * + * Expected Results: + * 1. MotionPlanResponse is received. + * 2. Command succeeds, result trajectory is not empty. + */ +TEST_F(IntegrationTestSequenceService, TestLargeRequest) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + moveit_msgs::MotionSequenceRequest req{ seq.toRequest() }; + // Make copy of sequence commands and add them to the end of sequence. + // Create large request by making copies of the original sequence commands + // and adding them to the end of the original sequence. + size_t n{ req.items.size() }; + for (size_t i = 0; i < n; ++i) + { + moveit_msgs::MotionSequenceItem item{ req.items.at(i) }; + if (i == 0) + { + // Remove start state because only the first request + // is allowed to have a start state in a sequence. + item.req.start_state = moveit_msgs::RobotState(); + } + req.items.push_back(item); + } + + moveit_msgs::GetMotionSequence srv; + srv.request.request = req; + + ASSERT_TRUE(client_.call(srv)); + + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, srv.response.response.error_code.val) << "Incorrect error code."; + EXPECT_EQ(srv.response.response.planned_trajectories.size(), 1u); + EXPECT_GT(srv.response.response.planned_trajectories.front().joint_trajectory.points.size(), 0u) + << "Trajectory should contain points."; +} + +/** + * @brief Tests the execution of a sequence command (without blending) + * consisting of most of the possible command type combination. + * + * Test Sequence: + * 1. Create sequence goal and send it via ActionClient. + * 2. Wait for successful completion of command. + * + * Expected Results: + * 1. - + * 2. ActionClient reports successful completion of command. + */ +TEST_F(IntegrationTestSequenceService, TestComplexSequenceWithoutBlending) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + + seq.setAllBlendRadiiToZero(); + + moveit_msgs::GetMotionSequence srv; + srv.request.request = seq.toRequest(); + + ASSERT_TRUE(client_.call(srv)); + + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, srv.response.response.error_code.val) << "Incorrect error code."; + EXPECT_EQ(srv.response.response.planned_trajectories.size(), 1u); + EXPECT_GT(srv.response.response.planned_trajectories.front().joint_trajectory.points.size(), 0u) + << "Trajectory should contain points."; +} + +/** + * @brief Tests the execution of a sequence command (with blending) + * consisting of most of the possible command type combination. + * + * Test Sequence: + * 1. Create sequence goal and send it via ActionClient. + * 2. Wait for successful completion of command. + * + * Expected Results: + * 1. - + * 2. ActionClient reports successful completion of command. + */ +TEST_F(IntegrationTestSequenceService, TestComplexSequenceWithBlending) +{ + Sequence seq{ data_loader_->getSequence("ComplexSequence") }; + + moveit_msgs::GetMotionSequence srv; + srv.request.request = seq.toRequest(); + + ASSERT_TRUE(client_.call(srv)); + + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, srv.response.response.error_code.val) << "Incorrect error code."; + EXPECT_EQ(srv.response.response.planned_trajectories.size(), 1u); + EXPECT_GT(srv.response.response.planned_trajectories.front().joint_trajectory.points.size(), 0u) + << "Trajectory should contain points."; +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "integrationtest_sequence_service_capability"); + ros::NodeHandle nh; + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability.test new file mode 100644 index 0000000000..9eec6f308b --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability.test @@ -0,0 +1,57 @@ + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_frankaemika_panda.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_frankaemika_panda.test new file mode 100644 index 0000000000..dbec926599 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_frankaemika_panda.test @@ -0,0 +1,59 @@ + + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_with_gripper.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_with_gripper.test new file mode 100644 index 0000000000..f214d4baf7 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_with_gripper.test @@ -0,0 +1,57 @@ + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/concept_testdata.odp b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/concept_testdata.odp new file mode 100644 index 0000000000000000000000000000000000000000..1e437d42041f326cc09967f88bd19e2a6a76ac4d GIT binary patch literal 14825 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 literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/concept_testdata.png b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/concept_testdata.png new file mode 100644 index 0000000000000000000000000000000000000000..0dbf6f8d88d5d761e0c4d79cb2b2852a4448a942 GIT binary patch literal 74304 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 z%0AQd0wUBoahlt*8+5eOL0yD+*h%ltmkMZsGqlH^aB*_2ZiB7YX>d0@F|a%WxqdJ+ zTd&n*Qf^y3cpzA9s77C~QwsMl%x%$#EWj?=t6iJqBwkZfeKZzw^DL*gudQpi)&~2T zxIETAtby0=UXDjB3GZ_BSaSrTgk84NKG_S#BxN1ols#XGpH7N)s>;WVd#yAklxBrK z9KY=1_A2&kRe*nTyYF6B%~bp;{9Mt~&>}ex7W(4Ij*D&;{;_;7d7gM+xBA0uqq3iK zAY00DQ{M-n(9WhB>SphL+C0CE zj=5Q%^qv+kq&j}4qgThmr$t`aF2QkhjzT@+Nk1ia$g$OCGXDZ=F)?hGj*`sz1g%H?PuVqR=rY*O1-C$Jy9)Hz8=5tAhpI8wVu9ofn2K&OBR z_40d6D&ns?Ptfo1YIuhHdGGowLQG6z`(=O7(y*dvXs65LHi8C(34JbWK#ek_g` zVMOfa3MWaHI#C&q5*B!b1TLuFT7Rr7!p(S0pIwMv$8*evKXO>Pyt-_UH)r5@(Y(=< zM4g4gVre3-l5=KHo_niS8uuFUMvxA-US^%A>L;&I=!+a)Q)l~;UuL0IbbuE|9{`+X z&CeWgz=hboM4w&d=?XA|2BdzVa!gBEmhf-N@k_mV-)6OL~ zg8w+7xCE!J8HqYcUJNwhXbi-j5%B92-(FI>Kb&25Sj{uMttk$@^2KkkNSiOme3#;$ zH0m4F$gkuO{Cm9_b_a(}sN`D@rG%fM>Lff)Jz;v(GsU3MkB|H{irS+flb>O&R$DiW zc<;3fdMaG`$8l+Tvmj|%U&i_|9j)cJ#tys^buaS4cPzq5Mj^)5Sm;Qx+!*g~ud;5< zipOd@tM!CQo}vf~J%N^YKXz@Bj$+k*77h2o1F7w?Gk0F*0ny~Y&wrmw5z7?sm_E&@ z(r3iAKae<#bAIJQ?)Lm^PNRM%TLxwJ@CZ2z_@Enz94Ri@NTV@ZGuL>qjufJeR4L_YR8H!?6NC6j&KT2kAbH6R zqgR?6;wRM~^Bwxy+OPTr1lo?UNEYWu(vuB>`@i9r~@?nE@r2TfYdrI274(XAm}?!553l5I(yaYv+RO z45AcwN_s$itMF$~G2w|0v&jB7fAN$lMOL<#{pQQo(!D}}f71tyxYR=_E_f(3bpS4_ z^kJObuDK2?y`c2HXt-7x5-l4x)*p9G`q?55(3OmEnr*rAd`EfiD5p)?*IwDe6G|z! zr0MA7jl%AMK-IzGlD-z|U0z*~d*__iaF+%vp9-1s-3W~=+QkQC51*CojetO8di7^u zt>7-7xdUUk^Kmddc1J1H;&iS||Fz8Za}Orru%hz0w*yU!k_4uW5zm1tsuwuVb`l4; z>SCHoy2z2DnB>9t;CabBEec3nfIQmW`>+k}yu%db54=dld$1I7< zs$f~0g`*=NCgF9|ZVf=sIc*L=TBTE=(W$pUvK;-%?0fb0(`Aj_-zbZ93zRb#LqkK~ zH-38r0)c_`7s!PhB5dnKJgg%`I;@pdR_j}@Px{$Bo{6KqfWh*49Ov9Mrb_g(83PkR zAUaWJXXkz@VP7^??7`lieSQmz+4=6IBT)VZ0$mb^JPhv$!`FfEIWMK4+>+$;N-X=6 z_v)qYfMT_)frfcfva;a;>wAD^Yqir<$*i=~C{T-fp7S)W4eH!$v)Fi^mU_UblEv1| zP7VsH7V}r=8p;&h>vVumK*!bpuZzzQ7g5ioBxvHRxa9r( z7JBo;g$CiZ-SQTxA6muQ_A%6=#_!WzZh>NT-#GV%%lSu212vjce0CEy#en7$2z31Y zY25ox4+Uw(-7U$Fk@rC_c_Q|JK?U5me_aoz^FbQ^js6K3oj#?%!vyA=L~qqZCs*_^ zp2O@m=q0m&=YGB7VyDAa)ni~5K(zYL(2tPg09AFsN6a4J75)2^0@2{VAF4zD|BL>2 zegv`Nnzx4cyM~*+QJd6{#Jr2O74488Xmn``TULk8BJm(B1V{HUjR|P zJXt_p>>YyRMzh}DK6T|u<260$5ji_psr3;4-1s?2wl0247ah3r>Hf5e@s%S6>J@nJ zAtBUwx~L{?rVsC@?h#;G)PV5oxpm=nj(JU&l~*o7OOtGhUT z$h`*;(ZG|E>$2cF2E!xb!}hUB^N$iup3>r9x?TwEcc6u6NfsK9)E|zkJc$pehgF?I z8!b;1ku(YWKc_k#1U;s)?Y09rweN1$iG)tD;(U8S(AUgxLK~>b=dOB<7|;Uh@|ls2 z+6KKL&W0MQx?7Ecp0Z_3DafLqFRG`Vemje8%6e>xqff5P?Soewh`mAdx>v&N8lJLpK0TqB0!T z?8bj8P~xse0;F?5BdPaq=J)*>fEnBUbY3xFvETk$`e50!vGwThn_=I)tD0VCk>&02 za;w6h-@S(2%4fY@&XG^!jQZjc`rM42yhdSEjW==C61C--r7E~L)N!w&*s+4A2|O0#eaX%BZiwv+L?T* z11sD{zo7+Nn|bld7m;C&g9jFVH7{O)Ku|mYI}MTT`c@wH#HAY3@^w4J+O5BCqdS}f z(oR4P4$h=*K4RV^AvH6#&Bd}+0P8ja=2F<;Wyl@ zu=$IxwIsHG)xU5ZK~;Rdzfgu2{xhgMetZkm6Aswtom7@r-AgVPJK1h^#$?2#q-?{R zHmnXM178e*hQm?2kfY-#&xehh35$Nc&UO**<6}-1Jbh0Y`ULa{=OJEQR_(@Bt#H9% z3LiHQf!=}RmxkG`NP;v(`m0T9Z!j;LkYRHmyjY}#+0DADQD~?8q=rrD$M-^X+Vmx zEIZ*da5gmp3=P?^uCj(^#BZM%^1R3`q^6B5j<9e8lQCUN+bYa!E4u+%*%gkL*I1yM z3W}xMo#!OSR?N#Ri!J|>6uK8)Kck!eh*d!&aw_nkg}X>&XDV-DA5kEd3T(_n831G@!#egYW4=wu}8ThwW3(R7SJ@u;A7k!Zj z7vYCZ1(t=JSO7V>)ep~l8l<^4ay~8LX$0msPCp$W87{T@n%834F*-GHis3F7cjDmP zN}yo_w&~rQndVy@4jAM=2#r$uW*dU?7c$KIwN@0mVMNl&mvNPoy2iWYyBvzRp113O5hGddnw77 z(BOKn5q;RQvA=i?5eJC&a{q25V_(r(hkdj9ysv{K+Ox9(uCDeT}j}C?KP8WvrzAo-0$l zYr6EGU#99o@J}Bbmd4Kmr;0O2j#QTJB?`HoDq(x3i(~vau*FG!Rw0JOKTR(|W52K* zuotI8jF;mHbQ0}}T{r4KQxy>kRqLs>it&kI1$^8)Jm@1ie3fOc+027@cl@-xiq+9s z1^hD^cP4-&l8$a!4+p$YI!a)FXBL_8qOKb)4T;O<0emJLLoiftT1LTg>eMYj9Yh&$K8(FNpY6EdIZ;yg+MQNezT9l~ zhI?4XkWepP-y{l@ZFU|By|^gCRLEz(b)?WTMr{eJk$1YzPU#gnJ8 z0>?Jsfo#WO8IUKE{-venpA{KGNP3fy^^F>>R15j*!~QWG+u0-DfQQQW-}X?0WaF<$ znBw1lR>VoUD;fr@BtguLFMG-Mr`v8NO{NYGwScgfD3t>(E#}wkp!LLYY+t$sniV-G zCVS6B-5|2H*&D$1JJdJjCP$DKWEiy|aV_dvoc^9SYO@85mFOnKhY5<{65vT|Zz3WZ z^*K4SI>1W2=8y+E;=tjf^sg$VB3832dDE*u={2=>*%#7$C$-SKdP@lJ<+Ikz7{n6p zQ~r>Jg*w0D7l%IQe+Z3a0G;+Ryc>u7<^80At;KF}lEYRw_~Mf@%4?;4tfy~P`8Z>$ zKVs{n?jo(qRHxySPZP34M*~jR1Ce#q4^8u&txo3jRZcK-8uYk$IMpXOnpRf}AD$cM zzYke5T8P^04^a(p(vXKc8QKXrZJj1Pqa}ZsQ&3&|#=1BuR@L0vk_1gvZ3Pc3byD)sHhXgQ7aHs5*NRa+5tBq%dWTd5)>L|; zDT!92oo?S>H7hI``6(Y$dvS75ajtc*wMw5CyMAmwj~Mj1EQ>&;Mr^jSd{IZ9ZMS`* zRe7NJyw<6%+oMm5H`35MkWztJSkQC3PE>gjBIMh!-*d^)AV1str@N;mr~Ht}(37#G zY5+PjOFa90-V9Ru{I5^x0^DBc!q2)F{T+gYEmCAh3iQI(L9xXD)-HR;0K7d3{m5Vx zcI)Tc-rsXgt^q%4x`!To3pm}D@X5y644sM}5H-l#O(51GNLVFRNY&pJCET^Hl8@(_ z(|X?rLa+HzMfr0oo~KQ?lR9vG{k^>w+6Uhkyx#h$@Tmjndj#Qa$r$}hQ4D8SXp_1d zr1_tqjO%&caFqiE$309g2gf>dmStWZ-R)IsTE#<`RmtTyj3Ua!#IxCtZBweGtsqCp zK$TwXN=?z8@mKx)d$`VJPJnymp?E$?QcRpFWJ#DsSI4qvH#bB6HTyclGlg1{U(E)T>|FBd{<| z%H`eMz2A04u{KzkHM4BeOlIa)W-y!(HV=%`0#Y@^x~W|wq%;T=@gDS z{(VlIcbXh$UT@4@;BHOwzFs@J-S1J&DG&YKTEWEB!o1G>RcyQ7OPo@V&P`&zWy1vz zDoa|_YQbBLi4~-!oRaknZ|;cc1GqnMqpBMB_KX%hKW^>|=7>VpIU1eS>l^@CQ4^=O zOV6XA6o}4?bF>0!Q}eFofW_{#$#SeFBtl!ivA$539F+>_To!wkXPiq`52@w+ISaV9 zyC3xUKVji_oC(oNv*pkYPRTnoe2?Gwcnw?b=K5`!QEHnKYgWmv99}S%*VN}FT6&g4 z;MO|A$NK%x?ueyH-AoJ2mn7dK?cBVB92K2-W9J7*ermcxo?qR_Ptp1}q?D~nbiD+$ zt*ChajOtg#MT@g|+06WMRquitpsrUN%|47-=NGWe<(sB=idV~B)q`R${%yQvrT8zE z{`4u@Ri4YD&#FwSxMl-#AAXuCeC3&`QMc@#RfF86i?N0~C`LW`0{t4N%C!E<5c(Vt zF>LSV6WfUG-JhkVl&@jkPTNT>Grtc4i~ci6dKSYDu9dmz2WRGWOBc}&{ppinm0rWC zNDoqC^_=e`A5TrJvjNE}j6yfq=S7Hw_PmPGi=W{f^X(EbF(TIp_xg~y>%+<%p2(fO z-r#CdF3?LdV7{?TE4Kpl%9>TR`{O#m=}C&0y8=`os75e>9?HajfAQK}%trg1o$P>x z-))CKw*j$GV26-H;WfUqB+gSZ1%KCrOrmv(-zty6>PxuRHI%!53#n6MxCw? zunY`Dy-f?v$})V;p3!gdcfovq^SoSpls*!fX@LhAxb~ZKD99oYfNo?wruBU)(+(y* z*kq0Hi~^Q;Rz)HCQsIRQZdN|kdlNstiSjWEouO#&fNTf>UxF6*yh<0loIr^$E;aS# zzE((RYG|P%zZFO}_NoL?w3fw+;_K0v0rbim%GTcRn%Wj&74zh?Y$6O-SQr zAQP6LD8=D3^T_*7L>`p)gU&41b_!0fgWI`E-<^0ba(cKX0YXf&!t(3A&EpG_@aU8} z6DzAGLA|R1G{J5J;BSD+@It;Dzld;0&X3zV4@NJ+D={ z$2U&~$TdN`r{0_&q{l2AkUb^cPn}$1=v_Fs* zro#mmtT;wkkF3UV9=WA~+oVpFms_g0dNECX^lZ*CqHh`sQAtT1Fp{Odw^ZuEi%B3JYNKphslROzISPIuK|Glk99AdI7 z-~{@O_%~>afo$qny{u<3&n`!$<8)^V;T~}nbqQvklWAaTLiJeN>)ETC`2L^2h_y}z z)V&(N-2;86ys>7#y~cHVZo3MmQijj*1}=BxzL^Ki%zxiI85S4OAJ#i?f#*EseS}|P zMZVCWGz31pYNxfl1GwKik8YyM!rNK1(b+!77k6k%R>`H8C$5!-Ug#mT*ptllpHXyL zGMiQ3WnjJMZOn>5k;kBofvRqM{etP=hQ4kI{O&)^d#g-}e*WegUc?A)ytyn1)5)xB zD+=cbGe9j)`o`N4soPpLJ0^A*BV*K z0;M(BQLAsc^@0P2-9?3L311udGKWALN;fvl__^7kiT&)AiImoF`mKA#O{AchY?7cB?SwEn6f) z`l8InAJy>yvtJh(49|Z&9(X)ZJU5GiH)REqPrTNZb!8PS=B9Vm=VaY9tNirpW+Soy zMD`)5f~H57u3J@*ko<%7vE+;1H8ZJD~Cu zlbGxFT0$E-TXba}A-IKn&(44U3PQ22KBfKIx%fe z4(7-nJ-hNrRYflPhsh{4KY!PrW4NJr%A$KVPV#D1Fe`TFE%5ezo#iyAVAsSPoz0qH zL@om4!xtFprBb-G?5vWhmHu$6#Lh8EoC`095T~T4`)=}*WbHC!*BN)>6*bL->X4!) z%WRg%ftGJ- zrR!hLel3;RS{fx>%dM4nl}d$#G+38aZdfbzI#B^kTS8toke!2UOtrb+#%Nz7@6oB_--{6=p&uJOW z?+82wktO9+iYKrLoB0HcGVWg6%w8vS$2czYZLKu19GbJFVT+#9tgc?cBCY(G1a+U6 z{<0H)vZs7MTV>%oTiw_5Y$Qljc{%f~XWkO#Yo?LHeBUa@;m(asxqRtM z^Ae3sTBfdIW0+oj$)0I&-wG65BR#puUvz7H_(mq{$5|YNec$en-xPT`0~EEPQ}i97 zO`(%DgIN|-TVe^UC{4I8pl=m_%1QE2HeHuc8i)mY`57h-*ZG&R0ynNZopOD4+sd6`%n^yW%3Yy~ zbT0H)nT0#)UwC%4YkY$hD{1v3@d0aauNRMFzJYzpdQ7r%;NquWal2Ii9~ai|3uB!> zmQ^_JX|9-Fi7ZhYIW2=nT-Ttej?G2HJFjM|jc5K5sfwCM+}lAzfD5A@Zn1yqJM&a# zZ#}y*tI{St)R7o>lmS@~eRkM%q0nHf3Zr_$I;pS;08f_#|1p|84UVrF0KB#0S4D$P zWA5PgSl;qbhTz`B#;IRSv|ci_E4XZSeJ_DlACv~1Rbu7_Ln7J8O>@GxN8JV?c+?W?jXtl%v z!`hRDQ6hHVz0Ueon)QzK7ct_J#59lF50vNvc<#vF1ME84ABA#I-5{e7P^gT^zrHy{ z+h|OEL+?j`{3sF_El=m2omF{Jq5zO-EC;cgZRT}jbZl^AwVQ{Lv`pS8vN!1rtFii| zfO1ykf80sQLJ0Yu`y?=y`&T}=8$#Y^@k*#F?^pq`&&x=jGW>?eo?$$!@f#soLR`xN zD6F?_B}gduUj687cQ-Po28RxRId=jL7azpLZCS>+;|XHOpTCd;YUhd|p< zpUY|)$&+0mkdC%h-^yWK(`O?kGBxrS^D)Ev?z^(X)GA-I#Fv?VFR8=h9^$AQznuj6ct8Ai|A6J?ONg9cm zV~rA-;~3jkHe4Y+8@t~zGsvCK0Qb2P$xM$jtRiG}R z|L0SquDdUh2Q5e7KQr`<(oI`#1bGo#${)QUiUa^|H<8(P5m}z1Wau9-G#BTw05k^> z8WpbxsgvDc)f09DODS9-S$T~Qa~^FuK+eJF+eJK7E$Fu7iYKlNZ^2>m9PEsaFgFc< z1?hybZ=&{ZH6*#s_o62aVwM~;Q*TQ;unj0lVy8*cA(7Zf+2e$t&y zB@-$!7zo%di{$JscJA%jvS~4xesfFKnBtpX6r=%jeH7p68p!gRE~%p86O;bC0=YW5 z2Sd@jhK(M_LY`q7FBL&h(i?D*|05C^;|#lIk0eq474VdkTf? zk~Igc%#I>#jAPu|q5h~z9U9-Vr5G|-T){qOE^;v}H3e{mJplFmwnFPSXlAwhO)^s@wfPW7c0yq%ZCn_79)FpQr!KIj1({LG$?*0X;s^Iz z@LMrpKRIt4l$b36U5a= zW=Sa4b?Zx)rN%o=5cK)Yi(2`X$J@)s*RAS%?CUj1I)}=V+l5Qh!tBA)E(O^f>)Bb< zgo)jxDAd}C3D8pu@iweS4hT2FI!iC2<ew?Eti1W-=CMkE8x45ZidRM5UpO5KuX3)zx+E(Lr z!j+pM&_h%fpwfWIR4v4hY98i5sO{^uW3C#pW30O-U6(D476B=*kx5vm660s7c{9I5 z_2jMMBJmp|=`DNdi&}`M{LOy0W!fu~#=P(aq;SoW7S@{qJ=A z@|+!HK;e@A;IaQvFzKf#&3h~SY}CZ{%SX$FgABY@e3{Yo_(mZB9|;r$z$xxh&y4Fm zSCT^j?BV9CcmHrFS={5d6{*Y84GsO3LUDBAL{YDioyPM$0sQdmw8+aWCxV_KIVi z0R(00F>roLUr>xL49@mRV!v{%^*>xfep%0GJ{YR$nf7(n`><4EtvUuEGpk2OYxLE#q~Pr^PTTxdGho+ zSW%148qm3(w^4WS476_WoRONMxT)~q3I`Hc`syNEB#gnS!7aVrd-r1B|AU%G-QH^d zvD!TDJ3R+meFg&+qt1IT&w=gn()dDKdYXU=r?-84f<)xC5HoypX2|2t*15y zlk-hS7?utl&i89M=KMh*K4$bqHGwY2z1P82-k$;Xy=sF2*BrK`hH?g)KlJ_W@;Q}i z(I(+I6gn+M?~q9^sHfT$mNT$yn^ma6C^H?DhNPP-Gyyi4*c=d<_I#g6LG20L2aDFy z#=gcSgjo|UIuzX8$Py-JR`Kx$-2FMw_tUWmdl^HFq%qlfKY_DY zrZ!F?mY6x}mMX`+jC%{`_f(hwv9EtDiJOc52l|$Uh3PFTETtbmLN4`}!oXjSS;dR= ze#sB=H=IJyOEfSg3yc3-TncQ{b_;evbu< z)buL_7xQu)Yw+05+8T8M*~I^1!Tf7#W-9Tbl!wy9G;=K=yNq9+!CLX=_uuXRuKUCdp+=m(L> zBWRzQ5$oCD%F$$z`tTwADT|hD-YaG769=v8s)mXd9kYV@+!BqtbQLi9jcJx~9JX}! zjJ*N8KtVG%9vL+Db)HMBPl1zR!>N$p(Ei1%gy;q)y#cnew(~n*Y%b?pw?u`&XI$0B zkbT^%I<^Z1@l(~FyuZ9enRA>X+ZF7UN(^!ZBw7VAEVVn>|KQBMLV`z?XflcB}s#JXz680ZsJq!80QS7gG+ zk$Fy{AtBYg1{#T~s;b&bU{uM7AZGW4`kZc3Ok@@p?@1VS-vf!6l^DYsm4J>DI*_!q ztI1*=XX_jK=5&#keN0@O+V?W^U{Bzb93wk-BoJmeKn@FMpB5OrersxFN4Icl&F3rx zMs)}W^7Wcod_RhDzD(Z8Xk7B$)etpcSUbIOc-=NJ zF{!$t#AhHPt03>$xyDEl@>LzlbO`zKtdKA4+ z@p$n}d8M#`$(p@98NSayxVty%n%BcB=J+V#~449#(WQMp#$tRkHQ-X+Uq)T~JUI z8_@n_xErABzSYCQGmUwSVLoWwn2x;Q@yl#ncK0MpC>^~jUh3nUa?xJ^$GD&_9th2` zW81*zUW53(5x{-o>7{PBiV9RUtkfrM5mPpw{qj(rE|Jb>2z~U;I+sxxe04VYAPL%5 zES!-3R-J^W`YA_{q&lN>FE>4;uV{B+O$FU(iGf)hXWmot63O=6)13_9hYdU0r+Z2N zsENp)gL{vA*b2{ER)%YG_-sA`^=z|f6}f9J()a)QSM5{ZdN8{`IXncNbC9weHtI~b zPF_SWXfVTcM@!_2h2K-2d~0}nuuMHL&Co9tcO#3qGxN)nzNx6mi~7z%fph&^pTc)O$<0x>yGY?&7q^0;u}W&s6w!dRx-G zO8MBNa7^1*jJRyk3x8^A?7K;5bHkb8G?0gSO5K~AHXYBMuxs4Uy=@j*6zB|d^ZB?V zdxQy&)T?o`MqT z^&1+A^8XQtSq@B9Ta9|3W55@=nRWb88p*}5npE~f z;zq#{6uWX)!K*-PXA?8OgS>#@m7k<(H5BL3iGO+h)G3%_;Jln0V>A2NQUy}JtsA%% z-MO)A6@Pr!4J5{rU+zi~;C|8g;~TvJm1?zZqg!Cz694lp4}eB-lYk3)+%1+=unY~! zLH}u=xgu}Ghk3~HPpJ0;;Ocj>Nf{*6H0eQ&(02y|&!I`tsi_)cmg8R=|HVE4y&ODV zoG&c$FLgv+Th`{<%rEn0pI`CY%PGv_8g++!`RD8dJYRk*o;s=%jpIyScC#P|-X$my~gjgb_tC zx23h=yoH3WQH{oBgVIsX(P&g>42jORY?r0ZTsaR-jO?}}|_LNhpPCrj)( zBn!)Ef!>Ep8apwq`}^DPg{MQ#tC|Vka%j-pImXPJa`kxfm0r6f)v*+mb@aU6qX2l3 z&tJuY+o|@3i&NeFhr8M32aR~@4J;q*j24?~$b0Qq1b7~9;LGgW!e1*N&Wj0*3h?FXU@*)**;h|nc`isY<@0L2tvJZgA$ z2HKz?Cmq)K$Y6!Y3&cWGdG6a-yYts)!_M76AAVevJIVHkkmmDGg$}z5YAT@~q%M4% zmL>C{QT#}5^U_SMa`g94xR`x?vzCf(@-UIoZq8;sudPnT^j+RxIDu@dCPM?`)GC}y z^wxn@dJ5T8?4zUaJ&lBwHX<$cSS|P5C!PC(kz1&lD50fsfA`6I`F8|{GezCSc;*kB zFQSWQpwnGs%2iIvLYGy0soT~^iRvTs^Sq4Cm&6YT4@<#_p?+y6+w(Tb3+)D&(bCS7 zy7e6)@7c2@BL#gb^hZ0-3TnZj3~cS*3f5_`bfH(AfTn_dZSCIqoF@8R-$#dnT-?Xh zB`*8Z0qxhtTH4Ft`YI1fKZw`SO4gw{0kw%mDx3)G(Z|;?RQov-bBP#kiLQLGAjDlI zGi}Vu-Wb*7Qah(g;= zQwOQ>pUJ3oIz1Df=09Va_MPq$XI&CrSS(AHFss!tOQwATZ}{^kW2AX%)3K#U{ZLCT zz?pTKg-)|a=8H3n=@Y$;qTh9U#nWCp z-saI3T3a1is7QrmzGs}l&fi?!yiDBlmymv?1w`lb=|^1IZ?_NCF$4O0*9?|vm=+J+ zJ9QpN*RS1bI!1p7ZIO0Kq~6<(<-vl=%0(0N*OL*7$1Qvg%0h}CTQ!976pnPu!JIJ& z-B`{ei};u~j}9LY36g=q*84<-Z=adoaxJfeJ2X3#d@hMv$286!uJ$JpN1n;gU1U{x z{;t2mvp42|E;ozS1+%i9On8qt?-ZE?vO>L%`nI`RlP||DuCKcb}*<0t+}SJkpq33Fa`gXA{tZ_Hq=10x~kMq;reOd)B7xlm8LD_rHo=}baJ$|_o0*V z_~oBrDSPENRJ@y0)HS$E<&GJtQWem;v)@a4dA{I?^6+8@{Q@cazQeiY6;oBC$W>_$ z=QWd|D{MWc(gP{VTE%xb>avzG=Vzcf%w`-?>NM}z2PHVo_CE8ZBmp;T^je(;qdbIN z$|qYlqWGX&J5z2OFa^(YV=JdQ@M-J$FnoW9uJw%P6{K%uY_40AM%?m#@(P4Y4;CYv zA%Vt2Ku1iYbNym89_TAEnKy5Yf9K$)qN=HfCp8#v8Lb62!W_g+J75*;KRkjbQ5VBZ zD2+cjj|io3vgYkw7a83aX_^WQ9SwI>T3e_Sh?lJ~-KZqHCh_C(VQbIo%c{gtPY;8* z4XQ0a4iZs+@|R+%^wj~USvv`QEtXeRy1jdmgu0u@9D2hIbK!hpyzC_nboMf5f{YQ!ps6yzCJaL9T7=`gO?5E`~r2E?Um8?xdvHkTlt2z20nHeL7Du=FrlAa zR~=~kYrU4kztQG`FW@$Bk$;bR{j;WxeOx5p{J0Y!)5u^3$ zi@Bskx~FO(jkqXuiY^c3PFfv?T5#D_M|6Dw8Si)YVqo}_6-G9KIXDA}2a+?#9JcD+ z8h=cQdmV#LJ@R|q^@c$W^?pSWRT^c15jQ1pa!lXJOnN`SSvt3HXkuy0yVrXBq^ew9 zWxB?;9G2I3fH>J{`rv^bn?kKWOV3kHR~9^pA?J66F9v-U&M@R)?6$UbdFJ;_V97CE zA>*54#ye(1al$L1>XEZ5)><@hmN}`0i&Y+rE;U5Cby9}yQTr?$@4AjtWs?VUq(AO6 zI6F!t?dUrvGF4BUR>NvT+v)RE<%(F=ttattZ_mMY zd@I2)%dACt{@#$*Ryrsh4OBd9xfi^boHL(7wvoBxa*zx>7Ko(^VNFTA0EgBefyi2% z5P4`KG<}_mdC1R;=;}n3c^6VTO!(YYjwvMnSgtbsxLwMoo@L2g0ldf8W*Oh#PN;9y zTUj*yd8_C%uE_bLxTVE+sn%-KyWA*_^TVaJ_2A6}`W>y${RP)T=*x@A89FDNA0P7)MycTx1Fkm!;q z|BW|G{W189Y-+xT|3`aQ7L^17MVp$kGi8>VTB9l1}nep8ni6VZZJsKzcObCrJx*V6u^_46qjS5!!-#FjVaG;N6yQuXSeqm7VOcuOs#r_V%5)*s`R4e zrQDIoeGM5T3t(E_no&uWuKuQQ|Tik{X(9Y$n4b>f^E3QLRnygET0D&HYPX?`P z$?O*1bBb~hJQD^eW^0O(HggJTFvxdXlX}j*g<}__>{Hri1;^iAbN2J?nWmSprrHU^ zR{T(i!atge6eJRu1Qy*R02S|nm1kO|IY@WKz;EY$z?hYy-0-kMGe8D#jW$S>&~Hoj;j zy7HBE6SCY>4y9Dpk;4LRrSBe+t5V76gpU6!(jya)mWnV>8C0$?rIwx$qyWq4&6MIGG2>C4N(0ST_sd z(Ka=H2CSM*gmgFz2ri-@D)Mf)CJuHg0R2TMO|#Tba{&SPT$KQ;4igw!tely7Rz+qq zt2lvGqF^9blL@7>f_%0uO+mbVJ)xWf(3BT}9q*Olo=n>fB+B>-56g;W#Muo@{xGJb zP>6()pOq^%JTp$j_BO=D$C*FQMl{+aH$R6grMgRw&pgK)#tg_Q1Jz%$msjThwpyiZ z~ literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/launch/moveit_planning_execution.launch b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/launch/moveit_planning_execution.launch new file mode 100644 index 0000000000..af5a15e896 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/launch/moveit_planning_execution.launch @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [/move_group/fake_controller_joint_states] + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/test_data/testdata_sequence.xml b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/test_data/testdata_sequence.xml new file mode 100644 index 0000000000..9699c5caad --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/test_data/testdata_sequence.xml @@ -0,0 +1,173 @@ + + + + + + + + 0.0 -0.785 0.0 -2.356 0.0 1.571 0.785 + + + + -0.022096 -0.753529 0.007612 -1.716165 0.0063464 0.962660 0.771123 + 0.2 0 0.8 0.924138 -0.382057 0.0 0.0 + -0.022096 -0.753529 0.007612 -1.716165 0.0063464 0.962660 0.771123 + + + + + -0.061035 -0.301221 0.410282 -1.665777 0.120602 1.389535 1.138547 + 0.4 0.2 0.7 0.924138 -0.382057 0.0 0.0 + -0.061035 -0.301221 0.410282 -1.665777 0.120602 1.389535 1.138547 + + + + + 0.0875228 -0.540765 0.770139 -1.990062 0.366596 1.582282 1.560837 + 0.2 0.4 0.6 0.924138 -0.382057 0.0 0.0 + 0.0875228 -0.540765 0.770139 -1.990062 0.366596 1.582282 1.560837 + + + + + 0.164988 -0.805223 0.304894 -2.020563 0.230321 1.247100 1.238191 + 0.2 0.2 0.7 0.924138 -0.382057 0.0 0.0 + 0.164988 -0.805223 0.304894 -2.020563 0.230321 1.247100 1.238191 + + + + + + + + panda_arm + panda_link8 + ZeroPose + P1 + 1.0 + 0.2 + + + + panda_arm + panda_link8 + P3 + P2 + 1.0 + 0.2 + + + + panda_arm + panda_link8 + P2 + P3 + 1.0 + 0.2 + + + + + + panda_arm + panda_link8 + P2 + P3 + 0.1 + 0.05 + + + + panda_arm + panda_link8 + P1 + P2 + 0.1 + 0.05 + + + + panda_arm + panda_link8 + P2 + P4 + 0.1 + 0.05 + + + + + + panda_arm + panda_link8 + P1 + P2 + P3 + 0.1 + 0.1 + + + + panda_arm + panda_link8 + P3 + P2 + P1 + 0.1 + 0.1 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/launch/test_context.launch b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/launch/test_context.launch new file mode 100644 index 0000000000..4c43af1420 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/launch/test_context.launch @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/testdata_deprecated.xml b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/testdata_deprecated.xml new file mode 100644 index 0000000000..65d6b388ce --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/testdata_deprecated.xml @@ -0,0 +1,434 @@ + + + + + + + + + 0.0 0.0 0.0 0.0 0.0 0.0 + + + 0 + + + + + + 0.5 0.0 0.0 0.0 0.0 0.0 + + + 0 + + + + + + 0.0 0.785398 0.785398 0.0 1.570796 0.0 + + + + + + 0.45 -0.1 0.62 0.0 0.0 0.0 1.0 + + + + + + 0.0 -0.52 1.13 0.0 -1.57 0.0 + + + 0 + + + + + + 0.0 -0.63 1.4 0.0 1.19 0.0 + + + 0 + + + + + + 0.463648 -0.418738 1.03505 0.0 -1.45379 -0.149488 + + + 0 + + + + + + 0.0 0.278259 2.11585 0.0 -1.83759 0.785398 + + + 0 + + + + + + 0.0 1.52001 1.13 0.0 -1.57 0.0 + + + 0 + + + + + + + 0.244979 0.333691 -1.48422 0.0 1.81791 -0.244979 + 0.4 0.1 0.6 0. 0. 0. 1.0 + + + 0 + + + + + + + 1.32582 0.333691 -1.48422 0.0 1.81791 -1.32582 + 0.1 0.4 0.7 0 0 0.923916 -0.382596 + + + 0 + + + + + + + 0.1 0.1 0.6 0 0 0 1.0 + + + 0 + + + + + + + -0.463648 -1.64103 -2.06227 0 0.421241 0.463648 + -0.2 0.1 0.6 0 0 0 1.0 + + + 0 + + + + + + + 0 0.4 0.5 0 0 0 1 + + + 0 + + + + + + 0.0 -0.0107869 -1.72665 0.0 1.71586 0.0 + 0.3 0.0 0.65 0.0 0.0 0.0 1.0 + + + 0 + + + + + + 0.300000001 0.0 0.65 0.0 0.0 0.0 1.0 + + + 0 + + + + + + 0.0 -0.010787 -1.72666 0.0 1.71586 0.0 + 0.300000001 0.0 0.650000001 0.0 0.0 0.0 1.0 + + + 0 + + + + + + 0.0 -1.56309 -1.72665 0.0 0.163561 0.0 + -0.3 0.0 0.65 0.0 0.0 0.0 1.0 + + + 0 + + + + + + 2.61799 -0.0107869 -1.72665 0.0 1.71586 -1.0472 + -0.25980762113533159 0.15 0.65 0 0 0.7071067811865475 0.7071067811865475 + + + 0 + + + + + + 0.0 0.0 0.65 0.0 0.0 0.0 1.0 + + + 0 + + + + + + 0.0 0.3 0.65 0.0 0.0 0.0 1.0 + + + 0 + + + + + + + 0.244979 0.333691 -1.48422 0.0 1.81791 -0.244979 + 0.4 0.1 0.7 0. 0. 0.923916 -0.382596 + + + 0 + + + + + + + 1.32582 0.333691 -1.48422 0.0 1.81791 -1.32582 + 0.3 0.2 0.7 0 0 0.923916 -0.382596 + + + 0 + + + + + + + -0.463648 -1.64103 -2.06227 0 0.421241 0.463648 + 0.2 0.1 0.7 0 0 0.923916 -0.382596 + + + 0 + + + + + + + + + manipulator + prbt_tcp + CIRCPose1 + CIRCAuxPose1 + CIRCPose6 + 0.05 + 0.05 + + + + + manipulator + prbt_tcp + CIRCPose4 + CIRCAuxPose3 + CIRCPose6 + 0.1 + 0.1 + + + + + manipulator + prbt_tcp + CIRCPose4 + CIRCAuxPose4 + CIRCPose6 + 0.1 + 0.1 + + + + + manipulator + prbt_tcp + CIRCPose4 + CIRCPose4_delta1 + CIRCPose4_delta2 + 0.1 + 0.1 + + + + + manipulator + prbt_tcp + CIRCPose4 + CIRCAuxPose4 + CIRCPose6 + 1.0 + 1.0 + + + + manipulator + prbt_tcp + CIRCPose4 + CIRCAuxPose3 + CIRCPose5 + 0.1 + 0.1 + + + + + manipulator + prbt_tcp + CIRCPose1 + CIRCAuxPose2 + CIRCAuxPose2 + CIRCPose2 + 0.05 + 0.05 + + + + + manipulator + prbt_tcp + CIRCPose7 + CIRCPose8 + CIRCPose9 + 0.1 + 0.1 + + + + + manipulator + prbt_tcp + CIRCPose4 + CIRCAuxPose3 + CIRCPose5 + 0.1 + 0.1 + + + + manipulator + prbt_tcp + CIRCPose4 + CIRCAuxPose4 + CIRCPose5 + 0.01 + 0.01 + + + + + + + + + manipulator + prbt_tcp + LINPose1 + LINPose2 + 0.4 + 0.3 + + + + manipulator + prbt_tcp + LINPose3 + LINPose4 + 0.2 + 0.2 + + + + manipulator + prbt_tcp + LINPose1 + LINPose1Opposite + 1.0 + 1.0 + + + + manipulator + prbt_tcp + LINPose1 + LINPose1 + 0.4 + 0.4 + + + + + + + + manipulator + prbt_tcp + ZeroPose + PTPJointValid + 1.0 + 1.0 + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/testdata_sequence.xml b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/testdata_sequence.xml new file mode 100644 index 0000000000..3b87ef0328 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/testdata_sequence.xml @@ -0,0 +1,227 @@ + + + + + + + + 0.0, 0.0, -0.4353981633974483, 0.0, -1.5700000000000003, 0.0 + + + + 0, -0.016763700542892668, -1.673499069949556, 0, -1.4848572841831293, 2.3561944901923377 + 0.3 0.0 0.5 0.923879532509 0.38268343237 0.0 0.0 + + + + 0.380506 0.731299 -0.960008 0.0 -1.450284 1.951302 + 0.5 0.2 0.4 0.707106 0.707106 0.0 0.0 + + + + 0.927295 0.708913 -1.343015 0.0 -1.089664 2.498091 + 0.3 0.4 0.3 0.707106 0.707106 0.0 0.0 + + 0.927295 0.708913 -1.343015 0.0 -1.089664 2.498091 + + + + + 0.588002 0.221990 -1.742660 0.0 -1.176941 2.158798 + 0.3 0.2 0.4 0.707106 0.707106 0.0 0.0 + + + + 0.0 + + + + 0.03 + + + + + + + manipulator + prbt_tcp + ZeroPose + P1 + 0.1 + 0.1 + + + + manipulator + prbt_tcp + P3 + P2 + 1.0 + 0.4 + + + + manipulator + prbt_tcp + P2 + P3 + 1.0 + 0.4 + + + + manipulator + prbt_tcp + P2 + P1 + 1.0 + 0.4 + + + + + + manipulator + prbt_tcp + P2 + P3 + 0.1 + 0.2 + + + + manipulator + prbt_tcp + P1 + P2 + 0.1 + 0.2 + + + + manipulator + prbt_tcp + P2 + P4 + 0.1 + 0.2 + + + + + + manipulator + prbt_tcp + P1 + P2 + P3 + 0.1 + 0.2 + + + + manipulator + prbt_tcp + P3 + P2 + P1 + 0.1 + 0.2 + + + + + + gripper + gripper_closed + gripper_open + + + gripper + gripper_open + gripper_closed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/testdata_with_gripper.xml b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/testdata_with_gripper.xml new file mode 100644 index 0000000000..cece30dc4b --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/testdata_with_gripper.xml @@ -0,0 +1,95 @@ + + + + + + + 0.0 0.0 0.0 0.0 0.0 0.0 + + + + 0.0 0.005583 -1.323096 0.0 -1.812912 -2.356194 + 0.3 0.0 0.5 0.707106 0.707106 0.0 0.0 + + + + 0.380506 0.752267 -0.595009 0.0 -1.794315 -1.975688 + 0.5 0.2 0.4 0.707106 0.707106 0.0 0.0 + + + + 0.927295 0.607232 -1.173008 0.0 -1.361351 -1.428899 + 0.3 0.4 0.3 0.707106 0.707106 0.0 0.0 + + + + + + + + manipulator + prbt_tcp + ZeroPose + P1 + 1.0 + 0.4 + + + + + + + manipulator + prbt_tcp + P1 + P2 + 0.1 + 0.2 + + + + + + manipulator + prbt_tcp + P3 + P2 + P1 + 0.1 + 0.2 + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_cartesian_limits_aggregator/test_cartesian_limit_all.yaml b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_cartesian_limits_aggregator/test_cartesian_limit_all.yaml new file mode 100644 index 0000000000..bd165e6ebc --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_cartesian_limits_aggregator/test_cartesian_limit_all.yaml @@ -0,0 +1,37 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2018 Pilz GmbH & Co. KG +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Pilz GmbH & Co. KG 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. + +cartesian_limits: + max_trans_vel: 1 + max_trans_acc: 2 + max_trans_dec: -3 + max_rot_vel: 4 diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_cartesian_limits_aggregator/test_cartesian_limit_only_vel.yaml b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_cartesian_limits_aggregator/test_cartesian_limit_only_vel.yaml new file mode 100644 index 0000000000..4ac9ff1ae8 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_cartesian_limits_aggregator/test_cartesian_limit_only_vel.yaml @@ -0,0 +1,34 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2018 Pilz GmbH & Co. KG +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Pilz GmbH & Co. KG 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. + +cartesian_limits: + max_trans_vel: 10 diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_valid_1.yaml b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_valid_1.yaml new file mode 100644 index 0000000000..dd953add3d --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_valid_1.yaml @@ -0,0 +1,52 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2018 Pilz GmbH & Co. KG +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Pilz GmbH & Co. KG 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. + +joint_limits: + prbt_joint_1: + has_position_limits: true + min_position: -2 + max_position: 2 + prbt_joint_2: + has_position_limits: false + min_position: -2 + max_position: 2 + prbt_joint_3: + has_velocity_limits: true + max_velocity: 1.1 + has_acceleration_limits: false + max_acceleration: 5.5 + prbt_joint_4: + has_acceleration_limits: true + max_acceleration: 5.5 + prbt_joint_5: + has_deceleration_limits: true + max_deceleration: -6.6 diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_violate_position_max.yaml b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_violate_position_max.yaml new file mode 100644 index 0000000000..7aecb01bc7 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_violate_position_max.yaml @@ -0,0 +1,37 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2018 Pilz GmbH & Co. KG +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Pilz GmbH & Co. KG 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. + +joint_limits: + prbt_joint_3: + has_position_limits: true + min_position: -1 + max_position: 4 diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_violate_position_min.yaml b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_violate_position_min.yaml new file mode 100644 index 0000000000..50612ed284 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_violate_position_min.yaml @@ -0,0 +1,37 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2018 Pilz GmbH & Co. KG +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Pilz GmbH & Co. KG 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. + +joint_limits: + prbt_joint_2: + has_position_limits: true + min_position: -4 + max_position: 2 diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_violate_velocity.yaml b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_violate_velocity.yaml new file mode 100644 index 0000000000..8373e05b28 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/test_data/unittest_joint_limits_aggregator_testdata/test_joint_limits_violate_velocity.yaml @@ -0,0 +1,36 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2018 Pilz GmbH & Co. KG +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Pilz GmbH & Co. KG 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. + +joint_limits: + prbt_joint_3: + has_velocity_limits: true + max_velocity: -90 diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/testpoints.py b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/testpoints.py new file mode 100755 index 0000000000..e0056728f3 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/testpoints.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python +# Software License Agreement (BSD License) +# +# Copyright (c) 2018 Pilz GmbH & Co. KG +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Pilz GmbH & Co. KG 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. + +from geometry_msgs.msg import Point +from pilz_robot_programming.robot import * +from pilz_robot_programming.commands import * +import math +import rospy + +__REQUIRED_API_VERSION__ = "1" + +robot_configs = {} +robot_configs['prbt'] = { + 'initJointPose': [0.0, 0.0, math.radians(-25), 0.0, -1.57, 0], + 'L': 0.2, + 'M': 0.1, + 'planning_group': 'manipulator', + 'target_link': 'prbt_tcp', + 'reference_frame': 'prbt_base', + 'default_or': from_euler(0, math.radians(180), math.radians(90)), + 'P1_position': Point(0.3, 0.0, 0.5), + 'P1_orientation': from_euler(0, math.radians(180), math.radians(135)) +} + +robot_configs['panda'] = { + 'initJointPose': [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785], + 'L': 0.2, + 'M': 0.1, + 'planning_group': 'panda_arm', + 'target_link': 'panda_link8', + 'reference_frame': 'panda_link0', + 'default_or': Quaternion(0.924, -0.382, 0.000, 0.000), + 'P1_position': Point(0.2, 0.0, 0.8) +} + + +def start_program(robot_name): + print("Executing " + __file__) + + test_sequence(**robot_configs[robot_name]) + +def test_sequence(initJointPose, L, M, planning_group, target_link, reference_frame, default_or, P1_position, P1_orientation): + r = Robot(__REQUIRED_API_VERSION__) + + r.move(Ptp(goal=initJointPose, planning_group=planning_group)) + + P1 = Pose(position=P1_position, orientation=P1_orientation) + + + P2 = Pose(position=Point(P1.position.x+L, P1.position.y+L, P1.position.z-M), orientation=default_or) + P3 = Pose(position=Point(P1.position.x, P1.position.y+2*L, P1.position.z-2*M), orientation=default_or) + P4 = Pose(position=Point(P1.position.x, P1.position.y+L, P1.position.z-M), orientation=default_or) + + ptp1 = Ptp(goal=P1, acc_scale=0.3, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) + ptp2 = Ptp(goal=P2, acc_scale=0.3, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) + ptp3 = Ptp(goal=P3, acc_scale=0.3, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) + ptp4 = Ptp(goal=P4, acc_scale=0.3, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) + lin1 = Lin(goal=P1, acc_scale=0.1, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) + lin2 = Lin(goal=P2, acc_scale=0.1, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) + lin3 = Lin(goal=P3, acc_scale=0.1, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) + lin4 = Lin(goal=P4, acc_scale=0.1, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) + + r.move(ptp1) #PTP_12 test + r.move(ptp2) #PTP_23 + r.move(ptp3) #PTP_34 + r.move(ptp4) #PTP_41 + r.move(ptp1) + + r.move(lin1) #LIN_12 + r.move(lin2) #LIN_23 + r.move(lin3) #LIN_34 + r.move(lin4) #LIN_41 + r.move(lin1) + + circ3_interim_2 = Circ(goal=P3, interim=P2.position, acc_scale=0.2, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) + circ1_center_2 = Circ(goal=P1, center=P2.position, acc_scale=0.2, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) + + for radius in [0, 0.1]: + r.move(Ptp(goal=initJointPose, planning_group=planning_group)) + + seq = Sequence() + seq.append(ptp1, blend_radius=radius) + seq.append(circ3_interim_2, blend_radius=radius) + seq.append(ptp2, blend_radius=radius) + seq.append(lin3, blend_radius=radius) + seq.append(circ1_center_2, blend_radius=radius) + seq.append(lin2, blend_radius=radius) + seq.append(ptp3) + + r.move(seq) + +if __name__ == "__main__": + # Init a ros node + rospy.init_node('robot_program_node') + + import sys + + robots = list(robot_configs.keys()) + + if(len(sys.argv) < 2): + print("Please specify the robot you want to use." + ', '.join('"{0}"'.format(r) for r in robots)) + sys.exit() + + + if(sys.argv[1] not in robots): + print("Robot " + sys.argv[1] + " not available. Use one of " + ', '.join('"{0}"'.format(r) for r in robots)) + sys.exit() + + + start_program(sys.argv[1]) + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_utils.cpp b/moveit_planners/pilz_industrial_motion_planner/test/test_utils.cpp new file mode 100644 index 0000000000..2c9b859e56 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_utils.cpp @@ -0,0 +1,1430 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "test_utils.h" + +pilz_industrial_motion_planner::JointLimitsContainer +testutils::createFakeLimits(const std::vector& joint_names) +{ + pilz_industrial_motion_planner::JointLimitsContainer container; + + for (const std::string& name : joint_names) + { + JointLimit limit; + limit.has_position_limits = true; + limit.max_position = 2.967; + limit.min_position = -2.967; + limit.has_velocity_limits = true; + limit.max_velocity = 1; + limit.has_acceleration_limits = true; + limit.max_acceleration = 0.5; + limit.has_deceleration_limits = true; + limit.max_deceleration = -1; + + container.addLimit(name, limit); + } + + return container; +} + +bool testutils::getExpectedGoalPose(const moveit::core::RobotModelConstPtr& robot_model, + const planning_interface::MotionPlanRequest& req, std::string& link_name, + Eigen::Isometry3d& goal_pose_expect) +{ + // ++++++++++++++++++++++++++++++++++ + // + Get goal from joint constraint + + // ++++++++++++++++++++++++++++++++++ + if (!req.goal_constraints.front().joint_constraints.empty()) + { + std::map goal_joint_position; + + // initializing all joints of the model + for (const auto& joint_name : robot_model->getVariableNames()) + { + goal_joint_position[joint_name] = 0; + } + + for (const auto& joint_item : req.goal_constraints.front().joint_constraints) + { + goal_joint_position[joint_item.joint_name] = joint_item.position; + } + + link_name = robot_model->getJointModelGroup(req.group_name)->getSolverInstance()->getTipFrame(); + + if (!computeLinkFK(robot_model, link_name, goal_joint_position, goal_pose_expect)) + { + std::cerr << "Failed to compute forward kinematics for link in goal " + "constraints \n"; + return false; + } + return true; + } + + // ++++++++++++++++++++++++++++++++++++++ + // + Get goal from cartesian constraint + + // ++++++++++++++++++++++++++++++++++++++ + // TODO frame id + link_name = req.goal_constraints.front().position_constraints.front().link_name; + geometry_msgs::Pose goal_pose_msg; + goal_pose_msg.position = + req.goal_constraints.front().position_constraints.front().constraint_region.primitive_poses.front().position; + goal_pose_msg.orientation = req.goal_constraints.front().orientation_constraints.front().orientation; + normalizeQuaternion(goal_pose_msg.orientation); + tf2::convert(goal_pose_msg, goal_pose_expect); + return true; +} + +bool testutils::isGoalReached(const trajectory_msgs::JointTrajectory& trajectory, + const std::vector& goal, + const double joint_position_tolerance, const double joint_velocity_tolerance) +{ + trajectory_msgs::JointTrajectoryPoint last_point = trajectory.points.back(); + + for (unsigned int i = 0; i < trajectory.joint_names.size(); ++i) + { + if (fabs(last_point.velocities.at(i)) > joint_velocity_tolerance) + { + std::cerr << "[ Fail ] goal has non zero velocity." + << " Joint Name: " << trajectory.joint_names.at(i) << "; Velocity: " << last_point.velocities.at(i) + << std::endl; + return false; + } + + for (const auto& joint_goal : goal) + { + if (trajectory.joint_names.at(i) == joint_goal.joint_name) + { + if (fabs(last_point.positions.at(i) - joint_goal.position) > joint_position_tolerance) + { + std::cerr << "[ Fail ] goal position not reached." + << " Joint Name: " << trajectory.joint_names.at(i) + << "; Actual Position: " << last_point.positions.at(i) + << "; Expected Position: " << joint_goal.position << std::endl; + return false; + } + } + } + } + + return true; +} + +bool testutils::isGoalReached(const moveit::core::RobotModelConstPtr& robot_model, + const trajectory_msgs::JointTrajectory& trajectory, + const planning_interface::MotionPlanRequest& req, const double pos_tolerance, + const double orientation_tolerance) +{ + std::string link_name; + Eigen::Isometry3d goal_pose_expect; + if (!testutils::getExpectedGoalPose(robot_model, req, link_name, goal_pose_expect)) + { + return false; + } + + // compute the actual goal pose in model frame + trajectory_msgs::JointTrajectoryPoint last_point = trajectory.points.back(); + Eigen::Isometry3d goal_pose_actual; + std::map joint_state; + + // initializing all joints of the model + for (const auto& joint_name : robot_model->getVariableNames()) + { + joint_state[joint_name] = 0; + } + + for (std::size_t i = 0; i < trajectory.joint_names.size(); ++i) + { + joint_state[trajectory.joint_names.at(i)] = last_point.positions.at(i); + } + + if (!computeLinkFK(robot_model, link_name, joint_state, goal_pose_actual)) + { + std::cerr << "[ Fail ] forward kinematics computation failed for link: " << link_name << std::endl; + } + + auto actual_rotation{ goal_pose_actual.rotation() }; + auto expected_rotation{ goal_pose_expect.rotation() }; + auto rot_diff{ actual_rotation - expected_rotation }; + if (rot_diff.norm() > orientation_tolerance) + { + std::cout << "\nOrientation difference = " << rot_diff.norm() << " (eps=" << orientation_tolerance << ")" + << "\n### Expected goal orientation: ### \n" + << expected_rotation << std::endl + << "### Actual goal orientation ### \n" + << actual_rotation << std::endl; + return false; + } + + auto actual_position{ goal_pose_actual.translation() }; + auto expected_position{ goal_pose_expect.translation() }; + auto pos_diff{ actual_position - expected_position }; + if (pos_diff.norm() > pos_tolerance) + { + std::cout << "\nPosition difference = " << pos_diff.norm() << " (eps=" << pos_tolerance << ")" + << "\n### Expected goal position: ### \n" + << expected_position << std::endl + << "### Actual goal position ### \n" + << actual_position << std::endl; + return false; + } + + return true; +} + +bool testutils::isGoalReached(const moveit::core::RobotModelConstPtr& robot_model, + const trajectory_msgs::JointTrajectory& trajectory, + const planning_interface::MotionPlanRequest& req, const double tolerance) +{ + return isGoalReached(robot_model, trajectory, req, tolerance, tolerance); +} + +bool testutils::checkCartesianLinearity(const moveit::core::RobotModelConstPtr& robot_model, + const trajectory_msgs::JointTrajectory& trajectory, + const planning_interface::MotionPlanRequest& req, + const double translation_norm_tolerance, const double rot_axis_norm_tolerance, + const double rot_angle_tolerance) +{ + std::string link_name; + Eigen::Isometry3d goal_pose_expect; + if (!testutils::getExpectedGoalPose(robot_model, req, link_name, goal_pose_expect)) + { + return false; + } + + // compute start pose + robot_state::RobotState rstate(robot_model); + rstate.setToDefaultValues(); + moveit::core::jointStateToRobotState(req.start_state.joint_state, rstate); + Eigen::Isometry3d start_pose = rstate.getFrameTransform(link_name); + + // start goal angle axis + Eigen::AngleAxisd start_goal_aa(start_pose.rotation().transpose() * goal_pose_expect.rotation()); + + // check the linearity + for (trajectory_msgs::JointTrajectoryPoint way_point : trajectory.points) + { + Eigen::Isometry3d way_point_pose; + std::map way_point_joint_state; + + // initializing all joints of the model + for (const auto& joint_name : robot_model->getVariableNames()) + { + way_point_joint_state[joint_name] = 0; + } + + for (std::size_t i = 0; i < trajectory.joint_names.size(); ++i) + { + way_point_joint_state[trajectory.joint_names.at(i)] = way_point.positions.at(i); + } + + if (!computeLinkFK(robot_model, link_name, way_point_joint_state, way_point_pose)) + { + std::cerr << "Failed to compute forward kinematics for link in goal " + "constraints \n"; + return false; + } + + // translational linearity + Eigen::Vector3d goal_start_translation = goal_pose_expect.translation() - start_pose.translation(); + // https://de.wikipedia.org/wiki/Geradengleichung + // Determined form of a straight line in 3D space + if (fabs((goal_start_translation.cross(way_point_pose.translation()) - + goal_start_translation.cross(start_pose.translation())) + .norm()) > fabs(translation_norm_tolerance)) + { + std::cout << "Translational linearity is violated. \n" + << "goal tanslation: " << goal_pose_expect.translation() << std::endl + << "start translation: " << start_pose.translation() << std::endl + << "acutual translation " << way_point_pose.translation() << std::endl; + return false; + } + + if (!checkSLERP(start_pose, goal_pose_expect, way_point_pose, rot_axis_norm_tolerance)) + { + return false; + } + } + + return true; +} + +bool testutils::checkSLERP(const Eigen::Isometry3d& start_pose, const Eigen::Isometry3d& goal_pose, + const Eigen::Isometry3d& wp_pose, const double rot_axis_norm_tolerance, + const double rot_angle_tolerance) +{ + // rotational linearity + // start way point angle axis + Eigen::AngleAxisd start_goal_aa(start_pose.rotation().transpose() * goal_pose.rotation()); + Eigen::AngleAxisd start_wp_aa(start_pose.rotation().transpose() * wp_pose.rotation()); + + // parallel rotation axis + // it is possible the axis opposite is + // if the angle is zero, axis is arbitrary + if (!(((start_goal_aa.axis() - start_wp_aa.axis()).norm() < fabs(rot_axis_norm_tolerance)) || + ((start_goal_aa.axis() + start_wp_aa.axis()).norm() < fabs(rot_axis_norm_tolerance)) || + (fabs(start_wp_aa.angle()) < fabs(rot_angle_tolerance)))) + { + std::cout << "Rotational linearity is violated. \n" + << std::endl + << "start goal angle: " << start_goal_aa.angle() << "; axis: " << std::endl + << start_goal_aa.axis() << std::endl + << "start waypoint angle: " << start_wp_aa.angle() << "; axis: " << std::endl + << start_wp_aa.axis() << std::endl; + + return false; + } + + return true; +} + +bool testutils::computeLinkFK(const moveit::core::RobotModelConstPtr& robot_model, const std::string& link_name, + const std::map& joint_state, Eigen::Isometry3d& pose) +{ + // create robot state + robot_state::RobotState rstate(robot_model); + rstate.setToDefaultValues(); + + // check the reference frame of the target pose + if (!rstate.knowsFrameTransform(link_name)) + { + ROS_ERROR_STREAM("The target link " << link_name << " is not known by robot."); + return false; + } + + // set the joint positions + try + { + rstate.setVariablePositions(joint_state); + } + catch (const std::exception& e) + { + std::cerr << e.what() << '\n'; + return false; + } + + // update the frame + rstate.update(); + pose = rstate.getFrameTransform(link_name); + + return true; +} + +bool testutils::isVelocityBounded(const trajectory_msgs::JointTrajectory& trajectory, + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits) +{ + for (const auto& point : trajectory.points) + { + for (std::size_t i = 0; i < point.velocities.size(); ++i) + { + if (fabs(point.velocities.at(i)) > fabs(joint_limits.getLimit(trajectory.joint_names.at(i)).max_velocity)) + { + std::cerr << "[ Fail ] Joint velocity limit violated in " << i << "th waypoint of joint: " + << " Joint Name: " << trajectory.joint_names.at(i) << "; Position: " << point.positions.at(i) + << "; Velocity: " << point.velocities.at(i) << "; Acceleration: " << point.accelerations.at(i) + << "; Time from start: " << point.time_from_start.toSec() + << "; Velocity Limit: " << joint_limits.getLimit(trajectory.joint_names.at(i)).max_velocity + << std::endl; + + return false; + } + } + } + + return true; +} + +bool testutils::isTrajectoryConsistent(const trajectory_msgs::JointTrajectory& trajectory) +{ + for (const auto& point : trajectory.points) + { + if (trajectory.joint_names.size() != point.positions.size() || + trajectory.joint_names.size() != point.velocities.size() || + trajectory.joint_names.size() != point.accelerations.size()) + { + return false; + } + } + + // TODO check value is consistant (time, position, velocity, acceleration) + + return true; +} + +bool testutils::isAccelerationBounded(const trajectory_msgs::JointTrajectory& trajectory, + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits) +{ + for (const auto& point : trajectory.points) + { + for (std::size_t i = 0; i < point.velocities.size(); ++i) + { + // deceleration + if (point.velocities.at(i) * point.accelerations.at(i) <= 0) + { + if (fabs(point.accelerations.at(i)) > fabs(joint_limits.getLimit(trajectory.joint_names.at(i)).max_deceleration)) + { + std::cerr << "[ Fail ] Deceleration limit violated of joint: " << trajectory.joint_names.at(i) + << ": Position: " << point.positions.at(i) << "; Velocity: " << point.velocities.at(i) + << "; Acceleration: " << point.accelerations.at(i) + << "; Time from start: " << point.time_from_start.toSec() + << ". Deceleration Limit: " << joint_limits.getLimit(trajectory.joint_names.at(i)).max_deceleration + << std::endl; + return false; + } + } + // acceleration + else + { + if (fabs(point.accelerations.at(i)) > fabs(joint_limits.getLimit(trajectory.joint_names.at(i)).max_acceleration)) + { + std::cerr << "[ Fail ] Acceleration limit violated of joint: " << trajectory.joint_names.at(i) + << ": Position: " << point.positions.at(i) << "; Velocity: " << point.velocities.at(i) + << "; Acceleration: " << point.accelerations.at(i) + << "; Time from start: " << point.time_from_start.toSec() + << ". Acceleration Limit: " << joint_limits.getLimit(trajectory.joint_names.at(i)).max_acceleration + << std::endl; + + return false; + } + } + } + } + + return true; +} + +bool testutils::isPositionBounded(const trajectory_msgs::JointTrajectory& trajectory, + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits) +{ + for (const auto& point : trajectory.points) + { + for (std::size_t i = 0; i < point.positions.size(); ++i) + { + if (point.positions.at(i) > joint_limits.getLimit(trajectory.joint_names.at(i)).max_position || + point.positions.at(i) < joint_limits.getLimit(trajectory.joint_names.at(i)).min_position) + { + std::cerr << "[ Fail ] Joint position limit violated in " << i << "th waypoint of joint: " + << " Joint Name: " << trajectory.joint_names.at(i) << "; Position: " << point.positions.at(i) + << "; Velocity: " << point.velocities.at(i) << "; Acceleration: " << point.accelerations.at(i) + << "; Time from start: " << point.time_from_start.toSec() + << "; Max Position: " << joint_limits.getLimit(trajectory.joint_names.at(i)).max_position + << "; Min Position: " << joint_limits.getLimit(trajectory.joint_names.at(i)).min_position + << std::endl; + + return false; + } + } + } + + return true; +} + +bool testutils::checkJointTrajectory(const trajectory_msgs::JointTrajectory& trajectory, + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits) +{ + if (!testutils::isTrajectoryConsistent(trajectory)) + { + std::cout << "Joint trajectory is not consistent." << std::endl; + return false; + } + if (!testutils::isPositionBounded(trajectory, joint_limits)) + { + std::cout << "Joint poisiton violated the limits." << std::endl; + return false; + } + if (!testutils::isVelocityBounded(trajectory, joint_limits)) + { + std::cout << "Joint velocity violated the limits." << std::endl; + return false; + } + if (!testutils::isAccelerationBounded(trajectory, joint_limits)) + { + std::cout << "Joint acceleration violated the limits." << std::endl; + return false; + } + + return true; +} + +::testing::AssertionResult testutils::hasStrictlyIncreasingTime(const robot_trajectory::RobotTrajectoryPtr& trajectory) +{ + // Check for strictly positively increasing time steps + for (unsigned int i = 1; i < trajectory->getWayPointCount(); ++i) + { + if (trajectory->getWayPointDurationFromPrevious(i) <= 0.0) + { + return ::testing::AssertionFailure() + << "Waypoint " << (i) << " has " << trajectory->getWayPointDurationFromPrevious(i) + << " time between itself and its predecessor." + << " Total points in trajectory: " << trajectory->getWayPointCount() << "."; + } + } + + return ::testing::AssertionSuccess(); +} + +void testutils::createDummyRequest(const moveit::core::RobotModelConstPtr& robot_model, + const std::string& planning_group, planning_interface::MotionPlanRequest& req) +{ + // valid motion plan request with goal in joint space + req.group_name = planning_group; + req.max_velocity_scaling_factor = 1.0; + req.max_acceleration_scaling_factor = 1.0; + robot_state::RobotState rstate(robot_model); + rstate.setToDefaultValues(); + moveit::core::robotStateToRobotStateMsg(rstate, req.start_state, false); +} + +void testutils::createPTPRequest(const std::string& planning_group, const robot_state::RobotState& start_state, + const robot_state::RobotState& goal_state, planning_interface::MotionPlanRequest& req) +{ + // valid motion plan request with goal in joint space + req.planner_id = "PTP"; + req.group_name = planning_group; + req.max_velocity_scaling_factor = 0.5; + req.max_acceleration_scaling_factor = 0.5; + // start state + moveit::core::robotStateToRobotStateMsg(start_state, req.start_state, false); + // goal state + req.goal_constraints.push_back(kinematic_constraints::constructGoalConstraints( + goal_state, goal_state.getRobotModel()->getJointModelGroup(planning_group))); +} + +bool testutils::toTCPPose(const moveit::core::RobotModelConstPtr& robot_model, const std::string& link_name, + const std::vector& joint_values, geometry_msgs::Pose& pose, + const std::string& joint_prefix) +{ + { + std::map joint_state; + auto joint_values_it = joint_values.begin(); + + // initializing all joints of the model + for (const auto& joint_name : robot_model->getVariableNames()) + { + joint_state[joint_name] = 0; + } + + for (std::size_t i = 0; i < joint_values.size(); ++i) + { + joint_state[testutils::getJointName(i + 1, joint_prefix)] = *joint_values_it; + ++joint_values_it; + } + + Eigen::Isometry3d eig_pose; + if (!testutils::computeLinkFK(robot_model, link_name, joint_state, eig_pose)) + { + return false; + } + tf2::convert(eig_pose, pose); + return true; + } +} + +bool testutils::checkOriginalTrajectoryAfterBlending(const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, + const pilz_industrial_motion_planner::TrajectoryBlendResponse& res, + const double time_tolerance) +{ + for (std::size_t i = 0; i < res.first_trajectory->getWayPointCount(); ++i) + { + for (const std::string& joint_name : + res.first_trajectory->getWayPoint(i).getJointModelGroup(req.group_name)->getActiveJointModelNames()) + { + // check joint position + if (res.first_trajectory->getWayPoint(i).getVariablePosition(joint_name) != + req.first_trajectory->getWayPoint(i).getVariablePosition(joint_name)) + { + std::cout << i << "th position of the first trajectory is not same." << std::endl; + return false; + } + + // check joint velocity + if (res.first_trajectory->getWayPoint(i).getVariableVelocity(joint_name) != + req.first_trajectory->getWayPoint(i).getVariableVelocity(joint_name)) + { + std::cout << i << "th velocity of the first trajectory is not same." << std::endl; + return false; + } + + // check joint acceleration + if (res.first_trajectory->getWayPoint(i).getVariableAcceleration(joint_name) != + req.first_trajectory->getWayPoint(i).getVariableAcceleration(joint_name)) + { + std::cout << i << "th acceleration of the first trajectory is not same." << std::endl; + return false; + } + } + + // check time from start + if (res.first_trajectory->getWayPointDurationFromStart(i) != req.first_trajectory->getWayPointDurationFromStart(i)) + { + std::cout << i << "th time_from_start of the first trajectory is not same." << std::endl; + return false; + } + } + + size_t size_second = res.second_trajectory->getWayPointCount(); + size_t size_second_original = req.second_trajectory->getWayPointCount(); + for (std::size_t i = 0; i < size_second; ++i) + { + for (const std::string& joint_name : res.second_trajectory->getWayPoint(size_second - i - 1) + .getJointModelGroup(req.group_name) + ->getActiveJointModelNames()) + { + // check joint position + if (res.second_trajectory->getWayPoint(size_second - i - 1).getVariablePosition(joint_name) != + req.second_trajectory->getWayPoint(size_second_original - i - 1).getVariablePosition(joint_name)) + { + std::cout << i - 1 << "th position of the second trajectory is not same." << std::endl; + return false; + } + + // check joint velocity + if (res.second_trajectory->getWayPoint(size_second - i - 1).getVariableVelocity(joint_name) != + req.second_trajectory->getWayPoint(size_second_original - i - 1).getVariableVelocity(joint_name)) + { + std::cout << i - 1 << "th position of the second trajectory is not same." << std::endl; + return false; + } + + // check joint acceleration + if (res.second_trajectory->getWayPoint(size_second - i - 1).getVariableAcceleration(joint_name) != + req.second_trajectory->getWayPoint(size_second_original - i - 1).getVariableAcceleration(joint_name)) + { + std::cout << i - 1 << "th position of the second trajectory is not same." << std::endl; + return false; + } + } + + // check time from start + if (i < size_second - 1) + { + if (fabs((res.second_trajectory->getWayPointDurationFromStart(size_second - i - 1) - + res.second_trajectory->getWayPointDurationFromStart(size_second - i - 2)) - + (req.second_trajectory->getWayPointDurationFromStart(size_second_original - i - 1) - + req.second_trajectory->getWayPointDurationFromStart(size_second_original - i - 2))) > time_tolerance) + { + std::cout << size_second - i - 1 << "th time from start of the second trajectory is not same." + << res.second_trajectory->getWayPointDurationFromStart(size_second - i - 1) << ", " + << res.second_trajectory->getWayPointDurationFromStart(size_second - i - 2) << ", " + << req.second_trajectory->getWayPointDurationFromStart(size_second_original - i - 1) << ", " + << req.second_trajectory->getWayPointDurationFromStart(size_second_original - i - 2) << std::endl; + return false; + } + } + else + { + if (fabs((res.second_trajectory->getWayPointDurationFromStart(size_second - i - 1)) - + (req.second_trajectory->getWayPointDurationFromStart(size_second_original - i - 1) - + req.second_trajectory->getWayPointDurationFromStart(size_second_original - i - 2))) > time_tolerance) + { + std::cout << size_second - i - 1 << "th time from start of the second trajectory is not same." + << res.second_trajectory->getWayPointDurationFromStart(size_second - i - 1) << ", " + << req.second_trajectory->getWayPointDurationFromStart(size_second_original - i - 1) - + req.second_trajectory->getWayPointDurationFromStart(size_second_original - i - 2) + << std::endl; + return false; + } + } + } + + return true; +} + +bool testutils::checkBlendingJointSpaceContinuity(const pilz_industrial_motion_planner::TrajectoryBlendResponse& res, + double joint_velocity_tolerance, double joint_accleration_tolerance) +{ + // convert to msgs + moveit_msgs::RobotTrajectory first_traj, blend_traj, second_traj; + res.first_trajectory->getRobotTrajectoryMsg(first_traj); + res.blend_trajectory->getRobotTrajectoryMsg(blend_traj); + res.second_trajectory->getRobotTrajectoryMsg(second_traj); + + // check the continuity between first trajectory and blend trajectory + trajectory_msgs::JointTrajectoryPoint first_end, blend_start; + first_end = first_traj.joint_trajectory.points.back(); + blend_start = blend_traj.joint_trajectory.points.front(); + + // check the dimensions + if (first_end.positions.size() != blend_start.positions.size() || + first_end.velocities.size() != blend_start.velocities.size() || + first_end.accelerations.size() != blend_start.accelerations.size()) + { + std::cout << "Different sizes of the position/velocity/acceleration " + "between first trajectory and blend trajectory." + << std::endl; + return false; + } + + // check the velocity and acceleration + for (std::size_t i = 0; i < first_end.positions.size(); ++i) + { + double blend_start_velo = + (blend_start.positions.at(i) - first_end.positions.at(i)) / blend_start.time_from_start.toSec(); + if (fabs(blend_start_velo - blend_start.velocities.at(i)) > joint_velocity_tolerance) + { + std::cout << "Velocity computed from positions are different from the " + "value in trajectory." + << std::endl + << "position: " << blend_start.positions.at(i) << "; " << first_end.positions.at(i) + << "computed: " << blend_start_velo << "; " + << "in trajectory: " << blend_start.velocities.at(i) << std::endl; + return false; + } + + double blend_start_acc = (blend_start_velo - first_end.velocities.at(i)) / blend_start.time_from_start.toSec(); + if (fabs(blend_start_acc - blend_start.accelerations.at(i)) > joint_velocity_tolerance) + { + std::cout << "Acceleration computed from positions/velocities are " + "different from the value in trajectory." + << std::endl + << "computed: " << blend_start_acc << "; " + << "in trajectory: " << blend_start.accelerations.at(i) << std::endl; + return false; + } + } + + // check the continuity between blend trajectory and second trajectory + trajectory_msgs::JointTrajectoryPoint blend_end, second_start; + blend_end = blend_traj.joint_trajectory.points.back(); + second_start = second_traj.joint_trajectory.points.front(); + + // check the dimensions + if (blend_end.positions.size() != second_start.positions.size() || + blend_end.velocities.size() != second_start.velocities.size() || + blend_end.accelerations.size() != second_start.accelerations.size()) + { + std::cout << "Different sizes of the position/velocity/acceleration " + "between first trajectory and blend trajectory." + << std::endl + << blend_end.positions.size() << ", " << second_start.positions.size() << std::endl + << blend_end.velocities.size() << ", " << second_start.positions.size() << std::endl + << blend_end.accelerations.size() << ", " << second_start.accelerations.size() << std::endl; + return false; + } + + // check the velocity and acceleration + for (std::size_t i = 0; i < blend_end.positions.size(); ++i) + { + double second_start_velo = + (second_start.positions.at(i) - blend_end.positions.at(i)) / second_start.time_from_start.toSec(); + if (fabs(second_start_velo - second_start.velocities.at(i)) > joint_accleration_tolerance) + { + std::cout << "Velocity computed from positions are different from the " + "value in trajectory." + << std::endl + << "computed: " << second_start_velo << "; " + << "in trajectory: " << second_start.velocities.at(i) << std::endl; + return false; + } + + double second_start_acc = (second_start_velo - blend_end.velocities.at(i)) / second_start.time_from_start.toSec(); + if (fabs(second_start_acc - second_start.accelerations.at(i)) > joint_accleration_tolerance) + { + std::cout << "Acceleration computed from positions/velocities are " + "different from the value in trajectory." + << std::endl + << "computed: " << second_start_acc << "; " + << "in trajectory: " << second_start.accelerations.at(i) << std::endl; + return false; + } + } + + return true; +} + +bool testutils::checkBlendingCartSpaceContinuity(const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, + const pilz_industrial_motion_planner::TrajectoryBlendResponse& res, + const pilz_industrial_motion_planner::LimitsContainer& planner_limits) +{ + // sampling time + double duration = res.blend_trajectory->getWayPointDurationFromPrevious(res.blend_trajectory->getWayPointCount() - 1); + if (duration == 0.0) + { + std::cout << "Cannot perform check of cartesian space continuity with " + "sampling time 0.0" + << std::endl; + return false; + } + + // limits + double max_trans_velo = planner_limits.getCartesianLimits().getMaxTranslationalVelocity(); + double max_trans_acc = planner_limits.getCartesianLimits().getMaxTranslationalAcceleration(); + double max_rot_velo = planner_limits.getCartesianLimits().getMaxRotationalVelocity(); + double max_rot_acc = max_trans_acc / max_trans_velo * max_rot_velo; + + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // +++ check the connection points between three trajectories +++ + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + // connection points + Eigen::Isometry3d pose_first_end, pose_first_end_1, pose_blend_start, pose_blend_start_1, pose_blend_end, + pose_blend_end_1, pose_second_start, pose_second_start_1; + // one sample before last point of first trajectory + pose_first_end_1 = res.first_trajectory->getWayPointPtr(res.first_trajectory->getWayPointCount() - 2) + ->getFrameTransform(req.link_name); + // last point of first trajectory + pose_first_end = res.first_trajectory->getLastWayPointPtr()->getFrameTransform(req.link_name); + // first point of blend trajectory + pose_blend_start = res.blend_trajectory->getFirstWayPointPtr()->getFrameTransform(req.link_name); + // second point of blend trajectory + pose_blend_start_1 = res.blend_trajectory->getWayPointPtr(1)->getFrameTransform(req.link_name); + // one sample before last point of blend trajectory + pose_blend_end_1 = res.blend_trajectory->getWayPointPtr(res.blend_trajectory->getWayPointCount() - 2) + ->getFrameTransform(req.link_name); + // last point of blend trajectory + pose_blend_end = res.blend_trajectory->getLastWayPointPtr()->getFrameTransform(req.link_name); + // first point of second trajectory + pose_second_start = res.second_trajectory->getFirstWayPointPtr()->getFrameTransform(req.link_name); + // second point of second trajectory + pose_second_start_1 = res.second_trajectory->getWayPointPtr(1)->getFrameTransform(req.link_name); + + // std::cout << "### sample duration: " << duration << " ###" << std::endl; + // std::cout << "### end pose of first trajectory ###" << std::endl; + // std::cout << pose_first_end.matrix() << std::endl; + // std::cout << "### start pose of blend trajectory ###" << std::endl; + // std::cout << pose_blend_start.matrix() << std::endl; + // std::cout << "### end pose of blend trajectory ###" << std::endl; + // std::cout << pose_blend_end.matrix() << std::endl; + // std::cout << "### start pose of second trajectory ###" << std::endl; + // std::cout << pose_second_start.matrix() << std::endl; + + // std::cout << "### v_1 ###" << std::endl; + // std::cout << v_1 << std::endl; + // std::cout << "### w_1 ###" << std::endl; + // std::cout << w_1 << std::endl; + // std::cout << "### v_2 ###" << std::endl; + // std::cout << v_2 << std::endl; + // std::cout << "### w_2 ###" << std::endl; + // std::cout << w_2 << std::endl; + // std::cout << "### v_3 ###" << std::endl; + // std::cout << v_3 << std::endl; + // std::cout << "### w_3 ###" << std::endl; + // std::cout << w_3 << std::endl; + + // check the connection points between first trajectory and blend trajectory + Eigen::Vector3d v_1, w_1, v_2, w_2, v_3, w_3; + computeCartVelocity(pose_first_end_1, pose_first_end, duration, v_1, w_1); + computeCartVelocity(pose_first_end, pose_blend_start, duration, v_2, w_2); + computeCartVelocity(pose_blend_start, pose_blend_start_1, duration, v_3, w_3); + + // translational velocity + if (v_2.norm() > max_trans_velo) + { + std::cout << "Translational velocity between first trajectory and blend " + "trajectory exceeds the limit." + << "Actual velocity (norm): " << v_2.norm() << "; " + << "Limits: " << max_trans_velo << std::endl; + } + // rotational velocity + if (w_2.norm() > max_rot_velo) + { + std::cout << "Rotational velocity between first trajectory and blend " + "trajectory exceeds the limit." + << "Actual velocity (norm): " << w_2.norm() << "; " + << "Limits: " << max_rot_velo << std::endl; + } + // translational acceleration + Eigen::Vector3d a_1 = (v_2 - v_1) / duration; + Eigen::Vector3d a_2 = (v_3 - v_2) / duration; + if (a_1.norm() > max_trans_acc || a_2.norm() > max_trans_acc) + { + std::cout << "Translational acceleration between first trajectory and " + "blend trajectory exceeds the limit." + << "Actual acceleration (norm): " << a_1.norm() << ", " << a_1.norm() << "; " + << "Limits: " << max_trans_acc << std::endl; + } + + // rotational acceleration + a_1 = (w_2 - w_1) / duration; + a_2 = (w_3 - w_2) / duration; + if (a_1.norm() > max_rot_acc || a_2.norm() > max_rot_acc) + { + std::cout << "Rotational acceleration between first trajectory and blend " + "trajectory exceeds the limit." + << "Actual acceleration (norm): " << a_1.norm() << ", " << a_1.norm() << "; " + << "Limits: " << max_rot_acc << std::endl; + } + + computeCartVelocity(pose_blend_end_1, pose_blend_end, duration, v_1, w_1); + computeCartVelocity(pose_blend_end, pose_second_start, duration, v_2, w_2); + computeCartVelocity(pose_second_start, pose_second_start_1, duration, v_3, w_3); + + if (v_2.norm() > max_trans_velo) + { + std::cout << "Translational velocity between blend trajectory and second " + "trajectory exceeds the limit." + << "Actual velocity (norm): " << v_2.norm() << "; " + << "Limits: " << max_trans_velo << std::endl; + } + if (w_2.norm() > max_rot_velo) + { + std::cout << "Rotational velocity between blend trajectory and second " + "trajectory exceeds the limit." + << "Actual velocity (norm): " << w_2.norm() << "; " + << "Limits: " << max_rot_velo << std::endl; + } + a_1 = (v_2 - v_1) / duration; + a_2 = (v_3 - v_2) / duration; + if (a_1.norm() > max_trans_acc || a_2.norm() > max_trans_acc) + { + std::cout << "Translational acceleration between blend trajectory and " + "second trajectory exceeds the limit." + << "Actual acceleration (norm): " << a_1.norm() << ", " << a_1.norm() << "; " + << "Limits: " << max_trans_acc << std::endl; + } + // check rotational acceleration + a_1 = (w_2 - w_1) / duration; + a_2 = (w_3 - w_2) / duration; + if (a_1.norm() > max_rot_acc || a_2.norm() > max_rot_acc) + { + std::cout << "Rotational acceleration between blend trajectory and second " + "trajectory exceeds the limit." + << "Actual acceleration (norm): " << a_1.norm() << ", " << a_1.norm() << "; " + << "Limits: " << max_rot_acc << std::endl; + } + + return true; +} + +bool testutils::checkThatPointsInRadius(const std::string& link_name, const double& r, Eigen::Isometry3d& circ_pose, + const pilz_industrial_motion_planner::TrajectoryBlendResponse& res) +{ + bool result = true; + for (size_t i = 1; i < res.blend_trajectory->getWayPointCount() - 1; ++i) + { + Eigen::Isometry3d curr_pos(res.blend_trajectory->getWayPointPtr(i)->getFrameTransform(link_name)); + if ((curr_pos.translation() - circ_pose.translation()).norm() > r) + { + std::cout << "Point " << i << " does not lie within blending radius (dist: " + << ((curr_pos.translation() - circ_pose.translation()).norm() - r) << ")." << std::endl; + result = false; + } + } + return result; +} + +void testutils::computeCartVelocity(const Eigen::Isometry3d& pose_1, const Eigen::Isometry3d& pose_2, double duration, + Eigen::Vector3d& v, Eigen::Vector3d& w) +{ + // translational velocity + v = (pose_2.translation() - pose_1.translation()) / duration; + + // angular velocity + // reference: A Mathematical Introduction to Robotics Manipulation 2.4.1 + // Rotational velocity + Eigen::Matrix3d rm_1 = pose_1.linear(); + Eigen::Matrix3d rm_2 = pose_2.linear(); + Eigen::Matrix3d rm_dot = (rm_2 - rm_1) / duration; + Eigen::Matrix3d w_hat = rm_dot * rm_1.transpose(); + w(0) = w_hat(2, 1); + w(1) = w_hat(0, 2); + w(2) = w_hat(1, 0); +} + +void testutils::getLinLinPosesWithoutOriChange(const std::string& frame_id, sensor_msgs::JointState& initialJointState, + geometry_msgs::PoseStamped& p1, geometry_msgs::PoseStamped& p2) +{ + initialJointState = + testutils::generateJointState({ 0., 0.007881892504574495, -1.8157263253868452, 0., 1.8236082178909834, 0. }); + + p1.header.frame_id = frame_id; + p1.pose.position.x = 0.25; + p1.pose.position.y = 0.3; + p1.pose.position.z = 0.65; + p1.pose.orientation.x = 0.; + p1.pose.orientation.y = 0.; + p1.pose.orientation.z = 0.; + p1.pose.orientation.w = 1.; + + p2 = p1; + p2.pose.position.x -= 0.15; +} + +void testutils::getOriChange(Eigen::Matrix3d& ori1, Eigen::Matrix3d& ori2) +{ + ori1 = Eigen::AngleAxisd(0.2 * M_PI, Eigen::Vector3d::UnitZ()); + ori2 = Eigen::AngleAxisd(0.4 * M_PI, Eigen::Vector3d::UnitZ()); +} + +void testutils::createFakeCartTraj(const robot_trajectory::RobotTrajectoryPtr& traj, const std::string& link_name, + moveit_msgs::RobotTrajectory& fake_traj) +{ + fake_traj.joint_trajectory.joint_names.push_back("x"); + fake_traj.joint_trajectory.joint_names.push_back("y"); + fake_traj.joint_trajectory.joint_names.push_back("z"); + // fake_traj.joint_trajectory.joint_names.push_back("a"); + // fake_traj.joint_trajectory.joint_names.push_back("b"); + // fake_traj.joint_trajectory.joint_names.push_back("c"); + + for (size_t i = 0; i < traj->getWayPointCount(); ++i) + { + trajectory_msgs::JointTrajectoryPoint waypoint; + waypoint.time_from_start = ros::Duration(traj->getWayPointDurationFromStart(i)); + Eigen::Isometry3d waypoint_pose = traj->getWayPointPtr(i)->getFrameTransform(link_name); + Eigen::Vector3d waypoint_position = waypoint_pose.translation(); + waypoint.positions.push_back(waypoint_position(0)); + waypoint.positions.push_back(waypoint_position(1)); + waypoint.positions.push_back(waypoint_position(2)); + waypoint.velocities.push_back(0); + waypoint.velocities.push_back(0); + waypoint.velocities.push_back(0); + waypoint.accelerations.push_back(0); + waypoint.accelerations.push_back(0); + waypoint.accelerations.push_back(0); + fake_traj.joint_trajectory.points.push_back(waypoint); + } +} + +bool testutils::getBlendTestData(const ros::NodeHandle& nh, const size_t& dataset_num, const std::string& name_prefix, + std::vector& datasets) +{ + datasets.clear(); + testutils::BlendTestData dataset; + for (size_t i = 1; i < dataset_num + 1; ++i) + { + std::string data_set_name = "blend_set_" + std::to_string(i); + if (nh.getParam(name_prefix + data_set_name + "/start_position", dataset.start_position) && + nh.getParam(name_prefix + data_set_name + "/mid_position", dataset.mid_position) && + nh.getParam(name_prefix + data_set_name + "/end_position", dataset.end_position)) + { + datasets.push_back(dataset); + } + else + { + return false; + } + } + return true; +} + +bool testutils::generateTrajFromBlendTestData( + const robot_model::RobotModelConstPtr& robot_model, + const std::shared_ptr& tg, const std::string& group_name, + const std::string& link_name, const testutils::BlendTestData& data, const double& sampling_time_1, + const double& sampling_time_2, planning_interface::MotionPlanResponse& res_1, + planning_interface::MotionPlanResponse& res_2, double& dis_1, double& dis_2) +{ + // generate first trajectory + planning_interface::MotionPlanRequest req_1; + req_1.group_name = group_name; + req_1.max_velocity_scaling_factor = 0.1; + req_1.max_acceleration_scaling_factor = 0.1; + // start state + robot_state::RobotState start_state(robot_model); + start_state.setToDefaultValues(); + start_state.setJointGroupPositions(group_name, data.start_position); + moveit::core::robotStateToRobotStateMsg(start_state, req_1.start_state, false); + // goal constraint + robot_state::RobotState goal_state_1(robot_model); + goal_state_1.setToDefaultValues(); + goal_state_1.setJointGroupPositions(group_name, data.mid_position); + req_1.goal_constraints.push_back(kinematic_constraints::constructGoalConstraints( + goal_state_1, goal_state_1.getRobotModel()->getJointModelGroup(group_name))); + + // trajectory generation + if (!tg->generate(req_1, res_1, sampling_time_1)) + { + std::cout << "Failed to generate first trajectory." << std::endl; + return false; + } + + // generate second LIN trajectory + planning_interface::MotionPlanRequest req_2; + req_2.group_name = group_name; + req_2.max_velocity_scaling_factor = 0.1; + req_2.max_acceleration_scaling_factor = 0.1; + // start state + moveit::core::robotStateToRobotStateMsg(goal_state_1, req_2.start_state, false); + // goal state + robot_state::RobotState goal_state_2(robot_model); + goal_state_2.setToDefaultValues(); + goal_state_2.setJointGroupPositions(group_name, data.end_position); + req_2.goal_constraints.push_back(kinematic_constraints::constructGoalConstraints( + goal_state_2, goal_state_2.getRobotModel()->getJointModelGroup(group_name))); + // trajectory generation + if (!tg->generate(req_2, res_2, sampling_time_2)) + { + std::cout << "Failed to generate second trajectory." << std::endl; + return false; + } + + // estimate a proper blend radius + dis_1 = + (start_state.getFrameTransform(link_name).translation() - goal_state_1.getFrameTransform(link_name).translation()) + .norm(); + + dis_2 = (goal_state_1.getFrameTransform(link_name).translation() - + goal_state_2.getFrameTransform(link_name).translation()) + .norm(); + + return true; +} + +bool testutils::checkBlendResult(const pilz_industrial_motion_planner::TrajectoryBlendRequest& blend_req, + const pilz_industrial_motion_planner::TrajectoryBlendResponse& blend_res, + const pilz_industrial_motion_planner::LimitsContainer& limits, + double joint_velocity_tolerance, double joint_acceleration_tolerance, + double cartesian_velocity_tolerance, double cartesian_angular_velocity_tolerance) +{ + // ++++++++++++++++++++++ + // + Check trajectories + + // ++++++++++++++++++++++ + moveit_msgs::RobotTrajectory traj_msg; + blend_res.first_trajectory->getRobotTrajectoryMsg(traj_msg); + if (!testutils::checkJointTrajectory(traj_msg.joint_trajectory, limits.getJointLimitContainer())) + { + return false; + } + + blend_res.blend_trajectory->getRobotTrajectoryMsg(traj_msg); + if (!testutils::checkJointTrajectory(traj_msg.joint_trajectory, limits.getJointLimitContainer())) + { + return false; + }; + + blend_res.second_trajectory->getRobotTrajectoryMsg(traj_msg); + if (!testutils::checkJointTrajectory(traj_msg.joint_trajectory, limits.getJointLimitContainer())) + { + return false; + }; + + Eigen::Isometry3d circ_pose = + blend_req.first_trajectory->getLastWayPointPtr()->getFrameTransform(blend_req.link_name); + if (!testutils::checkThatPointsInRadius(blend_req.link_name, blend_req.blend_radius, circ_pose, blend_res)) + { + return false; + } + + // check the first and second trajectories, if they are still the same before + // and after the bendling phase + if (!testutils::checkOriginalTrajectoryAfterBlending(blend_req, blend_res, 10e-5)) + { + return false; + } + + // check the continuity between the trajectories in joint space + if (!testutils::checkBlendingJointSpaceContinuity(blend_res, joint_velocity_tolerance, joint_acceleration_tolerance)) + { + return false; + } + + // check the continuity between the trajectories in cart space + if (!testutils::checkBlendingCartSpaceContinuity(blend_req, blend_res, limits)) + { + return false; + } + + // ++++++++++++++++++++++++ + // + Visualize the result + + // ++++++++++++++++++++++++ + // ros::NodeHandle nh; + // ros::Publisher pub = + // nh.advertise("my_planned_path", 1); + // ros::Duration duration(1.0); + // duration.sleep(); + + // // visualize the joint trajectory + // moveit_msgs::DisplayTrajectory displayTrajectory; + // moveit_msgs::RobotTrajectory res_first_traj_msg, res_blend_traj_msg, + // res_second_traj_msg; + // blend_res.first_trajectory->getRobotTrajectoryMsg(res_first_traj_msg); + // blend_res.blend_trajectory->getRobotTrajectoryMsg(res_blend_traj_msg); + // blend_res.second_trajectory->getRobotTrajectoryMsg(res_second_traj_msg); + // displayTrajectory.trajectory.push_back(res_first_traj_msg); + // displayTrajectory.trajectory.push_back(res_blend_traj_msg); + // displayTrajectory.trajectory.push_back(res_second_traj_msg); + + // pub.publish(displayTrajectory); + + return true; +} + +void testutils::generateRequestMsgFromBlendTestData(const moveit::core::RobotModelConstPtr& robot_model, + const testutils::BlendTestData& data, const std::string& planner_id, + const std::string& group_name, const std::string& link_name, + moveit_msgs::MotionSequenceRequest& req_list) +{ + // motion plan request of first trajectory + planning_interface::MotionPlanRequest req_1; + req_1.planner_id = planner_id; + req_1.group_name = group_name; + req_1.max_velocity_scaling_factor = 0.1; + req_1.max_acceleration_scaling_factor = 0.1; + // start state + robot_state::RobotState start_state(robot_model); + start_state.setToDefaultValues(); + start_state.setJointGroupPositions(group_name, data.start_position); + moveit::core::robotStateToRobotStateMsg(start_state, req_1.start_state, false); + // goal constraint + robot_state::RobotState goal_state_1(robot_model); + goal_state_1.setToDefaultValues(); + goal_state_1.setJointGroupPositions(group_name, data.mid_position); + req_1.goal_constraints.push_back(kinematic_constraints::constructGoalConstraints( + goal_state_1, goal_state_1.getRobotModel()->getJointModelGroup(group_name))); + + // motion plan request of second trajectory + planning_interface::MotionPlanRequest req_2; + req_2.planner_id = planner_id; + req_2.group_name = group_name; + req_2.max_velocity_scaling_factor = 0.1; + req_2.max_acceleration_scaling_factor = 0.1; + // start state + // moveit::core::robotStateToRobotStateMsg(goal_state_1, req_2.start_state, + // false); + // goal state + robot_state::RobotState goal_state_2(robot_model); + goal_state_2.setToDefaultValues(); + goal_state_2.setJointGroupPositions(group_name, data.end_position); + req_2.goal_constraints.push_back(kinematic_constraints::constructGoalConstraints( + goal_state_2, goal_state_2.getRobotModel()->getJointModelGroup(group_name))); + + // select a proper blending radius + // estimate a proper blend radius + double dis_1 = + (start_state.getFrameTransform(link_name).translation() - goal_state_1.getFrameTransform(link_name).translation()) + .norm(); + + double dis_2 = (goal_state_1.getFrameTransform(link_name).translation() - + goal_state_2.getFrameTransform(link_name).translation()) + .norm(); + + double blend_radius = 0.5 * std::min(dis_1, dis_2); + + moveit_msgs::MotionSequenceItem blend_req_1, blend_req_2; + blend_req_1.req = req_1; + blend_req_1.blend_radius = blend_radius; + blend_req_2.req = req_2; + blend_req_2.blend_radius = 0.0; + + req_list.items.push_back(blend_req_1); + req_list.items.push_back(blend_req_2); +} + +void testutils::checkRobotModel(const moveit::core::RobotModelConstPtr& robot_model, const std::string& group_name, + const std::string& link_name) +{ + ASSERT_TRUE(robot_model != nullptr) << "failed to load robot model"; + ASSERT_FALSE(robot_model->isEmpty()) << "robot model is empty"; + ASSERT_TRUE(robot_model->hasJointModelGroup(group_name)) << group_name << " is not known to robot"; + ASSERT_TRUE(robot_model->hasLinkModel(link_name)) << link_name << " is not known to robot"; + ASSERT_TRUE(robot_state::RobotState(robot_model).knowsFrameTransform(link_name)) + << "Transform of " << link_name << " is unknown"; +} + +::testing::AssertionResult testutils::hasTrapezoidVelocity(std::vector accelerations, const double acc_tol) +{ + // Check that acceleration is monotonously decreasing + if (!isMonotonouslyDecreasing(accelerations, acc_tol)) + { + return ::testing::AssertionFailure() << "Cannot be a trapezoid since " + "acceleration is not monotonously " + "decreasing!"; + } + + // Check accelerations + double first_acc = accelerations.front(); + auto it_last_acc = std::find_if(accelerations.begin(), accelerations.end(), + [first_acc, acc_tol](double el) { return (std::abs(el - first_acc) > acc_tol); }) - + 1; + + auto it_last_intermediate = + std::find_if(it_last_acc + 1, accelerations.end(), [acc_tol](double el) { return (el < acc_tol); }) - 1; + + // Check that there are 1 or 2 intermediate points + auto n_intermediate_1 = std::distance(it_last_acc, it_last_intermediate); + + if (n_intermediate_1 != 1 && n_intermediate_1 != 2) + { + return ::testing::AssertionFailure() << "Expected 1 or 2 intermediate points between acceleration and " + "constant " + "velocity phase but found: " + << n_intermediate_1; + } + + // Const phase (vel == 0) + auto it_first_const = it_last_intermediate + 1; + auto it_last_const = + std::find_if(it_first_const, accelerations.end(), [acc_tol](double el) { return (std::abs(el) > acc_tol); }) - 1; + // This test makes sense only if the generated traj has enough points such + // that the trapezoid is not degenerated. + if (std::distance(it_first_const, it_last_const) < 3) + { + return ::testing::AssertionFailure() << "Exptected the have at least 3 points during the phase of " + "constant " + "velocity."; + } + + // Deceleration + double deceleration = accelerations.back(); + auto it_first_dec = + std::find_if(it_last_const + 1, accelerations.end(), + [deceleration, acc_tol](double el) { return (std::abs(el - deceleration) > acc_tol); }) + + 1; + + // Points between const and deceleration (again 1 or 2) + auto n_intermediate_2 = std::distance(it_last_const, it_first_dec); + if (n_intermediate_2 != 1 && n_intermediate_2 != 2) + { + return ::testing::AssertionFailure() << "Expected 1 or 2 intermediate points between constant velocity " + "and " + "deceleration phase but found: " + << n_intermediate_2; + } + + std::stringstream debug_stream; + for (auto it = accelerations.begin(); it != it_last_acc + 1; it++) + { + debug_stream << *it << "(Acc)" << std::endl; + } + + for (auto it = it_last_acc + 1; it != it_last_intermediate + 1; it++) + { + debug_stream << *it << "(Inter1)" << std::endl; + } + + for (auto it = it_first_const; it != it_last_const + 1; it++) + { + debug_stream << *it << "(Const)" << std::endl; + } + + for (auto it = it_last_const + 1; it != it_first_dec; it++) + { + debug_stream << *it << "(Inter2)" << std::endl; + } + + for (auto it = it_first_dec; it != accelerations.end(); it++) + { + debug_stream << *it << "(Dec)" << std::endl; + } + + ROS_DEBUG_STREAM(debug_stream.str()); + + return ::testing::AssertionSuccess(); +} + +::testing::AssertionResult +testutils::checkCartesianTranslationalPath(const robot_trajectory::RobotTrajectoryConstPtr& trajectory, + const std::string& link_name, const double acc_tol) +{ + // We require the following such that the test makes sense, else the traj + // would have a degenerated velocity profile + EXPECT_GT(trajectory->getWayPointCount(), 9u); + + std::vector accelerations; + + // Iterate over waypoints collect accelerations + for (size_t i = 2; i < trajectory->getWayPointCount(); ++i) + { + auto waypoint_pose_0 = trajectory->getWayPoint(i - 2).getFrameTransform(link_name); + auto waypoint_pose_1 = trajectory->getWayPoint(i - 1).getFrameTransform(link_name); + auto waypoint_pose_2 = trajectory->getWayPoint(i).getFrameTransform(link_name); + + auto t1 = trajectory->getWayPointDurationFromPrevious(i - 1); + auto t2 = trajectory->getWayPointDurationFromPrevious(i); + + auto vel1 = (waypoint_pose_1.translation() - waypoint_pose_0.translation()).norm() / t1; + auto vel2 = (waypoint_pose_2.translation() - waypoint_pose_1.translation()).norm() / t2; + auto acc_transl = (vel2 - vel1) / (t1 + t2); + accelerations.push_back(acc_transl); + } + + return hasTrapezoidVelocity(accelerations, acc_tol); +} + +::testing::AssertionResult +testutils::checkCartesianRotationalPath(const robot_trajectory::RobotTrajectoryConstPtr& trajectory, + const std::string& link_name, const double rot_axis_tol, const double acc_tol) +{ + // skip computations if rotation angle is zero + if (trajectory->getFirstWayPoint().getFrameTransform(link_name).rotation().isApprox( + trajectory->getLastWayPoint().getFrameTransform(link_name).rotation(), rot_axis_tol)) + { + return ::testing::AssertionSuccess(); + } + + // We require the following such that the test makes sense, else the traj + // would have a degenerated velocity profile + EXPECT_GT(trajectory->getWayPointCount(), 9u); + + std::vector accelerations; + std::vector rotation_axes; + + // Iterate over waypoints collect accelerations and rotation axes + for (size_t i = 2; i < trajectory->getWayPointCount(); ++i) + { + auto waypoint_pose_0 = trajectory->getWayPoint(i - 2).getFrameTransform(link_name); + auto waypoint_pose_1 = trajectory->getWayPoint(i - 1).getFrameTransform(link_name); + auto waypoint_pose_2 = trajectory->getWayPoint(i).getFrameTransform(link_name); + + auto t1 = trajectory->getWayPointDurationFromPrevious(i - 1); + auto t2 = trajectory->getWayPointDurationFromPrevious(i); + + Eigen::Quaterniond orientation0(waypoint_pose_0.rotation()); + Eigen::Quaterniond orientation1(waypoint_pose_1.rotation()); + Eigen::Quaterniond orientation2(waypoint_pose_2.rotation()); + + Eigen::AngleAxisd axis1(orientation0 * orientation1.inverse()); + Eigen::AngleAxisd axis2(orientation1 * orientation2.inverse()); + if (i == 2) + { + rotation_axes.push_back(axis1); + } + rotation_axes.push_back(axis2); + + double angular_vel1 = axis1.angle() / t1; + double angular_vel2 = axis2.angle() / t2; + double angular_acc = (angular_vel2 - angular_vel1) / (t1 + t2); + accelerations.push_back(angular_acc); + } + + // Check that rotation axis is fixed + if (std::adjacent_find(rotation_axes.begin(), rotation_axes.end(), + [rot_axis_tol](const Eigen::AngleAxisd& axis1, const Eigen::AngleAxisd& axis2) { + return ((axis1.axis() - axis2.axis()).norm() > rot_axis_tol); + }) != rotation_axes.end()) + { + return ::testing::AssertionFailure() << "Rotational path of trajectory " + "does not have a fixed rotation " + "axis"; + } + + return hasTrapezoidVelocity(accelerations, acc_tol); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_utils.h b/moveit_planners/pilz_industrial_motion_planner/test/test_utils.h new file mode 100644 index 0000000000..2937ff1dae --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_utils.h @@ -0,0 +1,484 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#pragma once + +#include +#ifndef INSTANTIATE_TEST_SUITE_P // prior to gtest 1.10 +#define INSTANTIATE_TEST_SUITE_P(...) INSTANTIATE_TEST_CASE_P(__VA_ARGS__) +#endif +#ifndef TYPED_TEST_SUITE // prior to gtest 1.10 +#define TYPED_TEST_SUITE(...) TYPED_TEST_CASE(__VA_ARGS__) +#endif + +#include "moveit_msgs/MotionSequenceRequest.h" +#include "pilz_industrial_motion_planner/limits_container.h" +#include "pilz_industrial_motion_planner/trajectory_blend_request.h" +#include "pilz_industrial_motion_planner/trajectory_blend_response.h" +#include "pilz_industrial_motion_planner/trajectory_generator.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace testutils +{ +const std::string JOINT_NAME_PREFIX("prbt_joint_"); + +static constexpr int32_t DEFAULT_SERVICE_TIMEOUT(10); +static constexpr double DEFAULT_ACCELERATION_EQUALITY_TOLERANCE{ 1e-6 }; +static constexpr double DEFAULT_ROTATION_AXIS_EQUALITY_TOLERANCE{ 1e-8 }; + +/** + * @brief Convert degree to rad. + */ +inline static constexpr double deg2Rad(double angle) +{ + return (angle / 180.0) * M_PI; +} + +inline std::string getJointName(size_t joint_number, const std::string& joint_prefix) +{ + return joint_prefix + std::to_string(joint_number); +} + +/** + * @brief Create limits for tests to avoid the need to get the limits from the + * parameter server + */ +pilz_industrial_motion_planner::JointLimitsContainer createFakeLimits(const std::vector& joint_names); + +inline std::string demangel(char const* name) +{ + return boost::core::demangle(name); +} + +//******************************************** +// Motion plan requests +//******************************************** + +inline sensor_msgs::JointState generateJointState(const std::vector& pos, const std::vector& vel, + const std::string& joint_prefix = testutils::JOINT_NAME_PREFIX) +{ + sensor_msgs::JointState state; + auto posit = pos.cbegin(); + size_t i = 0; + + while (posit != pos.cend()) + { + state.name.push_back(testutils::getJointName(i + 1, joint_prefix)); + state.position.push_back(*posit); + + i++; + posit++; + } + for (const auto& one_vel : vel) + { + state.velocity.push_back(one_vel); + } + return state; +} + +inline sensor_msgs::JointState generateJointState(const std::vector& pos, + const std::string& joint_prefix = testutils::JOINT_NAME_PREFIX) +{ + return generateJointState(pos, std::vector(), joint_prefix); +} + +inline moveit_msgs::Constraints generateJointConstraint(const std::vector& pos_list, + const std::string& joint_prefix = testutils::JOINT_NAME_PREFIX) +{ + moveit_msgs::Constraints gc; + + auto pos_it = pos_list.begin(); + + for (size_t i = 0; i < pos_list.size(); ++i) + { + moveit_msgs::JointConstraint jc; + jc.joint_name = testutils::getJointName(i + 1, joint_prefix); + jc.position = *pos_it; + gc.joint_constraints.push_back(jc); + + ++pos_it; + } + + return gc; +} + +/** + * @brief Determines the goal position from the given request. + * TRUE if successful, FALSE otherwise. + */ +bool getExpectedGoalPose(const moveit::core::RobotModelConstPtr& robot_model, + const planning_interface::MotionPlanRequest& req, std::string& link_name, + Eigen::Isometry3d& goal_pose_expect); + +/** + * @brief create a dummy motion plan request with zero start state + * No goal constraint is given. + * @param robot_model + * @param planning_group + * @param req + */ +void createDummyRequest(const moveit::core::RobotModelConstPtr& robot_model, const std::string& planning_group, + planning_interface::MotionPlanRequest& req); + +void createPTPRequest(const std::string& planning_group, const moveit::core::RobotState& start_state, + const moveit::core::RobotState& goal_state, planning_interface::MotionPlanRequest& req); + +/** + * @brief check if the goal given in joint space is reached + * Only the last point in the trajectory is veryfied. + * @param trajectory: generated trajectory + * @param goal: goal in joint space + * @param joint_position_tolerance + * @param joint_velocity_tolerance + * @return true if satisfied + */ +bool isGoalReached(const trajectory_msgs::JointTrajectory& trajectory, + const std::vector& goal, const double joint_position_tolerance, + const double joint_velocity_tolerance = 1.0e-6); + +/** + * @brief check if the goal given in cartesian space is reached + * Only the last point in the trajectory is veryfied. + * @param robot_model + * @param trajectory + * @param req + * @param matrix_norm_tolerance: used to compare the transformation matrix + * @param joint_velocity_tolerance + * @return + */ +bool isGoalReached(const robot_model::RobotModelConstPtr& robot_model, + const trajectory_msgs::JointTrajectory& trajectory, const planning_interface::MotionPlanRequest& req, + const double pos_tolerance, const double orientation_tolerance); + +bool isGoalReached(const moveit::core::RobotModelConstPtr& robot_model, + const trajectory_msgs::JointTrajectory& trajectory, const planning_interface::MotionPlanRequest& req, + const double tolerance); + +/** + * @brief Check that given trajectory is straight line. + */ +bool checkCartesianLinearity(const robot_model::RobotModelConstPtr& robot_model, + const trajectory_msgs::JointTrajectory& trajectory, + const planning_interface::MotionPlanRequest& req, const double translation_norm_tolerance, + const double rot_axis_norm_tolerance, const double rot_angle_tolerance = 10e-5); + +/** + * @brief check SLERP. The orientation should rotate around the same axis + * linearly. + * @param start_pose + * @param goal_pose + * @param wp_pose + * @param rot_axis_norm_tolerance + * @return + */ +bool checkSLERP(const Eigen::Isometry3d& start_pose, const Eigen::Isometry3d& goal_pose, + const Eigen::Isometry3d& wp_pose, const double rot_axis_norm_tolerance, + const double rot_angle_tolerance = 10e-5); + +/** + * @brief get the waypoint index from time from start + * @param trajectory + * @param time_from_start + * @return + */ +inline int getWayPointIndex(const robot_trajectory::RobotTrajectoryPtr& trajectory, const double time_from_start) +{ + int index_before, index_after; + double blend; + trajectory->findWayPointIndicesForDurationAfterStart(time_from_start, index_before, index_after, blend); + return blend > 0.5 ? index_after : index_before; +} + +/** + * @brief check joint trajectory of consistency, position, velocity and + * acceleration limits + * @param trajectory + * @param joint_limits + * @return + */ +bool checkJointTrajectory(const trajectory_msgs::JointTrajectory& trajectory, + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits); + +/** + * @brief Checks that every waypoint in the trajectory has a non-zero duration + * between itself and its predecessor + * + * Usage in tests: + * @code + * EXPECT_TRUE(HasStrictlyIncreasingTime(trajectory)); + * @endcode + */ +::testing::AssertionResult hasStrictlyIncreasingTime(const robot_trajectory::RobotTrajectoryPtr& trajectory); + +/** + * @brief check if the sizes of the joint position/veloicty/acceleration are + * correct + * @param trajectory + * @return + */ +bool isTrajectoryConsistent(const trajectory_msgs::JointTrajectory& trajectory); + +/** + * @brief is Position Bounded + * @param trajectory + * @param joint_limits + * @return + */ +bool isPositionBounded(const trajectory_msgs::JointTrajectory& trajectory, + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits); + +/** + * @brief is Velocity Bounded + * @param trajectory + * @param joint_limits + * @return + */ +bool isVelocityBounded(const trajectory_msgs::JointTrajectory& trajectory, + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits); + +/** + * @brief is Acceleration Bounded + * @param trajectory + * @param joint_limits + * @return + */ +bool isAccelerationBounded(const trajectory_msgs::JointTrajectory& trajectory, + const pilz_industrial_motion_planner::JointLimitsContainer& joint_limits); + +/** + * @brief compute the tcp pose from joint values + * @param robot_model + * @param link_name + * @param joint_values + * @param pose + * @param joint_prefix Prefix of the joint names + * @return false if forward kinematics failed + */ +bool toTCPPose(const moveit::core::RobotModelConstPtr& robot_model, const std::string& link_name, + const std::vector& joint_values, geometry_msgs::Pose& pose, + const std::string& joint_prefix = testutils::JOINT_NAME_PREFIX); + +/** + * @brief computeLinkFK + * @param robot_model + * @param link_name + * @param joint_state + * @param pose + * @return + */ +bool computeLinkFK(const robot_model::RobotModelConstPtr& robot_model, const std::string& link_name, + const std::map& joint_state, Eigen::Isometry3d& pose); + +/** + * @brief checkOriginalTrajectoryAfterBlending + * @param blend_res + * @param traj_1_res + * @param traj_2_res + * @param time_tolerance + * @return + */ +bool checkOriginalTrajectoryAfterBlending(const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, + const pilz_industrial_motion_planner::TrajectoryBlendResponse& res, + const double time_tolerance); + +/** + * @brief check the blending result, if the joint space continuity is fulfilled + * @param res: trajectory blending response, contains three trajectories. + * Between these three trajectories should be continuous. + * @return true if joint position/velocity is continuous. joint acceleration can + * have jumps. + */ +bool checkBlendingJointSpaceContinuity(const pilz_industrial_motion_planner::TrajectoryBlendResponse& res, + double joint_velocity_tolerance, double joint_accleration_tolerance); + +bool checkBlendingCartSpaceContinuity(const pilz_industrial_motion_planner::TrajectoryBlendRequest& req, + const pilz_industrial_motion_planner::TrajectoryBlendResponse& res, + const pilz_industrial_motion_planner::LimitsContainer& planner_limits); + +/** + * @brief Checks if all points of the blending trajectory lie within the + * blending radius. + */ +bool checkThatPointsInRadius(const std::string& link_name, const double& r, Eigen::Isometry3d& circ_pose, + const pilz_industrial_motion_planner::TrajectoryBlendResponse& res); + +/** + * @brief compute Cartesian velocity + * @param pose_1 + * @param pose_2 + * @param duration + * @param v + * @param w + */ +void computeCartVelocity(const Eigen::Isometry3d& pose_1, const Eigen::Isometry3d& pose_2, double duration, + Eigen::Vector3d& v, Eigen::Vector3d& w); + +/** + * @brief Returns an initial joint state and two poses which + * can be used to perform a Lin-Lin movement. + * + * @param frame_id + * @param initialJointState As cartesian position: (0.3, 0, 0.65, 0, 0, 0) + * @param p1 (0.05, 0, 0.65, 0, 0, 0) + * @param p2 (0.05, 0.4, 0.65, 0, 0, 0) + */ +void getLinLinPosesWithoutOriChange(const std::string& frame_id, sensor_msgs::JointState& initialJointState, + geometry_msgs::PoseStamped& p1, geometry_msgs::PoseStamped& p2); + +void getOriChange(Eigen::Matrix3d& ori1, Eigen::Matrix3d& ori2); + +void createFakeCartTraj(const robot_trajectory::RobotTrajectoryPtr& traj, const std::string& link_name, + moveit_msgs::RobotTrajectory& fake_traj); + +inline geometry_msgs::Quaternion fromEuler(double a, double b, double c) +{ + tf2::Vector3 qvz(0., 0., 1.); + tf2::Vector3 qvy(0., 1., 0.); + tf2::Quaternion q1(qvz, a); + + q1 = q1 * tf2::Quaternion(qvy, b); + q1 = q1 * tf2::Quaternion(qvz, c); + + geometry_msgs::Quaternion msg; + tf2::convert(q1, msg); + return msg; +} + +/** + * @brief Test data for blending, which contains three joint position vectors of + * three robot state. + */ +struct BlendTestData +{ + std::vector start_position; + std::vector mid_position; + std::vector end_position; +}; + +/** + * @brief fetch test datasets from parameter server + * @param nh + * @return + */ +bool getBlendTestData(const ros::NodeHandle& nh, const size_t& dataset_num, const std::string& name_prefix, + std::vector& datasets); + +/** + * @brief check the blending result of lin-lin + * @param lin_res_1 + * @param lin_res_2 + * @param blend_req + * @param blend_res + * @param checkAcceleration + */ +bool checkBlendResult(const pilz_industrial_motion_planner::TrajectoryBlendRequest& blend_req, + const pilz_industrial_motion_planner::TrajectoryBlendResponse& blend_res, + const pilz_industrial_motion_planner::LimitsContainer& limits, double joint_velocity_tolerance, + double joint_acceleration_tolerance, double cartesian_velocity_tolerance, + double cartesian_angular_velocity_tolerance); + +/** + * @brief generate two LIN trajectories from test data set + * @param data: contains joint poisitons of start/mid/end states + * @param sampling_time_1: sampling time for first LIN + * @param sampling_time_2: sampling time for second LIN + * @param[out] res_lin_1: result of the first LIN motion planning + * @param[out] res_lin_2: result of the second LIN motion planning + * @param[out] dis_lin_1: translational distance of the first LIN + * @param[out] dis_lin_2: translational distance of the second LIN + * @return true if succeed + */ +bool generateTrajFromBlendTestData(const moveit::core::RobotModelConstPtr& robot_model, + const std::shared_ptr& tg, + const std::string& group_name, const std::string& link_name, + const BlendTestData& data, const double& sampling_time_1, + const double& sampling_time_2, planning_interface::MotionPlanResponse& res_lin_1, + planning_interface::MotionPlanResponse& res_lin_2, double& dis_lin_1, + double& dis_lin_2); + +void generateRequestMsgFromBlendTestData(const moveit::core::RobotModelConstPtr& robot_model, const BlendTestData& data, + const std::string& planner_id, const std::string& group_name, + const std::string& link_name, moveit_msgs::MotionSequenceRequest& req_list); + +void checkRobotModel(const moveit::core::RobotModelConstPtr& robot_model, const std::string& group_name, + const std::string& link_name); + +/** @brief Check that a given vector of accelerations represents a trapezoid + * velocity profile + * @param acc_tol: tolerance for comparing acceleration values + */ +::testing::AssertionResult hasTrapezoidVelocity(std::vector accelerations, const double acc_tol); + +/** + * @brief Check that the translational path of a given trajectory has a + * trapezoid velocity profile + * @param acc_tol: tolerance for comparing acceleration values + */ +::testing::AssertionResult +checkCartesianTranslationalPath(const robot_trajectory::RobotTrajectoryConstPtr& trajectory, + const std::string& link_name, + const double acc_tol = DEFAULT_ACCELERATION_EQUALITY_TOLERANCE); + +/** + * @brief Check that the rotational path of a given trajectory is a quaternion + * slerp. + * @param rot_axis_tol: tolerance for comparing rotation axes (in the L2 norm) + * @param acc_tol: tolerance for comparing angular acceleration values + */ +::testing::AssertionResult +checkCartesianRotationalPath(const robot_trajectory::RobotTrajectoryConstPtr& trajectory, const std::string& link_name, + const double rot_axis_tol = DEFAULT_ROTATION_AXIS_EQUALITY_TOLERANCE, + const double acc_tol = DEFAULT_ACCELERATION_EQUALITY_TOLERANCE); + +inline bool isMonotonouslyDecreasing(const std::vector& vec, const double& tol) +{ + return std::is_sorted(vec.begin(), vec.end(), [tol](double a, double b) { + return !(std::abs(a - b) < tol || a < b); // true -> a is ordered before b -> list is not sorted + }); +} + +} // namespace testutils diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_cartesian_limits_aggregator.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_cartesian_limits_aggregator.cpp new file mode 100644 index 0000000000..1809ada9c7 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_cartesian_limits_aggregator.cpp @@ -0,0 +1,92 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include + +#include "pilz_industrial_motion_planner/cartesian_limit.h" +#include "pilz_industrial_motion_planner/cartesian_limits_aggregator.h" + +/** + * @brief Unittest of the CartesianLimitsAggregator class + */ +class CartesianLimitsAggregator : public ::testing::Test +{ +}; + +/** + * @brief Check if only velocity is set + */ +TEST_F(CartesianLimitsAggregator, OnlyVelocity) +{ + ros::NodeHandle nh("~/vel_only"); + + pilz_industrial_motion_planner::CartesianLimit limit = + pilz_industrial_motion_planner::CartesianLimitsAggregator::getAggregatedLimits(nh); + EXPECT_TRUE(limit.hasMaxTranslationalVelocity()); + EXPECT_EQ(limit.getMaxTranslationalVelocity(), 10); + EXPECT_FALSE(limit.hasMaxTranslationalAcceleration()); + EXPECT_FALSE(limit.hasMaxTranslationalDeceleration()); + EXPECT_FALSE(limit.hasMaxRotationalVelocity()); +} + +/** + * @brief Check if all values are set correctly + */ +TEST_F(CartesianLimitsAggregator, AllValues) +{ + ros::NodeHandle nh("~/all"); + + pilz_industrial_motion_planner::CartesianLimit limit = + pilz_industrial_motion_planner::CartesianLimitsAggregator::getAggregatedLimits(nh); + EXPECT_TRUE(limit.hasMaxTranslationalVelocity()); + EXPECT_EQ(limit.getMaxTranslationalVelocity(), 1); + + EXPECT_TRUE(limit.hasMaxTranslationalAcceleration()); + EXPECT_EQ(limit.getMaxTranslationalAcceleration(), 2); + + EXPECT_TRUE(limit.hasMaxTranslationalDeceleration()); + EXPECT_EQ(limit.getMaxTranslationalDeceleration(), -3); + + EXPECT_TRUE(limit.hasMaxRotationalVelocity()); + EXPECT_EQ(limit.getMaxRotationalVelocity(), 4); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "unittest_cartesian_limits_aggregator"); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_cartesian_limits_aggregator.test b/moveit_planners/pilz_industrial_motion_planner/test/unittest_cartesian_limits_aggregator.test new file mode 100644 index 0000000000..382a5a5924 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_cartesian_limits_aggregator.test @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_get_solver_tip_frame.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_get_solver_tip_frame.cpp new file mode 100644 index 0000000000..b749d48ae3 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_get_solver_tip_frame.cpp @@ -0,0 +1,145 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include +#include +#include +#include + +#include +#include + +#include + +#include "pilz_industrial_motion_planner/tip_frame_getter.h" + +namespace pilz_industrial_motion_planner +{ +using ::testing::AtLeast; +using ::testing::Return; +using ::testing::ReturnRef; + +class SolverMock +{ +public: + MOCK_CONST_METHOD0(getTipFrames, const std::vector&()); +}; + +class JointModelGroupMock +{ +public: + MOCK_CONST_METHOD0(getSolverInstance, SolverMock const*()); + MOCK_CONST_METHOD0(getName, const std::string&()); +}; + +/** + * @brief Test fixture for getSolverTipFrame tests. + */ +class GetSolverTipFrameTest : public testing::Test +{ +protected: + void SetUp() override; + +protected: + SolverMock solver_mock_; + JointModelGroupMock jmg_mock_; + const std::string group_name_{ "fake_group" }; +}; + +void GetSolverTipFrameTest::SetUp() +{ + EXPECT_CALL(jmg_mock_, getName()).WillRepeatedly(ReturnRef(group_name_)); +} + +/** + * @brief Checks that each derived MoveItErrorCodeException contains the correct + * error code. + */ +TEST_F(GetSolverTipFrameTest, TestExceptionErrorCodeMapping) +{ + { + std::shared_ptr nse_ex{ new NoSolverException("") }; + EXPECT_EQ(nse_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::FAILURE); + } + + { + std::shared_ptr ex{ new MoreThanOneTipFrameException("") }; + EXPECT_EQ(ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::FAILURE); + } +} + +/** + * @brief Checks that an exceptions is thrown in case a group has more than + * one tip frame. + */ +TEST_F(GetSolverTipFrameTest, TestExceptionMoreThanOneTipFrame) +{ + std::vector tip_frames{ "fake_tip_frame1", "fake_tip_frame2" }; + + EXPECT_CALL(jmg_mock_, getSolverInstance()).Times(AtLeast(1)).WillRepeatedly(Return(&solver_mock_)); + + EXPECT_CALL(solver_mock_, getTipFrames()).Times(AtLeast(1)).WillRepeatedly(ReturnRef(tip_frames)); + + EXPECT_THROW(getSolverTipFrame(&jmg_mock_), MoreThanOneTipFrameException); +} + +/** + * @brief Checks that an exceptions is thrown in case a group does not + * possess a solver. + */ +TEST_F(GetSolverTipFrameTest, TestExceptionNoSolver) +{ + EXPECT_CALL(jmg_mock_, getSolverInstance()).WillOnce(Return(nullptr)); + + EXPECT_THROW(getSolverTipFrame(&jmg_mock_), NoSolverException); +} + +/** + * @brief Checks that an exceptions is thrown in case a nullptr is + * specified as JointModelGroup. + */ +TEST_F(GetSolverTipFrameTest, NullptrJointGroup) +{ + moveit::core::JointModelGroup* group = nullptr; + EXPECT_THROW(hasSolver(group), std::invalid_argument); +} + +} // namespace pilz_industrial_motion_planner + +int main(int argc, char** argv) +{ + testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limit.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limit.cpp new file mode 100644 index 0000000000..488a27bb00 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limit.cpp @@ -0,0 +1,111 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "ros/ros.h" + +#include + +#include + +#include "pilz_industrial_motion_planner/joint_limits_extension.h" +#include "pilz_industrial_motion_planner/joint_limits_interface_extension.h" + +using namespace pilz_industrial_motion_planner; +using namespace pilz_industrial_motion_planner::joint_limits_interface; + +namespace pilz_extensions_tests +{ +class JointLimitTest : public ::testing::Test +{ +}; + +TEST_F(JointLimitTest, SimpleRead) +{ + ros::NodeHandle node_handle("~"); + + // Joints limits interface + JointLimits joint_limits_extended; + JointLimits joint_limits; + + getJointLimits("joint_1", node_handle, joint_limits_extended); + + EXPECT_EQ(1, joint_limits_extended.max_acceleration); + EXPECT_EQ(-1, joint_limits_extended.max_deceleration); +} + +TEST_F(JointLimitTest, readNonExistingJointLimit) +{ + ros::NodeHandle node_handle("~"); + + // Joints limits interface + JointLimits joint_limits_extended; + JointLimits joint_limits; + + EXPECT_FALSE(getJointLimits("anything", node_handle, joint_limits_extended)); +} + +/** + * @brief Test reading a joint limit representing an invalid parameter key + * + * For full coverage. + */ +TEST_F(JointLimitTest, readInvalidParameterName) +{ + ros::NodeHandle node_handle("~"); + + // Joints limits interface + JointLimits joint_limits_extended; + JointLimits joint_limits; + + EXPECT_FALSE(getJointLimits("~anything", node_handle, joint_limits_extended)); +} + +TEST_F(JointLimitTest, OldRead) +{ + ros::NodeHandle node_handle("~"); + + // Joints limits interface + JointLimits joint_limits; + getJointLimits("joint_1", node_handle, joint_limits); + + EXPECT_EQ(1, joint_limits.max_acceleration); +} +} // namespace pilz_extensions_tests + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "unittest_joint_limits_extended"); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limit.test b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limit.test new file mode 100644 index 0000000000..361e6f5102 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limit.test @@ -0,0 +1,40 @@ + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limit_config.yaml b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limit_config.yaml new file mode 100644 index 0000000000..4f4bfffd6e --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limit_config.yaml @@ -0,0 +1,31 @@ +joint_limits: + joint_1: + has_acceleration_limits: true + max_acceleration: 1 + has_deceleration_limits: true + max_deceleration: -1 + joint_2: + has_acceleration_limits: true + max_acceleration: 2 + has_deceleration_limits: true + max_deceleration: -2 + joint_3: + has_acceleration_limits: true + max_acceleration: 3 + has_deceleration_limits: true + max_deceleration: -3 + joint_4: + has_acceleration_limits: true + max_acceleration: 4 + has_deceleration_limits: true + max_deceleration: -4 + joint_5: + has_acceleration_limits: true + max_acceleration: 5 + has_deceleration_limits: true + max_deceleration: -5 + joint_6: + has_acceleration_limits: true + max_acceleration: 6 + has_deceleration_limits: true + max_deceleration: -6 diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_aggregator.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_aggregator.cpp new file mode 100644 index 0000000000..06827e3284 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_aggregator.cpp @@ -0,0 +1,208 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include +#include + +#include "pilz_industrial_motion_planner/joint_limits_aggregator.h" +#include "pilz_industrial_motion_planner/joint_limits_extension.h" +#include "pilz_industrial_motion_planner/joint_limits_interface_extension.h" + +/** + * @brief Unittest of the JointLimitsAggregator class + */ +class JointLimitsAggregator : public ::testing::Test +{ +protected: + void SetUp() override + { + ros::NodeHandle node_handle("~"); + + // Load robot module + robot_model_loader::RobotModelLoader::Options opt("robot_description"); + model_loader_.reset(new robot_model_loader::RobotModelLoader(opt)); + robot_model_ = model_loader_->getModel(); + + return; + } + + /// The robot model loader + robot_model_loader::RobotModelLoaderPtr model_loader_; + + /// The robot model + robot_model::RobotModelConstPtr robot_model_; +}; + +/** + * @brief Check for that the size of the map and the size of the given joint + * models is equal + */ +TEST_F(JointLimitsAggregator, ExpectedMapSize) +{ + ros::NodeHandle nh("~"); + + pilz_industrial_motion_planner::JointLimitsContainer container = + pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits(nh, + robot_model_->getActiveJointModels()); + + EXPECT_EQ(robot_model_->getActiveJointModels().size(), container.getCount()); +} + +/** + * @brief Check that the value in the parameter server correctly overrides the + * position(if within limits) + */ +TEST_F(JointLimitsAggregator, CorrectOverwriteByParamterPosition) +{ + ros::NodeHandle nh("~/valid_1"); + + pilz_industrial_motion_planner::JointLimitsContainer container = + pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits(nh, + robot_model_->getActiveJointModels()); + + for (std::pair lim : container) + { + // Check for the overwrite + if (lim.first == "prbt_joint_1") + { + EXPECT_EQ(2, container.getLimit(lim.first).max_position); + EXPECT_EQ(-2, container.getLimit(lim.first).min_position); + } + // Check that nothing else changed + else + { + EXPECT_EQ(robot_model_->getJointModel(lim.first)->getVariableBounds()[0].min_position_, + container.getLimit(lim.first).min_position); + EXPECT_EQ(robot_model_->getJointModel(lim.first)->getVariableBounds()[0].max_position_, + container.getLimit(lim.first).max_position); + } + } +} + +/** + * @brief Check that the value in the parameter server correctly overrides the + * velocity(if within limits) + */ +TEST_F(JointLimitsAggregator, CorrectOverwriteByParamterVelocity) +{ + ros::NodeHandle nh("~/valid_1"); + + pilz_industrial_motion_planner::JointLimitsContainer container = + pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits(nh, + robot_model_->getActiveJointModels()); + + for (std::pair lim : container) + { + // Check that velocity was only changed in joint "prbt_joint_3" + if (lim.first == "prbt_joint_3") + { + EXPECT_EQ(1.1, container.getLimit(lim.first).max_velocity); + } + else + { + EXPECT_EQ(robot_model_->getJointModel(lim.first)->getVariableBounds()[0].max_velocity_, + container.getLimit(lim.first).max_velocity); + } + } +} + +/** + * @brief Check that the acceleration and deceleration are set properly + */ +TEST_F(JointLimitsAggregator, CorrectSettingAccelerationAndDeceleration) +{ + ros::NodeHandle nh("~/valid_1"); + + pilz_industrial_motion_planner::JointLimitsContainer container = + pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits(nh, + robot_model_->getActiveJointModels()); + + for (std::pair lim : container) + { + if (lim.first == "prbt_joint_4") + { + EXPECT_EQ(5.5, container.getLimit(lim.first).max_acceleration) << lim.first; + EXPECT_EQ(-5.5, container.getLimit(lim.first).max_deceleration) << lim.first; + } + else if (lim.first == "prbt_joint_5") + { + EXPECT_EQ(0, container.getLimit(lim.first).max_acceleration) << lim.first; + EXPECT_EQ(-6.6, container.getLimit(lim.first).max_deceleration) << lim.first; + } + else + { + EXPECT_EQ(0, container.getLimit(lim.first).max_acceleration) << lim.first; + EXPECT_EQ(0, container.getLimit(lim.first).max_deceleration) << lim.first; + } + } +} + +/** + * @brief Check that position limit violations are detected properly + */ +TEST_F(JointLimitsAggregator, LimitsViolationPosition) +{ + ros::NodeHandle nh_min("~/violate_position_min"); + + EXPECT_THROW(pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits( + nh_min, robot_model_->getActiveJointModels()), + pilz_industrial_motion_planner::AggregationBoundsViolationException); + + ros::NodeHandle nh_max("~/violate_position_max"); + + EXPECT_THROW(pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits( + nh_max, robot_model_->getActiveJointModels()), + pilz_industrial_motion_planner::AggregationBoundsViolationException); +} + +/** + * @brief Check that velocity limit violations are detected properly + */ +TEST_F(JointLimitsAggregator, LimitsViolationVelocity) +{ + ros::NodeHandle nh("~/violate_velocity"); + + EXPECT_THROW(pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits( + nh, robot_model_->getActiveJointModels()), + pilz_industrial_motion_planner::AggregationBoundsViolationException); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "unittest_joint_limits_aggregator"); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_aggregator.test b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_aggregator.test new file mode 100644 index 0000000000..28177da403 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_aggregator.test @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_container.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_container.cpp new file mode 100644 index 0000000000..2f7f7b80a4 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_container.cpp @@ -0,0 +1,229 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include "pilz_industrial_motion_planner/joint_limits_container.h" +#include "pilz_industrial_motion_planner/joint_limits_extension.h" + +using namespace pilz_industrial_motion_planner; + +class JointLimitsContainerTest : public ::testing::Test +{ +protected: + void SetUp() override + { + JointLimit lim1; + lim1.has_position_limits = true; + lim1.min_position = -2; + lim1.max_position = 2; + lim1.has_acceleration_limits = true; + lim1.max_acceleration = 3; //<- Expected for common_limit_.max_acceleration + + JointLimit lim2; + lim2.has_position_limits = true; + lim2.min_position = -1; //<- Expected for common_limit_.min_position + lim2.max_position = 1; //<- Expected for common_limit_.max_position + lim2.has_deceleration_limits = true; + lim2.max_deceleration = -5; //<- Expected for common_limit_.max_deceleration + + JointLimit lim3; + lim3.has_velocity_limits = true; + lim3.max_velocity = 10; + + JointLimit lim4; + lim4.has_position_limits = true; + lim4.min_position = -1; + lim4.max_position = 1; + lim4.has_acceleration_limits = true; + lim4.max_acceleration = 400; + lim4.has_deceleration_limits = false; + lim4.max_deceleration = -1; + + JointLimit lim5; + lim5.has_position_limits = true; + lim5.min_position = -1; + lim5.max_position = 1; + lim5.has_acceleration_limits = false; + lim5.max_acceleration = 1; + + JointLimit lim6; + lim6.has_velocity_limits = true; + lim6.max_velocity = 2; //<- Expected for common_limit_.max_velocity + lim6.has_deceleration_limits = true; + lim6.max_deceleration = -100; + + container_.addLimit("joint1", lim1); + container_.addLimit("joint2", lim2); + container_.addLimit("joint3", lim3); + container_.addLimit("joint4", lim4); + container_.addLimit("joint5", lim5); + container_.addLimit("joint6", lim6); + + common_limit_ = container_.getCommonLimit(); + } + + pilz_industrial_motion_planner::JointLimitsContainer container_; + JointLimit common_limit_; +}; + +/** + * @brief Check postion + */ +TEST_F(JointLimitsContainerTest, CheckPositionUnification) +{ + EXPECT_EQ(-1, common_limit_.min_position); + EXPECT_EQ(1, common_limit_.max_position); +} + +/** + * @brief Check velocity + */ +TEST_F(JointLimitsContainerTest, CheckVelocityUnification) +{ + EXPECT_EQ(2, common_limit_.max_velocity); +} + +/** + * @brief Check acceleration + */ +TEST_F(JointLimitsContainerTest, CheckAccelerationUnification) +{ + EXPECT_EQ(3, common_limit_.max_acceleration); +} + +/** + * @brief Check deceleration + */ +TEST_F(JointLimitsContainerTest, CheckDecelerationUnification) +{ + EXPECT_EQ(-5, common_limit_.max_deceleration); +} + +/** + * @brief Check AddLimit for positive and null deceleration + */ +TEST_F(JointLimitsContainerTest, CheckAddLimitDeceleration) +{ + JointLimit lim_invalid1; + lim_invalid1.has_deceleration_limits = true; + lim_invalid1.max_deceleration = 0; + + JointLimit lim_invalid2; + lim_invalid2.has_deceleration_limits = true; + lim_invalid2.max_deceleration = 1; + + JointLimit lim_valid; + lim_valid.has_deceleration_limits = true; + lim_valid.max_deceleration = -1; + + pilz_industrial_motion_planner::JointLimitsContainer container; + + EXPECT_EQ(false, container.addLimit("joint_invalid1", lim_invalid1)); + EXPECT_EQ(false, container.addLimit("joint_invalid2", lim_invalid2)); + EXPECT_EQ(true, container.addLimit("joint_valid", lim_valid)); +} + +/** + * @brief Check AddLimit for already contained limit + */ +TEST_F(JointLimitsContainerTest, CheckAddLimitAlreadyContained) +{ + JointLimit lim_valid; + lim_valid.has_deceleration_limits = true; + lim_valid.max_deceleration = -1; + + pilz_industrial_motion_planner::JointLimitsContainer container; + ASSERT_TRUE(container.addLimit("joint_valid", lim_valid)); + EXPECT_FALSE(container.addLimit("joint_valid", lim_valid)); +} + +/** + * @brief An uninitialized container should not have any limits set. + */ +TEST_F(JointLimitsContainerTest, CheckEmptyContainer) +{ + pilz_industrial_motion_planner::JointLimitsContainer container; + JointLimit limits = container.getCommonLimit(); + EXPECT_FALSE(limits.has_position_limits); + EXPECT_FALSE(limits.has_velocity_limits); + EXPECT_FALSE(limits.has_acceleration_limits); +} + +/** + * @brief empty position limits for first joint, second one should be returned + */ +TEST_F(JointLimitsContainerTest, FirstPositionEmpty) +{ + JointLimit lim1; + + JointLimit lim2; + lim2.has_position_limits = true; + lim2.min_position = -1; //<- Expected for common_limit_.min_position + lim2.max_position = 1; //<- Expected for common_limit_.max_position + + pilz_industrial_motion_planner::JointLimitsContainer container; + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + + JointLimit limits = container.getCommonLimit(); + EXPECT_TRUE(limits.has_position_limits); + EXPECT_EQ(1, limits.max_position); + EXPECT_EQ(-1, limits.min_position); +} + +/** + * @brief Check position limits + */ +TEST_F(JointLimitsContainerTest, CheckVerifyPositionLimits) +{ + // positive check: inside limits + std::vector joint_names{ "joint1", "joint2" }; + std::vector joint_positions{ 0.5, 0.5 }; + EXPECT_TRUE(container_.verifyPositionLimits(joint_names, joint_positions)); + + // outside limit2 + joint_positions[1] = 7; + EXPECT_FALSE(container_.verifyPositionLimits(joint_names, joint_positions)); + + // invalid size + std::vector joint_positions1{ 0. }; + EXPECT_THROW(container_.verifyPositionLimits(joint_names, joint_positions1), std::out_of_range); +} + +int main(int argc, char** argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_validator.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_validator.cpp new file mode 100644 index 0000000000..f622cdf8f1 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_joint_limits_validator.cpp @@ -0,0 +1,490 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include "pilz_industrial_motion_planner/joint_limits_extension.h" + +#include "pilz_industrial_motion_planner/joint_limits_validator.h" + +using namespace pilz_industrial_motion_planner; + +class JointLimitsValidatorTest : public ::testing::Test +{ +}; + +/** + * @brief Check postion equality + */ +TEST_F(JointLimitsValidatorTest, CheckPositionEquality) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_position_limits = true; + lim1.min_position = -1; + lim1.max_position = 1; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim1); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check postion inequality in min_position detection + */ +TEST_F(JointLimitsValidatorTest, CheckPositionInEqualityMinPosition) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_position_limits = true; + lim1.min_position = -1; + lim1.max_position = 1; + + JointLimit lim2; + lim2.has_position_limits = true; + lim2.min_position = -2; + lim2.max_position = 1; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + + EXPECT_EQ(false, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check postion inequality in max_position detection + */ +TEST_F(JointLimitsValidatorTest, CheckPositionInEqualityMaxPosition1) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_position_limits = true; + lim1.min_position = -1; + lim1.max_position = 2; + + JointLimit lim2; + lim2.has_position_limits = true; + lim2.min_position = -1; + lim2.max_position = 1; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + + EXPECT_EQ(false, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check postion inequality in max_position detection (using 3 limits) + */ +TEST_F(JointLimitsValidatorTest, CheckPositionInEqualityMaxPosition2) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_position_limits = true; + lim1.min_position = -1; + lim1.max_position = 2; + + JointLimit lim2; + lim2.has_position_limits = true; + lim2.min_position = -1; + lim2.max_position = 1; + + JointLimit lim3; + lim3.has_position_limits = true; + lim3.min_position = -1; + lim3.max_position = 1; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + container.addLimit("joint3", lim3); + + EXPECT_EQ(false, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check postion inequality in has_position_limits false detection + */ +TEST_F(JointLimitsValidatorTest, CheckPositionInEqualityHasPositionLimits) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_position_limits = true; + lim1.min_position = -1; + lim1.max_position = 1; + + JointLimit lim2; + lim2.has_position_limits = false; + lim2.min_position = -1; + lim2.max_position = 1; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + + EXPECT_EQ(false, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +//---------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------- +// VELOCITY +//---------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------- + +/** + * @brief Check velocity equality + */ +TEST_F(JointLimitsValidatorTest, CheckVelocityEquality) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_velocity_limits = true; + lim1.max_velocity = 1; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim1); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check max_velocity inequality + */ +TEST_F(JointLimitsValidatorTest, CheckPositionInEqualityMaxVelocity1) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_velocity_limits = true; + lim1.max_velocity = 1; + + JointLimit lim2; + lim2.has_velocity_limits = true; + lim2.max_velocity = 2; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(false, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check max_velocity inequality (using 3Limits) + */ +TEST_F(JointLimitsValidatorTest, CheckPositionInEqualityMaxVelocity2) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_velocity_limits = true; + lim1.max_velocity = 1; + + JointLimit lim2; + lim2.has_velocity_limits = true; + lim2.max_velocity = 2; + + JointLimit lim3; + lim3.has_velocity_limits = true; + lim3.max_velocity = 2; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + container.addLimit("joint3", lim3); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(false, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check postion inequality in has_position_limits false detection + */ +TEST_F(JointLimitsValidatorTest, CheckPositionInEqualityHasVelocityLimits) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_velocity_limits = true; + + JointLimit lim2; + lim2.has_velocity_limits = false; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(false, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +//---------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------- +// ACCELERATION +//---------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------- + +/** + * @brief Check acceleration equality + */ +TEST_F(JointLimitsValidatorTest, CheckAccelerationEquality) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_acceleration_limits = true; + lim1.max_acceleration = 1; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim1); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check max_acceleration inequality + */ +TEST_F(JointLimitsValidatorTest, CheckPositionInEqualityMaxAcceleration1) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_acceleration_limits = true; + lim1.max_acceleration = 1; + + JointLimit lim2; + lim2.has_acceleration_limits = true; + lim2.max_acceleration = 2; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(false, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check max_acceleration inequality (using 3 Limits) + */ +TEST_F(JointLimitsValidatorTest, CheckPositionInEqualityMaxAcceleration2) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_acceleration_limits = true; + lim1.max_acceleration = 1; + + JointLimit lim2; + lim2.has_acceleration_limits = true; + lim2.max_acceleration = 2; + + JointLimit lim3; + lim3.has_acceleration_limits = true; + lim3.max_acceleration = 2; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + container.addLimit("joint3", lim3); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(false, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check acceleration inequality in has_acceleration_limits false + * detection + */ +TEST_F(JointLimitsValidatorTest, CheckPositionInEqualityHasAccelerationLimits) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_acceleration_limits = true; + + JointLimit lim2; + lim2.has_acceleration_limits = false; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(false, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +//---------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------- +// DECELERATION +//---------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------- + +/** + * @brief Check deceleration equality + */ +TEST_F(JointLimitsValidatorTest, CheckDecelerationEquality) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_deceleration_limits = true; + lim1.max_deceleration = 1; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim1); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check max_deceleration inequality + */ +TEST_F(JointLimitsValidatorTest, CheckInEqualityMaxDeceleration1) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_deceleration_limits = true; + lim1.max_deceleration = -1; + + JointLimit lim2; + lim2.has_deceleration_limits = true; + lim2.max_deceleration = -2; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(false, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check max_deceleration inequality + */ +TEST_F(JointLimitsValidatorTest, CheckInEqualityMaxDeceleration2) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_deceleration_limits = true; + lim1.max_deceleration = -1; + + JointLimit lim2; + lim2.has_deceleration_limits = true; + lim2.max_deceleration = -2; + + JointLimit lim3; + lim3.has_deceleration_limits = true; + lim3.max_deceleration = -2; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + container.addLimit("joint3", lim3); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(false, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +/** + * @brief Check deceleration inequality in has_deceleration_limits false + * detection + */ +TEST_F(JointLimitsValidatorTest, CheckInEqualityHasDecelerationLimits) +{ + JointLimitsContainer container; + + JointLimit lim1; + lim1.has_deceleration_limits = true; + lim1.max_deceleration = -1; + + JointLimit lim2; + lim2.has_deceleration_limits = false; + + container.addLimit("joint1", lim1); + container.addLimit("joint2", lim2); + + ASSERT_EQ(2u, container.getCount()); + + EXPECT_EQ(true, JointLimitsValidator::validateAllPositionLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllVelocityLimitsEqual(container)); + EXPECT_EQ(true, JointLimitsValidator::validateAllAccelerationLimitsEqual(container)); + EXPECT_EQ(false, JointLimitsValidator::validateAllDecelerationLimitsEqual(container)); +} + +int main(int argc, char** argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_pilz_industrial_motion_planner.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_pilz_industrial_motion_planner.cpp new file mode 100644 index 0000000000..f413cb835a --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_pilz_industrial_motion_planner.cpp @@ -0,0 +1,232 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include + +#include +#include + +#include "pilz_industrial_motion_planner/pilz_industrial_motion_planner.h" +#include "test_utils.h" + +const std::string PARAM_MODEL_NO_GRIPPER_NAME{ "robot_description" }; +const std::string PARAM_MODEL_WITH_GRIPPER_NAME{ "robot_description_pg70" }; + +class CommandPlannerTest : public testing::TestWithParam +{ +protected: + void SetUp() override + { + createPlannerInstance(); + } + + /** + * @brief initialize the planner plugin + * The planner is loaded using the pluginlib. Checks that the planner was + * loaded properly. + * Exceptions will cause test failure. + * + * This function should be called only once during initialization of the + * class. + */ + void createPlannerInstance() + { + // Load planner name from parameter server + if (!ph_.getParam("planning_plugin", planner_plugin_name_)) + { + ROS_FATAL_STREAM("Could not find planner plugin name"); + FAIL(); + } + + // Load the plugin + try + { + planner_plugin_loader_.reset(new pluginlib::ClassLoader( + "moveit_core", "planning_interface::PlannerManager")); + } + catch (pluginlib::PluginlibException& ex) + { + ROS_FATAL_STREAM("Exception while creating planning plugin loader " << ex.what()); + FAIL(); + } + + // Create planner + try + { + planner_instance_.reset(planner_plugin_loader_->createUnmanagedInstance(planner_plugin_name_)); + ASSERT_TRUE(planner_instance_->initialize(robot_model_, ph_.getNamespace())) + << "Initialzing the planner instance failed."; + } + catch (pluginlib::PluginlibException& ex) + { + FAIL() << "Could not create planner " << ex.what() << "\n"; + } + } + + void TearDown() override + { + planner_plugin_loader_->unloadLibraryForClass(planner_plugin_name_); + } + +protected: + // ros stuff + ros::NodeHandle ph_{ "~" }; + robot_model::RobotModelConstPtr robot_model_{ robot_model_loader::RobotModelLoader(GetParam()).getModel() }; + + std::string planner_plugin_name_; + + std::unique_ptr> planner_plugin_loader_; + + planning_interface::PlannerManagerPtr planner_instance_; +}; + +// Instantiate the test cases for robot model with and without gripper +INSTANTIATE_TEST_SUITE_P(InstantiationName, CommandPlannerTest, + ::testing::Values(PARAM_MODEL_NO_GRIPPER_NAME, PARAM_MODEL_WITH_GRIPPER_NAME)); + +/** + * @brief Test that PTP can be loaded + * This needs to be extended with every new planning Algorithm + */ +TEST_P(CommandPlannerTest, ObtainLoadedPlanningAlgorithms) +{ + // Check for the algorithms + std::vector algs; + + planner_instance_->getPlanningAlgorithms(algs); + ASSERT_EQ(3u, algs.size()) << "Found more or less planning algorithms as expected! Found:" + << ::testing::PrintToString(algs); + + // Collect the algorithms, check for uniqueness + std::set algs_set; + for (const auto& alg : algs) + { + algs_set.insert(alg); + } + ASSERT_EQ(algs.size(), algs_set.size()) << "There are two or more algorithms with the same name!"; + ASSERT_TRUE(algs_set.find("LIN") != algs_set.end()); + ASSERT_TRUE(algs_set.find("PTP") != algs_set.end()); + ASSERT_TRUE(algs_set.find("CIRC") != algs_set.end()); +} + +/** + * @brief Check that all announced planning algorithms can perform the service + * request if the planner_id is set. + */ +TEST_P(CommandPlannerTest, CheckValidAlgorithmsForServiceRequest) +{ + // Check for the algorithms + std::vector algs; + planner_instance_->getPlanningAlgorithms(algs); + + for (const auto& alg : algs) + { + planning_interface::MotionPlanRequest req; + req.planner_id = alg; + + EXPECT_TRUE(planner_instance_->canServiceRequest(req)); + } +} + +/** + * @brief Check that canServiceRequest(req) returns false if planner_id is not + * supported + */ +TEST_P(CommandPlannerTest, CheckInvalidAlgorithmsForServiceRequest) +{ + planning_interface::MotionPlanRequest req; + req.planner_id = "NON_EXISTEND_ALGORITHM_HASH_da39a3ee5e6b4b0d3255bfef95601890afd80709"; + + EXPECT_FALSE(planner_instance_->canServiceRequest(req)); +} + +/** + * @brief Check that canServiceRequest(req) returns false if planner_id is empty + */ +TEST_P(CommandPlannerTest, CheckEmptyPlannerIdForServiceRequest) +{ + planning_interface::MotionPlanRequest req; + req.planner_id = ""; + + EXPECT_FALSE(planner_instance_->canServiceRequest(req)); +} + +/** + * @brief Check integrety against empty input + */ +TEST_P(CommandPlannerTest, CheckPlanningContextRequestNull) +{ + moveit_msgs::MotionPlanRequest req; + moveit_msgs::MoveItErrorCodes error_code; + EXPECT_EQ(nullptr, planner_instance_->getPlanningContext(nullptr, req, error_code)); +} + +/** + * @brief Check that for the announced algorithmns getPlanningContext does not + * return nullptr + */ +TEST_P(CommandPlannerTest, CheckPlanningContextRequest) +{ + moveit_msgs::MotionPlanRequest req; + moveit_msgs::MoveItErrorCodes error_code; + + // Check for the algorithms + std::vector algs; + planner_instance_->getPlanningAlgorithms(algs); + + for (const auto& alg : algs) + { + req.planner_id = alg; + + EXPECT_NE(nullptr, planner_instance_->getPlanningContext(nullptr, req, error_code)); + } +} + +/** + * @brief Check the description can be obtained and is not empty + */ +TEST_P(CommandPlannerTest, CheckPlanningContextDescriptionNotEmptyAndStable) +{ + std::string desc = planner_instance_->getDescription(); + EXPECT_GT(desc.length(), 0u); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "unittest_pilz_industrial_motion_planner"); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_pilz_industrial_motion_planner.test b/moveit_planners/pilz_industrial_motion_planner/test/unittest_pilz_industrial_motion_planner.test new file mode 100644 index 0000000000..574f005626 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_pilz_industrial_motion_planner.test @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_pilz_industrial_motion_planner_direct.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_pilz_industrial_motion_planner_direct.cpp new file mode 100644 index 0000000000..35bb528d27 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_pilz_industrial_motion_planner_direct.cpp @@ -0,0 +1,121 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include + +#include "pilz_industrial_motion_planner/pilz_industrial_motion_planner.h" +#include "pilz_industrial_motion_planner/planning_context_loader_ptp.h" +#include "pilz_industrial_motion_planner/planning_exceptions.h" + +using namespace pilz_industrial_motion_planner; + +TEST(CommandPlannerTestDirect, ExceptionCoverage) +{ + std::shared_ptr p_ex{ new PlanningException("") }; + std::shared_ptr clr_ex{ new ContextLoaderRegistrationException("") }; +} + +/** + * This test uses pilz_industrial_motion_planner::CommandPlanner directly and + * is thus seperated from + * unittest_pilz_industrial_motion_planner.cpp since plugin loading via + * pluginlib does not allow loading of classes + * already + * defined. + */ + +/** + * @brief Check that a exception is thrown if a already loaded + * PlanningContextLoader is loaded + * + * It this point the planning_instance_ has loaded ptp, lin, circ. + * A additional ptp is loaded which should throw the respective exception. + */ +TEST(CommandPlannerTestDirect, CheckDoubleLoadingException) +{ + /// Registed a found loader + pilz_industrial_motion_planner::CommandPlanner planner; + pilz_industrial_motion_planner::PlanningContextLoaderPtr planning_context_loader( + new pilz_industrial_motion_planner::PlanningContextLoaderPTP()); + + EXPECT_NO_THROW(planner.registerContextLoader(planning_context_loader)); + + EXPECT_THROW(planner.registerContextLoader(planning_context_loader), + pilz_industrial_motion_planner::ContextLoaderRegistrationException); +} + +/** + * @brief Check that getPlanningContext() fails if the underlying ContextLoader + * fails to load the context. + */ +TEST(CommandPlannerTestDirect, FailOnLoadContext) +{ + pilz_industrial_motion_planner::CommandPlanner planner; + + // Mock of failing PlanningContextLoader + class TestPlanningContextLoader : public pilz_industrial_motion_planner::PlanningContextLoader + { + public: + std::string getAlgorithm() const override + { + return "Test_Algorithm"; + } + + bool loadContext(planning_interface::PlanningContextPtr& /* planning_context */, const std::string& /* name */, + const std::string& /* group */) const override + { + // Mock behaviour: Cannot load planning context. + return false; + } + }; + + /// Registed a found loader + pilz_industrial_motion_planner::PlanningContextLoaderPtr planning_context_loader(new TestPlanningContextLoader()); + planner.registerContextLoader(planning_context_loader); + + moveit_msgs::MotionPlanRequest req; + req.planner_id = "Test_Algorithm"; + + moveit_msgs::MoveItErrorCodes error_code; + EXPECT_FALSE(planner.getPlanningContext(nullptr, req, error_code)); + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::PLANNING_FAILED, error_code.val); +} + +int main(int argc, char** argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context.cpp new file mode 100644 index 0000000000..016c612e0a --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context.cpp @@ -0,0 +1,282 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include "pilz_industrial_motion_planner/joint_limits_container.h" +#include "pilz_industrial_motion_planner/planning_context_circ.h" +#include "pilz_industrial_motion_planner/planning_context_lin.h" +#include "pilz_industrial_motion_planner/planning_context_ptp.h" + +#include "test_utils.h" + +const std::string PARAM_MODEL_NO_GRIPPER_NAME{ "robot_description" }; +const std::string PARAM_MODEL_WITH_GRIPPER_NAME{ "robot_description_pg70" }; + +// parameters from parameter server +const std::string PARAM_PLANNING_GROUP_NAME("planning_group"); +const std::string PARAM_TARGET_LINK_NAME("target_link"); + +/** + * A value type container to combine type and value + * In the tests types are trajectory generators. + * value = 0 refers to robot model without gripper + * value = 1 refers to robot model with gripper + */ +template +class ValueTypeContainer +{ +public: + typedef T Type_; + static const int VALUE = N; +}; +template +const int ValueTypeContainer::VALUE; + +typedef ValueTypeContainer PTP_NO_GRIPPER; +typedef ValueTypeContainer PTP_WITH_GRIPPER; +typedef ValueTypeContainer LIN_NO_GRIPPER; +typedef ValueTypeContainer LIN_WITH_GRIPPER; +typedef ValueTypeContainer CIRC_NO_GRIPPER; +typedef ValueTypeContainer CIRC_WITH_GRIPPER; + +typedef ::testing::Types + PlanningContextTestTypes; + +/** + * type parameterized test fixture + */ +template +class PlanningContextTest : public ::testing::Test +{ +protected: + void SetUp() override + { + ASSERT_FALSE(robot_model_ == nullptr) << "There is no robot model!"; + + // get parameters + ASSERT_TRUE(ph_.getParam(PARAM_PLANNING_GROUP_NAME, planning_group_)); + ASSERT_TRUE(ph_.getParam(PARAM_TARGET_LINK_NAME, target_link_)); + + pilz_industrial_motion_planner::JointLimitsContainer joint_limits = + testutils::createFakeLimits(robot_model_->getVariableNames()); + pilz_industrial_motion_planner::CartesianLimit cartesian_limit; + cartesian_limit.setMaxRotationalVelocity(1.0 * M_PI); + cartesian_limit.setMaxTranslationalAcceleration(1.0 * M_PI); + cartesian_limit.setMaxTranslationalDeceleration(1.0 * M_PI); + cartesian_limit.setMaxTranslationalVelocity(1.0 * M_PI); + + pilz_industrial_motion_planner::LimitsContainer limits; + limits.setJointLimits(joint_limits); + limits.setCartesianLimits(cartesian_limit); + + planning_context_ = std::unique_ptr( + new typename T::Type_("TestPlanningContext", "TestGroup", robot_model_, limits)); + + // Define and set the current scene + planning_scene::PlanningScenePtr scene(new planning_scene::PlanningScene(robot_model_)); + robot_state::RobotState current_state(robot_model_); + current_state.setToDefaultValues(); + current_state.setJointGroupPositions(planning_group_, { 0, 1.57, 1.57, 0, 0.2, 0 }); + scene->setCurrentState(current_state); + planning_context_->setPlanningScene(scene); // TODO Check what happens if this is missing + } + + /** + * @brief Generate a valid fully defined request + */ + planning_interface::MotionPlanRequest getValidRequest(const std::string& context_name) const + { + planning_interface::MotionPlanRequest req; + + req.planner_id = + std::string(context_name).erase(0, std::string("pilz_industrial_motion_planner::PlanningContext").length()); + req.group_name = this->planning_group_; + req.max_velocity_scaling_factor = 0.01; + req.max_acceleration_scaling_factor = 0.01; + + // start state + robot_state::RobotState rstate(this->robot_model_); + rstate.setToDefaultValues(); + // state state in joint space, used as initial positions, since IK does not + // work at zero positions + rstate.setJointGroupPositions(this->planning_group_, + { 4.430233957464225e-12, 0.007881892504574495, -1.8157263253868452, + 1.1801525390026025e-11, 1.8236082178909834, 8.591793942969161e-12 }); + Eigen::Isometry3d start_pose(Eigen::Isometry3d::Identity()); + start_pose.translation() = Eigen::Vector3d(0.3, 0, 0.65); + rstate.setFromIK(this->robot_model_->getJointModelGroup(this->planning_group_), start_pose); + moveit::core::robotStateToRobotStateMsg(rstate, req.start_state, false); + + // goal constraint + Eigen::Isometry3d goal_pose(Eigen::Isometry3d::Identity()); + goal_pose.translation() = Eigen::Vector3d(0, 0.3, 0.65); + Eigen::Matrix3d goal_rotation; + goal_rotation = Eigen::AngleAxisd(0 * M_PI, Eigen::Vector3d::UnitZ()); + goal_pose.linear() = goal_rotation; + rstate.setFromIK(this->robot_model_->getJointModelGroup(this->planning_group_), goal_pose); + req.goal_constraints.push_back(kinematic_constraints::constructGoalConstraints( + rstate, this->robot_model_->getJointModelGroup(this->planning_group_))); + + // path constraint + req.path_constraints.name = "center"; + moveit_msgs::PositionConstraint center_point; + center_point.link_name = this->target_link_; + geometry_msgs::Pose center_position; + center_position.position.x = 0.0; + center_position.position.y = 0.0; + center_position.position.z = 0.65; + center_point.constraint_region.primitive_poses.push_back(center_position); + req.path_constraints.position_constraints.push_back(center_point); + + return req; + } + +protected: + // ros stuff + ros::NodeHandle ph_{ "~" }; + robot_model::RobotModelConstPtr robot_model_{ + robot_model_loader::RobotModelLoader(!T::VALUE ? PARAM_MODEL_NO_GRIPPER_NAME : PARAM_MODEL_WITH_GRIPPER_NAME) + .getModel() + }; + + std::unique_ptr planning_context_; + + std::string planning_group_, target_link_; +}; + +// Define the types we need to test +TYPED_TEST_SUITE(PlanningContextTest, PlanningContextTestTypes); + +/** + * @brief No request is set. Check the output of solve. Using robot model + * without gripper. + */ +TYPED_TEST(PlanningContextTest, NoRequest) +{ + planning_interface::MotionPlanResponse res; + bool result = this->planning_context_->solve(res); + + EXPECT_FALSE(result) << testutils::demangel(typeid(TypeParam).name()); + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN, res.error_code_.val) + << testutils::demangel(typeid(TypeParam).name()); +} + +/** + * @brief Solve a valid request. + */ +TYPED_TEST(PlanningContextTest, SolveValidRequest) +{ + planning_interface::MotionPlanResponse res; + planning_interface::MotionPlanRequest req = this->getValidRequest(testutils::demangel(typeid(TypeParam).name())); + + this->planning_context_->setMotionPlanRequest(req); + + // TODO Formulate valid request + bool result = this->planning_context_->solve(res); + + EXPECT_TRUE(result) << testutils::demangel(typeid(TypeParam).name()); + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, res.error_code_.val) + << testutils::demangel(typeid(TypeParam).name()); + + planning_interface::MotionPlanDetailedResponse res_detailed; + bool result_detailed = this->planning_context_->solve(res_detailed); + + EXPECT_TRUE(result_detailed) << testutils::demangel(typeid(TypeParam).name()); + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, res.error_code_.val) + << testutils::demangel(typeid(TypeParam).name()); +} + +/** + * @brief Solve a valid request. Expect a detailed response. + */ +TYPED_TEST(PlanningContextTest, SolveValidRequestDetailedResponse) +{ + planning_interface::MotionPlanDetailedResponse res; //<-- Detailed! + planning_interface::MotionPlanRequest req = this->getValidRequest(testutils::demangel(typeid(TypeParam).name())); + + this->planning_context_->setMotionPlanRequest(req); + bool result = this->planning_context_->solve(res); + + EXPECT_TRUE(result) << testutils::demangel(typeid(TypeParam).name()); + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::SUCCESS, res.error_code_.val) + << testutils::demangel(typeid(TypeParam).name()); +} + +/** + * @brief Call solve on a terminated context. + */ +TYPED_TEST(PlanningContextTest, SolveOnTerminated) +{ + planning_interface::MotionPlanResponse res; + planning_interface::MotionPlanRequest req = this->getValidRequest(testutils::demangel(typeid(TypeParam).name())); + + this->planning_context_->setMotionPlanRequest(req); + + bool result_termination = this->planning_context_->terminate(); + EXPECT_TRUE(result_termination) << testutils::demangel(typeid(TypeParam).name()); + + bool result = this->planning_context_->solve(res); + EXPECT_FALSE(result) << testutils::demangel(typeid(TypeParam).name()); + + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::PLANNING_FAILED, res.error_code_.val) + << testutils::demangel(typeid(TypeParam).name()); +} + +/** + * @brief Check if clear can be called. So far only stability is expected. + */ +TYPED_TEST(PlanningContextTest, Clear) +{ + EXPECT_NO_THROW(this->planning_context_->clear()) << testutils::demangel(typeid(TypeParam).name()); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "unittest_planning_context"); + // ros::NodeHandle nh; + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context.test b/moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context.test new file mode 100644 index 0000000000..048e67c804 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context.test @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context_loaders.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context_loaders.cpp new file mode 100644 index 0000000000..a8926ed17e --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context_loaders.cpp @@ -0,0 +1,179 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +// Boost includes +#include + +#include + +#include +#include + +#include "pilz_industrial_motion_planner/planning_context_loader.h" + +#include "test_utils.h" + +const std::string PARAM_MODEL_NO_GRIPPER_NAME{ "robot_description" }; +const std::string PARAM_MODEL_WITH_GRIPPER_NAME{ "robot_description_pg70" }; + +class PlanningContextLoadersTest : public ::testing::TestWithParam> +{ +protected: + /** + * @brief To initialize the planning context loader + * The planning context loader is loaded using the pluginlib. + * Checks if planning context loader was loaded properly are performed. + * Exceptions will cause test failure. + */ + void SetUp() override + { + ASSERT_FALSE(robot_model_ == nullptr) << "There is no robot model!"; + + // Load the plugin + try + { + planning_context_loader_class_loader_.reset( + new pluginlib::ClassLoader( + "pilz_industrial_motion_planner", "pilz_industrial_motion_planner::PlanningContextLoader")); + } + catch (pluginlib::PluginlibException& ex) + { + ROS_FATAL_STREAM("Exception while creating planning context loader " << ex.what()); + FAIL(); + } + + // Create planning context loader ptp + try + { + planning_context_loader_.reset(planning_context_loader_class_loader_->createUnmanagedInstance(GetParam().front())); + } + catch (pluginlib::PluginlibException& ex) + { + FAIL() << ex.what(); + } + return; + } + + void TearDown() override + { + if (planning_context_loader_class_loader_) + { + planning_context_loader_class_loader_->unloadLibraryForClass(GetParam().front()); + } + } + +protected: + ros::NodeHandle ph_{ "~" }; + robot_model::RobotModelConstPtr robot_model_{ robot_model_loader::RobotModelLoader(GetParam().back()).getModel() }; + + // Load the plugin + boost::scoped_ptr> + planning_context_loader_class_loader_; + + pilz_industrial_motion_planner::PlanningContextLoaderPtr planning_context_loader_; +}; + +// Instantiate the test cases for all loaders, extend here if you added a new +// ContextLoader you want to test +INSTANTIATE_TEST_SUITE_P( + InstantiationName, PlanningContextLoadersTest, + ::testing::Values(std::vector{ "pilz_industrial_motion_planner::PlanningContextLoaderPTP", "PTP", + PARAM_MODEL_NO_GRIPPER_NAME }, // Test for PTP + std::vector{ "pilz_industrial_motion_planner::PlanningContextLoaderPTP", "PTP", + PARAM_MODEL_WITH_GRIPPER_NAME }, // Test for PTP + std::vector{ "pilz_industrial_motion_planner::PlanningContextLoaderLIN", "LIN", + PARAM_MODEL_NO_GRIPPER_NAME }, // Test for LIN + std::vector{ "pilz_industrial_motion_planner::PlanningContextLoaderLIN", "LIN", + PARAM_MODEL_WITH_GRIPPER_NAME }, // Test for LIN + std::vector{ "pilz_industrial_motion_planner::PlanningContextLoaderCIRC", "CIRC", + PARAM_MODEL_NO_GRIPPER_NAME }, // Test for CIRC + std::vector{ "pilz_industrial_motion_planner::PlanningContextLoaderCIRC", "CIRC", + PARAM_MODEL_WITH_GRIPPER_NAME } // Test for CIRC + )); + +/** + * @brief Test getAlgorithm returns PTP + */ +TEST_P(PlanningContextLoadersTest, GetAlgorithm) +{ + std::string alg = planning_context_loader_->getAlgorithm(); + EXPECT_EQ(alg, GetParam().at(1)); +} + +/** + * @brief Check that load Context returns initialized shared pointer + */ +TEST_P(PlanningContextLoadersTest, LoadContext) +{ + planning_interface::PlanningContextPtr planning_context; + + // Without limits should return false + bool res = planning_context_loader_->loadContext(planning_context, "test", "test"); + EXPECT_EQ(false, res) << "Context returned even when no limits where set"; + + // After setting the limits this should work + pilz_industrial_motion_planner::JointLimitsContainer joint_limits = + testutils::createFakeLimits(robot_model_->getVariableNames()); + pilz_industrial_motion_planner::LimitsContainer limits; + limits.setJointLimits(joint_limits); + pilz_industrial_motion_planner::CartesianLimit cart_limits; + cart_limits.setMaxRotationalVelocity(1 * M_PI); + cart_limits.setMaxTranslationalAcceleration(2); + cart_limits.setMaxTranslationalDeceleration(2); + cart_limits.setMaxTranslationalVelocity(1); + limits.setCartesianLimits(cart_limits); + + planning_context_loader_->setLimits(limits); + planning_context_loader_->setModel(robot_model_); + + try + { + res = planning_context_loader_->loadContext(planning_context, "test", "test"); + } + catch (std::exception& ex) + { + FAIL() << "Exception!" << ex.what() << " " << typeid(ex).name(); + } + + EXPECT_EQ(true, res) << "Context could not be loaded!"; +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "unittest_planning_context_loaders"); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context_loaders.test b/moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context_loaders.test new file mode 100644 index 0000000000..766bc1af98 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_planning_context_loaders.test @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_blender_transition_window.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_blender_transition_window.cpp new file mode 100644 index 0000000000..0b34d00991 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_blender_transition_window.cpp @@ -0,0 +1,727 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "pilz_industrial_motion_planner/joint_limits_aggregator.h" +#include "pilz_industrial_motion_planner/trajectory_blend_request.h" +#include "pilz_industrial_motion_planner/trajectory_blend_response.h" +#include "pilz_industrial_motion_planner/trajectory_blender_transition_window.h" +#include "pilz_industrial_motion_planner/trajectory_generator_lin.h" +#include "test_utils.h" + +const std::string PARAM_MODEL_NO_GRIPPER_NAME{ "robot_description" }; +const std::string PARAM_MODEL_WITH_GRIPPER_NAME{ "robot_description_pg70" }; + +// parameters from parameter server +const std::string PARAM_PLANNING_GROUP_NAME("planning_group"); +const std::string PARAM_TARGET_LINK_NAME("target_link"); +const std::string CARTESIAN_VELOCITY_TOLERANCE("cartesian_velocity_tolerance"); +const std::string CARTESIAN_ANGULAR_VELOCITY_TOLERANCE("cartesian_angular_velocity_tolerance"); +const std::string JOINT_VELOCITY_TOLERANCE("joint_velocity_tolerance"); +const std::string JOINT_ACCELERATION_TOLERANCE("joint_acceleration_tolerance"); +const std::string OTHER_TOLERANCE("other_tolerance"); +const std::string SAMPLING_TIME("sampling_time"); +const std::string TEST_DATA_FILE_NAME("testdata_file_name"); + +using namespace pilz_industrial_motion_planner; +using namespace pilz_industrial_motion_planner_testutils; + +class TrajectoryBlenderTransitionWindowTest : public testing::TestWithParam +{ +protected: + /** + * @brief Create test scenario for trajectory blender + * + */ + void SetUp() override; + + /** + * @brief Generate lin trajectories for blend sequences + */ + std::vector generateLinTrajs(const Sequence& seq, size_t num_cmds); + +protected: + // ros stuff + ros::NodeHandle ph_{ "~" }; + robot_model::RobotModelConstPtr robot_model_{ robot_model_loader::RobotModelLoader(GetParam()).getModel() }; + + std::unique_ptr lin_generator_; + std::unique_ptr blender_; + + // test parameters from parameter server + std::string planning_group_, target_link_; + double cartesian_velocity_tolerance_, cartesian_angular_velocity_tolerance_, joint_velocity_tolerance_, + joint_acceleration_tolerance_, sampling_time_; + LimitsContainer planner_limits_; + + std::string test_data_file_name_; + XmlTestDataLoaderUPtr data_loader_; +}; + +void TrajectoryBlenderTransitionWindowTest::SetUp() +{ + // get parameters + ASSERT_TRUE(ph_.getParam(PARAM_PLANNING_GROUP_NAME, planning_group_)); + ASSERT_TRUE(ph_.getParam(PARAM_TARGET_LINK_NAME, target_link_)); + ASSERT_TRUE(ph_.getParam(CARTESIAN_VELOCITY_TOLERANCE, cartesian_velocity_tolerance_)); + ASSERT_TRUE(ph_.getParam(CARTESIAN_ANGULAR_VELOCITY_TOLERANCE, cartesian_angular_velocity_tolerance_)); + ASSERT_TRUE(ph_.getParam(JOINT_VELOCITY_TOLERANCE, joint_velocity_tolerance_)); + ASSERT_TRUE(ph_.getParam(JOINT_ACCELERATION_TOLERANCE, joint_acceleration_tolerance_)); + ASSERT_TRUE(ph_.getParam(SAMPLING_TIME, sampling_time_)); + ASSERT_TRUE(ph_.getParam(TEST_DATA_FILE_NAME, test_data_file_name_)); + + // load the test data provider + data_loader_.reset(new XmlTestdataLoader(test_data_file_name_, robot_model_)); + ASSERT_NE(nullptr, data_loader_) << "Failed to load test data by provider."; + + // check robot model + testutils::checkRobotModel(robot_model_, planning_group_, target_link_); + + // create the limits container + pilz_industrial_motion_planner::JointLimitsContainer joint_limits = + pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits(ph_, + robot_model_->getActiveJointModels()); + CartesianLimit cart_limits; + cart_limits.setMaxRotationalVelocity(1 * M_PI); + cart_limits.setMaxTranslationalAcceleration(2); + cart_limits.setMaxTranslationalDeceleration(2); + cart_limits.setMaxTranslationalVelocity(1); + planner_limits_.setJointLimits(joint_limits); + planner_limits_.setCartesianLimits(cart_limits); + + // initialize trajectory generators and blender + lin_generator_.reset(new TrajectoryGeneratorLIN(robot_model_, planner_limits_)); + ASSERT_NE(nullptr, lin_generator_) << "failed to create LIN trajectory generator"; + blender_.reset(new TrajectoryBlenderTransitionWindow(planner_limits_)); + ASSERT_NE(nullptr, blender_) << "failed to create trajectory blender"; +} + +std::vector +TrajectoryBlenderTransitionWindowTest::generateLinTrajs(const Sequence& seq, size_t num_cmds) +{ + std::vector responses(num_cmds); + + for (size_t index = 0; index < num_cmds; ++index) + { + planning_interface::MotionPlanRequest req{ seq.getCmd(index).toRequest() }; + // Set start state of request to end state of previous trajectory (except + // for first) + if (index > 0) + { + moveit::core::robotStateToRobotStateMsg(responses[index - 1].trajectory_->getLastWayPoint(), req.start_state); + } + // generate trajectory + planning_interface::MotionPlanResponse resp; + if (!lin_generator_->generate(req, resp, sampling_time_)) + { + std::runtime_error("Failed to generate trajectory."); + } + responses.at(index) = resp; + } + return responses; +} + +// Instantiate the test cases for robot model with and without gripper +INSTANTIATE_TEST_SUITE_P(InstantiationName, TrajectoryBlenderTransitionWindowTest, + ::testing::Values(PARAM_MODEL_NO_GRIPPER_NAME, PARAM_MODEL_WITH_GRIPPER_NAME)); + +/** + * @brief Tests the blending of two trajectories with an invalid group name. + * + * Test Sequence: + * 1. Generate two linear trajectories. + * 2. Try to generate blending trajectory with invalid group name. + * + * Expected Results: + * 1. Two linear trajectories generated. + * 2. Blending trajectory cannot be generated. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testInvalidGroupName) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + + std::vector res{ generateLinTrajs(seq, 2) }; + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_req; + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_res; + + blend_req.group_name = "invalid_group_name"; + blend_req.link_name = target_link_; + blend_req.first_trajectory = res.at(0).trajectory_; + blend_req.second_trajectory = res.at(1).trajectory_; + + blend_req.blend_radius = seq.getBlendRadius(0); + EXPECT_FALSE(blender_->blend(blend_req, blend_res)); +} + +/** + * @brief Tests the blending of two trajectories with an invalid target link. + * + * Test Sequence: + * 1. Generate two linear trajectories. + * 2. Try to generate blending trajectory with invalid target link. + * + * Expected Results: + * 1. Two linear trajectories generated. + * 2. Blending trajectory cannot be generated. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testInvalidTargetLink) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + + std::vector res{ generateLinTrajs(seq, 2) }; + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_req; + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_res; + + blend_req.group_name = planning_group_; + blend_req.link_name = "invalid_target_link"; + blend_req.first_trajectory = res.at(0).trajectory_; + blend_req.second_trajectory = res.at(1).trajectory_; + + blend_req.blend_radius = seq.getBlendRadius(0); + EXPECT_FALSE(blender_->blend(blend_req, blend_res)); +} + +/** + * @brief Tests the blending of two trajectories with a negative blending + * radius. + * + * Test Sequence: + * 1. Generate two linear trajectories. + * 2. Try to generate blending trajectory with negative blending radius. + * + * Expected Results: + * 1. Two linear trajectories generated. + * 2. Blending trajectory cannot be generated. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testNegativeRadius) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + + std::vector res{ generateLinTrajs(seq, 2) }; + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_req; + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_res; + + blend_req.group_name = planning_group_; + blend_req.link_name = target_link_; + blend_req.first_trajectory = res.at(0).trajectory_; + blend_req.second_trajectory = res.at(1).trajectory_; + + blend_req.blend_radius = -0.1; + EXPECT_FALSE(blender_->blend(blend_req, blend_res)); +} + +/** + * @brief Tests the blending of two trajectories with zero blending radius. + * + * Test Sequence: + * 1. Generate two linear trajectories. + * 2. Try to generate blending trajectory with zero blending radius. + * + * Expected Results: + * 1. Two linear trajectories generated. + * 2. Blending trajectory cannot be generated. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testZeroRadius) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + + std::vector res{ generateLinTrajs(seq, 2) }; + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_req; + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_res; + + blend_req.group_name = planning_group_; + blend_req.link_name = target_link_; + blend_req.first_trajectory = res.at(0).trajectory_; + blend_req.second_trajectory = res.at(1).trajectory_; + + blend_req.blend_radius = 0.; + EXPECT_FALSE(blender_->blend(blend_req, blend_res)); +} + +/** + * @brief Tests the blending of two trajectories with differenent sampling + * times. + * + * Test Sequence: + * 1. Generate two linear trajectories with different sampling times. + * 2. Try to generate blending trajectory. + * + * Expected Results: + * 1. Two linear trajectories generated. + * 2. Blending trajectory cannot be generated. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testDifferentSamplingTimes) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + + // perform lin trajectory generation and modify sampling time + std::size_t num_cmds{ 2 }; + std::vector responses(num_cmds); + + for (size_t index = 0; index < num_cmds; ++index) + { + planning_interface::MotionPlanRequest req{ seq.getCmd(index).toRequest() }; + // Set start state of request to end state of previous trajectory (except + // for first) + if (index > 0) + { + moveit::core::robotStateToRobotStateMsg(responses[index - 1].trajectory_->getLastWayPoint(), req.start_state); + sampling_time_ *= 2; + } + // generate trajectory + planning_interface::MotionPlanResponse resp; + if (!lin_generator_->generate(req, resp, sampling_time_)) + { + std::runtime_error("Failed to generate trajectory."); + } + responses.at(index) = resp; + } + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_req; + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_res; + + blend_req.group_name = planning_group_; + blend_req.link_name = target_link_; + blend_req.first_trajectory = responses[0].trajectory_; + blend_req.second_trajectory = responses[1].trajectory_; + blend_req.blend_radius = seq.getBlendRadius(0); + EXPECT_FALSE(blender_->blend(blend_req, blend_res)); +} + +/** + * @brief Tests the blending of two trajectories with one trajectory + * having non-uniform sampling time (apart from the last sample, + * which is ignored). + * + * Test Sequence: + * 1. Generate two linear trajectories and corrupt uniformity of sampling + * time. + * 2. Try to generate blending trajectory. + * + * Expected Results: + * 1. Two linear trajectories generated. + * 2. Blending trajectory cannot be generated. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testNonUniformSamplingTime) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + + std::vector res{ generateLinTrajs(seq, 2) }; + + // Modify first time interval + EXPECT_GT(res[0].trajectory_->getWayPointCount(), 2u); + res[0].trajectory_->setWayPointDurationFromPrevious(1, 2 * sampling_time_); + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_req; + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_res; + + blend_req.group_name = planning_group_; + blend_req.link_name = target_link_; + blend_req.first_trajectory = res.at(0).trajectory_; + blend_req.second_trajectory = res.at(1).trajectory_; + blend_req.blend_radius = seq.getBlendRadius(0); + EXPECT_FALSE(blender_->blend(blend_req, blend_res)); +} + +/** + * @brief Tests the blending of two trajectories which do not intersect. + * + * Test Sequence: + * 1. Generate two trajectories from valid test data set. + * 2. Replace the second trajectory by the first one. + * 2. Try to generate blending trajectory. + * + * Expected Results: + * 1. Two trajectories generated. + * 2. Two trajectories that do not intersect. + * 2. Blending trajectory cannot be generated. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testNotIntersectingTrajectories) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + + std::vector res{ generateLinTrajs(seq, 1) }; + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_req; + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_res; + + blend_req.group_name = planning_group_; + blend_req.link_name = target_link_; + blend_req.first_trajectory = res.at(0).trajectory_; + // replace the second trajectory to make the two trajectories timely not + // intersect + blend_req.second_trajectory = res.at(0).trajectory_; + blend_req.blend_radius = seq.getBlendRadius(0); + EXPECT_FALSE(blender_->blend(blend_req, blend_res)); +} + +/** + * @brief Tests the blending of two cartesian trajectories with the + * shared point (last point of first, first point of second trajectory) + * having a non-zero velocity + * + * Test Sequence: + * 1. Generate two trajectories from the test data set. + * 2. Generate blending trajectory modify the shared point to have velocity. + * Expected Results: + * 1. Two trajectories generated. + * 2. Blending trajectory cannot be generated. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testNonStationaryPoint) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + + std::vector res{ generateLinTrajs(seq, 2) }; + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_req; + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_res; + + blend_req.group_name = planning_group_; + blend_req.link_name = target_link_; + blend_req.blend_radius = seq.getBlendRadius(0); + + blend_req.first_trajectory = res.at(0).trajectory_; + blend_req.second_trajectory = res.at(1).trajectory_; + + // Modify last waypoint of first trajectory and first point of second + // trajectory + blend_req.first_trajectory->getLastWayPointPtr()->setVariableVelocity(0, 1.0); + blend_req.second_trajectory->getFirstWayPointPtr()->setVariableVelocity(0, 1.0); + + EXPECT_FALSE(blender_->blend(blend_req, blend_res)); +} + +/** + * @brief Tests the blending of two cartesian trajectories where the first + * trajectory is completely within the sphere defined by the blend radius + * + * Test Sequence: + * 1. Generate two trajectories from the test data set. + * 2. Generate blending trajectory with a blend_radius larger + * than the smaller trajectory. + * + * Expected Results: + * 1. Two trajectories generated. + * 2. Blending trajectory cannot be generated. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testTraj1InsideBlendRadius) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + + std::vector res{ generateLinTrajs(seq, 2) }; + + double lin1_distance; + lin1_distance = (res[0].trajectory_->getFirstWayPoint().getFrameTransform(target_link_).translation() - + res[0].trajectory_->getLastWayPoint().getFrameTransform(target_link_).translation()) + .norm(); + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_req; + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_res; + + blend_req.group_name = planning_group_; + blend_req.link_name = target_link_; + blend_req.blend_radius = 1.1 * lin1_distance; + + blend_req.first_trajectory = res.at(0).trajectory_; + blend_req.second_trajectory = res.at(1).trajectory_; + + EXPECT_FALSE(blender_->blend(blend_req, blend_res)); +} + +/** + * @brief Tests the blending of two cartesian trajectories where the second + * trajectory is completely within the sphere defined by the blend radius + * + * Test Sequence: + * 1. Generate two trajectories from the test data set. + * 2. Generate blending trajectory with a blend_radius larger + * than the smaller trajectory. + * + * Expected Results: + * 1. Two trajectories generated. + * 2. Blending trajectory cannot be generated. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testTraj2InsideBlendRadius) +{ + Sequence seq{ data_loader_->getSequence("NoIntersectionTraj2") }; + + std::vector res{ generateLinTrajs(seq, 2) }; + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_req; + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_res; + + blend_req.group_name = planning_group_; + blend_req.link_name = target_link_; + blend_req.blend_radius = seq.getBlendRadius(0); + + blend_req.first_trajectory = res.at(0).trajectory_; + blend_req.second_trajectory = res.at(1).trajectory_; + + EXPECT_FALSE(blender_->blend(blend_req, blend_res)); +} + +/** + * @brief Tests the blending of two cartesian linear trajectories using robot + * model + * + * Test Sequence: + * 1. Generate two linear trajectories from the test data set. + * 2. Generate blending trajectory. + * 3. Check blending trajectory: + * - for position, velocity, and acceleration bounds, + * - for continuity in joint space, + * - for continuity in cartesian space. + * + * Expected Results: + * 1. Two linear trajectories generated. + * 2. Blending trajectory generated. + * 3. No bound is violated, the trajectories are continuous + * in joint and cartesian space. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testLinLinBlending) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + + std::vector res{ generateLinTrajs(seq, 2) }; + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_req; + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_res; + + blend_req.group_name = planning_group_; + blend_req.link_name = target_link_; + blend_req.blend_radius = seq.getBlendRadius(0); + + blend_req.first_trajectory = res.at(0).trajectory_; + blend_req.second_trajectory = res.at(1).trajectory_; + + EXPECT_TRUE(blender_->blend(blend_req, blend_res)); + + EXPECT_TRUE(testutils::checkBlendResult(blend_req, blend_res, planner_limits_, joint_velocity_tolerance_, + joint_acceleration_tolerance_, cartesian_velocity_tolerance_, + cartesian_angular_velocity_tolerance_)); +} + +/** + * @brief Tests the blending of two cartesian linear trajectories which have + * an overlap in the blending sphere using robot model. To be precise, + * the trajectories exactly lie on top of each other. + * + * Test Sequence: + * 1. Generate two linear trajectories from the test data set. Set goal of + * second traj to start of first traj. + * 2. Generate blending trajectory. + * 3. Check blending trajectory: + * - for position, velocity, and acceleration bounds, + * - for continuity in joint space, + * - for continuity in cartesian space. + * + * Expected Results: + * 1. Two linear trajectories generated. + * 2. Blending trajectory generated. + * 3. No bound is violated, the trajectories are continuous + * in joint and cartesian space. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testOverlappingBlendTrajectories) +{ + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + // Set goal of second traj to start of first traj. + seq.getCmd(1).setGoalConfiguration(seq.getCmd(0).getStartConfiguration()); + + std::vector res{ generateLinTrajs(seq, 2) }; + + pilz_industrial_motion_planner::TrajectoryBlendRequest blend_req; + pilz_industrial_motion_planner::TrajectoryBlendResponse blend_res; + + blend_req.group_name = planning_group_; + blend_req.link_name = target_link_; + blend_req.first_trajectory = res.at(0).trajectory_; + blend_req.second_trajectory = res.at(1).trajectory_; + blend_req.blend_radius = seq.getBlendRadius(0); + EXPECT_TRUE(blender_->blend(blend_req, blend_res)); + + EXPECT_TRUE(testutils::checkBlendResult(blend_req, blend_res, planner_limits_, joint_velocity_tolerance_, + joint_acceleration_tolerance_, cartesian_velocity_tolerance_, + cartesian_angular_velocity_tolerance_)); +} + +/** + * @brief Tests the blending of two cartesian trajectories which differ + * from a straight line. + * + * Test Sequence: + * 1. Generate two trajectories from the test data set. + * 2. Add scaled sine function to cartesian trajectories, such that + * start and end state remain unchanged; generate resulting + * joint trajectories using a time scaling in order to preserve + * joint velocity limits. + * 3. Generate blending trajectory. + * 4. Check blending trajectory: + * - for position, velocity, and acceleration bounds, + * - for continuity in joint space, + * - for continuity in cartesian space. + * + * Expected Results: + * 1. Two trajectories generated. + * 2. Modified joint trajectories generated. + * 3. Blending trajectory generated. + * 4. No bound is violated, the trajectories are continuous + * in joint and cartesian space. + */ +TEST_P(TrajectoryBlenderTransitionWindowTest, testNonLinearBlending) +{ + const double sine_scaling_factor{ 0.01 }; + const double time_scaling_factor{ 10 }; + + Sequence seq{ data_loader_->getSequence("SimpleSequence") }; + + std::vector res{ generateLinTrajs(seq, 2) }; + + // prepare looping over trajectories + std::vector sine_trajs(2); + + for (size_t traj_index = 0; traj_index < 2; ++traj_index) + { + auto lin_traj{ res.at(traj_index).trajectory_ }; + + CartesianTrajectory cart_traj; + trajectory_msgs::JointTrajectory joint_traj; + const double duration{ lin_traj->getWayPointDurationFromStart(lin_traj->getWayPointCount()) }; + // time from start zero does not work + const double time_from_start_offset{ time_scaling_factor * lin_traj->getWayPointDurations().back() }; + + // generate modified cartesian trajectory + for (size_t i = 0; i < lin_traj->getWayPointCount(); ++i) + { + // transform time to interval [0, 4*pi] + const double sine_arg{ 4 * M_PI * lin_traj->getWayPointDurationFromStart(i) / duration }; + + // get pose + CartesianTrajectoryPoint waypoint; + geometry_msgs::Pose waypoint_pose; + Eigen::Isometry3d eigen_pose{ lin_traj->getWayPointPtr(i)->getFrameTransform(target_link_) }; + tf2::convert(eigen_pose, waypoint_pose); + + // add scaled sine function + waypoint_pose.position.x += sine_scaling_factor * sin(sine_arg); + waypoint_pose.position.y += sine_scaling_factor * sin(sine_arg); + waypoint_pose.position.z += sine_scaling_factor * sin(sine_arg); + + // add to trajectory + waypoint.pose = waypoint_pose; + waypoint.time_from_start = + ros::Duration(time_from_start_offset + time_scaling_factor * lin_traj->getWayPointDurationFromStart(i)); + cart_traj.points.push_back(waypoint); + } + + // prepare ik + std::map initial_joint_position, initial_joint_velocity; + for (const std::string& joint_name : + lin_traj->getFirstWayPointPtr()->getJointModelGroup(planning_group_)->getActiveJointModelNames()) + { + if (traj_index == 0) + { + initial_joint_position[joint_name] = lin_traj->getFirstWayPoint().getVariablePosition(joint_name); + initial_joint_velocity[joint_name] = lin_traj->getFirstWayPoint().getVariableVelocity(joint_name); + } + else + { + initial_joint_position[joint_name] = + sine_trajs[traj_index - 1]->getLastWayPoint().getVariablePosition(joint_name); + initial_joint_velocity[joint_name] = + sine_trajs[traj_index - 1]->getLastWayPoint().getVariableVelocity(joint_name); + } + } + + moveit_msgs::MoveItErrorCodes error_code; + if (!generateJointTrajectory(robot_model_, planner_limits_.getJointLimitContainer(), cart_traj, planning_group_, + target_link_, initial_joint_position, initial_joint_velocity, joint_traj, error_code, + true)) + { + std::runtime_error("Failed to generate trajectory."); + } + + joint_traj.points.back().velocities.assign(joint_traj.points.back().velocities.size(), 0.0); + joint_traj.points.back().accelerations.assign(joint_traj.points.back().accelerations.size(), 0.0); + + // convert trajectory_msgs::JointTrajectory to + // robot_trajectory::RobotTrajectory + sine_trajs[traj_index] = std::make_shared(robot_model_, planning_group_); + sine_trajs.at(traj_index)->setRobotTrajectoryMsg(lin_traj->getFirstWayPoint(), joint_traj); + } + + TrajectoryBlendRequest blend_req; + TrajectoryBlendResponse blend_res; + + blend_req.group_name = planning_group_; + blend_req.link_name = target_link_; + blend_req.blend_radius = seq.getBlendRadius(0); + + blend_req.first_trajectory = sine_trajs.at(0); + blend_req.second_trajectory = sine_trajs.at(1); + + EXPECT_TRUE(blender_->blend(blend_req, blend_res)); + + EXPECT_TRUE(testutils::checkBlendResult(blend_req, blend_res, planner_limits_, joint_velocity_tolerance_, + joint_acceleration_tolerance_, cartesian_velocity_tolerance_, + cartesian_angular_velocity_tolerance_)); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "unittest_trajectory_blender_transition_window"); + ros::NodeHandle nh; + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_blender_transition_window.test b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_blender_transition_window.test new file mode 100644 index 0000000000..2d0bf6c3d5 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_blender_transition_window.test @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_functions.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_functions.cpp new file mode 100644 index 0000000000..a70575361f --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_functions.cpp @@ -0,0 +1,971 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pilz_industrial_motion_planner/cartesian_trajectory.h" +#include "pilz_industrial_motion_planner/cartesian_trajectory_point.h" +#include "pilz_industrial_motion_planner/limits_container.h" +#include "pilz_industrial_motion_planner/trajectory_functions.h" +#include "test_utils.h" + +#define _USE_MATH_DEFINES + +static constexpr double EPSILON{ 1.0e-6 }; +static constexpr double IK_SEED_OFFSET{ 0.1 }; +static constexpr double L0{ 0.2604 }; // Height of foot +static constexpr double L1{ 0.3500 }; // Height of first connector +static constexpr double L2{ 0.3070 }; // Height of second connector +static constexpr double L3{ 0.0840 }; // Distance last joint to flange + +const std::string PARAM_MODEL_NO_GRIPPER_NAME{ "robot_description" }; +const std::string PARAM_MODEL_WITH_GRIPPER_NAME{ "robot_description_pg70" }; + +// parameters from parameter server +const std::string PARAM_PLANNING_GROUP_NAME("planning_group"); +const std::string GROUP_TIP_LINK_NAME("group_tip_link"); +const std::string ROBOT_TCP_LINK_NAME("tcp_link"); +const std::string IK_FAST_LINK_NAME("ik_fast_link"); +const std::string RANDOM_TEST_NUMBER("random_test_number"); + +/** + * @brief test fixtures base class + */ +class TrajectoryFunctionsTestBase : public testing::TestWithParam +{ +protected: + /** + * @brief Create test scenario for trajectory functions + * + */ + void SetUp() override; + + /** + * @brief check if two transformations are close + * @param pose1 + * @param pose2 + * @param epsilon + * @return + */ + bool tfNear(const Eigen::Isometry3d& pose1, const Eigen::Isometry3d& pose2, const double& epsilon); + +protected: + // ros stuff + ros::NodeHandle ph_{ "~" }; + robot_model::RobotModelConstPtr robot_model_{ robot_model_loader::RobotModelLoader(GetParam()).getModel() }; + + // test parameters from parameter server + std::string planning_group_, group_tip_link_, tcp_link_, ik_fast_link_; + int random_test_number_; + std::vector joint_names_; + std::map zero_state_; + + // random seed + boost::uint32_t random_seed_{ 100 }; + random_numbers::RandomNumberGenerator rng_{ random_seed_ }; +}; + +void TrajectoryFunctionsTestBase::SetUp() +{ + // parameters + ASSERT_TRUE(ph_.getParam(PARAM_PLANNING_GROUP_NAME, planning_group_)); + ASSERT_TRUE(ph_.getParam(GROUP_TIP_LINK_NAME, group_tip_link_)); + ASSERT_TRUE(ph_.getParam(ROBOT_TCP_LINK_NAME, tcp_link_)); + ASSERT_TRUE(ph_.getParam(IK_FAST_LINK_NAME, ik_fast_link_)); + ASSERT_TRUE(ph_.getParam(RANDOM_TEST_NUMBER, random_test_number_)); + + // check robot model + testutils::checkRobotModel(robot_model_, planning_group_, tcp_link_); + + // initialize the zero state configurationg and test joint state + joint_names_ = robot_model_->getJointModelGroup(planning_group_)->getActiveJointModelNames(); + for (const auto& joint_name : joint_names_) + { + zero_state_[joint_name] = 0.0; + } +} + +bool TrajectoryFunctionsTestBase::tfNear(const Eigen::Isometry3d& pose1, const Eigen::Isometry3d& pose2, + const double& epsilon) +{ + for (std::size_t i = 0; i < 3; ++i) + for (std::size_t j = 0; j < 4; ++j) + { + if (fabs(pose1(i, j) - pose2(i, j)) > fabs(epsilon)) + return false; + } + return true; +} + +/** + * @brief Parametrized class for tests with and without gripper. + */ +class TrajectoryFunctionsTestFlangeAndGripper : public TrajectoryFunctionsTestBase +{ +}; + +/** + * @brief Parametrized class for tests, that only run with a gripper + */ +class TrajectoryFunctionsTestOnlyGripper : public TrajectoryFunctionsTestBase +{ +}; + +// Instantiate the test cases for robot model with and without gripper +INSTANTIATE_TEST_SUITE_P(InstantiationName, TrajectoryFunctionsTestFlangeAndGripper, + ::testing::Values(PARAM_MODEL_NO_GRIPPER_NAME, PARAM_MODEL_WITH_GRIPPER_NAME)); + +// Instantiate the test cases for robot model with a gripper +INSTANTIATE_TEST_SUITE_P(InstantiationName, TrajectoryFunctionsTestOnlyGripper, + ::testing::Values(PARAM_MODEL_WITH_GRIPPER_NAME)); + +/** + * @brief Test the forward kinematics function with simple robot poses for robot + * tip link + * using robot model without gripper. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, TipLinkFK) +{ + Eigen::Isometry3d tip_pose; + std::map test_state = zero_state_; + EXPECT_TRUE(pilz_industrial_motion_planner::computeLinkFK(robot_model_, group_tip_link_, test_state, tip_pose)); + EXPECT_NEAR(tip_pose(0, 3), 0, EPSILON); + EXPECT_NEAR(tip_pose(1, 3), 0, EPSILON); + EXPECT_NEAR(tip_pose(2, 3), L0 + L1 + L2 + L3, EPSILON); + + test_state[joint_names_.at(1)] = M_PI_2; + EXPECT_TRUE(pilz_industrial_motion_planner::computeLinkFK(robot_model_, group_tip_link_, test_state, tip_pose)); + EXPECT_NEAR(tip_pose(0, 3), L1 + L2 + L3, EPSILON); + EXPECT_NEAR(tip_pose(1, 3), 0, EPSILON); + EXPECT_NEAR(tip_pose(2, 3), L0, EPSILON); + + test_state[joint_names_.at(1)] = -M_PI_2; + test_state[joint_names_.at(2)] = M_PI_2; + EXPECT_TRUE(pilz_industrial_motion_planner::computeLinkFK(robot_model_, group_tip_link_, test_state, tip_pose)); + EXPECT_NEAR(tip_pose(0, 3), -L1, EPSILON); + EXPECT_NEAR(tip_pose(1, 3), 0, EPSILON); + EXPECT_NEAR(tip_pose(2, 3), L0 - L2 - L3, EPSILON); + + // wrong link name + std::string link_name = "wrong_link_name"; + EXPECT_FALSE(pilz_industrial_motion_planner::computeLinkFK(robot_model_, link_name, test_state, tip_pose)); +} + +/** + * @brief Test the inverse kinematics directly through ikfast solver + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testIKSolver) +{ + // Load solver + const robot_model::JointModelGroup* jmg = robot_model_->getJointModelGroup(planning_group_); + const kinematics::KinematicsBaseConstPtr& solver = jmg->getSolverInstance(); + + // robot state + robot_state::RobotState rstate(robot_model_); + + while (random_test_number_ > 0) + { + // sample random robot state + rstate.setToRandomPositions(jmg, rng_); + rstate.update(); + geometry_msgs::Pose pose_expect; + tf2::convert(rstate.getFrameTransform(ik_fast_link_), pose_expect); + + // prepare inverse kinematics + std::vector ik_poses; + ik_poses.push_back(pose_expect); + std::vector ik_seed, ik_expect, ik_actual; + for (const auto& joint_name : jmg->getActiveJointModelNames()) + { + ik_expect.push_back(rstate.getVariablePosition(joint_name)); + if (rstate.getVariablePosition(joint_name) > 0) + ik_seed.push_back(rstate.getVariablePosition(joint_name) - IK_SEED_OFFSET); + else + ik_seed.push_back(rstate.getVariablePosition(joint_name) + IK_SEED_OFFSET); + } + + std::vector> ik_solutions; + kinematics::KinematicsResult ik_result; + moveit_msgs::MoveItErrorCodes err_code; + kinematics::KinematicsQueryOptions options = kinematics::KinematicsQueryOptions(); + + // compute all ik solutions + EXPECT_TRUE(solver->getPositionIK(ik_poses, ik_seed, ik_solutions, ik_result, options)); + + // compute one ik solution + EXPECT_TRUE(solver->getPositionIK(pose_expect, ik_seed, ik_actual, err_code)); + + ASSERT_EQ(ik_expect.size(), ik_actual.size()); + + for (std::size_t i = 0; i < ik_expect.size(); ++i) + { + EXPECT_NEAR(ik_actual.at(i), ik_expect.at(i), 4 * IK_SEED_OFFSET); + } + + --random_test_number_; + } +} + +/** + * @brief Test the inverse kinematics using RobotState class (setFromIK) using + * robot model + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testIKRobotState) +{ + // robot state + robot_state::RobotState rstate(robot_model_); + const robot_model::JointModelGroup* jmg = robot_model_->getJointModelGroup(planning_group_); + + while (random_test_number_ > 0) + { + // sample random robot state + rstate.setToRandomPositions(jmg, rng_); + + Eigen::Isometry3d pose_expect = rstate.getFrameTransform(tcp_link_); + + // copy the random state and set ik seed + std::map ik_seed, ik_expect; + for (const auto& joint_name : joint_names_) + { + ik_expect[joint_name] = rstate.getVariablePosition(joint_name); + if (rstate.getVariablePosition(joint_name) > 0) + ik_seed[joint_name] = rstate.getVariablePosition(joint_name) - IK_SEED_OFFSET; + else + ik_seed[joint_name] = rstate.getVariablePosition(joint_name) + IK_SEED_OFFSET; + } + + rstate.setVariablePositions(ik_seed); + rstate.update(); + + // compute the ik + std::map ik_actual; + + EXPECT_TRUE(rstate.setFromIK(robot_model_->getJointModelGroup(planning_group_), pose_expect, tcp_link_)); + + for (const auto& joint_name : joint_names_) + { + ik_actual[joint_name] = rstate.getVariablePosition(joint_name); + } + + // compare ik solution and expected value + for (const auto& joint_pair : ik_actual) + { + EXPECT_NEAR(joint_pair.second, ik_expect.at(joint_pair.first), 4 * IK_SEED_OFFSET); + } + + // compute the pose from ik_solution + rstate.setVariablePositions(ik_actual); + rstate.update(); + Eigen::Isometry3d pose_actual = rstate.getFrameTransform(tcp_link_); + + EXPECT_TRUE(tfNear(pose_expect, pose_actual, EPSILON)); + + --random_test_number_; + } +} + +/** + * @brief Test the wrapper function to compute inverse kinematics using robot + * model + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testComputePoseIK) +{ + // robot state + robot_state::RobotState rstate(robot_model_); + + const std::string frame_id = robot_model_->getModelFrame(); + const robot_model::JointModelGroup* jmg = robot_model_->getJointModelGroup(planning_group_); + + while (random_test_number_ > 0) + { + // sample random robot state + rstate.setToRandomPositions(jmg, rng_); + + Eigen::Isometry3d pose_expect = rstate.getFrameTransform(tcp_link_); + + // copy the random state and set ik seed + std::map ik_seed, ik_expect; + for (const auto& joint_name : robot_model_->getJointModelGroup(planning_group_)->getActiveJointModelNames()) + { + ik_expect[joint_name] = rstate.getVariablePosition(joint_name); + if (rstate.getVariablePosition(joint_name) > 0) + { + ik_seed[joint_name] = rstate.getVariablePosition(joint_name) - IK_SEED_OFFSET; + } + else + { + ik_seed[joint_name] = rstate.getVariablePosition(joint_name) + IK_SEED_OFFSET; + } + } + + // compute the ik + std::map ik_actual; + EXPECT_TRUE(pilz_industrial_motion_planner::computePoseIK(robot_model_, planning_group_, tcp_link_, pose_expect, + frame_id, ik_seed, ik_actual, false)); + + // compare ik solution and expected value + for (const auto& joint_pair : ik_actual) + { + EXPECT_NEAR(joint_pair.second, ik_expect.at(joint_pair.first), 4 * IK_SEED_OFFSET); + } + + --random_test_number_; + } +} + +/** + * @brief Test computePoseIK for invalid group_name + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testComputePoseIKInvalidGroupName) +{ + const std::string frame_id = robot_model_->getModelFrame(); + Eigen::Isometry3d pose_expect; + + std::map ik_seed; + + // compute the ik + std::map ik_actual; + EXPECT_FALSE(pilz_industrial_motion_planner::computePoseIK(robot_model_, "InvalidGroupName", tcp_link_, pose_expect, + frame_id, ik_seed, ik_actual, false)); +} + +/** + * @brief Test computePoseIK for invalid link_name + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testComputePoseIKInvalidLinkName) +{ + const std::string frame_id = robot_model_->getModelFrame(); + Eigen::Isometry3d pose_expect; + + std::map ik_seed; + + // compute the ik + std::map ik_actual; + EXPECT_FALSE(pilz_industrial_motion_planner::computePoseIK(robot_model_, planning_group_, "WrongLink", pose_expect, + frame_id, ik_seed, ik_actual, false)); +} + +/** + * @brief Test computePoseIK for invalid frame_id + * + * Currently only robot_model_->getModelFrame() == frame_id + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testComputePoseIKInvalidFrameId) +{ + Eigen::Isometry3d pose_expect; + + std::map ik_seed; + + // compute the ik + std::map ik_actual; + EXPECT_FALSE(pilz_industrial_motion_planner::computePoseIK(robot_model_, planning_group_, tcp_link_, pose_expect, + "InvalidFrameId", ik_seed, ik_actual, false)); +} + +/** + * @brief Test if activated self collision for a pose that would be in self + * collision without the check results in a + * valid ik solution. + */ +TEST_P(TrajectoryFunctionsTestOnlyGripper, testComputePoseIKSelfCollisionForValidPosition) +{ + const std::string frame_id = robot_model_->getModelFrame(); + const robot_model::JointModelGroup* jmg = robot_model_->getJointModelGroup(planning_group_); + + // create seed + std::vector ik_seed_states = { -0.553, 0.956, 1.758, 0.146, -1.059, 1.247 }; + auto joint_names = jmg->getActiveJointModelNames(); + + std::map ik_seed; + for (unsigned int i = 0; i < ik_seed_states.size(); ++i) + { + ik_seed[joint_names[i]] = ik_seed_states[i]; + } + + // create expected pose + geometry_msgs::Pose pose; + pose.position.x = -0.454; + pose.position.y = -0.15; + pose.position.z = 0.431; + pose.orientation.y = 0.991562; + pose.orientation.w = -0.1296328; + Eigen::Isometry3d pose_expect; + normalizeQuaternion(pose.orientation); + tf2::convert(pose, pose_expect); + + // compute the ik without self collision check and expect the resulting pose + // to be in self collission. + std::map ik_actual1; + EXPECT_TRUE(pilz_industrial_motion_planner::computePoseIK(robot_model_, planning_group_, tcp_link_, pose_expect, + frame_id, ik_seed, ik_actual1, false)); + + robot_state::RobotState rstate(robot_model_); + planning_scene::PlanningScene rscene(robot_model_); + + std::vector ik_state; + std::transform(ik_actual1.begin(), ik_actual1.end(), std::back_inserter(ik_state), + boost::bind(&std::map::value_type::second, _1)); + + rstate.setJointGroupPositions(jmg, ik_state); + rstate.update(); + + collision_detection::CollisionRequest collision_req; + collision_req.group_name = jmg->getName(); + collision_detection::CollisionResult collision_res; + + rscene.checkSelfCollision(collision_req, collision_res, rstate); + + EXPECT_TRUE(collision_res.collision); + + // compute the ik with collision detection activated and expect the resulting + // pose to be without self collision. + std::map ik_actual2; + EXPECT_TRUE(pilz_industrial_motion_planner::computePoseIK(robot_model_, planning_group_, tcp_link_, pose_expect, + frame_id, ik_seed, ik_actual2, true)); + + std::vector ik_state2; + std::transform(ik_actual2.begin(), ik_actual2.end(), std::back_inserter(ik_state2), + boost::bind(&std::map::value_type::second, _1)); + rstate.setJointGroupPositions(jmg, ik_state2); + rstate.update(); + + collision_detection::CollisionResult collision_res2; + rscene.checkSelfCollision(collision_req, collision_res2, rstate); + + EXPECT_FALSE(collision_res2.collision); +} + +/** + * @brief Test if self collision is considered by using a pose that always has + * self collision. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testComputePoseIKSelfCollisionForInvalidPose) +{ + // robot state + robot_state::RobotState rstate(robot_model_); + + const std::string frame_id = robot_model_->getModelFrame(); + const robot_model::JointModelGroup* jmg = robot_model_->getJointModelGroup(planning_group_); + + // create seed + std::map ik_seed; + for (const auto& joint_name : jmg->getActiveJointModelNames()) + { + ik_seed[joint_name] = 0; + } + + // create goal + std::vector ik_goal = { 0, 2.3, -2.3, 0, 0, 0 }; + + rstate.setJointGroupPositions(jmg, ik_goal); + + Eigen::Isometry3d pose_expect = rstate.getFrameTransform(tcp_link_); + + // compute the ik with disabled collision check + std::map ik_actual; + EXPECT_TRUE(pilz_industrial_motion_planner::computePoseIK(robot_model_, planning_group_, tcp_link_, pose_expect, + frame_id, ik_seed, ik_actual, false)); + + // compute the ik with enabled collision check + EXPECT_FALSE(pilz_industrial_motion_planner::computePoseIK(robot_model_, planning_group_, tcp_link_, pose_expect, + frame_id, ik_seed, ik_actual, true)); +} + +/** + * @brief Check that function VerifySampleJointLimits() returns 'false' in case + * of very small sample duration. + * + * Test Sequence: + * 1. Call function with very small sample duration. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testVerifySampleJointLimitsWithSmallDuration) +{ + const std::map position_last, velocity_last, position_current; + double duration_last{ 0.0 }; + const pilz_industrial_motion_planner::JointLimitsContainer joint_limits; + + double duration_current = 10e-7; + + EXPECT_FALSE(pilz_industrial_motion_planner::verifySampleJointLimits(position_last, velocity_last, position_current, + duration_last, duration_current, joint_limits)); +} + +/** + * @brief Check that function VerifySampleJointLimits() returns 'false' in case + * of a velocity violation. + * + * Test Sequence: + * 1. Call function with a velocity violation. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testVerifySampleJointLimitsVelocityViolation) +{ + const std::string test_joint_name{ "joint" }; + + std::map position_last{ { test_joint_name, 2.0 } }; + std::map position_current{ { test_joint_name, 10.0 } }; + std::map velocity_last; + double duration_current{ 1.0 }; + double duration_last{ 0.0 }; + pilz_industrial_motion_planner::JointLimitsContainer joint_limits; + + JointLimit test_joint_limits; + // Calculate the max allowed velocity in such a way that it is always smaller + // than the current velocity. + test_joint_limits.max_velocity = + ((position_current.at(test_joint_name) - position_last.at(test_joint_name)) / duration_current) - 1.0; + test_joint_limits.has_velocity_limits = true; + joint_limits.addLimit(test_joint_name, test_joint_limits); + + EXPECT_FALSE(pilz_industrial_motion_planner::verifySampleJointLimits(position_last, velocity_last, position_current, + duration_last, duration_current, joint_limits)); +} + +/** + * @brief Check that function VerifySampleJointLimits() returns 'false' in case + * of a acceleration violation. + * + * Test Sequence: + * 1. Call function with a acceleration violation. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testVerifySampleJointLimitsAccelerationViolation) +{ + const std::string test_joint_name{ "joint" }; + + double duration_current = 1.0; + double duration_last = 1.0; + + std::map position_last{ { test_joint_name, 2.0 } }; + std::map position_current{ { test_joint_name, 20.0 } }; + double velocity_current = + ((position_current.at(test_joint_name) - position_last.at(test_joint_name)) / duration_current); + std::map velocity_last{ { test_joint_name, 9.0 } }; + pilz_industrial_motion_planner::JointLimitsContainer joint_limits; + + JointLimit test_joint_limits; + // Calculate the max allowed velocity in such a way that it is always bigger + // than the current velocity. + test_joint_limits.max_velocity = velocity_current + 1.0; + test_joint_limits.has_velocity_limits = true; + + double acceleration_current = + (velocity_current - velocity_last.at(test_joint_name)) / (duration_last + duration_current) * 2; + // Calculate the max allowed acceleration in such a way that it is always + // smaller than the current acceleration. + test_joint_limits.max_acceleration = acceleration_current - 1.0; + test_joint_limits.has_acceleration_limits = true; + + joint_limits.addLimit(test_joint_name, test_joint_limits); + + EXPECT_FALSE(pilz_industrial_motion_planner::verifySampleJointLimits(position_last, velocity_last, position_current, + duration_last, duration_current, joint_limits)); +} + +/** + * @brief Check that function VerifySampleJointLimits() returns 'false' in case + * of a deceleration violation. + * + * Test Sequence: + * 1. Call function with a deceleration violation. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testVerifySampleJointLimitsDecelerationViolation) +{ + const std::string test_joint_name{ "joint" }; + + double duration_current = 1.0; + double duration_last = 1.0; + + std::map position_last{ { test_joint_name, 20.0 } }; + std::map position_current{ { test_joint_name, 2.0 } }; + double velocity_current = + ((position_current.at(test_joint_name) - position_last.at(test_joint_name)) / duration_current); + std::map velocity_last{ { test_joint_name, 19.0 } }; + pilz_industrial_motion_planner::JointLimitsContainer joint_limits; + + JointLimit test_joint_limits; + // Calculate the max allowed velocity in such a way that it is always bigger + // than the current velocity. + test_joint_limits.max_velocity = fabs(velocity_current) + 1.0; + test_joint_limits.has_velocity_limits = true; + + double acceleration_current = + (velocity_current - velocity_last.at(test_joint_name)) / (duration_last + duration_current) * 2; + // Calculate the max allowed deceleration in such a way that it is always + // bigger than the current acceleration. + test_joint_limits.max_deceleration = acceleration_current + 1.0; + test_joint_limits.has_deceleration_limits = true; + + joint_limits.addLimit(test_joint_name, test_joint_limits); + + EXPECT_FALSE(pilz_industrial_motion_planner::verifySampleJointLimits(position_last, velocity_last, position_current, + duration_last, duration_current, joint_limits)); +} + +/** + * @brief Check that function generateJointTrajectory() returns 'false' if + * a joint trajectory cannot be computed from a cartesian trajectory. + * + * Please note: Both function variants are tested in this test. + * + * Test Sequence: + * 1. Call function with a cartesian trajectory which cannot be transformed + * into a joint trajectory by using + * an invalid group_name. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testGenerateJointTrajectoryWithInvalidCartesianTrajectory) +{ + // Create random test trajectory + // Note: 'path' is deleted by KDL::Trajectory_Segment + KDL::Path_RoundedComposite* path = + new KDL::Path_RoundedComposite(0.2, 0.01, new KDL::RotationalInterpolation_SingleAxis()); + path->Add(KDL::Frame(KDL::Rotation::RPY(0, 0, 0), KDL::Vector(-1, 0, 0))); + path->Finish(); + // Note: 'velprof' is deleted by KDL::Trajectory_Segment + KDL::VelocityProfile* vel_prof = new KDL::VelocityProfile_Trap(0.5, 0.1); + vel_prof->SetProfile(0, path->PathLength()); + KDL::Trajectory_Segment kdl_trajectory(path, vel_prof); + + pilz_industrial_motion_planner::JointLimitsContainer joint_limits; + std::string group_name{ "invalid_group_name" }; + std::map initial_joint_position; + double sampling_time{ 0.1 }; + trajectory_msgs::JointTrajectory joint_trajectory; + moveit_msgs::MoveItErrorCodes error_code; + bool check_self_collision{ false }; + + EXPECT_FALSE(pilz_industrial_motion_planner::generateJointTrajectory( + robot_model_, joint_limits, kdl_trajectory, group_name, tcp_link_, initial_joint_position, sampling_time, + joint_trajectory, error_code, check_self_collision)); + + std::map initial_joint_velocity; + + pilz_industrial_motion_planner::CartesianTrajectory cart_traj; + cart_traj.group_name = group_name; + cart_traj.link_name = tcp_link_; + pilz_industrial_motion_planner::CartesianTrajectoryPoint cart_traj_point; + cart_traj.points.push_back(cart_traj_point); + + EXPECT_FALSE(pilz_industrial_motion_planner::generateJointTrajectory( + robot_model_, joint_limits, cart_traj, group_name, tcp_link_, initial_joint_position, initial_joint_velocity, + joint_trajectory, error_code, check_self_collision)); +} + +/** + * @brief Check that function determineAndCheckSamplingTime() returns 'false' if + * both of the needed vectors have an incorrect vector size. + * + * + * Test Sequence: + * 1. Call function with vectors of incorrect size. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testDetermineAndCheckSamplingTimeInvalidVectorSize) +{ + robot_trajectory::RobotTrajectoryPtr first_trajectory = + std::make_shared(robot_model_, planning_group_); + robot_trajectory::RobotTrajectoryPtr second_trajectory = + std::make_shared(robot_model_, planning_group_); + double epsilon{ 0.0 }; + double sampling_time{ 0.0 }; + + robot_state::RobotState rstate(robot_model_); + first_trajectory->insertWayPoint(0, rstate, 0.1); + second_trajectory->insertWayPoint(0, rstate, 0.1); + + EXPECT_FALSE(pilz_industrial_motion_planner::determineAndCheckSamplingTime(first_trajectory, second_trajectory, + epsilon, sampling_time)); +} + +/** + * @brief Check that function determineAndCheckSamplingTime() returns 'true' if + * sampling time is correct. + * + * + * Test Sequence: + * 1. Call function with trajectories which do NOT violate sampling time. + * + * Expected Results: + * 1. Function returns 'true'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testDetermineAndCheckSamplingTimeCorrectSamplingTime) +{ + robot_trajectory::RobotTrajectoryPtr first_trajectory = + std::make_shared(robot_model_, planning_group_); + robot_trajectory::RobotTrajectoryPtr second_trajectory = + std::make_shared(robot_model_, planning_group_); + double epsilon{ 0.0001 }; + double sampling_time{ 0.0 }; + double expected_sampling_time{ 0.1 }; + + robot_state::RobotState rstate(robot_model_); + first_trajectory->insertWayPoint(0, rstate, expected_sampling_time); + first_trajectory->insertWayPoint(1, rstate, expected_sampling_time); + + second_trajectory->insertWayPoint(0, rstate, expected_sampling_time); + second_trajectory->insertWayPoint(1, rstate, expected_sampling_time); + second_trajectory->insertWayPoint(2, rstate, expected_sampling_time); + + EXPECT_TRUE(pilz_industrial_motion_planner::determineAndCheckSamplingTime(first_trajectory, second_trajectory, + epsilon, sampling_time)); + EXPECT_EQ(expected_sampling_time, sampling_time); +} + +/** + * @brief Check that function determineAndCheckSamplingTime() returns 'false' if + * sampling time is violated. + * + * + * Test Sequence: + * 1. Call function with trajectories which violate sampling time. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testDetermineAndCheckSamplingTimeViolateSamplingTime) +{ + robot_trajectory::RobotTrajectoryPtr first_trajectory = + std::make_shared(robot_model_, planning_group_); + robot_trajectory::RobotTrajectoryPtr second_trajectory = + std::make_shared(robot_model_, planning_group_); + double epsilon{ 0.0001 }; + double sampling_time{ 0.0 }; + double expected_sampling_time{ 0.1 }; + + robot_state::RobotState rstate(robot_model_); + first_trajectory->insertWayPoint(0, rstate, expected_sampling_time); + first_trajectory->insertWayPoint(1, rstate, expected_sampling_time); + first_trajectory->insertWayPoint(2, rstate, expected_sampling_time); + // Violate sampling time + first_trajectory->insertWayPoint(2, rstate, expected_sampling_time + 1.0); + first_trajectory->insertWayPoint(3, rstate, expected_sampling_time); + + second_trajectory->insertWayPoint(0, rstate, expected_sampling_time); + second_trajectory->insertWayPoint(1, rstate, expected_sampling_time); + second_trajectory->insertWayPoint(2, rstate, expected_sampling_time); + second_trajectory->insertWayPoint(3, rstate, expected_sampling_time); + + EXPECT_FALSE(pilz_industrial_motion_planner::determineAndCheckSamplingTime(first_trajectory, second_trajectory, + epsilon, sampling_time)); + EXPECT_EQ(expected_sampling_time, sampling_time); +} + +/** + * @brief Check that function isRobotStateEqual() returns 'false' if + * the positions of the robot states are not equal. + * + * + * Test Sequence: + * 1. Call function with robot states with different positions. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testIsRobotStateEqualPositionUnequal) +{ + robot_state::RobotState rstate_1 = robot_state::RobotState(robot_model_); + robot_state::RobotState rstate_2 = robot_state::RobotState(robot_model_); + + double default_joint_position[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + rstate_1.setJointGroupPositions(planning_group_, default_joint_position); + // Ensure that the joint positions of both robot states are different + default_joint_position[0] = default_joint_position[0] + 70.0; + rstate_2.setJointGroupPositions(planning_group_, default_joint_position); + + double epsilon{ 0.0001 }; + EXPECT_FALSE(pilz_industrial_motion_planner::isRobotStateEqual(rstate_1, rstate_2, planning_group_, epsilon)); +} + +/** + * @brief Check that function isRobotStateEqual() returns 'false' if + * the velocity of the robot states are not equal. + * + * + * Test Sequence: + * 1. Call function with robot states with different velocities. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testIsRobotStateEqualVelocityUnequal) +{ + robot_state::RobotState rstate_1 = robot_state::RobotState(robot_model_); + robot_state::RobotState rstate_2 = robot_state::RobotState(robot_model_); + + // Ensure that the joint positions of both robot state are equal + double default_joint_position[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + rstate_1.setJointGroupPositions(planning_group_, default_joint_position); + rstate_2.setJointGroupPositions(planning_group_, default_joint_position); + + double default_joint_velocity[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + rstate_1.setJointGroupVelocities(planning_group_, default_joint_velocity); + // Ensure that the joint velocites of both robot states are different + default_joint_velocity[1] = default_joint_velocity[1] + 10.0; + rstate_2.setJointGroupVelocities(planning_group_, default_joint_velocity); + + double epsilon{ 0.0001 }; + EXPECT_FALSE(pilz_industrial_motion_planner::isRobotStateEqual(rstate_1, rstate_2, planning_group_, epsilon)); +} + +/** + * @brief Check that function isRobotStateEqual() returns 'false' if + * the acceleration of the robot states are not equal. + * + * + * Test Sequence: + * 1. Call function with robot states with different acceleration. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testIsRobotStateEqualAccelerationUnequal) +{ + robot_state::RobotState rstate_1 = robot_state::RobotState(robot_model_); + robot_state::RobotState rstate_2 = robot_state::RobotState(robot_model_); + + // Ensure that the joint positions of both robot state are equal + double default_joint_position[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + rstate_1.setJointGroupPositions(planning_group_, default_joint_position); + rstate_2.setJointGroupPositions(planning_group_, default_joint_position); + + // Ensure that the joint velocities of both robot state are equal + double default_joint_velocity[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + rstate_1.setJointGroupVelocities(planning_group_, default_joint_velocity); + rstate_2.setJointGroupVelocities(planning_group_, default_joint_velocity); + + double default_joint_acceleration[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + rstate_1.setJointGroupAccelerations(planning_group_, default_joint_acceleration); + // Ensure that the joint accelerations of both robot states are different + default_joint_acceleration[1] = default_joint_acceleration[1] + 10.0; + rstate_2.setJointGroupAccelerations(planning_group_, default_joint_acceleration); + + double epsilon{ 0.0001 }; + EXPECT_FALSE(pilz_industrial_motion_planner::isRobotStateEqual(rstate_1, rstate_2, planning_group_, epsilon)); +} + +/** + * @brief Check that function isRobotStateStationary() returns 'false' if + * the joint velocities are not equal to zero. + * + * + * Test Sequence: + * 1. Call function with robot state with joint velocities != 0. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testIsRobotStateStationaryVelocityUnequal) +{ + robot_state::RobotState rstate_1 = robot_state::RobotState(robot_model_); + + // Ensure that the joint velocities are NOT zero + double default_joint_velocity[6] = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + rstate_1.setJointGroupVelocities(planning_group_, default_joint_velocity); + + double epsilon{ 0.0001 }; + EXPECT_FALSE(pilz_industrial_motion_planner::isRobotStateStationary(rstate_1, planning_group_, epsilon)); +} + +/** + * @brief Check that function isRobotStateStationary() returns 'false' if + * the joint acceleration are not equal to zero. + * + * + * Test Sequence: + * 1. Call function with robot state with joint acceleration != 0. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryFunctionsTestFlangeAndGripper, testIsRobotStateStationaryAccelerationUnequal) +{ + robot_state::RobotState rstate_1 = robot_state::RobotState(robot_model_); + + // Ensure that the joint velocities are zero + double default_joint_velocity[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + rstate_1.setJointGroupVelocities(planning_group_, default_joint_velocity); + + // Ensure that the joint acceleration are NOT zero + double default_joint_acceleration[6] = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + rstate_1.setJointGroupAccelerations(planning_group_, default_joint_acceleration); + + double epsilon{ 0.0001 }; + EXPECT_FALSE(pilz_industrial_motion_planner::isRobotStateStationary(rstate_1, planning_group_, epsilon)); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "unittest_trajectory_functions"); + ros::NodeHandle nh; + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_functions.test b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_functions.test new file mode 100644 index 0000000000..ff1c41bb0f --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_functions.test @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator.cpp new file mode 100644 index 0000000000..c1a24e7285 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator.cpp @@ -0,0 +1,146 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include + +#include "pilz_industrial_motion_planner/trajectory_generator.h" + +using namespace pilz_industrial_motion_planner; + +/** + * @brief Checks that each derived MoveItErrorCodeException contains the correct + * error code. + */ +TEST(TrajectoryGeneratorTest, TestExceptionErrorCodeMapping) +{ + { + std::shared_ptr tgil_ex{ new TrajectoryGeneratorInvalidLimitsException( + "") }; + EXPECT_EQ(tgil_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::FAILURE); + } + + { + std::shared_ptr vsi_ex{ new VelocityScalingIncorrect("") }; + EXPECT_EQ(vsi_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + } + + { + std::shared_ptr asi_ex{ new AccelerationScalingIncorrect("") }; + EXPECT_EQ(asi_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + } + + { + std::shared_ptr upg_ex{ new UnknownPlanningGroup("") }; + EXPECT_EQ(upg_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME); + } + + { + std::shared_ptr njniss_ex{ new NoJointNamesInStartState("") }; + EXPECT_EQ(njniss_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); + } + + { + std::shared_ptr smiss_ex{ new SizeMismatchInStartState("") }; + EXPECT_EQ(smiss_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); + } + + { + std::shared_ptr jofssoor_ex{ new JointsOfStartStateOutOfRange("") }; + EXPECT_EQ(jofssoor_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); + } + + { + std::shared_ptr nzviss_ex{ new NonZeroVelocityInStartState("") }; + EXPECT_EQ(nzviss_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); + } + + { + std::shared_ptr neogcg_ex{ new NotExactlyOneGoalConstraintGiven("") }; + EXPECT_EQ(neogcg_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + } + + { + std::shared_ptr oogta_ex{ new OnlyOneGoalTypeAllowed("") }; + EXPECT_EQ(oogta_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + } + + { + std::shared_ptr ssgsm_ex{ new StartStateGoalStateMismatch("") }; + EXPECT_EQ(ssgsm_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + } + + { + std::shared_ptr jcdnbtg_ex{ new JointConstraintDoesNotBelongToGroup("") }; + EXPECT_EQ(jcdnbtg_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + } + + { + std::shared_ptr jogoor_ex{ new JointsOfGoalOutOfRange("") }; + EXPECT_EQ(jogoor_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + } + + { + std::shared_ptr pcnm_ex{ new PositionConstraintNameMissing("") }; + EXPECT_EQ(pcnm_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + } + + { + std::shared_ptr ocnm_ex{ new OrientationConstraintNameMissing("") }; + EXPECT_EQ(ocnm_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + } + + { + std::shared_ptr pocnm_ex{ new PositionOrientationConstraintNameMismatch( + "") }; + EXPECT_EQ(pocnm_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + } + + { + std::shared_ptr nisa_ex{ new NoIKSolverAvailable("") }; + EXPECT_EQ(nisa_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION); + } + + { + std::shared_ptr nppg_ex{ new NoPrimitivePoseGiven("") }; + EXPECT_EQ(nppg_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + } +} + +int main(int argc, char** argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_circ.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_circ.cpp new file mode 100644 index 0000000000..1c1024cb4e --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_circ.cpp @@ -0,0 +1,785 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pilz_industrial_motion_planner/joint_limits_aggregator.h" +#include "pilz_industrial_motion_planner/trajectory_generator_circ.h" +#include "pilz_industrial_motion_planner_testutils/command_types_typedef.h" +#include "pilz_industrial_motion_planner_testutils/xml_testdata_loader.h" +#include "test_utils.h" + +const std::string PARAM_MODEL_NO_GRIPPER_NAME{ "robot_description" }; +const std::string PARAM_MODEL_WITH_GRIPPER_NAME{ "robot_description_pg70" }; + +// parameters from parameter server +const std::string TEST_DATA_FILE_NAME("testdata_file_name"); +const std::string PARAM_PLANNING_GROUP_NAME("planning_group"); +const std::string PARAM_TARGET_LINK_NAME("target_link"); +const std::string CARTESIAN_POSITION_TOLERANCE("cartesian_position_tolerance"); +const std::string ANGULAR_ACC_TOLERANCE("angular_acc_tolerance"); +const std::string ROTATION_AXIS_NORM_TOLERANCE("rot_axis_norm_tolerance"); +const std::string ACCELERATION_TOLERANCE("acceleration_tolerance"); +const std::string OTHER_TOLERANCE("other_tolerance"); + +#define SKIP_IF_GRIPPER \ + if (GetParam() == PARAM_MODEL_WITH_GRIPPER_NAME) \ + { \ + SUCCEED(); \ + return; \ + }; + +using namespace pilz_industrial_motion_planner; +using namespace pilz_industrial_motion_planner_testutils; + +class TrajectoryGeneratorCIRCTest : public testing::TestWithParam +{ +protected: + /** + * @brief Create test scenario for circ trajectory generator + * + */ + void SetUp() override; + + void checkCircResult(const planning_interface::MotionPlanRequest& req, + const planning_interface::MotionPlanResponse& res); + + void getCircCenter(const planning_interface::MotionPlanRequest& req, + const planning_interface::MotionPlanResponse& res, Eigen::Vector3d& circ_center); + +protected: + // ros stuff + ros::NodeHandle ph_{ "~" }; + robot_model::RobotModelConstPtr robot_model_{ robot_model_loader::RobotModelLoader(GetParam()).getModel() }; + std::unique_ptr circ_; + // test data provider + std::unique_ptr tdp_; + + // test parameters from parameter server + std::string planning_group_, target_link_, test_data_file_name_; + int random_trial_num_; + double cartesian_position_tolerance_, angular_acc_tolerance_, rot_axis_norm_tolerance_, acceleration_tolerance_, + other_tolerance_; + LimitsContainer planner_limits_; +}; + +void TrajectoryGeneratorCIRCTest::SetUp() +{ + // get parameters + ASSERT_TRUE(ph_.getParam(TEST_DATA_FILE_NAME, test_data_file_name_)); + ASSERT_TRUE(ph_.getParam(PARAM_PLANNING_GROUP_NAME, planning_group_)); + ASSERT_TRUE(ph_.getParam(PARAM_TARGET_LINK_NAME, target_link_)); + ASSERT_TRUE(ph_.getParam(CARTESIAN_POSITION_TOLERANCE, cartesian_position_tolerance_)); + ASSERT_TRUE(ph_.getParam(ANGULAR_ACC_TOLERANCE, angular_acc_tolerance_)); + ASSERT_TRUE(ph_.getParam(ROTATION_AXIS_NORM_TOLERANCE, rot_axis_norm_tolerance_)); + ASSERT_TRUE(ph_.getParam(ACCELERATION_TOLERANCE, acceleration_tolerance_)); + ASSERT_TRUE(ph_.getParam(OTHER_TOLERANCE, other_tolerance_)); + + // check robot model + testutils::checkRobotModel(robot_model_, planning_group_, target_link_); + + // load the test data provider + tdp_.reset(new pilz_industrial_motion_planner_testutils::XmlTestdataLoader{ test_data_file_name_ }); + ASSERT_NE(nullptr, tdp_) << "Failed to load test data by provider."; + + tdp_->setRobotModel(robot_model_); + + // create the limits container + pilz_industrial_motion_planner::JointLimitsContainer joint_limits = + pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits(ph_, + robot_model_->getActiveJointModels()); + CartesianLimit cart_limits; + // Cartesian limits are chose as such values to ease the manually compute the + // trajectory + + cart_limits.setMaxRotationalVelocity(1 * M_PI); + cart_limits.setMaxTranslationalAcceleration(1 * M_PI); + cart_limits.setMaxTranslationalDeceleration(1 * M_PI); + cart_limits.setMaxTranslationalVelocity(1 * M_PI); + planner_limits_.setJointLimits(joint_limits); + planner_limits_.setCartesianLimits(cart_limits); + + // initialize the LIN trajectory generator + circ_.reset(new TrajectoryGeneratorCIRC(robot_model_, planner_limits_)); + ASSERT_NE(nullptr, circ_) << "failed to create CIRC trajectory generator"; +} + +void TrajectoryGeneratorCIRCTest::checkCircResult(const planning_interface::MotionPlanRequest& req, + const planning_interface::MotionPlanResponse& res) +{ + moveit_msgs::MotionPlanResponse res_msg; + res.getMessage(res_msg); + EXPECT_TRUE(testutils::isGoalReached(res.trajectory_->getFirstWayPointPtr()->getRobotModel(), + res_msg.trajectory.joint_trajectory, req, other_tolerance_)); + + EXPECT_TRUE( + testutils::checkJointTrajectory(res_msg.trajectory.joint_trajectory, planner_limits_.getJointLimitContainer())); + + EXPECT_EQ(req.path_constraints.position_constraints.size(), 1u); + EXPECT_EQ(req.path_constraints.position_constraints.at(0).constraint_region.primitive_poses.size(), 1u); + + // Check that all point have the equal distance to the center + Eigen::Vector3d circ_center; + getCircCenter(req, res, circ_center); + + for (std::size_t i = 0; i < res.trajectory_->getWayPointCount(); ++i) + { + Eigen::Affine3d waypoint_pose = res.trajectory_->getWayPointPtr(i)->getFrameTransform(target_link_); + EXPECT_NEAR( + (res.trajectory_->getFirstWayPointPtr()->getFrameTransform(target_link_).translation() - circ_center).norm(), + (circ_center - waypoint_pose.translation()).norm(), cartesian_position_tolerance_); + } + + // check translational and rotational paths + ASSERT_TRUE(testutils::checkCartesianTranslationalPath(res.trajectory_, target_link_, acceleration_tolerance_)); + ASSERT_TRUE(testutils::checkCartesianRotationalPath(res.trajectory_, target_link_, angular_acc_tolerance_, + rot_axis_norm_tolerance_)); + + for (size_t idx = 0; idx < res.trajectory_->getLastWayPointPtr()->getVariableCount(); ++idx) + { + EXPECT_NEAR(0.0, res.trajectory_->getLastWayPointPtr()->getVariableVelocity(idx), other_tolerance_); + EXPECT_NEAR(0.0, res.trajectory_->getLastWayPointPtr()->getVariableAcceleration(idx), other_tolerance_); + } +} + +void TrajectoryGeneratorCIRCTest::getCircCenter(const planning_interface::MotionPlanRequest& req, + const planning_interface::MotionPlanResponse& res, + Eigen::Vector3d& circ_center) +{ + if (req.path_constraints.name == "center") + { + tf2::convert( + req.path_constraints.position_constraints.at(0).constraint_region.primitive_poses.at(0).position, circ_center); + } + else if (req.path_constraints.name == "interim") + { + Eigen::Vector3d interim; + tf2::convert( + req.path_constraints.position_constraints.at(0).constraint_region.primitive_poses.at(0).position, interim); + Eigen::Vector3d start = res.trajectory_->getFirstWayPointPtr()->getFrameTransform(target_link_).translation(); + Eigen::Vector3d goal = res.trajectory_->getLastWayPointPtr()->getFrameTransform(target_link_).translation(); + + const Eigen::Vector3d t = interim - start; + const Eigen::Vector3d u = goal - start; + const Eigen::Vector3d v = goal - interim; + + const Eigen::Vector3d w = t.cross(u); + + ASSERT_GT(w.norm(), 1e-8) << "Circle center not well defined for given start, interim and goal."; + + circ_center = start + (u * t.dot(t) * u.dot(v) - t * u.dot(u) * t.dot(v)) * 0.5 / pow(w.norm(), 2); + } +} + +/** + * @brief Checks that each derived MoveItErrorCodeException contains the correct + * error code. + */ +TEST(TrajectoryGeneratorCIRCTest, TestExceptionErrorCodeMapping) +{ + { + std::shared_ptr cnp_ex{ new CircleNoPlane("") }; + EXPECT_EQ(cnp_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + } + + { + std::shared_ptr cts_ex{ new CircleToSmall("") }; + EXPECT_EQ(cts_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + } + + { + std::shared_ptr cpdr_ex{ new CenterPointDifferentRadius("") }; + EXPECT_EQ(cpdr_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + } + + { + std::shared_ptr ctcf_ex{ new CircTrajectoryConversionFailure("") }; + EXPECT_EQ(ctcf_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + } + + { + std::shared_ptr upcn_ex{ new UnknownPathConstraintName("") }; + EXPECT_EQ(upcn_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + } + + { + std::shared_ptr npc_ex{ new NoPositionConstraints("") }; + EXPECT_EQ(npc_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + } + + { + std::shared_ptr npp_ex{ new NoPrimitivePose("") }; + EXPECT_EQ(npp_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + } + + { + std::shared_ptr ulnoap_ex{ new UnknownLinkNameOfAuxiliaryPoint("") }; + EXPECT_EQ(ulnoap_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_LINK_NAME); + } + + { + std::shared_ptr nocm_ex{ new NumberOfConstraintsMismatch("") }; + EXPECT_EQ(nocm_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + } + + { + std::shared_ptr cjmiss_ex{ new CircJointMissingInStartState("") }; + EXPECT_EQ(cjmiss_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); + } + + { + std::shared_ptr cifgi_ex{ new CircInverseForGoalIncalculable("") }; + EXPECT_EQ(cifgi_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION); + } +} + +// Instantiate the test cases for robot model with and without gripper +INSTANTIATE_TEST_SUITE_P(InstantiationName, TrajectoryGeneratorCIRCTest, + ::testing::Values(PARAM_MODEL_NO_GRIPPER_NAME, PARAM_MODEL_WITH_GRIPPER_NAME)); + +/** + * @brief Construct a TrajectoryGeneratorCirc with no limits given + */ +TEST_P(TrajectoryGeneratorCIRCTest, noLimits) +{ + LimitsContainer planner_limits; + EXPECT_THROW(TrajectoryGeneratorCIRC(this->robot_model_, planner_limits), TrajectoryGeneratorInvalidLimitsException); +} + +/** + * @brief test invalid motion plan request with incomplete start state and + * cartesian goal + */ +TEST_P(TrajectoryGeneratorCIRCTest, incompleteStartState) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + + planning_interface::MotionPlanRequest req{ circ.toRequest() }; + EXPECT_GT(req.start_state.joint_state.name.size(), 1u); + req.start_state.joint_state.name.resize(1); + req.start_state.joint_state.position.resize(1); // prevent failing check for equal sizes + + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +} + +/** + * @brief test invalid motion plan request with non zero start velocity + */ +TEST_P(TrajectoryGeneratorCIRCTest, nonZeroStartVelocity) +{ + moveit_msgs::MotionPlanRequest req{ tdp_->getCircJointCenterCart("circ1_center_2").toRequest() }; + + // start state has non-zero velocity + req.start_state.joint_state.velocity.push_back(1.0); + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); + req.start_state.joint_state.velocity.clear(); +} + +TEST_P(TrajectoryGeneratorCIRCTest, ValidCommand) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + + planning_interface::MotionPlanResponse res; + EXPECT_TRUE(circ_->generate(circ.toRequest(), res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); +} + +/** + * @brief Generate invalid circ with to high vel scaling + */ +TEST_P(TrajectoryGeneratorCIRCTest, velScaleToHigh) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + + circ.setVelocityScale(1.0); + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(circ.toRequest(), res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::PLANNING_FAILED); +} + +/** + * @brief Generate invalid circ with to high acc scaling + */ +TEST_P(TrajectoryGeneratorCIRCTest, accScaleToHigh) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + + circ.setAccelerationScale(1.0); + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(circ.toRequest(), res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::PLANNING_FAILED); +} + +/** + * @brief Use three points (with center) with a really small distance between to + * trigger a internal throw from KDL + */ +TEST_P(TrajectoryGeneratorCIRCTest, samePointsWithCenter) +{ + // Define auxiliary point and goal to be the same as the start + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose()); + circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.x += 1e-8; + circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.y += 1e-8; + circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.z += 1e-8; + circ.getGoalConfiguration().setPose(circ.getStartConfiguration().getPose()); + circ.getGoalConfiguration().getPose().position.x -= 1e-8; + circ.getGoalConfiguration().getPose().position.y -= 1e-8; + circ.getGoalConfiguration().getPose().position.z -= 1e-8; + + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(circ.toRequest(), res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +} + +/** + * @brief Use three points (with interim) with a really small distance between + * + * Expected: Planning should fail. + */ +TEST_P(TrajectoryGeneratorCIRCTest, samePointsWithInterim) +{ + // Define auxiliary point and goal to be the same as the start + auto circ{ tdp_->getCircCartInterimCart("circ3_interim") }; + circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose()); + circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.x += 1e-8; + circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.y += 1e-8; + circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.z += 1e-8; + circ.getGoalConfiguration().setPose(circ.getStartConfiguration().getPose()); + circ.getGoalConfiguration().getPose().position.x -= 1e-8; + circ.getGoalConfiguration().getPose().position.y -= 1e-8; + circ.getGoalConfiguration().getPose().position.z -= 1e-8; + + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(circ.toRequest(), res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +} + +/** + * @brief test invalid motion plan request with no aux point defined + */ +TEST_P(TrajectoryGeneratorCIRCTest, emptyAux) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + + planning_interface::MotionPlanRequest req = circ.toRequest(); + + req.path_constraints.position_constraints.clear(); + + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +} + +/** + * @brief test invalid motion plan request with no aux name defined + */ +TEST_P(TrajectoryGeneratorCIRCTest, invalidAuxName) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + + planning_interface::MotionPlanRequest req = circ.toRequest(); + + req.path_constraints.name = ""; + + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +} + +/** + * @brief test invalid motion plan request with invalid link name in the + * auxiliary point + */ +TEST_P(TrajectoryGeneratorCIRCTest, invalidAuxLinkName) +{ + auto circ{ tdp_->getCircJointInterimCart("circ3_interim") }; + + planning_interface::MotionPlanRequest req = circ.toRequest(); + + req.path_constraints.position_constraints.front().link_name = "INVALID"; + + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_LINK_NAME); +} + +/** + * @brief test the circ planner with invalid center point + */ +TEST_P(TrajectoryGeneratorCIRCTest, invalidCenter) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose()); + circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.y += 1; + + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(circ.toRequest(), res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +} + +/** + * @brief test the circ planner with colinear start/goal/center position + * + * Expected: Planning should fail since the path is not uniquely defined. + */ +TEST_P(TrajectoryGeneratorCIRCTest, colinearCenter) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose()); + circ.getGoalConfiguration().setPose(circ.getStartConfiguration().getPose()); + + // Stretch start and goal pose along line + circ.getStartConfiguration().getPose().position.x -= 0.1; + circ.getGoalConfiguration().getPose().position.x += 0.1; + + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(circ.toRequest(), res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +} + +/** + * @brief test the circ planner with colinear start/goal/interim position + * + * Expected: Planning should fail. These positions do not even represent a + * circle. + */ +TEST_P(TrajectoryGeneratorCIRCTest, colinearInterim) +{ + auto circ{ tdp_->getCircCartInterimCart("circ3_interim") }; + circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose()); + circ.getGoalConfiguration().setPose(circ.getStartConfiguration().getPose()); + + // Stretch start and goal pose along line + circ.getStartConfiguration().getPose().position.x -= 0.1; + circ.getGoalConfiguration().getPose().position.x += 0.1; + + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(circ.toRequest(), res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +} + +/** + * @brief test the circ planner with half circle with interim point + * + * The request contains start/interim/goal such that + * start, center (not explicitly given) and goal are colinear + * + * Expected: Planning should successfully return. + */ +TEST_P(TrajectoryGeneratorCIRCTest, colinearCenterDueToInterim) +{ + // get the test data from xml + auto circ{ tdp_->getCircCartInterimCart("circ3_interim") }; + + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(circ_->generate(circ.toRequest(), res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); +} + +/** + * @brief test the circ planner with colinear start/center/interim positions + * + * The request contains start/interim/goal such that + * start, center (not explicitly given) and interim are colinear. + * In case the interim is used as auxiliary point for KDL::Path_Circle this + * should fail. + * + * Expected: Planning should successfully return. + */ +TEST_P(TrajectoryGeneratorCIRCTest, colinearCenterAndInterim) +{ + auto circ{ tdp_->getCircCartInterimCart("circ3_interim") }; + + // alter start, interim and goal such that start/center and interim are + // colinear + circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose()); + circ.getGoalConfiguration().setPose(circ.getStartConfiguration().getPose()); + + circ.getStartConfiguration().getPose().position.x -= 0.2; + circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.x += 0.2; + circ.getGoalConfiguration().getPose().position.y -= 0.2; + + circ.setAccelerationScale(0.05); + circ.setVelocityScale(0.05); + + moveit_msgs::MotionPlanRequest req = circ.toRequest(); + + planning_interface::MotionPlanResponse res; + EXPECT_TRUE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + checkCircResult(req, res); +} + +/** + * @brief test the circ planner with a circ path where the angle between goal + * and interim is larger than 180 degree + * + * The request contains start/interim/goal such that 180 degree < interim angle + * < goal angle. + * + * Expected: Planning should successfully return. + */ +TEST_P(TrajectoryGeneratorCIRCTest, interimLarger180Degree) +{ + auto circ{ tdp_->getCircCartInterimCart("circ3_interim") }; + + // alter start, interim and goal such that start/center and interim are + // colinear + circ.getAuxiliaryConfiguration().getConfiguration().setPose(circ.getStartConfiguration().getPose()); + circ.getGoalConfiguration().setPose(circ.getStartConfiguration().getPose()); + + circ.getStartConfiguration().getPose().position.x -= 0.2; + circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.x += 0.14142136; + circ.getAuxiliaryConfiguration().getConfiguration().getPose().position.y -= 0.14142136; + circ.getGoalConfiguration().getPose().position.y -= 0.2; + + circ.setAccelerationScale(0.05); + circ.setVelocityScale(0.05); + + moveit_msgs::MotionPlanRequest req = circ.toRequest(); + + planning_interface::MotionPlanResponse res; + EXPECT_TRUE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + checkCircResult(req, res); +} + +/** + * @brief test the circ planner with center point and joint goal + */ +TEST_P(TrajectoryGeneratorCIRCTest, centerPointJointGoal) +{ + SKIP_IF_GRIPPER + + auto circ{ tdp_->getCircJointCenterCart("circ1_center_2") }; + moveit_msgs::MotionPlanRequest req = circ.toRequest(); + + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + checkCircResult(req, res); +} + +/** + * @brief A valid circ request contains a helping point (interim or center), in + * this test a additional + * point is defined as an invalid test case + */ +TEST_P(TrajectoryGeneratorCIRCTest, InvalidAdditionalPrimitivePose) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + + moveit_msgs::MotionPlanRequest req = circ.toRequest(); + + // Contains one pose (interim / center) + ASSERT_EQ(req.path_constraints.position_constraints.back().constraint_region.primitive_poses.size(), 1u); + + // Define a additional pose here + geometry_msgs::Pose center_position; + center_position.position.x = 0.0; + center_position.position.y = 0.0; + center_position.position.z = 0.65; + req.path_constraints.position_constraints.back().constraint_region.primitive_poses.push_back(center_position); + + planning_interface::MotionPlanResponse res; + ASSERT_FALSE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +} + +/** + * @brief Joint Goals are expected to match the start state in number and + * joint_names + * Here an additional joint constraints is "falsely" defined to check for the + * error. + */ +TEST_P(TrajectoryGeneratorCIRCTest, InvalidExtraJointConstraint) +{ + auto circ{ tdp_->getCircJointCenterCart("circ1_center_2") }; + + moveit_msgs::MotionPlanRequest req = circ.toRequest(); + + // Define the additional joint constraint + moveit_msgs::JointConstraint joint_constraint; + joint_constraint.joint_name = req.goal_constraints.front().joint_constraints.front().joint_name; + req.goal_constraints.front().joint_constraints.push_back(joint_constraint); //<-- Additional constraint + + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +} + +/** + * @brief test the circ planner with center point and pose goal + */ +TEST_P(TrajectoryGeneratorCIRCTest, CenterPointPoseGoal) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + + moveit_msgs::MotionPlanRequest req = circ.toRequest(); + + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + checkCircResult(req, res); +} + +/** + * @brief Set a frame id only on the position constrainst + */ +TEST_P(TrajectoryGeneratorCIRCTest, CenterPointPoseGoalFrameIdPositionConstraints) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + + moveit_msgs::MotionPlanRequest req = circ.toRequest(); + + req.goal_constraints.front().position_constraints.front().header.frame_id = robot_model_->getModelFrame(); + + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + checkCircResult(req, res); +} + +/** + * @brief Set a frame id only on the orientation constrainst + */ +TEST_P(TrajectoryGeneratorCIRCTest, CenterPointPoseGoalFrameIdOrientationConstraints) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + + moveit_msgs::MotionPlanRequest req = circ.toRequest(); + req.goal_constraints.front().orientation_constraints.front().header.frame_id = robot_model_->getModelFrame(); + + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + checkCircResult(req, res); +} + +/** + * @brief Set a frame_id on both position and orientation constraints + */ +TEST_P(TrajectoryGeneratorCIRCTest, CenterPointPoseGoalFrameIdBothConstraints) +{ + auto circ{ tdp_->getCircCartCenterCart("circ1_center_2") }; + + moveit_msgs::MotionPlanRequest req = circ.toRequest(); + + // Both set + req.goal_constraints.front().position_constraints.front().header.frame_id = robot_model_->getModelFrame(); + req.goal_constraints.front().orientation_constraints.front().header.frame_id = robot_model_->getModelFrame(); + + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + checkCircResult(req, res); +} + +/** + * @brief test the circ planner with interim point with joint goal + */ +TEST_P(TrajectoryGeneratorCIRCTest, InterimPointJointGoal) +{ + SKIP_IF_GRIPPER + + auto circ{ tdp_->getCircJointInterimCart("circ3_interim") }; + + moveit_msgs::MotionPlanRequest req = circ.toRequest(); + + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + checkCircResult(req, res); +} + +/** + * @brief test the circ planner with interim point with joint goal and a close + * to zero velocity of the start state + * + * The generator is expected to be robust against a velocity beeing almost zero. + */ +TEST_P(TrajectoryGeneratorCIRCTest, InterimPointJointGoalStartVelNearZero) +{ + SKIP_IF_GRIPPER + + auto circ{ tdp_->getCircJointInterimCart("circ3_interim") }; + + moveit_msgs::MotionPlanRequest req = circ.toRequest(); + + // Set velocity near zero + req.start_state.joint_state.velocity = std::vector(req.start_state.joint_state.position.size(), 1e-16); + + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + checkCircResult(req, res); +} + +/** + * @brief test the circ planner with interim point with pose goal + */ +TEST_P(TrajectoryGeneratorCIRCTest, InterimPointPoseGoal) +{ + auto circ{ tdp_->getCircJointInterimCart("circ3_interim") }; + moveit_msgs::MotionPlanRequest req = circ.toRequest(); + + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(circ_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + checkCircResult(req, res); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "unittest_trajectory_generator_circ"); + ros::NodeHandle nh; + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_circ.test b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_circ.test new file mode 100644 index 0000000000..6d84d42105 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_circ.test @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_common.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_common.cpp new file mode 100644 index 0000000000..aaba86c0f1 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_common.cpp @@ -0,0 +1,434 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pilz_industrial_motion_planner/joint_limits_aggregator.h" +#include "pilz_industrial_motion_planner/joint_limits_container.h" +#include "pilz_industrial_motion_planner/trajectory_generator_circ.h" +#include "pilz_industrial_motion_planner/trajectory_generator_lin.h" +#include "pilz_industrial_motion_planner/trajectory_generator_ptp.h" + +#include "test_utils.h" + +const std::string PARAM_MODEL_NO_GRIPPER_NAME{ "robot_description" }; +const std::string PARAM_MODEL_WITH_GRIPPER_NAME{ "robot_description_pg70" }; + +// parameters from parameter server +const std::string PARAM_PLANNING_GROUP_NAME("planning_group"); +const std::string PARAM_TARGET_LINK_NAME("target_link"); + +/** + * A value type container to combine type and value + * In the tests types are trajectory generators. + * value = 0 refers to robot model without gripper + * value = 1 refers to robot model with gripper + */ +template +class ValueTypeContainer +{ +public: + typedef T Type_; + static const int VALUE = N; +}; +template +const int ValueTypeContainer::VALUE; + +typedef ValueTypeContainer PTP_NO_GRIPPER; +typedef ValueTypeContainer PTP_WITH_GRIPPER; +typedef ValueTypeContainer LIN_NO_GRIPPER; +typedef ValueTypeContainer LIN_WITH_GRIPPER; +typedef ValueTypeContainer CIRC_NO_GRIPPER; +typedef ValueTypeContainer CIRC_WITH_GRIPPER; + +typedef ::testing::Types + TrajectoryGeneratorCommonTestTypes; + +typedef ::testing::Types TrajectoryGeneratorCommonTestTypesNoGripper; + +typedef ::testing::Types + TrajectoryGeneratorCommonTestTypesWithGripper; + +/** + * type parameterized test fixture + */ +template +class TrajectoryGeneratorCommonTest : public ::testing::Test +{ +protected: + void SetUp() override + { + ASSERT_TRUE(ph_.getParam(PARAM_PLANNING_GROUP_NAME, planning_group_)); + ASSERT_TRUE(ph_.getParam(PARAM_TARGET_LINK_NAME, target_link_)); + + testutils::checkRobotModel(robot_model_, planning_group_, target_link_); + + // create the limits container + std::string robot_description_param = (!T::VALUE ? PARAM_MODEL_NO_GRIPPER_NAME : PARAM_MODEL_WITH_GRIPPER_NAME); + pilz_industrial_motion_planner::JointLimitsContainer joint_limits = + pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits( + ros::NodeHandle(robot_description_param + "_planning"), robot_model_->getActiveJointModels()); + pilz_industrial_motion_planner::CartesianLimit cart_limits; + cart_limits.setMaxRotationalVelocity(0.5 * M_PI); + cart_limits.setMaxTranslationalAcceleration(2); + cart_limits.setMaxTranslationalDeceleration(2); + cart_limits.setMaxTranslationalVelocity(1); + pilz_industrial_motion_planner::LimitsContainer planner_limits; + planner_limits.setJointLimits(joint_limits); + planner_limits.setCartesianLimits(cart_limits); + + // create planner instance + trajectory_generator_ = std::unique_ptr(new typename T::Type_(robot_model_, planner_limits)); + ASSERT_NE(nullptr, trajectory_generator_) << "failed to create trajectory generator"; + + // create a valid motion plan request with goal in joint space as basis for + // tests + req_.group_name = planning_group_; + req_.max_velocity_scaling_factor = 1.0; + req_.max_acceleration_scaling_factor = 1.0; + robot_state::RobotState rstate(robot_model_); + rstate.setToDefaultValues(); + rstate.setJointGroupPositions(planning_group_, { 0, M_PI / 2, 0, M_PI / 2, 0, 0 }); + rstate.setVariableVelocities(std::vector(rstate.getVariableCount(), 0.0)); + moveit::core::robotStateToRobotStateMsg(rstate, req_.start_state, false); + moveit_msgs::Constraints goal_constraint; + moveit_msgs::JointConstraint joint_constraint; + joint_constraint.joint_name = this->robot_model_->getActiveJointModels().front()->getName(); + joint_constraint.position = 0.5; + goal_constraint.joint_constraints.push_back(joint_constraint); + req_.goal_constraints.push_back(goal_constraint); + } + +protected: + // ros stuff + ros::NodeHandle ph_{ "~" }; + robot_model::RobotModelConstPtr robot_model_{ + robot_model_loader::RobotModelLoader(!T::VALUE ? PARAM_MODEL_NO_GRIPPER_NAME : PARAM_MODEL_WITH_GRIPPER_NAME) + .getModel() + }; + + // trajectory generator + std::unique_ptr trajectory_generator_; + planning_interface::MotionPlanResponse res_; + planning_interface::MotionPlanRequest req_; + // test parameters from parameter server + std::string planning_group_, target_link_; +}; +// Define the types we need to test +TYPED_TEST_SUITE(TrajectoryGeneratorCommonTest, TrajectoryGeneratorCommonTestTypes); + +template +class TrajectoryGeneratorCommonTestNoGripper : public TrajectoryGeneratorCommonTest +{ +}; +TYPED_TEST_SUITE(TrajectoryGeneratorCommonTestNoGripper, TrajectoryGeneratorCommonTestTypesNoGripper); + +template +class TrajectoryGeneratorCommonTestWithGripper : public TrajectoryGeneratorCommonTest +{ +}; +TYPED_TEST_SUITE(TrajectoryGeneratorCommonTestWithGripper, TrajectoryGeneratorCommonTestTypesWithGripper); + +/** + * @brief test invalid scaling factor. The scaling factor must be in the range + * of [0.0001, 1] + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, InvalideScalingFactor) +{ + this->req_.max_velocity_scaling_factor = 2.0; + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + + this->req_.max_velocity_scaling_factor = 1.0; + this->req_.max_acceleration_scaling_factor = 0; + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + + this->req_.max_velocity_scaling_factor = 0.00001; + this->req_.max_acceleration_scaling_factor = 1; + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); + + this->req_.max_velocity_scaling_factor = 1; + this->req_.max_acceleration_scaling_factor = -1; + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN); +} + +/** + * @brief Test invalid motion plan request for all trajectory generators + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, InvalidGroupName) +{ + this->req_.group_name = "foot"; + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME, this->res_.error_code_.val); +} + +/** + * @brief Test invalid motion plan request for all trajectory generators + */ +TYPED_TEST(TrajectoryGeneratorCommonTestNoGripper, GripperGroup) +{ + this->req_.group_name = "gripper"; + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME, this->res_.error_code_.val); +} + +/** + * @brief Test invalid motion plan request for all trajectory generators + */ +TYPED_TEST(TrajectoryGeneratorCommonTestWithGripper, GripperGroup) +{ + this->req_.group_name = "gripper"; + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS, this->res_.error_code_.val); +} + +/** + * @brief Test if there is a valid inverse kinematics solver for this planning + * group + * You can only test this case by commenting the planning_context.launch in the + * .test file + * //TODO create a separate robot model without ik solver and use it to create a + * trajectory generator + */ +// TYPED_TEST(TrajectoryGeneratorCommonTest, NoIKSolver) +//{ +// EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); +// EXPECT_EQ(this->res_.error_code_.val, +// moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME); +//} + +/** + * @brief test the case of empty joint names in start state + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, EmptyJointNamesInStartState) +{ + this->req_.start_state.joint_state.name.clear(); + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +} + +/** + * @brief size of joint name and joint position does not match in start state + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, InconsistentStartState) +{ + this->req_.start_state.joint_state.name.push_back("joint_7"); + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +} + +/** + * @brief joint position out of limit in start state + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, StartPostionOutOfLimit) +{ + this->req_.start_state.joint_state.position[0] = 100; + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +} + +/** + * @brief Check that no trajectory is generated if a start velocity is given + * + * @note This test is here for regression, however in general generators that + * can work with a given + * start velocity are highly desired. + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, StartPositionVelocityNoneZero) +{ + this->req_.start_state.joint_state.velocity[0] = 100; + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +} + +/** + * @brief goal constraints is empty + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, EmptyGoalConstraints) +{ + this->req_.goal_constraints.clear(); + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +} + +/** + * @brief multiple goals + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, MultipleGoals) +{ + moveit_msgs::JointConstraint joint_constraint; + moveit_msgs::PositionConstraint position_constraint; + moveit_msgs::OrientationConstraint orientation_constraint; + moveit_msgs::Constraints goal_constraint; + + // two goal constraints + this->req_.goal_constraints.push_back(goal_constraint); + this->req_.goal_constraints.push_back(goal_constraint); + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + + // one joint constraint and one orientation constraint + goal_constraint.joint_constraints.push_back(joint_constraint); + goal_constraint.orientation_constraints.push_back(orientation_constraint); + this->req_.goal_constraints.clear(); + this->req_.goal_constraints.push_back(goal_constraint); + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + + // one joint constraint and one Cartesian constraint + goal_constraint.position_constraints.push_back(position_constraint); + goal_constraint.orientation_constraints.push_back(orientation_constraint); + this->req_.goal_constraints.clear(); + this->req_.goal_constraints.push_back(goal_constraint); + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + + // two Cartesian constraints + goal_constraint.joint_constraints.clear(); + goal_constraint.position_constraints.push_back(position_constraint); + goal_constraint.orientation_constraints.push_back(orientation_constraint); + goal_constraint.position_constraints.push_back(position_constraint); + goal_constraint.orientation_constraints.push_back(orientation_constraint); + this->req_.goal_constraints.clear(); + this->req_.goal_constraints.push_back(goal_constraint); + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +} + +/** + * @brief invalid joint name in joint constraint + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, InvalideJointNameInGoal) +{ + moveit_msgs::JointConstraint joint_constraint; + joint_constraint.joint_name = "test_joint_2"; + this->req_.goal_constraints.front().joint_constraints[0] = joint_constraint; + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +} + +/** + * @brief MissingJointConstraint + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, MissingJointConstraint) +{ + moveit_msgs::JointConstraint joint_constraint; + joint_constraint.joint_name = "test_joint_2"; + this->req_.goal_constraints.front().joint_constraints.pop_back(); //<-- Missing joint constraint + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +} + +/** + * @brief invalid joint position in joint constraint + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, InvalideJointPositionInGoal) +{ + this->req_.goal_constraints.front().joint_constraints[0].position = 100; + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +} + +/** + * @brief invalid link name in Cartesian goal constraint + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, InvalidLinkNameInCartesianGoal) +{ + moveit_msgs::PositionConstraint position_constraint; + moveit_msgs::OrientationConstraint orientation_constraint; + moveit_msgs::Constraints goal_constraint; + // link name not set + goal_constraint.position_constraints.push_back(position_constraint); + goal_constraint.orientation_constraints.push_back(orientation_constraint); + this->req_.goal_constraints.clear(); + this->req_.goal_constraints.push_back(goal_constraint); + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + + // different link names in position and orientation goals + goal_constraint.position_constraints.front().link_name = "test_link_1"; + goal_constraint.orientation_constraints.front().link_name = "test_link_2"; + this->req_.goal_constraints.clear(); + this->req_.goal_constraints.push_back(goal_constraint); + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + + // no solver for the link + goal_constraint.orientation_constraints.front().link_name = "test_link_1"; + this->req_.goal_constraints.clear(); + this->req_.goal_constraints.push_back(goal_constraint); + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION); +} + +/** + * @brief no pose set in position constraint + */ +TYPED_TEST(TrajectoryGeneratorCommonTest, EmptyPrimitivePoses) +{ + moveit_msgs::PositionConstraint position_constraint; + moveit_msgs::OrientationConstraint orientation_constraint; + moveit_msgs::Constraints goal_constraint; + position_constraint.link_name = + this->robot_model_->getJointModelGroup(this->planning_group_)->getLinkModelNames().back(); + orientation_constraint.link_name = position_constraint.link_name; + + goal_constraint.position_constraints.push_back(position_constraint); + goal_constraint.orientation_constraints.push_back(orientation_constraint); + this->req_.goal_constraints.clear(); + this->req_.goal_constraints.push_back(goal_constraint); + EXPECT_FALSE(this->trajectory_generator_->generate(this->req_, this->res_)); + EXPECT_EQ(this->res_.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "unittest_trajectory_generator_common"); + // ros::NodeHandle nh; + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_common.test b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_common.test new file mode 100644 index 0000000000..702c2dc5fc --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_common.test @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_lin.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_lin.cpp new file mode 100644 index 0000000000..f5724b7af5 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_lin.cpp @@ -0,0 +1,470 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include + +#include "pilz_industrial_motion_planner/joint_limits_aggregator.h" +#include "pilz_industrial_motion_planner/trajectory_generator_lin.h" +#include "pilz_industrial_motion_planner_testutils/command_types_typedef.h" +#include "pilz_industrial_motion_planner_testutils/xml_testdata_loader.h" +#include "test_utils.h" + +#include +#include +#include +#include +#include +#include + +#include + +const std::string PARAM_MODEL_NO_GRIPPER_NAME{ "robot_description" }; +const std::string PARAM_MODEL_WITH_GRIPPER_NAME{ "robot_description_pg70" }; + +// parameters from parameter server +const std::string TEST_DATA_FILE_NAME("testdata_file_name"); +const std::string PARAM_PLANNING_GROUP_NAME("planning_group"); +const std::string TARGET_LINK_HCD("target_link_hand_computed_data"); +const std::string RANDOM_TEST_TRIAL_NUM("random_trial_number"); +const std::string JOINT_POSITION_TOLERANCE("joint_position_tolerance"); +const std::string JOINT_VELOCITY_TOLERANCE("joint_velocity_tolerance"); +const std::string POSE_TRANSFORM_MATRIX_NORM_TOLERANCE("pose_norm_tolerance"); +const std::string ROTATION_AXIS_NORM_TOLERANCE("rot_axis_norm_tolerance"); +const std::string VELOCITY_SCALING_FACTOR("velocity_scaling_factor"); +const std::string OTHER_TOLERANCE("other_tolerance"); + +using namespace pilz_industrial_motion_planner; +using namespace pilz_industrial_motion_planner_testutils; + +/** + * @brief Parameterized unittest of trajectory generator LIN to enable tests + * against + * different robot models.The parameter is the name of robot model parameter on + * the + * ros parameter server. + */ +class TrajectoryGeneratorLINTest : public testing::TestWithParam +{ +protected: + /** + * @brief Create test scenario for lin trajectory generator + * + */ + void SetUp() override; + + bool checkLinResponse(const planning_interface::MotionPlanRequest& req, + const planning_interface::MotionPlanResponse& res); + +protected: + // ros stuff + ros::NodeHandle ph_{ "~" }; + robot_model::RobotModelConstPtr robot_model_{ robot_model_loader::RobotModelLoader(GetParam()).getModel() }; + + // lin trajectory generator using model without gripper + std::unique_ptr lin_; + // test data provider + std::unique_ptr tdp_; + + // test parameters from parameter server + std::string planning_group_, target_link_hcd_, test_data_file_name_; + int random_trial_num_; + double joint_position_tolerance_, joint_velocity_tolerance_, pose_norm_tolerance_, rot_axis_norm_tolerance_, + velocity_scaling_factor_, other_tolerance_; + LimitsContainer planner_limits_; +}; + +void TrajectoryGeneratorLINTest::SetUp() +{ + // get the parameters + ASSERT_TRUE(ph_.getParam(TEST_DATA_FILE_NAME, test_data_file_name_)); + ASSERT_TRUE(ph_.getParam(PARAM_PLANNING_GROUP_NAME, planning_group_)); + ASSERT_TRUE(ph_.getParam(TARGET_LINK_HCD, target_link_hcd_)); + ASSERT_TRUE(ph_.getParam(RANDOM_TEST_TRIAL_NUM, random_trial_num_)); + ASSERT_TRUE(ph_.getParam(JOINT_POSITION_TOLERANCE, joint_position_tolerance_)); + ASSERT_TRUE(ph_.getParam(JOINT_VELOCITY_TOLERANCE, joint_velocity_tolerance_)); + ASSERT_TRUE(ph_.getParam(POSE_TRANSFORM_MATRIX_NORM_TOLERANCE, pose_norm_tolerance_)); + ASSERT_TRUE(ph_.getParam(ROTATION_AXIS_NORM_TOLERANCE, rot_axis_norm_tolerance_)); + ASSERT_TRUE(ph_.getParam(VELOCITY_SCALING_FACTOR, velocity_scaling_factor_)); + ASSERT_TRUE(ph_.getParam(OTHER_TOLERANCE, other_tolerance_)); + + testutils::checkRobotModel(robot_model_, planning_group_, target_link_hcd_); + + // load the test data provider + tdp_.reset(new pilz_industrial_motion_planner_testutils::XmlTestdataLoader{ test_data_file_name_ }); + ASSERT_NE(nullptr, tdp_) << "Failed to load test data by provider."; + + tdp_->setRobotModel(robot_model_); + + // create the limits container + // TODO, move this also into test data set + pilz_industrial_motion_planner::JointLimitsContainer joint_limits = + pilz_industrial_motion_planner::JointLimitsAggregator::getAggregatedLimits(ph_, + robot_model_->getActiveJointModels()); + CartesianLimit cart_limits; + cart_limits.setMaxRotationalVelocity(0.5 * M_PI); + cart_limits.setMaxTranslationalAcceleration(2); + cart_limits.setMaxTranslationalDeceleration(2); + cart_limits.setMaxTranslationalVelocity(1); + planner_limits_.setJointLimits(joint_limits); + planner_limits_.setCartesianLimits(cart_limits); + + // initialize the LIN trajectory generator + lin_.reset(new TrajectoryGeneratorLIN(robot_model_, planner_limits_)); + ASSERT_NE(nullptr, lin_) << "Failed to create LIN trajectory generator."; +} + +bool TrajectoryGeneratorLINTest::checkLinResponse(const planning_interface::MotionPlanRequest& req, + const planning_interface::MotionPlanResponse& res) +{ + moveit_msgs::MotionPlanResponse res_msg; + res.getMessage(res_msg); + if (!testutils::isGoalReached(robot_model_, res_msg.trajectory.joint_trajectory, req, pose_norm_tolerance_)) + { + return false; + } + + if (!testutils::checkCartesianLinearity(robot_model_, res_msg.trajectory.joint_trajectory, req, pose_norm_tolerance_, + rot_axis_norm_tolerance_)) + { + return false; + } + + if (!testutils::checkJointTrajectory(res_msg.trajectory.joint_trajectory, planner_limits_.getJointLimitContainer())) + { + return false; + } + + return true; +} + +/** + * @brief Checks that each derived MoveItErrorCodeException contains the correct + * error code. + */ +TEST(TrajectoryGeneratorLINTest, TestExceptionErrorCodeMapping) +{ + { + std::shared_ptr ltcf_ex{ new LinTrajectoryConversionFailure("") }; + EXPECT_EQ(ltcf_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::FAILURE); + } + + { + std::shared_ptr jnm_ex{ new JointNumberMismatch("") }; + EXPECT_EQ(jnm_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + } + + { + std::shared_ptr ljmiss_ex{ new LinJointMissingInStartState("") }; + EXPECT_EQ(ljmiss_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); + } + + { + std::shared_ptr lifgi_ex{ new LinInverseForGoalIncalculable("") }; + EXPECT_EQ(lifgi_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION); + } +} + +// Instantiate the test cases for robot model with and without gripper +INSTANTIATE_TEST_SUITE_P(InstantiationName, TrajectoryGeneratorLINTest, + ::testing::Values(PARAM_MODEL_NO_GRIPPER_NAME, PARAM_MODEL_WITH_GRIPPER_NAME)); + +/** + * @brief test the lin planner with invalid motion plan request which has non + * zero start velocity + */ +TEST_P(TrajectoryGeneratorLINTest, nonZeroStartVelocity) +{ + planning_interface::MotionPlanRequest req{ tdp_->getLinJoint("lin2").toRequest() }; + + // add non-zero velocity in the start state + req.start_state.joint_state.velocity.push_back(1.0); + + // try to generate the result + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(lin_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +} + +/** + * @brief test the lin planner with joint space goal + */ +TEST_P(TrajectoryGeneratorLINTest, jointSpaceGoal) +{ + planning_interface::MotionPlanRequest lin_joint_req{ tdp_->getLinJoint("lin2").toRequest() }; + + // generate the LIN trajectory + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(lin_->generate(lin_joint_req, res)); + EXPECT_TRUE(res.error_code_.val == moveit_msgs::MoveItErrorCodes::SUCCESS); + + // check the resulted trajectory + EXPECT_TRUE(checkLinResponse(lin_joint_req, res)); +} + +/** + * @brief test the lin planner with joint space goal with start velocity almost + * zero + */ +TEST_P(TrajectoryGeneratorLINTest, jointSpaceGoalNearZeroStartVelocity) +{ + planning_interface::MotionPlanRequest lin_joint_req{ tdp_->getLinJoint("lin2").toRequest() }; + + // Set velocity near zero + lin_joint_req.start_state.joint_state.velocity = + std::vector(lin_joint_req.start_state.joint_state.position.size(), 1e-16); + + // generate the LIN trajectory + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(lin_->generate(lin_joint_req, res)); + EXPECT_TRUE(res.error_code_.val == moveit_msgs::MoveItErrorCodes::SUCCESS); + + // check the resulted trajectory + EXPECT_TRUE(checkLinResponse(lin_joint_req, res)); +} + +/** + * @brief test the lin planner with Cartesian goal + */ +TEST_P(TrajectoryGeneratorLINTest, cartesianSpaceGoal) +{ + // construct motion plan request + moveit_msgs::MotionPlanRequest lin_cart_req{ tdp_->getLinCart("lin2").toRequest() }; + + // generate lin trajectory + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(lin_->generate(lin_cart_req, res)); + EXPECT_TRUE(res.error_code_.val == moveit_msgs::MoveItErrorCodes::SUCCESS); + + // check the resulted trajectory + EXPECT_TRUE(checkLinResponse(lin_cart_req, res)); +} + +/** + * @brief test the trapezoid shape of the planning trajectory in Cartesian space + * + * The test checks translational path for a trapezoid velocity profile. + * Due to the way the acceleration is calculated 1 or 2 intermediate points + * occur that are neither + * acceleration, constant or deceleration. + */ +TEST_P(TrajectoryGeneratorLINTest, cartesianTrapezoidProfile) +{ + // construct motion plan request + moveit_msgs::MotionPlanRequest lin_joint_req{ tdp_->getLinJoint("lin2").toRequest() }; + + /// +++++++++++++++++++++++ + /// + plan LIN trajectory + + /// +++++++++++++++++++++++ + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(lin_->generate(lin_joint_req, res, 0.01)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + + ASSERT_TRUE(testutils::checkCartesianTranslationalPath(res.trajectory_, target_link_hcd_)); + + // check last point for vel=acc=0 + for (size_t idx = 0; idx < res.trajectory_->getLastWayPointPtr()->getVariableCount(); ++idx) + { + EXPECT_NEAR(0.0, res.trajectory_->getLastWayPointPtr()->getVariableVelocity(idx), other_tolerance_); + EXPECT_NEAR(0.0, res.trajectory_->getLastWayPointPtr()->getVariableAcceleration(idx), other_tolerance_); + } +} + +/** + * @brief Check that lin planner returns 'false' if + * calculated lin trajectory violates velocity/acceleration or deceleration + * limits. + * + * + * Test Sequence: + * 1. Call function with lin request violating velocity/acceleration or + * deceleration limits. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryGeneratorLINTest, LinPlannerLimitViolation) +{ + LinJoint lin{ tdp_->getLinJoint("lin2") }; + lin.setAccelerationScale(1.01); + + planning_interface::MotionPlanResponse res; + ASSERT_FALSE(lin_->generate(lin.toRequest(), res)); +} + +/** + * @brief test joint linear movement with discontinuities in joint space + * + * This will violate joint velocity/acceleration limits. + * + * Test Sequence: + * 1. Generate lin trajectory which is discontinuous in joint space. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryGeneratorLINTest, LinPlannerDiscontinuousJointTraj) +{ + LinJoint lin{ tdp_->getLinJoint("lin2") }; + // Alter goal joint configuration (represents the same cartesian pose, but + // does not fit together with start config) + lin.getGoalConfiguration().setJoint(1, 1.63); + lin.getGoalConfiguration().setJoint(2, 0.96); + lin.getGoalConfiguration().setJoint(4, -2.48); + lin.setVelocityScale(1.0); + lin.setAccelerationScale(1.0); + + planning_interface::MotionPlanResponse res; + ASSERT_FALSE(lin_->generate(lin.toRequest(), res)); +} + +/** + * @brief test joint linear movement with equal goal and start + * + * Test Sequence: + * 1. Call function with lin request start = goal + * + * Expected Results: + * 1. trajectory generation is successful. + */ +TEST_P(TrajectoryGeneratorLINTest, LinStartEqualsGoal) +{ + // construct motion plan request + moveit_msgs::MotionPlanRequest lin_joint_req{ tdp_->getLinJoint("lin2").toRequest() }; + + moveit::core::RobotState start_state(robot_model_); + jointStateToRobotState(lin_joint_req.start_state.joint_state, start_state); + + for (auto& joint_constraint : lin_joint_req.goal_constraints.at(0).joint_constraints) + { + joint_constraint.position = start_state.getVariablePosition(joint_constraint.joint_name); + } + + // generate the LIN trajectory + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(lin_->generate(lin_joint_req, res)); + EXPECT_TRUE(res.error_code_.val == moveit_msgs::MoveItErrorCodes::SUCCESS); + + // check the resulted trajectory + EXPECT_TRUE(checkLinResponse(lin_joint_req, res)); +} + +/** + * @brief Checks that constructor throws an exception if no limits are given. + * + * Test Sequence: + * 1. Call Ctor without set limits. + * + * Expected Results: + * 1. Ctor throws exception. + */ +TEST_P(TrajectoryGeneratorLINTest, CtorNoLimits) +{ + pilz_industrial_motion_planner::LimitsContainer planner_limits; + + EXPECT_THROW(pilz_industrial_motion_planner::TrajectoryGeneratorLIN(robot_model_, planner_limits), + pilz_industrial_motion_planner::TrajectoryGeneratorInvalidLimitsException); +} + +/** + * @brief Checks that generate() function returns 'false' if called with an + * incorrect number of joints. + * + * Test Sequence: + * 1. Call functions with incorrect number of joints. + * + * Expected Results: + * 1. Function returns 'false'. + */ +TEST_P(TrajectoryGeneratorLINTest, IncorrectJointNumber) +{ + // construct motion plan request + moveit_msgs::MotionPlanRequest lin_joint_req{ tdp_->getLinJoint("lin2").toRequest() }; + + // Ensure that request consists of an incorrect number of joints. + lin_joint_req.goal_constraints.front().joint_constraints.pop_back(); + + // generate the LIN trajectory + planning_interface::MotionPlanResponse res; + ASSERT_FALSE(lin_->generate(lin_joint_req, res)); + EXPECT_TRUE(res.error_code_.val == moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +} + +/** + * @brief test invalid motion plan request with incomplete start state and + * cartesian goal + */ +TEST_P(TrajectoryGeneratorLINTest, cartGoalIncompleteStartState) +{ + // construct motion plan request + moveit_msgs::MotionPlanRequest lin_cart_req{ tdp_->getLinCart("lin2").toRequest() }; + EXPECT_GT(lin_cart_req.start_state.joint_state.name.size(), 1u); + lin_cart_req.start_state.joint_state.name.resize(1); + lin_cart_req.start_state.joint_state.position.resize(1); // prevent failing check for equal sizes + + // generate lin trajectory + planning_interface::MotionPlanResponse res; + EXPECT_FALSE(lin_->generate(lin_cart_req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE); +} + +/** + * @brief Set a frame id in goal constraint with cartesian goal on both position + * and orientation constraints + */ +TEST_P(TrajectoryGeneratorLINTest, cartGoalFrameIdBothConstraints) +{ + // construct motion plan request + moveit_msgs::MotionPlanRequest lin_cart_req{ tdp_->getLinCart("lin2").toRequest() }; + + lin_cart_req.goal_constraints.front().position_constraints.front().header.frame_id = robot_model_->getModelFrame(); + lin_cart_req.goal_constraints.front().orientation_constraints.front().header.frame_id = robot_model_->getModelFrame(); + + // generate lin trajectory + planning_interface::MotionPlanResponse res; + ASSERT_TRUE(lin_->generate(lin_cart_req, res)); + EXPECT_TRUE(res.error_code_.val == moveit_msgs::MoveItErrorCodes::SUCCESS); + + // check the resulted trajectory + EXPECT_TRUE(checkLinResponse(lin_cart_req, res)); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "unittest_trajectory_generator_lin"); + ros::NodeHandle nh; + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_lin.test b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_lin.test new file mode 100644 index 0000000000..9cec117a1d --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_lin.test @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_ptp.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_ptp.cpp new file mode 100644 index 0000000000..94889460d3 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_ptp.cpp @@ -0,0 +1,971 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include + +#include "pilz_industrial_motion_planner/joint_limits_aggregator.h" +#include "pilz_industrial_motion_planner/trajectory_generator_ptp.h" +#include "test_utils.h" + +#include +#include +#include +#include + +// parameters for parameterized tests +const std::string PARAM_MODEL_NO_GRIPPER_NAME{ "robot_description" }; +const std::string PARAM_MODEL_WITH_GRIPPER_NAME{ "robot_description_pg70" }; + +// parameters from parameter server +const std::string PARAM_PLANNING_GROUP_NAME("planning_group"); +const std::string PARAM_TARGET_LINK_NAME("target_link"); +const std::string JOINT_POSITION_TOLERANCE("joint_position_tolerance"); +const std::string JOINT_VELOCITY_TOLERANCE("joint_velocity_tolerance"); +const std::string JOINT_ACCELERATION_TOLERANCE("joint_acceleration_tolerance"); +const std::string POSE_TRANSFORM_MATRIX_NORM_TOLERANCE("pose_norm_tolerance"); + +using namespace pilz_industrial_motion_planner; + +class TrajectoryGeneratorPTPTest : public testing::TestWithParam +{ +protected: + /** + * @brief Create test fixture for ptp trajectory generator + * + */ + void SetUp() override; + + /** + * @brief check the resulted joint trajectory + * @param trajectory + * @param req + * @param joint_limits + * @return + */ + bool checkTrajectory(const trajectory_msgs::JointTrajectory& trajectory, + const planning_interface::MotionPlanRequest& req, const JointLimitsContainer& joint_limits); + +protected: + // ros stuff + ros::NodeHandle ph_{ "~" }; + robot_model::RobotModelConstPtr robot_model_{ robot_model_loader::RobotModelLoader(GetParam()).getModel() }; + + // trajectory generator + std::unique_ptr ptp_; + + // test parameters from parameter server + LimitsContainer planner_limits_; + std::string planning_group_, target_link_; + double joint_position_tolerance_, joint_velocity_tolerance_, joint_acceleration_tolerance_, pose_norm_tolerance_; +}; + +void TrajectoryGeneratorPTPTest::SetUp() +{ + // get parameters from parameter server + ASSERT_TRUE(ph_.getParam(PARAM_PLANNING_GROUP_NAME, planning_group_)); + ASSERT_TRUE(ph_.getParam(PARAM_TARGET_LINK_NAME, target_link_)); + ASSERT_TRUE(ph_.getParam(JOINT_POSITION_TOLERANCE, joint_position_tolerance_)); + ASSERT_TRUE(ph_.getParam(JOINT_VELOCITY_TOLERANCE, joint_velocity_tolerance_)); + ASSERT_TRUE(ph_.getParam(JOINT_ACCELERATION_TOLERANCE, joint_acceleration_tolerance_)); + ASSERT_TRUE(ph_.getParam(POSE_TRANSFORM_MATRIX_NORM_TOLERANCE, pose_norm_tolerance_)); + + testutils::checkRobotModel(robot_model_, planning_group_, target_link_); + + // create the limits container + JointLimitsContainer joint_limits; + for (const auto& jmg : robot_model_->getJointModelGroups()) + { + std::vector joint_names = jmg->getActiveJointModelNames(); + JointLimit joint_limit; + joint_limit.max_position = 3.124; + joint_limit.min_position = -3.124; + joint_limit.has_velocity_limits = true; + joint_limit.max_velocity = 1; + joint_limit.has_acceleration_limits = true; + joint_limit.max_acceleration = 0.5; + joint_limit.has_deceleration_limits = true; + joint_limit.max_deceleration = -1; + for (const auto& joint_name : joint_names) + { + joint_limits.addLimit(joint_name, joint_limit); + } + } + + // create the trajectory generator + planner_limits_.setJointLimits(joint_limits); + ptp_.reset(new TrajectoryGeneratorPTP(robot_model_, planner_limits_)); + ASSERT_NE(nullptr, ptp_); +} + +bool TrajectoryGeneratorPTPTest::checkTrajectory(const trajectory_msgs::JointTrajectory& trajectory, + const planning_interface::MotionPlanRequest& req, + const JointLimitsContainer& joint_limits) +{ + return (testutils::isTrajectoryConsistent(trajectory) && + testutils::isGoalReached(trajectory, req.goal_constraints.front().joint_constraints, + joint_position_tolerance_, joint_velocity_tolerance_) && + testutils::isPositionBounded(trajectory, joint_limits) && + testutils::isVelocityBounded(trajectory, joint_limits) && + testutils::isAccelerationBounded(trajectory, joint_limits)); +} + +/** + * @brief Checks that each derived MoveItErrorCodeException contains the correct + * error code. + */ +TEST(TrajectoryGeneratorPTPTest, TestExceptionErrorCodeMapping) +{ + { + std::shared_ptr pvpsf_ex{ new PtpVelocityProfileSyncFailed("") }; + EXPECT_EQ(pvpsf_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::FAILURE); + } + + { + std::shared_ptr pnisfgp_ex{ new PtpNoIkSolutionForGoalPose("") }; + EXPECT_EQ(pnisfgp_ex->getErrorCode(), moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION); + } +} + +// Instantiate the test cases for robot model with and without gripper +INSTANTIATE_TEST_SUITE_P(InstantiationName, TrajectoryGeneratorPTPTest, + ::testing::Values(PARAM_MODEL_NO_GRIPPER_NAME, PARAM_MODEL_WITH_GRIPPER_NAME)); +/** + * @brief Construct a TrajectoryGeneratorPTP with no limits given + */ +TEST_P(TrajectoryGeneratorPTPTest, noLimits) +{ + LimitsContainer planner_limits; + EXPECT_THROW(TrajectoryGeneratorPTP(this->robot_model_, planner_limits), TrajectoryGeneratorInvalidLimitsException); +} + +/** + * @brief Send an empty request, define res.trajectory_ + * + * - Test Sequence: + * 1. Create request, define a trajectory in the result + * 2. assign at least one joint limit will all required limits + * + * - Expected Results: + * 1. the res.trajectory_ should be cleared (contain no waypoints) + */ +TEST_P(TrajectoryGeneratorPTPTest, emptyRequest) +{ + planning_interface::MotionPlanResponse res; + planning_interface::MotionPlanRequest req; + + robot_trajectory::RobotTrajectoryPtr trajectory( + new robot_trajectory::RobotTrajectory(this->robot_model_, planning_group_)); + robot_state::RobotState state(this->robot_model_); + trajectory->addPrefixWayPoint(state, 0); + res.trajectory_ = trajectory; + + EXPECT_FALSE(res.trajectory_->empty()); + + EXPECT_FALSE(ptp_->generate(req, res)); + + EXPECT_TRUE(res.trajectory_->empty()); +} + +/** + * @brief Construct a TrajectoryGeneratorPTP with missing velocity limits + */ +TEST_P(TrajectoryGeneratorPTPTest, missingVelocityLimits) +{ + LimitsContainer planner_limits; + + JointLimitsContainer joint_limits; + auto joint_models = robot_model_->getActiveJointModels(); + JointLimit joint_limit; + joint_limit.has_velocity_limits = false; + joint_limit.has_acceleration_limits = true; + joint_limit.max_deceleration = -1; + joint_limit.has_deceleration_limits = true; + for (const auto& joint_model : joint_models) + { + ASSERT_TRUE(joint_limits.addLimit(joint_model->getName(), joint_limit)) + << "Failed to add the limits for joint " << joint_model->getName(); + } + + planner_limits.setJointLimits(joint_limits); + EXPECT_THROW(TrajectoryGeneratorPTP(this->robot_model_, planner_limits), TrajectoryGeneratorInvalidLimitsException); +} + +/** + * @brief Construct a TrajectoryGeneratorPTP missing deceleration limits + */ +TEST_P(TrajectoryGeneratorPTPTest, missingDecelerationimits) +{ + LimitsContainer planner_limits; + + JointLimitsContainer joint_limits; + const auto& joint_models = robot_model_->getActiveJointModels(); + JointLimit joint_limit; + joint_limit.has_velocity_limits = true; + joint_limit.has_acceleration_limits = true; + joint_limit.has_deceleration_limits = false; + for (const auto& joint_model : joint_models) + { + ASSERT_TRUE(joint_limits.addLimit(joint_model->getName(), joint_limit)) + << "Failed to add the limits for joint " << joint_model->getName(); + } + + planner_limits.setJointLimits(joint_limits); + EXPECT_THROW(TrajectoryGeneratorPTP(this->robot_model_, planner_limits), TrajectoryGeneratorInvalidLimitsException); +} + +/** + * @brief test the constructor when insufficient limits are given + * - Test Sequence: + * 1. assign joint limits without acc and dec + * 2. assign at least one joint limit per group with all required limits + * + * - Expected Results: + * 1. the constructor throws an exception of type + * TrajectoryGeneratorInvalidLimitsException + * 2. the constructor throws no exception + */ +TEST_P(TrajectoryGeneratorPTPTest, testInsufficientLimit) +{ + /**********/ + /* Step 1 */ + /**********/ + const auto& joint_models = robot_model_->getActiveJointModels(); + ASSERT_TRUE(joint_models.size()); + + // joint limit with insufficient limits (no acc/dec limits) + JointLimit insufficient_limit; + insufficient_limit.has_position_limits = true; + insufficient_limit.max_position = 2.5; + insufficient_limit.min_position = -2.5; + insufficient_limit.has_velocity_limits = true; + insufficient_limit.max_velocity = 1.256; + insufficient_limit.has_acceleration_limits = false; + insufficient_limit.has_deceleration_limits = false; + JointLimitsContainer insufficient_joint_limits; + for (const auto& joint_model : joint_models) + { + ASSERT_TRUE(insufficient_joint_limits.addLimit(joint_model->getName(), insufficient_limit)) + << "Failed to add the limits for joint " << joint_model->getName(); + } + LimitsContainer insufficient_planner_limits; + insufficient_planner_limits.setJointLimits(insufficient_joint_limits); + + EXPECT_THROW( + { + std::unique_ptr ptp_error( + new TrajectoryGeneratorPTP(robot_model_, insufficient_planner_limits)); + }, + TrajectoryGeneratorInvalidLimitsException); + + /**********/ + /* Step 2 */ + /**********/ + // joint limit with sufficient limits + JointLimit sufficient_limit; + sufficient_limit.has_position_limits = true; + sufficient_limit.max_position = 2.356; + sufficient_limit.min_position = -2.356; + sufficient_limit.has_velocity_limits = true; + sufficient_limit.max_velocity = 1; + sufficient_limit.has_acceleration_limits = true; + sufficient_limit.max_acceleration = 0.5; + sufficient_limit.has_deceleration_limits = true; + sufficient_limit.max_deceleration = -1; + JointLimitsContainer sufficient_joint_limits; + // fill joint limits container, such that it contains one sufficient limit and + // all others are insufficient + for (const auto& jmg : robot_model_->getJointModelGroups()) + { + const auto& joint_names{ jmg->getActiveJointModelNames() }; + ASSERT_FALSE(joint_names.empty()); + ASSERT_TRUE(sufficient_joint_limits.addLimit(joint_names.front(), sufficient_limit)) + << "Failed to add the limits for joint " << joint_names.front(); + + for (auto it = std::next(joint_names.begin()); it != joint_names.end(); ++it) + { + ASSERT_TRUE(sufficient_joint_limits.addLimit((*it), insufficient_limit)) + << "Failed to add the limits for joint " << (*it); + } + } + LimitsContainer sufficient_planner_limits; + sufficient_planner_limits.setJointLimits(sufficient_joint_limits); + + EXPECT_NO_THROW({ + std::unique_ptr ptp_no_error( + new TrajectoryGeneratorPTP(robot_model_, sufficient_planner_limits)); + }); +} + +/** + * @brief test the ptp trajectory generator of Cartesian space goal + */ +TEST_P(TrajectoryGeneratorPTPTest, testCartesianGoal) +{ + //*************************************** + //*** prepare the motion plan request *** + //*************************************** + planning_interface::MotionPlanResponse res; + planning_interface::MotionPlanRequest req; + testutils::createDummyRequest(robot_model_, planning_group_, req); + + // cartesian goal pose + geometry_msgs::PoseStamped pose; + pose.pose.position.x = 0.1; + pose.pose.position.y = 0.2; + pose.pose.position.z = 0.65; + pose.pose.orientation.w = 1.0; + pose.pose.orientation.x = 0.0; + pose.pose.orientation.y = 0.0; + pose.pose.orientation.z = 0.0; + std::vector tolerance_pose(3, 0.01); + std::vector tolerance_angle(3, 0.01); + moveit_msgs::Constraints pose_goal = + kinematic_constraints::constructGoalConstraints(target_link_, pose, tolerance_pose, tolerance_angle); + req.goal_constraints.push_back(pose_goal); + + //**************************************** + //*** test robot model without gripper *** + //**************************************** + ASSERT_TRUE(ptp_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + + moveit_msgs::MotionPlanResponse res_msg; + res.getMessage(res_msg); + if (!res_msg.trajectory.joint_trajectory.points.empty()) + { + EXPECT_TRUE(checkTrajectory(res_msg.trajectory.joint_trajectory, req, planner_limits_.getJointLimitContainer())); + } + else + { + FAIL() << "Received empty trajectory."; + } + + // check goal pose + EXPECT_TRUE(testutils::isGoalReached(robot_model_, res_msg.trajectory.joint_trajectory, req, pose_norm_tolerance_)); +} + +/** + * @brief Check that missing a link_name in position or orientation constraints + * is detected + */ +TEST_P(TrajectoryGeneratorPTPTest, testCartesianGoalMissingLinkNameConstraints) +{ + //*************************************** + //*** prepare the motion plan request *** + //*************************************** + planning_interface::MotionPlanResponse res; + planning_interface::MotionPlanRequest req; + testutils::createDummyRequest(robot_model_, planning_group_, req); + + // cartesian goal pose + geometry_msgs::PoseStamped pose; + pose.pose.position.x = 0.1; + pose.pose.position.y = 0.2; + pose.pose.position.z = 0.65; + pose.pose.orientation.w = 1.0; + pose.pose.orientation.x = 0.0; + pose.pose.orientation.y = 0.0; + pose.pose.orientation.z = 0.0; + std::vector tolerance_pose(3, 0.01); + std::vector tolerance_angle(3, 0.01); + moveit_msgs::Constraints pose_goal = + kinematic_constraints::constructGoalConstraints(target_link_, pose, tolerance_pose, tolerance_angle); + req.goal_constraints.push_back(pose_goal); + + planning_interface::MotionPlanRequest req_no_position_constaint_link_name = req; + req_no_position_constaint_link_name.goal_constraints.front().position_constraints.front().link_name = ""; + ASSERT_FALSE(ptp_->generate(req_no_position_constaint_link_name, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + + planning_interface::MotionPlanRequest req_no_orientation_constaint_link_name = req; + req_no_orientation_constaint_link_name.goal_constraints.front().orientation_constraints.front().link_name = ""; + ASSERT_FALSE(ptp_->generate(req_no_orientation_constaint_link_name, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); +} + +/** + * @brief test the ptp trajectory generator of invalid Cartesian space goal + */ +TEST_P(TrajectoryGeneratorPTPTest, testInvalidCartesianGoal) +{ + planning_interface::MotionPlanResponse res; + planning_interface::MotionPlanRequest req; + testutils::createDummyRequest(robot_model_, planning_group_, req); + + geometry_msgs::PoseStamped pose; + pose.pose.position.x = 0.1; + pose.pose.position.y = 0.2; + pose.pose.position.z = 2.5; + pose.pose.orientation.w = 1.0; + pose.pose.orientation.x = 0.0; + pose.pose.orientation.y = 0.0; + pose.pose.orientation.z = 0.0; + std::vector tolerance_pose(3, 0.01); + std::vector tolerance_angle(3, 0.01); + moveit_msgs::Constraints pose_goal = + kinematic_constraints::constructGoalConstraints(target_link_, pose, tolerance_pose, tolerance_angle); + req.goal_constraints.push_back(pose_goal); + + ASSERT_FALSE(ptp_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION); + EXPECT_EQ(res.trajectory_, nullptr); +} + +/** + * @brief test the ptp trajectory generator of joint space goal which is close + * enough to the start which does not need + * to plan the trajectory + */ +TEST_P(TrajectoryGeneratorPTPTest, testJointGoalAlreadyReached) +{ + planning_interface::MotionPlanResponse res; + planning_interface::MotionPlanRequest req; + testutils::createDummyRequest(robot_model_, planning_group_, req); + ASSERT_TRUE(robot_model_->getJointModelGroup(planning_group_)->getActiveJointModelNames().size()) + << "No link exists in the planning group."; + + moveit_msgs::Constraints gc; + moveit_msgs::JointConstraint jc; + jc.joint_name = robot_model_->getJointModelGroup(planning_group_)->getActiveJointModelNames().front(); + jc.position = 0.0; + gc.joint_constraints.push_back(jc); + req.goal_constraints.push_back(gc); + + // TODO lin and circ has different settings + ASSERT_TRUE(ptp_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + + moveit_msgs::MotionPlanResponse res_msg; + res.getMessage(res_msg); + EXPECT_EQ(1u, res_msg.trajectory.joint_trajectory.points.size()); +} + +/** + * @brief test scaling factor + * with zero start velocity + */ +TEST_P(TrajectoryGeneratorPTPTest, testScalingFactor) +{ + // create ptp generator with different limits + JointLimit joint_limit; + JointLimitsContainer joint_limits; + + // set the joint limits + joint_limit.has_position_limits = true; + joint_limit.max_position = 2.967; + joint_limit.min_position = -2.967; + joint_limit.has_velocity_limits = true; + joint_limit.max_velocity = 2; + joint_limit.has_acceleration_limits = true; + joint_limit.max_acceleration = 1.5; + joint_limit.has_deceleration_limits = true; + joint_limit.max_deceleration = -3; + joint_limits.addLimit("prbt_joint_1", joint_limit); + joint_limit.max_position = 2.530; + joint_limit.min_position = -2.530; + joint_limits.addLimit("prbt_joint_2", joint_limit); + joint_limit.max_position = 2.356; + joint_limit.min_position = -2.356; + joint_limits.addLimit("prbt_joint_3", joint_limit); + joint_limit.max_position = 2.967; + joint_limit.min_position = -2.967; + joint_limits.addLimit("prbt_joint_4", joint_limit); + joint_limit.max_position = 2.967; + joint_limit.min_position = -2.967; + joint_limits.addLimit("prbt_joint_5", joint_limit); + joint_limit.max_position = 3.132; + joint_limit.min_position = -3.132; + joint_limits.addLimit("prbt_joint_6", joint_limit); + // add gripper limit such that generator does not complain about missing limit + joint_limits.addLimit("prbt_gripper_finger_left_joint", joint_limit); + + pilz_industrial_motion_planner::LimitsContainer planner_limits; + planner_limits.setJointLimits(joint_limits); + + // create the generator with new limits + ptp_.reset(new TrajectoryGeneratorPTP(robot_model_, planner_limits)); + + planning_interface::MotionPlanResponse res; + planning_interface::MotionPlanRequest req; + testutils::createDummyRequest(robot_model_, planning_group_, req); + req.start_state.joint_state.position[2] = 0.1; + moveit_msgs::Constraints gc; + moveit_msgs::JointConstraint jc; + jc.joint_name = "prbt_joint_1"; + jc.position = 1.5; + gc.joint_constraints.push_back(jc); + jc.joint_name = "prbt_joint_3"; + jc.position = 2.1; + gc.joint_constraints.push_back(jc); + jc.joint_name = "prbt_joint_6"; + jc.position = 3.0; + gc.joint_constraints.push_back(jc); + req.goal_constraints.push_back(gc); + req.max_velocity_scaling_factor = 0.5; + req.max_acceleration_scaling_factor = 1.0 / 3.0; + + ASSERT_TRUE(ptp_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + + moveit_msgs::MotionPlanResponse res_msg; + res.getMessage(res_msg); + EXPECT_TRUE(checkTrajectory(res_msg.trajectory.joint_trajectory, req, planner_limits_.getJointLimitContainer())); + + // trajectory duration + EXPECT_NEAR(4.5, res.trajectory_->getWayPointDurationFromStart(res.trajectory_->getWayPointCount()), + joint_acceleration_tolerance_); + + // way point at 1s + int index; + index = testutils::getWayPointIndex(res.trajectory_, 1.0); + // joint_1 + EXPECT_NEAR(0.125, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.25, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + EXPECT_NEAR(0.25, res_msg.trajectory.joint_trajectory.points[index].accelerations[0], joint_acceleration_tolerance_); + // joint_3 + EXPECT_NEAR(1.0 / 6.0 + 0.1, res_msg.trajectory.joint_trajectory.points[index].positions[2], + joint_position_tolerance_); + EXPECT_NEAR(1.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + EXPECT_NEAR(1.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[2], + joint_acceleration_tolerance_); + // joint_6 + EXPECT_NEAR(0.25, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].accelerations[5], joint_acceleration_tolerance_); + // other joints + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].positions[4], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[4], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[4], joint_acceleration_tolerance_); + + // way point at 2s + index = testutils::getWayPointIndex(res.trajectory_, 2.0); + // joint_1 + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + // joint_3 + EXPECT_NEAR(2.0 / 3.0 + 0.1, res_msg.trajectory.joint_trajectory.points[index].positions[2], + joint_position_tolerance_); + EXPECT_NEAR(2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + // joint_6 + EXPECT_NEAR(1.0, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(1.0, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + // other joints + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].positions[1], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[1], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[1], joint_acceleration_tolerance_); + + // way point at 3s + index = testutils::getWayPointIndex(res.trajectory_, 3.0); + // joint_1 + EXPECT_NEAR(1, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[0], joint_acceleration_tolerance_); + // joint_3 + EXPECT_NEAR(4.0 / 3.0 + 0.1, res_msg.trajectory.joint_trajectory.points[index].positions[2], + joint_position_tolerance_); + EXPECT_NEAR(2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[2], joint_acceleration_tolerance_); + // joint_6 + EXPECT_NEAR(2.0, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(1.0, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[5], joint_acceleration_tolerance_); + // other joints + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].positions[3], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[3], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[3], joint_acceleration_tolerance_); + + // way point at 4s + index = testutils::getWayPointIndex(res.trajectory_, 4.0); + // joint_1 + EXPECT_NEAR(2.875 / 2.0, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.25, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + EXPECT_NEAR(-0.5, res_msg.trajectory.joint_trajectory.points[index].accelerations[0], joint_acceleration_tolerance_); + // joint_3 + EXPECT_NEAR(5.75 / 3.0 + 0.1, res_msg.trajectory.joint_trajectory.points[index].positions[2], + joint_position_tolerance_); + EXPECT_NEAR(1.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + EXPECT_NEAR(-2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[2], + joint_acceleration_tolerance_); + // joint_6 + EXPECT_NEAR(2.875, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + EXPECT_NEAR(-1.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[5], joint_acceleration_tolerance_); + + // way point at 4.5s + index = testutils::getWayPointIndex(res.trajectory_, 4.5); + // joint_1 + EXPECT_NEAR(1.5, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + // joint_3 + EXPECT_NEAR(2.1, res_msg.trajectory.joint_trajectory.points[index].positions[2], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + // joint_6 + EXPECT_NEAR(3.0, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); +} + +/** + * @brief test the ptp trajectory generator of joint space goal + * with (almost) zero start velocity + */ +TEST_P(TrajectoryGeneratorPTPTest, testJointGoalAndAlmostZeroStartVelocity) +{ + planning_interface::MotionPlanResponse res; + planning_interface::MotionPlanRequest req; + testutils::createDummyRequest(robot_model_, planning_group_, req); + req.start_state.joint_state.position[2] = 0.1; + + // Set velocity to all 1e-16 + req.start_state.joint_state.velocity = std::vector(req.start_state.joint_state.position.size(), 1e-16); + + moveit_msgs::Constraints gc; + moveit_msgs::JointConstraint jc; + jc.joint_name = "prbt_joint_1"; + jc.position = 1.5; + gc.joint_constraints.push_back(jc); + jc.joint_name = "prbt_joint_3"; + jc.position = 2.1; + gc.joint_constraints.push_back(jc); + jc.joint_name = "prbt_joint_6"; + jc.position = 3.0; + gc.joint_constraints.push_back(jc); + req.goal_constraints.push_back(gc); + + ASSERT_TRUE(ptp_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + + moveit_msgs::MotionPlanResponse res_msg; + res.getMessage(res_msg); + EXPECT_TRUE(checkTrajectory(res_msg.trajectory.joint_trajectory, req, planner_limits_.getJointLimitContainer())); + + // trajectory duration + EXPECT_NEAR(4.5, res.trajectory_->getWayPointDurationFromStart(res.trajectory_->getWayPointCount()), + joint_acceleration_tolerance_); + + // way point at 1s + int index; + index = testutils::getWayPointIndex(res.trajectory_, 1.0); + // joint_1 + EXPECT_NEAR(0.125, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.25, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + EXPECT_NEAR(0.25, res_msg.trajectory.joint_trajectory.points[index].accelerations[0], joint_acceleration_tolerance_); + // joint_3 + EXPECT_NEAR(1.0 / 6.0 + 0.1, res_msg.trajectory.joint_trajectory.points[index].positions[2], + joint_position_tolerance_); + EXPECT_NEAR(1.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + EXPECT_NEAR(1.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[2], + joint_acceleration_tolerance_); + // joint_6 + EXPECT_NEAR(0.25, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].accelerations[5], joint_acceleration_tolerance_); + // other joints + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].positions[4], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[4], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[4], joint_acceleration_tolerance_); + + // way point at 2s + index = testutils::getWayPointIndex(res.trajectory_, 2.0); + // joint_1 + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + // joint_3 + EXPECT_NEAR(2.0 / 3.0 + 0.1, res_msg.trajectory.joint_trajectory.points[index].positions[2], + joint_position_tolerance_); + EXPECT_NEAR(2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + // joint_6 + EXPECT_NEAR(1.0, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(1.0, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + // other joints + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].positions[1], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[1], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[1], joint_acceleration_tolerance_); + + // way point at 3s + index = testutils::getWayPointIndex(res.trajectory_, 3.0); + // joint_1 + EXPECT_NEAR(1, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[0], joint_acceleration_tolerance_); + // joint_3 + EXPECT_NEAR(4.0 / 3.0 + 0.1, res_msg.trajectory.joint_trajectory.points[index].positions[2], + joint_position_tolerance_); + EXPECT_NEAR(2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[2], joint_acceleration_tolerance_); + // joint_6 + EXPECT_NEAR(2.0, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(1.0, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[5], joint_acceleration_tolerance_); + // other joints + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].positions[3], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[3], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[3], joint_acceleration_tolerance_); + + // way point at 4s + index = testutils::getWayPointIndex(res.trajectory_, 4.0); + // joint_1 + EXPECT_NEAR(2.875 / 2.0, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.25, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + EXPECT_NEAR(-0.5, res_msg.trajectory.joint_trajectory.points[index].accelerations[0], joint_acceleration_tolerance_); + // joint_3 + EXPECT_NEAR(5.75 / 3.0 + 0.1, res_msg.trajectory.joint_trajectory.points[index].positions[2], + joint_position_tolerance_); + EXPECT_NEAR(1.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + EXPECT_NEAR(-2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[2], + joint_acceleration_tolerance_); + // joint_6 + EXPECT_NEAR(2.875, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + EXPECT_NEAR(-1.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[5], joint_acceleration_tolerance_); + + // way point at 4.5s + index = testutils::getWayPointIndex(res.trajectory_, 4.5); + // joint_1 + EXPECT_NEAR(1.5, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + // joint_3 + EXPECT_NEAR(2.1, res_msg.trajectory.joint_trajectory.points[index].positions[2], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + // joint_6 + EXPECT_NEAR(3.0, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + + // Check that velocity at the end is all zero + EXPECT_TRUE(std::all_of(res_msg.trajectory.joint_trajectory.points.back().velocities.cbegin(), + res_msg.trajectory.joint_trajectory.points.back().velocities.cend(), + [this](double v) { return std::fabs(v) < this->joint_velocity_tolerance_; })); + + // Check that acceleration at the end is all zero + EXPECT_TRUE(std::all_of(res_msg.trajectory.joint_trajectory.points.back().accelerations.cbegin(), + res_msg.trajectory.joint_trajectory.points.back().accelerations.cend(), + [this](double v) { return std::fabs(v) < this->joint_acceleration_tolerance_; })); +} + +/** + * @brief test the ptp_ trajectory generator of joint space goal + * with zero start velocity + */ +TEST_P(TrajectoryGeneratorPTPTest, testJointGoalNoStartVel) +{ + planning_interface::MotionPlanResponse res; + planning_interface::MotionPlanRequest req; + testutils::createDummyRequest(robot_model_, planning_group_, req); + req.start_state.joint_state.position[4] = 0.3; + req.start_state.joint_state.position[2] = 0.11; + + moveit_msgs::Constraints gc; + moveit_msgs::JointConstraint jc; + + jc.joint_name = "prbt_joint_1"; + jc.position = 1.5; + gc.joint_constraints.push_back(jc); + jc.joint_name = "prbt_joint_2"; + jc.position = -1.5; + gc.joint_constraints.push_back(jc); + jc.joint_name = "prbt_joint_3"; + jc.position = 2.11; + gc.joint_constraints.push_back(jc); + jc.joint_name = "prbt_joint_4"; + jc.position = -2.0; + gc.joint_constraints.push_back(jc); + jc.joint_name = "prbt_joint_6"; + jc.position = 3.0; + gc.joint_constraints.push_back(jc); + req.goal_constraints.push_back(gc); + + ASSERT_TRUE(ptp_->generate(req, res)); + EXPECT_EQ(res.error_code_.val, moveit_msgs::MoveItErrorCodes::SUCCESS); + + moveit_msgs::MotionPlanResponse res_msg; + res.getMessage(res_msg); + EXPECT_TRUE(checkTrajectory(res_msg.trajectory.joint_trajectory, req, planner_limits_.getJointLimitContainer())); + + // trajectory duration + EXPECT_NEAR(4.5, res.trajectory_->getWayPointDurationFromStart(res.trajectory_->getWayPointCount()), + joint_position_tolerance_); + + // way point at 0s + // joint_1 + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[0].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[0].velocities[0], joint_velocity_tolerance_); + // joint_2 + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[0].positions[1], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[0].velocities[1], joint_velocity_tolerance_); + // joint_3 + EXPECT_NEAR(0.11, res_msg.trajectory.joint_trajectory.points[0].positions[2], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[0].velocities[2], joint_velocity_tolerance_); + // joint_4 + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[0].positions[3], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[0].velocities[3], joint_velocity_tolerance_); + // joint_6 + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[0].positions[5], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[0].velocities[5], joint_velocity_tolerance_); + + // way point at 1s + int index; + index = testutils::getWayPointIndex(res.trajectory_, 1.0); + // joint_1 + EXPECT_NEAR(0.125, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.25, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + EXPECT_NEAR(0.25, res_msg.trajectory.joint_trajectory.points[index].accelerations[0], joint_acceleration_tolerance_); + // joint_2 + EXPECT_NEAR(-0.125, res_msg.trajectory.joint_trajectory.points[index].positions[1], joint_position_tolerance_); + EXPECT_NEAR(-0.25, res_msg.trajectory.joint_trajectory.points[index].velocities[1], joint_velocity_tolerance_); + EXPECT_NEAR(-0.25, res_msg.trajectory.joint_trajectory.points[index].accelerations[1], joint_acceleration_tolerance_); + // joint_3 + EXPECT_NEAR(1.0 / 6.0 + 0.11, res_msg.trajectory.joint_trajectory.points[index].positions[2], + joint_position_tolerance_); + EXPECT_NEAR(1.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + EXPECT_NEAR(1.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[2], + joint_acceleration_tolerance_); + // joint_4 + EXPECT_NEAR(-1.0 / 6.0, res_msg.trajectory.joint_trajectory.points[index].positions[3], joint_position_tolerance_); + EXPECT_NEAR(-1.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[3], joint_velocity_tolerance_); + EXPECT_NEAR(-1.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[3], + joint_acceleration_tolerance_); + // joint_6 + EXPECT_NEAR(0.25, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].accelerations[5], joint_acceleration_tolerance_); + + // way point at 2s + index = testutils::getWayPointIndex(res.trajectory_, 2.0); + // joint_1 + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + // joint_2 + EXPECT_NEAR(-0.5, res_msg.trajectory.joint_trajectory.points[index].positions[1], joint_position_tolerance_); + EXPECT_NEAR(-0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[1], joint_velocity_tolerance_); + // joint_3 + EXPECT_NEAR(2.0 / 3.0 + 0.11, res_msg.trajectory.joint_trajectory.points[index].positions[2], + joint_position_tolerance_); + EXPECT_NEAR(2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + // joint_4 + EXPECT_NEAR(-2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].positions[3], joint_position_tolerance_); + EXPECT_NEAR(-2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[3], joint_velocity_tolerance_); + // joint_6 + EXPECT_NEAR(1.0, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(1.0, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + + // way point at 3s + index = testutils::getWayPointIndex(res.trajectory_, 3.0); + // joint_1 + EXPECT_NEAR(1, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[0], joint_acceleration_tolerance_); + // joint_2 + EXPECT_NEAR(-1, res_msg.trajectory.joint_trajectory.points[index].positions[1], joint_position_tolerance_); + EXPECT_NEAR(-0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[1], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[1], joint_acceleration_tolerance_); + // joint_3 + EXPECT_NEAR(4.0 / 3.0 + 0.11, res_msg.trajectory.joint_trajectory.points[index].positions[2], + joint_position_tolerance_); + EXPECT_NEAR(2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[2], joint_acceleration_tolerance_); + // joint_4 + EXPECT_NEAR(-4.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].positions[3], joint_position_tolerance_); + EXPECT_NEAR(-2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[3], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[3], joint_acceleration_tolerance_); + // joint_6 + EXPECT_NEAR(2.0, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(1.0, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[5], joint_acceleration_tolerance_); + + // way point at 4s + index = testutils::getWayPointIndex(res.trajectory_, 4.0); + // joint_1 + EXPECT_NEAR(2.875 / 2.0, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.25, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + EXPECT_NEAR(-0.5, res_msg.trajectory.joint_trajectory.points[index].accelerations[0], joint_acceleration_tolerance_); + // joint_2 + EXPECT_NEAR(-2.875 / 2.0, res_msg.trajectory.joint_trajectory.points[index].positions[1], joint_position_tolerance_); + EXPECT_NEAR(-0.25, res_msg.trajectory.joint_trajectory.points[index].velocities[1], joint_velocity_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].accelerations[1], joint_acceleration_tolerance_); + // joint_3 + EXPECT_NEAR(5.75 / 3.0 + 0.11, res_msg.trajectory.joint_trajectory.points[index].positions[2], + joint_position_tolerance_); + EXPECT_NEAR(1.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + EXPECT_NEAR(-2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[2], + joint_acceleration_tolerance_); + // joint_4 + EXPECT_NEAR(-5.75 / 3.0, res_msg.trajectory.joint_trajectory.points[index].positions[3], joint_position_tolerance_); + EXPECT_NEAR(-1.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].velocities[3], joint_velocity_tolerance_); + EXPECT_NEAR(2.0 / 3.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[3], + joint_acceleration_tolerance_); + // joint_6 + EXPECT_NEAR(2.875, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(0.5, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + EXPECT_NEAR(-1.0, res_msg.trajectory.joint_trajectory.points[index].accelerations[5], joint_acceleration_tolerance_); + + // way point at 4.5s + index = testutils::getWayPointIndex(res.trajectory_, 4.5); + // joint_1 + EXPECT_NEAR(1.5, res_msg.trajectory.joint_trajectory.points[index].positions[0], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[0], joint_velocity_tolerance_); + // joint_2 + EXPECT_NEAR(-1.5, res_msg.trajectory.joint_trajectory.points[index].positions[1], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[1], joint_velocity_tolerance_); + // joint_3 + EXPECT_NEAR(2.11, res_msg.trajectory.joint_trajectory.points[index].positions[2], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[2], joint_velocity_tolerance_); + // joint_4 + EXPECT_NEAR(-2.0, res_msg.trajectory.joint_trajectory.points[index].positions[3], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[3], joint_velocity_tolerance_); + // joint_6 + EXPECT_NEAR(3.0, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + EXPECT_NEAR(0.0, res_msg.trajectory.joint_trajectory.points[index].velocities[5], joint_velocity_tolerance_); + + // Check last point + EXPECT_NEAR(3.0, res_msg.trajectory.joint_trajectory.points[index].positions[5], joint_position_tolerance_); + + // Check that velocity at the end is all zero + EXPECT_TRUE(std::all_of(res_msg.trajectory.joint_trajectory.points.back().velocities.cbegin(), + res_msg.trajectory.joint_trajectory.points.back().velocities.cend(), + [this](double v) { return std::fabs(v) < this->joint_velocity_tolerance_; })); + + // Check that acceleration at the end is all zero + EXPECT_TRUE(std::all_of(res_msg.trajectory.joint_trajectory.points.back().accelerations.cbegin(), + res_msg.trajectory.joint_trajectory.points.back().accelerations.cend(), + [this](double v) { return std::fabs(v) < this->joint_acceleration_tolerance_; })); +} + +int main(int argc, char** argv) +{ + ros::init(argc, argv, "unittest_trajectory_generator_ptp"); + ros::NodeHandle nh; + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_ptp.test b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_ptp.test new file mode 100644 index 0000000000..86dbff3599 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_trajectory_generator_ptp.test @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/unittest_velocity_profile_atrap.cpp b/moveit_planners/pilz_industrial_motion_planner/test/unittest_velocity_profile_atrap.cpp new file mode 100644 index 0000000000..4962ab5301 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner/test/unittest_velocity_profile_atrap.cpp @@ -0,0 +1,631 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include + +#include "pilz_industrial_motion_planner/velocity_profile_atrap.h" + +// Modultest Level1 of Class VelocityProfileATrap +#define EPSILON 1.0e-10 + +TEST(ATrapTest, Test_SetProfile1) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + + // can reach the maximal velocity + vp.SetProfile(3, 35); + + EXPECT_NEAR(vp.Duration(), 11.0, EPSILON); + + EXPECT_NEAR(vp.Pos(-1), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(-1), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(-1), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(0), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(0), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(0), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(1), 4.0, EPSILON); + EXPECT_NEAR(vp.Vel(1), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(1), 2.0, EPSILON); + + EXPECT_NEAR(vp.Pos(2), 7.0, EPSILON); + EXPECT_NEAR(vp.Vel(2), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(2), 2.0, EPSILON); + + EXPECT_NEAR(vp.Pos(4.5), 17.0, EPSILON); + EXPECT_NEAR(vp.Vel(4.5), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(4.5), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(7), 27.0, EPSILON); + EXPECT_NEAR(vp.Vel(7), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(7), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(9), 33.0, EPSILON); + EXPECT_NEAR(vp.Vel(9), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(9), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(11), 35.0, EPSILON); + EXPECT_NEAR(vp.Vel(11), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(11), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(12), 35.0, EPSILON); + EXPECT_NEAR(vp.Vel(12), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(12), 0.0, EPSILON); +} + +TEST(ATrapTest, Test_SetProfile2) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(6, 2, 1.5); + + // just arrive the maximal velocity + vp.SetProfile(5, 26); + + EXPECT_NEAR(vp.Duration(), 7.0, EPSILON); + + EXPECT_NEAR(vp.Pos(-1), 5.0, EPSILON); + EXPECT_NEAR(vp.Vel(-1), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(-1), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(0), 5.0, EPSILON); + EXPECT_NEAR(vp.Vel(0), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(0), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(1.5), 7.25, EPSILON); + EXPECT_NEAR(vp.Vel(1.5), 3.0, EPSILON); + EXPECT_NEAR(vp.Acc(1.5), 2.0, EPSILON); + + EXPECT_NEAR(vp.Pos(3), 14.0, EPSILON); + EXPECT_NEAR(vp.Vel(3), 6.0, EPSILON); + EXPECT_NEAR(vp.Acc(3), 2.0, EPSILON); + + EXPECT_NEAR(vp.Pos(5), 23.0, EPSILON); + EXPECT_NEAR(vp.Vel(5), 3.0, EPSILON); + EXPECT_NEAR(vp.Acc(5), -1.5, EPSILON); + + EXPECT_NEAR(vp.Pos(7), 26.0, EPSILON); + EXPECT_NEAR(vp.Vel(7), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(7), -1.5, EPSILON); + + EXPECT_NEAR(vp.Pos(8), 26.0, EPSILON); + EXPECT_NEAR(vp.Vel(8), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(8), 0.0, EPSILON); +} + +TEST(ATrapTest, Test_SetProfile3) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(6, 2, 1); + + // cannot reach the maximal velocity + vp.SetProfile(5, 17); + + EXPECT_NEAR(vp.Duration(), 6.0, EPSILON); + + EXPECT_NEAR(vp.Pos(0), 5.0, EPSILON); + EXPECT_NEAR(vp.Vel(0), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(0), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(1), 6.0, EPSILON); + EXPECT_NEAR(vp.Vel(1), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(1), 2.0, EPSILON); + + EXPECT_NEAR(vp.Pos(2), 9.0, EPSILON); + EXPECT_NEAR(vp.Vel(2), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(2), 2.0, EPSILON); + + EXPECT_NEAR(vp.Pos(4), 15.0, EPSILON); + EXPECT_NEAR(vp.Vel(4), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(4), -1, EPSILON); + + EXPECT_NEAR(vp.Pos(6), 17.0, EPSILON); + EXPECT_NEAR(vp.Vel(6), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(6), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(7), 17.0, EPSILON); + EXPECT_NEAR(vp.Vel(7), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(7), 0.0, EPSILON); +} + +TEST(ATrapTest, Test_SetProfile4) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(6, 2, 1); + + // empty profile + vp.SetProfile(5, 5); + + EXPECT_NEAR(vp.Duration(), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(-1), 5.0, EPSILON); + EXPECT_NEAR(vp.Vel(-1), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(-1), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(0), 5.0, EPSILON); + EXPECT_NEAR(vp.Vel(0), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(0), 0.0, EPSILON); +} + +/** + * @brief Test Description + * + * Test Sequence: + * 1. Generate two profiles with same specifica + * 2. Set double EPSILON as duration of the first + * 3. Set the resulting duration as the duration of the second trajectory + * + * Expected Results: + * 1. - + * 2. - + * 3. Both profiles should be the same (checked with testpoints in the middle + * of each phase + */ +TEST(ATrapTest, Test_SetProfileToLowDuration) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp1 = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + pilz_industrial_motion_planner::VelocityProfileATrap vp2 = vp1; + + vp1.SetProfileDuration(3, 35, std::numeric_limits::epsilon()); + double fastest_duration = vp1.Duration(); + + vp2.SetProfileDuration(3, 35, fastest_duration); + + EXPECT_TRUE(vp1 == vp2) << "Not equal! Profile 1: \n" << vp1 << "\n Profile 2: " << vp2; +} + +/** + * @brief Define Profile with setProfileAllDurations with to low duration + * + * Test Sequence: + * 1. Define a profile with SetProfile(double, double), this will yield the + * fastest duration + * 2. Try to define a profile with setProfileAllDurations with a faster + * combination of durations + * + * Expected Results: + * 1. + * 2. Both trajectories should be equal + */ +TEST(ATrapTest, Test_setProfileAllDurationsToLowDuration) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp1 = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + pilz_industrial_motion_planner::VelocityProfileATrap vp2 = vp1; + + vp1.SetProfile(3, 35); + double fastest_duration = vp1.Duration(); + + // Trigger Duration()>(3*fastest_duration/4) + vp2.setProfileAllDurations(3, 35, fastest_duration / 4, fastest_duration / 4, fastest_duration / 4); + + EXPECT_TRUE(vp1 == vp2) << "Not equal! Profile 1: \n" << vp1 << "\n Profile 2: " << vp2; +} + +/** + * @brief Define Profile with setProfileStartVelocity with zero velocity + * + * Test Sequence: + * 1. Define a profile with SetProfile(double, double) + * 2. Try to define a profile with setProfileStartVelocity with zero velocity + * + * Expected Results: + * 1. + * 2. Both trajectories should be equal + */ +TEST(ATrapTest, Test_SetProfileZeroStartVelocity) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp1 = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + pilz_industrial_motion_planner::VelocityProfileATrap vp2 = vp1; + + vp1.SetProfile(1, 2); + + vp2.setProfileStartVelocity(1, 2, 0); // <-- Set zero velocity + EXPECT_TRUE(vp1 == vp2) << "Not equal! Profile 1: \n" << vp1 << "\n Profile 2: " << vp2; +} + +TEST(ATrapTest, Test_SetProfileDuration) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + + // set the duration as twice as the fastest profile + vp.SetProfileDuration(3, 35, 22.0); + + EXPECT_NEAR(vp.Duration(), 22.0, EPSILON); + + EXPECT_NEAR(vp.Pos(-1), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(-1), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(-1), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(0), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(0), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(0), 0, EPSILON); + + EXPECT_NEAR(vp.Pos(2), 4.0, EPSILON); + EXPECT_NEAR(vp.Vel(2), 1.0, EPSILON); + EXPECT_NEAR(vp.Acc(2), 0.5, EPSILON); + + EXPECT_NEAR(vp.Pos(4), 7.0, EPSILON); + EXPECT_NEAR(vp.Vel(4), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(4), 0.5, EPSILON); + + EXPECT_NEAR(vp.Pos(9), 17.0, EPSILON); + EXPECT_NEAR(vp.Vel(9), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(9), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(14), 27.0, EPSILON); + EXPECT_NEAR(vp.Vel(14), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(14), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(18), 33.0, EPSILON); + EXPECT_NEAR(vp.Vel(18), 1.0, EPSILON); + EXPECT_NEAR(vp.Acc(18), -0.25, EPSILON); + + EXPECT_NEAR(vp.Pos(22), 35.0, EPSILON); + EXPECT_NEAR(vp.Vel(22), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(22), -0.25, EPSILON); + + EXPECT_NEAR(vp.Pos(23), 35.0, EPSILON); + EXPECT_NEAR(vp.Vel(23), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(23), 0.0, EPSILON); +} + +TEST(ATrapTest, Test_setProfileAllDurations1) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + + // set durations + EXPECT_TRUE(vp.setProfileAllDurations(3, 35, 3.0, 4.0, 5.0)); + + EXPECT_NEAR(vp.Duration(), 12.0, EPSILON); + + EXPECT_NEAR(vp.Pos(-1), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(-1), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(-1), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(0), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(0), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(0), 0, EPSILON); + + EXPECT_NEAR(vp.Pos(2), 3.0 + 8.0 / 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(2), 8.0 / 3.0, EPSILON); + EXPECT_NEAR(vp.Acc(2), 4.0 / 3.0, EPSILON); + + EXPECT_NEAR(vp.Pos(3), 9.0, EPSILON); + EXPECT_NEAR(vp.Vel(3), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(3), 4.0 / 3.0, EPSILON); + + EXPECT_NEAR(vp.Pos(5), 17.0, EPSILON); + EXPECT_NEAR(vp.Vel(5), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(5), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(7), 25.0, EPSILON); + EXPECT_NEAR(vp.Vel(7), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(7), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(9), 31.4, EPSILON); + EXPECT_NEAR(vp.Vel(9), 2.4, EPSILON); + EXPECT_NEAR(vp.Acc(9), -0.8, EPSILON); + + EXPECT_NEAR(vp.Pos(12), 35.0, EPSILON); + EXPECT_NEAR(vp.Vel(12), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(12), -0.8, EPSILON); + + EXPECT_NEAR(vp.Pos(13), 35.0, EPSILON); + EXPECT_NEAR(vp.Vel(13), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(13), 0.0, EPSILON); +} + +TEST(ATrapTest, Test_setProfileAllDurations2) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + + // invalid maximal velocity + EXPECT_FALSE(vp.setProfileAllDurations(3, 35, 3.0, 3.0, 5.0)); + // invalid acceleration + EXPECT_FALSE(vp.setProfileAllDurations(3, 35, 1.0, 4.0, 7.0)); + // invalid deceleration + EXPECT_FALSE(vp.setProfileAllDurations(3, 35, 7.0, 4.0, 1.0)); +} + +TEST(ATrapTest, Test_setProfileStartVelocity1) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + + // invalide cases + EXPECT_FALSE(vp.setProfileStartVelocity(3.0, 5.0, -1.0)); + + // only deceleration + vp.setProfileStartVelocity(3.0, 5.0, 2.0); + + EXPECT_NEAR(vp.Duration(), 2.0, EPSILON); + EXPECT_NEAR(vp.firstPhaseDuration(), 2.0, EPSILON); + EXPECT_NEAR(vp.secondPhaseDuration(), 0.0, EPSILON); + EXPECT_NEAR(vp.thirdPhaseDuration(), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(-1), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(-1), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(-1), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(0), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(0), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(0), 0, EPSILON); + + EXPECT_NEAR(vp.Pos(1), 4.5, EPSILON); + EXPECT_NEAR(vp.Vel(1), 1.0, EPSILON); + EXPECT_NEAR(vp.Acc(1), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(2), 5.0, EPSILON); + EXPECT_NEAR(vp.Vel(2), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(2), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(3), 5.0, EPSILON); + EXPECT_NEAR(vp.Vel(3), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(3), 0.0, EPSILON); +} + +TEST(ATrapTest, Test_setProfileStartVelocity2) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + + // deceleration, acceleration and deceleration + vp.setProfileStartVelocity(3.0, 4.0, 2.0); + EXPECT_NEAR(vp.Duration(), 2.0 + 3 * sqrt(1.0 / 3.0), EPSILON); + EXPECT_NEAR(vp.firstPhaseDuration(), 2.0, EPSILON); + EXPECT_NEAR(vp.secondPhaseDuration(), sqrt(1.0 / 3.0), EPSILON); + EXPECT_NEAR(vp.thirdPhaseDuration(), 2 * sqrt(1.0 / 3.0), EPSILON); + + EXPECT_NEAR(vp.Pos(-1), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(-1), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(-1), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(0), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(0), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(0), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(1), 4.5, EPSILON); + EXPECT_NEAR(vp.Vel(1), 1.0, EPSILON); + EXPECT_NEAR(vp.Acc(1), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(2), 5.0, EPSILON); + EXPECT_NEAR(vp.Vel(2), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(2), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(2.1), 4.99, EPSILON); + EXPECT_NEAR(vp.Vel(2.1), -0.2, EPSILON); + EXPECT_NEAR(vp.Acc(2.1), -2.0, EPSILON); + + EXPECT_NEAR(vp.Pos(2 + sqrt(1.0 / 3.0)), 5.0 - 1.0 / 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(2 + sqrt(1.0 / 3.0)), -2 * sqrt(1.0 / 3.0), EPSILON); + EXPECT_NEAR(vp.Acc(2 + sqrt(1.0 / 3.0)), -2.0, EPSILON); + + EXPECT_NEAR(vp.Pos(2 + 3 * sqrt(1.0 / 3.0) - 0.2), 4.02, EPSILON); + EXPECT_NEAR(vp.Vel(2 + 3 * sqrt(1.0 / 3.0) - 0.2), -0.2, EPSILON); + EXPECT_NEAR(vp.Acc(2 + 3 * sqrt(1.0 / 3.0) - 0.2), 1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(2 + 3 * sqrt(1.0 / 3.0)), 4.0, EPSILON); + EXPECT_NEAR(vp.Vel(2 + 3 * sqrt(1.0 / 3.0)), 0, EPSILON); + EXPECT_NEAR(vp.Acc(2 + 3 * sqrt(1.0 / 3.0)), 1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(5), 4.0, EPSILON); + EXPECT_NEAR(vp.Vel(5), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(5), 0.0, EPSILON); +} + +TEST(ATrapTest, Test_setProfileStartVelocity3) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + + // acceleration, deceleration + vp.setProfileStartVelocity(3, 14, 2); + EXPECT_NEAR(vp.Duration(), 5.0, EPSILON); + EXPECT_NEAR(vp.firstPhaseDuration(), 1.0, EPSILON); + EXPECT_NEAR(vp.secondPhaseDuration(), 0.0, EPSILON); + EXPECT_NEAR(vp.thirdPhaseDuration(), 4.0, EPSILON); + + EXPECT_NEAR(vp.Pos(-1), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(-1), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(-1), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(0), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(0), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(0), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(1), 6.0, EPSILON); + EXPECT_NEAR(vp.Vel(1), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(1), 2.0, EPSILON); + + EXPECT_NEAR(vp.Pos(2), 9.5, EPSILON); + EXPECT_NEAR(vp.Vel(2), 3.0, EPSILON); + EXPECT_NEAR(vp.Acc(2), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(3), 12.0, EPSILON); + EXPECT_NEAR(vp.Vel(3), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(3), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(5), 14.0, EPSILON); + EXPECT_NEAR(vp.Vel(5), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(5), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(6), 14, EPSILON); + EXPECT_NEAR(vp.Vel(6), 0, EPSILON); + EXPECT_NEAR(vp.Acc(6), 0, EPSILON); +} + +TEST(ATrapTest, Test_setProfileStartVelocity4) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + + // acceleration, constant, deceleration + vp.setProfileStartVelocity(3, 14, 2); + EXPECT_NEAR(vp.Duration(), 5.0, EPSILON); + EXPECT_NEAR(vp.firstPhaseDuration(), 1.0, EPSILON); + EXPECT_NEAR(vp.secondPhaseDuration(), 0.0, EPSILON); + EXPECT_NEAR(vp.thirdPhaseDuration(), 4.0, EPSILON); + + EXPECT_NEAR(vp.Pos(-1), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(-1), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(-1), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(0), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(0), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(0), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(1), 6.0, EPSILON); + EXPECT_NEAR(vp.Vel(1), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(1), 2.0, EPSILON); + + EXPECT_NEAR(vp.Pos(2), 9.5, EPSILON); + EXPECT_NEAR(vp.Vel(2), 3.0, EPSILON); + EXPECT_NEAR(vp.Acc(2), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(3), 12.0, EPSILON); + EXPECT_NEAR(vp.Vel(3), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(3), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(5), 14.0, EPSILON); + EXPECT_NEAR(vp.Vel(5), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(5), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(6), 14, EPSILON); + EXPECT_NEAR(vp.Vel(6), 0, EPSILON); + EXPECT_NEAR(vp.Acc(6), 0, EPSILON); +} + +TEST(ATrapTest, Test_setProfileStartVelocity5) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + + // acceleration, constant, deceleration + vp.setProfileStartVelocity(3, 18, 2); + EXPECT_NEAR(vp.Duration(), 6.0, EPSILON); + EXPECT_NEAR(vp.firstPhaseDuration(), 1.0, EPSILON); + EXPECT_NEAR(vp.secondPhaseDuration(), 1.0, EPSILON); + EXPECT_NEAR(vp.thirdPhaseDuration(), 4.0, EPSILON); + + EXPECT_NEAR(vp.Pos(-1), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(-1), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(-1), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(0), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(0), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(0), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(1), 6.0, EPSILON); + EXPECT_NEAR(vp.Vel(1), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(1), 2.0, EPSILON); + + EXPECT_NEAR(vp.Pos(2), 10, EPSILON); + EXPECT_NEAR(vp.Vel(2), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(2), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(3), 13.5, EPSILON); + EXPECT_NEAR(vp.Vel(3), 3.0, EPSILON); + EXPECT_NEAR(vp.Acc(3), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(4), 16.0, EPSILON); + EXPECT_NEAR(vp.Vel(4), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(4), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(6), 18.0, EPSILON); + EXPECT_NEAR(vp.Vel(6), 0.0, EPSILON); + EXPECT_NEAR(vp.Acc(6), -1.0, EPSILON); + + EXPECT_NEAR(vp.Pos(7), 18, EPSILON); + EXPECT_NEAR(vp.Vel(7), 0, EPSILON); + EXPECT_NEAR(vp.Acc(7), 0, EPSILON); +} + +TEST(ATrapTest, Test_setProfileStartVelocity6) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 2, 1); + + // acceleration, constant, deceleration + vp.setProfileStartVelocity(3, 15, 4); + EXPECT_NEAR(vp.Duration(), 5.0, EPSILON); + EXPECT_NEAR(vp.firstPhaseDuration(), 0.0, EPSILON); + EXPECT_NEAR(vp.secondPhaseDuration(), 1.0, EPSILON); + EXPECT_NEAR(vp.thirdPhaseDuration(), 4.0, EPSILON); + + EXPECT_NEAR(vp.Pos(-1), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(-1), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(-1), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(0), 3.0, EPSILON); + EXPECT_NEAR(vp.Vel(0), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(0), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(1), 7.0, EPSILON); + EXPECT_NEAR(vp.Vel(1), 4.0, EPSILON); + EXPECT_NEAR(vp.Acc(1), 0.0, EPSILON); + + EXPECT_NEAR(vp.Pos(3), 13, EPSILON); + EXPECT_NEAR(vp.Vel(3), 2.0, EPSILON); + EXPECT_NEAR(vp.Acc(3), -1.0, EPSILON); +} + +/** + * @brief Check that the clone function returns a equal profile + * + * Note: Definitions other than setProfileAllDurations could fail due to numeric + * noise + */ +TEST(ATrapTest, Test_Clone) +{ + pilz_industrial_motion_planner::VelocityProfileATrap vp = + pilz_industrial_motion_planner::VelocityProfileATrap(4, 1, 1); + vp.setProfileAllDurations(0, 10, 10, 10, 10); + pilz_industrial_motion_planner::VelocityProfileATrap* vp_clone = + static_cast(vp.Clone()); + EXPECT_EQ(vp, *vp_clone); + delete vp_clone; +} + +int main(int argc, char** argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst b/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst new file mode 100644 index 0000000000..241af55e15 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst @@ -0,0 +1,84 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package pilz_industrial_motion_planner_testutils +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +0.4.10 (2019-12-04) +------------------- + +0.4.9 (2019-11-28) +------------------ + +0.4.8 (2019-11-22) +------------------ + +0.4.7 (2019-09-10) +------------------ +* Fix clang-tidy issues +* integrate clang-tidy via CMake flag +* Contributors: Pilz GmbH and Co. KG + +0.4.6 (2019-09-04) +------------------ + +0.4.5 (2019-09-03) +------------------ + +0.4.4 (2019-06-19) +------------------ + +0.4.3 (2019-04-08) +------------------ +* update package dependencies +* Add missing intialization +* Add getter for CircJointInterimCart in XMLTestdataLoader + +0.4.2 (2019-03-13) +------------------ + +0.4.1 (2019-02-27) +------------------ + +0.3.6 (2019-02-26) +------------------ + +0.3.5 (2019-02-06) +------------------ + +0.3.4 (2019-02-05) +------------------ +* Add high level abstraction data classes to represent configuration of robot +* Add high level abstraction data classes to represent different command types +* Add functions to TestdataLoader returning the high level abstraction classes + +0.4.0 (2018-12-18) +------------------ +* Use Eigen::Isometry3d to keep up with the recent changes in moveit +* Contributors: Chris Lalancette + +0.3.1 (2018-12-17) +------------------ +* Add RobotMotionObserver in testutils +* Contributors: Pilz GmbH and Co. KG + +0.3.0 (2018-11-28) +------------------ +* rename get_current_joint_values -> get_current_joint_states + +0.2.2 (2018-09-26) +------------------ +* fix missing dependency for melodic +* Contributors: Pilz GmbH and Co. KG + +0.2.1 (2018-09-25) +------------------ + +0.1.1 (2018-09-25) +------------------ + +0.2.0 (2018-09-14) +------------------ + +0.1.0 (2018-09-14) +------------------ +* xml test data loader. +* Contributors: Pilz GmbH and Co. KG diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/CMakeLists.txt b/moveit_planners/pilz_industrial_motion_planner_testutils/CMakeLists.txt new file mode 100644 index 0000000000..fc692408c9 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/CMakeLists.txt @@ -0,0 +1,88 @@ +cmake_minimum_required(VERSION 2.8.3) +project(pilz_industrial_motion_planner_testutils) + +## Add support for C++11, supported in ROS Kinetic and newer +add_definitions(-std=c++11) +add_definitions(-Wall) +add_definitions(-Wextra) +add_definitions(-Wno-unused-parameter) +add_definitions(-Werror) + +find_package(catkin REQUIRED COMPONENTS + eigen_conversions + moveit_core + moveit_msgs +) + +find_package(Boost REQUIRED COMPONENTS) + +################ +## Clang tidy ## +################ +if(CATKIN_ENABLE_CLANG_TIDY) + find_program( + CLANG_TIDY_EXE + NAMES "clang-tidy" + DOC "Path to clang-tidy executable" + ) + if(NOT CLANG_TIDY_EXE) + message(FATAL_ERROR "clang-tidy not found.") + else() + message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") + set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE}") + endif() +endif() + +################################### +## catkin specific configuration ## +################################### +catkin_package( + INCLUDE_DIRS include + LIBRARIES ${PROJECT_NAME} + CATKIN_DEPENDS moveit_core moveit_msgs + DEPENDS Boost +) + +########### +## Build ## +########### + +## Specify additional locations of header files +## Your package locations should be listed before other locations +include_directories( + include + ${catkin_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} +) + +## Declare a C++ library +add_library(${PROJECT_NAME} + src/cartesianconfiguration.cpp + src/jointconfiguration.cpp + src/robotconfiguration.cpp + src/sequence.cpp + src/xml_testdata_loader.cpp +) + +## Specify libraries to link a library or executable target against +target_link_libraries(${PROJECT_NAME} + ${catkin_LIBRARIES} +) + +add_dependencies(${PROJECT_NAME} + ${catkin_EXPORTED_TARGETS}) + +############# +## Install ## +############# + +install(DIRECTORY include/${PROJECT_NAME}/ + DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} + FILES_MATCHING PATTERN "*.h" + PATTERN ".svn" EXCLUDE +) + +## Mark executables and/or libraries for installation +install(TARGETS ${PROJECT_NAME} + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +) diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/README.md b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/README.md new file mode 100644 index 0000000000..d24acad427 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/README.md @@ -0,0 +1,34 @@ +# Test data provider/loader + +## General information +- Use as little as possible test points (Reason: Reduces maintenance overhead). +- Test points should be defined following the concept shown below. +![TestDataConcept](../../pilz_trajectory_generation/test/test_robots/concept_testdata.png) +- Test points can be defined in joint space or Cartesian space. However, one +test point should not be defined in both spaces (data redundancy) +- If a test point is defined in Cartesian space, then also state the +corresponding seed. +- Store preferably only valid test points and test commands. You can use the +valid test points and test commands to create invalid test points or commands if +needed (Reason: Reduces maintenance overhead). + +## Diagrams/ Data types +- The following diagrams show the main classes which can be loaded from the +test data provider/loader, and the relationship between them. + +### Robot configurations +![RobotConfigurations](diagrams/diag_class_robot_configurations.png) + +### Command types +![Commands](diagrams/diag_class_commands.png) + +### Circ auxiliary types +![AuxiliaryTypes](diagrams/diag_class_circ_auxiliary.png) + +## Usage +The usage of the TestDataLoader is as shown below. +![RobotConfigurations](diagrams/diag_seq_testdataloader_usage.png) + +The idea is that the TestdataLoader returns high level data abstraction classes +which can then directly be used to generate/build the ROS messages needed +for testing. diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_circ_auxiliary.png b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_circ_auxiliary.png new file mode 100644 index 0000000000000000000000000000000000000000..a8e633c8a2cbb3e6e2b75e34f945c97602804526 GIT binary patch literal 24644 zcmb5W1z43^^FE9sqEceep@Ik^Aqa>FsDuhC0@9_#rn_4OK~X?yrAt6cxF)l|v%xs$J@5PbKCW|d5cYodidi%F+;h)*_3*)Mf@2iNu&}TQ?%olW!ooUafrWKo z>BvF&P0NqzFf6Rccz1UDhhXtj5D_e`bdAz`D;yGK`b-$@>vP=4@`m}4wH zt;jFv{TGodgjVXDRw?Z<(&n7x#bgE*x<{(oh7+!WP#Z>a{yo#jP6p%um9Auo{h5 z*$*K<+{i@+h*f$T`F=bF`HtnvjC?<%d;t01ATlMaBXY?1zrF0K2@dkBy%+!OWq*6- z-(L3TGjozxINk*Y#`WKuNhi<1!8|9v^t8*~DBu~G$G|%X@PCi}A$P)Mrl=kb zFB2ThB;DMYVUtxF)`NQkI=*KAwUZ#0}ac zr5vNCC=m|=ZlfMDN=iPvC7nFS$>f~O0ZCcefRK=>;bBgvt+kMlkoNZW;N1-##z5kc zI-dSF9v(hL<>lp7VWHS>vVVN9@?GtBF3}X6j$Bz;`TY6wYf?5nrD_^Y!E|JlEK1p9 ztI`Sz@BRGf>wMkYQ&hTJTIiUy>Lyc5`kI?>tK}6H`m`J& z{PrvJ!xhU)*L=cUGNrjqE@^9OQt_Gz+mCInFPfT~cBvfo@IlAWon*LYvx3%^2)TL_ zM&LnCG~mS$LTsahMK{=ck2(dmFwXf=fR?9*U`MK&b)L3JuFq(f0rz%a>!8@Z&}&)g z=~5)cTMIR>mRl6)8`gy*h*IW>`BV}>A&HTvMybtIFX`i zGl-L6Qa-Ev42}%g`B<5f*v*^IhMto!F){I3O*PKQK6<1>i)TTnOfEpeSOd!v78X`n zSqWBKWlEs-&TL0MVkM3RotvB6nIvs!Xn6koc^@>xy`ax_%X%5!I0xaOa7u2__DM}y zZ7z+sn46nZQc$F*7U^Z6SEkU>Djr3Jh1buWi^|THEzohbx{1eA>K~IZHa6xhxRV8Lr1JCg!6Ju-hl`4eun!)DMaj_bV4ZFn8d9&~R#jDX z6HhB3PBH4s|6D+St|GScwTH*|mqpp1lar_W>}R)Ex{X6~TDur{lVf6pcjH}CmX<7> zot*^*1r^>poM)!B8#~JzUoM`8z4wV<8g0aR9o9b6=d1E0e)?p$P<6r9{?HM*LTYJs z!jzTZ?VNLLtfi-)5)Y-Q#hkrxVf3$8CqqL+!<{yC)zybKmM7b~dAPXlf4DLZre(b| z{SHs@sR`G0^z_Qs)|RX5AzIq-FJHdAd4suYRm?CmwoKz~Y1%u0Pv z7&+KXafToMAucX%|Kq*(;fu-yt&F|PPcmszmJ$}guLy3U8|WnnTc53sx|-lT?yRY) zF<(Df<|f#IKY;QouwIMU?s;Q-u(Zu2!>IRKIgXS>=(Xie4R5e|+{1@iRSV@epMS)E z@Z`x8@T~6c6?M+rLhepI7nzxTeS91o9Msj-!5>ZLq8?~yL{nY9bg8zx+rHY5sXN<{ z6F(Pyle*i_-~arD3pD~2-n8MqzAar{6AKQZg3eB*u160uIsS?JJ5kPj$W`3yrvc|WdqAMZ0kF`2ci$Cf(aH-VT z0@5ZdeR8Mx20h>y6$T%0O}u%3yT$3%t5=(=v$GQu8#|k`a>gC4_O`2O;8bbNv z$WmNziK<%=2PS=SEzf+E4O}l^VR%x;0 zW>rReoiu*RHPWFsHj`vSyX~g<2&QZZ<^3(Gxw%(h*1Qx znC|pEry8T(U30e|yvW7XHb?iSD;nh+(@`va@}U>gx0~_D zi9}mmW8>M*PI+E2ZEfvTd(Nq9gV6~|3Lc}79Z7`%t_jDLYe!JS2C;k-k{nn1w8WQ! z?_yI>P>`@H=UR+Qt(MA|n0&57wRn54#G~m=(bjqgtBJ7&dhyRF6X;D46@nYOJHNf$ zp|-lT)H!V>;yF_&dhnG1_gGs8c=!^hDxdQwZh;dcuxIBRt1I4$d7P?}t2_9dq>Eyi zF`>*KEzsujc*TObcYKnOH|HR_|ot<}AR;(%(Zqqu(#5aL6O;IWMsK%-B?G5;~<)(%ZUQVki`7(hz!U@$}sj0d~ zRC#?{w4aYpx<&=zw2_F&iye(;MfJ?vXO_C?nO&l<#xLrcp-+tR-#OGQpu~s=@vuuM z+<7Ojn-=fUy%VLUM~-04867^J;zm}`D*z#=r>Dow%`H(bwaXwI;-d~Jxx|A9td}l9 zc)xD9GzM<%^oaevd-v|&_uOgGv0t4bAS7gEVS!jNJvR2X0FUI-+hsUNn{#DETAr@1 z1eDzOg1PHHOJum@lct=q=gd?{Ghb%(4-C95EZo}Ou19LnsMc6IB2afYvV%c^oJ!<& zh=gxVK<<`&gw_0;q@*PH;Ex{}Y}%lP>C&d!dLlT-Sc*o>r}BKy@TbcUm&BSdI0Qdn_~&N%eVUOYLEBJ!@J9cEv3 zKVbj|1_nuifq{#$ohmae2FL9Tef+;lTKu(sCC}j1juc7sZSR0PA06HA-#L!N3TioH z2{AG7ag)nZQ-Fkg97YzTrdTf=9rQ3eguSz?gA#O^Svh1gozEbI!Pft$?f%TZ|5$Byz=bcsO-JDB>^WP}bd-QXCl+ek-5fJ<317i6vU%q_*{{4v? zv1-|C(JKI2THSBFGRe!!t3A+n=K#Rvhu|e1W5qisG#p1Q3HEJ+4VCQfY}QNU*)31R z-1Vg@5w-@OjZ0&5qkV}Y#g#shc4y8Vmx#ts({gF7Nfp~4{rwS41fVD20^^?C!CXH3 zm8szhZ%$krIvfP*-@n28oR2yMo<0o_egWI^^y$-Vg>%oXc$k^R+vShS@ffS@RFsts zH#qNPL=mtCChx{?wVH5azg|& z#DVuETO(|4(KcpN^~{pqV0S$7oD^V^YgE9aHOZC%s?DUO-LA*&Q0Hm zUhygZ&gf1^{o%5P+a=BekVhRB&s9Hk0Dtqt)7AVZ65E_(9wstMN}FZ0J0`0$y&HIn zg)3e9yYsZWPp-NqH95^yPg#E}0h9_ppKr&FA!oJMI(%`K>S6#aLD5^5J;27h3AP6a zECK?|*Beq>`1u|M@~j2w#4K*X4~@b4&wrl{Tl5pFd-i%=)7a> zys7ly{Ne7o6Dd!hHMh22(QS@d9Btq{RTzs+COcR?&99?ovN}I+JNFe=&0$`o!njjO zFkqw6s(>E=-r2J^S7^z|g5JH8l#$`G=^MTz&@_airly7n6ekgG)x&SQpeZjepE}HY zWH*5tg1cy9eHP!XzszoW%eISN=jBDZ-d3+dzxsC;PmWTn2uEY!{N%z%+wCE zMMaeQPjQ|oSdJpxQSXkZs(nmyPMPRv>7M3o#5nYvC?bZKhpn( zZ=n8O_TW1Q*tahQpt*I+esDi`#;ySiL9BY*ezp&sWgywuJA*%nk&wD5a;T_XH79 zavQw#@(Kv$bGjm`-t9spFg7~Mqu+jM`hy%wV-2S9!qs(bSG^sLX421mO)4iV%W(eu zT^>NFfaelb1mr3CUw2Gp_dN(KJKyK9SQj79sOzAt9AY8NU#K@xg<4S@Ytc04<#4M) zakun@85rT?fZwsW2=oN-Gm>Tb||ePS6|-?5@O;` zi^2VeaByNje$=xjWmWE+B-{CZLGWFdO7~Q#b>BNKuMq?e>QpAvvoiIJ)`u!ReE3+$ zdzt97fd4zYvUm zcszyulz%`#bz)yljs6`8f5~XkUgzCy2q8nRCsMH9M40&d_((}gMy9f9*9Jw}MEMy3 zEO!3>?zU`-vTo;(g^?O5?~A1}Dk`B?IeB@!^z?tFO-)WRi$p2}*D1z#KDlw@Y0WGF zA5TJYao<$##thknO2+UtqSTszwe@vg*5$-;2xW+__ z8-0q6YSOpPfbobNnFkU?dJC-83aqBB?)e`GS3&Xlt%$SHtC`+9Du?BEFE_s;q@4c^ zCC>vj{p$22({^hq4+ws(viQ zehS~;GfJVGxup^3XL)6P+RhNkMa9M4wjVt-cq;QT>zl0dA?^~N6y(1!S*=b^Q*TTXA z(juqemN7hs&ZSiey1&)ku$WWCtlHt4*w7(OZVQo(aZG&kL;!#4NSVD%Jc zq}P;}b<-1aa&}6`TQnyp5z}&=kSr%v=K-pTl#~akCR@_pbgkDbeg}3Jrt6gYg+s4d ze)9H~5EgbFUUVwj$zkw)UsZbstBh9}P!{`)_ilb)V7e+ z@$2({oy=iVW~yJf5bm%rOuH*j;R9RN!xsvAXSNKPVQO%?sQasul9T;w7r)}tUZtU! zW9y&k%98= zn$k=<{%+~DFQ89${Ia%{>F!wW<)x)oV`XJ!DoV=9krAzJsi_YT<(Q;D+SuERpWpaK zX*|ZmNhQARy!#7zr!%jUn%0N#ZuBczpl_8ETF>^e>=tiqY(QFpLZS3XH)pc$qI%Qh zXE9#p&RrI3Ut3Dz?Wx#ax-oE&YS2587Fg0 zhrd-;-q~k%4khHs(Mn!M*NP^j`qtTM;@dwgH0cR8Kq05`ZK5zlxDd`aLwIR!-UL8I z@CD#*)#NNZKq!FX2OWaD>kVG1$!2DV&ymk9J)REK#Wc~)^ttZ-oq)?}V{?OLKCj8# z2USkasq(1btzS>w-AD!6rpykEtgf`J?%B>l@)X+Bt%qEhd#If^TEfrK(S?@S za%I}s*z^F_4dyZa;kq{sK+F5NE{4H_l;Vu?{0YG1>RSi?z|(v29*g}dP@nijTlxn9 zWIZi`3IW0$97DlfNCv9gU* zDO7lJDar}IDKvKFDkJItVB1Ea2JrnsfWJ^7aFK%B;}QhSu^F?)o2=$LR%DVHuYbUugn~9Y00m!@uyE*q zs$od5?(FPjsjD}`raPUbx=_oNfU&`Xykl?e-;ArNN zF}evDq0`SZGuI5+_J4jNWMPpxWe%jEI}vR_=E{Hz(Z>3E-3P8oaP%Igki5*^x^-*G z`P}5xlpj}mpJ`5dItLTe-3{=t8CKI>VPP~vt1PMl-F9>;gzsz?>v*E0qGIMDw{9k$ zmPd6nzlleeQ!*hecxju;5joZzCN{P}MH9e)KsT5%*YH`-Sdgd0OqpN0z`!umU!pd# zj3lsapJbS2li0iSlJ4HQ^R_oTCkLokEp2Um(^5(20)rR@-&Q_9#l`;$0uwfely^Q* zcbFUrtb1DtHljwRXa*3FX(l;D!1m5U6(q_dV8r#F>V@Xa#pF>AaJa^O|kl1KHF979J6&Aa#y{y*h`N zmYSMc0cfW)-8ndwRg(S@u-%C1vZE=hbDfv|Ro5C6V7t3^my@Od+bu&0 zA?8#?I{t^jl)uQ9bBiDtAiPOC6hj~jb#4mqrs9qAZiHsfJ=Z4Cr}C9XpZ~qRU-=6Mt#X;^N|>Y>|2i z8cSqdzny-WF!lu`U=o7cOYO-@Y|6P2IzE4iOs6QQh195J3{wyerjs|LRm=Q03j1?S zg-qr6jo_HQV{inX&TEanrt3&$`Y21Zs3%mZ-l|kR?;flcqpNefvxnB?!WFWJxe9)= z0PJ(_RXUE6Wx~EYuBJ4beT$Cmj29>!~6uBhft^_9SBuhvk~~)y-V|W(Y~(WP5Uf?WD&X5>l4W{*@$ZO{c6- zGI?Ft!(_zF{*N)_=JO3!*VIgQW$ABl{ZXGG6CfF@?e8xsD(X$!YPwCUt8{HvS&~c4 z-`J|^Kn6o^ro+urPVM?P)O_t?zO@_bMO&5vuI8NkK&mWSDcity=+%Y8?8;2vrhS2! znfG?SgeSPsgo)2baL&MKh>eSGqk;j)zPT?QnP=8 zApLz1ge;~!n=^sC3HlAB!%EH~xbBGGb`CwdY@L$SBl9MhPWGBYe#xk_7ZOSXA3MVav3&*GANdrk7C#D=7eY$&u8-_{)iU z)3D^Yh0%rVuf{vuK9Xr#@Q&4e>_;+l%xzK8Ypms}j~>xq5Gg9! zcuA-I%N3N{_f}#MiTABr0nVG<{T!E2gtP*e@?M($!Ok^m^YZducn~r+HMO(QAJapC&()Yw=RJr8 zugNWfC_Iq8yWPJF#BVm*03XM#=-an%5fKpq0VHk*ks!@JN8_|Mh`9gQKvi`{_NkHY z-zyEAClcbwjv;aQ3s!fgZcE8_cS$I}JvSrcSg>*NlN;<{(N9`!kZ zAOCR&X7| z%}F4t@$uYZKYaKA#Y~7a6}=b2Y=-hi!!+bEg@5eF9VseO`V+g0#qsevP@jH-??zko z2v}C6P}&Yej*fFS4ibC5I0A_7&=3n{5-N~H^RY&?|ry(mpEKcUw^rO6W8rZ zg})-bFjG`Vq3t3We;7twADZnE&ZvWX-^Ku(o}y@qYcol^NMgmJC^6vfE?Vt_^*nT%O4)-NvvhnQMBu)7(c^!7;_m^k#X&*=cJS)wtDib0 zBq!e&7uTTLA7+GFeHg!zqGI*c$KMC6Q}zdh31`LkZz#oya?ewO6dKj5i*D+l9&pZ7+!KemBz zJ!4okv$>L^|HrBs$|@>$b#_)FlXyYBfn?q5FP*B)aXgIt@>?E8^l zHn@G_^l8hLDTV(WsYwo$0ni5A-wx2>mYCxprtmLo1;0Y3(Svfxqph{wJ0L@Kfi+St zyhO;l-4H|@WZTac1^(U|Ui%e;M~_bZ8p8iR2H?DduIQfl_3CXi&{P0B0>e7?e-G;c z9GUJk4O}=fFF+}Q?DSz(I2h6r{N-04|IbCkmxhFqRyJ9&{P!{V-uvrJz z@9g-keWh0)3l9pO`o9cJ7sdtuX;868{WP#IN|`!MYC8+0Ftfyg0jVj>{vHSn2>2G; z2^t&Zto%0le_6DhRNa=3)VyYzZ#%xSlC!QcSfdRp4MlU+vpKsDz?<=DA&&(;8uj-< zkCrRfciS!~U+#WCjZDGK7d&Hdov7qO#iybSB1(ZO0P z&x1mghzuQ<**rGLf|_jG6x_VA6oDg*6oL>%%(1(nkcQWl__LA`Jg8=I4Z1K@p6 zpVGa1wUI*Z8;`JiHD(^jdQt#3A1`MExdw=_2qVpWy}$e#lmFROiJgBHWk8xZyFz%| zlfn`*z#TtF>(TIgy{54{0=5g^8=O`+6AE!Z&6jNocDYw)YX6*lf_2|bH5syr0n5pD z7RAgvY1^Ptf`D=xK_bRQ%K`0m!0CVgt_iXeDEEwh|DKth-M7`TOKi=125Qx)N00ob zSXfyftV~^3?xJ8?n}M_{!7a;uuP&Ims}{(jMU+m9M&<|wf~C!bq@;UL0{T%Uq~DP; z4JFmdSH9SugS0#fRS3aI0Oz~JD-eyNp#P9;bhg@yluw12>6Y~ZU4&@pD+P#Ng# zyb861=g$vLmZ|4-0~eKr$SQUhHWiK9TU&MbEi>=i-)Z7TGw}0oLmt;fIFbj74uWIH z6bo(A-Z-R+aJGb@>kV+h*Rk7}SALF}jZRISjTH~96+N>jmQZu754v1-nZwf3vTNhV zj~{Q}zE!QM!zj}F&n^4r_xPEy2neWdcD6y~*_&1{rN3En^V%IgE$oVPzgM@tsG4Z5 zIqyKNL|LsNtF;{|-}W%`07*$;*g_+fc|SWLHPzZExOGFys-{vRh?L{HfSH*Yz+|AwU{%R)Ei#iDE*rOxF26 z-Vz7;0^0-^E%^}IqGUA(il|@Xz#5#Ww-npH$t04e8@n~(oVN}j5iqtiiK^532*}wQ z)bp6Qmf*n~wkaj+KY~H}73eLNkj%<+nqMX}xnrGSCzg~S3h z(|?go#IdrmdB1!apPbxQ{3*q;yx-GIdZOm>ARnFbDefL;UW zxJ*p-c&h6_c4x`L6*cTr2lZUDzf^-e+S{#Wi&mXBr*rC+^bCEgvoMl5Kf6Da6EeMZ zN*%1`TP&p`pLM9@3RE*t_qDa-h9#K@0LE2){>-jx0*W&Q1%*`7xV}tXU$j=PN_L%A zKO(dvKmVFEj^URhJ|bt`I{&1{`jt<-^~n?il7c?>c>)th8le-*@I~ ztM;AMRaLyEL&DnHqjBL*pmfM}+O}I>fvTS`!+kh5*R|bE$_;R_4?Qqu1tuBsYVqo&N|@J27*_(v|^ z2|GLA{=A4qk62Y zthl+k>qGf+A|k#tMZ3DXBC6t_G@Z7V)_Y6YG~d07tm$D}mY!Y{EmMx*I?X^|w8@d9 zk{2Yx{DiiC@RS@qc1-O4{k9qK^>57&A;G#VQht7U8H&3;=xB0sa>RGefMP&^m9@Sp z8iW&ujv!gRbLXXk_Gv!wnxps&in)`6)kB)x!BwmmG6s*Ih^4AoFyrj;Pb$ak?9)No z6sRKp(&}0WlTh*JJ8kFJ2wbyaO^{gfF8B_UKM2+CFVi~-+W z9ntT;QiU?{=Vm&Q-1Op;m^Yl*dqYy+tHtPvf;|Hv`&7O!*yTjkB20}m)A-1U<#ZR< zs#PiZ_bm4KQvWB&LVzv9e-D$ke0z<;1sv^+jEsbY%Gwg;47t0*`0X>r(`I`Mc&=W} zg*+DWRuJCKu*!eFp(6I}ufJMbTgL>owHz;m+*HMLxu{Iekb%C(uqS^nuikBIYXfx_ zDJ|{n^fdMHxtB?A|%@dG{T2c(BTk zX&-+>KY9dtKcnpb=X2;|eh3+sOT7HohZR?TWPLF}^1`Q264TNyGcv{l5Q)UHd4b6` zdjfrZ&HEi!`IlRz@o~N|V?!W{f9QD0tw+K> z_wVkk;uHUTXu-cS2~Xu1k(Iqsj>@=e%5eTe)MqHs&|u@t9YfSnSn*p6fhFKiV%4!L zc*gr}N2$LZ+aHEWa%}7fjXoR&Ee%op{a>;t_mLgif9B(Xk&%(hN3c>KVsfF9{)pK@ z7K;5BMp$6)uPb9O*8Ycy@%&sKKcoG3VZ~DJkN?K_;r-|0^KE$$?*Dc#XGL-|m;`(w z%f6RulRb1$q1pd1vX?wMtV{U&AM-H(!2Slo$LtRxmh$H!@`&+du=KL-#8Vtl#n4DM z5E(W2X9U?lbz}Y{3VVQT!&q7B*qwJs(GmEhrs&&HeFtfJdET1u$bUjAL~qxk1J#wD2R!9XbcXz)3)Qr0YKKXX1;h4 z)etsK^|!*n2-17dl69e4GR$s*i8m_y%d5SG6Y7T2bH2%7X-W#Kf;<$MA!-X;gCLUf z)2G~%)Ed=+YHcr*v9!!W3oyGOodS&X#T zFW4QayX-W243j(Z7W9UNhljs?I{+HXpAxc>l|B%y6H;GmjVoQHF)u?oY@h=Vkb4w3 zMHx$fIQIn`lZwCi-;F?@1WTx|cODygMiE}nm-^KzYSymx5Mt&LYKn@A9?;(7OIm2bjLj>~Hy*DNQ}DroQs2?_D>l_CGhX4X~x zCFQ>#Cs>z22?-VBZND%(dwYrZ99qC@x;?qV7e7?E)I}Vqy>1nvlfh|3c6qsz!po>r zTWwR_lmTNya}rXy;!JF(^`PIUIaXX>Uq8#8K_bjyZSG0Ng#btdiwgdh2u`#@{au0X zSzJN_6CWQR)Fic*lS-6iWX|KP{;%Gn?t5V~o&FXV_D|e(i@AZXpiRu1h9YGI$6h8F zSmb*F)LTK2N|q?2*q7HTpRLUH_qVkzZ?E>JDrV`Gdz@BW+>`!~rmIbeibdEhx5=?V zHq_g@4cV6#3PllSWc6^_7BsCj&j zZHbUyutV7m$u*b>DAzVN#Hfw4%l!QOKw9HCa!unK{_RjjQ0FHbW7PTMS#zOW`T;xQ z0#fCl%KTeLK=a(C-2eyQacj-gkTY4Q*miR0*h0JpFCE=*?TNrxYWtm_@?R7oWpatf>V6zpkse?QTE!{f!soqxpFk;;0*;2d2H5Cd9RS&WILy)38%yJ( z;m)caHqeVRzdn(e%E8GA!elC1NnaPey2+Ut*(LF&O3;E;M*l7x4s2OuxO{4O9Yu%2 z*c_7Ey)LWXVy;Q;aILYI__mYT&uANm3YOlvRg%A6rYWRPnI!dC!2On7Xd zh6OrL8&rlKjU2BQ>rZ!__4CCG6xlWtdyOMKS}gLL(L^o>OfBD)j~!?cTM?K$@a8y$wpf$ zG+ePmv7;`ShtK)aXQVM8)CDX7>LWUcchB_3$(J;z6kuVfDQYi}l84F>%{7ZVUWvO5 zZx$;KW|iny1wbocJ1#(Yq`T={$eU)cFap}c(%wj>!ySX@v(6zJE_Kku*~lvX95uhPF0shP2MNg)o|HKT zXpU_hmjBWj7FmGl47-)xkwO`%(pc*GLCFK^&%YbP(ABgje>H{?1e3GsoUOCEo(cLP zP`N_!1T;{*ZxIdDvzjOG;CO=mva0fttZaVan`d?oAbX9qg^nwrxI(X*Mx9eG#~@uD zT5;(sW_u#6$RxiML&#Zx@^_>D0K1}kiuy8NP0p||q#U3R0F^+M5VZJ6+_}RJYJVe& z!!1Bq@@%MUF+jY9|DKvGvw?7|phMMuI?|n{Idy7c0!p~Ay}eggRtS$A34*#T2;(zv zLv%XdZ37ZH*76zAI>*I!t@QJ!cvBixpt^T^Dhm&oC?Gp#q3)^Qc~3v6bq4U?#_jVK zv2k&m@U^~P^<0=VF#7E98N;#VgFPPepe70C(DFzMJh$V?)A!Idak@K4oR6QMKg+$A zA`iMSpiZ>;Q(_gyYyR!CP=-t2)U-FJhga@(WQyWJkcMBNCjGG2hrqc%!8v7^pXsmp zaowR7aF9Q?jcIc8F$+0oIhJk{WxI!77<)I){EyDIs*TvH%fb>@_5k3Q0gg3ik+{sv zN2R|tOFFq%vdzy=%+99nzBwl{@vtfGWZfRJ1{jBgZ1{qZH^90p9#MEJ6dgcks40rV zcDuRB^1xUi7=wq|NnQez+7Df@6!R zTOA29ZcUdg{SHX5u7;`p6y^-3*Dd%V5qTRsbsr9(qoM1=ZYr$;yeKv{Hmpg~bhXKt z{f>V=8k#fAge$xUAMD5CCU(Afjo>}ViXL5?A2v5LQ&dt?A^ZUaGzdZwGtVRIJfP8Q z{716d4!qmnd~|EEfOU1;?6@*_m5E22OSC|IO^asxiHyAIzNMMT9xL98q*`qZVjdun zlbX0Ye?i9JR}@zfC^yOxZz}*&wPJUsK++LNRe-b980f3wb%K~UlHcx+7%XM8*Zu1S z0+G0IKI{4<>2zA%j7;UO67$gq$p&q~usuKx)vcVV=q+(}mXqs1TAlUUKAmQk)nVbG z>dLD@)dd{e`44?hrwh_ONKa2c)tw_Dn(zxZTvEQ9GG=M)X0DmN*P0}L`0a&kOp|ks zPU0$h@=TCthX0H_?fHxV#vj>~E#01Z(>>OC`dR{e&`u-w+CPJM0$ymi`WcyJ!JT;` zXg7l>C;JXMP>)SZGU;LTGz369dc}2gbgXu9C9Ls4BMyZ4@tTYV0p{&yL5Rf6FS7j4 z=0jw*c&MK@*jTT^t#1W^c~OEgctmL%Ceqs0rfVG>94vI}7QRH_TN9vdZqwKbFWi8B zxGP_femH1|ezzFgpvciR;iyP;Xqkz7(#v16IoIHox>3R9qTZnHddH5isIUgaLZ99w zP5JmBbmI#)QQ_LqYuI_&uyZ)j1yxr10uLIjq2KHnrsChF!Zea~`_KO6q(GdCmXX}{ zO`H9A{Yi5?wA=&`ks1IY(97{&G|+WvH!F(_Eih=GLc+DsAK|(XH^b#x_T{bk6sO13 zAjkkum|h(3O*eng`S)=7Qt3_n!l^|rg*Lt&rSW&_A_XqxWZIiva>M> za)E;0l=!C5jvy|j-|@V8vb6M88BHyrUQtp`^NU~-kXI&4diz{cem^bEe*`6w(;Qmt z%DmfieEM5YHpeN}QBK68J#Ku#Jf8#cT@K>A>(P^_x(`{li>N?ayemoXIGX0y zne(9Qvc27TXMJ>gU4GyVIj6_#*U6daSPcK{^PW>%Oieab)o_hW2I=UQB7l}P#R|cV zF*;~Y+@pxLDKb!#p}giOsOY*mexPnGGKuXB-aE|DwTV>JH_YR9FAF>aK4EbxOs)r6$Cn3Ca0)P1@5ydMFn*m-81I-kqtcv`v-TX zSk+l%6gm*>q3;fQmd-k6#UZL=zvQk}hZreLzzocJfN9*zFk@P|AIyE1U}C|nO)BW) z??~MmAzSL7nH?V=-ytq%ZE1OTb$EC%KN4XVMQZu-yY{YSgxwj4t_<16UXg?3k9??<7ny(bR6-`+X)64TyU-eYBKw`ys` zw|eVv|B%Ds{ZRUw9)Y-uq~v?`|HGcDY&r+_>6I^~luP`DBG|t=P{TNk|R#&!7(fK*odZky`Wf!?5QM*S!cku+L|S@$3%?K4zZ} z0@~;|AN1e(oG)`g&g_#(UwU)s2fT(YaghQzS=gY*O)P0b47Rwa!ajmohKOby_!V+2 zFRDCca_4)sS1pHM2bn!yK;8%B{LdeOYIG@!e_n-+0qHsNpb=bOUk8>(KtSNxvuD6D z%gD%B7wd2Lmp!%643Y_Gt@!zjJfRfjJV@Kq9o841Tn0>WaGk7*3O@*w&vs-zn>aFf z?B`2OE1<`jghf$vW$a(%ygJlOmoDKG5v|V6ne?=^gsEa~?)VNA#4jPO0w(MJo0u2h zMFZ)V-e>h2e${yu$6qRF)LM1M(U6O}FyZ#4V%Q{l5@ygg3&0fz=;*zMs=s%-C(}W- z2RfOgEvBJ%x?q9Hmv3sP!LyIo5W-5I$|!|Q!mny^p}xp?Kv zOJ-TP&fxs0JbD3omXLD$Z3u#GDm9grSIxe^v|8P}k|X{2@#AM|NN{gE!_<&^YA>dq zdYqa1vi=)&_jdd5*D3Dt;$v^sV;J(%wi|ALw42Y5UzL!MNT!31yor<-Zf7^W-xN}7XT6r`hQ%iR8 zfh;k~VSetuNO6~MV=6{Y4I0I_H_nR(04bL8`E%oE2y>sj6K7!cPw{2;MSrDw3}F{B z!_qctDX3lM61tX@INRG7XsiP#Cv}L3jV%?b>Ej)6n?rPNuDs*YzU~w0rv8-iHlGgV zDLK_>=e_@!hvPeoIg$U?i*oD-6m}pP{m=YpOi(@Nj|{8b%Zm`>v=s!QWKSfx^|1ZU z^RCZN%0MNBzX>$XHM|5q^>(sy!sOMLkhLPrmj8?(Yy^Fy*=)sLm-UP26dg6 zJ4lm1-g|#;lJ4BOKE(0mb`?9?gJ>L(-A*JnE@8}XFB(Iv@UM9cOcnB&;g=p>L0qC~ zLX-UGl%L4&gKC(!G~qoO#I>Dbh989t7lI7OSC%yTkc&zp)ZtgI%zN@JBxUdpd@Y)iX7F=LJqTv<){@Rp}ZUw$bz!+Gbpr3}fYc zr*hdC(U&|Nf6nASc-aql%D zLge&v*VEI3(!r8MN7&k=+HTipj8+U8(GwjBC{c$&tc{I{xk>^e$|u_apmA?Su5GCW z?J2J^6Q>9g#&Qetv}Chsp&S@F=RdG@t`js zbfK*hoWQ{JBE65$R%D*ryi1?6BZ=;uvzR{1TMZ|Sxn0|1%mh*+#`cG;f(`&VMQW2_yH==wex8=Dh^)2lu`VV zr!4#zM)&tZ)&bi28=o5&eopxn5^sx#Kph0JB;MkyUm3e*ZUheEu8{S|Ww*urn1pqY zckf3i68-Z>*lqYNtnHXY7?7yoK$Fkcjt*{Qv)eqlV*UpH>fDU=k?L^G_kVTlMmc90 z7=AQH3OVXE^Zz(p7Ef5Ywv@q!&2h?lTe$zDZM{7MjLo0*i(gqp&~?zGgML(@*ufUi zv9)zh9V#&;1*(t5-G*dbdXJo)_-sDc?fznTZGGwYLk(H0-F9eVKtKQ(MobL7VclLd zh_R{uhi->k{69NTBY?0M z>&0Vlx8Lkx77EQC(GQXn6IOXLa@1CbkP;VO)n^;&|vzgA&hWpk8 zoVIea-^*U}$ad@5pMF>353TA`Twf+BGWKHbNekLbwW$=CkxF<_Fc z>F>EAsyn_6)8*lfbmg`tAdMUf0~e2}*`~m~Dzo>gQ>auxWZ?G#NK_6kE}4?|Pvqc! zC$Evl#)l0`qMj5ZgM(+4s-OE0Ufa9(icO@Dsng^_zB?n3hUM0LWH?w}g%{j~) zu{z(8;N0{_aCZ9F z>mz~v_Otwuph&p}+zqi#S({7tYelYuh>Vf-miT*QU!^#^^u8|XT~u)~g!N_dfJ^U) znc;$^>%Fjc!xyhb5z=GZM-epmWDYObOFK?{TsDanV4B!pK7|lAoqtIHN4;_2q9Dc; z^S6K8;Ifi-gGbM(EUsKLuftC6*yPU(x|aK0O_2+_tXa_Ma6#8b1XT9nzJ)ukzLJVX zc3FdEk0<8mS64gSmJs;h3R)ioKImGra4+n2-f~Sf{<+WB=;>pA>YaFg@`3Q#`-CSJ zmMBTa?yErgbEo54+d+K@oh9#go|9M=z>bZ>wH5Y!b9Mq zn;Y?h(lL$WB!Zx@Toaw=;TnS?xE2GhS$XTE^{W>oC&&86jV~d*=FoBw%de=cdeT(1 z_xRUNo_zQW$CFc4XZi4RR#DQxa+O+@+By|70@b&jysVE&)lH7R;>o>?^GdSyueanX zoT!(kmpmVsYDCGTCCl@K8@GSI?)ac#efc5zkWC5eJ^T9c+5UCIb*F5*jfq5P=u zFnlakkdu{F9_HUDBQ33w(+wBdjJyygEo*yg`Svos16Gc@qk}+r_jJIp)L-Cam`i1# z?E8ij4l17(cO}UCKywvb_rv7sbsF#f*$yt9_VEniU31aP#AO9r5PUVMk%k7R?g7DOMN<+r1Xf~ zNw|2-1p1{Ov#&u-4d_#DF0O=Bxc$xvnsJf@KTxradmct|NVq2LGE^&11VC*|MM`RD z+0N4Yn^(A3uaWn**SWz7t;>;=1b`$kn0)UI`vPvE`4V$39Hs}MV<^Qw`@uy=G^xY2 zH~m8^POkz!U>vfDWz08J25)FRAl9upKR2_on$Gu}U$PwD?VX zS)2KcA!cUxdf`SfNV@==dK{dGfr9UMLapO!S_T4N-#Km}>de0ad5#BvH-J4A=-jKs z0Tsb(;d4#i_C%-uy^hWuyEi*zDc#coc1!U_T(#FcRa=^xB;gVc!}?&J)X2yu78b20ml0(z z)jcPr3+|?L0%{nf zI^&4`pbHK1Q$M&GBmC>*hhl>=iLzYW+@gZ2($eN2zsmS3&c}fw&wH~A-oB-}T^=;o zGqbZi`ZqVGCnxb<+**ZtE;P3QZpnN%neP>zj{Y3`T+n3T3-B@DDk|7i3&-YdELegp zDT=<0m;tRODys_@*1=_yDJk^`V|=Ic!wk)Pt`yZ+&;;E*{FVrE=Z8Cf9qC;Y+$UL| zqpvBw_ga?WpnRond?BsKx3k;LJSROI8qBe<*i^T$S%4czhZ{%0%K_jAGrOxoruJ~+ zj?6a9lYulvHc38G=KB!T?wjhxB<;tWV>>%P!=;F06>y8*i3j&D?!cvuGEgQ^7T8(S zcrP~v_jxb?WqcmE^k?@TQs$*ht}z7@KwX@9C(bkcy@Sl9?3OVufp7_XJ`N73b1U~& zoTuMf8}>FX+0Op{%r$xZ@ZtY-W8uUyd_p_6JPA|!+=m=)XtR`ntgOzXy( zh$4R}RlZ4+t5Un%P}l@x74YQ%N37ahhXB!ZOzB&M zr*enomS3G)5!~#^n+2p9-EFU)Vn@DWoQwz29b-<9c&wg8Lm3|GZLxum*@HfFsYs(d z6Xlq|r>!Iv2GIT93Oj!b7apo#n<1N>Gq^X2do3o*>!abjaG@rN;5kI(3QhZK(o*9L z_&?d=iuQhw17thpah>W*K+w0Gj-FsE1j18%-VvyRJMoYY-+(AFuCt z-|zk2_jh@IzvoFqFVM5=o9@eGg*@k&&Vy|R&<+Z-OUy>03QTs{a({7B@9;lQn=^9u zw-&ed+)UxG?o6MD%`4*bpL7J(Cf0IGbk_`&#H^f4fxV9^53L0uLhXQhWIRxSWi z(!X*PeT!6tC^a<^AtBBS&sN}Ilxd4{7kzb@!AMG|6$+bPf^!ng!_kK*Zpxr-*pU9* z8Axunhu=nRwX*H`Z1otBpv{boww)bd6kI_A>D!I~f3auHkvB+SdVX%cnwRGXt-h)? zQYzid!)RA)BC7>Q9PQx-!&`T{SBI9(xoXa7)Ed7Y!xGf8W2HK-($-U1Ftieb6=5t%K0Se3cIS5uCOsjHfIr4e|4d} zTaagdsi+8fB?8)^jr*7;ds18UYFw?FO>jw-rOPo&m-E6Spj&}YU7IjFNl0m>MGkthf8n*amw zLzrq6p3Bp;QL^mR*xx!B>eXqI&%^DjJik&&8IGRx^`9D7M2uu9XPq#IVcn}dL(3Y)|}e;w_nd=Z>I>#?Gz|)D|$0 zB@)TBW9tFdTMt}&b&tLe5;N|axD(U$zj zZ;qg(0r3ZZ(4N4>KvWUW0?`bnW+~k>H<<9V%^(CjIfYht;*#8_#Ip)o_EV`;lr!?A z$YNKoT9uHLR9_-!_lxUZrR)1%x4SwZFwn@@_!pL`=e6HzYscU+pl{^u?@#DGjYirk zmlvJk(zhw*SUV_W_u#jfh9P5$Q8bZoI?Cyp8|ic@p?Z{z-oN8VJro-1G1`S-fWcrG zO1@^IJo^|-1XMCmO@7U@shUp&0Nvb5ur(~uylrFS0Xmbb>)!OE#UA+!d~aGc?w`30 z=|GAZ?eCssm{6h`8w3=vN%_s#{w`H(GU?o;6qCg^Jf@plA>EtJUcasgUjcNQz#s$? zm8celoq@V*3B_zH2fKj#@b*VvUthTWxCTk1-^mRI=X0*58qSNL%qk2wVZ~EEBfqWu zS(M1D_QfD?=+M>$*36P|BQqlvQ5isf5IJBnFXz&+@h8n#pt3eIprdC;TCp4(^8 zzAUL=KL~t%&UWm5YpK`np)ziU&*_;@4WaJxd}W=x>Ks`J@3}-#N+IBO`7V^CmYvyR zskQ5VFT%cv8 zrL}c+(WumSf3_?StA?(s)paN;?kHe1XxTF<6bh2rmR|!O^yS8ybXrQ)?Ma-Eh`hZo zG6PVY10&f1=l}nf3OED$(RRiP$4!-N2Z{v3k7kb_uiHPtb_F<5+Gxlpa$|)fhZbs% zzuf2SCK4qn48fHq4auZeTFo7pE_usKdkO4Z4P~40+xT%v##LR=Xw?x(F_UpsxBK|` z(2dk-WXA9xdosC+`Sg0&O=Z2RzhY_Rq^%A*={_n0rfjl>;UpG4!Ol%m8ykOkg2^Rw q(+}M-yUZ6Qhevl2v)kJ-z87s|AO9ESlZw;; literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_circ_auxiliary.uxf b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_circ_auxiliary.uxf new file mode 100644 index 0000000000..a1f7b6b415 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_circ_auxiliary.uxf @@ -0,0 +1,133 @@ + + 10 + + UMLClass + + 40 + 100 + 380 + 70 + + CartesianPathConstraintsBuilder +-- ++ to PathConstraints() : moveit_msgs::Constraints + + + + UMLClass + + 410 + 430 + 210 + 40 + + CartesianCenter + + + + UMLClass + + 460 + 90 + 470 + 80 + + template=ConfigType> +CircAuxiliary +{abstract} +-- ++ toPathConstraints(): moveit_msgs::Constraints + + + + UMLClass + + 470 + 280 + 230 + 50 + + template=ConfigType, Builder> +Center + + + + UMLClass + + 730 + 280 + 220 + 50 + + template=ConfigType, Builder> +Interim + + + + Relation + + 730 + 160 + 30 + 150 + + lt=<<. + 10.0;10.0;10.0;130.0 + + + Relation + + 470 + 160 + 40 + 150 + + lt=<<. + 20.0;10.0;17.0;130.0 + + + Relation + + 490 + 320 + 340 + 130 + + lt=<<. +<<bind>> +<ConfigType->CartesianConfiguration> +<Builder->CartesianPathConstraintsBuilder> + 10.0;10.0;10.0;110.0 + + + UMLClass + + 710 + 510 + 210 + 40 + + CartesianInterim + + + + Relation + + 800 + 320 + 340 + 210 + + lt=<<. + + + + + + +<<bind>> +<ConfigType->CartesianConfiguration> +<Builder->CartesianPathConstraintsBuilder> + 10.0;10.0;10.0;190.0 + + diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_commands.png b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_commands.png new file mode 100644 index 0000000000000000000000000000000000000000..74900cf3381f2af13a6d3064c368752c7be8c92f GIT binary patch literal 9020 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 literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_commands.uxf b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_commands.uxf new file mode 100644 index 0000000000..1c57939fb2 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_commands.uxf @@ -0,0 +1,175 @@ + + 10 + + UMLClass + + 530 + 370 + 560 + 150 + + template=StartType, GoalType +BaseCommand +{abstract} +-- ++ setStartConfiguration(...) ++ getStartConfiguration(...) : StartType + ++ setGoalConfiguration(...) ++ getGoalConfiguration(...) : GoalType + + + + + UMLClass + + 910 + 560 + 230 + 70 + + template=StartType, GoalType +Ptp + + + + Relation + + 970 + 510 + 30 + 80 + + lt=<<- + 10.0;10.0;10.0;60.0 + + + Relation + + 710 + 510 + 30 + 80 + + lt=<<- + 10.0;10.0;10.0;60.0 + + + UMLClass + + 650 + 560 + 230 + 70 + + template=StartType, GoalType +Lin + + + + UMLClass + + 530 + 670 + 300 + 70 + + template=StartType, AuxiliaryType, GoalType +Circ + + + + Relation + + 540 + 510 + 30 + 190 + + lt=<<- + 10.0;10.0;10.0;170.0 + + + UMLClass + + 50 + 200 + 400 + 150 + + Sequence +-- ++ add(cmd : MotionCmdUPtr) ++ setAllBlendRadiiToZero() ++ getBlendRadius(index: int) ++ getCmd() : MotionCmd& + ++ toRequest() : moveit_msgs::MotionSequenceRequest + + + + UMLClass + + 590 + 200 + 390 + 120 + + MotionCmd +{abstract} +-- ++ setPlanningGroup(...) ++ setTargetLink(...) ++ setVelocityScale(...) ++ setAccelerationScale(...) + + + + Relation + + 750 + 310 + 30 + 90 + + lt=<<- + 10.0;10.0;10.0;70.0 + + + UMLClass + + 640 + 80 + 260 + 60 + + MPReqConvertible +{abstract} +-- +/+ toRequest(): MotionPlanRequest/ + + + + Relation + + 750 + 130 + 30 + 90 + + lt=<<- + 10.0;10.0;10.0;70.0 + + + Relation + + 440 + 280 + 170 + 40 + + lt=<<<<- +m2=* + 10.0;10.0;150.0;10.0 + + diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_robot_configurations.png b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_robot_configurations.png new file mode 100644 index 0000000000000000000000000000000000000000..4ad0c01e3523c400f9530a60ca11a348ae9e1118 GIT binary patch literal 18548 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 Nh{!(9d-&|-{{wHqcDw)p literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_robot_configurations.uxf b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_robot_configurations.uxf new file mode 100644 index 0000000000..a6d1c2b94b --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_robot_configurations.uxf @@ -0,0 +1,133 @@ + + 10 + + UMLClass + + 330 + 210 + 280 + 70 + + RobotConfiguration +-- ++ setRobotModel() ++ setGroupName() + + + + UMLClass + + 220 + 340 + 170 + 30 + + JointConfiguration + + + + UMLClass + + 530 + 340 + 170 + 30 + + CartesianConfiguration + + + + Relation + + 310 + 270 + 110 + 90 + + lt=<<- + 90.0;10.0;10.0;70.0 + + + Relation + + 480 + 270 + 140 + 90 + + lt=<<- + 10.0;10.0;120.0;70.0 + + + UMLNote + + 700 + 200 + 210 + 40 + + Defines a configuration of the robot in space + + + + Relation + + 600 + 210 + 120 + 30 + + lt=.. + 10.0;10.0;100.0;10.0 + + + UMLClass + + 20 + 20 + 450 + 80 + + RobotStateMsgConvertible +{abstract} +-- +/+ toMoveitMsgRobotState() : moveit_msgs::RobotState / + + + + UMLClass + + 490 + 20 + 400 + 80 + + GoalConstraintMsgConvertible +{abstract} +-- +/+ toGoalConstraints() : moveit_msgs::Constraints / + + + + Relation + + 470 + 90 + 150 + 140 + + lt=<<- + 130.0;10.0;10.0;120.0 + + + Relation + + 270 + 90 + 160 + 140 + + lt=<<- + 10.0;10.0;140.0;120.0 + + diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_seq_testdataloader_usage.png b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_seq_testdataloader_usage.png new file mode 100644 index 0000000000000000000000000000000000000000..4659b8be23fc5302521d82bb079472defb31fd10 GIT binary patch literal 16098 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 A{Qv*} literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_seq_testdataloader_usage.uxf b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_seq_testdataloader_usage.uxf new file mode 100644 index 0000000000..9707b26ea5 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_seq_testdataloader_usage.uxf @@ -0,0 +1,215 @@ + + // Uncomment the following line to change the fontsize and font: +fontsize=10 +// fontfamily=SansSerif //possible: SansSerif,Serif,Monospaced + + +////////////////////////////////////////////////////////////////////////////////////////////// +// Welcome to UMLet! +// +// Double-click on elements to add them to the diagram, or to copy them +// Edit elements by modifying the text in this panel +// Hold Ctrl to select multiple elements +// Use Ctrl+mouse to select via lasso +// +// Use +/- or Ctrl+mouse wheel to zoom +// Drag a whole relation at its central square icon +// +// Press Ctrl+C to copy the whole diagram to the system clipboard (then just paste it to, eg, Word) +// Edit the files in the "palettes" directory to create your own element palettes +// +// Select "Custom Elements > New..." to create new element types +////////////////////////////////////////////////////////////////////////////////////////////// + + +// This text will be stored with each diagram; use it for notes. + 12 + + UMLGeneric + + 252 + 96 + 168 + 36 + + _:ExampleTestClass_ + + + + Relation + + 324 + 120 + 36 + 408 + + lt=. +layer=-10 + 10.0;10.0;10.0;320.0 + + + UMLGeneric + + 708 + 96 + 144 + 36 + + _:TestDataLoader_ + + + + Relation + + 768 + 120 + 36 + 396 + + lt=. +layer=-10 + 10.0;10.0;10.0;310.0 + + + UMLGeneric + + 324 + 156 + 24 + 312 + + layer=10 +transparency=0 + + + + UMLSpecialState + + 132 + 144 + 24 + 24 + + type=initial + + + + Relation + + 144 + 132 + 204 + 48 + + lt=<- +myAwesomeTest() + 150.0;20.0;10.0;20.0 + + + UMLGeneric + + 768 + 204 + 24 + 84 + + layer=10 +transparency=0 + + + + Relation + + 336 + 180 + 456 + 48 + + lt=<- +getPtpCart() : PtpCart + 360.0;20.0;10.0;20.0 + + + UMLGeneric + + 612 + 360 + 24 + 24 + + layer=10 +transparency=0 + + + + Relation + + 348 + 336 + 288 + 48 + + lt=<- +toRequest() : +moveit_msgs::MotionPlanRequest + 220.0;20.0;10.0;20.0 + + + UMLGeneric + + 576 + 252 + 96 + 36 + + _:PtpCart_ + + + + Relation + + 612 + 276 + 36 + 216 + + lt=. + 10.0;10.0;10.0;160.0 + + + Relation + + 660 + 252 + 132 + 36 + + lt=<- + 10.0;10.0;90.0;10.0 + + + UMLGeneric + + 336 + 324 + 24 + 96 + + layer=100 +transparency=0 + + + + + Relation + + 336 + 276 + 204 + 72 + + lt=<- +doAwesomeThings() + 20.0;40.0;50.0;40.0;50.0;10.0;10.0;10.0 + + diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/async_test.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/async_test.h new file mode 100644 index 0000000000..4b408e2bd8 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/async_test.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2018 Pilz GmbH & Co. KG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ASYNC_TEST_H +#define ASYNC_TEST_H + +#include +#include +#include +#include +#include + +#include + +#include + +namespace testing +{ +/** + * @brief Test class that allows the handling of asynchronous test objects + * + * The class provides the two basic functions AsyncTest::barricade and AsyncTest::triggerClearEvent. + * During the test setup gates between the steps with one or more clear events. Allow passing on by calling + * triggerClearEvent after a test. + * + * \e Usage:
    + * Suppose you want to test a function that calls another function asynchronously, like the following example: + * + * \code + * void asyncCall(std::function fun) + * { + * std::thread t(fun); + * t.detach(); + * } + * \endcode + * + * You expect that fun gets called, so your test thread has to wait for the completion, else it would fail. This can be + * achieved via: + * + * \code + * class MyTest : public testing::Test, public testing::AsyncTest + * { + * public: + * MOCK_METHOD0(myMethod, void()); + * }; + * + * TEST_F(MyTest, testCase) + * { + * EXPECT_CALL(*this, myMethod()).Times(1).WillOnce(ACTION_OPEN_BARRIER_VOID("myMethod")); + * const int timeout_ms {100}; + * asyncCall(std::bind(&MyTest::myMethod, this)); + * BARRIER("myMethod", timeout_ms) << "Timed-out waiting for myMethod call."; + * } + * \endcode + */ +class AsyncTest +{ +public: + /** + * @brief Triggeres a clear event. If a call to barricade is currently pending it will unblock as soon as all clear + * events are triggered. Else the event is put on the waitlist. This waitlist is emptied upon a call to barricade. + * + * @param event The event that is triggered + */ + void triggerClearEvent(const std::string& event); + + /** + * @brief Will block until the event given by clear_event is triggered or a timeout is reached. + * Unblocks immediately, if the event was on the waitlist. + * + * @param clear_event Event that allows the test to pass on + * @param timeout_ms Timeout [ms] (optional). + * @return True if the event was triggered, false otherwise. + */ + bool barricade(const std::string& clear_event, const int timeout_ms = -1); + + /** + * @brief Will block until all events given by clear_events are triggered or a timeout is reached. + * Events on the waitlist are taken into account, too. + * + * @param clear_events List of events that allow the test to pass on + * @param timeout_ms Timeout [ms] (optional). + * @return True if all events were triggered, false otherwise. + */ + bool barricade(std::initializer_list clear_events, const int timeout_ms = -1); + +protected: + std::mutex m_; + std::condition_variable cv_; + std::set clear_events_{}; + std::set waitlist_{}; +}; + +// for better readability in tests +#define BARRIER(...) EXPECT_TRUE(barricade(__VA_ARGS__)) +#define BARRIER_FATAL(...) ASSERT_TRUE(barricade(__VA_ARGS__)) + +#define ACTION_OPEN_BARRIER(str) \ + ::testing::InvokeWithoutArgs([this](void) { \ + this->triggerClearEvent(str); \ + return true; \ + }) +#define ACTION_OPEN_BARRIER_VOID(str) ::testing::InvokeWithoutArgs([this](void) { this->triggerClearEvent(str); }) + +inline void AsyncTest::triggerClearEvent(const std::string& event) +{ + std::lock_guard lk(m_); + + if (clear_events_.empty()) + { + ROS_DEBUG_NAMED("Test", "Clearing Barricade[%s]", event.c_str()); + waitlist_.insert(event); + } + else if (clear_events_.erase(event) < 1) + { + ROS_WARN_STREAM("Triggered event " << event << " despite not waiting for it."); + } + cv_.notify_one(); +} + +inline bool AsyncTest::barricade(const std::string& clear_event, const int timeout_ms) +{ + return barricade({ clear_event }, timeout_ms); +} + +inline bool AsyncTest::barricade(std::initializer_list clear_events, const int timeout_ms) +{ + std::unique_lock lk(m_); + + std::stringstream events_stringstream; + for (const auto& event : clear_events) + { + events_stringstream << event << ", "; + } + ROS_DEBUG_NAMED("Test", "Adding Barricade[%s]", events_stringstream.str().c_str()); + + std::copy_if(clear_events.begin(), clear_events.end(), std::inserter(clear_events_, clear_events_.end()), + [this](std::string event) { return this->waitlist_.count(event) == 0; }); + waitlist_.clear(); + + auto end_time_point = std::chrono::system_clock::now() + std::chrono::milliseconds(timeout_ms); + + while (!clear_events_.empty()) + { + if (timeout_ms < 0) + { + cv_.wait(lk); + } + else + { + std::cv_status status = cv_.wait_for(lk, end_time_point - std::chrono::system_clock::now()); + if (status == std::cv_status::timeout) + { + return clear_events_.empty(); + } + } + } + return true; +} + +} // namespace testing + +#endif // ASYNC_TEST_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/basecmd.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/basecmd.h new file mode 100644 index 0000000000..8b1e0382ea --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/basecmd.h @@ -0,0 +1,128 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef BASECMD_H +#define BASECMD_H + +#include + +#include "motioncmd.h" + +namespace pilz_industrial_motion_planner_testutils +{ +template +class BaseCmd : public MotionCmd +{ +public: + BaseCmd() : MotionCmd() + { + } + + virtual ~BaseCmd() = default; + +public: + planning_interface::MotionPlanRequest toRequest() const override; + + void setStartConfiguration(StartType start); + void setGoalConfiguration(GoalType goal); + + StartType& getStartConfiguration(); + const StartType& getStartConfiguration() const; + + GoalType& getGoalConfiguration(); + const GoalType& getGoalConfiguration() const; + +private: + virtual std::string getPlannerId() const = 0; + +protected: + GoalType goal_; + StartType start_; +}; + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +template +inline void BaseCmd::setStartConfiguration(StartType start) +{ + start_ = start; +} + +template +inline void BaseCmd::setGoalConfiguration(GoalType goal) +{ + goal_ = goal; +} + +template +inline StartType& BaseCmd::getStartConfiguration() +{ + return start_; +} + +template +inline const StartType& BaseCmd::getStartConfiguration() const +{ + return start_; +} + +template +inline GoalType& BaseCmd::getGoalConfiguration() +{ + return goal_; +} + +template +inline const GoalType& BaseCmd::getGoalConfiguration() const +{ + return goal_; +} + +template +planning_interface::MotionPlanRequest BaseCmd::toRequest() const +{ + planning_interface::MotionPlanRequest req; + req.planner_id = getPlannerId(); + req.group_name = this->planning_group_; + + req.max_velocity_scaling_factor = this->vel_scale_; + req.max_acceleration_scaling_factor = this->acc_scale_; + + req.start_state = this->start_.toMoveitMsgsRobotState(); + req.goal_constraints.push_back(this->goal_.toGoalConstraints()); + + return req; +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // BASECMD_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/cartesianconfiguration.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/cartesianconfiguration.h new file mode 100644 index 0000000000..b1c9dbeb53 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/cartesianconfiguration.h @@ -0,0 +1,188 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef CARTESIANCONFIGURATION_H +#define CARTESIANCONFIGURATION_H + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "robotconfiguration.h" +#include "jointconfiguration.h" + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Class to define a robot configuration in space + * with the help of cartesian coordinates. + */ +class CartesianConfiguration : public RobotConfiguration +{ +public: + CartesianConfiguration(); + + CartesianConfiguration(const std::string& group_name, const std::string& link_name, const std::vector& config); + + CartesianConfiguration(const std::string& group_name, const std::string& link_name, const std::vector& config, + const moveit::core::RobotModelConstPtr& robot_model); + +public: + moveit_msgs::Constraints toGoalConstraints() const override; + moveit_msgs::RobotState toMoveitMsgsRobotState() const override; + + void setLinkName(const std::string& link_name); + const std::string& getLinkName() const; + + void setPose(const geometry_msgs::Pose& pose); + const geometry_msgs::Pose& getPose() const; + geometry_msgs::Pose& getPose(); + + void setSeed(const JointConfiguration& config); + const JointConfiguration& getSeed() const; + //! @brief States if a seed for the cartesian configuration is set. + bool hasSeed() const; + + void setPoseTolerance(const double tol); + const boost::optional getPoseTolerance() const; + + void setAngleTolerance(const double tol); + const boost::optional getAngleTolerance() const; + +private: + static geometry_msgs::Pose toPose(const std::vector& pose); + static geometry_msgs::PoseStamped toStampedPose(const geometry_msgs::Pose& pose); + +private: + std::string link_name_; + geometry_msgs::Pose pose_; + + //! @brief The dimensions of the sphere associated with the target region + //! of the position constraint. + boost::optional tolerance_pose_{ boost::none }; + + //! @brief The value to assign to the absolute tolerances of the + //! orientation constraint. + boost::optional tolerance_angle_{ boost::none }; + + //! @brief The seed for computing the IK solution of the cartesian configuration. + boost::optional seed_{ boost::none }; +}; + +std::ostream& operator<<(std::ostream& /*os*/, const CartesianConfiguration& /*obj*/); + +inline void CartesianConfiguration::setLinkName(const std::string& link_name) +{ + link_name_ = link_name; +} + +inline const std::string& CartesianConfiguration::getLinkName() const +{ + return link_name_; +} + +inline void CartesianConfiguration::setPose(const geometry_msgs::Pose& pose) +{ + pose_ = pose; +} + +inline const geometry_msgs::Pose& CartesianConfiguration::getPose() const +{ + return pose_; +} + +inline geometry_msgs::Pose& CartesianConfiguration::getPose() +{ + return pose_; +} + +inline moveit_msgs::Constraints CartesianConfiguration::toGoalConstraints() const +{ + if (!tolerance_pose_ || !tolerance_angle_) + { + return kinematic_constraints::constructGoalConstraints(link_name_, toStampedPose(pose_)); + } + else + { + return kinematic_constraints::constructGoalConstraints(link_name_, toStampedPose(pose_), tolerance_pose_.value(), + tolerance_angle_.value()); + } +} + +inline void CartesianConfiguration::setSeed(const JointConfiguration& config) +{ + seed_ = config; +} + +inline const JointConfiguration& CartesianConfiguration::getSeed() const +{ + return seed_.value(); +} + +inline bool CartesianConfiguration::hasSeed() const +{ + return seed_.is_initialized(); +} + +inline void CartesianConfiguration::setPoseTolerance(const double tol) +{ + tolerance_pose_ = tol; +} + +inline const boost::optional CartesianConfiguration::getPoseTolerance() const +{ + return tolerance_pose_; +} + +inline void CartesianConfiguration::setAngleTolerance(const double tol) +{ + tolerance_angle_ = tol; +} + +inline const boost::optional CartesianConfiguration::getAngleTolerance() const +{ + return tolerance_angle_; +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // CARTESIANCONFIGURATION_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/cartesianpathconstraintsbuilder.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/cartesianpathconstraintsbuilder.h new file mode 100644 index 0000000000..c30ce98360 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/cartesianpathconstraintsbuilder.h @@ -0,0 +1,90 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef CARTESIANPATHCONSTRAINTSBUILDER_H +#define CARTESIANPATHCONSTRAINTSBUILDER_H + +#include + +#include + +#include "cartesianconfiguration.h" + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Helper class to build moveit_msgs::Constraints from a + * given configuration. + */ +class CartesianPathConstraintsBuilder +{ +public: + CartesianPathConstraintsBuilder& setConstraintName(const std::string& constraint_name); + CartesianPathConstraintsBuilder& setConfiguration(const CartesianConfiguration& configuration); + + moveit_msgs::Constraints toPathConstraints() const; + +private: + std::string constraint_name_; + CartesianConfiguration configuration_; +}; + +inline CartesianPathConstraintsBuilder& +CartesianPathConstraintsBuilder::setConstraintName(const std::string& constraint_name) +{ + constraint_name_ = constraint_name; + return *this; +} + +inline CartesianPathConstraintsBuilder& +CartesianPathConstraintsBuilder::setConfiguration(const CartesianConfiguration& configuration) +{ + configuration_ = configuration; + return *this; +} + +inline moveit_msgs::Constraints CartesianPathConstraintsBuilder::toPathConstraints() const +{ + moveit_msgs::PositionConstraint pos_constraint; + pos_constraint.link_name = configuration_.getLinkName(); + pos_constraint.constraint_region.primitive_poses.push_back(configuration_.getPose()); + + moveit_msgs::Constraints path_constraints; + path_constraints.name = constraint_name_; + path_constraints.position_constraints.push_back(pos_constraint); + return path_constraints; +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // CARTESIANPATHCONSTRAINTSBUILDER_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/center.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/center.h new file mode 100644 index 0000000000..3e7d7f8a55 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/center.h @@ -0,0 +1,60 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef CENTERAUXILIARY_H +#define CENTERAUXILIARY_H + +#include "circauxiliary.h" + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Class to define the center point of the circle + * on which the robot is supposed to move via circ command. + */ +template +class Center : public CircAuxiliary +{ +private: + std::string getConstraintName() const override; +}; + +template +std::string Center::getConstraintName() const +{ + return "center"; +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // CENTERAUXILIARY_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/checks.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/checks.h new file mode 100644 index 0000000000..e9519f2071 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/checks.h @@ -0,0 +1,62 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef CHECKS_H +#define CHECKS_H + +#include +#include + +namespace pilz_industrial_motion_planner_testutils +{ +::testing::AssertionResult isAtExpectedPosition(const robot_state::RobotState& expected, + const robot_state::RobotState& actual, const double epsilon, + const std::string& group_name = "") +{ + if (group_name.empty() && expected.distance(actual) <= epsilon) + { + return ::testing::AssertionSuccess(); + } + else if (!group_name.empty() && expected.distance(actual, actual.getJointModelGroup(group_name)) <= epsilon) + { + return ::testing::AssertionSuccess(); + } + std::stringstream msg; + msg << " expected: " << expected << " actual: " << actual; + + return ::testing::AssertionFailure() << msg.str(); +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // CENTERAUXILIARY_H \ No newline at end of file diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/circ.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/circ.h new file mode 100644 index 0000000000..1888cfbffb --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/circ.h @@ -0,0 +1,106 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef CIRC_H +#define CIRC_H + +#include + +#include "basecmd.h" +#include "circauxiliary.h" + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Data class storing all information regarding a Circ command. + */ +template +class Circ : public BaseCmd +{ +public: + Circ() : BaseCmd() + { + } + +public: + void setAuxiliaryConfiguration(AuxiliaryType auxiliary); + AuxiliaryType& getAuxiliaryConfiguration(); + const AuxiliaryType& getAuxiliaryConfiguration() const; + +public: + planning_interface::MotionPlanRequest toRequest() const override; + +private: + std::string getPlannerId() const override; + +private: + AuxiliaryType auxiliary_; +}; + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +template +inline void Circ::setAuxiliaryConfiguration(AuxiliaryType auxiliary) +{ + auxiliary_ = auxiliary; +} + +template +inline std::string Circ::getPlannerId() const +{ + return "CIRC"; +} + +template +inline planning_interface::MotionPlanRequest Circ::toRequest() const +{ + planning_interface::MotionPlanRequest req{ BaseCmd::toRequest() }; + req.path_constraints = auxiliary_.toPathConstraints(); + + return req; +} + +template +inline AuxiliaryType& Circ::getAuxiliaryConfiguration() +{ + return auxiliary_; +} + +template +inline const AuxiliaryType& Circ::getAuxiliaryConfiguration() const +{ + return auxiliary_; +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // CIRC_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/circ_auxiliary_types.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/circ_auxiliary_types.h new file mode 100644 index 0000000000..3fbe7b7b7d --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/circ_auxiliary_types.h @@ -0,0 +1,49 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef CIRC_AUXILIARY_TYPES_H +#define CIRC_AUXILIARY_TYPES_H + +#include "center.h" +#include "interim.h" +#include "cartesianconfiguration.h" +#include "cartesianpathconstraintsbuilder.h" + +namespace pilz_industrial_motion_planner_testutils +{ +using CartesianCenter = Center; +using CartesianInterim = Interim; +} // namespace pilz_industrial_motion_planner_testutils + +#endif // CIRC_AUXILIARY_TYPES_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/circauxiliary.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/circauxiliary.h new file mode 100644 index 0000000000..81958f9b67 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/circauxiliary.h @@ -0,0 +1,91 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef CIRCAUXILIARY_H +#define CIRCAUXILIARY_H + +#include + +#include + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Base class to define an auxiliary point needed to specify + * circ commands. + */ +template +class CircAuxiliary +{ +public: + void setConfiguration(const ConfigType& auxiliary_config); + ConfigType& getConfiguration(); + const ConfigType& getConfiguration() const; + +public: + moveit_msgs::Constraints toPathConstraints() const; + +private: + virtual std::string getConstraintName() const = 0; + +protected: + ConfigType auxiliary_config_; +}; + +template +void CircAuxiliary::setConfiguration(const ConfigType& auxiliary_config) +{ + auxiliary_config_ = auxiliary_config; +} + +template +inline ConfigType& CircAuxiliary::getConfiguration() +{ + return auxiliary_config_; +} + +template +inline const ConfigType& CircAuxiliary::getConfiguration() const +{ + return auxiliary_config_; +} + +template +inline moveit_msgs::Constraints CircAuxiliary::toPathConstraints() const +{ + return BuilderType().setConstraintName(getConstraintName()).setConfiguration(getConfiguration()).toPathConstraints(); +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // CIRCAUXILIARY_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/command_types_typedef.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/command_types_typedef.h new file mode 100644 index 0000000000..6bd4356637 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/command_types_typedef.h @@ -0,0 +1,69 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef COMMAND_TYPES_TYPEDEF_H +#define COMMAND_TYPES_TYPEDEF_H + +#include + +#include "ptp.h" +#include "lin.h" +#include "circ.h" +#include "gripper.h" +#include "jointconfiguration.h" +#include "cartesianconfiguration.h" +#include "circ_auxiliary_types.h" + +namespace pilz_industrial_motion_planner_testutils +{ +typedef Ptp PtpJoint; +typedef Ptp PtpJointCart; +typedef Ptp PtpCart; + +typedef Lin LinJoint; +typedef Lin LinJointCart; +typedef Lin LinCart; + +typedef Circ CircCenterCart; +typedef Circ CircInterimCart; + +typedef Circ CircJointCenterCart; +typedef Circ CircJointInterimCart; + +typedef boost::variant + CmdVariant; +} // namespace pilz_industrial_motion_planner_testutils + +#endif // COMMAND_TYPES_TYPEDEF_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/default_values.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/default_values.h new file mode 100644 index 0000000000..ddded20bf3 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/default_values.h @@ -0,0 +1,51 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef DEFAULT_VALUES_H +#define DEFAULT_VALUES_H + +/* + * @brief This file contains all default values needed for testing. + */ +namespace pilz_industrial_motion_planner_testutils +{ +static constexpr double DEFAULT_VEL{ 0.01 }; +static constexpr double DEFAULT_ACC{ 0.01 }; +static constexpr double DEFAULT_BLEND_RADIUS{ 0.01 }; + +static constexpr double DEFAULT_VEL_GRIPPER{ 0.5 }; +static constexpr double DEFAULT_ACC_GRIPPER{ 0.8 }; +} // namespace pilz_industrial_motion_planner_testutils + +#endif // DEFAULT_VALUES_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/exception_types.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/exception_types.h new file mode 100644 index 0000000000..dec173bbc1 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/exception_types.h @@ -0,0 +1,52 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef EXCEPTION_TYPES_H +#define EXCEPTION_TYPES_H + +#include +#include + +namespace pilz_industrial_motion_planner_testutils +{ +class TestDataLoaderReadingException : public std::runtime_error +{ +public: + TestDataLoaderReadingException(const std::string& error_desc) : std::runtime_error(error_desc) + { + } +}; +} // namespace pilz_industrial_motion_planner_testutils + +#endif // EXCEPTION_TYPES_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/goalconstraintsmsgconvertible.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/goalconstraintsmsgconvertible.h new file mode 100644 index 0000000000..1595570449 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/goalconstraintsmsgconvertible.h @@ -0,0 +1,56 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef GOALCONSTRAINTSMSGCONVERTIBLE_H +#define GOALCONSTRAINTSMSGCONVERTIBLE_H + +#include + +#include +#include + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Interface class to express that a derived class can be converted + * into a moveit_msgs::Constaints. + */ +class GoalConstraintMsgConvertible +{ +public: + virtual moveit_msgs::Constraints toGoalConstraints() const = 0; +}; +} // namespace pilz_industrial_motion_planner_testutils + +#endif // GOALCONSTRAINTSMSGCONVERTIBLE_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/gripper.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/gripper.h new file mode 100644 index 0000000000..b3d0f2fd5a --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/gripper.h @@ -0,0 +1,48 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef GRIPPER_H +#define GRIPPER_H + +#include "ptp.h" +#include "jointconfiguration.h" + +namespace pilz_industrial_motion_planner_testutils +{ +class Gripper : public Ptp +{ +}; +} // namespace pilz_industrial_motion_planner_testutils + +#endif // GRIPPER_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/interim.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/interim.h new file mode 100644 index 0000000000..d6822ab43a --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/interim.h @@ -0,0 +1,60 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef INTERIMAXILIARY_H +#define INTERIMAXILIARY_H + +#include "circauxiliary.h" + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Class to define a point on the circle on which the robot is supposed + * to move via circ command. + */ +template +class Interim : public CircAuxiliary +{ +private: + std::string getConstraintName() const override; +}; + +template +std::string Interim::getConstraintName() const +{ + return "interim"; +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // INTERIMAXILIARY_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/jointconfiguration.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/jointconfiguration.h new file mode 100644 index 0000000000..b133d568c2 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/jointconfiguration.h @@ -0,0 +1,145 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef JOINTCONFIGURATION_H +#define JOINTCONFIGURATION_H + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "robotconfiguration.h" + +namespace pilz_industrial_motion_planner_testutils +{ +class JointConfigurationException : public std::runtime_error +{ +public: + JointConfigurationException(const std::string& error_desc) : std::runtime_error(error_desc) + { + } +}; + +using CreateJointNameFunc = std::function; + +/** + * @brief Class to define a robot configuration in space with the help + * of joint values. + */ +class JointConfiguration : public RobotConfiguration +{ +public: + JointConfiguration(); + + JointConfiguration(const std::string& group_name, const std::vector& config, + CreateJointNameFunc&& create_joint_name_func); + + JointConfiguration(const std::string& group_name, const std::vector& config, + const moveit::core::RobotModelConstPtr& robot_model); + +public: + void setJoint(const size_t index, const double value); + double getJoint(const size_t index) const; + const std::vector getJoints() const; + + size_t size() const; + + moveit_msgs::Constraints toGoalConstraints() const override; + moveit_msgs::RobotState toMoveitMsgsRobotState() const override; + + sensor_msgs::JointState toSensorMsg() const; + + robot_state::RobotState toRobotState() const; + + void setCreateJointNameFunc(CreateJointNameFunc create_joint_name_func); + +private: + moveit_msgs::RobotState toMoveitMsgsRobotStateWithoutModel() const; + moveit_msgs::RobotState toMoveitMsgsRobotStateWithModel() const; + + moveit_msgs::Constraints toGoalConstraintsWithoutModel() const; + moveit_msgs::Constraints toGoalConstraintsWithModel() const; + +private: + //! Joint positions + std::vector joints_; + + CreateJointNameFunc create_joint_name_func_; +}; + +std::ostream& operator<<(std::ostream& /*os*/, const JointConfiguration& /*obj*/); + +inline moveit_msgs::Constraints JointConfiguration::toGoalConstraints() const +{ + return robot_model_ ? toGoalConstraintsWithModel() : toGoalConstraintsWithoutModel(); +} + +inline moveit_msgs::RobotState JointConfiguration::toMoveitMsgsRobotState() const +{ + return robot_model_ ? toMoveitMsgsRobotStateWithModel() : toMoveitMsgsRobotStateWithoutModel(); +} + +inline void JointConfiguration::setJoint(const size_t index, const double value) +{ + joints_.at(index) = value; +} + +inline double JointConfiguration::getJoint(const size_t index) const +{ + return joints_.at(index); +} + +inline const std::vector JointConfiguration::getJoints() const +{ + return joints_; +} + +inline size_t JointConfiguration::size() const +{ + return joints_.size(); +} + +inline void JointConfiguration::setCreateJointNameFunc(CreateJointNameFunc create_joint_name_func) +{ + create_joint_name_func_ = std::move(create_joint_name_func); +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // JOINTCONFIGURATION_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/lin.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/lin.h new file mode 100644 index 0000000000..56e74a51d3 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/lin.h @@ -0,0 +1,67 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef LIN_H +#define LIN_H + +#include + +#include "basecmd.h" + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Data class storing all information regarding a linear command. + */ +template +class Lin : public BaseCmd +{ +public: + Lin() : BaseCmd() + { + } + +private: + std::string getPlannerId() const override; +}; + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +template +inline std::string Lin::getPlannerId() const +{ + return "LIN"; +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // LIN_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/motioncmd.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/motioncmd.h new file mode 100644 index 0000000000..f54beb0c56 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/motioncmd.h @@ -0,0 +1,93 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef MOTIONCMD_H +#define MOTIONCMD_H + +#include +#include + +#include "motionplanrequestconvertible.h" + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Base class for commands storing all general information of a command. + */ +class MotionCmd : public MotionPlanRequestConvertible +{ +public: + MotionCmd() : MotionPlanRequestConvertible() + { + } + +public: + void setPlanningGroup(const std::string& planning_group); + const std::string& getPlanningGroup() const; + + void setVelocityScale(double velocity_scale); + void setAccelerationScale(double acceleration_scale); + +protected: + std::string planning_group_; + //! Link to which all cartesian poses refer to. + std::string target_link_; + double vel_scale_{ 1.0 }; + double acc_scale_{ 1.0 }; +}; + +inline void MotionCmd::setPlanningGroup(const std::string& planning_group) +{ + planning_group_ = planning_group; +} + +inline const std::string& MotionCmd::getPlanningGroup() const +{ + return planning_group_; +} + +inline void MotionCmd::setVelocityScale(double velocity_scale) +{ + vel_scale_ = velocity_scale; +} + +inline void MotionCmd::setAccelerationScale(double acceleration_scale) +{ + acc_scale_ = acceleration_scale; +} + +using MotionCmdUPtr = std::unique_ptr; +} // namespace pilz_industrial_motion_planner_testutils + +#endif // MOTIONCMD_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/motionplanrequestconvertible.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/motionplanrequestconvertible.h new file mode 100644 index 0000000000..803fc499fa --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/motionplanrequestconvertible.h @@ -0,0 +1,54 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef MOTIONPLANREQUESTCONVERTIBLE_H +#define MOTIONPLANREQUESTCONVERTIBLE_H + +#include +#include + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Interface class to express that a derived class can be converted + * into a planning_interface::MotionPlanRequest. + */ +class MotionPlanRequestConvertible +{ +public: + virtual planning_interface::MotionPlanRequest toRequest() const = 0; +}; +} // namespace pilz_industrial_motion_planner_testutils + +#endif // MOTIONPLANREQUESTCONVERTIBLE_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/ptp.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/ptp.h new file mode 100644 index 0000000000..cc7c2ce228 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/ptp.h @@ -0,0 +1,67 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef PTP_H +#define PTP_H + +#include + +#include "basecmd.h" + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Data class storing all information regarding a Ptp command. + */ +template +class Ptp : public BaseCmd +{ +public: + Ptp() : BaseCmd() + { + } + +private: + std::string getPlannerId() const override; +}; + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +template +inline std::string Ptp::getPlannerId() const +{ + return "PTP"; +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // PTP_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/robotconfiguration.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/robotconfiguration.h new file mode 100644 index 0000000000..433146dcfb --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/robotconfiguration.h @@ -0,0 +1,92 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef ROBOTCONFIGURATION_H +#define ROBOTCONFIGURATION_H + +#include +#include + +#include + +#include "goalconstraintsmsgconvertible.h" +#include "robotstatemsgconvertible.h" + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Class to define robot configuration in space. + */ +class RobotConfiguration : public RobotStateMsgConvertible, public GoalConstraintMsgConvertible +{ +public: + RobotConfiguration(); + + RobotConfiguration(const std::string& group_name); + + RobotConfiguration(const std::string& group_name, const moveit::core::RobotModelConstPtr& robot_model); + +public: + void setRobotModel(moveit::core::RobotModelConstPtr robot_model); + void setGroupName(const std::string& group_name); + std::string getGroupName() const; + void clearModel(); + +protected: + std::string group_name_; + moveit::core::RobotModelConstPtr robot_model_; +}; + +inline void RobotConfiguration::setRobotModel(moveit::core::RobotModelConstPtr robot_model) +{ + robot_model_ = std::move(robot_model); +} + +inline void RobotConfiguration::setGroupName(const std::string& group_name) +{ + group_name_ = group_name; +} + +inline std::string RobotConfiguration::getGroupName() const +{ + return group_name_; +} + +inline void RobotConfiguration::clearModel() +{ + robot_model_ = nullptr; +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // ROBOTCONFIGURATION_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/robotstatemsgconvertible.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/robotstatemsgconvertible.h new file mode 100644 index 0000000000..4b9ba87df4 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/robotstatemsgconvertible.h @@ -0,0 +1,54 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef ROBOTSTATEMSGCONVERTIBLE_H +#define ROBOTSTATEMSGCONVERTIBLE_H + +#include +#include + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Interface class to express that a derived class can be converted + * into a moveit_msgs::RobotState. + */ +class RobotStateMsgConvertible +{ +public: + virtual moveit_msgs::RobotState toMoveitMsgsRobotState() const = 0; +}; +} // namespace pilz_industrial_motion_planner_testutils + +#endif // ROBOTSTATEMSGCONVERTIBLE_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/sequence.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/sequence.h new file mode 100644 index 0000000000..e555b8405d --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/sequence.h @@ -0,0 +1,147 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef SEQUENCE_H +#define SEQUENCE_H + +#include +#include +#include +#include + +#include + +#include "command_types_typedef.h" +#include "motioncmd.h" + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Data class storing all information regarding a Sequence command. + */ +class Sequence +{ +public: + /** + * @brief Adds a command to the end of the sequence. + * @param cmd The command which has to be added. + */ + void add(const CmdVariant& cmd, const double blend_radius = 0.); + + /** + * @brief Returns the number of commands. + */ + size_t size() const; + + template + T& getCmd(const size_t index_cmd); + + template + const T& getCmd(const size_t index_cmd) const; + + /** + * @return TRUE if the specified command is of the specified type, + * otherwise FALSE. + */ + template + bool cmdIsOfType(const size_t index_cmd) const; + + /** + * @brief Returns the specific command as base class reference. + * This function allows the user to operate on the sequence without + * having knowledge of the underlying specific command type. + */ + MotionCmd& getCmd(const size_t index_cmd); + + void setAllBlendRadiiToZero(); + void setBlendRadius(const size_t index_cmd, const double blend_radius); + double getBlendRadius(const size_t index_cmd) const; + + /** + * @brief Deletes all commands from index 'start' to index 'end'. + */ + void erase(const size_t start, const size_t end); + + moveit_msgs::MotionSequenceRequest toRequest() const; + +private: + using TCmdRadiiPair = std::pair; + std::vector cmds_; +}; + +inline void Sequence::add(const CmdVariant& cmd, const double blend_radius) +{ + cmds_.emplace_back(cmd, blend_radius); +} + +inline size_t Sequence::size() const +{ + return cmds_.size(); +} + +template +inline T& Sequence::getCmd(const size_t index_cmd) +{ + return boost::get(cmds_.at(index_cmd).first); +} + +template +inline const T& Sequence::getCmd(const size_t index_cmd) const +{ + return boost::get(cmds_.at(index_cmd).first); +} + +inline double Sequence::getBlendRadius(const size_t index_cmd) const +{ + return cmds_.at(index_cmd).second; +} + +inline void Sequence::setBlendRadius(const size_t index_cmd, const double blend_radius) +{ + cmds_.at(index_cmd).second = blend_radius; +} + +inline void Sequence::setAllBlendRadiiToZero() +{ + std::for_each(cmds_.begin(), cmds_.end(), [](TCmdRadiiPair& cmd) { cmd.second = 0.; }); +} + +template +inline bool Sequence::cmdIsOfType(const size_t index_cmd) const +{ + return cmds_.at(index_cmd).first.type() == typeid(T); +} +} // namespace pilz_industrial_motion_planner_testutils + +#endif // SEQUENCE_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/testdata_loader.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/testdata_loader.h new file mode 100644 index 0000000000..5b2f550bfb --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/testdata_loader.h @@ -0,0 +1,117 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef TESTDATA_LOADER_H +#define TESTDATA_LOADER_H + +#include +#include + +#include + +#include "jointconfiguration.h" +#include "cartesianconfiguration.h" +#include "command_types_typedef.h" +#include "sequence.h" +#include "gripper.h" + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Abstract base class describing the interface to access + * test data like robot poses and robot commands. + */ +class TestdataLoader +{ +public: + TestdataLoader() = default; + + TestdataLoader(moveit::core::RobotModelConstPtr robot_model) : robot_model_(std::move(robot_model)) + { + } + + virtual ~TestdataLoader() = default; + +public: + void setRobotModel(moveit::core::RobotModelConstPtr robot_model); + + virtual JointConfiguration getJoints(const std::string& pos_name, const std::string& group_name) const = 0; + + virtual CartesianConfiguration getPose(const std::string& pos_name, const std::string& group_name) const = 0; + + /** + * @brief Returns the command with the specified name from the test data. + */ + virtual PtpJoint getPtpJoint(const std::string& cmd_name) const = 0; + virtual PtpCart getPtpCart(const std::string& cmd_name) const = 0; + virtual PtpJointCart getPtpJointCart(const std::string& cmd_name) const = 0; + + /** + * @brief Returns the command with the specified name from the test data. + */ + virtual LinJoint getLinJoint(const std::string& cmd_name) const = 0; + virtual LinCart getLinCart(const std::string& cmd_name) const = 0; + virtual LinJointCart getLinJointCart(const std::string& cmd_name) const = 0; + + /** + * @brief Returns the command with the specified name from the test data. + */ + virtual CircCenterCart getCircCartCenterCart(const std::string& cmd_name) const = 0; + virtual CircJointCenterCart getCircJointCenterCart(const std::string& cmd_name) const = 0; + virtual CircInterimCart getCircCartInterimCart(const std::string& cmd_name) const = 0; + virtual CircJointInterimCart getCircJointInterimCart(const std::string& cmd_name) const = 0; + + /** + * @brief Returns the command with the specified name from the test data. + */ + virtual Sequence getSequence(const std::string& cmd_name) const = 0; + + /** + * @brief Returns the command with the specified name from the test data. + */ + virtual Gripper getGripper(const std::string& cmd_name) const = 0; + +protected: + moveit::core::RobotModelConstPtr robot_model_; +}; + +inline void TestdataLoader::setRobotModel(moveit::core::RobotModelConstPtr robot_model) +{ + robot_model_ = std::move(robot_model); +} + +using TestdataLoaderUPtr = std::unique_ptr; +} // namespace pilz_industrial_motion_planner_testutils + +#endif // TESTDATA_LOADER_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/xml_constants.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/xml_constants.h new file mode 100644 index 0000000000..8c6c4e6914 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/xml_constants.h @@ -0,0 +1,80 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef XML_CONSTANTS_H +#define XML_CONSTANTS_H + +#include + +namespace pilz_industrial_motion_planner_testutils +{ +const std::string EMPTY_STR{}; + +const std::string XML_ATTR_STR{ "" }; +const std::string JOINT_STR{ "joints" }; +const std::string POSE_STR{ "pos" }; +const std::string XYZ_QUAT_STR{ "xyzQuat" }; +const std::string XYZ_EULER_STR{ "xyzEuler" }; +const std::string SEED_STR{ "seed" }; + +const std::string PTP_STR{ "ptp" }; +const std::string LIN_STR{ "lin" }; +const std::string CIRC_STR{ "circ" }; +const std::string BLEND_STR{ "blend" }; +const std::string GRIPPER_STR{ "gripper" }; + +const std::string PLANNING_GROUP_STR{ "planningGroup" }; +const std::string TARGET_LINK_STR{ "targetLink" }; +const std::string START_POS_STR{ "startPos" }; +const std::string END_POS_STR{ "endPos" }; +const std::string INTERMEDIATE_POS_STR{ "intermediatePos" }; +const std::string CENTER_POS_STR{ "centerPos" }; +const std::string VEL_STR{ "vel" }; +const std::string ACC_STR{ "acc" }; + +const std::string POSES_PATH_STR{ "testdata.poses" }; +const std::string PTPS_PATH_STR{ "testdata." + PTP_STR + "s" }; +const std::string LINS_PATH_STR{ "testdata." + LIN_STR + "s" }; +const std::string CIRCS_PATH_STR{ "testdata." + CIRC_STR + "s" }; +const std::string SEQUENCE_PATH_STR{ "testdata.sequences" }; +const std::string GRIPPERS_PATH_STR{ "testdata." + GRIPPER_STR + "s" }; + +const std::string NAME_PATH_STR{ XML_ATTR_STR + ".name" }; +const std::string CMD_TYPE_PATH_STR{ XML_ATTR_STR + ".type" }; +const std::string BLEND_RADIUS_PATH_STR{ XML_ATTR_STR + ".blend_radius" }; +const std::string LINK_NAME_PATH_STR{ XML_ATTR_STR + ".link_name" }; +const std::string GROUP_NAME_PATH_STR{ XML_ATTR_STR + ".group_name" }; +} // namespace pilz_industrial_motion_planner_testutils + +#endif // XML_CONSTANTS_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/xml_testdata_loader.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/xml_testdata_loader.h new file mode 100644 index 0000000000..c07da6ffb7 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/xml_testdata_loader.h @@ -0,0 +1,223 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#ifndef XML_TESTDATA_LOADER_H +#define XML_TESTDATA_LOADER_H + +#include +#include +#include +#include +#include + +#include + +#include "pilz_industrial_motion_planner_testutils/testdata_loader.h" + +namespace pt = boost::property_tree; +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Implements a test data loader which uses a xml file + * to store the test data. + * + * The Xml-file has the following structure: + * + * + * + * + * + * j1 j2 j3 j4 j5 j6 + * + * x y z wx wy wz w + * s1 s2 s3 s4 s5 s6 + * + * j_gripper + * + * + * + * j1 j2 j3 j4 j5 j6 + * x y z wx wy wz w + * j_gripper + * + * + * + * + * + * MyTestPos1 + * MyTestPos2 + * 0.1 + * 0.2 + * + * + * + * + * + * manipulator + * prbt_tcp + * MyTestPos1 + * MyTestPos2 + * 0.3 + * 0.4 + * + * + * + * + * + * manipulator + * prbt_tcp + * MyTestPos1 + * MyTestPos1 + * MyTestPos2 + * MyTestPos1 + * 0.2 + * 0.5 + * + * + * + * + * + * + * + * + * + * + * + * + */ + +class XmlTestdataLoader : public TestdataLoader +{ +public: + XmlTestdataLoader(const std::string& path_filename); + XmlTestdataLoader(const std::string& path_filename, const moveit::core::RobotModelConstPtr& robot_model); + ~XmlTestdataLoader() override; + +public: + JointConfiguration getJoints(const std::string& pos_name, const std::string& group_name) const override; + + CartesianConfiguration getPose(const std::string& pos_name, const std::string& group_name) const override; + + PtpJoint getPtpJoint(const std::string& cmd_name) const override; + PtpCart getPtpCart(const std::string& cmd_name) const override; + PtpJointCart getPtpJointCart(const std::string& cmd_name) const override; + + LinJoint getLinJoint(const std::string& cmd_name) const override; + LinCart getLinCart(const std::string& cmd_name) const override; + LinJointCart getLinJointCart(const std::string& cmd_name) const override; + + CircCenterCart getCircCartCenterCart(const std::string& cmd_name) const override; + CircInterimCart getCircCartInterimCart(const std::string& cmd_name) const override; + CircJointCenterCart getCircJointCenterCart(const std::string& cmd_name) const override; + CircJointInterimCart getCircJointInterimCart(const std::string& cmd_name) const override; + + Sequence getSequence(const std::string& cmd_name) const override; + + Gripper getGripper(const std::string& cmd_name) const override; + +private: + /** + * @brief Use this function to search for a node (like an pos or cmd) + * with a given name. + * + * @param tree Tree containing the node. + * @param name Name of node to look for. + */ + const pt::ptree::value_type& findNodeWithName(const boost::property_tree::ptree& tree, const std::string& name, + const std::string& key, const std::string& path = "") const; + + /** + * @brief Use this function to search for a cmd-node with a given name. + */ + const pt::ptree::value_type& findCmd(const std::string& cmd_name, const std::string& cmd_path, + const std::string& cmd_key) const; + + CartesianCenter getCartesianCenter(const std::string& cmd_name, const std::string& planning_group) const; + + CartesianInterim getCartesianInterim(const std::string& cmd_name, const std::string& planning_group) const; + +private: + JointConfiguration getJoints(const boost::property_tree::ptree& joints_tree, const std::string& group_name) const; + +private: + /** + * @brief Converts string vector to double vector. + */ + inline static std::vector strVec2doubleVec(std::vector& strVec); + +public: + /** + * @brief Abstract base class providing a GENERIC getter-function signature + * which can be used to load DIFFERENT command types (like Ptp, Lin, etc.) + * from the test data file. + */ + class AbstractCmdGetterAdapter + { + public: + virtual CmdVariant getCmd(const std::string& /*cmd_name*/) const = 0; + virtual ~AbstractCmdGetterAdapter() = default; + }; + +private: + std::string path_filename_; + pt::ptree tree_{}; + + using AbstractCmdGetterUPtr = std::unique_ptr; + + //! Stores the mapping between command type and the getter function + //! which have to be called. + //! + //! Please note: + //! This mapping is only relevant for sequence commands. + std::map cmd_getter_funcs_; + +private: + const pt::ptree::value_type empty_value_type_{}; + const pt::ptree empty_tree_{}; +}; + +std::vector XmlTestdataLoader::strVec2doubleVec(std::vector& strVec) +{ + std::vector vec; + + vec.resize(strVec.size()); + std::transform(strVec.begin(), strVec.end(), vec.begin(), [](const std::string& val) { return std::stod(val); }); + + return vec; +} + +using XmlTestDataLoaderUPtr = std::unique_ptr; +} // namespace pilz_industrial_motion_planner_testutils + +#endif // XML_TESTDATA_LOADER_H diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml b/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml new file mode 100644 index 0000000000..624abcec8c --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml @@ -0,0 +1,29 @@ + + + pilz_industrial_motion_planner_testutils + 0.4.10 + Helper scripts and functionality to test industrial motion generation + + Alexander Gutenkunst + Christian Henkel + Immanuel Martini + Joachim Schleicher + Hagen Slusarek + + BSD + + http://moveit.ros.org + https://github.com/ros-planning/moveit/issues + https://github.com/ros-planning/moveit + + eigen_conversions + moveit_core + moveit_msgs + + moveit_core + moveit_msgs + moveit_commander + + catkin + + diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/src/cartesianconfiguration.cpp b/moveit_planners/pilz_industrial_motion_planner_testutils/src/cartesianconfiguration.cpp new file mode 100644 index 0000000000..104d762567 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/src/cartesianconfiguration.cpp @@ -0,0 +1,132 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner_testutils/cartesianconfiguration.h" + +#include + +namespace pilz_industrial_motion_planner_testutils +{ +CartesianConfiguration::CartesianConfiguration() : RobotConfiguration() +{ +} + +CartesianConfiguration::CartesianConfiguration(const std::string& group_name, const std::string& link_name, + const std::vector& config) + : RobotConfiguration(group_name), link_name_(link_name), pose_(toPose(config)) +{ +} + +CartesianConfiguration::CartesianConfiguration(const std::string& group_name, const std::string& link_name, + const std::vector& config, + const moveit::core::RobotModelConstPtr& robot_model) + : RobotConfiguration(group_name, robot_model), link_name_(link_name), pose_(toPose(config)) +{ + if (robot_model && (!robot_model_->hasLinkModel(link_name_))) + { + std::string msg{ "Link \"" }; + msg.append(link_name).append("\" not known to robot model"); + throw std::invalid_argument(msg); + } + + if (robot_model && (!robot_state::RobotState(robot_model_).knowsFrameTransform(link_name_))) + { + std::string msg{ "Tranform of \"" }; + msg.append(link_name).append("\" is unknown"); + throw std::invalid_argument(msg); + } +} + +geometry_msgs::Pose CartesianConfiguration::toPose(const std::vector& pose) +{ + geometry_msgs::Pose pose_msg; + pose_msg.position.x = pose.at(0); + pose_msg.position.y = pose.at(1); + pose_msg.position.z = pose.at(2); + pose_msg.orientation.x = pose.at(3); + pose_msg.orientation.y = pose.at(4); + pose_msg.orientation.z = pose.at(5); + pose_msg.orientation.w = pose.at(6); + + return pose_msg; +} + +geometry_msgs::PoseStamped CartesianConfiguration::toStampedPose(const geometry_msgs::Pose& pose) +{ + geometry_msgs::PoseStamped pose_stamped_msg; + pose_stamped_msg.pose = pose; + return pose_stamped_msg; +} + +moveit_msgs::RobotState CartesianConfiguration::toMoveitMsgsRobotState() const +{ + if (!robot_model_) + { + throw std::runtime_error("No robot model set"); + } + + robot_state::RobotState rstate(robot_model_); + rstate.setToDefaultValues(); + if (hasSeed()) + { + rstate.setJointGroupPositions(group_name_, getSeed().getJoints()); + } + + rstate.update(); + + // set to Cartesian pose + Eigen::Isometry3d start_pose; + tf::poseMsgToEigen(pose_, start_pose); + if (!rstate.setFromIK(rstate.getRobotModel()->getJointModelGroup(group_name_), start_pose, link_name_)) + { + std::ostringstream os; + os << "No solution for ik \n" << start_pose.translation() << "\n" << start_pose.linear(); + throw std::runtime_error(os.str()); + } + + // Conversion to RobotState msg type + moveit_msgs::RobotState robot_state_msg; + moveit::core::robotStateToRobotStateMsg(rstate, robot_state_msg, true); + return robot_state_msg; +} + +std::ostream& operator<<(std::ostream& os, const CartesianConfiguration& obj) +{ + os << "Group name: \"" << obj.getGroupName() << "\""; + os << " | link name: \"" << obj.getLinkName() << "\""; + os << "\n" << obj.getPose(); + return os; +} + +} // namespace pilz_industrial_motion_planner_testutils diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/src/jointconfiguration.cpp b/moveit_planners/pilz_industrial_motion_planner_testutils/src/jointconfiguration.cpp new file mode 100644 index 0000000000..4ab2cbb5d9 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/src/jointconfiguration.cpp @@ -0,0 +1,161 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner_testutils/jointconfiguration.h" + +#include + +namespace pilz_industrial_motion_planner_testutils +{ +JointConfiguration::JointConfiguration() : RobotConfiguration() +{ +} + +JointConfiguration::JointConfiguration(const std::string& group_name, const std::vector& config, + CreateJointNameFunc&& create_joint_name_func) + : RobotConfiguration(group_name), joints_(config), create_joint_name_func_(create_joint_name_func) +{ +} + +JointConfiguration::JointConfiguration(const std::string& group_name, const std::vector& config, + const moveit::core::RobotModelConstPtr& robot_model) + : RobotConfiguration(group_name, robot_model), joints_(config) +{ +} + +moveit_msgs::Constraints JointConfiguration::toGoalConstraintsWithoutModel() const +{ + if (!create_joint_name_func_) + { + throw JointConfigurationException("Create-Joint-Name function not set"); + } + + moveit_msgs::Constraints gc; + + for (size_t i = 0; i < joints_.size(); ++i) + { + moveit_msgs::JointConstraint jc; + jc.joint_name = create_joint_name_func_(i); + jc.position = joints_.at(i); + gc.joint_constraints.push_back(jc); + } + + return gc; +} + +moveit_msgs::Constraints JointConfiguration::toGoalConstraintsWithModel() const +{ + if (!robot_model_) + { + throw JointConfigurationException("No robot model set"); + } + + robot_state::RobotState state(robot_model_); + state.setToDefaultValues(); + state.setJointGroupPositions(group_name_, joints_); + + return kinematic_constraints::constructGoalConstraints(state, state.getRobotModel()->getJointModelGroup(group_name_)); +} + +moveit_msgs::RobotState JointConfiguration::toMoveitMsgsRobotStateWithoutModel() const +{ + if (!create_joint_name_func_) + { + throw JointConfigurationException("Create-Joint-Name function not set"); + } + + moveit_msgs::RobotState robot_state; + for (size_t i = 0; i < joints_.size(); ++i) + { + robot_state.joint_state.name.emplace_back(create_joint_name_func_(i)); + robot_state.joint_state.position.push_back(joints_.at(i)); + } + return robot_state; +} + +robot_state::RobotState JointConfiguration::toRobotState() const +{ + if (!robot_model_) + { + throw JointConfigurationException("No robot model set"); + } + + robot_state::RobotState robot_state(robot_model_); + robot_state.setToDefaultValues(); + robot_state.setJointGroupPositions(group_name_, joints_); + return robot_state; +} + +moveit_msgs::RobotState JointConfiguration::toMoveitMsgsRobotStateWithModel() const +{ + robot_state::RobotState start_state(toRobotState()); + moveit_msgs::RobotState rob_state_msg; + moveit::core::robotStateToRobotStateMsg(start_state, rob_state_msg, false); + return rob_state_msg; +} + +sensor_msgs::JointState JointConfiguration::toSensorMsg() const +{ + if (!create_joint_name_func_) + { + throw JointConfigurationException("Create-Joint-Name function not set"); + } + + sensor_msgs::JointState state; + for (size_t i = 0; i < joints_.size(); ++i) + { + state.name.emplace_back(create_joint_name_func_(i)); + state.position.push_back(joints_.at(i)); + } + return state; +} + +std::ostream& operator<<(std::ostream& os, const JointConfiguration& obj) +{ + const size_t n{ obj.size() }; + os << "JointConfiguration: ["; + for (size_t i = 0; i < n; ++i) + { + os << obj.getJoint(i); + if (i != n - 1) + { + os << ", "; + } + } + os << "]"; + + return os; +} + +} // namespace pilz_industrial_motion_planner_testutils diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/src/robotconfiguration.cpp b/moveit_planners/pilz_industrial_motion_planner_testutils/src/robotconfiguration.cpp new file mode 100644 index 0000000000..7de626c3f1 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/src/robotconfiguration.cpp @@ -0,0 +1,62 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner_testutils/robotconfiguration.h" + +#include + +namespace pilz_industrial_motion_planner_testutils +{ +RobotConfiguration::RobotConfiguration() : RobotStateMsgConvertible(), GoalConstraintMsgConvertible() +{ +} + +RobotConfiguration::RobotConfiguration(const std::string& group_name) + : RobotStateMsgConvertible(), GoalConstraintMsgConvertible(), group_name_(group_name) +{ +} + +RobotConfiguration::RobotConfiguration(const std::string& group_name, + const moveit::core::RobotModelConstPtr& robot_model) + : RobotStateMsgConvertible(), GoalConstraintMsgConvertible(), group_name_(group_name), robot_model_(robot_model) +{ + if (robot_model && (!robot_model_->hasJointModelGroup(group_name_))) + { + std::string msg{ "Specified robot model does not contain specified group \"" }; + msg.append(group_name).append("\""); + throw std::invalid_argument(msg); + } +} + +} // namespace pilz_industrial_motion_planner_testutils diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/src/sequence.cpp b/moveit_planners/pilz_industrial_motion_planner_testutils/src/sequence.cpp new file mode 100644 index 0000000000..b606668385 --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/src/sequence.cpp @@ -0,0 +1,120 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner_testutils/sequence.h" + +#include +#include + +namespace pilz_industrial_motion_planner_testutils +{ +/** + * @brief Visitor transforming the stored command into a MotionPlanRequest. + */ +class ToReqVisitor : public boost::static_visitor +{ +public: + template + planning_interface::MotionPlanRequest operator()(T& cmd) const + { + return cmd.toRequest(); + } +}; + +/** + * @brief Visitor returning not the specific command type but the base type. + */ +class ToBaseVisitor : public boost::static_visitor +{ +public: + template + MotionCmd& operator()(T& cmd) const + { + return cmd; + } +}; + +moveit_msgs::MotionSequenceRequest Sequence::toRequest() const +{ + moveit_msgs::MotionSequenceRequest req; + + std::vector group_names; + for (const auto& cmd : cmds_) + { + moveit_msgs::MotionSequenceItem item; + item.req = boost::apply_visitor(ToReqVisitor(), cmd.first); + + if (std::find(group_names.begin(), group_names.end(), item.req.group_name) != group_names.end()) + { + // Remove start state because only the first request of a group + // is allowed to have a start state in a sequence. + item.req.start_state = moveit_msgs::RobotState(); + } + else + { + group_names.emplace_back(item.req.group_name); + } + + item.blend_radius = cmd.second; + req.items.push_back(item); + } + return req; +} + +void Sequence::erase(const size_t start, const size_t end) +{ + const size_t orig_n{ size() }; + if (start > orig_n || end > orig_n) + { + std::string msg; + msg.append("Parameter start=").append(std::to_string(start)); + msg.append(" and end=").append(std::to_string(end)); + msg.append(" must not be greater then the number of #commands="); + msg.append(std::to_string(size())); + throw std::invalid_argument(msg); + } + cmds_.erase(cmds_.begin() + start, cmds_.begin() + end); + if (end == orig_n) + { + // Make sure last radius is set zero + cmds_.at(size() - 1).second = 0.; + } +} + +MotionCmd& Sequence::getCmd(const size_t index_cmd) +{ + return boost::apply_visitor(ToBaseVisitor(), cmds_.at(index_cmd).first); +} + +} // namespace pilz_industrial_motion_planner_testutils diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/src/xml_testdata_loader.cpp b/moveit_planners/pilz_industrial_motion_planner_testutils/src/xml_testdata_loader.cpp new file mode 100644 index 0000000000..69054bc45d --- /dev/null +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/src/xml_testdata_loader.cpp @@ -0,0 +1,555 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2018 Pilz GmbH & Co. KG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Pilz GmbH & Co. KG 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. + *********************************************************************/ + +#include "pilz_industrial_motion_planner_testutils/xml_testdata_loader.h" + +#include + +#include +#include +#include + +#include "pilz_industrial_motion_planner_testutils/default_values.h" +#include "pilz_industrial_motion_planner_testutils/exception_types.h" +#include "pilz_industrial_motion_planner_testutils/xml_constants.h" + +namespace pt = boost::property_tree; +namespace pilz_industrial_motion_planner_testutils +{ +class CmdReader +{ +public: + CmdReader(const pt::ptree::value_type& node) : cmd_node_(node) + { + } + +public: + std::string getPlanningGroup() const; + std::string getTargetLink() const; + std::string getStartPoseName() const; + std::string getEndPoseName() const; + + double getVelocityScale() const; + double getAccelerationScale() const; + + CmdReader& setDefaultVelocityScale(double scale); + CmdReader& setDefaultAccelerationScale(double scale); + +private: + const pt::ptree::value_type& cmd_node_; + + double default_velocity_scale_{ DEFAULT_VEL }; + double default_acceleration_scale_{ DEFAULT_ACC }; +}; + +inline std::string CmdReader::getPlanningGroup() const +{ + return cmd_node_.second.get(PLANNING_GROUP_STR); +} + +inline std::string CmdReader::getTargetLink() const +{ + return cmd_node_.second.get(TARGET_LINK_STR); +} + +inline std::string CmdReader::getStartPoseName() const +{ + return cmd_node_.second.get(START_POS_STR); +} + +inline std::string CmdReader::getEndPoseName() const +{ + return cmd_node_.second.get(END_POS_STR); +} + +inline double CmdReader::getVelocityScale() const +{ + return cmd_node_.second.get(VEL_STR, default_velocity_scale_); +} + +inline double CmdReader::getAccelerationScale() const +{ + return cmd_node_.second.get(ACC_STR, default_acceleration_scale_); +} + +inline CmdReader& CmdReader::setDefaultVelocityScale(double scale) +{ + default_velocity_scale_ = scale; + return *this; +} + +inline CmdReader& CmdReader::setDefaultAccelerationScale(double scale) +{ + default_acceleration_scale_ = scale; + return *this; +} + +template +class CmdGetterAdapter : public XmlTestdataLoader::AbstractCmdGetterAdapter +{ +public: + using FuncType = std::function; + + CmdGetterAdapter(FuncType func) : AbstractCmdGetterAdapter(), func_(func) + { + } + +public: + CmdVariant getCmd(const std::string& cmd_name) const override + { + return CmdVariant(func_(cmd_name)); + } + +private: + FuncType func_; +}; + +XmlTestdataLoader::XmlTestdataLoader(const std::string& path_filename) : TestdataLoader(), path_filename_(path_filename) +{ + // Parse the XML into the property tree. + pt::read_xml(path_filename_, tree_, pt::xml_parser::no_comments); + + using std::placeholders::_1; + cmd_getter_funcs_["ptp"] = + AbstractCmdGetterUPtr(new CmdGetterAdapter(std::bind(&XmlTestdataLoader::getPtpJoint, this, _1))); + cmd_getter_funcs_["ptp_joint_cart"] = AbstractCmdGetterUPtr( + new CmdGetterAdapter(std::bind(&XmlTestdataLoader::getPtpJointCart, this, _1))); + cmd_getter_funcs_["ptp_cart_cart"] = + AbstractCmdGetterUPtr(new CmdGetterAdapter(std::bind(&XmlTestdataLoader::getPtpCart, this, _1))); + + cmd_getter_funcs_["lin"] = + AbstractCmdGetterUPtr(new CmdGetterAdapter(std::bind(&XmlTestdataLoader::getLinJoint, this, _1))); + cmd_getter_funcs_["lin_cart"] = + AbstractCmdGetterUPtr(new CmdGetterAdapter(std::bind(&XmlTestdataLoader::getLinCart, this, _1))); + + cmd_getter_funcs_["circ_center_cart"] = AbstractCmdGetterUPtr( + new CmdGetterAdapter(std::bind(&XmlTestdataLoader::getCircCartCenterCart, this, _1))); + cmd_getter_funcs_["circ_interim_cart"] = AbstractCmdGetterUPtr( + new CmdGetterAdapter(std::bind(&XmlTestdataLoader::getCircCartInterimCart, this, _1))); + cmd_getter_funcs_["circ_joint_interim_cart"] = AbstractCmdGetterUPtr( + new CmdGetterAdapter(std::bind(&XmlTestdataLoader::getCircJointInterimCart, this, _1))); + + cmd_getter_funcs_["gripper"] = + AbstractCmdGetterUPtr(new CmdGetterAdapter(std::bind(&XmlTestdataLoader::getGripper, this, _1))); +} + +XmlTestdataLoader::XmlTestdataLoader(const std::string& path_filename, + const moveit::core::RobotModelConstPtr& robot_model) + : XmlTestdataLoader(path_filename) +{ + setRobotModel(robot_model); +} + +XmlTestdataLoader::~XmlTestdataLoader() +{ +} + +const pt::ptree::value_type& XmlTestdataLoader::findNodeWithName(const boost::property_tree::ptree& tree, + const std::string& name, const std::string& key, + const std::string& path) const +{ + std::string path_str{ (path.empty() ? NAME_PATH_STR : path) }; + + // Search for node with given name. + for (const pt::ptree::value_type& val : tree) + { + // Ignore attributes which are always the first element of a tree. + if (val.first == XML_ATTR_STR) + { + continue; + } + + if (val.first != key) + { + continue; + } + + const auto& node{ val.second.get_child(path_str, empty_tree_) }; + if (node == empty_tree_) + { + break; + } + if (node.data() == name) + { + return val; + } + } + + std::string msg; + msg.append("Node of type \"") + .append(key) + .append("\" with ") + .append(path_str) + .append("=\"") + .append(name) + .append("\" " + "not " + "foun" + "d."); + throw TestDataLoaderReadingException(msg); +} + +JointConfiguration XmlTestdataLoader::getJoints(const std::string& pos_name, const std::string& group_name) const +{ + // Search for node with given name. + const auto& poses_tree{ tree_.get_child(POSES_PATH_STR, empty_tree_) }; + if (poses_tree == empty_tree_) + { + throw TestDataLoaderReadingException("No poses found."); + } + return getJoints(findNodeWithName(poses_tree, pos_name, POSE_STR).second, group_name); +} + +JointConfiguration XmlTestdataLoader::getJoints(const boost::property_tree::ptree& joints_tree, + const std::string& group_name) const +{ + // Search joints node with given group_name. + if (joints_tree == empty_tree_) + { + throw TestDataLoaderReadingException("No joints found."); + } + const auto& joint_node{ findNodeWithName(joints_tree, group_name, JOINT_STR, GROUP_NAME_PATH_STR) }; + + std::vector strs; + boost::split(strs, joint_node.second.data(), boost::is_any_of(" ")); + return JointConfiguration(group_name, strVec2doubleVec(strs), robot_model_); +} + +CartesianConfiguration XmlTestdataLoader::getPose(const std::string& pos_name, const std::string& group_name) const +{ + const auto& all_poses_tree{ tree_.get_child(POSES_PATH_STR, empty_tree_) }; + if (all_poses_tree == empty_tree_) + { + throw TestDataLoaderReadingException("No poses found."); + } + const auto& pose_tree{ findNodeWithName(all_poses_tree, pos_name, POSE_STR).second }; + const auto& xyz_quat_tree{ findNodeWithName(pose_tree, group_name, XYZ_QUAT_STR, GROUP_NAME_PATH_STR).second }; + const boost::property_tree::ptree& link_name_attr{ xyz_quat_tree.get_child(LINK_NAME_PATH_STR, empty_tree_) }; + if (link_name_attr == empty_tree_) + { + throw TestDataLoaderReadingException("No link name found."); + } + + // Get rid of things like "\n", etc. + std::string data{ xyz_quat_tree.data() }; + boost::trim(data); + + std::vector pos_ori_str; + boost::split(pos_ori_str, data, boost::is_any_of(" ")); + CartesianConfiguration cart_config{ CartesianConfiguration(group_name, link_name_attr.data(), + strVec2doubleVec(pos_ori_str), robot_model_) }; + + const auto& seeds_tree{ xyz_quat_tree.get_child(SEED_STR, empty_tree_) }; + if (seeds_tree != empty_tree_) + { + cart_config.setSeed(getJoints(seeds_tree, group_name)); + } + return cart_config; +} + +PtpJoint XmlTestdataLoader::getPtpJoint(const std::string& cmd_name) const +{ + CmdReader cmd_reader{ findCmd(cmd_name, PTPS_PATH_STR, PTP_STR) }; + std::string planning_group{ cmd_reader.getPlanningGroup() }; + + PtpJoint cmd; + cmd.setPlanningGroup(planning_group); + cmd.setVelocityScale(cmd_reader.getVelocityScale()); + cmd.setAccelerationScale(cmd_reader.getAccelerationScale()); + + cmd.setStartConfiguration(getJoints(cmd_reader.getStartPoseName(), planning_group)); + cmd.setGoalConfiguration(getJoints(cmd_reader.getEndPoseName(), planning_group)); + + return cmd; +} + +PtpJointCart XmlTestdataLoader::getPtpJointCart(const std::string& cmd_name) const +{ + CmdReader cmd_reader{ findCmd(cmd_name, PTPS_PATH_STR, PTP_STR) }; + std::string planning_group{ cmd_reader.getPlanningGroup() }; + + PtpJointCart cmd; + cmd.setPlanningGroup(planning_group); + cmd.setVelocityScale(cmd_reader.getVelocityScale()); + cmd.setAccelerationScale(cmd_reader.getAccelerationScale()); + + cmd.setStartConfiguration(getJoints(cmd_reader.getStartPoseName(), planning_group)); + cmd.setGoalConfiguration(getPose(cmd_reader.getEndPoseName(), planning_group)); + + return cmd; +} + +PtpCart XmlTestdataLoader::getPtpCart(const std::string& cmd_name) const +{ + CmdReader cmd_reader{ findCmd(cmd_name, PTPS_PATH_STR, PTP_STR) }; + std::string planning_group{ cmd_reader.getPlanningGroup() }; + + PtpCart cmd; + cmd.setPlanningGroup(planning_group); + cmd.setVelocityScale(cmd_reader.getVelocityScale()); + cmd.setAccelerationScale(cmd_reader.getAccelerationScale()); + + cmd.setStartConfiguration(getPose(cmd_reader.getStartPoseName(), planning_group)); + cmd.setGoalConfiguration(getPose(cmd_reader.getEndPoseName(), planning_group)); + + return cmd; +} + +LinJoint XmlTestdataLoader::getLinJoint(const std::string& cmd_name) const +{ + CmdReader cmd_reader{ findCmd(cmd_name, LINS_PATH_STR, LIN_STR) }; + std::string planning_group{ cmd_reader.getPlanningGroup() }; + + LinJoint cmd; + cmd.setPlanningGroup(planning_group); + cmd.setVelocityScale(cmd_reader.getVelocityScale()); + cmd.setAccelerationScale(cmd_reader.getAccelerationScale()); + + cmd.setStartConfiguration(getJoints(cmd_reader.getStartPoseName(), planning_group)); + cmd.setGoalConfiguration(getJoints(cmd_reader.getEndPoseName(), planning_group)); + + return cmd; +} + +LinCart XmlTestdataLoader::getLinCart(const std::string& cmd_name) const +{ + CmdReader cmd_reader{ findCmd(cmd_name, LINS_PATH_STR, LIN_STR) }; + std::string planning_group{ cmd_reader.getPlanningGroup() }; + + LinCart cmd; + cmd.setPlanningGroup(planning_group); + cmd.setVelocityScale(cmd_reader.getVelocityScale()); + cmd.setAccelerationScale(cmd_reader.getAccelerationScale()); + + cmd.setStartConfiguration(getPose(cmd_reader.getStartPoseName(), planning_group)); + cmd.setGoalConfiguration(getPose(cmd_reader.getEndPoseName(), planning_group)); + + return cmd; +} + +LinJointCart XmlTestdataLoader::getLinJointCart(const std::string& cmd_name) const +{ + CmdReader cmd_reader{ findCmd(cmd_name, LINS_PATH_STR, LIN_STR) }; + std::string planning_group{ cmd_reader.getPlanningGroup() }; + + LinJointCart cmd; + cmd.setPlanningGroup(planning_group); + cmd.setVelocityScale(cmd_reader.getVelocityScale()); + cmd.setAccelerationScale(cmd_reader.getAccelerationScale()); + + cmd.setStartConfiguration(getJoints(cmd_reader.getStartPoseName(), planning_group)); + cmd.setGoalConfiguration(getPose(cmd_reader.getEndPoseName(), planning_group)); + + return cmd; +} + +const pt::ptree::value_type& XmlTestdataLoader::findCmd(const std::string& cmd_name, const std::string& cmd_path, + const std::string& cmd_key) const +{ + // Search for node with given name. + const boost::property_tree::ptree& cmds_tree{ tree_.get_child(cmd_path, empty_tree_) }; + if (cmds_tree == empty_tree_) + { + throw TestDataLoaderReadingException("No list of commands of type \"" + cmd_key + "\" found"); + } + + return findNodeWithName(cmds_tree, cmd_name, cmd_key); +} + +CartesianCenter XmlTestdataLoader::getCartesianCenter(const std::string& cmd_name, + const std::string& planning_group) const +{ + const pt::ptree::value_type& cmd_node{ findCmd(cmd_name, CIRCS_PATH_STR, CIRC_STR) }; + std::string aux_pos_name; + try + { + aux_pos_name = cmd_node.second.get(CENTER_POS_STR); + } + catch (...) + { + throw TestDataLoaderReadingException("Did not find center of circ"); + } + + CartesianCenter aux; + aux.setConfiguration(getPose(aux_pos_name, planning_group)); + return aux; +} + +CartesianInterim XmlTestdataLoader::getCartesianInterim(const std::string& cmd_name, + const std::string& planning_group) const +{ + const pt::ptree::value_type& cmd_node{ findCmd(cmd_name, CIRCS_PATH_STR, CIRC_STR) }; + std::string aux_pos_name; + try + { + aux_pos_name = cmd_node.second.get(INTERMEDIATE_POS_STR); + } + catch (...) + { + throw TestDataLoaderReadingException("Did not find interim of circ"); + } + + CartesianInterim aux; + aux.setConfiguration(getPose(aux_pos_name, planning_group)); + return aux; +} + +CircCenterCart XmlTestdataLoader::getCircCartCenterCart(const std::string& cmd_name) const +{ + CmdReader cmd_reader{ findCmd(cmd_name, CIRCS_PATH_STR, CIRC_STR) }; + std::string planning_group{ cmd_reader.getPlanningGroup() }; + + CircCenterCart cmd; + cmd.setPlanningGroup(planning_group); + cmd.setVelocityScale(cmd_reader.getVelocityScale()); + cmd.setAccelerationScale(cmd_reader.getAccelerationScale()); + + cmd.setStartConfiguration(getPose(cmd_reader.getStartPoseName(), planning_group)); + cmd.setAuxiliaryConfiguration(getCartesianCenter(cmd_name, planning_group)); + cmd.setGoalConfiguration(getPose(cmd_reader.getEndPoseName(), planning_group)); + + return cmd; +} + +CircInterimCart XmlTestdataLoader::getCircCartInterimCart(const std::string& cmd_name) const +{ + CmdReader cmd_reader{ findCmd(cmd_name, CIRCS_PATH_STR, CIRC_STR) }; + std::string planning_group{ cmd_reader.getPlanningGroup() }; + + CircInterimCart cmd; + cmd.setPlanningGroup(planning_group); + cmd.setVelocityScale(cmd_reader.getVelocityScale()); + cmd.setAccelerationScale(cmd_reader.getAccelerationScale()); + + cmd.setStartConfiguration(getPose(cmd_reader.getStartPoseName(), planning_group)); + cmd.setAuxiliaryConfiguration(getCartesianInterim(cmd_name, planning_group)); + cmd.setGoalConfiguration(getPose(cmd_reader.getEndPoseName(), planning_group)); + + return cmd; +} + +CircJointInterimCart XmlTestdataLoader::getCircJointInterimCart(const std::string& cmd_name) const +{ + CmdReader cmd_reader{ findCmd(cmd_name, CIRCS_PATH_STR, CIRC_STR) }; + std::string planning_group{ cmd_reader.getPlanningGroup() }; + + CircJointInterimCart cmd; + cmd.setPlanningGroup(planning_group); + cmd.setVelocityScale(cmd_reader.getVelocityScale()); + cmd.setAccelerationScale(cmd_reader.getAccelerationScale()); + + cmd.setStartConfiguration(getJoints(cmd_reader.getStartPoseName(), planning_group)); + cmd.setAuxiliaryConfiguration(getCartesianInterim(cmd_name, planning_group)); + cmd.setGoalConfiguration(getJoints(cmd_reader.getEndPoseName(), planning_group)); + + return cmd; +} + +CircJointCenterCart XmlTestdataLoader::getCircJointCenterCart(const std::string& cmd_name) const +{ + CmdReader cmd_reader{ findCmd(cmd_name, CIRCS_PATH_STR, CIRC_STR) }; + std::string planning_group{ cmd_reader.getPlanningGroup() }; + + CircJointCenterCart cmd; + cmd.setPlanningGroup(planning_group); + cmd.setVelocityScale(cmd_reader.getVelocityScale()); + cmd.setAccelerationScale(cmd_reader.getAccelerationScale()); + + cmd.setStartConfiguration(getJoints(cmd_reader.getStartPoseName(), planning_group)); + cmd.setAuxiliaryConfiguration(getCartesianCenter(cmd_name, planning_group)); + cmd.setGoalConfiguration(getJoints(cmd_reader.getEndPoseName(), planning_group)); + + return cmd; +} + +Sequence XmlTestdataLoader::getSequence(const std::string& cmd_name) const +{ + Sequence seq; + + // Find sequence with given name and loop over all its cmds + const auto& sequence_cmd_tree{ findCmd(cmd_name, SEQUENCE_PATH_STR, BLEND_STR).second }; + for (const pt::ptree::value_type& seq_cmd : sequence_cmd_tree) + { + // Ignore attributes which are always the first element of a tree. + if (seq_cmd.first == XML_ATTR_STR) + { + continue; + } + + // Get name of blend cmd. + const boost::property_tree::ptree& cmd_name_attr = seq_cmd.second.get_child(NAME_PATH_STR, empty_tree_); + if (cmd_name_attr == empty_tree_) + { + throw TestDataLoaderReadingException("Did not find name of sequence cmd"); + } + + const std::string& cmd_name{ cmd_name_attr.data() }; + + // Get type of blend cmd + const boost::property_tree::ptree& type_name_attr{ seq_cmd.second.get_child(CMD_TYPE_PATH_STR, empty_tree_) }; + if (type_name_attr == empty_tree_) + { + throw TestDataLoaderReadingException("Did not find type of sequence cmd \"" + cmd_name + "\""); + } + const std::string& cmd_type{ type_name_attr.data() }; + + // Get blend radius of blend cmd. + double blend_radius{ seq_cmd.second.get(BLEND_RADIUS_PATH_STR, DEFAULT_BLEND_RADIUS) }; + + // Read current command from test data + Add command to sequence + seq.add(cmd_getter_funcs_.at(cmd_type)->getCmd(cmd_name), blend_radius); + } + + return seq; +} + +Gripper XmlTestdataLoader::getGripper(const std::string& cmd_name) const +{ + CmdReader cmd_reader{ findCmd(cmd_name, GRIPPERS_PATH_STR, GRIPPER_STR) }; + cmd_reader.setDefaultVelocityScale(DEFAULT_VEL_GRIPPER); + cmd_reader.setDefaultAccelerationScale(DEFAULT_ACC_GRIPPER); + std::string planning_group{ cmd_reader.getPlanningGroup() }; + + Gripper cmd; + cmd.setPlanningGroup(planning_group); + cmd.setVelocityScale(cmd_reader.getVelocityScale()); + cmd.setAccelerationScale(cmd_reader.getAccelerationScale()); + + cmd.setStartConfiguration(getJoints(cmd_reader.getStartPoseName(), planning_group)); + cmd.setGoalConfiguration(getJoints(cmd_reader.getEndPoseName(), planning_group)); + + return cmd; +} + +} // namespace pilz_industrial_motion_planner_testutils diff --git a/moveit_setup_assistant/src/tools/moveit_config_data.cpp b/moveit_setup_assistant/src/tools/moveit_config_data.cpp index 0946efe9f7..e5d52a82f9 100644 --- a/moveit_setup_assistant/src/tools/moveit_config_data.cpp +++ b/moveit_setup_assistant/src/tools/moveit_config_data.cpp @@ -518,6 +518,8 @@ bool MoveItConfigData::outputFakeControllersYAML(const std::string& file_path) const std::vector& joint_models = joint_model_group->getActiveJointModels(); emitter << YAML::Key << "name"; emitter << YAML::Value << "fake_" + group_it->name_ + "_controller"; + emitter << YAML::Key << "type"; + emitter << YAML::Value << "$(arg execution_type)"; emitter << YAML::Key << "joints"; emitter << YAML::Value << YAML::BeginSeq; diff --git a/moveit_setup_assistant/src/widgets/configuration_files_widget.cpp b/moveit_setup_assistant/src/widgets/configuration_files_widget.cpp index 3f7fda2bdb..10eb45dd6b 100644 --- a/moveit_setup_assistant/src/widgets/configuration_files_widget.cpp +++ b/moveit_setup_assistant/src/widgets/configuration_files_widget.cpp @@ -297,6 +297,17 @@ bool ConfigurationFilesWidget::loadGenFiles() file.write_on_changes = 0; // Can they be changed? gen_files_.push_back(file); + // cartesian_limits.yaml -------------------------------------------------------------------------------------- + file.file_name_ = "cartesian_limits.yaml"; + file.rel_path_ = config_data_->appendPaths(config_path, file.file_name_); + template_path = config_data_->appendPaths(config_data_->template_package_path_, file.rel_path_); + file.description_ = "Cartesian velocity for planning in the workspace." + "The velocity is used by pilz industrial motion planner as maximum velocity for cartesian " + "planning requests scaled by the velocity scaling factor of an individual planning request."; + file.gen_func_ = boost::bind(&ConfigurationFilesWidget::copyTemplate, this, template_path, _1); + file.write_on_changes = 0; // Can they be changed? + gen_files_.push_back(file); + // fake_controllers.yaml -------------------------------------------------------------------------------------- file.file_name_ = "fake_controllers.yaml"; file.rel_path_ = config_data_->appendPaths(config_path, file.file_name_); @@ -381,6 +392,18 @@ bool ConfigurationFilesWidget::loadGenFiles() file.write_on_changes = 0; gen_files_.push_back(file); + // pilz_industrial_motion_planner_planning_pipeline.launch + // -------------------------------------------------------------------------------------- + file.file_name_ = "pilz_industrial_motion_planner_planning_pipeline.launch.xml"; + file.rel_path_ = config_data_->appendPaths(launch_path, file.file_name_); + template_path = config_data_->appendPaths(template_launch_path, file.file_name_); + file.description_ = "Intended to be included in other launch files that require the Pilz industrial motion planner " + "planning plugin. Defines the proper plugin name on the parameter server and a default selection " + "of planning request adapters."; + file.gen_func_ = boost::bind(&ConfigurationFilesWidget::copyTemplate, this, template_path, _1); + file.write_on_changes = 0; + gen_files_.push_back(file); + // chomp_planning_pipeline.launch // -------------------------------------------------------------------------------------- file.file_name_ = "chomp_planning_pipeline.launch.xml"; diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/config/cartesian_limits.yaml b/moveit_setup_assistant/templates/moveit_config_pkg_template/config/cartesian_limits.yaml new file mode 100644 index 0000000000..7df72f693b --- /dev/null +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/config/cartesian_limits.yaml @@ -0,0 +1,5 @@ +cartesian_limits: + max_trans_vel: 1 + max_trans_acc: 2.25 + max_trans_dec: -5 + max_rot_vel: 1.57 diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/chomp_planning_pipeline.launch.xml b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/chomp_planning_pipeline.launch.xml index 1ec94ef5ae..a28ad6d52b 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/chomp_planning_pipeline.launch.xml +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/chomp_planning_pipeline.launch.xml @@ -1,20 +1,30 @@ - - - - - + + - - - + + - + + + + + + + + + + + + + + diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/fake_moveit_controller_manager.launch.xml b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/fake_moveit_controller_manager.launch.xml index 06b3a93e74..f668745bb0 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/fake_moveit_controller_manager.launch.xml +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/fake_moveit_controller_manager.launch.xml @@ -1,9 +1,12 @@ + + + - + diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/move_group.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/move_group.launch index b41620c229..6637d21031 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/move_group.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/move_group.launch @@ -15,6 +15,7 @@ + @@ -46,6 +47,8 @@ + + @@ -53,6 +56,7 @@ + @@ -68,8 +72,6 @@ - - diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/ompl_planning_pipeline.launch.xml b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/ompl_planning_pipeline.launch.xml index 7dbc6e96b7..4cc5f7b19c 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/ompl_planning_pipeline.launch.xml +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/ompl_planning_pipeline.launch.xml @@ -3,6 +3,12 @@ + + + + + + + + diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/pilz_industrial_motion_planner_planning_pipeline.launch.xml b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/pilz_industrial_motion_planner_planning_pipeline.launch.xml new file mode 100644 index 0000000000..ac6272e235 --- /dev/null +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/pilz_industrial_motion_planner_planning_pipeline.launch.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/planning_context.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/planning_context.launch index 54efbec4e7..635179b3b8 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/planning_context.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/planning_context.launch @@ -14,6 +14,7 @@ + diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/planning_pipeline.launch.xml b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/planning_pipeline.launch.xml index b58d3f4660..f1b5c7fcec 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/planning_pipeline.launch.xml +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/planning_pipeline.launch.xml @@ -5,6 +5,15 @@ - + + + + + + + + + + diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/trajectory_execution.launch.xml b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/trajectory_execution.launch.xml index 9354d7a7c1..3e5ee656c9 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/trajectory_execution.launch.xml +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/trajectory_execution.launch.xml @@ -2,6 +2,8 @@ + + @@ -15,6 +17,8 @@ - + + + From 7e3f4bbec4413feb15e05843a3480139279cb30b Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Thu, 25 Mar 2021 16:27:15 -0600 Subject: [PATCH 056/179] Migrate from Travis to GitHub Actions --- .ci.prepare_codecov | 21 ++++++ .ci.upstream.rosinstall | 5 ++ .github/{config.yml => config.yaml} | 0 .github/workflows/ci.yaml | 101 ++++++++++++++++++++++++++++ .github/workflows/format.yaml | 20 ++++++ .pre-commit-config.yaml | 43 ++++++++++++ .travis.yml | 38 ----------- README.md | 5 +- 8 files changed, 193 insertions(+), 40 deletions(-) create mode 100755 .ci.prepare_codecov create mode 100644 .ci.upstream.rosinstall rename .github/{config.yml => config.yaml} (100%) create mode 100644 .github/workflows/ci.yaml create mode 100644 .github/workflows/format.yaml create mode 100644 .pre-commit-config.yaml delete mode 100644 .travis.yml diff --git a/.ci.prepare_codecov b/.ci.prepare_codecov new file mode 100755 index 0000000000..91119f5dc1 --- /dev/null +++ b/.ci.prepare_codecov @@ -0,0 +1,21 @@ +#!/bin/bash +pushd $BASEDIR + +BLUE='\033[0;34m' +NOCOLOR='\033[0m' + +apt-get install -qq lcov + +echo -e "${BLUE}Capture coverage info${NOCOLOR}" +lcov --capture --directory target_ws --output-file coverage.info + +echo -e "${BLUE}Extract repository files${NOCOLOR}" +lcov --extract coverage.info "$BASEDIR/target_ws/src/$TARGET_REPO_NAME/*" --output-file coverage.info + +echo -e "${BLUE}Filter out test files${NOCOLOR}" +lcov --remove coverage.info '*/test/*' --output-file coverage.info + +echo -e "${BLUE}Output coverage data for debugging${NOCOLOR}" +lcov --list coverage.info + +popd diff --git a/.ci.upstream.rosinstall b/.ci.upstream.rosinstall new file mode 100644 index 0000000000..3680219519 --- /dev/null +++ b/.ci.upstream.rosinstall @@ -0,0 +1,5 @@ +# This file is intended for use by CI +- git: + local-name: moveit_resources + uri: https://github.com/ros-planning/moveit_resources.git + version: master diff --git a/.github/config.yml b/.github/config.yaml similarity index 100% rename from .github/config.yml rename to .github/config.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000000..b56b84f1d5 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,101 @@ +# This config uses industrial_ci (https://github.com/ros-industrial/industrial_ci.git). +# For troubleshooting, see readme (https://github.com/ros-industrial/industrial_ci/blob/master/README.rst) + +name: CI + +on: + workflow_dispatch: + pull_request: + push: + branches: + - master + - "[kmn]*-devel" + +jobs: + industrial_ci: + strategy: + matrix: + env: + - IMAGE: melodic-ci + CCOV: true + - IMAGE: melodic-ci-shadow-fixed + IKFAST_TEST: true + CATKIN_LINT: true + env: + DOCKER_IMAGE: moveit/moveit:${{ matrix.env.IMAGE }} + UPSTREAM_WORKSPACE: .ci.upstream.rosinstall + AFTER_SETUP_UPSTREAM_WORKSPACE: vcs pull $BASEDIR/upstream_ws/src + BEFORE_TARGET_TEST_EMBED: ${{ matrix.env.IKFAST_TEST && 'set +u && source moveit_kinematics/test/test_ikfast_plugins.sh && set -u' || '' }} + AFTER_RUN_TARGET_TEST: ${{ matrix.env.CCOV && './.ci.prepare_codecov' || '' }} + TARGET_CMAKE_ARGS: > + -DCMAKE_BUILD_TYPE=${{ matrix.env.CCOV && 'RelWithDebInfo' || 'Release'}} + ${{ matrix.env.CCOV && '-DCMAKE_CXX_FLAGS="--coverage" --no-warn-unused-cli' || '' }} + CCACHE_DIR: ${{ github.workspace }}/.ccache + BASEDIR: ${{ github.workspace }}/.work + CACHE_PREFIX: ${{ matrix.env.IMAGE }}${{ matrix.env.CCOV && '-ccov' || '' }} + CLANG_TIDY_BASE_REF: ${{ github.base_ref || github.ref }} + + name: ${{ matrix.env.IMAGE }}${{ matrix.env.CATKIN_LINT && ' + catkin_lint' || ''}}${{ matrix.env.CCOV && ' + ccov' || ''}}${{ matrix.env.IKFAST_TEST && ' + ikfast' || ''}}${{ matrix.env.CLANG_TIDY && ' + clang-tidy' || '' }} + runs-on: ubuntu-latest + steps: + - name: "Free up disk space" + if: ${{ matrix.env.CCOV }} + run: | + sudo apt-get -qq purge build-essential ghc* + sudo apt-get clean + # cleanup docker images not used by us + docker system prune -af + # shift ccache folder to /mnt on a separate disk + sudo mkdir /mnt/ccache + mkdir ${{ env.CCACHE_DIR }} + sudo mount --bind ${{ env.CCACHE_DIR }} /mnt/ccache + # free up a lot of stuff from /usr/local + sudo rm -rf /usr/local/* + df -h + - uses: actions/checkout@v2 + - name: cache upstream_ws + uses: pat-s/always-upload-cache@v2.1.3 + with: + path: ${{ env.BASEDIR }}/upstream_ws + key: upstream_ws-${{ env.CACHE_PREFIX }}-${{ hashFiles('.ci.upstream.rosinstall') }}-${{ github.run_id }} + restore-keys: | + upstream_ws-${{ env.CACHE_PREFIX }}-${{ hashFiles('.ci.upstream.rosinstall') }} + # The target directory cache doesn't include the source directory because + # that comes from the checkout. See "prepare target_ws for cache" task below + - name: cache target_ws + if: ${{ ! matrix.env.CCOV }} + uses: pat-s/always-upload-cache@v2.1.3 + with: + path: ${{ env.BASEDIR }}/target_ws + key: target_ws-${{ env.CACHE_PREFIX }}-${{ hashFiles('**/CMakeLists.txt', '**/package.xml') }}-${{ github.run_id }} + restore-keys: | + target_ws-${{ env.CACHE_PREFIX }}-${{ hashFiles('**/CMakeLists.txt', '**/package.xml') }} + - name: cache ccache + uses: pat-s/always-upload-cache@v2.1.3 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-${{ env.CACHE_PREFIX }}-${{ github.sha }}-${{ github.run_id }} + restore-keys: | + ccache-${{ env.CACHE_PREFIX }}-${{ github.sha }} + ccache-${{ env.CACHE_PREFIX }} + - name: industrial_ci + uses: ros-industrial/industrial_ci@master + env: ${{ matrix.env }} + - name: upload test artifacts (on failure) + uses: actions/upload-artifact@v2 + if: failure() + with: + name: test-results + path: ${{ env.BASEDIR }}/target_ws/**/test_results/**/*.xml + - name: upload codecov report + uses: codecov/codecov-action@v1 + if: ${{ matrix.env.CCOV }} + with: + files: ${{ env.BASEDIR }}/coverage.info + - name: prepare target_ws for cache + if: ${{ always() && ! matrix.env.CCOV }} + run: | + du -sh ${{ env.BASEDIR }}/target_ws + sudo find ${{ env.BASEDIR }}/target_ws -wholename '*/test_results/*' -delete + sudo rm -rf ${{ env.BASEDIR }}/target_ws/src + du -sh ${{ env.BASEDIR }}/target_ws diff --git a/.github/workflows/format.yaml b/.github/workflows/format.yaml new file mode 100644 index 0000000000..87e7617dec --- /dev/null +++ b/.github/workflows/format.yaml @@ -0,0 +1,20 @@ +# This is a format job. Pre-commit has a first-party GitHub action, so we use +# that: https://github.com/pre-commit/action + +name: Format + +on: + workflow_dispatch: + pull_request: + push: + +jobs: + pre-commit: + name: pre-commit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - name: Install clang-format-10 + run: sudo apt-get install clang-format-10 + - uses: pre-commit/action@v2.0.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..b380f58c88 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,43 @@ +# To use: +# +# pre-commit run -a +# +# Or: +# +# pre-commit install # (runs every time you commit in git) +# +# To update this file: +# +# pre-commit autoupdate +# +# See https://github.com/pre-commit/pre-commit + +repos: + # Standard hooks + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.4.0 + hooks: + - id: check-added-large-files + - id: check-case-conflict + - id: check-merge-conflict + - id: check-symlinks + - id: check-yaml + - id: debug-statements + - id: end-of-file-fixer + - id: mixed-line-ending + - id: trailing-whitespace + + - repo: https://github.com/psf/black + rev: 20.8b1 + hooks: + - id: black + + - repo: local + hooks: + - id: clang-format + name: clang-format + description: Format files with ClangFormat. + entry: clang-format-10 + language: system + files: \.(c|cc|cxx|cpp|frag|glsl|h|hpp|hxx|ih|ispc|ipp|java|js|m|proto|vert)$ + args: ['-fallback-style=none', '-i'] diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c05d44d40f..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,38 +0,0 @@ -# This config file for Travis CI utilizes https://github.com/ros-planning/moveit_ci/ package. -os: linux -dist: bionic # distro used by Travis, moveit_ci uses the docker image's distro -services: - - docker -language: cpp -cache: ccache -compiler: gcc - -notifications: - email: true - -env: - global: - - MOVEIT_CI_TRAVIS_TIMEOUT=85 # Travis grants us 90 min, but we add a safety margin of 5 min - - ROS_DISTRO=melodic - - ROS_REPO=ros - - UPSTREAM_WORKSPACE=moveit.rosinstall - - CXXFLAGS="-Wall -Wextra -Wwrite-strings -Wunreachable-code -Wpointer-arith -Wredundant-decls -Wno-unused-parameter -Wno-unused-but-set-parameter -Wno-unused-function" - - WARNINGS_OK=false - -jobs: - fast_finish: true - include: - - env: TEST="clang-format catkin_lint" - - env: TEST=code-coverage - - env: ROS_DISTRO=melodic - - env: BEFORE_DOCKER_SCRIPT="source moveit_kinematics/test/test_ikfast_plugins.sh" - - if: branch =~ /^(.*-devel|master)$/ - env: ROS_REPO=ros-shadow-fixed - allow_failures: - - env: TEST=code-coverage - -before_script: - - git clone -q --depth=1 https://github.com/ros-planning/moveit_ci.git .moveit_ci - -script: - - .moveit_ci/travis.sh diff --git a/README.md b/README.md index bfcc3bad5d..b8ffdc6312 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,10 @@ For MoveIt 2.0 development, see [moveit2](https://github.com/ros-planning/moveit service | Indigo | Kinetic | Melodic | Master ---------- | ------ | ------- | ------- | ------ -Travis | [![Build Status](https://travis-ci.com/ros-planning/moveit.svg?branch=indigo-devel)](https://travis-ci.com/ros-planning/moveit/branches) | [![Build Status](https://travis-ci.com/ros-planning/moveit.svg?branch=kinetic-devel)](https://travis-ci.com/ros-planning/moveit/branches) | [![Build Status](https://travis-ci.com/ros-planning/moveit.svg?branch=melodic-devel)](https://travis-ci.com/ros-planning/moveit/branches) | [![Build Status](https://travis-ci.com/ros-planning/moveit.svg?branch=master)](https://travis-ci.com/ros-planning/moveit/branches) | +Travis | [![Build Status](https://travis-ci.com/ros-planning/moveit.svg?branch=indigo-devel)](https://travis-ci.com/ros-planning/moveit/branches) | [![Build Status](https://travis-ci.com/ros-planning/moveit.svg?branch=kinetic-devel)](https://travis-ci.com/ros-planning/moveit/branches) | N/A | N/A | +GitHub | N/A | N/A | [![Format](https://github.com/ros-planning/moveit/actions/workflows/format.yaml/badge.svg?branch=melodic-devel)](https://github.com/ros-planning/moveit/actions/workflows/format.yaml?query=branch%3Amelodic-devel) [![CI](https://github.com/ros-planning/moveit/actions/workflows/ci.yaml/badge.svg?branch=melodic-devel)](https://github.com/ros-planning/moveit/actions/workflows/ci.yaml?query=branch%3Amelodic-devel) | [![Format](https://github.com/ros-planning/moveit/actions/workflows/format.yaml/badge.svg?branch=master)](https://github.com/ros-planning/moveit/actions/workflows/format.yaml?query=branch%3Amaster) [![CI](https://github.com/ros-planning/moveit/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/ros-planning/moveit/actions/workflows/ci.yaml?query=branch%3Amaster) | build farm | [![Build Status](http://build.ros.org/buildStatus/icon?job=Idev__moveit__ubuntu_trusty_amd64)](http://build.ros.org/job/Idev__moveit__ubuntu_trusty_amd64) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kdev__moveit__ubuntu_xenial_amd64)](http://build.ros.org/job/Kdev__moveit__ubuntu_xenial_amd64) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mdev__moveit__ubuntu_bionic_amd64)](http://build.ros.org/job/Mdev__moveit__ubuntu_bionic_amd64) | N/A | - +CodeCov | N/A | N/A | [![codecov](https://codecov.io/gh/ros-planning/moveit/branch/melodic-devel/graph/badge.svg?token=W7uHKcY0ly)](https://codecov.io/gh/ros-planning/moveit) | [![codecov](https://codecov.io/gh/ros-planning/moveit/branch/master/graph/badge.svg?token=W7uHKcY0ly)](https://codecov.io/gh/ros-planning/moveit) | ## Docker Containers From 20bc17c36a4c9e2af4db8e1368aa4332ddd82e85 Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Thu, 25 Mar 2021 16:31:16 -0600 Subject: [PATCH 057/179] Fix formatting errors --- moveit/scripts/create_maintainer_table.py | 124 +++- moveit/scripts/create_readme_table.py | 80 +- .../bin/moveit_commander_cmdline.py | 104 ++- moveit_commander/demos/pick.py | 11 +- moveit_commander/demos/plan.py | 16 +- .../demos/plan_with_constraints.py | 10 +- moveit_commander/setup.py | 4 +- .../src/moveit_commander/conversions.py | 15 +- .../src/moveit_commander/exception.py | 4 +- .../src/moveit_commander/interpreter.py | 496 ++++++++++--- .../src/moveit_commander/move_group.py | 297 ++++++-- .../planning_scene_interface.py | 51 +- .../src/moveit_commander/robot.py | 19 +- .../moveit_commander/roscpp_initializer.py | 4 +- .../test/python_moveit_commander.py | 42 +- .../test/python_moveit_commander_ns.py | 22 +- .../python_moveit_commander_ros_namespace.py | 12 +- .../test/python_time_parameterization.py | 46 +- .../src/background_processing.cpp | 2 +- .../src/collision_world.cpp | 2 +- .../test/test_all_valid.cpp | 2 +- .../collision_detector_fcl_plugin_loader.h | 2 +- .../collision_detector_fcl_description.xml | 2 +- .../dox/constraint_samplers.dox | 2 +- .../src/default_constraint_samplers.cpp | 2 +- .../src/union_constraint_sampler.cpp | 2 +- .../distance_field/src/distance_field.cpp | 2 +- .../dynamics_solver/src/dynamics_solver.cpp | 2 +- .../src/planning_interface.cpp | 2 +- .../src/planning_request_adapter.cpp | 2 +- .../robot_model/src/fixed_joint_model.cpp | 2 +- moveit_core/robot_model/src/link_model.cpp | 2 +- .../src/order_robot_model_items.inc | 2 +- .../robot_model/src/planar_joint_model.cpp | 2 +- .../robot_model/src/prismatic_joint_model.cpp | 2 +- .../collision_distance_field_ros/Makefile | 2 +- .../collision_distance_field_ros/mainpage.dox | 4 +- .../collision_distance_field_ros/manifest.xml | 2 - .../v1/kinematics_cache/Makefile | 2 +- .../v1/kinematics_cache/mainpage.dox | 4 +- .../v1/kinematics_cache_ros/Makefile | 2 +- .../v1/kinematics_cache_ros/manifest.xml | 2 - .../v2/kinematics_cache/CMakeLists.txt | 1 - .../CMakeLists.txt | 6 +- .../scripts/create_ikfast_moveit_plugin.py | 701 ++++++++++-------- .../scripts/round_collada_numbers.py | 68 +- .../kdl_kinematics_plugin/CMakeLists.txt | 6 +- .../lma_kinematics_plugin/CMakeLists.txt | 2 +- .../srv_kinematics_plugin/CMakeLists.txt | 2 +- .../chomp_interface/test/chomp_planning.yaml | 1 - .../chomp_interface/test/joint_limits.yaml | 2 +- .../CMakeLists.txt | 4 +- .../doc/.gitignore | 8 +- .../doc/MotionBlendAlgorithmDescription.tex | 6 +- .../prbt/launch/test_context.launch | 2 +- .../test/test_robots/testpoints.py | 191 +++-- .../diagrams/diag_class_circ_auxiliary.uxf | 10 +- .../doc/diagrams/diag_class_commands.uxf | 8 +- .../diag_seq_testdataloader_usage.uxf | 2 +- .../checks.h | 2 +- .../sbpl/core/sbpl_interface/Makefile | 2 +- .../sbpl/core/sbpl_interface/manifest.xml | 2 - .../sbpl/ros/sbpl_interface_ros/Makefile | 2 +- .../sbpl/ros/sbpl_interface_ros/manifest.xml | 2 - .../CMakeLists.txt | 6 +- .../benchmarks/examples/demo_obstacles.yaml | 1 - .../examples/demo_panda_all_planners.launch | 1 - .../examples/demo_panda_all_planners.yaml | 1 - .../scripts/moveit_benchmark_statistics.py | 569 +++++++++----- moveit_ros/move_group/scripts/load_map | 8 +- moveit_ros/move_group/scripts/save_map | 9 +- .../test/test_cancel_before_plan_execution.py | 32 +- ...est_check_state_validity_in_empty_scene.py | 45 +- moveit_ros/moveit_servo/README.md | 2 +- .../src/teleop_examples/spacenav_to_twist.cpp | 2 +- .../test/config/initial_position.yaml | 1 - .../State_Operations_i2600K_PR2_Groovy.txt | 1 - ...ng_request_adapters_plugin_description.xml | 2 +- .../dox/trajectory_execution.dox | 2 +- .../lib/plugin_description.xml | 1 - .../py_bindings_tools/dox/py_bindings.dox | 2 +- moveit_ros/planning_interface/setup.py | 6 +- moveit_ros/planning_interface/test/cleanup.py | 13 +- .../planning_interface/test/moveit_cpp.yaml | 2 +- .../test/python_move_group.py | 61 +- .../test/python_move_group_ns.py | 28 +- .../test/robot_state_update.py | 24 +- .../planning_interface/test/serialize_msg.py | 16 +- .../planning_interface/test/test_cleanup.py | 5 +- moveit_ros/visualization/setup.py | 4 +- .../moveitjoy_module.py | 201 +++-- .../visualization/test/test_moveit_joy.py | 8 +- moveit_ros/warehouse/warehouse/Makefile | 2 +- .../warehouse/warehouse/src/db_path_config.py | 12 +- .../launch/demo_gazebo.launch | 2 +- .../launch/gdb_settings.gdb | 2 +- .../moveit_controller_manager.launch.xml | 2 +- 97 files changed, 2327 insertions(+), 1185 deletions(-) diff --git a/moveit/scripts/create_maintainer_table.py b/moveit/scripts/create_maintainer_table.py index af7615c2a9..3f3878443d 100644 --- a/moveit/scripts/create_maintainer_table.py +++ b/moveit/scripts/create_maintainer_table.py @@ -8,80 +8,129 @@ import webbrowser from catkin_pkg.packages import find_packages -maintainers_dict = {"Ioan Sucan" : "isucan", - "Michael Ferguson" : "mikeferguson", - "Sachin Chitta" : "sachinchitta", - "G.A. vd. Hoorn" : "gavanderhoorn", - "Dave Coleman" : "davetcoleman", - "Acorn Pooley" : "acorn", - "Jon Binney" : "jonbinney", - "Matei Ciocarlie" : "mateiciocarlie", - "Michael Görner".decode('utf8') : "v4hn", - "Robert Haschke" : "rhaschke", - "Ian McMahon" : "IanTheEngineer", - "Isaac I. Y. Saito" : "130s", - "Mathias Lüdtke".decode('utf8') : "ipa-mdl", - "Ryan Luna" : "ryanluna", - "Chittaranjan Srinivas Swaminathan" : "ksatyaki", - "Chittaranjan S Srinivas" : "ksatyaki" +maintainers_dict = { + "Ioan Sucan": "isucan", + "Michael Ferguson": "mikeferguson", + "Sachin Chitta": "sachinchitta", + "G.A. vd. Hoorn": "gavanderhoorn", + "Dave Coleman": "davetcoleman", + "Acorn Pooley": "acorn", + "Jon Binney": "jonbinney", + "Matei Ciocarlie": "mateiciocarlie", + "Michael Görner".decode("utf8"): "v4hn", + "Robert Haschke": "rhaschke", + "Ian McMahon": "IanTheEngineer", + "Isaac I. Y. Saito": "130s", + "Mathias Lüdtke".decode("utf8"): "ipa-mdl", + "Ryan Luna": "ryanluna", + "Chittaranjan Srinivas Swaminathan": "ksatyaki", + "Chittaranjan S Srinivas": "ksatyaki", } + def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) + def author_to_github(maintainer): try: name = maintainers_dict[maintainer.name] except KeyError: - eprint( "Missing maintainer: ", maintainer.name) + eprint("Missing maintainer: ", maintainer.name) name = maintainer.email return name + def template_file(src, dst, subs): print("++ Templating '{0}'".format(src)) - with open(src, 'r') as f: + with open(src, "r") as f: data = f.read() for k, v in subs.items(): data = data.replace(k, v) - with open(dst, 'w+') as f: + with open(dst, "w+") as f: f.write(data) print("++ Webpage ready at '{0}'".format(dst)) webbrowser.open(dst) + def create_travis_badge(package_name): - output = '' + output = "" # Indigo output += "" - output += "
    " + output += ( + "" + ) output += "" - output += "" + output += ( + "" + ) output += "" # Jade output += "" - output += "" + output += ( + "" + ) output += "" - output += "" + output += ( + "" + ) output += "" # Kinetic output += "" - output += "" + output += ( + "" + ) output += "" - output += "" + output += ( + "" + ) output += "" return output -def get_first_folder(path) : - head,tail = os.path.split(path) + +def get_first_folder(path): + head, tail = os.path.split(path) components = [] - while len(tail)>0: - components.insert(0,tail) - head,tail = os.path.split(head) + while len(tail) > 0: + components.insert(0, tail) + head, tail = os.path.split(head) return components[0] + def populate_package_data(path, package): - output = "" + package.name + "" + output = ( + "" + + package.name + + "" + ) output += "" + package.version + "" output += "" first = True @@ -96,11 +145,12 @@ def populate_package_data(path, package): output += create_travis_badge(package.name) return output + def list_moveit_packages(): """ Creates MoveIt! List """ - output = '' + output = "" packages = find_packages(os.getcwd()) for path, package in packages.items(): @@ -110,9 +160,11 @@ def list_moveit_packages(): # Save to file basepath = os.path.dirname(os.path.realpath(__file__)) - template_file(os.path.join(basepath, 'maintainer_table_template.html'), - os.path.join(basepath, 'index.html'), - {'CONTENTS' : output}) + template_file( + os.path.join(basepath, "maintainer_table_template.html"), + os.path.join(basepath, "index.html"), + {"CONTENTS": output}, + ) if __name__ == "__main__": diff --git a/moveit/scripts/create_readme_table.py b/moveit/scripts/create_readme_table.py index 9a5af08554..db67b94c85 100644 --- a/moveit/scripts/create_readme_table.py +++ b/moveit/scripts/create_readme_table.py @@ -8,45 +8,62 @@ import catkin_pkg from catkin_pkg.packages import find_packages + def create_header(ros_ubuntu_dict): - ros_distros = sorted(ros_ubuntu_dict.keys()) - section_header = "## ROS Buildfarm\n" - header="MoveIt! Package" - header_lines = '-'*len(header) - for ros in ros_distros: - source = ' '.join([ros.capitalize(), "Source"]) - debian = ' '.join([ros.capitalize(), "Debian"]) - header = ' | '.join([header, source, debian]) - header_lines = ' | '.join([header_lines, '-'*len(source), '-'*len(debian)]) - return '\n'.join([section_header, header, header_lines]) + ros_distros = sorted(ros_ubuntu_dict.keys()) + section_header = "## ROS Buildfarm\n" + header = "MoveIt! Package" + header_lines = "-" * len(header) + for ros in ros_distros: + source = " ".join([ros.capitalize(), "Source"]) + debian = " ".join([ros.capitalize(), "Debian"]) + header = " | ".join([header, source, debian]) + header_lines = " | ".join([header_lines, "-" * len(source), "-" * len(debian)]) + return "\n".join([section_header, header, header_lines]) + def define_urls(target, params): - if target == 'src': - params['job'] = "{R}src_u{U}__{package}__ubuntu_{ubuntu}__source".format(**params) - params['url'] = "{base_url}/view/{R}src_u{U}/job/{job}".format(**params) - elif target == 'bin': - params['job'] = "{R}bin_u{U}64__{package}__ubuntu_{ubuntu}_amd64__binary".format(**params) - params['url'] = "{base_url}/view/{R}bin_u{U}64/job/{job}".format(**params) + if target == "src": + params["job"] = "{R}src_u{U}__{package}__ubuntu_{ubuntu}__source".format( + **params + ) + params["url"] = "{base_url}/view/{R}src_u{U}/job/{job}".format(**params) + elif target == "bin": + params[ + "job" + ] = "{R}bin_u{U}64__{package}__ubuntu_{ubuntu}_amd64__binary".format(**params) + params["url"] = "{base_url}/view/{R}bin_u{U}64/job/{job}".format(**params) + def create_line(package, ros_ubuntu_dict): ros_distros = sorted(ros_ubuntu_dict.keys()) - line = '\n' + package + line = "\n" + package print(package, file=sys.stderr) for ros in ros_distros: ubuntu = ros_ubuntu_dict[ros] - params = dict(R=ros[0].upper(), U=ubuntu[0].upper(), ubuntu=ubuntu.lower(), - package=package, base_url="http://build.ros.org") - for target in ['src', 'bin']: + params = dict( + R=ros[0].upper(), + U=ubuntu[0].upper(), + ubuntu=ubuntu.lower(), + package=package, + base_url="http://build.ros.org", + ) + for target in ["src", "bin"]: define_urls(target, params) - response = requests.get(params['url']).status_code + response = requests.get(params["url"]).status_code if response < 400: # success - line += ' | [![Build Status]({base_url}/buildStatus/icon?job={job})]({url})'.format(**params) + line += " | [![Build Status]({base_url}/buildStatus/icon?job={job})]({url})".format( + **params + ) else: # error - line += ' | ' - print(' {}: {} {}'.format(ros, response, params['url']), file=sys.stderr) + line += " | " + print( + " {}: {} {}".format(ros, response, params["url"]), file=sys.stderr + ) return line + def create_moveit_buildfarm_table(): """ Creates MoveIt! buildfarm badge table @@ -55,13 +72,19 @@ def create_moveit_buildfarm_table(): # combinations for supported distribitions. For instance, in Noetic, # remove {"indigo":"trusty"} and add {"noetic":"fbuntu"} with "fbuntu" # being whatever the 20.04 distro is named - supported_distro_ubuntu_dict = {"indigo":"trusty", "kinetic":"xenial", "melodic":"bionic"} + supported_distro_ubuntu_dict = { + "indigo": "trusty", + "kinetic": "xenial", + "melodic": "bionic", + } - all_packages = sorted([package.name for _, package in find_packages(os.getcwd()).items()]) + all_packages = sorted( + [package.name for _, package in find_packages(os.getcwd()).items()] + ) moveit_packages = list() other_packages = list() for package in all_packages: - if package.startswith('moveit'): + if package.startswith("moveit"): moveit_packages.append(package) else: other_packages.append(package) @@ -69,8 +92,9 @@ def create_moveit_buildfarm_table(): buildfarm_table = create_header(supported_distro_ubuntu_dict) for package in moveit_packages: - buildfarm_table += create_line(package, supported_distro_ubuntu_dict) + buildfarm_table += create_line(package, supported_distro_ubuntu_dict) print(buildfarm_table) + if __name__ == "__main__": sys.exit(create_moveit_buildfarm_table()) diff --git a/moveit_commander/bin/moveit_commander_cmdline.py b/moveit_commander/bin/moveit_commander_cmdline.py index fd425d3a82..d045270fee 100755 --- a/moveit_commander/bin/moveit_commander_cmdline.py +++ b/moveit_commander/bin/moveit_commander_cmdline.py @@ -4,35 +4,43 @@ import roslib import rospy + try: import readline except ImportError: - import pyreadline as readline # for Windows + import pyreadline as readline # for Windows import sys import os import signal import argparse -from moveit_commander import MoveGroupCommandInterpreter, MoveGroupInfoLevel, roscpp_initialize, roscpp_shutdown +from moveit_commander import ( + MoveGroupCommandInterpreter, + MoveGroupInfoLevel, + roscpp_initialize, + roscpp_shutdown, +) # python3 has renamed raw_input to input: https://www.python.org/dev/peps/pep-3111 # Here, we use the new input(). Hence, for python2, we redirect raw_input to input try: import __builtin__ # This is named builtin in python3 - input = getattr(__builtin__, 'raw_input') + + input = getattr(__builtin__, "raw_input") except (ImportError, AttributeError): pass + class bcolors: - HEADER = '\033[95m' - OKBLUE = '\033[94m' - OKGREEN = '\033[92m' - WARNING = '\033[93m' - FAIL = '\033[91m' - ENDC = '\033[0m' + HEADER = "\033[95m" + OKBLUE = "\033[94m" + OKGREEN = "\033[92m" + WARNING = "\033[93m" + FAIL = "\033[91m" + ENDC = "\033[0m" -class SimpleCompleter(object): +class SimpleCompleter(object): def __init__(self, options): self.options = options @@ -52,13 +60,13 @@ def complete(self, text, state): # This is the first time for this text, so build a match list. if text: if len(prefix) == 0: - self.matches = sorted([s - for s in self.options.keys() - if s and s.startswith(text)]) + self.matches = sorted( + [s for s in self.options.keys() if s and s.startswith(text)] + ) else: - self.matches = sorted([s - for s in self.options[prefix] - if s and s.startswith(text)]) + self.matches = sorted( + [s for s in self.options[prefix] if s and s.startswith(text)] + ) else: if len(prefix) == 0: self.matches = sorted(self.options.keys()) @@ -73,6 +81,7 @@ def complete(self, text, state): response = None return response + def print_message(level, msg): if level == MoveGroupInfoLevel.FAIL: print(bcolors.FAIL + msg + bcolors.ENDC) @@ -85,11 +94,13 @@ def print_message(level, msg): else: print(msg) + def get_context_keywords(interpreter): kw = interpreter.get_keywords() kw["quit"] = [] return kw + def run_interactive(group_name): c = MoveGroupCommandInterpreter() if len(group_name) > 0: @@ -98,9 +109,13 @@ def run_interactive(group_name): readline.set_completer(completer.complete) print() - print(bcolors.HEADER + "Waiting for commands. Type 'help' to get a list of known commands." + bcolors.ENDC) + print( + bcolors.HEADER + + "Waiting for commands. Type 'help' to get a list of known commands." + + bcolors.ENDC + ) print() - readline.parse_and_bind('tab: complete') + readline.parse_and_bind("tab: complete") while not rospy.is_shutdown(): cmd = "" @@ -109,7 +124,7 @@ def run_interactive(group_name): ag = c.get_active_group() if ag != None: name = ag.get_name() - cmd = input(bcolors.OKBLUE + name + '> ' + bcolors.ENDC) + cmd = input(bcolors.OKBLUE + name + "> " + bcolors.ENDC) except: break cmdorig = cmd.strip() @@ -120,7 +135,10 @@ def run_interactive(group_name): if cmd == "q" or cmd == "quit" or cmd == "exit": break if cmd == "host": - print_message(MoveGroupInfoLevel.INFO, "Master is '" + os.environ['ROS_MASTER_URI'] + "'") + print_message( + MoveGroupInfoLevel.INFO, + "Master is '" + os.environ["ROS_MASTER_URI"] + "'", + ) continue (level, msg) = c.execute(cmdorig) @@ -128,6 +146,7 @@ def run_interactive(group_name): # update the set of keywords completer.set_options(get_context_keywords(c)) + def run_service(group_name): c = MoveGroupCommandInterpreter() if len(group_name) > 0: @@ -136,30 +155,55 @@ def run_service(group_name): print("Running ROS service") rospy.spin() + def stop_ros(reason): rospy.signal_shutdown(reason) roscpp_shutdown() + def sigint_handler(signal, frame): stop_ros("Ctrl+C pressed") # this won't actually exit, but trigger an exception to terminate input sys.exit(0) -if __name__=='__main__': + +if __name__ == "__main__": signal.signal(signal.SIGINT, sigint_handler) roscpp_initialize(sys.argv) - rospy.init_node('move_group_interface_cmdline', anonymous=True, disable_signals=True) - - parser = argparse.ArgumentParser(usage = """%(prog)s [options] []""", - description = "Command Line Interface to MoveIt!") - parser.add_argument("-i", "--interactive", action="store_true", dest="interactive", default=True, - help="Run the command processing script in interactive mode (default)") - parser.add_argument("-s", "--service", action="store_true", dest="service", default=False, - help="Run the command processing script as a ROS service") - parser.add_argument("group_name", type=str, default="", nargs='?', help="Group name to initialize the CLI for.") + rospy.init_node( + "move_group_interface_cmdline", anonymous=True, disable_signals=True + ) + + parser = argparse.ArgumentParser( + usage="""%(prog)s [options] []""", + description="Command Line Interface to MoveIt!", + ) + parser.add_argument( + "-i", + "--interactive", + action="store_true", + dest="interactive", + default=True, + help="Run the command processing script in interactive mode (default)", + ) + parser.add_argument( + "-s", + "--service", + action="store_true", + dest="service", + default=False, + help="Run the command processing script as a ROS service", + ) + parser.add_argument( + "group_name", + type=str, + default="", + nargs="?", + help="Group name to initialize the CLI for.", + ) opt = parser.parse_args(rospy.myargv()[1:]) diff --git a/moveit_commander/demos/pick.py b/moveit_commander/demos/pick.py index 8912ca6067..175400bbae 100755 --- a/moveit_commander/demos/pick.py +++ b/moveit_commander/demos/pick.py @@ -36,13 +36,18 @@ import sys import rospy -from moveit_commander import RobotCommander, PlanningSceneInterface, roscpp_initialize, roscpp_shutdown +from moveit_commander import ( + RobotCommander, + PlanningSceneInterface, + roscpp_initialize, + roscpp_shutdown, +) from geometry_msgs.msg import PoseStamped -if __name__=='__main__': +if __name__ == "__main__": roscpp_initialize(sys.argv) - rospy.init_node('moveit_py_demo', anonymous=True) + rospy.init_node("moveit_py_demo", anonymous=True) scene = PlanningSceneInterface() robot = RobotCommander() diff --git a/moveit_commander/demos/plan.py b/moveit_commander/demos/plan.py index a65a6ae0af..6eee209f0c 100755 --- a/moveit_commander/demos/plan.py +++ b/moveit_commander/demos/plan.py @@ -39,25 +39,25 @@ from moveit_commander import RobotCommander, roscpp_initialize, roscpp_shutdown from moveit_msgs.msg import RobotState -if __name__=='__main__': +if __name__ == "__main__": roscpp_initialize(sys.argv) - rospy.init_node('moveit_py_demo', anonymous=True) + rospy.init_node("moveit_py_demo", anonymous=True) robot = RobotCommander() rospy.sleep(1) - print "Current state:" - print robot.get_current_state() + print("Current state:") + print(robot.get_current_state()) # plan to a random location a = robot.right_arm a.set_start_state(RobotState()) r = a.get_random_joint_values() - print "Planning to random joint position: " - print r + print("Planning to random joint position: ") + print(r) p = a.plan(r) - print "Solution:" - print p + print("Solution:") + print(p) roscpp_shutdown() diff --git a/moveit_commander/demos/plan_with_constraints.py b/moveit_commander/demos/plan_with_constraints.py index 8f169ae43a..01b69ed1a1 100755 --- a/moveit_commander/demos/plan_with_constraints.py +++ b/moveit_commander/demos/plan_with_constraints.py @@ -40,10 +40,10 @@ from moveit_msgs.msg import RobotState, Constraints from geometry_msgs.msg import Pose -if __name__=='__main__': +if __name__ == "__main__": roscpp_initialize(sys.argv) - rospy.init_node('moveit_py_demo', anonymous=True) + rospy.init_node("moveit_py_demo", anonymous=True) robot = RobotCommander() rospy.sleep(1) @@ -51,8 +51,8 @@ a = robot.right_arm a.set_start_state(RobotState()) - print "current pose:" - print a.get_current_pose() + print("current pose:") + print(a.get_current_pose()) c = Constraints() waypoints = [] @@ -72,4 +72,4 @@ waypoints.append(wpose) plan, fraction = a.compute_cartesian_path(waypoints, 0.01, 0.0, path_constraints=c) - print 'Plan success percent: ', fraction + print("Plan success percent: ", fraction) diff --git a/moveit_commander/setup.py b/moveit_commander/setup.py index 531c7291ac..8e1007e775 100644 --- a/moveit_commander/setup.py +++ b/moveit_commander/setup.py @@ -2,7 +2,7 @@ from catkin_pkg.python_setup import generate_distutils_setup d = generate_distutils_setup() -d['packages'] = ['moveit_commander'] -d['package_dir'] = {'': 'src'} +d["packages"] = ["moveit_commander"] +d["package_dir"] = {"": "src"} setup(**d) diff --git a/moveit_commander/src/moveit_commander/conversions.py b/moveit_commander/src/moveit_commander/conversions.py index f9129ffd8f..dcf884aa47 100644 --- a/moveit_commander/src/moveit_commander/conversions.py +++ b/moveit_commander/src/moveit_commander/conversions.py @@ -44,14 +44,17 @@ import rospy import tf + def msg_to_string(msg): buf = StringIO() msg.serialize(buf) return buf.getvalue() + def msg_from_string(msg, data): msg.deserialize(data) + def pose_to_list(pose_msg): pose = [] pose.append(pose_msg.position.x) @@ -63,6 +66,7 @@ def pose_to_list(pose_msg): pose.append(pose_msg.orientation.w) return pose + def list_to_pose(pose_list): pose_msg = Pose() if len(pose_list) == 7: @@ -77,15 +81,20 @@ def list_to_pose(pose_list): pose_msg.position.x = pose_list[0] pose_msg.position.y = pose_list[1] pose_msg.position.z = pose_list[2] - q = tf.transformations.quaternion_from_euler(pose_list[3], pose_list[4], pose_list[5]) + q = tf.transformations.quaternion_from_euler( + pose_list[3], pose_list[4], pose_list[5] + ) pose_msg.orientation.x = q[0] pose_msg.orientation.y = q[1] pose_msg.orientation.z = q[2] pose_msg.orientation.w = q[3] else: - raise MoveItCommanderException("Expected either 6 or 7 elements in list: (x,y,z,r,p,y) or (x,y,z,qx,qy,qz,qw)") + raise MoveItCommanderException( + "Expected either 6 or 7 elements in list: (x,y,z,r,p,y) or (x,y,z,qx,qy,qz,qw)" + ) return pose_msg + def list_to_pose_stamped(pose_list, target_frame): pose_msg = PoseStamped() pose_msg.pose = list_to_pose(pose_list) @@ -93,6 +102,7 @@ def list_to_pose_stamped(pose_list, target_frame): pose_msg.header.stamp = rospy.Time.now() return pose_msg + def transform_to_list(trf_msg): trf = [] trf.append(trf_msg.translation.x) @@ -104,6 +114,7 @@ def transform_to_list(trf_msg): trf.append(trf_msg.rotation.w) return trf + def list_to_transform(trf_list): trf_msg = Transform() trf_msg.translation.x = trf_list[0] diff --git a/moveit_commander/src/moveit_commander/exception.py b/moveit_commander/src/moveit_commander/exception.py index cbd7fd1e43..8b48333897 100644 --- a/moveit_commander/src/moveit_commander/exception.py +++ b/moveit_commander/src/moveit_commander/exception.py @@ -32,4 +32,6 @@ # # Author: Ioan Sucan -class MoveItCommanderException(Exception): pass + +class MoveItCommanderException(Exception): + pass diff --git a/moveit_commander/src/moveit_commander/interpreter.py b/moveit_commander/src/moveit_commander/interpreter.py index a7f6027b2a..d1eaf9355e 100644 --- a/moveit_commander/src/moveit_commander/interpreter.py +++ b/moveit_commander/src/moveit_commander/interpreter.py @@ -33,13 +33,19 @@ # Author: Ioan Sucan import rospy -from moveit_commander import RobotCommander, MoveGroupCommander, PlanningSceneInterface, MoveItCommanderException +from moveit_commander import ( + RobotCommander, + MoveGroupCommander, + PlanningSceneInterface, + MoveItCommanderException, +) from geometry_msgs.msg import Pose, PoseStamped import tf import re import time import os.path + class MoveGroupInfoLevel: FAIL = 1 WARN = 2 @@ -47,15 +53,25 @@ class MoveGroupInfoLevel: INFO = 4 DEBUG = 5 + class MoveGroupCommandInterpreter(object): """ Interpreter for simple commands """ DEFAULT_FILENAME = "move_group.cfg" - GO_DIRS = {"up" : (2,1), "down" : (2, -1), "z" : (2, 1), - "left" : (1, 1), "right" : (1, -1), "y" : (1, 1), - "forward" : (0, 1), "backward" : (0, -1), "back" : (0, -1), "x" : (0, 1) } + GO_DIRS = { + "up": (2, 1), + "down": (2, -1), + "z": (2, 1), + "left": (1, 1), + "right": (1, -1), + "y": (1, 1), + "forward": (0, 1), + "backward": (0, -1), + "back": (0, -1), + "x": (0, 1), + } def __init__(self): self._gdict = {} @@ -86,7 +102,11 @@ def execute(self, cmd): if len(self._group_name) > 0: return self.execute_group_command(self._gdict[self._group_name], cmd) else: - return (MoveGroupInfoLevel.INFO, self.get_help() + "\n\nNo groups initialized yet. You must call the 'use' or the 'load' command first.\n") + return ( + MoveGroupInfoLevel.INFO, + self.get_help() + + "\n\nNo groups initialized yet. You must call the 'use' or the 'load' command first.\n", + ) def execute_generic_command(self, cmd): if os.path.isfile("cmd/" + cmd): @@ -114,12 +134,21 @@ def execute_generic_command(self, cmd): self._group_name = clist[1] return (MoveGroupInfoLevel.DEBUG, "OK") except MoveItCommanderException as e: - return (MoveGroupInfoLevel.FAIL, "Initializing " + clist[1] + ": " + str(e)) + return ( + MoveGroupInfoLevel.FAIL, + "Initializing " + clist[1] + ": " + str(e), + ) except: - return (MoveGroupInfoLevel.FAIL, "Unable to initialize " + clist[1]) + return ( + MoveGroupInfoLevel.FAIL, + "Unable to initialize " + clist[1], + ) elif cmdlow.startswith("trace"): if cmdlow == "trace": - return (MoveGroupInfoLevel.INFO, "trace is on" if self._trace else "trace is off") + return ( + MoveGroupInfoLevel.INFO, + "trace is on" if self._trace else "trace is off", + ) clist = cmdlow.split() if clist[0] == "trace" and clist[1] == "on": self._trace = True @@ -139,28 +168,38 @@ def execute_generic_command(self, cmd): line_num = 0 line_content = "" try: - f = open(filename, 'r') + f = open(filename, "r") for line in f: line_num += 1 line = line.rstrip() line_content = line if self._trace: - print ("%s:%d: %s" % (filename, line_num, line_content)) + print("%s:%d: %s" % (filename, line_num, line_content)) comment = line.find("#") if comment != -1: - line = line[0:comment].rstrip() + line = line[0:comment].rstrip() if line != "": - self.execute(line.rstrip()) + self.execute(line.rstrip()) line_content = "" return (MoveGroupInfoLevel.DEBUG, "OK") except MoveItCommanderException as e: if line_num > 0: - return (MoveGroupInfoLevel.WARN, "Error at %s:%d: %s\n%s" % (filename, line_num, line_content, str(e))) + return ( + MoveGroupInfoLevel.WARN, + "Error at %s:%d: %s\n%s" + % (filename, line_num, line_content, str(e)), + ) else: - return (MoveGroupInfoLevel.WARN, "Processing " + filename + ": " + str(e)) + return ( + MoveGroupInfoLevel.WARN, + "Processing " + filename + ": " + str(e), + ) except: if line_num > 0: - return (MoveGroupInfoLevel.WARN, "Error at %s:%d: %s" % (filename, line_num, line_content)) + return ( + MoveGroupInfoLevel.WARN, + "Error at %s:%d: %s" % (filename, line_num, line_content), + ) else: return (MoveGroupInfoLevel.WARN, "Unable to load " + filename) elif cmdlow.startswith("save"): @@ -171,14 +210,18 @@ def execute_generic_command(self, cmd): if len(clist) == 2: filename = clist[1] try: - f = open(filename, 'w') + f = open(filename, "w") for gr in self._gdict.keys(): f.write("use " + gr + "\n") known = self._gdict[gr].get_remembered_joint_values() for v in known.keys(): - f.write(v + " = [" + " ".join([str(x) for x in known[v]]) + "]\n") + f.write( + v + " = [" + " ".join([str(x) for x in known[v]]) + "]\n" + ) if self._db_host != None: - f.write("database " + self._db_host + " " + str(self._db_port) + "\n") + f.write( + "database " + self._db_host + " " + str(self._db_port) + "\n" + ) return (MoveGroupInfoLevel.DEBUG, "OK") except: return (MoveGroupInfoLevel.WARN, "Unable to save " + filename) @@ -204,7 +247,12 @@ def execute_group_command(self, g, cmdorig): if cmd == "joints": joints = g.get_joints() - return (MoveGroupInfoLevel.INFO, "\n" + "\n".join([str(i) + " = " + joints[i] for i in range(len(joints))]) + "\n") + return ( + MoveGroupInfoLevel.INFO, + "\n" + + "\n".join([str(i) + " = " + joints[i] for i in range(len(joints))]) + + "\n", + ) if cmd == "show": return self.command_show(g) @@ -224,7 +272,9 @@ def execute_group_command(self, g, cmdorig): pose.pose.orientation.w = 1 pose.header.stamp = rospy.get_rostime() pose.header.frame_id = self._robot.get_root_link() - self._planning_scene_interface.attach_box(self._robot.get_root_link(), "ground", pose, (3, 3, 0.1)) + self._planning_scene_interface.attach_box( + self._robot.get_root_link(), "ground", pose, (3, 3, 0.1) + ) return (MoveGroupInfoLevel.INFO, "Added ground") if cmd == "eef": @@ -237,7 +287,10 @@ def execute_group_command(self, g, cmdorig): if self._db_host == None: return (MoveGroupInfoLevel.INFO, "Not connected to a database") else: - return (MoveGroupInfoLevel.INFO, "Connected to " + self._db_host + ":" + str(self._db_port)) + return ( + MoveGroupInfoLevel.INFO, + "Connected to " + self._db_host + ":" + str(self._db_port), + ) if cmd == "plan": if self._last_plan != None: return (MoveGroupInfoLevel.INFO, str(self._last_plan)) @@ -249,7 +302,11 @@ def execute_group_command(self, g, cmdorig): return (MoveGroupInfoLevel.SUCCESS, "Cleared path constraints") if cmd == "tol" or cmd == "tolerance": - return (MoveGroupInfoLevel.INFO, "Joint = %0.6g, Position = %0.6g, Orientation = %0.6g" % g.get_goal_tolerance()) + return ( + MoveGroupInfoLevel.INFO, + "Joint = %0.6g, Position = %0.6g, Orientation = %0.6g" + % g.get_goal_tolerance(), + ) if cmd == "time": return (MoveGroupInfoLevel.INFO, str(g.get_planning_time())) @@ -259,7 +316,10 @@ def execute_group_command(self, g, cmdorig): if g.execute(self._last_plan): return (MoveGroupInfoLevel.SUCCESS, "Plan submitted for execution") else: - return (MoveGroupInfoLevel.WARN, "Failed to submit plan for execution") + return ( + MoveGroupInfoLevel.WARN, + "Failed to submit plan for execution", + ) else: return (MoveGroupInfoLevel.WARN, "No motion plan computed") @@ -268,8 +328,15 @@ def execute_group_command(self, g, cmdorig): if assign_match: known = g.get_remembered_joint_values() if assign_match.group(2) in known: - g.remember_joint_values(assign_match.group(1), known[assign_match.group(2)]) - return (MoveGroupInfoLevel.SUCCESS, assign_match.group(1) + " is now the same as " + assign_match.group(2)) + g.remember_joint_values( + assign_match.group(1), known[assign_match.group(2)] + ) + return ( + MoveGroupInfoLevel.SUCCESS, + assign_match.group(1) + + " is now the same as " + + assign_match.group(2), + ) else: return (MoveGroupInfoLevel.WARN, "Unknown command: '" + cmd + "'") @@ -277,13 +344,26 @@ def execute_group_command(self, g, cmdorig): set_match = re.match(r"^(\w+)\s*=\s*\[([\d\.e\-\+\s]+)\]$", cmd) if set_match: try: - g.remember_joint_values(set_match.group(1), [float(x) for x in set_match.group(2).split()]) - return (MoveGroupInfoLevel.SUCCESS, "Remembered joint values [" + set_match.group(2) + "] under the name " + set_match.group(1)) + g.remember_joint_values( + set_match.group(1), [float(x) for x in set_match.group(2).split()] + ) + return ( + MoveGroupInfoLevel.SUCCESS, + "Remembered joint values [" + + set_match.group(2) + + "] under the name " + + set_match.group(1), + ) except: - return (MoveGroupInfoLevel.WARN, "Unable to parse joint value [" + set_match.group(2) + "]") + return ( + MoveGroupInfoLevel.WARN, + "Unable to parse joint value [" + set_match.group(2) + "]", + ) # see if we have assignment of matlab-like element update - component_match = re.match(r"^(\w+)\s*\[\s*(\d+)\s*\]\s*=\s*([\d\.e\-\+]+)$", cmd) + component_match = re.match( + r"^(\w+)\s*\[\s*(\d+)\s*\]\s*=\s*([\d\.e\-\+]+)$", cmd + ) if component_match: known = g.get_remembered_joint_values() if component_match.group(1) in known: @@ -291,9 +371,19 @@ def execute_group_command(self, g, cmdorig): val = known[component_match.group(1)] val[int(component_match.group(2))] = float(component_match.group(3)) g.remember_joint_values(component_match.group(1), val) - return (MoveGroupInfoLevel.SUCCESS, "Updated " + component_match.group(1) + "[" + component_match.group(2) + "]") + return ( + MoveGroupInfoLevel.SUCCESS, + "Updated " + + component_match.group(1) + + "[" + + component_match.group(2) + + "]", + ) except: - return (MoveGroupInfoLevel.WARN, "Unable to parse index or value in '" + cmd +"'") + return ( + MoveGroupInfoLevel.WARN, + "Unable to parse index or value in '" + cmd + "'", + ) else: return (MoveGroupInfoLevel.WARN, "Unknown command: '" + cmd + "'") @@ -304,7 +394,10 @@ def execute_group_command(self, g, cmdorig): if len(clist) == 1: known = g.get_remembered_joint_values() if cmd in known: - return (MoveGroupInfoLevel.INFO, "[" + " ".join([str(x) for x in known[cmd]]) + "]") + return ( + MoveGroupInfoLevel.INFO, + "[" + " ".join([str(x) for x in known[cmd]]) + "]", + ) else: return (MoveGroupInfoLevel.WARN, "Unknown command: '" + cmd + "'") @@ -316,18 +409,34 @@ def execute_group_command(self, g, cmdorig): vals = g.get_random_joint_values() g.set_joint_value_target(vals) if g.go(): - return (MoveGroupInfoLevel.SUCCESS, "Moved to random target [" + " ".join([str(x) for x in vals]) + "]") + return ( + MoveGroupInfoLevel.SUCCESS, + "Moved to random target [" + + " ".join([str(x) for x in vals]) + + "]", + ) else: - return (MoveGroupInfoLevel.FAIL, "Failed while moving to random target [" + " ".join([str(x) for x in vals]) + "]") + return ( + MoveGroupInfoLevel.FAIL, + "Failed while moving to random target [" + + " ".join([str(x) for x in vals]) + + "]", + ) else: try: g.set_named_target(clist[1]) if g.go(): return (MoveGroupInfoLevel.SUCCESS, "Moved to " + clist[1]) else: - return (MoveGroupInfoLevel.FAIL, "Failed while moving to " + clist[1]) + return ( + MoveGroupInfoLevel.FAIL, + "Failed while moving to " + clist[1], + ) except MoveItCommanderException as e: - return (MoveGroupInfoLevel.WARN, "Going to " + clist[1] + ": " + str(e)) + return ( + MoveGroupInfoLevel.WARN, + "Going to " + clist[1] + ": " + str(e), + ) except: return (MoveGroupInfoLevel.WARN, clist[1] + " is unknown") if clist[0] == "plan": @@ -342,11 +451,17 @@ def execute_group_command(self, g, cmdorig): g.set_named_target(clist[1]) self._last_plan = g.plan() except MoveItCommanderException as e: - return (MoveGroupInfoLevel.WARN, "Planning to " + clist[1] + ": " + str(e)) + return ( + MoveGroupInfoLevel.WARN, + "Planning to " + clist[1] + ": " + str(e), + ) except: return (MoveGroupInfoLevel.WARN, clist[1] + " is unknown") if self._last_plan != None: - if len(self._last_plan.joint_trajectory.points) == 0 and len(self._last_plan.multi_dof_joint_trajectory.points) == 0: + if ( + len(self._last_plan.joint_trajectory.points) == 0 + and len(self._last_plan.multi_dof_joint_trajectory.points) == 0 + ): self._last_plan = None dest_str = clist[1] if vals != None: @@ -354,56 +469,89 @@ def execute_group_command(self, g, cmdorig): if self._last_plan != None: return (MoveGroupInfoLevel.SUCCESS, "Planned to " + dest_str) else: - return (MoveGroupInfoLevel.FAIL, "Failed while planning to " + dest_str) + return ( + MoveGroupInfoLevel.FAIL, + "Failed while planning to " + dest_str, + ) elif clist[0] == "pick": self._last_plan = None if g.pick(clist[1]): return (MoveGroupInfoLevel.SUCCESS, "Picked object " + clist[1]) else: - return (MoveGroupInfoLevel.FAIL, "Failed while trying to pick object " + clist[1]) + return ( + MoveGroupInfoLevel.FAIL, + "Failed while trying to pick object " + clist[1], + ) elif clist[0] == "place": self._last_plan = None if g.place(clist[1]): return (MoveGroupInfoLevel.SUCCESS, "Placed object " + clist[1]) else: - return (MoveGroupInfoLevel.FAIL, "Failed while trying to place object " + clist[1]) + return ( + MoveGroupInfoLevel.FAIL, + "Failed while trying to place object " + clist[1], + ) elif clist[0] == "planner": g.set_planner_id(clist[1]) return (MoveGroupInfoLevel.SUCCESS, "Planner is now " + clist[1]) elif clist[0] == "record" or clist[0] == "rec": g.remember_joint_values(clist[1]) - return (MoveGroupInfoLevel.SUCCESS, "Remembered current joint values under the name " + clist[1]) + return ( + MoveGroupInfoLevel.SUCCESS, + "Remembered current joint values under the name " + clist[1], + ) elif clist[0] == "rand" or clist[0] == "random": g.remember_joint_values(clist[1], g.get_random_joint_values()) - return (MoveGroupInfoLevel.SUCCESS, "Remembered random joint values under the name " + clist[1]) + return ( + MoveGroupInfoLevel.SUCCESS, + "Remembered random joint values under the name " + clist[1], + ) elif clist[0] == "del" or clist[0] == "delete": g.forget_joint_values(clist[1]) - return (MoveGroupInfoLevel.SUCCESS, "Forgot joint values under the name " + clist[1]) + return ( + MoveGroupInfoLevel.SUCCESS, + "Forgot joint values under the name " + clist[1], + ) elif clist[0] == "show": known = g.get_remembered_joint_values() if clist[1] in known: - return (MoveGroupInfoLevel.INFO, "[" + " ".join([str(x) for x in known[clist[1]]]) + "]") + return ( + MoveGroupInfoLevel.INFO, + "[" + " ".join([str(x) for x in known[clist[1]]]) + "]", + ) else: - return (MoveGroupInfoLevel.WARN, "Joint values for " + clist[1] + " are not known") + return ( + MoveGroupInfoLevel.WARN, + "Joint values for " + clist[1] + " are not known", + ) elif clist[0] == "tol" or clist[0] == "tolerance": try: g.set_goal_tolerance(float(clist[1])) return (MoveGroupInfoLevel.SUCCESS, "OK") except: - return (MoveGroupInfoLevel.WARN, "Unable to parse tolerance value '" + clist[1] + "'") + return ( + MoveGroupInfoLevel.WARN, + "Unable to parse tolerance value '" + clist[1] + "'", + ) elif clist[0] == "time": try: g.set_planning_time(float(clist[1])) return (MoveGroupInfoLevel.SUCCESS, "OK") except: - return (MoveGroupInfoLevel.WARN, "Unable to parse planning duration value '" + clist[1] + "'") + return ( + MoveGroupInfoLevel.WARN, + "Unable to parse planning duration value '" + clist[1] + "'", + ) elif clist[0] == "constrain": try: g.set_path_constraints(clist[1]) return (MoveGroupInfoLevel.SUCCESS, "OK") except: if self._db_host != None: - return (MoveGroupInfoLevel.WARN, "Constraint " + clist[1] + " is not known.") + return ( + MoveGroupInfoLevel.WARN, + "Constraint " + clist[1] + " is not known.", + ) else: return (MoveGroupInfoLevel.WARN, "Not connected to a database.") elif clist[0] == "wait": @@ -411,14 +559,27 @@ def execute_group_command(self, g, cmdorig): time.sleep(float(clist[1])) return (MoveGroupInfoLevel.SUCCESS, clist[1] + " seconds passed") except: - return (MoveGroupInfoLevel.WARN, "Unable to wait '" + clist[1] + "' seconds") + return ( + MoveGroupInfoLevel.WARN, + "Unable to wait '" + clist[1] + "' seconds", + ) elif clist[0] == "database": try: g.set_constraints_database(clist[1], self._db_port) self._db_host = clist[1] - return (MoveGroupInfoLevel.SUCCESS, "Connected to " + self._db_host + ":" + str(self._db_port)) + return ( + MoveGroupInfoLevel.SUCCESS, + "Connected to " + self._db_host + ":" + str(self._db_port), + ) except: - return (MoveGroupInfoLevel.WARN, "Unable to connect to '" + clist[1] + ":" + str(self._db_port) + "'") + return ( + MoveGroupInfoLevel.WARN, + "Unable to connect to '" + + clist[1] + + ":" + + str(self._db_port) + + "'", + ) else: return (MoveGroupInfoLevel.WARN, "Unknown command: '" + cmd + "'") @@ -430,17 +591,35 @@ def execute_group_command(self, g, cmdorig): (axis, factor) = self.GO_DIRS[clist[1]] return self.command_go_offset(g, offset, factor, axis, clist[1]) except MoveItCommanderException as e: - return (MoveGroupInfoLevel.WARN, "Going " + clist[1] + ": " + str(e)) + return ( + MoveGroupInfoLevel.WARN, + "Going " + clist[1] + ": " + str(e), + ) except: - return (MoveGroupInfoLevel.WARN, "Unable to parse distance '" + clist[2] + "'") + return ( + MoveGroupInfoLevel.WARN, + "Unable to parse distance '" + clist[2] + "'", + ) elif clist[0] == "allow" and (clist[1] == "look" or clist[1] == "looking"): - if clist[2] == "1" or clist[2] == "true" or clist[2] == "T" or clist[2] == "True": + if ( + clist[2] == "1" + or clist[2] == "true" + or clist[2] == "T" + or clist[2] == "True" + ): g.allow_looking(True) else: g.allow_looking(False) return (MoveGroupInfoLevel.DEBUG, "OK") - elif clist[0] == "allow" and (clist[1] == "replan" or clist[1] == "replanning"): - if clist[2] == "1" or clist[2] == "true" or clist[2] == "T" or clist[2] == "True": + elif clist[0] == "allow" and ( + clist[1] == "replan" or clist[1] == "replanning" + ): + if ( + clist[2] == "1" + or clist[2] == "true" + or clist[2] == "T" + or clist[2] == "True" + ): g.allow_replanning(True) else: g.allow_replanning(False) @@ -450,10 +629,16 @@ def execute_group_command(self, g, cmdorig): g.set_constraints_database(clist[1], int(clist[2])) self._db_host = clist[1] self._db_port = int(clist[2]) - return (MoveGroupInfoLevel.SUCCESS, "Connected to " + self._db_host + ":" + str(self._db_port)) + return ( + MoveGroupInfoLevel.SUCCESS, + "Connected to " + self._db_host + ":" + str(self._db_port), + ) except: self._db_host = None - return (MoveGroupInfoLevel.WARN, "Unable to connect to '" + clist[1] + ":" + clist[2] + "'") + return ( + MoveGroupInfoLevel.WARN, + "Unable to connect to '" + clist[1] + ":" + clist[2] + "'", + ) if len(clist) == 4: if clist[0] == "rotate": try: @@ -461,24 +646,34 @@ def execute_group_command(self, g, cmdorig): if g.go(): return (MoveGroupInfoLevel.SUCCESS, "Rotation complete") else: - return (MoveGroupInfoLevel.FAIL, "Failed while rotating to " + " ".join(clist[1:])) + return ( + MoveGroupInfoLevel.FAIL, + "Failed while rotating to " + " ".join(clist[1:]), + ) except MoveItCommanderException as e: return (MoveGroupInfoLevel.WARN, str(e)) except: - return (MoveGroupInfoLevel.WARN, "Unable to parse X-Y-Z rotation values '" + " ".join(clist[1:]) + "'") + return ( + MoveGroupInfoLevel.WARN, + "Unable to parse X-Y-Z rotation values '" + + " ".join(clist[1:]) + + "'", + ) if len(clist) >= 7: if clist[0] == "go": self._last_plan = None approx = False - if (len(clist) > 7): - if (clist[7] == "approx" or clist[7] == "approximate"): + if len(clist) > 7: + if clist[7] == "approx" or clist[7] == "approximate": approx = True try: p = Pose() p.position.x = float(clist[1]) p.position.y = float(clist[2]) p.position.z = float(clist[3]) - q = tf.transformations.quaternion_from_euler(float(clist[4]), float(clist[5]), float(clist[6])) + q = tf.transformations.quaternion_from_euler( + float(clist[4]), float(clist[5]), float(clist[6]) + ) p.orientation.x = q[0] p.orientation.y = q[1] p.orientation.z = q[2] @@ -488,13 +683,25 @@ def execute_group_command(self, g, cmdorig): else: g.set_pose_target(p) if g.go(): - return (MoveGroupInfoLevel.SUCCESS, "Moved to pose target\n%s\n" % (str(p))) + return ( + MoveGroupInfoLevel.SUCCESS, + "Moved to pose target\n%s\n" % (str(p)), + ) else: - return (MoveGroupInfoLevel.FAIL, "Failed while moving to pose \n%s\n" % (str(p))) + return ( + MoveGroupInfoLevel.FAIL, + "Failed while moving to pose \n%s\n" % (str(p)), + ) except MoveItCommanderException as e: - return (MoveGroupInfoLevel.WARN, "Going to pose target: %s" % (str(e))) + return ( + MoveGroupInfoLevel.WARN, + "Going to pose target: %s" % (str(e)), + ) except: - return (MoveGroupInfoLevel.WARN, "Unable to parse pose '" + " ".join(clist[1:]) + "'") + return ( + MoveGroupInfoLevel.WARN, + "Unable to parse pose '" + " ".join(clist[1:]) + "'", + ) return (MoveGroupInfoLevel.WARN, "Unknown command: '" + cmd + "'") @@ -506,10 +713,27 @@ def command_show(self, g): return (MoveGroupInfoLevel.INFO, "\n".join(res)) def command_current(self, g): - res = "joints = [" + " ".join([str(x) for x in g.get_current_joint_values()]) + "]" + res = ( + "joints = [" + + " ".join([str(x) for x in g.get_current_joint_values()]) + + "]" + ) if len(g.get_end_effector_link()) > 0: - res = res + "\n" + g.get_end_effector_link() + " pose = [\n" + str(g.get_current_pose()) + " ]" - res = res + "\n" + g.get_end_effector_link() + " RPY = " + str(g.get_current_rpy()) + res = ( + res + + "\n" + + g.get_end_effector_link() + + " pose = [\n" + + str(g.get_current_pose()) + + " ]" + ) + res = ( + res + + "\n" + + g.get_end_effector_link() + + " RPY = " + + str(g.get_current_rpy()) + ) return (MoveGroupInfoLevel.INFO, res) def command_go_offset(self, g, offset, factor, dimension_index, direction_name): @@ -517,15 +741,24 @@ def command_go_offset(self, g, offset, factor, dimension_index, direction_name): try: g.shift_pose_target(dimension_index, factor * offset) if g.go(): - return (MoveGroupInfoLevel.SUCCESS, "Moved " + direction_name + " by " + str(offset) + " m") + return ( + MoveGroupInfoLevel.SUCCESS, + "Moved " + direction_name + " by " + str(offset) + " m", + ) else: - return (MoveGroupInfoLevel.FAIL, "Failed while moving " + direction_name) + return ( + MoveGroupInfoLevel.FAIL, + "Failed while moving " + direction_name, + ) except MoveItCommanderException as e: return (MoveGroupInfoLevel.WARN, str(e)) except: return (MoveGroupInfoLevel.WARN, "Unable to process pose update") else: - return (MoveGroupInfoLevel.WARN, "No known end effector. Cannot move " + direction_name) + return ( + MoveGroupInfoLevel.WARN, + "No known end effector. Cannot move " + direction_name, + ) def resolve_command_alias(self, cmdorig): cmd = cmdorig.lower() @@ -542,36 +775,68 @@ def get_help(self): res.append(" allow looking enable/disable looking around") res.append(" allow replanning enable/disable replanning") res.append(" constrain clear path constraints") - res.append(" constrain use the constraint as a path constraint") + res.append( + " constrain use the constraint as a path constraint" + ) res.append(" current show the current state of the active group") - res.append(" database display the current database connection (if any)") - res.append(" delete forget the joint values under the name ") - res.append(" eef print the name of the end effector attached to the current group") + res.append( + " database display the current database connection (if any)" + ) + res.append( + " delete forget the joint values under the name " + ) + res.append( + " eef print the name of the end effector attached to the current group" + ) res.append(" execute execute a previously computed motion plan") - res.append(" go plan and execute a motion to the state ") + res.append( + " go plan and execute a motion to the state " + ) res.append(" go rand plan and execute a motion to a random state") - res.append(" go

    | plan and execute a motion in direction up|down|left|right|forward|backward for distance ") + res.append( + " go | plan and execute a motion in direction up|down|left|right|forward|backward for distance " + ) res.append(" ground add a ground plane to the planning scene") - res.append(" id|which display the name of the group that is operated on") - res.append(" joints display names of the joints in the active group") - res.append(" load [] load a set of interpreted commands from a file") + res.append( + " id|which display the name of the group that is operated on" + ) + res.append( + " joints display names of the joints in the active group" + ) + res.append( + " load [] load a set of interpreted commands from a file" + ) res.append(" pick pick up object ") res.append(" place place object ") res.append(" plan plan a motion to the state ") res.append(" plan rand plan a motion to a random state") res.append(" planner use planner to plan next motion") - res.append(" record record the current joint values under the name ") - res.append(" rotate plan and execute a motion to a specified orientation (about the X,Y,Z axes)") - res.append(" save [] save the currently known variables as a set of commands") - res.append(" show display the names and values of the known states") + res.append( + " record record the current joint values under the name " + ) + res.append( + " rotate plan and execute a motion to a specified orientation (about the X,Y,Z axes)" + ) + res.append( + " save [] save the currently known variables as a set of commands" + ) + res.append( + " show display the names and values of the known states" + ) res.append(" show display the value of a state") res.append(" stop stop the active group") res.append(" time show the configured allowed planning time") res.append(" time set the allowed planning time") - res.append(" tolerance show the tolerance for reaching the goal region") - res.append(" tolerance set the tolerance for reaching the goal region") + res.append( + " tolerance show the tolerance for reaching the goal region" + ) + res.append( + " tolerance set the tolerance for reaching the goal region" + ) res.append(" trace enable/disable replanning or looking around") - res.append(" use switch to using the group named (and load it if necessary)") + res.append( + " use switch to using the group named (and load it if necessary)" + ) res.append(" use|groups show the group names that are already loaded") res.append(" vars display the names of the known states") res.append(" wait
    sleep for
    seconds") @@ -587,27 +852,30 @@ def get_keywords(self): known_vars = self.get_active_group().get_remembered_joint_values().keys() known_constr = self.get_active_group().get_known_constraints() groups = self._robot.get_group_names() - return {'go':['up', 'down', 'left', 'right', 'backward', 'forward', 'random'] + list(known_vars), - 'help':[], - 'record':known_vars, - 'show':known_vars, - 'wait':[], - 'delete':known_vars, - 'database': [], - 'current':[], - 'use':groups, - 'load':[], - 'save':[], - 'pick':[], - 'place':[], - 'plan':known_vars, - 'allow':['replanning', 'looking'], - 'constrain':known_constr, - 'vars':[], - 'joints':[], - 'tolerance':[], - 'time':[], - 'eef':[], - 'execute':[], - 'ground':[], - 'id':[]} + return { + "go": ["up", "down", "left", "right", "backward", "forward", "random"] + + list(known_vars), + "help": [], + "record": known_vars, + "show": known_vars, + "wait": [], + "delete": known_vars, + "database": [], + "current": [], + "use": groups, + "load": [], + "save": [], + "pick": [], + "place": [], + "plan": known_vars, + "allow": ["replanning", "looking"], + "constrain": known_constr, + "vars": [], + "joints": [], + "tolerance": [], + "time": [], + "eef": [], + "execute": [], + "ground": [], + "id": [], + } diff --git a/moveit_commander/src/moveit_commander/move_group.py b/moveit_commander/src/moveit_commander/move_group.py index a9af06c79b..526c777391 100644 --- a/moveit_commander/src/moveit_commander/move_group.py +++ b/moveit_commander/src/moveit_commander/move_group.py @@ -33,8 +33,18 @@ # Author: Ioan Sucan, William Baker from geometry_msgs.msg import Pose, PoseStamped -from moveit_msgs.msg import RobotTrajectory, Grasp, PlaceLocation, Constraints, RobotState -from moveit_msgs.msg import MoveItErrorCodes, TrajectoryConstraints, PlannerInterfaceDescription +from moveit_msgs.msg import ( + RobotTrajectory, + Grasp, + PlaceLocation, + Constraints, + RobotState, +) +from moveit_msgs.msg import ( + MoveItErrorCodes, + TrajectoryConstraints, + PlannerInterfaceDescription, +) from sensor_msgs.msg import JointState import rospy import tf @@ -42,14 +52,19 @@ from .exception import MoveItCommanderException import moveit_commander.conversions as conversions + class MoveGroupCommander(object): """ Execution of simple commands for a particular group """ - def __init__(self, name, robot_description="robot_description", ns="", wait_for_servers=5.0): + def __init__( + self, name, robot_description="robot_description", ns="", wait_for_servers=5.0 + ): """ Specify the group name for which to construct this commander instance. Throws an exception if there is an initialization error. """ - self._g = _moveit_move_group_interface.MoveGroupInterface(name, robot_description, ns, wait_for_servers) + self._g = _moveit_move_group_interface.MoveGroupInterface( + name, robot_description, ns, wait_for_servers + ) def get_name(self): """ Get the name of the group this instance was initialized for """ @@ -106,14 +121,18 @@ def get_current_joint_values(self): """ Get the current configuration of the group as a list (these are values published on /joint_states) """ return self._g.get_current_joint_values() - def get_current_pose(self, end_effector_link = ""): + def get_current_pose(self, end_effector_link=""): """ Get the current pose of the end-effector of the group. Throws an exception if there is not end-effector. """ if len(end_effector_link) > 0 or self.has_end_effector_link(): - return conversions.list_to_pose_stamped(self._g.get_current_pose(end_effector_link), self.get_planning_frame()) + return conversions.list_to_pose_stamped( + self._g.get_current_pose(end_effector_link), self.get_planning_frame() + ) else: - raise MoveItCommanderException("There is no end effector to get the pose of") + raise MoveItCommanderException( + "There is no end effector to get the pose of" + ) - def get_current_rpy(self, end_effector_link = ""): + def get_current_rpy(self, end_effector_link=""): """ Get a list of 3 elements defining the [roll, pitch, yaw] of the end-effector. Throws an exception if there is not end-effector. """ if len(end_effector_link) > 0 or self.has_end_effector_link(): return self._g.get_current_rpy(end_effector_link) @@ -123,11 +142,15 @@ def get_current_rpy(self, end_effector_link = ""): def get_random_joint_values(self): return self._g.get_random_joint_values() - def get_random_pose(self, end_effector_link = ""): + def get_random_pose(self, end_effector_link=""): if len(end_effector_link) > 0 or self.has_end_effector_link(): - return conversions.list_to_pose_stamped(self._g.get_random_pose(end_effector_link), self.get_planning_frame()) + return conversions.list_to_pose_stamped( + self._g.get_random_pose(end_effector_link), self.get_planning_frame() + ) else: - raise MoveItCommanderException("There is no end effector to get the pose of") + raise MoveItCommanderException( + "There is no end effector to get the pose of" + ) def set_start_state_to_current_state(self): self._g.set_start_state_to_current_state() @@ -172,7 +195,7 @@ def get_current_state(self): def get_joint_value_target(self): return self._g.get_joint_value_target() - def set_joint_value_target(self, arg1, arg2 = None, arg3 = None): + def set_joint_value_target(self, arg1, arg2=None, arg3=None): """ Specify a target joint configuration for the group. - if the type of arg1 is one of the following: dict, list, JointState message, then no other arguments should be provided. @@ -188,26 +211,36 @@ def set_joint_value_target(self, arg1, arg2 = None, arg3 = None): """ if isinstance(arg1, RobotState): if not self._g.set_state_value_target(conversions.msg_to_string(arg1)): - raise MoveItCommanderException("Error setting state target. Is the target state within bounds?") + raise MoveItCommanderException( + "Error setting state target. Is the target state within bounds?" + ) elif isinstance(arg1, JointState): - if (arg2 is not None or arg3 is not None): + if arg2 is not None or arg3 is not None: raise MoveItCommanderException("Too many arguments specified") - if not self._g.set_joint_value_target_from_joint_state_message(conversions.msg_to_string(arg1)): - raise MoveItCommanderException("Error setting joint target. Is the target within bounds?") + if not self._g.set_joint_value_target_from_joint_state_message( + conversions.msg_to_string(arg1) + ): + raise MoveItCommanderException( + "Error setting joint target. Is the target within bounds?" + ) elif isinstance(arg1, str): - if (arg2 is None): - raise MoveItCommanderException("Joint value expected when joint name specified") - if (arg3 is not None): + if arg2 is None: + raise MoveItCommanderException( + "Joint value expected when joint name specified" + ) + if arg3 is not None: raise MoveItCommanderException("Too many arguments specified") if not self._g.set_joint_value_target(arg1, arg2): - raise MoveItCommanderException("Error setting joint target. Is the target within bounds?") + raise MoveItCommanderException( + "Error setting joint target. Is the target within bounds?" + ) elif isinstance(arg1, (Pose, PoseStamped)): approx = False eef = "" - if (arg2 is not None): + if arg2 is not None: if type(arg2) is str: eef = arg2 else: @@ -215,7 +248,7 @@ def set_joint_value_target(self, arg1, arg2 = None, arg3 = None): approx = arg2 else: raise MoveItCommanderException("Unexpected type") - if (arg3 is not None): + if arg3 is not None: if type(arg3) is str: eef = arg3 else: @@ -225,55 +258,79 @@ def set_joint_value_target(self, arg1, arg2 = None, arg3 = None): raise MoveItCommanderException("Unexpected type") r = False if type(arg1) is PoseStamped: - r = self._g.set_joint_value_target_from_pose_stamped(conversions.msg_to_string(arg1), eef, approx) + r = self._g.set_joint_value_target_from_pose_stamped( + conversions.msg_to_string(arg1), eef, approx + ) else: - r = self._g.set_joint_value_target_from_pose(conversions.msg_to_string(arg1), eef, approx) + r = self._g.set_joint_value_target_from_pose( + conversions.msg_to_string(arg1), eef, approx + ) if not r: if approx: - raise MoveItCommanderException("Error setting joint target. Does your IK solver support approximate IK?") + raise MoveItCommanderException( + "Error setting joint target. Does your IK solver support approximate IK?" + ) else: - raise MoveItCommanderException("Error setting joint target. Is the IK solver functional?") + raise MoveItCommanderException( + "Error setting joint target. Is the IK solver functional?" + ) - elif (hasattr(arg1, '__iter__')): - if (arg2 is not None or arg3 is not None): + elif hasattr(arg1, "__iter__"): + if arg2 is not None or arg3 is not None: raise MoveItCommanderException("Too many arguments specified") if not self._g.set_joint_value_target(arg1): - raise MoveItCommanderException("Error setting joint target. Is the target within bounds?") + raise MoveItCommanderException( + "Error setting joint target. Is the target within bounds?" + ) else: - raise MoveItCommanderException("Unsupported argument of type %s" % type(arg1)) + raise MoveItCommanderException( + "Unsupported argument of type %s" % type(arg1) + ) def set_rpy_target(self, rpy, end_effector_link=""): """ Specify a target orientation for the end-effector. Any position of the end-effector is acceptable.""" if len(end_effector_link) > 0 or self.has_end_effector_link(): if len(rpy) == 3: - if not self._g.set_rpy_target(rpy[0], rpy[1], rpy[2], end_effector_link): + if not self._g.set_rpy_target( + rpy[0], rpy[1], rpy[2], end_effector_link + ): raise MoveItCommanderException("Unable to set orientation target") else: raise MoveItCommanderException("Expected [roll, pitch, yaw]") else: - raise MoveItCommanderException("There is no end effector to set the pose for") + raise MoveItCommanderException( + "There is no end effector to set the pose for" + ) - def set_orientation_target(self, q, end_effector_link = ""): + def set_orientation_target(self, q, end_effector_link=""): """ Specify a target orientation for the end-effector. Any position of the end-effector is acceptable.""" if len(end_effector_link) > 0 or self.has_end_effector_link(): if len(q) == 4: - if not self._g.set_orientation_target(q[0], q[1], q[2], q[3], end_effector_link): + if not self._g.set_orientation_target( + q[0], q[1], q[2], q[3], end_effector_link + ): raise MoveItCommanderException("Unable to set orientation target") else: raise MoveItCommanderException("Expected [qx, qy, qz, qw]") else: - raise MoveItCommanderException("There is no end effector to set the pose for") + raise MoveItCommanderException( + "There is no end effector to set the pose for" + ) - def set_position_target(self, xyz, end_effector_link = ""): + def set_position_target(self, xyz, end_effector_link=""): """ Specify a target position for the end-effector. Any orientation of the end-effector is acceptable.""" if len(end_effector_link) > 0 or self.has_end_effector_link(): - if not self._g.set_position_target(xyz[0], xyz[1], xyz[2], end_effector_link): + if not self._g.set_position_target( + xyz[0], xyz[1], xyz[2], end_effector_link + ): raise MoveItCommanderException("Unable to set position target") else: - raise MoveItCommanderException("There is no end effector to set the pose for") + raise MoveItCommanderException( + "There is no end effector to set the pose for" + ) - def set_pose_target(self, pose, end_effector_link = ""): + def set_pose_target(self, pose, end_effector_link=""): """ Set the pose of the end-effector, if one is available. The expected input is a Pose message, a PoseStamped message or a list of 6 floats:""" """ [x, y, z, rot_x, rot_y, rot_z] or a list of 7 floats [x, y, z, qx, qy, qz, qw] """ if len(end_effector_link) > 0 or self.has_end_effector_link(): @@ -281,26 +338,35 @@ def set_pose_target(self, pose, end_effector_link = ""): if type(pose) is PoseStamped: old = self.get_pose_reference_frame() self.set_pose_reference_frame(pose.header.frame_id) - ok = self._g.set_pose_target(conversions.pose_to_list(pose.pose), end_effector_link) + ok = self._g.set_pose_target( + conversions.pose_to_list(pose.pose), end_effector_link + ) self.set_pose_reference_frame(old) elif type(pose) is Pose: - ok = self._g.set_pose_target(conversions.pose_to_list(pose), end_effector_link) + ok = self._g.set_pose_target( + conversions.pose_to_list(pose), end_effector_link + ) else: ok = self._g.set_pose_target(pose, end_effector_link) if not ok: raise MoveItCommanderException("Unable to set target pose") else: - raise MoveItCommanderException("There is no end effector to set the pose for") + raise MoveItCommanderException( + "There is no end effector to set the pose for" + ) - def set_pose_targets(self, poses, end_effector_link = ""): + def set_pose_targets(self, poses, end_effector_link=""): """ Set the pose of the end-effector, if one is available. The expected input is a list of poses. Each pose can be a Pose message, a list of 6 floats: [x, y, z, rot_x, rot_y, rot_z] or a list of 7 floats [x, y, z, qx, qy, qz, qw] """ if len(end_effector_link) > 0 or self.has_end_effector_link(): - if not self._g.set_pose_targets([conversions.pose_to_list(p) if type(p) is Pose else p for p in poses], end_effector_link): + if not self._g.set_pose_targets( + [conversions.pose_to_list(p) if type(p) is Pose else p for p in poses], + end_effector_link, + ): raise MoveItCommanderException("Unable to set target poses") else: raise MoveItCommanderException("There is no end effector to set poses for") - def shift_pose_target(self, axis, value, end_effector_link = ""): + def shift_pose_target(self, axis, value, end_effector_link=""): """ Get the current pose of the end effector, add value to the corresponding axis (0..5: X, Y, Z, R, P, Y) and set the new pose as the pose target """ if len(end_effector_link) > 0 or self.has_end_effector_link(): pose = self._g.get_current_pose(end_effector_link) @@ -336,13 +402,15 @@ def get_named_targets(self): def set_named_target(self, name): """ Set a joint configuration by name. The name can be a name previlusy remembered with remember_joint_values() or a configuration specified in the SRDF. """ if not self._g.set_named_target(name): - raise MoveItCommanderException("Unable to set target %s. Is the target within bounds?" % name) + raise MoveItCommanderException( + "Unable to set target %s. Is the target within bounds?" % name + ) def get_named_target_values(self, target): """Get a dictionary of joint values of a named target""" return self._g.get_named_target_values(target) - def remember_joint_values(self, name, values = None): + def remember_joint_values(self, name, values=None): """ Record the specified joint configuration of the group under the specified name. If no values are specified, the current state of the group is recorded. """ if values is None: values = self.get_current_joint_values() @@ -358,7 +426,11 @@ def forget_joint_values(self, name): def get_goal_tolerance(self): """ Return a tuple of goal tolerances: joint, position and orientation. """ - return (self.get_goal_joint_tolerance(), self.get_goal_position_tolerance(), self.get_goal_orientation_tolerance()) + return ( + self.get_goal_joint_tolerance(), + self.get_goal_position_tolerance(), + self.get_goal_orientation_tolerance(), + ) def get_goal_joint_tolerance(self): """ Get the tolerance for achieving a joint goal (distance for each joint variable) """ @@ -404,7 +476,7 @@ def get_path_constraints(self): """ Get the acutal path constraints in form of a moveit_msgs.msgs.Constraints """ c = Constraints() c_str = self._g.get_path_constraints() - conversions.msg_from_string(c,c_str) + conversions.msg_from_string(c, c_str) return c def set_path_constraints(self, value): @@ -415,7 +487,9 @@ def set_path_constraints(self, value): if type(value) is Constraints: self._g.set_path_constraints_from_msg(conversions.msg_to_string(value)) elif not self._g.set_path_constraints(value): - raise MoveItCommanderException("Unable to set path constraints " + value) + raise MoveItCommanderException( + "Unable to set path constraints " + value + ) def clear_path_constraints(self): """ Specify that no path constraints are to be used during motion planning """ @@ -434,9 +508,13 @@ def set_trajectory_constraints(self, value): self.clear_trajectory_constraints() else: if type(value) is TrajectoryConstraints: - self._g.set_trajectory_constraints_from_msg(conversions.msg_to_string(value)) + self._g.set_trajectory_constraints_from_msg( + conversions.msg_to_string(value) + ) elif not self._g.set_trajectory_constraints(value): - raise MoveItCommanderException("Unable to set trajectory constraints " + value) + raise MoveItCommanderException( + "Unable to set trajectory constraints " + value + ) def clear_trajectory_constraints(self): """ Specify that no trajectory constraints are to be used during motion planning """ @@ -477,23 +555,29 @@ def set_workspace(self, ws): if len(ws) == 6: self._g.set_workspace(ws[0], ws[1], ws[2], ws[3], ws[4], ws[5]) else: - raise MoveItCommanderException("Expected 0, 4 or 6 values in list specifying workspace") + raise MoveItCommanderException( + "Expected 0, 4 or 6 values in list specifying workspace" + ) def set_max_velocity_scaling_factor(self, value): """ Set a scaling factor for optionally reducing the maximum joint velocity. Allowed values are in (0,1]. """ if value > 0 and value <= 1: self._g.set_max_velocity_scaling_factor(value) else: - raise MoveItCommanderException("Expected value in the range from 0 to 1 for scaling factor" ) + raise MoveItCommanderException( + "Expected value in the range from 0 to 1 for scaling factor" + ) def set_max_acceleration_scaling_factor(self, value): """ Set a scaling factor for optionally reducing the maximum joint acceleration. Allowed values are in (0,1]. """ if value > 0 and value <= 1: self._g.set_max_acceleration_scaling_factor(value) else: - raise MoveItCommanderException("Expected value in the range from 0 to 1 for scaling factor" ) + raise MoveItCommanderException( + "Expected value in the range from 0 to 1 for scaling factor" + ) - def go(self, joints = None, wait = True): + def go(self, joints=None, wait=True): """ Set the target of the group and then move the group to the specified target """ if type(joints) is bool: wait = joints @@ -515,7 +599,7 @@ def go(self, joints = None, wait = True): else: return self._g.async_move() - def plan(self, joints = None): + def plan(self, joints=None): """ Return a motion plan (a RobotTrajectory) to the set goal state (or specified by the joints argument) """ if type(joints) is JointState: self.set_joint_value_target(joints) @@ -532,42 +616,67 @@ def plan(self, joints = None): plan.deserialize(self._g.compute_plan()) return plan - def compute_cartesian_path(self, waypoints, eef_step, jump_threshold, avoid_collisions = True, path_constraints = None): + def compute_cartesian_path( + self, + waypoints, + eef_step, + jump_threshold, + avoid_collisions=True, + path_constraints=None, + ): """ Compute a sequence of waypoints that make the end-effector move in straight line segments that follow the poses specified as waypoints. Configurations are computed for every eef_step meters; The jump_threshold specifies the maximum distance in configuration space between consecutive points in the resultingpath; Kinematic constraints for the path given by path_constraints will be met for every point along the trajectory, if they are not met, a partial solution will be returned. The return value is a tuple: a fraction of how much of the path was followed, the actual RobotTrajectory. """ if path_constraints: if type(path_constraints) is Constraints: constraints_str = conversions.msg_to_string(path_constraints) else: - raise MoveItCommanderException("Unable to set path constraints, unknown constraint type " + type(path_constraints)) - (ser_path, fraction) = self._g.compute_cartesian_path([conversions.pose_to_list(p) for p in waypoints], eef_step, jump_threshold, avoid_collisions, constraints_str) + raise MoveItCommanderException( + "Unable to set path constraints, unknown constraint type " + + type(path_constraints) + ) + (ser_path, fraction) = self._g.compute_cartesian_path( + [conversions.pose_to_list(p) for p in waypoints], + eef_step, + jump_threshold, + avoid_collisions, + constraints_str, + ) else: - (ser_path, fraction) = self._g.compute_cartesian_path([conversions.pose_to_list(p) for p in waypoints], eef_step, jump_threshold, avoid_collisions) + (ser_path, fraction) = self._g.compute_cartesian_path( + [conversions.pose_to_list(p) for p in waypoints], + eef_step, + jump_threshold, + avoid_collisions, + ) path = RobotTrajectory() path.deserialize(ser_path) return (path, fraction) - def execute(self, plan_msg, wait = True): + def execute(self, plan_msg, wait=True): """Execute a previously planned path""" if wait: return self._g.execute(conversions.msg_to_string(plan_msg)) else: return self._g.async_execute(conversions.msg_to_string(plan_msg)) - def attach_object(self, object_name, link_name = "", touch_links = []): + def attach_object(self, object_name, link_name="", touch_links=[]): """ Given the name of an object existing in the planning scene, attach it to a link. The link used is specified by the second argument. If left unspecified, the end-effector link is used, if one is known. If there is no end-effector link, the first link in the group is used. If no link is identified, failure is reported. True is returned if an attach request was succesfully sent to the move_group node. This does not verify that the attach request also was successfuly applied by move_group.""" return self._g.attach_object(object_name, link_name, touch_links) - def detach_object(self, name = ""): + def detach_object(self, name=""): """ Given the name of a link, detach the object(s) from that link. If no such link exists, the name is interpreted as an object name. If there is no name specified, an attempt is made to detach all objects attached to any link in the group.""" return self._g.detach_object(name) - def pick(self, object_name, grasp = [], plan_only=False): + def pick(self, object_name, grasp=[], plan_only=False): """Pick the named object. A grasp message, or a list of Grasp messages can also be specified as argument.""" if type(grasp) is Grasp: - return self._g.pick(object_name, conversions.msg_to_string(grasp), plan_only) + return self._g.pick( + object_name, conversions.msg_to_string(grasp), plan_only + ) else: - return self._g.pick(object_name, [conversions.msg_to_string(x) for x in grasp], plan_only) + return self._g.pick( + object_name, [conversions.msg_to_string(x) for x in grasp], plan_only + ) def place(self, object_name, location=None, plan_only=False): """Place the named object at a particular location in the environment or somewhere safe in the world if location is not provided""" @@ -577,39 +686,73 @@ def place(self, object_name, location=None, plan_only=False): elif type(location) is PoseStamped: old = self.get_pose_reference_frame() self.set_pose_reference_frame(location.header.frame_id) - result = self._g.place(object_name, conversions.pose_to_list(location.pose), plan_only) + result = self._g.place( + object_name, conversions.pose_to_list(location.pose), plan_only + ) self.set_pose_reference_frame(old) elif type(location) is Pose: - result = self._g.place(object_name, conversions.pose_to_list(location), plan_only) + result = self._g.place( + object_name, conversions.pose_to_list(location), plan_only + ) elif type(location) is PlaceLocation: - result = self._g.place(object_name, conversions.msg_to_string(location), plan_only) + result = self._g.place( + object_name, conversions.msg_to_string(location), plan_only + ) elif type(location) is list: if location: if type(location[0]) is PlaceLocation: - result = self._g.place_locations_list(object_name, [conversions.msg_to_string(x) for x in location], plan_only) + result = self._g.place_locations_list( + object_name, + [conversions.msg_to_string(x) for x in location], + plan_only, + ) elif type(location[0]) is PoseStamped: - result = self._g.place_poses_list(object_name, [conversions.msg_to_string(x) for x in location], plan_only) + result = self._g.place_poses_list( + object_name, + [conversions.msg_to_string(x) for x in location], + plan_only, + ) else: - raise MoveItCommanderException("Parameter location must be a Pose, PoseStamped, PlaceLocation, list of PoseStamped or list of PlaceLocation object") + raise MoveItCommanderException( + "Parameter location must be a Pose, PoseStamped, PlaceLocation, list of PoseStamped or list of PlaceLocation object" + ) else: - raise MoveItCommanderException("Parameter location must be a Pose, PoseStamped, PlaceLocation, list of PoseStamped or list of PlaceLocation object") + raise MoveItCommanderException( + "Parameter location must be a Pose, PoseStamped, PlaceLocation, list of PoseStamped or list of PlaceLocation object" + ) return result def set_support_surface_name(self, value): """ Set the support surface name for a place operation """ self._g.set_support_surface_name(value) - def retime_trajectory(self, ref_state_in, traj_in, velocity_scaling_factor=1.0, acceleration_scaling_factor=1.0, algorithm="iterative_time_parameterization"): + def retime_trajectory( + self, + ref_state_in, + traj_in, + velocity_scaling_factor=1.0, + acceleration_scaling_factor=1.0, + algorithm="iterative_time_parameterization", + ): ser_ref_state_in = conversions.msg_to_string(ref_state_in) ser_traj_in = conversions.msg_to_string(traj_in) - ser_traj_out = self._g.retime_trajectory(ser_ref_state_in, ser_traj_in, velocity_scaling_factor, acceleration_scaling_factor, algorithm) + ser_traj_out = self._g.retime_trajectory( + ser_ref_state_in, + ser_traj_in, + velocity_scaling_factor, + acceleration_scaling_factor, + algorithm, + ) traj_out = RobotTrajectory() traj_out.deserialize(ser_traj_out) return traj_out def get_jacobian_matrix(self, joint_values, reference_point=None): """ Get the jacobian matrix of the group as a list""" - return self._g.get_jacobian_matrix(joint_values, [0.0, 0.0, 0.0] if reference_point is None else reference_point) + return self._g.get_jacobian_matrix( + joint_values, + [0.0, 0.0, 0.0] if reference_point is None else reference_point, + ) def enforce_bounds(self, robot_state_msg): """ Takes a moveit_msgs RobotState and enforces the state bounds, based on the C++ RobotState enforceBounds() """ diff --git a/moveit_commander/src/moveit_commander/planning_scene_interface.py b/moveit_commander/src/moveit_commander/planning_scene_interface.py index 9de2da057f..a2439cc658 100644 --- a/moveit_commander/src/moveit_commander/planning_scene_interface.py +++ b/moveit_commander/src/moveit_commander/planning_scene_interface.py @@ -51,21 +51,31 @@ import pyassimp except: pyassimp = False - print("Failed to import pyassimp, see https://github.com/ros-planning/moveit/issues/86 for more info") + print( + "Failed to import pyassimp, see https://github.com/ros-planning/moveit/issues/86 for more info" + ) class PlanningSceneInterface(object): """ Simple interface to making updates to a planning scene """ - def __init__(self, ns='', synchronous=False, service_timeout=5.0): + def __init__(self, ns="", synchronous=False, service_timeout=5.0): """ Create a planning scene interface; it uses both C++ wrapped methods and scene manipulation topics. """ self._psi = _moveit_planning_scene_interface.PlanningSceneInterface(ns) - self._pub_co = rospy.Publisher(ns_join(ns, 'collision_object'), CollisionObject, queue_size=100) - self._pub_aco = rospy.Publisher(ns_join(ns, 'attached_collision_object'), AttachedCollisionObject, queue_size=100) + self._pub_co = rospy.Publisher( + ns_join(ns, "collision_object"), CollisionObject, queue_size=100 + ) + self._pub_aco = rospy.Publisher( + ns_join(ns, "attached_collision_object"), + AttachedCollisionObject, + queue_size=100, + ) self.__synchronous = synchronous if self.__synchronous: - self._apply_planning_scene_diff = rospy.ServiceProxy(ns_join(ns, 'apply_planning_scene'), ApplyPlanningScene) + self._apply_planning_scene_diff = rospy.ServiceProxy( + ns_join(ns, "apply_planning_scene"), ApplyPlanningScene + ) self._apply_planning_scene_diff.wait_for_service(service_timeout) def __submit(self, collision_object, attach=False): @@ -119,7 +129,9 @@ def add_plane(self, name, pose, normal=(0, 0, 1), offset=0): co.plane_poses = [pose.pose] self.__submit(co, attach=False) - def attach_mesh(self, link, name, pose=None, filename='', size=(1, 1, 1), touch_links=[]): + def attach_mesh( + self, link, name, pose=None, filename="", size=(1, 1, 1), touch_links=[] + ): aco = AttachedCollisionObject() if (pose is not None) and filename: aco.object = self.__make_mesh(name, pose, filename, size) @@ -171,12 +183,16 @@ def get_known_object_names(self, with_type=False): """ return self._psi.get_known_object_names(with_type) - def get_known_object_names_in_roi(self, minx, miny, minz, maxx, maxy, maxz, with_type=False): + def get_known_object_names_in_roi( + self, minx, miny, minz, maxx, maxy, maxz, with_type=False + ): """ Get the names of known objects in the world that are located within a bounding region (specified in the frame reported by get_planning_frame()). If with_type is set to true, only return objects that have a known type. """ - return self._psi.get_known_object_names_in_roi(minx, miny, minz, maxx, maxy, maxz, with_type) + return self._psi.get_known_object_names_in_roi( + minx, miny, minz, maxx, maxy, maxz, with_type + ) def get_object_poses(self, object_ids): """ @@ -241,7 +257,8 @@ def __make_mesh(name, pose, filename, scale=(1, 1, 1)): co = CollisionObject() if pyassimp is False: raise MoveItCommanderException( - "Pyassimp needs patch https://launchpadlibrarian.net/319496602/patchPyassim.txt") + "Pyassimp needs patch https://launchpadlibrarian.net/319496602/patchPyassim.txt" + ) scene = pyassimp.load(filename) if not scene.meshes or len(scene.meshes) == 0: raise MoveItCommanderException("There are no meshes in the file") @@ -253,22 +270,26 @@ def __make_mesh(name, pose, filename, scale=(1, 1, 1)): mesh = Mesh() first_face = scene.meshes[0].faces[0] - if hasattr(first_face, '__len__'): + if hasattr(first_face, "__len__"): for face in scene.meshes[0].faces: if len(face) == 3: triangle = MeshTriangle() triangle.vertex_indices = [face[0], face[1], face[2]] mesh.triangles.append(triangle) - elif hasattr(first_face, 'indices'): + elif hasattr(first_face, "indices"): for face in scene.meshes[0].faces: if len(face.indices) == 3: triangle = MeshTriangle() - triangle.vertex_indices = [face.indices[0], - face.indices[1], - face.indices[2]] + triangle.vertex_indices = [ + face.indices[0], + face.indices[1], + face.indices[2], + ] mesh.triangles.append(triangle) else: - raise MoveItCommanderException("Unable to build triangles from mesh due to mesh object structure") + raise MoveItCommanderException( + "Unable to build triangles from mesh due to mesh object structure" + ) for vertex in scene.meshes[0].vertices: point = Point() point.x = vertex[0] * scale[0] diff --git a/moveit_commander/src/moveit_commander/robot.py b/moveit_commander/src/moveit_commander/robot.py index 137fe4b4b4..a9297178f4 100644 --- a/moveit_commander/src/moveit_commander/robot.py +++ b/moveit_commander/src/moveit_commander/robot.py @@ -40,7 +40,6 @@ class RobotCommander(object): - class Joint(object): def __init__(self, robot, name): self._robot = robot @@ -116,7 +115,10 @@ def move(self, position, wait=True): """ group = self._robot.get_default_owner_group(self.name()) if group is None: - raise MoveItCommanderException("There is no known group containing joint %s. Cannot move." % self._name) + raise MoveItCommanderException( + "There is no known group containing joint %s. Cannot move." + % self._name + ) gc = self._robot.get_group(group) if gc is not None: gc.set_joint_value_target(gc.get_current_joint_values()) @@ -143,7 +145,10 @@ def pose(self): """ @rtype: geometry_msgs.Pose """ - return conversions.list_to_pose_stamped(self._robot._r.get_link_pose(self._name), self._robot.get_planning_frame()) + return conversions.list_to_pose_stamped( + self._robot._r.get_link_pose(self._name), + self._robot.get_planning_frame(), + ) def __init__(self, robot_description="robot_description", ns=""): self._robot_description = robot_description @@ -264,7 +269,9 @@ def get_group(self, name): if not name in self._groups: if not self.has_group(name): raise MoveItCommanderException("There is no group named %s" % name) - self._groups[name] = MoveGroupCommander(name, self._robot_description, self._ns) + self._groups[name] = MoveGroupCommander( + name, self._robot_description, self._ns + ) return self._groups[name] def has_group(self, name): @@ -286,7 +293,9 @@ def get_default_owner_group(self, joint_name): if group is None: group = g else: - if len(self.get_link_names(g)) < len(self.get_link_names(group)): + if len(self.get_link_names(g)) < len( + self.get_link_names(group) + ): group = g self._joint_owner_groups[joint_name] = group return self._joint_owner_groups[joint_name] diff --git a/moveit_commander/src/moveit_commander/roscpp_initializer.py b/moveit_commander/src/moveit_commander/roscpp_initializer.py index 383571ee7e..8f7f5145b3 100644 --- a/moveit_commander/src/moveit_commander/roscpp_initializer.py +++ b/moveit_commander/src/moveit_commander/roscpp_initializer.py @@ -34,10 +34,12 @@ from moveit_ros_planning_interface import _moveit_roscpp_initializer + def roscpp_initialize(args): # remove __name:= argument - args2 = [ a for a in args if not a.startswith("__name:=") ] + args2 = [a for a in args if not a.startswith("__name:=")] _moveit_roscpp_initializer.roscpp_init("move_group_commander_wrappers", args2) + def roscpp_shutdown(): _moveit_roscpp_initializer.roscpp_shutdown() diff --git a/moveit_commander/test/python_moveit_commander.py b/moveit_commander/test/python_moveit_commander.py index 294f562e83..40637d3dca 100755 --- a/moveit_commander/test/python_moveit_commander.py +++ b/moveit_commander/test/python_moveit_commander.py @@ -66,8 +66,15 @@ def test_enforce_bounds_empty_state(self): def test_enforce_bounds(self): in_msg = RobotState() - in_msg.joint_state.header.frame_id = 'base_link' - in_msg.joint_state.name = ['joint_1', 'joint_2', 'joint_3', 'joint_4', 'joint_5', 'joint_6'] + in_msg.joint_state.header.frame_id = "base_link" + in_msg.joint_state.name = [ + "joint_1", + "joint_2", + "joint_3", + "joint_4", + "joint_5", + "joint_6", + ] in_msg.joint_state.position = [0] * 6 in_msg.joint_state.position[0] = 1000 @@ -78,9 +85,16 @@ def test_enforce_bounds(self): def test_get_current_state(self): expected_state = RobotState() - expected_state.joint_state.header.frame_id = 'base_link' - expected_state.multi_dof_joint_state.header.frame_id = 'base_link' - expected_state.joint_state.name = ['joint_1', 'joint_2', 'joint_3', 'joint_4', 'joint_5', 'joint_6'] + expected_state.joint_state.header.frame_id = "base_link" + expected_state.multi_dof_joint_state.header.frame_id = "base_link" + expected_state.joint_state.name = [ + "joint_1", + "joint_2", + "joint_3", + "joint_4", + "joint_5", + "joint_6", + ] expected_state.joint_state.position = [0] * 6 self.assertEqual(self.group.get_current_state(), expected_state) @@ -89,16 +103,20 @@ def check_target_setting(self, expect, *args): args = [expect] self.group.set_joint_value_target(*args) res = self.group.get_joint_value_target() - self.assertTrue(np.all(np.asarray(res) == np.asarray(expect)), - "Setting failed for %s, values: %s" % (type(args[0]), res)) + self.assertTrue( + np.all(np.asarray(res) == np.asarray(expect)), + "Setting failed for %s, values: %s" % (type(args[0]), res), + ) def test_target_setting(self): n = self.group.get_variable_count() self.check_target_setting([0.1] * n) self.check_target_setting((0.2,) * n) self.check_target_setting(np.zeros(n)) - self.check_target_setting([0.3] * n, {name: 0.3 for name in self.group.get_active_joints()}) - self.check_target_setting([0.5] + [0.3]*(n-1), "joint_1", 0.5) + self.check_target_setting( + [0.3] * n, {name: 0.3 for name in self.group.get_active_joints()} + ) + self.check_target_setting([0.5] + [0.3] * (n - 1), "joint_1", 0.5) def plan(self, target): self.group.set_joint_value_target(target) @@ -124,9 +142,9 @@ def test_planning_scene_interface(self): planning_scene = PlanningSceneInterface() -if __name__ == '__main__': - PKGNAME = 'moveit_ros_planning_interface' - NODENAME = 'moveit_test_python_moveit_commander' +if __name__ == "__main__": + PKGNAME = "moveit_ros_planning_interface" + NODENAME = "moveit_test_python_moveit_commander" rospy.init_node(NODENAME) rostest.rosrun(PKGNAME, NODENAME, PythonMoveitCommanderTest) diff --git a/moveit_commander/test/python_moveit_commander_ns.py b/moveit_commander/test/python_moveit_commander_ns.py index efaa6f03d3..4b73802841 100755 --- a/moveit_commander/test/python_moveit_commander_ns.py +++ b/moveit_commander/test/python_moveit_commander_ns.py @@ -52,7 +52,9 @@ class PythonMoveitCommanderNsTest(unittest.TestCase): @classmethod def setUpClass(self): - self.commander = RobotCommander("%srobot_description"%self.PLANNING_NS, self.PLANNING_NS) + self.commander = RobotCommander( + "%srobot_description" % self.PLANNING_NS, self.PLANNING_NS + ) self.group = self.commander.get_group(self.PLANNING_GROUP) @classmethod @@ -64,16 +66,20 @@ def check_target_setting(self, expect, *args): args = [expect] self.group.set_joint_value_target(*args) res = self.group.get_joint_value_target() - self.assertTrue(np.all(np.asarray(res) == np.asarray(expect)), - "Setting failed for %s, values: %s" % (type(args[0]), res)) + self.assertTrue( + np.all(np.asarray(res) == np.asarray(expect)), + "Setting failed for %s, values: %s" % (type(args[0]), res), + ) def test_target_setting(self): n = self.group.get_variable_count() self.check_target_setting([0.1] * n) self.check_target_setting((0.2,) * n) self.check_target_setting(np.zeros(n)) - self.check_target_setting([0.3] * n, {name: 0.3 for name in self.group.get_active_joints()}) - self.check_target_setting([0.5] + [0.3]*(n-1), "joint_1", 0.5) + self.check_target_setting( + [0.3] * n, {name: 0.3 for name in self.group.get_active_joints()} + ) + self.check_target_setting([0.5] + [0.3] * (n - 1), "joint_1", 0.5) def plan(self, target): self.group.set_joint_value_target(target) @@ -96,9 +102,9 @@ def test_validation(self): self.assertTrue(self.group.execute(plan3)) -if __name__ == '__main__': - PKGNAME = 'moveit_ros_planning_interface' - NODENAME = 'moveit_test_python_moveit_commander_ns' +if __name__ == "__main__": + PKGNAME = "moveit_ros_planning_interface" + NODENAME = "moveit_test_python_moveit_commander_ns" rospy.init_node(NODENAME) rostest.rosrun(PKGNAME, NODENAME, PythonMoveitCommanderNsTest) diff --git a/moveit_commander/test/python_moveit_commander_ros_namespace.py b/moveit_commander/test/python_moveit_commander_ros_namespace.py index 2b36e937a2..b7de1f059e 100755 --- a/moveit_commander/test/python_moveit_commander_ros_namespace.py +++ b/moveit_commander/test/python_moveit_commander_ros_namespace.py @@ -46,7 +46,6 @@ class PythonMoveitCommanderRosNamespaceTest(unittest.TestCase): - def test_namespace(self): self.scene = PlanningSceneInterface() expected_resolved_co_name = "/test_ros_namespace/collision_object" @@ -57,12 +56,15 @@ def test_namespace(self): def test_namespace_synchronous(self): self.scene = PlanningSceneInterface(synchronous=True) expected_resolved_apply_diff_name = "/test_ros_namespace/apply_planning_scene" - self.assertEqual(self.scene._apply_planning_scene_diff.resolved_name, expected_resolved_apply_diff_name) + self.assertEqual( + self.scene._apply_planning_scene_diff.resolved_name, + expected_resolved_apply_diff_name, + ) -if __name__ == '__main__': - PKGNAME = 'moveit_ros_planning_interface' - NODENAME = 'moveit_test_python_moveit_commander_ros_namespace' +if __name__ == "__main__": + PKGNAME = "moveit_ros_planning_interface" + NODENAME = "moveit_test_python_moveit_commander_ros_namespace" rospy.init_node(NODENAME) rostest.rosrun(PKGNAME, NODENAME, PythonMoveitCommanderRosNamespaceTest) diff --git a/moveit_commander/test/python_time_parameterization.py b/moveit_commander/test/python_time_parameterization.py index 3fe1a9809f..1cf587d6af 100755 --- a/moveit_commander/test/python_time_parameterization.py +++ b/moveit_commander/test/python_time_parameterization.py @@ -59,34 +59,52 @@ def plan(self): start_pose = self.group.get_current_pose().pose goal_pose = self.group.get_current_pose().pose goal_pose.position.z -= 0.1 - (plan, fraction) = self.group.compute_cartesian_path([start_pose, goal_pose], 0.005, 0.0) + (plan, fraction) = self.group.compute_cartesian_path( + [start_pose, goal_pose], 0.005, 0.0 + ) self.assertEqual(fraction, 1.0, "Cartesian path plan failed") return plan def time_parameterization(self, plan, algorithm): ref_state = self.commander.get_current_state() retimed_plan = self.group.retime_trajectory( - ref_state, plan, + ref_state, + plan, velocity_scaling_factor=0.1, acceleration_scaling_factor=0.1, - algorithm=algorithm) + algorithm=algorithm, + ) return retimed_plan - def test_plan_and_time_parameterization(self): plan = self.plan() - retimed_plan = self.time_parameterization(plan, "iterative_time_parameterization") - self.assertTrue(len(retimed_plan.joint_trajectory.points) > 0, "Retimed plan is invalid") - retimed_plan = self.time_parameterization(plan, "iterative_spline_parameterization") - self.assertTrue(len(retimed_plan.joint_trajectory.points) > 0, "Retimed plan is invalid") - retimed_plan = self.time_parameterization(plan, "time_optimal_trajectory_generation") - self.assertTrue(len(retimed_plan.joint_trajectory.points) > 0, "Retimed plan is invalid") + retimed_plan = self.time_parameterization( + plan, "iterative_time_parameterization" + ) + self.assertTrue( + len(retimed_plan.joint_trajectory.points) > 0, "Retimed plan is invalid" + ) + retimed_plan = self.time_parameterization( + plan, "iterative_spline_parameterization" + ) + self.assertTrue( + len(retimed_plan.joint_trajectory.points) > 0, "Retimed plan is invalid" + ) + retimed_plan = self.time_parameterization( + plan, "time_optimal_trajectory_generation" + ) + self.assertTrue( + len(retimed_plan.joint_trajectory.points) > 0, "Retimed plan is invalid" + ) retimed_plan = self.time_parameterization(plan, "") - self.assertTrue(len(retimed_plan.joint_trajectory.points) == 0, "Invalid retime algorithm") + self.assertTrue( + len(retimed_plan.joint_trajectory.points) == 0, "Invalid retime algorithm" + ) + -if __name__ == '__main__': - PKGNAME = 'moveit_ros_planning_interface' - NODENAME = 'moveit_test_python_time_parameterization' +if __name__ == "__main__": + PKGNAME = "moveit_ros_planning_interface" + NODENAME = "moveit_test_python_time_parameterization" rospy.init_node(NODENAME) rostest.rosrun(PKGNAME, NODENAME, PythonTimeParameterizationTest) diff --git a/moveit_core/background_processing/src/background_processing.cpp b/moveit_core/background_processing/src/background_processing.cpp index f86c879260..8b9e8f66e3 100644 --- a/moveit_core/background_processing/src/background_processing.cpp +++ b/moveit_core/background_processing/src/background_processing.cpp @@ -139,4 +139,4 @@ void BackgroundProcessing::clearJobUpdateEvent() } } // end of namespace tools -} // end of namespace moveit \ No newline at end of file +} // end of namespace moveit diff --git a/moveit_core/collision_detection/src/collision_world.cpp b/moveit_core/collision_detection/src/collision_world.cpp index ec2f3abcf9..68bd11235f 100644 --- a/moveit_core/collision_detection/src/collision_world.cpp +++ b/moveit_core/collision_detection/src/collision_world.cpp @@ -93,4 +93,4 @@ void CollisionWorld::setWorld(const WorldPtr& world) world_const_ = world; } -} // end of namespace collision_detection \ No newline at end of file +} // end of namespace collision_detection diff --git a/moveit_core/collision_detection/test/test_all_valid.cpp b/moveit_core/collision_detection/test/test_all_valid.cpp index 47a33a81cf..16aaab8a64 100644 --- a/moveit_core/collision_detection/test/test_all_valid.cpp +++ b/moveit_core/collision_detection/test/test_all_valid.cpp @@ -58,4 +58,4 @@ int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} \ No newline at end of file +} diff --git a/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_detector_fcl_plugin_loader.h b/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_detector_fcl_plugin_loader.h index 81e3995bab..2bf3c7759f 100644 --- a/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_detector_fcl_plugin_loader.h +++ b/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_detector_fcl_plugin_loader.h @@ -16,4 +16,4 @@ class CollisionDetectorFCLPluginLoader : public CollisionPlugin virtual bool initialize(const planning_scene::PlanningScenePtr& scene, bool exclusive) const; }; } // namespace collision_detection -#endif // MOVEIT_COLLISION_DETECTION_FCL_COLLISION_DETECTOR_FCL_PLUGIN_LOADER_H_ \ No newline at end of file +#endif // MOVEIT_COLLISION_DETECTION_FCL_COLLISION_DETECTOR_FCL_PLUGIN_LOADER_H_ diff --git a/moveit_core/collision_detector_fcl_description.xml b/moveit_core/collision_detector_fcl_description.xml index 0bd2cfbdb1..f96b06c05e 100644 --- a/moveit_core/collision_detector_fcl_description.xml +++ b/moveit_core/collision_detector_fcl_description.xml @@ -5,4 +5,4 @@ FCL Collision Detector, default for MoveIt. - \ No newline at end of file + diff --git a/moveit_core/constraint_samplers/dox/constraint_samplers.dox b/moveit_core/constraint_samplers/dox/constraint_samplers.dox index 45205f8b6e..86a82fb560 100644 --- a/moveit_core/constraint_samplers/dox/constraint_samplers.dox +++ b/moveit_core/constraint_samplers/dox/constraint_samplers.dox @@ -4,4 +4,4 @@ See constraint_samplers namespace -*/ \ No newline at end of file +*/ diff --git a/moveit_core/constraint_samplers/src/default_constraint_samplers.cpp b/moveit_core/constraint_samplers/src/default_constraint_samplers.cpp index 643d4d3418..49e35a6710 100644 --- a/moveit_core/constraint_samplers/src/default_constraint_samplers.cpp +++ b/moveit_core/constraint_samplers/src/default_constraint_samplers.cpp @@ -647,4 +647,4 @@ bool IKConstraintSampler::callIK(const geometry_msgs::Pose& ik_query, return false; } -} // end of namespace constraint_samplers \ No newline at end of file +} // end of namespace constraint_samplers diff --git a/moveit_core/constraint_samplers/src/union_constraint_sampler.cpp b/moveit_core/constraint_samplers/src/union_constraint_sampler.cpp index 84dbc233f9..ceb6801279 100644 --- a/moveit_core/constraint_samplers/src/union_constraint_sampler.cpp +++ b/moveit_core/constraint_samplers/src/union_constraint_sampler.cpp @@ -161,4 +161,4 @@ bool UnionConstraintSampler::project(robot_state::RobotState& state, unsigned in return true; } -} // end of namespace constraint_samplers \ No newline at end of file +} // end of namespace constraint_samplers diff --git a/moveit_core/distance_field/src/distance_field.cpp b/moveit_core/distance_field/src/distance_field.cpp index 071777706b..ed9133c34e 100644 --- a/moveit_core/distance_field/src/distance_field.cpp +++ b/moveit_core/distance_field/src/distance_field.cpp @@ -557,4 +557,4 @@ void DistanceField::getProjectionPlanes(const std::string& frame_id, const ros:: delete[] z_projection; } -} // end of namespace distance_field \ No newline at end of file +} // end of namespace distance_field diff --git a/moveit_core/dynamics_solver/src/dynamics_solver.cpp b/moveit_core/dynamics_solver/src/dynamics_solver.cpp index 0ff30f9dec..530d5d0799 100644 --- a/moveit_core/dynamics_solver/src/dynamics_solver.cpp +++ b/moveit_core/dynamics_solver/src/dynamics_solver.cpp @@ -313,4 +313,4 @@ const std::vector& DynamicsSolver::getMaxTorques() const return max_torques_; } -} // end of namespace dynamics_solver \ No newline at end of file +} // end of namespace dynamics_solver diff --git a/moveit_core/planning_interface/src/planning_interface.cpp b/moveit_core/planning_interface/src/planning_interface.cpp index 26c393c997..32337f3de3 100644 --- a/moveit_core/planning_interface/src/planning_interface.cpp +++ b/moveit_core/planning_interface/src/planning_interface.cpp @@ -127,4 +127,4 @@ void PlannerManager::terminate() const (*it)->terminate(); } -} // end of namespace planning_interface \ No newline at end of file +} // end of namespace planning_interface diff --git a/moveit_core/planning_request_adapter/src/planning_request_adapter.cpp b/moveit_core/planning_request_adapter/src/planning_request_adapter.cpp index a62ac0acb3..37b942b2cf 100644 --- a/moveit_core/planning_request_adapter/src/planning_request_adapter.cpp +++ b/moveit_core/planning_request_adapter/src/planning_request_adapter.cpp @@ -166,4 +166,4 @@ bool PlanningRequestAdapterChain::adaptAndPlan(const planning_interface::Planner } } -} // end of namespace planning_request_adapter \ No newline at end of file +} // end of namespace planning_request_adapter diff --git a/moveit_core/robot_model/src/fixed_joint_model.cpp b/moveit_core/robot_model/src/fixed_joint_model.cpp index a5c8d288c3..1bb2fd8bb1 100644 --- a/moveit_core/robot_model/src/fixed_joint_model.cpp +++ b/moveit_core/robot_model/src/fixed_joint_model.cpp @@ -100,4 +100,4 @@ void FixedJointModel::computeVariablePositions(const Eigen::Isometry3d& /* trans } } // end of namespace core -} // end of namespace moveit \ No newline at end of file +} // end of namespace moveit diff --git a/moveit_core/robot_model/src/link_model.cpp b/moveit_core/robot_model/src/link_model.cpp index 9c8dfcfa3b..32e9590d9d 100644 --- a/moveit_core/robot_model/src/link_model.cpp +++ b/moveit_core/robot_model/src/link_model.cpp @@ -121,4 +121,4 @@ void LinkModel::setVisualMesh(const std::string& visual_mesh, const Eigen::Isome } } // end of namespace core -} // end of namespace moveit \ No newline at end of file +} // end of namespace moveit diff --git a/moveit_core/robot_model/src/order_robot_model_items.inc b/moveit_core/robot_model/src/order_robot_model_items.inc index 8c6a261773..5f7200306b 100644 --- a/moveit_core/robot_model/src/order_robot_model_items.inc +++ b/moveit_core/robot_model/src/order_robot_model_items.inc @@ -67,4 +67,4 @@ struct OrderGroupsByName } } -} \ No newline at end of file +} diff --git a/moveit_core/robot_model/src/planar_joint_model.cpp b/moveit_core/robot_model/src/planar_joint_model.cpp index 10a8ac5879..aca66d5ba0 100644 --- a/moveit_core/robot_model/src/planar_joint_model.cpp +++ b/moveit_core/robot_model/src/planar_joint_model.cpp @@ -237,4 +237,4 @@ void PlanarJointModel::computeVariablePositions(const Eigen::Isometry3d& transf, } } // end of namespace core -} // end of namespace moveit \ No newline at end of file +} // end of namespace moveit diff --git a/moveit_core/robot_model/src/prismatic_joint_model.cpp b/moveit_core/robot_model/src/prismatic_joint_model.cpp index 2f2166edb5..65a95ad507 100644 --- a/moveit_core/robot_model/src/prismatic_joint_model.cpp +++ b/moveit_core/robot_model/src/prismatic_joint_model.cpp @@ -149,4 +149,4 @@ void PrismaticJointModel::computeVariablePositions(const Eigen::Isometry3d& tran } } // end of namespace core -} // end of namespace moveit \ No newline at end of file +} // end of namespace moveit diff --git a/moveit_experimental/collision_distance_field_ros/Makefile b/moveit_experimental/collision_distance_field_ros/Makefile index b75b928f20..bbd3fc6049 100644 --- a/moveit_experimental/collision_distance_field_ros/Makefile +++ b/moveit_experimental/collision_distance_field_ros/Makefile @@ -1 +1 @@ -include $(shell rospack find mk)/cmake.mk \ No newline at end of file +include $(shell rospack find mk)/cmake.mk diff --git a/moveit_experimental/collision_distance_field_ros/mainpage.dox b/moveit_experimental/collision_distance_field_ros/mainpage.dox index 5aa6d661cd..a8ca7e0512 100644 --- a/moveit_experimental/collision_distance_field_ros/mainpage.dox +++ b/moveit_experimental/collision_distance_field_ros/mainpage.dox @@ -2,9 +2,9 @@ \mainpage \htmlinclude manifest.html -\b collision_distance_field_ros +\b collision_distance_field_ros - diff --git a/moveit_experimental/collision_distance_field_ros/manifest.xml b/moveit_experimental/collision_distance_field_ros/manifest.xml index d29dffb155..c612633e9c 100644 --- a/moveit_experimental/collision_distance_field_ros/manifest.xml +++ b/moveit_experimental/collision_distance_field_ros/manifest.xml @@ -16,5 +16,3 @@ - - diff --git a/moveit_experimental/kinematics_cache/v1/kinematics_cache/Makefile b/moveit_experimental/kinematics_cache/v1/kinematics_cache/Makefile index b75b928f20..bbd3fc6049 100644 --- a/moveit_experimental/kinematics_cache/v1/kinematics_cache/Makefile +++ b/moveit_experimental/kinematics_cache/v1/kinematics_cache/Makefile @@ -1 +1 @@ -include $(shell rospack find mk)/cmake.mk \ No newline at end of file +include $(shell rospack find mk)/cmake.mk diff --git a/moveit_experimental/kinematics_cache/v1/kinematics_cache/mainpage.dox b/moveit_experimental/kinematics_cache/v1/kinematics_cache/mainpage.dox index 29c7b2feff..a96ba936ff 100644 --- a/moveit_experimental/kinematics_cache/v1/kinematics_cache/mainpage.dox +++ b/moveit_experimental/kinematics_cache/v1/kinematics_cache/mainpage.dox @@ -2,9 +2,9 @@ \mainpage \htmlinclude manifest.html -\b kinematics_cache +\b kinematics_cache - diff --git a/moveit_experimental/kinematics_cache/v1/kinematics_cache_ros/Makefile b/moveit_experimental/kinematics_cache/v1/kinematics_cache_ros/Makefile index b75b928f20..bbd3fc6049 100644 --- a/moveit_experimental/kinematics_cache/v1/kinematics_cache_ros/Makefile +++ b/moveit_experimental/kinematics_cache/v1/kinematics_cache_ros/Makefile @@ -1 +1 @@ -include $(shell rospack find mk)/cmake.mk \ No newline at end of file +include $(shell rospack find mk)/cmake.mk diff --git a/moveit_experimental/kinematics_cache/v1/kinematics_cache_ros/manifest.xml b/moveit_experimental/kinematics_cache/v1/kinematics_cache_ros/manifest.xml index 4eb7facc5b..cf86451d79 100644 --- a/moveit_experimental/kinematics_cache/v1/kinematics_cache_ros/manifest.xml +++ b/moveit_experimental/kinematics_cache/v1/kinematics_cache_ros/manifest.xml @@ -17,5 +17,3 @@ - - diff --git a/moveit_experimental/kinematics_cache/v2/kinematics_cache/CMakeLists.txt b/moveit_experimental/kinematics_cache/v2/kinematics_cache/CMakeLists.txt index 6dcd3680b0..6667751f5b 100644 --- a/moveit_experimental/kinematics_cache/v2/kinematics_cache/CMakeLists.txt +++ b/moveit_experimental/kinematics_cache/v2/kinematics_cache/CMakeLists.txt @@ -14,4 +14,3 @@ install(TARGETS ${MOVEIT_LIB_NAME} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) install(DIRECTORY include/ DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}) - diff --git a/moveit_kinematics/cached_ik_kinematics_plugin/CMakeLists.txt b/moveit_kinematics/cached_ik_kinematics_plugin/CMakeLists.txt index b295d3eb50..15f08b94a8 100644 --- a/moveit_kinematics/cached_ik_kinematics_plugin/CMakeLists.txt +++ b/moveit_kinematics/cached_ik_kinematics_plugin/CMakeLists.txt @@ -9,7 +9,7 @@ set_target_properties(${MOVEIT_LIB_NAME} PROPERTIES VERSION "${${PROJECT_NAME}_V target_link_libraries(${MOVEIT_LIB_NAME} ${Boost_FILESYSTEM_LIBRARY} ${catkin_LIBRARIES}) -install(TARGETS ${MOVEIT_LIB_NAME} +install(TARGETS ${MOVEIT_LIB_NAME} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) @@ -30,7 +30,7 @@ if(trac_ik_kinematics_plugin_FOUND) target_link_libraries(${MOVEIT_LIB_NAME} ${trac_ik_kinematics_plugin_LIBRARIES}) set_target_properties(${MOVEIT_LIB_NAME} PROPERTIES COMPILE_DEFINITIONS "CACHED_IK_KINEMATICS_TRAC_IK") endif() -install(TARGETS ${MOVEIT_LIB_NAME} +install(TARGETS ${MOVEIT_LIB_NAME} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) @@ -48,7 +48,7 @@ if(ur_kinematics_FOUND) moveit_cached_ik_kinematics_base ${ur${UR}_pluginlib} ${catkin_LIBRARIES}) - install(TARGETS ${MOVEIT_LIB_NAME} + install(TARGETS ${MOVEIT_LIB_NAME} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) diff --git a/moveit_kinematics/ikfast_kinematics_plugin/scripts/create_ikfast_moveit_plugin.py b/moveit_kinematics/ikfast_kinematics_plugin/scripts/create_ikfast_moveit_plugin.py index 0617eeb17a..ff80dcdc2d 100755 --- a/moveit_kinematics/ikfast_kinematics_plugin/scripts/create_ikfast_moveit_plugin.py +++ b/moveit_kinematics/ikfast_kinematics_plugin/scripts/create_ikfast_moveit_plugin.py @@ -1,6 +1,7 @@ #! /usr/bin/env python from __future__ import print_function -''' + +""" IKFast Plugin Generator for MoveIt! Creates a kinematics plugin using the output of IKFast from OpenRAVE. @@ -15,8 +16,8 @@ Date: March 2013 -''' -''' +""" +""" Copyright (c) 2013, Jeremy Zoss, SwRI All rights reserved. @@ -43,7 +44,7 @@ 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. -''' +""" import re import os @@ -54,252 +55,360 @@ import argparse try: - from roslib.packages import get_pkg_dir, InvalidROSPkgException + from roslib.packages import get_pkg_dir, InvalidROSPkgException except ImportError: - print("Failed to import roslib. No ROS environment available? Trying without.") - # define stubs - class InvalidROSPkgException(Exception): - pass - def get_pkg_dir(pkg_name): - raise InvalidROSPkgException('Failed to locate ROS package {}'.format(pkg_name)) + print("Failed to import roslib. No ROS environment available? Trying without.") + # define stubs + class InvalidROSPkgException(Exception): + pass + + def get_pkg_dir(pkg_name): + raise InvalidROSPkgException("Failed to locate ROS package {}".format(pkg_name)) + # Package containing this file -plugin_gen_pkg = 'moveit_kinematics' +plugin_gen_pkg = "moveit_kinematics" # Allowed search modes, see SEARCH_MODE enum in template file -search_modes = ['OPTIMIZE_MAX_JOINT', 'OPTIMIZE_FREE_JOINT'] +search_modes = ["OPTIMIZE_MAX_JOINT", "OPTIMIZE_FREE_JOINT"] def create_parser(): - parser = argparse.ArgumentParser( - description="Generate an IKFast MoveIt! kinematic plugin") - parser.add_argument("robot_name", - help="The name of your robot") - parser.add_argument("planning_group_name", - help="The name of the planning group for which your IKFast solution was generated") - parser.add_argument("ikfast_plugin_pkg", - help="The name of the MoveIt! IKFast Kinematics Plugin to be created/updated") - parser.add_argument("base_link_name", - help="The name of the base link that was used when generating your IKFast solution") - parser.add_argument("eef_link_name", - help="The name of the end effector link that was used when generating your IKFast solution") - parser.add_argument("ikfast_output_path", - help="The full path to the analytic IK solution output by IKFast") - parser.add_argument("--search_mode", - default=search_modes[0], - help="The search mode used to solve IK for robots with more than 6DOF") - parser.add_argument("--srdf_filename", - help="The name of your robot. Defaults to .srdf") - parser.add_argument("--robot_name_in_srdf", - help="The name of your robot as defined in the srdf. Defaults to ") - parser.add_argument("--moveit_config_pkg", - help="The robot moveit_config package. Defaults to _moveit_config") - return parser + parser = argparse.ArgumentParser( + description="Generate an IKFast MoveIt! kinematic plugin" + ) + parser.add_argument("robot_name", help="The name of your robot") + parser.add_argument( + "planning_group_name", + help="The name of the planning group for which your IKFast solution was generated", + ) + parser.add_argument( + "ikfast_plugin_pkg", + help="The name of the MoveIt! IKFast Kinematics Plugin to be created/updated", + ) + parser.add_argument( + "base_link_name", + help="The name of the base link that was used when generating your IKFast solution", + ) + parser.add_argument( + "eef_link_name", + help="The name of the end effector link that was used when generating your IKFast solution", + ) + parser.add_argument( + "ikfast_output_path", + help="The full path to the analytic IK solution output by IKFast", + ) + parser.add_argument( + "--search_mode", + default=search_modes[0], + help="The search mode used to solve IK for robots with more than 6DOF", + ) + parser.add_argument( + "--srdf_filename", help="The name of your robot. Defaults to .srdf" + ) + parser.add_argument( + "--robot_name_in_srdf", + help="The name of your robot as defined in the srdf. Defaults to ", + ) + parser.add_argument( + "--moveit_config_pkg", + help="The robot moveit_config package. Defaults to _moveit_config", + ) + return parser def populate_optional(args): - if args.srdf_filename is None: - args.srdf_filename = args.robot_name + ".srdf" - if args.robot_name_in_srdf is None: - args.robot_name_in_srdf = args.robot_name - if args.moveit_config_pkg is None: - args.moveit_config_pkg = args.robot_name + "_moveit_config" + if args.srdf_filename is None: + args.srdf_filename = args.robot_name + ".srdf" + if args.robot_name_in_srdf is None: + args.robot_name_in_srdf = args.robot_name + if args.moveit_config_pkg is None: + args.moveit_config_pkg = args.robot_name + "_moveit_config" def print_args(args): - print("Creating IKFastKinematicsPlugin with parameters: ") - print(" robot_name: %s" % args.robot_name) - print(" base_link_name: %s" % args.base_link_name) - print(" eef_link_name: %s" % args.eef_link_name) - print(" planning_group_name: %s" % args.planning_group_name) - print(" ikfast_plugin_pkg: %s" % args.ikfast_plugin_pkg) - print(" ikfast_output_path: %s" % args.ikfast_output_path) - print(" search_mode: %s" % args.search_mode) - print(" srdf_filename: %s" % args.srdf_filename) - print(" robot_name_in_srdf: %s" % args.robot_name_in_srdf) - print(" moveit_config_pkg: %s" % args.moveit_config_pkg) - print("") + print("Creating IKFastKinematicsPlugin with parameters: ") + print(" robot_name: %s" % args.robot_name) + print(" base_link_name: %s" % args.base_link_name) + print(" eef_link_name: %s" % args.eef_link_name) + print(" planning_group_name: %s" % args.planning_group_name) + print(" ikfast_plugin_pkg: %s" % args.ikfast_plugin_pkg) + print(" ikfast_output_path: %s" % args.ikfast_output_path) + print(" search_mode: %s" % args.search_mode) + print(" srdf_filename: %s" % args.srdf_filename) + print(" robot_name_in_srdf: %s" % args.robot_name_in_srdf) + print(" moveit_config_pkg: %s" % args.moveit_config_pkg) + print("") def update_deps(reqd_deps, req_type, e_parent): - curr_deps = [e.text for e in e_parent.findall(req_type)] - missing_deps = set(reqd_deps) - set(curr_deps) - for dep in missing_deps: - etree.SubElement(e_parent, req_type).text = dep + curr_deps = [e.text for e in e_parent.findall(req_type)] + missing_deps = set(reqd_deps) - set(curr_deps) + for dep in missing_deps: + etree.SubElement(e_parent, req_type).text = dep def validate_openrave_version(args): - if not os.path.exists(args.ikfast_output_path): - raise Exception("Can't find IKFast source code at " + args.ikfast_output_path) - - # Detect version of IKFast used to generate solver code - solver_version = 0 - with open(args.ikfast_output_path, 'r') as src: - for line in src: - if line.startswith('/// ikfast version'): - line_search = re.search('ikfast version (.*) generated', line) - if line_search: - solver_version = int(line_search.group(1), 0) & ~0x10000000 - break - print('Found source code generated by IKFast version %s' % str(solver_version)) - - # Chose template depending on IKFast version - if solver_version >= 56: - setattr(args, 'template_version', 61) - else: - raise Exception('This converter requires IKFast 0.5.6 or newer.') + if not os.path.exists(args.ikfast_output_path): + raise Exception("Can't find IKFast source code at " + args.ikfast_output_path) + + # Detect version of IKFast used to generate solver code + solver_version = 0 + with open(args.ikfast_output_path, "r") as src: + for line in src: + if line.startswith("/// ikfast version"): + line_search = re.search("ikfast version (.*) generated", line) + if line_search: + solver_version = int(line_search.group(1), 0) & ~0x10000000 + break + print("Found source code generated by IKFast version %s" % str(solver_version)) + + # Chose template depending on IKFast version + if solver_version >= 56: + setattr(args, "template_version", 61) + else: + raise Exception("This converter requires IKFast 0.5.6 or newer.") + def xmlElement(name, text=None, **attributes): - e = etree.Element(name, **attributes) - e.text = text - return e + e = etree.Element(name, **attributes) + e.text = text + return e + def create_ikfast_package(args): - try: - setattr(args, 'ikfast_plugin_pkg_path', get_pkg_dir(args.ikfast_plugin_pkg)) - except InvalidROSPkgException: - args.ikfast_plugin_pkg_path = os.path.abspath(args.ikfast_plugin_pkg) - print("Failed to find package: %s. Will create it in %s." % - (args.ikfast_plugin_pkg, args.ikfast_plugin_pkg_path)) - # update pkg name to basename of path - args.ikfast_plugin_pkg=os.path.basename(args.ikfast_plugin_pkg_path) - - src_path = args.ikfast_plugin_pkg_path + '/src/' - if not os.path.exists(src_path): - os.makedirs(src_path) - - include_path = args.ikfast_plugin_pkg_path + '/include/' - if not os.path.exists(include_path): - os.makedirs(include_path) - - # Create package.xml - pkg_xml_path = args.ikfast_plugin_pkg_path + '/package.xml' - if not os.path.exists(pkg_xml_path): - root = xmlElement("package", format="2") - root.append(xmlElement("name", text=args.ikfast_plugin_pkg)) - root.append(xmlElement("version", text="0.0.0")) - root.append(xmlElement("description", text="IKFast plugin for " + args.robot_name)) - root.append(xmlElement("license", text="BSD")) - user_name = getuser() - root.append(xmlElement("maintainer", email="%s@todo.todo" % user_name, text=user_name)) - root.append(xmlElement("buildtool_depend", text="catkin")) - etree.ElementTree(root).write(pkg_xml_path, xml_declaration=True, pretty_print=True, encoding="UTF-8") - print("Created package.xml at: '%s'" % pkg_xml_path) + try: + setattr(args, "ikfast_plugin_pkg_path", get_pkg_dir(args.ikfast_plugin_pkg)) + except InvalidROSPkgException: + args.ikfast_plugin_pkg_path = os.path.abspath(args.ikfast_plugin_pkg) + print( + "Failed to find package: %s. Will create it in %s." + % (args.ikfast_plugin_pkg, args.ikfast_plugin_pkg_path) + ) + # update pkg name to basename of path + args.ikfast_plugin_pkg = os.path.basename(args.ikfast_plugin_pkg_path) + + src_path = args.ikfast_plugin_pkg_path + "/src/" + if not os.path.exists(src_path): + os.makedirs(src_path) + + include_path = args.ikfast_plugin_pkg_path + "/include/" + if not os.path.exists(include_path): + os.makedirs(include_path) + + # Create package.xml + pkg_xml_path = args.ikfast_plugin_pkg_path + "/package.xml" + if not os.path.exists(pkg_xml_path): + root = xmlElement("package", format="2") + root.append(xmlElement("name", text=args.ikfast_plugin_pkg)) + root.append(xmlElement("version", text="0.0.0")) + root.append( + xmlElement("description", text="IKFast plugin for " + args.robot_name) + ) + root.append(xmlElement("license", text="BSD")) + user_name = getuser() + root.append( + xmlElement("maintainer", email="%s@todo.todo" % user_name, text=user_name) + ) + root.append(xmlElement("buildtool_depend", text="catkin")) + etree.ElementTree(root).write( + pkg_xml_path, xml_declaration=True, pretty_print=True, encoding="UTF-8" + ) + print("Created package.xml at: '%s'" % pkg_xml_path) def find_template_dir(): - for candidate in [os.path.dirname(__file__) + '/../templates']: - if os.path.exists(candidate) and os.path.exists(candidate + '/ikfast.h'): - return os.path.realpath(candidate) - try: - return os.path.join(get_pkg_dir(plugin_gen_pkg), 'ikfast_kinematics_plugin/templates') - except InvalidROSPkgException: - raise Exception("Can't find package %s" % plugin_gen_pkg) + for candidate in [os.path.dirname(__file__) + "/../templates"]: + if os.path.exists(candidate) and os.path.exists(candidate + "/ikfast.h"): + return os.path.realpath(candidate) + try: + return os.path.join( + get_pkg_dir(plugin_gen_pkg), "ikfast_kinematics_plugin/templates" + ) + except InvalidROSPkgException: + raise Exception("Can't find package %s" % plugin_gen_pkg) def update_ikfast_package(args): - # Copy the source code generated by IKFast into our src folder - src_path = args.ikfast_plugin_pkg_path + '/src/' - solver_file_path = src_path + args.robot_name + '_' + args.planning_group_name + '_ikfast_solver.cpp' - if not os.path.exists(solver_file_path) or not os.path.samefile(args.ikfast_output_path, solver_file_path): - shutil.copy2(args.ikfast_output_path, solver_file_path) - - if not os.path.exists(solver_file_path): - raise Exception("Failed to copy IKFast source code from '%s' to '%s'\n" - "Manually copy the source file generated by IKFast to this location and re-run" % - (args.ikfast_output_path, solver_file_path)) - # Remember ikfast solver file for update of MoveIt package - args.ikfast_output_path = solver_file_path - - # Get template folder location - template_dir = find_template_dir() - - # namespace for the plugin - setattr(args, 'namespace', args.robot_name + "_" + args.planning_group_name) - replacements = dict(_ROBOT_NAME_= args.robot_name, - _GROUP_NAME_ = args.planning_group_name, - _SEARCH_MODE_ = args.search_mode, - _EEF_LINK_ = args.eef_link_name, - _BASE_LINK_ = args.base_link_name, - _PACKAGE_NAME_ = args.ikfast_plugin_pkg, - _NAMESPACE_ = args.namespace - ) - - # Copy ikfast header file - copy_file(template_dir + '/ikfast.h', args.ikfast_plugin_pkg_path + "/include/ikfast.h", - "ikfast header file") - # Create ikfast plugin template - copy_file(template_dir + '/ikfast' + str(args.template_version) + '_moveit_plugin_template.cpp', - args.ikfast_plugin_pkg_path + "/src/" + args.robot_name + '_' + args.planning_group_name + "_ikfast_moveit_plugin.cpp", - "ikfast plugin file", replacements) - - # Create plugin definition .xml file - ik_library_name = args.namespace + "_moveit_ikfast_plugin" - plugin_def = etree.Element("library", path="lib/lib" + ik_library_name) - setattr(args, 'plugin_name', args.namespace + '/IKFastKinematicsPlugin') - cl = etree.SubElement(plugin_def, "class", name=args.plugin_name, - type=args.namespace + "::IKFastKinematicsPlugin", - base_class_type="kinematics::KinematicsBase") - desc = etree.SubElement(cl, "description") - desc.text = 'IKFast{template} plugin for closed-form kinematics of {robot} {group}' \ - .format(template=args.template_version, robot=args.robot_name, group=args.planning_group_name) - - # Write plugin definition to file - plugin_file_name = ik_library_name + "_description.xml" - plugin_file_path = args.ikfast_plugin_pkg_path + "/" + plugin_file_name - etree.ElementTree(plugin_def).write(plugin_file_path, xml_declaration=True, pretty_print=True, encoding="UTF-8") - print("Created plugin definition at '%s'" % plugin_file_path) - - # Create CMakeLists file - replacements.update(dict(_LIBRARY_NAME_ = ik_library_name)) - copy_file(template_dir + "/CMakeLists.txt", args.ikfast_plugin_pkg_path + '/CMakeLists.txt', - "cmake file", replacements) - - # Add plugin export to package manifest - parser = etree.XMLParser(remove_blank_text=True) - package_file_name = args.ikfast_plugin_pkg_path + "/package.xml" - package_xml = etree.parse(package_file_name, parser).getroot() - - # Make sure at least all required dependencies are in the depends lists - build_deps = ["liblapack-dev", "moveit_core", "pluginlib", "roscpp", "tf2_kdl", "tf2_eigen", "eigen_conversions"] - run_deps = ["liblapack-dev", "moveit_core", "pluginlib", "roscpp", "eigen_conversions"] - - update_deps(build_deps, "build_depend", package_xml) - update_deps(run_deps, "exec_depend", package_xml) - - # Check that plugin definition file is in the export list - new_export = etree.Element("moveit_core", plugin="${prefix}/" + plugin_file_name) - - export_element = package_xml.find("export") - if export_element is None: - export_element = etree.SubElement(package_xml, "export") - - found = False - for el in export_element.findall("moveit_core"): - found = (etree.tostring(new_export) == etree.tostring(el)) - if found: - break - - if not found: - export_element.append(new_export) - - # Always write the package xml file, even if there are no changes, to ensure - # proper encodings are used in the future (UTF-8) - etree.ElementTree(package_xml).write(package_file_name, xml_declaration=True, pretty_print=True, encoding="UTF-8") - print("Wrote package.xml at '%s'" % package_file_name) - - # Create a script for easily updating the plugin in the future in case the plugin needs to be updated - easy_script_file_path = args.ikfast_plugin_pkg_path + "/update_ikfast_plugin.sh" - with open(easy_script_file_path, 'w') as f: - f.write("search_mode=" + args.search_mode + "\n" - + "srdf_filename=" + args.srdf_filename + "\n" - + "robot_name_in_srdf=" + args.robot_name_in_srdf + "\n" - + "moveit_config_pkg=" + args.moveit_config_pkg + "\n" - + "robot_name=" + args.robot_name + "\n" - + "planning_group_name=" + args.planning_group_name + "\n" - + "ikfast_plugin_pkg=" + args.ikfast_plugin_pkg + "\n" - + "base_link_name=" + args.base_link_name + "\n" - + "eef_link_name=" + args.eef_link_name + "\n" - + "ikfast_output_path=" + args.ikfast_output_path + "\n\n" + # Copy the source code generated by IKFast into our src folder + src_path = args.ikfast_plugin_pkg_path + "/src/" + solver_file_path = ( + src_path + + args.robot_name + + "_" + + args.planning_group_name + + "_ikfast_solver.cpp" + ) + if not os.path.exists(solver_file_path) or not os.path.samefile( + args.ikfast_output_path, solver_file_path + ): + shutil.copy2(args.ikfast_output_path, solver_file_path) + + if not os.path.exists(solver_file_path): + raise Exception( + "Failed to copy IKFast source code from '%s' to '%s'\n" + "Manually copy the source file generated by IKFast to this location and re-run" + % (args.ikfast_output_path, solver_file_path) + ) + # Remember ikfast solver file for update of MoveIt package + args.ikfast_output_path = solver_file_path + + # Get template folder location + template_dir = find_template_dir() + + # namespace for the plugin + setattr(args, "namespace", args.robot_name + "_" + args.planning_group_name) + replacements = dict( + _ROBOT_NAME_=args.robot_name, + _GROUP_NAME_=args.planning_group_name, + _SEARCH_MODE_=args.search_mode, + _EEF_LINK_=args.eef_link_name, + _BASE_LINK_=args.base_link_name, + _PACKAGE_NAME_=args.ikfast_plugin_pkg, + _NAMESPACE_=args.namespace, + ) + + # Copy ikfast header file + copy_file( + template_dir + "/ikfast.h", + args.ikfast_plugin_pkg_path + "/include/ikfast.h", + "ikfast header file", + ) + # Create ikfast plugin template + copy_file( + template_dir + + "/ikfast" + + str(args.template_version) + + "_moveit_plugin_template.cpp", + args.ikfast_plugin_pkg_path + + "/src/" + + args.robot_name + + "_" + + args.planning_group_name + + "_ikfast_moveit_plugin.cpp", + "ikfast plugin file", + replacements, + ) + + # Create plugin definition .xml file + ik_library_name = args.namespace + "_moveit_ikfast_plugin" + plugin_def = etree.Element("library", path="lib/lib" + ik_library_name) + setattr(args, "plugin_name", args.namespace + "/IKFastKinematicsPlugin") + cl = etree.SubElement( + plugin_def, + "class", + name=args.plugin_name, + type=args.namespace + "::IKFastKinematicsPlugin", + base_class_type="kinematics::KinematicsBase", + ) + desc = etree.SubElement(cl, "description") + desc.text = ( + "IKFast{template} plugin for closed-form kinematics of {robot} {group}".format( + template=args.template_version, + robot=args.robot_name, + group=args.planning_group_name, + ) + ) + + # Write plugin definition to file + plugin_file_name = ik_library_name + "_description.xml" + plugin_file_path = args.ikfast_plugin_pkg_path + "/" + plugin_file_name + etree.ElementTree(plugin_def).write( + plugin_file_path, xml_declaration=True, pretty_print=True, encoding="UTF-8" + ) + print("Created plugin definition at '%s'" % plugin_file_path) + + # Create CMakeLists file + replacements.update(dict(_LIBRARY_NAME_=ik_library_name)) + copy_file( + template_dir + "/CMakeLists.txt", + args.ikfast_plugin_pkg_path + "/CMakeLists.txt", + "cmake file", + replacements, + ) + + # Add plugin export to package manifest + parser = etree.XMLParser(remove_blank_text=True) + package_file_name = args.ikfast_plugin_pkg_path + "/package.xml" + package_xml = etree.parse(package_file_name, parser).getroot() + + # Make sure at least all required dependencies are in the depends lists + build_deps = [ + "liblapack-dev", + "moveit_core", + "pluginlib", + "roscpp", + "tf2_kdl", + "tf2_eigen", + "eigen_conversions", + ] + run_deps = [ + "liblapack-dev", + "moveit_core", + "pluginlib", + "roscpp", + "eigen_conversions", + ] + + update_deps(build_deps, "build_depend", package_xml) + update_deps(run_deps, "exec_depend", package_xml) + + # Check that plugin definition file is in the export list + new_export = etree.Element("moveit_core", plugin="${prefix}/" + plugin_file_name) + + export_element = package_xml.find("export") + if export_element is None: + export_element = etree.SubElement(package_xml, "export") + + found = False + for el in export_element.findall("moveit_core"): + found = etree.tostring(new_export) == etree.tostring(el) + if found: + break + + if not found: + export_element.append(new_export) + + # Always write the package xml file, even if there are no changes, to ensure + # proper encodings are used in the future (UTF-8) + etree.ElementTree(package_xml).write( + package_file_name, xml_declaration=True, pretty_print=True, encoding="UTF-8" + ) + print("Wrote package.xml at '%s'" % package_file_name) + + # Create a script for easily updating the plugin in the future in case the plugin needs to be updated + easy_script_file_path = args.ikfast_plugin_pkg_path + "/update_ikfast_plugin.sh" + with open(easy_script_file_path, "w") as f: + f.write( + "search_mode=" + + args.search_mode + + "\n" + + "srdf_filename=" + + args.srdf_filename + + "\n" + + "robot_name_in_srdf=" + + args.robot_name_in_srdf + + "\n" + + "moveit_config_pkg=" + + args.moveit_config_pkg + + "\n" + + "robot_name=" + + args.robot_name + + "\n" + + "planning_group_name=" + + args.planning_group_name + + "\n" + + "ikfast_plugin_pkg=" + + args.ikfast_plugin_pkg + + "\n" + + "base_link_name=" + + args.base_link_name + + "\n" + + "eef_link_name=" + + args.eef_link_name + + "\n" + + "ikfast_output_path=" + + args.ikfast_output_path + + "\n\n" + "rosrun moveit_kinematics create_ikfast_moveit_plugin.py\\\n" + " --search_mode=$search_mode\\\n" + " --srdf_filename=$srdf_filename\\\n" @@ -310,87 +419,97 @@ def update_ikfast_package(args): + " $ikfast_plugin_pkg\\\n" + " $base_link_name\\\n" + " $eef_link_name\\\n" - + " $ikfast_output_path\n") + + " $ikfast_output_path\n" + ) - print("Created update plugin script at '%s'" % easy_script_file_path) + print("Created update plugin script at '%s'" % easy_script_file_path) def update_moveit_package(args): - try: - moveit_config_pkg_path = get_pkg_dir(args.moveit_config_pkg) - except InvalidROSPkgException: - raise Exception("Failed to find package: " + args.moveit_config_pkg) - - try: - srdf_file_name = moveit_config_pkg_path + '/config/' + args.srdf_filename - srdf = etree.parse(srdf_file_name).getroot() - except IOError: - raise Exception("Failed to find SRDF file: " + srdf_file_name) - except etree.XMLSyntaxError as err: - raise Exception("Failed to parse xml in file: %s\n%s" % (srdf_file_name, err.msg)) - - if args.robot_name_in_srdf != srdf.get('name'): - raise Exception("Robot name in srdf ('%s') doesn't match expected name ('%s')" % - (srdf.get('name'), args.robot_name_in_srdf)) - - groups = srdf.findall('group') - if len(groups) < 1: - raise Exception("No planning groups are defined in the SRDF") - - planning_group = None - for group in groups: - if group.get('name').lower() == args.planning_group_name.lower(): - planning_group = group - - if planning_group is None: - raise Exception("Planning group '%s' not defined in the SRDF. Available groups: \n%s" % ( - args.planning_group_name, ", ".join([group_name.get('name') for group_name in groups]))) - - # Modify kinematics.yaml file - kin_yaml_file_name = moveit_config_pkg_path + "/config/kinematics.yaml" - with open(kin_yaml_file_name, 'r') as f: - kin_yaml_data = yaml.safe_load(f) - - kin_yaml_data[args.planning_group_name]["kinematics_solver"] = args.plugin_name - with open(kin_yaml_file_name, 'w') as f: - yaml.dump(kin_yaml_data, f, default_flow_style=False) - - print("Modified kinematics.yaml at '%s'" % kin_yaml_file_name) + try: + moveit_config_pkg_path = get_pkg_dir(args.moveit_config_pkg) + except InvalidROSPkgException: + raise Exception("Failed to find package: " + args.moveit_config_pkg) + + try: + srdf_file_name = moveit_config_pkg_path + "/config/" + args.srdf_filename + srdf = etree.parse(srdf_file_name).getroot() + except IOError: + raise Exception("Failed to find SRDF file: " + srdf_file_name) + except etree.XMLSyntaxError as err: + raise Exception( + "Failed to parse xml in file: %s\n%s" % (srdf_file_name, err.msg) + ) + + if args.robot_name_in_srdf != srdf.get("name"): + raise Exception( + "Robot name in srdf ('%s') doesn't match expected name ('%s')" + % (srdf.get("name"), args.robot_name_in_srdf) + ) + + groups = srdf.findall("group") + if len(groups) < 1: + raise Exception("No planning groups are defined in the SRDF") + + planning_group = None + for group in groups: + if group.get("name").lower() == args.planning_group_name.lower(): + planning_group = group + + if planning_group is None: + raise Exception( + "Planning group '%s' not defined in the SRDF. Available groups: \n%s" + % ( + args.planning_group_name, + ", ".join([group_name.get("name") for group_name in groups]), + ) + ) + + # Modify kinematics.yaml file + kin_yaml_file_name = moveit_config_pkg_path + "/config/kinematics.yaml" + with open(kin_yaml_file_name, "r") as f: + kin_yaml_data = yaml.safe_load(f) + + kin_yaml_data[args.planning_group_name]["kinematics_solver"] = args.plugin_name + with open(kin_yaml_file_name, "w") as f: + yaml.dump(kin_yaml_data, f, default_flow_style=False) + + print("Modified kinematics.yaml at '%s'" % kin_yaml_file_name) def copy_file(src_path, dest_path, description, replacements=None): - if not os.path.exists(src_path): - raise Exception("Can't find %s at '%s'" % (description, src_path)) + if not os.path.exists(src_path): + raise Exception("Can't find %s at '%s'" % (description, src_path)) - if replacements is None: - replacements = dict() + if replacements is None: + replacements = dict() - with open(src_path, 'r') as f: - content = f.read() + with open(src_path, "r") as f: + content = f.read() - # replace templates - for key, value in replacements.items(): - content = re.sub(key, value, content) + # replace templates + for key, value in replacements.items(): + content = re.sub(key, value, content) - with open(dest_path, 'w') as f: - f.write(content) - print("Created %s at '%s'" % (description, dest_path)) + with open(dest_path, "w") as f: + f.write(content) + print("Created %s at '%s'" % (description, dest_path)) def main(): - parser = create_parser() - args = parser.parse_args() - - populate_optional(args) - print_args(args) - validate_openrave_version(args) - create_ikfast_package(args) - update_ikfast_package(args) - try: - update_moveit_package(args) - except Exception as e: - print("Failed to update MoveIt package:\n" + str(e)) - - -if __name__ == '__main__': - main() + parser = create_parser() + args = parser.parse_args() + + populate_optional(args) + print_args(args) + validate_openrave_version(args) + create_ikfast_package(args) + update_ikfast_package(args) + try: + update_moveit_package(args) + except Exception as e: + print("Failed to update MoveIt package:\n" + str(e)) + + +if __name__ == "__main__": + main() diff --git a/moveit_kinematics/ikfast_kinematics_plugin/scripts/round_collada_numbers.py b/moveit_kinematics/ikfast_kinematics_plugin/scripts/round_collada_numbers.py index 2e587ae49a..8ee19548f4 100755 --- a/moveit_kinematics/ikfast_kinematics_plugin/scripts/round_collada_numbers.py +++ b/moveit_kinematics/ikfast_kinematics_plugin/scripts/round_collada_numbers.py @@ -1,6 +1,6 @@ #! /usr/bin/env python -''' +""" /********************************************************************* * Software License Agreement (BSD License) * @@ -35,7 +35,7 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *********************************************************************/ -''' +""" # Author: Dave Coleman # Desc: Rounds all the numbers to places @@ -44,80 +44,82 @@ import sys import io -def doRound(values,decimal_places): + +def doRound(values, decimal_places): num_vector = shlex.split(values) new_vector = [] for num in num_vector: - new_num = round(float(num),decimal_places) - print "Old:",num,"New:",new_num + new_num = round(float(num), decimal_places) + print("Old:", num, "New:", new_num) new_vector.append(str(new_num)) new = " ".join(new_vector) - #print 'Original:', values, ' Updated: ', new + # print('Original:', values, ' Updated: ', new) return new + # ----------------------------------------------------------------------------- -if __name__ == '__main__': +if __name__ == "__main__": # Check input arguments try: input_file = sys.argv[1] output_file = sys.argv[2] decimal_places = int(sys.argv[3]) - assert( len(sys.argv) < 5 ) # invalid num-arguments + assert len(sys.argv) < 5 # invalid num-arguments except: - print '\nUsage: round_collada_numbers.py ' - print 'Rounds all the numbers to places\n' + print( + "\nUsage: round_collada_numbers.py " + ) + print("Rounds all the numbers to places\n") sys.exit(-1) - print '\nCollada Number Rounder' - print 'Rounding numbers to', decimal_places, ' decimal places\n' + print("\nCollada Number Rounder") + print("Rounding numbers to", decimal_places, " decimal places\n") # Read string from file - f = open(input_file,'r') - xml = f.read(); + f = open(input_file, "r") + xml = f.read() # Parse XML - #doc = etree.fromstring(xml) - #print(doc.tag) - #doc = etree.parse(io.BytesIO(xml)) - #element=doc.xpath('//ns:asset',namespaces={'ns','http://www.collada.org/2008/03/COLLADASchema'}) - #print element + # doc = etree.fromstring(xml) + # print(doc.tag) + # doc = etree.parse(io.BytesIO(xml)) + # element=doc.xpath('//ns:asset',namespaces={'ns','http://www.collada.org/2008/03/COLLADASchema'}) + # print(element) - namespace = 'http://www.collada.org/2008/03/COLLADASchema' + namespace = "http://www.collada.org/2008/03/COLLADASchema" dom = etree.parse(io.BytesIO(xml)) # find elements of particular name - elements=dom.xpath('//ns:translate',namespaces={'ns':namespace}) + elements = dom.xpath("//ns:translate", namespaces={"ns": namespace}) for i in range(len(elements)): - elements[i].text = doRound(elements[i].text,decimal_places) + elements[i].text = doRound(elements[i].text, decimal_places) # find elements of particular name - elements=dom.xpath('//ns:rotate',namespaces={'ns':namespace}) + elements = dom.xpath("//ns:rotate", namespaces={"ns": namespace}) for i in range(len(elements)): - elements[i].text = doRound(elements[i].text,decimal_places) + elements[i].text = doRound(elements[i].text, decimal_places) # find elements of particular name - elements=dom.xpath('//ns:min',namespaces={'ns':namespace}) + elements = dom.xpath("//ns:min", namespaces={"ns": namespace}) for i in range(len(elements)): - elements[i].text = doRound(elements[i].text,decimal_places) + elements[i].text = doRound(elements[i].text, decimal_places) # find elements of particular name - elements=dom.xpath('//ns:max',namespaces={'ns':namespace}) + elements = dom.xpath("//ns:max", namespaces={"ns": namespace}) for i in range(len(elements)): - elements[i].text = doRound(elements[i].text,decimal_places) + elements[i].text = doRound(elements[i].text, decimal_places) # find elements of particular name - elements=dom.xpath('//ns:float',namespaces={'ns':namespace}) + elements = dom.xpath("//ns:float", namespaces={"ns": namespace}) for i in range(len(elements)): - elements[i].text = doRound(elements[i].text,decimal_places) + elements[i].text = doRound(elements[i].text, decimal_places) # save changes - f = open(output_file,'w') + f = open(output_file, "w") f.write(etree.tostring(dom)) f.close() - - diff --git a/moveit_kinematics/kdl_kinematics_plugin/CMakeLists.txt b/moveit_kinematics/kdl_kinematics_plugin/CMakeLists.txt index cd3ffc0891..5f915e2e3e 100644 --- a/moveit_kinematics/kdl_kinematics_plugin/CMakeLists.txt +++ b/moveit_kinematics/kdl_kinematics_plugin/CMakeLists.txt @@ -7,8 +7,8 @@ set_target_properties(${MOVEIT_LIB_NAME} PROPERTIES VERSION "${${PROJECT_NAME}_V target_link_libraries(${MOVEIT_LIB_NAME} ${catkin_LIBRARIES}) -install(TARGETS ${MOVEIT_LIB_NAME} - LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +install(TARGETS ${MOVEIT_LIB_NAME} + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} - RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) + RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) install(DIRECTORY include/ DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}) diff --git a/moveit_kinematics/lma_kinematics_plugin/CMakeLists.txt b/moveit_kinematics/lma_kinematics_plugin/CMakeLists.txt index 1dadddcd56..5867598904 100644 --- a/moveit_kinematics/lma_kinematics_plugin/CMakeLists.txt +++ b/moveit_kinematics/lma_kinematics_plugin/CMakeLists.txt @@ -5,7 +5,7 @@ set_target_properties(${MOVEIT_LIB_NAME} PROPERTIES VERSION "${${PROJECT_NAME}_V target_link_libraries(${MOVEIT_LIB_NAME} ${catkin_LIBRARIES}) -install(TARGETS ${MOVEIT_LIB_NAME} +install(TARGETS ${MOVEIT_LIB_NAME} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) diff --git a/moveit_kinematics/srv_kinematics_plugin/CMakeLists.txt b/moveit_kinematics/srv_kinematics_plugin/CMakeLists.txt index 2cf14dd877..7cf4de66e9 100644 --- a/moveit_kinematics/srv_kinematics_plugin/CMakeLists.txt +++ b/moveit_kinematics/srv_kinematics_plugin/CMakeLists.txt @@ -5,7 +5,7 @@ set_target_properties(${MOVEIT_LIB_NAME} PROPERTIES VERSION "${${PROJECT_NAME}_V target_link_libraries(${MOVEIT_LIB_NAME} ${catkin_LIBRARIES}) -install(TARGETS ${MOVEIT_LIB_NAME} +install(TARGETS ${MOVEIT_LIB_NAME} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) diff --git a/moveit_planners/chomp/chomp_interface/test/chomp_planning.yaml b/moveit_planners/chomp/chomp_interface/test/chomp_planning.yaml index bc9af083fa..e4e92e8ed0 100644 --- a/moveit_planners/chomp/chomp_interface/test/chomp_planning.yaml +++ b/moveit_planners/chomp/chomp_interface/test/chomp_planning.yaml @@ -23,4 +23,3 @@ collision_clearence: 0.2 collision_threshold: 0.07 random_jump_amount: 1.0 use_stochastic_descent: true - diff --git a/moveit_planners/chomp/chomp_interface/test/joint_limits.yaml b/moveit_planners/chomp/chomp_interface/test/joint_limits.yaml index 071846af20..fb7bab1217 100644 --- a/moveit_planners/chomp/chomp_interface/test/joint_limits.yaml +++ b/moveit_planners/chomp/chomp_interface/test/joint_limits.yaml @@ -11,4 +11,4 @@ joint_limits: has_velocity_limits: true max_velocity: 6.28318530718 has_acceleration_limits: false - max_acceleration: 0 \ No newline at end of file + max_acceleration: 0 diff --git a/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt b/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt index 7c3f86c8a1..1fd8466ab2 100644 --- a/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt +++ b/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt @@ -339,7 +339,7 @@ if(CATKIN_ENABLE_TESTING) test/unittest_velocity_profile_atrap.cpp src/velocity_profile_atrap.cpp ) - target_link_libraries(unittest_velocity_profile_atrap + target_link_libraries(unittest_velocity_profile_atrap ${catkin_LIBRARIES} ) @@ -502,7 +502,7 @@ if(CATKIN_ENABLE_TESTING) catkin_add_gmock(unittest_get_solver_tip_frame test/unittest_get_solver_tip_frame.cpp ) - target_link_libraries(unittest_get_solver_tip_frame + target_link_libraries(unittest_get_solver_tip_frame ${catkin_LIBRARIES} ) diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/.gitignore b/moveit_planners/pilz_industrial_motion_planner/doc/.gitignore index 2edfaf4621..85523e9d4a 100644 --- a/moveit_planners/pilz_industrial_motion_planner/doc/.gitignore +++ b/moveit_planners/pilz_industrial_motion_planner/doc/.gitignore @@ -4,9 +4,9 @@ *.dvi *.log *.ps -*.tps -*.fdb_latexmk -*.fls +*.tps +*.fdb_latexmk +*.fls *.out *.synctex.gz -*.pdf \ No newline at end of file +*.pdf diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/MotionBlendAlgorithmDescription.tex b/moveit_planners/pilz_industrial_motion_planner/doc/MotionBlendAlgorithmDescription.tex index a040465426..6238ec8747 100644 --- a/moveit_planners/pilz_industrial_motion_planner/doc/MotionBlendAlgorithmDescription.tex +++ b/moveit_planners/pilz_industrial_motion_planner/doc/MotionBlendAlgorithmDescription.tex @@ -88,21 +88,21 @@ \section{Blending the orientation} \caption{Motion blend case 1: $T_s = 6s$, blending starts at 3.5s, ends at 8s. The resulted blending trajectory comes to a stop in the middle.}% \label{blend_case_1}% \end{subfigure} - + \begin{subfigure}[ht]{0.8\textwidth}% \centering \includegraphics[width=0.8\columnwidth]{figure/blend_case_2.eps}% \caption{Motion blend case 2: $T_s = 3.5s$, blending starts at 3.5s, ends at 5.5s. The resulted blending trajectory smoothly transits from first trajectory to the second trajectory. The velocity profile has no jumps.}% \label{blend_case_2}% \end{subfigure} - + \begin{subfigure}[ht]{0.8\textwidth}% \centering \includegraphics[width=0.8\columnwidth]{figure/blend_case_3.eps}% \caption{Motion blend case 3: $T_s = 4.5s$, blending starts at 3.5s, ends at 6.5s. The resulted blending trajectory smoothly transits from first trajectory to the second trajectory. The velocity profile has no jumps.}% \label{blend_case_3}% \end{subfigure} - + \end{figure} diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/launch/test_context.launch b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/launch/test_context.launch index 4c43af1420..49ac94b65d 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/launch/test_context.launch +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/prbt/launch/test_context.launch @@ -39,5 +39,5 @@ - + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/testpoints.py b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/testpoints.py index e0056728f3..d88f58dc42 100755 --- a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/testpoints.py +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/testpoints.py @@ -40,27 +40,27 @@ __REQUIRED_API_VERSION__ = "1" robot_configs = {} -robot_configs['prbt'] = { - 'initJointPose': [0.0, 0.0, math.radians(-25), 0.0, -1.57, 0], - 'L': 0.2, - 'M': 0.1, - 'planning_group': 'manipulator', - 'target_link': 'prbt_tcp', - 'reference_frame': 'prbt_base', - 'default_or': from_euler(0, math.radians(180), math.radians(90)), - 'P1_position': Point(0.3, 0.0, 0.5), - 'P1_orientation': from_euler(0, math.radians(180), math.radians(135)) +robot_configs["prbt"] = { + "initJointPose": [0.0, 0.0, math.radians(-25), 0.0, -1.57, 0], + "L": 0.2, + "M": 0.1, + "planning_group": "manipulator", + "target_link": "prbt_tcp", + "reference_frame": "prbt_base", + "default_or": from_euler(0, math.radians(180), math.radians(90)), + "P1_position": Point(0.3, 0.0, 0.5), + "P1_orientation": from_euler(0, math.radians(180), math.radians(135)), } -robot_configs['panda'] = { - 'initJointPose': [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785], - 'L': 0.2, - 'M': 0.1, - 'planning_group': 'panda_arm', - 'target_link': 'panda_link8', - 'reference_frame': 'panda_link0', - 'default_or': Quaternion(0.924, -0.382, 0.000, 0.000), - 'P1_position': Point(0.2, 0.0, 0.8) +robot_configs["panda"] = { + "initJointPose": [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785], + "L": 0.2, + "M": 0.1, + "planning_group": "panda_arm", + "target_link": "panda_link8", + "reference_frame": "panda_link0", + "default_or": Quaternion(0.924, -0.382, 0.000, 0.000), + "P1_position": Point(0.2, 0.0, 0.8), } @@ -69,41 +69,122 @@ def start_program(robot_name): test_sequence(**robot_configs[robot_name]) -def test_sequence(initJointPose, L, M, planning_group, target_link, reference_frame, default_or, P1_position, P1_orientation): + +def test_sequence( + initJointPose, + L, + M, + planning_group, + target_link, + reference_frame, + default_or, + P1_position, + P1_orientation, +): r = Robot(__REQUIRED_API_VERSION__) r.move(Ptp(goal=initJointPose, planning_group=planning_group)) P1 = Pose(position=P1_position, orientation=P1_orientation) - - P2 = Pose(position=Point(P1.position.x+L, P1.position.y+L, P1.position.z-M), orientation=default_or) - P3 = Pose(position=Point(P1.position.x, P1.position.y+2*L, P1.position.z-2*M), orientation=default_or) - P4 = Pose(position=Point(P1.position.x, P1.position.y+L, P1.position.z-M), orientation=default_or) - - ptp1 = Ptp(goal=P1, acc_scale=0.3, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) - ptp2 = Ptp(goal=P2, acc_scale=0.3, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) - ptp3 = Ptp(goal=P3, acc_scale=0.3, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) - ptp4 = Ptp(goal=P4, acc_scale=0.3, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) - lin1 = Lin(goal=P1, acc_scale=0.1, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) - lin2 = Lin(goal=P2, acc_scale=0.1, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) - lin3 = Lin(goal=P3, acc_scale=0.1, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) - lin4 = Lin(goal=P4, acc_scale=0.1, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) - - r.move(ptp1) #PTP_12 test - r.move(ptp2) #PTP_23 - r.move(ptp3) #PTP_34 - r.move(ptp4) #PTP_41 + P2 = Pose( + position=Point(P1.position.x + L, P1.position.y + L, P1.position.z - M), + orientation=default_or, + ) + P3 = Pose( + position=Point(P1.position.x, P1.position.y + 2 * L, P1.position.z - 2 * M), + orientation=default_or, + ) + P4 = Pose( + position=Point(P1.position.x, P1.position.y + L, P1.position.z - M), + orientation=default_or, + ) + + ptp1 = Ptp( + goal=P1, + acc_scale=0.3, + planning_group=planning_group, + target_link=target_link, + reference_frame=reference_frame, + ) + ptp2 = Ptp( + goal=P2, + acc_scale=0.3, + planning_group=planning_group, + target_link=target_link, + reference_frame=reference_frame, + ) + ptp3 = Ptp( + goal=P3, + acc_scale=0.3, + planning_group=planning_group, + target_link=target_link, + reference_frame=reference_frame, + ) + ptp4 = Ptp( + goal=P4, + acc_scale=0.3, + planning_group=planning_group, + target_link=target_link, + reference_frame=reference_frame, + ) + lin1 = Lin( + goal=P1, + acc_scale=0.1, + planning_group=planning_group, + target_link=target_link, + reference_frame=reference_frame, + ) + lin2 = Lin( + goal=P2, + acc_scale=0.1, + planning_group=planning_group, + target_link=target_link, + reference_frame=reference_frame, + ) + lin3 = Lin( + goal=P3, + acc_scale=0.1, + planning_group=planning_group, + target_link=target_link, + reference_frame=reference_frame, + ) + lin4 = Lin( + goal=P4, + acc_scale=0.1, + planning_group=planning_group, + target_link=target_link, + reference_frame=reference_frame, + ) + + r.move(ptp1) # PTP_12 test + r.move(ptp2) # PTP_23 + r.move(ptp3) # PTP_34 + r.move(ptp4) # PTP_41 r.move(ptp1) - r.move(lin1) #LIN_12 - r.move(lin2) #LIN_23 - r.move(lin3) #LIN_34 - r.move(lin4) #LIN_41 + r.move(lin1) # LIN_12 + r.move(lin2) # LIN_23 + r.move(lin3) # LIN_34 + r.move(lin4) # LIN_41 r.move(lin1) - circ3_interim_2 = Circ(goal=P3, interim=P2.position, acc_scale=0.2, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) - circ1_center_2 = Circ(goal=P1, center=P2.position, acc_scale=0.2, planning_group=planning_group, target_link=target_link, reference_frame=reference_frame) + circ3_interim_2 = Circ( + goal=P3, + interim=P2.position, + acc_scale=0.2, + planning_group=planning_group, + target_link=target_link, + reference_frame=reference_frame, + ) + circ1_center_2 = Circ( + goal=P1, + center=P2.position, + acc_scale=0.2, + planning_group=planning_group, + target_link=target_link, + reference_frame=reference_frame, + ) for radius in [0, 0.1]: r.move(Ptp(goal=initJointPose, planning_group=planning_group)) @@ -119,23 +200,29 @@ def test_sequence(initJointPose, L, M, planning_group, target_link, reference_fr r.move(seq) + if __name__ == "__main__": # Init a ros node - rospy.init_node('robot_program_node') + rospy.init_node("robot_program_node") import sys robots = list(robot_configs.keys()) - if(len(sys.argv) < 2): - print("Please specify the robot you want to use." + ', '.join('"{0}"'.format(r) for r in robots)) + if len(sys.argv) < 2: + print( + "Please specify the robot you want to use." + + ", ".join('"{0}"'.format(r) for r in robots) + ) sys.exit() - - if(sys.argv[1] not in robots): - print("Robot " + sys.argv[1] + " not available. Use one of " + ', '.join('"{0}"'.format(r) for r in robots)) + if sys.argv[1] not in robots: + print( + "Robot " + + sys.argv[1] + + " not available. Use one of " + + ", ".join('"{0}"'.format(r) for r in robots) + ) sys.exit() - start_program(sys.argv[1]) - diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_circ_auxiliary.uxf b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_circ_auxiliary.uxf index a1f7b6b415..236af5e988 100644 --- a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_circ_auxiliary.uxf +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_circ_auxiliary.uxf @@ -32,7 +32,7 @@ 470 80 - template=ConfigType> + template=ConfigType> CircAuxiliary {abstract} -- @@ -47,7 +47,7 @@ CircAuxiliary 230 50 - template=ConfigType, Builder> + template=ConfigType, Builder> Center @@ -59,7 +59,7 @@ Center 220 50 - template=ConfigType, Builder> + template=ConfigType, Builder> Interim @@ -94,7 +94,7 @@ Interim 130 lt=<<. -<<bind>> +<<bind>> <ConfigType->CartesianConfiguration> <Builder->CartesianPathConstraintsBuilder> 10.0;10.0;10.0;110.0 @@ -125,7 +125,7 @@ Interim -<<bind>> +<<bind>> <ConfigType->CartesianConfiguration> <Builder->CartesianPathConstraintsBuilder> 10.0;10.0;10.0;190.0 diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_commands.uxf b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_commands.uxf index 1c57939fb2..ab33fcc08b 100644 --- a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_commands.uxf +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_class_commands.uxf @@ -8,7 +8,7 @@ 560 150 - template=StartType, GoalType + template=StartType, GoalType BaseCommand {abstract} -- @@ -28,7 +28,7 @@ BaseCommand 230 70 - template=StartType, GoalType + template=StartType, GoalType Ptp @@ -62,7 +62,7 @@ Ptp 230 70 - template=StartType, GoalType + template=StartType, GoalType Lin @@ -74,7 +74,7 @@ Lin 300 70 - template=StartType, AuxiliaryType, GoalType + template=StartType, AuxiliaryType, GoalType Circ diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_seq_testdataloader_usage.uxf b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_seq_testdataloader_usage.uxf index 9707b26ea5..b47471023f 100644 --- a/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_seq_testdataloader_usage.uxf +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/doc/diagrams/diag_seq_testdataloader_usage.uxf @@ -150,7 +150,7 @@ transparency=0 48 lt=<- -toRequest() : +toRequest() : moveit_msgs::MotionPlanRequest 220.0;20.0;10.0;20.0 diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/checks.h b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/checks.h index e9519f2071..1921c8ba00 100644 --- a/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/checks.h +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/include/pilz_industrial_motion_planner_testutils/checks.h @@ -59,4 +59,4 @@ ::testing::AssertionResult isAtExpectedPosition(const robot_state::RobotState& e } } // namespace pilz_industrial_motion_planner_testutils -#endif // CENTERAUXILIARY_H \ No newline at end of file +#endif // CENTERAUXILIARY_H diff --git a/moveit_planners/sbpl/core/sbpl_interface/Makefile b/moveit_planners/sbpl/core/sbpl_interface/Makefile index b75b928f20..bbd3fc6049 100644 --- a/moveit_planners/sbpl/core/sbpl_interface/Makefile +++ b/moveit_planners/sbpl/core/sbpl_interface/Makefile @@ -1 +1 @@ -include $(shell rospack find mk)/cmake.mk \ No newline at end of file +include $(shell rospack find mk)/cmake.mk diff --git a/moveit_planners/sbpl/core/sbpl_interface/manifest.xml b/moveit_planners/sbpl/core/sbpl_interface/manifest.xml index cf6ff29fac..bd05d28a35 100644 --- a/moveit_planners/sbpl/core/sbpl_interface/manifest.xml +++ b/moveit_planners/sbpl/core/sbpl_interface/manifest.xml @@ -20,5 +20,3 @@ - - diff --git a/moveit_planners/sbpl/ros/sbpl_interface_ros/Makefile b/moveit_planners/sbpl/ros/sbpl_interface_ros/Makefile index b75b928f20..bbd3fc6049 100644 --- a/moveit_planners/sbpl/ros/sbpl_interface_ros/Makefile +++ b/moveit_planners/sbpl/ros/sbpl_interface_ros/Makefile @@ -1 +1 @@ -include $(shell rospack find mk)/cmake.mk \ No newline at end of file +include $(shell rospack find mk)/cmake.mk diff --git a/moveit_planners/sbpl/ros/sbpl_interface_ros/manifest.xml b/moveit_planners/sbpl/ros/sbpl_interface_ros/manifest.xml index 0593c47a3f..ebffd4ef22 100644 --- a/moveit_planners/sbpl/ros/sbpl_interface_ros/manifest.xml +++ b/moveit_planners/sbpl/ros/sbpl_interface_ros/manifest.xml @@ -19,5 +19,3 @@ - - diff --git a/moveit_plugins/moveit_fake_controller_manager/CMakeLists.txt b/moveit_plugins/moveit_fake_controller_manager/CMakeLists.txt index 2d4c43f82b..05df4dca3a 100644 --- a/moveit_plugins/moveit_fake_controller_manager/CMakeLists.txt +++ b/moveit_plugins/moveit_fake_controller_manager/CMakeLists.txt @@ -36,10 +36,10 @@ add_library(${PROJECT_NAME} set_target_properties(${PROJECT_NAME} PROPERTIES VERSION "${${PROJECT_NAME}_VERSION}") target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES} ${Boost_LIBRARIES}) -install(TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +install(TARGETS ${PROJECT_NAME} + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} - RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) + RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) install(FILES moveit_fake_controller_manager_plugin_description.xml DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} diff --git a/moveit_ros/benchmarks/examples/demo_obstacles.yaml b/moveit_ros/benchmarks/examples/demo_obstacles.yaml index 70c7604e03..9ac65e96d3 100644 --- a/moveit_ros/benchmarks/examples/demo_obstacles.yaml +++ b/moveit_ros/benchmarks/examples/demo_obstacles.yaml @@ -30,4 +30,3 @@ benchmark_config: - plugin: stomp_moveit/StompPlannerManager planners: - STOMP - diff --git a/moveit_ros/benchmarks/examples/demo_panda_all_planners.launch b/moveit_ros/benchmarks/examples/demo_panda_all_planners.launch index 5ffdc5b3f1..281e80a370 100644 --- a/moveit_ros/benchmarks/examples/demo_panda_all_planners.launch +++ b/moveit_ros/benchmarks/examples/demo_panda_all_planners.launch @@ -28,4 +28,3 @@ - diff --git a/moveit_ros/benchmarks/examples/demo_panda_all_planners.yaml b/moveit_ros/benchmarks/examples/demo_panda_all_planners.yaml index 00ac5066e6..eac2c21acb 100644 --- a/moveit_ros/benchmarks/examples/demo_panda_all_planners.yaml +++ b/moveit_ros/benchmarks/examples/demo_panda_all_planners.yaml @@ -30,4 +30,3 @@ benchmark_config: - plugin: stomp_moveit/StompPlannerManager planners: - STOMP - diff --git a/moveit_ros/benchmarks/scripts/moveit_benchmark_statistics.py b/moveit_ros/benchmarks/scripts/moveit_benchmark_statistics.py index 50896a037d..6723858e17 100755 --- a/moveit_ros/benchmarks/scripts/moveit_benchmark_statistics.py +++ b/moveit_ros/benchmarks/scripts/moveit_benchmark_statistics.py @@ -41,7 +41,8 @@ import sqlite3 import datetime import matplotlib -matplotlib.use('pdf') + +matplotlib.use("pdf") from matplotlib import __version__ as matplotlibversion from matplotlib.backends.backend_pdf import PdfPages import matplotlib.pyplot as plt @@ -52,7 +53,7 @@ # Given a text line, split it into tokens (by space) and return the token # at the desired index. Additionally, test that some expected tokens exist. # Return None if they do not. -def readLogValue(filevar, desired_token_index, expected_tokens) : +def readLogValue(filevar, desired_token_index, expected_tokens): start_pos = filevar.tell() tokens = filevar.readline().split() for token_index in expected_tokens: @@ -62,40 +63,45 @@ def readLogValue(filevar, desired_token_index, expected_tokens) : return None return tokens[desired_token_index] -def readOptionalLogValue(filevar, desired_token_index, expected_tokens = {}) : + +def readOptionalLogValue(filevar, desired_token_index, expected_tokens={}): return readLogValue(filevar, desired_token_index, expected_tokens) -def readRequiredLogValue(name, filevar, desired_token_index, expected_tokens = {}) : + +def readRequiredLogValue(name, filevar, desired_token_index, expected_tokens={}): result = readLogValue(filevar, desired_token_index, expected_tokens) if result == None: raise Exception("Unable to read " + name) return result + def ensurePrefix(line, prefix): if not line.startswith(prefix): raise Exception("Expected prefix " + prefix + " was not found") return line + def readOptionalMultilineValue(filevar): start_pos = filevar.tell() line = filevar.readline() if not line.startswith("<<<|"): filevar.seek(start_pos) return None - value = '' + value = "" line = filevar.readline() - while not line.startswith('|>>>'): + while not line.startswith("|>>>"): value = value + line line = filevar.readline() if line == None: raise Exception("Expected token |>>> missing") return value + def readRequiredMultilineValue(filevar): ensurePrefix(filevar.readline(), "<<<|") - value = '' + value = "" line = filevar.readline() - while not line.startswith('|>>>'): + while not line.startswith("|>>>"): value = value + line line = filevar.readline() if line == None: @@ -108,10 +114,11 @@ def readBenchmarkLog(dbname, filenames): conn = sqlite3.connect(dbname) c = conn.cursor() - c.execute('PRAGMA FOREIGN_KEYS = ON') + c.execute("PRAGMA FOREIGN_KEYS = ON") # create all tables if they don't already exist - c.executescript("""CREATE TABLE IF NOT EXISTS experiments + c.executescript( + """CREATE TABLE IF NOT EXISTS experiments (id INTEGER PRIMARY KEY ON CONFLICT REPLACE AUTOINCREMENT, name VARCHAR(512), totaltime REAL, timelimit REAL, memorylimit REAL, runcount INTEGER, version VARCHAR(128), hostname VARCHAR(1024), cpuinfo TEXT, @@ -128,117 +135,187 @@ def readBenchmarkLog(dbname, filenames): FOREIGN KEY (plannerid) REFERENCES plannerConfigs(id) ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS progress (runid INTEGER, time REAL, PRIMARY KEY (runid, time), - FOREIGN KEY (runid) REFERENCES runs(id) ON DELETE CASCADE)""") + FOREIGN KEY (runid) REFERENCES runs(id) ON DELETE CASCADE)""" + ) # add placeholder entry for all_experiments allExperimentsName = "all_experiments" allExperimentsValues = { - "totaltime": 0.0, "timelimit": 0.0, "memorylimit": 0.0, "runcount": 0, "version": "0.0.0", - "hostname": "", "cpuinfo": "", "date": 0, "seed": 0, "setup": "" + "totaltime": 0.0, + "timelimit": 0.0, + "memorylimit": 0.0, + "runcount": 0, + "version": "0.0.0", + "hostname": "", + "cpuinfo": "", + "date": 0, + "seed": 0, + "setup": "", } addAllExperiments = len(filenames) > 0 if addAllExperiments: - c.execute('INSERT INTO experiments VALUES (?,?,?,?,?,?,?,?,?,?,?,?)', - (None, allExperimentsName) + tuple(allExperimentsValues.values())) + c.execute( + "INSERT INTO experiments VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", + (None, allExperimentsName) + tuple(allExperimentsValues.values()), + ) allExperimentsId = c.lastrowid for i, filename in enumerate(filenames): - print('Processing ' + filename) - logfile = open(filename,'r') + print("Processing " + filename) + logfile = open(filename, "r") start_pos = logfile.tell() - libname = readOptionalLogValue(logfile, 0, {1 : "version"}) + libname = readOptionalLogValue(logfile, 0, {1: "version"}) if libname == None: libname = "OMPL" logfile.seek(start_pos) - version = readOptionalLogValue(logfile, -1, {1 : "version"}) + version = readOptionalLogValue(logfile, -1, {1: "version"}) if version == None: # set the version number to make Planner Arena happy version = "0.0.0" - version = ' '.join([libname, version]) - expname = readRequiredLogValue("experiment name", logfile, -1, {0 : "Experiment"}) - hostname = readRequiredLogValue("hostname", logfile, -1, {0 : "Running"}) - date = ' '.join(ensurePrefix(logfile.readline(), "Starting").split()[2:]) + version = " ".join([libname, version]) + expname = readRequiredLogValue( + "experiment name", logfile, -1, {0: "Experiment"} + ) + hostname = readRequiredLogValue("hostname", logfile, -1, {0: "Running"}) + date = " ".join(ensurePrefix(logfile.readline(), "Starting").split()[2:]) expsetup = readRequiredMultilineValue(logfile) cpuinfo = readOptionalMultilineValue(logfile) - rseed = int(readRequiredLogValue("random seed", logfile, 0, {-2 : "random", -1 : "seed"})) - timelimit = float(readRequiredLogValue("time limit", logfile, 0, {-3 : "seconds", -2 : "per", -1 : "run"})) - memorylimit = float(readRequiredLogValue("memory limit", logfile, 0, {-3 : "MB", -2 : "per", -1 : "run"})) - nrrunsOrNone = readOptionalLogValue(logfile, 0, {-3 : "runs", -2 : "per", -1 : "planner"}) + rseed = int( + readRequiredLogValue("random seed", logfile, 0, {-2: "random", -1: "seed"}) + ) + timelimit = float( + readRequiredLogValue( + "time limit", logfile, 0, {-3: "seconds", -2: "per", -1: "run"} + ) + ) + memorylimit = float( + readRequiredLogValue( + "memory limit", logfile, 0, {-3: "MB", -2: "per", -1: "run"} + ) + ) + nrrunsOrNone = readOptionalLogValue( + logfile, 0, {-3: "runs", -2: "per", -1: "planner"} + ) nrruns = -1 if nrrunsOrNone != None: nrruns = int(nrrunsOrNone) - allExperimentsValues['runcount'] += nrruns - totaltime = float(readRequiredLogValue("total time", logfile, 0, {-3 : "collect", -2 : "the", -1 : "data"})) + allExperimentsValues["runcount"] += nrruns + totaltime = float( + readRequiredLogValue( + "total time", logfile, 0, {-3: "collect", -2: "the", -1: "data"} + ) + ) # fill in fields of all_experiments - allExperimentsValues['totaltime'] += totaltime - allExperimentsValues['memorylimit'] = max(allExperimentsValues['memorylimit'], totaltime) - allExperimentsValues['timelimit'] = max(allExperimentsValues['timelimit'], totaltime) + allExperimentsValues["totaltime"] += totaltime + allExperimentsValues["memorylimit"] = max( + allExperimentsValues["memorylimit"], totaltime + ) + allExperimentsValues["timelimit"] = max( + allExperimentsValues["timelimit"], totaltime + ) # copy the fields of the first file to all_experiments so that they are not empty - if (i==0): - allExperimentsValues['version'] = version - allExperimentsValues['date'] = date - allExperimentsValues['setup'] = expsetup - allExperimentsValues['hostname'] = hostname - allExperimentsValues['cpuinfo'] = cpuinfo + if i == 0: + allExperimentsValues["version"] = version + allExperimentsValues["date"] = date + allExperimentsValues["setup"] = expsetup + allExperimentsValues["hostname"] = hostname + allExperimentsValues["cpuinfo"] = cpuinfo numEnums = 0 - numEnumsOrNone = readOptionalLogValue(logfile, 0, {-2 : "enum"}) + numEnumsOrNone = readOptionalLogValue(logfile, 0, {-2: "enum"}) if numEnumsOrNone != None: numEnums = int(numEnumsOrNone) for i in range(numEnums): - enum = logfile.readline()[:-1].split('|') + enum = logfile.readline()[:-1].split("|") c.execute('SELECT * FROM enums WHERE name IS "%s"' % enum[0]) if c.fetchone() == None: - for j in range(len(enum)-1): - c.execute('INSERT INTO enums VALUES (?,?,?)', - (enum[0],j,enum[j+1])) - c.execute('INSERT INTO experiments VALUES (?,?,?,?,?,?,?,?,?,?,?,?)', - (None, expname, totaltime, timelimit, memorylimit, nrruns, - version, hostname, cpuinfo, date, rseed, expsetup) ) + for j in range(len(enum) - 1): + c.execute( + "INSERT INTO enums VALUES (?,?,?)", (enum[0], j, enum[j + 1]) + ) + c.execute( + "INSERT INTO experiments VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", + ( + None, + expname, + totaltime, + timelimit, + memorylimit, + nrruns, + version, + hostname, + cpuinfo, + date, + rseed, + expsetup, + ), + ) experimentId = c.lastrowid - numPlanners = int(readRequiredLogValue("planner count", logfile, 0, {-1 : "planners"})) + numPlanners = int( + readRequiredLogValue("planner count", logfile, 0, {-1: "planners"}) + ) for i in range(numPlanners): plannerName = logfile.readline()[:-1] - print('Parsing data for ' + plannerName) + print("Parsing data for " + plannerName) # read common data for planner numCommon = int(logfile.readline().split()[0]) - settings = '' + settings = "" for j in range(numCommon): - settings = settings + logfile.readline() + ';' + settings = settings + logfile.readline() + ";" # find planner id - c.execute('SELECT id FROM plannerConfigs WHERE (name=? AND settings=?)', - (plannerName, settings,)) + c.execute( + "SELECT id FROM plannerConfigs WHERE (name=? AND settings=?)", + ( + plannerName, + settings, + ), + ) p = c.fetchone() - if p==None: - c.execute('INSERT INTO plannerConfigs VALUES (?,?,?)', - (None, plannerName, settings,)) + if p == None: + c.execute( + "INSERT INTO plannerConfigs VALUES (?,?,?)", + ( + None, + plannerName, + settings, + ), + ) plannerId = c.lastrowid else: plannerId = p[0] # get current column names - c.execute('PRAGMA table_info(runs)') + c.execute("PRAGMA table_info(runs)") columnNames = [col[1] for col in c.fetchall()] # read properties and add columns as necessary numProperties = int(logfile.readline().split()[0]) - propertyNames = ['experimentid', 'plannerid'] + propertyNames = ["experimentid", "plannerid"] for j in range(numProperties): field = logfile.readline().split() propertyType = field[-1] - propertyName = '_'.join(field[:-1]) + propertyName = "_".join(field[:-1]) if propertyName not in columnNames: - c.execute('ALTER TABLE runs ADD %s %s' % (propertyName, propertyType)) + c.execute( + "ALTER TABLE runs ADD %s %s" % (propertyName, propertyType) + ) propertyNames.append(propertyName) # read measurements - insertFmtStr = 'INSERT INTO runs (' + ','.join(propertyNames) + \ - ') VALUES (' + ','.join('?'*len(propertyNames)) + ')' + insertFmtStr = ( + "INSERT INTO runs (" + + ",".join(propertyNames) + + ") VALUES (" + + ",".join("?" * len(propertyNames)) + + ")" + ) numRuns = int(logfile.readline().split()[0]) runIds = [] for j in range(numRuns): - runValues = [None if len(x) == 0 or x == 'nan' or x == 'inf' else x - for x in logfile.readline().split('; ')[:-1]] + runValues = [ + None if len(x) == 0 or x == "nan" or x == "inf" else x + for x in logfile.readline().split("; ")[:-1] + ] values = tuple([experimentId, plannerId] + runValues) c.execute(insertFmtStr, values) # extract primary key of each run row so we can reference them @@ -252,37 +329,49 @@ def readBenchmarkLog(dbname, filenames): nextLine = logfile.readline().strip() # read planner progress data if it's supplied - if nextLine != '.': + if nextLine != ".": # get current column names - c.execute('PRAGMA table_info(progress)') + c.execute("PRAGMA table_info(progress)") columnNames = [col[1] for col in c.fetchall()] # read progress properties and add columns as necesary numProgressProperties = int(nextLine.split()[0]) - progressPropertyNames = ['runid'] + progressPropertyNames = ["runid"] for i in range(numProgressProperties): field = logfile.readline().split() progressPropertyType = field[-1] progressPropertyName = "_".join(field[:-1]) if progressPropertyName not in columnNames: - c.execute('ALTER TABLE progress ADD %s %s' % - (progressPropertyName, progressPropertyType)) + c.execute( + "ALTER TABLE progress ADD %s %s" + % (progressPropertyName, progressPropertyType) + ) progressPropertyNames.append(progressPropertyName) # read progress measurements - insertFmtStr = 'INSERT INTO progress (' + \ - ','.join(progressPropertyNames) + ') VALUES (' + \ - ','.join('?'*len(progressPropertyNames)) + ')' + insertFmtStr = ( + "INSERT INTO progress (" + + ",".join(progressPropertyNames) + + ") VALUES (" + + ",".join("?" * len(progressPropertyNames)) + + ")" + ) numRuns = int(logfile.readline().split()[0]) for j in range(numRuns): - dataSeries = logfile.readline().split(';')[:-1] + dataSeries = logfile.readline().split(";")[:-1] for dataSample in dataSeries: - values = tuple([runIds[j]] + \ - [None if len(x) == 0 or x == 'nan' or x == 'inf' else x - for x in dataSample.split(',')[:-1]]) + values = tuple( + [runIds[j]] + + [ + None if len(x) == 0 or x == "nan" or x == "inf" else x + for x in dataSample.split(",")[:-1] + ] + ) try: c.execute(insertFmtStr, values) except sqlite3.IntegrityError: - print('Ignoring duplicate progress data. Consider increasing ompl::tools::Benchmark::Request::timeBetweenUpdates.') + print( + "Ignoring duplicate progress data. Consider increasing ompl::tools::Benchmark::Request::timeBetweenUpdates." + ) pass logfile.readline() @@ -299,125 +388,158 @@ def readBenchmarkLog(dbname, filenames): conn.commit() c.close() + def plotAttribute(cur, planners, attribute, typename): """Create a plot for a particular attribute. It will include data for all planners that have data for this attribute.""" labels = [] measurements = [] nanCounts = [] - if typename == 'ENUM': + if typename == "ENUM": cur.execute('SELECT description FROM enums where name IS "%s"' % attribute) - descriptions = [ t[0] for t in cur.fetchall() ] + descriptions = [t[0] for t in cur.fetchall()] numValues = len(descriptions) for planner in planners: - cur.execute('SELECT %s FROM runs WHERE plannerid = %s AND %s IS NOT NULL' \ - % (attribute, planner[0], attribute)) - measurement = [ t[0] for t in cur.fetchall() if t[0] != None ] + cur.execute( + "SELECT %s FROM runs WHERE plannerid = %s AND %s IS NOT NULL" + % (attribute, planner[0], attribute) + ) + measurement = [t[0] for t in cur.fetchall() if t[0] != None] if len(measurement) > 0: - cur.execute('SELECT count(*) FROM runs WHERE plannerid = %s AND %s IS NULL' \ - % (planner[0], attribute)) + cur.execute( + "SELECT count(*) FROM runs WHERE plannerid = %s AND %s IS NULL" + % (planner[0], attribute) + ) nanCounts.append(cur.fetchone()[0]) labels.append(planner[1]) - if typename == 'ENUM': - scale = 100. / len(measurement) - measurements.append([measurement.count(i)*scale for i in range(numValues)]) + if typename == "ENUM": + scale = 100.0 / len(measurement) + measurements.append( + [measurement.count(i) * scale for i in range(numValues)] + ) else: measurements.append(measurement) - if len(measurements)==0: + if len(measurements) == 0: print('Skipping "%s": no available measurements' % attribute) return plt.clf() ax = plt.gca() - if typename == 'ENUM': - width = .5 + if typename == "ENUM": + width = 0.5 measurements = np.transpose(np.vstack(measurements)) colsum = np.sum(measurements, axis=1) rows = np.where(colsum != 0)[0] - heights = np.zeros((1,measurements.shape[1])) + heights = np.zeros((1, measurements.shape[1])) ind = range(measurements.shape[1]) legend_labels = [] for i in rows: - plt.bar(ind, measurements[i], width, bottom=heights[0], - color=matplotlib.cm.hot(int(floor(i*256/numValues))), - label=descriptions[i]) + plt.bar( + ind, + measurements[i], + width, + bottom=heights[0], + color=matplotlib.cm.hot(int(floor(i * 256 / numValues))), + label=descriptions[i], + ) heights = heights + measurements[i] - xtickNames = plt.xticks([x + width / 2. for x in ind], labels, rotation=30, fontsize=8, ha='right') - ax.set_ylabel(attribute.replace('_',' ') + ' (%)') + xtickNames = plt.xticks( + [x + width / 2.0 for x in ind], labels, rotation=30, fontsize=8, ha="right" + ) + ax.set_ylabel(attribute.replace("_", " ") + " (%)") box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.8, box.height]) props = matplotlib.font_manager.FontProperties() - props.set_size('small') - ax.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop = props) - elif typename == 'BOOLEAN': - width = .5 - measurementsPercentage = [sum(m) * 100. / len(m) for m in measurements] + props.set_size("small") + ax.legend(loc="center left", bbox_to_anchor=(1, 0.5), prop=props) + elif typename == "BOOLEAN": + width = 0.5 + measurementsPercentage = [sum(m) * 100.0 / len(m) for m in measurements] ind = range(len(measurements)) plt.bar(ind, measurementsPercentage, width) - ### uncommenting this line will remove the term 'kConfigDefault' from the labels for OMPL Solvers. + ### uncommenting this line will remove the term 'kConfigDefault' from the labels for OMPL Solvers. ### Fits situations where you need more control in the plot, such as in an academic publication for example - #labels = [l.replace('kConfigDefault', '') for l in labels] - - xtickNames = plt.xticks([x + width / 2. for x in ind], labels, rotation=30, fontsize=8, ha='right') - ax.set_ylabel(attribute.replace('_',' ') + ' (%)') - plt.subplots_adjust(bottom=0.3) # Squish the plot into the upper 2/3 of the page. Leave room for labels + # labels = [l.replace('kConfigDefault', '') for l in labels] + + xtickNames = plt.xticks( + [x + width / 2.0 for x in ind], labels, rotation=30, fontsize=8, ha="right" + ) + ax.set_ylabel(attribute.replace("_", " ") + " (%)") + plt.subplots_adjust( + bottom=0.3 + ) # Squish the plot into the upper 2/3 of the page. Leave room for labels else: - if int(matplotlibversion.split('.')[0])<1: - plt.boxplot(measurements, notch=0, sym='k+', vert=1, whis=1.5) + if int(matplotlibversion.split(".")[0]) < 1: + plt.boxplot(measurements, notch=0, sym="k+", vert=1, whis=1.5) else: - plt.boxplot(measurements, notch=0, sym='k+', vert=1, whis=1.5, bootstrap=1000) - ax.set_ylabel(attribute.replace('_',' ')) + plt.boxplot( + measurements, notch=0, sym="k+", vert=1, whis=1.5, bootstrap=1000 + ) + ax.set_ylabel(attribute.replace("_", " ")) - #xtickNames = plt.xticks(labels, rotation=30, fontsize=10) - #plt.subplots_adjust(bottom=0.3) # Squish the plot into the upper 2/3 of the page. Leave room for labels - - ### uncommenting this line will remove the term 'kConfigDefault' from the labels for OMPL Solvers. + # xtickNames = plt.xticks(labels, rotation=30, fontsize=10) + # plt.subplots_adjust(bottom=0.3) # Squish the plot into the upper 2/3 of the page. Leave room for labels + + ### uncommenting this line will remove the term 'kConfigDefault' from the labels for OMPL Solvers. ### Fits situations where you need more control in the plot, such as in an academic publication for example - #labels = [l.replace('kConfigDefault', '') for l in labels] - - xtickNames = plt.setp(ax,xticklabels=labels) - plt.setp(xtickNames, rotation=30, fontsize=8, ha='right') - for tick in ax.xaxis.get_major_ticks(): # shrink the font size of the x tick labels + # labels = [l.replace('kConfigDefault', '') for l in labels] + + xtickNames = plt.setp(ax, xticklabels=labels) + plt.setp(xtickNames, rotation=30, fontsize=8, ha="right") + for ( + tick + ) in ax.xaxis.get_major_ticks(): # shrink the font size of the x tick labels tick.label.set_fontsize(8) - plt.subplots_adjust(bottom=0.3) # Squish the plot into the upper 2/3 of the page. Leave room for labels - ax.set_xlabel('Motion planning algorithm', fontsize=12) - ax.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5) - if max(nanCounts)>0: + plt.subplots_adjust( + bottom=0.3 + ) # Squish the plot into the upper 2/3 of the page. Leave room for labels + ax.set_xlabel("Motion planning algorithm", fontsize=12) + ax.yaxis.grid(True, linestyle="-", which="major", color="lightgrey", alpha=0.5) + if max(nanCounts) > 0: maxy = max([max(y) for y in measurements]) for i in range(len(labels)): - x = i+width/2 if typename=='BOOLEAN' else i+1 + x = i + width / 2 if typename == "BOOLEAN" else i + 1 ### uncommenting the next line, the number of failed planning attempts will be added to each bar # ax.text(x, .95*maxy, str(nanCounts[i]), horizontalalignment='center', size='small') plt.show() + def plotProgressAttribute(cur, planners, attribute): """Plot data for a single planner progress attribute. Will create an -average time-plot with error bars of the attribute over all runs for -each planner.""" + average time-plot with error bars of the attribute over all runs for + each planner.""" import numpy.ma as ma plt.clf() ax = plt.gca() - ax.set_xlabel('time (s)') - ax.set_ylabel(attribute.replace('_',' ')) + ax.set_xlabel("time (s)") + ax.set_ylabel(attribute.replace("_", " ")) plannerNames = [] for planner in planners: - cur.execute("""SELECT count(progress.%s) FROM progress INNER JOIN runs + cur.execute( + """SELECT count(progress.%s) FROM progress INNER JOIN runs ON progress.runid = runs.id AND runs.plannerid=%s - AND progress.%s IS NOT NULL""" \ - % (attribute, planner[0], attribute)) + AND progress.%s IS NOT NULL""" + % (attribute, planner[0], attribute) + ) if cur.fetchone()[0] > 0: plannerNames.append(planner[1]) - cur.execute("""SELECT DISTINCT progress.runid FROM progress INNER JOIN runs - WHERE progress.runid=runs.id AND runs.plannerid=?""", (planner[0],)) + cur.execute( + """SELECT DISTINCT progress.runid FROM progress INNER JOIN runs + WHERE progress.runid=runs.id AND runs.plannerid=?""", + (planner[0],), + ) runids = [t[0] for t in cur.fetchall()] timeTable = [] dataTable = [] for r in runids: # Select data for given run - cur.execute('SELECT time, %s FROM progress WHERE runid = %s ORDER BY time' % (attribute,r)) + cur.execute( + "SELECT time, %s FROM progress WHERE runid = %s ORDER BY time" + % (attribute, r) + ) (time, data) = zip(*(cur.fetchall())) timeTable.append(time) dataTable.append(data) @@ -428,39 +550,50 @@ def plotProgressAttribute(cur, planners, attribute): fewestSamples = min(len(time[:]) for time in timeTable) times = np.array(timeTable[0][:fewestSamples]) dataArrays = np.array([data[:fewestSamples] for data in dataTable]) - filteredData = ma.masked_array(dataArrays, np.equal(dataArrays, None), dtype=float) + filteredData = ma.masked_array( + dataArrays, np.equal(dataArrays, None), dtype=float + ) means = np.mean(filteredData, axis=0) stddevs = np.std(filteredData, axis=0, ddof=1) # plot average with error bars - plt.errorbar(times, means, yerr=2*stddevs, errorevery=max(1, len(times) // 20)) + plt.errorbar( + times, means, yerr=2 * stddevs, errorevery=max(1, len(times) // 20) + ) ax.legend(plannerNames) - if len(plannerNames)>0: + if len(plannerNames) > 0: plt.show() else: plt.clf() + def plotStatistics(dbname, fname): """Create a PDF file with box plots for all attributes.""" print("Generating plots...") conn = sqlite3.connect(dbname) c = conn.cursor() - c.execute('PRAGMA FOREIGN_KEYS = ON') - c.execute('SELECT id, name FROM plannerConfigs') - planners = [(t[0],t[1].replace('geometric_','').replace('control_','')) - for t in c.fetchall()] - c.execute('PRAGMA table_info(runs)') + c.execute("PRAGMA FOREIGN_KEYS = ON") + c.execute("SELECT id, name FROM plannerConfigs") + planners = [ + (t[0], t[1].replace("geometric_", "").replace("control_", "")) + for t in c.fetchall() + ] + c.execute("PRAGMA table_info(runs)") colInfo = c.fetchall()[3:] pp = PdfPages(fname) for col in colInfo: - if col[2] == 'BOOLEAN' or col[2] == 'ENUM' or \ - col[2] == 'INTEGER' or col[2] == 'REAL': - plotAttribute(c, planners, col[1], col[2]) - pp.savefig(plt.gcf()) - - c.execute('PRAGMA table_info(progress)') + if ( + col[2] == "BOOLEAN" + or col[2] == "ENUM" + or col[2] == "INTEGER" + or col[2] == "REAL" + ): + plotAttribute(c, planners, col[1], col[2]) + pp.savefig(plt.gcf()) + + c.execute("PRAGMA table_info(progress)") colInfo = c.fetchall()[2:] for col in colInfo: plotProgressAttribute(c, planners, col[1]) @@ -472,34 +605,41 @@ def plotStatistics(dbname, fname): c.execute("""SELECT id, name, timelimit, memorylimit FROM experiments""") experiments = c.fetchall() for experiment in experiments: - c.execute("""SELECT count(*) FROM runs WHERE runs.experimentid = %d - GROUP BY runs.plannerid""" % experiment[0]) + c.execute( + """SELECT count(*) FROM runs WHERE runs.experimentid = %d + GROUP BY runs.plannerid""" + % experiment[0] + ) numRuns = [run[0] for run in c.fetchall()] - numRuns = numRuns[0] if len(set(numRuns)) == 1 else ','.join(numRuns) + numRuns = numRuns[0] if len(set(numRuns)) == 1 else ",".join(numRuns) plt.figtext(pagex, pagey, 'Experiment "%s"' % experiment[1]) - plt.figtext(pagex, pagey-0.05, 'Number of averaged runs: %d' % numRuns) - plt.figtext(pagex, pagey-0.10, "Time limit per run: %g seconds" % experiment[2]) - plt.figtext(pagex, pagey-0.15, "Memory limit per run: %g MB" % experiment[3]) + plt.figtext(pagex, pagey - 0.05, "Number of averaged runs: %d" % numRuns) + plt.figtext( + pagex, pagey - 0.10, "Time limit per run: %g seconds" % experiment[2] + ) + plt.figtext(pagex, pagey - 0.15, "Memory limit per run: %g MB" % experiment[3]) pagey -= 0.22 plt.show() pp.savefig(plt.gcf()) pp.close() + def saveAsMysql(dbname, mysqldump): # See http://stackoverflow.com/questions/1067060/perl-to-python import re + print("Saving as MySQL dump file...") conn = sqlite3.connect(dbname) - mysqldump = open(mysqldump,'w') + mysqldump = open(mysqldump, "w") # make sure all tables are dropped in an order that keepd foreign keys valid c = conn.cursor() c.execute("SELECT name FROM sqlite_master WHERE type='table'") - table_names = [ str(t[0]) for t in c.fetchall() ] + table_names = [str(t[0]) for t in c.fetchall()] c.close() - last = ['experiments', 'planner_configs'] + last = ["experiments", "planner_configs"] for table in table_names: if table.startswith("sqlite"): continue @@ -511,44 +651,52 @@ def saveAsMysql(dbname, mysqldump): for line in conn.iterdump(): process = False - for nope in ('BEGIN TRANSACTION','COMMIT', - 'sqlite_sequence','CREATE UNIQUE INDEX', 'CREATE VIEW'): - if nope in line: break + for nope in ( + "BEGIN TRANSACTION", + "COMMIT", + "sqlite_sequence", + "CREATE UNIQUE INDEX", + "CREATE VIEW", + ): + if nope in line: + break else: process = True - if not process: continue + if not process: + continue line = re.sub(r"[\n\r\t ]+", " ", line) - m = re.search('CREATE TABLE ([a-zA-Z0-9_]*)(.*)', line) + m = re.search("CREATE TABLE ([a-zA-Z0-9_]*)(.*)", line) if m: name, sub = m.groups() - sub = sub.replace('"','`') - line = '''CREATE TABLE IF NOT EXISTS %(name)s%(sub)s''' + sub = sub.replace('"', "`") + line = """CREATE TABLE IF NOT EXISTS %(name)s%(sub)s""" line = line % dict(name=name, sub=sub) # make sure we use an engine that supports foreign keys line = line.rstrip("\n\t ;") + " ENGINE = InnoDB;\n" else: m = re.search('INSERT INTO "([a-zA-Z0-9_]*)"(.*)', line) if m: - line = 'INSERT INTO %s%s\n' % m.groups() - line = line.replace('"', r'\"') + line = "INSERT INTO %s%s\n" % m.groups() + line = line.replace('"', r"\"") line = line.replace('"', "'") line = re.sub(r"([^'])'t'(.)", "\\1THIS_IS_TRUE\\2", line) - line = line.replace('THIS_IS_TRUE', '1') + line = line.replace("THIS_IS_TRUE", "1") line = re.sub(r"([^'])'f'(.)", "\\1THIS_IS_FALSE\\2", line) - line = line.replace('THIS_IS_FALSE', '0') - line = line.replace('AUTOINCREMENT', 'AUTO_INCREMENT') + line = line.replace("THIS_IS_FALSE", "0") + line = line.replace("AUTOINCREMENT", "AUTO_INCREMENT") mysqldump.write(line) mysqldump.close() + def computeViews(dbname): conn = sqlite3.connect(dbname) c = conn.cursor() - c.execute('PRAGMA FOREIGN_KEYS = ON') - c.execute('PRAGMA table_info(runs)') + c.execute("PRAGMA FOREIGN_KEYS = ON") + c.execute("PRAGMA table_info(runs)") # kinodynamic paths cannot be simplified (or least not easily), # so simplification_time may not exist as a database column - if 'simplification_time' in [col[1] for col in c.fetchall()]: + if "simplification_time" in [col[1] for col in c.fetchall()]: s0 = """SELECT plannerid, plannerConfigs.name AS plannerName, experimentid, solved, time + simplification_time AS total_time FROM plannerConfigs INNER JOIN experiments INNER JOIN runs ON plannerConfigs.id=runs.plannerid AND experiments.id=runs.experimentid""" @@ -556,34 +704,68 @@ def computeViews(dbname): s0 = """SELECT plannerid, plannerConfigs.name AS plannerName, experimentid, solved, time AS total_time FROM plannerConfigs INNER JOIN experiments INNER JOIN runs ON plannerConfigs.id=runs.plannerid AND experiments.id=runs.experimentid""" - s1 = """SELECT plannerid, plannerName, experimentid, AVG(solved) AS avg_solved, AVG(total_time) AS avg_total_time - FROM (%s) GROUP BY plannerid, experimentid""" % s0 - s2 = """SELECT plannerid, experimentid, MIN(avg_solved) AS avg_solved, avg_total_time - FROM (%s) GROUP BY plannerName, experimentid ORDER BY avg_solved DESC, avg_total_time ASC""" % s1 - c.execute('DROP VIEW IF EXISTS bestPlannerConfigsPerExperiment') - c.execute('CREATE VIEW IF NOT EXISTS bestPlannerConfigsPerExperiment AS %s' % s2) - - s1 = """SELECT plannerid, plannerName, AVG(solved) AS avg_solved, AVG(total_time) AS avg_total_time - FROM (%s) GROUP BY plannerid""" % s0 - s2 = """SELECT plannerid, MIN(avg_solved) AS avg_solved, avg_total_time - FROM (%s) GROUP BY plannerName ORDER BY avg_solved DESC, avg_total_time ASC""" % s1 - c.execute('DROP VIEW IF EXISTS bestPlannerConfigs') - c.execute('CREATE VIEW IF NOT EXISTS bestPlannerConfigs AS %s' % s2) + s1 = ( + """SELECT plannerid, plannerName, experimentid, AVG(solved) AS avg_solved, AVG(total_time) AS avg_total_time + FROM (%s) GROUP BY plannerid, experimentid""" + % s0 + ) + s2 = ( + """SELECT plannerid, experimentid, MIN(avg_solved) AS avg_solved, avg_total_time + FROM (%s) GROUP BY plannerName, experimentid ORDER BY avg_solved DESC, avg_total_time ASC""" + % s1 + ) + c.execute("DROP VIEW IF EXISTS bestPlannerConfigsPerExperiment") + c.execute("CREATE VIEW IF NOT EXISTS bestPlannerConfigsPerExperiment AS %s" % s2) + + s1 = ( + """SELECT plannerid, plannerName, AVG(solved) AS avg_solved, AVG(total_time) AS avg_total_time + FROM (%s) GROUP BY plannerid""" + % s0 + ) + s2 = ( + """SELECT plannerid, MIN(avg_solved) AS avg_solved, avg_total_time + FROM (%s) GROUP BY plannerName ORDER BY avg_solved DESC, avg_total_time ASC""" + % s1 + ) + c.execute("DROP VIEW IF EXISTS bestPlannerConfigs") + c.execute("CREATE VIEW IF NOT EXISTS bestPlannerConfigs AS %s" % s2) conn.commit() c.close() + if __name__ == "__main__": usage = """%prog [options] [ ...]""" parser = OptionParser("A script to parse benchmarking results.\n" + usage) - parser.add_option("-d", "--database", dest="dbname", default="benchmark.db", - help="Filename of benchmark database [default: %default]") - parser.add_option("-v", "--view", action="store_true", dest="view", default=False, - help="Compute the views for best planner configurations") - parser.add_option("-p", "--plot", dest="plot", default=None, - help="Create a PDF of plots with the filename provided") - parser.add_option("-m", "--mysql", dest="mysqldb", default=None, - help="Save SQLite3 database as a MySQL dump file") + parser.add_option( + "-d", + "--database", + dest="dbname", + default="benchmark.db", + help="Filename of benchmark database [default: %default]", + ) + parser.add_option( + "-v", + "--view", + action="store_true", + dest="view", + default=False, + help="Compute the views for best planner configurations", + ) + parser.add_option( + "-p", + "--plot", + dest="plot", + default=None, + help="Create a PDF of plots with the filename provided", + ) + parser.add_option( + "-m", + "--mysql", + dest="mysqldb", + default=None, + help="Save SQLite3 database as a MySQL dump file", + ) (options, args) = parser.parse_args() if len(args) == 0: @@ -602,4 +784,3 @@ def computeViews(dbname): if options.mysqldb: saveAsMysql(options.dbname, options.mysqldb) - diff --git a/moveit_ros/move_group/scripts/load_map b/moveit_ros/move_group/scripts/load_map index c63803f33f..862e69c558 100755 --- a/moveit_ros/move_group/scripts/load_map +++ b/moveit_ros/move_group/scripts/load_map @@ -5,10 +5,10 @@ from moveit_msgs.srv import LoadMap filename = sys.argv[1] -rospy.init_node('load_map', anonymous=True) +rospy.init_node("load_map", anonymous=True) -load_map_service = rospy.ServiceProxy('move_group/load_map', LoadMap) +load_map_service = rospy.ServiceProxy("move_group/load_map", LoadMap) if load_map_service(filename): - rospy.loginfo('Succeeded') + rospy.loginfo("Succeeded") else: - rospy.loginfo('Failed') + rospy.loginfo("Failed") diff --git a/moveit_ros/move_group/scripts/save_map b/moveit_ros/move_group/scripts/save_map index e8bcc60457..d9c7511318 100755 --- a/moveit_ros/move_group/scripts/save_map +++ b/moveit_ros/move_group/scripts/save_map @@ -5,11 +5,10 @@ from moveit_msgs.srv import SaveMap filename = sys.argv[1] -rospy.init_node('save_map', anonymous=True) +rospy.init_node("save_map", anonymous=True) -save_map_service = rospy.ServiceProxy('move_group/save_map', SaveMap) +save_map_service = rospy.ServiceProxy("move_group/save_map", SaveMap) if save_map_service(filename): - rospy.loginfo('Succeeded') + rospy.loginfo("Succeeded") else: - rospy.loginfo('Failed') - + rospy.loginfo("Failed") diff --git a/moveit_ros/move_group/test/test_cancel_before_plan_execution.py b/moveit_ros/move_group/test/test_cancel_before_plan_execution.py index 801bbe26c4..b337eff115 100755 --- a/moveit_ros/move_group/test/test_cancel_before_plan_execution.py +++ b/moveit_ros/move_group/test/test_cancel_before_plan_execution.py @@ -5,14 +5,19 @@ import unittest from actionlib import SimpleActionClient import moveit_commander -from moveit_msgs.msg import MoveItErrorCodes, MoveGroupGoal, Constraints, JointConstraint, MoveGroupAction +from moveit_msgs.msg import ( + MoveItErrorCodes, + MoveGroupGoal, + Constraints, + JointConstraint, + MoveGroupAction, +) class TestMoveActionCancelDrop(unittest.TestCase): - def setUp(self): # create a action client of move group - self._move_client = SimpleActionClient('move_group', MoveGroupAction) + self._move_client = SimpleActionClient("move_group", MoveGroupAction) self._move_client.wait_for_server() moveit_commander.roscpp_initialize(sys.argv) @@ -57,7 +62,10 @@ def test_cancel_drop_plan_execution(self): # check the error code in result # error code is 0 if the server ends with RECALLED status - self.assertTrue(result.error_code.val == MoveItErrorCodes.PREEMPTED or result.error_code.val == 0) + self.assertTrue( + result.error_code.val == MoveItErrorCodes.PREEMPTED + or result.error_code.val == 0 + ) def test_cancel_drop_plan_only(self): # set the plan only flag @@ -80,7 +88,10 @@ def test_cancel_drop_plan_only(self): # check the error code in result # error code is 0 if the server ends with RECALLED status - self.assertTrue(result.error_code.val == MoveItErrorCodes.PREEMPTED or result.error_code.val == 0) + self.assertTrue( + result.error_code.val == MoveItErrorCodes.PREEMPTED + or result.error_code.val == 0 + ) def test_cancel_resend(self): # send the goal @@ -105,7 +116,12 @@ def test_cancel_resend(self): self.assertEqual(result.error_code.val, MoveItErrorCodes.SUCCESS) -if __name__ == '__main__': +if __name__ == "__main__": import rostest - rospy.init_node('cancel_before_plan_execution') - rostest.rosrun('moveit_ros_move_group', 'test_cancel_before_plan_execution', TestMoveActionCancelDrop) + + rospy.init_node("cancel_before_plan_execution") + rostest.rosrun( + "moveit_ros_move_group", + "test_cancel_before_plan_execution", + TestMoveActionCancelDrop, + ) diff --git a/moveit_ros/move_group/test/test_check_state_validity_in_empty_scene.py b/moveit_ros/move_group/test/test_check_state_validity_in_empty_scene.py index 784a40ae3c..5dba11031f 100755 --- a/moveit_ros/move_group/test/test_check_state_validity_in_empty_scene.py +++ b/moveit_ros/move_group/test/test_check_state_validity_in_empty_scene.py @@ -10,35 +10,56 @@ class TestCheckStateValidityInEmptyScene(unittest.TestCase): - def setUp(self): moveit_commander.roscpp_initialize(sys.argv) self.robot_commander = moveit_commander.RobotCommander() self.group_name = self.robot_commander.get_group_names()[0] self.group_commander = moveit_commander.MoveGroupCommander(self.group_name) - self._check_state_validity = rospy.ServiceProxy('/check_state_validity', GetStateValidity) + self._check_state_validity = rospy.ServiceProxy( + "/check_state_validity", GetStateValidity + ) def test_check_collision_free_state_validity_in_empty_scene(self): current_robot_state = self.robot_commander.get_current_state() - validity_report = self._check_state_validity(current_robot_state, self.group_name, Constraints()) - self.assertListEqual(validity_report.contacts, [], "In the default_robot_state, the robot should not collide with itself") - + validity_report = self._check_state_validity( + current_robot_state, self.group_name, Constraints() + ) + self.assertListEqual( + validity_report.contacts, + [], + "In the default_robot_state, the robot should not collide with itself", + ) def test_check_colliding_state_validity_in_empty_scene(self): current_robot_state = self.robot_commander.get_current_state() # force a colliding state with the Fanuc M-10iA - current_robot_state.joint_state.position = list(current_robot_state.joint_state.position) - current_robot_state.joint_state.position[current_robot_state.joint_state.name.index("joint_3")] = -2 + current_robot_state.joint_state.position = list( + current_robot_state.joint_state.position + ) + current_robot_state.joint_state.position[ + current_robot_state.joint_state.name.index("joint_3") + ] = -2 - validity_report = self._check_state_validity(current_robot_state, self.group_name, Constraints()) + validity_report = self._check_state_validity( + current_robot_state, self.group_name, Constraints() + ) - self.assertNotEqual(len(validity_report.contacts), 0, "When the robot collides with itself, it should have some contacts (with itself)") + self.assertNotEqual( + len(validity_report.contacts), + 0, + "When the robot collides with itself, it should have some contacts (with itself)", + ) -if __name__ == '__main__': +if __name__ == "__main__": import rostest - rospy.init_node('check_state_validity_in_empty_scene') - rostest.rosrun('moveit_ros_move_group', 'test_check_state_validity_in_empty_scene', TestCheckStateValidityInEmptyScene) + + rospy.init_node("check_state_validity_in_empty_scene") + rostest.rosrun( + "moveit_ros_move_group", + "test_check_state_validity_in_empty_scene", + TestCheckStateValidityInEmptyScene, + ) diff --git a/moveit_ros/moveit_servo/README.md b/moveit_ros/moveit_servo/README.md index e889244cb8..de63784416 100644 --- a/moveit_ros/moveit_servo/README.md +++ b/moveit_ros/moveit_servo/README.md @@ -55,4 +55,4 @@ If you see a warning about "close to singularity", try changing the direction of Run tests from the moveit\_servo folder: - catkin run_tests --no-deps --this \ No newline at end of file + catkin run_tests --no-deps --this diff --git a/moveit_ros/moveit_servo/src/teleop_examples/spacenav_to_twist.cpp b/moveit_ros/moveit_servo/src/teleop_examples/spacenav_to_twist.cpp index cec304711a..7f5c685d6a 100644 --- a/moveit_ros/moveit_servo/src/teleop_examples/spacenav_to_twist.cpp +++ b/moveit_ros/moveit_servo/src/teleop_examples/spacenav_to_twist.cpp @@ -104,4 +104,4 @@ int main(int argc, char** argv) moveit_servo::SpaceNavToTwist to_twist; return 0; -} \ No newline at end of file +} diff --git a/moveit_ros/moveit_servo/test/config/initial_position.yaml b/moveit_ros/moveit_servo/test/config/initial_position.yaml index 7a86cc0aa7..38ac0fcecf 100644 --- a/moveit_ros/moveit_servo/test/config/initial_position.yaml +++ b/moveit_ros/moveit_servo/test/config/initial_position.yaml @@ -8,4 +8,3 @@ zeros: panda_joint6: 1.571 panda_joint7: 0.785 publish_default_positions: True - diff --git a/moveit_ros/planning/planning_components_tools/results/State_Operations_i2600K_PR2_Groovy.txt b/moveit_ros/planning/planning_components_tools/results/State_Operations_i2600K_PR2_Groovy.txt index c85b727771..cfadbf5271 100644 --- a/moveit_ros/planning/planning_components_tools/results/State_Operations_i2600K_PR2_Groovy.txt +++ b/moveit_ros/planning/planning_components_tools/results/State_Operations_i2600K_PR2_Groovy.txt @@ -66,4 +66,3 @@ left_gripper:FK Default: 0.017607s (0.401701%), [1e-06s --> 3.5e-05 s], 10000 pa right_gripper:FK Random: 0.011327s (0.258424%), [1e-06s --> 1.2e-05 s], 10000 parts, 1.1327e-06 s on average (882846 /s) left_gripper:FK Random: 0.011019s (0.251397%), [1e-06s --> 9e-06 s], 10000 parts, 1.1019e-06 s on average (907523 /s) Unaccounted time : 0.061805 (1.41007 %) - diff --git a/moveit_ros/planning/planning_request_adapters_plugin_description.xml b/moveit_ros/planning/planning_request_adapters_plugin_description.xml index 50b5f0b1c0..d883f2a717 100644 --- a/moveit_ros/planning/planning_request_adapters_plugin_description.xml +++ b/moveit_ros/planning/planning_request_adapters_plugin_description.xml @@ -37,7 +37,7 @@ - This is an improved time parameterization using Time-Optimal Trajectory Generation for Path Following With Bounded Acceleration and Velocity (Kunz and Stilman, RSS 2008) + This is an improved time parameterization using Time-Optimal Trajectory Generation for Path Following With Bounded Acceleration and Velocity (Kunz and Stilman, RSS 2008) diff --git a/moveit_ros/planning/trajectory_execution_manager/dox/trajectory_execution.dox b/moveit_ros/planning/trajectory_execution_manager/dox/trajectory_execution.dox index bb4b9068a4..8f578b6af6 100644 --- a/moveit_ros/planning/trajectory_execution_manager/dox/trajectory_execution.dox +++ b/moveit_ros/planning/trajectory_execution_manager/dox/trajectory_execution.dox @@ -8,4 +8,4 @@ The trajectory_execution_manager::TrajectoryExecutionManager class allows two ma The functionality of the trajectory execution in MoveIt! usually needs robot-specific interaction with controllers. For this reason, the concept of a controller manager specific to MoveIt! (moveit_controller_manager::MoveItControllerManager) was defined. This is an abstract class that defines the functionality needed by trajectory_execution_manager::TrajectoryExecutionManager and needs to be implemented for each robot type. Often, the implementation of these plugins are quite similar and it is easy to modify existing code to achieve the desired functionality (see for example pr2_moveit_controller_manager::Pr2MoveItControllerManager). -*/ \ No newline at end of file +*/ diff --git a/moveit_ros/planning/trajectory_execution_manager/lib/plugin_description.xml b/moveit_ros/planning/trajectory_execution_manager/lib/plugin_description.xml index 686b38e1f2..faf679d629 100644 --- a/moveit_ros/planning/trajectory_execution_manager/lib/plugin_description.xml +++ b/moveit_ros/planning/trajectory_execution_manager/lib/plugin_description.xml @@ -4,4 +4,3 @@ - diff --git a/moveit_ros/planning_interface/py_bindings_tools/dox/py_bindings.dox b/moveit_ros/planning_interface/py_bindings_tools/dox/py_bindings.dox index 9546ad12f0..061314d0d8 100644 --- a/moveit_ros/planning_interface/py_bindings_tools/dox/py_bindings.dox +++ b/moveit_ros/planning_interface/py_bindings_tools/dox/py_bindings.dox @@ -45,4 +45,4 @@ But to forward these parameters an explicit function call needs to be made. For that we provide a function call -*/ \ No newline at end of file +*/ diff --git a/moveit_ros/planning_interface/setup.py b/moveit_ros/planning_interface/setup.py index 685bfa2d77..60f5f44547 100644 --- a/moveit_ros/planning_interface/setup.py +++ b/moveit_ros/planning_interface/setup.py @@ -2,8 +2,8 @@ from catkin_pkg.python_setup import generate_distutils_setup d = generate_distutils_setup() -d['packages'] = ['moveit_ros_planning_interface'] -d['scripts'] = [] -d['package_dir'] = {'': 'python'} +d["packages"] = ["moveit_ros_planning_interface"] +d["scripts"] = [] +d["package_dir"] = {"": "python"} setup(**d) diff --git a/moveit_ros/planning_interface/test/cleanup.py b/moveit_ros/planning_interface/test/cleanup.py index bca6618a96..07cf98caa1 100755 --- a/moveit_ros/planning_interface/test/cleanup.py +++ b/moveit_ros/planning_interface/test/cleanup.py @@ -8,8 +8,8 @@ import rospkg import roslib.packages -PKGNAME = 'moveit_ros_planning_interface' -NODENAME = 'moveit_cleanup_tests' +PKGNAME = "moveit_ros_planning_interface" +NODENAME = "moveit_cleanup_tests" # As issue #592 is related to a crash during program exit, # we cannot perform a standard unit test. @@ -21,7 +21,7 @@ def __init__(self, *args, **kwargs): super(CleanupTest, self).__init__(*args, **kwargs) self._rospack = rospkg.RosPack() - def run_cmd(self, cmd, num = 5): + def run_cmd(self, cmd, num=5): failures = 0 for i in range(num): if subprocess.call(cmd) != 0: @@ -29,10 +29,13 @@ def run_cmd(self, cmd, num = 5): self.assertEqual(failures, 0, "%d of %d runs failed" % (failures, num)) def test_py(self): - self.run_cmd(roslib.packages.find_node(PKGNAME, "test_cleanup.py", self._rospack)) + self.run_cmd( + roslib.packages.find_node(PKGNAME, "test_cleanup.py", self._rospack) + ) def test_cpp(self): self.run_cmd(roslib.packages.find_node(PKGNAME, "test_cleanup", self._rospack)) -if __name__ == '__main__': + +if __name__ == "__main__": rostest.rosrun(PKGNAME, NODENAME, CleanupTest) diff --git a/moveit_ros/planning_interface/test/moveit_cpp.yaml b/moveit_ros/planning_interface/test/moveit_cpp.yaml index 6d622662c9..9a69f0dd1d 100644 --- a/moveit_ros/planning_interface/test/moveit_cpp.yaml +++ b/moveit_ros/planning_interface/test/moveit_cpp.yaml @@ -15,4 +15,4 @@ plan_request_params: planning_attempts: 1 planning_pipeline: ompl max_velocity_scaling_factor: 1.0 - max_acceleration_scaling_factor: 1.0 \ No newline at end of file + max_acceleration_scaling_factor: 1.0 diff --git a/moveit_ros/planning_interface/test/python_move_group.py b/moveit_ros/planning_interface/test/python_move_group.py index 187e7bfebb..4dc9b81ae2 100755 --- a/moveit_ros/planning_interface/test/python_move_group.py +++ b/moveit_ros/planning_interface/test/python_move_group.py @@ -6,7 +6,9 @@ import rostest import os -from moveit_ros_planning_interface._moveit_move_group_interface import MoveGroupInterface +from moveit_ros_planning_interface._moveit_move_group_interface import ( + MoveGroupInterface, +) class PythonMoveGroupTest(unittest.TestCase): @@ -14,7 +16,9 @@ class PythonMoveGroupTest(unittest.TestCase): @classmethod def setUpClass(self): - self.group = MoveGroupInterface(self.PLANNING_GROUP, "robot_description", rospy.get_namespace()) + self.group = MoveGroupInterface( + self.PLANNING_GROUP, "robot_description", rospy.get_namespace() + ) @classmethod def tearDown(self): @@ -25,16 +29,20 @@ def check_target_setting(self, expect, *args): args = [expect] self.group.set_joint_value_target(*args) res = self.group.get_joint_value_target() - self.assertTrue(np.all(np.asarray(res) == np.asarray(expect)), - "Setting failed for %s, values: %s" % (type(args[0]), res)) + self.assertTrue( + np.all(np.asarray(res) == np.asarray(expect)), + "Setting failed for %s, values: %s" % (type(args[0]), res), + ) def test_target_setting(self): n = self.group.get_variable_count() self.check_target_setting([0.1] * n) self.check_target_setting((0.2,) * n) self.check_target_setting(np.zeros(n)) - self.check_target_setting([0.3] * n, {name: 0.3 for name in self.group.get_active_joints()}) - self.check_target_setting([0.5] + [0.3]*(n-1), "joint_1", 0.5) + self.check_target_setting( + [0.3] * n, {name: 0.3 for name in self.group.get_active_joints()} + ) + self.check_target_setting([0.5] + [0.3] * (n - 1), "joint_1", 0.5) def plan(self, target): self.group.set_joint_value_target(target) @@ -60,24 +68,33 @@ def test_get_jacobian_matrix(self): current = self.group.get_current_joint_values() result = self.group.get_jacobian_matrix(current) # Value check by known value at the initial pose - expected = np.array([[ 0. , 0.8 , -0.2 , 0. , 0. , 0. ], - [ 0.89, 0. , 0. , 0. , 0. , 0. ], - [ 0. , -0.74, 0.74, 0. , 0.1 , 0. ], - [ 0. , 0. , 0. , -1. , 0. , -1. ], - [ 0. , 1. , -1. , 0. , -1. , 0. ], - [ 1. , 0. , 0. , 0. , 0. , 0. ]]) + expected = np.array( + [ + [0.0, 0.8, -0.2, 0.0, 0.0, 0.0], + [0.89, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, -0.74, 0.74, 0.0, 0.1, 0.0], + [0.0, 0.0, 0.0, -1.0, 0.0, -1.0], + [0.0, 1.0, -1.0, 0.0, -1.0, 0.0], + [1.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ] + ) self.assertTrue(np.allclose(result, expected)) result = self.group.get_jacobian_matrix(current, [1.0, 1.0, 1.0]) - expected = np.array([[ 1. , 1.8 , -1.2 , 0. , -1. , 0. ], - [ 1.89, 0. , 0. , 1. , 0. , 1. ], - [ 0. , -1.74, 1.74, 1. , 1.1 , 1. ], - [ 0. , 0. , 0. , -1. , 0. , -1. ], - [ 0. , 1. , -1. , 0. , -1. , 0. ], - [ 1. , 0. , 0. , 0. , 0. , 0. ]]) - -if __name__ == '__main__': - PKGNAME = 'moveit_ros_planning_interface' - NODENAME = 'moveit_test_python_move_group' + expected = np.array( + [ + [1.0, 1.8, -1.2, 0.0, -1.0, 0.0], + [1.89, 0.0, 0.0, 1.0, 0.0, 1.0], + [0.0, -1.74, 1.74, 1.0, 1.1, 1.0], + [0.0, 0.0, 0.0, -1.0, 0.0, -1.0], + [0.0, 1.0, -1.0, 0.0, -1.0, 0.0], + [1.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ] + ) + + +if __name__ == "__main__": + PKGNAME = "moveit_ros_planning_interface" + NODENAME = "moveit_test_python_move_group" rospy.init_node(NODENAME) rostest.rosrun(PKGNAME, NODENAME, PythonMoveGroupTest) diff --git a/moveit_ros/planning_interface/test/python_move_group_ns.py b/moveit_ros/planning_interface/test/python_move_group_ns.py index 13a5c21fed..2e85e4f6c3 100755 --- a/moveit_ros/planning_interface/test/python_move_group_ns.py +++ b/moveit_ros/planning_interface/test/python_move_group_ns.py @@ -43,7 +43,9 @@ import rostest import os -from moveit_ros_planning_interface._moveit_move_group_interface import MoveGroupInterface +from moveit_ros_planning_interface._moveit_move_group_interface import ( + MoveGroupInterface, +) class PythonMoveGroupNsTest(unittest.TestCase): @@ -52,7 +54,11 @@ class PythonMoveGroupNsTest(unittest.TestCase): @classmethod def setUpClass(self): - self.group = MoveGroupInterface(self.PLANNING_GROUP, "%srobot_description"%self.PLANNING_NS, self.PLANNING_NS) + self.group = MoveGroupInterface( + self.PLANNING_GROUP, + "%srobot_description" % self.PLANNING_NS, + self.PLANNING_NS, + ) @classmethod def tearDown(self): @@ -63,16 +69,20 @@ def check_target_setting(self, expect, *args): args = [expect] self.group.set_joint_value_target(*args) res = self.group.get_joint_value_target() - self.assertTrue(np.all(np.asarray(res) == np.asarray(expect)), - "Setting failed for %s, values: %s" % (type(args[0]), res)) + self.assertTrue( + np.all(np.asarray(res) == np.asarray(expect)), + "Setting failed for %s, values: %s" % (type(args[0]), res), + ) def test_target_setting(self): n = self.group.get_variable_count() self.check_target_setting([0.1] * n) self.check_target_setting((0.2,) * n) self.check_target_setting(np.zeros(n)) - self.check_target_setting([0.3] * n, {name: 0.3 for name in self.group.get_active_joints()}) - self.check_target_setting([0.5] + [0.3]*(n-1), "joint_1", 0.5) + self.check_target_setting( + [0.3] * n, {name: 0.3 for name in self.group.get_active_joints()} + ) + self.check_target_setting([0.5] + [0.3] * (n - 1), "joint_1", 0.5) def plan(self, target): self.group.set_joint_value_target(target) @@ -95,8 +105,8 @@ def test_validation(self): self.assertTrue(self.group.execute(plan3)) -if __name__ == '__main__': - PKGNAME = 'moveit_ros_planning_interface' - NODENAME = 'moveit_test_python_move_group' +if __name__ == "__main__": + PKGNAME = "moveit_ros_planning_interface" + NODENAME = "moveit_test_python_move_group" rospy.init_node(NODENAME) rostest.rosrun(PKGNAME, NODENAME, PythonMoveGroupNsTest) diff --git a/moveit_ros/planning_interface/test/robot_state_update.py b/moveit_ros/planning_interface/test/robot_state_update.py index f85c5328e1..394c7af3ec 100755 --- a/moveit_ros/planning_interface/test/robot_state_update.py +++ b/moveit_ros/planning_interface/test/robot_state_update.py @@ -6,7 +6,9 @@ import rostest import os -from moveit_ros_planning_interface._moveit_move_group_interface import MoveGroupInterface +from moveit_ros_planning_interface._moveit_move_group_interface import ( + MoveGroupInterface, +) class RobotStateUpdateTest(unittest.TestCase): @@ -14,7 +16,9 @@ class RobotStateUpdateTest(unittest.TestCase): @classmethod def setUpClass(self): - self.group = MoveGroupInterface(self.PLANNING_GROUP, "robot_description", rospy.get_namespace()) + self.group = MoveGroupInterface( + self.PLANNING_GROUP, "robot_description", rospy.get_namespace() + ) @classmethod def tearDown(self): @@ -27,20 +31,20 @@ def plan(self, target): def test(self): current = np.asarray(self.group.get_current_joint_values()) for i in range(30): - target = current + np.random.uniform(-0.5, 0.5, size = current.shape) + target = current + np.random.uniform(-0.5, 0.5, size=current.shape) # if plan was successfully executed, current state should be reported at target if self.group.execute(self.plan(target)): - actual = np.asarray(self.group.get_current_joint_values()) - self.assertTrue(np.allclose(target, actual, atol=1e-4, rtol=0.0)) + actual = np.asarray(self.group.get_current_joint_values()) + self.assertTrue(np.allclose(target, actual, atol=1e-4, rtol=0.0)) # otherwise current state should be still the same else: - actual = np.asarray(self.group.get_current_joint_values()) - self.assertTrue(np.allclose(current, actual, atol=1e-4, rtol=0.0)) + actual = np.asarray(self.group.get_current_joint_values()) + self.assertTrue(np.allclose(current, actual, atol=1e-4, rtol=0.0)) -if __name__ == '__main__': - PKGNAME = 'moveit_ros_planning_interface' - NODENAME = 'moveit_test_robot_state_update' +if __name__ == "__main__": + PKGNAME = "moveit_ros_planning_interface" + NODENAME = "moveit_test_robot_state_update" rospy.init_node(NODENAME) rostest.rosrun(PKGNAME, NODENAME, RobotStateUpdateTest) diff --git a/moveit_ros/planning_interface/test/serialize_msg.py b/moveit_ros/planning_interface/test/serialize_msg.py index 0497d5d9f9..212c0905eb 100644 --- a/moveit_ros/planning_interface/test/serialize_msg.py +++ b/moveit_ros/planning_interface/test/serialize_msg.py @@ -35,17 +35,21 @@ # Author: Bjarne von Horn # -from moveit_ros_planning_interface._moveit_planning_interface_test_serialize_msg_cpp_helper import ByteStringTestHelper +from moveit_ros_planning_interface._moveit_planning_interface_test_serialize_msg_cpp_helper import ( + ByteStringTestHelper, +) from geometry_msgs.msg import Vector3 import unittest try: # Try Python 2.7 behaviour first from StringIO import StringIO + py_version_maj = 2 except ImportError: # Use Python 3.x behaviour as fallback and choose the non-unicode version from io import BytesIO as StringIO + py_version_maj = 3 @@ -98,13 +102,15 @@ def test_rejectIntTuple(self): def test_rejectUnicode(self): with self.assertRaisesRegexp(Exception, "Python argument types in"): - self.helper.compareEmbeddedZeros(u'kdasd') + self.helper.compareEmbeddedZeros(u"kdasd") @unittest.skipIf(py_version_maj == 2, "does not trigger with python 2.7") def test_rejectUnicodeTuple(self): - with self.assertRaisesRegexp(RuntimeError, "Underlying python object is not a Bytes/String instance"): - self.helper.compareVectorTuple((u'kdasd',)) + with self.assertRaisesRegexp( + RuntimeError, "Underlying python object is not a Bytes/String instance" + ): + self.helper.compareVectorTuple((u"kdasd",)) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/moveit_ros/planning_interface/test/test_cleanup.py b/moveit_ros/planning_interface/test/test_cleanup.py index 1567c1ea3c..bb0aad1f72 100755 --- a/moveit_ros/planning_interface/test/test_cleanup.py +++ b/moveit_ros/planning_interface/test/test_cleanup.py @@ -1,5 +1,8 @@ #!/usr/bin/env python import rospy -from moveit_ros_planning_interface._moveit_move_group_interface import MoveGroupInterface +from moveit_ros_planning_interface._moveit_move_group_interface import ( + MoveGroupInterface, +) + group = MoveGroupInterface("manipulator", "robot_description", rospy.get_namespace()) diff --git a/moveit_ros/visualization/setup.py b/moveit_ros/visualization/setup.py index 8b428f692c..65f309f202 100644 --- a/moveit_ros/visualization/setup.py +++ b/moveit_ros/visualization/setup.py @@ -2,6 +2,6 @@ from catkin_pkg.python_setup import generate_distutils_setup d = generate_distutils_setup() -d['packages'] = ['moveit_ros_visualization'] -d['package_dir'] = {'': 'src'} +d["packages"] = ["moveit_ros_visualization"] +d["package_dir"] = {"": "src"} setup(**d) diff --git a/moveit_ros/visualization/src/moveit_ros_visualization/moveitjoy_module.py b/moveit_ros/visualization/src/moveit_ros_visualization/moveitjoy_module.py index 435eb611ff..4476a22dee 100644 --- a/moveit_ros/visualization/src/moveit_ros_visualization/moveitjoy_module.py +++ b/moveit_ros/visualization/src/moveit_ros_visualization/moveitjoy_module.py @@ -54,17 +54,19 @@ from geometry_msgs.msg import PoseStamped from visualization_msgs.msg import InteractiveMarkerInit + def signedSquare(val): - if val > 0: - sign = 1 - else: - sign = -1 - return val * val * sign + if val > 0: + sign = 1 + else: + sign = -1 + return val * val * sign # classes to use joystick of xbox, ps3(wired) and ps3(wireless). -class JoyStatus(): + +class JoyStatus: def __init__(self): self.center = False self.select = False @@ -88,6 +90,7 @@ def __init__(self): self.right_analog_x = 0.0 self.right_analog_y = 0.0 + class XBoxStatus(JoyStatus): def __init__(self, msg): JoyStatus.__init__(self) @@ -165,6 +168,7 @@ def __init__(self, msg): self.right_analog_y = msg.axes[4] self.orig_msg = msg + class PS3Status(JoyStatus): def __init__(self, msg): JoyStatus.__init__(self) @@ -243,6 +247,7 @@ def __init__(self, msg): self.right_analog_y = msg.axes[3] self.orig_msg = msg + class PS3WiredStatus(JoyStatus): def __init__(self, msg): JoyStatus.__init__(self) @@ -321,10 +326,11 @@ def __init__(self, msg): self.right_analog_y = msg.axes[3] self.orig_msg = msg + class PS4Status(JoyStatus): def __init__(self, msg): JoyStatus.__init__(self) - #creating from sensor_msg/Joy + # creating from sensor_msg/Joy if msg.buttons[12] == 1: self.center = True else: @@ -399,10 +405,11 @@ def __init__(self, msg): self.right_analog_y = msg.axes[2] self.orig_msg = msg + class PS4WiredStatus(JoyStatus): def __init__(self, msg): JoyStatus.__init__(self) - #creating from sensor_msg/Joy + # creating from sensor_msg/Joy if msg.buttons[10] == 1: self.center = True else: @@ -478,31 +485,37 @@ def __init__(self, msg): self.orig_msg = msg -class StatusHistory(): - def __init__(self, max_length=10): - self.max_length = max_length - self.buffer = [] - def add(self, status): - self.buffer.append(status) - if len(self.buffer) > self.max_length: - self.buffer = self.buffer[1:self.max_length+1] - def all(self, proc): - for status in self.buffer: - if not proc(status): - return False - return True - def latest(self): - if len(self.buffer) > 0: - return self.buffer[-1] - else: - return None - def length(self): - return len(self.buffer) - def new(self, status, attr): - if len(self.buffer) == 0: - return getattr(status, attr) - else: - return getattr(status, attr) and not getattr(self.latest(), attr) +class StatusHistory: + def __init__(self, max_length=10): + self.max_length = max_length + self.buffer = [] + + def add(self, status): + self.buffer.append(status) + if len(self.buffer) > self.max_length: + self.buffer = self.buffer[1 : self.max_length + 1] + + def all(self, proc): + for status in self.buffer: + if not proc(status): + return False + return True + + def latest(self): + if len(self.buffer) > 0: + return self.buffer[-1] + else: + return None + + def length(self): + return len(self.buffer) + + def new(self, status, attr): + if len(self.buffer) == 0: + return getattr(status, attr) + else: + return getattr(status, attr) and not getattr(self.latest(), attr) + class MoveitJoy: def parseSRDF(self): @@ -510,16 +523,21 @@ def parseSRDF(self): planning_groups = {} for g in ri.get_group_names(): self.planning_groups_tips[g] = ri.get_group_joint_tips(g) - planning_groups[g] = ["/rviz/moveit/move_marker/goal_" + l - for l in self.planning_groups_tips[g]] + planning_groups[g] = [ + "/rviz/moveit/move_marker/goal_" + l + for l in self.planning_groups_tips[g] + ] for name in planning_groups.keys(): if len(planning_groups[name]) == 0: del planning_groups[name] else: print(name, planning_groups[name]) self.planning_groups = planning_groups - self.planning_groups_keys = planning_groups.keys() #we'd like to store the 'order' + self.planning_groups_keys = ( + planning_groups.keys() + ) # we'd like to store the 'order' self.frame_id = ri.get_planning_frame() + def __init__(self): self.initial_poses = {} self.planning_groups_tips = {} @@ -535,18 +553,28 @@ def __init__(self): self.initialize_poses = False self.initialized = False self.parseSRDF() - self.plan_group_pub = rospy.Publisher('/rviz/moveit/select_planning_group', String, queue_size=5) + self.plan_group_pub = rospy.Publisher( + "/rviz/moveit/select_planning_group", String, queue_size=5 + ) self.updatePlanningGroup(0) self.updatePoseTopic(0, False) self.joy_pose_pub = rospy.Publisher("/joy_pose", PoseStamped, queue_size=1) self.plan_pub = rospy.Publisher("/rviz/moveit/plan", Empty, queue_size=5) self.execute_pub = rospy.Publisher("/rviz/moveit/execute", Empty, queue_size=5) - self.update_start_state_pub = rospy.Publisher("/rviz/moveit/update_start_state", Empty, queue_size=5) - self.update_goal_state_pub = rospy.Publisher("/rviz/moveit/update_goal_state", Empty, queue_size=5) - self.interactive_marker_sub = rospy.Subscriber("/rviz_moveit_motion_planning_display/robot_interaction_interactive_marker_topic/update_full", - InteractiveMarkerInit, - self.markerCB, queue_size=1) + self.update_start_state_pub = rospy.Publisher( + "/rviz/moveit/update_start_state", Empty, queue_size=5 + ) + self.update_goal_state_pub = rospy.Publisher( + "/rviz/moveit/update_goal_state", Empty, queue_size=5 + ) + self.interactive_marker_sub = rospy.Subscriber( + "/rviz_moveit_motion_planning_display/robot_interaction_interactive_marker_topic/update_full", + InteractiveMarkerInit, + self.markerCB, + queue_size=1, + ) self.sub = rospy.Subscriber("/joy", Joy, self.joyCB, queue_size=1) + def updatePlanningGroup(self, next_index): if next_index >= len(self.planning_groups_keys): self.current_planning_group_index = 0 @@ -556,13 +584,16 @@ def updatePlanningGroup(self, next_index): self.current_planning_group_index = next_index next_planning_group = None try: - next_planning_group = self.planning_groups_keys[self.current_planning_group_index] + next_planning_group = self.planning_groups_keys[ + self.current_planning_group_index + ] except IndexError: - msg = 'Check if you started movegroups. Exiting.' + msg = "Check if you started movegroups. Exiting." rospy.logfatal(msg) raise rospy.ROSInitException(msg) rospy.loginfo("Changed planning group to " + next_planning_group) self.plan_group_pub.publish(next_planning_group) + def updatePoseTopic(self, next_index, wait=True): planning_group = self.planning_groups_keys[self.current_planning_group_index] topics = self.planning_groups[planning_group] @@ -574,11 +605,15 @@ def updatePoseTopic(self, next_index, wait=True): self.current_eef_index = next_index next_topic = topics[self.current_eef_index] - rospy.loginfo("Changed controlled end effector to " + self.planning_groups_tips[planning_group][self.current_eef_index]) + rospy.loginfo( + "Changed controlled end effector to " + + self.planning_groups_tips[planning_group][self.current_eef_index] + ) self.pose_pub = rospy.Publisher(next_topic, PoseStamped, queue_size=5) if wait: self.waitForInitialPose(next_topic) self.current_pose_topic = next_topic + def markerCB(self, msg): try: self.marker_lock.acquire() @@ -591,14 +626,24 @@ def markerCB(self, msg): if marker.header.frame_id != self.frame_id: ps = PoseStamped(header=marker.header, pose=marker.pose) try: - transformed_pose = self.tf_listener.transformPose(self.frame_id, ps) + transformed_pose = self.tf_listener.transformPose( + self.frame_id, ps + ) self.initial_poses[marker.name[3:]] = transformed_pose.pose - except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException, e): + except ( + tf.LookupException, + tf.ConnectivityException, + tf.ExtrapolationException, + e, + ): rospy.logerr("tf error when resolving tf: %s" % e) else: - self.initial_poses[marker.name[3:]] = marker.pose #tf should be resolved + self.initial_poses[ + marker.name[3:] + ] = marker.pose # tf should be resolved finally: self.marker_lock.release() + def waitForInitialPose(self, next_topic, timeout=None): counter = 0 while not rospy.is_shutdown(): @@ -615,11 +660,13 @@ def waitForInitialPose(self, next_topic, timeout=None): return True else: rospy.logdebug(self.initial_poses.keys()) - rospy.loginfo("Waiting for pose topic of '%s' to be initialized", - topic_suffix) + rospy.loginfo( + "Waiting for pose topic of '%s' to be initialized", topic_suffix + ) rospy.sleep(1) finally: self.marker_lock.release() + def joyCB(self, msg): if len(msg.axes) == 27 and len(msg.buttons) == 19: status = PS3WiredStatus(msg) @@ -635,12 +682,16 @@ def joyCB(self, msg): raise Exception("Unknown joystick") self.run(status) self.history.add(status) + def computePoseFromJoy(self, pre_pose, status): new_pose = PoseStamped() new_pose.header.frame_id = self.frame_id new_pose.header.stamp = rospy.Time(0.0) # move in local - dist = status.left_analog_y * status.left_analog_y + status.left_analog_x * status.left_analog_x + dist = ( + status.left_analog_y * status.left_analog_y + + status.left_analog_x * status.left_analog_x + ) scale = 200.0 x_diff = signedSquare(status.left_analog_y) / scale y_diff = signedSquare(status.left_analog_x) / scale @@ -655,15 +706,16 @@ def computePoseFromJoy(self, pre_pose, status): z_scale = 4.0 else: z_scale = 2.0 - local_move = numpy.array((x_diff, y_diff, - z_diff * z_scale, - 1.0)) - q = numpy.array((pre_pose.pose.orientation.x, - pre_pose.pose.orientation.y, - pre_pose.pose.orientation.z, - pre_pose.pose.orientation.w)) - xyz_move = numpy.dot(tf.transformations.quaternion_matrix(q), - local_move) + local_move = numpy.array((x_diff, y_diff, z_diff * z_scale, 1.0)) + q = numpy.array( + ( + pre_pose.pose.orientation.x, + pre_pose.pose.orientation.y, + pre_pose.pose.orientation.z, + pre_pose.pose.orientation.w, + ) + ) + xyz_move = numpy.dot(tf.transformations.quaternion_matrix(q), local_move) new_pose.pose.position.x = pre_pose.pose.position.x + xyz_move[0] new_pose.pose.position.y = pre_pose.pose.position.y + xyz_move[1] new_pose.pose.position.z = pre_pose.pose.position.z + xyz_move[2] @@ -708,17 +760,26 @@ def computePoseFromJoy(self, pre_pose, status): new_pose.pose.orientation.z = new_q[2] new_pose.pose.orientation.w = new_q[3] return new_pose + def run(self, status): if not self.initialized: # when not initialized, we will force to change planning_group while True: self.updatePlanningGroup(self.current_planning_group_index) - planning_group = self.planning_groups_keys[self.current_planning_group_index] + planning_group = self.planning_groups_keys[ + self.current_planning_group_index + ] topics = self.planning_groups[planning_group] next_topic = topics[self.current_eef_index] if not self.waitForInitialPose(next_topic, timeout=3): - rospy.logwarn("Unable to initialize planning group " + planning_group + ". Trying different group.") - rospy.logwarn("Is 'Allow External Comm.' enabled in Rviz? Is the 'Query Goal State' robot enabled?") + rospy.logwarn( + "Unable to initialize planning group " + + planning_group + + ". Trying different group." + ) + rospy.logwarn( + "Is 'Allow External Comm.' enabled in Rviz? Is the 'Query Goal State' robot enabled?" + ) else: rospy.loginfo("Initialized planning group") self.initialized = True @@ -727,15 +788,15 @@ def run(self, status): # Try to initialize with different planning group self.current_planning_group_index += 1 if self.current_planning_group_index >= len(self.planning_groups_keys): - self.current_planning_group_index = 0 # reset loop - if self.history.new(status, "select"): #increment planning group + self.current_planning_group_index = 0 # reset loop + if self.history.new(status, "select"): # increment planning group self.updatePlanningGroup(self.current_planning_group_index + 1) - self.current_eef_index = 0 # force to reset + self.current_eef_index = 0 # force to reset self.updatePoseTopic(self.current_eef_index) return - elif self.history.new(status, "start"): #decrement planning group + elif self.history.new(status, "start"): # decrement planning group self.updatePlanningGroup(self.current_planning_group_index - 1) - self.current_eef_index = 0 # force to reset + self.current_eef_index = 0 # force to reset self.updatePoseTopic(self.current_eef_index) return elif self.history.new(status, "triangle"): @@ -744,11 +805,11 @@ def run(self, status): elif self.history.new(status, "cross"): self.updatePoseTopic(self.current_eef_index - 1) return - elif self.history.new(status, "square"): #plan + elif self.history.new(status, "square"): # plan rospy.loginfo("Plan") self.plan_pub.publish(Empty()) return - elif self.history.new(status, "circle"): #execute + elif self.history.new(status, "circle"): # execute rospy.loginfo("Execute") self.execute_pub.publish(Empty()) return diff --git a/moveit_ros/visualization/test/test_moveit_joy.py b/moveit_ros/visualization/test/test_moveit_joy.py index b3974e8e52..9f36914a73 100755 --- a/moveit_ros/visualization/test/test_moveit_joy.py +++ b/moveit_ros/visualization/test/test_moveit_joy.py @@ -42,8 +42,9 @@ import rostest import os -_PKGNAME = 'moveit_ros_visualization' -_NODENAME = 'test_moveit_joy' +_PKGNAME = "moveit_ros_visualization" +_NODENAME = "test_moveit_joy" + class TestMoveitJoy(unittest.TestCase): def __init__(self, *args, **kwargs): @@ -54,7 +55,8 @@ def test_constructor(self): # However, at least we tested, that MoveitJoy constructor can be called... self.assertRaises(RuntimeError, MoveitJoy) -if __name__ == '__main__': + +if __name__ == "__main__": rospy.init_node(_NODENAME) rostest.rosrun(_PKGNAME, _NODENAME, TestMoveitJoy) # Don't get trapped by https://github.com/ros/ros_comm/issues/870 diff --git a/moveit_ros/warehouse/warehouse/Makefile b/moveit_ros/warehouse/warehouse/Makefile index b75b928f20..bbd3fc6049 100644 --- a/moveit_ros/warehouse/warehouse/Makefile +++ b/moveit_ros/warehouse/warehouse/Makefile @@ -1 +1 @@ -include $(shell rospack find mk)/cmake.mk \ No newline at end of file +include $(shell rospack find mk)/cmake.mk diff --git a/moveit_ros/warehouse/warehouse/src/db_path_config.py b/moveit_ros/warehouse/warehouse/src/db_path_config.py index 7b0cc11e76..15356ea79e 100755 --- a/moveit_ros/warehouse/warehouse/src/db_path_config.py +++ b/moveit_ros/warehouse/warehouse/src/db_path_config.py @@ -4,12 +4,14 @@ # This is used in conjunction with ROS_HOME & roslaunch # to set the default path for database storage -import roslib; roslib.load_manifest('moveit_warehouse') +import roslib + +roslib.load_manifest("moveit_warehouse") import rospy import os -if __name__ == '__main__': - rospy.init_node('moveit_warehouse') +if __name__ == "__main__": + rospy.init_node("moveit_warehouse") path_base = os.getcwd() + "/moveit_warehouse/" - rospy.set_param('~database_path_base', path_base) - rospy.set_param('~default_database', path_base + "default") + rospy.set_param("~database_path_base", path_base) + rospy.set_param("~default_database", path_base + "default") diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo_gazebo.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo_gazebo.launch index 75ea8eb387..e4183aa164 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo_gazebo.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo_gazebo.launch @@ -57,7 +57,7 @@ - + diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/gdb_settings.gdb b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/gdb_settings.gdb index 9eeb4cb95b..1c207c8e0b 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/gdb_settings.gdb +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/gdb_settings.gdb @@ -5,4 +5,4 @@ set breakpoint pending on ## Example break point: -#break trajectory_execution_manager.cpp:228 \ No newline at end of file +#break trajectory_execution_manager.cpp:228 diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/moveit_controller_manager.launch.xml b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/moveit_controller_manager.launch.xml index 833414a345..67cb8aa108 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/moveit_controller_manager.launch.xml +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/moveit_controller_manager.launch.xml @@ -1,6 +1,6 @@ - From 9de7bd25741c4d8b634215be9deeb80cc5187f7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Mon, 26 Apr 2021 15:33:51 +0200 Subject: [PATCH 058/179] use new melodic-devel branch for moveit_resources --- .ci.upstream.rosinstall | 5 ----- .github/workflows/ci.yaml | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) delete mode 100644 .ci.upstream.rosinstall diff --git a/.ci.upstream.rosinstall b/.ci.upstream.rosinstall deleted file mode 100644 index 3680219519..0000000000 --- a/.ci.upstream.rosinstall +++ /dev/null @@ -1,5 +0,0 @@ -# This file is intended for use by CI -- git: - local-name: moveit_resources - uri: https://github.com/ros-planning/moveit_resources.git - version: master diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b56b84f1d5..92f6ac6ed3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -23,7 +23,7 @@ jobs: CATKIN_LINT: true env: DOCKER_IMAGE: moveit/moveit:${{ matrix.env.IMAGE }} - UPSTREAM_WORKSPACE: .ci.upstream.rosinstall + UPSTREAM_WORKSPACE: github:ros-planning/moveit_resources#melodic-devel AFTER_SETUP_UPSTREAM_WORKSPACE: vcs pull $BASEDIR/upstream_ws/src BEFORE_TARGET_TEST_EMBED: ${{ matrix.env.IKFAST_TEST && 'set +u && source moveit_kinematics/test/test_ikfast_plugins.sh && set -u' || '' }} AFTER_RUN_TARGET_TEST: ${{ matrix.env.CCOV && './.ci.prepare_codecov' || '' }} From 460be6b949c1febf3d3e9ad4041604935a3668a8 Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Mon, 26 Apr 2021 16:31:20 -0600 Subject: [PATCH 059/179] Drop Indigo from readme CI table --- README.md | 70 +++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index b8ffdc6312..fcfe9e8a33 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,12 @@ For MoveIt 2.0 development, see [moveit2](https://github.com/ros-planning/moveit ## Continuous Integration Status -service | Indigo | Kinetic | Melodic | Master ----------- | ------ | ------- | ------- | ------ -Travis | [![Build Status](https://travis-ci.com/ros-planning/moveit.svg?branch=indigo-devel)](https://travis-ci.com/ros-planning/moveit/branches) | [![Build Status](https://travis-ci.com/ros-planning/moveit.svg?branch=kinetic-devel)](https://travis-ci.com/ros-planning/moveit/branches) | N/A | N/A | -GitHub | N/A | N/A | [![Format](https://github.com/ros-planning/moveit/actions/workflows/format.yaml/badge.svg?branch=melodic-devel)](https://github.com/ros-planning/moveit/actions/workflows/format.yaml?query=branch%3Amelodic-devel) [![CI](https://github.com/ros-planning/moveit/actions/workflows/ci.yaml/badge.svg?branch=melodic-devel)](https://github.com/ros-planning/moveit/actions/workflows/ci.yaml?query=branch%3Amelodic-devel) | [![Format](https://github.com/ros-planning/moveit/actions/workflows/format.yaml/badge.svg?branch=master)](https://github.com/ros-planning/moveit/actions/workflows/format.yaml?query=branch%3Amaster) [![CI](https://github.com/ros-planning/moveit/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/ros-planning/moveit/actions/workflows/ci.yaml?query=branch%3Amaster) | -build farm | [![Build Status](http://build.ros.org/buildStatus/icon?job=Idev__moveit__ubuntu_trusty_amd64)](http://build.ros.org/job/Idev__moveit__ubuntu_trusty_amd64) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kdev__moveit__ubuntu_xenial_amd64)](http://build.ros.org/job/Kdev__moveit__ubuntu_xenial_amd64) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mdev__moveit__ubuntu_bionic_amd64)](http://build.ros.org/job/Mdev__moveit__ubuntu_bionic_amd64) | N/A | -CodeCov | N/A | N/A | [![codecov](https://codecov.io/gh/ros-planning/moveit/branch/melodic-devel/graph/badge.svg?token=W7uHKcY0ly)](https://codecov.io/gh/ros-planning/moveit) | [![codecov](https://codecov.io/gh/ros-planning/moveit/branch/master/graph/badge.svg?token=W7uHKcY0ly)](https://codecov.io/gh/ros-planning/moveit) | +service | Kinetic | Melodic | Master +---------- | ------- | ------- | ------ +Travis | [![Build Status](https://travis-ci.com/ros-planning/moveit.svg?branch=kinetic-devel)](https://travis-ci.com/ros-planning/moveit/branches) | N/A | N/A | +GitHub | N/A | [![Format](https://github.com/ros-planning/moveit/actions/workflows/format.yaml/badge.svg?branch=melodic-devel)](https://github.com/ros-planning/moveit/actions/workflows/format.yaml?query=branch%3Amelodic-devel) [![CI](https://github.com/ros-planning/moveit/actions/workflows/ci.yaml/badge.svg?branch=melodic-devel)](https://github.com/ros-planning/moveit/actions/workflows/ci.yaml?query=branch%3Amelodic-devel) | [![Format](https://github.com/ros-planning/moveit/actions/workflows/format.yaml/badge.svg?branch=master)](https://github.com/ros-planning/moveit/actions/workflows/format.yaml?query=branch%3Amaster) [![CI](https://github.com/ros-planning/moveit/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/ros-planning/moveit/actions/workflows/ci.yaml?query=branch%3Amaster) | +build farm | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kdev__moveit__ubuntu_xenial_amd64)](http://build.ros.org/job/Kdev__moveit__ubuntu_xenial_amd64) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mdev__moveit__ubuntu_bionic_amd64)](http://build.ros.org/job/Mdev__moveit__ubuntu_bionic_amd64) | N/A | +CodeCov | N/A | [![codecov](https://codecov.io/gh/ros-planning/moveit/branch/melodic-devel/graph/badge.svg?token=W7uHKcY0ly)](https://codecov.io/gh/ros-planning/moveit) | [![codecov](https://codecov.io/gh/ros-planning/moveit/branch/master/graph/badge.svg?token=W7uHKcY0ly)](https://codecov.io/gh/ros-planning/moveit) | ## Docker Containers @@ -33,32 +33,32 @@ CodeCov | N/A | N/A | [![codecov](https://codecov.io/gh/ros-planning/moveit/bran [![Docker Automated build](https://img.shields.io/docker/automated/moveit/moveit.svg?maxAge=2592000)](https://hub.docker.com/r/moveit/moveit/) [![Docker Pulls](https://img.shields.io/docker/pulls/moveit/moveit.svg?maxAge=2592000)](https://hub.docker.com/r/moveit/moveit/) [![Docker Stars](https://img.shields.io/docker/stars/moveit/moveit.svg)](https://registry.hub.docker.com/moveit/moveit/) ## ROS Buildfarm -MoveIt! Package | Indigo Source | Indigo Debian | Kinetic Source | Kinetic Debian | Melodic Source | Melodic Debian ---------------- | ------------- | ------------- | -------------- | -------------- | -------------- | -------------- -moveit | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit__ubuntu_bionic_amd64__binary) -moveit_chomp_optimizer_adapter | | | | | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_chomp_optimizer_adapter__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_chomp_optimizer_adapter__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_chomp_optimizer_adapter__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_chomp_optimizer_adapter__ubuntu_bionic_amd64__binary) -moveit_commander | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_commander__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_commander__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_commander__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_commander__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_commander__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_commander__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_commander__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_commander__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_commander__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_commander__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_commander__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_commander__ubuntu_bionic_amd64__binary) -moveit_controller_manager_example | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_controller_manager_example__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_controller_manager_example__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_controller_manager_example__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_controller_manager_example__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_controller_manager_example__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_controller_manager_example__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_controller_manager_example__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_controller_manager_example__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_controller_manager_example__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_controller_manager_example__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_controller_manager_example__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_controller_manager_example__ubuntu_bionic_amd64__binary) -moveit_core | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_core__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_core__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_core__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_core__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_core__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_core__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_core__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_core__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_core__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_core__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_core__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_core__ubuntu_bionic_amd64__binary) -moveit_experimental | | | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_experimental__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_experimental__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_experimental__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_experimental__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_experimental__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_experimental__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_experimental__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_experimental__ubuntu_bionic_amd64__binary) -moveit_fake_controller_manager | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_fake_controller_manager__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_fake_controller_manager__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_fake_controller_manager__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_fake_controller_manager__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_fake_controller_manager__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_fake_controller_manager__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_fake_controller_manager__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_fake_controller_manager__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_fake_controller_manager__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_fake_controller_manager__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_fake_controller_manager__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_fake_controller_manager__ubuntu_bionic_amd64__binary) -moveit_kinematics | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_kinematics__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_kinematics__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_kinematics__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_kinematics__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_kinematics__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_kinematics__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_kinematics__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_kinematics__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_kinematics__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_kinematics__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_kinematics__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_kinematics__ubuntu_bionic_amd64__binary) -moveit_planners | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_planners__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_planners__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_planners__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_planners__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_planners__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_planners__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_planners__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_planners__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_planners__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_planners__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_planners__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_planners__ubuntu_bionic_amd64__binary) -moveit_planners_chomp | | | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_planners_chomp__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_planners_chomp__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_planners_chomp__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_planners_chomp__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_planners_chomp__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_planners_chomp__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_planners_chomp__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_planners_chomp__ubuntu_bionic_amd64__binary) -moveit_planners_ompl | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_planners_ompl__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_planners_ompl__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_planners_ompl__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_planners_ompl__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_planners_ompl__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_planners_ompl__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_planners_ompl__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_planners_ompl__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_planners_ompl__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_planners_ompl__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_planners_ompl__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_planners_ompl__ubuntu_bionic_amd64__binary) -moveit_plugins | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_plugins__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_plugins__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_plugins__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_plugins__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_plugins__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_plugins__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_plugins__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_plugins__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_plugins__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_plugins__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_plugins__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_plugins__ubuntu_bionic_amd64__binary) -moveit_ros | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_ros__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_ros__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_ros__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_ros__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros__ubuntu_bionic_amd64__binary) -moveit_ros_benchmarks | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_ros_benchmarks__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_ros_benchmarks__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_ros_benchmarks__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_ros_benchmarks__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_benchmarks__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_benchmarks__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_benchmarks__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_benchmarks__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_benchmarks__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_benchmarks__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_benchmarks__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_benchmarks__ubuntu_bionic_amd64__binary) -moveit_ros_control_interface | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_ros_control_interface__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_ros_control_interface__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_ros_control_interface__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_ros_control_interface__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_control_interface__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_control_interface__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_control_interface__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_control_interface__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_control_interface__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_control_interface__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_control_interface__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_control_interface__ubuntu_bionic_amd64__binary) -moveit_ros_manipulation | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_ros_manipulation__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_ros_manipulation__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_ros_manipulation__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_ros_manipulation__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_manipulation__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_manipulation__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_manipulation__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_manipulation__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_manipulation__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_manipulation__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_manipulation__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_manipulation__ubuntu_bionic_amd64__binary) -moveit_ros_move_group | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_ros_move_group__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_ros_move_group__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_ros_move_group__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_ros_move_group__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_move_group__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_move_group__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_move_group__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_move_group__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_move_group__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_move_group__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_move_group__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_move_group__ubuntu_bionic_amd64__binary) -moveit_ros_perception | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_ros_perception__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_ros_perception__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_ros_perception__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_ros_perception__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_perception__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_perception__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_perception__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_perception__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_perception__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_perception__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_perception__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_perception__ubuntu_bionic_amd64__binary) -moveit_ros_planning | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_ros_planning__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_ros_planning__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_ros_planning__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_ros_planning__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_planning__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_planning__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_planning__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_planning__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_planning__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_planning__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_planning__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_planning__ubuntu_bionic_amd64__binary) -moveit_ros_planning_interface | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_ros_planning_interface__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_ros_planning_interface__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_ros_planning_interface__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_ros_planning_interface__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_planning_interface__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_planning_interface__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_planning_interface__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_planning_interface__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_planning_interface__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_planning_interface__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_planning_interface__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_planning_interface__ubuntu_bionic_amd64__binary) -moveit_ros_robot_interaction | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_ros_robot_interaction__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_ros_robot_interaction__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_ros_robot_interaction__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_ros_robot_interaction__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_robot_interaction__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_robot_interaction__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_robot_interaction__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_robot_interaction__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_robot_interaction__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_robot_interaction__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_robot_interaction__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_robot_interaction__ubuntu_bionic_amd64__binary) -moveit_ros_visualization | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_ros_visualization__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_ros_visualization__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_ros_visualization__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_ros_visualization__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_visualization__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_visualization__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_visualization__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_visualization__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_visualization__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_visualization__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_visualization__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_visualization__ubuntu_bionic_amd64__binary) -moveit_ros_warehouse | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_ros_warehouse__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_ros_warehouse__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_ros_warehouse__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_ros_warehouse__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_warehouse__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_warehouse__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_warehouse__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_warehouse__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_warehouse__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_warehouse__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_warehouse__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_warehouse__ubuntu_bionic_amd64__binary) -moveit_runtime | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_runtime__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_runtime__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_runtime__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_runtime__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_runtime__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_runtime__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_runtime__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_runtime__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_runtime__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_runtime__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_runtime__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_runtime__ubuntu_bionic_amd64__binary) -moveit_setup_assistant | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_setup_assistant__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_setup_assistant__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_setup_assistant__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_setup_assistant__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_setup_assistant__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_setup_assistant__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_setup_assistant__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_setup_assistant__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_setup_assistant__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_setup_assistant__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_setup_assistant__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_setup_assistant__ubuntu_bionic_amd64__binary) -moveit_simple_controller_manager | [![Build Status](http://build.ros.org/buildStatus/icon?job=Isrc_uT__moveit_simple_controller_manager__ubuntu_trusty__source)](http://build.ros.org/view/Isrc_uT/job/Isrc_uT__moveit_simple_controller_manager__ubuntu_trusty__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ibin_uT64__moveit_simple_controller_manager__ubuntu_trusty_amd64__binary)](http://build.ros.org/view/Ibin_uT64/job/Ibin_uT64__moveit_simple_controller_manager__ubuntu_trusty_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_simple_controller_manager__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_simple_controller_manager__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_simple_controller_manager__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_simple_controller_manager__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_simple_controller_manager__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_simple_controller_manager__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_simple_controller_manager__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_simple_controller_manager__ubuntu_bionic_amd64__binary) -chomp_motion_planner | | | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__chomp_motion_planner__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__chomp_motion_planner__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__chomp_motion_planner__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__chomp_motion_planner__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__chomp_motion_planner__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__chomp_motion_planner__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__chomp_motion_planner__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__chomp_motion_planner__ubuntu_bionic_amd64__binary) +MoveIt! Package | Kinetic Source | Kinetic Debian | Melodic Source | Melodic Debian +--------------- | -------------- | -------------- | -------------- | -------------- +moveit | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit__ubuntu_bionic_amd64__binary) +moveit_chomp_optimizer_adapter | | | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_chomp_optimizer_adapter__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_chomp_optimizer_adapter__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_chomp_optimizer_adapter__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_chomp_optimizer_adapter__ubuntu_bionic_amd64__binary) +moveit_commander | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_commander__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_commander__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_commander__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_commander__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_commander__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_commander__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_commander__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_commander__ubuntu_bionic_amd64__binary) +moveit_controller_manager_example | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_controller_manager_example__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_controller_manager_example__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_controller_manager_example__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_controller_manager_example__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_controller_manager_example__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_controller_manager_example__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_controller_manager_example__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_controller_manager_example__ubuntu_bionic_amd64__binary) +moveit_core | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_core__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_core__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_core__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_core__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_core__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_core__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_core__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_core__ubuntu_bionic_amd64__binary) +moveit_experimental | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_experimental__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_experimental__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_experimental__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_experimental__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_experimental__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_experimental__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_experimental__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_experimental__ubuntu_bionic_amd64__binary) +moveit_fake_controller_manager | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_fake_controller_manager__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_fake_controller_manager__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_fake_controller_manager__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_fake_controller_manager__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_fake_controller_manager__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_fake_controller_manager__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_fake_controller_manager__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_fake_controller_manager__ubuntu_bionic_amd64__binary) +moveit_kinematics | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_kinematics__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_kinematics__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_kinematics__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_kinematics__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_kinematics__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_kinematics__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_kinematics__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_kinematics__ubuntu_bionic_amd64__binary) +moveit_planners | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_planners__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_planners__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_planners__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_planners__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_planners__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_planners__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_planners__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_planners__ubuntu_bionic_amd64__binary) +moveit_planners_chomp | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_planners_chomp__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_planners_chomp__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_planners_chomp__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_planners_chomp__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_planners_chomp__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_planners_chomp__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_planners_chomp__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_planners_chomp__ubuntu_bionic_amd64__binary) +moveit_planners_ompl | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_planners_ompl__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_planners_ompl__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_planners_ompl__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_planners_ompl__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_planners_ompl__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_planners_ompl__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_planners_ompl__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_planners_ompl__ubuntu_bionic_amd64__binary) +moveit_plugins | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_plugins__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_plugins__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_plugins__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_plugins__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_plugins__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_plugins__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_plugins__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_plugins__ubuntu_bionic_amd64__binary) +moveit_ros | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros__ubuntu_bionic_amd64__binary) +moveit_ros_benchmarks | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_benchmarks__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_benchmarks__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_benchmarks__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_benchmarks__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_benchmarks__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_benchmarks__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_benchmarks__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_benchmarks__ubuntu_bionic_amd64__binary) +moveit_ros_control_interface | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_control_interface__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_control_interface__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_control_interface__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_control_interface__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_control_interface__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_control_interface__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_control_interface__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_control_interface__ubuntu_bionic_amd64__binary) +moveit_ros_manipulation | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_manipulation__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_manipulation__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_manipulation__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_manipulation__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_manipulation__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_manipulation__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_manipulation__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_manipulation__ubuntu_bionic_amd64__binary) +moveit_ros_move_group | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_move_group__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_move_group__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_move_group__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_move_group__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_move_group__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_move_group__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_move_group__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_move_group__ubuntu_bionic_amd64__binary) +moveit_ros_perception | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_perception__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_perception__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_perception__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_perception__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_perception__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_perception__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_perception__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_perception__ubuntu_bionic_amd64__binary) +moveit_ros_planning | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_planning__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_planning__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_planning__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_planning__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_planning__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_planning__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_planning__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_planning__ubuntu_bionic_amd64__binary) +moveit_ros_planning_interface | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_planning_interface__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_planning_interface__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_planning_interface__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_planning_interface__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_planning_interface__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_planning_interface__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_planning_interface__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_planning_interface__ubuntu_bionic_amd64__binary) +moveit_ros_robot_interaction | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_robot_interaction__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_robot_interaction__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_robot_interaction__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_robot_interaction__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_robot_interaction__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_robot_interaction__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_robot_interaction__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_robot_interaction__ubuntu_bionic_amd64__binary) +moveit_ros_visualization | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_visualization__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_visualization__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_visualization__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_visualization__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_visualization__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_visualization__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_visualization__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_visualization__ubuntu_bionic_amd64__binary) +moveit_ros_warehouse | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_ros_warehouse__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_ros_warehouse__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_ros_warehouse__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_ros_warehouse__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_ros_warehouse__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_ros_warehouse__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_ros_warehouse__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_ros_warehouse__ubuntu_bionic_amd64__binary) +moveit_runtime | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_runtime__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_runtime__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_runtime__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_runtime__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_runtime__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_runtime__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_runtime__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_runtime__ubuntu_bionic_amd64__binary) +moveit_setup_assistant | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_setup_assistant__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_setup_assistant__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_setup_assistant__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_setup_assistant__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_setup_assistant__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_setup_assistant__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_setup_assistant__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_setup_assistant__ubuntu_bionic_amd64__binary) +moveit_simple_controller_manager | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__moveit_simple_controller_manager__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__moveit_simple_controller_manager__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__moveit_simple_controller_manager__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__moveit_simple_controller_manager__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__moveit_simple_controller_manager__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__moveit_simple_controller_manager__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__moveit_simple_controller_manager__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__moveit_simple_controller_manager__ubuntu_bionic_amd64__binary) +chomp_motion_planner | [![Build Status](http://build.ros.org/buildStatus/icon?job=Ksrc_uX__chomp_motion_planner__ubuntu_xenial__source)](http://build.ros.org/view/Ksrc_uX/job/Ksrc_uX__chomp_motion_planner__ubuntu_xenial__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Kbin_uX64__chomp_motion_planner__ubuntu_xenial_amd64__binary)](http://build.ros.org/view/Kbin_uX64/job/Kbin_uX64__chomp_motion_planner__ubuntu_xenial_amd64__binary) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Msrc_uB__chomp_motion_planner__ubuntu_bionic__source)](http://build.ros.org/view/Msrc_uB/job/Msrc_uB__chomp_motion_planner__ubuntu_bionic__source) | [![Build Status](http://build.ros.org/buildStatus/icon?job=Mbin_uB64__chomp_motion_planner__ubuntu_bionic_amd64__binary)](http://build.ros.org/view/Mbin_uB64/job/Mbin_uB64__chomp_motion_planner__ubuntu_bionic_amd64__binary) From 7c2d606fcd264a4dd763dc6dd8c394177b9a837b Mon Sep 17 00:00:00 2001 From: Jafar Abdi Date: Fri, 30 Apr 2021 22:37:15 +0300 Subject: [PATCH 060/179] Simplify logic in PSM (#2632) (#2637) Co-authored-by: Rojas Rafael --- .../src/collision_plugin_loader.cpp | 4 ++++ .../src/planning_scene_monitor.cpp | 9 ++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/moveit_ros/planning/collision_plugin_loader/src/collision_plugin_loader.cpp b/moveit_ros/planning/collision_plugin_loader/src/collision_plugin_loader.cpp index 0a08260f49..c4141111a5 100644 --- a/moveit_ros/planning/collision_plugin_loader/src/collision_plugin_loader.cpp +++ b/moveit_ros/planning/collision_plugin_loader/src/collision_plugin_loader.cpp @@ -36,6 +36,7 @@ #include #include +static const std::string LOGNAME = "collision_detection"; namespace collision_detection { class CollisionPluginLoader::CollisionPluginLoaderImpl @@ -108,7 +109,10 @@ bool CollisionPluginLoader::activate(const std::string& name, const planning_sce void CollisionPluginLoader::setupScene(ros::NodeHandle& nh, const planning_scene::PlanningScenePtr& scene) { if (!scene) + { + ROS_WARN_NAMED(LOGNAME, "Cannot setup scene, PlanningScenePtr is null."); return; + } std::string param_name; std::string collision_detector_name; diff --git a/moveit_ros/planning/planning_scene_monitor/src/planning_scene_monitor.cpp b/moveit_ros/planning/planning_scene_monitor/src/planning_scene_monitor.cpp index 2c7c116780..b8245766ac 100644 --- a/moveit_ros/planning/planning_scene_monitor/src/planning_scene_monitor.cpp +++ b/moveit_ros/planning/planning_scene_monitor/src/planning_scene_monitor.cpp @@ -190,15 +190,11 @@ void PlanningSceneMonitor::initialize(const planning_scene::PlanningScenePtr& sc { robot_model_ = rm_loader_->getModel(); scene_ = scene; - collision_loader_.setupScene(nh_, scene_); - scene_const_ = scene_; if (!scene_) { try { scene_.reset(new planning_scene::PlanningScene(rm_loader_->getModel())); - collision_loader_.setupScene(nh_, scene_); - scene_const_ = scene_; configureCollisionMatrix(scene_); configureDefaultPadding(); @@ -220,11 +216,14 @@ void PlanningSceneMonitor::initialize(const planning_scene::PlanningScenePtr& sc { ROS_ERROR_NAMED(LOGNAME, "Configuration of planning scene failed"); scene_.reset(); - scene_const_ = scene_; } } + // scene_const_ is set regardless if scene_ is null or not + scene_const_ = scene_; if (scene_) { + // The scene_ is loaded on the collision loader only if it was correctly instantiated + collision_loader_.setupScene(nh_, scene_); scene_->setAttachedBodyUpdateCallback( boost::bind(&PlanningSceneMonitor::currentStateAttachedBodyUpdateCallback, this, _1, _2)); scene_->setCollisionObjectUpdateCallback( From 89210ed0f0fce829f05ea355dd929aaa9c40804b Mon Sep 17 00:00:00 2001 From: Jere Liukkonen Date: Sat, 31 Oct 2020 07:06:36 -0600 Subject: [PATCH 061/179] Fix pose tracking race condition (#2395) * Stop rewriting target_pose_ timestamps. It is caller's responsibility to ensure timestamp is correct and recent enough. * Prevent data races on target_pose_ by limiting access to it with a mutex. * Re-arrange part in targetPoseCallback function to make the callback lightweight when the target pose is in planning frame. * Small improvements to comments and code readability. * Set mutex as mutable. * Fix formatting. * Improve comment re. angle-axis PID tracking * Implement resetTargetPose() and add it to test & example * Add mutex protection to resetTargetPose() * Add missing semicolon and fix formatting. Co-authored-by: AndyZe --- .../include/moveit_servo/pose_tracking.h | 4 + .../pose_tracking_example.cpp | 4 + moveit_ros/moveit_servo/src/pose_tracking.cpp | 91 +++++++++++-------- .../moveit_servo/test/pose_tracking_test.cpp | 5 + 4 files changed, 64 insertions(+), 40 deletions(-) diff --git a/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h b/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h index d76c58481b..ad391b158b 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h @@ -114,6 +114,9 @@ class PoseTracking */ bool getCommandFrameTransform(geometry_msgs::TransformStamped& transform); + /** \brief Re-initialize the target pose to an empty message. Can be used to reset motion between waypoints. */ + void resetTargetPose(); + // moveit_servo::Servo instance. Public so we can access member functions like setPaused() std::unique_ptr servo_; @@ -170,6 +173,7 @@ class PoseTracking Eigen::Isometry3d command_frame_transform_; ros::Time command_frame_transform_stamp_; geometry_msgs::PoseStamped target_pose_; + mutable std::mutex target_pose_mtx_; // Subscribe to target pose ros::Subscriber target_pose_sub_; diff --git a/moveit_ros/moveit_servo/src/cpp_interface_example/pose_tracking_example.cpp b/moveit_ros/moveit_servo/src/cpp_interface_example/pose_tracking_example.cpp index b5ec8d176f..3657d52864 100644 --- a/moveit_ros/moveit_servo/src/cpp_interface_example/pose_tracking_example.cpp +++ b/moveit_ros/moveit_servo/src/cpp_interface_example/pose_tracking_example.cpp @@ -127,6 +127,10 @@ int main(int argc, char** argv) // Modify it a little bit target_pose.pose.position.x += 0.1; + // resetTargetPose() can be used to clear the target pose and wait for a new one, e.g. when moving between multiple + // waypoints + tracker.resetTargetPose(); + // Publish target pose target_pose.header.stamp = ros::Time::now(); target_pose_pub.publish(target_pose); diff --git a/moveit_ros/moveit_servo/src/pose_tracking.cpp b/moveit_ros/moveit_servo/src/pose_tracking.cpp index 065e547f8e..e8dcff87b1 100644 --- a/moveit_ros/moveit_servo/src/pose_tracking.cpp +++ b/moveit_ros/moveit_servo/src/pose_tracking.cpp @@ -79,12 +79,9 @@ PoseTracking::PoseTracking(const ros::NodeHandle& nh, PoseTrackingStatusCode PoseTracking::moveToPose(const Eigen::Vector3d& positional_tolerance, const double angular_tolerance, const double target_pose_timeout) { - // Roll back the target pose timestamp to ensure we wait for a new target pose message - target_pose_.header.stamp = ros::Time::now() - ros::Duration(2 * target_pose_timeout); - // Wait a bit for a target pose message to arrive. // The target pose may get updated by new messages as the robot moves (in a callback function). - ros::Time start_time = ros::Time::now(); + const ros::Time start_time = ros::Time::now(); while ((!haveRecentTargetPose(target_pose_timeout) || !haveRecentEndEffectorPose(target_pose_timeout)) && ((ros::Time::now() - start_time).toSec() < target_pose_timeout)) { @@ -94,36 +91,34 @@ PoseTrackingStatusCode PoseTracking::moveToPose(const Eigen::Vector3d& positiona } ros::Duration(0.001).sleep(); } + if (!haveRecentTargetPose(target_pose_timeout)) { ROS_ERROR_STREAM_NAMED(LOGNAME, "The target pose was not updated recently. Aborting."); return PoseTrackingStatusCode::NO_RECENT_TARGET_POSE; } - while (ros::ok()) + // Continue sending PID controller output to Servo until one of the following conditions is met: + // - Goal tolerance is satisfied + // - Target pose becomes outdated + // - Command frame transform becomes outdated + // - Another thread requested a stop + while (ros::ok() && !satisfiesPoseTolerance(positional_tolerance, angular_tolerance)) { - // Check for reasons to stop: - // - Goal tolerance is satisfied - // - Timeout - // - Another thread requested a stop - // - PID controllers aren't initialized - if (satisfiesPoseTolerance(positional_tolerance, angular_tolerance)) - { - break; - } - // Attempt to update robot pose if (servo_->getCommandFrameTransform(command_frame_transform_)) { command_frame_transform_stamp_ = ros::Time::now(); } + // Check that end-effector pose (command frame transform) is recent enough. if (!haveRecentEndEffectorPose(target_pose_timeout)) { ROS_ERROR_STREAM_NAMED(LOGNAME, "The end effector pose was not updated in time. Aborting."); doPostMotionReset(); return PoseTrackingStatusCode::NO_RECENT_END_EFFECTOR_POSE; } + if (stop_requested_) { ROS_INFO_STREAM_NAMED(LOGNAME, "Halting servo motion, a stop was requested."); @@ -210,6 +205,7 @@ void PoseTracking::initializePID(const PIDConfig& pid_config, std::vector lock(target_pose_mtx_); return ((ros::Time::now() - target_pose_.header.stamp).toSec() < timespan); } @@ -220,59 +216,67 @@ bool PoseTracking::haveRecentEndEffectorPose(const double timespan) bool PoseTracking::satisfiesPoseTolerance(const Eigen::Vector3d& positional_tolerance, const double angular_tolerance) { + std::lock_guard lock(target_pose_mtx_); double x_error = target_pose_.pose.position.x - command_frame_transform_.translation()(0); double y_error = target_pose_.pose.position.y - command_frame_transform_.translation()(1); double z_error = target_pose_.pose.position.z - command_frame_transform_.translation()(2); - return (fabs(x_error) < positional_tolerance(0)) && (fabs(y_error) < positional_tolerance(1)) && - (fabs(z_error) < positional_tolerance(2) && fabs(angular_error_) < angular_tolerance); + return ((std::abs(x_error) < positional_tolerance(0)) && (std::abs(y_error) < positional_tolerance(1)) && + (std::abs(z_error) < positional_tolerance(2)) && (std::abs(angular_error_) < angular_tolerance)); } void PoseTracking::targetPoseCallback(const geometry_msgs::PoseStampedConstPtr& msg) { - // Transform to planning frame + std::lock_guard lock(target_pose_mtx_); target_pose_ = *msg; - geometry_msgs::TransformStamped target_to_planning_frame; + + // If the target pose is not defined in planning frame, transform the target pose. if (target_pose_.header.frame_id != planning_frame_) { try { - target_to_planning_frame = transform_buffer_.lookupTransform(planning_frame_, target_pose_.header.frame_id, - ros::Time(0), ros::Duration(0.1)); + geometry_msgs::TransformStamped target_to_planning_frame = transform_buffer_.lookupTransform( + planning_frame_, target_pose_.header.frame_id, ros::Time(0), ros::Duration(0.1)); + tf2::doTransform(target_pose_, target_pose_, target_to_planning_frame); } - catch (tf2::TransformException& ex) + catch (const tf2::TransformException& ex) { - ROS_WARN_NAMED(LOGNAME, "%s", ex.what()); + ROS_WARN_STREAM_NAMED(LOGNAME, ex.what()); return; } - tf2::doTransform(target_pose_, target_pose_, target_to_planning_frame); } - target_pose_.header.stamp = ros::Time::now(); } geometry_msgs::TwistStampedConstPtr PoseTracking::calculateTwistCommand() { // use the shared pool to create a message more efficiently auto msg = moveit::util::make_shared_from_pool(); - msg->header.frame_id = target_pose_.header.frame_id; // Get twist components from PID controllers geometry_msgs::Twist& twist = msg->twist; + Eigen::Quaterniond q_desired; + + // Scope mutex locking only to operations which require access to target pose. + { + std::lock_guard lock(target_pose_mtx_); + msg->header.frame_id = target_pose_.header.frame_id; + + // Position + twist.linear.x = cartesian_position_pids_[0].computeCommand( + target_pose_.pose.position.x - command_frame_transform_.translation()(0), loop_rate_.expectedCycleTime()); + twist.linear.y = cartesian_position_pids_[1].computeCommand( + target_pose_.pose.position.y - command_frame_transform_.translation()(1), loop_rate_.expectedCycleTime()); + twist.linear.z = cartesian_position_pids_[2].computeCommand( + target_pose_.pose.position.z - command_frame_transform_.translation()(2), loop_rate_.expectedCycleTime()); + + // Orientation algorithm: + // - Find the orientation error as a quaternion: q_error = q_desired * q_current ^ -1 + // - Use the angle-axis PID controller to calculate an angular rate + // - Convert to angular velocity for the TwistStamped message + q_desired = Eigen::Quaterniond(target_pose_.pose.orientation.w, target_pose_.pose.orientation.x, + target_pose_.pose.orientation.y, target_pose_.pose.orientation.z); + } - // Position - twist.linear.x = cartesian_position_pids_[0].computeCommand( - target_pose_.pose.position.x - command_frame_transform_.translation()(0), loop_rate_.expectedCycleTime()); - twist.linear.y = cartesian_position_pids_[1].computeCommand( - target_pose_.pose.position.y - command_frame_transform_.translation()(1), loop_rate_.expectedCycleTime()); - twist.linear.z = cartesian_position_pids_[2].computeCommand( - target_pose_.pose.position.z - command_frame_transform_.translation()(2), loop_rate_.expectedCycleTime()); - - // Orientation algorithm: - // - Find the orientation error as a quaternion: q_error = q_desired * q_current ^ -1 - // - Use the quaternion PID controllers to calculate a quaternion rate, q_error_dot - // - Convert to angular velocity for the TwistStamped message - Eigen::Quaterniond q_desired(target_pose_.pose.orientation.w, target_pose_.pose.orientation.x, - target_pose_.pose.orientation.y, target_pose_.pose.orientation.z); Eigen::Quaterniond q_current(command_frame_transform_.rotation()); Eigen::Quaterniond q_error = q_desired * q_current.inverse(); @@ -345,6 +349,13 @@ void PoseTracking::getPIDErrors(double& x_error, double& y_error, double& z_erro cartesian_orientation_pids_.at(0).getCurrentPIDErrors(&orientation_error, &dummy1, &dummy2); } +void PoseTracking::resetTargetPose() +{ + std::lock_guard lock(target_pose_mtx_); + target_pose_ = geometry_msgs::PoseStamped(); + target_pose_.header.stamp = ros::Time(0); +} + bool PoseTracking::getCommandFrameTransform(geometry_msgs::TransformStamped& transform) { return servo_->getCommandFrameTransform(transform); diff --git a/moveit_ros/moveit_servo/test/pose_tracking_test.cpp b/moveit_ros/moveit_servo/test/pose_tracking_test.cpp index 765094899d..5dab02713f 100644 --- a/moveit_ros/moveit_servo/test/pose_tracking_test.cpp +++ b/moveit_ros/moveit_servo/test/pose_tracking_test.cpp @@ -141,6 +141,11 @@ TEST_F(PoseTrackingFixture, OutgoingMsgTest) }); ros::Duration(ROS_PUB_SUB_DELAY).sleep(); + + // resetTargetPose() can be used to clear the target pose and wait for a new one, e.g. when moving between multiple + // waypoints + tracker_->resetTargetPose(); + tracker_->moveToPose(translation_tolerance_, ROTATION_TOLERANCE, 1 /* target pose timeout */); target_pub_thread.join(); From 40fa98c365b9cd916c10fcec37499b372d211e4d Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 4 Nov 2020 19:10:32 +0100 Subject: [PATCH 062/179] Fix QObject::connect: Cannot queue arguments of type 'QVector' (#2392) --- .../planning_scene_display.h | 1 + .../src/planning_scene_display.cpp | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/moveit_ros/visualization/planning_scene_rviz_plugin/include/moveit/planning_scene_rviz_plugin/planning_scene_display.h b/moveit_ros/visualization/planning_scene_rviz_plugin/include/moveit/planning_scene_rviz_plugin/planning_scene_display.h index 57b474eea8..43d87c855b 100644 --- a/moveit_ros/visualization/planning_scene_rviz_plugin/include/moveit/planning_scene_rviz_plugin/planning_scene_display.h +++ b/moveit_ros/visualization/planning_scene_rviz_plugin/include/moveit/planning_scene_rviz_plugin/planning_scene_display.h @@ -131,6 +131,7 @@ private Q_SLOTS: void changedSceneDisplayTime(); void changedOctreeRenderMode(); void changedOctreeColorMode(); + void setSceneName(const QString& name); protected Q_SLOTS: virtual void changedAttachedBodyColor(); diff --git a/moveit_ros/visualization/planning_scene_rviz_plugin/src/planning_scene_display.cpp b/moveit_ros/visualization/planning_scene_rviz_plugin/src/planning_scene_display.cpp index f644c424bb..21917663b3 100644 --- a/moveit_ros/visualization/planning_scene_rviz_plugin/src/planning_scene_display.cpp +++ b/moveit_ros/visualization/planning_scene_rviz_plugin/src/planning_scene_display.cpp @@ -583,14 +583,17 @@ void PlanningSceneDisplay::sceneMonitorReceivedUpdate( void PlanningSceneDisplay::onSceneMonitorReceivedUpdate( planning_scene_monitor::PlanningSceneMonitor::SceneUpdateType update_type) { - bool old_state = scene_name_property_->blockSignals(true); getPlanningSceneRW()->getCurrentStateNonConst().update(); - scene_name_property_->setStdString(getPlanningSceneRO()->getName()); - scene_name_property_->blockSignals(old_state); - + QMetaObject::invokeMethod(this, "setSceneName", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(getPlanningSceneRO()->getName()))); planning_scene_needs_render_ = true; } +void PlanningSceneDisplay::setSceneName(const QString& name) +{ + scene_name_property_->setString(name); +} + void PlanningSceneDisplay::onEnable() { Display::onEnable(); From e25bf6dcee2d4fd8475ca3cf17f770da03d1f0bc Mon Sep 17 00:00:00 2001 From: "David V. Lu!!" Date: Tue, 10 Nov 2020 16:04:04 -0500 Subject: [PATCH 063/179] Fix empty sequence in moveit_setup_assistant (#2406) --- moveit_setup_assistant/src/tools/moveit_config_data.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/moveit_setup_assistant/src/tools/moveit_config_data.cpp b/moveit_setup_assistant/src/tools/moveit_config_data.cpp index e5d52a82f9..e12c5bc5f1 100644 --- a/moveit_setup_assistant/src/tools/moveit_config_data.cpp +++ b/moveit_setup_assistant/src/tools/moveit_config_data.cpp @@ -574,6 +574,10 @@ bool MoveItConfigData::outputFakeControllersYAML(const std::string& file_path) emitter << YAML::Newline; emitter << YAML::Comment(" - group: " + default_group_name) << YAML::Newline; emitter << YAML::Comment(" pose: home") << YAML::Newline; + + // Add empty list for valid yaml + emitter << YAML::BeginSeq; + emitter << YAML::EndSeq; } emitter << YAML::EndMap; From 881d4d8c3fdf970d7dcec0fdbcbc76f4bf772fea Mon Sep 17 00:00:00 2001 From: AndyZe Date: Wed, 4 Nov 2020 13:08:20 -0600 Subject: [PATCH 064/179] Move timer initialization down to fix potential race condition --- moveit_ros/moveit_servo/src/servo_calcs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index 8e34341380..bbec0c173c 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -182,13 +182,13 @@ void ServoCalcs::start() initial_joint_trajectory->points.push_back(point); last_sent_command_ = initial_joint_trajectory; - timer_ = nh_.createTimer(period_, &ServoCalcs::run, this); - current_state_ = planning_scene_monitor_->getStateMonitor()->getCurrentState(); tf_moveit_to_ee_frame_ = current_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * current_state_->getGlobalLinkTransform(parameters_.ee_frame_name); tf_moveit_to_robot_cmd_frame_ = current_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * current_state_->getGlobalLinkTransform(parameters_.robot_link_command_frame); + + timer_ = nh_.createTimer(period_, &ServoCalcs::run, this); } void ServoCalcs::run(const ros::TimerEvent& timer_event) From 41874cd624d1e27ac94888fa0e6a307070518d70 Mon Sep 17 00:00:00 2001 From: Thomas G Date: Sat, 14 Nov 2020 00:12:11 +0000 Subject: [PATCH 065/179] Changed processing_thread_ spin to use std::make_unique instead of new (#2412) --- moveit_core/background_processing/src/background_processing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moveit_core/background_processing/src/background_processing.cpp b/moveit_core/background_processing/src/background_processing.cpp index 8b9e8f66e3..f1fcba275e 100644 --- a/moveit_core/background_processing/src/background_processing.cpp +++ b/moveit_core/background_processing/src/background_processing.cpp @@ -46,7 +46,7 @@ BackgroundProcessing::BackgroundProcessing() // spin a thread that will process user events run_processing_thread_ = true; processing_ = false; - processing_thread_.reset(new boost::thread(boost::bind(&BackgroundProcessing::processingThread, this))); + processing_thread_ = std::make_unique(boost::bind(&BackgroundProcessing::processingThread, this)); } BackgroundProcessing::~BackgroundProcessing() From 664d9c30dda646ddcb9ada369b9a494079094dd9 Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Mon, 16 Nov 2020 11:43:01 -0700 Subject: [PATCH 066/179] [feature] Low latency mode (#2401) Co-authored-by: AndyZe --- moveit_ros/moveit_servo/CMakeLists.txt | 10 + .../config/ur_simulated_config.yaml | 1 + .../include/moveit_servo/servo_calcs.h | 31 ++- .../include/moveit_servo/servo_parameters.h | 1 + moveit_ros/moveit_servo/src/servo.cpp | 13 +- moveit_ros/moveit_servo/src/servo_calcs.cpp | 133 ++++++++++--- .../test/config/servo_settings.yaml | 1 + .../config/servo_settings_low_latency.yaml | 68 +++++++ .../test/servo_low_latency_test.cpp | 185 ++++++++++++++++++ .../test/servo_low_latency_test.test | 18 ++ 10 files changed, 420 insertions(+), 41 deletions(-) create mode 100644 moveit_ros/moveit_servo/test/config/servo_settings_low_latency.yaml create mode 100644 moveit_ros/moveit_servo/test/servo_low_latency_test.cpp create mode 100644 moveit_ros/moveit_servo/test/servo_low_latency_test.test diff --git a/moveit_ros/moveit_servo/CMakeLists.txt b/moveit_ros/moveit_servo/CMakeLists.txt index e2562ea35c..585d660f4c 100644 --- a/moveit_ros/moveit_servo/CMakeLists.txt +++ b/moveit_ros/moveit_servo/CMakeLists.txt @@ -175,6 +175,16 @@ if(CATKIN_ENABLE_TESTING) ${catkin_LIBRARIES} ) + # low_latency + add_rostest_gtest(servo_low_latency_test + test/servo_low_latency_test.test + test/servo_low_latency_test.cpp + ) + target_link_libraries(servo_low_latency_test + ${SERVO_LIB_NAME} + ${catkin_LIBRARIES} + ) + # pose_tracking add_rostest_gtest(pose_tracking_test test/pose_tracking_test.test diff --git a/moveit_ros/moveit_servo/config/ur_simulated_config.yaml b/moveit_ros/moveit_servo/config/ur_simulated_config.yaml index 59b6599e5d..21a2c6aecd 100644 --- a/moveit_ros/moveit_servo/config/ur_simulated_config.yaml +++ b/moveit_ros/moveit_servo/config/ur_simulated_config.yaml @@ -15,6 +15,7 @@ low_pass_filter_coeff: 2. # Larger --> trust the filtered data more, trust the ## Properties of outgoing commands publish_period: 0.008 # 1/Nominal publish rate [seconds] +low_latency_mode: false # Set this to true to publish as soon as an incoming Twist command is received (publish_period is ignored) # What type of topic does your robot driver expect? # Currently supported are std_msgs/Float64MultiArray (for ros_control JointGroupVelocityController or JointGroupPositionController) diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h index c92171b179..055335e3f6 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h @@ -39,7 +39,9 @@ #pragma once // C++ +#include #include +#include // ROS #include @@ -69,10 +71,7 @@ class ServoCalcs ServoCalcs(ros::NodeHandle& nh, ServoParameters& parameters, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor); - ~ServoCalcs() - { - timer_.stop(); - } + ~ServoCalcs(); /** \brief Start the timer where we do work and publish outputs */ void start(); @@ -106,8 +105,14 @@ class ServoCalcs void changeRobotLinkCommandFrame(const std::string& new_command_frame); private: - /** \brief Timer method */ - void run(const ros::TimerEvent& timer_event); + /** \brief Run the main calculation loop */ + void mainCalcLoop(); + + /** \brief Do calculations for a single iteration. Publish one outgoing command */ + void calculateSingleIteration(); + + /** \brief Stop the currently running thread */ + void stop(); /** \brief Do servoing calculations for Cartesian twist commands. */ bool cartesianServoCalcs(geometry_msgs::TwistStamped& cmd, trajectory_msgs::JointTrajectory& joint_trajectory); @@ -257,8 +262,6 @@ class ServoCalcs trajectory_msgs::JointTrajectoryConstPtr last_sent_command_; // ROS - ros::Timer timer_; - ros::Duration period_; ros::Subscriber joint_state_sub_; ros::Subscriber twist_stamped_sub_; ros::Subscriber joint_cmd_sub_; @@ -270,6 +273,10 @@ class ServoCalcs ros::ServiceServer control_dimensions_server_; ros::ServiceServer reset_servo_status_; + // Main tracking / result publisher loop + std::thread thread_; + bool stop_requested_; + // Status StatusCode status_ = StatusCode::NO_WARNING; bool paused_ = false; @@ -292,8 +299,8 @@ class ServoCalcs // The dimesions to control. In the command frame. [x, y, z, roll, pitch, yaw] std::array control_dimensions_ = { { true, true, true, true, true, true } }; - // latest_state_mutex_ is used to protect the state below it - mutable std::mutex latest_state_mutex_; + // input_mutex_ is used to protect the state below it + mutable std::mutex input_mutex_; Eigen::Isometry3d tf_moveit_to_robot_cmd_frame_; Eigen::Isometry3d tf_moveit_to_ee_frame_; geometry_msgs::TwistStampedConstPtr latest_twist_stamped_; @@ -302,5 +309,9 @@ class ServoCalcs ros::Time latest_joint_command_stamp_ = ros::Time(0.); bool latest_nonzero_twist_stamped_ = false; bool latest_nonzero_joint_cmd_ = false; + + // input condition variable used for low latency mode + std::condition_variable input_cv_; + bool new_input_cmd_ = false; }; } // namespace moveit_servo diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo_parameters.h b/moveit_ros/moveit_servo/include/moveit_servo/servo_parameters.h index 45b208db8e..14d993cc71 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo_parameters.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo_parameters.h @@ -71,6 +71,7 @@ struct ServoParameters bool publish_joint_positions; bool publish_joint_velocities; bool publish_joint_accelerations; + bool low_latency_mode; // Collision checking bool check_collisions; std::string collision_check_type; diff --git a/moveit_ros/moveit_servo/src/servo.cpp b/moveit_ros/moveit_servo/src/servo.cpp index b35267cc5b..aba61fc1fe 100644 --- a/moveit_ros/moveit_servo/src/servo.cpp +++ b/moveit_ros/moveit_servo/src/servo.cpp @@ -136,7 +136,7 @@ bool Servo::readParameters() // 'collision_proximity_threshold' parameter was removed, replaced with separate self- and scene-collision proximity // thresholds // TODO(JStech): remove this deprecation warning in ROS Noetic; simplify error case handling - if (nh_.hasParam("collision_proximity_threshold") && + if (nh.hasParam("collision_proximity_threshold") && rosparam_shortcuts::get(LOGNAME, nh, "collision_proximity_threshold", collision_proximity_threshold)) { ROS_WARN_NAMED(LOGNAME, "'collision_proximity_threshold' parameter is deprecated, and has been replaced by separate" @@ -170,6 +170,17 @@ bool Servo::readParameters() error += !rosparam_shortcuts::get(LOGNAME, nh, "warning_topic", parameters_.status_topic); } + if (nh.hasParam("low_latency_mode")) + { + error += !rosparam_shortcuts::get(LOGNAME, nh, "low_latency_mode", parameters_.low_latency_mode); + } + else + { + ROS_WARN_NAMED(LOGNAME, "'low_latency_mode' is a new parameter that runs servo calc immediately after receiving " + "input. Setting to the default value of false."); + parameters_.low_latency_mode = false; + } + rosparam_shortcuts::shutdownIfError(LOGNAME, error); // Input checking diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index bbec0c173c..e94800d9d7 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -86,7 +86,7 @@ geometry_msgs::TransformStamped convertIsometryToTransform(const Eigen::Isometry // Constructor for the class that handles servoing calculations ServoCalcs::ServoCalcs(ros::NodeHandle& nh, ServoParameters& parameters, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor) - : nh_(nh), parameters_(parameters), planning_scene_monitor_(planning_scene_monitor), period_(parameters.publish_period) + : nh_(nh), parameters_(parameters), planning_scene_monitor_(planning_scene_monitor), stop_requested_(true) { // MoveIt Setup current_state_ = planning_scene_monitor_->getStateMonitor()->getCurrentState(); @@ -150,8 +150,16 @@ ServoCalcs::ServoCalcs(ros::NodeHandle& nh, ServoParameters& parameters, tf_moveit_to_robot_cmd_frame_ = empty_matrix; } +ServoCalcs::~ServoCalcs() +{ + stop(); +} + void ServoCalcs::start() { + // Stop the thread if we are currently running + stop(); + // We will update last_sent_command_ every time we start servo auto initial_joint_trajectory = moveit::util::make_shared_from_pool(); @@ -188,19 +196,78 @@ void ServoCalcs::start() tf_moveit_to_robot_cmd_frame_ = current_state_->getGlobalLinkTransform(parameters_.planning_frame).inverse() * current_state_->getGlobalLinkTransform(parameters_.robot_link_command_frame); - timer_ = nh_.createTimer(period_, &ServoCalcs::run, this); + stop_requested_ = false; + thread_ = std::thread([this] { mainCalcLoop(); }); + new_input_cmd_ = false; } -void ServoCalcs::run(const ros::TimerEvent& timer_event) +void ServoCalcs::stop() { - // Log warning when the last loop duration was longer than the period - if (timer_event.profile.last_duration.toSec() > period_.toSec()) + // Request stop + stop_requested_ = true; + + // Notify condition variable in case the thread is blocked on it { - ROS_WARN_STREAM_THROTTLE_NAMED(ROS_LOG_THROTTLE_PERIOD, LOGNAME, - "last_duration: " << timer_event.profile.last_duration.toSec() << " (" - << period_.toSec() << ")"); + // scope so the mutex is unlocked after so the thread can continue + // and therefore be joinable + const std::lock_guard lock(input_mutex_); + new_input_cmd_ = false; + input_cv_.notify_all(); + } + + // Join the thread + if (thread_.joinable()) + { + thread_.join(); + } +} + +void ServoCalcs::mainCalcLoop() +{ + ros::Rate rate(1.0 / parameters_.publish_period); + + while (ros::ok() && !stop_requested_) + { + // lock the input state mutex + std::unique_lock input_lock(input_mutex_); + + // low latency mode + if (parameters_.low_latency_mode) + { + input_cv_.wait(input_lock, [this] { return (new_input_cmd_ || stop_requested_); }); + + // break out of the loop if stop was requested + if (stop_requested_) + break; + } + + // reset new_input_cmd_ flag + new_input_cmd_ = false; + + // run servo calcs + const auto start_time = ros::Time::now(); + calculateSingleIteration(); + const auto run_duration = ros::Time::now() - start_time; + + // Log warning when the run duration was longer than the period + if (run_duration.toSec() > parameters_.publish_period) + { + ROS_WARN_STREAM_THROTTLE_NAMED(ROS_LOG_THROTTLE_PERIOD, LOGNAME, + "run_duration: " << run_duration.toSec() << " (" << parameters_.publish_period + << ")"); + } + + // normal mode, unlock input mutex and wait for the period of the loop + if (!parameters_.low_latency_mode) + { + input_lock.unlock(); + rate.sleep(); + } } +} +void ServoCalcs::calculateSingleIteration() +{ // Publish status each loop iteration auto status_msg = moveit::util::make_shared_from_pool(); status_msg->data = static_cast(status_); @@ -213,22 +280,20 @@ void ServoCalcs::run(const ros::TimerEvent& timer_event) // Update from latest state current_state_ = planning_scene_monitor_->getStateMonitor()->getCurrentState(); - { - const std::lock_guard lock(latest_state_mutex_); - if (latest_twist_stamped_) - twist_stamped_cmd_ = *latest_twist_stamped_; - if (latest_joint_cmd_) - joint_servo_cmd_ = *latest_joint_cmd_; - - // Check for stale cmds - twist_command_is_stale_ = - ((ros::Time::now() - latest_twist_command_stamp_) >= ros::Duration(parameters_.incoming_command_timeout)); - joint_command_is_stale_ = - ((ros::Time::now() - latest_joint_command_stamp_) >= ros::Duration(parameters_.incoming_command_timeout)); - - have_nonzero_twist_stamped_ = latest_nonzero_twist_stamped_; - have_nonzero_joint_command_ = latest_nonzero_joint_cmd_; - } + + if (latest_twist_stamped_) + twist_stamped_cmd_ = *latest_twist_stamped_; + if (latest_joint_cmd_) + joint_servo_cmd_ = *latest_joint_cmd_; + + // Check for stale cmds + twist_command_is_stale_ = + ((ros::Time::now() - latest_twist_command_stamp_) >= ros::Duration(parameters_.incoming_command_timeout)); + joint_command_is_stale_ = + ((ros::Time::now() - latest_joint_command_stamp_) >= ros::Duration(parameters_.incoming_command_timeout)); + + have_nonzero_twist_stamped_ = latest_nonzero_twist_stamped_; + have_nonzero_joint_command_ = latest_nonzero_joint_cmd_; // Get the transform from MoveIt planning frame to servoing command frame // Calculate this transform to ensure it is available via C++ API @@ -980,7 +1045,7 @@ void ServoCalcs::removeDimension(Eigen::MatrixXd& jacobian, Eigen::VectorXd& del bool ServoCalcs::getCommandFrameTransform(Eigen::Isometry3d& transform) { - const std::lock_guard lock(latest_state_mutex_); + const std::lock_guard lock(input_mutex_); transform = tf_moveit_to_robot_cmd_frame_; // All zeros means the transform wasn't initialized, so return false @@ -989,7 +1054,7 @@ bool ServoCalcs::getCommandFrameTransform(Eigen::Isometry3d& transform) bool ServoCalcs::getCommandFrameTransform(geometry_msgs::TransformStamped& transform) { - const std::lock_guard lock(latest_state_mutex_); + const std::lock_guard lock(input_mutex_); // All zeros means the transform wasn't initialized, so return false if (tf_moveit_to_robot_cmd_frame_.matrix().isZero(0)) { @@ -1003,7 +1068,7 @@ bool ServoCalcs::getCommandFrameTransform(geometry_msgs::TransformStamped& trans bool ServoCalcs::getEEFrameTransform(Eigen::Isometry3d& transform) { - const std::lock_guard lock(latest_state_mutex_); + const std::lock_guard lock(input_mutex_); transform = tf_moveit_to_ee_frame_; // All zeros means the transform wasn't initialized, so return false @@ -1012,7 +1077,7 @@ bool ServoCalcs::getEEFrameTransform(Eigen::Isometry3d& transform) bool ServoCalcs::getEEFrameTransform(geometry_msgs::TransformStamped& transform) { - const std::lock_guard lock(latest_state_mutex_); + const std::lock_guard lock(input_mutex_); // All zeros means the transform wasn't initialized, so return false if (tf_moveit_to_ee_frame_.matrix().isZero(0)) { @@ -1025,22 +1090,30 @@ bool ServoCalcs::getEEFrameTransform(geometry_msgs::TransformStamped& transform) void ServoCalcs::twistStampedCB(const geometry_msgs::TwistStampedConstPtr& msg) { - const std::lock_guard lock(latest_state_mutex_); + const std::lock_guard lock(input_mutex_); latest_twist_stamped_ = msg; latest_nonzero_twist_stamped_ = isNonZero(*latest_twist_stamped_); if (msg->header.stamp != ros::Time(0.)) latest_twist_command_stamp_ = msg->header.stamp; + + // notify that we have a new input + new_input_cmd_ = true; + input_cv_.notify_all(); } void ServoCalcs::jointCmdCB(const control_msgs::JointJogConstPtr& msg) { - const std::lock_guard lock(latest_state_mutex_); + const std::lock_guard lock(input_mutex_); latest_joint_cmd_ = msg; latest_nonzero_joint_cmd_ = isNonZero(*latest_joint_cmd_); if (msg->header.stamp != ros::Time(0.)) latest_joint_command_stamp_ = msg->header.stamp; + + // notify that we have a new input + new_input_cmd_ = true; + input_cv_.notify_all(); } void ServoCalcs::collisionVelocityScaleCB(const std_msgs::Float64ConstPtr& msg) diff --git a/moveit_ros/moveit_servo/test/config/servo_settings.yaml b/moveit_ros/moveit_servo/test/config/servo_settings.yaml index 802aeadca2..b081f28c73 100644 --- a/moveit_ros/moveit_servo/test/config/servo_settings.yaml +++ b/moveit_ros/moveit_servo/test/config/servo_settings.yaml @@ -14,6 +14,7 @@ scale: low_pass_filter_coeff: 2. # Larger --> trust the filtered data more, trust the measurements less. ## Properties of outgoing commands +low_latency_mode: false # Set this to true to tie the output rate to the input rate publish_period: 0.01 # 1/Nominal publish rate [seconds] # What type of topic does your robot driver expect? diff --git a/moveit_ros/moveit_servo/test/config/servo_settings_low_latency.yaml b/moveit_ros/moveit_servo/test/config/servo_settings_low_latency.yaml new file mode 100644 index 0000000000..b470e02ac2 --- /dev/null +++ b/moveit_ros/moveit_servo/test/config/servo_settings_low_latency.yaml @@ -0,0 +1,68 @@ +############################################### +# Modify all parameters related to servoing here +############################################### +use_gazebo: false # Whether the robot is started in a Gazebo simulation environment + +## Properties of incoming commands +command_in_type: "speed_units" # "unitless"> in the range [-1:1], as if from joystick. "speed_units"> cmds are in m/s and rad/s +scale: + # Scale parameters are only used if command_in_type=="unitless" + linear: 0.003 # Max linear velocity. Meters per publish_period. Unit is [m/s]. Only used for Cartesian commands. + rotational: 0.006 # Max angular velocity. Rads per publish_period. Unit is [rad/s]. Only used for Cartesian commands. + # Max joint angular/linear velocity. Rads or Meters per publish period. Only used for joint commands on joint_command_in_topic. + joint: 0.01 +low_pass_filter_coeff: 2. # Larger --> trust the filtered data more, trust the measurements less. + +## Properties of outgoing commands +low_latency_mode: true # Set this to true to tie the output rate to the input rate +publish_period: 0.01 # 1/Nominal publish rate [seconds] + +# What type of topic does your robot driver expect? +# Currently supported are std_msgs/Float64MultiArray (for ros_control JointGroupVelocityController or JointGroupPositionController) +# or trajectory_msgs/JointTrajectory (for Universal Robots and other non-ros_control robots) +command_out_type: trajectory_msgs/JointTrajectory + +# What to publish? Can save some bandwidth as most robots only require positions or velocities +publish_joint_positions: true +publish_joint_velocities: false +publish_joint_accelerations: false + +## MoveIt properties +move_group_name: panda_arm # Often 'manipulator' or 'arm' +planning_frame: panda_link0 # The MoveIt planning frame. Often 'panda_link0' or 'world' + +## Other frames +ee_frame_name: panda_link7 # The name of the end effector link, used to return the EE pose +robot_link_command_frame: panda_link0 # commands must be given in the frame of a robot link. Usually either the base or end effector + +## Stopping behaviour +incoming_command_timeout: 1 # Stop servoing if X seconds elapse without a new command +# If 0, republish commands forever even if the robot is stationary. Otherwise, specify num. to publish. +# Important because ROS may drop some messages and we need the robot to halt reliably. +num_outgoing_halt_msgs_to_publish: 1 + +## Configure handling of singularities and joint limits +lower_singularity_threshold: 30 # Start decelerating when the condition number hits this (close to singularity) +hard_stop_singularity_threshold: 45 # Stop when the condition number hits this +joint_limit_margin: 0.1 # added as a buffer to joint limits [radians]. If moving quickly, make this larger. + +## Topic names +cartesian_command_in_topic: servo_server/delta_twist_cmds # Topic for incoming Cartesian twist commands +joint_command_in_topic: servo_server/delta_joint_cmds # Topic for incoming joint angle commands +joint_topic: joint_states +status_topic: servo_server/status # Publish status to this topic +command_out_topic: servo_server/command # Publish outgoing commands here + +## Collision checking for the entire robot body +check_collisions: true # Check collisions? +collision_check_rate: 5 # [Hz] Collision-checking can easily bog down a CPU if done too often. +# Two collision check algorithms are available: +# "threshold_distance" begins slowing down when nearer than a specified distance. Good if you want to tune collision thresholds manually. +# "stop_distance" stops if a collision is nearer than the worst-case stopping distance and the distance is decreasing. Requires joint acceleration limits +collision_check_type: stop_distance +# Parameters for "threshold_distance"-type collision checking +self_collision_proximity_threshold: 0.01 # Start decelerating when a collision is this far [m] +scene_collision_proximity_threshold: 0.03 # Start decelerating when a collision is this far [m] +# Parameters for "stop_distance"-type collision checking +collision_distance_safety_factor: 1000 # Must be >= 1. A large safety factor is recommended to account for latency +min_allowable_collision_distance: 0.01 # Stop if a collision is closer than this [m] diff --git a/moveit_ros/moveit_servo/test/servo_low_latency_test.cpp b/moveit_ros/moveit_servo/test/servo_low_latency_test.cpp new file mode 100644 index 0000000000..011e7bab1b --- /dev/null +++ b/moveit_ros/moveit_servo/test/servo_low_latency_test.cpp @@ -0,0 +1,185 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2020, PickNik LLC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of PickNik LLC 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: Tyler Weaver + Desc: Test for the low latency mode of servo +*/ + +// C++ +#include + +// ROS +#include + +// Testing +#include + +// Servo +#include +#include + +static const std::string LOGNAME = "servo_low_latency_test"; + +namespace moveit_servo +{ +class ServoFixture : public ::testing::Test +{ +public: + void SetUp() override + { + // Wait for several key topics / parameters + ros::topic::waitForMessage("/joint_states"); + while (!nh_.hasParam("/robot_description") && ros::ok()) + { + ros::Duration(0.1).sleep(); + } + + // Load the planning scene monitor + planning_scene_monitor_ = std::make_shared("robot_description"); + planning_scene_monitor_->startSceneMonitor(); + planning_scene_monitor_->startStateMonitor(); + planning_scene_monitor_->startWorldGeometryMonitor( + planning_scene_monitor::PlanningSceneMonitor::DEFAULT_COLLISION_OBJECT_TOPIC, + planning_scene_monitor::PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_WORLD_TOPIC, + false /* skip octomap monitor */); + + // Create moveit_servo + servo_ = std::make_shared(nh_, planning_scene_monitor_); + } + void TearDown() override + { + } + +protected: + ros::NodeHandle nh_{ "~" }; + planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_; + moveit_servo::ServoPtr servo_; +}; // class ServoFixture + +TEST_F(ServoFixture, SendTwistStampedTest) +{ + servo_->start(); + + auto parameters = servo_->getParameters(); + + // count trajectory messages sent by servo + size_t received_count = 0; + boost::function traj_callback = + [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& /*msg*/) { ++received_count; }; + auto traj_sub = nh_.subscribe(parameters.command_out_topic, 1, traj_callback); + + // Create publisher to send servo commands + auto twist_stamped_pub = nh_.advertise(parameters.cartesian_command_in_topic, 1); + + constexpr double test_duration = 1.0; + const double publish_period = parameters.publish_period; + const size_t num_commands = static_cast(test_duration / publish_period); + + // Set the rate differently from the publish period from the parameters to show that + // the number of outputs is set by the number of commands sent and not the rate they are sent. + ros::Rate publish_rate(2. / publish_period); + + // Send a few Cartesian velocity commands + for (size_t i = 0; i < num_commands && ros::ok(); ++i) + { + auto msg = moveit::util::make_shared_from_pool(); + msg->header.stamp = ros::Time::now(); + msg->header.frame_id = "panda_link0"; + msg->twist.angular.y = 1.0; + + // Send the message + twist_stamped_pub.publish(msg); + publish_rate.sleep(); + } + + EXPECT_GT(received_count, num_commands - 20); + EXPECT_GT(received_count, (unsigned)0); + EXPECT_LT(received_count, num_commands + 20); + servo_->setPaused(true); +} + +TEST_F(ServoFixture, SendJointServoTest) +{ + servo_->start(); + + auto parameters = servo_->getParameters(); + + // count trajectory messages sent by servo + size_t received_count = 0; + boost::function traj_callback = + [&received_count](const trajectory_msgs::JointTrajectoryConstPtr& /*msg*/) { ++received_count; }; + auto traj_sub = nh_.subscribe(parameters.command_out_topic, 1, traj_callback); + + // Create publisher to send servo commands + auto joint_servo_pub = nh_.advertise(parameters.joint_command_in_topic, 1); + + constexpr double test_duration = 1.0; + const double publish_period = parameters.publish_period; + const size_t num_commands = static_cast(test_duration / publish_period); + + // Set the rate differently from the publish period from the parameters to show that + // the number of outputs is set by the number of commands sent and not the rate they are sent. + ros::Rate publish_rate(2. / publish_period); + + // Send a few joint velocity commands + for (size_t i = 0; i < num_commands && ros::ok(); ++i) + { + auto msg = moveit::util::make_shared_from_pool(); + msg->header.stamp = ros::Time::now(); + msg->header.frame_id = "panda_link3"; + msg->velocities.push_back(0.1); + + // Send the message + joint_servo_pub.publish(msg); + publish_rate.sleep(); + } + + EXPECT_GT(received_count, num_commands - 20); + EXPECT_GT(received_count, (unsigned)0); + EXPECT_LT(received_count, num_commands + 20); + servo_->setPaused(true); +} +} // namespace moveit_servo + +int main(int argc, char** argv) +{ + ros::init(argc, argv, LOGNAME); + testing::InitGoogleTest(&argc, argv); + + ros::AsyncSpinner spinner(8); + spinner.start(); + + int result = RUN_ALL_TESTS(); + return result; +} diff --git a/moveit_ros/moveit_servo/test/servo_low_latency_test.test b/moveit_ros/moveit_servo/test/servo_low_latency_test.test new file mode 100644 index 0000000000..6df90be617 --- /dev/null +++ b/moveit_ros/moveit_servo/test/servo_low_latency_test.test @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + From d90acb32d3f27d893bc69252430361e4cc09822f Mon Sep 17 00:00:00 2001 From: Stuart Anderson <57372215+stuart-fb@users.noreply.github.com> Date: Wed, 18 Nov 2020 09:05:36 -0500 Subject: [PATCH 067/179] Fix OrientationConstraint::decide (#2414) * Fix OrientationConstraint::decide * Add new test case for OrientationConstraintsSimple * Add comments for clarity --- .../kinematic_constraints/src/kinematic_constraint.cpp | 7 ++++--- .../kinematic_constraints/test/test_constraints.cpp | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/moveit_core/kinematic_constraints/src/kinematic_constraint.cpp b/moveit_core/kinematic_constraints/src/kinematic_constraint.cpp index 847cb84b73..a924c627f8 100644 --- a/moveit_core/kinematic_constraints/src/kinematic_constraint.cpp +++ b/moveit_core/kinematic_constraints/src/kinematic_constraint.cpp @@ -615,9 +615,10 @@ ConstraintEvaluationResult OrientationConstraint::decide(const robot_state::Robo diff.rotation().eulerAngles(0, 1, 2); // 0,1,2 corresponds to XYZ, the convention used in sampling constraints } - xyz(0) = std::min(fabs(xyz(0)), boost::math::constants::pi() - fabs(xyz(0))); - xyz(1) = std::min(fabs(xyz(1)), boost::math::constants::pi() - fabs(xyz(1))); - xyz(2) = std::min(fabs(xyz(2)), boost::math::constants::pi() - fabs(xyz(2))); + // Account for angle wrapping + xyz(0) = std::min(fabs(xyz(0)), boost::math::constants::two_pi() - fabs(xyz(0))); + xyz(1) = std::min(fabs(xyz(1)), boost::math::constants::two_pi() - fabs(xyz(1))); + xyz(2) = std::min(fabs(xyz(2)), boost::math::constants::two_pi() - fabs(xyz(2))); bool result = xyz(2) < absolute_z_axis_tolerance_ + std::numeric_limits::epsilon() && xyz(1) < absolute_y_axis_tolerance_ + std::numeric_limits::epsilon() && xyz(0) < absolute_x_axis_tolerance_ + std::numeric_limits::epsilon(); diff --git a/moveit_core/kinematic_constraints/test/test_constraints.cpp b/moveit_core/kinematic_constraints/test/test_constraints.cpp index 4c6cd14eba..1817847bb3 100644 --- a/moveit_core/kinematic_constraints/test/test_constraints.cpp +++ b/moveit_core/kinematic_constraints/test/test_constraints.cpp @@ -40,6 +40,7 @@ #include #include #include +#include class LoadPlanningModelsPr2 : public testing::Test { @@ -652,6 +653,12 @@ TEST_F(LoadPlanningModelsPr2, OrientationConstraintsSimple) robot_state.setVariablePositions(jvals); robot_state.update(); EXPECT_FALSE(oc.decide(robot_state).satisfied); + + // rotation by pi does not wrap to zero + jvals["r_wrist_roll_joint"] = boost::math::constants::pi(); + robot_state.setVariablePositions(jvals); + robot_state.update(); + EXPECT_FALSE(oc.decide(robot_state).satisfied); } TEST_F(LoadPlanningModelsPr2, VisibilityConstraintsSimple) From 1fb9d83bd0715e6b4c4997e46685257cf289ab07 Mon Sep 17 00:00:00 2001 From: Nathan Brooks Date: Fri, 20 Nov 2020 12:38:53 -0700 Subject: [PATCH 068/179] Prevent moveit_servo transforms between fixed frames from causing timeout (#2418) --- moveit_ros/moveit_servo/src/pose_tracking.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/moveit_ros/moveit_servo/src/pose_tracking.cpp b/moveit_ros/moveit_servo/src/pose_tracking.cpp index e8dcff87b1..c51a54f75a 100644 --- a/moveit_ros/moveit_servo/src/pose_tracking.cpp +++ b/moveit_ros/moveit_servo/src/pose_tracking.cpp @@ -238,6 +238,9 @@ void PoseTracking::targetPoseCallback(const geometry_msgs::PoseStampedConstPtr& geometry_msgs::TransformStamped target_to_planning_frame = transform_buffer_.lookupTransform( planning_frame_, target_pose_.header.frame_id, ros::Time(0), ros::Duration(0.1)); tf2::doTransform(target_pose_, target_pose_, target_to_planning_frame); + + // Prevent doTransform from copying a stamp of 0, which will cause the haveRecentTargetPose check to fail servo motions + target_pose_.header.stamp = ros::Time::now(); } catch (const tf2::TransformException& ex) { From 52225bb7658c68431396db9f682ac1a5a8ed858e Mon Sep 17 00:00:00 2001 From: archonixX <72344256+archonixX@users.noreply.github.com> Date: Thu, 26 Nov 2020 00:59:33 -0700 Subject: [PATCH 069/179] docker-source: support running clang-tidy (#2430) --- .docker/source/Dockerfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.docker/source/Dockerfile b/.docker/source/Dockerfile index 5cd789d830..ece82c5072 100644 --- a/.docker/source/Dockerfile +++ b/.docker/source/Dockerfile @@ -24,7 +24,11 @@ RUN \ ENV PYTHONIOENCODING UTF-8 RUN cd .. && \ - catkin config --extend /opt/ros/$ROS_DISTRO --install --cmake-args -DCMAKE_BUILD_TYPE=Release && \ + catkin config --extend /opt/ros/$ROS_DISTRO --install --cmake-args -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON && \ # Status rate is limited so that just enough info is shown to keep Docker from timing out, # but not too much such that the Docker log gets too long (another form of timeout) catkin build --limit-status-rate 0.001 --no-notify + +# Environment variable used in instructions on moveit.ros.org website for running clang-tidy +ENV CATKIN_WS /root/ws_moveit + From 081fe956ce457f1e177aac748529c596d69d7f76 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Tue, 8 Dec 2020 22:17:32 +0100 Subject: [PATCH 070/179] Upgrade cmake_minimum_required to 3.1 (#2453) to suppress CMP0048 warning --- moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt | 2 +- .../pilz_industrial_motion_planner_testutils/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt b/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt index 1fd8466ab2..05ed96c791 100644 --- a/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt +++ b/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.3) +cmake_minimum_required(VERSION 3.1.3) project(pilz_industrial_motion_planner) ## Add support for C++11, supported in ROS Kinetic and newer diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/CMakeLists.txt b/moveit_planners/pilz_industrial_motion_planner_testutils/CMakeLists.txt index fc692408c9..3e8b72f629 100644 --- a/moveit_planners/pilz_industrial_motion_planner_testutils/CMakeLists.txt +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.3) +cmake_minimum_required(VERSION 3.1.3) project(pilz_industrial_motion_planner_testutils) ## Add support for C++11, supported in ROS Kinetic and newer From c4f8fd4f5e48a5ddee0a320b3009b63dd54ba21a Mon Sep 17 00:00:00 2001 From: JafarAbdi Date: Fri, 27 Nov 2020 23:19:50 +0300 Subject: [PATCH 071/179] Fix validation of orientation constraints (#2434) --- .docker/source/Dockerfile | 1 - .../kinematic_constraints/CMakeLists.txt | 3 + .../src/kinematic_constraint.cpp | 92 ++++++- .../test/test_orientation_constraints.cpp | 244 ++++++++++++++++++ 4 files changed, 327 insertions(+), 13 deletions(-) create mode 100644 moveit_core/kinematic_constraints/test/test_orientation_constraints.cpp diff --git a/.docker/source/Dockerfile b/.docker/source/Dockerfile index ece82c5072..7e2b50802f 100644 --- a/.docker/source/Dockerfile +++ b/.docker/source/Dockerfile @@ -31,4 +31,3 @@ RUN cd .. && \ # Environment variable used in instructions on moveit.ros.org website for running clang-tidy ENV CATKIN_WS /root/ws_moveit - diff --git a/moveit_core/kinematic_constraints/CMakeLists.txt b/moveit_core/kinematic_constraints/CMakeLists.txt index 619f7a4229..31198de4aa 100644 --- a/moveit_core/kinematic_constraints/CMakeLists.txt +++ b/moveit_core/kinematic_constraints/CMakeLists.txt @@ -20,4 +20,7 @@ install(DIRECTORY include/ DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}) if(CATKIN_ENABLE_TESTING) catkin_add_gtest(test_constraints test/test_constraints.cpp) target_link_libraries(test_constraints moveit_test_utils ${MOVEIT_LIB_NAME}) + + catkin_add_gtest(test_orientation_constraints test/test_orientation_constraints.cpp) + target_link_libraries(test_orientation_constraints moveit_test_utils ${MOVEIT_LIB_NAME}) endif() diff --git a/moveit_core/kinematic_constraints/src/kinematic_constraint.cpp b/moveit_core/kinematic_constraints/src/kinematic_constraint.cpp index a924c627f8..749cc61e35 100644 --- a/moveit_core/kinematic_constraints/src/kinematic_constraint.cpp +++ b/moveit_core/kinematic_constraints/src/kinematic_constraint.cpp @@ -58,7 +58,59 @@ static double normalizeAngle(double angle) return v; } -KinematicConstraint::KinematicConstraint(const robot_model::RobotModelConstPtr& model) +// Normalizes an angle to the interval [-pi, +pi] and then take the absolute value +// The returned values will be in the following range [0, +pi] +static double normalizeAbsoluteAngle(const double angle) +{ + const double normalized_angle = std::fmod(std::abs(angle), 2 * M_PI); + return std::min(2 * M_PI - normalized_angle, normalized_angle); +} + +/** + * This's copied from + * https://gitlab.com/libeigen/eigen/-/blob/master/unsupported/Eigen/src/EulerAngles/EulerSystem.h#L187 + * Return the intrinsic Roll-Pitch-Yaw euler angles given the input rotation matrix and boolean indicating whether the + * there's a singularity in the input rotation matrix (true: the input rotation matrix don't have a singularity, false: + * the input rotation matrix have a singularity) The returned angles are in the ranges [-pi:pi]x[-pi/2:pi/2]x[-pi:pi] + */ +template +std::tuple::Scalar, 3, 1>, bool> +CalcEulerAngles(const Eigen::MatrixBase& R) +{ + using std::atan2; + using std::sqrt; + EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived, 3, 3) + using Index = EIGEN_DEFAULT_DENSE_INDEX_TYPE; + using Scalar = typename Eigen::MatrixBase::Scalar; + const Index i = 0; + const Index j = 1; + const Index k = 2; + Eigen::Matrix res; + const Scalar rsum = sqrt((R(i, i) * R(i, i) + R(i, j) * R(i, j) + R(j, k) * R(j, k) + R(k, k) * R(k, k)) / 2); + res[1] = atan2(R(i, k), rsum); + // There is a singularity when cos(beta) == 0 + if (rsum > 4 * Eigen::NumTraits::epsilon()) + { // cos(beta) != 0 + res[0] = atan2(-R(j, k), R(k, k)); + res[2] = atan2(-R(i, j), R(i, i)); + return { res, true }; + } + else if (R(i, k) > 0) + { // cos(beta) == 0 and sin(beta) == 1 + const Scalar spos = R(j, i) + R(k, j); // 2*sin(alpha + gamma) + const Scalar cpos = R(j, j) - R(k, i); // 2*cos(alpha + gamma) + res[0] = atan2(spos, cpos); + res[2] = 0; + return { res, false }; + } // cos(beta) == 0 and sin(beta) == -1 + const Scalar sneg = R(k, j) - R(j, i); // 2*sin(alpha + gamma) + const Scalar cneg = R(j, j) + R(k, i); // 2*cos(alpha + gamma) + res[0] = atan2(sneg, cneg); + res[2] = 0; + return { res, false }; +} + +KinematicConstraint::KinematicConstraint(const moveit::core::RobotModelConstPtr& model) : type_(UNKNOWN_CONSTRAINT), robot_model_(model), constraint_weight_(std::numeric_limits::epsilon()) { } @@ -600,25 +652,41 @@ ConstraintEvaluationResult OrientationConstraint::decide(const robot_state::Robo if (!link_model_) return ConstraintEvaluationResult(true, 0.0); - Eigen::Vector3d xyz; + std::tuple euler_angles_error; if (mobile_frame_) { - Eigen::Matrix3d tmp = state.getFrameTransform(desired_rotation_frame_id_).rotation() * desired_rotation_matrix_; - Eigen::Isometry3d diff(tmp.transpose() * state.getGlobalLinkTransform(link_model_).rotation()); - xyz = diff.rotation().eulerAngles(0, 1, 2); - // 0,1,2 corresponds to XYZ, the convention used in sampling constraints + // getFrameTransform() returns a valid isometry by contract + Eigen::Matrix3d tmp = state.getFrameTransform(desired_rotation_frame_id_).linear() * desired_rotation_matrix_; + // getGlobalLinkTransform() returns a valid isometry by contract + Eigen::Isometry3d diff(tmp.transpose() * state.getGlobalLinkTransform(link_model_).linear()); // valid isometry + euler_angles_error = CalcEulerAngles(diff.linear()); } else { - Eigen::Isometry3d diff(desired_rotation_matrix_inv_ * state.getGlobalLinkTransform(link_model_).rotation()); - xyz = - diff.rotation().eulerAngles(0, 1, 2); // 0,1,2 corresponds to XYZ, the convention used in sampling constraints + // diff is valid isometry by construction + Eigen::Isometry3d diff(desired_rotation_matrix_inv_ * state.getGlobalLinkTransform(link_model_).linear()); + euler_angles_error = CalcEulerAngles(diff.linear()); } + // Converting from a rotation matrix to an intrinsic XYZ euler angles have 2 singularities: + // pitch ~= pi/2 ==> roll + yaw = theta + // pitch ~= -pi/2 ==> roll - yaw = theta + // in those cases CalcEulerAngles will set roll (xyz(0)) to theta and yaw (xyz(2)) to zero, so for us to be able to + // capture yaw tolerance violation we do the following, if theta violate the absolute yaw tolerance we think of it as + // pure yaw rotation and set roll to zero + auto& xyz = std::get(euler_angles_error); + if (!std::get(euler_angles_error)) + { + if (normalizeAbsoluteAngle(xyz(0)) > absolute_z_axis_tolerance_ + std::numeric_limits::epsilon()) + { + xyz(2) = xyz(0); + xyz(0) = 0; + } + } // Account for angle wrapping - xyz(0) = std::min(fabs(xyz(0)), boost::math::constants::two_pi() - fabs(xyz(0))); - xyz(1) = std::min(fabs(xyz(1)), boost::math::constants::two_pi() - fabs(xyz(1))); - xyz(2) = std::min(fabs(xyz(2)), boost::math::constants::two_pi() - fabs(xyz(2))); + xyz = xyz.unaryExpr(&normalizeAbsoluteAngle); + + // 0,1,2 corresponds to XYZ, the convention used in sampling constraints bool result = xyz(2) < absolute_z_axis_tolerance_ + std::numeric_limits::epsilon() && xyz(1) < absolute_y_axis_tolerance_ + std::numeric_limits::epsilon() && xyz(0) < absolute_x_axis_tolerance_ + std::numeric_limits::epsilon(); diff --git a/moveit_core/kinematic_constraints/test/test_orientation_constraints.cpp b/moveit_core/kinematic_constraints/test/test_orientation_constraints.cpp new file mode 100644 index 0000000000..dc4eb8a37e --- /dev/null +++ b/moveit_core/kinematic_constraints/test/test_orientation_constraints.cpp @@ -0,0 +1,244 @@ +#include +#include +#include +#include +#include +#include + +class SphericalRobot : public testing::Test +{ +protected: + void SetUp() override + { + moveit::core::RobotModelBuilder builder("robot", "base_link"); + geometry_msgs::Pose origin; + origin.orientation.w = 1; + builder.addChain("base_link->roll", "revolute", { origin }, urdf::Vector3(1, 0, 0)); + builder.addChain("roll->pitch", "revolute", { origin }, urdf::Vector3(0, 1, 0)); + builder.addChain("pitch->yaw", "revolute", { origin }, urdf::Vector3(0, 0, 1)); + ASSERT_TRUE(builder.isValid()); + robot_model_ = builder.build(); + } + + std::map getJointValues(const double roll, const double pitch, const double yaw) + { + std::map jvals; + jvals["base_link-roll-joint"] = roll; + jvals["roll-pitch-joint"] = pitch; + jvals["pitch-yaw-joint"] = yaw; + return jvals; + } + + void TearDown() override + { + } + +protected: + moveit::core::RobotModelPtr robot_model_; +}; + +TEST_F(SphericalRobot, Test1) +{ + kinematic_constraints::OrientationConstraint oc(robot_model_); + + moveit::core::Transforms tf(robot_model_->getModelFrame()); + moveit_msgs::OrientationConstraint ocm; + + ocm.link_name = "yaw"; + ocm.header.frame_id = robot_model_->getModelFrame(); + ocm.orientation.x = 0.0; + ocm.orientation.y = 0.0; + ocm.orientation.z = 0.0; + ocm.orientation.w = 1.0; + ocm.absolute_x_axis_tolerance = 0.8; + ocm.absolute_y_axis_tolerance = 0.8; + ocm.absolute_z_axis_tolerance = 3.15; + ocm.weight = 1.0; + + moveit::core::RobotState robot_state(robot_model_); + // This's identical to a -1.57rad rotation around Z-axis + robot_state.setVariablePositions(getJointValues(3.140208, 3.141588, 1.570821)); + robot_state.update(); + + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_TRUE(oc.decide(robot_state).satisfied); +} + +TEST_F(SphericalRobot, Test2) +{ + kinematic_constraints::OrientationConstraint oc(robot_model_); + + moveit::core::Transforms tf(robot_model_->getModelFrame()); + moveit_msgs::OrientationConstraint ocm; + + ocm.link_name = "yaw"; + ocm.header.frame_id = robot_model_->getModelFrame(); + ocm.orientation.x = 0.0; + ocm.orientation.y = 0.0; + ocm.orientation.z = 0.0; + ocm.orientation.w = 1.0; + ocm.absolute_x_axis_tolerance = 0.2; + ocm.absolute_y_axis_tolerance = 2.0; + ocm.absolute_z_axis_tolerance = 0.2; + ocm.weight = 1.0; + + moveit::core::RobotState robot_state(robot_model_); + // Singularity: roll + yaw = theta + // These violate either absolute_x_axis_tolerance or absolute_z_axis_tolerance + robot_state.setVariablePositions(getJointValues(0.15, boost::math::constants::half_pi(), 0.15)); + robot_state.update(); + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_FALSE(oc.decide(robot_state).satisfied); + + robot_state.setVariablePositions(getJointValues(0.21, boost::math::constants::half_pi(), 0.0)); + robot_state.update(); + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_FALSE(oc.decide(robot_state).satisfied); + + robot_state.setVariablePositions(getJointValues(0.0, boost::math::constants::half_pi(), 0.21)); + robot_state.update(); + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_FALSE(oc.decide(robot_state).satisfied); + + // Singularity: roll - yaw = theta + // This's identical to -pi/2 pitch rotation + robot_state.setVariablePositions(getJointValues(0.15, -boost::math::constants::half_pi(), 0.15)); + robot_state.update(); + + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_TRUE(oc.decide(robot_state).satisfied); +} + +TEST_F(SphericalRobot, Test3) +{ + kinematic_constraints::OrientationConstraint oc(robot_model_); + + moveit::core::Transforms tf(robot_model_->getModelFrame()); + moveit_msgs::OrientationConstraint ocm; + + ocm.link_name = "yaw"; + ocm.header.frame_id = robot_model_->getModelFrame(); + ocm.orientation.x = 0.0; + ocm.orientation.y = 0.0; + ocm.orientation.z = 0.0; + ocm.orientation.w = 1.0; + ocm.absolute_x_axis_tolerance = 0.2; + ocm.absolute_y_axis_tolerance = 2.0; + ocm.absolute_z_axis_tolerance = 0.3; + ocm.weight = 1.0; + + moveit::core::RobotState robot_state(robot_model_); + // Singularity: roll + yaw = theta + + // These tests violate absolute_x_axis_tolerance + robot_state.setVariablePositions(getJointValues(0.21, boost::math::constants::half_pi(), 0.0)); + robot_state.update(); + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_FALSE(oc.decide(robot_state).satisfied); + + robot_state.setVariablePositions(getJointValues(0.0, boost::math::constants::half_pi(), 0.21)); + robot_state.update(); + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_FALSE(oc.decide(robot_state).satisfied); + + ocm.absolute_x_axis_tolerance = 0.3; + ocm.absolute_y_axis_tolerance = 2.0; + ocm.absolute_z_axis_tolerance = 0.2; + + // These tests violate absolute_z_axis_tolerance + robot_state.setVariablePositions(getJointValues(0.21, boost::math::constants::half_pi(), 0.0)); + robot_state.update(); + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_FALSE(oc.decide(robot_state).satisfied); + + robot_state.setVariablePositions(getJointValues(0.0, boost::math::constants::half_pi(), 0.21)); + robot_state.update(); + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_FALSE(oc.decide(robot_state).satisfied); +} + +TEST_F(SphericalRobot, Test4) +{ + kinematic_constraints::OrientationConstraint oc(robot_model_); + + moveit::core::Transforms tf(robot_model_->getModelFrame()); + moveit_msgs::OrientationConstraint ocm; + + ocm.link_name = "yaw"; + ocm.header.frame_id = robot_model_->getModelFrame(); + ocm.orientation.x = 0.0; + ocm.orientation.y = 0.0; + ocm.orientation.z = 0.0; + ocm.orientation.w = 1.0; + ocm.absolute_x_axis_tolerance = 0.2; + ocm.absolute_y_axis_tolerance = 2.0; + ocm.absolute_z_axis_tolerance = 0.3; + ocm.weight = 1.0; + + moveit::core::RobotState robot_state(robot_model_); + // Singularity: roll + yaw = theta + + // These tests violate absolute_x_axis_tolerance + robot_state.setVariablePositions(getJointValues(0.21, -boost::math::constants::half_pi(), 0.0)); + robot_state.update(); + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_FALSE(oc.decide(robot_state).satisfied); + + robot_state.setVariablePositions(getJointValues(0.0, -boost::math::constants::half_pi(), 0.21)); + robot_state.update(); + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_FALSE(oc.decide(robot_state).satisfied); + + ocm.absolute_x_axis_tolerance = 0.3; + ocm.absolute_y_axis_tolerance = 2.0; + ocm.absolute_z_axis_tolerance = 0.2; + + // These tests violate absolute_z_axis_tolerance + robot_state.setVariablePositions(getJointValues(0.21, -boost::math::constants::half_pi(), 0.0)); + robot_state.update(); + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_FALSE(oc.decide(robot_state).satisfied); + + robot_state.setVariablePositions(getJointValues(0.0, -boost::math::constants::half_pi(), 0.21)); + robot_state.update(); + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_FALSE(oc.decide(robot_state).satisfied); + + robot_state.setVariablePositions(getJointValues(0.5, -boost::math::constants::half_pi(), 0.21)); + robot_state.update(); + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_FALSE(oc.decide(robot_state).satisfied); +} + +// Both the current and the desired orientations are in singularities +TEST_F(SphericalRobot, Test5) +{ + kinematic_constraints::OrientationConstraint oc(robot_model_); + + moveit::core::Transforms tf(robot_model_->getModelFrame()); + moveit_msgs::OrientationConstraint ocm; + + moveit::core::RobotState robot_state(robot_model_); + robot_state.setVariablePositions(getJointValues(0.0, boost::math::constants::half_pi(), 0.0)); + robot_state.update(); + + ocm.link_name = "yaw"; + ocm.header.frame_id = robot_model_->getModelFrame(); + tf2::convert(Eigen::Quaterniond(robot_state.getGlobalLinkTransform(ocm.link_name).linear()), ocm.orientation); + ocm.absolute_x_axis_tolerance = 0.0; + ocm.absolute_y_axis_tolerance = 0.0; + ocm.absolute_z_axis_tolerance = 1.0; + ocm.weight = 1.0; + + robot_state.setVariablePositions(getJointValues(0.2, boost::math::constants::half_pi(), 0.3)); + robot_state.update(); + + EXPECT_TRUE(oc.configure(ocm, tf)); + EXPECT_TRUE(oc.decide(robot_state, true).satisfied); +} + +int main(int argc, char** argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From 779d3e44e32da3b0f0d49f93f1c708fb4545d258 Mon Sep 17 00:00:00 2001 From: AndyZe Date: Thu, 17 Dec 2020 11:01:38 -0600 Subject: [PATCH 072/179] Fix doxygen documentation for setToIKSolverFrame (#2461) * Fix doxygen documentation for setToIKSolverFrame * "Convert" -> "Transform" * Make function private. Update comments. * Make inline and private * Longer function should not be inline Co-authored-by: Robert Haschke Co-authored-by: Robert Haschke --- .../include/moveit/robot_state/robot_state.h | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/moveit_core/robot_state/include/moveit/robot_state/robot_state.h b/moveit_core/robot_state/include/moveit/robot_state/robot_state.h index abb97e69fe..5c8596fbbb 100644 --- a/moveit_core/robot_state/include/moveit/robot_state/robot_state.h +++ b/moveit_core/robot_state/include/moveit/robot_state/robot_state.h @@ -951,22 +951,6 @@ as the new values that correspond to the group */ * @{ */ - /** - * \brief Convert the frame of reference of the pose to that same frame as the IK solver expects - * @param pose - the input to change - * @param solver - a kin solver whose base frame is important to us - * @return true if no error - */ - bool setToIKSolverFrame(Eigen::Isometry3d& pose, const kinematics::KinematicsBaseConstPtr& solver); - - /** - * \brief Convert the frame of reference of the pose to that same frame as the IK solver expects - * @param pose - the input to change - * @param ik_frame - the name of frame of reference of base of ik solver - * @return true if no error - */ - bool setToIKSolverFrame(Eigen::Isometry3d& pose, const std::string& ik_frame); - /** \brief If the group this state corresponds to is a chain and a solver is available, then the joint values can be set by computing inverse kinematics. The pose is assumed to be in the reference frame of the kinematic model. Returns true on success. @@ -1832,6 +1816,22 @@ as the new values that correspond to the group */ void initTransforms(); void copyFrom(const RobotState& other); + /** + * \brief Transform pose from the robot model's base frame to the reference frame of the IK solver + * @param pose - the input to change + * @param solver - a kin solver whose base frame is important to us + * @return true if no error + */ + inline bool setToIKSolverFrame(Eigen::Isometry3d& pose, const kinematics::KinematicsBaseConstPtr& solver); + + /** + * \brief Transform pose from the robot model's base frame to the reference frame of the IK solver + * @param pose - the input to change + * @param ik_frame - the name of frame of reference of base of ik solver + * @return true if no error + */ + bool setToIKSolverFrame(Eigen::Isometry3d& pose, const std::string& ik_frame); + void markDirtyJointTransforms(const JointModel* joint) { dirty_joint_transforms_[joint->getJointIndex()] = 1; From e9c5d181f6c56502dc651e5c8ed3453d48a2343d Mon Sep 17 00:00:00 2001 From: AndyZe Date: Fri, 18 Dec 2020 15:12:24 -0600 Subject: [PATCH 073/179] Add an important sleep in Servo pose tracking (#2463) --- moveit_ros/moveit_servo/src/pose_tracking.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/moveit_ros/moveit_servo/src/pose_tracking.cpp b/moveit_ros/moveit_servo/src/pose_tracking.cpp index c51a54f75a..0c134db35c 100644 --- a/moveit_ros/moveit_servo/src/pose_tracking.cpp +++ b/moveit_ros/moveit_servo/src/pose_tracking.cpp @@ -128,6 +128,11 @@ PoseTrackingStatusCode PoseTracking::moveToPose(const Eigen::Vector3d& positiona // Compute servo command from PID controller output and send it to the Servo object, for execution twist_stamped_pub_.publish(calculateTwistCommand()); + + if (!loop_rate_.sleep()) + { + ROS_WARN_STREAM_THROTTLE_NAMED(1, LOGNAME, "Target control rate was missed"); + } } doPostMotionReset(); From 171aee4ab5419f2f95eb26d980a02d0f74bdce7d Mon Sep 17 00:00:00 2001 From: "David V. Lu!!" Date: Mon, 21 Dec 2020 10:55:49 -0500 Subject: [PATCH 074/179] Missing RViz and moveit_simple_controller_manager dependencies in MSA template (#2455) --- .../templates/moveit_config_pkg_template/package.xml.template | 2 ++ 1 file changed, 2 insertions(+) diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/package.xml.template b/moveit_setup_assistant/templates/moveit_config_pkg_template/package.xml.template index 60202e870e..bd38696c9f 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/package.xml.template +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/package.xml.template @@ -22,9 +22,11 @@ moveit_planners_ompl moveit_ros_visualization moveit_setup_assistant + moveit_simple_controller_manager joint_state_publisher joint_state_publisher_gui robot_state_publisher + rviz tf2_ros xacro From 929bfe14a745c846605c6db066d658eec69544ba Mon Sep 17 00:00:00 2001 From: Udbhavbisarya23 <43880582+Udbhavbisarya23@users.noreply.github.com> Date: Wed, 23 Dec 2020 01:54:33 +0530 Subject: [PATCH 075/179] Fix some typos in comments (#2466) --- moveit_ros/planning/plan_execution/src/plan_execution.cpp | 2 +- moveit_ros/planning/plan_execution/src/plan_with_sensing.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/moveit_ros/planning/plan_execution/src/plan_execution.cpp b/moveit_ros/planning/plan_execution/src/plan_execution.cpp index b8caaedc95..a3d81b33e0 100644 --- a/moveit_ros/planning/plan_execution/src/plan_execution.cpp +++ b/moveit_ros/planning/plan_execution/src/plan_execution.cpp @@ -219,7 +219,7 @@ void plan_execution::PlanExecution::planAndExecuteHelper(ExecutableMotionPlan& p if (preempt_requested_) break; - // execute the trajectory, and monitor its executionm + // execute the trajectory, and monitor its execution plan.error_code_ = executeAndMonitor(plan); } diff --git a/moveit_ros/planning/plan_execution/src/plan_with_sensing.cpp b/moveit_ros/planning/plan_execution/src/plan_with_sensing.cpp index dfce531e83..b7bf116b5d 100644 --- a/moveit_ros/planning/plan_execution/src/plan_with_sensing.cpp +++ b/moveit_ros/planning/plan_execution/src/plan_with_sensing.cpp @@ -150,7 +150,7 @@ bool plan_execution::PlanWithSensing::computePlan(ExecutableMotionPlan& plan, unsigned int look_attempts = 0; // this flag is set to true when all conditions for looking around are met, and the command is sent. - // the intention is for the planning looop not to terminate when having just looked around + // the intention is for the planning loop not to terminate when having just looked around bool just_looked_around = false; // this flag indicates whether the last lookAt() operation failed. If this operation fails once, we assume that @@ -212,7 +212,7 @@ bool plan_execution::PlanWithSensing::computePlan(ExecutableMotionPlan& plan, bool looked_at_result = lookAt(cost_sources, plan.planning_scene_->getPlanningFrame()); if (looked_at_result) - ROS_INFO("Sensor was succesfully actuated. Attempting to recompute a motion plan."); + ROS_INFO("Sensor was successfully actuated. Attempting to recompute a motion plan."); else { if (look_around_failed) From cb775ca43ba494cfdbe370e2eef94d6cb5dbbc58 Mon Sep 17 00:00:00 2001 From: Simon Schmeisser Date: Mon, 28 Dec 2020 11:40:06 +0100 Subject: [PATCH 076/179] Catch exceptions during RobotModel loading in rviz (#2468) --- .../src/robot_state_display.cpp | 35 +++++++++++-------- .../src/trajectory_display.cpp | 35 +++++++++++-------- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/moveit_ros/visualization/robot_state_rviz_plugin/src/robot_state_display.cpp b/moveit_ros/visualization/robot_state_rviz_plugin/src/robot_state_display.cpp index beb49e28b8..4efb92a360 100644 --- a/moveit_ros/visualization/robot_state_rviz_plugin/src/robot_state_display.cpp +++ b/moveit_ros/visualization/robot_state_rviz_plugin/src/robot_state_display.cpp @@ -366,20 +366,27 @@ void RobotStateDisplay::loadRobotModel() if (rdf_loader_->getURDF()) { - const srdf::ModelSharedPtr& srdf = - rdf_loader_->getSRDF() ? rdf_loader_->getSRDF() : srdf::ModelSharedPtr(new srdf::Model()); - robot_model_.reset(new robot_model::RobotModel(rdf_loader_->getURDF(), srdf)); - robot_->load(*robot_model_->getURDF()); - robot_state_.reset(new robot_state::RobotState(robot_model_)); - robot_state_->setToDefaultValues(); - bool old_state = root_link_name_property_->blockSignals(true); - root_link_name_property_->setStdString(getRobotModel()->getRootLinkName()); - root_link_name_property_->blockSignals(old_state); - update_state_ = true; - setStatus(rviz::StatusProperty::Ok, "RobotModel", "Loaded successfully"); - - changedEnableVisualVisible(); - changedEnableCollisionVisible(); + try + { + const srdf::ModelSharedPtr& srdf = + rdf_loader_->getSRDF() ? rdf_loader_->getSRDF() : srdf::ModelSharedPtr(new srdf::Model()); + robot_model_.reset(new robot_model::RobotModel(rdf_loader_->getURDF(), srdf)); + robot_->load(*robot_model_->getURDF()); + robot_state_.reset(new robot_state::RobotState(robot_model_)); + robot_state_->setToDefaultValues(); + bool old_state = root_link_name_property_->blockSignals(true); + root_link_name_property_->setStdString(getRobotModel()->getRootLinkName()); + root_link_name_property_->blockSignals(old_state); + update_state_ = true; + setStatus(rviz::StatusProperty::Ok, "RobotModel", "Loaded successfully"); + + changedEnableVisualVisible(); + changedEnableCollisionVisible(); + } + catch (std::exception& e) + { + setStatus(rviz::StatusProperty::Error, "RobotModel", QString("Loading failed: %1").arg(e.what())); + } } else setStatus(rviz::StatusProperty::Error, "RobotModel", "Loading failed"); diff --git a/moveit_ros/visualization/trajectory_rviz_plugin/src/trajectory_display.cpp b/moveit_ros/visualization/trajectory_rviz_plugin/src/trajectory_display.cpp index db0884d95a..cdea836eed 100644 --- a/moveit_ros/visualization/trajectory_rviz_plugin/src/trajectory_display.cpp +++ b/moveit_ros/visualization/trajectory_rviz_plugin/src/trajectory_display.cpp @@ -64,22 +64,29 @@ void TrajectoryDisplay::onInitialize() void TrajectoryDisplay::loadRobotModel() { - rdf_loader_.reset(new rdf_loader::RDFLoader(robot_description_property_->getStdString())); - - if (!rdf_loader_->getURDF()) + try { - this->setStatus(rviz::StatusProperty::Error, "Robot Model", - "Failed to load from parameter " + robot_description_property_->getString()); - return; + rdf_loader_.reset(new rdf_loader::RDFLoader(robot_description_property_->getStdString())); + + if (!rdf_loader_->getURDF()) + { + this->setStatus(rviz::StatusProperty::Error, "Robot Model", + "Failed to load from parameter " + robot_description_property_->getString()); + return; + } + this->setStatus(rviz::StatusProperty::Ok, "Robot Model", "Successfully loaded"); + + const srdf::ModelSharedPtr& srdf = + rdf_loader_->getSRDF() ? rdf_loader_->getSRDF() : srdf::ModelSharedPtr(new srdf::Model()); + robot_model_.reset(new robot_model::RobotModel(rdf_loader_->getURDF(), srdf)); + + // Send to child class + trajectory_visual_->onRobotModelLoaded(robot_model_); + } + catch (std::exception& e) + { + setStatus(rviz::StatusProperty::Error, "RobotModel", QString("Loading failed: %1").arg(e.what())); } - this->setStatus(rviz::StatusProperty::Ok, "Robot Model", "Successfully loaded"); - - const srdf::ModelSharedPtr& srdf = - rdf_loader_->getSRDF() ? rdf_loader_->getSRDF() : srdf::ModelSharedPtr(new srdf::Model()); - robot_model_.reset(new robot_model::RobotModel(rdf_loader_->getURDF(), srdf)); - - // Send to child class - trajectory_visual_->onRobotModelLoaded(robot_model_); } void TrajectoryDisplay::reset() From 594342dd8254ed5cf802b3f54516bde917a7bfbc Mon Sep 17 00:00:00 2001 From: Tobias Fischer Date: Wed, 6 Jan 2021 19:14:07 +1000 Subject: [PATCH 077/179] Python3 compatibility for ikfast's round_collada_numbers.py (#2473) --- .../ikfast_kinematics_plugin/scripts/round_collada_numbers.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/moveit_kinematics/ikfast_kinematics_plugin/scripts/round_collada_numbers.py b/moveit_kinematics/ikfast_kinematics_plugin/scripts/round_collada_numbers.py index 8ee19548f4..d72ab98cd8 100755 --- a/moveit_kinematics/ikfast_kinematics_plugin/scripts/round_collada_numbers.py +++ b/moveit_kinematics/ikfast_kinematics_plugin/scripts/round_collada_numbers.py @@ -39,6 +39,8 @@ # Author: Dave Coleman # Desc: Rounds all the numbers to places +from __future__ import print_function + from lxml import etree import shlex import sys @@ -78,7 +80,7 @@ def doRound(values, decimal_places): sys.exit(-1) print("\nCollada Number Rounder") - print("Rounding numbers to", decimal_places, " decimal places\n") + print("Rounding numbers to", decimal_places, "decimal places\n") # Read string from file f = open(input_file, "r") From 7879b39183939a8edf098940f6f92b45c3afce85 Mon Sep 17 00:00:00 2001 From: AdamPettinger Date: Thu, 7 Jan 2021 13:00:50 -0600 Subject: [PATCH 078/179] [Servo] Fix initial angle error is always 0 (#2464) Co-authored-by: AndyZe Co-authored-by: Bjar Ne --- .../include/moveit_servo/pose_tracking.h | 3 ++- moveit_ros/moveit_servo/src/pose_tracking.cpp | 12 ++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h b/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h index ad391b158b..5163cc08c8 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h @@ -39,6 +39,7 @@ #pragma once #include +#include #include #include #include @@ -187,7 +188,7 @@ class PoseTracking // Flag that a different thread has requested a stop. std::atomic stop_requested_; - double angular_error_; + boost::optional angular_error_; }; // using alias diff --git a/moveit_ros/moveit_servo/src/pose_tracking.cpp b/moveit_ros/moveit_servo/src/pose_tracking.cpp index 0c134db35c..723fe2d8f7 100644 --- a/moveit_ros/moveit_servo/src/pose_tracking.cpp +++ b/moveit_ros/moveit_servo/src/pose_tracking.cpp @@ -50,7 +50,7 @@ PoseTracking::PoseTracking(const ros::NodeHandle& nh, , loop_rate_(DEFAULT_LOOP_RATE) , transform_listener_(transform_buffer_) , stop_requested_(false) - , angular_error_(0) + , angular_error_(boost::none) { readROSParams(); @@ -226,8 +226,12 @@ bool PoseTracking::satisfiesPoseTolerance(const Eigen::Vector3d& positional_tole double y_error = target_pose_.pose.position.y - command_frame_transform_.translation()(1); double z_error = target_pose_.pose.position.z - command_frame_transform_.translation()(2); + // If uninitialized, likely haven't received the target pose yet. + if (!angular_error_) + return false; + return ((std::abs(x_error) < positional_tolerance(0)) && (std::abs(y_error) < positional_tolerance(1)) && - (std::abs(z_error) < positional_tolerance(2)) && (std::abs(angular_error_) < angular_tolerance)); + (std::abs(z_error) < positional_tolerance(2)) && (std::abs(*angular_error_) < angular_tolerance)); } void PoseTracking::targetPoseCallback(const geometry_msgs::PoseStampedConstPtr& msg) @@ -293,7 +297,7 @@ geometry_msgs::TwistStampedConstPtr PoseTracking::calculateTwistCommand() // Cache the angular error, for rotation tolerance checking angular_error_ = axis_angle.angle(); double ang_vel_magnitude = - cartesian_orientation_pids_[0].computeCommand(angular_error_, loop_rate_.expectedCycleTime()); + cartesian_orientation_pids_[0].computeCommand(*angular_error_, loop_rate_.expectedCycleTime()); twist.angular.x = ang_vel_magnitude * axis_angle.axis()[0]; twist.angular.y = ang_vel_magnitude * axis_angle.axis()[1]; twist.angular.z = ang_vel_magnitude * axis_angle.axis()[2]; @@ -306,7 +310,7 @@ geometry_msgs::TwistStampedConstPtr PoseTracking::calculateTwistCommand() void PoseTracking::doPostMotionReset() { stop_requested_ = false; - angular_error_ = 0; + angular_error_ = boost::none; // Reset error integrals and previous errors of PID controllers cartesian_position_pids_[0].reset(); From 558c5286638b383fccb51f1dbb9483577bcb8389 Mon Sep 17 00:00:00 2001 From: sevangelatos Date: Mon, 11 Jan 2021 18:00:19 +0200 Subject: [PATCH 079/179] Fix RobotState::dropAccelerations/dropEffort to not drop velocities (#2478) --- moveit_core/robot_state/src/robot_state.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moveit_core/robot_state/src/robot_state.cpp b/moveit_core/robot_state/src/robot_state.cpp index e2b3f05feb..6587cfd863 100644 --- a/moveit_core/robot_state/src/robot_state.cpp +++ b/moveit_core/robot_state/src/robot_state.cpp @@ -261,12 +261,12 @@ void RobotState::dropVelocities() void RobotState::dropAccelerations() { - has_velocity_ = false; + has_acceleration_ = false; } void RobotState::dropEffort() { - has_velocity_ = false; + has_effort_ = false; } void RobotState::dropDynamics() From 98177e379ad35b74f706751f99453c089d4a1b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Tue, 12 Jan 2021 13:21:56 +0100 Subject: [PATCH 080/179] pilz planner: add string includes (#2483) --- .../pilz_industrial_motion_planner/joint_limits_container.h | 1 + .../pilz_industrial_motion_planner/joint_limits_extension.h | 1 + 2 files changed, 2 insertions(+) diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_container.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_container.h index fac49e9106..7a91ffe545 100644 --- a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_container.h +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_container.h @@ -38,6 +38,7 @@ #include #include +#include namespace pilz_industrial_motion_planner { diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_extension.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_extension.h index 84bb1fc79f..789cafa88e 100644 --- a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_extension.h +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/joint_limits_extension.h @@ -37,6 +37,7 @@ #include #include +#include namespace pilz_industrial_motion_planner { From ca653f8196f61c30e629b3ae0bb23c1d1d0ef380 Mon Sep 17 00:00:00 2001 From: AndyZe Date: Tue, 12 Jan 2021 14:38:41 -0600 Subject: [PATCH 081/179] Clean up collision-related log statements (#2480) --- .../src/collision_env_bullet.cpp | 432 ++++++++++++++++++ 1 file changed, 432 insertions(+) create mode 100644 moveit_core/collision_detection_bullet/src/collision_env_bullet.cpp diff --git a/moveit_core/collision_detection_bullet/src/collision_env_bullet.cpp b/moveit_core/collision_detection_bullet/src/collision_env_bullet.cpp new file mode 100644 index 0000000000..0be13bcfbc --- /dev/null +++ b/moveit_core/collision_detection_bullet/src/collision_env_bullet.cpp @@ -0,0 +1,432 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2019, Jens Petit + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT 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: Jens Petit */ + +#include +#include +#include +#include +#include +#include + +namespace collision_detection +{ +const std::string CollisionDetectorAllocatorBullet::NAME("Bullet"); +const double MAX_DISTANCE_MARGIN = 99; +constexpr char LOGNAME[] = "collision_detection.bullet"; + +CollisionEnvBullet::CollisionEnvBullet(const moveit::core::RobotModelConstPtr& model, double padding, double scale) + : CollisionEnv(model, padding, scale) +{ + // request notifications about changes to new world + observer_handle_ = getWorld()->addObserver(boost::bind(&CollisionEnvBullet::notifyObjectChange, this, _1, _2)); + + for (const std::pair& link : robot_model_->getURDF()->links_) + { + addLinkAsCollisionObject(link.second); + } +} + +CollisionEnvBullet::CollisionEnvBullet(const moveit::core::RobotModelConstPtr& model, const WorldPtr& world, + double padding, double scale) + : CollisionEnv(model, world, padding, scale) +{ + // request notifications about changes to new world + observer_handle_ = getWorld()->addObserver(boost::bind(&CollisionEnvBullet::notifyObjectChange, this, _1, _2)); + + for (const std::pair& link : robot_model_->getURDF()->links_) + { + addLinkAsCollisionObject(link.second); + } + + getWorld()->notifyObserverAllObjects(observer_handle_, World::CREATE); +} + +CollisionEnvBullet::CollisionEnvBullet(const CollisionEnvBullet& other, const WorldPtr& world) + : CollisionEnv(other, world) +{ + // TODO(j-petit): Verify this constructor + + // request notifications about changes to new world + observer_handle_ = getWorld()->addObserver(boost::bind(&CollisionEnvBullet::notifyObjectChange, this, _1, _2)); + + for (const std::pair& link : other.robot_model_->getURDF()->links_) + { + addLinkAsCollisionObject(link.second); + } +} + +CollisionEnvBullet::~CollisionEnvBullet() +{ + getWorld()->removeObserver(observer_handle_); +} + +void CollisionEnvBullet::checkSelfCollision(const CollisionRequest& req, CollisionResult& res, + const moveit::core::RobotState& state) const +{ + checkSelfCollisionHelper(req, res, state, nullptr); +} + +void CollisionEnvBullet::checkSelfCollision(const CollisionRequest& req, CollisionResult& res, + const moveit::core::RobotState& state, + const AllowedCollisionMatrix& acm) const +{ + checkSelfCollisionHelper(req, res, state, &acm); +} + +void CollisionEnvBullet::checkSelfCollisionHelper(const CollisionRequest& req, CollisionResult& res, + const moveit::core::RobotState& state, + const AllowedCollisionMatrix* acm) const +{ + std::vector cows; + addAttachedOjects(state, cows); + + if (req.distance) + { + manager_->setContactDistanceThreshold(MAX_DISTANCE_MARGIN); + } + + for (const collision_detection_bullet::CollisionObjectWrapperPtr& cow : cows) + { + manager_->addCollisionObject(cow); + manager_->setCollisionObjectsTransform( + cow->getName(), state.getAttachedBody(cow->getName())->getGlobalCollisionBodyTransforms()[0]); + } + + // updating link positions with the current robot state + for (const std::string& link : active_) + { + manager_->setCollisionObjectsTransform(link, state.getCollisionBodyTransform(link, 0)); + } + + manager_->contactTest(res, req, acm, true); + + for (const collision_detection_bullet::CollisionObjectWrapperPtr& cow : cows) + { + manager_->removeCollisionObject(cow->getName()); + } +} + +void CollisionEnvBullet::checkRobotCollision(const CollisionRequest& req, CollisionResult& res, + const moveit::core::RobotState& state) const +{ + checkRobotCollisionHelper(req, res, state, nullptr); +} + +void CollisionEnvBullet::checkRobotCollision(const CollisionRequest& req, CollisionResult& res, + const moveit::core::RobotState& state, + const AllowedCollisionMatrix& acm) const +{ + checkRobotCollisionHelper(req, res, state, &acm); +} + +void CollisionEnvBullet::checkRobotCollision(const CollisionRequest& req, CollisionResult& res, + const moveit::core::RobotState& state1, + const moveit::core::RobotState& state2) const +{ + checkRobotCollisionHelperCCD(req, res, state1, state2, nullptr); +} + +void CollisionEnvBullet::checkRobotCollision(const CollisionRequest& req, CollisionResult& res, + const moveit::core::RobotState& state1, + const moveit::core::RobotState& state2, + const AllowedCollisionMatrix& acm) const +{ + checkRobotCollisionHelperCCD(req, res, state1, state2, &acm); +} + +void CollisionEnvBullet::checkRobotCollisionHelper(const CollisionRequest& req, CollisionResult& res, + const moveit::core::RobotState& state, + const AllowedCollisionMatrix* acm) const +{ + if (req.distance) + { + manager_->setContactDistanceThreshold(MAX_DISTANCE_MARGIN); + } + + std::vector attached_cows; + addAttachedOjects(state, attached_cows); + updateTransformsFromState(state, manager_); + + for (const collision_detection_bullet::CollisionObjectWrapperPtr& cow : attached_cows) + { + manager_->addCollisionObject(cow); + manager_->setCollisionObjectsTransform( + cow->getName(), state.getAttachedBody(cow->getName())->getGlobalCollisionBodyTransforms()[0]); + } + + manager_->contactTest(res, req, acm, false); + + for (const collision_detection_bullet::CollisionObjectWrapperPtr& cow : attached_cows) + { + manager_->removeCollisionObject(cow->getName()); + } +} + +void CollisionEnvBullet::checkRobotCollisionHelperCCD(const CollisionRequest& req, CollisionResult& res, + const moveit::core::RobotState& state1, + const moveit::core::RobotState& state2, + const AllowedCollisionMatrix* acm) const +{ + std::vector attached_cows; + addAttachedOjects(state1, attached_cows); + + for (const collision_detection_bullet::CollisionObjectWrapperPtr& cow : attached_cows) + { + manager_CCD_->addCollisionObject(cow); + manager_CCD_->setCastCollisionObjectsTransform( + cow->getName(), state1.getAttachedBody(cow->getName())->getGlobalCollisionBodyTransforms()[0], + state2.getAttachedBody(cow->getName())->getGlobalCollisionBodyTransforms()[0]); + } + + for (const std::string& link : active_) + { + manager_CCD_->setCastCollisionObjectsTransform(link, state1.getCollisionBodyTransform(link, 0), + state2.getCollisionBodyTransform(link, 0)); + } + + manager_CCD_->contactTest(res, req, acm, false); + + for (const collision_detection_bullet::CollisionObjectWrapperPtr& cow : attached_cows) + { + manager_CCD_->removeCollisionObject(cow->getName()); + } +} + +void CollisionEnvBullet::distanceSelf(const DistanceRequest& req, DistanceResult& res, + const moveit::core::RobotState& state) const +{ + ROS_INFO_NAMED(LOGNAME, "distanceSelf is not implemented for Bullet."); +} + +void CollisionEnvBullet::distanceRobot(const DistanceRequest& req, DistanceResult& res, + const moveit::core::RobotState& state) const +{ + ROS_INFO_NAMED(LOGNAME, "distanceRobot is not implemented for Bullet."); +} + +void CollisionEnvBullet::addToManager(const World::Object* obj) +{ + std::vector collision_object_types; + + for (const shapes::ShapeConstPtr& shape : obj->shapes_) + { + if (shape->type == shapes::MESH) + collision_object_types.push_back(collision_detection_bullet::CollisionObjectType::CONVEX_HULL); + else + collision_object_types.push_back(collision_detection_bullet::CollisionObjectType::USE_SHAPE_TYPE); + } + + collision_detection_bullet::CollisionObjectWrapperPtr cow(new collision_detection_bullet::CollisionObjectWrapper( + obj->id_, collision_detection::BodyType::WORLD_OBJECT, obj->shapes_, obj->shape_poses_, collision_object_types, + false)); + + manager_->addCollisionObject(cow); + manager_CCD_->addCollisionObject(cow->clone()); +} + +void CollisionEnvBullet::updateManagedObject(const std::string& id) +{ + if (getWorld()->hasObject(id)) + { + auto it = getWorld()->find(id); + if (manager_->hasCollisionObject(id)) + { + manager_->removeCollisionObject(id); + manager_CCD_->removeCollisionObject(id); + addToManager(it->second.get()); + } + else + { + addToManager(it->second.get()); + } + } + else + { + if (manager_->hasCollisionObject(id)) + { + manager_->removeCollisionObject(id); + manager_CCD_->removeCollisionObject(id); + } + } +} + +void CollisionEnvBullet::setWorld(const WorldPtr& world) +{ + if (world == getWorld()) + return; + + // turn off notifications about old world + getWorld()->removeObserver(observer_handle_); + + CollisionEnv::setWorld(world); + + // request notifications about changes to new world + observer_handle_ = getWorld()->addObserver(boost::bind(&CollisionEnvBullet::notifyObjectChange, this, _1, _2)); + + // get notifications any objects already in the new world + getWorld()->notifyObserverAllObjects(observer_handle_, World::CREATE); +} + +void CollisionEnvBullet::notifyObjectChange(const ObjectConstPtr& obj, World::Action action) +{ + if (action == World::DESTROY) + { + manager_->removeCollisionObject(obj->id_); + manager_CCD_->removeCollisionObject(obj->id_); + } + else + { + updateManagedObject(obj->id_); + } +} + +void CollisionEnvBullet::addAttachedOjects(const moveit::core::RobotState& state, + std::vector& cows) const +{ + std::vector attached_bodies; + state.getAttachedBodies(attached_bodies); + + for (const moveit::core::AttachedBody*& body : attached_bodies) + { + const EigenSTL::vector_Isometry3d& attached_body_transform = body->getGlobalCollisionBodyTransforms(); + + std::vector collision_object_types( + attached_body_transform.size(), collision_detection_bullet::CollisionObjectType::USE_SHAPE_TYPE); + + try + { + collision_detection_bullet::CollisionObjectWrapperPtr cow(new collision_detection_bullet::CollisionObjectWrapper( + body->getName(), collision_detection::BodyType::ROBOT_ATTACHED, body->getShapes(), attached_body_transform, + collision_object_types, body->getTouchLinks())); + cows.push_back(cow); + } + catch (std::exception&) + { + ROS_ERROR_STREAM_NAMED("collision_detetction.bullet", + "Not adding " << body->getName() << " due to bad arguments."); + } + } +} + +void CollisionEnvBullet::updatedPaddingOrScaling(const std::vector& links) +{ + for (const std::string& link : links) + { + if (robot_model_->getURDF()->links_.find(link) != robot_model_->getURDF()->links_.end()) + { + addLinkAsCollisionObject(robot_model_->getURDF()->links_[link]); + } + else + { + ROS_ERROR_NAMED("collision_detection.bullet", "Updating padding or scaling for unknown link: '%s'", link.c_str()); + } + } +} + +void CollisionEnvBullet::updateTransformsFromState( + const moveit::core::RobotState& state, const collision_detection_bullet::BulletDiscreteBVHManagerPtr& manager) const +{ + // updating link positions with the current robot state + for (const std::string& link : active_) + { + // select the first of the transformations for each link (composed of multiple shapes...) + manager->setCollisionObjectsTransform(link, state.getCollisionBodyTransform(link, 0)); + } +} + +void CollisionEnvBullet::addLinkAsCollisionObject(const urdf::LinkSharedPtr& link) +{ + if (!link->collision_array.empty()) + { + const std::vector& col_array = + link->collision_array.empty() ? std::vector(1, link->collision) : + link->collision_array; + + std::vector shapes; + collision_detection_bullet::AlignedVector shape_poses; + std::vector collision_object_types; + + for (const auto& i : col_array) + { + if (i && i->geometry) + { + shapes::ShapePtr shape = collision_detection_bullet::constructShape(i->geometry.get()); + + if (shape) + { + if (fabs(getLinkScale(link->name) - 1.0) >= std::numeric_limits::epsilon() || + fabs(getLinkPadding(link->name)) >= std::numeric_limits::epsilon()) + { + shape->scaleAndPadd(getLinkScale(link->name), getLinkPadding(link->name)); + } + + shapes.push_back(shape); + shape_poses.push_back(collision_detection_bullet::urdfPose2Eigen(i->origin)); + + if (shape->type == shapes::MESH) + { + collision_object_types.push_back(collision_detection_bullet::CollisionObjectType::CONVEX_HULL); + } + else + { + collision_object_types.push_back(collision_detection_bullet::CollisionObjectType::USE_SHAPE_TYPE); + } + } + } + } + + if (manager_->hasCollisionObject(link->name)) + { + manager_->removeCollisionObject(link->name); + manager_CCD_->removeCollisionObject(link->name); + } + + try + { + collision_detection_bullet::CollisionObjectWrapperPtr cow(new collision_detection_bullet::CollisionObjectWrapper( + link->name, collision_detection::BodyType::ROBOT_LINK, shapes, shape_poses, collision_object_types, true)); + manager_->addCollisionObject(cow); + manager_CCD_->addCollisionObject(cow->clone()); + active_.push_back(cow->getName()); + } + catch (std::exception&) + { + ROS_ERROR_STREAM_NAMED("collision_detetction.bullet", "Not adding " << link->name << " due to bad arguments."); + } + } +} + +} // end of namespace collision_detection From f8216e9d416b10ac67bc234ffd4ef4c122e2493a Mon Sep 17 00:00:00 2001 From: Shota Aoki Date: Wed, 13 Jan 2021 20:24:17 +0900 Subject: [PATCH 082/179] Fix scaling factor parameter names (#2452) --- .../move_group_interface/src/move_group_interface.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp b/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp index 1802b80f30..b98a476147 100644 --- a/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp +++ b/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp @@ -124,8 +124,10 @@ class MoveGroupInterface::MoveGroupInterfaceImpl goal_orientation_tolerance_ = 1e-3; // ~0.1 deg allowed_planning_time_ = 5.0; num_planning_attempts_ = 1; - max_velocity_scaling_factor_ = 1.0; - max_acceleration_scaling_factor_ = 1.0; + node_handle_.param("robot_description_planning/default_velocity_scaling_factor", + max_velocity_scaling_factor_, 0.1); + node_handle_.param("robot_description_planning/default_acceleration_scaling_factor", + max_acceleration_scaling_factor_, 0.1); initializing_constraints_ = false; if (joint_model_group_->isChain()) From c02baf701e85fcd612ffede23883d2bfc4eee804 Mon Sep 17 00:00:00 2001 From: Boston Cleek <36201047+bostoncleek@users.noreply.github.com> Date: Wed, 13 Jan 2021 08:10:19 -0700 Subject: [PATCH 083/179] Improve robustness of move group interface test (#2484) --- .../test/move_group_interface_cpp_test.cpp | 216 +++++++----------- 1 file changed, 88 insertions(+), 128 deletions(-) diff --git a/moveit_ros/planning_interface/test/move_group_interface_cpp_test.cpp b/moveit_ros/planning_interface/test/move_group_interface_cpp_test.cpp index ceae107b73..3789ed631e 100644 --- a/moveit_ros/planning_interface/test/move_group_interface_cpp_test.cpp +++ b/moveit_ros/planning_interface/test/move_group_interface_cpp_test.cpp @@ -33,7 +33,7 @@ * POSSIBILITY OF SUCH DAMAGE. *********************************************************************/ -/* Author: Tyler Weaver */ +/* Author: Tyler Weaver, Boston Cleek */ /* These integration tests are based on the tutorials for using move_group: * https://ros-planning.github.io/moveit_tutorials/doc/move_group_interface/move_group_interface_tutorial.html @@ -150,16 +150,27 @@ class MoveGroupTestFixture : public ::testing::Test moveit::planning_interface::PlanningSceneInterface planning_scene_interface_; }; -TEST_F(MoveGroupTestFixture, MoveToPoseTest) +TEST_F(MoveGroupTestFixture, PathConstraintCollisionTest) { - SCOPED_TRACE("MoveToPoseTest"); + SCOPED_TRACE("PathConstraintCollisionTest"); + //////////////////////////////////////////////////////////////////// + // set a custom start state + // this simplifies planning for the orientation constraint bellow + geometry_msgs::Pose start_pose; + start_pose.orientation.w = 1.0; + start_pose.position.x = 0.3; + start_pose.position.y = 0.0; + start_pose.position.z = 0.6; + planAndMoveToPose(start_pose); + + //////////////////////////////////////////////////////////////////// // Test setting target pose with eigen and with geometry_msgs geometry_msgs::Pose target_pose; target_pose.orientation.w = 1.0; - target_pose.position.x = 0.28; - target_pose.position.y = -0.2; - target_pose.position.z = 0.5; + target_pose.position.x = 0.3; + target_pose.position.y = -0.3; + target_pose.position.z = 0.6; // convert to eigen Eigen::Isometry3d eigen_target_pose; @@ -174,46 +185,7 @@ TEST_F(MoveGroupTestFixture, MoveToPoseTest) // expect that they are identical testEigenPose(eigen_target_pose, eigen_set_target_pose); - // plan and move - planAndMove(); - - // get the pose after the movement - testPose(eigen_target_pose); -} - -TEST_F(MoveGroupTestFixture, JointSpaceGoalTest) -{ - SCOPED_TRACE("JointSpaceGoalTest"); - - // Next get the current set of joint values for the group. - std::vector plan_joint_positions; - move_group_->getCurrentState()->copyJointGroupPositions( - move_group_->getCurrentState()->getJointModelGroup(PLANNING_GROUP), plan_joint_positions); - - // Now, let's modify the joint positions. (radians) - ASSERT_EQ(plan_joint_positions.size(), std::size_t(7)); - plan_joint_positions = { 1.2, -1.0, -0.1, -2.4, 0.0, 1.5, 0.6 }; - move_group_->setJointValueTarget(plan_joint_positions); - - // plan and move - planAndMove(); - - // test that we moved to the expected joint positions - testJointPositions(plan_joint_positions); -} - -TEST_F(MoveGroupTestFixture, PathConstraintTest) -{ - SCOPED_TRACE("PathConstraintTest"); - - // set a custom start state - geometry_msgs::Pose start_pose; - start_pose.orientation.w = 1.0; - start_pose.position.x = 0.55; - start_pose.position.y = -0.05; - start_pose.position.z = 0.8; - planAndMoveToPose(start_pose); - + //////////////////////////////////////////////////////////////////// // create an orientation constraint moveit_msgs::OrientationConstraint ocm; ocm.link_name = move_group_->getEndEffectorLink(); @@ -227,72 +199,7 @@ TEST_F(MoveGroupTestFixture, PathConstraintTest) test_constraints.orientation_constraints.push_back(ocm); move_group_->setPathConstraints(test_constraints); - // move to a custom target pose - geometry_msgs::Pose target_pose; - target_pose.orientation.w = 1.0; - target_pose.position.x = 0.28; - target_pose.position.y = -0.2; - target_pose.position.z = 0.5; - planAndMoveToPose(target_pose); - - // clear path constraints - move_group_->clearPathConstraints(); - - // get the pose after the movement - testPose(target_pose); -} - -TEST_F(MoveGroupTestFixture, CartPathTest) -{ - SCOPED_TRACE("CartPathTest"); - - // set a custom start state - geometry_msgs::Pose start_pose; - start_pose.orientation.w = 1.0; - start_pose.position.x = 0.55; - start_pose.position.y = -0.05; - start_pose.position.z = 0.8; - planAndMoveToPose(start_pose); - - std::vector waypoints; - waypoints.push_back(start_pose); - - geometry_msgs::Pose target_waypoint = start_pose; - target_waypoint.position.z -= 0.2; - waypoints.push_back(target_waypoint); // down - - target_waypoint.position.y -= 0.2; - waypoints.push_back(target_waypoint); // right - - target_waypoint.position.z += 0.2; - target_waypoint.position.y += 0.2; - target_waypoint.position.x -= 0.2; - waypoints.push_back(target_waypoint); // up and left - - moveit_msgs::RobotTrajectory trajectory; - const double jump_threshold = 0.0; - const double eef_step = 0.01; - move_group_->computeCartesianPath(waypoints, eef_step, jump_threshold, trajectory); - - // Execute trajectory - EXPECT_EQ(move_group_->execute(trajectory), moveit::planning_interface::MoveItErrorCode::SUCCESS); - - // get the pose after the movement - testPose(target_waypoint); -} - -TEST_F(MoveGroupTestFixture, CollisionObjectsTest) -{ - SCOPED_TRACE("CollisionObjectsTest"); - - // set a custom start state - geometry_msgs::Pose start_pose; - start_pose.orientation.w = 1.0; - start_pose.position.x = 0.28; - start_pose.position.y = -0.2; - start_pose.position.z = 0.5; - planAndMoveToPose(start_pose); - + //////////////////////////////////////////////////////////////////// // Define a collision object ROS message. moveit_msgs::CollisionObject collision_object; collision_object.header.frame_id = move_group_->getPlanningFrame(); @@ -304,16 +211,16 @@ TEST_F(MoveGroupTestFixture, CollisionObjectsTest) shape_msgs::SolidPrimitive primitive; primitive.type = primitive.BOX; primitive.dimensions.resize(3); - primitive.dimensions[0] = 0.4; - primitive.dimensions[1] = 0.1; - primitive.dimensions[2] = 0.1; + primitive.dimensions[0] = 0.1; + primitive.dimensions[1] = 1.0; + primitive.dimensions[2] = 1.0; // Define a pose for the box (specified relative to frame_id) geometry_msgs::Pose box_pose; box_pose.orientation.w = 1.0; - box_pose.position.x = 0.4; - box_pose.position.y = -0.2; - box_pose.position.z = 0.8; + box_pose.position.x = 0.5; + box_pose.position.y = 0.0; + box_pose.position.z = 0.5; collision_object.primitives.push_back(primitive); collision_object.primitive_poses.push_back(box_pose); @@ -325,16 +232,15 @@ TEST_F(MoveGroupTestFixture, CollisionObjectsTest) // Now, let's add the collision object into the world planning_scene_interface_.addCollisionObjects(collision_objects); - // plan trajectory avoiding object - geometry_msgs::Pose target_pose; - target_pose.orientation.w = 0.0; - target_pose.position.x = 0.4; - target_pose.position.y = -0.4; - target_pose.position.z = 0.7; - planAndMoveToPose(target_pose); + //////////////////////////////////////////////////////////////////// + // plan and move + planAndMove(); // get the pose after the movement - testPose(target_pose); + testPose(eigen_target_pose); + + // clear path constraints + move_group_->clearPathConstraints(); // attach and detach collision object EXPECT_TRUE(move_group_->attachObject(collision_object.id)); @@ -343,13 +249,67 @@ TEST_F(MoveGroupTestFixture, CollisionObjectsTest) EXPECT_EQ(planning_scene_interface_.getAttachedObjects().size(), std::size_t(0)); // remove object from world - std::vector object_ids; - object_ids.push_back(collision_object.id); + const std::vector object_ids = { collision_object.id }; EXPECT_EQ(planning_scene_interface_.getObjects().size(), std::size_t(1)); planning_scene_interface_.removeCollisionObjects(object_ids); EXPECT_EQ(planning_scene_interface_.getObjects().size(), std::size_t(0)); } +TEST_F(MoveGroupTestFixture, CartPathTest) +{ + SCOPED_TRACE("CartPathTest"); + + // Plan from current pose + const geometry_msgs::PoseStamped start_pose = move_group_->getCurrentPose(); + + std::vector waypoints; + waypoints.push_back(start_pose.pose); + + geometry_msgs::Pose target_waypoint = start_pose.pose; + target_waypoint.position.z -= 0.2; + waypoints.push_back(target_waypoint); // down + + target_waypoint.position.y -= 0.2; + waypoints.push_back(target_waypoint); // right + + target_waypoint.position.z += 0.2; + target_waypoint.position.y += 0.2; + target_waypoint.position.x -= 0.2; + waypoints.push_back(target_waypoint); // up and left + + moveit_msgs::RobotTrajectory trajectory; + const auto jump_threshold = 0.0; + const auto eef_step = 0.01; + move_group_->computeCartesianPath(waypoints, eef_step, jump_threshold, trajectory); + + // Execute trajectory + EXPECT_EQ(move_group_->execute(trajectory), moveit::planning_interface::MoveItErrorCode::SUCCESS); + + // get the pose after the movement + testPose(target_waypoint); +} + +TEST_F(MoveGroupTestFixture, JointSpaceGoalTest) +{ + SCOPED_TRACE("JointSpaceGoalTest"); + + // Next get the current set of joint values for the group. + std::vector plan_joint_positions; + move_group_->getCurrentState()->copyJointGroupPositions( + move_group_->getCurrentState()->getJointModelGroup(PLANNING_GROUP), plan_joint_positions); + + // Now, let's modify the joint positions. (radians) + ASSERT_EQ(plan_joint_positions.size(), std::size_t(7)); + plan_joint_positions = { 1.2, -1.0, -0.1, -2.4, 0.0, 1.5, 0.6 }; + move_group_->setJointValueTarget(plan_joint_positions); + + // plan and move + planAndMove(); + + // test that we moved to the expected joint positions + testJointPositions(plan_joint_positions); +} + int main(int argc, char** argv) { ros::init(argc, argv, "move_group_interface_cpp_test"); From 5a1da2ee5e234160abfafb8538efb2afb4848513 Mon Sep 17 00:00:00 2001 From: Immanuel Martini <35950815+martiniil@users.noreply.github.com> Date: Wed, 20 Jan 2021 19:57:56 +0100 Subject: [PATCH 084/179] Use kinematics solver timeout if not specified otherwise (#2489) --- .../pilz_industrial_motion_planner/trajectory_functions.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_functions.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_functions.h index f31bbada01..6a23e3f41e 100644 --- a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_functions.h +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/trajectory_functions.h @@ -61,18 +61,18 @@ namespace pilz_industrial_motion_planner * @param solution: solution of IK * @param check_self_collision: true to enable self collision checking after IK * computation - * @param max_attempt: maximal attempts of IK + * @param timeout: timeout for IK, if not set the default solver timeout is used * @return true if succeed */ bool computePoseIK(const robot_model::RobotModelConstPtr& robot_model, const std::string& group_name, const std::string& link_name, const Eigen::Isometry3d& pose, const std::string& frame_id, const std::map& seed, std::map& solution, - bool check_self_collision = true, const double timeout = 0.1); + bool check_self_collision = true, const double timeout = 0.0); bool computePoseIK(const robot_model::RobotModelConstPtr& robot_model, const std::string& group_name, const std::string& link_name, const geometry_msgs::Pose& pose, const std::string& frame_id, const std::map& seed, std::map& solution, - bool check_self_collision = true, const double timeout = 0.1); + bool check_self_collision = true, const double timeout = 0.0); /** * @brief compute the pose of a link at give robot state From 1ada1db81b5b8ea626430d8dfa183364f1ae7d27 Mon Sep 17 00:00:00 2001 From: AndyZe Date: Fri, 22 Jan 2021 08:20:58 -0600 Subject: [PATCH 085/179] Do not break out of loop -- need to update low pass filters (#2496) --- moveit_ros/moveit_servo/src/servo_calcs.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index e94800d9d7..5190b3889d 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -231,14 +231,10 @@ void ServoCalcs::mainCalcLoop() // lock the input state mutex std::unique_lock input_lock(input_mutex_); - // low latency mode + // low latency mode -- begin calculations as soon as a new command is received. if (parameters_.low_latency_mode) { input_cv_.wait(input_lock, [this] { return (new_input_cmd_ || stop_requested_); }); - - // break out of the loop if stop was requested - if (stop_requested_) - break; } // reset new_input_cmd_ flag From 248b397a6af24a43a017c2d5b905b5a2bb0a0a98 Mon Sep 17 00:00:00 2001 From: AndyZe Date: Fri, 22 Jan 2021 08:21:24 -0600 Subject: [PATCH 086/179] Protect paused_ flag, for thread safety (#2494) --- moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h | 2 +- moveit_ros/moveit_servo/src/servo_calcs.cpp | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h index 055335e3f6..5303b8a296 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h @@ -279,7 +279,7 @@ class ServoCalcs // Status StatusCode status_ = StatusCode::NO_WARNING; - bool paused_ = false; + std::atomic paused_; bool twist_command_is_stale_ = false; bool joint_command_is_stale_ = false; bool ok_to_publish_ = false; diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index 5190b3889d..2857ef13bf 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -86,7 +86,11 @@ geometry_msgs::TransformStamped convertIsometryToTransform(const Eigen::Isometry // Constructor for the class that handles servoing calculations ServoCalcs::ServoCalcs(ros::NodeHandle& nh, ServoParameters& parameters, const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor) - : nh_(nh), parameters_(parameters), planning_scene_monitor_(planning_scene_monitor), stop_requested_(true) + : nh_(nh) + , parameters_(parameters) + , planning_scene_monitor_(planning_scene_monitor) + , stop_requested_(true) + , paused_(false) { // MoveIt Setup current_state_ = planning_scene_monitor_->getStateMonitor()->getCurrentState(); From bb54b12c18fc9c3d526e17bd3ca7e14128d2e608 Mon Sep 17 00:00:00 2001 From: Christian Henkel Date: Wed, 27 Jan 2021 19:50:34 +0100 Subject: [PATCH 087/179] Add missing dependency on joint_limits_interface (#2487) --- moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt | 1 + moveit_planners/pilz_industrial_motion_planner/package.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt b/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt index 05ed96c791..5f9be95485 100644 --- a/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt +++ b/moveit_planners/pilz_industrial_motion_planner/CMakeLists.txt @@ -9,6 +9,7 @@ add_definitions(-Wno-unused-parameter) find_package(catkin REQUIRED COMPONENTS eigen_conversions + joint_limits_interface kdl_conversions moveit_core moveit_msgs diff --git a/moveit_planners/pilz_industrial_motion_planner/package.xml b/moveit_planners/pilz_industrial_motion_planner/package.xml index d69a541779..dacb721b00 100644 --- a/moveit_planners/pilz_industrial_motion_planner/package.xml +++ b/moveit_planners/pilz_industrial_motion_planner/package.xml @@ -19,6 +19,7 @@ catkin eigen_conversions + joint_limits_interface kdl_conversions moveit_ros_planning_interface moveit_msgs From 741a9a3521087c96181647d5026addf478d1b8c9 Mon Sep 17 00:00:00 2001 From: Jere Liukkonen Date: Thu, 4 Feb 2021 09:35:40 -0700 Subject: [PATCH 088/179] Refactor Servo velocity bounds enforcement (#2471) * Refactor/fix Servo enforceVelLimits function to utilize joint velocity limits correctly. * Use uniform scaling factor instead of joint specific velocity bounds. * Move joint increment outside of if() * Add friend test for velocity limits * Clean up debug code, clang format * Test for negative velocities, too * Apply velocity scaling correctly and skip clamping zero velocities. * Improve enforceVelLimits unit tests. * Use EXPECT_NEAR in the new unit test Co-authored-by: AndyZe --- moveit_ros/moveit_servo/CMakeLists.txt | 20 ++--- .../moveit_servo/include/moveit_servo/servo.h | 8 ++ .../include/moveit_servo/servo_calcs.h | 3 + moveit_ros/moveit_servo/src/servo_calcs.cpp | 56 +++---------- ...latency_test.cpp => basic_servo_tests.cpp} | 78 ++++++++++++++++++- ...tency_test.test => basic_servo_tests.test} | 2 +- 6 files changed, 108 insertions(+), 59 deletions(-) rename moveit_ros/moveit_servo/test/{servo_low_latency_test.cpp => basic_servo_tests.cpp} (72%) rename moveit_ros/moveit_servo/test/{servo_low_latency_test.test => basic_servo_tests.test} (86%) diff --git a/moveit_ros/moveit_servo/CMakeLists.txt b/moveit_ros/moveit_servo/CMakeLists.txt index 585d660f4c..5228a8559e 100644 --- a/moveit_ros/moveit_servo/CMakeLists.txt +++ b/moveit_ros/moveit_servo/CMakeLists.txt @@ -165,22 +165,22 @@ install(DIRECTORY config DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) if(CATKIN_ENABLE_TESTING) find_package(rostest REQUIRED) - # servo_cpp_interface - add_rostest_gtest(servo_cpp_interface_test - test/servo_cpp_interface_test.test - test/servo_cpp_interface_test.cpp + # basic functionality + add_rostest_gtest(basic_servo_tests + test/basic_servo_tests.test + test/basic_servo_tests.cpp ) - target_link_libraries(servo_cpp_interface_test + target_link_libraries(basic_servo_tests ${SERVO_LIB_NAME} ${catkin_LIBRARIES} ) - # low_latency - add_rostest_gtest(servo_low_latency_test - test/servo_low_latency_test.test - test/servo_low_latency_test.cpp + # servo_cpp_interface + add_rostest_gtest(servo_cpp_interface_test + test/servo_cpp_interface_test.test + test/servo_cpp_interface_test.cpp ) - target_link_libraries(servo_low_latency_test + target_link_libraries(servo_cpp_interface_test ${SERVO_LIB_NAME} ${catkin_LIBRARIES} ) diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo.h b/moveit_ros/moveit_servo/include/moveit_servo/servo.h index aeb61dab2b..8258c72923 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo.h @@ -38,12 +38,17 @@ #pragma once +// System #include +// MoveIt #include #include #include +// testing +#include + namespace moveit_servo { /** @@ -93,6 +98,9 @@ class Servo servo_calcs_->changeRobotLinkCommandFrame(new_command_frame); } + // Give test access to private/protected methods + friend class ServoFixture; + private: bool readParameters(); diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h index 5303b8a296..437700c4d5 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h @@ -104,6 +104,9 @@ class ServoCalcs */ void changeRobotLinkCommandFrame(const std::string& new_command_frame); + // Give test access to private/protected methods + friend class ServoFixture; + private: /** \brief Run the main calculation loop */ void mainCalcLoop(); diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index 2857ef13bf..6270c507eb 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -758,58 +758,26 @@ double ServoCalcs::velocityScalingFactorForSingularity(const Eigen::VectorXd& co void ServoCalcs::enforceVelLimits(Eigen::ArrayXd& delta_theta) { + // Convert to joint angle velocities for checking and applying joint specific velocity limits. Eigen::ArrayXd velocity = delta_theta / parameters_.publish_period; - std::size_t joint_delta_index = 0; - // Track the smallest velocity scaling factor required, across all joints - double velocity_limit_scaling_factor = 1; - - for (auto joint : joint_model_group_->getActiveJointModels()) + std::size_t joint_delta_index{ 0 }; + double velocity_scaling_factor{ 1.0 }; + for (const moveit::core::JointModel* joint : joint_model_group_->getActiveJointModels()) { - // Some joints do not have bounds defined - const auto bounds = joint->getVariableBounds(joint->getName()); - - if (bounds.velocity_bounded_) + const auto& bounds = joint->getVariableBounds(joint->getName()); + if (bounds.velocity_bounded_ && velocity(joint_delta_index) != 0.0) { - velocity(joint_delta_index) = delta_theta(joint_delta_index) / parameters_.publish_period; - - bool clip_velocity = false; - double velocity_limit = 0.0; - if (velocity(joint_delta_index) < bounds.min_velocity_) - { - clip_velocity = true; - velocity_limit = bounds.min_velocity_; - } - else if (velocity(joint_delta_index) > bounds.max_velocity_) - { - clip_velocity = true; - velocity_limit = bounds.max_velocity_; - } - - // Apply velocity bounds - if (clip_velocity) - { - const double scaling_factor = - fabs(velocity_limit * parameters_.publish_period) / fabs(delta_theta(joint_delta_index)); - - // Store the scaling factor if it's the smallest yet - if (scaling_factor < velocity_limit_scaling_factor) - velocity_limit_scaling_factor = scaling_factor; - } + const double unbounded_velocity = velocity(joint_delta_index); + // Clamp each joint velocity to a joint specific [min_velocity, max_velocity] range. + const auto bounded_velocity = std::min(std::max(unbounded_velocity, bounds.min_velocity_), bounds.max_velocity_); + velocity_scaling_factor = std::min(velocity_scaling_factor, bounded_velocity / unbounded_velocity); } ++joint_delta_index; } - // Apply the velocity scaling to all joints - if (velocity_limit_scaling_factor < 1) - { - for (joint_delta_index = 0; joint_delta_index < joint_model_group_->getActiveJointModels().size(); - ++joint_delta_index) - { - delta_theta(joint_delta_index) = velocity_limit_scaling_factor * delta_theta(joint_delta_index); - velocity(joint_delta_index) = velocity_limit_scaling_factor * velocity(joint_delta_index); - } - } + // Convert back to joint angle increments. + delta_theta = velocity_scaling_factor * velocity * parameters_.publish_period; } bool ServoCalcs::enforcePositionLimits() diff --git a/moveit_ros/moveit_servo/test/servo_low_latency_test.cpp b/moveit_ros/moveit_servo/test/basic_servo_tests.cpp similarity index 72% rename from moveit_ros/moveit_servo/test/servo_low_latency_test.cpp rename to moveit_ros/moveit_servo/test/basic_servo_tests.cpp index 011e7bab1b..b73e59c5c6 100644 --- a/moveit_ros/moveit_servo/test/servo_low_latency_test.cpp +++ b/moveit_ros/moveit_servo/test/basic_servo_tests.cpp @@ -32,11 +32,11 @@ * POSSIBILITY OF SUCH DAMAGE. *********************************************************************/ -/* Author: Tyler Weaver - Desc: Test for the low latency mode of servo +/* Author: Tyler Weaver, Andy Zelenak + Desc: Basic functionality tests */ -// C++ +// System #include // ROS @@ -49,7 +49,7 @@ #include #include -static const std::string LOGNAME = "servo_low_latency_test"; +static const std::string LOGNAME = "basic_servo_tests"; namespace moveit_servo { @@ -82,6 +82,10 @@ class ServoFixture : public ::testing::Test } protected: + void enforceVelLimits(Eigen::ArrayXd& delta_theta) + { + servo_->servo_calcs_->enforceVelLimits(delta_theta); + } ros::NodeHandle nh_{ "~" }; planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_; moveit_servo::ServoPtr servo_; @@ -170,6 +174,72 @@ TEST_F(ServoFixture, SendJointServoTest) EXPECT_LT(received_count, num_commands + 20); servo_->setPaused(true); } + +// This a friend test of a private member function +TEST_F(ServoFixture, EnforceVelLimitsTest) +{ + auto parameters = servo_->getParameters(); + const double publish_period = parameters.publish_period; + + // Request joint angle changes that are too fast, given the control period in servo settings YAML file. + Eigen::ArrayXd delta_theta(7); + delta_theta[0] = 0; // rad + delta_theta[1] = 0.01; + delta_theta[2] = 0.02; + delta_theta[3] = 0.03; + delta_theta[4] = 0.04; + delta_theta[5] = 0.05; + delta_theta[6] = 0.06; + + // Store the original joint commands for comparison before applying velocity scaling. + Eigen::ArrayXd orig_delta_theta = delta_theta; + enforceVelLimits(delta_theta); + + // From Panda arm MoveIt joint_limits.yaml. The largest velocity limits for a joint. + const double panda_max_joint_vel = 2.610; // rad/s + const double velocity_scaling_factor = panda_max_joint_vel / (orig_delta_theta.maxCoeff() / publish_period); + const double tolerance = 5e-3; + for (int i = 0; i < 7; ++i) + { + EXPECT_NEAR(orig_delta_theta(i) * velocity_scaling_factor, delta_theta(i), tolerance); + } + + // Now, negative joint angle deltas. Some will result to velocities + // greater than the arm joint velocity limits. + delta_theta[0] = 0; // rad + delta_theta[1] = -0.01; + delta_theta[2] = -0.02; + delta_theta[3] = -0.03; + delta_theta[4] = -0.04; + delta_theta[5] = -0.05; + delta_theta[6] = -0.06; + + // Store the original joint commands for comparison before applying velocity scaling. + orig_delta_theta = delta_theta; + enforceVelLimits(delta_theta); + for (int i = 0; i < 7; ++i) + { + EXPECT_NEAR(orig_delta_theta(i) * velocity_scaling_factor, delta_theta(i), tolerance); + } + + // Final test with joint angle deltas that will result in velocities + // below the lowest Panda arm joint velocity limit. + delta_theta[0] = 0; // rad + delta_theta[1] = -0.013; + delta_theta[2] = 0.023; + delta_theta[3] = -0.004; + delta_theta[4] = 0.021; + delta_theta[5] = 0.012; + delta_theta[6] = 0.0075; + + // Store the original joint commands for comparison before applying velocity scaling. + orig_delta_theta = delta_theta; + enforceVelLimits(delta_theta); + for (int i = 0; i < 7; ++i) + { + EXPECT_NEAR(orig_delta_theta(i), delta_theta(i), tolerance); + } +} } // namespace moveit_servo int main(int argc, char** argv) diff --git a/moveit_ros/moveit_servo/test/servo_low_latency_test.test b/moveit_ros/moveit_servo/test/basic_servo_tests.test similarity index 86% rename from moveit_ros/moveit_servo/test/servo_low_latency_test.test rename to moveit_ros/moveit_servo/test/basic_servo_tests.test index 6df90be617..930d0d0e41 100644 --- a/moveit_ros/moveit_servo/test/servo_low_latency_test.test +++ b/moveit_ros/moveit_servo/test/basic_servo_tests.test @@ -11,7 +11,7 @@ - + From e4c15255863511d8f3106ec7d6fc190bbba795bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Tue, 16 Feb 2021 15:43:22 +0100 Subject: [PATCH 089/179] Servo: add missing include (#2519) --- moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h index 437700c4d5..dddf2ef8bc 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/servo_calcs.h @@ -42,6 +42,7 @@ #include #include #include +#include // ROS #include From 36f4ad2b4a66a8314f440c3ef25ce48839564fc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Wed, 17 Feb 2021 11:38:08 +0100 Subject: [PATCH 090/179] It's not an error not to define a plugin (#2521) --- .../occupancy_map_monitor/src/occupancy_map_monitor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/moveit_ros/occupancy_map_monitor/src/occupancy_map_monitor.cpp b/moveit_ros/occupancy_map_monitor/src/occupancy_map_monitor.cpp index 441538e468..34a2581ff1 100644 --- a/moveit_ros/occupancy_map_monitor/src/occupancy_map_monitor.cpp +++ b/moveit_ros/occupancy_map_monitor/src/occupancy_map_monitor.cpp @@ -174,7 +174,9 @@ void OccupancyMapMonitor::initialize() } } else - ROS_ERROR("Failed to find 3D sensor plugin parameters for octomap generation"); + { + ROS_INFO("No 3D sensor plugin(s) defined for octomap updates"); + } /* advertise a service for loading octomaps from disk */ save_map_srv_ = nh_.advertiseService("save_map", &OccupancyMapMonitor::saveMapCallback, this); From 89214a5706234bb8ebdbd5eff3e5e24135bf5767 Mon Sep 17 00:00:00 2001 From: jschleicher Date: Mon, 22 Feb 2021 11:01:53 +0100 Subject: [PATCH 091/179] Update README.md (#2525) --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fcfe9e8a33..1283b78954 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,10 @@ Currently we support ROS Indigo, Kinetic, and Melodic. ## Branches Policy -We develop all new 1.0 features on ``master``. The ``*-devel`` branches correspond to -released and stable versions of MoveIt for specific distributions of ROS. -Bug fixes occationally get backported to these released versions of MoveIt. -The next version of MoveIt 1.0 will be branched to ``noetic-devel`` around May 2020. +- We develop latest features on ``master``. +- The ``*-devel`` branches correspond to released and stable versions of MoveIt for specific distributions of ROS. +- Bug fixes occasionally get backported to these released versions of MoveIt. +- For MoveIt 2 development, see [moveit2](https://github.com/ros-planning/moveit2). For MoveIt 2.0 development, see [moveit2](https://github.com/ros-planning/moveit2). From 8cd6d7bd56d261daf75e6a5712358b34641bd546 Mon Sep 17 00:00:00 2001 From: AndyZe Date: Tue, 23 Feb 2021 13:58:45 -0600 Subject: [PATCH 092/179] Update doxygen comments for distance() and interpolate() (#2528) --- .../include/moveit/robot_model/robot_model.h | 10 +++++ .../include/moveit/robot_state/robot_state.h | 38 ++++++++++++++----- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/moveit_core/robot_model/include/moveit/robot_model/robot_model.h b/moveit_core/robot_model/include/moveit/robot_model/robot_model.h index e23a91a99d..04076880e0 100644 --- a/moveit_core/robot_model/include/moveit/robot_model/robot_model.h +++ b/moveit_core/robot_model/include/moveit/robot_model/robot_model.h @@ -337,7 +337,17 @@ class RobotModel } double getMaximumExtent(const JointBoundsVector& active_joint_bounds) const; + /** \brief Return the sum of joint distances between two states. Only considers active joints. */ double distance(const double* state1, const double* state2) const; + + /** + * Interpolate between "from" state, to "to" state. Mimic joints are correctly updated. + * + * @param from interpolate from this state + * @param to to this state + * @param t a fraction in the range [0 1]. If 1, the result matches "to" state exactly. + * @param state holds the result + */ void interpolate(const double* from, const double* to, double t, double* state) const; /** \name Access to joint groups diff --git a/moveit_core/robot_state/include/moveit/robot_state/robot_state.h b/moveit_core/robot_state/include/moveit/robot_state/robot_state.h index 5c8596fbbb..2df3b232d7 100644 --- a/moveit_core/robot_state/include/moveit/robot_state/robot_state.h +++ b/moveit_core/robot_state/include/moveit/robot_state/robot_state.h @@ -1521,32 +1521,52 @@ as the new values that correspond to the group */ * @{ */ + /** \brief Return the sum of joint distances to "other" state. Only considers active joints. */ double distance(const RobotState& other) const { return robot_model_->distance(position_, other.getVariablePositions()); } + /** \brief Return the sum of joint distances to "other" state. Only considers active joints. */ double distance(const RobotState& other, const JointModelGroup* joint_group) const; + /** \brief Return the sum of joint distances to "other" state. Only considers active joints. */ double distance(const RobotState& other, const JointModel* joint) const { const int idx = joint->getFirstVariableIndex(); return joint->distance(position_ + idx, other.position_ + idx); } - /** \brief Interpolate from this state towards state \e to, at time \e t in [0,1]. - The result is stored in \e state, mimic joints are correctly updated and flags are set - so that FK is recomputed when needed. */ + /** + * Interpolate towards "to" state. Mimic joints are correctly updated and flags are set so that FK is recomputed + * when needed. + * + * @param to interpolate to this state + * @param t a fraction in the range [0 1]. If 1, the result matches "to" state exactly. + * @param state holds the result + */ void interpolate(const RobotState& to, double t, RobotState& state) const; - /** \brief Interpolate from this state towards \e to, at time \e t in [0,1], but only for the joints in the - specified group. If mimic joints need to be updated, they are updated accordingly. Flags are set so that FK - computation is triggered when needed. */ + /** + * Interpolate towards "to" state, but only for the joints in the specified group. Mimic joints are correctly updated + * and flags are set so that FK is recomputed when needed. + * + * @param to interpolate to this state + * @param t a fraction in the range [0 1]. If 1, the result matches "to" state exactly. + * @param state holds the result + * @param joint_group interpolate only for the joints in this group + */ void interpolate(const RobotState& to, double t, RobotState& state, const JointModelGroup* joint_group) const; - /** \brief Update \e state by interpolating form this state towards \e to, at time \e t in [0,1] but only for - the joint \e joint. If there are joints that mimic this joint, they are updated. Flags are set so that - FK computation is triggered as needed. */ + /** + * Interpolate towards "to" state, but only for a single joint. Mimic joints are correctly updated + * and flags are set so that FK is recomputed when needed. + * + * @param to interpolate to this state + * @param t a fraction in the range [0 1]. If 1, the result matches "to" state exactly. + * @param state holds the result + * @param joint interpolate only for this joint + */ void interpolate(const RobotState& to, double t, RobotState& state, const JointModel* joint) const { const int idx = joint->getFirstVariableIndex(); From e3beb96ee426de0680a5bc53bb9920a1c65b7469 Mon Sep 17 00:00:00 2001 From: Peter Mitrano Date: Thu, 25 Feb 2021 11:51:15 -0500 Subject: [PATCH 093/179] Add debugging log statement for a common error (#2509) add debugging informative log statement for a common error Co-authored-by: Peter Mitrano --- .../move_group_interface/src/move_group_interface.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp b/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp index b98a476147..193837384c 100644 --- a/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp +++ b/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp @@ -1612,8 +1612,14 @@ bool moveit::planning_interface::MoveGroupInterface::setNamedTarget(const std::s bool moveit::planning_interface::MoveGroupInterface::setJointValueTarget(const std::vector& joint_values) { - if (joint_values.size() != impl_->getJointModelGroup()->getVariableCount()) + auto const n_group_joints = impl_->getJointModelGroup()->getVariableCount(); + if (joint_values.size() != n_group_joints) + { + ROS_DEBUG_STREAM_NAMED(LOGNAME, "Provided joint value list has length " << joint_values.size() << " but group " + << impl_->getJointModelGroup()->getName() + << " has " << n_group_joints << " joints"); return false; + } impl_->setTargetType(JOINT); impl_->getJointStateTarget().setJointGroupPositions(impl_->getJointModelGroup(), joint_values); return impl_->getJointStateTarget().satisfiesBounds(impl_->getJointModelGroup(), impl_->getGoalJointTolerance()); From 5781a59b9e174143b91eaf494a034569c72dfb32 Mon Sep 17 00:00:00 2001 From: Peter Mitrano Date: Mon, 1 Mar 2021 15:01:20 -0500 Subject: [PATCH 094/179] add get_active_joint_names (#2533) add get_active_joint_names and getActiveJointModelNames to Python and C++, respectively. To keep calling costs constant we add the additional vector to the RobotModel class. Co-authored-by: Peter Mitrano --- .../src/moveit_commander/robot.py | 21 +++++++++++++++---- .../include/moveit/robot_model/robot_model.h | 9 ++++++++ moveit_core/robot_model/src/robot_model.cpp | 1 + .../src/wrap_python_robot_interface.cpp | 16 ++++++++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/moveit_commander/src/moveit_commander/robot.py b/moveit_commander/src/moveit_commander/robot.py index a9297178f4..413f6d1774 100644 --- a/moveit_commander/src/moveit_commander/robot.py +++ b/moveit_commander/src/moveit_commander/robot.py @@ -194,12 +194,25 @@ def get_root_link(self): """Get the name of the root link of the robot model """ return self._r.get_robot_root_link() + def get_active_joint_names(self, group=None): + """ + Get the names of all the movable joints that make up a group. + If no group name is specified, all joints in the robot model are returned. + Excludes fixed and mimic joints. + """ + if group is not None: + if self.has_group(group): + return self._r.get_group_active_joint_names(group) + else: + raise MoveItCommanderException("There is no group named %s" % group) + else: + return self._r.get_active_joint_names() + def get_joint_names(self, group=None): """ - Get the names of all the movable joints that make up a group - (mimic joints and fixed joints are excluded). If no group name is - specified, all joints in the robot model are returned, including - fixed and mimic joints. + Get the names of all the movable joints that make up a group. + If no group name is specified, all joints in the robot model are returned. + Includes fixed and mimic joints. """ if group is not None: if self.has_group(group): diff --git a/moveit_core/robot_model/include/moveit/robot_model/robot_model.h b/moveit_core/robot_model/include/moveit/robot_model/robot_model.h index 04076880e0..f79317bd73 100644 --- a/moveit_core/robot_model/include/moveit/robot_model/robot_model.h +++ b/moveit_core/robot_model/include/moveit/robot_model/robot_model.h @@ -164,6 +164,12 @@ class RobotModel return active_joint_model_vector_const_; } + /** \brief Get the array of active joint names, in the order they appear in the robot state. */ + const std::vector& getActiveJointModelNames() const + { + return active_joint_model_names_vector_; + } + /** \brief Get the array of joints that are active (not fixed, not mimic) in this model */ const std::vector& getActiveJointModels() { @@ -514,6 +520,9 @@ class RobotModel /** \brief The vector of joints in the model, in the order they appear in the state vector */ std::vector active_joint_model_vector_; + /** \brief The vector of joint names that corresponds to active_joint_model_vector_ */ + std::vector active_joint_model_names_vector_; + /** \brief The vector of joints in the model, in the order they appear in the state vector */ std::vector active_joint_model_vector_const_; diff --git a/moveit_core/robot_model/src/robot_model.cpp b/moveit_core/robot_model/src/robot_model.cpp index 2835352d83..7d8dd786fe 100644 --- a/moveit_core/robot_model/src/robot_model.cpp +++ b/moveit_core/robot_model/src/robot_model.cpp @@ -271,6 +271,7 @@ void RobotModel::buildJointInfo() { active_joint_model_start_index_.push_back(variable_count_); active_joint_model_vector_.push_back(joint_model_vector_[i]); + active_joint_model_names_vector_.push_back(joint_model_vector_[i]->getName()); active_joint_model_vector_const_.push_back(joint_model_vector_[i]); active_joint_models_bounds_.push_back(&joint_model_vector_[i]->getVariableBounds()); } diff --git a/moveit_ros/planning_interface/robot_interface/src/wrap_python_robot_interface.cpp b/moveit_ros/planning_interface/robot_interface/src/wrap_python_robot_interface.cpp index 126d7f0cd3..86c6be8ac8 100644 --- a/moveit_ros/planning_interface/robot_interface/src/wrap_python_robot_interface.cpp +++ b/moveit_ros/planning_interface/robot_interface/src/wrap_python_robot_interface.cpp @@ -72,6 +72,20 @@ class RobotInterfacePython : protected py_bindings_tools::ROScppInitializer return robot_model_->getName().c_str(); } + bp::list getActiveJointNames() const + { + return py_bindings_tools::listFromString(robot_model_->getActiveJointModelNames()); + } + + bp::list getGroupActiveJointNames(const std::string& group) const + { + const moveit::core::JointModelGroup* jmg = robot_model_->getJointModelGroup(group); + if (jmg) + return py_bindings_tools::listFromString(jmg->getActiveJointModelNames()); + else + return bp::list(); + } + bp::list getJointNames() const { return py_bindings_tools::listFromString(robot_model_->getJointModelNames()); @@ -380,6 +394,8 @@ static void wrap_robot_interface() robot_class.def("get_joint_names", &RobotInterfacePython::getJointNames); robot_class.def("get_group_joint_names", &RobotInterfacePython::getGroupJointNames); + robot_class.def("get_active_joint_names", &RobotInterfacePython::getActiveJointNames); + robot_class.def("get_group_active_joint_names", &RobotInterfacePython::getGroupActiveJointNames); robot_class.def("get_group_default_states", &RobotInterfacePython::getDefaultStateNames); robot_class.def("get_group_joint_tips", &RobotInterfacePython::getGroupJointTips); robot_class.def("get_group_names", &RobotInterfacePython::getGroupNames); From 9cbfd873e1520a79eebafbb1158ce0ff92eecb21 Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Tue, 2 Mar 2021 18:07:15 +0900 Subject: [PATCH 095/179] Add utility functions to Python PSI (#2532) --- .../planning_scene_interface.py | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/moveit_commander/src/moveit_commander/planning_scene_interface.py b/moveit_commander/src/moveit_commander/planning_scene_interface.py index a2439cc658..be12734fba 100644 --- a/moveit_commander/src/moveit_commander/planning_scene_interface.py +++ b/moveit_commander/src/moveit_commander/planning_scene_interface.py @@ -57,7 +57,12 @@ class PlanningSceneInterface(object): - """ Simple interface to making updates to a planning scene """ + """ + Python interface for a C++ PlanningSceneInterface. + Uses both C++ wrapped methods and scene manipulation topics + to manipulate the PlanningScene managed by the PlanningSceneMonitor. + See wrap_python_planning_scene_interface.cpp for the wrapped methods. + """ def __init__(self, ns="", synchronous=False, service_timeout=5.0): """ Create a planning scene interface; it uses both C++ wrapped methods and scene manipulation topics. """ @@ -88,6 +93,12 @@ def __submit(self, collision_object, attach=False): else: self._pub_co.publish(collision_object) + def add_object(self, collision_object): + """ + Add an object to the planning scene + """ + self.__submit(collision_object, attach=False) + def add_sphere(self, name, pose, radius=1): """ Add a sphere to the planning scene @@ -129,6 +140,12 @@ def add_plane(self, name, pose, normal=(0, 0, 1), offset=0): co.plane_poses = [pose.pose] self.__submit(co, attach=False) + def attach_object(self, attached_collision_object): + """ + Attach an object in the planning scene + """ + self.__submit(attached_collision_object, attach=True) + def attach_mesh( self, link, name, pose=None, filename="", size=(1, 1, 1), touch_links=[] ): @@ -230,6 +247,14 @@ def get_attached_objects(self, object_ids=[]): aobjs[key] = msg return aobjs + def apply_planning_scene(self, planning_scene_message): + """ + Applies the planning scene message. + """ + return self._psi.apply_planning_scene( + conversions.msg_to_string(planning_scene_message) + ) + @staticmethod def __make_existing(name): """ From ede1e7d6db134f0b575190673ebc1428dbd2c872 Mon Sep 17 00:00:00 2001 From: Simon Schmeisser Date: Wed, 3 Mar 2021 11:43:12 +0100 Subject: [PATCH 096/179] thread safety in clear octomap & only update geometry (#2500) The method used UPDATE_SCENE which caused a full scene to be transmitted. But only the octomap is modified, so UPDATE_GEOMETRY suffices. Also add comment about necessary scoping of non-recursive lock. --- .../src/planning_scene_monitor.cpp | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/moveit_ros/planning/planning_scene_monitor/src/planning_scene_monitor.cpp b/moveit_ros/planning/planning_scene_monitor/src/planning_scene_monitor.cpp index b8245766ac..044bd197ea 100644 --- a/moveit_ros/planning/planning_scene_monitor/src/planning_scene_monitor.cpp +++ b/moveit_ros/planning/planning_scene_monitor/src/planning_scene_monitor.cpp @@ -536,18 +536,25 @@ void PlanningSceneMonitor::newPlanningSceneCallback(const moveit_msgs::PlanningS void PlanningSceneMonitor::clearOctomap() { - if (scene_->getWorldNonConst()->removeObject(scene_->OCTOMAP_NS)) - triggerSceneUpdateEvent(UPDATE_SCENE); - if (octomap_monitor_) - { - octomap_monitor_->getOcTreePtr()->lockWrite(); - octomap_monitor_->getOcTreePtr()->clear(); - octomap_monitor_->getOcTreePtr()->unlockWrite(); - } - else + bool removed = false; { - ROS_WARN_NAMED(LOGNAME, "Unable to clear octomap since no octomap monitor has been initialized"); + boost::unique_lock ulock(scene_update_mutex_); + removed = scene_->getWorldNonConst()->removeObject(scene_->OCTOMAP_NS); + + if (octomap_monitor_) + { + octomap_monitor_->getOcTreePtr()->lockWrite(); + octomap_monitor_->getOcTreePtr()->clear(); + octomap_monitor_->getOcTreePtr()->unlockWrite(); + } + else + { + ROS_WARN_NAMED(LOGNAME, "Unable to clear octomap since no octomap monitor has been initialized"); + } // Lift the scoped lock before calling triggerSceneUpdateEvent to avoid deadlock } + + if (removed) + triggerSceneUpdateEvent(UPDATE_GEOMETRY); } bool PlanningSceneMonitor::newPlanningSceneMessage(const moveit_msgs::PlanningScene& scene) From d5c4d7f87bc96244d03c977dcb47059633149e71 Mon Sep 17 00:00:00 2001 From: Cong Liu Date: Wed, 10 Mar 2021 18:50:12 +0800 Subject: [PATCH 097/179] Sanitize CHOMP initialization method parameter (#2540) --- .../chomp/chomp_interface/src/chomp_interface.cpp | 9 +++++++-- .../chomp_motion_planner/chomp_parameters.h | 9 +++++++++ .../chomp_motion_planner/src/chomp_parameters.cpp | 14 ++++++++++++++ .../chomp_motion_planner/src/chomp_planner.cpp | 3 +++ .../src/chomp_optimizer_adapter.cpp | 14 +++++++++++--- 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/moveit_planners/chomp/chomp_interface/src/chomp_interface.cpp b/moveit_planners/chomp/chomp_interface/src/chomp_interface.cpp index 48a03b1fc1..546d516b76 100644 --- a/moveit_planners/chomp/chomp_interface/src/chomp_interface.cpp +++ b/moveit_planners/chomp/chomp_interface/src/chomp_interface.cpp @@ -69,8 +69,13 @@ void CHOMPInterface::loadParams() nh_.param("collision_threshold", params_.collision_threshold_, 0.07); // nh_.param("random_jump_amount", params_.random_jump_amount_, 1.0); nh_.param("use_stochastic_descent", params_.use_stochastic_descent_, true); - nh_.param("trajectory_initialization_method", params_.trajectory_initialization_method_, - std::string("quintic-spline")); + { + params_.trajectory_initialization_method_ = "quintic-spline"; + std::string method; + if (nh_.getParam("trajectory_initialization_method", method) && !params_.setTrajectoryInitializationMethod(method)) + ROS_ERROR_STREAM("Attempted to set trajectory_initialization_method to invalid value '" + << method << "'. Using default '" << params_.trajectory_initialization_method_ << "' instead."); + } nh_.param("enable_failure_recovery", params_.enable_failure_recovery_, false); nh_.param("max_recovery_attempts", params_.max_recovery_attempts_, 5); } diff --git a/moveit_planners/chomp/chomp_motion_planner/include/chomp_motion_planner/chomp_parameters.h b/moveit_planners/chomp/chomp_motion_planner/include/chomp_motion_planner/chomp_parameters.h index f1446c9d8a..25b3381c8a 100644 --- a/moveit_planners/chomp/chomp_motion_planner/include/chomp_motion_planner/chomp_parameters.h +++ b/moveit_planners/chomp/chomp_motion_planner/include/chomp_motion_planner/chomp_parameters.h @@ -57,6 +57,12 @@ class ChompParameters */ void setRecoveryParams(double learning_rate, double ridge_factor, int planning_time_limit, int max_iterations); + /** + * sets a valid trajectory initialization method + * @return true if a valid method (one of VALID_INITIALIZATION_METHODS) was specified + */ + bool setTrajectoryInitializationMethod(std::string method); + public: double planning_time_limit_; /// maximum time the optimizer can take to find a solution before terminating int max_iterations_; /// maximum number of iterations that the planner can take to find a good solution while @@ -90,7 +96,10 @@ class ChompParameters double collision_threshold_; /// the collision threshold cost that needs to be mainted to avoid collisions bool filter_mode_; // double random_jump_amount_; + + static const std::vector VALID_INITIALIZATION_METHODS; std::string trajectory_initialization_method_; /// trajectory initialization method to be specified + bool enable_failure_recovery_; /// if set to true, CHOMP tries to vary certain parameters to try and find a path if /// an initial path is not found with the specified chomp parameters int max_recovery_attempts_; /// this the maximum recovery attempts to find a collision free path after an initial diff --git a/moveit_planners/chomp/chomp_motion_planner/src/chomp_parameters.cpp b/moveit_planners/chomp/chomp_motion_planner/src/chomp_parameters.cpp index 89d700f8e4..d318bda135 100644 --- a/moveit_planners/chomp/chomp_motion_planner/src/chomp_parameters.cpp +++ b/moveit_planners/chomp/chomp_motion_planner/src/chomp_parameters.cpp @@ -80,4 +80,18 @@ void ChompParameters::setRecoveryParams(double learning_rate, double ridge_facto this->planning_time_limit_ = planning_time_limit; this->max_iterations_ = max_iterations; } + +const std::vector ChompParameters::VALID_INITIALIZATION_METHODS{ "quintic-spline", "linear", "cubic", + "fillTrajectory" }; + +bool ChompParameters::setTrajectoryInitializationMethod(std::string method) +{ + if (std::find(VALID_INITIALIZATION_METHODS.cbegin(), VALID_INITIALIZATION_METHODS.cend(), method) != + VALID_INITIALIZATION_METHODS.end()) + { + this->trajectory_initialization_method_ = std::move(method); + return true; + } + return false; +} } // namespace chomp diff --git a/moveit_planners/chomp/chomp_motion_planner/src/chomp_planner.cpp b/moveit_planners/chomp/chomp_motion_planner/src/chomp_planner.cpp index 3db4ea538c..3ef7b6e00e 100644 --- a/moveit_planners/chomp/chomp_motion_planner/src/chomp_planner.cpp +++ b/moveit_planners/chomp/chomp_motion_planner/src/chomp_planner.cpp @@ -136,7 +136,10 @@ bool ChompPlanner::solve(const planning_scene::PlanningSceneConstPtr& planning_s } } else + { ROS_ERROR_STREAM_NAMED("chomp_planner", "invalid interpolation method specified in the chomp_planner file"); + return false; + } ROS_INFO_NAMED("chomp_planner", "CHOMP trajectory initialized using method: %s ", (params.trajectory_initialization_method_).c_str()); diff --git a/moveit_planners/chomp/chomp_optimizer_adapter/src/chomp_optimizer_adapter.cpp b/moveit_planners/chomp/chomp_optimizer_adapter/src/chomp_optimizer_adapter.cpp index 3697230b63..acbcf6ef25 100644 --- a/moveit_planners/chomp/chomp_optimizer_adapter/src/chomp_optimizer_adapter.cpp +++ b/moveit_planners/chomp/chomp_optimizer_adapter/src/chomp_optimizer_adapter.cpp @@ -146,12 +146,20 @@ class OptimizerAdapter : public planning_request_adapter::PlanningRequestAdapter ROS_INFO_STREAM( "Param use_stochastic_descent was not set. Using default value: " << params_.use_stochastic_descent_); } - if (!nh_.getParam("trajectory_initialization_method", params_.trajectory_initialization_method_)) + // default + params_.trajectory_initialization_method_ = std::string("fillTrajectory"); + std::string trajectory_initialization_method; + if (!nh.getParam("trajectory_initialization_method", trajectory_initialization_method)) { - params_.trajectory_initialization_method_ = std::string("fillTrajectory"); - ROS_INFO_STREAM("Param trajectory_initialization_method was not set. Using New value as: " + ROS_INFO_STREAM("Param trajectory_initialization_method was not set. Using value: " << params_.trajectory_initialization_method_); } + else if (!params_.setTrajectoryInitializationMethod(trajectory_initialization_method)) + { + ROS_ERROR_STREAM("Param trajectory_initialization_method set to invalid value '" + << trajectory_initialization_method << "'. Using '" << params_.trajectory_initialization_method_ + << "' instead."); + } } std::string getDescription() const override From b973cc53a70ee734ff7dc89a03a0bd236a776da8 Mon Sep 17 00:00:00 2001 From: Jafar Abdi Date: Wed, 10 Mar 2021 23:00:07 +0300 Subject: [PATCH 098/179] Enable mesh filter (#2448) --- .../src/chomp_optimizer_adapter.cpp | 2 +- moveit_ros/perception/CMakeLists.txt | 24 ++++++-- .../perception/mesh_filter/CMakeLists.txt | 12 +++- .../mesh_filter/depth_self_filter_nodelet.h | 8 +-- .../include/moveit/mesh_filter/filter_job.h | 23 ++++---- .../include/moveit/mesh_filter/gl_renderer.h | 8 ++- .../include/moveit/mesh_filter/mesh_filter.h | 1 - .../moveit/mesh_filter/mesh_filter_base.h | 17 +++--- .../moveit/mesh_filter/transform_provider.h | 9 ++- .../src/depth_self_filter_nodelet.cpp | 51 ++++++++-------- .../mesh_filter/src/gl_renderer.cpp | 17 +++--- .../mesh_filter/src/mesh_filter.cpp | 4 +- .../mesh_filter/src/mesh_filter_base.cpp | 41 +++++++------ .../mesh_filter/src/stereo_camera_model.cpp | 37 ++++++------ .../mesh_filter/src/transform_provider.cpp | 59 ++++++++----------- .../mesh_filter/test/mesh_filter_test.cpp | 4 +- .../perception/moveit_depth_self_filter.xml | 7 +++ moveit_ros/perception/package.xml | 3 + .../src/move_group_interface.cpp | 6 +- 19 files changed, 178 insertions(+), 155 deletions(-) create mode 100644 moveit_ros/perception/moveit_depth_self_filter.xml diff --git a/moveit_planners/chomp/chomp_optimizer_adapter/src/chomp_optimizer_adapter.cpp b/moveit_planners/chomp/chomp_optimizer_adapter/src/chomp_optimizer_adapter.cpp index acbcf6ef25..a53f74d9b0 100644 --- a/moveit_planners/chomp/chomp_optimizer_adapter/src/chomp_optimizer_adapter.cpp +++ b/moveit_planners/chomp/chomp_optimizer_adapter/src/chomp_optimizer_adapter.cpp @@ -149,7 +149,7 @@ class OptimizerAdapter : public planning_request_adapter::PlanningRequestAdapter // default params_.trajectory_initialization_method_ = std::string("fillTrajectory"); std::string trajectory_initialization_method; - if (!nh.getParam("trajectory_initialization_method", trajectory_initialization_method)) + if (!nh_.getParam("trajectory_initialization_method", trajectory_initialization_method)) { ROS_INFO_STREAM("Param trajectory_initialization_method was not set. Using value: " << params_.trajectory_initialization_method_); diff --git a/moveit_ros/perception/CMakeLists.txt b/moveit_ros/perception/CMakeLists.txt index 44353476bb..d3457f7b6e 100644 --- a/moveit_ros/perception/CMakeLists.txt +++ b/moveit_ros/perception/CMakeLists.txt @@ -49,12 +49,28 @@ find_package(catkin REQUIRED COMPONENTS sensor_msgs moveit_msgs moveit_ros_occupancy_map_monitor + moveit_ros_planning + nodelet ) find_package(Eigen3 REQUIRED) find_package(OpenMP REQUIRED) find_package(OpenCV) +set(PACKAGE_LIBRARIES + moveit_lazy_free_space_updater + moveit_point_containment_filter + moveit_pointcloud_octomap_updater_core + moveit_semantic_world +) + +if (WITH_OPENGL) + list(APPEND PACKAGE_LIBRARIES + moveit_mesh_filter + moveit_depth_self_filter + moveit_depth_image_octomap_updater) +endif(WITH_OPENGL) + catkin_package( INCLUDE_DIRS lazy_free_space_updater/include @@ -63,15 +79,14 @@ catkin_package( semantic_world/include ${perception_GL_INCLUDE_DIRS} LIBRARIES - moveit_lazy_free_space_updater - moveit_point_containment_filter - moveit_pointcloud_octomap_updater_core - moveit_semantic_world + ${PACKAGE_LIBRARIES} CATKIN_DEPENDS image_transport moveit_core moveit_msgs moveit_ros_occupancy_map_monitor + moveit_ros_planning + nodelet object_recognition_msgs roscpp sensor_msgs @@ -109,5 +124,6 @@ install( FILES pointcloud_octomap_updater_plugin_description.xml depth_image_octomap_updater_plugin_description.xml + moveit_depth_self_filter.xml DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) diff --git a/moveit_ros/perception/mesh_filter/CMakeLists.txt b/moveit_ros/perception/mesh_filter/CMakeLists.txt index 100350e472..3abb380bfd 100644 --- a/moveit_ros/perception/mesh_filter/CMakeLists.txt +++ b/moveit_ros/perception/mesh_filter/CMakeLists.txt @@ -6,11 +6,19 @@ add_library(${MOVEIT_LIB_NAME} src/stereo_camera_model.cpp src/gl_renderer.cpp src/gl_mesh.cpp - ) +) set_target_properties(${MOVEIT_LIB_NAME} PROPERTIES VERSION "${${PROJECT_NAME}_VERSION}") target_link_libraries(${MOVEIT_LIB_NAME} ${catkin_LIBRARIES} ${gl_LIBS} GLUT::GLUT ${GLEW_LIBRARIES}) +add_library(moveit_depth_self_filter + src/depth_self_filter_nodelet.cpp + src/transform_provider.cpp +) +set_target_properties(moveit_depth_self_filter PROPERTIES VERSION "${${PROJECT_NAME}_VERSION}") + +target_link_libraries(moveit_depth_self_filter ${catkin_LIBRARIES} ${MOVEIT_LIB_NAME}) + if (CATKIN_ENABLE_TESTING) #catkin_lint: ignore_once env_var # Can only run this test if we have a display @@ -24,7 +32,7 @@ if (CATKIN_ENABLE_TESTING) endif() endif() -install(TARGETS ${MOVEIT_LIB_NAME} +install(TARGETS ${MOVEIT_LIB_NAME} moveit_depth_self_filter LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) diff --git a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/depth_self_filter_nodelet.h b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/depth_self_filter_nodelet.h index 6ab4d6ab37..af50c4b7ea 100644 --- a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/depth_self_filter_nodelet.h +++ b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/depth_self_filter_nodelet.h @@ -39,8 +39,6 @@ #include #include -#include -#include #include #include #include @@ -58,10 +56,10 @@ class DepthSelfFiltering : public nodelet::Nodelet { public: /** \brief Nodelet init callback*/ - virtual void onInit(); + void onInit() override; private: - ~DepthSelfFiltering(); + ~DepthSelfFiltering() override; /** * \brief adding the meshes to a given mesh filter object. @@ -104,7 +102,7 @@ class DepthSelfFiltering : public nodelet::Nodelet image_transport::CameraPublisher pub_model_label_image_; /** \brief required to avoid listener registration before we are all set*/ - boost::mutex connect_mutex_; + std::mutex connect_mutex_; int queue_size_; TransformProvider transform_provider_; diff --git a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/filter_job.h b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/filter_job.h index 51fbfef872..5a0aea9207 100644 --- a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/filter_job.h +++ b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/filter_job.h @@ -38,9 +38,6 @@ #define MOVEIT_MESH_FILTER_FILTER_JOB_ #include -#include -#include -#include namespace mesh_filter { @@ -65,20 +62,20 @@ class Job protected: bool done_; - mutable boost::condition_variable condition_; - mutable boost::mutex mutex_; + mutable std::condition_variable condition_; + mutable std::mutex mutex_; }; void Job::wait() const { - boost::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); while (!done_) condition_.wait(lock); } void Job::cancel() { - boost::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); done_ = true; condition_.notify_all(); } @@ -92,21 +89,21 @@ template class FilterJob : public Job { public: - FilterJob(const boost::function& exec) : Job(), exec_(exec) + FilterJob(const std::function& exec) : Job(), exec_(exec) { } void execute() override; const ReturnType& getResult() const; private: - boost::function exec_; + std::function exec_; ReturnType result_; }; template void FilterJob::execute() { - boost::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); if (!done_) // not canceled ! result_ = exec_(); @@ -125,12 +122,12 @@ template <> class FilterJob : public Job { public: - FilterJob(const boost::function& exec) : Job(), exec_(exec) + FilterJob(const std::function& exec) : Job(), exec_(exec) { } void execute() override { - boost::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); if (!done_) // not canceled ! exec_(); @@ -139,7 +136,7 @@ class FilterJob : public Job } private: - boost::function exec_; + std::function exec_; }; } // namespace mesh_filter #endif diff --git a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/gl_renderer.h b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/gl_renderer.h index a956d84513..7d15cf5852 100644 --- a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/gl_renderer.h +++ b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/gl_renderer.h @@ -45,7 +45,9 @@ #include #endif #include -#include +#include +#include +#include namespace mesh_filter { @@ -295,10 +297,10 @@ class GLRenderer float cy_; /** \brief map from thread id to OpenGL context */ - static std::map > context_; + static std::map > context_; /* \brief lock for context map */ - static boost::mutex context_lock_; + static std::mutex context_lock_; static bool glutInitialized_; }; diff --git a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/mesh_filter.h b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/mesh_filter.h index 7d482b21b2..e3c0ba0a78 100644 --- a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/mesh_filter.h +++ b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/mesh_filter.h @@ -41,7 +41,6 @@ #include #include #include -#include // forward declarations namespace shapes diff --git a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/mesh_filter_base.h b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/mesh_filter_base.h index 400eae1924..44c9573a9d 100644 --- a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/mesh_filter_base.h +++ b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/mesh_filter_base.h @@ -41,10 +41,11 @@ #include #include #include -#include -#include #include // for Isometry3d #include +#include +#include +#include // forward declarations namespace shapes @@ -64,7 +65,7 @@ class MeshFilterBase { // inner types and typedefs public: - typedef boost::function TransformCallback; + typedef std::function TransformCallback; // \todo @suat: to avoid a few comparisons, it would be much nicer if background = 14 and shadow = 15 (near/far clip // can be anything below that) // this would allow me to do a single comparison instead of 3, in the code i write @@ -246,22 +247,22 @@ class MeshFilterBase MeshHandle min_handle_; /** \brief the filtering thread that also holds the OpenGL context*/ - boost::thread filter_thread_; + std::thread filter_thread_; /** \brief condition variable to notify the filtering thread if a new image arrived*/ - mutable boost::condition_variable jobs_condition_; + mutable std::condition_variable jobs_condition_; /** \brief mutex required for synchronization of condition states*/ - mutable boost::mutex jobs_mutex_; + mutable std::mutex jobs_mutex_; /** \brief OpenGL job queue that need to be processed by the worker thread*/ mutable std::queue jobs_queue_; /** \brief mutex for synchronization of updating filtered meshes */ - mutable boost::mutex meshes_mutex_; + mutable std::mutex meshes_mutex_; /** \brief mutex for synchronization of setting/calling transform_callback_ */ - mutable boost::mutex transform_callback_mutex_; + mutable std::mutex transform_callback_mutex_; /** \brief indicates whether the filtering loop should stop*/ bool stop_; diff --git a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/transform_provider.h b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/transform_provider.h index a5b53ee749..2179e30919 100644 --- a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/transform_provider.h +++ b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/transform_provider.h @@ -38,8 +38,6 @@ #define MOVEIT_MESH_FILTER_TRANSFORM_PROVIDER_ #include -#include -#include #include #include #include @@ -127,8 +125,9 @@ class TransformProvider * \brief Context Object for registered frames * \author Suat Gedikli (gedikli@willowgarage.com) */ - struct TransformContext + class TransformContext { + public: TransformContext(const std::string& name) : frame_id_(name) { transformation_.matrix().setZero(); @@ -136,7 +135,7 @@ class TransformProvider EIGEN_MAKE_ALIGNED_OPERATOR_NEW std::string frame_id_; Eigen::Isometry3d transformation_; - boost::mutex mutex_; + std::mutex mutex_; }; /** @@ -159,7 +158,7 @@ class TransformProvider std::string frame_id_; /** \brief thread object*/ - boost::thread thread_; + std::thread thread_; /** \flag to leave the update loop*/ bool stop_; diff --git a/moveit_ros/perception/mesh_filter/src/depth_self_filter_nodelet.cpp b/moveit_ros/perception/mesh_filter/src/depth_self_filter_nodelet.cpp index 20dc29f101..720c3a2674 100644 --- a/moveit_ros/perception/mesh_filter/src/depth_self_filter_nodelet.cpp +++ b/moveit_ros/perception/mesh_filter/src/depth_self_filter_nodelet.cpp @@ -45,8 +45,6 @@ #include namespace enc = sensor_msgs::image_encodings; -using namespace std; -using namespace boost; mesh_filter::DepthSelfFiltering::~DepthSelfFiltering() { @@ -74,10 +72,10 @@ void mesh_filter::DepthSelfFiltering::onInit() private_nh.param("tf_update_rate", tf_update_rate, 30.0); transform_provider_.setUpdateInterval(long(1000000.0 / tf_update_rate)); - image_transport::SubscriberStatusCallback itssc = bind(&DepthSelfFiltering::connectCb, this); - ros::SubscriberStatusCallback rssc = bind(&DepthSelfFiltering::connectCb, this); + image_transport::SubscriberStatusCallback itssc = std::bind(&DepthSelfFiltering::connectCb, this); + ros::SubscriberStatusCallback rssc = std::bind(&DepthSelfFiltering::connectCb, this); - lock_guard lock(connect_mutex_); + std::lock_guard lock(connect_mutex_); pub_filtered_depth_image_ = filtered_depth_transport_->advertiseCamera("/filtered/depth", queue_size_, itssc, itssc, rssc, rssc); pub_filtered_label_image_ = @@ -94,7 +92,7 @@ void mesh_filter::DepthSelfFiltering::onInit() mesh_filter_.reset( new MeshFilter(bind(&TransformProvider::getTransform, &transform_provider_, _1, _2), - mesh_filter::StereoCameraModel::RegisteredPSDKParams)); + mesh_filter::StereoCameraModel::REGISTERED_PSDK_PARAMS)); mesh_filter_->parameters().setDepthRange(near_clipping_plane_distance_, far_clipping_plane_distance_); mesh_filter_->setShadowThreshold(shadow_threshold_); mesh_filter_->setPaddingOffset(padding_offset_); @@ -115,9 +113,9 @@ void mesh_filter::DepthSelfFiltering::filter(const sensor_msgs::ImageConstPtr& d const float* src = (const float*)&depth_msg->data[0]; //* - static unsigned dataSize = 0; - static unsigned short* data = 0; - if (dataSize < depth_msg->width * depth_msg->height) + static unsigned data_size = 0; + static unsigned short* data = nullptr; + if (data_size < depth_msg->width * depth_msg->height) data = new unsigned short[depth_msg->width * depth_msg->height]; for (unsigned idx = 0; idx < depth_msg->width * depth_msg->height; ++idx) data[idx] = (unsigned short)(src[idx] * 1000.0); @@ -132,7 +130,8 @@ void mesh_filter::DepthSelfFiltering::filter(const sensor_msgs::ImageConstPtr& d filtered_depth_ptr_->encoding = sensor_msgs::image_encodings::TYPE_32FC1; filtered_depth_ptr_->header = depth_msg->header; - if (filtered_depth_ptr_->image.cols != depth_msg->width || filtered_depth_ptr_->image.rows != depth_msg->height) + if (static_cast(filtered_depth_ptr_->image.cols) != depth_msg->width || + static_cast(filtered_depth_ptr_->image.rows) != depth_msg->height) filtered_depth_ptr_->image = cv::Mat(depth_msg->height, depth_msg->width, CV_32FC1); mesh_filter_->getFilteredDepth((float*)filtered_depth_ptr_->image.data); pub_filtered_depth_image_.publish(filtered_depth_ptr_->toImageMsg(), info_msg); @@ -144,7 +143,8 @@ void mesh_filter::DepthSelfFiltering::filter(const sensor_msgs::ImageConstPtr& d model_depth_ptr_->encoding = sensor_msgs::image_encodings::TYPE_32FC1; model_depth_ptr_->header = depth_msg->header; - if (model_depth_ptr_->image.cols != depth_msg->width || model_depth_ptr_->image.rows != depth_msg->height) + if (static_cast(model_depth_ptr_->image.cols) != depth_msg->width || + static_cast(model_depth_ptr_->image.rows) != depth_msg->height) model_depth_ptr_->image = cv::Mat(depth_msg->height, depth_msg->width, CV_32FC1); mesh_filter_->getModelDepth((float*)model_depth_ptr_->image.data); pub_model_depth_image_.publish(model_depth_ptr_->toImageMsg(), info_msg); @@ -155,7 +155,8 @@ void mesh_filter::DepthSelfFiltering::filter(const sensor_msgs::ImageConstPtr& d filtered_label_ptr_->encoding = sensor_msgs::image_encodings::RGBA8; filtered_label_ptr_->header = depth_msg->header; - if (filtered_label_ptr_->image.cols != depth_msg->width || filtered_label_ptr_->image.rows != depth_msg->height) + if (static_cast(filtered_label_ptr_->image.cols) != depth_msg->width || + static_cast(filtered_label_ptr_->image.rows) != depth_msg->height) filtered_label_ptr_->image = cv::Mat(depth_msg->height, depth_msg->width, CV_8UC4); mesh_filter_->getFilteredLabels((unsigned int*)filtered_label_ptr_->image.data); pub_filtered_label_image_.publish(filtered_label_ptr_->toImageMsg(), info_msg); @@ -165,7 +166,8 @@ void mesh_filter::DepthSelfFiltering::filter(const sensor_msgs::ImageConstPtr& d { model_label_ptr_->encoding = sensor_msgs::image_encodings::RGBA8; model_label_ptr_->header = depth_msg->header; - if (model_label_ptr_->image.cols != depth_msg->width || model_label_ptr_->image.rows != depth_msg->height) + if (static_cast(model_label_ptr_->image.cols) != depth_msg->width || + static_cast(model_label_ptr_->image.rows) != depth_msg->height) model_label_ptr_->image = cv::Mat(depth_msg->height, depth_msg->width, CV_8UC4); mesh_filter_->getModelLabels((unsigned int*)model_label_ptr_->image.data); pub_model_label_image_.publish(model_label_ptr_->toImageMsg(), info_msg); @@ -174,17 +176,20 @@ void mesh_filter::DepthSelfFiltering::filter(const sensor_msgs::ImageConstPtr& d void mesh_filter::DepthSelfFiltering::addMeshes(MeshFilter& mesh_filter) { - robot_model_loader::RobotModelLoader robotModelLoader("robot_description"); - robot_model::RobotModelConstPtr robotModel = robotModelLoader.getModel(); - const vector& links = robotModel->getLinkModelsWithCollisionGeometry(); - for (size_t i = 0; i < links.size(); ++i) + robot_model_loader::RobotModelLoader robot_model_loader("robot_description"); + robot_model::RobotModelConstPtr robot_model = robot_model_loader.getModel(); + const auto& links = robot_model->getLinkModelsWithCollisionGeometry(); + for (auto link : links) { - shapes::ShapeConstPtr shape = links[i]->getShape(); - if (shape->type == shapes::MESH) + const auto& shapes = link->getShapes(); + for (const auto& shape : shapes) { - const shapes::Mesh& m = static_cast(*shape); - MeshHandle mesh_handle = mesh_filter.addMesh(m); - transform_provider_.addHandle(mesh_handle, links[i]->getName()); + if (shape->type == shapes::MESH) + { + const shapes::Mesh& m = static_cast(*shape); + MeshHandle mesh_handle = mesh_filter.addMesh(m); + transform_provider_.addHandle(mesh_handle, link->getName()); + } } } } @@ -192,7 +197,7 @@ void mesh_filter::DepthSelfFiltering::addMeshes(MeshFilter& m // Handles (un)subscribing when clients (un)subscribe void mesh_filter::DepthSelfFiltering::connectCb() { - lock_guard lock(connect_mutex_); + std::lock_guard lock(connect_mutex_); if (pub_filtered_depth_image_.getNumSubscribers() == 0 && pub_filtered_label_image_.getNumSubscribers() == 0 && pub_model_depth_image_.getNumSubscribers() == 0 && pub_model_label_image_.getNumSubscribers() == 0) { diff --git a/moveit_ros/perception/mesh_filter/src/gl_renderer.cpp b/moveit_ros/perception/mesh_filter/src/gl_renderer.cpp index 4f351b53e6..834d2b4edd 100644 --- a/moveit_ros/perception/mesh_filter/src/gl_renderer.cpp +++ b/moveit_ros/perception/mesh_filter/src/gl_renderer.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #include using namespace std; @@ -352,8 +351,8 @@ GLuint mesh_filter::GLRenderer::loadShaders(const string& vertex_source, const s return program_id; } -map > mesh_filter::GLRenderer::context_; -boost::mutex mesh_filter::GLRenderer::context_lock_; +map > mesh_filter::GLRenderer::context_; +std::mutex mesh_filter::GLRenderer::context_lock_; bool mesh_filter::GLRenderer::glutInitialized_ = false; namespace @@ -363,7 +362,7 @@ void nullDisplayFunction(){}; void mesh_filter::GLRenderer::createGLContext() { - boost::mutex::scoped_lock _(context_lock_); + std::unique_lock _(context_lock_); if (!glutInitialized_) { char buffer[1]; @@ -376,8 +375,8 @@ void mesh_filter::GLRenderer::createGLContext() } // check if our thread is initialized - boost::thread::id thread_id = boost::this_thread::get_id(); - map >::iterator context_it = context_.find(thread_id); + std::thread::id thread_id = std::this_thread::get_id(); + map >::iterator context_it = context_.find(thread_id); if (context_it == context_.end()) { @@ -410,9 +409,9 @@ void mesh_filter::GLRenderer::createGLContext() void mesh_filter::GLRenderer::deleteGLContext() { - boost::mutex::scoped_lock _(context_lock_); - boost::thread::id thread_id = boost::this_thread::get_id(); - map >::iterator context_it = context_.find(thread_id); + std::unique_lock _(context_lock_); + std::thread::id thread_id = std::this_thread::get_id(); + map >::iterator context_it = context_.find(thread_id); if (context_it == context_.end()) { stringstream error_msg; diff --git a/moveit_ros/perception/mesh_filter/src/mesh_filter.cpp b/moveit_ros/perception/mesh_filter/src/mesh_filter.cpp index 98ed797ae4..007e9e8397 100644 --- a/moveit_ros/perception/mesh_filter/src/mesh_filter.cpp +++ b/moveit_ros/perception/mesh_filter/src/mesh_filter.cpp @@ -52,7 +52,7 @@ using namespace std; using namespace Eigen; using shapes::Mesh; -mesh_filter::MeshFilter::MeshFilter(const boost::function& transform_callback) +mesh_filter::MeshFilter::MeshFilter(const std::function& transform_callback) : mesh_renderer_(640, 480, 0.3, 10) // some default values for buffer sizes and clipping planes , depth_filter_(640, 480, 0.3, 10) , next_handle_(FirstLabel) // 0 and 1 are reserved! @@ -117,7 +117,7 @@ void mesh_filter::MeshFilter::setSize(unsigned width, unsigned height) } void mesh_filter::MeshFilter::setTransformCallback( - const boost::function& transform_callback) + const std::function& transform_callback) { transform_callback_ = transform_callback; } diff --git a/moveit_ros/perception/mesh_filter/src/mesh_filter_base.cpp b/moveit_ros/perception/mesh_filter/src/mesh_filter_base.cpp index edc97ceb91..9ce1f2da88 100644 --- a/moveit_ros/perception/mesh_filter/src/mesh_filter_base.cpp +++ b/moveit_ros/perception/mesh_filter/src/mesh_filter_base.cpp @@ -66,8 +66,8 @@ mesh_filter::MeshFilterBase::MeshFilterBase(const TransformCallback& transform_c , padding_offset_(0.01) , shadow_threshold_(0.5) { - filter_thread_ = boost::thread(boost::bind(&MeshFilterBase::run, this, render_vertex_shader, render_fragment_shader, - filter_vertex_shader, filter_fragment_shader)); + filter_thread_ = std::thread(std::bind(&MeshFilterBase::run, this, render_vertex_shader, render_fragment_shader, + filter_vertex_shader, filter_fragment_shader)); } void mesh_filter::MeshFilterBase::initialize(const std::string& render_vertex_shader, @@ -121,7 +121,7 @@ void mesh_filter::MeshFilterBase::initialize(const std::string& render_vertex_sh mesh_filter::MeshFilterBase::~MeshFilterBase() { { - boost::unique_lock lock(jobs_mutex_); + std::unique_lock lock(jobs_mutex_); stop_ = true; while (!jobs_queue_.empty()) { @@ -136,7 +136,7 @@ mesh_filter::MeshFilterBase::~MeshFilterBase() void mesh_filter::MeshFilterBase::addJob(const JobPtr& job) const { { - boost::unique_lock _(jobs_mutex_); + std::unique_lock _(jobs_mutex_); jobs_queue_.push(job); } jobs_condition_.notify_one(); @@ -163,15 +163,15 @@ void mesh_filter::MeshFilterBase::setSize(unsigned int width, unsigned int heigh void mesh_filter::MeshFilterBase::setTransformCallback(const TransformCallback& transform_callback) { - boost::mutex::scoped_lock _(transform_callback_mutex_); + std::unique_lock _(transform_callback_mutex_); transform_callback_ = transform_callback; } mesh_filter::MeshHandle mesh_filter::MeshFilterBase::addMesh(const shapes::Mesh& mesh) { - boost::mutex::scoped_lock _(meshes_mutex_); + std::unique_lock _(meshes_mutex_); - JobPtr job(new FilterJob(boost::bind(&MeshFilterBase::addMeshHelper, this, next_handle_, &mesh))); + JobPtr job(new FilterJob(std::bind(&MeshFilterBase::addMeshHelper, this, next_handle_, &mesh))); addJob(job); job->wait(); mesh_filter::MeshHandle ret = next_handle_; @@ -193,8 +193,8 @@ void mesh_filter::MeshFilterBase::addMeshHelper(MeshHandle handle, const shapes: void mesh_filter::MeshFilterBase::removeMesh(MeshHandle handle) { - boost::mutex::scoped_lock _(meshes_mutex_); - FilterJob* remover = new FilterJob(boost::bind(&MeshFilterBase::removeMeshHelper, this, handle)); + std::unique_lock _(meshes_mutex_); + FilterJob* remover = new FilterJob(std::bind(&MeshFilterBase::removeMeshHelper, this, handle)); JobPtr job(remover); addJob(job); job->wait(); @@ -217,19 +217,18 @@ void mesh_filter::MeshFilterBase::setShadowThreshold(float threshold) void mesh_filter::MeshFilterBase::getModelLabels(LabelType* labels) const { - JobPtr job( - new FilterJob(boost::bind(&GLRenderer::getColorBuffer, mesh_renderer_.get(), (unsigned char*)labels))); + JobPtr job(new FilterJob(std::bind(&GLRenderer::getColorBuffer, mesh_renderer_.get(), (unsigned char*)labels))); addJob(job); job->wait(); } void mesh_filter::MeshFilterBase::getModelDepth(float* depth) const { - JobPtr job1(new FilterJob(boost::bind(&GLRenderer::getDepthBuffer, mesh_renderer_.get(), depth))); + JobPtr job1(new FilterJob(std::bind(&GLRenderer::getDepthBuffer, mesh_renderer_.get(), depth))); JobPtr job2(new FilterJob( - boost::bind(&SensorModel::Parameters::transformModelDepthToMetricDepth, sensor_parameters_.get(), depth))); + std::bind(&SensorModel::Parameters::transformModelDepthToMetricDepth, sensor_parameters_.get(), depth))); { - boost::unique_lock lock(jobs_mutex_); + std::unique_lock lock(jobs_mutex_); jobs_queue_.push(job1); jobs_queue_.push(job2); } @@ -240,11 +239,11 @@ void mesh_filter::MeshFilterBase::getModelDepth(float* depth) const void mesh_filter::MeshFilterBase::getFilteredDepth(float* depth) const { - JobPtr job1(new FilterJob(boost::bind(&GLRenderer::getDepthBuffer, depth_filter_.get(), depth))); + JobPtr job1(new FilterJob(std::bind(&GLRenderer::getDepthBuffer, depth_filter_.get(), depth))); JobPtr job2(new FilterJob( - boost::bind(&SensorModel::Parameters::transformFilteredDepthToMetricDepth, sensor_parameters_.get(), depth))); + std::bind(&SensorModel::Parameters::transformFilteredDepthToMetricDepth, sensor_parameters_.get(), depth))); { - boost::unique_lock lock(jobs_mutex_); + std::unique_lock lock(jobs_mutex_); jobs_queue_.push(job1); jobs_queue_.push(job2); } @@ -255,7 +254,7 @@ void mesh_filter::MeshFilterBase::getFilteredDepth(float* depth) const void mesh_filter::MeshFilterBase::getFilteredLabels(LabelType* labels) const { - JobPtr job(new FilterJob(boost::bind(&GLRenderer::getColorBuffer, depth_filter_.get(), (unsigned char*)labels))); + JobPtr job(new FilterJob(std::bind(&GLRenderer::getColorBuffer, depth_filter_.get(), (unsigned char*)labels))); addJob(job); job->wait(); } @@ -269,7 +268,7 @@ void mesh_filter::MeshFilterBase::run(const std::string& render_vertex_shader, while (!stop_) { - boost::unique_lock lock(jobs_mutex_); + std::unique_lock lock(jobs_mutex_); // check if we have new sensor data to be processed. If not, wait until we get notified. if (jobs_queue_.empty()) jobs_condition_.wait(lock); @@ -295,7 +294,7 @@ void mesh_filter::MeshFilterBase::filter(const void* sensor_data, GLushort type, throw std::runtime_error(msg.str()); } - JobPtr job(new FilterJob(boost::bind(&MeshFilterBase::doFilter, this, sensor_data, type))); + JobPtr job(new FilterJob(std::bind(&MeshFilterBase::doFilter, this, sensor_data, type))); addJob(job); if (wait) job->wait(); @@ -303,7 +302,7 @@ void mesh_filter::MeshFilterBase::filter(const void* sensor_data, GLushort type, void mesh_filter::MeshFilterBase::doFilter(const void* sensor_data, const int encoding) const { - boost::mutex::scoped_lock _(transform_callback_mutex_); + std::unique_lock _(transform_callback_mutex_); mesh_renderer_->begin(); sensor_parameters_->setRenderParameters(*mesh_renderer_); diff --git a/moveit_ros/perception/mesh_filter/src/stereo_camera_model.cpp b/moveit_ros/perception/mesh_filter/src/stereo_camera_model.cpp index 5881faffd8..eaa9d54118 100644 --- a/moveit_ros/perception/mesh_filter/src/stereo_camera_model.cpp +++ b/moveit_ros/perception/mesh_filter/src/stereo_camera_model.cpp @@ -37,8 +37,6 @@ #include #include -using namespace std; - mesh_filter::StereoCameraModel::Parameters::Parameters(unsigned width, unsigned height, float near_clipping_plane_distance, float far_clipping_plane_distance, float fx, float fy, float cx, @@ -112,7 +110,7 @@ void mesh_filter::StereoCameraModel::Parameters::setFilterParameters(GLRenderer& const mesh_filter::StereoCameraModel::Parameters& mesh_filter::StereoCameraModel::REGISTERED_PSDK_PARAMS = mesh_filter::StereoCameraModel::Parameters(640, 480, 0.4, 10.0, 525, 525, 319.5, 239.5, 0.075, 0.125); -const string mesh_filter::StereoCameraModel::RENDER_VERTEX_SHADER_SOURCE = +const std::string mesh_filter::StereoCameraModel::RENDER_VERTEX_SHADER_SOURCE = "#version 120\n" "uniform vec3 padding_coefficients;" "void main()" @@ -127,22 +125,23 @@ const string mesh_filter::StereoCameraModel::RENDER_VERTEX_SHADER_SOURCE = " gl_Position.y = -gl_Position.y;" "}"; -const string mesh_filter::StereoCameraModel::RENDER_FRAGMENT_SHADER_SOURCE = "#version 120\n" - "void main()" - "{" - " gl_FragColor = gl_Color;" - "}"; - -const string mesh_filter::StereoCameraModel::FILTER_VERTEX_SHADER_SOURCE = "#version 120\n" - "void main ()" - "{" - " gl_FrontColor = gl_Color;" - " gl_TexCoord[0] = gl_MultiTexCoord0;" - " gl_Position = gl_Vertex;" - " gl_Position.w = 1.0;" - "}"; - -const string mesh_filter::StereoCameraModel::FILTER_FRAGMENT_SHADER_SOURCE = +const std::string mesh_filter::StereoCameraModel::RENDER_FRAGMENT_SHADER_SOURCE = "#version 120\n" + "void main()" + "{" + " gl_FragColor = gl_Color;" + "}"; + +const std::string mesh_filter::StereoCameraModel::FILTER_VERTEX_SHADER_SOURCE = + "#version 120\n" + "void main ()" + "{" + " gl_FrontColor = gl_Color;" + " gl_TexCoord[0] = gl_MultiTexCoord0;" + " gl_Position = gl_Vertex;" + " gl_Position.w = 1.0;" + "}"; + +const std::string mesh_filter::StereoCameraModel::FILTER_FRAGMENT_SHADER_SOURCE = "#version 120\n" "uniform sampler2D sensor;" "uniform sampler2D depth;" diff --git a/moveit_ros/perception/mesh_filter/src/transform_provider.cpp b/moveit_ros/perception/mesh_filter/src/transform_provider.cpp index cc5e8bda85..888130367f 100644 --- a/moveit_ros/perception/mesh_filter/src/transform_provider.cpp +++ b/moveit_ros/perception/mesh_filter/src/transform_provider.cpp @@ -39,12 +39,6 @@ #include #include -using namespace std; -using namespace boost; -using namespace Eigen; -using namespace tf; -using namespace mesh_filter; - TransformProvider::TransformProvider(unsigned long interval_us) : stop_(true), interval_us_(interval_us) { tf_buffer_ = std::make_shared(); @@ -61,7 +55,7 @@ TransformProvider::~TransformProvider() void TransformProvider::start() { stop_ = false; - thread_ = thread(&TransformProvider::run, this); + thread_ = std::thread(&TransformProvider::run, this); } void TransformProvider::stop() @@ -70,49 +64,48 @@ void TransformProvider::stop() thread_.join(); } -void TransformProvider::addHandle(MeshHandle handle, const string& name) +void TransformProvider::addHandle(mesh_filter::MeshHandle handle, const std::string& name) { if (!stop_) - throw runtime_error("Can not add handles if TransformProvider is running"); + throw std::runtime_error("Can not add handles if TransformProvider is running"); handle2context_[handle].reset(new TransformContext(name)); } -void TransformProvider::setFrame(const string& frame) +void TransformProvider::setFrame(const std::string& frame) { if (frame_id_ != frame) { frame_id_ = frame; - for (map >::iterator contextIt = handle2context_.begin(); - contextIt != handle2context_.end(); ++contextIt) + for (auto& context_it : handle2context_) { // invalidate transformations - contextIt->second->mutex_.lock(); - contextIt->second->transformation_.matrix().setZero(); - contextIt->second->mutex_.unlock(); + context_it.second->mutex_.lock(); + context_it.second->transformation_.matrix().setZero(); + context_it.second->mutex_.unlock(); } } } -bool TransformProvider::getTransform(MeshHandle handle, Isometry3d& transform) const +bool TransformProvider::getTransform(mesh_filter::MeshHandle handle, Eigen::Isometry3d& transform) const { - map >::const_iterator contextIt = handle2context_.find(handle); + auto context_it = handle2context_.find(handle); - if (contextIt == handle2context_.end()) + if (context_it == handle2context_.end()) { ROS_ERROR("Unable to find mesh with handle %d", handle); return false; } - contextIt->second->mutex_.lock(); - transform = contextIt->second->transformation_; - contextIt->second->mutex_.unlock(); + context_it->second->mutex_.lock(); + transform = context_it->second->transformation_; + context_it->second->mutex_.unlock(); return !(transform.matrix().isZero(0)); } void TransformProvider::run() { if (handle2context_.empty()) - throw runtime_error("TransformProvider is listening to empty list of frames!"); + throw std::runtime_error("TransformProvider is listening to empty list of frames!"); while (!stop_) { @@ -128,45 +121,43 @@ void TransformProvider::setUpdateInterval(unsigned long usecs) void TransformProvider::updateTransforms() { - static tf2::Stamped input_transform, output_transform; + static tf2::Stamped input_transform, output_transform; static robot_state::RobotStatePtr robot_state; robot_state = psm_->getStateMonitor()->getCurrentState(); try { geometry_msgs::TransformStamped common_tf = tf_buffer_->lookupTransform(frame_id_, psm_->getPlanningScene()->getPlanningFrame(), ros::Time(0.0)); + input_transform.stamp_ = common_tf.header.stamp; } catch (tf2::TransformException& ex) { ROS_ERROR("TF Problem: %s", ex.what()); return; } - input_transform.stamp_ = common_tf.header.stamp; input_transform.frame_id_ = psm_->getPlanningScene()->getPlanningFrame(); - for (map >::const_iterator contextIt = handle2context_.begin(); - contextIt != handle2context_.end(); ++contextIt) + for (auto& context_it : handle2context_) { try { // TODO: check logic here - which global collision body's transform should be used? - input_transform.setData( - robot_state->getAttachedBody(contextIt->second->frame_id_)->getGlobalCollisionBodyTransforms()[0]); + input_transform.setData(robot_state->getGlobalLinkTransform(context_it.second->frame_id_)); tf_buffer_->transform(input_transform, output_transform, frame_id_); } catch (const tf2::TransformException& ex) { - handle2context_[contextIt->first]->mutex_.lock(); - handle2context_[contextIt->first]->transformation_.matrix().setZero(); - handle2context_[contextIt->first]->mutex_.unlock(); + handle2context_[context_it.first]->mutex_.lock(); + handle2context_[context_it.first]->transformation_.matrix().setZero(); + handle2context_[context_it.first]->mutex_.unlock(); continue; } catch (std::exception& ex) { ROS_ERROR("Caught %s while updating transforms", ex.what()); } - handle2context_[contextIt->first]->mutex_.lock(); - handle2context_[contextIt->first]->transformation_ = static_cast(output_transform); - handle2context_[contextIt->first]->mutex_.unlock(); + handle2context_[context_it.first]->mutex_.lock(); + handle2context_[context_it.first]->transformation_ = static_cast(output_transform); + handle2context_[context_it.first]->mutex_.unlock(); } } diff --git a/moveit_ros/perception/mesh_filter/test/mesh_filter_test.cpp b/moveit_ros/perception/mesh_filter/test/mesh_filter_test.cpp index e0a0c628a0..47fe8fbc4e 100644 --- a/moveit_ros/perception/mesh_filter/test/mesh_filter_test.cpp +++ b/moveit_ros/perception/mesh_filter/test/mesh_filter_test.cpp @@ -43,7 +43,7 @@ using namespace mesh_filter; using namespace Eigen; using namespace std; -using namespace boost; +using namespace std::placeholders; namespace mesh_filter_test { @@ -118,7 +118,7 @@ MeshFilterTest::MeshFilterTest(unsigned width, unsigned height, double nea , shadow_(shadow) , epsilon_(epsilon) , sensor_parameters_(width, height, near_, far_, width >> 1, height >> 1, width >> 1, height >> 1, 0.1, 0.1) - , filter_(boost::bind(&MeshFilterTest::transformCallback, this, _1, _2), sensor_parameters_) + , filter_(std::bind(&MeshFilterTest::transformCallback, this, _1, _2), sensor_parameters_) , sensor_data_(width_ * height_) , distance_(0.0) { diff --git a/moveit_ros/perception/moveit_depth_self_filter.xml b/moveit_ros/perception/moveit_depth_self_filter.xml new file mode 100644 index 0000000000..4153868295 --- /dev/null +++ b/moveit_ros/perception/moveit_depth_self_filter.xml @@ -0,0 +1,7 @@ + + + + Nodelet for filtering meshes from depth images. e.g. meshes of the robot or any attached object where a transformation can be provided for. + + + diff --git a/moveit_ros/perception/package.xml b/moveit_ros/perception/package.xml index 07e4555811..0b3c7875a9 100644 --- a/moveit_ros/perception/package.xml +++ b/moveit_ros/perception/package.xml @@ -38,6 +38,8 @@ tf2_geometry_msgs tf2_ros moveit_ros_occupancy_map_monitor + moveit_ros_planning + nodelet eigen @@ -46,6 +48,7 @@ + diff --git a/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp b/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp index 193837384c..82de6ca6b3 100644 --- a/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp +++ b/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp @@ -1615,9 +1615,9 @@ bool moveit::planning_interface::MoveGroupInterface::setJointValueTarget(const s auto const n_group_joints = impl_->getJointModelGroup()->getVariableCount(); if (joint_values.size() != n_group_joints) { - ROS_DEBUG_STREAM_NAMED(LOGNAME, "Provided joint value list has length " << joint_values.size() << " but group " - << impl_->getJointModelGroup()->getName() - << " has " << n_group_joints << " joints"); + ROS_DEBUG_STREAM("Provided joint value list has length " << joint_values.size() << " but group " + << impl_->getJointModelGroup()->getName() << " has " + << n_group_joints << " joints"); return false; } impl_->setTargetType(JOINT); From a6035daf7d5b7714b294f7ecc85fae1942158da9 Mon Sep 17 00:00:00 2001 From: parunapu <80062145+parunapu@users.noreply.github.com> Date: Thu, 11 Mar 2021 13:03:02 -0500 Subject: [PATCH 099/179] stop_requested_ flag clearing fix (#2537) --- moveit_ros/moveit_servo/src/pose_tracking.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/moveit_ros/moveit_servo/src/pose_tracking.cpp b/moveit_ros/moveit_servo/src/pose_tracking.cpp index 723fe2d8f7..4fffe29954 100644 --- a/moveit_ros/moveit_servo/src/pose_tracking.cpp +++ b/moveit_ros/moveit_servo/src/pose_tracking.cpp @@ -79,6 +79,8 @@ PoseTracking::PoseTracking(const ros::NodeHandle& nh, PoseTrackingStatusCode PoseTracking::moveToPose(const Eigen::Vector3d& positional_tolerance, const double angular_tolerance, const double target_pose_timeout) { + // Reset stop requested flag before starting motions + stop_requested_ = false; // Wait a bit for a target pose message to arrive. // The target pose may get updated by new messages as the robot moves (in a callback function). const ros::Time start_time = ros::Time::now(); From 3aea9b1189db34e238415e8d6ca26fee5c32f2f4 Mon Sep 17 00:00:00 2001 From: John Stechschulte Date: Fri, 12 Mar 2021 10:06:44 -0700 Subject: [PATCH 100/179] Fixed flood of errors on startup for `mesh_filter` (#2550) * fixed mesh_filter error spam on startup * infinite loop fix from Andy --- .../moveit/mesh_filter/transform_provider.h | 19 +++++++++---------- .../src/depth_self_filter_nodelet.cpp | 4 ++-- .../mesh_filter/src/transform_provider.cpp | 17 ++++++++++++----- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/transform_provider.h b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/transform_provider.h index 2179e30919..386f293be2 100644 --- a/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/transform_provider.h +++ b/moveit_ros/perception/mesh_filter/include/moveit/mesh_filter/transform_provider.h @@ -59,9 +59,9 @@ class TransformProvider /** * \brief Constructor * \author Suat Gedikli (gedikli@willowgarage.com) - * \param[in] interval_us update interval in micro seconds + * \param[in] update_rate update rate in Hz */ - TransformProvider(unsigned long interval_us = 30000); + TransformProvider(double update_rate = 30.); /** \brief Destructor */ ~TransformProvider(); @@ -79,7 +79,7 @@ class TransformProvider * \brief registers a mesh with its handle * \author Suat Gedikli (gedikli@willowgarage.com) * \param[in] handle handle of the mesh - * \param[in] name frame_id_ of teh mesh + * \param[in] name frame_id_ of the mesh */ void addHandle(mesh_filter::MeshHandle handle, const std::string& name); @@ -103,13 +103,12 @@ class TransformProvider void stop(); /** - * \brief sets the update interval in micro seconds. This should be low enough to reduce the system load but high - * enough - * to get up-to-date transformations. For PSDK compatible devices this value should be around 30000 = 30ms + * \brief sets the update rate in Hz. This should be slow enough to reduce the system load but fast enough to get + * up-to-date transformations. For PSDK compatible devices this value should be around 30 Hz. * \author Suat Gedikli (gedikli@willowgarage.com) - * \param[in] usecs interval in micro seconds + * \param[in] update_rate update rate in Hz */ - void setUpdateInterval(unsigned long usecs); + void setUpdateRate(double update_rate); private: /** @@ -163,7 +162,7 @@ class TransformProvider /** \flag to leave the update loop*/ bool stop_; - /** \brief update interval in micro seconds*/ - unsigned long interval_us_; + /** \brief update rate in Hz*/ + ros::Rate update_rate_; }; #endif diff --git a/moveit_ros/perception/mesh_filter/src/depth_self_filter_nodelet.cpp b/moveit_ros/perception/mesh_filter/src/depth_self_filter_nodelet.cpp index 720c3a2674..dc91e5b884 100644 --- a/moveit_ros/perception/mesh_filter/src/depth_self_filter_nodelet.cpp +++ b/moveit_ros/perception/mesh_filter/src/depth_self_filter_nodelet.cpp @@ -68,9 +68,9 @@ void mesh_filter::DepthSelfFiltering::onInit() private_nh.param("shadow_threshold", shadow_threshold_, 0.3); private_nh.param("padding_scale", padding_scale_, 1.0); private_nh.param("padding_offset", padding_offset_, 0.005); - double tf_update_rate = 30; + double tf_update_rate = 30.; private_nh.param("tf_update_rate", tf_update_rate, 30.0); - transform_provider_.setUpdateInterval(long(1000000.0 / tf_update_rate)); + transform_provider_.setUpdateRate(tf_update_rate); image_transport::SubscriberStatusCallback itssc = std::bind(&DepthSelfFiltering::connectCb, this); ros::SubscriberStatusCallback rssc = std::bind(&DepthSelfFiltering::connectCb, this); diff --git a/moveit_ros/perception/mesh_filter/src/transform_provider.cpp b/moveit_ros/perception/mesh_filter/src/transform_provider.cpp index 888130367f..e16fb34de8 100644 --- a/moveit_ros/perception/mesh_filter/src/transform_provider.cpp +++ b/moveit_ros/perception/mesh_filter/src/transform_provider.cpp @@ -39,7 +39,7 @@ #include #include -TransformProvider::TransformProvider(unsigned long interval_us) : stop_(true), interval_us_(interval_us) +TransformProvider::TransformProvider(double update_rate) : stop_(true), update_rate_(update_rate) { tf_buffer_ = std::make_shared(); tf_listener_.reset(new tf2_ros::TransformListener(*tf_buffer_)); @@ -107,20 +107,27 @@ void TransformProvider::run() if (handle2context_.empty()) throw std::runtime_error("TransformProvider is listening to empty list of frames!"); - while (!stop_) + while (ros::ok() && !stop_) { updateTransforms(); - usleep(interval_us_); + update_rate_.sleep(); } } -void TransformProvider::setUpdateInterval(unsigned long usecs) +void TransformProvider::setUpdateRate(double update_rate) { - interval_us_ = usecs; + update_rate_ = ros::Rate(update_rate); } void TransformProvider::updateTransforms() { + // Don't bother if frame_id_ is empty (true initially) + if (frame_id_.empty()) + { + ROS_DEBUG_THROTTLE(2., "Not updating transforms because frame_id_ is empty."); + return; + } + static tf2::Stamped input_transform, output_transform; static robot_state::RobotStatePtr robot_state; robot_state = psm_->getStateMonitor()->getCurrentState(); From 37c6c1a0ab799d9c98c48c4d6a492f90bde4c1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Fri, 19 Mar 2021 16:20:12 +0100 Subject: [PATCH 101/179] PlanExecution: Correctly handle preempt-requested flag (#2554) So far, executeAndMonitor() was only called via planAndExecuteHelper(), which was resetting the preempt-requested flag when entering the function (ignoring leftover preempt signals from previous runs). However, now MTC also calls executeAndMonitor() directly and thus we need to reset the flag there as well - but only if it is called directly. --- .../moveit/plan_execution/plan_execution.h | 24 ++++++++- .../plan_execution/src/plan_execution.cpp | 53 ++++++++++++------- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_execution.h b/moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_execution.h index 0eb02648fa..5933ce5b5b 100644 --- a/moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_execution.h +++ b/moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_execution.h @@ -45,6 +45,8 @@ #include #include +#include + /** \brief This namespace includes functionality specific to the execution and monitoring of motion plans */ namespace plan_execution { @@ -134,7 +136,7 @@ class PlanExecution In case there is no \e planning_scene or \e planning_scene_monitor set in the \e plan they will be set at the start of the method. They are then used to monitor the execution. */ - moveit_msgs::MoveItErrorCodes executeAndMonitor(ExecutableMotionPlan& plan); + moveit_msgs::MoveItErrorCodes executeAndMonitor(ExecutableMotionPlan& plan, bool reset_preempted = true); void stop(); @@ -156,7 +158,25 @@ class PlanExecution unsigned int default_max_replan_attempts_; - bool preempt_requested_; + class + { + private: + std::atomic preemption_requested{ false }; + + public: + /** \brief check *and clear* the preemption flag + + A true return value has to trigger full execution stop, as it consumes the request */ + inline bool checkAndClear() + { + return preemption_requested.exchange(false); + } + inline void request() + { + preemption_requested.store(true); + } + } preempt_; + bool new_scene_update_; bool execution_complete_; diff --git a/moveit_ros/planning/plan_execution/src/plan_execution.cpp b/moveit_ros/planning/plan_execution/src/plan_execution.cpp index a3d81b33e0..814e301bda 100644 --- a/moveit_ros/planning/plan_execution/src/plan_execution.cpp +++ b/moveit_ros/planning/plan_execution/src/plan_execution.cpp @@ -82,7 +82,6 @@ plan_execution::PlanExecution::PlanExecution( default_max_replan_attempts_ = 5; - preempt_requested_ = false; new_scene_update_ = false; // we want to be notified when new information is available @@ -99,7 +98,7 @@ plan_execution::PlanExecution::~PlanExecution() void plan_execution::PlanExecution::stop() { - preempt_requested_ = true; + preempt_.request(); } std::string plan_execution::PlanExecution::getErrorCodeString(const moveit_msgs::MoveItErrorCodes& error_code) @@ -160,7 +159,9 @@ void plan_execution::PlanExecution::planAndExecute(ExecutableMotionPlan& plan, void plan_execution::PlanExecution::planAndExecuteHelper(ExecutableMotionPlan& plan, const Options& opt) { // perform initial configuration steps & various checks - preempt_requested_ = false; + preempt_.checkAndClear(); // clear any previous preempt_ request + + bool preempt_requested = false; // run the actual motion plan & execution unsigned int max_replan_attempts = @@ -188,7 +189,8 @@ void plan_execution::PlanExecution::planAndExecuteHelper(ExecutableMotionPlan& p opt.plan_callback_(plan) : opt.repair_plan_callback_(plan, trajectory_execution_manager_->getCurrentExpectedTrajectoryIndex()); - if (preempt_requested_) + preempt_requested = preempt_.checkAndClear(); + if (preempt_requested) break; // if planning fails in a manner that is not recoverable, we exit the loop, @@ -216,23 +218,23 @@ void plan_execution::PlanExecution::planAndExecuteHelper(ExecutableMotionPlan& p if (opt.before_execution_callback_) opt.before_execution_callback_(); - if (preempt_requested_) + preempt_requested = preempt_.checkAndClear(); + if (preempt_requested) break; // execute the trajectory, and monitor its execution - plan.error_code_ = executeAndMonitor(plan); + plan.error_code_ = executeAndMonitor(plan, false); } - // if we are done, then we exit the loop - if (plan.error_code_.val == moveit_msgs::MoveItErrorCodes::SUCCESS) - break; + if (plan.error_code_.val == moveit_msgs::MoveItErrorCodes::PREEMPTED) + preempt_requested = true; - // if execution failed in a manner that we do not consider recoverable, we exit the loop (with failure) + // if execution succeeded or failed in a manner that we do not consider recoverable, we exit the loop (with failure) if (plan.error_code_.val != moveit_msgs::MoveItErrorCodes::MOTION_PLAN_INVALIDATED_BY_ENVIRONMENT_CHANGE) break; else { - // othewrise, we wait (if needed) + // otherwise, we wait (if needed) if (opt.replan_delay_ > 0.0) { ROS_INFO_NAMED("plan_execution", "Waiting for a %lf seconds before attempting a new plan ...", @@ -242,9 +244,14 @@ void plan_execution::PlanExecution::planAndExecuteHelper(ExecutableMotionPlan& p ROS_INFO_NAMED("plan_execution", "Done waiting"); } } - } while (!preempt_requested_ && max_replan_attempts > replan_attempts); - if (preempt_requested_) + preempt_requested = preempt_.checkAndClear(); + if (preempt_requested) + break; + + } while (replan_attempts < max_replan_attempts); + + if (preempt_requested) { ROS_DEBUG_NAMED("plan_execution", "PlanExecution was preempted"); plan.error_code_.val = moveit_msgs::MoveItErrorCodes::PREEMPTED; @@ -313,8 +320,12 @@ bool plan_execution::PlanExecution::isRemainingPathValid(const ExecutableMotionP return true; } -moveit_msgs::MoveItErrorCodes plan_execution::PlanExecution::executeAndMonitor(ExecutableMotionPlan& plan) +moveit_msgs::MoveItErrorCodes plan_execution::PlanExecution::executeAndMonitor(ExecutableMotionPlan& plan, + bool reset_preempted) { + if (reset_preempted) + preempt_.checkAndClear(); + if (!plan.planning_scene_monitor_) plan.planning_scene_monitor_ = planning_scene_monitor_; if (!plan.planning_scene_) @@ -409,7 +420,9 @@ moveit_msgs::MoveItErrorCodes plan_execution::PlanExecution::executeAndMonitor(E // wait for path to be done, while checking that the path does not become invalid ros::Rate r(100); path_became_invalid_ = false; - while (node_handle_.ok() && !execution_complete_ && !preempt_requested_ && !path_became_invalid_) + bool preempt_requested = false; + + while (node_handle_.ok() && !execution_complete_ && !path_became_invalid_) { r.sleep(); // check the path if there was an environment update in the meantime @@ -422,10 +435,14 @@ moveit_msgs::MoveItErrorCodes plan_execution::PlanExecution::executeAndMonitor(E break; } } + + preempt_requested = preempt_.checkAndClear(); + if (preempt_requested) + break; } // stop execution if needed - if (preempt_requested_) + if (preempt_requested) { ROS_INFO_NAMED("plan_execution", "Stopping execution due to preempt request"); trajectory_execution_manager_->stopExecution(); @@ -457,7 +474,7 @@ moveit_msgs::MoveItErrorCodes plan_execution::PlanExecution::executeAndMonitor(E result.val = moveit_msgs::MoveItErrorCodes::MOTION_PLAN_INVALIDATED_BY_ENVIRONMENT_CHANGE; else { - if (preempt_requested_) + if (preempt_requested) { result.val = moveit_msgs::MoveItErrorCodes::PREEMPTED; } @@ -505,7 +522,7 @@ void plan_execution::PlanExecution::successfulTrajectorySegmentExecution(const E { // execution of side-effect failed ROS_ERROR_NAMED("plan_execution", "Execution of path-completion side-effect failed. Preempting."); - preempt_requested_ = true; + preempt_.request(); return; } From f310c58e2fa821347e917b37c95db322a02201b6 Mon Sep 17 00:00:00 2001 From: AdamPettinger Date: Mon, 22 Mar 2021 08:45:47 -0500 Subject: [PATCH 102/179] [Servo] Halt Servo command on Pose Tracking stop (#2501) * Publish Servo stop in Pose Tracking cleanup * Move publish halt to stopMotion() --- .../include/moveit_servo/pose_tracking.h | 5 +---- moveit_ros/moveit_servo/src/pose_tracking.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h b/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h index 5163cc08c8..d705938f91 100644 --- a/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h +++ b/moveit_ros/moveit_servo/include/moveit_servo/pose_tracking.h @@ -92,10 +92,7 @@ class PoseTracking const double target_pose_timeout); /** \brief A method for a different thread to stop motion and return early from control loop */ - void stopMotion() - { - stop_requested_ = true; - } + void stopMotion(); /** \brief Change PID parameters. Motion is stopped before the udpate */ void updatePIDConfig(const double x_proportional_gain, const double x_integral_gain, const double x_derivative_gain, diff --git a/moveit_ros/moveit_servo/src/pose_tracking.cpp b/moveit_ros/moveit_servo/src/pose_tracking.cpp index 4fffe29954..f56182e44f 100644 --- a/moveit_ros/moveit_servo/src/pose_tracking.cpp +++ b/moveit_ros/moveit_servo/src/pose_tracking.cpp @@ -309,8 +309,23 @@ geometry_msgs::TwistStampedConstPtr PoseTracking::calculateTwistCommand() return msg; } +void PoseTracking::stopMotion() +{ + stop_requested_ = true; + + // Send a 0 command to Servo to halt arm motion + auto msg = moveit::util::make_shared_from_pool(); + { + std::lock_guard lock(target_pose_mtx_); + msg->header.frame_id = target_pose_.header.frame_id; + } + msg->header.stamp = ros::Time::now(); + twist_stamped_pub_.publish(msg); +} + void PoseTracking::doPostMotionReset() { + stopMotion(); stop_requested_ = false; angular_error_ = boost::none; From 3cd504cda91ab28cc1389a309a5a9b0438f09a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Thu, 25 Mar 2021 17:14:29 +0100 Subject: [PATCH 103/179] Fix segfault in MSA (#2564) Occurred when a group was defined in the launch file without a `ns` attribute. --- moveit_setup_assistant/src/tools/moveit_config_data.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/moveit_setup_assistant/src/tools/moveit_config_data.cpp b/moveit_setup_assistant/src/tools/moveit_config_data.cpp index e12c5bc5f1..547ab2508c 100644 --- a/moveit_setup_assistant/src/tools/moveit_config_data.cpp +++ b/moveit_setup_assistant/src/tools/moveit_config_data.cpp @@ -1395,7 +1395,8 @@ bool MoveItConfigData::inputPlanningContextLaunch(const std::string& file_path) // find the kinematics section TiXmlHandle doc(&launch_document); TiXmlElement* kinematics_group = doc.FirstChild("launch").FirstChild("group").ToElement(); - while (kinematics_group && kinematics_group->Attribute("ns") != std::string("$(arg robot_description)_kinematics")) + while (kinematics_group && kinematics_group->Attribute("ns") && + kinematics_group->Attribute("ns") != std::string("$(arg robot_description)_kinematics")) { kinematics_group = kinematics_group->NextSiblingElement("group"); } From 80ae2c98ae8009b9e6792d9f3b6535120d6c8e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Tue, 6 Apr 2021 17:02:19 +0200 Subject: [PATCH 104/179] Make setToIKSolverFrame accessible again (#2580) This is public API because the solver's getPositionIK requires input poses in the frame and the relevant transform is otherwise inaccessible. Partially reverts #2461. --- .../include/moveit/robot_state/robot_state.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/moveit_core/robot_state/include/moveit/robot_state/robot_state.h b/moveit_core/robot_state/include/moveit/robot_state/robot_state.h index 2df3b232d7..46c261fec8 100644 --- a/moveit_core/robot_state/include/moveit/robot_state/robot_state.h +++ b/moveit_core/robot_state/include/moveit/robot_state/robot_state.h @@ -1831,18 +1831,13 @@ as the new values that correspond to the group */ std::string getStateTreeString(const std::string& prefix = "") const; -private: - void allocMemory(); - void initTransforms(); - void copyFrom(const RobotState& other); - /** * \brief Transform pose from the robot model's base frame to the reference frame of the IK solver * @param pose - the input to change * @param solver - a kin solver whose base frame is important to us * @return true if no error */ - inline bool setToIKSolverFrame(Eigen::Isometry3d& pose, const kinematics::KinematicsBaseConstPtr& solver); + bool setToIKSolverFrame(Eigen::Isometry3d& pose, const kinematics::KinematicsBaseConstPtr& solver); /** * \brief Transform pose from the robot model's base frame to the reference frame of the IK solver @@ -1852,6 +1847,11 @@ as the new values that correspond to the group */ */ bool setToIKSolverFrame(Eigen::Isometry3d& pose, const std::string& ik_frame); +private: + void allocMemory(); + void initTransforms(); + void copyFrom(const RobotState& other); + void markDirtyJointTransforms(const JointModel* joint) { dirty_joint_transforms_[joint->getJointIndex()] = 1; From 7a6731a7e909fdf9c440a31f081f29d5da3825d1 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 7 Apr 2021 00:32:27 +0200 Subject: [PATCH 105/179] Keep MotionPlanningFrame hidden on Display::reset() --- .../src/motion_planning_display.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_display.cpp b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_display.cpp index 95097f0e45..2388518d10 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_display.cpp +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_display.cpp @@ -298,11 +298,14 @@ void MotionPlanningDisplay::reset() // Planned Path Display trajectory_visual_->reset(); + bool enabled = this->isEnabled(); frame_->disable(); - frame_->enable(); - - query_robot_start_->setVisible(query_start_state_property_->getBool()); - query_robot_goal_->setVisible(query_goal_state_property_->getBool()); + if (enabled) + { + frame_->enable(); + query_robot_start_->setVisible(query_start_state_property_->getBool()); + query_robot_goal_->setVisible(query_goal_state_property_->getBool()); + } } void MotionPlanningDisplay::setName(const QString& name) From b36d7826691f43a820779db89de013e21595352b Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 7 Apr 2021 00:33:36 +0200 Subject: [PATCH 106/179] Call renderPlanningScene() only if planning_scene_render_ is valid --- .../src/planning_scene_display.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/moveit_ros/visualization/planning_scene_rviz_plugin/src/planning_scene_display.cpp b/moveit_ros/visualization/planning_scene_rviz_plugin/src/planning_scene_display.cpp index 21917663b3..13ce10871f 100644 --- a/moveit_ros/visualization/planning_scene_rviz_plugin/src/planning_scene_display.cpp +++ b/moveit_ros/visualization/planning_scene_rviz_plugin/src/planning_scene_display.cpp @@ -647,9 +647,9 @@ void PlanningSceneDisplay::update(float wall_dt, float ros_dt) void PlanningSceneDisplay::updateInternal(float wall_dt, float ros_dt) { current_scene_time_ += wall_dt; - if ((current_scene_time_ > scene_display_time_property_->getFloat() && planning_scene_render_ && - robot_state_needs_render_) || - planning_scene_needs_render_) + if (planning_scene_render_ && + ((current_scene_time_ > scene_display_time_property_->getFloat() && robot_state_needs_render_) || + planning_scene_needs_render_)) { renderPlanningScene(); calculateOffsetPosition(); From a505a74a469b03fadd929ff1a013fe832da0dbc6 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 7 Apr 2021 01:04:06 +0200 Subject: [PATCH 107/179] Fix deadlock in PlanningSceneDisplay Only trigger loadRobotModel() if display is enabled. Otherwise, it tries to waitForMainLoopJobs(), which are never called because update() isn't called anymore. --- .../src/planning_scene_display.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/moveit_ros/visualization/planning_scene_rviz_plugin/src/planning_scene_display.cpp b/moveit_ros/visualization/planning_scene_rviz_plugin/src/planning_scene_display.cpp index 13ce10871f..0739cdccb2 100644 --- a/moveit_ros/visualization/planning_scene_rviz_plugin/src/planning_scene_display.cpp +++ b/moveit_ros/visualization/planning_scene_rviz_plugin/src/planning_scene_display.cpp @@ -206,10 +206,11 @@ void PlanningSceneDisplay::reset() planning_scene_render_.reset(); if (planning_scene_robot_) planning_scene_robot_->clear(); - - addBackgroundJob(boost::bind(&PlanningSceneDisplay::loadRobotModel, this), "loadRobotModel"); Display::reset(); + if (isEnabled()) + addBackgroundJob(boost::bind(&PlanningSceneDisplay::loadRobotModel, this), "loadRobotModel"); + if (planning_scene_robot_) { planning_scene_robot_->setVisible(true); From 118b15815e75ba2a52c6ecb895875eb735c76107 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 9 Apr 2021 22:58:42 +0200 Subject: [PATCH 108/179] GHA: Add pre-release job --- .github/workflows/prerelease.yaml | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/prerelease.yaml diff --git a/.github/workflows/prerelease.yaml b/.github/workflows/prerelease.yaml new file mode 100644 index 0000000000..2fddb7884f --- /dev/null +++ b/.github/workflows/prerelease.yaml @@ -0,0 +1,53 @@ +# This config uses industrial_ci (https://github.com/ros-industrial/industrial_ci.git). +# For troubleshooting, see readme (https://github.com/ros-industrial/industrial_ci/blob/master/README.rst) + +name: pre-release + +on: + workflow_dispatch: + pull_request: + push: + branches: + - melodic-devel + +jobs: + default: + env: + ROS_DISTRO: melodic + PRERELEASE: true + BASEDIR: ${{ github.workspace }}/.work + CCACHE_DIR: ${{ github.workspace }}/.ccache + CACHE_PREFIX: melodic-pre-release + + runs-on: ubuntu-latest + steps: + - name: "Free up disk space" + run: | + sudo apt-get -qq purge build-essential ghc* + sudo apt-get clean + # cleanup docker images not used by us + docker system prune -af + # shift ccache folder to /mnt on a separate disk + sudo mkdir /mnt/ccache + mkdir ${{ env.CCACHE_DIR }} + sudo mount --bind ${{ env.CCACHE_DIR }} /mnt/ccache + # free up a lot of stuff from /usr/local + sudo rm -rf /usr/local/* + df -h + - uses: actions/checkout@v2 + - name: cache ccache + uses: pat-s/always-upload-cache@v2.1.3 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-${{ env.CACHE_PREFIX }}-${{ github.sha }}-${{ github.run_id }} + restore-keys: | + ccache-${{ env.CACHE_PREFIX }}-${{ github.sha }} + ccache-${{ env.CACHE_PREFIX }} + - name: industrial_ci + uses: ros-industrial/industrial_ci@master + - name: upload test artifacts (on failure) + uses: actions/upload-artifact@v2 + if: failure() + with: + name: test-results + path: ${{ env.BASEDIR }}/target_ws/**/test_results/**/*.xml From 70fd40c3f2529078bd697b947876a871fccea81a Mon Sep 17 00:00:00 2001 From: Nathan Brooks Date: Tue, 13 Apr 2021 01:40:58 -0600 Subject: [PATCH 109/179] Avoid joint jump when SuddenHalt() is called in velocity mode (#2594) Port of https://github.com/ros-planning/moveit2/pull/410 * Avoid joint jump when SuddenHalt() is called in velocity mode * Fix parameters_ access (different in MoveIt2) --- moveit_ros/moveit_servo/src/servo_calcs.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index 6270c507eb..9ee531445b 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -188,8 +188,7 @@ void ServoCalcs::start() // I do not know of a robot that takes acceleration commands. // However, some controllers check that this data is non-empty. // Send all zeros, for now. - std::vector acceleration(num_joints_); - point.accelerations = acceleration; + point.accelerations.resize(num_joints_); } initial_joint_trajectory->points.push_back(point); last_sent_command_ = initial_joint_trajectory; @@ -835,8 +834,10 @@ void ServoCalcs::suddenHalt(trajectory_msgs::JointTrajectory& joint_trajectory) // being 0 seconds in the past, the smallest supported timestep is added as time from start to the trajectory point. point.time_from_start.fromNSec(1); - point.positions.resize(num_joints_); - point.velocities.resize(num_joints_); + if (parameters_.publish_joint_positions) + point.positions.resize(num_joints_); + if (parameters_.publish_joint_velocities) + point.velocities.resize(num_joints_); // Assert the following loop is safe to execute assert(original_joint_state_.position.size() >= num_joints_); From ea4bbc6eb4ab9cea16a1f32180474d903b0b1aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Wed, 14 Apr 2021 16:46:33 +0200 Subject: [PATCH 110/179] Let users override fake execution type from demo.launch (#2602) This should be the main entry point for simulated robot systems and we specifically want to support `last point` here for rostests. --- .../templates/moveit_config_pkg_template/launch/demo.launch | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch index 78452951eb..5c9de5e38b 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch @@ -14,6 +14,9 @@ + + + - - + + From e0640259be84734a41a2287c77dd1d3da13ac8a0 Mon Sep 17 00:00:00 2001 From: Toru Kuga Date: Mon, 16 Aug 2021 12:56:16 +0900 Subject: [PATCH 142/179] code fix on wrong substitution --- moveit_core/kinematic_constraints/src/utils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moveit_core/kinematic_constraints/src/utils.cpp b/moveit_core/kinematic_constraints/src/utils.cpp index ee12c491a2..a7add9a709 100644 --- a/moveit_core/kinematic_constraints/src/utils.cpp +++ b/moveit_core/kinematic_constraints/src/utils.cpp @@ -144,8 +144,8 @@ moveit_msgs::Constraints constructGoalConstraints(const robot_state::RobotState& { goal.joint_constraints[i].joint_name = jmg->getVariableNames()[i]; goal.joint_constraints[i].position = vals[i]; - goal.joint_constraints[i].tolerance_above = tolerance_below; - goal.joint_constraints[i].tolerance_below = tolerance_above; + goal.joint_constraints[i].tolerance_above = tolerance_above; + goal.joint_constraints[i].tolerance_below = tolerance_below; goal.joint_constraints[i].weight = 1.0; } From a780c156b2ad8bb386dc9746e2c33561ca427c2c Mon Sep 17 00:00:00 2001 From: Vatan Aksoy Tezer Date: Thu, 19 Aug 2021 18:38:48 +0300 Subject: [PATCH 143/179] CI: Update pat-s/always-upload-cache --- .github/workflows/ci.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 838845c2c6..cb4e41ef0f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -62,7 +62,7 @@ jobs: df -h - uses: actions/checkout@v2 - name: cache upstream workspace - uses: pat-s/always-upload-cache@v2.1.3 + uses: pat-s/always-upload-cache@v2.1.5 with: path: ${{ env.BASEDIR }}/upstream_ws key: ${{ env.CACHE_PREFIX }}-${{ github.run_id }} @@ -70,7 +70,7 @@ jobs: env: CACHE_PREFIX: upstream_ws-${{ matrix.env.IMAGE }}-${{ hashFiles('.github/workflows/upstream.rosinstall') }} - name: cache downstream workspace - uses: pat-s/always-upload-cache@v2.1.3 + uses: pat-s/always-upload-cache@v2.1.5 with: path: ${{ env.BASEDIR }}/downstream_ws key: ${{ env.CACHE_PREFIX }}-${{ github.run_id }} @@ -81,7 +81,7 @@ jobs: # that comes from the checkout. See "prepare target_ws for cache" task below - name: cache target workspace if: ${{ ! matrix.env.CCOV }} - uses: pat-s/always-upload-cache@v2.1.3 + uses: pat-s/always-upload-cache@v2.1.5 with: path: ${{ env.BASEDIR }}/target_ws key: ${{ env.CACHE_PREFIX }}-${{ github.run_id }} @@ -89,7 +89,7 @@ jobs: env: CACHE_PREFIX: target_ws${{ matrix.env.CCOV && '-ccov' || '' }}-${{ matrix.env.IMAGE }}-${{ hashFiles('**/CMakeLists.txt', '**/package.xml') }} - name: cache ccache - uses: pat-s/always-upload-cache@v2.1.3 + uses: pat-s/always-upload-cache@v2.1.5 with: path: ${{ env.CCACHE_DIR }} key: ${{ env.CACHE_PREFIX }}-${{ github.sha }}-${{ github.run_id }} From b2e08c1e2a00bead38d60bd94aff29fa55051312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Sun, 17 Oct 2021 19:56:00 +0200 Subject: [PATCH 144/179] Revert "Fix scaling factor parameter names (#2452)" (#2907) This reverts commit f8216e9d416b10ac67bc234ffd4ef4c122e2493a. should never have been committed to melodic. The change was meant only for noetic and the backport is incomplete. --- .../move_group_interface/src/move_group_interface.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp b/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp index 82de6ca6b3..edb102b8b7 100644 --- a/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp +++ b/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp @@ -124,10 +124,8 @@ class MoveGroupInterface::MoveGroupInterfaceImpl goal_orientation_tolerance_ = 1e-3; // ~0.1 deg allowed_planning_time_ = 5.0; num_planning_attempts_ = 1; - node_handle_.param("robot_description_planning/default_velocity_scaling_factor", - max_velocity_scaling_factor_, 0.1); - node_handle_.param("robot_description_planning/default_acceleration_scaling_factor", - max_acceleration_scaling_factor_, 0.1); + max_velocity_scaling_factor_ = 1.0; + max_acceleration_scaling_factor_ = 1.0; initializing_constraints_ = false; if (joint_model_group_->isChain()) From 0082c0f9ea2a1d3b259e517611e12fb2ca282ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Mon, 18 Oct 2021 05:21:36 +0200 Subject: [PATCH 145/179] Fix an off-by-one error in servo_calcs.cpp (#2740) (#2908) Co-authored-by: luisrayas3 --- moveit_ros/moveit_servo/src/servo_calcs.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/moveit_ros/moveit_servo/src/servo_calcs.cpp b/moveit_ros/moveit_servo/src/servo_calcs.cpp index 9ee531445b..e9d990ffd7 100644 --- a/moveit_ros/moveit_servo/src/servo_calcs.cpp +++ b/moveit_ros/moveit_servo/src/servo_calcs.cpp @@ -597,15 +597,15 @@ bool ServoCalcs::convertDeltasToOutgoingCmd(trajectory_msgs::JointTrajectory& jo // Spam several redundant points into the trajectory. The first few may be skipped if the // time stamp is in the past when it reaches the client. Needed for gazebo simulation. -// Start from 2 because the first point's timestamp is already 1*parameters_.publish_period void ServoCalcs::insertRedundantPointsIntoTrajectory(trajectory_msgs::JointTrajectory& joint_trajectory, int count) const { joint_trajectory.points.resize(count); auto point = joint_trajectory.points[0]; - // Start from 2 because we already have the first point. End at count+1 so (total #) == count - for (int i = 2; i < count; ++i) + // Start from 2nd point (i = 1) because we already have the first point. + // The timestamps are shifted up one period since first point is at 1 * publish_period, not 0. + for (int i = 1; i < count; ++i) { - point.time_from_start = ros::Duration(i * parameters_.publish_period); + point.time_from_start = ros::Duration((i + 1) * parameters_.publish_period); joint_trajectory.points[i] = point; } } From 7fcf076e88c12cc720d3e3614ea2a4532a9535ed Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 5 Nov 2021 13:53:35 +0100 Subject: [PATCH 146/179] CI: Adopt settings from noetic-devel --- .ci.prepare_codecov | 21 --------- .github/workflows/ci.yaml | 85 ++++++++++++++++++++++------------- .github/workflows/format.yaml | 8 +++- .pre-commit-config.yaml | 2 +- 4 files changed, 61 insertions(+), 55 deletions(-) delete mode 100755 .ci.prepare_codecov diff --git a/.ci.prepare_codecov b/.ci.prepare_codecov deleted file mode 100755 index 91119f5dc1..0000000000 --- a/.ci.prepare_codecov +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -pushd $BASEDIR - -BLUE='\033[0;34m' -NOCOLOR='\033[0m' - -apt-get install -qq lcov - -echo -e "${BLUE}Capture coverage info${NOCOLOR}" -lcov --capture --directory target_ws --output-file coverage.info - -echo -e "${BLUE}Extract repository files${NOCOLOR}" -lcov --extract coverage.info "$BASEDIR/target_ws/src/$TARGET_REPO_NAME/*" --output-file coverage.info - -echo -e "${BLUE}Filter out test files${NOCOLOR}" -lcov --remove coverage.info '*/test/*' --output-file coverage.info - -echo -e "${BLUE}Output coverage data for debugging${NOCOLOR}" -lcov --list coverage.info - -popd diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index cb4e41ef0f..a7cf1a8add 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,11 +21,12 @@ jobs: - IMAGE: melodic-ci-shadow-fixed IKFAST_TEST: true CATKIN_LINT: true - CLANG_TIDY: true + CLANG_TIDY: pedantic env: CXXFLAGS: >- - -Werror -Wall -Wextra -Wwrite-strings -Wunreachable-code -Wpointer-arith -Wredundant-decls + -Wall -Wextra -Wwrite-strings -Wunreachable-code -Wpointer-arith -Wredundant-decls -Wno-deprecated-copy -Wno-unused-parameter -Wno-unused-but-set-parameter + CLANG_TIDY_ARGS: --fix --fix-errors --format-style=file DOCKER_IMAGE: moveit/moveit:${{ matrix.env.IMAGE }} UPSTREAM_WORKSPACE: .github/workflows/upstream.rosinstall TARGET_WORKSPACE: $TARGET_REPO_PATH github:ros-planning/moveit_resources#melodic-devel @@ -33,21 +34,28 @@ jobs: # Pull any updates to the upstream workspace (after restoring it from cache) AFTER_SETUP_UPSTREAM_WORKSPACE: vcs pull $BASEDIR/upstream_ws/src AFTER_SETUP_DOWNSTREAM_WORKSPACE: vcs pull $BASEDIR/downstream_ws/src - AFTER_RUN_TARGET_TEST: ${{ matrix.env.CCOV && './.ci.prepare_codecov' || '' }} + # Compile CCOV with Debug. Enable -Werror (except CLANG_TIDY=pedantic, which makes the clang-tidy step fail on warnings) TARGET_CMAKE_ARGS: > - -DCMAKE_BUILD_TYPE=${{ matrix.env.CCOV && 'RelWithDebInfo' || 'Release'}} - ${{ matrix.env.CCOV && '-DCMAKE_CXX_FLAGS="$CXXFLAGS --coverage"' || '' }} + -DCMAKE_BUILD_TYPE=${{ matrix.env.CCOV && 'Debug' || 'Release'}} + -DCMAKE_CXX_FLAGS="${{ matrix.env.CLANG_TIDY != 'pedantic' && '-Werror ' || '' }}$CXXFLAGS${{ matrix.env.CCOV && ' --coverage -O2 -fno-omit-frame-pointer'}}" UPSTREAM_CMAKE_ARGS: "-DCMAKE_CXX_FLAGS=''" - DOWNSTREAM_CMAKE_ARGS: "-DCMAKE_CXX_FLAGS=''" - CCACHE_DIR: "${{ github.workspace }}/.ccache" + DOWNSTREAM_CMAKE_ARGS: -DCMAKE_CXX_FLAGS="-Wall -Wextra" + CCACHE_DIR: ${{ github.workspace }}/.ccache BASEDIR: ${{ github.workspace }}/.work - CLANG_TIDY_BASE_REF: "${{ github.base_ref || github.ref }}" + CLANG_TIDY_BASE_REF: ${{ github.event_name != 'workflow_dispatch' && (github.base_ref || github.ref) || '' }} + BEFORE_CLANG_TIDY_CHECKS: | + # Show list of applied checks + (cd $TARGET_REPO_PATH; clang-tidy --list-checks) + # Disable clang-tidy for ikfast plugins as we cannot fix the generated code + find $BASEDIR/target_ws/build -iwholename "*_ikfast_plugin/compile_commands.json" -exec rm {} \; + CC: ${{ matrix.env.CLANG_TIDY && 'clang' }} + CXX: ${{ matrix.env.CLANG_TIDY && 'clang++' }} - name: "${{ matrix.env.IMAGE }}${{ matrix.env.CATKIN_LINT && ' + catkin_lint' || ''}}${{ matrix.env.CCOV && ' + ccov' || ''}}${{ matrix.env.IKFAST_TEST && ' + ikfast' || ''}}${{ matrix.env.CLANG_TIDY && ' + clang-tidy' || '' }}" + name: "${{ matrix.env.IMAGE }}${{ matrix.env.CATKIN_LINT && ' + catkin_lint' || ''}}${{ matrix.env.CCOV && ' + ccov' || ''}}${{ matrix.env.IKFAST_TEST && ' + ikfast' || ''}}${{ matrix.env.CLANG_TIDY && (github.event_name != 'workflow_dispatch' && ' + clang-tidy (delta)' || ' + clang-tidy (all)') || '' }}" runs-on: ubuntu-latest steps: - name: "Free up disk space" - if: ${{ matrix.env.CCOV }} + if: matrix.env.CCOV run: | sudo apt-get -qq purge build-essential "ghc*" sudo apt-get clean @@ -61,34 +69,34 @@ jobs: sudo rm -rf /usr/local df -h - uses: actions/checkout@v2 - - name: cache upstream workspace + - name: Cache upstream workspace uses: pat-s/always-upload-cache@v2.1.5 with: path: ${{ env.BASEDIR }}/upstream_ws key: ${{ env.CACHE_PREFIX }}-${{ github.run_id }} restore-keys: ${{ env.CACHE_PREFIX }} env: - CACHE_PREFIX: upstream_ws-${{ matrix.env.IMAGE }}-${{ hashFiles('.github/workflows/upstream.rosinstall') }} - - name: cache downstream workspace + CACHE_PREFIX: upstream_ws-${{ matrix.env.IMAGE }}-${{ hashFiles('.github/workflows/upstream.rosinstall', '.github/workflows/ci.yaml') }} + - name: Cache downstream workspace uses: pat-s/always-upload-cache@v2.1.5 with: path: ${{ env.BASEDIR }}/downstream_ws key: ${{ env.CACHE_PREFIX }}-${{ github.run_id }} restore-keys: ${{ env.CACHE_PREFIX }} env: - CACHE_PREFIX: downstream_ws-${{ matrix.env.IMAGE }}-${{ hashFiles('.github/workflows/downstream.rosinstall') }} + CACHE_PREFIX: downstream_ws-${{ matrix.env.IMAGE }}-${{ hashFiles('.github/workflows/downstream.rosinstall', '.github/workflows/ci.yaml') }} # The target directory cache doesn't include the source directory because # that comes from the checkout. See "prepare target_ws for cache" task below - - name: cache target workspace - if: ${{ ! matrix.env.CCOV }} + - name: Cache target workspace + if: "!matrix.env.CCOV" uses: pat-s/always-upload-cache@v2.1.5 with: path: ${{ env.BASEDIR }}/target_ws key: ${{ env.CACHE_PREFIX }}-${{ github.run_id }} restore-keys: ${{ env.CACHE_PREFIX }} env: - CACHE_PREFIX: target_ws${{ matrix.env.CCOV && '-ccov' || '' }}-${{ matrix.env.IMAGE }}-${{ hashFiles('**/CMakeLists.txt', '**/package.xml') }} - - name: cache ccache + CACHE_PREFIX: target_ws${{ matrix.env.CCOV && '-ccov' || '' }}-${{ matrix.env.IMAGE }}-${{ hashFiles('**/CMakeLists.txt', '**/package.xml', '.github/workflows/ci.yaml') }} + - name: Cache ccache uses: pat-s/always-upload-cache@v2.1.5 with: path: ${{ env.CCACHE_DIR }} @@ -99,27 +107,40 @@ jobs: env: CACHE_PREFIX: ccache-${{ matrix.env.IMAGE }}${{ matrix.env.CCOV && '-ccov' || '' }} - - name: generate ikfast packages - if: ${{ matrix.env.IKFAST_TEST }} - run: | - moveit_kinematics/test/test_ikfast_plugins.sh - - name: industrial_ci + - name: Generate ikfast packages + if: matrix.env.IKFAST_TEST + run: moveit_kinematics/test/test_ikfast_plugins.sh + - id: ici + name: Run industrial_ci uses: ros-industrial/industrial_ci@master env: ${{ matrix.env }} - - name: upload test artifacts (on failure) + - name: Upload test artifacts (on failure) uses: actions/upload-artifact@v2 - if: failure() + if: failure() && (steps.ici.outputs.run_target_test || steps.ici.outputs.target_test_results) with: - name: test-results + name: test-results-${{ matrix.env.IMAGE }} path: ${{ env.BASEDIR }}/target_ws/**/test_results/**/*.xml - - name: upload codecov report - uses: codecov/codecov-action@v1 - if: ${{ matrix.env.CCOV }} + - name: Generate codecov report + uses: rhaschke/lcov-action@main + if: always() && matrix.env.CCOV && steps.ici.outputs.target_test_results == '0' + with: + docker: $DOCKER_IMAGE + workdir: ${{ env.BASEDIR }}/target_ws + ignore: '"*/target_ws/build/*" "*/target_ws/install/*" "*/test/*"' + - name: Upload codecov report + uses: codecov/codecov-action@v2 + if: always() && matrix.env.CCOV && steps.ici.outputs.target_test_results == '0' + with: + files: ${{ env.BASEDIR }}/target_ws/coverage.info + - name: Upload clang-tidy changes + uses: rhaschke/upload-git-patch-action@main + if: always() && matrix.env.CLANG_TIDY with: - files: ${{ env.BASEDIR }}/coverage.info - - name: prepare target_ws for cache - if: ${{ always() && ! matrix.env.CCOV }} + name: clang-tidy + path: ${{ env.BASEDIR }}/target_ws/src/$(basename $(pwd)) + - name: Prepare target_ws for cache + if: always() && !matrix.env.CCOV run: | du -sh ${{ env.BASEDIR }}/target_ws sudo find ${{ env.BASEDIR }}/target_ws -wholename '*/test_results/*' -delete diff --git a/.github/workflows/format.yaml b/.github/workflows/format.yaml index 2f714e7cc0..5159c05ccc 100644 --- a/.github/workflows/format.yaml +++ b/.github/workflows/format.yaml @@ -20,4 +20,10 @@ jobs: - uses: rhaschke/install-catkin_lint-action@v1.0 with: distro: melodic - - uses: pre-commit/action@v2.0.0 + - uses: pre-commit/action@v2.0.3 + id: precommit + - name: Upload pre-commit changes + if: failure() && steps.precommit.outcome == 'failure' + uses: rhaschke/upload-git-patch-action@main + with: + name: pre-commit diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 182523010f..39e7d9d60e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -50,7 +50,7 @@ repos: - id: catkin_lint name: catkin_lint description: Check package.xml and cmake files - entry: catkin_lint . + entry: catkin_lint --rosdistro melodic --explain . language: system always_run: true pass_filenames: false From cd9f3624826c381ccc83bc0cbe981c43a050a9e1 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 5 Nov 2021 14:50:56 +0100 Subject: [PATCH 147/179] Adapt CXXFLAGS --- .github/workflows/ci.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a7cf1a8add..f662b8ee14 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -25,7 +25,8 @@ jobs: env: CXXFLAGS: >- -Wall -Wextra -Wwrite-strings -Wunreachable-code -Wpointer-arith -Wredundant-decls - -Wno-deprecated-copy -Wno-unused-parameter -Wno-unused-but-set-parameter + -Wno-unused-parameter + ${{ matrix.env.CLANG_TIDY && '-Wno-error=c++17-compat -Wno-error=overloaded-virtual -Wno-error=unused-function' || '' }} CLANG_TIDY_ARGS: --fix --fix-errors --format-style=file DOCKER_IMAGE: moveit/moveit:${{ matrix.env.IMAGE }} UPSTREAM_WORKSPACE: .github/workflows/upstream.rosinstall From fdd76adc57a8098a0278cd88d283579746c33d5b Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 19 Nov 2021 07:47:24 +0100 Subject: [PATCH 148/179] CI: Skip clang-format when clang-tidying We cannot use clang-tidy option --format-style=file, as this will apply clang-format from libllvm 6.0 only, but we require 10.0. --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f662b8ee14..1da78dedf2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,7 +27,7 @@ jobs: -Wall -Wextra -Wwrite-strings -Wunreachable-code -Wpointer-arith -Wredundant-decls -Wno-unused-parameter ${{ matrix.env.CLANG_TIDY && '-Wno-error=c++17-compat -Wno-error=overloaded-virtual -Wno-error=unused-function' || '' }} - CLANG_TIDY_ARGS: --fix --fix-errors --format-style=file + CLANG_TIDY_ARGS: --fix --fix-errors DOCKER_IMAGE: moveit/moveit:${{ matrix.env.IMAGE }} UPSTREAM_WORKSPACE: .github/workflows/upstream.rosinstall TARGET_WORKSPACE: $TARGET_REPO_PATH github:ros-planning/moveit_resources#melodic-devel From b08727c4ba52a138ec6c6e3885fdf08d3c07d342 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 19 Nov 2021 10:12:51 +0100 Subject: [PATCH 149/179] Apply trivial clang-tidy fixes --- .../collision_detection/collision_matrix.h | 2 +- .../moveit/collision_detection/world.h | 4 +-- .../moveit/collision_detection/world_diff.h | 2 +- .../collision_common.h | 4 +-- .../collision_detector_fcl_plugin_loader.h | 2 +- .../propagation_distance_field.h | 6 ++-- .../moveit/distance_field/voxel_grid.h | 4 +-- .../kinematic_constraint.h | 8 ++--- .../moveit/kinematics_base/kinematics_base.h | 8 ++--- .../moveit/planning_scene/planning_scene.h | 16 +++++----- .../include/moveit/profiler/profiler.h | 30 +++++++++---------- .../include/moveit/robot_model/robot_model.h | 2 +- .../src/order_robot_model_items.inc | 6 ++-- .../include/moveit/robot_state/robot_state.h | 4 +-- .../time_optimal_trajectory_generation.h | 2 +- .../cached_ik_kinematics_plugin.h | 7 +++-- .../src/kdl_kinematics_plugin.cpp | 18 +++++------ .../include/chomp_motion_planner/chomp_cost.h | 9 +++--- .../pilz_industrial_motion_planner.h | 2 +- .../src/trajectory_generator_ptp.cpp | 2 +- .../src/moveit_fake_controllers.h | 4 +-- .../action_based_controller_handle.h | 2 +- .../moveit/pick_place/manipulation_plan.h | 6 ++-- .../occupancy_map_monitor/occupancy_map.h | 2 +- .../point_containment_filter/shape_mask.h | 2 +- .../move_group_interface.h | 4 +-- .../robot_interaction/interaction_handler.h | 2 +- .../robot_interaction/robot_interaction.h | 2 +- .../motion_planning_frame.h | 2 +- .../motion_planning_frame_joints_widget.h | 4 +-- .../motion_planning_param_widget.h | 2 +- .../trajectory_panel.h | 2 +- .../trajectory_constraints_storage.h | 4 +-- .../tools/moveit_config_data.h | 20 +++++++------ .../src/tools/collision_linear_model.h | 4 +-- .../src/tools/collision_matrix_model.h | 4 +-- .../src/tools/moveit_config_data.cpp | 2 +- .../src/tools/rotated_header_view.h | 2 +- .../src/widgets/default_collisions_widget.h | 2 +- .../src/widgets/double_list_widget.h | 2 +- .../src/widgets/group_edit_widget.cpp | 15 +++++----- .../src/widgets/navigation_widget.h | 4 +-- 42 files changed, 118 insertions(+), 113 deletions(-) diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/collision_matrix.h b/moveit_core/collision_detection/include/moveit/collision_detection/collision_matrix.h index d9cba840c2..83943db290 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/collision_matrix.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/collision_matrix.h @@ -66,7 +66,7 @@ enum Type imply that the two bodies are in collision*/ CONDITIONAL }; -} +} // namespace AllowedCollision /** \brief Signature of predicate that decides whether a contact is allowed or not (when AllowedCollision::Type is * CONDITIONAL) */ diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/world.h b/moveit_core/collision_detection/include/moveit/collision_detection/world.h index f940f2fe4e..bc7f121d89 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/world.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/world.h @@ -217,7 +217,7 @@ class World class ObserverHandle { public: - ObserverHandle() : observer_(NULL) + ObserverHandle() : observer_(nullptr) { } @@ -246,7 +246,7 @@ class World private: /** notify all observers of a change */ - void notify(const ObjectConstPtr&, Action); + void notify(const ObjectConstPtr& obj, Action action); /** send notification of change to all objects. */ void notifyAll(Action action); diff --git a/moveit_core/collision_detection/include/moveit/collision_detection/world_diff.h b/moveit_core/collision_detection/include/moveit/collision_detection/world_diff.h index 46587136d8..38863fec14 100644 --- a/moveit_core/collision_detection/include/moveit/collision_detection/world_diff.h +++ b/moveit_core/collision_detection/include/moveit/collision_detection/world_diff.h @@ -112,7 +112,7 @@ class WorldDiff private: /** \brief Notification function */ - void notify(const World::ObjectConstPtr&, World::Action); + void notify(const World::ObjectConstPtr& obj, World::Action action); /** keep changes in a map so they can be coalesced */ std::map changes_; diff --git a/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_common.h b/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_common.h index 9f1565442d..1eeaa2a3aa 100644 --- a/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_common.h +++ b/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_common.h @@ -139,12 +139,12 @@ struct CollisionGeometryData /** \brief Data structure which is passed to the collision callback function of the collision manager. */ struct CollisionData { - CollisionData() : req_(NULL), active_components_only_(NULL), res_(NULL), acm_(NULL), done_(false) + CollisionData() : req_(nullptr), active_components_only_(nullptr), res_(nullptr), acm_(nullptr), done_(false) { } CollisionData(const CollisionRequest* req, CollisionResult* res, const AllowedCollisionMatrix* acm) - : req_(req), active_components_only_(NULL), res_(res), acm_(acm), done_(false) + : req_(req), active_components_only_(nullptr), res_(res), acm_(acm), done_(false) { } diff --git a/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_detector_fcl_plugin_loader.h b/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_detector_fcl_plugin_loader.h index 2bf3c7759f..2248d94ca0 100644 --- a/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_detector_fcl_plugin_loader.h +++ b/moveit_core/collision_detection_fcl/include/moveit/collision_detection_fcl/collision_detector_fcl_plugin_loader.h @@ -13,7 +13,7 @@ namespace collision_detection class CollisionDetectorFCLPluginLoader : public CollisionPlugin { public: - virtual bool initialize(const planning_scene::PlanningScenePtr& scene, bool exclusive) const; + bool initialize(const planning_scene::PlanningScenePtr& scene, bool exclusive) const override; }; } // namespace collision_detection #endif // MOVEIT_COLLISION_DETECTION_FCL_COLLISION_DETECTOR_FCL_PLUGIN_LOADER_H_ diff --git a/moveit_core/distance_field/include/moveit/distance_field/propagation_distance_field.h b/moveit_core/distance_field/include/moveit/distance_field/propagation_distance_field.h index 128eb925db..c4f50782a0 100644 --- a/moveit_core/distance_field/include/moveit/distance_field/propagation_distance_field.h +++ b/moveit_core/distance_field/include/moveit/distance_field/propagation_distance_field.h @@ -417,20 +417,20 @@ class PropagationDistanceField : public DistanceField dist = sqrt_table_[cell->distance_square_]; pos = cell->closest_point_; const PropDistanceFieldVoxel* ncell = &voxel_grid_->getCell(pos.x(), pos.y(), pos.z()); - return ncell == cell ? NULL : ncell; + return ncell == cell ? nullptr : ncell; } if (cell->negative_distance_square_ > 0) { dist = -sqrt_table_[cell->negative_distance_square_]; pos = cell->closest_negative_point_; const PropDistanceFieldVoxel* ncell = &voxel_grid_->getCell(pos.x(), pos.y(), pos.z()); - return ncell == cell ? NULL : ncell; + return ncell == cell ? nullptr : ncell; } dist = 0.0; pos.x() = x; pos.y() = y; pos.z() = z; - return NULL; + return nullptr; } /** diff --git a/moveit_core/distance_field/include/moveit/distance_field/voxel_grid.h b/moveit_core/distance_field/include/moveit/distance_field/voxel_grid.h index f85cfbdcd7..34ed83c18d 100644 --- a/moveit_core/distance_field/include/moveit/distance_field/voxel_grid.h +++ b/moveit_core/distance_field/include/moveit/distance_field/voxel_grid.h @@ -342,7 +342,7 @@ class VoxelGrid template VoxelGrid::VoxelGrid(double size_x, double size_y, double size_z, double resolution, double origin_x, double origin_y, double origin_z, T default_object) - : data_(NULL) + : data_(nullptr) { resize(size_x, size_y, size_z, resolution, origin_x, origin_y, origin_z, default_object); } @@ -369,7 +369,7 @@ void VoxelGrid::resize(double size_x, double size_y, double size_z, double re double origin_y, double origin_z, T default_object) { delete[] data_; - data_ = NULL; + data_ = nullptr; size_[DIM_X] = size_x; size_[DIM_Y] = size_y; diff --git a/moveit_core/kinematic_constraints/include/moveit/kinematic_constraints/kinematic_constraint.h b/moveit_core/kinematic_constraints/include/moveit/kinematic_constraints/kinematic_constraint.h index f227cf5fc5..0698d71480 100644 --- a/moveit_core/kinematic_constraints/include/moveit/kinematic_constraints/kinematic_constraint.h +++ b/moveit_core/kinematic_constraints/include/moveit/kinematic_constraints/kinematic_constraint.h @@ -145,7 +145,7 @@ class KinematicConstraint * * @param [in] out The file descriptor for printing */ - virtual void print(std::ostream& = std::cout) const + virtual void print(std::ostream& /*unused*/ = std::cout) const { } @@ -209,7 +209,7 @@ class JointConstraint : public KinematicConstraint * @param [in] model The kinematic model used for constraint evaluation */ JointConstraint(const robot_model::RobotModelConstPtr& model) - : KinematicConstraint(model), joint_model_(NULL), joint_variable_index_(-1) + : KinematicConstraint(model), joint_model_(nullptr), joint_variable_index_(-1) { type_ = JOINT_CONSTRAINT; } @@ -356,7 +356,7 @@ class OrientationConstraint : public KinematicConstraint * * @param [in] model The kinematic model used for constraint evaluation */ - OrientationConstraint(const robot_model::RobotModelConstPtr& model) : KinematicConstraint(model), link_model_(NULL) + OrientationConstraint(const robot_model::RobotModelConstPtr& model) : KinematicConstraint(model), link_model_(nullptr) { type_ = ORIENTATION_CONSTRAINT; } @@ -513,7 +513,7 @@ class PositionConstraint : public KinematicConstraint * * @param [in] model The kinematic model used for constraint evaluation */ - PositionConstraint(const robot_model::RobotModelConstPtr& model) : KinematicConstraint(model), link_model_(NULL) + PositionConstraint(const robot_model::RobotModelConstPtr& model) : KinematicConstraint(model), link_model_(nullptr) { type_ = POSITION_CONSTRAINT; } diff --git a/moveit_core/kinematics_base/include/moveit/kinematics_base/kinematics_base.h b/moveit_core/kinematics_base/include/moveit/kinematics_base/kinematics_base.h index 6c6340fb34..9b7e68be53 100644 --- a/moveit_core/kinematics_base/include/moveit/kinematics_base/kinematics_base.h +++ b/moveit_core/kinematics_base/include/moveit/kinematics_base/kinematics_base.h @@ -76,7 +76,7 @@ enum DiscretizationMethod SOME_RANDOM_SAMPLED /**< the discretization for some redundant joint will be randomly generated. The unused redundant joints will be fixed at their current value. */ }; -} +} // namespace DiscretizationMethods typedef DiscretizationMethods::DiscretizationMethod DiscretizationMethod; /* @@ -98,7 +98,7 @@ enum KinematicError NO_SOLUTION /**< A valid joint solution that can reach this pose(s) could not be found */ }; -} +} // namespace KinematicErrors typedef KinematicErrors::KinematicError KinematicError; /** @@ -298,7 +298,7 @@ class KinematicsBase double timeout, const std::vector& consistency_limits, std::vector& solution, const IKCallbackFn& solution_callback, moveit_msgs::MoveItErrorCodes& error_code, const kinematics::KinematicsQueryOptions& options = kinematics::KinematicsQueryOptions(), - const moveit::core::RobotState* context_state = NULL) const + const moveit::core::RobotState* context_state = nullptr) const { // For IK solvers that do not support multiple poses, fall back to single pose call if (ik_poses.size() == 1) @@ -508,7 +508,7 @@ class KinematicsBase * supported. * \return True if the group is supported, false if not. */ - virtual bool supportsGroup(const moveit::core::JointModelGroup* jmg, std::string* error_text_out = NULL) const; + virtual bool supportsGroup(const moveit::core::JointModelGroup* jmg, std::string* error_text_out = nullptr) const; /** * @brief Set the search discretization value for all the redundant joints diff --git a/moveit_core/planning_scene/include/moveit/planning_scene/planning_scene.h b/moveit_core/planning_scene/include/moveit/planning_scene/planning_scene.h index e7cbe83314..e40907e7ed 100644 --- a/moveit_core/planning_scene/include/moveit/planning_scene/planning_scene.h +++ b/moveit_core/planning_scene/include/moveit/planning_scene/planning_scene.h @@ -873,14 +873,14 @@ class PlanningScene : private boost::noncopyable, public std::enable_shared_from /** \brief Check if a given path is valid. Each state is checked for validity (collision avoidance and feasibility) */ bool isPathValid(const moveit_msgs::RobotState& start_state, const moveit_msgs::RobotTrajectory& trajectory, const std::string& group = "", bool verbose = false, - std::vector* invalid_index = NULL) const; + std::vector* invalid_index = nullptr) const; /** \brief Check if a given path is valid. Each state is checked for validity (collision avoidance, feasibility and * constraint satisfaction). It is also checked that the goal constraints are satisfied by the last state on the * passed in trajectory. */ bool isPathValid(const moveit_msgs::RobotState& start_state, const moveit_msgs::RobotTrajectory& trajectory, const moveit_msgs::Constraints& path_constraints, const std::string& group = "", - bool verbose = false, std::vector* invalid_index = NULL) const; + bool verbose = false, std::vector* invalid_index = nullptr) const; /** \brief Check if a given path is valid. Each state is checked for validity (collision avoidance, feasibility and * constraint satisfaction). It is also checked that the goal constraints are satisfied by the last state on the @@ -888,7 +888,7 @@ class PlanningScene : private boost::noncopyable, public std::enable_shared_from bool isPathValid(const moveit_msgs::RobotState& start_state, const moveit_msgs::RobotTrajectory& trajectory, const moveit_msgs::Constraints& path_constraints, const moveit_msgs::Constraints& goal_constraints, const std::string& group = "", bool verbose = false, - std::vector* invalid_index = NULL) const; + std::vector* invalid_index = nullptr) const; /** \brief Check if a given path is valid. Each state is checked for validity (collision avoidance, feasibility and * constraint satisfaction). It is also checked that the goal constraints are satisfied by the last state on the @@ -896,7 +896,7 @@ class PlanningScene : private boost::noncopyable, public std::enable_shared_from bool isPathValid(const moveit_msgs::RobotState& start_state, const moveit_msgs::RobotTrajectory& trajectory, const moveit_msgs::Constraints& path_constraints, const std::vector& goal_constraints, const std::string& group = "", - bool verbose = false, std::vector* invalid_index = NULL) const; + bool verbose = false, std::vector* invalid_index = nullptr) const; /** \brief Check if a given path is valid. Each state is checked for validity (collision avoidance, feasibility and * constraint satisfaction). It is also checked that the goal constraints are satisfied by the last state on the @@ -904,7 +904,7 @@ class PlanningScene : private boost::noncopyable, public std::enable_shared_from bool isPathValid(const robot_trajectory::RobotTrajectory& trajectory, const moveit_msgs::Constraints& path_constraints, const std::vector& goal_constraints, const std::string& group = "", - bool verbose = false, std::vector* invalid_index = NULL) const; + bool verbose = false, std::vector* invalid_index = nullptr) const; /** \brief Check if a given path is valid. Each state is checked for validity (collision avoidance, feasibility and * constraint satisfaction). It is also checked that the goal constraints are satisfied by the last state on the @@ -912,17 +912,17 @@ class PlanningScene : private boost::noncopyable, public std::enable_shared_from bool isPathValid(const robot_trajectory::RobotTrajectory& trajectory, const moveit_msgs::Constraints& path_constraints, const moveit_msgs::Constraints& goal_constraints, const std::string& group = "", bool verbose = false, - std::vector* invalid_index = NULL) const; + std::vector* invalid_index = nullptr) const; /** \brief Check if a given path is valid. Each state is checked for validity (collision avoidance, feasibility and * constraint satisfaction). */ bool isPathValid(const robot_trajectory::RobotTrajectory& trajectory, const moveit_msgs::Constraints& path_constraints, const std::string& group = "", - bool verbose = false, std::vector* invalid_index = NULL) const; + bool verbose = false, std::vector* invalid_index = nullptr) const; /** \brief Check if a given path is valid. Each state is checked for validity (collision avoidance and feasibility) */ bool isPathValid(const robot_trajectory::RobotTrajectory& trajectory, const std::string& group = "", - bool verbose = false, std::vector* invalid_index = NULL) const; + bool verbose = false, std::vector* invalid_index = nullptr) const; /** \brief Get the top \e max_costs cost sources for a specified trajectory. The resulting costs are stored in \e * costs */ diff --git a/moveit_core/profiler/include/moveit/profiler/profiler.h b/moveit_core/profiler/include/moveit/profiler/profiler.h index 43645088d9..5e24e8bef1 100644 --- a/moveit_core/profiler/include/moveit/profiler/profiler.h +++ b/moveit_core/profiler/include/moveit/profiler/profiler.h @@ -84,7 +84,7 @@ class Profiler : private boost::noncopyable prof_.begin(name); } - ~ScopedBlock(void) + ~ScopedBlock() { prof_.end(name_); } @@ -106,7 +106,7 @@ class Profiler : private boost::noncopyable prof_.start(); } - ~ScopedStart(void) + ~ScopedStart() { if (!wasRunning_) prof_.stop(); @@ -118,7 +118,7 @@ class Profiler : private boost::noncopyable }; /** \brief Return an instance of the class */ - static Profiler& instance(void); + static Profiler& instance(); /** \brief Constructor. It is allowed to separately instantiate this class (not only as a singleton) */ @@ -129,38 +129,38 @@ class Profiler : private boost::noncopyable } /** \brief Destructor */ - ~Profiler(void) + ~Profiler() { if (printOnDestroy_ && !data_.empty()) status(); } /** \brief Start counting time */ - static void Start(void) + static void Start() { instance().start(); } /** \brief Stop counting time */ - static void Stop(void) + static void Stop() { instance().stop(); } /** \brief Clear counted time and events */ - static void Clear(void) + static void Clear() { instance().clear(); } /** \brief Start counting time */ - void start(void); + void start(); /** \brief Stop counting time */ - void stop(void); + void stop(); /** \brief Clear counted time and events */ - void clear(void); + void clear(); /** \brief Count a specific event for a number of times */ static void Event(const std::string& name, const unsigned int times = 1) @@ -220,10 +220,10 @@ class Profiler : private boost::noncopyable /** \brief Print the status of the profiled code chunks and events to the console (using msg::Console) */ - void console(void); + void console(); /** \brief Check if the profiler is counting time or not */ - bool running(void) const + bool running() const { return running_; } @@ -238,7 +238,7 @@ class Profiler : private boost::noncopyable /** \brief Information about time spent in a section of the code */ struct TimeInfo { - TimeInfo(void) + TimeInfo() : total(0, 0, 0, 0), shortest(boost::posix_time::pos_infin), longest(boost::posix_time::neg_infin), parts(0) { } @@ -259,13 +259,13 @@ class Profiler : private boost::noncopyable boost::posix_time::ptime start; /** \brief Begin counting time */ - void set(void) + void set() { start = boost::posix_time::microsec_clock::universal_time(); } /** \brief Add the counted time to the total time */ - void update(void) + void update() { const boost::posix_time::time_duration& dt = boost::posix_time::microsec_clock::universal_time() - start; if (dt > longest) diff --git a/moveit_core/robot_model/include/moveit/robot_model/robot_model.h b/moveit_core/robot_model/include/moveit/robot_model/robot_model.h index 318518f78e..32155e62a5 100644 --- a/moveit_core/robot_model/include/moveit/robot_model/robot_model.h +++ b/moveit_core/robot_model/include/moveit/robot_model/robot_model.h @@ -100,7 +100,7 @@ class RobotModel /** \brief Return true if the model is empty (has no root link, no joints) */ bool isEmpty() const { - return root_link_ == NULL; + return root_link_ == nullptr; } /** \brief Get the parsed URDF model */ diff --git a/moveit_core/robot_model/src/order_robot_model_items.inc b/moveit_core/robot_model/src/order_robot_model_items.inc index 5f7200306b..640808b7f4 100644 --- a/moveit_core/robot_model/src/order_robot_model_items.inc +++ b/moveit_core/robot_model/src/order_robot_model_items.inc @@ -65,6 +65,6 @@ struct OrderGroupsByName } }; -} -} -} +} // namespace +} // namespace core +} // namespace moveit diff --git a/moveit_core/robot_state/include/moveit/robot_state/robot_state.h b/moveit_core/robot_state/include/moveit/robot_state/robot_state.h index 750869e5ab..beb943a18b 100644 --- a/moveit_core/robot_state/include/moveit/robot_state/robot_state.h +++ b/moveit_core/robot_state/include/moveit/robot_state/robot_state.h @@ -1905,7 +1905,7 @@ as the new values that correspond to the group */ { dirty_joint_transforms_[joint->getJointIndex()] = 1; dirty_link_transforms_ = - dirty_link_transforms_ == NULL ? joint : robot_model_->getCommonRoot(dirty_link_transforms_, joint); + dirty_link_transforms_ == nullptr ? joint : robot_model_->getCommonRoot(dirty_link_transforms_, joint); } void markDirtyJointTransforms(const JointModelGroup* group) @@ -1913,7 +1913,7 @@ as the new values that correspond to the group */ const std::vector& jm = group->getActiveJointModels(); for (std::size_t i = 0; i < jm.size(); ++i) dirty_joint_transforms_[jm[i]->getJointIndex()] = 1; - dirty_link_transforms_ = dirty_link_transforms_ == NULL ? + dirty_link_transforms_ = dirty_link_transforms_ == nullptr ? group->getCommonRoot() : robot_model_->getCommonRoot(dirty_link_transforms_, group->getCommonRoot()); } diff --git a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_optimal_trajectory_generation.h b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_optimal_trajectory_generation.h index 8c41aafe05..0edbe1a338 100644 --- a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_optimal_trajectory_generation.h +++ b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_optimal_trajectory_generation.h @@ -96,7 +96,7 @@ class Trajectory Trajectory(const Path& path, const Eigen::VectorXd& max_velocity, const Eigen::VectorXd& max_acceleration, double time_step = 0.001); - ~Trajectory(void); + ~Trajectory(); /** @brief Call this method after constructing the object to make sure the trajectory generation succeeded without errors. If this method returns diff --git a/moveit_kinematics/cached_ik_kinematics_plugin/include/moveit/cached_ik_kinematics_plugin/cached_ik_kinematics_plugin.h b/moveit_kinematics/cached_ik_kinematics_plugin/include/moveit/cached_ik_kinematics_plugin/cached_ik_kinematics_plugin.h index cb2b041f50..c0f71f041f 100644 --- a/moveit_kinematics/cached_ik_kinematics_plugin/include/moveit/cached_ik_kinematics_plugin/cached_ik_kinematics_plugin.h +++ b/moveit_kinematics/cached_ik_kinematics_plugin/include/moveit/cached_ik_kinematics_plugin/cached_ik_kinematics_plugin.h @@ -286,8 +286,8 @@ class CachedIKKinematicsPlugin : public KinematicsPlugin template typename std::enable_if::value, bool>::type - initializeImpl(const moveit::core::RobotModel&, const std::string&, const std::string&, - const std::vector&, double) + initializeImpl(const moveit::core::RobotModel& /*unused*/, const std::string& /*unused*/, + const std::string& /*unused*/, const std::vector& /*unused*/, double /*unused*/) { return false; // API not supported } @@ -306,7 +306,8 @@ class CachedIKKinematicsPlugin : public KinematicsPlugin template typename std::enable_if::value, bool>::type - initializeImpl(const std::string&, const std::string&, const std::string&, const std::string&, double) + initializeImpl(const std::string& /*unused*/, const std::string& /*unused*/, const std::string& /*unused*/, + const std::string& /*unused*/, double /*unused*/) { return false; // API not supported } diff --git a/moveit_kinematics/kdl_kinematics_plugin/src/kdl_kinematics_plugin.cpp b/moveit_kinematics/kdl_kinematics_plugin/src/kdl_kinematics_plugin.cpp index b947af295c..622374be31 100644 --- a/moveit_kinematics/kdl_kinematics_plugin/src/kdl_kinematics_plugin.cpp +++ b/moveit_kinematics/kdl_kinematics_plugin/src/kdl_kinematics_plugin.cpp @@ -240,26 +240,26 @@ bool KDLKinematicsPlugin::initialize(const moveit::core::RobotModel& robot_model } } } - for (std::size_t i = 0; i < mimic_joints_.size(); ++i) + for (JointMimic& mimic_joint : mimic_joints_) { - if (!mimic_joints_[i].active) + if (!mimic_joint.active) { - const robot_model::JointModel* joint_model = - joint_model_group_->getJointModel(mimic_joints_[i].joint_name)->getMimic(); - for (std::size_t j = 0; j < mimic_joints_.size(); ++j) + const moveit::core::JointModel* joint_model = + joint_model_group_->getJointModel(mimic_joint.joint_name)->getMimic(); + for (JointMimic& mimic_joint_recal : mimic_joints_) { - if (mimic_joints_[j].joint_name == joint_model->getName()) + if (mimic_joint_recal.joint_name == joint_model->getName()) { - mimic_joints_[i].map_index = mimic_joints_[j].map_index; + mimic_joint.map_index = mimic_joint_recal.map_index; } } } } // Setup the joint state groups that we need - state_.reset(new robot_state::RobotState(robot_model_)); + state_ = std::make_shared(robot_model_); - fk_solver_.reset(new KDL::ChainFkSolverPos_recursive(kdl_chain_)); + fk_solver_ = std::make_unique(kdl_chain_); initialized_ = true; ROS_DEBUG_NAMED("kdl", "KDL solver initialized"); diff --git a/moveit_planners/chomp/chomp_motion_planner/include/chomp_motion_planner/chomp_cost.h b/moveit_planners/chomp/chomp_motion_planner/include/chomp_motion_planner/chomp_cost.h index bda7cbd3f9..58822b3fe9 100644 --- a/moveit_planners/chomp/chomp_motion_planner/include/chomp_motion_planner/chomp_cost.h +++ b/moveit_planners/chomp/chomp_motion_planner/include/chomp_motion_planner/chomp_cost.h @@ -54,13 +54,13 @@ class ChompCost virtual ~ChompCost(); template - void getDerivative(Eigen::MatrixXd::ColXpr joint_trajectory, Eigen::MatrixBase& derivative) const; + void getDerivative(const Eigen::MatrixXd::ColXpr& joint_trajectory, Eigen::MatrixBase& derivative) const; const Eigen::MatrixXd& getQuadraticCostInverse() const; const Eigen::MatrixXd& getQuadraticCost() const; - double getCost(Eigen::MatrixXd::ColXpr joint_trajectory) const; + double getCost(const Eigen::MatrixXd::ColXpr& joint_trajectory) const; double getMaxQuadCostInvValue() const; @@ -76,7 +76,8 @@ class ChompCost }; template -void ChompCost::getDerivative(Eigen::MatrixXd::ColXpr joint_trajectory, Eigen::MatrixBase& derivative) const +void ChompCost::getDerivative(const Eigen::MatrixXd::ColXpr& joint_trajectory, + Eigen::MatrixBase& derivative) const { derivative = (quad_cost_full_ * (2.0 * joint_trajectory)); } @@ -91,7 +92,7 @@ inline const Eigen::MatrixXd& ChompCost::getQuadraticCost() const return quad_cost_; } -inline double ChompCost::getCost(Eigen::MatrixXd::ColXpr joint_trajectory) const +inline double ChompCost::getCost(const Eigen::MatrixXd::ColXpr& joint_trajectory) const { return joint_trajectory.dot(quad_cost_full_ * joint_trajectory); } diff --git a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/pilz_industrial_motion_planner.h b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/pilz_industrial_motion_planner.h index 13ae41e67e..443c8099fb 100644 --- a/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/pilz_industrial_motion_planner.h +++ b/moveit_planners/pilz_industrial_motion_planner/include/pilz_industrial_motion_planner/pilz_industrial_motion_planner.h @@ -50,7 +50,7 @@ namespace pilz_industrial_motion_planner { /** - * @brief Moveit Plugin for Planning with Standart Robot Commands + * @brief MoveIt Plugin for Planning with Standard Robot Commands * This planner is dedicated to return a instance of PlanningContext that * corresponds to the requested motion command * set as planner_id in the MotionPlanRequest). diff --git a/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_ptp.cpp b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_ptp.cpp index c5ac44f6af..cfb1887952 100644 --- a/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_ptp.cpp +++ b/moveit_planners/pilz_industrial_motion_planner/src/trajectory_generator_ptp.cpp @@ -60,7 +60,7 @@ TrajectoryGeneratorPTP::TrajectoryGeneratorPTP(const robot_model::RobotModelCons // collect most strict joint limits for each group in robot model for (const auto& jmg : robot_model->getJointModelGroups()) { - auto active_joints = jmg->getActiveJointModelNames(); + const auto& active_joints = jmg->getActiveJointModelNames(); // no active joints if (active_joints.empty()) diff --git a/moveit_plugins/moveit_fake_controller_manager/src/moveit_fake_controllers.h b/moveit_plugins/moveit_fake_controller_manager/src/moveit_fake_controllers.h index 818696fc00..3eaf290d83 100644 --- a/moveit_plugins/moveit_fake_controller_manager/src/moveit_fake_controllers.h +++ b/moveit_plugins/moveit_fake_controller_manager/src/moveit_fake_controllers.h @@ -70,7 +70,7 @@ class LastPointController : public BaseFakeController bool sendTrajectory(const moveit_msgs::RobotTrajectory& t) override; bool cancelExecution() override; - bool waitForExecution(const ros::Duration&) override; + bool waitForExecution(const ros::Duration& timeout) override; }; class ThreadedController : public BaseFakeController @@ -81,7 +81,7 @@ class ThreadedController : public BaseFakeController bool sendTrajectory(const moveit_msgs::RobotTrajectory& t) override; bool cancelExecution() override; - bool waitForExecution(const ros::Duration&) override; + bool waitForExecution(const ros::Duration& timeout) override; moveit_controller_manager::ExecutionStatus getLastExecutionStatus() override; protected: diff --git a/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/action_based_controller_handle.h b/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/action_based_controller_handle.h index 3225538d79..3527ae2e7a 100644 --- a/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/action_based_controller_handle.h +++ b/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/action_based_controller_handle.h @@ -154,7 +154,7 @@ class ActionBasedControllerHandle : public ActionBasedControllerHandleBase protected: ros::NodeHandle nh_; - std::string getActionName(void) const + std::string getActionName() const { if (namespace_.empty()) return name_; diff --git a/moveit_ros/manipulation/pick_place/include/moveit/pick_place/manipulation_plan.h b/moveit_ros/manipulation/pick_place/include/moveit/pick_place/manipulation_plan.h index 1cb36b9142..eb3b13861c 100644 --- a/moveit_ros/manipulation/pick_place/include/moveit/pick_place/manipulation_plan.h +++ b/moveit_ros/manipulation/pick_place/include/moveit/pick_place/manipulation_plan.h @@ -56,9 +56,9 @@ MOVEIT_STRUCT_FORWARD(ManipulationPlanSharedData); struct ManipulationPlanSharedData { ManipulationPlanSharedData() - : planning_group_(NULL) - , end_effector_group_(NULL) - , ik_link_(NULL) + : planning_group_(nullptr) + , end_effector_group_(nullptr) + , ik_link_(nullptr) , max_goal_sampling_attempts_(0) , minimize_object_distance_(false) { diff --git a/moveit_ros/occupancy_map_monitor/include/moveit/occupancy_map_monitor/occupancy_map.h b/moveit_ros/occupancy_map_monitor/include/moveit/occupancy_map_monitor/occupancy_map.h index 210f1ebea6..376a3639ff 100644 --- a/moveit_ros/occupancy_map_monitor/include/moveit/occupancy_map_monitor/occupancy_map.h +++ b/moveit_ros/occupancy_map_monitor/include/moveit/occupancy_map_monitor/occupancy_map.h @@ -97,7 +97,7 @@ class OccMapTree : public octomap::OcTree return WriteLock(tree_mutex_); } - void triggerUpdateCallback(void) + void triggerUpdateCallback() { if (update_callback_) update_callback_(); diff --git a/moveit_ros/perception/point_containment_filter/include/moveit/point_containment_filter/shape_mask.h b/moveit_ros/perception/point_containment_filter/include/moveit/point_containment_filter/shape_mask.h index 782525c283..a4aa0cb15d 100644 --- a/moveit_ros/perception/point_containment_filter/include/moveit/point_containment_filter/shape_mask.h +++ b/moveit_ros/perception/point_containment_filter/include/moveit/point_containment_filter/shape_mask.h @@ -95,7 +95,7 @@ class ShapeMask { SeeShape() { - body = NULL; + body = nullptr; } bodies::Body* body; diff --git a/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h b/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h index d49aaf8932..d08f3b3acf 100644 --- a/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h +++ b/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h @@ -738,7 +738,7 @@ class MoveGroupInterface Return -1.0 in case of error. */ double computeCartesianPath(const std::vector& waypoints, double eef_step, double jump_threshold, moveit_msgs::RobotTrajectory& trajectory, bool avoid_collisions = true, - moveit_msgs::MoveItErrorCodes* error_code = NULL); + moveit_msgs::MoveItErrorCodes* error_code = nullptr); /** \brief Compute a Cartesian path that follows specified waypoints with a step size of at most \e eef_step meters between end effector configurations of consecutive points in the result \e trajectory. The reference frame for the @@ -755,7 +755,7 @@ class MoveGroupInterface double computeCartesianPath(const std::vector& waypoints, double eef_step, double jump_threshold, moveit_msgs::RobotTrajectory& trajectory, const moveit_msgs::Constraints& path_constraints, bool avoid_collisions = true, - moveit_msgs::MoveItErrorCodes* error_code = NULL); + moveit_msgs::MoveItErrorCodes* error_code = nullptr); /** \brief Stop any trajectory execution, if one is active */ void stop(); diff --git a/moveit_ros/robot_interaction/include/moveit/robot_interaction/interaction_handler.h b/moveit_ros/robot_interaction/include/moveit/robot_interaction/interaction_handler.h index bbea62da1f..6bd22ae98d 100644 --- a/moveit_ros/robot_interaction/include/moveit/robot_interaction/interaction_handler.h +++ b/moveit_ros/robot_interaction/include/moveit/robot_interaction/interaction_handler.h @@ -217,7 +217,7 @@ class InteractionHandler : public LockedRobotState /** \brief Clear any error settings. * This makes the markers appear as if the state is no longer invalid. */ - void clearError(void); + void clearError(); protected: bool transformFeedbackPose(const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback, diff --git a/moveit_ros/robot_interaction/include/moveit/robot_interaction/robot_interaction.h b/moveit_ros/robot_interaction/include/moveit/robot_interaction/robot_interaction.h index a649961906..7a912ff0ec 100644 --- a/moveit_ros/robot_interaction/include/moveit/robot_interaction/robot_interaction.h +++ b/moveit_ros/robot_interaction/include/moveit/robot_interaction/robot_interaction.h @@ -79,7 +79,7 @@ class RobotInteraction RobotInteraction(const robot_model::RobotModelConstPtr& robot_model, const std::string& ns = ""); virtual ~RobotInteraction(); - const std::string& getServerTopic(void) const + const std::string& getServerTopic() const { return topic_; } diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_frame.h b/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_frame.h index d9f58bdefc..b2d43331e8 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_frame.h +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_frame.h @@ -103,7 +103,7 @@ class MotionPlanningFrame : public QWidget public: MotionPlanningFrame(const MotionPlanningFrame&) = delete; - MotionPlanningFrame(MotionPlanningDisplay* pdisplay, rviz::DisplayContext* context, QWidget* parent = 0); + MotionPlanningFrame(MotionPlanningDisplay* pdisplay, rviz::DisplayContext* context, QWidget* parent = nullptr); ~MotionPlanningFrame() override; void changePlanningGroup(); diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_frame_joints_widget.h b/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_frame_joints_widget.h index 3f52a306f8..984f776926 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_frame_joints_widget.h +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_frame_joints_widget.h @@ -124,7 +124,7 @@ class MotionPlanningFrameJointsWidget : public QWidget public: MotionPlanningFrameJointsWidget(const MotionPlanningFrameJointsWidget&) = delete; MotionPlanningFrameJointsWidget(MotionPlanningDisplay* display, QWidget* parent = nullptr); - ~MotionPlanningFrameJointsWidget(); + ~MotionPlanningFrameJointsWidget() override; void changePlanningGroup(const std::string& group_name, const robot_interaction::InteractionHandlerPtr& start_state_handler, @@ -168,7 +168,7 @@ class ProgressBarDelegate : public QStyledItemDelegate VariableBoundsRole }; - ProgressBarDelegate(QWidget* parent = 0) : QStyledItemDelegate(parent) + ProgressBarDelegate(QWidget* parent = nullptr) : QStyledItemDelegate(parent) { } diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_param_widget.h b/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_param_widget.h index 4cc55720ee..c721089b54 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_param_widget.h +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/include/moveit/motion_planning_rviz_plugin/motion_planning_param_widget.h @@ -54,7 +54,7 @@ class MotionPlanningParamWidget : public rviz::PropertyTreeWidget Q_OBJECT public: MotionPlanningParamWidget(const MotionPlanningParamWidget&) = delete; - MotionPlanningParamWidget(QWidget* parent = 0); + MotionPlanningParamWidget(QWidget* parent = nullptr); ~MotionPlanningParamWidget() override; void setMoveGroup(const moveit::planning_interface::MoveGroupInterfacePtr& mg); diff --git a/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/trajectory_panel.h b/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/trajectory_panel.h index e4c7d731d1..ec41081283 100644 --- a/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/trajectory_panel.h +++ b/moveit_ros/visualization/rviz_plugin_render_tools/include/moveit/rviz_plugin_render_tools/trajectory_panel.h @@ -54,7 +54,7 @@ class TrajectoryPanel : public rviz::Panel Q_OBJECT public: - TrajectoryPanel(QWidget* parent = 0); + TrajectoryPanel(QWidget* parent = nullptr); ~TrajectoryPanel() override; diff --git a/moveit_ros/warehouse/warehouse/include/moveit/warehouse/trajectory_constraints_storage.h b/moveit_ros/warehouse/warehouse/include/moveit/warehouse/trajectory_constraints_storage.h index 5b6df5e4de..689a9677ed 100644 --- a/moveit_ros/warehouse/warehouse/include/moveit/warehouse/trajectory_constraints_storage.h +++ b/moveit_ros/warehouse/warehouse/include/moveit/warehouse/trajectory_constraints_storage.h @@ -79,10 +79,10 @@ class TrajectoryConstraintsStorage : public MoveItMessageStorage void removeTrajectoryConstraints(const std::string& name, const std::string& robot = "", const std::string& group = ""); - void reset(void); + void reset(); private: - void createCollections(void); + void createCollections(); TrajectoryConstraintsCollection constraints_collection_; }; diff --git a/moveit_setup_assistant/include/moveit/setup_assistant/tools/moveit_config_data.h b/moveit_setup_assistant/include/moveit/setup_assistant/tools/moveit_config_data.h index 5334d0678b..3ba247adc1 100644 --- a/moveit_setup_assistant/include/moveit/setup_assistant/tools/moveit_config_data.h +++ b/moveit_setup_assistant/include/moveit/setup_assistant/tools/moveit_config_data.h @@ -44,6 +44,8 @@ #include // to share throughout app #include // for writing srdf data +#include + namespace moveit_setup_assistant { // ****************************************************************************************** @@ -144,25 +146,25 @@ class GenericParameter void setName(std::string name) { - name_ = name; + name_ = std::move(name); }; void setValue(std::string value) { - value_ = value; + value_ = std::move(value); }; void setComment(std::string comment) { - comment_ = comment; + comment_ = std::move(comment); }; - std::string getName() + const std::string& getName() const { return name_; }; - std::string getValue() + const std::string& getValue() const { return value_; }; - std::string getComment() + const std::string& getComment() const { return comment_; }; @@ -176,7 +178,7 @@ class GenericParameter MOVEIT_CLASS_FORWARD(MoveItConfigData); // Defines MoveItConfigDataPtr, ConstPtr, WeakPtr... etc /** \brief This class is shared with all widgets and contains the common configuration data - needed for generating each robot's MoveIt! configuration package. + needed for generating each robot's MoveIt configuration package. All SRDF data is contained in a subclass of this class - srdf_writer.cpp. This class also contains the functions for writing @@ -204,7 +206,7 @@ class MoveItConfigData }; unsigned long changes; // bitfield of changes (composed of InformationFields) - // All of the data needed for creating a MoveIt! Configuration Files + // All of the data needed for creating a MoveIt Configuration Files // ****************************************************************************************** // URDF Data @@ -304,7 +306,7 @@ class MoveItConfigData // ****************************************************************************************** // Public Functions for outputting configuration and setting files // ****************************************************************************************** - std::vector getOMPLPlanners(); + std::vector getOMPLPlanners() const; bool outputSetupAssistantFile(const std::string& file_path); bool outputOMPLPlanningYAML(const std::string& file_path); bool outputCHOMPPlanningYAML(const std::string& file_path); diff --git a/moveit_setup_assistant/src/tools/collision_linear_model.h b/moveit_setup_assistant/src/tools/collision_linear_model.h index 9744170243..3b8b266c6e 100644 --- a/moveit_setup_assistant/src/tools/collision_linear_model.h +++ b/moveit_setup_assistant/src/tools/collision_linear_model.h @@ -52,7 +52,7 @@ class CollisionLinearModel : public QAbstractProxyModel Q_OBJECT public: - CollisionLinearModel(CollisionMatrixModel* src, QObject* parent = NULL); + CollisionLinearModel(CollisionMatrixModel* src, QObject* parent = nullptr); ~CollisionLinearModel() override; // reimplement to return the model index in the proxy model that to the sourceIndex from the source model @@ -82,7 +82,7 @@ class SortFilterProxyModel : public QSortFilterProxyModel Q_OBJECT public: - SortFilterProxyModel(QObject* parent = 0); + SortFilterProxyModel(QObject* parent = nullptr); QVariant headerData(int section, Qt::Orientation orientation, int role) const override; void sort(int column, Qt::SortOrder order) override; void setShowAll(bool show_all); diff --git a/moveit_setup_assistant/src/tools/collision_matrix_model.h b/moveit_setup_assistant/src/tools/collision_matrix_model.h index dccbc2eed1..9783abf3e2 100644 --- a/moveit_setup_assistant/src/tools/collision_matrix_model.h +++ b/moveit_setup_assistant/src/tools/collision_matrix_model.h @@ -50,7 +50,7 @@ class CollisionMatrixModel : public QAbstractTableModel Q_OBJECT public: CollisionMatrixModel(moveit_setup_assistant::LinkPairMap& pairs, const std::vector& names, - QObject* parent = NULL); + QObject* parent = nullptr); int rowCount(const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; @@ -59,7 +59,7 @@ class CollisionMatrixModel : public QAbstractTableModel // for editing Qt::ItemFlags flags(const QModelIndex& index) const override; - bool setData(const QModelIndex&, const QVariant& value, int role) override; + bool setData(const QModelIndex& index, const QVariant& value, int role) override; void setEnabled(const QItemSelection& selection, bool value); void setEnabled(const QModelIndexList& indexes, bool value); diff --git a/moveit_setup_assistant/src/tools/moveit_config_data.cpp b/moveit_setup_assistant/src/tools/moveit_config_data.cpp index ad5e073045..64b0348efd 100644 --- a/moveit_setup_assistant/src/tools/moveit_config_data.cpp +++ b/moveit_setup_assistant/src/tools/moveit_config_data.cpp @@ -595,7 +595,7 @@ bool MoveItConfigData::outputFakeControllersYAML(const std::string& file_path) return true; // file created successfully } -std::vector MoveItConfigData::getOMPLPlanners() +std::vector MoveItConfigData::getOMPLPlanners() const { std::vector planner_des; diff --git a/moveit_setup_assistant/src/tools/rotated_header_view.h b/moveit_setup_assistant/src/tools/rotated_header_view.h index 6c518b7cf5..9081a64c5a 100644 --- a/moveit_setup_assistant/src/tools/rotated_header_view.h +++ b/moveit_setup_assistant/src/tools/rotated_header_view.h @@ -44,7 +44,7 @@ namespace moveit_setup_assistant class RotatedHeaderView : public QHeaderView { public: - RotatedHeaderView(Qt::Orientation orientation, QWidget* parent = NULL); + RotatedHeaderView(Qt::Orientation orientation, QWidget* parent = nullptr); void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const override; QSize sectionSizeFromContents(int logicalIndex) const override; int sectionSizeHint(int logicalIndex) const; diff --git a/moveit_setup_assistant/src/widgets/default_collisions_widget.h b/moveit_setup_assistant/src/widgets/default_collisions_widget.h index e17ad54ca6..ae14fdfe97 100644 --- a/moveit_setup_assistant/src/widgets/default_collisions_widget.h +++ b/moveit_setup_assistant/src/widgets/default_collisions_widget.h @@ -241,7 +241,7 @@ class MonitorThread : public QThread Q_OBJECT public: - MonitorThread(const boost::function& f, QProgressBar* progress_bar = NULL); + MonitorThread(const boost::function& f, QProgressBar* progress_bar = nullptr); void run() override; void cancel() { diff --git a/moveit_setup_assistant/src/widgets/double_list_widget.h b/moveit_setup_assistant/src/widgets/double_list_widget.h index 80357a8f1b..afa80c2379 100644 --- a/moveit_setup_assistant/src/widgets/double_list_widget.h +++ b/moveit_setup_assistant/src/widgets/double_list_widget.h @@ -71,7 +71,7 @@ class DoubleListWidget : public QWidget /// Set the right box void setSelected(const std::vector& items); - void clearContents(void); + void clearContents(); /// Convenience function for reusing set table code void setTable(const std::vector& items, QTableWidget* table); diff --git a/moveit_setup_assistant/src/widgets/group_edit_widget.cpp b/moveit_setup_assistant/src/widgets/group_edit_widget.cpp index a975ce69d6..a3d84bd178 100644 --- a/moveit_setup_assistant/src/widgets/group_edit_widget.cpp +++ b/moveit_setup_assistant/src/widgets/group_edit_widget.cpp @@ -266,7 +266,7 @@ void GroupEditWidget::setSelected(const std::string& group_name) QString("Unable to find the kinematic solver '") .append(kin_solver.c_str()) .append("'. Trying running rosmake for this package. Until fixed, this setting will be " - "lost the next time the MoveIt! configuration files are generated")); + "lost the next time the MoveIt configuration files are generated")); return; } else @@ -321,7 +321,8 @@ void GroupEditWidget::loadKinematicPlannersComboBox() std::unique_ptr> loader; try { - loader.reset(new pluginlib::ClassLoader("moveit_core", "kinematics::KinematicsBase")); + loader = std::make_unique>("moveit_core", + "kinematics::KinematicsBase"); } catch (pluginlib::PluginlibException& ex) { @@ -339,22 +340,22 @@ void GroupEditWidget::loadKinematicPlannersComboBox() if (classes.empty()) { QMessageBox::warning(this, "Missing Kinematic Solvers", - "No MoveIt!-compatible kinematics solvers found. Try " + "No MoveIt-compatible kinematics solvers found. Try " "installing moveit_kinematics (sudo apt-get install " "ros-${ROS_DISTRO}-moveit-kinematics)"); return; } // Loop through all planners and add to combo box - for (std::vector::const_iterator plugin_it = classes.begin(); plugin_it != classes.end(); ++plugin_it) + for (const std::string& kinematics_plugin_name : classes) { - kinematics_solver_field_->addItem(plugin_it->c_str()); + kinematics_solver_field_->addItem(kinematics_plugin_name.c_str()); } std::vector planners = config_data_->getOMPLPlanners(); - for (std::size_t i = 0; i < planners.size(); ++i) + for (OMPLPlannerDescription& planner : planners) { - std::string planner_name = planners[i].name_; + std::string planner_name = planner.name_; default_planner_field_->addItem(planner_name.c_str()); } } diff --git a/moveit_setup_assistant/src/widgets/navigation_widget.h b/moveit_setup_assistant/src/widgets/navigation_widget.h index b9df37ca0d..382ba6223c 100644 --- a/moveit_setup_assistant/src/widgets/navigation_widget.h +++ b/moveit_setup_assistant/src/widgets/navigation_widget.h @@ -54,7 +54,7 @@ class NavigationWidget : public QListView { Q_OBJECT public: - explicit NavigationWidget(QWidget* parent = 0); + explicit NavigationWidget(QWidget* parent = nullptr); void setNavs(const QList& navs); void setEnabled(const int& index, bool enabled); @@ -75,7 +75,7 @@ class NavDelegate : public QStyledItemDelegate { Q_OBJECT public: - explicit NavDelegate(QObject* parent = 0); + explicit NavDelegate(QObject* parnullptrnt = nullptr); QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override; void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; From 43c60c41234d84962194926d35b40334f26a1328 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 19 Nov 2021 08:05:08 +0100 Subject: [PATCH 150/179] clang-tidy: NOLINT Keep existing names for API stability. --- .../include/moveit/profiler/profiler.h | 20 +++++++++---------- .../chainiksolver_vel_mimic_svd.hpp | 3 ++- .../kdl_kinematics_plugin.h | 3 ++- .../tools/moveit_config_data.h | 6 +++--- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/moveit_core/profiler/include/moveit/profiler/profiler.h b/moveit_core/profiler/include/moveit/profiler/profiler.h index 5e24e8bef1..9ed619e5e8 100644 --- a/moveit_core/profiler/include/moveit/profiler/profiler.h +++ b/moveit_core/profiler/include/moveit/profiler/profiler.h @@ -136,19 +136,19 @@ class Profiler : private boost::noncopyable } /** \brief Start counting time */ - static void Start() + static void Start() // NOLINT(readability-identifier-naming) { instance().start(); } /** \brief Stop counting time */ - static void Stop() + static void Stop() // NOLINT(readability-identifier-naming) { instance().stop(); } /** \brief Clear counted time and events */ - static void Clear() + static void Clear() // NOLINT(readability-identifier-naming) { instance().clear(); } @@ -163,7 +163,7 @@ class Profiler : private boost::noncopyable void clear(); /** \brief Count a specific event for a number of times */ - static void Event(const std::string& name, const unsigned int times = 1) + static void Event(const std::string& name, const unsigned int times = 1) // NOLINT(readability-identifier-naming) { instance().event(name, times); } @@ -172,7 +172,7 @@ class Profiler : private boost::noncopyable void event(const std::string& name, const unsigned int times = 1); /** \brief Maintain the average of a specific value */ - static void Average(const std::string& name, const double value) + static void Average(const std::string& name, const double value) // NOLINT(readability-identifier-naming) { instance().average(name, value); } @@ -181,13 +181,13 @@ class Profiler : private boost::noncopyable void average(const std::string& name, const double value); /** \brief Begin counting time for a specific chunk of code */ - static void Begin(const std::string& name) + static void Begin(const std::string& name) // NOLINT(readability-identifier-naming) { instance().begin(name); } /** \brief Stop counting time for a specific chunk of code */ - static void End(const std::string& name) + static void End(const std::string& name) // NOLINT(readability-identifier-naming) { instance().end(name); } @@ -201,7 +201,7 @@ class Profiler : private boost::noncopyable /** \brief Print the status of the profiled code chunks and events. Optionally, computation done by different threads can be printed separately. */ - static void Status(std::ostream& out = std::cout, bool merge = true) + static void Status(std::ostream& out = std::cout, bool merge = true) // NOLINT(readability-identifier-naming) { instance().status(out, merge); } @@ -213,7 +213,7 @@ class Profiler : private boost::noncopyable /** \brief Print the status of the profiled code chunks and events to the console (using msg::Console) */ - static void Console(void) + static void Console() // NOLINT(readability-identifier-naming) { instance().console(); } @@ -229,7 +229,7 @@ class Profiler : private boost::noncopyable } /** \brief Check if the profiler is counting time or not */ - static bool Running(void) + static bool Running() // NOLINT(readability-identifier-naming) { return instance().running(); } diff --git a/moveit_kinematics/kdl_kinematics_plugin/include/moveit/kdl_kinematics_plugin/chainiksolver_vel_mimic_svd.hpp b/moveit_kinematics/kdl_kinematics_plugin/include/moveit/kdl_kinematics_plugin/chainiksolver_vel_mimic_svd.hpp index 043134b8d0..038e62d862 100644 --- a/moveit_kinematics/kdl_kinematics_plugin/include/moveit/kdl_kinematics_plugin/chainiksolver_vel_mimic_svd.hpp +++ b/moveit_kinematics/kdl_kinematics_plugin/include/moveit/kdl_kinematics_plugin/chainiksolver_vel_mimic_svd.hpp @@ -84,11 +84,12 @@ class ChainIkSolverVelMimicSVD : public ChainIkSolverVel * * where W_q and W_x are joint- and Cartesian weights respectively. * A smaller joint weight (< 1.0) will reduce the contribution of this joint to the solution. */ + // NOLINTNEXTLINE(readability-identifier-naming) int CartToJnt(const JntArray& q_in, const Twist& v_in, JntArray& qdot_out, const Eigen::VectorXd& joint_weights, const Eigen::Matrix& cartesian_weights); /// not implemented. - int CartToJnt(const JntArray& q_init, const FrameVel& v_in, JntArrayVel& q_out) override + int CartToJnt(const JntArray& /*q_init*/, const FrameVel& /*v_in*/, JntArrayVel& /*q_out*/) override { return -1; } diff --git a/moveit_kinematics/kdl_kinematics_plugin/include/moveit/kdl_kinematics_plugin/kdl_kinematics_plugin.h b/moveit_kinematics/kdl_kinematics_plugin/include/moveit/kdl_kinematics_plugin/kdl_kinematics_plugin.h index f3743c467f..6b27c8977e 100644 --- a/moveit_kinematics/kdl_kinematics_plugin/include/moveit/kdl_kinematics_plugin/kdl_kinematics_plugin.h +++ b/moveit_kinematics/kdl_kinematics_plugin/include/moveit/kdl_kinematics_plugin/kdl_kinematics_plugin.h @@ -53,7 +53,7 @@ #include #include -// MoveIt! +// MoveIt #include #include #include @@ -143,6 +143,7 @@ class KDLKinematicsPlugin : public kinematics::KinematicsBase typedef Eigen::Matrix Twist; /// Solve position IK given initial joint values + // NOLINTNEXTLINE(readability-identifier-naming) int CartToJnt(KDL::ChainIkSolverVelMimicSVD& ik_solver, const KDL::JntArray& q_init, const KDL::Frame& p_in, KDL::JntArray& q_out, const unsigned int max_iter, const Eigen::VectorXd& joint_weights, const Twist& cartesian_weights) const; diff --git a/moveit_setup_assistant/include/moveit/setup_assistant/tools/moveit_config_data.h b/moveit_setup_assistant/include/moveit/setup_assistant/tools/moveit_config_data.h index 3ba247adc1..a2af4d5316 100644 --- a/moveit_setup_assistant/include/moveit/setup_assistant/tools/moveit_config_data.h +++ b/moveit_setup_assistant/include/moveit/setup_assistant/tools/moveit_config_data.h @@ -57,8 +57,8 @@ static const std::string ROBOT_DESCRIPTION = "robot_description"; static const std::string MOVEIT_ROBOT_STATE = "moveit_robot_state"; // Default kin solver values -static const double DEFAULT_KIN_SOLVER_SEARCH_RESOLUTION_ = 0.005; -static const double DEFAULT_KIN_SOLVER_TIMEOUT_ = 0.005; +static const double DEFAULT_KIN_SOLVER_SEARCH_RESOLUTION_ = 0.005; // NOLINT(readability-identifier-naming) +static const double DEFAULT_KIN_SOLVER_TIMEOUT_ = 0.005; // NOLINT(readability-identifier-naming) // ****************************************************************************************** // Structs @@ -513,7 +513,7 @@ class MoveItConfigData * \param jm2 - a pointer to the second joint model to compare * \return bool of alphabetical sorting comparison */ - struct joint_model_compare + struct joint_model_compare // NOLINT(readability-identifier-naming) { bool operator()(const robot_model::JointModel* jm1, const robot_model::JointModel* jm2) const { From 0cd15de01591d505a360a13f8852b2a05691f90a Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Thu, 4 Nov 2021 10:58:45 +0100 Subject: [PATCH 151/179] Pilz unittests: use test_environment.launch --- .../test/integrationtest_sequence_action.test | 14 +------------- ...nce_action_capability_frankaemika_panda.test | 15 +-------------- ...sequence_action_capability_with_gripper.test | 14 ++------------ ...egrationtest_sequence_action_preemption.test | 17 +++-------------- 4 files changed, 7 insertions(+), 53 deletions(-) diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.test index df51f007b1..369da0e53b 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.test @@ -33,19 +33,7 @@ POSSIBILITY OF SUCH DAMAGE. --> - - - [/move_group/fake_controller_joint_states] - - - - - - - - - - + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_frankaemika_panda.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_frankaemika_panda.test index bc6afb0a8e..4037981141 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_frankaemika_panda.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_frankaemika_panda.test @@ -34,20 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. - - - [/move_group/fake_controller_joint_states] - - - - - - - - - - + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_with_gripper.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_with_gripper.test index c45f964dbc..ce9044196e 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_with_gripper.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_with_gripper.test @@ -34,18 +34,8 @@ POSSIBILITY OF SUCH DAMAGE. - - - [/move_group/fake_controller_joint_states] - - - - - - - - - + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.test index 614b5ffe1d..73b3ed6a05 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.test @@ -33,21 +33,10 @@ POSSIBILITY OF SUCH DAMAGE. --> - - - [/move_group/fake_controller_joint_states] - - - - - - - - - - + + - + From 2cd921f2f254398ea3010030f89f2d4869b85546 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Thu, 4 Nov 2021 11:00:39 +0100 Subject: [PATCH 152/179] Rename launch argument execution_type -> fake_execution_type ... to clarify that this parameter is only used for fake controllers --- .../test/integrationtest_sequence_action.test | 2 +- ...iontest_sequence_action_capability_frankaemika_panda.test | 2 +- ...egrationtest_sequence_action_capability_with_gripper.test | 2 +- .../test/integrationtest_sequence_action_preemption.test | 2 +- moveit_setup_assistant/src/tools/moveit_config_data.cpp | 2 +- .../templates/moveit_config_pkg_template/launch/demo.launch | 4 ++-- .../launch/fake_moveit_controller_manager.launch.xml | 2 +- .../moveit_config_pkg_template/launch/move_group.launch | 4 ++-- .../launch/trajectory_execution.launch.xml | 5 ++--- 9 files changed, 12 insertions(+), 13 deletions(-) diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.test index 369da0e53b..5fb2934c69 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action.test @@ -35,7 +35,7 @@ POSSIBILITY OF SUCH DAMAGE. - + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_frankaemika_panda.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_frankaemika_panda.test index 4037981141..75c4afc29f 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_frankaemika_panda.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_frankaemika_panda.test @@ -35,7 +35,7 @@ POSSIBILITY OF SUCH DAMAGE. - + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_with_gripper.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_with_gripper.test index ce9044196e..2c36fb699a 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_with_gripper.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_capability_with_gripper.test @@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE. - + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.test index 73b3ed6a05..11f7c5572a 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_action_preemption.test @@ -36,7 +36,7 @@ POSSIBILITY OF SUCH DAMAGE. - + diff --git a/moveit_setup_assistant/src/tools/moveit_config_data.cpp b/moveit_setup_assistant/src/tools/moveit_config_data.cpp index 64b0348efd..d6491c9dc5 100644 --- a/moveit_setup_assistant/src/tools/moveit_config_data.cpp +++ b/moveit_setup_assistant/src/tools/moveit_config_data.cpp @@ -519,7 +519,7 @@ bool MoveItConfigData::outputFakeControllersYAML(const std::string& file_path) emitter << YAML::Key << "name"; emitter << YAML::Value << "fake_" + group_it->name_ + "_controller"; emitter << YAML::Key << "type"; - emitter << YAML::Value << "$(arg execution_type)"; + emitter << YAML::Value << "$(arg fake_execution_type)"; emitter << YAML::Key << "joints"; emitter << YAML::Value << YAML::BeginSeq; diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch index 5c9de5e38b..73817c359d 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/demo.launch @@ -15,7 +15,7 @@ - + - + diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/move_group.launch b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/move_group.launch index a7d5ebc8c3..7c7a4f6a4b 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/move_group.launch +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/move_group.launch @@ -15,7 +15,7 @@ - + @@ -56,7 +56,7 @@ - + diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/trajectory_execution.launch.xml b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/trajectory_execution.launch.xml index 3e5ee656c9..3554c05ffa 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/trajectory_execution.launch.xml +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/trajectory_execution.launch.xml @@ -1,8 +1,7 @@ - - + @@ -18,7 +17,7 @@ - + From b1ffe484aa7592c55e78fa403812e45618733b04 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 22 Oct 2021 14:27:39 +0200 Subject: [PATCH 153/179] moveit_controller_manager.launch: pass execution_type via pass_all_args (#2928) While we need to pass execution_type to fake_moveit_controller_manager.launch, the controller_manager.launch files of real-robot shouldn't be required to define this argument. However, if they don't roslaunch fails with an `unused args` exception (see #2786). Passing arguments via pass_all_args should solve that issue. --- .../launch/trajectory_execution.launch.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/trajectory_execution.launch.xml b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/trajectory_execution.launch.xml index 3554c05ffa..be577b0c0c 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/trajectory_execution.launch.xml +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/trajectory_execution.launch.xml @@ -16,8 +16,8 @@ - - - + + From 713a96bedb2b7998e856d3ff6b906998f3380c43 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Sat, 23 Oct 2021 11:11:19 +0200 Subject: [PATCH 154/179] Fix definition of real-robot moveit_controller_manager Fixes the following error (occurring since 61d18f2f073aa4c8a13c2278c41a63591d401c4a) ``` [FATAL] ros.moveit_ros_planning.trajectory_execution_manager: Exception while loading controller manager 'robot': According to the loaded plugin descriptions the class robot with base class type moveit_controller_manager::MoveItControllerManager does not exist. ``` As we introduced `pass_all_args="true"`, the value of the argument `moveit_controller_manager` was the robot name. --- .../launch/moveit_controller_manager.launch.xml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/moveit_controller_manager.launch.xml b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/moveit_controller_manager.launch.xml index 67cb8aa108..b3959b8630 100644 --- a/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/moveit_controller_manager.launch.xml +++ b/moveit_setup_assistant/templates/moveit_config_pkg_template/launch/moveit_controller_manager.launch.xml @@ -1,10 +1,7 @@ + + - - - - - + From c25eeed6f753f2bee1a5e6ae7f18eacea10fc1f5 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 5 Nov 2021 17:49:50 +0100 Subject: [PATCH 155/179] Use test_environment.launch in unittests --- .../test/rrbot_move_group.launch | 5 ++- .../integrationtest_command_planning.test | 14 +------- ...st_command_planning_frankaemika_panda.test | 14 +------- ...iontest_command_planning_with_gripper.test | 12 +------ ...ationtest_sequence_service_capability.test | 14 +------- ..._service_capability_frankaemika_panda.test | 14 +------- ...uence_service_capability_with_gripper.test | 12 +------ .../launch/moveit_planning_execution.launch | 33 ++----------------- .../test/move_group_interface_cpp_test.test | 24 +------------- 9 files changed, 11 insertions(+), 131 deletions(-) diff --git a/moveit_planners/chomp/chomp_interface/test/rrbot_move_group.launch b/moveit_planners/chomp/chomp_interface/test/rrbot_move_group.launch index ab54cf53fc..56100a65ff 100644 --- a/moveit_planners/chomp/chomp_interface/test/rrbot_move_group.launch +++ b/moveit_planners/chomp/chomp_interface/test/rrbot_move_group.launch @@ -27,9 +27,8 @@ - - - + + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning.test index ba73e8b56b..6d26187e4d 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning.test @@ -34,19 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. - - - [/move_group/fake_controller_joint_states] - - - - - - - - - - + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_frankaemika_panda.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_frankaemika_panda.test index d360fbcafa..44f7d54b3d 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_frankaemika_panda.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_frankaemika_panda.test @@ -34,19 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. - - - [/move_group/fake_controller_joint_states] - - - - - - - - - - + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_with_gripper.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_with_gripper.test index 64fb904bde..27212a2b92 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_with_gripper.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_command_planning_with_gripper.test @@ -34,17 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. - - - [/move_group/fake_controller_joint_states] - - - - - - - - + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability.test index 9eec6f308b..049cb5a253 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability.test @@ -33,19 +33,7 @@ POSSIBILITY OF SUCH DAMAGE. --> - - - [/move_group/fake_controller_joint_states] - - - - - - - - - - + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_frankaemika_panda.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_frankaemika_panda.test index dbec926599..604d6ace07 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_frankaemika_panda.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_frankaemika_panda.test @@ -34,19 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. - - - [/move_group/fake_controller_joint_states] - - - - - - - - - - + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_with_gripper.test b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_with_gripper.test index f214d4baf7..0c516453ac 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_with_gripper.test +++ b/moveit_planners/pilz_industrial_motion_planner/test/integrationtest_sequence_service_capability_with_gripper.test @@ -33,17 +33,7 @@ POSSIBILITY OF SUCH DAMAGE. --> - - - [/move_group/fake_controller_joint_states] - - - - - - - - + diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/launch/moveit_planning_execution.launch b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/launch/moveit_planning_execution.launch index af5a15e896..134a32ba3e 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/launch/moveit_planning_execution.launch +++ b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/launch/moveit_planning_execution.launch @@ -37,38 +37,9 @@ POSSIBILITY OF SUCH DAMAGE. - - - - - - - - - - - - - - - - - - - - - - - [/move_group/fake_controller_joint_states] - - - - - - - - + + diff --git a/moveit_ros/planning_interface/test/move_group_interface_cpp_test.test b/moveit_ros/planning_interface/test/move_group_interface_cpp_test.test index 9975f257d2..02d1f7201c 100644 --- a/moveit_ros/planning_interface/test/move_group_interface_cpp_test.test +++ b/moveit_ros/planning_interface/test/move_group_interface_cpp_test.test @@ -1,27 +1,5 @@ - - - - - - - - - - - [/move_group/fake_controller_joint_states] - - - - - - - - - - - - + Date: Fri, 5 Nov 2021 18:07:30 +0100 Subject: [PATCH 156/179] Remove unused moveit_planning_execution.launch --- .../acceptance_tests/acceptance_test_lin.md | 2 +- .../acceptance_tests/acceptance_test_ptp.md | 2 +- .../launch/moveit_planning_execution.launch | 48 ------------------- 3 files changed, 2 insertions(+), 50 deletions(-) delete mode 100644 moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/launch/moveit_planning_execution.launch diff --git a/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_lin.md b/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_lin.md index 4f2abec293..867c7f6587 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_lin.md +++ b/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_lin.md @@ -41,7 +41,7 @@ to be moved out of singularities. ## Test Sequence: 1. Bringup can: `sudo ip link set can0 up type can bitrate 1000000` - 2. Run `roslaunch moveit_resources_prbt_moveit_config moveit_planning_execution.launch sim:=False pipeline:=pilz_industrial_motion_planner` + 2. Run `roslaunch moveit_resources_prbt_moveit_config demo.launch pipeline:=pilz_industrial_motion_planner` 3. In the motion planing widget (lower left part of moveit) choose PTP in the dropdown below "Trapezoidal Command Planner" (see image) ![moveit_1](img/acceptance_test_lin_img1.png) 4. Switch to the tab "Planning" in the moveit planning plugin. Move the ball handle to select a singularity free position. Click on "plan and execute". diff --git a/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_ptp.md b/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_ptp.md index 732ec8ec4f..be2dce5489 100644 --- a/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_ptp.md +++ b/moveit_planners/pilz_industrial_motion_planner/test/acceptance_tests/acceptance_test_ptp.md @@ -40,7 +40,7 @@ This test checks that the real robot system is able to perform a PTP Motion to a ## Test Sequence: 1. Bringup can: `sudo ip link set can0 up type can bitrate 1000000` - 2. Run `roslaunch moveit_resources_prbt_moveit_config moveit_planning_execution.launch sim:=False pipeline:=pilz_industrial_motion_planner` + 2. Run `roslaunch moveit_resources_prbt_moveit_config demo.launch pipeline:=pilz_industrial_motion_planner` 3. The motion planning widget (lower left part of moveit) choose PTP in the dropdown below "Trapezoidal Command Planner" (see image) ![moveit_1](img/acceptance_test_ptp_img1.png) 4. Switch to the tab "Planning" in the moveit planning plugin. Move the ball handle the select goal pose. Click on "plan and execute". diff --git a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/launch/moveit_planning_execution.launch b/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/launch/moveit_planning_execution.launch deleted file mode 100644 index 134a32ba3e..0000000000 --- a/moveit_planners/pilz_industrial_motion_planner/test/test_robots/frankaemika_panda/launch/moveit_planning_execution.launch +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - From 371cc4a62a36126df215b1463d9802849ebd4e7e Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 17 Dec 2021 17:01:11 +0100 Subject: [PATCH 157/179] Provide MOVEIT_VERSION_CHECK macro (#2997) - Rename MOVEIT_VERSION -> MOVEIT_VERSION_STR - MOVEIT_VERSION becomes a numeric identifier - Use like: #if MOVEIT_VERSION >= MOVEIT_VERSION_CHECK(1, 0, 0) --- MIGRATION.md | 1 + moveit_core/version/version.cpp | 2 +- moveit_core/version/version.h.in | 8 +++++++- moveit_ros/benchmarks/src/BenchmarkExecutor.cpp | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 18e4ae0a53..c703307e1d 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -23,6 +23,7 @@ API changes in MoveIt! releases Use [the corresponding `InteractionStyle` definitions](https://github.com/ros-planning/moveit/pull/1287/files#diff-24e57a8ea7f2f2d8a63cfc31580d09ddL240) instead - `moveit_ros_plannning` no longer depends on `moveit_ros_perception` - The joint states of `passive` joints must be published in ROS and the CurrentStateMonitor will now wait for them as well. Their semantics dictate that they cannot be actively controlled, but they must be known to use the full robot state in collision checks. (https://github.com/ros-planning/moveit/pull/2663) +- In release 1.0.9 the macro `MOVEIT_VERSION` was renamed to `MOVEIT_VERSION_STR` in favour of `MOVEIT_VERSION` becoming a numeric version identifier suitable for a version check via: `#if MOVEIT_VERSION >= MOVEIT_VERSION_CHECK(1, 0, 9)`. ## ROS Kinetic diff --git a/moveit_core/version/version.cpp b/moveit_core/version/version.cpp index 0bbb8638dc..42b83e7d56 100644 --- a/moveit_core/version/version.cpp +++ b/moveit_core/version/version.cpp @@ -39,6 +39,6 @@ int main(int argc, char** argv) { - printf("%s\n", MOVEIT_VERSION); + printf("%s\n", MOVEIT_VERSION_STR); return 0; } diff --git a/moveit_core/version/version.h.in b/moveit_core/version/version.h.in index 573a2e72b5..8e596d8f9f 100644 --- a/moveit_core/version/version.h.in +++ b/moveit_core/version/version.h.in @@ -35,11 +35,17 @@ #ifndef MOVEIT_VERSION_ #define MOVEIT_VERSION_ -#define MOVEIT_VERSION "@MOVEIT_VERSION@" +#define MOVEIT_VERSION_STR "@MOVEIT_VERSION@" #define MOVEIT_VERSION_MAJOR @MOVEIT_VERSION_MAJOR@ #define MOVEIT_VERSION_MINOR @MOVEIT_VERSION_MINOR@ #define MOVEIT_VERSION_PATCH @MOVEIT_VERSION_PATCH@ #define MOVEIT_VERSION_EXTRA "@MOVEIT_VERSION_EXTRA@" +/// MOVEIT_VERSION is (major << 16) + (minor << 8) + patch. +#define MOVEIT_VERSION MOVEIT_VERSION_CHECK(MOVEIT_VERSION_MAJOR, MOVEIT_VERSION_MINOR, MOVEIT_VERSION_PATCH) + +/// Use like: #if MOVEIT_VERSION >= MOVEIT_VERSION_CHECK(1, 0, 0) +#define MOVEIT_VERSION_CHECK(major, minor, patch) ((major << 16) | (minor << 8) | (patch)) + #endif diff --git a/moveit_ros/benchmarks/src/BenchmarkExecutor.cpp b/moveit_ros/benchmarks/src/BenchmarkExecutor.cpp index 2cf5b7aec7..e6df397765 100644 --- a/moveit_ros/benchmarks/src/BenchmarkExecutor.cpp +++ b/moveit_ros/benchmarks/src/BenchmarkExecutor.cpp @@ -1069,7 +1069,7 @@ void BenchmarkExecutor::writeOutput(const BenchmarkRequest& brequest, const std: return; } - out << "MoveIt! version " << MOVEIT_VERSION << std::endl; + out << "MoveIt version " << MOVEIT_VERSION_STR << std::endl; out << "Experiment " << brequest.name << std::endl; out << "Running on " << hostname << std::endl; out << "Starting at " << start_time << std::endl; From eaa00841038f38e9945e0ae60269ed72eff85ffd Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 29 Dec 2021 19:40:35 +0100 Subject: [PATCH 158/179] Move MoveItErrorCode class to moveit_core (#3009) ... reducing code duplication and facilitating re-use --- .../include/moveit/utils/moveit_error_code.h | 76 ++++++++++++++++ .../test/chomp_moveit_test.cpp | 20 ++--- .../move_group_interface.h | 72 +++++---------- .../src/move_group_interface.cpp | 89 +++++++++---------- .../src/wrap_python_move_group.cpp | 20 ++--- .../moveit/moveit_cpp/planning_component.h | 32 +------ .../moveit_cpp/src/planning_component.cpp | 6 +- .../test/move_group_interface_cpp_test.cpp | 6 +- .../src/motion_planning_frame_planning.cpp | 6 +- 9 files changed, 175 insertions(+), 152 deletions(-) create mode 100644 moveit_core/utils/include/moveit/utils/moveit_error_code.h diff --git a/moveit_core/utils/include/moveit/utils/moveit_error_code.h b/moveit_core/utils/include/moveit/utils/moveit_error_code.h new file mode 100644 index 0000000000..5e9aa4bb11 --- /dev/null +++ b/moveit_core/utils/include/moveit/utils/moveit_error_code.h @@ -0,0 +1,76 @@ +/********************************************************************* + * Software License Agreement (BSD License) + * + * Copyright (c) 2021, PickNik Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT 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. + *********************************************************************/ + +#pragma once + +#include + +namespace moveit +{ +namespace core +{ +/** + * @brief a wrapper around moveit_msgs::MoveItErrorCodes to make it easier to return an error code message from a function + */ +class MoveItErrorCode : public moveit_msgs::MoveItErrorCodes +{ +public: + MoveItErrorCode() + { + val = 0; + } + MoveItErrorCode(int code) + { + val = code; + } + MoveItErrorCode(const moveit_msgs::MoveItErrorCodes& code) + { + val = code.val; + } + explicit operator bool() const + { + return val == moveit_msgs::MoveItErrorCodes::SUCCESS; + } + bool operator==(const int c) const + { + return val == c; + } + bool operator!=(const int c) const + { + return val != c; + } +}; + +} // namespace core +} // namespace moveit diff --git a/moveit_planners/chomp/chomp_interface/test/chomp_moveit_test.cpp b/moveit_planners/chomp/chomp_interface/test/chomp_moveit_test.cpp index 7ec6538be9..7ea3e9ba65 100644 --- a/moveit_planners/chomp/chomp_interface/test/chomp_moveit_test.cpp +++ b/moveit_planners/chomp/chomp_interface/test/chomp_moveit_test.cpp @@ -58,9 +58,9 @@ TEST_F(CHOMPMoveitTest, jointSpaceGoodGoal) move_group_.setStartState(*(move_group_.getCurrentState())); move_group_.setJointValueTarget(std::vector({ 1.0, 1.0 })); - moveit::planning_interface::MoveItErrorCode error_code = move_group_.plan(my_plan_); + moveit::core::MoveItErrorCode error_code = move_group_.plan(my_plan_); EXPECT_GT(my_plan_.trajectory_.joint_trajectory.points.size(), 0u); - EXPECT_EQ(error_code.val, moveit::planning_interface::MoveItErrorCode::SUCCESS); + EXPECT_EQ(error_code.val, moveit::core::MoveItErrorCode::SUCCESS); } TEST_F(CHOMPMoveitTest, jointSpaceBadGoal) @@ -69,8 +69,8 @@ TEST_F(CHOMPMoveitTest, jointSpaceBadGoal) // joint2 is limited to [-PI/2, PI/2] move_group_.setJointValueTarget(std::vector({ 100.0, 2 * M_PI / 3.0 })); - moveit::planning_interface::MoveItErrorCode error_code = move_group_.plan(my_plan_); - EXPECT_EQ(error_code.val, moveit::planning_interface::MoveItErrorCode::INVALID_ROBOT_STATE); + moveit::core::MoveItErrorCode error_code = move_group_.plan(my_plan_); + EXPECT_EQ(error_code.val, moveit::core::MoveItErrorCode::INVALID_ROBOT_STATE); } TEST_F(CHOMPMoveitTest, cartesianGoal) @@ -83,17 +83,17 @@ TEST_F(CHOMPMoveitTest, cartesianGoal) target_pose1.position.z = 10000.; move_group_.setPoseTarget(target_pose1); - moveit::planning_interface::MoveItErrorCode error_code = move_group_.plan(my_plan_); + moveit::core::MoveItErrorCode error_code = move_group_.plan(my_plan_); // CHOMP doesn't support Cartesian-space goals at the moment - EXPECT_EQ(error_code.val, moveit::planning_interface::MoveItErrorCode::INVALID_GOAL_CONSTRAINTS); + EXPECT_EQ(error_code.val, moveit::core::MoveItErrorCode::INVALID_GOAL_CONSTRAINTS); } TEST_F(CHOMPMoveitTest, noStartState) { move_group_.setJointValueTarget(std::vector({ 0.2, 0.2 })); - moveit::planning_interface::MoveItErrorCode error_code = move_group_.plan(my_plan_); - EXPECT_EQ(error_code.val, moveit::planning_interface::MoveItErrorCode::SUCCESS); + moveit::core::MoveItErrorCode error_code = move_group_.plan(my_plan_); + EXPECT_EQ(error_code.val, moveit::core::MoveItErrorCode::SUCCESS); } TEST_F(CHOMPMoveitTest, collisionAtEndOfPath) @@ -101,8 +101,8 @@ TEST_F(CHOMPMoveitTest, collisionAtEndOfPath) move_group_.setStartState(*(move_group_.getCurrentState())); move_group_.setJointValueTarget(std::vector({ M_PI / 2.0, 0 })); - moveit::planning_interface::MoveItErrorCode error_code = move_group_.plan(my_plan_); - EXPECT_EQ(error_code.val, moveit::planning_interface::MoveItErrorCode::INVALID_MOTION_PLAN); + moveit::core::MoveItErrorCode error_code = move_group_.plan(my_plan_); + EXPECT_EQ(error_code.val, moveit::core::MoveItErrorCode::INVALID_MOTION_PLAN); } int main(int argc, char** argv) diff --git a/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h b/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h index d08f3b3acf..2eec003819 100644 --- a/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h +++ b/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -60,34 +61,7 @@ namespace moveit /** \brief Simple interface to MoveIt! components */ namespace planning_interface { -class MoveItErrorCode : public moveit_msgs::MoveItErrorCodes -{ -public: - MoveItErrorCode() - { - val = 0; - } - MoveItErrorCode(int code) - { - val = code; - } - MoveItErrorCode(const moveit_msgs::MoveItErrorCodes& code) - { - val = code.val; - } - explicit operator bool() const - { - return val == moveit_msgs::MoveItErrorCodes::SUCCESS; - } - bool operator==(const int c) const - { - return val == c; - } - bool operator!=(const int c) const - { - return val != c; - } -}; +using MoveItErrorCode = moveit::core::MoveItErrorCode; MOVEIT_CLASS_FORWARD(MoveGroupInterface); // Defines MoveGroupInterfacePtr, ConstPtr, WeakPtr... etc @@ -697,7 +671,7 @@ class MoveGroupInterface /** \brief Plan and execute a trajectory that takes the group of joints declared in the constructor to the specified target. This call is not blocking (does not wait for the execution of the trajectory to complete). */ - MoveItErrorCode asyncMove(); + moveit::core::MoveItErrorCode asyncMove(); /** \brief Get the move_group action client used by the \e MoveGroupInterface. The client can be used for querying the execution state of the trajectory and abort trajectory execution @@ -708,24 +682,24 @@ class MoveGroupInterface target. This call is always blocking (waits for the execution of the trajectory to complete) and requires an asynchronous spinner to be started.*/ - MoveItErrorCode move(); + moveit::core::MoveItErrorCode move(); /** \brief Compute a motion plan that takes the group declared in the constructor from the current state to the specified target. No execution is performed. The resulting plan is stored in \e plan*/ - MoveItErrorCode plan(Plan& plan); + moveit::core::MoveItErrorCode plan(Plan& plan); /** \brief Given a \e plan, execute it without waiting for completion. */ - MoveItErrorCode asyncExecute(const Plan& plan); + moveit::core::MoveItErrorCode asyncExecute(const Plan& plan); /** \brief Given a \e robot trajectory, execute it without waiting for completion. */ - MoveItErrorCode asyncExecute(const moveit_msgs::RobotTrajectory& trajectory); + moveit::core::MoveItErrorCode asyncExecute(const moveit_msgs::RobotTrajectory& trajectory); /** \brief Given a \e plan, execute it while waiting for completion. */ - MoveItErrorCode execute(const Plan& plan); + moveit::core::MoveItErrorCode execute(const Plan& plan); /** \brief Given a \e robot trajectory, execute it while waiting for completion. */ - MoveItErrorCode execute(const moveit_msgs::RobotTrajectory& trajectory); + moveit::core::MoveItErrorCode execute(const moveit_msgs::RobotTrajectory& trajectory); /** \brief Compute a Cartesian path that follows specified waypoints with a step size of at most \e eef_step meters between end effector configurations of consecutive points in the result \e trajectory. The reference frame for the @@ -792,19 +766,20 @@ class MoveGroupInterface /** \brief Pick up an object This applies a number of hard-coded default grasps */ - MoveItErrorCode pick(const std::string& object, bool plan_only = false) + moveit::core::MoveItErrorCode pick(const std::string& object, bool plan_only = false) { return pick(constructPickupGoal(object, std::vector(), plan_only)); } /** \brief Pick up an object given a grasp pose */ - MoveItErrorCode pick(const std::string& object, const moveit_msgs::Grasp& grasp, bool plan_only = false) + moveit::core::MoveItErrorCode pick(const std::string& object, const moveit_msgs::Grasp& grasp, bool plan_only = false) { return pick(constructPickupGoal(object, { grasp }, plan_only)); } /** \brief Pick up an object given possible grasp poses */ - MoveItErrorCode pick(const std::string& object, std::vector grasps, bool plan_only = false) + moveit::core::MoveItErrorCode pick(const std::string& object, std::vector grasps, + bool plan_only = false) { return pick(constructPickupGoal(object, std::move(grasps), plan_only)); } @@ -813,40 +788,41 @@ class MoveGroupInterface Use as follows: first create the goal with constructPickupGoal(), then set \e possible_grasps and any other desired variable in the goal, and finally pass it on to this function */ - MoveItErrorCode pick(const moveit_msgs::PickupGoal& goal); + moveit::core::MoveItErrorCode pick(const moveit_msgs::PickupGoal& goal); /** \brief Pick up an object calls the external moveit_msgs::GraspPlanning service "plan_grasps" to compute possible grasps */ - MoveItErrorCode planGraspsAndPick(const std::string& object = "", bool plan_only = false); + moveit::core::MoveItErrorCode planGraspsAndPick(const std::string& object = "", bool plan_only = false); /** \brief Pick up an object calls the external moveit_msgs::GraspPlanning service "plan_grasps" to compute possible grasps */ - MoveItErrorCode planGraspsAndPick(const moveit_msgs::CollisionObject& object, bool plan_only = false); + moveit::core::MoveItErrorCode planGraspsAndPick(const moveit_msgs::CollisionObject& object, bool plan_only = false); /** \brief Place an object somewhere safe in the world (a safe location will be detected) */ - MoveItErrorCode place(const std::string& object, bool plan_only = false) + moveit::core::MoveItErrorCode place(const std::string& object, bool plan_only = false) { return place(constructPlaceGoal(object, std::vector(), plan_only)); } /** \brief Place an object at one of the specified possible locations */ - MoveItErrorCode place(const std::string& object, std::vector locations, - bool plan_only = false) + moveit::core::MoveItErrorCode place(const std::string& object, std::vector locations, + bool plan_only = false) { return place(constructPlaceGoal(object, std::move(locations), plan_only)); } /** \brief Place an object at one of the specified possible locations */ - MoveItErrorCode place(const std::string& object, const std::vector& poses, - bool plan_only = false) + moveit::core::MoveItErrorCode place(const std::string& object, const std::vector& poses, + bool plan_only = false) { return place(constructPlaceGoal(object, posesToPlaceLocations(poses), plan_only)); } /** \brief Place an object at one of the specified possible location */ - MoveItErrorCode place(const std::string& object, const geometry_msgs::PoseStamped& pose, bool plan_only = false) + moveit::core::MoveItErrorCode place(const std::string& object, const geometry_msgs::PoseStamped& pose, + bool plan_only = false) { return place(constructPlaceGoal(object, posesToPlaceLocations({ pose }), plan_only)); } @@ -855,7 +831,7 @@ class MoveGroupInterface Use as follows: first create the goal with constructPlaceGoal(), then set \e place_locations and any other desired variable in the goal, and finally pass it on to this function */ - MoveItErrorCode place(const moveit_msgs::PlaceGoal& goal); + moveit::core::MoveItErrorCode place(const moveit_msgs::PlaceGoal& goal); /** \brief Given the name of an object in the planning scene, make the object attached to a link of the robot. If no link name is diff --git a/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp b/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp index edb102b8b7..65b0f654d4 100644 --- a/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp +++ b/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp @@ -602,17 +602,17 @@ class MoveGroupInterface::MoveGroupInterfaceImpl return locations; } - MoveItErrorCode place(const moveit_msgs::PlaceGoal& goal) + moveit::core::MoveItErrorCode place(const moveit_msgs::PlaceGoal& goal) { if (!place_action_client_) { ROS_ERROR_STREAM_NAMED("move_group_interface", "Place action client not found"); - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + return moveit::core::MoveItErrorCode::FAILURE; } if (!place_action_client_->isServerConnected()) { ROS_ERROR_STREAM_NAMED("move_group_interface", "Place action server not connected"); - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + return moveit::core::MoveItErrorCode::FAILURE; } place_action_client_->sendGoal(goal); @@ -623,27 +623,27 @@ class MoveGroupInterface::MoveGroupInterfaceImpl } if (place_action_client_->getState() == actionlib::SimpleClientGoalState::SUCCEEDED) { - return MoveItErrorCode(place_action_client_->getResult()->error_code); + return place_action_client_->getResult()->error_code; } else { ROS_WARN_STREAM_NAMED("move_group_interface", "Fail: " << place_action_client_->getState().toString() << ": " << place_action_client_->getState().getText()); - return MoveItErrorCode(place_action_client_->getResult()->error_code); + return place_action_client_->getResult()->error_code; } } - MoveItErrorCode pick(const moveit_msgs::PickupGoal& goal) + moveit::core::MoveItErrorCode pick(const moveit_msgs::PickupGoal& goal) { if (!pick_action_client_) { ROS_ERROR_STREAM_NAMED("move_group_interface", "Pick action client not found"); - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + return moveit::core::MoveItErrorCode::FAILURE; } if (!pick_action_client_->isServerConnected()) { ROS_ERROR_STREAM_NAMED("move_group_interface", "Pick action server not connected"); - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + return moveit::core::MoveItErrorCode::FAILURE; } pick_action_client_->sendGoal(goal); @@ -653,17 +653,17 @@ class MoveGroupInterface::MoveGroupInterfaceImpl } if (pick_action_client_->getState() == actionlib::SimpleClientGoalState::SUCCEEDED) { - return MoveItErrorCode(pick_action_client_->getResult()->error_code); + return pick_action_client_->getResult()->error_code; } else { ROS_WARN_STREAM_NAMED("move_group_interface", "Fail: " << pick_action_client_->getState().toString() << ": " << pick_action_client_->getState().getText()); - return MoveItErrorCode(pick_action_client_->getResult()->error_code); + return pick_action_client_->getResult()->error_code; } } - MoveItErrorCode planGraspsAndPick(const std::string& object, bool plan_only = false) + moveit::core::MoveItErrorCode planGraspsAndPick(const std::string& object, bool plan_only = false) { if (object.empty()) { @@ -677,13 +677,13 @@ class MoveGroupInterface::MoveGroupInterfaceImpl { ROS_ERROR_STREAM_NAMED("move_group_interface", "Asked for grasps for the object '" << object << "', but the object could not be found"); - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::INVALID_OBJECT_NAME); + return moveit::core::MoveItErrorCode::INVALID_OBJECT_NAME; } return planGraspsAndPick(objects[object], plan_only); } - MoveItErrorCode planGraspsAndPick(const moveit_msgs::CollisionObject& object, bool plan_only = false) + moveit::core::MoveItErrorCode planGraspsAndPick(const moveit_msgs::CollisionObject& object, bool plan_only = false) { if (!plan_grasps_service_.exists()) { @@ -691,7 +691,7 @@ class MoveGroupInterface::MoveGroupInterfaceImpl << GRASP_PLANNING_SERVICE_NAME << "' is not available." " This has to be implemented and started separately."); - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + return moveit::core::MoveItErrorCode::FAILURE; } moveit_msgs::GraspPlanning::Request request; @@ -706,21 +706,21 @@ class MoveGroupInterface::MoveGroupInterfaceImpl response.error_code.val != moveit_msgs::MoveItErrorCodes::SUCCESS) { ROS_ERROR_NAMED("move_group_interface", "Grasp planning failed. Unable to pick."); - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + return moveit::core::MoveItErrorCode::FAILURE; } return pick(constructPickupGoal(object.id, std::move(response.grasps), plan_only)); } - MoveItErrorCode plan(Plan& plan) + moveit::core::MoveItErrorCode plan(Plan& plan) { if (!move_action_client_) { - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + return moveit::core::MoveItErrorCode::FAILURE; } if (!move_action_client_->isServerConnected()) { - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + return moveit::core::MoveItErrorCode::FAILURE; } moveit_msgs::MoveGroupGoal goal; @@ -741,25 +741,25 @@ class MoveGroupInterface::MoveGroupInterfaceImpl plan.trajectory_ = move_action_client_->getResult()->planned_trajectory; plan.start_state_ = move_action_client_->getResult()->trajectory_start; plan.planning_time_ = move_action_client_->getResult()->planning_time; - return MoveItErrorCode(move_action_client_->getResult()->error_code); + return move_action_client_->getResult()->error_code; } else { ROS_WARN_STREAM_NAMED("move_group_interface", "Fail: " << move_action_client_->getState().toString() << ": " << move_action_client_->getState().getText()); - return MoveItErrorCode(move_action_client_->getResult()->error_code); + return move_action_client_->getResult()->error_code; } } - MoveItErrorCode move(bool wait) + moveit::core::MoveItErrorCode move(bool wait) { if (!move_action_client_) { - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + return moveit::core::MoveItErrorCode::FAILURE; } if (!move_action_client_->isServerConnected()) { - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + return moveit::core::MoveItErrorCode::FAILURE; } moveit_msgs::MoveGroupGoal goal; @@ -774,7 +774,7 @@ class MoveGroupInterface::MoveGroupInterfaceImpl move_action_client_->sendGoal(goal); if (!wait) { - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::SUCCESS); + return moveit::core::MoveItErrorCode::SUCCESS; } if (!move_action_client_->waitForResult()) @@ -784,27 +784,27 @@ class MoveGroupInterface::MoveGroupInterfaceImpl if (move_action_client_->getState() == actionlib::SimpleClientGoalState::SUCCEEDED) { - return MoveItErrorCode(move_action_client_->getResult()->error_code); + return move_action_client_->getResult()->error_code; } else { ROS_INFO_STREAM_NAMED("move_group_interface", move_action_client_->getState().toString() << ": " << move_action_client_->getState().getText()); - return MoveItErrorCode(move_action_client_->getResult()->error_code); + return move_action_client_->getResult()->error_code; } } - MoveItErrorCode execute(const moveit_msgs::RobotTrajectory& trajectory, bool wait) + moveit::core::MoveItErrorCode execute(const moveit_msgs::RobotTrajectory& trajectory, bool wait) { if (!execute_action_client_) { ROS_ERROR_STREAM_NAMED("move_group_interface", "execute action client not found"); - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + return moveit::core::MoveItErrorCode::FAILURE; } if (!execute_action_client_->isServerConnected()) { ROS_WARN_STREAM_NAMED("move_group_interface", "execute action server not connected"); - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + return moveit::core::MoveItErrorCode::FAILURE; } moveit_msgs::ExecuteTrajectoryGoal goal; @@ -813,7 +813,7 @@ class MoveGroupInterface::MoveGroupInterfaceImpl execute_action_client_->sendGoal(goal); if (!wait) { - return MoveItErrorCode(moveit_msgs::MoveItErrorCodes::SUCCESS); + return moveit::core::MoveItErrorCode::SUCCESS; } if (!execute_action_client_->waitForResult()) @@ -823,13 +823,13 @@ class MoveGroupInterface::MoveGroupInterfaceImpl if (execute_action_client_->getState() == actionlib::SimpleClientGoalState::SUCCEEDED) { - return MoveItErrorCode(execute_action_client_->getResult()->error_code); + return execute_action_client_->getResult()->error_code; } else { ROS_INFO_STREAM_NAMED("move_group_interface", execute_action_client_->getState().toString() << ": " << execute_action_client_->getState().getText()); - return MoveItErrorCode(execute_action_client_->getResult()->error_code); + return execute_action_client_->getResult()->error_code; } } @@ -1415,7 +1415,7 @@ void moveit::planning_interface::MoveGroupInterface::setMaxAccelerationScalingFa impl_->setMaxAccelerationScalingFactor(max_acceleration_scaling_factor); } -moveit::planning_interface::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::asyncMove() +moveit::core::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::asyncMove() { return impl_->move(false); } @@ -1426,35 +1426,34 @@ moveit::planning_interface::MoveGroupInterface::getMoveGroupClient() const return impl_->getMoveGroupClient(); } -moveit::planning_interface::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::move() +moveit::core::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::move() { return impl_->move(true); } -moveit::planning_interface::MoveItErrorCode -moveit::planning_interface::MoveGroupInterface::asyncExecute(const Plan& plan) +moveit::core::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::asyncExecute(const Plan& plan) { return impl_->execute(plan.trajectory_, false); } -moveit::planning_interface::MoveItErrorCode +moveit::core::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::asyncExecute(const moveit_msgs::RobotTrajectory& trajectory) { return impl_->execute(trajectory, false); } -moveit::planning_interface::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::execute(const Plan& plan) +moveit::core::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::execute(const Plan& plan) { return impl_->execute(plan.trajectory_, true); } -moveit::planning_interface::MoveItErrorCode +moveit::core::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::execute(const moveit_msgs::RobotTrajectory& trajectory) { return impl_->execute(trajectory, true); } -moveit::planning_interface::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::plan(Plan& plan) +moveit::core::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::plan(Plan& plan) { return impl_->plan(plan); } @@ -1477,27 +1476,25 @@ std::vector moveit::planning_interface::MoveGroupInt return impl_->posesToPlaceLocations(poses); } -moveit::planning_interface::MoveItErrorCode -moveit::planning_interface::MoveGroupInterface::pick(const moveit_msgs::PickupGoal& goal) +moveit::core::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::pick(const moveit_msgs::PickupGoal& goal) { return impl_->pick(goal); } -moveit::planning_interface::MoveItErrorCode +moveit::core::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::planGraspsAndPick(const std::string& object, bool plan_only) { return impl_->planGraspsAndPick(object, plan_only); } -moveit::planning_interface::MoveItErrorCode +moveit::core::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::planGraspsAndPick(const moveit_msgs::CollisionObject& object, bool plan_only) { return impl_->planGraspsAndPick(object, plan_only); } -moveit::planning_interface::MoveItErrorCode -moveit::planning_interface::MoveGroupInterface::place(const moveit_msgs::PlaceGoal& goal) +moveit::core::MoveItErrorCode moveit::planning_interface::MoveGroupInterface::place(const moveit_msgs::PlaceGoal& goal) { return impl_->place(goal); } diff --git a/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp b/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp index 4244838404..09f1f22ddf 100644 --- a/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp +++ b/moveit_ros/planning_interface/move_group_interface/src/wrap_python_move_group.cpp @@ -271,7 +271,7 @@ class MoveGroupInterfaceWrapper : protected py_bindings_tools::ROScppInitializer msg.header.frame_id = getPoseReferenceFrame(); msg.header.stamp = ros::Time::now(); GILReleaser gr; - return place(object_name, msg, plan_only) == MoveItErrorCode::SUCCESS; + return place(object_name, msg, plan_only) == moveit::core::MoveItErrorCode::SUCCESS; } bool placePoses(const std::string& object_name, const bp::list& poses_list, bool plan_only = false) @@ -281,7 +281,7 @@ class MoveGroupInterfaceWrapper : protected py_bindings_tools::ROScppInitializer for (int i = 0; i < l; ++i) py_bindings_tools::deserializeMsg(py_bindings_tools::ByteString(poses_list[i]), poses[i]); GILReleaser gr; - return place(object_name, poses, plan_only) == MoveItErrorCode::SUCCESS; + return place(object_name, poses, plan_only) == moveit::core::MoveItErrorCode::SUCCESS; } bool placeLocation(const std::string& object_name, const py_bindings_tools::ByteString& location_str, @@ -290,7 +290,7 @@ class MoveGroupInterfaceWrapper : protected py_bindings_tools::ROScppInitializer std::vector locations(1); py_bindings_tools::deserializeMsg(location_str, locations[0]); GILReleaser gr; - return place(object_name, std::move(locations), plan_only) == MoveItErrorCode::SUCCESS; + return place(object_name, std::move(locations), plan_only) == moveit::core::MoveItErrorCode::SUCCESS; } bool placeLocations(const std::string& object_name, const bp::list& location_list, bool plan_only = false) @@ -300,13 +300,13 @@ class MoveGroupInterfaceWrapper : protected py_bindings_tools::ROScppInitializer for (int i = 0; i < l; ++i) py_bindings_tools::deserializeMsg(py_bindings_tools::ByteString(location_list[i]), locations[i]); GILReleaser gr; - return place(object_name, std::move(locations), plan_only) == MoveItErrorCode::SUCCESS; + return place(object_name, std::move(locations), plan_only) == moveit::core::MoveItErrorCode::SUCCESS; } bool placeAnywhere(const std::string& object_name, bool plan_only = false) { GILReleaser gr; - return place(object_name, plan_only) == MoveItErrorCode::SUCCESS; + return place(object_name, plan_only) == moveit::core::MoveItErrorCode::SUCCESS; } void convertListToArrayOfPoses(const bp::list& poses, std::vector& msg) @@ -444,12 +444,12 @@ class MoveGroupInterfaceWrapper : protected py_bindings_tools::ROScppInitializer bool movePython() { GILReleaser gr; - return move() == MoveItErrorCode::SUCCESS; + return move() == moveit::core::MoveItErrorCode::SUCCESS; } bool asyncMovePython() { - return asyncMove() == MoveItErrorCode::SUCCESS; + return asyncMove() == moveit::core::MoveItErrorCode::SUCCESS; } bool attachObjectPython(const std::string& object_name, const std::string& link_name, const bp::list& touch_links) @@ -462,14 +462,14 @@ class MoveGroupInterfaceWrapper : protected py_bindings_tools::ROScppInitializer MoveGroupInterface::Plan plan; py_bindings_tools::deserializeMsg(plan_str, plan.trajectory_); GILReleaser gr; - return execute(plan) == MoveItErrorCode::SUCCESS; + return execute(plan) == moveit::core::MoveItErrorCode::SUCCESS; } bool asyncExecutePython(const py_bindings_tools::ByteString& plan_str) { MoveGroupInterface::Plan plan; py_bindings_tools::deserializeMsg(plan_str, plan.trajectory_); - return asyncExecute(plan) == MoveItErrorCode::SUCCESS; + return asyncExecute(plan) == moveit::core::MoveItErrorCode::SUCCESS; } py_bindings_tools::ByteString getPlanPython() @@ -649,7 +649,7 @@ static void wrap_move_group_interface() move_group_interface_class.def("move", &MoveGroupInterfaceWrapper::movePython); move_group_interface_class.def("execute", &MoveGroupInterfaceWrapper::executePython); move_group_interface_class.def("async_execute", &MoveGroupInterfaceWrapper::asyncExecutePython); - moveit::planning_interface::MoveItErrorCode (MoveGroupInterfaceWrapper::*pick_1)(const std::string&, bool) = + moveit::core::MoveItErrorCode (MoveGroupInterfaceWrapper::*pick_1)(const std::string&, bool) = &MoveGroupInterfaceWrapper::pick; move_group_interface_class.def("pick", pick_1); move_group_interface_class.def("pick", &MoveGroupInterfaceWrapper::pickGrasp); diff --git a/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/planning_component.h b/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/planning_component.h index 0bc2d5ef1c..aca8ab4c12 100644 --- a/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/planning_component.h +++ b/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/planning_component.h @@ -44,6 +44,7 @@ #include #include #include +#include namespace moveit { @@ -56,34 +57,7 @@ class PlanningComponent public: MOVEIT_STRUCT_FORWARD(PlanSolution); - class MoveItErrorCode : public moveit_msgs::MoveItErrorCodes - { - public: - MoveItErrorCode() - { - val = 0; - } - MoveItErrorCode(int code) - { - val = code; - } - MoveItErrorCode(const moveit_msgs::MoveItErrorCodes& code) - { - val = code.val; - } - explicit operator bool() const - { - return val == moveit_msgs::MoveItErrorCodes::SUCCESS; - } - bool operator==(const int code) const - { - return val == code; - } - bool operator!=(const int code) const - { - return val != code; - } - }; + using MoveItErrorCode = moveit::core::MoveItErrorCode; /// The representation of a plan solution struct PlanSolution @@ -95,7 +69,7 @@ class PlanningComponent robot_trajectory::RobotTrajectoryPtr trajectory; /// Reason why the plan failed - MoveItErrorCode error_code; + moveit::core::MoveItErrorCode error_code; explicit operator bool() const { diff --git a/moveit_ros/planning_interface/moveit_cpp/src/planning_component.cpp b/moveit_ros/planning_interface/moveit_cpp/src/planning_component.cpp index 086f3d9e9b..2c3501a19c 100644 --- a/moveit_ros/planning_interface/moveit_cpp/src/planning_component.cpp +++ b/moveit_ros/planning_interface/moveit_cpp/src/planning_component.cpp @@ -130,7 +130,7 @@ PlanningComponent::PlanSolution PlanningComponent::plan(const PlanRequestParamet if (!joint_model_group_) { ROS_ERROR_NAMED(LOGNAME, "Failed to retrieve joint model group for name '%s'.", group_name_.c_str()); - last_plan_solution_->error_code = MoveItErrorCode(moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME); + last_plan_solution_->error_code = moveit::core::MoveItErrorCode::INVALID_GROUP_NAME; return *last_plan_solution_; } @@ -167,7 +167,7 @@ PlanningComponent::PlanSolution PlanningComponent::plan(const PlanRequestParamet if (current_goal_constraints_.empty()) { ROS_ERROR_NAMED(LOGNAME, "No goal constraints set for planning request"); - last_plan_solution_->error_code = MoveItErrorCode(moveit_msgs::MoveItErrorCodes::INVALID_GOAL_CONSTRAINTS); + last_plan_solution_->error_code = moveit::core::MoveItErrorCode::INVALID_GOAL_CONSTRAINTS; return *last_plan_solution_; } req.goal_constraints = current_goal_constraints_; @@ -177,7 +177,7 @@ PlanningComponent::PlanSolution PlanningComponent::plan(const PlanRequestParamet if (planning_pipeline_names_.find(parameters.planning_pipeline) == planning_pipeline_names_.end()) { ROS_ERROR_NAMED(LOGNAME, "No planning pipeline available for name '%s'", parameters.planning_pipeline.c_str()); - last_plan_solution_->error_code = MoveItErrorCode(moveit_msgs::MoveItErrorCodes::FAILURE); + last_plan_solution_->error_code = moveit::core::MoveItErrorCode::FAILURE; return *last_plan_solution_; } const planning_pipeline::PlanningPipelinePtr pipeline = diff --git a/moveit_ros/planning_interface/test/move_group_interface_cpp_test.cpp b/moveit_ros/planning_interface/test/move_group_interface_cpp_test.cpp index 9c9423f188..0155e75a68 100644 --- a/moveit_ros/planning_interface/test/move_group_interface_cpp_test.cpp +++ b/moveit_ros/planning_interface/test/move_group_interface_cpp_test.cpp @@ -126,8 +126,8 @@ class MoveGroupTestFixture : public ::testing::Test { SCOPED_TRACE("planAndMove"); moveit::planning_interface::MoveGroupInterface::Plan my_plan; - ASSERT_EQ(move_group_->plan(my_plan), moveit::planning_interface::MoveItErrorCode::SUCCESS); - ASSERT_EQ(move_group_->move(), moveit::planning_interface::MoveItErrorCode::SUCCESS); + ASSERT_EQ(move_group_->plan(my_plan), moveit::core::MoveItErrorCode::SUCCESS); + ASSERT_EQ(move_group_->move(), moveit::core::MoveItErrorCode::SUCCESS); } void testEigenPose(const Eigen::Isometry3d& expected, const Eigen::Isometry3d& actual) @@ -318,7 +318,7 @@ TEST_F(MoveGroupTestFixture, CartPathTest) ASSERT_GE(EPSILON + move_group_->computeCartesianPath(waypoints, eef_step, jump_threshold, trajectory), 1.0); // Execute trajectory - EXPECT_EQ(move_group_->execute(trajectory), moveit::planning_interface::MoveItErrorCode::SUCCESS); + EXPECT_EQ(move_group_->execute(trajectory), moveit::core::MoveItErrorCode::SUCCESS); // get the pose after the movement testPose(target_waypoint); diff --git a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_planning.cpp b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_planning.cpp index de3c3548a2..b85ca3e6bd 100644 --- a/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_planning.cpp +++ b/moveit_ros/visualization/motion_planning_rviz_plugin/src/motion_planning_frame_planning.cpp @@ -163,7 +163,7 @@ bool MotionPlanningFrame::computeCartesianPlan() bool MotionPlanningFrame::computeJointSpacePlan() { current_plan_.reset(new moveit::planning_interface::MoveGroupInterface::Plan()); - return move_group_->plan(*current_plan_) == moveit::planning_interface::MoveItErrorCode::SUCCESS; + return move_group_->plan(*current_plan_) == moveit::core::MoveItErrorCode::SUCCESS; } void MotionPlanningFrame::computePlanButtonClicked() @@ -200,7 +200,7 @@ void MotionPlanningFrame::computeExecuteButtonClicked() if (mgi && current_plan_) { ui_->stop_button->setEnabled(true); // enable stopping - bool success = mgi->execute(*current_plan_) == moveit::planning_interface::MoveItErrorCode::SUCCESS; + bool success = mgi->execute(*current_plan_) == moveit::core::MoveItErrorCode::SUCCESS; onFinishedExecution(success); } } @@ -222,7 +222,7 @@ void MotionPlanningFrame::computePlanAndExecuteButtonClicked() } else { - bool success = move_group_->move() == moveit::planning_interface::MoveItErrorCode::SUCCESS; + bool success = move_group_->move() == moveit::core::MoveItErrorCode::SUCCESS; onFinishedExecution(success); } ui_->plan_and_execute_button->setEnabled(true); From b8603b4ef5aa2852c90acf4b6195750ddd43cb9d Mon Sep 17 00:00:00 2001 From: Tyler Weaver Date: Mon, 13 Dec 2021 01:09:12 -0700 Subject: [PATCH 159/179] Increase ccache size (#2990) Increase ccache size to 10G. This is particularly needed for ccov's debug build, which uses 8G according to the stats. Co-authored-by: Robert Haschke --- .github/workflows/ci.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1da78dedf2..9e220fd8d4 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -35,6 +35,10 @@ jobs: # Pull any updates to the upstream workspace (after restoring it from cache) AFTER_SETUP_UPSTREAM_WORKSPACE: vcs pull $BASEDIR/upstream_ws/src AFTER_SETUP_DOWNSTREAM_WORKSPACE: vcs pull $BASEDIR/downstream_ws/src + # Clear the ccache stats before and log the stats after the build + AFTER_SETUP_CCACHE: ccache --zero-stats --max-size=10.0G + AFTER_BUILD_TARGET_WORKSPACE: ccache --show-stats + AFTER_BUILD_DOWNSTREAM_WORKSPACE: ccache --show-stats # Compile CCOV with Debug. Enable -Werror (except CLANG_TIDY=pedantic, which makes the clang-tidy step fail on warnings) TARGET_CMAKE_ARGS: > -DCMAKE_BUILD_TYPE=${{ matrix.env.CCOV && 'Debug' || 'Release'}} From e123e4fbd6a253b44d97f284b1b7ec741667042b Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Wed, 29 Dec 2021 21:54:49 +0100 Subject: [PATCH 160/179] Add missing noexcept declarations (#3016) ... as suggested by clang-tidy --- .../moveit/move_group_interface/move_group_interface.h | 4 ++-- .../move_group_interface/src/move_group_interface.cpp | 4 ++-- .../moveit_cpp/include/moveit/moveit_cpp/moveit_cpp.h | 4 ++-- .../moveit_cpp/include/moveit/moveit_cpp/planning_component.h | 4 ++-- moveit_ros/planning_interface/moveit_cpp/src/moveit_cpp.cpp | 4 ++-- .../planning_interface/moveit_cpp/src/planning_component.cpp | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h b/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h index 2eec003819..6f16527b34 100644 --- a/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h +++ b/moveit_ros/planning_interface/move_group_interface/include/moveit/move_group_interface/move_group_interface.h @@ -151,8 +151,8 @@ class MoveGroupInterface MoveGroupInterface(const MoveGroupInterface&) = delete; MoveGroupInterface& operator=(const MoveGroupInterface&) = delete; - MoveGroupInterface(MoveGroupInterface&& other); - MoveGroupInterface& operator=(MoveGroupInterface&& other); + MoveGroupInterface(MoveGroupInterface&& other) noexcept; + MoveGroupInterface& operator=(MoveGroupInterface&& other) noexcept; /** \brief Get the name of the group this instance operates on */ const std::string& getName() const; diff --git a/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp b/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp index 65b0f654d4..ca4be411b5 100644 --- a/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp +++ b/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp @@ -1314,14 +1314,14 @@ moveit::planning_interface::MoveGroupInterface::~MoveGroupInterface() delete impl_; } -moveit::planning_interface::MoveGroupInterface::MoveGroupInterface(MoveGroupInterface&& other) +moveit::planning_interface::MoveGroupInterface::MoveGroupInterface(MoveGroupInterface&& other) noexcept : remembered_joint_values_(std::move(other.remembered_joint_values_)), impl_(other.impl_) { other.impl_ = nullptr; } moveit::planning_interface::MoveGroupInterface& -moveit::planning_interface::MoveGroupInterface::operator=(MoveGroupInterface&& other) +moveit::planning_interface::MoveGroupInterface::operator=(MoveGroupInterface&& other) noexcept { if (this != &other) { diff --git a/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/moveit_cpp.h b/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/moveit_cpp.h index eb3d5e6296..1c481e473b 100644 --- a/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/moveit_cpp.h +++ b/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/moveit_cpp.h @@ -120,8 +120,8 @@ class MoveItCpp MoveItCpp(const MoveItCpp&) = delete; MoveItCpp& operator=(const MoveItCpp&) = delete; - MoveItCpp(MoveItCpp&& other); - MoveItCpp& operator=(MoveItCpp&& other); + MoveItCpp(MoveItCpp&& other) noexcept; + MoveItCpp& operator=(MoveItCpp&& other) noexcept; /** \brief Destructor */ ~MoveItCpp(); diff --git a/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/planning_component.h b/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/planning_component.h index aca8ab4c12..03c2f73760 100644 --- a/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/planning_component.h +++ b/moveit_ros/planning_interface/moveit_cpp/include/moveit/moveit_cpp/planning_component.h @@ -111,8 +111,8 @@ class PlanningComponent PlanningComponent(const PlanningComponent&) = delete; PlanningComponent& operator=(const PlanningComponent&) = delete; - PlanningComponent(PlanningComponent&& other); - PlanningComponent& operator=(PlanningComponent&& other); + PlanningComponent(PlanningComponent&& other) = delete; + PlanningComponent& operator=(PlanningComponent&& other) noexcept; /** \brief Destructor */ ~PlanningComponent(); diff --git a/moveit_ros/planning_interface/moveit_cpp/src/moveit_cpp.cpp b/moveit_ros/planning_interface/moveit_cpp/src/moveit_cpp.cpp index ddf0682de2..2f5aa6b384 100644 --- a/moveit_ros/planning_interface/moveit_cpp/src/moveit_cpp.cpp +++ b/moveit_ros/planning_interface/moveit_cpp/src/moveit_cpp.cpp @@ -96,7 +96,7 @@ MoveItCpp::MoveItCpp(const Options& options, const ros::NodeHandle& nh, ROS_INFO_NAMED(LOGNAME, "MoveItCpp running"); } -MoveItCpp::MoveItCpp(MoveItCpp&& other) +MoveItCpp::MoveItCpp(MoveItCpp&& other) noexcept { other.clearContents(); } @@ -107,7 +107,7 @@ MoveItCpp::~MoveItCpp() clearContents(); } -MoveItCpp& MoveItCpp::operator=(MoveItCpp&& other) +MoveItCpp& MoveItCpp::operator=(MoveItCpp&& other) noexcept { if (this != &other) { diff --git a/moveit_ros/planning_interface/moveit_cpp/src/planning_component.cpp b/moveit_ros/planning_interface/moveit_cpp/src/planning_component.cpp index 2c3501a19c..198c274551 100644 --- a/moveit_ros/planning_interface/moveit_cpp/src/planning_component.cpp +++ b/moveit_ros/planning_interface/moveit_cpp/src/planning_component.cpp @@ -92,7 +92,7 @@ PlanningComponent::~PlanningComponent() clearContents(); } -PlanningComponent& PlanningComponent::operator=(PlanningComponent&& other) +PlanningComponent& PlanningComponent::operator=(PlanningComponent&& other) noexcept { if (this != &other) { From e4b04a73a585858eaaf5025ed61bcac6dc3f6d55 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Thu, 18 Nov 2021 17:27:57 +0100 Subject: [PATCH 161/179] Use move_group namespace --- moveit_ros/move_group/src/move_group_context.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/moveit_ros/move_group/src/move_group_context.cpp b/moveit_ros/move_group/src/move_group_context.cpp index a36325766b..1e2d721f3d 100644 --- a/moveit_ros/move_group/src/move_group_context.cpp +++ b/moveit_ros/move_group/src/move_group_context.cpp @@ -40,9 +40,10 @@ #include #include -move_group::MoveGroupContext::MoveGroupContext( - const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, bool allow_trajectory_execution, - bool debug) +namespace move_group +{ +MoveGroupContext::MoveGroupContext(const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor, + bool allow_trajectory_execution, bool debug) : planning_scene_monitor_(planning_scene_monitor) , allow_trajectory_execution_(allow_trajectory_execution) , debug_(debug) @@ -67,7 +68,7 @@ move_group::MoveGroupContext::MoveGroupContext( planning_pipeline_->publishReceivedRequests(true); } -move_group::MoveGroupContext::~MoveGroupContext() +MoveGroupContext::~MoveGroupContext() { plan_with_sensing_.reset(); plan_execution_.reset(); @@ -76,7 +77,7 @@ move_group::MoveGroupContext::~MoveGroupContext() planning_scene_monitor_.reset(); } -bool move_group::MoveGroupContext::status() const +bool MoveGroupContext::status() const { const planning_interface::PlannerManagerPtr& planner_interface = planning_pipeline_->getPlannerManager(); if (planner_interface) @@ -91,3 +92,5 @@ bool move_group::MoveGroupContext::status() const return false; } } + +} // namespace move_group From 0247b56587569cc2372944b1b9116da1047e2ef3 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 5 Nov 2021 13:56:53 +0100 Subject: [PATCH 162/179] Switch to moveit_resource@master --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1da78dedf2..d94e849054 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -30,7 +30,7 @@ jobs: CLANG_TIDY_ARGS: --fix --fix-errors DOCKER_IMAGE: moveit/moveit:${{ matrix.env.IMAGE }} UPSTREAM_WORKSPACE: .github/workflows/upstream.rosinstall - TARGET_WORKSPACE: $TARGET_REPO_PATH github:ros-planning/moveit_resources#melodic-devel + TARGET_WORKSPACE: $TARGET_REPO_PATH github:ros-planning/moveit_resources#master DOWNSTREAM_WORKSPACE: .github/workflows/downstream.rosinstall # Pull any updates to the upstream workspace (after restoring it from cache) AFTER_SETUP_UPSTREAM_WORKSPACE: vcs pull $BASEDIR/upstream_ws/src From 9b622a77c5edf967e36cce3526f5fedf2ac587c6 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 5 Nov 2021 13:56:53 +0100 Subject: [PATCH 163/179] Support new configuration scheme with multiple pipelines Traditionally, PlanningPipeline parameters were defined in the private namespace of the move_group node. Since MoveIt 1.1.2 multiple pipeline configs are supported in parallel, defined as ~planning_pipelines/*. To support this new scheme as well (in a minimal fashion), we check for presence of the new scheme and use the parameters of the default pipeline, specified via the parameter ~default_planning_pipeline. --- .../moveit/planning_interface/planning_interface.h | 7 +++++++ .../planning_interface/src/planning_interface.cpp | 10 ++++++++++ .../src/chomp_optimizer_adapter.cpp | 3 ++- moveit_ros/move_group/src/move_group.cpp | 8 ++++++++ .../planning_pipeline/src/planning_pipeline.cpp | 7 ++++--- .../src/fix_start_state_bounds.cpp | 3 ++- .../src/fix_start_state_collision.cpp | 3 ++- .../src/fix_workspace_bounds.cpp | 3 ++- 8 files changed, 37 insertions(+), 7 deletions(-) diff --git a/moveit_core/planning_interface/include/moveit/planning_interface/planning_interface.h b/moveit_core/planning_interface/include/moveit/planning_interface/planning_interface.h index abfea8506d..d4f6fd7711 100644 --- a/moveit_core/planning_interface/include/moveit/planning_interface/planning_interface.h +++ b/moveit_core/planning_interface/include/moveit/planning_interface/planning_interface.h @@ -51,6 +51,13 @@ MOVEIT_CLASS_FORWARD(PlanningScene); // Defines PlanningScenePtr, ConstPtr, Wea /** \brief This namespace includes the base class for MoveIt! planners */ namespace planning_interface { +/** \brief Retrieve NodeHandle/namespace defining the PlanningPipeline parameters + * Traditionally, these were directly defined in the private namespace of the move_group node. + * Since MoveIt 1.1.2 multiple pipeline configs are supported in parallel. + * In Melodic we support this new scheme by allowing to choose the default pipeline, + * specified via the parameter ~default_planning_pipeline. */ +ros::NodeHandle getConfigNodeHandle(const ros::NodeHandle& nh = ros::NodeHandle("~")); + /** \brief Specify the settings for a particular planning algorithm, for a particular group. The Planner plugin uses these settings to configure the algorithm. diff --git a/moveit_core/planning_interface/src/planning_interface.cpp b/moveit_core/planning_interface/src/planning_interface.cpp index 32337f3de3..65a706ed19 100644 --- a/moveit_core/planning_interface/src/planning_interface.cpp +++ b/moveit_core/planning_interface/src/planning_interface.cpp @@ -56,6 +56,16 @@ static ActiveContexts& getActiveContexts() } } // namespace +ros::NodeHandle getConfigNodeHandle(const ros::NodeHandle& nh) +{ + // Handle new configuration scheme with multiple pipelines configured in namespaces planning_pipelines/* + std::string default_pipeline; + if (nh.getParam("default_planning_pipeline", default_pipeline) && + nh.hasParam("planning_pipelines/" + default_pipeline)) + return ros::NodeHandle(nh, "planning_pipelines/" + default_pipeline); + return nh; +} + PlanningContext::PlanningContext(const std::string& name, const std::string& group) : name_(name), group_(group) { ActiveContexts& ac = getActiveContexts(); diff --git a/moveit_planners/chomp/chomp_optimizer_adapter/src/chomp_optimizer_adapter.cpp b/moveit_planners/chomp/chomp_optimizer_adapter/src/chomp_optimizer_adapter.cpp index a53f74d9b0..9b5fe0fd3e 100644 --- a/moveit_planners/chomp/chomp_optimizer_adapter/src/chomp_optimizer_adapter.cpp +++ b/moveit_planners/chomp/chomp_optimizer_adapter/src/chomp_optimizer_adapter.cpp @@ -58,7 +58,8 @@ namespace chomp class OptimizerAdapter : public planning_request_adapter::PlanningRequestAdapter { public: - OptimizerAdapter() : planning_request_adapter::PlanningRequestAdapter(), nh_("~") + OptimizerAdapter() + : planning_request_adapter::PlanningRequestAdapter(), nh_(planning_interface::getConfigNodeHandle()) { if (!nh_.getParam("planning_time_limit", params_.planning_time_limit_)) { diff --git a/moveit_ros/move_group/src/move_group.cpp b/moveit_ros/move_group/src/move_group.cpp index 9ab89beef6..256dfbe410 100644 --- a/moveit_ros/move_group/src/move_group.cpp +++ b/moveit_ros/move_group/src/move_group.cpp @@ -135,6 +135,14 @@ class MoveGroupExe capabilities.insert(tok.begin(), tok.end()); } + // add capabilities configured for default planning pipeline (Noetic pipeline definitions) + if (planning_interface::getConfigNodeHandle().getParam("capabilities", capability_plugins)) + { + boost::char_separator sep(" "); + boost::tokenizer> tok(capability_plugins, sep); + capabilities.insert(tok.begin(), tok.end()); + } + // drop capabilities that have been explicitly disabled if (node_handle_.getParam("disable_capabilities", capability_plugins)) { diff --git a/moveit_ros/planning/planning_pipeline/src/planning_pipeline.cpp b/moveit_ros/planning/planning_pipeline/src/planning_pipeline.cpp index 18cb516806..26e52294b8 100644 --- a/moveit_ros/planning/planning_pipeline/src/planning_pipeline.cpp +++ b/moveit_ros/planning/planning_pipeline/src/planning_pipeline.cpp @@ -55,11 +55,12 @@ planning_pipeline::PlanningPipeline::PlanningPipeline(const robot_model::RobotMo : nh_(nh), robot_model_(model) { std::string planner; - if (nh_.getParam(planner_plugin_param_name, planner)) + ros::NodeHandle cnh = planning_interface::getConfigNodeHandle(nh); + if (cnh.getParam(planner_plugin_param_name, planner)) planner_plugin_name_ = planner; std::string adapters; - if (nh_.getParam(adapter_plugins_param_name, adapters)) + if (cnh.getParam(adapter_plugins_param_name, adapters)) { boost::char_separator sep(" "); boost::tokenizer > tok(adapters, sep); @@ -114,7 +115,7 @@ void planning_pipeline::PlanningPipeline::configure() try { planner_instance_ = planner_plugin_loader_->createUniqueInstance(planner_plugin_name_); - if (!planner_instance_->initialize(robot_model_, nh_.getNamespace())) + if (!planner_instance_->initialize(robot_model_, planning_interface::getConfigNodeHandle(nh_).getNamespace())) throw std::runtime_error("Unable to initialize planning plugin"); ROS_INFO_STREAM("Using planning interface '" << planner_instance_->getDescription() << "'"); } diff --git a/moveit_ros/planning/planning_request_adapter_plugins/src/fix_start_state_bounds.cpp b/moveit_ros/planning/planning_request_adapter_plugins/src/fix_start_state_bounds.cpp index 883931b2d9..f41a5edd47 100644 --- a/moveit_ros/planning/planning_request_adapter_plugins/src/fix_start_state_bounds.cpp +++ b/moveit_ros/planning/planning_request_adapter_plugins/src/fix_start_state_bounds.cpp @@ -49,7 +49,8 @@ class FixStartStateBounds : public planning_request_adapter::PlanningRequestAdap static const std::string BOUNDS_PARAM_NAME; static const std::string DT_PARAM_NAME; - FixStartStateBounds() : planning_request_adapter::PlanningRequestAdapter(), nh_("~") + FixStartStateBounds() + : planning_request_adapter::PlanningRequestAdapter(), nh_(planning_interface::getConfigNodeHandle()) { if (!nh_.getParam(BOUNDS_PARAM_NAME, bounds_dist_)) { diff --git a/moveit_ros/planning/planning_request_adapter_plugins/src/fix_start_state_collision.cpp b/moveit_ros/planning/planning_request_adapter_plugins/src/fix_start_state_collision.cpp index 237b59fe51..87ef1e6f01 100644 --- a/moveit_ros/planning/planning_request_adapter_plugins/src/fix_start_state_collision.cpp +++ b/moveit_ros/planning/planning_request_adapter_plugins/src/fix_start_state_collision.cpp @@ -49,7 +49,8 @@ class FixStartStateCollision : public planning_request_adapter::PlanningRequestA static const std::string JIGGLE_PARAM_NAME; static const std::string ATTEMPTS_PARAM_NAME; - FixStartStateCollision() : planning_request_adapter::PlanningRequestAdapter(), nh_("~") + FixStartStateCollision() + : planning_request_adapter::PlanningRequestAdapter(), nh_(planning_interface::getConfigNodeHandle()) { if (!nh_.getParam(DT_PARAM_NAME, max_dt_offset_)) { diff --git a/moveit_ros/planning/planning_request_adapter_plugins/src/fix_workspace_bounds.cpp b/moveit_ros/planning/planning_request_adapter_plugins/src/fix_workspace_bounds.cpp index 15fbce16fa..16b5ae0e19 100644 --- a/moveit_ros/planning/planning_request_adapter_plugins/src/fix_workspace_bounds.cpp +++ b/moveit_ros/planning/planning_request_adapter_plugins/src/fix_workspace_bounds.cpp @@ -45,7 +45,8 @@ class FixWorkspaceBounds : public planning_request_adapter::PlanningRequestAdapt public: static const std::string WBOUNDS_PARAM_NAME; - FixWorkspaceBounds() : planning_request_adapter::PlanningRequestAdapter(), nh_("~") + FixWorkspaceBounds() + : planning_request_adapter::PlanningRequestAdapter(), nh_(planning_interface::getConfigNodeHandle()) { if (!nh_.getParam(WBOUNDS_PARAM_NAME, workspace_extent_)) { From d9b4eecdd8c19453d18635a6009c63886c147a7f Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Sun, 2 Jan 2022 12:37:01 +0100 Subject: [PATCH 164/179] clang-format --- moveit_ros/move_group/src/move_group.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/moveit_ros/move_group/src/move_group.cpp b/moveit_ros/move_group/src/move_group.cpp index 256dfbe410..e913a1b915 100644 --- a/moveit_ros/move_group/src/move_group.cpp +++ b/moveit_ros/move_group/src/move_group.cpp @@ -131,7 +131,7 @@ class MoveGroupExe if (node_handle_.getParam("capabilities", capability_plugins)) { boost::char_separator sep(" "); - boost::tokenizer > tok(capability_plugins, sep); + boost::tokenizer> tok(capability_plugins, sep); capabilities.insert(tok.begin(), tok.end()); } @@ -147,8 +147,8 @@ class MoveGroupExe if (node_handle_.getParam("disable_capabilities", capability_plugins)) { boost::char_separator sep(" "); - boost::tokenizer > tok(capability_plugins, sep); - for (boost::tokenizer >::iterator cap_name = tok.begin(); cap_name != tok.end(); + boost::tokenizer> tok(capability_plugins, sep); + for (boost::tokenizer>::iterator cap_name = tok.begin(); cap_name != tok.end(); ++cap_name) capabilities.erase(*cap_name); } @@ -182,7 +182,7 @@ class MoveGroupExe ros::NodeHandle node_handle_; MoveGroupContextPtr context_; - std::shared_ptr > capability_plugin_loader_; + std::shared_ptr> capability_plugin_loader_; std::vector capabilities_; }; } // namespace move_group From 393815e4872de6349ae3784360dbe276a9abda7a Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 7 Jan 2022 08:24:49 +0100 Subject: [PATCH 165/179] Make TimeParameterization classes polymorphic (#3021) (#3023) --- .../iterative_spline_parameterization.h | 6 +++--- .../iterative_time_parameterization.h | 6 +++--- .../time_optimal_trajectory_generation.h | 6 +++--- .../time_parameterization.h | 18 ++++++++++++++++++ .../src/iterative_spline_parameterization.cpp | 2 -- .../src/iterative_time_parameterization.cpp | 2 -- .../src/time_optimal_trajectory_generation.cpp | 4 ---- 7 files changed, 27 insertions(+), 17 deletions(-) create mode 100644 moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_parameterization.h diff --git a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/iterative_spline_parameterization.h b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/iterative_spline_parameterization.h index bc287eccef..b4ecb04f25 100644 --- a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/iterative_spline_parameterization.h +++ b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/iterative_spline_parameterization.h @@ -39,6 +39,7 @@ #define MOVEIT_TRAJECTORY_PROCESSING_ITERATIVE_SPLINE_PARAMETERIZATION__ #include +#include namespace trajectory_processing { @@ -68,14 +69,13 @@ namespace trajectory_processing /// velocity and acceleration limits, will result in a longer trajectory. /// If this is a problem, try retuning (increasing) the limits. /// -class IterativeSplineParameterization +class IterativeSplineParameterization : public TimeParameterization { public: IterativeSplineParameterization(bool add_points = true); - ~IterativeSplineParameterization(); bool computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory, const double max_velocity_scaling_factor = 1.0, - const double max_acceleration_scaling_factor = 1.0) const; + const double max_acceleration_scaling_factor = 1.0) const override; private: bool add_points_; /// @brief If true, add two points to trajectory (first and last segments). diff --git a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/iterative_time_parameterization.h b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/iterative_time_parameterization.h index 29a9bcf348..11244f6b20 100644 --- a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/iterative_time_parameterization.h +++ b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/iterative_time_parameterization.h @@ -38,19 +38,19 @@ #define MOVEIT_TRAJECTORY_PROCESSING_ITERATIVE_PARABOLIC_SMOOTHER_ #include +#include namespace trajectory_processing { /// \brief This class modifies the timestamps of a trajectory to respect /// velocity and acceleration constraints. -class IterativeParabolicTimeParameterization +class IterativeParabolicTimeParameterization : public TimeParameterization { public: IterativeParabolicTimeParameterization(unsigned int max_iterations = 100, double max_time_change_per_it = .01); - ~IterativeParabolicTimeParameterization(); bool computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory, const double max_velocity_scaling_factor = 1.0, - const double max_acceleration_scaling_factor = 1.0) const; + const double max_acceleration_scaling_factor = 1.0) const override; private: unsigned int max_iterations_; /// @brief maximum number of iterations to find solution diff --git a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_optimal_trajectory_generation.h b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_optimal_trajectory_generation.h index 0edbe1a338..17b548d812 100644 --- a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_optimal_trajectory_generation.h +++ b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_optimal_trajectory_generation.h @@ -42,6 +42,7 @@ #include #include #include +#include namespace trajectory_processing { @@ -160,15 +161,14 @@ class Trajectory mutable std::list::const_iterator cached_trajectory_segment_; }; -class TimeOptimalTrajectoryGeneration +class TimeOptimalTrajectoryGeneration : public TimeParameterization { public: TimeOptimalTrajectoryGeneration(const double path_tolerance = 0.1, const double resample_dt = 0.1, const double min_angle_change = 0.001); - ~TimeOptimalTrajectoryGeneration(); bool computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory, const double max_velocity_scaling_factor = 1.0, - const double max_acceleration_scaling_factor = 1.0) const; + const double max_acceleration_scaling_factor = 1.0) const override; private: const double path_tolerance_; diff --git a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_parameterization.h b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_parameterization.h new file mode 100644 index 0000000000..3a64960e54 --- /dev/null +++ b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_parameterization.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace trajectory_processing +{ +/** + * @brief Base class for trajectory parameterization algorithms + */ +class TimeParameterization +{ +public: + virtual ~TimeParameterization() = default; + virtual bool computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory, + const double max_velocity_scaling_factor = 1.0, + const double max_acceleration_scaling_factor = 1.0) const = 0; +}; +} // namespace trajectory_processing diff --git a/moveit_core/trajectory_processing/src/iterative_spline_parameterization.cpp b/moveit_core/trajectory_processing/src/iterative_spline_parameterization.cpp index 498957f6ab..a026985cc2 100644 --- a/moveit_core/trajectory_processing/src/iterative_spline_parameterization.cpp +++ b/moveit_core/trajectory_processing/src/iterative_spline_parameterization.cpp @@ -76,8 +76,6 @@ IterativeSplineParameterization::IterativeSplineParameterization(bool add_points { } -IterativeSplineParameterization::~IterativeSplineParameterization() = default; - bool IterativeSplineParameterization::computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory, const double max_velocity_scaling_factor, const double max_acceleration_scaling_factor) const diff --git a/moveit_core/trajectory_processing/src/iterative_time_parameterization.cpp b/moveit_core/trajectory_processing/src/iterative_time_parameterization.cpp index 1b86b56918..4f4072a2ec 100644 --- a/moveit_core/trajectory_processing/src/iterative_time_parameterization.cpp +++ b/moveit_core/trajectory_processing/src/iterative_time_parameterization.cpp @@ -50,8 +50,6 @@ IterativeParabolicTimeParameterization::IterativeParabolicTimeParameterization(u { } -IterativeParabolicTimeParameterization::~IterativeParabolicTimeParameterization() = default; - namespace { void printPoint(const trajectory_msgs::JointTrajectoryPoint& point, std::size_t i) diff --git a/moveit_core/trajectory_processing/src/time_optimal_trajectory_generation.cpp b/moveit_core/trajectory_processing/src/time_optimal_trajectory_generation.cpp index 63f8512989..4ae1806481 100644 --- a/moveit_core/trajectory_processing/src/time_optimal_trajectory_generation.cpp +++ b/moveit_core/trajectory_processing/src/time_optimal_trajectory_generation.cpp @@ -867,10 +867,6 @@ TimeOptimalTrajectoryGeneration::TimeOptimalTrajectoryGeneration(const double pa { } -TimeOptimalTrajectoryGeneration::~TimeOptimalTrajectoryGeneration() -{ -} - bool TimeOptimalTrajectoryGeneration::computeTimeStamps(robot_trajectory::RobotTrajectory& trajectory, const double max_velocity_scaling_factor, const double max_acceleration_scaling_factor) const From e12053f9a8316225747e0720df9abaf599689c89 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Sun, 9 Jan 2022 17:25:48 +0100 Subject: [PATCH 166/179] 1.0.9 --- moveit/CHANGELOG.rst | 3 +++ moveit/package.xml | 2 +- moveit_commander/CHANGELOG.rst | 3 +++ moveit_commander/package.xml | 2 +- moveit_core/CHANGELOG.rst | 13 +++++++++++++ moveit_core/package.xml | 2 +- moveit_kinematics/CHANGELOG.rst | 3 +++ moveit_kinematics/package.xml | 2 +- moveit_planners/chomp/chomp_interface/CHANGELOG.rst | 10 ++++++++++ moveit_planners/chomp/chomp_interface/package.xml | 2 +- .../chomp/chomp_motion_planner/CHANGELOG.rst | 3 +++ .../chomp/chomp_motion_planner/package.xml | 2 +- .../chomp/chomp_optimizer_adapter/CHANGELOG.rst | 9 +++++++++ .../chomp/chomp_optimizer_adapter/package.xml | 2 +- moveit_planners/moveit_planners/CHANGELOG.rst | 3 +++ moveit_planners/moveit_planners/package.xml | 2 +- moveit_planners/ompl/CHANGELOG.rst | 3 +++ moveit_planners/ompl/package.xml | 2 +- .../pilz_industrial_motion_planner/CHANGELOG.rst | 10 ++++++++++ .../pilz_industrial_motion_planner/package.xml | 2 +- .../CHANGELOG.rst | 3 +++ .../package.xml | 2 +- .../moveit_controller_manager_example/CHANGELOG.rst | 3 +++ .../moveit_controller_manager_example/package.xml | 2 +- .../moveit_fake_controller_manager/CHANGELOG.rst | 3 +++ .../moveit_fake_controller_manager/package.xml | 2 +- moveit_plugins/moveit_plugins/CHANGELOG.rst | 3 +++ moveit_plugins/moveit_plugins/package.xml | 2 +- .../moveit_ros_control_interface/CHANGELOG.rst | 3 +++ .../moveit_ros_control_interface/package.xml | 2 +- .../moveit_simple_controller_manager/CHANGELOG.rst | 3 +++ .../moveit_simple_controller_manager/package.xml | 2 +- moveit_ros/benchmarks/CHANGELOG.rst | 5 +++++ moveit_ros/benchmarks/package.xml | 2 +- moveit_ros/manipulation/CHANGELOG.rst | 3 +++ moveit_ros/manipulation/package.xml | 2 +- moveit_ros/move_group/CHANGELOG.rst | 9 +++++++++ moveit_ros/move_group/package.xml | 2 +- moveit_ros/moveit_ros/CHANGELOG.rst | 3 +++ moveit_ros/moveit_ros/package.xml | 2 +- moveit_ros/moveit_servo/CHANGELOG.rst | 5 +++++ moveit_ros/moveit_servo/package.xml | 2 +- moveit_ros/occupancy_map_monitor/CHANGELOG.rst | 3 +++ moveit_ros/occupancy_map_monitor/package.xml | 2 +- moveit_ros/perception/CHANGELOG.rst | 3 +++ moveit_ros/perception/package.xml | 2 +- moveit_ros/planning/CHANGELOG.rst | 9 +++++++++ moveit_ros/planning/package.xml | 2 +- moveit_ros/planning_interface/CHANGELOG.rst | 12 ++++++++++++ moveit_ros/planning_interface/package.xml | 2 +- moveit_ros/robot_interaction/CHANGELOG.rst | 3 +++ moveit_ros/robot_interaction/package.xml | 2 +- moveit_ros/visualization/CHANGELOG.rst | 5 +++++ moveit_ros/visualization/package.xml | 2 +- moveit_ros/warehouse/CHANGELOG.rst | 3 +++ moveit_ros/warehouse/package.xml | 2 +- moveit_runtime/CHANGELOG.rst | 3 +++ moveit_runtime/package.xml | 2 +- moveit_setup_assistant/CHANGELOG.rst | 12 ++++++++++++ moveit_setup_assistant/package.xml | 2 +- 60 files changed, 186 insertions(+), 30 deletions(-) diff --git a/moveit/CHANGELOG.rst b/moveit/CHANGELOG.rst index 6522946ba2..d8f381cea4 100644 --- a/moveit/CHANGELOG.rst +++ b/moveit/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit/package.xml b/moveit/package.xml index 3daf8cd5ed..45fa1f9c96 100644 --- a/moveit/package.xml +++ b/moveit/package.xml @@ -1,7 +1,7 @@ moveit - 1.0.8 + 1.0.9 Meta package that contains all essential package of MoveIt!. Until Summer 2016 MoveIt! had been developed over multiple repositories, where developers' usability and maintenance effort was non-trivial. See the detailed discussion for the merge of several repositories. Dave Coleman Michael Ferguson diff --git a/moveit_commander/CHANGELOG.rst b/moveit_commander/CHANGELOG.rst index e6ccf6f458..be458f2945 100644 --- a/moveit_commander/CHANGELOG.rst +++ b/moveit_commander/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_commander ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ * Add clear() to Python PSI + Allow empty call to remove_attached_object() (`#2609 `_) diff --git a/moveit_commander/package.xml b/moveit_commander/package.xml index 025840d51e..a4a117e4bd 100644 --- a/moveit_commander/package.xml +++ b/moveit_commander/package.xml @@ -1,6 +1,6 @@ moveit_commander - 1.0.8 + 1.0.9 Python interfaces to MoveIt Ioan Sucan diff --git a/moveit_core/CHANGELOG.rst b/moveit_core/CHANGELOG.rst index 34d4999442..839dc5b707 100644 --- a/moveit_core/CHANGELOG.rst +++ b/moveit_core/CHANGELOG.rst @@ -2,6 +2,19 @@ Changelog for package moveit_core ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ +* Use moveit-resources@master (`#2951 `_) + + - Simplify launch files to use the test_environment.launch files from moveit_resources@master + - Provide compatibility to the Noetic-style configuration of (multiple) planning pipelines + Only a single pipeline can be used at a time, specified via the ~default_planning_pipeline parameter. +* Make TimeParameterization classes polymorphic (`#3023 `_) +* Move ``MoveItErrorCode`` class to ``moveit_core`` (`#3009 `_) +* Provide ``MOVEIT_VERSION_CHECK`` macro (`#2997 `_) +* Fix padding collision attached objects (`#2721 `_) +* Contributors: Michael Görner, Robert Haschke, Toru Kuga, Andrea Pupa + 1.0.8 (2021-05-23) ------------------ * RobotState interpolation: warn if interpolation parameter is out of range [0, 1] (`#2664 `_) diff --git a/moveit_core/package.xml b/moveit_core/package.xml index 1c76b3aa54..17ca4ca9e8 100644 --- a/moveit_core/package.xml +++ b/moveit_core/package.xml @@ -1,6 +1,6 @@ moveit_core - 1.0.8 + 1.0.9 Core libraries used by MoveIt! Ioan Sucan Sachin Chitta diff --git a/moveit_kinematics/CHANGELOG.rst b/moveit_kinematics/CHANGELOG.rst index 734ce31572..d30ab47f76 100644 --- a/moveit_kinematics/CHANGELOG.rst +++ b/moveit_kinematics/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_kinematics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ * Improve ikfast QUIET handling (`#2685 `_) diff --git a/moveit_kinematics/package.xml b/moveit_kinematics/package.xml index 54d096a315..89a32522c3 100644 --- a/moveit_kinematics/package.xml +++ b/moveit_kinematics/package.xml @@ -1,7 +1,7 @@ moveit_kinematics - 1.0.8 + 1.0.9 Package for all inverse kinematics solvers in MoveIt! Dave Coleman diff --git a/moveit_planners/chomp/chomp_interface/CHANGELOG.rst b/moveit_planners/chomp/chomp_interface/CHANGELOG.rst index 07c6cdd157..ce03904255 100644 --- a/moveit_planners/chomp/chomp_interface/CHANGELOG.rst +++ b/moveit_planners/chomp/chomp_interface/CHANGELOG.rst @@ -2,6 +2,16 @@ Changelog for package chomp_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ +* Use moveit-resources@master (`#2951 `_) + + - Simplify launch files to use the test_environment.launch files from moveit_resources@master + - Provide compatibility to the Noetic-style configuration of (multiple) planning pipelines + Only a single pipeline can be used at a time, specified via the ~default_planning_pipeline parameter. +* Move ``MoveItErrorCode`` class to ``moveit_core`` (`#3009 `_) +* Contributors: Robert Haschke + 1.0.8 (2021-05-23) ------------------ * Sanitize CHOMP initialization method parameter (`#2540 `_) diff --git a/moveit_planners/chomp/chomp_interface/package.xml b/moveit_planners/chomp/chomp_interface/package.xml index 9bc53a0756..58b71fa8af 100644 --- a/moveit_planners/chomp/chomp_interface/package.xml +++ b/moveit_planners/chomp/chomp_interface/package.xml @@ -2,7 +2,7 @@ moveit_planners_chomp The interface for using CHOMP within MoveIt! - 1.0.8 + 1.0.9 Gil Jones Chittaranjan Srinivas Swaminathan diff --git a/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst b/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst index 6591f51a4e..992ac7eb1d 100644 --- a/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst +++ b/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package chomp_motion_planner ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ * Sanitize CHOMP initialization method parameter (`#2540 `_) diff --git a/moveit_planners/chomp/chomp_motion_planner/package.xml b/moveit_planners/chomp/chomp_motion_planner/package.xml index d6402b6c87..36149f9921 100644 --- a/moveit_planners/chomp/chomp_motion_planner/package.xml +++ b/moveit_planners/chomp/chomp_motion_planner/package.xml @@ -2,7 +2,7 @@ chomp_motion_planner chomp_motion_planner - 1.0.8 + 1.0.9 Gil Jones Mrinal Kalakrishnan diff --git a/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst b/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst index 3c28c180f7..273dff4bfc 100644 --- a/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst +++ b/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst @@ -2,6 +2,15 @@ Changelog for package moveit_chomp_optimizer_adapter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ +* Use moveit-resources@master (`#2951 `_) + + - Simplify launch files to use the test_environment.launch files from moveit_resources@master + - Provide compatibility to the Noetic-style configuration of (multiple) planning pipelines + Only a single pipeline can be used at a time, specified via the ~default_planning_pipeline parameter. +* Contributors: Robert Haschke + 1.0.8 (2021-05-23) ------------------ * Enable mesh filter (`#2448 `_) diff --git a/moveit_planners/chomp/chomp_optimizer_adapter/package.xml b/moveit_planners/chomp/chomp_optimizer_adapter/package.xml index 1996ff4a09..cec10ce355 100644 --- a/moveit_planners/chomp/chomp_optimizer_adapter/package.xml +++ b/moveit_planners/chomp/chomp_optimizer_adapter/package.xml @@ -3,7 +3,7 @@ moveit_chomp_optimizer_adapter MoveIt planning request adapter utilizing chomp for solution optimization - 1.0.8 + 1.0.9 Raghavender Sahdev Raghavender Sahdev MoveIt! Release Team diff --git a/moveit_planners/moveit_planners/CHANGELOG.rst b/moveit_planners/moveit_planners/CHANGELOG.rst index 8de27fe179..6b44fb4279 100644 --- a/moveit_planners/moveit_planners/CHANGELOG.rst +++ b/moveit_planners/moveit_planners/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_planners ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit_planners/moveit_planners/package.xml b/moveit_planners/moveit_planners/package.xml index 4a7e192952..a7a284473f 100644 --- a/moveit_planners/moveit_planners/package.xml +++ b/moveit_planners/moveit_planners/package.xml @@ -1,6 +1,6 @@ moveit_planners - 1.0.8 + 1.0.9 Metapacakge that installs all available planners for MoveIt Ioan Sucan Sachin Chitta diff --git a/moveit_planners/ompl/CHANGELOG.rst b/moveit_planners/ompl/CHANGELOG.rst index b17da540d3..bb9db46d1e 100644 --- a/moveit_planners/ompl/CHANGELOG.rst +++ b/moveit_planners/ompl/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_planners_ompl ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit_planners/ompl/package.xml b/moveit_planners/ompl/package.xml index 880006c1c1..77724f810c 100644 --- a/moveit_planners/ompl/package.xml +++ b/moveit_planners/ompl/package.xml @@ -1,6 +1,6 @@ moveit_planners_ompl - 1.0.8 + 1.0.9 MoveIt! interface to OMPL Ioan Sucan diff --git a/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst b/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst index d16d0c3733..5c28cb0a31 100644 --- a/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst +++ b/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst @@ -2,6 +2,16 @@ Changelog for package pilz_industrial_motion_planner ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ +* Use moveit-resources@master (`#2951 `_) + + - Simplify launch files to use the test_environment.launch files from moveit_resources@master + - Provide compatibility to the Noetic-style configuration of (multiple) planning pipelines + Only a single pipeline can be used at a time, specified via the ~default_planning_pipeline parameter. + - Rename launch argument execution_type -> fake_execution_type +* Contributors: Michael Görner, Robert Haschke + 1.0.8 (2021-05-23) ------------------ * Fix velocity limit error (`#2610 `_) diff --git a/moveit_planners/pilz_industrial_motion_planner/package.xml b/moveit_planners/pilz_industrial_motion_planner/package.xml index eea6780bfe..0828d3e5ba 100644 --- a/moveit_planners/pilz_industrial_motion_planner/package.xml +++ b/moveit_planners/pilz_industrial_motion_planner/package.xml @@ -1,7 +1,7 @@ pilz_industrial_motion_planner - 1.0.8 + 1.0.9 MoveIt plugin to generate industrial trajectories PTP, LIN, CIRC and sequences thereof. Alexander Gutenkunst diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst b/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst index 338af8f17f..eaf146e833 100644 --- a/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package pilz_industrial_motion_planner_testutils ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ * Add pilz_industrial_motion_planner to moveit_planners (`#2507 `_) diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml b/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml index c1d2993171..4be2eaa152 100644 --- a/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml @@ -1,7 +1,7 @@ pilz_industrial_motion_planner_testutils - 1.0.8 + 1.0.9 Helper scripts and functionality to test industrial motion generation Alexander Gutenkunst diff --git a/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst b/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst index f18e569b7e..1ee86b1677 100644 --- a/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst +++ b/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_controller_manager_example ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit_plugins/moveit_controller_manager_example/package.xml b/moveit_plugins/moveit_controller_manager_example/package.xml index 7a6178e222..79adebc6a0 100644 --- a/moveit_plugins/moveit_controller_manager_example/package.xml +++ b/moveit_plugins/moveit_controller_manager_example/package.xml @@ -1,6 +1,6 @@ moveit_controller_manager_example - 1.0.8 + 1.0.9 An example controller manager plugin for MoveIt. This is not functional code. Ioan Sucan diff --git a/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst b/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst index 7cc85f3cc2..a562c39152 100644 --- a/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst +++ b/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_fake_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit_plugins/moveit_fake_controller_manager/package.xml b/moveit_plugins/moveit_fake_controller_manager/package.xml index f158f2e2c7..2dde4cbd1e 100644 --- a/moveit_plugins/moveit_fake_controller_manager/package.xml +++ b/moveit_plugins/moveit_fake_controller_manager/package.xml @@ -1,6 +1,6 @@ moveit_fake_controller_manager - 1.0.8 + 1.0.9 A fake controller manager plugin for MoveIt. Ioan Sucan diff --git a/moveit_plugins/moveit_plugins/CHANGELOG.rst b/moveit_plugins/moveit_plugins/CHANGELOG.rst index 7f0ab89a34..859bd7fc19 100644 --- a/moveit_plugins/moveit_plugins/CHANGELOG.rst +++ b/moveit_plugins/moveit_plugins/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_plugins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit_plugins/moveit_plugins/package.xml b/moveit_plugins/moveit_plugins/package.xml index 660c165699..428980767a 100644 --- a/moveit_plugins/moveit_plugins/package.xml +++ b/moveit_plugins/moveit_plugins/package.xml @@ -1,6 +1,6 @@ moveit_plugins - 1.0.8 + 1.0.9 Metapackage for MoveIt! plugins. Michael Ferguson diff --git a/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst b/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst index db0c6795cc..a4a97e8fc8 100644 --- a/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst +++ b/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_control_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit_plugins/moveit_ros_control_interface/package.xml b/moveit_plugins/moveit_ros_control_interface/package.xml index 34ff66d40b..bae36c4e41 100644 --- a/moveit_plugins/moveit_ros_control_interface/package.xml +++ b/moveit_plugins/moveit_ros_control_interface/package.xml @@ -1,7 +1,7 @@ moveit_ros_control_interface - 1.0.8 + 1.0.9 ros_control controller manager interface for MoveIt! Mathias Lüdtke diff --git a/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst b/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst index f68445422f..43fe248b1c 100644 --- a/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst +++ b/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_simple_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit_plugins/moveit_simple_controller_manager/package.xml b/moveit_plugins/moveit_simple_controller_manager/package.xml index 0c59c2e0bc..70fec61816 100644 --- a/moveit_plugins/moveit_simple_controller_manager/package.xml +++ b/moveit_plugins/moveit_simple_controller_manager/package.xml @@ -1,6 +1,6 @@ moveit_simple_controller_manager - 1.0.8 + 1.0.9 A generic, simple controller manager plugin for MoveIt. Michael Ferguson diff --git a/moveit_ros/benchmarks/CHANGELOG.rst b/moveit_ros/benchmarks/CHANGELOG.rst index 2bc167f5a4..4d32acdddf 100644 --- a/moveit_ros/benchmarks/CHANGELOG.rst +++ b/moveit_ros/benchmarks/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_ros_benchmarks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ +* Provide ``MOVEIT_VERSION_CHECK`` macro (`#2997 `_) +* Contributors: Robert Haschke + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit_ros/benchmarks/package.xml b/moveit_ros/benchmarks/package.xml index 0753b0a990..fc06fa83d4 100644 --- a/moveit_ros/benchmarks/package.xml +++ b/moveit_ros/benchmarks/package.xml @@ -1,6 +1,6 @@ moveit_ros_benchmarks - 1.0.8 + 1.0.9 Enhanced tools for benchmarks in MoveIt! diff --git a/moveit_ros/manipulation/CHANGELOG.rst b/moveit_ros/manipulation/CHANGELOG.rst index 34b50fddb5..292407f320 100644 --- a/moveit_ros/manipulation/CHANGELOG.rst +++ b/moveit_ros/manipulation/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_manipulation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit_ros/manipulation/package.xml b/moveit_ros/manipulation/package.xml index 06fafb8777..5dd889ad06 100644 --- a/moveit_ros/manipulation/package.xml +++ b/moveit_ros/manipulation/package.xml @@ -1,6 +1,6 @@ moveit_ros_manipulation - 1.0.8 + 1.0.9 Components of MoveIt! used for manipulation Ioan Sucan diff --git a/moveit_ros/move_group/CHANGELOG.rst b/moveit_ros/move_group/CHANGELOG.rst index 849d0dffb4..0a866a4e45 100644 --- a/moveit_ros/move_group/CHANGELOG.rst +++ b/moveit_ros/move_group/CHANGELOG.rst @@ -2,6 +2,15 @@ Changelog for package moveit_ros_move_group ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ +* Use moveit-resources@master (`#2951 `_) + + - Simplify launch files to use the test_environment.launch files from moveit_resources@master + - Provide compatibility to the Noetic-style configuration of (multiple) planning pipelines + Only a single pipeline can be used at a time, specified via the ~default_planning_pipeline parameter. +* Contributors: Robert Haschke + 1.0.8 (2021-05-23) ------------------ * Fix missing isEmpty() check in compute_ik service (`#2544 `_) diff --git a/moveit_ros/move_group/package.xml b/moveit_ros/move_group/package.xml index 06ce69202e..ff941fd649 100644 --- a/moveit_ros/move_group/package.xml +++ b/moveit_ros/move_group/package.xml @@ -1,6 +1,6 @@ moveit_ros_move_group - 1.0.8 + 1.0.9 The move_group node for MoveIt Ioan Sucan Sachin Chitta diff --git a/moveit_ros/moveit_ros/CHANGELOG.rst b/moveit_ros/moveit_ros/CHANGELOG.rst index 5775e2a3aa..980409e278 100644 --- a/moveit_ros/moveit_ros/CHANGELOG.rst +++ b/moveit_ros/moveit_ros/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit_ros/moveit_ros/package.xml b/moveit_ros/moveit_ros/package.xml index 6b6131c16e..178f434aa6 100644 --- a/moveit_ros/moveit_ros/package.xml +++ b/moveit_ros/moveit_ros/package.xml @@ -1,6 +1,6 @@ moveit_ros - 1.0.8 + 1.0.9 Components of MoveIt! that use ROS Ioan Sucan Sachin Chitta diff --git a/moveit_ros/moveit_servo/CHANGELOG.rst b/moveit_ros/moveit_servo/CHANGELOG.rst index ba62745da2..ffc24bf0ac 100644 --- a/moveit_ros/moveit_servo/CHANGELOG.rst +++ b/moveit_ros/moveit_servo/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_servo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ +* Fix an off-by-one error in servo_calcs.cpp (`#2908 `_) +* Contributors: Michael Görner + 1.0.8 (2021-05-23) ------------------ * Avoid joint jump when SuddenHalt() is called in velocity mode (`#2594 `_) diff --git a/moveit_ros/moveit_servo/package.xml b/moveit_ros/moveit_servo/package.xml index 98e5aff6d2..83ef049f88 100644 --- a/moveit_ros/moveit_servo/package.xml +++ b/moveit_ros/moveit_servo/package.xml @@ -1,7 +1,7 @@ moveit_servo - 1.0.8 + 1.0.9 Provides real-time manipulator Cartesian and joint servoing. diff --git a/moveit_ros/occupancy_map_monitor/CHANGELOG.rst b/moveit_ros/occupancy_map_monitor/CHANGELOG.rst index fd072251d5..fef2b8f446 100644 --- a/moveit_ros/occupancy_map_monitor/CHANGELOG.rst +++ b/moveit_ros/occupancy_map_monitor/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_occupancy_map_monitor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ * Document solution in ROS_ERROR on failed self-filtering (`#2627 `_) diff --git a/moveit_ros/occupancy_map_monitor/package.xml b/moveit_ros/occupancy_map_monitor/package.xml index 1700eb392b..b7bf082100 100644 --- a/moveit_ros/occupancy_map_monitor/package.xml +++ b/moveit_ros/occupancy_map_monitor/package.xml @@ -1,7 +1,7 @@ moveit_ros_occupancy_map_monitor - 1.0.8 + 1.0.9 Components of MoveIt! connecting to occupancy map Ioan Sucan diff --git a/moveit_ros/perception/CHANGELOG.rst b/moveit_ros/perception/CHANGELOG.rst index 7422191bbd..82df26c6f4 100644 --- a/moveit_ros/perception/CHANGELOG.rst +++ b/moveit_ros/perception/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_perception ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ * Document solution in ROS_ERROR on failed self-filtering (`#2627 `_) diff --git a/moveit_ros/perception/package.xml b/moveit_ros/perception/package.xml index 5016d617e6..77b7aef540 100644 --- a/moveit_ros/perception/package.xml +++ b/moveit_ros/perception/package.xml @@ -1,6 +1,6 @@ moveit_ros_perception - 1.0.8 + 1.0.9 Components of MoveIt! connecting to perception Ioan Sucan diff --git a/moveit_ros/planning/CHANGELOG.rst b/moveit_ros/planning/CHANGELOG.rst index ac0a4a0ca8..39197f51aa 100644 --- a/moveit_ros/planning/CHANGELOG.rst +++ b/moveit_ros/planning/CHANGELOG.rst @@ -2,6 +2,15 @@ Changelog for package moveit_ros_planning ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ +* Use moveit-resources@master (`#2951 `_) + + - Simplify launch files to use the test_environment.launch files from moveit_resources@master + - Provide compatibility to the Noetic-style configuration of (multiple) planning pipelines + Only a single pipeline can be used at a time, specified via the ~default_planning_pipeline parameter. +* Contributors: Robert Haschke + 1.0.8 (2021-05-23) ------------------ * Unify and simplify CSM::haveCompleteState overloads (`#2663 `_) diff --git a/moveit_ros/planning/package.xml b/moveit_ros/planning/package.xml index 4eef18484e..7610a73024 100644 --- a/moveit_ros/planning/package.xml +++ b/moveit_ros/planning/package.xml @@ -1,7 +1,7 @@ moveit_ros_planning - 1.0.8 + 1.0.9 Planning components of MoveIt! that use ROS Ioan Sucan Sachin Chitta diff --git a/moveit_ros/planning_interface/CHANGELOG.rst b/moveit_ros/planning_interface/CHANGELOG.rst index 53f3c29e47..f4335ba493 100644 --- a/moveit_ros/planning_interface/CHANGELOG.rst +++ b/moveit_ros/planning_interface/CHANGELOG.rst @@ -2,6 +2,18 @@ Changelog for package moveit_ros_planning_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ +* Use moveit-resources@master (`#2951 `_) + + - Simplify launch files to use the test_environment.launch files from moveit_resources@master + - Provide compatibility to the Noetic-style configuration of (multiple) planning pipelines + Only a single pipeline can be used at a time, specified via the ~default_planning_pipeline parameter. +* Add missing noexcept declarations (`#3016 `_) +* Move ``MoveItErrorCode`` class to ``moveit_core`` (`#3009 `_) +* Revert "Fix scaling factor parameter names" (`#2907 `_) +* Contributors: Michael Görner, Robert Haschke + 1.0.8 (2021-05-23) ------------------ * planning_interface: synchronize async interfaces in test (`#2640 `_) diff --git a/moveit_ros/planning_interface/package.xml b/moveit_ros/planning_interface/package.xml index 8f65c7b3b5..471b605057 100644 --- a/moveit_ros/planning_interface/package.xml +++ b/moveit_ros/planning_interface/package.xml @@ -1,6 +1,6 @@ moveit_ros_planning_interface - 1.0.8 + 1.0.9 Components of MoveIt! that offer simpler interfaces to planning and execution Ioan Sucan diff --git a/moveit_ros/robot_interaction/CHANGELOG.rst b/moveit_ros/robot_interaction/CHANGELOG.rst index 681f0a8f1f..2935791cb0 100644 --- a/moveit_ros/robot_interaction/CHANGELOG.rst +++ b/moveit_ros/robot_interaction/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_robot_interaction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ * Suppress warnings "mesh_use_embedded_materials is ignored" diff --git a/moveit_ros/robot_interaction/package.xml b/moveit_ros/robot_interaction/package.xml index b00a0f3e22..7ff055432d 100644 --- a/moveit_ros/robot_interaction/package.xml +++ b/moveit_ros/robot_interaction/package.xml @@ -1,6 +1,6 @@ moveit_ros_robot_interaction - 1.0.8 + 1.0.9 Components of MoveIt! that offer interaction via interactive markers Ioan Sucan diff --git a/moveit_ros/visualization/CHANGELOG.rst b/moveit_ros/visualization/CHANGELOG.rst index a7ad1ebbb7..ce606f252f 100644 --- a/moveit_ros/visualization/CHANGELOG.rst +++ b/moveit_ros/visualization/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_ros_visualization ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ +* Move ``MoveItErrorCode`` class to ``moveit_core`` (`#3009 `_) +* Contributors: Michael Görner, Robert Haschke + 1.0.8 (2021-05-23) ------------------ * Remove unused model_is_loading\_ diff --git a/moveit_ros/visualization/package.xml b/moveit_ros/visualization/package.xml index aa9175a926..5a16833431 100644 --- a/moveit_ros/visualization/package.xml +++ b/moveit_ros/visualization/package.xml @@ -1,6 +1,6 @@ moveit_ros_visualization - 1.0.8 + 1.0.9 Components of MoveIt! that offer visualization Ioan Sucan diff --git a/moveit_ros/warehouse/CHANGELOG.rst b/moveit_ros/warehouse/CHANGELOG.rst index a23e97e754..824e7b0006 100644 --- a/moveit_ros/warehouse/CHANGELOG.rst +++ b/moveit_ros/warehouse/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_warehouse ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit_ros/warehouse/package.xml b/moveit_ros/warehouse/package.xml index 7b7c735784..9b06388ee8 100644 --- a/moveit_ros/warehouse/package.xml +++ b/moveit_ros/warehouse/package.xml @@ -1,6 +1,6 @@ moveit_ros_warehouse - 1.0.8 + 1.0.9 Components of MoveIt! connecting to MongoDB Ioan Sucan diff --git a/moveit_runtime/CHANGELOG.rst b/moveit_runtime/CHANGELOG.rst index cc6cf64058..cd30aa37a7 100644 --- a/moveit_runtime/CHANGELOG.rst +++ b/moveit_runtime/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_runtime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ + 1.0.8 (2021-05-23) ------------------ diff --git a/moveit_runtime/package.xml b/moveit_runtime/package.xml index 9eed90305b..62d9aaa21b 100644 --- a/moveit_runtime/package.xml +++ b/moveit_runtime/package.xml @@ -1,7 +1,7 @@ moveit_runtime - 1.0.8 + 1.0.9 moveit_runtime meta package contains MoveIt! packages that are essential for its runtime (e.g. running MoveIt! on robots). Isaac I. Y. Saito diff --git a/moveit_setup_assistant/CHANGELOG.rst b/moveit_setup_assistant/CHANGELOG.rst index e551d8d0a7..d9ae36970e 100644 --- a/moveit_setup_assistant/CHANGELOG.rst +++ b/moveit_setup_assistant/CHANGELOG.rst @@ -2,6 +2,18 @@ Changelog for package moveit_setup_assistant ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.9 (2022-01-09) +------------------ +* Use moveit-resources@master (`#2951 `_) + + - Simplify launch files to use the test_environment.launch files from moveit_resources@master + - Provide compatibility to the Noetic-style configuration of (multiple) planning pipelines + Only a single pipeline can be used at a time, specified via the ~default_planning_pipeline parameter. + - Rename launch argument execution_type -> fake_execution_type +* Templates: Fix passing capabilities arguments (`#2729 `_) +* Fix writing an empty sensor config (`#2708 `_) +* Contributors: David V. Lu!!, G.A. vd. Hoorn, Michael Görner, Robert Haschke + 1.0.8 (2021-05-23) ------------------ * Let users override fake execution type from demo.launch (`#2602 `_) diff --git a/moveit_setup_assistant/package.xml b/moveit_setup_assistant/package.xml index 100f832448..1687123e79 100644 --- a/moveit_setup_assistant/package.xml +++ b/moveit_setup_assistant/package.xml @@ -1,6 +1,6 @@ moveit_setup_assistant - 1.0.8 + 1.0.9 Generates a configuration package that makes it easy to use MoveIt! From 462b2c0cce10b757089f7f587c76e2f2515543d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Fri, 4 Mar 2022 17:35:29 +0100 Subject: [PATCH 167/179] Add Ptr definitions for TimeParameterization classes (#3078) Follow up on #3021. --- .../trajectory_processing/iterative_time_parameterization.h | 1 + .../trajectory_processing/time_optimal_trajectory_generation.h | 1 + .../include/moveit/trajectory_processing/time_parameterization.h | 1 + 3 files changed, 3 insertions(+) diff --git a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/iterative_time_parameterization.h b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/iterative_time_parameterization.h index 11244f6b20..8229b684c9 100644 --- a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/iterative_time_parameterization.h +++ b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/iterative_time_parameterization.h @@ -44,6 +44,7 @@ namespace trajectory_processing { /// \brief This class modifies the timestamps of a trajectory to respect /// velocity and acceleration constraints. +MOVEIT_CLASS_FORWARD(IterativeParabolicTimeParameterization); class IterativeParabolicTimeParameterization : public TimeParameterization { public: diff --git a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_optimal_trajectory_generation.h b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_optimal_trajectory_generation.h index 17b548d812..8d8e8b76a5 100644 --- a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_optimal_trajectory_generation.h +++ b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_optimal_trajectory_generation.h @@ -161,6 +161,7 @@ class Trajectory mutable std::list::const_iterator cached_trajectory_segment_; }; +MOVEIT_CLASS_FORWARD(TimeOptimalTrajectoryGeneration); class TimeOptimalTrajectoryGeneration : public TimeParameterization { public: diff --git a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_parameterization.h b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_parameterization.h index 3a64960e54..2cbc29121f 100644 --- a/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_parameterization.h +++ b/moveit_core/trajectory_processing/include/moveit/trajectory_processing/time_parameterization.h @@ -7,6 +7,7 @@ namespace trajectory_processing /** * @brief Base class for trajectory parameterization algorithms */ +MOVEIT_CLASS_FORWARD(TimeParameterization); class TimeParameterization { public: From 789f44e7814b2bff4e1a6ba535af5cd074112e0e Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Sun, 6 Mar 2022 10:22:21 +0100 Subject: [PATCH 168/179] 1.0.10 --- moveit/CHANGELOG.rst | 3 +++ moveit/package.xml | 2 +- moveit_commander/CHANGELOG.rst | 3 +++ moveit_commander/package.xml | 2 +- moveit_core/CHANGELOG.rst | 5 +++++ moveit_core/package.xml | 2 +- moveit_kinematics/CHANGELOG.rst | 3 +++ moveit_kinematics/package.xml | 2 +- moveit_planners/chomp/chomp_interface/CHANGELOG.rst | 3 +++ moveit_planners/chomp/chomp_interface/package.xml | 2 +- moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst | 3 +++ moveit_planners/chomp/chomp_motion_planner/package.xml | 2 +- moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst | 3 +++ moveit_planners/chomp/chomp_optimizer_adapter/package.xml | 2 +- moveit_planners/moveit_planners/CHANGELOG.rst | 3 +++ moveit_planners/moveit_planners/package.xml | 2 +- moveit_planners/ompl/CHANGELOG.rst | 3 +++ moveit_planners/ompl/package.xml | 2 +- moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst | 3 +++ moveit_planners/pilz_industrial_motion_planner/package.xml | 2 +- .../pilz_industrial_motion_planner_testutils/CHANGELOG.rst | 3 +++ .../pilz_industrial_motion_planner_testutils/package.xml | 2 +- .../moveit_controller_manager_example/CHANGELOG.rst | 3 +++ moveit_plugins/moveit_controller_manager_example/package.xml | 2 +- moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst | 3 +++ moveit_plugins/moveit_fake_controller_manager/package.xml | 2 +- moveit_plugins/moveit_plugins/CHANGELOG.rst | 3 +++ moveit_plugins/moveit_plugins/package.xml | 2 +- moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst | 3 +++ moveit_plugins/moveit_ros_control_interface/package.xml | 2 +- .../moveit_simple_controller_manager/CHANGELOG.rst | 3 +++ moveit_plugins/moveit_simple_controller_manager/package.xml | 2 +- moveit_ros/benchmarks/CHANGELOG.rst | 3 +++ moveit_ros/benchmarks/package.xml | 2 +- moveit_ros/manipulation/CHANGELOG.rst | 3 +++ moveit_ros/manipulation/package.xml | 2 +- moveit_ros/move_group/CHANGELOG.rst | 3 +++ moveit_ros/move_group/package.xml | 2 +- moveit_ros/moveit_ros/CHANGELOG.rst | 3 +++ moveit_ros/moveit_ros/package.xml | 2 +- moveit_ros/moveit_servo/CHANGELOG.rst | 3 +++ moveit_ros/moveit_servo/package.xml | 2 +- moveit_ros/occupancy_map_monitor/CHANGELOG.rst | 3 +++ moveit_ros/occupancy_map_monitor/package.xml | 2 +- moveit_ros/perception/CHANGELOG.rst | 3 +++ moveit_ros/perception/package.xml | 2 +- moveit_ros/planning/CHANGELOG.rst | 3 +++ moveit_ros/planning/package.xml | 2 +- moveit_ros/planning_interface/CHANGELOG.rst | 3 +++ moveit_ros/planning_interface/package.xml | 2 +- moveit_ros/robot_interaction/CHANGELOG.rst | 3 +++ moveit_ros/robot_interaction/package.xml | 2 +- moveit_ros/visualization/CHANGELOG.rst | 3 +++ moveit_ros/visualization/package.xml | 2 +- moveit_ros/warehouse/CHANGELOG.rst | 3 +++ moveit_ros/warehouse/package.xml | 2 +- moveit_runtime/CHANGELOG.rst | 3 +++ moveit_runtime/package.xml | 2 +- moveit_setup_assistant/CHANGELOG.rst | 3 +++ moveit_setup_assistant/package.xml | 2 +- 60 files changed, 122 insertions(+), 30 deletions(-) diff --git a/moveit/CHANGELOG.rst b/moveit/CHANGELOG.rst index d8f381cea4..df87700960 100644 --- a/moveit/CHANGELOG.rst +++ b/moveit/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit/package.xml b/moveit/package.xml index 45fa1f9c96..22a3c62668 100644 --- a/moveit/package.xml +++ b/moveit/package.xml @@ -1,7 +1,7 @@ moveit - 1.0.9 + 1.0.10 Meta package that contains all essential package of MoveIt!. Until Summer 2016 MoveIt! had been developed over multiple repositories, where developers' usability and maintenance effort was non-trivial. See the detailed discussion for the merge of several repositories. Dave Coleman Michael Ferguson diff --git a/moveit_commander/CHANGELOG.rst b/moveit_commander/CHANGELOG.rst index be458f2945..74b45f81fb 100644 --- a/moveit_commander/CHANGELOG.rst +++ b/moveit_commander/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_commander ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_commander/package.xml b/moveit_commander/package.xml index a4a117e4bd..bcc2040290 100644 --- a/moveit_commander/package.xml +++ b/moveit_commander/package.xml @@ -1,6 +1,6 @@ moveit_commander - 1.0.9 + 1.0.10 Python interfaces to MoveIt Ioan Sucan diff --git a/moveit_core/CHANGELOG.rst b/moveit_core/CHANGELOG.rst index 839dc5b707..c034853f35 100644 --- a/moveit_core/CHANGELOG.rst +++ b/moveit_core/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_core ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- +* Add Ptr definitions for TimeParameterization classes (`#3078 `_) +* Contributors: Michael Görner + 1.0.9 (2022-01-09) ------------------ * Use moveit-resources@master (`#2951 `_) diff --git a/moveit_core/package.xml b/moveit_core/package.xml index 17ca4ca9e8..6ea144fa84 100644 --- a/moveit_core/package.xml +++ b/moveit_core/package.xml @@ -1,6 +1,6 @@ moveit_core - 1.0.9 + 1.0.10 Core libraries used by MoveIt! Ioan Sucan Sachin Chitta diff --git a/moveit_kinematics/CHANGELOG.rst b/moveit_kinematics/CHANGELOG.rst index d30ab47f76..bf7edba9b8 100644 --- a/moveit_kinematics/CHANGELOG.rst +++ b/moveit_kinematics/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_kinematics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_kinematics/package.xml b/moveit_kinematics/package.xml index 89a32522c3..07af8fca3a 100644 --- a/moveit_kinematics/package.xml +++ b/moveit_kinematics/package.xml @@ -1,7 +1,7 @@ moveit_kinematics - 1.0.9 + 1.0.10 Package for all inverse kinematics solvers in MoveIt! Dave Coleman diff --git a/moveit_planners/chomp/chomp_interface/CHANGELOG.rst b/moveit_planners/chomp/chomp_interface/CHANGELOG.rst index ce03904255..52db3e636d 100644 --- a/moveit_planners/chomp/chomp_interface/CHANGELOG.rst +++ b/moveit_planners/chomp/chomp_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package chomp_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ * Use moveit-resources@master (`#2951 `_) diff --git a/moveit_planners/chomp/chomp_interface/package.xml b/moveit_planners/chomp/chomp_interface/package.xml index 58b71fa8af..108e30a6de 100644 --- a/moveit_planners/chomp/chomp_interface/package.xml +++ b/moveit_planners/chomp/chomp_interface/package.xml @@ -2,7 +2,7 @@ moveit_planners_chomp The interface for using CHOMP within MoveIt! - 1.0.9 + 1.0.10 Gil Jones Chittaranjan Srinivas Swaminathan diff --git a/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst b/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst index 992ac7eb1d..bfdb42cd77 100644 --- a/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst +++ b/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package chomp_motion_planner ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_planners/chomp/chomp_motion_planner/package.xml b/moveit_planners/chomp/chomp_motion_planner/package.xml index 36149f9921..39167687f6 100644 --- a/moveit_planners/chomp/chomp_motion_planner/package.xml +++ b/moveit_planners/chomp/chomp_motion_planner/package.xml @@ -2,7 +2,7 @@ chomp_motion_planner chomp_motion_planner - 1.0.9 + 1.0.10 Gil Jones Mrinal Kalakrishnan diff --git a/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst b/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst index 273dff4bfc..1691c93aa6 100644 --- a/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst +++ b/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_chomp_optimizer_adapter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ * Use moveit-resources@master (`#2951 `_) diff --git a/moveit_planners/chomp/chomp_optimizer_adapter/package.xml b/moveit_planners/chomp/chomp_optimizer_adapter/package.xml index cec10ce355..f45420bb20 100644 --- a/moveit_planners/chomp/chomp_optimizer_adapter/package.xml +++ b/moveit_planners/chomp/chomp_optimizer_adapter/package.xml @@ -3,7 +3,7 @@ moveit_chomp_optimizer_adapter MoveIt planning request adapter utilizing chomp for solution optimization - 1.0.9 + 1.0.10 Raghavender Sahdev Raghavender Sahdev MoveIt! Release Team diff --git a/moveit_planners/moveit_planners/CHANGELOG.rst b/moveit_planners/moveit_planners/CHANGELOG.rst index 6b44fb4279..1abc57e84b 100644 --- a/moveit_planners/moveit_planners/CHANGELOG.rst +++ b/moveit_planners/moveit_planners/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_planners ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_planners/moveit_planners/package.xml b/moveit_planners/moveit_planners/package.xml index a7a284473f..c8c2dda08b 100644 --- a/moveit_planners/moveit_planners/package.xml +++ b/moveit_planners/moveit_planners/package.xml @@ -1,6 +1,6 @@ moveit_planners - 1.0.9 + 1.0.10 Metapacakge that installs all available planners for MoveIt Ioan Sucan Sachin Chitta diff --git a/moveit_planners/ompl/CHANGELOG.rst b/moveit_planners/ompl/CHANGELOG.rst index bb9db46d1e..464701093c 100644 --- a/moveit_planners/ompl/CHANGELOG.rst +++ b/moveit_planners/ompl/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_planners_ompl ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_planners/ompl/package.xml b/moveit_planners/ompl/package.xml index 77724f810c..1c8e35d696 100644 --- a/moveit_planners/ompl/package.xml +++ b/moveit_planners/ompl/package.xml @@ -1,6 +1,6 @@ moveit_planners_ompl - 1.0.9 + 1.0.10 MoveIt! interface to OMPL Ioan Sucan diff --git a/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst b/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst index 5c28cb0a31..7e392edd50 100644 --- a/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst +++ b/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package pilz_industrial_motion_planner ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ * Use moveit-resources@master (`#2951 `_) diff --git a/moveit_planners/pilz_industrial_motion_planner/package.xml b/moveit_planners/pilz_industrial_motion_planner/package.xml index 0828d3e5ba..2a747cc3d4 100644 --- a/moveit_planners/pilz_industrial_motion_planner/package.xml +++ b/moveit_planners/pilz_industrial_motion_planner/package.xml @@ -1,7 +1,7 @@ pilz_industrial_motion_planner - 1.0.9 + 1.0.10 MoveIt plugin to generate industrial trajectories PTP, LIN, CIRC and sequences thereof. Alexander Gutenkunst diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst b/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst index eaf146e833..74258516ed 100644 --- a/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package pilz_industrial_motion_planner_testutils ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml b/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml index 4be2eaa152..410cb7f952 100644 --- a/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml @@ -1,7 +1,7 @@ pilz_industrial_motion_planner_testutils - 1.0.9 + 1.0.10 Helper scripts and functionality to test industrial motion generation Alexander Gutenkunst diff --git a/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst b/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst index 1ee86b1677..f225454b20 100644 --- a/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst +++ b/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_controller_manager_example ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_plugins/moveit_controller_manager_example/package.xml b/moveit_plugins/moveit_controller_manager_example/package.xml index 79adebc6a0..ac181c68e8 100644 --- a/moveit_plugins/moveit_controller_manager_example/package.xml +++ b/moveit_plugins/moveit_controller_manager_example/package.xml @@ -1,6 +1,6 @@ moveit_controller_manager_example - 1.0.9 + 1.0.10 An example controller manager plugin for MoveIt. This is not functional code. Ioan Sucan diff --git a/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst b/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst index a562c39152..922d518a85 100644 --- a/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst +++ b/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_fake_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_plugins/moveit_fake_controller_manager/package.xml b/moveit_plugins/moveit_fake_controller_manager/package.xml index 2dde4cbd1e..ac8d14f84e 100644 --- a/moveit_plugins/moveit_fake_controller_manager/package.xml +++ b/moveit_plugins/moveit_fake_controller_manager/package.xml @@ -1,6 +1,6 @@ moveit_fake_controller_manager - 1.0.9 + 1.0.10 A fake controller manager plugin for MoveIt. Ioan Sucan diff --git a/moveit_plugins/moveit_plugins/CHANGELOG.rst b/moveit_plugins/moveit_plugins/CHANGELOG.rst index 859bd7fc19..e50fbe8825 100644 --- a/moveit_plugins/moveit_plugins/CHANGELOG.rst +++ b/moveit_plugins/moveit_plugins/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_plugins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_plugins/moveit_plugins/package.xml b/moveit_plugins/moveit_plugins/package.xml index 428980767a..c0b2b752e9 100644 --- a/moveit_plugins/moveit_plugins/package.xml +++ b/moveit_plugins/moveit_plugins/package.xml @@ -1,6 +1,6 @@ moveit_plugins - 1.0.9 + 1.0.10 Metapackage for MoveIt! plugins. Michael Ferguson diff --git a/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst b/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst index a4a97e8fc8..fa143f6c6c 100644 --- a/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst +++ b/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_control_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_plugins/moveit_ros_control_interface/package.xml b/moveit_plugins/moveit_ros_control_interface/package.xml index bae36c4e41..eebce312b2 100644 --- a/moveit_plugins/moveit_ros_control_interface/package.xml +++ b/moveit_plugins/moveit_ros_control_interface/package.xml @@ -1,7 +1,7 @@ moveit_ros_control_interface - 1.0.9 + 1.0.10 ros_control controller manager interface for MoveIt! Mathias Lüdtke diff --git a/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst b/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst index 43fe248b1c..f71efd0d0e 100644 --- a/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst +++ b/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_simple_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_plugins/moveit_simple_controller_manager/package.xml b/moveit_plugins/moveit_simple_controller_manager/package.xml index 70fec61816..35a81d8a2d 100644 --- a/moveit_plugins/moveit_simple_controller_manager/package.xml +++ b/moveit_plugins/moveit_simple_controller_manager/package.xml @@ -1,6 +1,6 @@ moveit_simple_controller_manager - 1.0.9 + 1.0.10 A generic, simple controller manager plugin for MoveIt. Michael Ferguson diff --git a/moveit_ros/benchmarks/CHANGELOG.rst b/moveit_ros/benchmarks/CHANGELOG.rst index 4d32acdddf..f34733e858 100644 --- a/moveit_ros/benchmarks/CHANGELOG.rst +++ b/moveit_ros/benchmarks/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_benchmarks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ * Provide ``MOVEIT_VERSION_CHECK`` macro (`#2997 `_) diff --git a/moveit_ros/benchmarks/package.xml b/moveit_ros/benchmarks/package.xml index fc06fa83d4..adee56dabf 100644 --- a/moveit_ros/benchmarks/package.xml +++ b/moveit_ros/benchmarks/package.xml @@ -1,6 +1,6 @@ moveit_ros_benchmarks - 1.0.9 + 1.0.10 Enhanced tools for benchmarks in MoveIt! diff --git a/moveit_ros/manipulation/CHANGELOG.rst b/moveit_ros/manipulation/CHANGELOG.rst index 292407f320..4c2279cf3e 100644 --- a/moveit_ros/manipulation/CHANGELOG.rst +++ b/moveit_ros/manipulation/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_manipulation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_ros/manipulation/package.xml b/moveit_ros/manipulation/package.xml index 5dd889ad06..ee3290743f 100644 --- a/moveit_ros/manipulation/package.xml +++ b/moveit_ros/manipulation/package.xml @@ -1,6 +1,6 @@ moveit_ros_manipulation - 1.0.9 + 1.0.10 Components of MoveIt! used for manipulation Ioan Sucan diff --git a/moveit_ros/move_group/CHANGELOG.rst b/moveit_ros/move_group/CHANGELOG.rst index 0a866a4e45..e4bf83e7c8 100644 --- a/moveit_ros/move_group/CHANGELOG.rst +++ b/moveit_ros/move_group/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_move_group ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ * Use moveit-resources@master (`#2951 `_) diff --git a/moveit_ros/move_group/package.xml b/moveit_ros/move_group/package.xml index ff941fd649..ce05c87d8c 100644 --- a/moveit_ros/move_group/package.xml +++ b/moveit_ros/move_group/package.xml @@ -1,6 +1,6 @@ moveit_ros_move_group - 1.0.9 + 1.0.10 The move_group node for MoveIt Ioan Sucan Sachin Chitta diff --git a/moveit_ros/moveit_ros/CHANGELOG.rst b/moveit_ros/moveit_ros/CHANGELOG.rst index 980409e278..64a7252cfe 100644 --- a/moveit_ros/moveit_ros/CHANGELOG.rst +++ b/moveit_ros/moveit_ros/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_ros/moveit_ros/package.xml b/moveit_ros/moveit_ros/package.xml index 178f434aa6..977c54101f 100644 --- a/moveit_ros/moveit_ros/package.xml +++ b/moveit_ros/moveit_ros/package.xml @@ -1,6 +1,6 @@ moveit_ros - 1.0.9 + 1.0.10 Components of MoveIt! that use ROS Ioan Sucan Sachin Chitta diff --git a/moveit_ros/moveit_servo/CHANGELOG.rst b/moveit_ros/moveit_servo/CHANGELOG.rst index ffc24bf0ac..25e3bc92f8 100644 --- a/moveit_ros/moveit_servo/CHANGELOG.rst +++ b/moveit_ros/moveit_servo/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_servo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ * Fix an off-by-one error in servo_calcs.cpp (`#2908 `_) diff --git a/moveit_ros/moveit_servo/package.xml b/moveit_ros/moveit_servo/package.xml index 83ef049f88..f7b600438a 100644 --- a/moveit_ros/moveit_servo/package.xml +++ b/moveit_ros/moveit_servo/package.xml @@ -1,7 +1,7 @@ moveit_servo - 1.0.9 + 1.0.10 Provides real-time manipulator Cartesian and joint servoing. diff --git a/moveit_ros/occupancy_map_monitor/CHANGELOG.rst b/moveit_ros/occupancy_map_monitor/CHANGELOG.rst index fef2b8f446..736531b270 100644 --- a/moveit_ros/occupancy_map_monitor/CHANGELOG.rst +++ b/moveit_ros/occupancy_map_monitor/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_occupancy_map_monitor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_ros/occupancy_map_monitor/package.xml b/moveit_ros/occupancy_map_monitor/package.xml index b7bf082100..4d6e6ecfda 100644 --- a/moveit_ros/occupancy_map_monitor/package.xml +++ b/moveit_ros/occupancy_map_monitor/package.xml @@ -1,7 +1,7 @@ moveit_ros_occupancy_map_monitor - 1.0.9 + 1.0.10 Components of MoveIt! connecting to occupancy map Ioan Sucan diff --git a/moveit_ros/perception/CHANGELOG.rst b/moveit_ros/perception/CHANGELOG.rst index 82df26c6f4..79016a7be7 100644 --- a/moveit_ros/perception/CHANGELOG.rst +++ b/moveit_ros/perception/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_perception ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_ros/perception/package.xml b/moveit_ros/perception/package.xml index 77b7aef540..d8ac81f048 100644 --- a/moveit_ros/perception/package.xml +++ b/moveit_ros/perception/package.xml @@ -1,6 +1,6 @@ moveit_ros_perception - 1.0.9 + 1.0.10 Components of MoveIt! connecting to perception Ioan Sucan diff --git a/moveit_ros/planning/CHANGELOG.rst b/moveit_ros/planning/CHANGELOG.rst index 39197f51aa..9c26cc28e5 100644 --- a/moveit_ros/planning/CHANGELOG.rst +++ b/moveit_ros/planning/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_planning ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ * Use moveit-resources@master (`#2951 `_) diff --git a/moveit_ros/planning/package.xml b/moveit_ros/planning/package.xml index 7610a73024..9d3ad1d707 100644 --- a/moveit_ros/planning/package.xml +++ b/moveit_ros/planning/package.xml @@ -1,7 +1,7 @@ moveit_ros_planning - 1.0.9 + 1.0.10 Planning components of MoveIt! that use ROS Ioan Sucan Sachin Chitta diff --git a/moveit_ros/planning_interface/CHANGELOG.rst b/moveit_ros/planning_interface/CHANGELOG.rst index f4335ba493..5980adc55d 100644 --- a/moveit_ros/planning_interface/CHANGELOG.rst +++ b/moveit_ros/planning_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_planning_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ * Use moveit-resources@master (`#2951 `_) diff --git a/moveit_ros/planning_interface/package.xml b/moveit_ros/planning_interface/package.xml index 471b605057..9638d03042 100644 --- a/moveit_ros/planning_interface/package.xml +++ b/moveit_ros/planning_interface/package.xml @@ -1,6 +1,6 @@ moveit_ros_planning_interface - 1.0.9 + 1.0.10 Components of MoveIt! that offer simpler interfaces to planning and execution Ioan Sucan diff --git a/moveit_ros/robot_interaction/CHANGELOG.rst b/moveit_ros/robot_interaction/CHANGELOG.rst index 2935791cb0..ccc62703c8 100644 --- a/moveit_ros/robot_interaction/CHANGELOG.rst +++ b/moveit_ros/robot_interaction/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_robot_interaction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_ros/robot_interaction/package.xml b/moveit_ros/robot_interaction/package.xml index 7ff055432d..2888e38bc9 100644 --- a/moveit_ros/robot_interaction/package.xml +++ b/moveit_ros/robot_interaction/package.xml @@ -1,6 +1,6 @@ moveit_ros_robot_interaction - 1.0.9 + 1.0.10 Components of MoveIt! that offer interaction via interactive markers Ioan Sucan diff --git a/moveit_ros/visualization/CHANGELOG.rst b/moveit_ros/visualization/CHANGELOG.rst index ce606f252f..0f66d02f8c 100644 --- a/moveit_ros/visualization/CHANGELOG.rst +++ b/moveit_ros/visualization/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_visualization ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ * Move ``MoveItErrorCode`` class to ``moveit_core`` (`#3009 `_) diff --git a/moveit_ros/visualization/package.xml b/moveit_ros/visualization/package.xml index 5a16833431..621fdcbf22 100644 --- a/moveit_ros/visualization/package.xml +++ b/moveit_ros/visualization/package.xml @@ -1,6 +1,6 @@ moveit_ros_visualization - 1.0.9 + 1.0.10 Components of MoveIt! that offer visualization Ioan Sucan diff --git a/moveit_ros/warehouse/CHANGELOG.rst b/moveit_ros/warehouse/CHANGELOG.rst index 824e7b0006..8a266df243 100644 --- a/moveit_ros/warehouse/CHANGELOG.rst +++ b/moveit_ros/warehouse/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_warehouse ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_ros/warehouse/package.xml b/moveit_ros/warehouse/package.xml index 9b06388ee8..88599a6f7f 100644 --- a/moveit_ros/warehouse/package.xml +++ b/moveit_ros/warehouse/package.xml @@ -1,6 +1,6 @@ moveit_ros_warehouse - 1.0.9 + 1.0.10 Components of MoveIt! connecting to MongoDB Ioan Sucan diff --git a/moveit_runtime/CHANGELOG.rst b/moveit_runtime/CHANGELOG.rst index cd30aa37a7..1760c3e0f1 100644 --- a/moveit_runtime/CHANGELOG.rst +++ b/moveit_runtime/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_runtime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ diff --git a/moveit_runtime/package.xml b/moveit_runtime/package.xml index 62d9aaa21b..ad08bcbc33 100644 --- a/moveit_runtime/package.xml +++ b/moveit_runtime/package.xml @@ -1,7 +1,7 @@ moveit_runtime - 1.0.9 + 1.0.10 moveit_runtime meta package contains MoveIt! packages that are essential for its runtime (e.g. running MoveIt! on robots). Isaac I. Y. Saito diff --git a/moveit_setup_assistant/CHANGELOG.rst b/moveit_setup_assistant/CHANGELOG.rst index d9ae36970e..9de844cecd 100644 --- a/moveit_setup_assistant/CHANGELOG.rst +++ b/moveit_setup_assistant/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_setup_assistant ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.10 (2022-03-06) +------------------- + 1.0.9 (2022-01-09) ------------------ * Use moveit-resources@master (`#2951 `_) diff --git a/moveit_setup_assistant/package.xml b/moveit_setup_assistant/package.xml index 1687123e79..38066255cb 100644 --- a/moveit_setup_assistant/package.xml +++ b/moveit_setup_assistant/package.xml @@ -1,6 +1,6 @@ moveit_setup_assistant - 1.0.9 + 1.0.10 Generates a configuration package that makes it easy to use MoveIt! From 183113421a34d82f527a2e26ccca0da12cfa7b62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20G=C3=B6rner?= Date: Wed, 16 Mar 2022 20:37:15 +0100 Subject: [PATCH 169/179] feat(simple_controller_manager): add `max_effort` parameter to GripperCommand action (#2984) (#3091) This commit adds the `max_effort` parameter to the GripperCommand declaration in the `controller_list` (see issue #2956). This value is only used when effort is set in the requested gripper trajectory. Co-authored-by: Rick Staa Co-authored-by: Jafar Abdi --- .../gripper_controller_handle.h | 16 ++++++++++++++-- .../src/moveit_simple_controller_manager.cpp | 5 ++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/gripper_controller_handle.h b/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/gripper_controller_handle.h index 8574dee376..28591f41fa 100644 --- a/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/gripper_controller_handle.h +++ b/moveit_plugins/moveit_simple_controller_manager/include/moveit_simple_controller_manager/gripper_controller_handle.h @@ -52,10 +52,11 @@ class GripperControllerHandle : public ActionBasedControllerHandle(name, ns) , allow_failure_(false) , parallel_jaw_gripper_(false) + , max_effort_(max_effort) { } @@ -111,7 +112,6 @@ class GripperControllerHandle : public ActionBasedControllerHandle idx) + { goal.command.max_effort = trajectory.joint_trajectory.points[tpoint].effort[idx]; + } + else + { + goal.command.max_effort = max_effort_; + } } controller_action_client_->sendGoal(goal, @@ -204,6 +210,12 @@ class GripperControllerHandle : public ActionBasedControllerHandle(name, action_ns, max_effort); if (static_cast(new_handle.get())->isConnected()) { if (controller_list[i].hasMember("parallel")) From 5b6194f8fae49aa8e153684da75f783538176231 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 8 Jul 2022 11:40:43 +0200 Subject: [PATCH 170/179] auto_create_ikfast_moveit_plugin.sh: allow xacro input --- .../scripts/auto_create_ikfast_moveit_plugin.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh b/moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh index b2a07597cc..cd005eeb00 100755 --- a/moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh +++ b/moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh @@ -207,6 +207,11 @@ while true ; do filename=$(basename -- "$INPUT") extension=$(echo "${filename##*.}" | tr '[:upper:]' '[:lower:]') case "$extension" in + xacro) + URDF="$TMP_DIR/${filename%.*}.urdf" + xacro "$INPUT" > "$URDF" + INPUT="$URDF" + ;; urdf) # create .dae from .urdf extract_robot_name "$INPUT" create_dae_file From 0af816eac7e012bef20c6c9d70848be79e95a9a9 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 8 Jul 2022 12:28:29 +0200 Subject: [PATCH 171/179] Fix run_quiet() - Show output on error - Restore both stdout and stderr --- .../auto_create_ikfast_moveit_plugin.sh | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh b/moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh index cd005eeb00..e819fd91fe 100755 --- a/moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh +++ b/moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh @@ -87,23 +87,26 @@ function cleanup { function run_quiet { # When running in quiet mode, save stdout as 3, then redirect stdout to $TMP_DIR/ikfast.log if [ "$QUIET" == "1" ] ; then - local STDOUT=3; - local STDERR=4; - exec 3>&1 1>$TMP_DIR/ifast.log - exec 4>&2 2>$TMP_DIR/ifast.log + local STDOUT=3 + local STDERR=4 + exec 3>&1 1>"$TMP_DIR/ikfast.log" + exec 4>&2 2>&1 fi set +e "$@" ret=$? set -e - if [ $ret != 0 ] ; then - echo "$@\nfailed with exec code $ret:" - cat $TMP_DIR/ifast.log - fi # Restore stdout + stderr exec 1>&${STDOUT:-1} # restore stdout + exec 2>&${STDERR:-2} # restore stderr + + if [ $ret != 0 ] ; then + echo "'$*' failed with exec code $ret:" + test "$QUIET" == "1" && cat "$TMP_DIR/ikfast.log" + fi + return $ret } From b3f9967d5007a4d5cc644f6ec60e7f3f0c5c5e66 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 8 Jul 2022 20:57:40 +0200 Subject: [PATCH 172/179] Fix test_ikfast_plugins.sh - Create panda.urdf using catkin build panda_description - Improve debug output --- .github/workflows/ci.yaml | 1 - .../scripts/auto_create_ikfast_moveit_plugin.sh | 4 ++-- moveit_kinematics/test/test_ikfast_plugins.sh | 12 +++++++++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9d39a57da3..dedda8d0bf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -118,7 +118,6 @@ jobs: - id: ici name: Run industrial_ci uses: ros-industrial/industrial_ci@master - env: ${{ matrix.env }} - name: Upload test artifacts (on failure) uses: actions/upload-artifact@v2 diff --git a/moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh b/moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh index e819fd91fe..055c2f7365 100755 --- a/moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh +++ b/moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh @@ -142,11 +142,11 @@ function extract_robot_name { } function create_dae_file { - echo "Converting urdf to Collada" + echo "Try converting urdf to Collada directly" if ! rosrun collada_urdf urdf_to_collada "$INPUT" "$DAE_FILE" 2> /dev/null ; then # When this failed, run docker + echo "Failed. Converting urdf to Collada (in docker)" build_docker_image - echo "Converting urdf to Collada" cp "$INPUT" "$TMP_DIR/robot.urdf" run_quiet docker run --rm --user $(id -u):$(id -g) -v $TMP_DIR:/input --workdir /input -e HOME=/input \ fixed-openrave:latest rosrun collada_urdf urdf_to_collada robot.urdf robot.dae diff --git a/moveit_kinematics/test/test_ikfast_plugins.sh b/moveit_kinematics/test/test_ikfast_plugins.sh index 17f3102989..817bc11729 100755 --- a/moveit_kinematics/test/test_ikfast_plugins.sh +++ b/moveit_kinematics/test/test_ikfast_plugins.sh @@ -19,16 +19,22 @@ else fi # Clone moveit_resources for URDFs. They are not available before running docker. -git clone -q --depth=1 https://github.com/ros-planning/moveit_resources /tmp/resources -fanuc=/tmp/resources/fanuc_description/urdf/fanuc.urdf -panda=/tmp/resources/panda_description/urdf/panda.urdf +git clone -q --depth=1 https://github.com/ros-planning/moveit_resources /tmp/ros/src/moveit_resources +docker run --rm -v /tmp/ros:/tmp/ros -w /tmp/ros "$DOCKER_IMAGE" bash -c "catkin build --no-status --no-summary --no-deps moveit_resources_panda_description" + +fanuc=/tmp/ros/src/moveit_resources/fanuc_description/urdf/fanuc.urdf +panda=/tmp/ros/src/moveit_resources/panda_description/urdf/panda.urdf export QUIET=${QUIET:=1} # Create ikfast plugins for Fanuc and Panda +echo +echo "Creating IKFast package for Fanuc robot" moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh \ --name fanuc --pkg $PWD/fanuc_ikfast_plugin $fanuc manipulator base_link tool0 +echo +echo "Creating IKFast package for Panda robot" moveit_kinematics/ikfast_kinematics_plugin/scripts/auto_create_ikfast_moveit_plugin.sh \ --name panda --pkg $PWD/panda_ikfast_plugin $panda panda_arm panda_link0 panda_link8 From c6bedee9e188752f2c53400d94f9907a2a318f1a Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 26 Aug 2022 14:08:44 +0200 Subject: [PATCH 173/179] Update pre-commit hooks --- .pre-commit-config.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 39e7d9d60e..f89df73fa0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: # Standard hooks - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.4.0 + rev: v4.3.0 hooks: - id: check-added-large-files - id: check-case-conflict @@ -28,9 +28,11 @@ repos: - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 20.8b1 + rev: 22.6.0 hooks: - id: black + # https://github.com/psf/black/issues/406#issuecomment-1101449515 + args: [ "--skip-string-normalization" ] - repo: https://github.com/Lucas-C/pre-commit-hooks-markup rev: v1.0.1 From 4fccf94c342e7d325121544a31920f5e300afcc6 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 26 Aug 2022 14:19:46 +0200 Subject: [PATCH 174/179] Apply black formatting --- .../src/moveit_commander/move_group.py | 132 +++++++++--------- .../planning_scene_interface.py | 18 +-- .../src/moveit_commander/robot.py | 4 +- 3 files changed, 77 insertions(+), 77 deletions(-) diff --git a/moveit_commander/src/moveit_commander/move_group.py b/moveit_commander/src/moveit_commander/move_group.py index 526c777391..7a7f95a21e 100644 --- a/moveit_commander/src/moveit_commander/move_group.py +++ b/moveit_commander/src/moveit_commander/move_group.py @@ -61,68 +61,68 @@ class MoveGroupCommander(object): def __init__( self, name, robot_description="robot_description", ns="", wait_for_servers=5.0 ): - """ Specify the group name for which to construct this commander instance. Throws an exception if there is an initialization error. """ + """Specify the group name for which to construct this commander instance. Throws an exception if there is an initialization error.""" self._g = _moveit_move_group_interface.MoveGroupInterface( name, robot_description, ns, wait_for_servers ) def get_name(self): - """ Get the name of the group this instance was initialized for """ + """Get the name of the group this instance was initialized for""" return self._g.get_name() def stop(self): - """ Stop the current execution, if any """ + """Stop the current execution, if any""" self._g.stop() def get_active_joints(self): - """ Get the active joints of this group """ + """Get the active joints of this group""" return self._g.get_active_joints() def get_joints(self): - """ Get the joints of this group """ + """Get the joints of this group""" return self._g.get_joints() def get_variable_count(self): - """ Return the number of variables used to parameterize a state in this group (larger or equal to number of DOF)""" + """Return the number of variables used to parameterize a state in this group (larger or equal to number of DOF)""" return self._g.get_variable_count() def has_end_effector_link(self): - """ Check if this group has a link that is considered to be an end effector """ + """Check if this group has a link that is considered to be an end effector""" return len(self._g.get_end_effector_link()) > 0 def get_end_effector_link(self): - """ Get the name of the link that is considered to be an end-effector. Return an empty string if there is no end-effector. """ + """Get the name of the link that is considered to be an end-effector. Return an empty string if there is no end-effector.""" return self._g.get_end_effector_link() def set_end_effector_link(self, link_name): - """ Set the name of the link to be considered as an end effector """ + """Set the name of the link to be considered as an end effector""" if not self._g.set_end_effector_link(link_name): raise MoveItCommanderException("Unable to set end effector link") def get_interface_description(self): - """ Get the description of the planner interface (list of planner ids) """ + """Get the description of the planner interface (list of planner ids)""" desc = PlannerInterfaceDescription() conversions.msg_from_string(desc, self._g.get_interface_description()) return desc def get_pose_reference_frame(self): - """ Get the reference frame assumed for poses of end-effectors """ + """Get the reference frame assumed for poses of end-effectors""" return self._g.get_pose_reference_frame() def set_pose_reference_frame(self, reference_frame): - """ Set the reference frame to assume for poses of end-effectors """ + """Set the reference frame to assume for poses of end-effectors""" self._g.set_pose_reference_frame(reference_frame) def get_planning_frame(self): - """ Get the name of the frame where all planning is performed """ + """Get the name of the frame where all planning is performed""" return self._g.get_planning_frame() def get_current_joint_values(self): - """ Get the current configuration of the group as a list (these are values published on /joint_states) """ + """Get the current configuration of the group as a list (these are values published on /joint_states)""" return self._g.get_current_joint_values() def get_current_pose(self, end_effector_link=""): - """ Get the current pose of the end-effector of the group. Throws an exception if there is not end-effector. """ + """Get the current pose of the end-effector of the group. Throws an exception if there is not end-effector.""" if len(end_effector_link) > 0 or self.has_end_effector_link(): return conversions.list_to_pose_stamped( self._g.get_current_pose(end_effector_link), self.get_planning_frame() @@ -133,7 +133,7 @@ def get_current_pose(self, end_effector_link=""): ) def get_current_rpy(self, end_effector_link=""): - """ Get a list of 3 elements defining the [roll, pitch, yaw] of the end-effector. Throws an exception if there is not end-effector. """ + """Get a list of 3 elements defining the [roll, pitch, yaw] of the end-effector. Throws an exception if there is not end-effector.""" if len(end_effector_link) > 0 or self.has_end_effector_link(): return self._g.get_current_rpy(end_effector_link) else: @@ -179,14 +179,14 @@ def set_start_state(self, msg): self._g.set_start_state(conversions.msg_to_string(msg)) def get_current_state_bounded(self): - """ Get the current state of the robot bounded.""" + """Get the current state of the robot bounded.""" s = RobotState() c_str = self._g.get_current_state_bounded() conversions.msg_from_string(s, c_str) return s def get_current_state(self): - """ Get the current state of the robot.""" + """Get the current state of the robot.""" s = RobotState() c_str = self._g.get_current_state() conversions.msg_from_string(s, c_str) @@ -289,7 +289,7 @@ def set_joint_value_target(self, arg1, arg2=None, arg3=None): ) def set_rpy_target(self, rpy, end_effector_link=""): - """ Specify a target orientation for the end-effector. Any position of the end-effector is acceptable.""" + """Specify a target orientation for the end-effector. Any position of the end-effector is acceptable.""" if len(end_effector_link) > 0 or self.has_end_effector_link(): if len(rpy) == 3: if not self._g.set_rpy_target( @@ -304,7 +304,7 @@ def set_rpy_target(self, rpy, end_effector_link=""): ) def set_orientation_target(self, q, end_effector_link=""): - """ Specify a target orientation for the end-effector. Any position of the end-effector is acceptable.""" + """Specify a target orientation for the end-effector. Any position of the end-effector is acceptable.""" if len(end_effector_link) > 0 or self.has_end_effector_link(): if len(q) == 4: if not self._g.set_orientation_target( @@ -319,7 +319,7 @@ def set_orientation_target(self, q, end_effector_link=""): ) def set_position_target(self, xyz, end_effector_link=""): - """ Specify a target position for the end-effector. Any orientation of the end-effector is acceptable.""" + """Specify a target position for the end-effector. Any orientation of the end-effector is acceptable.""" if len(end_effector_link) > 0 or self.has_end_effector_link(): if not self._g.set_position_target( xyz[0], xyz[1], xyz[2], end_effector_link @@ -331,7 +331,7 @@ def set_position_target(self, xyz, end_effector_link=""): ) def set_pose_target(self, pose, end_effector_link=""): - """ Set the pose of the end-effector, if one is available. The expected input is a Pose message, a PoseStamped message or a list of 6 floats:""" + """Set the pose of the end-effector, if one is available. The expected input is a Pose message, a PoseStamped message or a list of 6 floats:""" """ [x, y, z, rot_x, rot_y, rot_z] or a list of 7 floats [x, y, z, qx, qy, qz, qw] """ if len(end_effector_link) > 0 or self.has_end_effector_link(): ok = False @@ -356,7 +356,7 @@ def set_pose_target(self, pose, end_effector_link=""): ) def set_pose_targets(self, poses, end_effector_link=""): - """ Set the pose of the end-effector, if one is available. The expected input is a list of poses. Each pose can be a Pose message, a list of 6 floats: [x, y, z, rot_x, rot_y, rot_z] or a list of 7 floats [x, y, z, qx, qy, qz, qw] """ + """Set the pose of the end-effector, if one is available. The expected input is a list of poses. Each pose can be a Pose message, a list of 6 floats: [x, y, z, rot_x, rot_y, rot_z] or a list of 7 floats [x, y, z, qx, qy, qz, qw]""" if len(end_effector_link) > 0 or self.has_end_effector_link(): if not self._g.set_pose_targets( [conversions.pose_to_list(p) if type(p) is Pose else p for p in poses], @@ -367,7 +367,7 @@ def set_pose_targets(self, poses, end_effector_link=""): raise MoveItCommanderException("There is no end effector to set poses for") def shift_pose_target(self, axis, value, end_effector_link=""): - """ Get the current pose of the end effector, add value to the corresponding axis (0..5: X, Y, Z, R, P, Y) and set the new pose as the pose target """ + """Get the current pose of the end effector, add value to the corresponding axis (0..5: X, Y, Z, R, P, Y) and set the new pose as the pose target""" if len(end_effector_link) > 0 or self.has_end_effector_link(): pose = self._g.get_current_pose(end_effector_link) # by default we get orientation as a quaternion list @@ -384,23 +384,23 @@ def shift_pose_target(self, axis, value, end_effector_link=""): raise MoveItCommanderException("There is no end effector to set poses for") def clear_pose_target(self, end_effector_link): - """ Clear the pose target for a particular end-effector """ + """Clear the pose target for a particular end-effector""" self._g.clear_pose_target(end_effector_link) def clear_pose_targets(self): - """ Clear all known pose targets """ + """Clear all known pose targets""" self._g.clear_pose_targets() def set_random_target(self): - """ Set a random joint configuration target """ + """Set a random joint configuration target""" self._g.set_random_target() def get_named_targets(self): - """ Get a list of all the names of joint configurations.""" + """Get a list of all the names of joint configurations.""" return self._g.get_named_targets() def set_named_target(self, name): - """ Set a joint configuration by name. The name can be a name previlusy remembered with remember_joint_values() or a configuration specified in the SRDF. """ + """Set a joint configuration by name. The name can be a name previlusy remembered with remember_joint_values() or a configuration specified in the SRDF.""" if not self._g.set_named_target(name): raise MoveItCommanderException( "Unable to set target %s. Is the target within bounds?" % name @@ -411,21 +411,21 @@ def get_named_target_values(self, target): return self._g.get_named_target_values(target) def remember_joint_values(self, name, values=None): - """ Record the specified joint configuration of the group under the specified name. If no values are specified, the current state of the group is recorded. """ + """Record the specified joint configuration of the group under the specified name. If no values are specified, the current state of the group is recorded.""" if values is None: values = self.get_current_joint_values() self._g.remember_joint_values(name, values) def get_remembered_joint_values(self): - """ Get a dictionary that maps names to joint configurations for the group """ + """Get a dictionary that maps names to joint configurations for the group""" return self._g.get_remembered_joint_values() def forget_joint_values(self, name): - """ Forget a stored joint configuration """ + """Forget a stored joint configuration""" self._g.forget_joint_values(name) def get_goal_tolerance(self): - """ Return a tuple of goal tolerances: joint, position and orientation. """ + """Return a tuple of goal tolerances: joint, position and orientation.""" return ( self.get_goal_joint_tolerance(), self.get_goal_position_tolerance(), @@ -433,54 +433,54 @@ def get_goal_tolerance(self): ) def get_goal_joint_tolerance(self): - """ Get the tolerance for achieving a joint goal (distance for each joint variable) """ + """Get the tolerance for achieving a joint goal (distance for each joint variable)""" return self._g.get_goal_joint_tolerance() def get_goal_position_tolerance(self): - """ When moving to a position goal or to a pose goal, the tolerance for the goal position is specified as the radius a sphere around the target origin of the end-effector """ + """When moving to a position goal or to a pose goal, the tolerance for the goal position is specified as the radius a sphere around the target origin of the end-effector""" return self._g.get_goal_position_tolerance() def get_goal_orientation_tolerance(self): - """ When moving to an orientation goal or to a pose goal, the tolerance for the goal orientation is specified as the distance (roll, pitch, yaw) to the target origin of the end-effector """ + """When moving to an orientation goal or to a pose goal, the tolerance for the goal orientation is specified as the distance (roll, pitch, yaw) to the target origin of the end-effector""" return self._g.get_goal_orientation_tolerance() def set_goal_tolerance(self, value): - """ Set the joint, position and orientation goal tolerances simultaneously """ + """Set the joint, position and orientation goal tolerances simultaneously""" self._g.set_goal_tolerance(value) def set_goal_joint_tolerance(self, value): - """ Set the tolerance for a target joint configuration """ + """Set the tolerance for a target joint configuration""" self._g.set_goal_joint_tolerance(value) def set_goal_position_tolerance(self, value): - """ Set the tolerance for a target end-effector position """ + """Set the tolerance for a target end-effector position""" self._g.set_goal_position_tolerance(value) def set_goal_orientation_tolerance(self, value): - """ Set the tolerance for a target end-effector orientation """ + """Set the tolerance for a target end-effector orientation""" self._g.set_goal_orientation_tolerance(value) def allow_looking(self, value): - """ Enable/disable looking around for motion planning """ + """Enable/disable looking around for motion planning""" self._g.allow_looking(value) def allow_replanning(self, value): - """ Enable/disable replanning """ + """Enable/disable replanning""" self._g.allow_replanning(value) def get_known_constraints(self): - """ Get a list of names for the constraints specific for this group, as read from the warehouse """ + """Get a list of names for the constraints specific for this group, as read from the warehouse""" return self._g.get_known_constraints() def get_path_constraints(self): - """ Get the acutal path constraints in form of a moveit_msgs.msgs.Constraints """ + """Get the acutal path constraints in form of a moveit_msgs.msgs.Constraints""" c = Constraints() c_str = self._g.get_path_constraints() conversions.msg_from_string(c, c_str) return c def set_path_constraints(self, value): - """ Specify the path constraints to be used (as read from the database) """ + """Specify the path constraints to be used (as read from the database)""" if value is None: self.clear_path_constraints() else: @@ -492,18 +492,18 @@ def set_path_constraints(self, value): ) def clear_path_constraints(self): - """ Specify that no path constraints are to be used during motion planning """ + """Specify that no path constraints are to be used during motion planning""" self._g.clear_path_constraints() def get_trajectory_constraints(self): - """ Get the actual trajectory constraints in form of a moveit_msgs.msgs.Constraints """ + """Get the actual trajectory constraints in form of a moveit_msgs.msgs.Constraints""" c = Constraints() c_str = self._g.get_trajectory_constraints() conversions.msg_from_string(c, c_str) return c def set_trajectory_constraints(self, value): - """ Specify the trajectory constraints to be used """ + """Specify the trajectory constraints to be used""" if value is None: self.clear_trajectory_constraints() else: @@ -517,35 +517,35 @@ def set_trajectory_constraints(self, value): ) def clear_trajectory_constraints(self): - """ Specify that no trajectory constraints are to be used during motion planning """ + """Specify that no trajectory constraints are to be used during motion planning""" self._g.clear_trajectory_constraints() def set_constraints_database(self, host, port): - """ Specify which database to connect to for loading possible path constraints """ + """Specify which database to connect to for loading possible path constraints""" self._g.set_constraints_database(host, port) def set_planning_time(self, seconds): - """ Specify the amount of time to be used for motion planning. """ + """Specify the amount of time to be used for motion planning.""" self._g.set_planning_time(seconds) def get_planning_time(self): - """ Specify the amount of time to be used for motion planning. """ + """Specify the amount of time to be used for motion planning.""" return self._g.get_planning_time() def set_planner_id(self, planner_id): - """ Specify which planner to use when motion planning """ + """Specify which planner to use when motion planning""" self._g.set_planner_id(planner_id) def get_planner_id(self): - """ Get the current planner_id """ + """Get the current planner_id""" return self._g.get_planner_id() def set_num_planning_attempts(self, num_planning_attempts): - """ Set the number of times the motion plan is to be computed from scratch before the shortest solution is returned. The default value is 1. """ + """Set the number of times the motion plan is to be computed from scratch before the shortest solution is returned. The default value is 1.""" self._g.set_num_planning_attempts(num_planning_attempts) def set_workspace(self, ws): - """ Set the workspace for the robot as either [], [minX, minY, maxX, maxY] or [minX, minY, minZ, maxX, maxY, maxZ] """ + """Set the workspace for the robot as either [], [minX, minY, maxX, maxY] or [minX, minY, minZ, maxX, maxY, maxZ]""" if len(ws) == 0: self._g.set_workspace(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) else: @@ -560,7 +560,7 @@ def set_workspace(self, ws): ) def set_max_velocity_scaling_factor(self, value): - """ Set a scaling factor for optionally reducing the maximum joint velocity. Allowed values are in (0,1]. """ + """Set a scaling factor for optionally reducing the maximum joint velocity. Allowed values are in (0,1].""" if value > 0 and value <= 1: self._g.set_max_velocity_scaling_factor(value) else: @@ -569,7 +569,7 @@ def set_max_velocity_scaling_factor(self, value): ) def set_max_acceleration_scaling_factor(self, value): - """ Set a scaling factor for optionally reducing the maximum joint acceleration. Allowed values are in (0,1]. """ + """Set a scaling factor for optionally reducing the maximum joint acceleration. Allowed values are in (0,1].""" if value > 0 and value <= 1: self._g.set_max_acceleration_scaling_factor(value) else: @@ -578,7 +578,7 @@ def set_max_acceleration_scaling_factor(self, value): ) def go(self, joints=None, wait=True): - """ Set the target of the group and then move the group to the specified target """ + """Set the target of the group and then move the group to the specified target""" if type(joints) is bool: wait = joints joints = None @@ -600,7 +600,7 @@ def go(self, joints=None, wait=True): return self._g.async_move() def plan(self, joints=None): - """ Return a motion plan (a RobotTrajectory) to the set goal state (or specified by the joints argument) """ + """Return a motion plan (a RobotTrajectory) to the set goal state (or specified by the joints argument)""" if type(joints) is JointState: self.set_joint_value_target(joints) @@ -624,7 +624,7 @@ def compute_cartesian_path( avoid_collisions=True, path_constraints=None, ): - """ Compute a sequence of waypoints that make the end-effector move in straight line segments that follow the poses specified as waypoints. Configurations are computed for every eef_step meters; The jump_threshold specifies the maximum distance in configuration space between consecutive points in the resultingpath; Kinematic constraints for the path given by path_constraints will be met for every point along the trajectory, if they are not met, a partial solution will be returned. The return value is a tuple: a fraction of how much of the path was followed, the actual RobotTrajectory. """ + """Compute a sequence of waypoints that make the end-effector move in straight line segments that follow the poses specified as waypoints. Configurations are computed for every eef_step meters; The jump_threshold specifies the maximum distance in configuration space between consecutive points in the resultingpath; Kinematic constraints for the path given by path_constraints will be met for every point along the trajectory, if they are not met, a partial solution will be returned. The return value is a tuple: a fraction of how much of the path was followed, the actual RobotTrajectory.""" if path_constraints: if type(path_constraints) is Constraints: constraints_str = conversions.msg_to_string(path_constraints) @@ -660,11 +660,11 @@ def execute(self, plan_msg, wait=True): return self._g.async_execute(conversions.msg_to_string(plan_msg)) def attach_object(self, object_name, link_name="", touch_links=[]): - """ Given the name of an object existing in the planning scene, attach it to a link. The link used is specified by the second argument. If left unspecified, the end-effector link is used, if one is known. If there is no end-effector link, the first link in the group is used. If no link is identified, failure is reported. True is returned if an attach request was succesfully sent to the move_group node. This does not verify that the attach request also was successfuly applied by move_group.""" + """Given the name of an object existing in the planning scene, attach it to a link. The link used is specified by the second argument. If left unspecified, the end-effector link is used, if one is known. If there is no end-effector link, the first link in the group is used. If no link is identified, failure is reported. True is returned if an attach request was succesfully sent to the move_group node. This does not verify that the attach request also was successfuly applied by move_group.""" return self._g.attach_object(object_name, link_name, touch_links) def detach_object(self, name=""): - """ Given the name of a link, detach the object(s) from that link. If no such link exists, the name is interpreted as an object name. If there is no name specified, an attempt is made to detach all objects attached to any link in the group.""" + """Given the name of a link, detach the object(s) from that link. If no such link exists, the name is interpreted as an object name. If there is no name specified, an attempt is made to detach all objects attached to any link in the group.""" return self._g.detach_object(name) def pick(self, object_name, grasp=[], plan_only=False): @@ -723,7 +723,7 @@ def place(self, object_name, location=None, plan_only=False): return result def set_support_surface_name(self, value): - """ Set the support surface name for a place operation """ + """Set the support surface name for a place operation""" self._g.set_support_surface_name(value) def retime_trajectory( @@ -748,14 +748,14 @@ def retime_trajectory( return traj_out def get_jacobian_matrix(self, joint_values, reference_point=None): - """ Get the jacobian matrix of the group as a list""" + """Get the jacobian matrix of the group as a list""" return self._g.get_jacobian_matrix( joint_values, [0.0, 0.0, 0.0] if reference_point is None else reference_point, ) def enforce_bounds(self, robot_state_msg): - """ Takes a moveit_msgs RobotState and enforces the state bounds, based on the C++ RobotState enforceBounds() """ + """Takes a moveit_msgs RobotState and enforces the state bounds, based on the C++ RobotState enforceBounds()""" s = RobotState() c_str = self._g.enforce_bounds(conversions.msg_to_string(robot_state_msg)) conversions.msg_from_string(s, c_str) diff --git a/moveit_commander/src/moveit_commander/planning_scene_interface.py b/moveit_commander/src/moveit_commander/planning_scene_interface.py index efa16d08ac..acd442e77e 100644 --- a/moveit_commander/src/moveit_commander/planning_scene_interface.py +++ b/moveit_commander/src/moveit_commander/planning_scene_interface.py @@ -65,7 +65,7 @@ class PlanningSceneInterface(object): """ def __init__(self, ns="", synchronous=False, service_timeout=5.0): - """ Create a planning scene interface; it uses both C++ wrapped methods and scene manipulation topics. """ + """Create a planning scene interface; it uses both C++ wrapped methods and scene manipulation topics.""" self._psi = _moveit_planning_scene_interface.PlanningSceneInterface(ns) self._pub_co = rospy.Publisher( @@ -94,31 +94,31 @@ def __submit(self, collision_object, attach=False): self._pub_co.publish(collision_object) def add_object(self, collision_object): - """ Add an object to the planning scene """ + """Add an object to the planning scene""" self.__submit(collision_object, attach=False) def add_sphere(self, name, pose, radius=1): - """ Add a sphere to the planning scene """ + """Add a sphere to the planning scene""" co = self.__make_sphere(name, pose, radius) self.__submit(co, attach=False) def add_cylinder(self, name, pose, height, radius): - """ Add a cylinder to the planning scene """ + """Add a cylinder to the planning scene""" co = self.__make_cylinder(name, pose, height, radius) self.__submit(co, attach=False) def add_mesh(self, name, pose, filename, size=(1, 1, 1)): - """ Add a mesh to the planning scene """ + """Add a mesh to the planning scene""" co = self.__make_mesh(name, pose, filename, size) self.__submit(co, attach=False) def add_box(self, name, pose, size=(1, 1, 1)): - """ Add a box to the planning scene """ + """Add a box to the planning scene""" co = self.__make_box(name, pose, size) self.__submit(co, attach=False) def add_plane(self, name, pose, normal=(0, 0, 1), offset=0): - """ Add a plane to the planning scene """ + """Add a plane to the planning scene""" co = CollisionObject() co.operation = CollisionObject.ADD co.id = name @@ -131,7 +131,7 @@ def add_plane(self, name, pose, normal=(0, 0, 1), offset=0): self.__submit(co, attach=False) def attach_object(self, attached_collision_object): - """ Attach an object in the planning scene """ + """Attach an object in the planning scene""" self.__submit(attached_collision_object, attach=True) def attach_mesh( @@ -162,7 +162,7 @@ def attach_box(self, link, name, pose=None, size=(1, 1, 1), touch_links=[]): self.__submit(aco, attach=True) def clear(self): - """ Remove all objects from the planning scene """ + """Remove all objects from the planning scene""" self.remove_attached_object() self.remove_world_object() diff --git a/moveit_commander/src/moveit_commander/robot.py b/moveit_commander/src/moveit_commander/robot.py index 413f6d1774..7b9b51848e 100644 --- a/moveit_commander/src/moveit_commander/robot.py +++ b/moveit_commander/src/moveit_commander/robot.py @@ -191,7 +191,7 @@ def get_robot_markers(self, *args): return mrkr def get_root_link(self): - """Get the name of the root link of the robot model """ + """Get the name of the root link of the robot model""" return self._r.get_robot_root_link() def get_active_joint_names(self, group=None): @@ -240,7 +240,7 @@ def get_group_names(self): return self._r.get_group_names() def get_current_state(self): - """ Get a RobotState message describing the current state of the robot""" + """Get a RobotState message describing the current state of the robot""" s = RobotState() s.deserialize(self._r.get_current_state()) return s From 2433d8fac6e6eedb0714dc0260393d7611940142 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Thu, 1 Sep 2022 17:38:15 +0200 Subject: [PATCH 175/179] Backport Dockerfile changes (#3201) ... from noetic-devel branch and build docker images via GHA. --- .docker/README.md | 4 +- .../Dockerfile | 4 +- .docker/ci/Dockerfile | 23 ++- .docker/release/Dockerfile | 5 +- .docker/source/Dockerfile | 41 +++-- .dockerignore | 37 ++++ .github/workflows/ci.yaml | 2 +- .github/workflows/docker.yaml | 158 ++++++++++++++++++ 8 files changed, 236 insertions(+), 38 deletions(-) rename .docker/{ci-shadow-fixed => ci-testing}/Dockerfile (83%) create mode 100644 .dockerignore create mode 100644 .github/workflows/docker.yaml diff --git a/.docker/README.md b/.docker/README.md index a0cf726f20..6fb3ce6056 100644 --- a/.docker/README.md +++ b/.docker/README.md @@ -1,3 +1,3 @@ -# MoveIt! Docker Containers +# MoveIt Docker Containers -For more information see [Continuous Integration and Docker](http://moveit.ros.org/documentation/contributing/continuous_integration.html) documentation. +For more information see the pages [Continuous Integration and Docker](http://moveit.ros.org/documentation/contributing/continuous_integration.html) and [Using Docker Containers with MoveIt](https://moveit.ros.org/install/docker/). diff --git a/.docker/ci-shadow-fixed/Dockerfile b/.docker/ci-testing/Dockerfile similarity index 83% rename from .docker/ci-shadow-fixed/Dockerfile rename to .docker/ci-testing/Dockerfile index bc9107c99e..924ff0541d 100644 --- a/.docker/ci-shadow-fixed/Dockerfile +++ b/.docker/ci-testing/Dockerfile @@ -1,8 +1,8 @@ -# moveit/moveit:melodic-ci-shadow-fixed +# moveit/moveit:melodic-ci-testing # Sets up a base image to use for running Continuous Integration on Travis FROM moveit/moveit:melodic-ci -MAINTAINER Dave Coleman dave@picknik.ai +MAINTAINER Robert Haschke rhaschke@techfak.uni-bielefeld.de # Switch to ros-shadow-fixed RUN echo "deb http://packages.ros.org/ros-shadow-fixed/ubuntu `lsb_release -cs` main" | tee /etc/apt/sources.list.d/ros-latest.list diff --git a/.docker/ci/Dockerfile b/.docker/ci/Dockerfile index eee8a028b6..f58fbd81ca 100644 --- a/.docker/ci/Dockerfile +++ b/.docker/ci/Dockerfile @@ -2,32 +2,34 @@ # Sets up a base image to use for running Continuous Integration on Travis FROM ros:melodic-ros-base -MAINTAINER Dave Coleman dave@picknik.ai +MAINTAINER Robert Haschke rhaschke@techfak.uni-bielefeld.de ENV TERM xterm # Setup (temporary) ROS workspace WORKDIR /root/ws_moveit +# Copy MoveIt sources from docker context +COPY . src/moveit + # Commands are combined in single RUN statement with "apt/lists" folder removal to reduce image size # https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#minimize-the-number-of-layers RUN \ # Update apt package list as previous containers clear the cache - apt-get -qq update && \ - apt-get -qq dist-upgrade && \ + apt-get -q update && \ + apt-get -q -y dist-upgrade && \ # # Install some base dependencies - apt-get -qq install --no-install-recommends -y \ + apt-get -q install --no-install-recommends -y \ # Some basic requirements wget git sudo \ # Preferred build tools - python-catkin-tools \ + python$(test "${ROS_DISTRO}" = "noetic" && echo 3)-catkin-tools \ clang clang-format-10 clang-tidy clang-tools \ ccache && \ # - # Download MoveIt source, so that we can fetch all necessary dependencies - wstool init --shallow src https://raw.githubusercontent.com/ros-planning/moveit/${ROS_DISTRO}-devel/.github/workflows/upstream.rosinstall && \ - git clone --depth 1 --branch ${ROS_DISTRO}-devel https://github.com/ros-planning/moveit src/moveit && \ + # Download MoveIt sources, so that we can fetch all necessary dependencies + wstool init --shallow src src/moveit/.github/workflows/upstream.rosinstall && \ git clone --depth 1 --branch ${ROS_DISTRO}-devel https://github.com/ros-planning/moveit_resources src/moveit_resources && \ # # Download all dependencies of MoveIt @@ -38,7 +40,10 @@ RUN \ rm -rf src && \ # # Clear apt-cache to reduce image size - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/* && \ + # Globally disable git security + # https://github.blog/2022-04-12-git-security-vulnerability-announced + git config --global --add safe.directory "*" # Continous Integration Setting ENV IN_DOCKER 1 diff --git a/.docker/release/Dockerfile b/.docker/release/Dockerfile index e06998b1a2..45cc49f311 100644 --- a/.docker/release/Dockerfile +++ b/.docker/release/Dockerfile @@ -1,10 +1,11 @@ # moveit/moveit:melodic-release -# Full debian-based install of MoveIt! using apt-get +# Full debian-based install of MoveIt using apt-get FROM ros:melodic-ros-base MAINTAINER Dave Coleman dave@picknik.ai # Commands are combined in single RUN statement with "apt/lists" folder removal to reduce image size -RUN apt-get update && \ +RUN apt-get update -q && \ + apt-get dist-upgrade -q -y && \ apt-get install -y ros-${ROS_DISTRO}-moveit-* && \ rm -rf /var/lib/apt/lists/* diff --git a/.docker/source/Dockerfile b/.docker/source/Dockerfile index 882eee60fb..3c497d3a66 100644 --- a/.docker/source/Dockerfile +++ b/.docker/source/Dockerfile @@ -1,38 +1,35 @@ +# syntax = docker/dockerfile:1.3 + # moveit/moveit:melodic-source # Downloads the moveit source code and install remaining debian dependencies -FROM moveit/moveit:melodic-ci-shadow-fixed -MAINTAINER Dave Coleman dave@picknik.ai +FROM moveit/moveit:melodic-ci-testing +MAINTAINER Robert Haschke rhaschke@techfak.uni-bielefeld.de +ENV PYTHONIOENCODING UTF-8 +# Export ROS_UNDERLAY for downstream docker containers ENV ROS_UNDERLAY /root/ws_moveit/install -WORKDIR $ROS_UNDERLAY/../src +# Environment variable used in instructions on moveit.ros.org website for running clang-tidy +ENV CATKIN_WS $(realpath $ROS_UNDERLAY/..) +WORKDIR $ROS_UNDERLAY/.. + +# Copy MoveIt sources from docker context +COPY . src/moveit # Commands are combined in single RUN statement with "apt/lists" folder removal to reduce image size # https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#minimize-the-number-of-layers -RUN \ - # Download moveit source so that we can get necessary dependencies - wstool init --shallow . https://raw.githubusercontent.com/ros-planning/moveit/${ROS_DISTRO}-devel/.github/workflows/upstream.rosinstall && \ - git clone --depth 1 --branch ${ROS_DISTRO}-devel https://github.com/ros-planning/moveit && \ - git clone --depth 1 --branch ${ROS_DISTRO}-devel https://github.com/ros-planning/moveit_resources && \ - # - # Update apt package list as cache is cleared in previous container - # Usually upgrading involves a few packages only (if container builds became out-of-sync) - apt-get -qq update && \ - apt-get -qq dist-upgrade && \ +RUN --mount=type=cache,target=/root/.ccache/ \ + # Enable ccache + PATH=/usr/lib/ccache:$PATH && \ + # Fetch required upstream sources for building + wstool init --shallow src src/moveit/.github/workflows/upstream.rosinstall && \ + git clone --depth 1 --branch ${ROS_DISTRO}-devel https://github.com/ros-planning/moveit_resources src/moveit_resources && \ # - rosdep update && \ - rosdep install -y --from-paths . --ignore-src --rosdistro ${ROS_DISTRO} --as-root=apt:false && \ - rm -rf /var/lib/apt/lists/* - -ENV PYTHONIOENCODING UTF-8 -RUN cd .. && \ catkin config --extend /opt/ros/$ROS_DISTRO --install --cmake-args -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON && \ # Status rate is limited so that just enough info is shown to keep Docker from timing out, # but not too much such that the Docker log gets too long (another form of timeout) catkin build --limit-status-rate 0.001 --no-notify && \ + ccache -s && \ # # Update /ros_entrypoint.sh to source our new workspace sed -i "s#/opt/ros/\$ROS_DISTRO/setup.bash#$ROS_UNDERLAY/setup.sh#g" /ros_entrypoint.sh - -# Environment variable used in instructions on moveit.ros.org website for running clang-tidy -ENV CATKIN_WS $(realpath $ROS_UNDERLAY/..) diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..c586edd699 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,37 @@ +# ignore everything +* +# but include these: +!.github/workflows/upstream.rosinstall +!**/package.xml +!**/CATKIN_IGNORE + +# https://github.com/moby/moby/issues/42788 +!moveit_plugins/moveit_plugins/package.xml +!moveit_plugins/moveit_ros_control_interface/package.xml +!moveit_plugins/moveit_simple_controller_manager/package.xml +!moveit_plugins/moveit_fake_controller_manager/package.xml +!moveit_kinematics/package.xml +!moveit_setup_assistant/package.xml +!moveit_core/package.xml +!moveit_commander/package.xml +!moveit_planners/ompl/package.xml +!moveit_planners/chomp/chomp_motion_planner/package.xml +!moveit_planners/chomp/chomp_interface/package.xml +!moveit_planners/chomp/chomp_optimizer_adapter/package.xml +!moveit_planners/pilz_industrial_motion_planner_testutils/package.xml +!moveit_planners/pilz_industrial_motion_planner/package.xml +!moveit_planners/moveit_planners/package.xml +!moveit_runtime/package.xml +!moveit/package.xml +!moveit_ros/warehouse/package.xml +!moveit_ros/moveit_servo/package.xml +!moveit_ros/occupancy_map_monitor/package.xml +!moveit_ros/perception/package.xml +!moveit_ros/move_group/package.xml +!moveit_ros/robot_interaction/package.xml +!moveit_ros/visualization/package.xml +!moveit_ros/manipulation/package.xml +!moveit_ros/planning/package.xml +!moveit_ros/planning_interface/package.xml +!moveit_ros/benchmarks/package.xml +!moveit_ros/moveit_ros/package.xml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index dedda8d0bf..c7ea6520b8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,7 +18,7 @@ jobs: env: - IMAGE: melodic-ci CCOV: true - - IMAGE: melodic-ci-shadow-fixed + - IMAGE: melodic-ci-testing IKFAST_TEST: true CATKIN_LINT: true CLANG_TIDY: pedantic diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml new file mode 100644 index 0000000000..06e1fe7855 --- /dev/null +++ b/.github/workflows/docker.yaml @@ -0,0 +1,158 @@ +name: docker + +on: + schedule: + # 6 AM UTC every Sunday + - cron: "0 6 * * 6" + workflow_dispatch: + push: + branches: + - melodic-devel + +jobs: + release: + runs-on: ubuntu-latest + permissions: + packages: write + contents: read + env: + IMAGE: moveit/moveit:melodic-${{ github.job }} + + steps: + - uses: addnab/docker-run-action@v3 + name: Check for apt updates + continue-on-error: true + id: apt + with: + image: ${{ env.IMAGE }} + run: | + apt-get update + have_updates=$(apt-get --simulate upgrade | grep -q "^0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.$" && echo false || echo true) + echo "::set-output name=no_cache::$have_updates" + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + if: ${{ github.event_name == 'workflow_dispatch' || github.event_name != 'schedule' || steps.apt.outputs.no_cache }} + - name: Login to Container Registry + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and Push + uses: docker/build-push-action@v2 + if: ${{ github.event_name == 'workflow_dispatch' || github.event_name != 'schedule' || steps.apt.outputs.no_cache }} + with: + file: .docker/${{ github.job }}/Dockerfile + push: true + no-cache: ${{ steps.apt.outputs.no_cache || github.event_name == 'workflow_dispatch' }} + cache-from: type=registry,ref=${{ env.IMAGE }} + cache-to: type=inline + tags: ${{ env.IMAGE }} + + ci: + runs-on: ubuntu-latest + permissions: + packages: write + contents: read + env: + IMAGE: moveit/moveit:melodic-${{ github.job }} + + steps: + - uses: addnab/docker-run-action@v3 + name: Check for apt updates + continue-on-error: true + id: apt + with: + image: ${{ env.IMAGE }} + run: | + apt-get update + have_updates=$(apt-get --simulate upgrade | grep -q "^0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.$" && echo false || echo true) + echo "::set-output name=no_cache::$have_updates" + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + if: ${{ github.event_name == 'workflow_dispatch' || github.event_name != 'schedule' || steps.apt.outputs.no_cache }} + - name: Login to Container Registry + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and Push + uses: docker/build-push-action@v2 + if: ${{ github.event_name == 'workflow_dispatch' || github.event_name != 'schedule' || steps.apt.outputs.no_cache }} + with: + file: .docker/${{ github.job }}/Dockerfile + push: true + no-cache: ${{ steps.apt.outputs.no_cache || github.event_name == 'workflow_dispatch' }} + cache-from: type=registry,ref=${{ env.IMAGE }} + cache-to: type=inline + tags: ${{ env.IMAGE }} + + ci-testing: + needs: ci + runs-on: ubuntu-latest + permissions: + packages: write + contents: read + env: + IMAGE: moveit/moveit:melodic-${{ github.job }} + + steps: + - uses: addnab/docker-run-action@v3 + name: Check for apt updates + continue-on-error: true + id: apt + with: + image: ${{ env.IMAGE }} + run: | + apt-get update + have_updates=$(apt-get --simulate upgrade | grep -q "^0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.$" && echo false || echo true) + echo "::set-output name=no_cache::$have_updates" + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + if: ${{ github.event_name == 'workflow_dispatch' || github.event_name != 'schedule' || steps.apt.outputs.no_cache }} + - name: Login to Container Registry + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and Push + uses: docker/build-push-action@v2 + if: ${{ github.event_name == 'workflow_dispatch' || github.event_name != 'schedule' || steps.apt.outputs.no_cache }} + with: + file: .docker/${{ github.job }}/Dockerfile + push: true + no-cache: ${{ steps.apt.outputs.no_cache || github.event_name == 'workflow_dispatch' }} + cache-from: type=registry,ref=${{ env.IMAGE }} + cache-to: type=inline + tags: | + ${{ env.IMAGE }} + moveit/moveit:melodic-ci-shadow-fixed + + source: + needs: ci-testing + runs-on: ubuntu-latest + permissions: + packages: write + contents: read + env: + IMAGE: moveit/moveit:melodic-${{ github.job }} + + steps: + - uses: actions/checkout@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Login to Container Registry + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: "Remove .dockerignore" + run: rm .dockerignore # enforce full source context + - name: Build and Push + uses: docker/build-push-action@v2 + with: + context: . + file: .docker/${{ github.job }}/Dockerfile + push: true + cache-from: type=registry,ref=${{ env.IMAGE }} + cache-to: type=inline + tags: ${{ env.IMAGE }} From c6933ba2722117e2d468755cad93ec93f18052b7 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Fri, 2 Sep 2022 08:11:15 +0200 Subject: [PATCH 176/179] Fix CI: Relax compiler warnings (#3203) --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c7ea6520b8..ff0d62095c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,7 +26,7 @@ jobs: CXXFLAGS: >- -Wall -Wextra -Wwrite-strings -Wunreachable-code -Wpointer-arith -Wredundant-decls -Wno-unused-parameter - ${{ matrix.env.CLANG_TIDY && '-Wno-error=c++17-compat -Wno-error=overloaded-virtual -Wno-error=unused-function' || '' }} + ${{ matrix.env.CLANG_TIDY && '-Wno-c++17-compat -Wno-overloaded-virtual -Wno-unused-function' || '-Wno-unused-but-set-parameter' }} CLANG_TIDY_ARGS: --fix --fix-errors DOCKER_IMAGE: moveit/moveit:${{ matrix.env.IMAGE }} UPSTREAM_WORKSPACE: .github/workflows/upstream.rosinstall From a619a2a163fba05882428c2dfc74057a7b265425 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Sat, 3 Sep 2022 06:02:04 +0200 Subject: [PATCH 177/179] Dockerfile: Update ci-shadow-fixed -> ci-testing --- .docker/ci-testing/Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.docker/ci-testing/Dockerfile b/.docker/ci-testing/Dockerfile index 924ff0541d..2d45c763c9 100644 --- a/.docker/ci-testing/Dockerfile +++ b/.docker/ci-testing/Dockerfile @@ -4,12 +4,12 @@ FROM moveit/moveit:melodic-ci MAINTAINER Robert Haschke rhaschke@techfak.uni-bielefeld.de -# Switch to ros-shadow-fixed -RUN echo "deb http://packages.ros.org/ros-shadow-fixed/ubuntu `lsb_release -cs` main" | tee /etc/apt/sources.list.d/ros-latest.list +# Switch to ros-testing +RUN echo "deb http://packages.ros.org/ros-testing/ubuntu `lsb_release -cs` main" | tee /etc/apt/sources.list.d/ros1-latest.list -# Upgrade packages to ros-shadow-fixed and clean apt-cache within one RUN command +# Upgrade packages to ros-testing and clean apt-cache within one RUN command RUN apt-get -qq update && \ - apt-get -qq dist-upgrade && \ + apt-get -qq -y dist-upgrade && \ # # Clear apt-cache to reduce image size rm -rf /var/lib/apt/lists/* From f736c3ad66667ba8ba1c52cacb8050c5a0de844d Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Sat, 3 Sep 2022 07:21:56 +0200 Subject: [PATCH 178/179] Pass xacro_args to both, urdf and srdf loading (#3200) --- .../src/widgets/start_screen_widget.cpp | 12 ++++-------- .../src/widgets/start_screen_widget.h | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/moveit_setup_assistant/src/widgets/start_screen_widget.cpp b/moveit_setup_assistant/src/widgets/start_screen_widget.cpp index a5534e41a9..4ec835ffc9 100644 --- a/moveit_setup_assistant/src/widgets/start_screen_widget.cpp +++ b/moveit_setup_assistant/src/widgets/start_screen_widget.cpp @@ -395,7 +395,7 @@ bool StartScreenWidget::loadExistingFiles() QApplication::processEvents(); // Load the SRDF - if (!loadSRDFFile(config_data_->srdf_path_)) + if (!loadSRDFFile(config_data_->srdf_path_, config_data_->xacro_args_)) return false; // error occured // Progress Indicator @@ -546,9 +546,7 @@ bool StartScreenWidget::loadNewFiles() // ****************************************************************************************** bool StartScreenWidget::loadURDFFile(const std::string& urdf_file_path, const std::string& xacro_args) { - const std::vector vec_xacro_args = { xacro_args }; - - if (!rdf_loader::RDFLoader::loadXmlFileToString(config_data_->urdf_string_, urdf_file_path, vec_xacro_args)) + if (!rdf_loader::RDFLoader::loadXmlFileToString(config_data_->urdf_string_, urdf_file_path, { xacro_args })) { QMessageBox::warning(this, "Error Loading Files", QString("URDF/COLLADA file not found: ").append(urdf_file_path.c_str())); @@ -592,12 +590,10 @@ bool StartScreenWidget::loadURDFFile(const std::string& urdf_file_path, const st // ****************************************************************************************** // Load SRDF File to Parameter Server // ****************************************************************************************** -bool StartScreenWidget::loadSRDFFile(const std::string& srdf_file_path) +bool StartScreenWidget::loadSRDFFile(const std::string& srdf_file_path, const std::string& xacro_args) { - const std::vector xacro_args; - std::string srdf_string; - if (!rdf_loader::RDFLoader::loadXmlFileToString(srdf_string, srdf_file_path, xacro_args)) + if (!rdf_loader::RDFLoader::loadXmlFileToString(srdf_string, srdf_file_path, { xacro_args })) { QMessageBox::warning(this, "Error Loading Files", QString("SRDF file not found: ").append(srdf_file_path.c_str())); return false; diff --git a/moveit_setup_assistant/src/widgets/start_screen_widget.h b/moveit_setup_assistant/src/widgets/start_screen_widget.h index 9b5f28e8c6..293c9e5c71 100644 --- a/moveit_setup_assistant/src/widgets/start_screen_widget.h +++ b/moveit_setup_assistant/src/widgets/start_screen_widget.h @@ -147,7 +147,7 @@ private Q_SLOTS: bool loadURDFFile(const std::string& urdf_file_path, const std::string& xacro_args); /// Load SRDF File - bool loadSRDFFile(const std::string& srdf_file_path); + bool loadSRDFFile(const std::string& srdf_file_path, const std::string& xacro_args); /// Put SRDF File on Parameter Server bool setSRDFFile(const std::string& srdf_string); From 1fbb2c4c555fe59cb316fea184760468aa702d66 Mon Sep 17 00:00:00 2001 From: Robert Haschke Date: Tue, 13 Sep 2022 08:04:09 +0200 Subject: [PATCH 179/179] 1.0.11 --- moveit/CHANGELOG.rst | 3 +++ moveit/package.xml | 2 +- moveit_commander/CHANGELOG.rst | 3 +++ moveit_commander/package.xml | 2 +- moveit_core/CHANGELOG.rst | 3 +++ moveit_core/package.xml | 2 +- moveit_kinematics/CHANGELOG.rst | 3 +++ moveit_kinematics/package.xml | 2 +- moveit_planners/chomp/chomp_interface/CHANGELOG.rst | 3 +++ moveit_planners/chomp/chomp_interface/package.xml | 2 +- moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst | 3 +++ moveit_planners/chomp/chomp_motion_planner/package.xml | 2 +- moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst | 3 +++ moveit_planners/chomp/chomp_optimizer_adapter/package.xml | 2 +- moveit_planners/moveit_planners/CHANGELOG.rst | 3 +++ moveit_planners/moveit_planners/package.xml | 2 +- moveit_planners/ompl/CHANGELOG.rst | 3 +++ moveit_planners/ompl/package.xml | 2 +- moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst | 3 +++ moveit_planners/pilz_industrial_motion_planner/package.xml | 2 +- .../pilz_industrial_motion_planner_testutils/CHANGELOG.rst | 3 +++ .../pilz_industrial_motion_planner_testutils/package.xml | 2 +- .../moveit_controller_manager_example/CHANGELOG.rst | 3 +++ moveit_plugins/moveit_controller_manager_example/package.xml | 2 +- moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst | 3 +++ moveit_plugins/moveit_fake_controller_manager/package.xml | 2 +- moveit_plugins/moveit_plugins/CHANGELOG.rst | 3 +++ moveit_plugins/moveit_plugins/package.xml | 2 +- moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst | 3 +++ moveit_plugins/moveit_ros_control_interface/package.xml | 2 +- .../moveit_simple_controller_manager/CHANGELOG.rst | 5 +++++ moveit_plugins/moveit_simple_controller_manager/package.xml | 2 +- moveit_ros/benchmarks/CHANGELOG.rst | 3 +++ moveit_ros/benchmarks/package.xml | 2 +- moveit_ros/manipulation/CHANGELOG.rst | 3 +++ moveit_ros/manipulation/package.xml | 2 +- moveit_ros/move_group/CHANGELOG.rst | 3 +++ moveit_ros/move_group/package.xml | 2 +- moveit_ros/moveit_ros/CHANGELOG.rst | 3 +++ moveit_ros/moveit_ros/package.xml | 2 +- moveit_ros/moveit_servo/CHANGELOG.rst | 3 +++ moveit_ros/moveit_servo/package.xml | 2 +- moveit_ros/occupancy_map_monitor/CHANGELOG.rst | 3 +++ moveit_ros/occupancy_map_monitor/package.xml | 2 +- moveit_ros/perception/CHANGELOG.rst | 3 +++ moveit_ros/perception/package.xml | 2 +- moveit_ros/planning/CHANGELOG.rst | 3 +++ moveit_ros/planning/package.xml | 2 +- moveit_ros/planning_interface/CHANGELOG.rst | 3 +++ moveit_ros/planning_interface/package.xml | 2 +- moveit_ros/robot_interaction/CHANGELOG.rst | 3 +++ moveit_ros/robot_interaction/package.xml | 2 +- moveit_ros/visualization/CHANGELOG.rst | 3 +++ moveit_ros/visualization/package.xml | 2 +- moveit_ros/warehouse/CHANGELOG.rst | 3 +++ moveit_ros/warehouse/package.xml | 2 +- moveit_runtime/CHANGELOG.rst | 3 +++ moveit_runtime/package.xml | 2 +- moveit_setup_assistant/CHANGELOG.rst | 5 +++++ moveit_setup_assistant/package.xml | 2 +- 60 files changed, 124 insertions(+), 30 deletions(-) diff --git a/moveit/CHANGELOG.rst b/moveit/CHANGELOG.rst index df87700960..b5be0b191a 100644 --- a/moveit/CHANGELOG.rst +++ b/moveit/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit/package.xml b/moveit/package.xml index 22a3c62668..6a29c51f85 100644 --- a/moveit/package.xml +++ b/moveit/package.xml @@ -1,7 +1,7 @@ moveit - 1.0.10 + 1.0.11 Meta package that contains all essential package of MoveIt!. Until Summer 2016 MoveIt! had been developed over multiple repositories, where developers' usability and maintenance effort was non-trivial. See the detailed discussion for the merge of several repositories. Dave Coleman Michael Ferguson diff --git a/moveit_commander/CHANGELOG.rst b/moveit_commander/CHANGELOG.rst index 74b45f81fb..901128c64f 100644 --- a/moveit_commander/CHANGELOG.rst +++ b/moveit_commander/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_commander ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_commander/package.xml b/moveit_commander/package.xml index bcc2040290..5d7e5c2312 100644 --- a/moveit_commander/package.xml +++ b/moveit_commander/package.xml @@ -1,6 +1,6 @@ moveit_commander - 1.0.10 + 1.0.11 Python interfaces to MoveIt Ioan Sucan diff --git a/moveit_core/CHANGELOG.rst b/moveit_core/CHANGELOG.rst index c034853f35..b133b5cc0c 100644 --- a/moveit_core/CHANGELOG.rst +++ b/moveit_core/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_core ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- * Add Ptr definitions for TimeParameterization classes (`#3078 `_) diff --git a/moveit_core/package.xml b/moveit_core/package.xml index 6ea144fa84..63df6e1741 100644 --- a/moveit_core/package.xml +++ b/moveit_core/package.xml @@ -1,6 +1,6 @@ moveit_core - 1.0.10 + 1.0.11 Core libraries used by MoveIt! Ioan Sucan Sachin Chitta diff --git a/moveit_kinematics/CHANGELOG.rst b/moveit_kinematics/CHANGELOG.rst index bf7edba9b8..d99b8e9f99 100644 --- a/moveit_kinematics/CHANGELOG.rst +++ b/moveit_kinematics/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_kinematics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_kinematics/package.xml b/moveit_kinematics/package.xml index 07af8fca3a..d61570684e 100644 --- a/moveit_kinematics/package.xml +++ b/moveit_kinematics/package.xml @@ -1,7 +1,7 @@ moveit_kinematics - 1.0.10 + 1.0.11 Package for all inverse kinematics solvers in MoveIt! Dave Coleman diff --git a/moveit_planners/chomp/chomp_interface/CHANGELOG.rst b/moveit_planners/chomp/chomp_interface/CHANGELOG.rst index 52db3e636d..7677393080 100644 --- a/moveit_planners/chomp/chomp_interface/CHANGELOG.rst +++ b/moveit_planners/chomp/chomp_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package chomp_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_planners/chomp/chomp_interface/package.xml b/moveit_planners/chomp/chomp_interface/package.xml index 108e30a6de..e0db0dcc9f 100644 --- a/moveit_planners/chomp/chomp_interface/package.xml +++ b/moveit_planners/chomp/chomp_interface/package.xml @@ -2,7 +2,7 @@ moveit_planners_chomp The interface for using CHOMP within MoveIt! - 1.0.10 + 1.0.11 Gil Jones Chittaranjan Srinivas Swaminathan diff --git a/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst b/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst index bfdb42cd77..b6053babee 100644 --- a/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst +++ b/moveit_planners/chomp/chomp_motion_planner/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package chomp_motion_planner ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_planners/chomp/chomp_motion_planner/package.xml b/moveit_planners/chomp/chomp_motion_planner/package.xml index 39167687f6..37e025c910 100644 --- a/moveit_planners/chomp/chomp_motion_planner/package.xml +++ b/moveit_planners/chomp/chomp_motion_planner/package.xml @@ -2,7 +2,7 @@ chomp_motion_planner chomp_motion_planner - 1.0.10 + 1.0.11 Gil Jones Mrinal Kalakrishnan diff --git a/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst b/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst index 1691c93aa6..57fa3d2e53 100644 --- a/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst +++ b/moveit_planners/chomp/chomp_optimizer_adapter/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_chomp_optimizer_adapter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_planners/chomp/chomp_optimizer_adapter/package.xml b/moveit_planners/chomp/chomp_optimizer_adapter/package.xml index f45420bb20..45cfdd3c9c 100644 --- a/moveit_planners/chomp/chomp_optimizer_adapter/package.xml +++ b/moveit_planners/chomp/chomp_optimizer_adapter/package.xml @@ -3,7 +3,7 @@ moveit_chomp_optimizer_adapter MoveIt planning request adapter utilizing chomp for solution optimization - 1.0.10 + 1.0.11 Raghavender Sahdev Raghavender Sahdev MoveIt! Release Team diff --git a/moveit_planners/moveit_planners/CHANGELOG.rst b/moveit_planners/moveit_planners/CHANGELOG.rst index 1abc57e84b..eaf85c1ad9 100644 --- a/moveit_planners/moveit_planners/CHANGELOG.rst +++ b/moveit_planners/moveit_planners/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_planners ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_planners/moveit_planners/package.xml b/moveit_planners/moveit_planners/package.xml index c8c2dda08b..efc27a442b 100644 --- a/moveit_planners/moveit_planners/package.xml +++ b/moveit_planners/moveit_planners/package.xml @@ -1,6 +1,6 @@ moveit_planners - 1.0.10 + 1.0.11 Metapacakge that installs all available planners for MoveIt Ioan Sucan Sachin Chitta diff --git a/moveit_planners/ompl/CHANGELOG.rst b/moveit_planners/ompl/CHANGELOG.rst index 464701093c..1149aab6ea 100644 --- a/moveit_planners/ompl/CHANGELOG.rst +++ b/moveit_planners/ompl/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_planners_ompl ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_planners/ompl/package.xml b/moveit_planners/ompl/package.xml index 1c8e35d696..3274053fcb 100644 --- a/moveit_planners/ompl/package.xml +++ b/moveit_planners/ompl/package.xml @@ -1,6 +1,6 @@ moveit_planners_ompl - 1.0.10 + 1.0.11 MoveIt! interface to OMPL Ioan Sucan diff --git a/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst b/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst index 7e392edd50..44e3339ccd 100644 --- a/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst +++ b/moveit_planners/pilz_industrial_motion_planner/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package pilz_industrial_motion_planner ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_planners/pilz_industrial_motion_planner/package.xml b/moveit_planners/pilz_industrial_motion_planner/package.xml index 2a747cc3d4..1c44de0024 100644 --- a/moveit_planners/pilz_industrial_motion_planner/package.xml +++ b/moveit_planners/pilz_industrial_motion_planner/package.xml @@ -1,7 +1,7 @@ pilz_industrial_motion_planner - 1.0.10 + 1.0.11 MoveIt plugin to generate industrial trajectories PTP, LIN, CIRC and sequences thereof. Alexander Gutenkunst diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst b/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst index 74258516ed..041f9ad3a5 100644 --- a/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package pilz_industrial_motion_planner_testutils ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml b/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml index 410cb7f952..b12152ff71 100644 --- a/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml +++ b/moveit_planners/pilz_industrial_motion_planner_testutils/package.xml @@ -1,7 +1,7 @@ pilz_industrial_motion_planner_testutils - 1.0.10 + 1.0.11 Helper scripts and functionality to test industrial motion generation Alexander Gutenkunst diff --git a/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst b/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst index f225454b20..69c2051535 100644 --- a/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst +++ b/moveit_plugins/moveit_controller_manager_example/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_controller_manager_example ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_plugins/moveit_controller_manager_example/package.xml b/moveit_plugins/moveit_controller_manager_example/package.xml index ac181c68e8..5968662397 100644 --- a/moveit_plugins/moveit_controller_manager_example/package.xml +++ b/moveit_plugins/moveit_controller_manager_example/package.xml @@ -1,6 +1,6 @@ moveit_controller_manager_example - 1.0.10 + 1.0.11 An example controller manager plugin for MoveIt. This is not functional code. Ioan Sucan diff --git a/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst b/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst index 922d518a85..48f9fd0b48 100644 --- a/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst +++ b/moveit_plugins/moveit_fake_controller_manager/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_fake_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_plugins/moveit_fake_controller_manager/package.xml b/moveit_plugins/moveit_fake_controller_manager/package.xml index ac8d14f84e..fcb23cde8a 100644 --- a/moveit_plugins/moveit_fake_controller_manager/package.xml +++ b/moveit_plugins/moveit_fake_controller_manager/package.xml @@ -1,6 +1,6 @@ moveit_fake_controller_manager - 1.0.10 + 1.0.11 A fake controller manager plugin for MoveIt. Ioan Sucan diff --git a/moveit_plugins/moveit_plugins/CHANGELOG.rst b/moveit_plugins/moveit_plugins/CHANGELOG.rst index e50fbe8825..6a7f624049 100644 --- a/moveit_plugins/moveit_plugins/CHANGELOG.rst +++ b/moveit_plugins/moveit_plugins/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_plugins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_plugins/moveit_plugins/package.xml b/moveit_plugins/moveit_plugins/package.xml index c0b2b752e9..8f4684b61d 100644 --- a/moveit_plugins/moveit_plugins/package.xml +++ b/moveit_plugins/moveit_plugins/package.xml @@ -1,6 +1,6 @@ moveit_plugins - 1.0.10 + 1.0.11 Metapackage for MoveIt! plugins. Michael Ferguson diff --git a/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst b/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst index fa143f6c6c..ebfca2e474 100644 --- a/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst +++ b/moveit_plugins/moveit_ros_control_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_control_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_plugins/moveit_ros_control_interface/package.xml b/moveit_plugins/moveit_ros_control_interface/package.xml index eebce312b2..7107b3ab61 100644 --- a/moveit_plugins/moveit_ros_control_interface/package.xml +++ b/moveit_plugins/moveit_ros_control_interface/package.xml @@ -1,7 +1,7 @@ moveit_ros_control_interface - 1.0.10 + 1.0.11 ros_control controller manager interface for MoveIt! Mathias Lüdtke diff --git a/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst b/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst index f71efd0d0e..22cdf14996 100644 --- a/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst +++ b/moveit_plugins/moveit_simple_controller_manager/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_simple_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- +* feat(simple_controller_manager): add `max_effort` parameter to GripperCommand action (`#2984 `_) (`#3091 `_) +* Contributors: Michael Görner, Rick Staa + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_plugins/moveit_simple_controller_manager/package.xml b/moveit_plugins/moveit_simple_controller_manager/package.xml index 35a81d8a2d..5fef0b8e79 100644 --- a/moveit_plugins/moveit_simple_controller_manager/package.xml +++ b/moveit_plugins/moveit_simple_controller_manager/package.xml @@ -1,6 +1,6 @@ moveit_simple_controller_manager - 1.0.10 + 1.0.11 A generic, simple controller manager plugin for MoveIt. Michael Ferguson diff --git a/moveit_ros/benchmarks/CHANGELOG.rst b/moveit_ros/benchmarks/CHANGELOG.rst index f34733e858..f76c7649ac 100644 --- a/moveit_ros/benchmarks/CHANGELOG.rst +++ b/moveit_ros/benchmarks/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_benchmarks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_ros/benchmarks/package.xml b/moveit_ros/benchmarks/package.xml index adee56dabf..8318607fc2 100644 --- a/moveit_ros/benchmarks/package.xml +++ b/moveit_ros/benchmarks/package.xml @@ -1,6 +1,6 @@ moveit_ros_benchmarks - 1.0.10 + 1.0.11 Enhanced tools for benchmarks in MoveIt! diff --git a/moveit_ros/manipulation/CHANGELOG.rst b/moveit_ros/manipulation/CHANGELOG.rst index 4c2279cf3e..cd48a2d81b 100644 --- a/moveit_ros/manipulation/CHANGELOG.rst +++ b/moveit_ros/manipulation/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_manipulation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_ros/manipulation/package.xml b/moveit_ros/manipulation/package.xml index ee3290743f..89dd4ed44f 100644 --- a/moveit_ros/manipulation/package.xml +++ b/moveit_ros/manipulation/package.xml @@ -1,6 +1,6 @@ moveit_ros_manipulation - 1.0.10 + 1.0.11 Components of MoveIt! used for manipulation Ioan Sucan diff --git a/moveit_ros/move_group/CHANGELOG.rst b/moveit_ros/move_group/CHANGELOG.rst index e4bf83e7c8..5f83f5feee 100644 --- a/moveit_ros/move_group/CHANGELOG.rst +++ b/moveit_ros/move_group/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_move_group ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_ros/move_group/package.xml b/moveit_ros/move_group/package.xml index ce05c87d8c..8b6b938750 100644 --- a/moveit_ros/move_group/package.xml +++ b/moveit_ros/move_group/package.xml @@ -1,6 +1,6 @@ moveit_ros_move_group - 1.0.10 + 1.0.11 The move_group node for MoveIt Ioan Sucan Sachin Chitta diff --git a/moveit_ros/moveit_ros/CHANGELOG.rst b/moveit_ros/moveit_ros/CHANGELOG.rst index 64a7252cfe..d584285c04 100644 --- a/moveit_ros/moveit_ros/CHANGELOG.rst +++ b/moveit_ros/moveit_ros/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_ros/moveit_ros/package.xml b/moveit_ros/moveit_ros/package.xml index 977c54101f..908c4f8f13 100644 --- a/moveit_ros/moveit_ros/package.xml +++ b/moveit_ros/moveit_ros/package.xml @@ -1,6 +1,6 @@ moveit_ros - 1.0.10 + 1.0.11 Components of MoveIt! that use ROS Ioan Sucan Sachin Chitta diff --git a/moveit_ros/moveit_servo/CHANGELOG.rst b/moveit_ros/moveit_servo/CHANGELOG.rst index 25e3bc92f8..b7b2faee6b 100644 --- a/moveit_ros/moveit_servo/CHANGELOG.rst +++ b/moveit_ros/moveit_servo/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_servo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_ros/moveit_servo/package.xml b/moveit_ros/moveit_servo/package.xml index f7b600438a..0170c72593 100644 --- a/moveit_ros/moveit_servo/package.xml +++ b/moveit_ros/moveit_servo/package.xml @@ -1,7 +1,7 @@ moveit_servo - 1.0.10 + 1.0.11 Provides real-time manipulator Cartesian and joint servoing. diff --git a/moveit_ros/occupancy_map_monitor/CHANGELOG.rst b/moveit_ros/occupancy_map_monitor/CHANGELOG.rst index 736531b270..7c777d91b1 100644 --- a/moveit_ros/occupancy_map_monitor/CHANGELOG.rst +++ b/moveit_ros/occupancy_map_monitor/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_occupancy_map_monitor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_ros/occupancy_map_monitor/package.xml b/moveit_ros/occupancy_map_monitor/package.xml index 4d6e6ecfda..6ee9808645 100644 --- a/moveit_ros/occupancy_map_monitor/package.xml +++ b/moveit_ros/occupancy_map_monitor/package.xml @@ -1,7 +1,7 @@ moveit_ros_occupancy_map_monitor - 1.0.10 + 1.0.11 Components of MoveIt! connecting to occupancy map Ioan Sucan diff --git a/moveit_ros/perception/CHANGELOG.rst b/moveit_ros/perception/CHANGELOG.rst index 79016a7be7..6c701852c9 100644 --- a/moveit_ros/perception/CHANGELOG.rst +++ b/moveit_ros/perception/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_perception ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_ros/perception/package.xml b/moveit_ros/perception/package.xml index d8ac81f048..5c1ed4ccc9 100644 --- a/moveit_ros/perception/package.xml +++ b/moveit_ros/perception/package.xml @@ -1,6 +1,6 @@ moveit_ros_perception - 1.0.10 + 1.0.11 Components of MoveIt! connecting to perception Ioan Sucan diff --git a/moveit_ros/planning/CHANGELOG.rst b/moveit_ros/planning/CHANGELOG.rst index 9c26cc28e5..7b1340540c 100644 --- a/moveit_ros/planning/CHANGELOG.rst +++ b/moveit_ros/planning/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_planning ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_ros/planning/package.xml b/moveit_ros/planning/package.xml index 9d3ad1d707..9cec2ce55d 100644 --- a/moveit_ros/planning/package.xml +++ b/moveit_ros/planning/package.xml @@ -1,7 +1,7 @@ moveit_ros_planning - 1.0.10 + 1.0.11 Planning components of MoveIt! that use ROS Ioan Sucan Sachin Chitta diff --git a/moveit_ros/planning_interface/CHANGELOG.rst b/moveit_ros/planning_interface/CHANGELOG.rst index 5980adc55d..1dacff1b6a 100644 --- a/moveit_ros/planning_interface/CHANGELOG.rst +++ b/moveit_ros/planning_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_planning_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_ros/planning_interface/package.xml b/moveit_ros/planning_interface/package.xml index 9638d03042..44532a43da 100644 --- a/moveit_ros/planning_interface/package.xml +++ b/moveit_ros/planning_interface/package.xml @@ -1,6 +1,6 @@ moveit_ros_planning_interface - 1.0.10 + 1.0.11 Components of MoveIt! that offer simpler interfaces to planning and execution Ioan Sucan diff --git a/moveit_ros/robot_interaction/CHANGELOG.rst b/moveit_ros/robot_interaction/CHANGELOG.rst index ccc62703c8..0fbd86179f 100644 --- a/moveit_ros/robot_interaction/CHANGELOG.rst +++ b/moveit_ros/robot_interaction/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_robot_interaction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_ros/robot_interaction/package.xml b/moveit_ros/robot_interaction/package.xml index 2888e38bc9..28a50e62d2 100644 --- a/moveit_ros/robot_interaction/package.xml +++ b/moveit_ros/robot_interaction/package.xml @@ -1,6 +1,6 @@ moveit_ros_robot_interaction - 1.0.10 + 1.0.11 Components of MoveIt! that offer interaction via interactive markers Ioan Sucan diff --git a/moveit_ros/visualization/CHANGELOG.rst b/moveit_ros/visualization/CHANGELOG.rst index 0f66d02f8c..b8040cabba 100644 --- a/moveit_ros/visualization/CHANGELOG.rst +++ b/moveit_ros/visualization/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_visualization ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_ros/visualization/package.xml b/moveit_ros/visualization/package.xml index 621fdcbf22..389d71eac2 100644 --- a/moveit_ros/visualization/package.xml +++ b/moveit_ros/visualization/package.xml @@ -1,6 +1,6 @@ moveit_ros_visualization - 1.0.10 + 1.0.11 Components of MoveIt! that offer visualization Ioan Sucan diff --git a/moveit_ros/warehouse/CHANGELOG.rst b/moveit_ros/warehouse/CHANGELOG.rst index 8a266df243..43a8f11a57 100644 --- a/moveit_ros/warehouse/CHANGELOG.rst +++ b/moveit_ros/warehouse/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_ros_warehouse ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_ros/warehouse/package.xml b/moveit_ros/warehouse/package.xml index 88599a6f7f..413b58a77f 100644 --- a/moveit_ros/warehouse/package.xml +++ b/moveit_ros/warehouse/package.xml @@ -1,6 +1,6 @@ moveit_ros_warehouse - 1.0.10 + 1.0.11 Components of MoveIt! connecting to MongoDB Ioan Sucan diff --git a/moveit_runtime/CHANGELOG.rst b/moveit_runtime/CHANGELOG.rst index 1760c3e0f1..26cab1162b 100644 --- a/moveit_runtime/CHANGELOG.rst +++ b/moveit_runtime/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package moveit_runtime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_runtime/package.xml b/moveit_runtime/package.xml index ad08bcbc33..dfd95e22fe 100644 --- a/moveit_runtime/package.xml +++ b/moveit_runtime/package.xml @@ -1,7 +1,7 @@ moveit_runtime - 1.0.10 + 1.0.11 moveit_runtime meta package contains MoveIt! packages that are essential for its runtime (e.g. running MoveIt! on robots). Isaac I. Y. Saito diff --git a/moveit_setup_assistant/CHANGELOG.rst b/moveit_setup_assistant/CHANGELOG.rst index 9de844cecd..7fb5cac8bf 100644 --- a/moveit_setup_assistant/CHANGELOG.rst +++ b/moveit_setup_assistant/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package moveit_setup_assistant ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +1.0.11 (2022-09-13) +------------------- +* Pass xacro_args to both, urdf and srdf loading (`#3200 `_) +* Contributors: Robert Haschke + 1.0.10 (2022-03-06) ------------------- diff --git a/moveit_setup_assistant/package.xml b/moveit_setup_assistant/package.xml index 38066255cb..06009bdb34 100644 --- a/moveit_setup_assistant/package.xml +++ b/moveit_setup_assistant/package.xml @@ -1,6 +1,6 @@ moveit_setup_assistant - 1.0.10 + 1.0.11 Generates a configuration package that makes it easy to use MoveIt!
  • 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + t + v + + + 0 + joint 1 (lead axis) + joint 2 + joint 3 + acceleration + constant + deceleration + + max v + max acc + max dec + + + + + + t + v + + + 0 + joint 1 (lead axis) + joint 2 + joint 3 + acceleration + constant + deceleration + + max v + max acc + max dec + + + + + + + lead axis + + brake + + + t + v + + + 0 + acc + constant + deceleration + + max v + max acc + max dec + + (1) + (2) + (3) + + diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/figure/ptp_movement_1.png b/moveit_planners/pilz_industrial_motion_planner/doc/figure/ptp_movement_1.png new file mode 100644 index 0000000000000000000000000000000000000000..7226ec5e6fff499fc02d1ee3eeb3607cbedbc34d GIT binary patch literal 100740 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%0DS?-^=p_UNdo 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 J``*Ln{|7mkyH)@I literal 0 HcmV?d00001 diff --git a/moveit_planners/pilz_industrial_motion_planner/doc/figure/ptp_movement_2.png b/moveit_planners/pilz_industrial_motion_planner/doc/figure/ptp_movement_2.png new file mode 100644 index 0000000000000000000000000000000000000000..5158e329597be231d579b261c9a056d8a4b07b05 GIT binary patch literal 117675 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%0Ahfr-eoge0Hp%VpRaftHK44DYMhduGVFP~8k z9!`L|_|sm6qrmBEx1aE+-fb3y;> z3%9d=`^baZ;&xIuCrkB1aT`i9H|@C=F|KvOX|tBuX;UB9h8VFnw_su2q3iY4P)O$& zn3rNfZtNfsPXYBh*432#`fip;whlbfX*yx6ARVjnvyzZ~lg(_k#tWlg#pu(n58J6- z5)^D${n~Bx{?|RGWqz#rg_4Jd2SU+2<=J{KEWT7I|)n@>A4-Alcndzb9nh!8BW6 zz5x?08}Qr^i7iNvA)SoX}KVYyB0wbE*5Rhap|3<59Vf1dd(lbeu?-(L}=H{ zC}*d0@MEdPvFknbw4Y19 zJ907=fU7Ey9whl}Hb9fsvqK8=7LuLuoZ_|szr2nHbp-~>;s>n(Lspf!?Q=+4KlsKJ z$vhn#9Are9P^hC^Dy*dzO}w8AcC>EZ#IAF524bABd6e{9ZVXa2PTyWsxH?Zu9q+QB z1;>p4jXe(h#mUr%yEpA#TIzW*s5M7qO6G{NU+!c`&rG_(pg8dE_6M+~ySOi~B()K0 zLmgPQljoGFdrF)}95m_eJARQM@%Qrsq|hKTop6!}+%3hz!UBAa@7AlIP#1Nzb(|QD zF&Z<>@e72SG=+6CA$m_|Sbz)I_2Ook3)lD+Z>i;l%r^BFVhQUlBGHbH2hQ96deX}x zB)E2%+T2R_q$!~fB`0^H*H?4h)m@=AOim-KxU>TG(kKx%opIi-)DrFBjDT#AgH9X9!<{;1d|pv&|^3oyMLajjq?MuhAx7wlS2I1)53z>aP-uK;!ufw2K#i4P$%-&wxKsG+m(l$dx8xP-XOI5ugLp&=dDLl@n@ zL#cNkS%AYyDK8g++J|c}fCykmJBP8g(!Vjkc{Fy#ivqQrYCV6p>&;vk8314g2EBZl zotkQo^}1uNt$HP7vJMWimX^e!w>Dx@lFxFpve;zEDzi^*$wMfn^t_yU4o~dZ6+t67 z?9M>Z!V-gyW{R^%=Uit|>MM5Xu-9!6n;f0p6&Auu)LkCkXWJc0tB<^bL-|D4>@9HW zJIL_$^z_J@GZD=SU%fgD{A^rYTq5>!GiRme0D0vYzB7&Wj~I;ES5bG=jlZCypD=bq zy>R98drTq4A%-_@V^8Da{FEPTOv&n7)$ZW0#9Y4~8=%~ynj1X$x`cwMO(NQ|MZP5< zI_b0Qx{dmgKSN{t852pI1AO3^PpVUpb* zs+HT`Ko`!6Vg0u%Dzs|u{!-uWdAjhSdcDVb!x~g}bY1ZS6y%cBOC2&4p^~&JO3|`A zK{SP{3Q_^iQ?Y*7ojh|!?566cT?`sZc0s`D`#H?905WQmn9F%PZ6X!;&^!?H=7M2s zoR<4Uu)5dG3n)b~78)zod+nOkgPS}HDW3{Z*igZt0A{vcvz9hk;DPK;yBFh})anaA zaGo0-zAO(u`Ef2*@=jr$4C*5{ z*xK6Cs<1b0+xYPGm=S({pnCU{!(#b#qs01fgg_~jqB8UIaSn?JTP-|df3r=?$jGP% zm{cen*fr+A9S?Xe<>lFi$VA8(mqv4V9jod6zd| zMNGU&?;fwGQVr5E8KG6%mQt(7tcL`*35!m&OYPWgPd5;0)|g(0o@M9q$I@@aJHMO_ zbGBGEvRQf=Xw)V)T^|@zMa`M7Ph)PaPglFsWNp;<>CV#pM7w;&NHf>&`bF}Uzdflp z#830+QllB&ER+*P1z`x%YHB2*^4mRE{P?|6mwk$P^G~dDGBPp=&g1?zE!<`GP;Y9| zOY&+HnXd18rDW6^Cnz#OW#DeZrTg}xkOk&vC^A&%nOj%{0SSrxu&1||^v(`=X`7FZ z#%Vhx_=kGkw3g8?myz?}u)u%-~8alw;9u;LzuP#hKrI=rVk8{(fJs z4pqFcb;#?R8S;1T+>w<{@W2n)Kz*?Rip30G>rP%&6ck8~3Ke1jxO~F#t8f70W&tDx z&pM~Euv%qdE;QJ;@N<$@r6nXjIhQxtm)iTdT(Eah8jkT+iF z6_dy>E*D@IFPxZ*&M1=|iYuKN?uxb38+cxnnecW+WA8HWs0<_}oO8QS{UtT}b+TU@3{)q{*_2aB&W!pfZ$S>H2j zo$k{EQxMZ6Hg@;&X3asL=qN-- zBE-hvB(i=qiyI{(Sd%>6|cLG{&gIqzS#;V-|RnXtLN2$-}O}4h| zv5x?R9%80?d&zXk(%%s}gR41DoT_)BvQU+V3X3NXRU-{dFgD2N#y8t+C~Z_fO# zG(-73`KzXk`gDxGtLcAC6?IVNzs3#f^l(QAMT5{t7pecuTCjlv4(LJZ*uSFZr#y#X zk|E*zvhjz}A^-j_@tRM=@+2}||MSuJ$o8qWM4j&(&EBoP|1S~;0_S$hpUMPJUi`Jf zfvPiH{?hcLFn}=m)W`q2^pPur$Nz9~+nX!@a&gjOAgu{Rs&9OzT`v*I4G3{Wkcyt3 zJ|dcsKNs<}q_?k+Os2O$<>t+s|1`|eKV(Lgj-xKqdk)!d>XSdX>PGIe;S(*<+=0G~ zuIEQrlGazaW#9-w>Cmrj5m(`{xcM7TohZ% zVeyqu0yaJB3Jo)zX?Bf}S&Z7bLjiS1A9N`6o*QFJQ}Nb~nd)idp9I>24jemO56K(; z;YdOC+FU>St<3~dq?7%z1~^r^uXeZj%>-Rq7~YZ`TJc01l@kUM>E}H1M=I6&T|D~Z zg8dfRv(r1*B6}~j7rvREF3c{pRI_3DsI|BujmEzTrW-P>-Qif@m`1sg|KQlS>X?M6 zD)wWt4=YMjAXrp6;c{XBM!o+@R+Vn8;s+|V{flK-&m}eDs+vvng$!8@4GrziGjVqp?!>@)H`JE4B8z^;HFxe7`_GfF7mF=<%%_FeM@kg)rUUX(L)27nK_F!W zlPsgdwQ4k4l3V*z_cx54c^_I ziIO{alR~k`k`Cj!*|(my@-}_0BJcY95R%^#7fkRS-nEl+bj3^EFN{ihL_ z&nqo$^m~4LhW~CpRKMj?($mjr>$qj?*U{E?4Vgy7GJ(9FOMy$DpO7C_yl62yyL}e* zF%*KQdFGaU+ymcB#s!tkK7R9OOv3$@(?$7XvpyPUu_$Jh*5J%@&Na8J58cZlB)H2Q zdosX_t@ss0bzW0{Vw!6od$as4%eahlW3>Iq42+!*Nuro}Uk;$p_5oFq$;h|UNp7}n zI#td#fIdMy6t2YMA8%E0!6c`!kPiX3pzafy(A2e&`vk=#6N}y~4Mc+062se0Q~U3T z*GvqUq1HO_Pk%hq-mQQ@rf8sVW(GsACcbpneKpOCA^SFWAc#YFN-a!-TI0P=+D&_M zpLpjEp&y0Mas14!?ALQT>|WqZwli4JsjF-DWk)(tJZ1{9!d(;Q!JF=>>eVt{Kh zpl%1$yuIjTf-bsWY&i94X=#F~mXnrNHGn-?Tr!&5O#xI?zioU}FauH2zVR>xd2}7Q zW_=xb3}_Iw=vJn2Ora7&e2iY(9a^RHGaE5pB0Q4YV<#tKO&-*PgvaAzk_Vo3Y1qz- zDtTw#rSR_ijEM#+A~Wa>S_*9^dqH^QG#-&$#k0GC7BlKjH)x3FChZ*F_TAWBX9{K7 znJK>-9*~(y%_JzOP)}z~Ph+sz9F2MNRl?@;<7xCu#hCgpO$NcfOuLV^S2J*-X`#C| zAd@0e;M}M6Amegs+}>nYuv;Nd&0F+$Uaw5{|JogcZjQntYPN*SYdy6f?y+t(%_u>C zicPesBV`I+oAaW_xwH>no{Xe~M6DL+qFM$`eV6MAk3OUU2S(m#gC1c*)7v=#i|h%4 znOflx$t_>NcGytXkhelYR^ptJ#LW!Dp3HXS;sQWf=2ibvkw^`?nc5R&qg&ea&Yw5= z?tKseh3TEn9(!H)t#09Z^Lz$+!lD>!V~B(Z;7RRa_mw(6>(S7(Qb)5}nri-8Sx?f^ zjBbI9GC2rbDj0cllJ{>!!rxMji=j7?(U3w-fO0ArVg%luT>yl5`pKln^~2M@UUmI^ zuEQ6RA^~qwjVZV%6T~P{VY01*-MXy{m2(8(KEGsoLw_9+_@w3K@gQKAK zoqc_$5!F)yxKSX#5S0bQN_vmgPKo|JgIY-ty~NnnB58oW*Us7oggtThh?FlQ_T4Hr zopMw^Dr#=Ec~y@6r8|VYoq5%eHA!I=G1gQ&^Q$SvCUdkc3|OI3OL3 z-5F?5nl5e3LUNp6jn_t!KCAM{Xe|&O!@RaiOzS;*e_#o8hq6MI3$YD|^a+Gz!XXlP z45)%b6qr0NAyF9QOM!vBHO|t>#Q99V_HHe2XIZkbqER3=E@5T)$T!fsCqPe5$D+b)uk z?CFYxy3WqR1p^9Cd~tFx^4CJwwb_TJrv4Xhrtc~2V)PvE1knnbWh4(&yLU^hyYq*L zOuds35{AU%EJc`w2b=T>J%ep_iHUOb!HVR8U~}Kpki~BwO255NI>P51gdo(5+aPZC ziGH@fgO{jAwFeMp)zTa)-UsNjEKdkRIm-;lq!|-}^R>2ZE+BNh}`jqat6`U9QXM{A@-vn0eR7Qi@~m~a@?g0X6EJ-Un0~(4l%hulJ3vDQ+y8C zk_3!(?T+C*rf^Rs-NIX2<;&@#E4A}g?O)C;9k$VvAxR0D=KA=r$9VjRYqh(Ykufo7 zM7StiyV3iP2Jta=X(lbSvA+gi@^&^Wd;Duga!9OzNh3HR-`B2wfbqHiX?$Ni{mjy2)TlH zThMbFp+r=Xi1>OOZXkr*{qsJg=rP|}@#9GHCqVu9Q@i+zGQC5OI-l$6Ou`cQv2}W! zQe67d5O!AxQLU|u3VCd;Zh#8;ly&u5UkBB34}|FWx1s$X@p5v%C2*x6StnErv20bJ z_8I)QED}N8f5WepJS+ztxQ~~3ZDn|I{L_#F3;zR4>bM1$y?L`rkHb~?K{4gWVsWEG z?)fCUYEX%JKb{uHD7NwW38Bgg)cT=-m4DHztcEg|9F*nS90AqWBUGf_C}?Vgwah1mgig1{iNVfYWeydlOjY+qrwJW{tZ`+s0bI0e0?=6$s;yZz{#` zw9**7eRL1_s!B~ufRuSI&wc;5C))4%pF_L6hey8?Kjea6*9P8wKKnh@#+3i>!9BTO zHCa*u*edbejR}znrmYU&ai~iMNNtai?|51Pv8o&|#7#>}o0^wr_3)fblQ!H!)y{%7 z?|-tEKRb`gmUY34Z}uz^k^jSE1CeDX6(X@?GFoRGR_WrAt2z4BqMjg_U$4M7u_p&X zFGx}$7FsG0@%iQH1Uny-pMKW6$K>t)J$?DBA1(|BMfBoi;_hZLQ6yb8kru%O;%hxO z_kInptSo!Wb1$aGFO)AL@?J!2S!ywG!eFZ_Cbg10m%Sbe*6{4$*huOs<{d zk3__c5$tL_|8{fD$MjGaFCr>xK+n9PP!i-uX&QIB;_zMLoD19ru#4ZH2y%7*CP7G5i?u@na7!e)asUc_?OfSr1yxWFa+p$Yk7IECG zp^QNKWw|)mnN{%El#p;n&26NqyCkeBbMzXJnt*s z={Ha3n)X;PT)>hyxJ2EL3cG-tuJT-rmp!2vetck<1eJoRimo}$X(;!i#k<;PkD4mz zZ%!Y;bXA-cDzRuDh#QReVXNxs8xZ=e-7GMvepCNs31x};P4$SCn$lDuvu1O{Pcxw8 z9wj&%OfPQKq*tATuT>tuxJ{fNae1ELkjS%`A*y4-EOx|AE5iADh&^kwxAeE;v~8GF zL+^d#zn%5F=&Ge~>b{65+4*srQHGZ5)IsYq3Px2r`Xvh`Jz7s$BSY8!% z>&J!0aV0KtS!ZdABm`VPFJb-tUhdjup$6I5>YP zk_|OOp%l&41bSfj;JVD0gV!U6F(OedlU#ZwZ}i@eMN#J4pO>(Abi3cc>0;Sne!*l# zla`^!y5n@Z~xzl?pU;uJy4d zNwLs?mOW^M5|p(<$u$L!zSiY28JN94q-!=a@2pdv+uhGN?Da^#FVw*A+kGic>WBo!n^qGp+`hL9j#?W)P8Y?fuZ6$jJ3%a8mJ+LK#4sBPSk1f*ViJ{{ z@C|Nfo*-|^lW`oeXu5Z6C$ncgU+wj+tPcT5NUe}pL>8{=3)}Jp&D&K)HJFY&oA)LX z&qU|n8C~4mxwgX(2fDU&53?~ZY+GAp*Mskb$OXFZ^$(^nW&c$szJ7fH(QcHW zQD%O_-ia*%f}G3E%bEb!VphhBsLHh6wYp2w;V7i^eR*FVeHm5AtF3RSFw#u0liOX$ z^J@7_@+AAswUpDFvHQ+nL(HGldsI&GCvQfZ_XntMx$RGB{75>Z2V)MFm82P68;+RU zCP5{nx?;Sys%ShaN2@rs&YXmZ&EQ|Ea>wuM};$&8svw+qYJBKYP#%MAs#C zB72^MTeJ!$Cx<(KVYS)^%;&|sg8pySrCN`uH4H9DADWD3x+ zQ?_=%pN&S$(IQR($h zSo(6XgRrGG=gTg zR3+AWblnz8XhiL2LTKp*V9z8B|h|E&+0k!DehmLfmI=)5=HMlP#bY4=%@1Ct@&y_tP9$VP{ z`!(L;iD~I&{0UQ}=QwaS14Nz(^Wuoc0qefqYp|o?xlzY7#Yh-oo> z`0%QZj?Ug+fahodY4L~qs6R-}Y8`~P@n)fFMqlPXC zpgP>5Zd|La@T9qX_wH8I)+;YPA~G6dbHO2&TOOKBI_oc;CxUnbAXkoSE0{QgO??R|9khX6{>8yr#m&fh+Nu+xQBtWC&=qmsA3 zuEvWcq)Wy6y1K&C z)6==`6ulf-;>@q&NA#4HMo3}`0;Oeu_iw~Jp2Sjt~{ap{g9jf9T-iz+Hn?Z!y+4jGQrUJvk5Ot!@Sg8Lv+ zXaV8TbGg9NC1S`8AtD3b+HKo|$EmN+2*&W}#Zj=z8#e~gYy#mo_*Ep&M$Rb?YW~m^ zuCc)9O^bxozgTH$OuKoC+koOvX73b122G{!%uL+MCsyoY!p|x#C*s`M;ieXj0*Ak8 zjFgYou=%>>{E##*e2YUG;KPlfCr<2{l;b@3`Gx#Y&( z5(Si5&>nJ>*8DGw>d>#J`3FY*n``^wHf9n52X$dE&q23w>C&ZJZuDll=H});$7yc- z`&4=}j>VvUplnkJ)^gmm>{(6zm8~3?e?TuD5{5gFWdO9`(E_}9Z|-=+~D`i z>0k#0`s3m8D*~Iw0e0m6!+oc+kw}L=w6y%EzyE(77jN1Ekd?VZcW*mzVKHNMz8O&O zfS!ELRa(&YG=tyeH|xm^qUK{kLMhVP%y5bC`(;Yw5ZeS2@4)8vv{W*vH(h4r+8E4*G7G%XvwI?SdC?y}z0$JP-!$ooqZ`wzgd%lxEzcjOkiiaQL ztt$AoQo9_L{{>pvKazWXd!p;U)Ub&`OGX2c%#K_aP)W7>&iRBybKSY|57rF$(Cl5u z3mF01FCTfNyxI~(Tv~KSyB0+?BF?Eai;XUYxXKH7+X_w6epYzns5K~i%7NN!hFoR=nY*RaC_(_jM`W;#$M%WV2Q6SGXnpn@7bg=k@#4X2pQP{BMZK5HASc@0=TtSGo7P_K8Yt13Yh@tNu zgG6yi@O1W{z6`<9F~DJ-izopIWs6&M?b zt*YqgXb}3RmzNI+c4Mp{>U)A#FaMU?@f4r$Ii>y6-!tnc3zLW&+R2tcbyPz!c;HQG z=>w2=%!MY}cPW-bX{o!bt7w-fPQ|754B2O*e7>k9OOV4O$l#|R-pG42Lszvg$J9%w z+I6Vbpjz}!r6alxc6{(U3zTJu2l?IU?;&<*ZV8<&K{Brk6D{vPC6EjYvYBc3n=d2| z!?4C(UqhpUtML@mwegIq-x#io8Nw_x!T9SjA_=H01!W2P2zyBm&N2 zyAX9PR?xg}D_@vLG4k3gP-&L9Ef(CXTZU~|xFGJ|lZ0Jl(gD0f39tzg3}n-Y^y$-( zb9SIhO3voj*1Q-l`08PT7V@xY2xzVKd>wh5`q?VZpxknMEgfsUP`I^~Ct+agap zwU(U&O1>?mxiD6=Wbo#@HW}~(^^IaO7EQ4J`oAtgeUTNAFR?3;6;82wVbbPT5CDgx;jkf>u_jXI~pHNbx!#znaE3{ z7cYv7WIU=FPGkAgt7M*s0eTcsuD5mH1Em&J19&eT?H?dpx`b|&$+MyB^Z zJvS!qlvTOaRS@(X6@|)|nFX)>>0rP>v|277UUm5Iz}RspswGN~{xtWX?dI6#G^d#EO(y7!0J(M;IF<9t@Sug)W6K>^=hoK4Zm)r+s%81HlP!mM^tJvmgyD@yOEHC-v) z)30fQP^8ieH<2j(=`Xn&LP&{?HpbLox)#X;shm8&20F<3riCtU^Ha0Rv%R{p)~A4F z`+J}UUxE)rUH98VK12Dr+?(CW;R;MDpuK`+n`^LT_~|*RoUd?Aq3zc|l@@Xyk6*0M z{pldrfU?nDVD=t;{XN?;wX#wLRdER#Zm8mya^3P%jTJ2Qjq9OONjX~TBKclK;}5?X z=U0nj*Y34TM2t8&eFf9=W@!C`q(OaceHh?%FHkWRGzFlbkW{pvwOx zz479$_isMl34R`02_z2T(4g)6p>$dMm z9DhZ=zIA%<>oX0vbFU@27u|5jyg3dc6S_7!!K@pe&oA@2^j8XLyxT;L;wqUTbr^m!<#T&cT*exxiR(!}tu6tgd%_NO!ygZX){ONfX z4~f}rZj(dT8U6(6R{bVIrD}eMHf#9d^Dz-}fugmSV7sl`jzL$$AMcCUN1k(v33iPl zJ?n?udF%P8tV%M>z$$(o<;wJfpN+XuuFIq8b~we!%+yp7YA>*(M|VfZ^#y3KPwD53 ziHOmktvbB4G0{|XKWYVR75Zj9NDN1IM%^?SK}P9a4?{k($BUs3aO>Q@AjPG1{erZG zyW3hX>GVRi)2r=A^%PAsCKl&q=F1H3qxbdzag7F)1;cK*FlapXfmF`#z%e2BoeU|< z%hvsRoRhv!$W>Lv3zygG{hLS*vB~({vIZIlg%Z872OFVGhGZ3gP?4IpX}YS>Tm#pC z#cb>@p(8Z1Ii`F2H66X5U%If_;mdK>PcedHJxzYWy8$K9*iQc!Y`p3RO;>H8yk&;b zHB%}tba#2RT3||H`2N=~QJNgnk=L3e3AdWban1_1qb_s-KfB=)dwSPC8+tQNnEZ!@ z{^xPbv_bd?!&=i66pVR^y{S29TCY~N80J)ZO~p3nQ7GP@_En4!I(4RRgvt3Xzw;x9 ze$=Y?A9UDzJd)<{iXkNF_6Zb{V70nzPPXxeE@6yhiVWo@6CUs5d0EoU3-a6nPnx(MWyNcHG@#NE_1@NhtO_X;FCOVTs4;r@323}9~4Z&-#Za~#K|NczJi@DIXm9j=)C}E469%Ix}b;An}yhGdtySjDsXPlb>p~WbO zE++Dtj+az9$$xOe9wYBfd+|;Du8S^^Gl;qekO9xgvg`GF*a+z6cj%kqWNxmc?`|Ul zWbYBf2^?`X!?+=UwEcCqk|VadXkWb!HZH-Y(TAnJhH!4*K?|(1?Y_UH$&gKW$d>E2 z!H!YMpf`U2<0Aq)A=&M$^_##}UcHRLlH=C9Q`T7$KV3Kaa`0AroM6*RyAzkVh3;?8 zi{;HOa}bc{OEin7lcET9WZA>k?sQT$MMm`@fJy$A2X-6+4GafV^SvSvP>Fy}BuPLd z!ke%sS0bXEp%JpsDpA;vO7YFn3ggo5ae*7#ytg#otV%I=oH1b@7W51>(=~M}IB`h_ zG3X3jK7#*>T9K;%mCD zD5muudQ8kuCC&-PizHNvVf_&n#ns68=GZlQvI&>D3g| zUpDL>GS4sZ8pRaS1(3lWQ-nk&{BW`D5P0bvQ-x=Ae@)usUtA%Nhoe|kE|lhuB75vX zJBo*IThaQc+w^3N!RV|Dd%~kDfPDu?ke#g{l9r9QAnmpAktnkBUVA&Jn1>k5!Lo zHDzpS;$d6{N!y$4iZ{EX!0no^^yZ&S-Zq|eAQzp9)%}0ey=7FEZ5lPKqM(8xC?zEb zqI7qtpp=4&lypl=cd3LTARt|$ASy@-NXJd5gmiaz=XYG7GtcA9GwXZTdjGulni)sr zuIoC_Blh0MK5dj_V;oH}9Pe#+a<#*F=(4OyH#3m)bcZclrrau=D*+Zh>6q;?g%vKc-a zO0t3l%s#a%dc?=vWekzMY(73wMh zH5GU*Hjfw`KQ@UyW|5(HFJbb&6|I+bRY&sFZk8AJoT5e;Px^`$>Z6C(_IAvkC9=7X zWk*9~_eOjvukUpT(=+_Ht^%}3F-ZK~LbMmjis@9yhd^YAFk2WaURYd#aV+p#7EO`@ zZIZmn_krFHWygZaj-HhQMq<|Y+U}aEh1mr`sJsy-U8IOT#!m}TAD3hSE1hPe&sN<_ zTOE9ya%Kt#HiQnS0_Qebq&nc66n{Osy?tgQROKHlo@W{5PY6P-_v4*pjmBUJpyWj< zsWP581M4f?`wokPehFTECPfGfFMw0*5t7`*;3QyhE9$ytbZ0J5r_Kc-F8_ z1Se~}`bv`Esryo+cQ)vQUqQdMoTYW*XIppoVTrfSs+N-zgO^Yq7_)N|MBn0wTH(c40iN? z57Dt7SHO={>7U^qH}d9|mVbhS68;g~JbVW?p{jqE?Z{6K!O5dHzww`#B_JUGZqoit zae!&UMBKZ7xPnr@K=mK|S>L|JgJ8a)p#kFDr*)pAcXRgp1&km4_1NSE=;YBs+AZ9m zq#qqD5p)%)Ul5+p0)nOv_`UY*{v%e$bJ$rxo3#Kro^#L)=G9k_wi~emwLmBYFxhL! zDO&rA1TnD6>z!T+WmFD9U^>L%5#e7D2i9;<$RomBNE`HmX(z;yfun!E4~8Y@xO?AJ zQMd}k?(|MrfK@BN5L9lI7+r3gUX_mOoZm#?Q}Eez<^|_N1j;d9 zvqr}ukD^ALp1rE%lNFoiqwamBmk|I~LfM(3GeUiDTEW1;;8%h|dXm2shCN1o6CC@^ z^j0`XT?O*6Mw6Vr?0XZY4liFL?!s_~oe#wW<(UVKhUszWMAo2r4WM%!^nH}$Y|+ox6l7Y>BU39&AymALbJeqDF|Mi`}A z0p;5S@Jsr@11Zm$zZ*x`Wq{Hf-d>l@05luvM(lyiF6gp^)ctR$4g{pu2voO%_=7@z zmk30<3|})RZG>=!(k8ZV$mnQA9Q(wDvS4P|LBE| z8HPtQM}da?=!}5FUKsh8AGB?9$Y}K8!!70yy5{J|{}B=YANz6J3%EB_Ky8PE)2)Bu z1bA^rAmkkk?+LEQz?UiUI~2+sGY)N)5f+4B-0JQq%Km8ymeiX7V2(lfRKvNOy$2m7 z{KsnqYH0=7f{Gq5;mK}uhe{cEvSlMLt%Poe2cr_`ToFs`SzvqZH}VJiE_^V_K}tzz zAEcow&mW1#r$wIHFLS7w>STfda2H-N4DSC#PVwHHUQ<5Ifdf&_4(en02$kv*NGpiQ zFThV-e(nMCY}5NBt_Z4mY}F9Nq|(43AjH2kg&8aW*t;R{9g)R2+oBvbRCR=cElod0CIIei+wi`vCl^KC$JsMK+yuPWV&Yp1Tnw{p|a}gvB0dFtve@5 zM+Ud%8fwgMT;KH z$;?*}F_8UuI3h!^Xpx}R1xj4mX#rVvh$js)NuXj;Lo?$KX5_I@)6V==YFPK4tQi^x>-h8gv2~V*V8@h$OJwQNZq~OV^*wU)qH!7 zoF9?{J8(2mpi%=JrRus{Nn&`pkSrEy<$pJ=u1@gHn(r`VIe8gBZ0UIHR8itpwrl+hZ!`hw2#>r5uvv%(F^K>SKN`V|T@$SY6vg4l#)f1y)1;h(DuWRTK1PY; zOej(qiw59*LZ}b9M`x$LC0MLkeS3(>H)GvY#^I0$Q{ie0GLbbSg~vVMWa%a4hrE+u z-53}A;bw}&8!RH0%iy3d)}E{sge*ZB!L>&SHHU14nI;leEz!VHG>Xj|?J27HT|H2R zWK?V@Z}9mLGDBC42x9u|uZa2G4Ma9?PtK38L~J_ZjWB3~_-$`Z$+$)!k_+h5%>DSL zKNSp}GwY07I0x@;9CMhKewZK=ZbyH(O+u!Knzn>@!dfG465i4)?q-2&b4*akn` zy&!6&c7+w`RRxPT_TwYE1ejQoU~}4BybH`H!XLw3b+y`Z-dURog}DdQrKpuger7<9 zkOmKV@sF@*A#=_xJ0i$Z&rwjGl>Ze}Q(%Y{VJv>_+RphXgerrnnQEjf_jjJvJ}kI8 zkeis37laIJvjJjs_-(yhH@$59K{+ULxX;tItHu#nVtWKBS6bWKLy+K=TD7V6ADlw#dfGLM@mCL$sikT=%Dj3wA!Inkn_V^t&RrSv&Qs_+2{CQ%Usb0nMc zPQH7NaKlhMaW)BVsJOuW7)O2qjK*Y=g^M%E=zxf~9fb^M0=|#7mYrwzh?S|G;<@jTqcdw-^OF+w~?&H#L2jmg|BUFE-7x7l+yCV1I`lVh4b{#LCX| z;KLsS-e2qo$VnNqa9RWe&Z+pIT`6c-+{i|kswkS`C4!I@i9nT~4;#-P6S=+UZQjTV zfL+@NmI5sxSplMH|?$i zuu_515<OlL|W-;!aO(f|?xol4f^57mlD|!nK z4hV-MYQA=B-)N8xbQ79Ini}NboUSU!g#*;V2d&O1lKvkevgw(5;G|%QI>-GFqJuS< zz?pz<5c?E>oEZ_DwZf*L4zANP&f9A#KG-Qv1g|#aSc8RzqV_x~ zVk=U^>=#Q=|LDS70O8sQxfWT~$Q-tuGLCZ{ zj7ugRu@3(QNV;)u3#l0N!MaQWcJnf5bhwf95JZi%q?w=uhTWTxl9JN5g4hn*V=GrQjPuU;R&45yW^$4>zHkhb0^GHv}Am zr@?stzwk)Ga1w}r0(({y{(^f}W9IL;HvgO&_$y54z{c&zdzE*k-tYFy#Ml&4;qfqX zl2e`1F5~|mi@E+wBjk|yH-!Hu!aX|#TYGpzIiWM)%Qs#g4$Z;B0S(HNM#RgefI@)hdhi!PXE;HkFaz_BK8=53tTeO@ zqaqa3Q=gF+$@4!Vs!PpWBX{=(Xb%PsLg6Tk;AIrP0=05aYWkyT#h6Z&xc8Ym4T4-c z;tzA834f~C5(nI~MRnSRV!=zeJ^pwoyF3Mj5u_O!+kt4{>nwiUtO+ev;pMW_V{>uJ zFjfLKwta!0e;v%3U7Y5+zcz8{RIi6JGv&r-@K+w}71sbU=0lkO8sX2=Ru1)(f9hZO z*|=-RB(D!I?59}p`f?Ysg2~yar?=!eF1n&d!r zLZ2^Qu+tYTWojk=LQ&!EW>-_5$y+kh!4jRePqhgmS7oH(V3=?gN{BeM5hRxaR~n^? zmV80L6Xfqit@J&uTUKOaiT&>bU&oH^hIXjSq!bH5t{+8FNMj3f0An6VvCqOg9#-pz zEwLPjW8#wN?Y!|-KrJc8#Q|kX1U(+q>B~I>@~CQkhi%H&ITZ*9v$+c_i(GMG?eMEdqWUfp2awb*AWp`v0k_?>3wlzYL#L8(*@z+Zax!D&v_6Hd*L6SZo4ieDm zAr*v)%RbW8Ky#@B^fba2Bh3hS&A4JnW6d?dJn`>1i(lgl3ZOO4z_jt3R`#b<>xz0}eV%24KBUH%`zlaW1xvm)HMF!)8q3_p>_h!ksF48rpp^CV zCGCvRnC{HwsKaSPZvcxF-WYIoMLJ99uCZ27YcjTiajxf-|;hLOLO^yN^v2UPeFPJnW~7OCB-_C6jW3IO~amZFFy4}dcT zh{kcMBUK%_wqyuL@JJo>O?S)l`-3?+s2dt;6pA0`s+7}&UK6(p1rd*B` z?w6jPqkRj~023L?AYI0N1pC%1aXU`TZK@I)!w(f2(iz)BOOe0d2?L!-yMEYU05+a) zbQiuRClKKS`-}kej&^DXO~lH~7qBa(y~}VEb#~68?d3g3^af0OXmNz2V5X>M#Ge-8 zLPGrVO00q-a^%muRHQ7@fbsHZ(_*X5A+JOjfbbXEeuDq;1eCX66DdhN{6+*ODB@F? zw)QuIU~Zpxtu5a5z)+@>dvzf;%I5Jh#X-RCiZHF~wroP$vhco`u09gF-3+0W5gJ6$ zuS48^Gfx|u#p$Vl$>*S%Qv1z#z+H9#9f?j$e681t<6LlkWT?QV#cyj@K|uq1OyC{{R9Z%66>AmsM!#~`655xVzpf}K2QlEdKY;^bM_Y0N-P{B7T|xHQ zv-6lK-xngDqyz^m8A?75G4RnHOO=hTZJqwC(jv*2Bs=jf;$^sAIOWv{J%fM{%+ChT zX1>3_cAAQxy=lQ;?7_*l<^avrmAsVP68-V;t^N}OHy4^L2ln^(Z~I}KJgGs14*r(p zpCnT_px@6-lsb>g{Go`FYGS67HB5l`{Rgx0^s0B-V%|Q_Z~F{(8wsjLN9kmh&E=qC zU2j=&=;%cxNm?yn`w-GIP{w>1;1w;Gnu?`E;dQn1U`mTKk#=m#Y=bx9QOkD|iFq@X}Wh9AYk$!h0V zS@n3{%TP?VogrYjuXsx`)@9;6uEJ+CZ||fwZc))%0uO4@lw&XzOMUe!0k6xlBB-Ss z9b5*AoWURZn$=8q7CpE^dywbo)ZoF1d#|Dn0Eb)w00p0qfRIp3RP>~nAL(@~Cukah zM*sXHUC?p;JTC4{Cnu-4k%i&|A*5rC(+&?07ZnvfPeP(RxjEaF>7&|W42AwBugW;{ zC#3)SBh*)WLCtRZ`X^;uoC~yfSTt@3 zO~A{{#N>xf#+PQ=$5)0z^~o1|!=u{6+aKgx8sm3QV|&uZzHr^Y@a55xmF_STy?jYh zYMG4i&6)P`vy{)#-5bWIYT=5&LqKeWlWIO8m|B#H9Rr7)nv(Lk7wW-N;~(#ClJZ$0 z2TJ0T@>`6a2CR;Tit2r*+Y9gf=8z^s^4-cf~8Rx?BM17UD8=ZR3!mc?8EG9)Re=w_W{UQ z0?j!-L*GR*vIa;EmGIv?4i0?B00yN3=1l`S{8JO>E^&A_M)R)#hs5TxYbUh3C}R43 z2t7)g7J!_!^82G_Iqa8pWI``fsoilF8LibLT3l&*y3+6?{fcqtF$z~Ke%rF*{ZnIg zgo0wuBg@T&{0wSXuDi#5Nl=9ww|od#ocTt_?DP0?dq3G8tXgD~`mB(uR=NkxDuR%S-o70W9DEy~aXWybo*?TvHE}Gm zJerN2{mj|3%T~lx!?$4vq}-LJWl%h3R-h^UCdUZl!=31X5X@U1PGDyt*n z!cd{(^NQiA>Gd*y5(BNNt4+v-6j$uJ#j)nH5^$r-qi^owl3jrwAhfq4ugk< z#O*uJ`qXxvmzJI$?EQ#8(`!r7mWornf3|q{g!A^b%ak5jCYb83=OVenZ$`i(yTtiy zqyKp_gNyQjc_rIxX-_FtEPbma z@tK=5Xq>iajJr-0I+Pag>zblibf0S`eM+hm`25_gFWf>o%0 z8cP^g1D0g6DkgK`N$Z)iNVBqcH`A=?>toK%b*uKyd@@t9kKpo{YK0}ey~dt1a2k_6 z$3#MA!^(P?v5o)Fn1_pd9Ul&4T(LSsHLMG_hKYHs_U1_Ck6iYGJ+4Q|r<3GMla+S5L&w!0I9p|1rX!wSf z9va7<#y)X;xw>7WMXeii|$&%)z-T<0&KL z?sg2q(u(7P`T?5)=NU}?HO2fsm9f$Kk)zA4>oIO5+ABpbadZ8KQSx?x^a|jEqyyhkD`{1=@zWMYN&1lQnbDRon={-Xf2P_J# zO8MHC_==k2IdZ!aEU|($0v$bq z=-1eomag}2Ig3a>EabZzq2rP&xPnE>t7TgJAc^3`3s?|K9BbIP=E2*ZM-e36_`%_; zSHR56!W5opdEF;7Z#%F0yDO4=p643oIOmH`t(mwu3)+PkEOEDOoe<7eFb$c94I>;0W~%IH(WlHM2W zq!6DBq<{X`7e0!&NB3spZ77Cp;;q(?i<=`)_tw&MF`f2vc|SWPyi}ohDfm-u)_MIA zf56NYshrEaiJ2xl%VVKWTkpXJTV23u5;8(}htFbRDfr;)?^Q#0_SXUwf4RIu$%Yrf z?IlL;&ZMf*dNqu<73;3bXNMPS8k@UAx1Zs`OQR-m62%m8nl4_Yxx|(HD(TAJ*J zOtc}oTS{?1)=5qyJx}-L6{%GDUvVJU>L?C?4=wfY5MQ22iXFy@`8ewt2DzKfoCXR# zj2+`~_NtY21${#iE|=>m_U_`x*RGkfU1t5Tm-M1R{efZD_aOOd7ES{#boc%3y53jX zn@?AET-q5{^hKDMx1;}l>yO?tAUu5PUkl8$^~``1nn_QY;6_-|?PO()mGSVZ+Kh*D zB!Uk2C#IU~pB&I_)aQGhDZYDI%jTrN+>BJNSS)pl1dI7gb7Sf5`t`SSv-f(W9^Sz- z=rYim&>!K5N>E6`+)m*u`}A4ll`5rnTN~x7s&zTLhrM``{CJayN>uK9Fm4KSkF#GX zVG&S`{_gW$N^ zYHMSh^o5EScA|re8;7@-)SoIWjLfE-T=Oscw#Bl`)u}qw+caXdRxtpKL}c*{h0KmX z3GHB6?8G;JA$f|lo|-(@Yp5$&{dRU-n)s-*C-7R|GoEY=lUt6#S8x;FcT-SvPmqdp zc7(LHy?)B4qBR&QJV-uccafz&HZpYr$zX6)uO$|mmX^lqlNG})60;Ybij)0)t--;J zUVao>OY0To#{QZ$el+oVi4R+g&#sy_nyDLKPSYbZ&fm~d`RP||BZo?Fx>JqJ3s zFC@S0)Zm{hL||d^W=5N`3cX9nbE{eJjfr)ju4SOEb)bRu8w1NX2Ig-J8m^)&qDDdl z0vYUe6qm(mLrL|Sc(-^*c`VL4b9_%TqD&^B-{*3@WV<%xN}+2hrN#a_ZTk^_RH?1- zqcXGgU3$LD$Mv2(slkKjf+e*&gQ1!irui~P5I^KsAYDTLy*pIgu}}qOMzJX*9TVmK*zMHm~1K7EB{>+ut_{4`_>?SN4+~%CYWj=@>qJrgD9Q zDI?E%xal?7w+$SsPEC)fDA}Ce-ZEDq`~0v9GH2(~fq{apQ|_)bSgx*%8>p!Xuhu5Q z#ME%&^O%yZ3B4X} z7Zzim%Qko+hsD2xc?q3|^!D=$G^glZ@w-&A*1h!4?o~0?7h1Pt8r6x~v0qs}E9s=q zJi5uVd4bL4qf=?0V&`()g_^_`58$CC$yvF-#(&1>TUWb}A|( zlut6KW0UchC8ge4=mT{IV{k4;5JVG2Z(ncqOdJ4`&^0#YC7h3Jly{xs~VoIi7L+68%8di-ocK z*5GTUQ$zmAJ6_A>4O;~d7H)n?Rm5aveY$x0&Qq3`s>+%1;W!JAUg>{WW5GwGYe_Vx z*yfxQi>-A2bWyRU6-6h9jRAG>YckB998|Pz*?05toHuXp{Wa9T@kv06V5C}+jOSKG zGR{J_4dZKK?MD3^LtW`MY|_*6Ns09If}Wab`-2VyChDT~*+lYl${s^c*?4kTamcX} zR>mLQ8s4uQetIKQPw(=3TQkdn7w_H$#`3VWU_H1<_#&-Gv*Ik#xHG*(y|2BGGHoM2 z{u`bt(fe9MJ~`~47Ba^(&dhW~4yZuaj90}{{iHQ2YwpXE{Z|nu+%$ZjhC3S$eN!Fr z6nl|tiAuqGicC3H(r1=epkQ2?FdY#3K0&@Rk^bO{jKbB!1mAz>u!wl`!uzebSswDE zeghP`C7aE@lV!i_tm2BHO=JUvR=;nv93k^6weL-Q6u&v+zO1@n@a96ftO4U>ew~+R zQjVsSwELjOWLGQJ?OqEXg_PYv8^TNbJQgQiHcPSYLjQFAIuD%!oO*Dz-Yl#tA3r;7 zfI0F`@TKNd1L1A%xu&eO)QYBY+s|U7=DfU%UHUAVC#Y#kpW{UI^tUBV{OUu?m7o04 z&6MXG_Zy>AjW=?p%2TkTdtx1@ppa3pF(CFV{TP4mSCrh%-r%mT(-(Je_M~Yaoo=}P z!nj*ch(}=e(Y5zR3X5xN#!I1BywLVHQSeDsPS12`D}E(4>3FTK96W)V&flWsdHKfe zys3eeRB1Np&sw<^tFh2W@&rz+xCKk-@d>5gxQh#}B2PXg(qBN9L_mf#a!svIF=o(F zQN^qR5b>{uWP+Kp6ieir0h&>Jn8H`Ht`k5{ZJ|@QShl=;<*!x#47bfOhulQiurB|C z+IVB<#q9mIS5dZg>?3`Bt18*g-`GSC`Y;a;-c-!NR Vl@>YvQVON_+_bMg;llpz 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 z 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