spawn_object.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 
17 
18 import sys
19 import os
20 
21 import roslib
22 import rospy
23 import copy
24 import math
25 
26 from gazebo_msgs.srv import SpawnModel, SpawnModelRequest, DeleteModel, DeleteModelRequest, GetWorldProperties
27 from geometry_msgs.msg import Pose
28 import tf.transformations as tft
29 
30 parents = {}
31 compound_keys={}
32 
33 def get_flat_dict(objects, parent_name):
34  """expands all objects to a flat dictionary"""
35  flat_objects = {}
36  for key, value in objects.items():
37  # check if we have an atomic object
38 
39  if(parent_name!=None):
40 
41  if('parent_name' not in parents):
42  parents[key] = parent_name
43 
44  compound_keys[parent_name] = parent_name
45 
46  compound_keys[key] = compound_keys[parent_name] + '_' + key
47 
48  else:
49  compound_keys[key] = key
50 
51  if "children" in value:
52  # add parent object without children to flat_objects
53  tmp_value = copy.deepcopy(value)
54  to_process = tmp_value["children"]
55 
56  # add position and orientation of parent to all children
57  for child_key, child_value in tmp_value["children"].items():
58  yaw = objects[key]["orientation"][2]
59  x = objects[key]["position"][0] + math.cos(yaw) * child_value["position"][0] - math.sin(yaw) * child_value["position"][1]
60  y = objects[key]["position"][1] + math.sin(yaw) * child_value["position"][0] + math.cos(yaw) * child_value["position"][1]
61  child_value["position"][0] = x
62  child_value["position"][1] = y
63  child_value["position"][2] = objects[key]["position"][2] + child_value["position"][2]
64  child_value["orientation"][2] = yaw + child_value["orientation"][2]
65  del tmp_value["children"]
66  flat_objects.update({compound_keys[key]:tmp_value})
67  # add flattened children to flat_objects
68  flat_objects.update(get_flat_dict(to_process, compound_keys[key]))
69 
70  else:
71  # add object to flat_objects
72  flat_objects.update({compound_keys[key]:value})
73 
74  return flat_objects
75 
76 if __name__ == "__main__":
77  if len(sys.argv) < 2:
78  print('[spawn_object.py] Please specify the names of the objects to be loaded')
79  sys.exit()
80 
81  rospy.init_node("object_spawner")
82 
83  # check for all objects on parameter server
84  if not rospy.has_param("/objects"):
85  rospy.logerr("No objects uploaded to /objects")
86  sys.exit()
87  objects = rospy.get_param("/objects")
88  flat_objects = get_flat_dict(objects,None)
89 
90  # check for all object groups on parameter server
91  if rospy.has_param("/object_groups"):
92  groups = rospy.get_param("/object_groups")
93  else:
94  groups = {}
95  rospy.loginfo('No object-groups uploaded to /object_groups')
96 
97  # if keyword all is in list of object names we'll load all models uploaded to parameter server
98  if "all" in sys.argv:
99  objects = flat_objects
100  elif not set(groups.keys()).isdisjoint(sys.argv):
101  # get all key that are in both, the dictionary and argv
102  found_groups = set(groups.keys()) & set(sys.argv)
103  # get all object_names from keys that are in argv
104  object_names = [groups[k] for k in found_groups]
105  # flatten list of lists 'object_names' to a list
106  object_names = [item for sublist in object_names for item in sublist]
107  # save all dict-objects with names in 'object_names' in 'objects'
108  objects = {}
109  for object_name in object_names:
110  if object_name in list(flat_objects.keys()):
111  objects.update({object_name:flat_objects[object_name]})
112  elif sys.argv[1] not in list(flat_objects.keys()):
113  rospy.logerr("Object %s not found", sys.argv[1])
114  sys.exit()
115  else:
116  objects = {sys.argv[1]:flat_objects[sys.argv[1]]}
117 
118  rospy.loginfo("Trying to spawn %s", list(objects.keys()))
119 
120  # get all current models from gazebo
121  # check if object is already spawned
122  try:
123  rospy.wait_for_service('/gazebo/get_world_properties', 30)
124  except rospy.exceptions.ROSException:
125  rospy.logerr("Service /gazebo/get_world_properties not available.")
126  sys.exit()
127 
128  srv_get_world_properties = rospy.ServiceProxy('/gazebo/get_world_properties', GetWorldProperties)
129 
130  try:
131  world_properties = srv_get_world_properties()
132  except rospy.ServiceException as exc:
133  rospy.logerr("Service did not process request: " + str(exc))
134 
135  if world_properties.success:
136  existing_models = world_properties.model_names
137  else:
138  existing_models = []
139 
140  # Iterate through all objects
141  for key, value in objects.items():
142  # check for model
143  if not "model" in value:
144  rospy.logerr("No model for " + key + " found.")
145  continue
146  model_string = value["model"]
147  model_package = model_string.split("/")[0]
148  model_path = model_string.replace(model_package + "/", "")
149  model_type = model_string.split(".").pop()
150 
151  # check for position
152  if not "position" in value:
153  rospy.logerr("No position for " + key + " found.")
154  continue
155  position = value["position"]
156 
157  # check for orientation
158  if not "orientation" in value:
159  rospy.logerr("No orientation for " + key + " found.")
160  continue
161  # convert rpy to quaternion for Pose message
162  orientation = value["orientation"]
163  quaternion = tft.quaternion_from_euler(orientation[0], orientation[1], orientation[2])
164 
165  # compose pose of object
166  object_pose = Pose()
167  object_pose.position.x = float(position[0])
168  object_pose.position.y = float(position[1])
169  object_pose.position.z = float(position[2])
170  object_pose.orientation.x = quaternion[0]
171  object_pose.orientation.y = quaternion[1]
172  object_pose.orientation.z = quaternion[2]
173  object_pose.orientation.w = quaternion[3]
174 
175  # get file location
176  try:
177  file_location = roslib.packages.get_pkg_dir(model_package) + "/" + model_path
178  except roslib.packages.InvalidROSPkgException:
179  rospy.logerr("No model package found for " + key + ": " + model_package + " does not exist in ROS_PACKAGE_PATH")
180  continue
181 
182  # open file for urdf.xacro or urdf/sdf/model
183  if model_type == "xacro":
184  try:
185  xacro_args = '--inorder' if (os.environ['ROS_DISTRO'] < 'melodic') else ''
186  f = os.popen("xacro "+ xacro_args + " " + file_location)
187  except:
188  rospy.logerr("No xacro file found for " + key + " at " + file_location)
189  continue
190  model_type = "urdf"
191  elif model_type in ['urdf', 'sdf', 'model']:
192  try:
193  f = open(file_location)
194  except:
195  rospy.logerr("No model file found for " + key + " at " + file_location)
196  continue
197  else:
198  rospy.logerr('Model type not known. model_type = ' + model_type)
199  continue
200 
201  # read and close file
202  xml_string = f.read()
203  f.close()
204 
205  # open spawn service
206  try:
207  rospy.wait_for_service('/gazebo/spawn_'+model_type+'_model',30)
208  except rospy.exceptions.ROSException:
209  rospy.logerr("Service /gazebo/spawn_"+model_type+"_model not available.")
210  sys.exit()
211  srv_spawn_model = rospy.ServiceProxy('/gazebo/spawn_'+model_type+'_model', SpawnModel)
212 
213  # delete model if it already exists
214  if key in existing_models:
215  srv_delete_model = rospy.ServiceProxy('gazebo/delete_model', DeleteModel) # TODO this service causes gazebo (current groovy version) to crash
216  try:
217  res = srv_delete_model(key)
218  except rospy.ServiceException:
219  rospy.logdebug("Error while trying to call Service /gazebo/get_world_properties.")
220  rospy.loginfo("Model %s already exists in gazebo. Model will be deleted and added again.", key)
221 
222  # spawn new model
223  req = SpawnModelRequest()
224  req.model_name = key # model name from command line input
225  req.model_xml = xml_string
226  req.initial_pose = object_pose
227 
228  try:
229  res = srv_spawn_model(req)
230  except rospy.service.ServiceException:
231  break
232 
233  # evaluate response
234  if res.success == True:
235  rospy.loginfo(res.status_message + " " + key)
236  else:
237  rospy.logerr("Error: model %s not spawn. error message = "% key + res.status_message)
238 
def get_flat_dict(objects, parent_name)
Definition: spawn_object.py:33


cob_gazebo_tools
Author(s): Felix Messmer , Nadia Hammoudeh Garcia , Florian Weisshardt
autogenerated on Sat Dec 5 2020 03:59:48