Skip to content

Commit 1e42730

Browse files
committed
Added mtc to jtc converter
1 parent 44eed6f commit 1e42730

28 files changed

+41001
-808
lines changed

src/example_behaviors/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ find_package(moveit_studio_common REQUIRED)
55
find_package(example_interfaces REQUIRED)
66
moveit_studio_package()
77

8-
set(THIS_PACKAGE_INCLUDE_DEPENDS moveit_studio_behavior_interface pluginlib example_interfaces)
8+
set(THIS_PACKAGE_INCLUDE_DEPENDS moveit_studio_behavior moveit_studio_behavior_interface pluginlib example_interfaces)
99
foreach(package IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS})
1010
find_package(${package} REQUIRED)
1111
endforeach()
@@ -14,6 +14,7 @@ add_library(
1414
example_behaviors
1515
SHARED
1616
src/add_two_ints_service_client.cpp
17+
src/convert_mtc_solution_to_joint_trajectory.cpp
1718
src/delayed_message.cpp
1819
src/get_string_from_topic.cpp
1920
src/fibonacci_action_client.cpp
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
objectives:
22
behavior_loader_plugins:
33
example_behaviors:
4-
- "example_behaviors::ExampleBehaviorsBehaviorsLoader"
4+
- "example_behaviors::ExampleBehaviorsLoader"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="utf-8" ?>
22
<library path="example_behaviors">
33
<class
4-
type="example_behaviors::ExampleBehaviorsBehaviorsLoader"
4+
type="example_behaviors::ExampleBehaviorsLoader"
55
base_class_type="moveit_studio::behaviors::SharedResourcesNodeLoaderBase"
66
/>
77
</library>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#pragma once
2+
3+
#include <Eigen/Core>
4+
#include <behaviortree_cpp/action_node.h>
5+
#include <behaviortree_cpp/bt_factory.h>
6+
#include <moveit/robot_model_loader/robot_model_loader.h>
7+
#include <moveit_msgs/msg/robot_trajectory.hpp>
8+
#include <moveit_studio_behavior/utils/trajectory_utils.hpp>
9+
#include <moveit_studio_behavior_interface/behavior_context.hpp>
10+
#include <moveit_studio_behavior_interface/check_for_error.hpp>
11+
#include <moveit_studio_behavior_interface/shared_resources_node.hpp>
12+
#include <moveit_task_constructor_msgs/msg/solution.hpp>
13+
#include <spdlog/spdlog.h>
14+
#include <trajectory_msgs/msg/joint_trajectory.hpp>
15+
#include <yaml-cpp/yaml.h>
16+
17+
namespace example_behaviors
18+
{
19+
/**
20+
* @brief Converts a MoveIt Task Constructor Solution into a JointTrajectory.
21+
*
22+
* @details
23+
* | Data Port Name | Port Type | Object Type |
24+
* | ----------------- |---------------|---------------------------------------------------------|
25+
* | solution | Input | moveit_task_constructor_msgs::msg::Solution |
26+
* | joint_group | Input | std::string |
27+
* | velocity_scaling_factor | Input | double |
28+
* | acceleration_scaling_factor | Input | double |
29+
* | sampling_rate | Input | int |
30+
* | joint_trajectory | Output | trajectory_msgs::msg::JointTrajectory |
31+
*/
32+
class ConvertMtcSolutionToJointTrajectory final : public moveit_studio::behaviors::SharedResourcesNode<BT::SyncActionNode>
33+
{
34+
public:
35+
ConvertMtcSolutionToJointTrajectory(const std::string& name, const BT::NodeConfiguration& config,
36+
const std::shared_ptr<moveit_studio::behaviors::BehaviorContext>& shared_resources);
37+
38+
static BT::PortsList providedPorts();
39+
40+
static BT::KeyValueVector metadata();
41+
42+
BT::NodeStatus tick() override;
43+
44+
private:
45+
std::unique_ptr<robot_model_loader::RobotModelLoader> robot_model_loader_;
46+
47+
const std::vector<Eigen::VectorXd>& extractJointPositions(const moveit_task_constructor_msgs::msg::Solution& solution);
48+
};
49+
} // namespace example_behaviors
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#include <example_behaviors/convert_mtc_solution_to_joint_trajectory.hpp>
2+
3+
namespace
4+
{
5+
const auto kLogger = rclcpp::get_logger("ConvertMtcSolutionToJointTrajectory");
6+
7+
// Port names for input and output ports.
8+
constexpr auto kPortIDSolution = "solution";
9+
constexpr auto kPortIDJointGroup = "joint_group";
10+
constexpr auto kPortIDJointTrajectory = "joint_trajectory";
11+
constexpr auto kPortIDVelocityScalingFactor = "velocity_scaling_factor";
12+
constexpr auto kPortIDAccelerationScalingFactor = "acceleration_scaling_factor";
13+
constexpr auto kPortIDSamplingRate = "sampling_rate";
14+
} // namespace
15+
16+
namespace example_behaviors
17+
{
18+
ConvertMtcSolutionToJointTrajectory::ConvertMtcSolutionToJointTrajectory(
19+
const std::string& name, const BT::NodeConfiguration& config,
20+
const std::shared_ptr<moveit_studio::behaviors::BehaviorContext>& shared_resources)
21+
: moveit_studio::behaviors::SharedResourcesNode<BT::SyncActionNode>(name, config, shared_resources)
22+
{
23+
}
24+
25+
BT::PortsList ConvertMtcSolutionToJointTrajectory::providedPorts()
26+
{
27+
return {
28+
BT::InputPort<moveit_task_constructor_msgs::msg::Solution>(kPortIDSolution, "{mtc_solution}",
29+
"MoveIt Task Constructor solution."),
30+
BT::InputPort<std::string>(kPortIDJointGroup, "manipulator",
31+
"Joint group name used in the MTC solution."),
32+
BT::InputPort<double>(kPortIDVelocityScalingFactor, 1.0,
33+
"Velocity scaling factor for trajectory generation."),
34+
BT::InputPort<double>(kPortIDAccelerationScalingFactor, 1.0,
35+
"Acceleration scaling factor for trajectory generation."),
36+
BT::InputPort<int>(kPortIDSamplingRate, 100,
37+
"Sampling rate for trajectory generation."),
38+
BT::OutputPort<trajectory_msgs::msg::JointTrajectory>(kPortIDJointTrajectory, "{joint_trajectory_msg}",
39+
"Resulting joint trajectory."),
40+
};
41+
}
42+
43+
BT::KeyValueVector ConvertMtcSolutionToJointTrajectory::metadata()
44+
{
45+
return { { "subcategory", "Motion Planning" },
46+
{ "description", "Extracts joint space trajectories from an MTC solution and adds time parameterization using TOTG." } };
47+
}
48+
49+
BT::NodeStatus ConvertMtcSolutionToJointTrajectory::tick()
50+
{
51+
using namespace moveit_studio::behaviors;
52+
53+
// Load data from the behavior input ports.
54+
const auto solution = getInput<moveit_task_constructor_msgs::msg::Solution>(kPortIDSolution);
55+
const auto joint_group_name = getInput<std::string>(kPortIDJointGroup);
56+
const auto velocity_scaling_factor = getInput<double>(kPortIDVelocityScalingFactor);
57+
const auto acceleration_scaling_factor = getInput<double>(kPortIDAccelerationScalingFactor);
58+
const auto sampling_rate = getInput<int>(kPortIDSamplingRate);
59+
60+
// Check that the required input data port was set
61+
if (const auto error = maybe_error(solution, joint_group_name, velocity_scaling_factor, acceleration_scaling_factor, sampling_rate); error)
62+
{
63+
spdlog::error("Failed to get required value from input data port: {}", error.value());
64+
return BT::NodeStatus::FAILURE;
65+
}
66+
// Initialize the robot model loader if this is the first time this Behavior has been run.
67+
if (robot_model_loader_ == nullptr)
68+
{
69+
robot_model_loader_ = std::make_unique<robot_model_loader::RobotModelLoader>(shared_resources_->node);
70+
}
71+
72+
// Get the robot model from the robot model loader.
73+
const auto robot_model = robot_model_loader_->getModel();
74+
if (robot_model == nullptr)
75+
{
76+
// Return as a failure case if the robot model loader has no robot model.
77+
spdlog::error("Failed to load robot model.");
78+
return BT::NodeStatus::FAILURE;
79+
}
80+
81+
// Get the JointModelGroup using the joint group name from the input port
82+
auto joint_model_group = robot_model->getJointModelGroup(joint_group_name.value());
83+
if (!joint_model_group)
84+
{
85+
spdlog::error("Failed to get JointModelGroup '{}'.", joint_group_name.value());
86+
return BT::NodeStatus::FAILURE;
87+
}
88+
89+
// Extract joint positions from the MTC solution
90+
const auto& waypoints = extractJointPositions(solution.value());
91+
92+
// Use trajectory_utils.hpp to create a trajectory
93+
auto trajectory_result = createTrajectoryFromWaypoints(
94+
*joint_model_group, waypoints, velocity_scaling_factor.value(), acceleration_scaling_factor.value(), sampling_rate.value());
95+
96+
if (!trajectory_result)
97+
{
98+
spdlog::error("Trajectory generation failed: {}", trajectory_result.error());
99+
return BT::NodeStatus::FAILURE;
100+
}
101+
102+
// Set the output port with the resulting joint trajectory
103+
setOutput(kPortIDJointTrajectory, trajectory_result.value());
104+
105+
spdlog::info("Successfully converted MTC Solution to JointTrajectory with {} points.",
106+
trajectory_result.value().points.size());
107+
108+
return BT::NodeStatus::SUCCESS;
109+
}
110+
111+
const std::vector<Eigen::VectorXd>& ConvertMtcSolutionToJointTrajectory::extractJointPositions(const moveit_task_constructor_msgs::msg::Solution& solution)
112+
{
113+
static std::vector<Eigen::VectorXd> waypoints;
114+
waypoints.clear();
115+
for (size_t sub_traj_idx = 0; sub_traj_idx < solution.sub_trajectory.size(); ++sub_traj_idx)
116+
{
117+
const auto& sub_traj = solution.sub_trajectory[sub_traj_idx];
118+
const auto& joint_traj = sub_traj.trajectory.joint_trajectory;
119+
120+
if (joint_traj.points.empty())
121+
{
122+
spdlog::warn("Sub-trajectory {} has no points.", sub_traj_idx);
123+
continue;
124+
}
125+
126+
spdlog::info("Processing sub-trajectory {} with {} points.",
127+
sub_traj_idx, joint_traj.points.size());
128+
129+
for (const auto& point : joint_traj.points)
130+
{
131+
Eigen::VectorXd positions(point.positions.size());
132+
for (size_t i = 0; i < point.positions.size(); ++i)
133+
{
134+
positions[i] = point.positions[i];
135+
}
136+
waypoints.push_back(positions);
137+
}
138+
}
139+
return waypoints;
140+
}
141+
142+
} // namespace example_behaviors

src/example_behaviors/src/register_behaviors.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <moveit_studio_behavior_interface/shared_resources_node_loader.hpp>
44

55
#include <example_behaviors/hello_world.hpp>
6+
#include <example_behaviors/convert_mtc_solution_to_joint_trajectory.hpp>
67
#include <example_behaviors/delayed_message.hpp>
78
#include <example_behaviors/setup_mtc_wave_hand.hpp>
89
#include <example_behaviors/add_two_ints_service_client.hpp>
@@ -23,6 +24,7 @@ class ExampleBehaviorsLoader : public moveit_studio::behaviors::SharedResourcesN
2324
const std::shared_ptr<moveit_studio::behaviors::BehaviorContext>& shared_resources) override
2425
{
2526
moveit_studio::behaviors::registerBehavior<HelloWorld>(factory, "HelloWorld", shared_resources);
27+
moveit_studio::behaviors::registerBehavior<ConvertMtcSolutionToJointTrajectory>(factory, "ConvertMtcSolutionToJointTrajectory", shared_resources);
2628
moveit_studio::behaviors::registerBehavior<DelayedMessage>(factory, "DelayedMessage", shared_resources);
2729
moveit_studio::behaviors::registerBehavior<SetupMTCWaveHand>(factory, "SetupMTCWaveHand", shared_resources);
2830
moveit_studio::behaviors::registerBehavior<GetStringFromTopic>(factory, "GetStringFromTopic", shared_resources);

src/lab_sim/config/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ ros2_control:
7171
- "robotiq_gripper_controller"
7272
- "joint_state_broadcaster"
7373
- "servo_controller"
74+
- "joint_trajectory_controller"
7475
# Load but do not start these controllers so they can be activated later if needed.
7576
controllers_inactive_at_startup:
76-
- "joint_trajectory_controller"
7777
- "joint_trajectory_admittance_controller"
7878
- "velocity_force_controller"
7979
# Any controllers here will not be spawned by MoveIt Pro.
Lines changed: 1 addition & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1 @@
1-
<root BTCPP_format="4" main_tree_to_execute="3 Waypoints Pick and Place">
2-
<!--//////////-->
3-
<BehaviorTree
4-
ID="3 Waypoints Pick and Place"
5-
_description="Basic example of repeatedly grabbing a small (invisible) object, placing it at desired destination, and then moving back to a home position"
6-
_favorite="true"
7-
>
8-
<Control ID="Sequence">
9-
<!--Reset the planning scene to ensure no old collision objects are hanging around-->
10-
<Action ID="ClearSnapshot" />
11-
<!--Setup the environment to its "home" configuration - move to center and open gripper-->
12-
<SubTree
13-
ID="Move to Waypoint"
14-
waypoint_name="Look at Table"
15-
joint_group_name="manipulator"
16-
controller_names="/joint_trajectory_controller /robotiq_gripper_controller"
17-
planner_interface="moveit_default"
18-
constraints="{constraints}"
19-
/>
20-
<Action
21-
ID="MoveGripperAction"
22-
gripper_command_action_name="/robotiq_gripper_controller/gripper_cmd"
23-
position="0"
24-
/>
25-
<!--Run pick and place on loop-->
26-
<Decorator ID="KeepRunningUntilFailure">
27-
<Control ID="Sequence">
28-
<!--Pick object from original location, put it down at a different part of the table, and go back to center pose-->
29-
<Control ID="Sequence">
30-
<SubTree
31-
ID="Move to Waypoint"
32-
waypoint_name="Pick Cube"
33-
joint_group_name="manipulator"
34-
controller_names="/joint_trajectory_controller /robotiq_gripper_controller"
35-
planner_interface="moveit_default"
36-
constraints="{constraints}"
37-
/>
38-
<Action
39-
ID="MoveGripperAction"
40-
gripper_command_action_name="/robotiq_gripper_controller/gripper_cmd"
41-
position="0.7929"
42-
/>
43-
<SubTree
44-
ID="Move to Waypoint"
45-
waypoint_name="Look at Table"
46-
joint_group_name="manipulator"
47-
controller_names="/joint_trajectory_controller /robotiq_gripper_controller"
48-
planner_interface="moveit_default"
49-
constraints="{constraints}"
50-
/>
51-
<SubTree
52-
ID="Move to Waypoint"
53-
joint_group_name="manipulator"
54-
controller_names="/joint_trajectory_controller /robotiq_gripper_controller"
55-
planner_interface="moveit_default"
56-
constraints="{constraints}"
57-
waypoint_name="Place Cube"
58-
/>
59-
<Action
60-
ID="MoveGripperAction"
61-
gripper_command_action_name="/robotiq_gripper_controller/gripper_cmd"
62-
position="0"
63-
/>
64-
<SubTree
65-
ID="Move to Waypoint"
66-
waypoint_name="Look at Table"
67-
joint_group_name="manipulator"
68-
controller_names="/joint_trajectory_controller /robotiq_gripper_controller"
69-
planner_interface="moveit_default"
70-
constraints="{constraints}"
71-
/>
72-
</Control>
73-
<!--Pick object from where it was placed, put it down on the original location, and go back to center pose-->
74-
<Control ID="Sequence">
75-
<SubTree
76-
ID="Move to Waypoint"
77-
waypoint_name="Place Cube"
78-
joint_group_name="manipulator"
79-
controller_names="/joint_trajectory_controller /robotiq_gripper_controller"
80-
planner_interface="moveit_default"
81-
constraints="{constraints}"
82-
/>
83-
<Action
84-
ID="MoveGripperAction"
85-
gripper_command_action_name="/robotiq_gripper_controller/gripper_cmd"
86-
position="0.7929"
87-
/>
88-
<SubTree
89-
ID="Move to Waypoint"
90-
waypoint_name="Look at Table"
91-
joint_group_name="manipulator"
92-
controller_names="/joint_trajectory_controller /robotiq_gripper_controller"
93-
planner_interface="moveit_default"
94-
constraints="{constraints}"
95-
/>
96-
<SubTree
97-
ID="Move to Waypoint"
98-
waypoint_name="Pick Cube"
99-
joint_group_name="manipulator"
100-
controller_names="/joint_trajectory_controller /robotiq_gripper_controller"
101-
planner_interface="moveit_default"
102-
constraints="{constraints}"
103-
/>
104-
<Action
105-
ID="MoveGripperAction"
106-
gripper_command_action_name="/robotiq_gripper_controller/gripper_cmd"
107-
position="0"
108-
/>
109-
<SubTree
110-
ID="Move to Waypoint"
111-
waypoint_name="Look at Table"
112-
joint_group_name="manipulator"
113-
controller_names="/joint_trajectory_controller /robotiq_gripper_controller"
114-
planner_interface="moveit_default"
115-
constraints="{constraints}"
116-
/>
117-
</Control>
118-
</Control>
119-
</Decorator>
120-
</Control>
121-
</BehaviorTree>
122-
</root>
1+
<root BTCPP_format="4" main_tree_to_execute="3 Waypoints Pick and Place"><!--//////////--><BehaviorTree ID="3 Waypoints Pick and Place" _description="Basic example of repeatedly grabbing a small (invisible) object, placing it at desired destination, and then moving back to a home position" _favorite="false"><Control ID="Sequence"><!--Reset the planning scene to ensure no old collision objects are hanging around--><Action ID="ClearSnapshot"/><!--Setup the environment to its "home" configuration - move to center and open gripper--><SubTree ID="Move to Waypoint" waypoint_name="Look at Table" joint_group_name="manipulator" controller_names="/joint_trajectory_controller /robotiq_gripper_controller" planner_interface="moveit_default" constraints="{constraints}"/><Action ID="MoveGripperAction" gripper_command_action_name="/robotiq_gripper_controller/gripper_cmd" position="0"/><!--Run pick and place on loop--><Decorator ID="KeepRunningUntilFailure"><Control ID="Sequence"><!--Pick object from original location, put it down at a different part of the table, and go back to center pose--><Control ID="Sequence"><SubTree ID="Move to Waypoint" waypoint_name="Pick Cube" joint_group_name="manipulator" controller_names="/joint_trajectory_controller /robotiq_gripper_controller" planner_interface="moveit_default" constraints="{constraints}"/><Action ID="MoveGripperAction" gripper_command_action_name="/robotiq_gripper_controller/gripper_cmd" position="0.7929"/><SubTree ID="Move to Waypoint" waypoint_name="Look at Table" joint_group_name="manipulator" controller_names="/joint_trajectory_controller /robotiq_gripper_controller" planner_interface="moveit_default" constraints="{constraints}"/><SubTree ID="Move to Waypoint" joint_group_name="manipulator" controller_names="/joint_trajectory_controller /robotiq_gripper_controller" planner_interface="moveit_default" constraints="{constraints}" waypoint_name="Place Cube"/><Action ID="MoveGripperAction" gripper_command_action_name="/robotiq_gripper_controller/gripper_cmd" position="0"/><SubTree ID="Move to Waypoint" waypoint_name="Look at Table" joint_group_name="manipulator" controller_names="/joint_trajectory_controller /robotiq_gripper_controller" planner_interface="moveit_default" constraints="{constraints}"/></Control><!--Pick object from where it was placed, put it down on the original location, and go back to center pose--><Control ID="Sequence"><SubTree ID="Move to Waypoint" waypoint_name="Place Cube" joint_group_name="manipulator" controller_names="/joint_trajectory_controller /robotiq_gripper_controller" planner_interface="moveit_default" constraints="{constraints}"/><Action ID="MoveGripperAction" gripper_command_action_name="/robotiq_gripper_controller/gripper_cmd" position="0.7929"/><SubTree ID="Move to Waypoint" waypoint_name="Look at Table" joint_group_name="manipulator" controller_names="/joint_trajectory_controller /robotiq_gripper_controller" planner_interface="moveit_default" constraints="{constraints}"/><SubTree ID="Move to Waypoint" waypoint_name="Pick Cube" joint_group_name="manipulator" controller_names="/joint_trajectory_controller /robotiq_gripper_controller" planner_interface="moveit_default" constraints="{constraints}"/><Action ID="MoveGripperAction" gripper_command_action_name="/robotiq_gripper_controller/gripper_cmd" position="0"/><SubTree ID="Move to Waypoint" waypoint_name="Look at Table" joint_group_name="manipulator" controller_names="/joint_trajectory_controller /robotiq_gripper_controller" planner_interface="moveit_default" constraints="{constraints}"/></Control></Control></Decorator></Control></BehaviorTree></root>

0 commit comments

Comments
 (0)