When using ROS Noetic (ROS2 answer great though too) with the Pilz industrial planner, I noticed that the plan output trajectory has 100ms between samples. I searched the web (and the source-code) but couldn't figure out where this 100ms comes from. Is there a parameter to adjust it or is it hard-coded somewhere?

I didn't see a parameter for the other planners (CHOMP, STOMP, ...) either. I get that post-processing can "fill-in" these trajectories, but I'm curious how to increase the planner output density instead.

The pilz source-code has a "plan(...)" function that takes a sampling rate, which seems to be called by a "generate(...)" function which also takes a sampling rate, but I couldn't figure out what calls the "generate(...)" function.

Extra tags: frequency, duration, sampling rate, sample rate, hz, publish rate,

  • $\begingroup$ Hi! Have you had a look at the parameter server to see if you can find anything related to the sampling time of the planner? Just a hint, as I am not very experienced with trajectory planners... $\endgroup$
    – Luca
    Commented Feb 23 at 14:38

2 Answers 2


In case of ROS2

Moveit2 planners inherit the planning_interface::PlanningContext and planning_interface::PlannerManager classes as shown here.

When a planning problem has to be solved then the the planning_interface::PlanningContext::solve method of the PlanningContextof the planner is called.

In case of the pilz planner the pilz_industrial_motion_planner::PlanningContextBase inherits from planning_interface::PlanningContext and pilz_industrial_motion_planner::CommandPlanner inherits from planning_interface::PlannerManager.

The solve method of pilz_industrial_motion_planner::PlanningContextBase directly calls the generate method of a pilz_industrial_motion_planner::TrajectoryController which then calls its own pilz_industrial_motion_planner::TrajectoryController plan method (Note, the plan method is virtual in the TrajectoryGenerator class and only implemented in the TrajectoryGenerator{PTP|LIN|CIRC} classes respectively).

Depending on the used motion planning strategy of pilz (e.g. point-to-point motion, linear trajectory or circular trajectory) the generator then plans the motion.

In summary, a simplified call stack looks like this (types are left out and names shortened):

↓ is implemented by pilz
↓ calls
TrajectoryGenerator::generate(scene, req, res, sampling_time=0.1)
↓ calls
TrajectoryGenerator::plan(scene, req, plan_info, sampling_time, joint_trajectory)

where res is a reference to the motion plan response, scene is the planning scene of the context, req is the motion planning request of the context, sampling_time is the sampling rate of your question and plan_info is a pilz collection of some scene and req information.

Note, that the sampling_time parameter is introduced in the TrajectoryGenerator::generate method with a default value of 0.1 (the 100ms you mentioned) and is directly forwarded to the call of TrajectoryGenerator::plan but not changed (not even in the point-to-point, linear nor circular trajectory generators calls of the TrajectoryGenerator::generate method - the default value of 100ms of the parameter is used) nor read from anywhere like a ros parameter. Thus the value appears truly hardcoded in ROS2.

The implementation of moveit for ROS1 is different - so it still might be possible there.


       planning_interface::MotionPlanResponse& res, double sampling_time = 0.1);


Found with

cd pilz_industrial_motion_planner
grep -r "0.1"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.