object_detection.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 '''
4 Copyright (c) 2016, Allgeyer Tobias, Aumann Florian, Borella Jocelyn, Hutmacher Robin, Karrenbauer Oliver, Marek Felix, Meissner Pascal, Trautmann Jeremias, Wittenbeck Valerij
5 
6 All rights reserved.
7 
8 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
11 
12 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.
13 
14 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
15 
16 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.
17 '''
18 
19 import roslib
20 import rospy
21 import smach
22 import smach_ros
23 import time
24 import tf
25 import move
26 import sys
27 
28 from asr_msgs.msg import AsrObject, AsrViewport
29 from geometry_msgs.msg import (Pose, PoseWithCovariance,
30  PoseWithCovarianceStamped, Point, Quaternion, PoseStamped)
31 from asr_world_model.srv import PushFoundObject, PushFoundObjectList, GetMissingObjectList, PushViewport
32 from common.evaluation_decorators import *
33 from object_detectors_manager import ObjectDetectorsManager
34 import state_acquisition
35 
36 class ObjectDetection(smach.State):
37  """
38  Tries to detect given searched_object_types in current_camera_pose.
39  If no current_camera_pose is given, it is determined via tf.
40  """
41  # Keeps actual AsrObjects
42  #Required to transmit detected objects to other states.
43  detected_objects = set()
44  #Objects still searched (type and id).
45  missing_pbd_typeAndId = []
46 
47  current_camera_pose = None
48 
49  global numberOfObjectDetectionRuns
50  numberOfObjectDetectionRuns = 0
51  global numberOfAllSearchedObjectTypes
52  numberOfAllSearchedObjectTypes = 0
53 
54  def __init__(self):
55  smach.State.__init__(
56  self,
57  outcomes=['found_objects', 'aborted', 'no_objects_found'],
58  input_keys=['searched_object_types'],
59  output_keys=['detected_objects'])
60  self.isInitDone = 0
61 
62  def detection_callback(self, data):
63  #Do not accept estimates from objects not being part of any searched scene
64  if not any(typeAndId.type == data.type and typeAndId.identifier == data.identifier for typeAndId in self.missing_pbd_typeAndId):
65  rospy.loginfo("Object with id " + data.identifier + " and type " + data.type + " is not missing in any scene, we look for.")
66  return
67  if not any(object.type == data.type and object.identifier == data.identifier for object in self.detected_objects):
68  #found object for the first time
69  rospy.loginfo("Received at least one estimate for object with type=" + data.type + " and id=" + data.identifier)
70  if ( len(data.sampledPoses) == 0 ):
71  rospy.logerr("ObjectDetection got AsrObject message, not containing any poses.")
72  sys.exit(1)
73 
74  # frustum culling
75  # Note that this is over simplified frustum culling just used to
76  # filter some very bad outliers.
77  # Here we just put a bounding box around the camera
78  is_valid = (abs(data.sampledPoses[0].pose.position.x) < 0.4 and
79  abs(data.sampledPoses[0].pose.position.y) < 0.4 and
80  data.sampledPoses[0].pose.position.z < self.fcp*1.1 and
81  data.sampledPoses[0].pose.position.z > self.ncp*0.9)
82  if not is_valid:
83  rospy.loginfo("An object estimate for "+str(data.type)+" rejected, since classified as outlier.")
84  return
85 
86  # Construct FoundObject to push to world_model
87  # objects are transformed to map frame in world_model
88  rospy.logdebug("Pushing object estimate " + str(data.type) + " into return lists and world model lists.")
89  self.detected_objects.add(data)
90 
91  def initNode(self):
92  rospy.loginfo('Init OBJECT_DETECTION')
93  self.isInitDone = 1
95  try:
96  self.ncp = rospy.get_param("/nbv/ncp")
97  self.fcp = rospy.get_param("/nbv/fcp")
98  self.fovx = rospy.get_param("/nbv/fovx")
99  self.fovy = rospy.get_param("/nbv/fovy")
100  except Exception, e:
101  rospy.logwarn("Could not get parameters from nbv")
102  self.ncp = 0.4
103  self.fcp = 1.5
104  self.fovx = 30
105  self.fovy = 20
106 
107  @log
108  @key_press
109  @timed
110  def execute(self, userdata):
111  rospy.loginfo('Executing OBJECT_DETECTION')
112  if (self.isInitDone == 0):
113  self.initNode()
114 
115  # Return immediately if we have no objects to look for
116  if not 'searched_object_types' in userdata:
117  userdata.detected_objects = []
118  return 'no_objects_found'
119  if not userdata.searched_object_types:
120  return 'no_objects_found'
121 
122  #Acquire current pose of camera from tf tree.
123  self.current_camera_pose = state_acquisition.get_camera_pose_cpp()
124 
125  #Empty detection result list and missingTypeAndIds each time state is reached.
126  self.detected_objects.clear()
127  del self.missing_pbd_typeAndId[:]
128 
129  #check if searched_object_types is only one object type and transform to list
130  if not isinstance(userdata.searched_object_types, list):
131  self.searched_object_types = [userdata.searched_object_types]
132  else:
133  self.searched_object_types = userdata.searched_object_types
134 
135  #Push viewports to world_model
136  try:
137  rospy.wait_for_service('/env/asr_world_model/push_viewport', timeout=5)
138  push_viewport = rospy.ServiceProxy(
139  '/env/asr_world_model/push_viewport', PushViewport)
140  viewport = AsrViewport()
141  viewport.pose = self.current_camera_pose
142  viewport.object_type_name_list = self.searched_object_types
143  viewport.ncp = self.ncp
144  viewport.fcp = self.fcp
145  viewport.fovx = self.fovx
146  viewport.fovy = self.fovy
147  push_viewport(viewport)
148 
149  except (rospy.ServiceException, rospy.exceptions.ROSException), e:
150  rospy.logwarn(str(e))
151  rospy.logwarn("service exception from world_model")
152 
153  # Get all missing objects
154  try:
155  rospy.wait_for_service('/env/asr_world_model/get_missing_object_list', timeout=5)
156  get_missing_object_list =rospy.ServiceProxy(
157  '/env/asr_world_model/get_missing_object_list', GetMissingObjectList)
158  self.missing_pbd_typeAndId = get_missing_object_list().missingObjects
159 
160  except (rospy.ServiceException, rospy.exceptions.ROSException), e:
161  rospy.logwarn(str(e))
162  rospy.logwarn("service exception from world_model")
163  return 'no_objects_found'
164 
165  # We need to filter the search_objects in random/cropbox search mode
166  # cropbox record doesn't use object_detection
167  mode = rospy.get_param("/scene_exploration_sm/mode");
168  if mode == 4 or mode == 5:
169  self.searched_object_types = set()
170  for obj in self.missing_pbd_typeAndId:
171  self.searched_object_types.add(str(obj.type))
172 
173  global numberOfObjectDetectionRuns
174  global numberOfAllSearchedObjectTypes
175  numberOfObjectDetectionRuns += 1
176  numberOfAllSearchedObjectTypes += len(self.searched_object_types)
177  rospy.loginfo("Number of object detections: " + str(numberOfObjectDetectionRuns))
178  rospy.loginfo("Number of all searched_object_types: " + str(numberOfAllSearchedObjectTypes))
179  rospy.loginfo("Average number of searched_object_types per run: " + str((1.0 * numberOfAllSearchedObjectTypes / numberOfObjectDetectionRuns)))
180 
181  detectors_manager = ObjectDetectorsManager()
182  if detectors_manager.start_recognizers(self.searched_object_types) is 'aborted':
183  return 'aborted'
184  # wait till object detectors will be started
185  rospy.sleep(2.0)
186  # Listen for 'detection_duration * number_of_searched_object_types' seconds for detected objects
187  rospy.loginfo("All requested recognizers should now publish to " + "/stereo/objects")
188  wait_time = rospy.get_param("/nbv/speedFactorRecognizer")*len(self.searched_object_types)
189 
190  future = time() + wait_time
191  sub = rospy.Subscriber('/stereo/objects',
192  AsrObject,
193  self.detection_callback)
194  while (time() < future):
195  pass
196  # unregister, otherwise the callbacks are still called
197  sub.unregister()
198 
199  if detectors_manager.stop_recognizers(self.searched_object_types) is 'aborted':
200  rospy.loginfo("stop recog send aborted")
201  return 'aborted'
202 
203  rospy.loginfo("All recognizers are shut down.")
204 
205  if len(self.detected_objects) == 0:
206  userdata.detected_objects = list(self.detected_objects)
207  return 'no_objects_found'
208 
209  # Push to found objects in world model
210  rospy.loginfo("Pushing the following estimates to world_model.")
211  try:
212  for output_object in self.detected_objects:
213  rospy.loginfo("Got object estimate with type " + output_object.type + " and id " + output_object.identifier + " provided by " + output_object.providedBy)
214  rospy.loginfo("Its position is "
215  + "x: " + str(output_object.sampledPoses[0].pose.position.x)
216  + " y: " + str(output_object.sampledPoses[0].pose.position.y)
217  + " z: " + str(output_object.sampledPoses[0].pose.position.z) + " and its orientation is "
218  + "x: " + str(output_object.sampledPoses[0].pose.orientation.x)
219  + " y: " + str(output_object.sampledPoses[0].pose.orientation.y)
220  + " z: " + str(output_object.sampledPoses[0].pose.orientation.z)
221  + " w: " + str(output_object.sampledPoses[0].pose.orientation.w))
222 
223  rospy.wait_for_service('/env/asr_world_model/push_found_object_list',
224  timeout=3)
225  push_found_objects = rospy.ServiceProxy(
226  '/env/asr_world_model/push_found_object_list', PushFoundObjectList)
227  push_found_objects(list(self.detected_objects))
228  except (rospy.exceptions.ROSException, rospy.ServiceException) as e:
229  rospy.logwarn("Could not find world_model service")
230  return 'aborted'
231 
232  userdata.detected_objects = list(self.detected_objects)
233  return 'found_objects'


asr_state_machine
Author(s): Allgeyer Tobias, Aumann Florian, Borella Jocelyn, Hutmacher Robin, Karrenbauer Oliver, Marek Felix, Meißner Pascal, Trautmann Jeremias, Wittenbeck Valerij
autogenerated on Mon Feb 28 2022 21:53:50