diff --git a/README.md b/README.md index 334fb91..45bfe9d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ The various tutorials are: 2. [tutorial 2](./tutorial_2/README.md) How to define and solve a simple pick and place problem. 3. [tutorial 3](./tutorial_3/README.md) How to use HPP in manufacturing. 4. [tutorial 4](./tutorial_4/README.md) How to control the trajectory of a tool. -5. [tutorial 5](./tutorial_5/README.md) +5. [tutorial 5](./tutorial_5/README.md) How to optimize and time-parameterize paths. 6. [tutorial 6](./tutorial_6/README.md) How to execute motions on a real robot. [![Pipeline status](https://gitlab.laas.fr/humanoid-path-planner/hpp_tutorial/badges/master/pipeline.svg)](https://gitlab.laas.fr/humanoid-path-planner/hpp_tutorial/commits/master) diff --git a/doc/Doxyfile.extra.in b/doc/Doxyfile.extra.in index 1a2941a..bbbd040 100644 --- a/doc/Doxyfile.extra.in +++ b/doc/Doxyfile.extra.in @@ -3,7 +3,7 @@ TAGFILES = @HPP_CORE_DOXYGENDOCDIR@/hpp-core.doxytag=@HPP_CORE_DOXYGENDOCDIR@ \ @HPP_MANIPULATION_DOXYGENDOCDIR@/hpp-manipulation.doxytag=@HPP_MANIPULATION_DOXYGENDOCDIR@ \ @HPP_MANIPULATION_CORBA_DOXYGENDOCDIR@/hpp-manipulation-corba.doxytag=@HPP_MANIPULATION_CORBA_DOXYGENDOCDIR@ \ -INPUT=@CMAKE_SOURCE_DIR@/include @CMAKE_SOURCE_DIR@/src/hpp/corbaserver/pr2/robot.py +INPUT=@CMAKE_SOURCE_DIR@/include IMAGE_PATH = @CMAKE_SOURCE_DIR@/doc/figures USE_MATHJAX= YES diff --git a/include/hpp_tutorial/doc.hh b/include/hpp_tutorial/doc.hh index 202315f..5651ecf 100644 --- a/include/hpp_tutorial/doc.hh +++ b/include/hpp_tutorial/doc.hh @@ -2,50 +2,36 @@ // Copyright (c) 2014 CNRS // Authors: Florent Lamiraux // -// -// This file is part of hpp_tutorial -// hpp_tutorial is free software: you can redistribute it -// and/or modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation, either version -// 3 of the License, or (at your option) any later version. -// -// hpp_tutorial is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Lesser Public License for more details. You should have -// received a copy of the GNU Lesser General Public License along with -// hpp_tutorial If not, see -// . +// BSD 2-Clause License + +// Copyright (c) 2014-2024, CNRS + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: + +// 1. Redistributions of source code must retain the above copyright notice, +// this +// list of conditions and the following disclaimer. + +// 2. 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. + +// 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. /// \mainpage Tutorials /// \anchor hpp_tutorial_documentation /// -/// \par Introduction -/// -/// These tutorials explain how to define and solve a path planning -/// problem, how to display the resulting paths in gepetto-viewer, and -/// how to implement a new path planning algorithm. -/// -/// \par Setting up your environment -/// -/// Before starting, make sure that -/// \li \c bash is you default shell script language, -/// \li the line \code source $DEVEL_DIR/config.sh \endcode is in your .bashrc -/// file, where \c DEVEL_DIR is the environment variable defined in the -/// -/// installation instructions. -/// -/// \par Tutorials -/// -/// \li \link hpp_tutorial_tutorial_1 Tutorial 1 (python)\endlink: how to -/// define and solve a path planning problem using CORBA. -/// \li \link hpp_tutorial_tutorial_1_cpp Tutorial 1 (C++)\endlink how to -/// define and solve the same path planning problem without middleware. -/// \li \link hpp_tutorial_tutorial_2 Tutorial 2 - plugin\endlink : how to -/// implement -/// a new path planning algorithm in C++. -/// \li \link hpp_tutorial_tutorial_3 Tutorial 3 - manipulation \endlink : how -/// to define and solve a manipulation planning problem. \li \link -/// hpp_tutorial_tutorial_4 Tutorial 4 - inverse kinematics \endlink: how to -/// plan -/// end-effector trajectoties +/// The tutorials are accessible on +/// github. diff --git a/include/hpp_tutorial/tutorial_1.hh b/include/hpp_tutorial/tutorial_1.hh deleted file mode 100644 index 0dbd3b8..0000000 --- a/include/hpp_tutorial/tutorial_1.hh +++ /dev/null @@ -1,243 +0,0 @@ -// -// Copyright (c) 2014 CNRS -// Authors: Florent Lamiraux -// -// -// This file is part of hpp_tutorial -// hpp_tutorial is free software: you can redistribute it -// and/or modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation, either version -// 3 of the License, or (at your option) any later version. -// -// hpp_tutorial is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Lesser Public License for more details. You should have -// received a copy of the GNU Lesser General Public License along with -// hpp_tutorial If not, see -// . - -/// \page hpp_tutorial_tutorial_1 Tutorial 1 - Python -/// -/// To run the tutorial, open a terminal and open 3 tabs by typing -/// \c CTRL+SHIFT+T twice. When the terminal is selected, you can select a tab -/// by typing \c ALT-[1|2|3]. -/// -/// \section hpp_tutorial_1_starting_hppcorbaserver Starting hppcorbaserver -/// -/// In the first tab, type -/// \code -/// hppcorbaserver -/// \endcode -/// See package \c hpp-corbaserver for details. -/// -/// \section hpp_tutorial_1_starting_gui Starting gepetto-gui -/// -/// In the second tab, type -/// \code -/// gepetto-gui -c basic -/// \endcode -/// A window opens and is ready to display the scene containing the robot. The -/// robot and environment will appear later. -/// -/// Note that \c gepetto-gui and \c hppcorbaserver executables are -/// completely independent. -/// -/// \section hpp_tutorial_1_python Controlling via a python terminal -/// -/// In the third tab, type -/// \code -/// cd script -/// python -i tutorial_1.py -/// \endcode -/// to run the script script/tutorial_1.py in an -/// interactive python terminal. -/// -/// To display the scene, type -/// \code -/// >>> v = vf.createViewer () -/// \endcode -/// gepetto-gui window should now display a scene containing a PR2 robot in a -/// kitchen environment. -/// -/// To display initial and goal configurations type the following commands -/// \code -/// >>> v (q_init) -/// >>> v (q_goal) -/// \endcode -/// -/// To solve the path planning problem between those configurations, type -/// \code -/// >>> ps.solve () -/// \endcode -/// -/// To display the resulting of RRT, type -/// \code -/// >>> from hpp.gepetto import PathPlayer -/// >>> pp = PathPlayer (v) -/// >>> pp(0) -/// \endcode -/// -/// To display an optimized solutions, -/// \code -/// >>> pp(1) -/// >>> pp(2) -/// \endcode -/// -/// \section hpp_tutorial_1_script Detailed explanation -/// This section presents in more details the content of \c -/// script/tutorial_1.py. -/// -/// \code -/// from hpp.corbaserver.pr2 import Robot -/// robot = Robot ('pr2') -/// robot.setJointBounds ("root_joint", [-4, -3, -5, -3]) -/// \endcode -/// Import class pr2.robot.Robot and create an instance and set bounds of -/// translation degrees of freedom of the base. -/// Note that the constructor of the instance calls idl method -/// hpp::corbaserver::Robot::loadRobotModel. This triggers the loading of the -/// urdf/srdf model of the PR2 robot in \c hppcorbaserver executable. -/// -/// \code -/// from hpp.corbaserver import ProblemSolver -/// ps = ProblemSolver (robot) -/// \endcode -/// Import class hpp.corbaserver.problem_solver.ProblemSolver and create an -/// instance. This class is a helper class to define and solve path planning -/// problems. -/// -/// \code -/// from hpp.gepetto import ViewerFactory -/// vf = ViewerFactory (ps) -/// \endcode -/// Import class gepetto.viewerFactory.ViewerFactory and create an instance. -/// This object takes as input the \c ProblemSolver instance that enables the -/// viewer client to also control \c hppcorbaserver executable -/// -/// \code -/// q_init = robot.getCurrentConfig () -/// q_goal = q_init [::] -/// q_init [0:2] = [-3.2, -4] -/// rank = robot.rankInConfiguration ['torso_lift_joint'] -/// q_init [rank] = 0.2 -/// \endcode -/// Define initial configuration. -/// \note Initial configuration is built from configuration of the robot at -/// construction, and by modification of joints retrieved by name. This method -/// is more robust than specifying a hard-coded configuration vector since the -/// ordering of joints in the configuration vector is not unique. -/// -/// \code -/// q_goal [0:2] = [-3.2, -4] -/// rank = robot.rankInConfiguration ['l_shoulder_lift_joint'] -/// q_goal [rank] = 0.5 -/// rank = robot.rankInConfiguration ['l_elbow_flex_joint'] -/// q_goal [rank] = -0.5 -/// rank = robot.rankInConfiguration ['r_shoulder_lift_joint'] -/// q_goal [rank] = 0.5 -/// rank = robot.rankInConfiguration ['r_elbow_flex_joint'] -/// q_goal [rank] = -0.5 -/// \endcode -/// Define goal configuration. -/// -/// \code -/// vf.loadObstacleModel ("package://hpp_tutorial/urdf/kitchen_area.urdf", -/// "kitchen") - -/// \endcode -/// Load obstacles from urdf file. -/// \note this method loads the objects defined in the urdf file both in -/// hppcorbaserver and in \c gepetto-viewer-server. -/// -/// \code -/// ps.setInitialConfig (q_init) -/// ps.addGoalConfig (q_goal) -/// \endcode -/// Define initial and goal configurations. -/// -/// \code -/// ps.addPathOptimizer ("RandomShortcut") -/// \endcode -/// Add a path optimizer (hpp::core::pathOptimization::RandomShortcut). -/// -/// \code -/// loaded = ps.client.problem.loadPlugin("spline-gradient-based.so") -/// if loaded: -/// ps.addPathOptimizer("SplineGradientBased_bezier1") -/// else: -/// print("Could not load spline-gradient-based.so") -/// \endcode -/// Load a plugin that implements another path optimizer -/// (hpp::core::pathOptimization::SplineGradientBasedAbstract) and add the path -/// optimizer. The two selected path optimizers will be called in sequence. -/// Note that in this example, the second path optimizer will not improve the -/// result of the first one. -/// -/// \code -/// print (ps.solve ()) -/// \endcode -/// Solve problem and print the results. -/// -/// \code -/// v = vf.createViewer() -/// from hpp.gepetto import PathPlayer -/// pp = PathPlayer (v) -/// \endcode -/// Create the display window. -/// Import and create an instance of PathPlayer. This class samples a path in -/// \c hppcorbaserver and displays it in \c gepetto-viewer-server. -/// -/// \note Paths can be displayed in \c gepetto-gui after installing \c hpp-gui -/// package and loading plugin \c hppwidgetsplugin. -/// -/// \code -/// pp(0) -/// \endcode -/// Display first path, result of RRT. -/// -/// \code -/// pp(1) -/// \endcode -/// Display second path after optimization by random shortcut algorithm. -/// -/// \code -/// pp(2) -/// \endcode -/// Display third path after optimization by spline gradient based algorithm. - -/// \page hpp_tutorial_tutorial_1_cpp Tutorial 1 - C++ -/// -/// Currently, there is no visualization with the C++ version. -/// -/// \section hpp_tutorial_tutorial_1_cpp_execution Execute the binary. -/// -/// Compile the code and run the following command in a terminal, type -/// \code -/// build-folder/src/hpp-tutorial-1 -/// \endcode -/// -/// \section hpp_tutorial_tutorial_1_cpp_source Understanding the source code. -/// -/// Have a look at the file \c src/tutorial_1.cc. It contains the C++ code that -/// defines and solves the same path planning problem as \c tutorial_1.py. -/// -/// \code -/// ProblemSolverPtr_t ps = ProblemSolver::create(); -/// \endcode -/// -/// Class hpp::core::ProblemSolver is a container class that stores -/// \li a robot, -/// \li objstacles, -/// \li various types of path planning algorithms (hpp::core::PathPlanner), -/// \li various types of path optimizers (hpp::core::PathOptimizer), -/// \li various types of configuration shooter -/// (hpp::core::ConfigurationShooter), -/// \li various types of steering methods (hpp::core::SteeringMethod), -/// \li various types of path validation methods -/// (hpp::core::PathValidation) -/// \li various types of path projection algorithms (hpp::core::PathProjector) -/// \li various types of metrics defined on the configuration space -/// (hpp::core::Distance). -/// diff --git a/include/hpp_tutorial/tutorial_2.hh b/include/hpp_tutorial/tutorial_2.hh deleted file mode 100644 index c2b8aca..0000000 --- a/include/hpp_tutorial/tutorial_2.hh +++ /dev/null @@ -1,134 +0,0 @@ -// -// Copyright (c) 2014 CNRS -// Authors: Florent Lamiraux -// -// -// This file is part of hpp_tutorial -// hpp_tutorial is free software: you can redistribute it -// and/or modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation, either version -// 3 of the License, or (at your option) any later version. -// -// hpp_tutorial is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Lesser Public License for more details. You should have -// received a copy of the GNU Lesser General Public License along with -// hpp_tutorial If not, see -// . - -/// \page hpp_tutorial_tutorial_2 Tutorial 2 - Plugin -/// -/// In this tutorial, we are going to implement a new path planning algorithm -/// within a plugin. -/// -/// \section hpp_tutorial_tutorial_2_implementation Implementing a new path -/// planning algorithm in a plugin -/// -/// The code of this tutorial can be found in \c src/tutorial_2.cc. -/// The compilation and installation instructions can be found in -/// \c src/CMakeLists.txt. -/// -/// \subsection hpp_tutorial_tutorial_2_class_planner Implementation of class -/// Planner -/// -/// File \c src/tutorial_2.cc implements \c class -/// hpp::tutorial::Planner, deriving from abstract class hpp::core::PathPlanner. -/// In this section, we explain some specific parts of the code. -/// -/// \code HPP_PREDEF_CLASS (Planner);\endcode -/// is a macro containing the forward declaration of class \c Planner as well as -/// \c PlannerWkPtr_t for weak pointer to class \c Planner. See -/// \c hpp/util/pointer.hh -/// for details. -/// -/// \code -/// static PlannerPtr_t create (const core::Problem& problem, -/// const core::RoadmapPtr_t& roadmap) -/// \endcode -/// As most classes, hpp::core::PathPlanner and any derived class are -/// manipulated -/// via shared pointers. Users are not allowed to define variables of the type. -/// Instead, they are required to call method \c create and to store the -/// resulting shared pointer. For this reason, the constructors are all -/// protected. -/// \note method \c create calls protected method \c init that is explained -/// later on. -/// -/// \code -/// virtual void oneStep () -/// \endcode -/// This method runs one step of our the algorithm. The new algorithm is a -/// basic version of PRM. Notice the compactness of the code. -/// -/// \code -/// void init (const PlannerWkPtr_t& weak) -/// \endcode -/// Method \c init takes as input a weak pointer to a new instance and stores -/// this weak pointer as a private member. This enables any object to -/// create a shared pointer to itself on demand using the following line of code -/// \code -/// weakPtr_.lock (); -/// \endcode -/// which is the shared pointer equivalent to \c this when using simple -/// pointers. \note Method \c init always calls the parent implementation so -/// that the parent part of the object also stores a weak pointer to itself. -/// -/// \subsection hpp_tutorial_tutorial_2_plugin Implementation of plugin -/// tutorial-2.so -/// -/// Now that the new class \c hpp::tutorial::Planner has been implemented, we -/// are going to add it via a plugin. -/// -/// \code -/// class Plugin : public core::ProblemSolverPlugin { -/// public: -/// Plugin() : ProblemSolverPlugin("TutorialPlugin", "0.0") {} -/// protected: -/// virtual bool impl_initialize(core::ProblemSolverPtr_t ps) { -/// ps->pathPlanners.add("TutorialPRM", Planner::create); -/// return true; -/// } -/// }; // class Plugin -/// \endcode -/// class \c hpp::tutorial::Plugin derives from abstract class -/// \c hpp::core::ProblemSolverPlugin. Upon loading of the plugin by -/// \c hppcorbaserver, method \c impl_initialize is called. This method register -/// our new path planning class with key "TutorialPRM" -/// -/// \code -/// HPP_CORE_DEFINE_PLUGIN(hpp::tutorial::Plugin) -/// \endcode -/// This macro register the new plugin. -/// -/// \section hpp_tutorial_tutorial_2_CMakeLists Compilation and installation -/// -/// The compilation and installation is done in file \c src/CMakeLists.txt by -/// the following lines -/// \code -/// ## Tutorial 2 -/// include(${HPP_CORE_CMAKE_PLUGIN}) -/// # Create and install the plugin -/// hpp_add_plugin(tutorial-2 SOURCES tutorial_2.cc LINK_DEPENDENCIES -/// hpp-corbaserver::hpp-corbaserver) -/// \endcode -/// These two lines declare a new plugin the source file of which is -/// tutorial-2.cc and install this plugin into lib/hppPlugins subdirectory -/// of the installation prefix. -/// -/// \section hpp_tutorial_tutorial_2_running Using the plugin and solving a -/// problem. -/// -/// To solve a problem with the new path planning -/// algorithm, we simply need to follow the same steps as in tutorial 1, -/// except that we should source \c script/tutorial_2.py instead of -/// \c script/tutorial_1.py -/// -/// \code -/// loaded = ps.client.problem.loadPlugin("tutorial-2.so") -/// assert(loaded) -/// -/// ps.selectPathPlanner("TutorialPRM") -/// \endcode -/// The above lines load the plugin and select the new path planner. -/// diff --git a/include/hpp_tutorial/tutorial_3.hh b/include/hpp_tutorial/tutorial_3.hh deleted file mode 100644 index 4fcc446..0000000 --- a/include/hpp_tutorial/tutorial_3.hh +++ /dev/null @@ -1,87 +0,0 @@ -// -// Copyright (c) 2017 CNRS -// Authors: Florent Lamiraux -// -// -// This file is part of hpp_tutorial -// hpp_tutorial is free software: you can redistribute it -// and/or modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation, either version -// 3 of the License, or (at your option) any later version. -// -// hpp_tutorial is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Lesser Public License for more details. You should have -// received a copy of the GNU Lesser General Public License along with -// hpp_tutorial If not, see -// . - -/// \page hpp_tutorial_tutorial_3 Tutorial 3 - manipulation -/// -/// To run the tutorial, open a terminal and open 3 tabs by typing -/// \c CTRL+SHIFT+T twice. When the terminal is selected, you can select a tab -/// by typing \c ALT-[1|2|3]. -/// -/// \section hpp_tutorial_3_starting_hpp_manipulation_server Starting -/// hppcorbaserver -/// -/// In the first tab, type -/// \code -/// hppcorbaserver -/// \endcode -/// See package \c hpp-manipulation-corba for details. -/// -/// \section hpp_tutorial_3_python Controlling via a python terminal -/// -/// In the second tab, type -/// \code -/// cd script -/// python -i tutorial_3.py -/// \endcode -/// Script script/tutorial_3.py -/// defines a manipulation planning problem. -/// -/// \section hpp_tutorial_3_starting_gui Starting gepetto-gui -/// -/// In the third tab, type -/// \code -/// gepetto-gui -/// \endcode -/// A window opens and is ready to display the scene containing the robot. The -/// robot, environment and object will appear later. -/// -/// Note that \c gepetto-gui and \c hppcorbaserver executables are -/// completely independent. -/// -/// \section hpp_tutorial_3_python Controlling via a python terminal -/// -/// To display the scene, create a client to the viewer in the python terminal. -/// \code -/// >>> v = vf.createViewer () -/// \endcode -/// The robot and environment should appear in the viewer. If the viewer -/// window is black, select the window and hit space. -/// -/// To solve the problem, type -/// \code -/// >>> ps.solve () -/// \endcode -/// -/// and to display the (non optimized) solution path, type -/// \code -/// >>> pp = PathPlayer (v) -/// >>> pp (0) -/// \endcode -/// -/// \section hpp_tutorial_3_optimization Optimizing the solution path -/// -/// To optimize the solution path, select a path optimizer: -/// \code -/// >>> ps.addPathOptimizer('Graph-RandomShortcut') -/// >>> ps.optimizePath(0) -/// \endcode -/// To display the solution: -/// \code -/// >>> pp(1) -/// \endcode diff --git a/include/hpp_tutorial/tutorial_4.hh b/include/hpp_tutorial/tutorial_4.hh deleted file mode 100644 index 3c5743c..0000000 --- a/include/hpp_tutorial/tutorial_4.hh +++ /dev/null @@ -1,315 +0,0 @@ -// -// Copyright (c) 2017 CNRS -// Authors: Florent Lamiraux -// -// -// This file is part of hpp_tutorial -// hpp_tutorial is free software: you can redistribute it -// and/or modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation, either version -// 3 of the License, or (at your option) any later version. -// -// hpp_tutorial is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Lesser Public License for more details. You should have -// received a copy of the GNU Lesser General Public License along with -// hpp_tutorial If not, see -// . - -/// \page hpp_tutorial_tutorial_4 Tutorial 4 - inverse kinematics -/// -/// To run this tutorial, you need to install package \c ur_description. -/// -/// To run the tutorial, open a terminal and open 3 tabs by typing -/// \c CTRL+SHIFT+T twice. When the terminal is selected, you can select a tab -/// by typing \c ALT-[1|2|3]. -/// -/// \section hpp_tutorial_4_starting_hpp_manipulation_server Starting -/// hppcorbaserver -/// -/// In the first tab, type -/// \code -/// hppcorbaserver -/// \endcode -/// See package \c hpp-manipulation-corba for details. -/// -/// \section hpp_tutorial_4_python Controlling via a python terminal -/// -/// In the second tab, type -/// \code -/// cd script -/// python -i tutorial_4.py -/// \endcode -/// Script script/tutorial_4.py -/// defines a path for an UR10 end-effector -/// -/// \section hpp_tutorial_4_starting_gui Starting gepetto-gui -/// -/// In the third tab, type -/// \code -/// gepetto-gui -/// \endcode -/// A window opens and is ready to display the scene containing the robot. The -/// robot, environment and object will appear later. -/// -/// \section hpp_tutorial_4_python Controlling via a python terminal -/// -/// To display the scene, create a client to the viewer in the python terminal. -/// \code -/// >>> v = vf.createViewer () -/// \endcode -/// The robot and environment should appear in the viewer. If the viewer -/// window is black, select the window and hit space. -/// -/// \section hpp_tutorial_4_explanition Explaining the script -/// -/// The first part of the script below -/// \li creates the robot from a xacro file, -/// \li creates the problem solver and the viewer factory. -/// -/// \code -/// ## Load robot from processing of a xacro file -/// Robot.urdfString = process_xacro\ -/// ("package://hpp_tutorial/urdf/ur10e.urdf.xacro", -/// "transmission_hw_interface:=hardware_interface/PositionJointInterface") -/// # Deactivate collision checking between consecutive links -/// Robot.srdfString = """ -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// """ -/// loadServerPlugin ("corbaserver", "manipulation-corba.so") -/// newProblem() -/// -/// robot = Robot('robot', 'ur10e', rootJointType="anchor") -/// ps = ProblemSolver(robot) -/// vf = ViewerFactory(ps) -/// \endcode -/// -/// The following lines -/// \li create a gripper attached to the end-effector of the robot, -/// \li create two handles attached to the base of the robot. -/// -/// These grippers and handles will ease the creation of pose constraints for -/// the end-effector. -/// -/// \code -/// ## Add a gripper to the robot -/// robot.client.manipulation.robot.addGripper\ -/// ('ur10e/wrist_3_link', 'ur10e/gripper', [0,0,.1,0.5,0.5,0.5,-0.5], 0.1) -/// -/// ## Create two handles -/// robot.client.manipulation.robot.addHandle\ -/// ('ur10e/base_link', 'handle1', [.8, -.4, .5, 0, 0, 0, 1], .1, 6*[True]) -/// robot.client.manipulation.robot.addHandle\ -/// ('ur10e/base_link', 'handle2', [.8, .4, .5, 0, 0, 0, 1], .1, 6*[True]) -/// \endcode -/// -/// Then two grasp constraints are created to defined initial and goal pose -/// of the gripper -/// -/// \code -/// ## Create grasp constraints -/// robot.client.manipulation.problem.createGrasp\ -/// ("ur10e/gripper grasps handle1", "ur10e/gripper", "handle1") -/// robot.client.manipulation.problem.createGrasp\ -/// ("ur10e/gripper grasps handle2", "ur10e/gripper", "handle2") -/// \endcode -/// -/// Configurations satisfying the pose constraints are computed by creating -/// a constraint graph with two nodes and no edge. -/// -/// \code -/// ## Create a constraint graph with one node for each grasp -/// cg = ConstraintGraph(robot, "graph") -/// cg.createNode(["ur10e/gripper grasps handle1", "ur10e/gripper grasps -/// handle2"]) -/// cg.addConstraints(node = "ur10e/gripper grasps handle1", constraints = \ -/// Constraints(numConstraints = ["ur10e/gripper grasps handle1"])) -/// cg.addConstraints(node = "ur10e/gripper grasps handle2", constraints = \ -/// Constraints(numConstraints = ["ur10e/gripper grasps handle2"])) -/// cg.initialize() -///\endcode -/// -/// We compute the initial and goal configurations by numerical inverse -/// kinematics. -/// -/// \code -/// # Generate one configuration satisfying each constraint -/// found = False -/// while not found: -/// q0 = robot.shootRandomConfig() -/// res, q1, err = cg.applyNodeConstraints("ur10e/gripper grasps handle1", -/// q0) if not res: continue res, msg = robot.isConfigValid(q1) if not res: -/// continue res, q2, err = cg.applyNodeConstraints("ur10e/gripper grasps -/// handle2", q1) if not res: continue res, msg = robot.isConfigValid(q2) if -/// not res: continue found = True -/// -/// We create several CORBA objects: -/// \li the current manipulation planning problem \c cmp, -/// \li the robot stored in this problem \c crobot, -/// \li a steering method \c csm of type -/// hpp::manipulation::steeringMethod::EndEffectorTrajectory -/// -/// \code -/// ## Create an EndEffectorTrajectory steering method -/// cmp = wd(ps.client.basic.problem.getProblem()) -/// crobot = wd(cmp.robot()) -/// cproblem = wd(ps.client.basic.problem.createProblem(crobot)) -/// csm = -/// wd(ps.client.basic.problem.createSteeringMethod("EndEffectorTrajectory", -/// cproblem)) \endcode -/// -/// Then we create a \link hpp::core::ConstraintSet ContraintSet \endlink -/// containing an empty \link hpp::core::ConfigProjector ConfigProjector -/// \endlink that we pass to the problem. We set \link -/// hpp::manipulation::steeringMethod::EndEffectorTrajectory \c csm \endlink as -/// the steering method of the problem. Note that the last line passes the \link -/// hpp::core::ConstraintSet ContraintSet \endlink of the problem to the -/// steering method. The order is important here since at construction the -/// problem is given an empty \link hpp::core::ConstraintSet ContraintSet -/// \endlink and setting the steering method of -/// the problem passes the \link hpp::core::ConstraintSet ContraintSet \endlink -/// of the problem to the steering method. -/// -/// \code -/// cs = wd(ps.client.basic.problem.createConstraintSet(crobot, -/// "sm-constraints")) cp = -/// wd(ps.client.basic.problem.createConfigProjector(crobot, "cp", 1e-4, 40)) -/// cs.addConstraint(cp) -/// cproblem.setConstraints(cs) -/// cproblem.setSteeringMethod(csm) -/// \endcode -/// -/// We need to create a time varying constraint for the end-effector. For that, -/// we create a new grasp between the gripper and the first handle. Note that -/// we cannot use the previously created identical grasp, since the comparison -/// type of this one should be \c Equality. -/// -/// \code -/// # Create a new grasp constraint for the steering method right hand side -/// # The previously created one has EqualToZero as comparison types. -/// robot.client.manipulation.problem.createGrasp \ -/// ("end-effector-tc", "ur10e/gripper", "handle1") -/// # Set comparison type to Equality -/// ps.setConstantRightHandSide("end-effector-tc", False) -/// \endcode -/// -/// We insert this constraint into the \link hpp::core::ConfigProjector -/// ConfigProjector \endlink of the \link hpp::core::Problem problem \endlink -/// (and thus of the steering method) -/// -/// \code -/// tc = wd(ps.client.basic.problem.getConstraint("end-effector-tc")) -/// cp.add(tc, 0) -/// \endcode -/// -/// We pass this constraint to the steering method as the trajectory constraint. -/// Note that from a mathematical point of view, the trajectory constraint is -/// a mapping from the robot configuration space \f$\mathcal{C}\f$ to -/// \f$SE(3)\f$ defined by -/// \f{equation} -/// tc(\mathbf{q}) = g^{-1}(\mathbf{q})h_1 -/// \f} -/// where \f$g(\mathbf{q})\in SE(3)\f$ is the pose of the gripper in -/// configuration \f$\mathbf{q}\f$ and \f$h_1\in SE(3)\f$ is the pose of -/// \c handle1. -/// -/// \code -/// csm.trajectoryConstraint(tc) -/// \endcode -/// -/// We now need to build the right hand side of the constraint as a linear -/// interpolation between the initial and final values. For that we evaluate -/// the fonction \f$tc\f$ of the constraint at the initial and goal -/// configurations, -/// we create a path in SE(3) linking these two values and we give this path -/// to the steering method to define the time-varying right hand side. -/// -/// From a mathematical point of view, \f$\mathbf{p}\f$ is a mapping from an -/// interval \f$[0,T]\f$ to \f$SE(3)\f$ such that -/// \f{eqnarray} -/// \mathbf{p}(0) &=& tc(\mathbf{q}_1) \\ -/// \mathbf{p}(T) &=& tc(\mathbf{q}_2) \\ -/// \f} -/// The constraint applied along the path computed by the steering method is -/// thus: -/// \f{equation} -/// \forall t\in[0,T],\ \ \mathbf{tc}(\mathbf{q}(t)) = \mathbf{p}(t) -/// \f} -/// -/// \code -/// # Get right hand side for q1 and q2 -/// rhs1 = tc.function().value(q1) -/// rhs2 = tc.function().value(q2) -/// # Create linear path for end-effector -/// p = wd(csm.makePiecewiseLinearTrajectory([rhs1, rhs2], 6*[1.])) -/// # Set this path as the time-varying right hand side of the constraint -/// csm.trajectory(p, True) -///\endcode -/// -/// We can now call the steering method between the initial and goal -/// configurations and insert this path in the ProblemSolver in order to -/// make it visible in \c gepetto-gui. -/// -/// \code -/// ## Call steering method -/// p1 = wd(csm.call(q1,q2)) -/// if p1: -/// ps.client.basic.problem.addPath(p1.asVector()) -///\endcode -/// -/// After connecting and refreshing \c gepetto-gui, you should be able to -/// display the path. Notice that the path might be discontinuous. -/// -/// To get a continuous path for sure, we need to use the \link -/// hpp::manipulation::pathPlanner::EndEffectorTrajectory EndEffectorTrajectory -/// path planner \endlink. -/// -/// \code -/// ## Using EndEffectorTrajectory path planner -/// cdistance = wd(cproblem.getDistance()) -/// croadmap = wd(ps.client.basic.problem.createRoadmap(cdistance, crobot)) -/// cplanner = wd(ps.client.basic.problem.createPathPlanner( -/// "EndEffectorTrajectory", cproblem, croadmap)) -/// cplanner.setNRandomConfig(0) -/// cplanner.maxIterations(1) -/// cplanner.setNDiscreteSteps(20) -/// -/// cproblem.setInitConfig(q1) -/// cproblem.addGoalConfig(q2) -/// -/// p2 = wd(cplanner.solve()) -/// if p2: -/// ps.client.basic.problem.addPath(p2) -///\endcode -/// -/// We set the number of random configurations to 0 in order to force the -/// planner to start from \c q1. Otherwise, in case of failure to plan a -/// continuous path starting from \c q1, the planner would generate random -/// initial configurations that satisfy the constraints at the beginning. -/// To be consistent, we set the maximal number of iterations to 1 since new -/// iterations would simply retry to start from \c q1. We set the number of -/// steps at which a configuration is computed for the corresponding pose of the -/// end effector to 20. -/// -/// Notice that the path satisfies the end-effector time-varying constraint, but -/// does not necessarily end at \f$\mathbf{q}_2\f$ since the final -/// configuration is completely determined by the initial one. diff --git a/tutorial_1/Dockerfile b/tutorial_1/Dockerfile index 7ff4451..c379dc5 100644 --- a/tutorial_1/Dockerfile +++ b/tutorial_1/Dockerfile @@ -19,9 +19,7 @@ RUN apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -qqy \ robotpkg-hpp-manipulation-urdf+doc robotpkg-qt5-qgv \ libboost-filesystem1.83-dev libboost-python1.83.0 \ libboost-thread1.83-dev python3-numpy liburdfdom-dev wget python3.12-venv \ - python-is-python3 doxygen - -RUN apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -qqy \ + python-is-python3 doxygen \ libasound2-dev libatk1.0-0 libc6 libcairo-gobject2 libcairo2 libdbus-1-3 libdbus-glib-1-2 \ libffi8 libfontconfig1 libfreetype6 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 \ libstdc++6 libvpx9 apulse \ diff --git a/tutorial_1/Makefile b/tutorial_1/Makefile index 3ea90f8..e754a2b 100644 --- a/tutorial_1/Makefile +++ b/tutorial_1/Makefile @@ -59,17 +59,29 @@ hpp-plot_extra_flags= -DINSTALL_DOCUMENTATION=OFF # }}} ################################## -# {{{ Packages for gepetto-gui +# {{{ Packages for hpp-plot qgv_branch=devel qgv_repository=${HPP_REPO} qgv_extra_flags=-DBINDINGS_QT5=ON -DBINDINGS_QT4=OFF +# }}} +################################## +# {{{ Packages for toppra + +toppra_repository=https://github.com/hungpham2511 +toppra_branch=develop +toppra_extra_flags= -DBUILD_TESTS=OFF -DPYTHON_BINDINGS=OFF + +hpp-toppra_repository=${HPP_REPO} +hpp-toppra_branch=main +hpp-toppra_extra_flags= + # }}} ################################## # {{{ High-level targets -all: hpp-plot.install hpp_tutorial.install +all: hpp-plot.install hpp_tutorial.install hpp-toppra.install ${MAKE} hpp-doc.install # }}} @@ -96,6 +108,8 @@ qgv.configure.dep: qgv.checkout jrl-cmakemodules.install hpp_tutorial.configure.dep: hpp_tutorial.checkout hpp-gepetto-viewer.install \ hpp-python.install hpp-gepetto-viewer.configure.dep: hpp-gepetto-viewer.checkout python-venv hpp-python.install +toppra.configure.dep: toppra.checkout +hpp-toppra.configure.dep: hpp-toppra.checkout jrl-cmakemodules.install toppra.install # }}} ################################## @@ -203,3 +217,20 @@ update: echo -n "$(@:.log=): "; \ cat .git/refs/heads/${$(@:.log=)_branch}; \ fi + +toppra.configure_nodep:toppra.checkout + mkdir -p ${SRC_DIR}/$(@:.configure_nodep=)/cpp/${BUILD_FOLDER}; \ + cd ${SRC_DIR}/$(@:.configure_nodep=)/cpp/${BUILD_FOLDER}; \ + cmake -DCMAKE_INSTALL_PREFIX=${INSTALL_HPP_DIR} -DCMAKE_INSTALL_LIBDIR=lib -DCMAKE_BU\ +ILD_TYPE=${BUILD_TYPE} \ + -DENFORCE_MINIMAL_CXX_STANDARD=ON \ + -DINSTALL_DOCUMENTATION=${INSTALL_DOCUMENTATION} \ + -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="-g -O3 -DNDEBUG" \ + ${CLANG_FLAGS} \ + ${$(@:.configure_nodep=)_extra_flags} .. + +toppra.install:toppra.configure + ${MAKE} -C ${SRC_DIR}/$(@:.install=)/cpp/${BUILD_FOLDER} install + +toppra.install_nodep:toppra.configure_nodep + ${MAKE} -C ${SRC_DIR}/$(@:.install_nodep=)/cpp/${BUILD_FOLDER} install diff --git a/tutorial_2/README.md b/tutorial_2/README.md index 7e76622..2442a44 100644 --- a/tutorial_2/README.md +++ b/tutorial_2/README.md @@ -43,7 +43,7 @@ v = Viewer(robot) v.initViewer(open=False, loadModel=True) v(q) ``` -Then in midor address bar, type `http://localhost:8080`. You should see the panda robot. +Then in midori address bar, type `http://localhost:8080`. You should see the panda robot. You can have a quick look at the script to see the instructions used to define the robot. diff --git a/tutorial_5/README.md b/tutorial_5/README.md new file mode 100644 index 0000000..5dcc1e4 --- /dev/null +++ b/tutorial_5/README.md @@ -0,0 +1,3 @@ +# How to optimize and time-parameterize paths. + +Work in progress, please be patient. diff --git a/tutorial_6/README.md b/tutorial_6/README.md new file mode 100644 index 0000000..aded22d --- /dev/null +++ b/tutorial_6/README.md @@ -0,0 +1,3 @@ +# How to execute motions on a real robot. + +Work in progress, please be patient.