From 4568da59bc53075c27e66ebdd7bab317100a977a Mon Sep 17 00:00:00 2001 From: artable-dev Date: Fri, 29 Jun 2018 08:29:22 +0200 Subject: [PATCH 1/2] blue container bundle --- .../bundles/blue_container.xml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 art_arcode_detector/bundles/blue_container.xml diff --git a/art_arcode_detector/bundles/blue_container.xml b/art_arcode_detector/bundles/blue_container.xml new file mode 100644 index 0000000..b531b00 --- /dev/null +++ b/art_arcode_detector/bundles/blue_container.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + From 2a1be29e1355d369657cc700b7a56de1dd21dd07 Mon Sep 17 00:00:00 2001 From: Michal Kapinus Date: Thu, 12 Jul 2018 19:33:48 +0200 Subject: [PATCH 2/2] node for user detection and program running control --- art_presence_detector/CMakeLists.txt | 32 +++ .../launch/art_presence_detector.launch | 12 ++ art_presence_detector/package.xml | 28 +++ art_presence_detector/scripts/control_run.py | 78 +++++++ art_presence_detector/src/node.cpp | 191 ++++++++++++++++++ 5 files changed, 341 insertions(+) create mode 100644 art_presence_detector/CMakeLists.txt create mode 100644 art_presence_detector/launch/art_presence_detector.launch create mode 100644 art_presence_detector/package.xml create mode 100755 art_presence_detector/scripts/control_run.py create mode 100644 art_presence_detector/src/node.cpp diff --git a/art_presence_detector/CMakeLists.txt b/art_presence_detector/CMakeLists.txt new file mode 100644 index 0000000..8469245 --- /dev/null +++ b/art_presence_detector/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 2.8.3) +project(art_presence_detector) + +find_package(catkin REQUIRED COMPONENTS + pcl_ros + roscpp + art_msgs + std_msgs + sensor_msgs + pcl_conversions +) + + + +add_definitions( + ${PCL_DEFINITIONS} +) + +catkin_package( + CATKIN_DEPENDS art_msgs std_msgs +) + +include_directories( +# include + ${catkin_INCLUDE_DIRS} +) + +add_executable(${PROJECT_NAME}_node src/node.cpp) + +target_link_libraries(${PROJECT_NAME}_node + ${catkin_LIBRARIES} +) diff --git a/art_presence_detector/launch/art_presence_detector.launch b/art_presence_detector/launch/art_presence_detector.launch new file mode 100644 index 0000000..54581f4 --- /dev/null +++ b/art_presence_detector/launch/art_presence_detector.launch @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/art_presence_detector/package.xml b/art_presence_detector/package.xml new file mode 100644 index 0000000..9ddd60a --- /dev/null +++ b/art_presence_detector/package.xml @@ -0,0 +1,28 @@ + + + art_presence_detector + 0.0.0 + The art_presence_detector package + + Michal Kapinus + + TODO + + catkin + pcl_ros + roscpp + art_msgs + std_msgs + sensor_msgs + pcl_conversions + pcl_ros + roscpp + pcl_conversions + pcl_ros + sensor_msgs + art_msgs + std_msgs + roscpp + + + diff --git a/art_presence_detector/scripts/control_run.py b/art_presence_detector/scripts/control_run.py new file mode 100755 index 0000000..706034a --- /dev/null +++ b/art_presence_detector/scripts/control_run.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +import rospy +from std_msgs.msg import Bool +from std_srvs.srv import Trigger, TriggerRequest +from art_msgs.srv import ProgramIdTrigger, ProgramIdTriggerResponse, ProgramIdTriggerRequest + + +class ControlProgramRun: + + def __init__(self): + self.user_presence_sub = rospy.Subscriber('/art/interface/user/present', Bool, + self.user_presence_cb) + self.pause_program_client = rospy.ServiceProxy("/art/brain/program/pause", Trigger) + self.resume_program_client = rospy.ServiceProxy("/art/brain/program/resume", Trigger) + self.stop_program_client = rospy.ServiceProxy("/art/brain/program/stop", Trigger) + self.start_program_client = rospy.ServiceProxy("/art/brain/program/start", ProgramIdTrigger) + self.time_user_appeared = None + self.time_user_disappeared = None + + self.demo_program = rospy.get_param("~demo_program", 1) + + resp = self.start_program_client.call(ProgramIdTriggerRequest(program_id=self.demo_program)) + if not resp.success: + rospy.logerr("Demo program could not be launched, exiting!") + rospy.signal_shutdown("Demo program could not be launched") + self.program_is_running = True + self.program_is_paused = False + + def user_presence_cb(self, data): + if data.data: # user is presented + self.time_user_disappeared = None + if self.time_user_appeared is None: # user just arrived + self.time_user_appeared = rospy.Time.now() + if not self.program_is_paused: + resp = self.pause_program_client.call(TriggerRequest()) + if not resp.success: + rospy.logerr("Failed to pause program!") # TODO: what to do? + self.program_is_paused = True + elif self.program_is_running and (rospy.Time.now() - self.time_user_appeared) > rospy.Duration(2): + # user is at least 2 seconds in front of the table -> stop program + resp = self.stop_program_client.call(TriggerRequest()) + if not resp.success: + rospy.logerr("Failed to stop program!") # TODO: what to do? + self.program_is_running = False + self.program_is_paused = False + else: + self.time_user_appeared = None + if self.time_user_disappeared is None: + self.time_user_disappeared = rospy.Time.now() + if self.program_is_paused and self.program_is_running: + resp = self.resume_program_client.call(TriggerRequest()) + if not resp.success: + rospy.logerr("Failed to resume program!") # TODO: what to do? + self.program_is_paused = False + elif not self.program_is_running: + resp = self.start_program_client.call(ProgramIdTriggerRequest(program_id=self.demo_program)) + if not resp.success: + rospy.logerr("Demo program could not be launched!") + self.program_is_running = True + self.program_is_paused = False + elif (rospy.Time.now() - self.time_user_disappeared) > rospy.Duration(2) and not self.program_is_running: + resp = self.start_program_client.call(ProgramIdTriggerRequest(program_id=self.demo_program)) + if not resp.success: + rospy.logerr("Demo program could not be launched!") + self.program_is_running = True + self.program_is_paused = False + + +if __name__ == '__main__': + rospy.init_node('control_program_run') + ''',log_level=rospy.DEBUG''' + + try: + node = ControlProgramRun() + rospy.spin() + except rospy.ROSInterruptException: + pass diff --git a/art_presence_detector/src/node.cpp b/art_presence_detector/src/node.cpp new file mode 100644 index 0000000..4aec52d --- /dev/null +++ b/art_presence_detector/src/node.cpp @@ -0,0 +1,191 @@ +#include +// PCL specific includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + + +typedef pcl::PointXYZRGB PointType; +typedef pcl::PointCloud PointCloud; +typedef PointCloud::Ptr PointCloudPtr; + +class ClusterDetector { +public: + ClusterDetector() : spinner(4){ + sub = nh.subscribe ("/kinect2/qhd/points", 1, &ClusterDetector::cloud_cb, this); + + // Create a ROS publisher for the output point cloud + pub = nh.advertise ("/output", 1); + vis_pub = nh.advertise ("/visualization", 1); + user_pub = nh.advertise ("/art/interface/user/present", 1); + spinner.start(); + } + +private: + ros::Publisher pub; + ros::Publisher user_pub; + ros::Publisher vis_pub; + ros::Subscriber sub; + tf::TransformListener listener_; + ros::NodeHandle nh; + ros::AsyncSpinner spinner; + + + + void cloud_cb (const sensor_msgs::PointCloud2ConstPtr& input) + { + ros::Time begin = ros::Time::now(); + + ROS_INFO_STREAM_ONCE("First point cloud arrived"); + // Create a container for the data. + + sensor_msgs::PointCloud2 output; + pcl::PCLPointCloud2 temp_cloud; + pcl::IndicesPtr indices1 (new std::vector ), indices2 (new std::vector ); + pcl_conversions::toPCL(*input, temp_cloud); + //temp_cloud.header.stamp = ros::Time::now().toSec()*1000000; + PointCloudPtr pc(new PointCloud); + pcl::fromPCLPointCloud2(temp_cloud, *pc); + PointCloudPtr pc_transformed(new PointCloud); + + + listener_.waitForTransform(input->header.frame_id, "/marker", + input->header.stamp, ros::Duration(2)); + + pcl_ros::transformPointCloud("/marker", *pc, *pc_transformed, listener_); + + + pcl::search::Search ::Ptr tree = boost::shared_ptr > (new pcl::search::KdTree); + + std::vector cluster_indices; + pcl::EuclideanClusterExtraction ec; + PointCloudPtr pc_filtered(new PointCloud); + + pcl::PassThrough pass; + pass.setInputCloud(pc_transformed); + pass.setFilterFieldName("x"); + pass.setFilterLimits(-0.2,1.2); + pass.filter(*indices1); + + pass.setIndices(indices1); + pass.setFilterFieldName("y"); + pass.setFilterLimits(-2,0); + pass.filter(*indices2); + + pass.setIndices(indices2); + pass.setFilterFieldName("z"); + pass.setFilterLimits(-1,1); + pass.filter(*indices1); + + + + pcl::ExtractIndices extract; + extract.setInputCloud(pc); + extract.setIndices(indices1); + extract.filter(*pc_filtered); + + pcl::VoxelGrid sor; + sor.setInputCloud(pc_filtered); + sor.setLeafSize (0.01f, 0.01f, 0.01f); + sor.filter (*pc_filtered); + + + ec.setClusterTolerance (0.05); + ec.setMinClusterSize (100); + ec.setMaxClusterSize (10500); + ec.setSearchMethod (tree); + ec.setInputCloud (pc_filtered); + ec.extract (cluster_indices); + + art_msgs::ObjectsCentroids centroids; + centroids.header.frame_id = "/marker"; + + std::cout << "Clusters: " << cluster_indices.size() << std::endl; + if (cluster_indices.size() > 0) { + user_pub.publish(true); + } else { + user_pub.publish(false); + } + + int j = 0; + for (std::vector::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it) + { + + Eigen::Vector4f centroid; + pcl::compute3DCentroid(*pc_filtered, it->indices, centroid); + visualization_msgs::Marker marker; + marker.header.frame_id = "/kinect2_ir_optical_frame"; + marker.header.stamp = ros::Time::now(); + marker.ns = "my_namespace"; + marker.id = j; + marker.type = visualization_msgs::Marker::SPHERE; + marker.action = visualization_msgs::Marker::ADD; + marker.pose.position.x = centroid[0]; + marker.pose.position.y = centroid[1]; + marker.pose.position.z = centroid[2]; + marker.pose.orientation.x = 0.0; + marker.pose.orientation.y = 0.0; + marker.pose.orientation.z = 0.0; + marker.pose.orientation.w = 1.0; + marker.scale.x = 0.03; + marker.scale.y = 0.03; + marker.scale.z = 0.03; + marker.color.a = 1.0; // Don't forget to set the alpha! + marker.color.r = 0.0; + marker.color.g = 1.0; + marker.color.b = 0.0; + + vis_pub.publish( marker ); + j++; + + + + + } + + + //ROS_INFO_STREAM("size: " << pc_filtered->size()); + if (pc_filtered->size() > 0) { + pcl::toROSMsg(*pc_filtered, output); + pub.publish(output); + } + + std::cout << "Processing time: " << ros::Time::now() - begin << std::endl; + } + +}; + + +int main (int argc, char** argv) +{ + // Initialize ROS + ros::init (argc, argv, "art_cluster_detector_node"); + + + ClusterDetector detector; + + // Create a ROS subscriber for the input point cloud + + + // Spin + ros::waitForShutdown(); + +}