From 387349027c5b1eacbb7b46517428599ef662810f Mon Sep 17 00:00:00 2001
From: SebastianEbert <sebastian.ebert@tu-dresden.de>
Date: Thu, 2 Apr 2020 09:42:22 +0200
Subject: [PATCH] velocity constraint planning, retreival and logging of robot
 state

---
 CMakeLists.txt                  |  14 ++--
 launch/simulation_rosrag.launch |  63 ++++++++++++++++
 src/RobotStateProvider.cpp      | 124 ++++++++++++++++++++++++++++++++
 src/TimedCartesianPlanner.cpp   | 120 +++++++++++++++++++++++++++++++
 4 files changed, 316 insertions(+), 5 deletions(-)
 create mode 100644 launch/simulation_rosrag.launch
 create mode 100644 src/RobotStateProvider.cpp
 create mode 100644 src/TimedCartesianPlanner.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4835386..a88278c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,6 +12,7 @@ find_package(catkin REQUIRED
              COMPONENTS controller_manager
                         effort_controllers
                         gazebo_ros
+                        genmsg
                         joint_state_controller
                         joint_state_publisher
                         joint_trajectory_controller
@@ -45,7 +46,8 @@ catkin_package(CATKIN_DEPENDS
                controller_interface
                hardware_interface
                pluginlib
-#               DEPENDS
+               #DEPENDS
+               #libpaho-mqtt
 #               system_lib
         )
 
@@ -58,20 +60,22 @@ include_directories(${catkin_INCLUDE_DIRS})
 
 # add custom controller as library
 add_library(${PROJECT_NAME}_controllers_lib src/joint_position_controller.cpp)
-#add_library(SafetyEnvironmentCreator src/SafetyEnvironmentCreator.cpp)
 
 # Specify libraries to link a library or executable target against
 target_link_libraries(${PROJECT_NAME}_controllers_lib ${catkin_LIBRARIES})
-#target_link_libraries(SafetyEnvironmentCreator ${catkin_LIBRARIES} ${Boost_LIBRARIES})
 
 add_executable(robot_control_node src/robot_control_node.cpp)
 add_executable(box_publisher_node src/box_publisher.cpp)
 add_executable(robot_state_initializer_node src/robot_state_initializer.cpp)
 add_executable(SafetyAwarePlanner src/SafetyAwarePlanner.cpp src/SafetyEnvironmentCreator.cpp)
+add_executable(SampleConstraintPlanner src/SampleConstraintPlanner.cpp)
+add_executable(RobotStateProvider src/RobotStateProvider.cpp)
+add_executable(TimedCartesianPlanner src/TimedCartesianPlanner.cpp)
 
 target_link_libraries(robot_control_node ${catkin_LIBRARIES} boost_filesystem ${JSONCPP_LIBRARIES})
 target_link_libraries(box_publisher_node ${catkin_LIBRARIES})
 target_link_libraries(robot_state_initializer_node ${catkin_LIBRARIES})
 target_link_libraries(SafetyAwarePlanner ${catkin_LIBRARIES})
-#target_link_libraries(constraint_planner ${catkin_LIBRARIES} ${Boost_LIBRARIES} SafetyEnvironmentCreator)
-
+target_link_libraries(SampleConstraintPlanner ${catkin_LIBRARIES} ${Boost_LIBRARIES})
+target_link_libraries(RobotStateProvider ${catkin_LIBRARIES})
+target_link_libraries(TimedCartesianPlanner ${catkin_LIBRARIES})
\ No newline at end of file
diff --git a/launch/simulation_rosrag.launch b/launch/simulation_rosrag.launch
new file mode 100644
index 0000000..91e8184
--- /dev/null
+++ b/launch/simulation_rosrag.launch
@@ -0,0 +1,63 @@
+<launch>
+    <param name="robot_description" command="$(find xacro)/xacro $(find franka_description)/robots/panda_arm_hand.urdf.xacro" />
+
+    <!-- GAZEBO arguments -->
+    <arg name="paused" default="false" />
+    <arg name="use_sim_time" default="true" />
+    <arg name="gui" default="true" />
+    <arg name="headless" default="false" />
+    <arg name="debug" default="false" />
+    <arg name="load_gripper" default="true" />
+
+    <!--launch GAZEBO with own world configuration -->
+    <include file="$(find gazebo_ros)/launch/empty_world.launch">
+        <!-- <arg name="world_name" value="$(find robotics_assisted_tomography)/worlds/tomography.world"/> -->
+        <arg name="debug" value="$(arg debug)" />
+        <arg name="gui" value="$(arg gui)" />
+        <arg name="paused" value="$(arg paused)" />
+        <arg name="use_sim_time" value="$(arg use_sim_time)" />
+        <arg name="headless" value="$(arg headless)" />
+    </include>
+
+    <node name="rqt_console" pkg="rqt_console" type="rqt_console" />
+    <!-- <node name="rqt_logger_level" pkg="rqt_logger_level" type="rqt_logger_level" /> -->
+
+    <node name="spawn_urdf" pkg="gazebo_ros" type="spawn_model" args="-param robot_description -urdf -model panda" />
+
+    <!-- Load joint controller configurations from YAML file to parameter server -->
+    <rosparam file="$(find panda_simulation)/config/panda_control.yaml" command="load" />
+
+    <!-- load the controllers -->
+    <node name="controller_spawner" pkg="controller_manager" type="spawner" respawn="false" output="screen" args="joint_state_controller panda_arm_controller" />
+    <node if="$(arg load_gripper)" name="controller_spawner_hand" pkg="controller_manager" type="spawner" respawn="false" output="screen" args="panda_hand_controller" />
+
+
+    <!-- convert joint states to TF transforms for rviz, etc -->
+    <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" respawn="true" output="screen" />
+
+    <include file="$(find panda_moveit_config)/launch/planning_context.launch">
+        <arg name="load_robot_description" value="true" />
+        <arg name="load_gripper" value="$(arg load_gripper)" />
+    </include>
+    <include file="$(find panda_moveit_config)/launch/move_group.launch">
+        <arg name="load_gripper" value="$(arg load_gripper)" />
+    </include>
+    <group if="$(arg gui)">
+        <include file="$(find panda_moveit_config)/launch/moveit_rviz.launch" />
+    </group>
+
+    <node name="joint_state_desired_publisher" pkg="topic_tools" type="relay" args="joint_states joint_states_desired" />
+
+    <!-- launch robot control node for moveit motion planning -->
+    <node pkg="panda_simulation" type="robot_control_node" name="robot_control_node" output="screen" />
+
+    <!-- load (not start!) custom joint position controller -->
+    <node pkg="controller_manager" type="spawner" name="joint_position_launcher" args="--stopped joint_position_controller" />
+
+    <!-- run custom node for automatic intialization -->
+    <node pkg="panda_simulation" type="robot_state_initializer_node" name="robot_state_initializer_node" />
+
+    <node name="TimedCartesianPlanner" pkg="panda_simulation" type="TimedCartesianPlanner" respawn="false" output="screen"/>
+    <node name="RobotStateProvider" pkg="panda_simulation" type="RobotStateProvider"/>
+
+</launch>
diff --git a/src/RobotStateProvider.cpp b/src/RobotStateProvider.cpp
new file mode 100644
index 0000000..33fc60e
--- /dev/null
+++ b/src/RobotStateProvider.cpp
@@ -0,0 +1,124 @@
+//
+// Created by sebastian on 31.03.20.
+//
+#include "ros/ros.h"
+#include "std_msgs/String.h"
+#include <gazebo_msgs/LinkStates.h>
+#include <MQTTClient.h>
+
+// CONFIGURATION START
+// ^^^^^^^^^^^^^^^^^^^
+
+// configure the number of not redirected messages between redirected messages
+const int message_redirect_rate = 100;
+
+// values to export
+bool export_position = true;
+bool export_orientation = true;
+bool export_twist_linear = true;
+bool export_twist_angular = true;
+bool export_names = true;
+
+// CONFIGURATION END
+// ^^^^^^^^^^^^^^^^^
+
+int current_redirect = 0;
+bool isInitialized = false;
+
+/*
+ * logs to its own file in /.ros/logs (configured in launch-file)
+ */
+void exportMessageToLog(const gazebo_msgs::LinkStates & msg)
+{
+    if(export_names){
+
+        ROS_INFO_STREAM("<<< LINK NAMES >>>");
+
+        for(int i = 0; i < msg.name.size(); i++)
+        {
+            ROS_INFO_STREAM("[" << i << "] " << msg.name.at(i));
+        }
+    }
+
+    if(export_position){
+
+        ROS_INFO_STREAM("<<< POSITIONS BY LINK >>>");
+
+        for(int i = 0; i < msg.pose.size(); i++)
+        {
+            ROS_INFO_STREAM("[" << i << "] [x] " << msg.pose.at(i).position.x);
+            ROS_INFO_STREAM("[" << i << "] [y] " << msg.pose.at(i).position.y);
+            ROS_INFO_STREAM("[" << i << "] [z] " << msg.pose.at(i).position.z);
+        }
+    }
+
+    if(export_orientation){
+
+        ROS_INFO_STREAM("<<< ORIENTATIONS BY LINK >>>");
+
+        for(int i = 0; i < msg.pose.size(); i++)
+        {
+            ROS_INFO_STREAM("[" << i << "] [w] " <<  msg.pose.at(i).orientation.w);
+            ROS_INFO_STREAM("[" << i << "] [x] " <<  msg.pose.at(i).orientation.x);
+            ROS_INFO_STREAM("[" << i << "] [y] " <<  msg.pose.at(i).orientation.y);
+            ROS_INFO_STREAM("[" << i << "] [z] " <<  msg.pose.at(i).orientation.z);
+        }
+    }
+
+    if(export_twist_linear){
+        ROS_INFO_STREAM("<<< LINEAR TWISTS BY LINK >>>");
+        for(int i = 0; i < msg.twist.size(); i++)
+        {
+            ROS_INFO_STREAM("[" << i << "] [x] " <<  msg.twist.at(i).linear.x);
+            ROS_INFO_STREAM("[" << i << "] [y] " <<  msg.twist.at(i).linear.y);
+            ROS_INFO_STREAM("[" << i << "] [z] " <<  msg.twist.at(i).linear.z);
+        }
+    }
+
+    if(export_twist_angular){
+        ROS_INFO_STREAM("<<< ANGULAR TWISTS BY LINK >>>");
+        for(int i = 0; i < msg.twist.size(); i++)
+        {
+            ROS_INFO_STREAM("[" << i << "] [x] " <<  msg.twist.at(i).angular.x);
+            ROS_INFO_STREAM("[" << i << "] [y] " <<  msg.twist.at(i).angular.y);
+            ROS_INFO_STREAM("[" << i << "] [z] " <<  msg.twist.at(i).angular.z);
+        }
+    }
+}
+
+void providerCallback(const gazebo_msgs::LinkStates & msg)
+{
+    if(current_redirect != 0 && current_redirect != message_redirect_rate){
+        //std::cout << "Ignoring message (redirect: " << current_redirect << " )" << std::endl;
+        current_redirect++;
+        return;
+    }
+
+    if(current_redirect == 0 || current_redirect == message_redirect_rate){
+        //std::cout << "Redirecting message:" << msg.pose.at(1).position << std::endl;
+        exportMessageToLog(msg);
+        if(current_redirect == message_redirect_rate){
+            current_redirect = 1;
+        } else{
+            current_redirect++;
+        }
+    }
+}
+
+int main(int argc, char **argv)
+{
+    ros::init(argc, argv, "listener");
+    ros::NodeHandle n;
+    n.getParam("ready", isInitialized);
+
+    // make sure the robot is initialized
+    while(!isInitialized){
+        //std::cout << "Waiting" << std::endl;
+        n.getParam("tud_planner_ready", isInitialized);
+    }
+
+    ros::Subscriber sub = n.subscribe("/gazebo/link_states", 10000, providerCallback);
+    ros::spin();
+
+    return 0;
+}
\ No newline at end of file
diff --git a/src/TimedCartesianPlanner.cpp b/src/TimedCartesianPlanner.cpp
new file mode 100644
index 0000000..e2552ec
--- /dev/null
+++ b/src/TimedCartesianPlanner.cpp
@@ -0,0 +1,120 @@
+//
+// Created by sebastian on 31.03.20.
+//
+#include <moveit/move_group_interface/move_group_interface.h>
+#include <moveit/planning_scene_interface/planning_scene_interface.h>
+
+#include <moveit_msgs/DisplayRobotState.h>
+#include <moveit_msgs/DisplayTrajectory.h>
+
+#include <moveit_msgs/AttachedCollisionObject.h>
+#include <moveit_msgs/CollisionObject.h>
+
+#include <moveit_visual_tools/moveit_visual_tools.h>
+#include <moveit/trajectory_processing/iterative_time_parameterization.h>
+#include <trajectory_msgs/JointTrajectoryPoint.h>
+
+/**
+ * allows time/velocity-constraint planning for cartesian paths
+ */
+int main(int argc, char **argv)
+{
+    ros::init(argc, argv, "move_group_interface_tutorial");
+    ros::NodeHandle node_handle;
+    ros::AsyncSpinner spinner(1);
+    spinner.start();
+
+    // wait for robot init of robot_state_initializer
+    std::cout << ">>>>>>>>>>>>>>>>> SLEEPING <<<<<<<<<<<<<<<< " << std::endl;
+    ros::Duration(5.0).sleep();
+    std::cout << ">>>>>>>>>>>>>>>>> WAKING UP <<<<<<<<<<<<<<<< " << std::endl;
+    node_handle.setParam("tud_planner_ready", true);
+
+    // Visualization Setup
+    namespace rvt = rviz_visual_tools;
+    moveit_visual_tools::MoveItVisualTools visual_tools("panda_link0");
+    visual_tools.deleteAllMarkers();
+    visual_tools.loadRemoteControl();
+
+    Eigen::Isometry3d text_pose = Eigen::Isometry3d::Identity();
+    text_pose.translation().z() = 1.75;
+    visual_tools.publishText(text_pose, "Sample constraint planner node", rvt::WHITE, rvt::XLARGE);
+
+    // Batch publishing is used to reduce the number of messages being sent to RViz for large visualizations
+    visual_tools.trigger();
+
+    moveit::planning_interface::MoveGroupInterface group("panda_arm");
+
+    moveit::planning_interface::PlanningSceneInterface planning_scene_interface;
+
+    ros::Publisher display_publisher = node_handle.advertise<moveit_msgs::DisplayTrajectory>("/move_group/display_planned_path", 1, true);
+    moveit_msgs::DisplayTrajectory display_trajectory;
+
+    moveit::planning_interface::MoveGroupInterface::Plan plan;
+    group.setStartStateToCurrentState();
+
+    std::vector<geometry_msgs::Pose> waypoints;
+
+    geometry_msgs::Pose start_pose = group.getCurrentPose().pose;
+    geometry_msgs::Pose target_pose_1 = group.getCurrentPose().pose;
+
+    target_pose_1.position.z = start_pose.position.z - 0.2;
+    target_pose_1.position.y = start_pose.position.y + 0.2;
+    target_pose_1.position.x = start_pose.position.x + 0.2;
+    waypoints.push_back(target_pose_1);
+
+    geometry_msgs::Pose target_pose_2 = group.getCurrentPose().pose;
+    target_pose_2.position.z = start_pose.position.z + 0.2;
+    target_pose_1.position.y = start_pose.position.y - 0.2;
+    target_pose_2.position.x = start_pose.position.x - 0.2;
+    waypoints.push_back(target_pose_2);
+
+    moveit_msgs::RobotTrajectory trajectory_msg;
+    group.setPlanningTime(10.0);
+
+    double fraction = group.computeCartesianPath(waypoints,0.01,0.0,trajectory_msg, false);
+
+    // The trajectory needs to be modified so it will include velocities as well.
+    // First to create a RobotTrajectory object
+    robot_trajectory::RobotTrajectory rt(group.getCurrentState()->getRobotModel(), "panda_arm");
+
+    // Second get a RobotTrajectory from trajectory
+    rt.setRobotTrajectoryMsg(*group.getCurrentState(), trajectory_msg);
+
+    // Third create a IterativeParabolicTimeParameterization object
+    trajectory_processing::IterativeParabolicTimeParameterization iptp;
+    // Fourth compute computeTimeStamps
+    bool success = iptp.computeTimeStamps(rt);
+    ROS_INFO("Computed time stamp %s",success?"SUCCEDED":"FAILED");
+    rt.getRobotTrajectoryMsg(trajectory_msg);
+
+    //std::cout << ">>>>>>>>>>>>>>>>> data before: " << trajectory_msg << std::endl;
+
+    // adjust velocities, accelerations and time_from_start
+    for(int i = 0; i < trajectory_msg.joint_trajectory.points.size(); i++)
+    {
+        trajectory_msg.joint_trajectory.points[i].time_from_start.operator*=(2);
+        for(int j = 0; j < trajectory_msg.joint_trajectory.points.at(i).velocities.size(); j++)
+        {
+            if(trajectory_msg.joint_trajectory.points.at(i).velocities.at(j) != 0.0){
+                trajectory_msg.joint_trajectory.points.at(i).velocities.at(j) /= 2;
+                //trajectory_msg.joint_trajectory.points.at(i).velocities.at(j) = 0;
+            }
+        }
+
+        for(int j = 0; j < trajectory_msg.joint_trajectory.points.at(i).accelerations.size(); j++)
+        {
+            trajectory_msg.joint_trajectory.points.at(i).accelerations.at(j) =
+                    sqrt(std::abs(trajectory_msg.joint_trajectory.points.at(i).accelerations.at(j)));
+        }
+    }
+
+    //std::cout << ">>>>>>>>>>>>>>>>> data after: " << trajectory_msg << std::endl;
+    plan.trajectory_ = trajectory_msg;
+    ROS_INFO("Visualizing plan 4 (cartesian path) (%.2f%% acheived)",fraction * 100.0);
+
+    group.execute(plan);
+
+    ros::shutdown();
+    return 0;
+}
\ No newline at end of file
-- 
GitLab