laser.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Copyright (C) 2014 Aldebaran Robotics
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 
19 #import ROS dependencies
20 import rospy
21 from sensor_msgs.msg import PointCloud2, PointField
22 
23 # navigation test
24 from sensor_msgs.msg import LaserScan
25 
26 #import PEPPER dependencies
27 from naoqi_driver.naoqi_node import NaoqiNode
28 
29 #general
30 import copy
31 import math
32 import struct
33 
34 #PEPPER specifications:
35 #https://community.aldebaran.com/doc/1-14/family/robots/laser_robot.html
37 
38  # PEPPER laser specs
39  # see https://community.aldebaran.com/doc/2-1/family/juliette_technical/laser_juliette.html#juliette-laser
40  PEPPER_LASER_FREQ = 6 # [hZ] --> check on that
41  PEPPER_LASER_MIN_ANGLE = -0.523598776 # [rad]
42  PEPPER_LASER_MAX_ANGLE = 0.523598776 # [radi]
43  PEPPER_LASER_FOV = math.fabs(PEPPER_LASER_MIN_ANGLE)+math.fabs(PEPPER_LASER_MAX_ANGLE)
44 
45  PEPPER_LASER_MIN_RANGE = 0.1 # [m] --> no spec given here
46  PEPPER_LASER_MAX_RANGE = 5.0 # [m] --> same here, 5m as quality guess
47 
48  # FRONT GROUND LASERS
49  PEPPER_LASER_GROUND_SHOVEL_POINTS = 3
50  PEPPER_LASER_GROUND_LEFT_POINTS = 1
51  PEPPER_LASER_GROUND_RIGHT_POINTS = 1
52  # SURROUNDING LASER
53  PEPPER_LASER_SRD_POINTS = 15
54 
55  # memory key to fetch laser readings from
56  # see memory key listing https://community.aldebaran.com/doc/2-1/family/juliette_technical/juliette_dcm/actuator_sensor_names.html#lasers
57  # iterate over all segments e.g./SubDeviceList/Platform/LaserSensor/Front/Shovel/Seg01/X/Value
58  PEPPER_MEM_KEY_GROUND_SHOVEL = 'Device/SubDeviceList/Platform/LaserSensor/Front/Shovel/'
59  PEPPER_MEM_KEY_GROUND_LEFT = 'Device/SubDeviceList/Platform/LaserSensor/Front/Vertical/Left/'
60  PEPPER_MEM_KEY_GROUND_RIGHT = 'Device/SubDeviceList/Platform/LaserSensor/Front/Vertical/Right/'
61  PEPPER_MEM_KEY_SRD_FRONT = 'Device/SubDeviceList/Platform/LaserSensor/Front/Horizontal/'
62  PEPPER_MEM_KEY_SRD_LEFT = 'Device/SubDeviceList/Platform/LaserSensor/Left/Horizontal/'
63  PEPPER_MEM_KEY_SRD_RIGHT = 'Device/SubDeviceList/Platform/LaserSensor/Right/Horizontal/'
64 
65  # ROS params to check
66  # acc. to spec: 40 kHz
67  PARAM_LASER_RATE = '~laser_rate'
68  PARAM_LASER_RATE_DEFAULT = PEPPER_LASER_FREQ
69 
70  # frame id to publish
71  PARAM_LASER_SHOVEL_FRAME = '~laser_shovel_frame_id'
72  PARAM_LASER_SHOVEL_FRAME_DEFAULT = 'ShovelLaser_frame'
73 
74  PARAM_LASER_GROUND_LEFT_FRAME = '~laser_ground_left_frame_id'
75  PARAM_LASER_GROUND_LEFT_FRAME_DEFAULT = 'VerticalLeftLaser_frame'
76 
77  PARAM_LASER_GROUND_RIGHT_FRAME = '~laser_ground_right_frame_id'
78  PARAM_LASER_GROUND_RIGHT_FRAME_DEFAULT = 'VerticalRightLaser_frame'
79 
80  PARAM_LASER_SRD_FRONT_FRAME = '~laser_srd_front_frame_id'
81  PARAM_LASER_SRD_FRONT_FRAME_DEFAULT = 'SurroundingFrontLaser_frame'
82 
83  PARAM_LASER_SRD_LEFT_FRAME = '~laser_srd_left_frame_id'
84  PARAM_LASER_SRD_LEFT_FRAME_DEFAULT = 'SurroundingLeftLaser_frame'
85 
86  PARAM_LASER_SRD_RIGHT_FRAME = '~laser_srd_right_frame_id'
87  PARAM_LASER_SRD_RIGHT_FRAME_DEFAULT = 'SurroundingRightLaser_frame'
88 
89  TOPIC_LASER_SHOVEL = '~/laser/shovel/'
90  TOPIC_LASER_GROUND_LEFT = '~/laser/ground_left/'
91  TOPIC_LASER_GROUND_RIGHT = '~/laser/ground_right/'
92  TOPIC_LASER_SRD_FRONT = '~/laser/srd_front/'
93  TOPIC_LASER_SRD_LEFT = '~/laser/srd_left/'
94  TOPIC_LASER_SRD_RIGHT = '~/laser/srd_right/'
95 
96  PEPPER_LASER_SUB_NAME = 'pepper_ros_laser'
97 
98  def __init__(self, pointcloud=True, laserscan=False):
99  self.pointcloud = pointcloud
100  self.laserscan = laserscan
101 
102  NaoqiNode.__init__(self, 'pepper_node')
103 
104  # ROS initialization;
105  self.connectNaoQi()
106 
107  # default sensor rate: 25 Hz (50 is max, stresses Nao's CPU)
108  self.laserRate = rospy.Rate(rospy.get_param(
109  self.PARAM_LASER_RATE,
111 
112  self.laserShovelFrame = rospy.get_param(
115  self.laserGroundLeftFrame = rospy.get_param(
118  self.laserGroundRightFrame = rospy.get_param(
121  self.laserSRDFrontFrame = rospy.get_param(
124  self.laserSRDLeftFrame = rospy.get_param(
127  self.laserSRDRightFrame = rospy.get_param(
130 
131  if self.pointcloud:
132  self.pcShovelPublisher = rospy.Publisher(self.TOPIC_LASER_SHOVEL+'pointcloud', PointCloud2, queue_size=1)
133  self.pcGroundLeftPublisher = rospy.Publisher(self.TOPIC_LASER_GROUND_LEFT+'pointcloud', PointCloud2, queue_size=1)
134  self.pcGroundRightPublisher = rospy.Publisher(self.TOPIC_LASER_GROUND_RIGHT+'pointcloud', PointCloud2, queue_size=1)
135  self.pcSRDFrontPublisher = rospy.Publisher(self.TOPIC_LASER_SRD_FRONT+'pointcloud', PointCloud2, queue_size=1)
136  self.pcSRDLeftPublisher = rospy.Publisher(self.TOPIC_LASER_SRD_LEFT+'pointcloud', PointCloud2, queue_size=1)
137  self.pcSRDRightPublisher = rospy.Publisher(self.TOPIC_LASER_SRD_RIGHT+'pointcloud', PointCloud2, queue_size=1)
138 
139  if self.laserscan:
140  self.laserShovelPublisher = rospy.Publisher(self.TOPIC_LASER_SHOVEL+'scan', LaserScan, queue_size=1)
141  self.laserGroundLeftPublisher = rospy.Publisher(self.TOPIC_LASER_GROUND_LEFT+'scan', LaserScan, queue_size=1)
142  self.laserGroundRightPublisher = rospy.Publisher(self.TOPIC_LASER_GROUND_RIGHT+'scan', LaserScan, queue_size=1)
143  self.laserSRDFrontPublisher = rospy.Publisher(self.TOPIC_LASER_SRD_FRONT+'scan', LaserScan, queue_size=1)
144  self.laserSRDLeftPublisher = rospy.Publisher(self.TOPIC_LASER_SRD_LEFT+'scan', LaserScan, queue_size=1)
145  self.laserSRDRightPublisher = rospy.Publisher(self.TOPIC_LASER_SRD_RIGHT+'scan', LaserScan, queue_size=1)
146 
147  self.laserSRDFrontPublisher_test = rospy.Publisher("~/pepper_navigation/front", LaserScan, queue_size=1)
148 
149  # (re-) connect to NaoQI:
150  def connectNaoQi(self):
151  rospy.loginfo("Connecting to NaoQi at %s:%d", self.pip, self.pport)
152  self.laserProxy = self.get_proxy("ALLaser")
153  self.memProxy = self.get_proxy("ALMemory")
154  if self.laserProxy is None or self.memProxy is None:
155  print "could not start either laser or memory proxy"
156  exit(1)
157 
158  # fetch laser values
159  ''' the idea here is to get the point xy
160  calculate the length from the origin (range)
161  assumption: field of view spanning from very min to very max
162  '''
163  def fetchLaserValues(self, keyPrefix, scanNum):
164  ranges = []
165  # traverse backwards
166  tmp_array = []
167  for i in xrange(scanNum, 0, -1):
168  keyX = keyPrefix + 'Seg' + '%02d' % (i,) + '/X/Sensor/Value'
169  keyY = keyPrefix + 'Seg' + '%02d' % (i,) + '/Y/Sensor/Value'
170  tmp_array.append(keyX)
171  tmp_array.append(keyY)
172  memData = self.memProxy.getListData(tmp_array)
173  for i in xrange(0, len(tmp_array), 2):
174  x = memData[i]
175  y = memData[i+1]
176  ranges.append(math.sqrt(math.pow(x, 2.0) + math.pow(y, 2.0)))
177  return ranges
178 
179  def fetchPCValues(self, keyPrefix, scanNum):
180  scans = []
181  for i in xrange(scanNum,0,-1):
182  keyX = keyPrefix+'Seg'+'%02d'%(i,)+'/X/Sensor/Value'
183  keyY = keyPrefix+'Seg'+'%02d'%(i,)+'/Y/Sensor/Value'
184  x = self.memProxy.getData(keyX)
185  y = self.memProxy.getData(keyY)
186  scans.append(x)
187  scans.append(y)
188  scans.append(0.0)
189  ba = struct.pack('%sf' %len(scans), *scans)
190  return ba
191 
192  def createPointCloudMessage(self, frameID, keyPrefix, scanNum):
193  pointCloudMsg = PointCloud2()
194  pointCloudMsg.header.frame_id = frameID
195  pointCloudMsg.header.stamp = rospy.Time.now()
196  pointCloudMsg.height = 1
197  pointCloudMsg.width = scanNum
198  pointCloudMsg.is_dense = False
199  pointCloudMsg.is_bigendian = False
200  pointCloudMsg.fields = [PointField('x', 0, PointField.FLOAT32, 1),
201  PointField('y', 4, PointField.FLOAT32, 1),
202  PointField('z', 8, PointField.FLOAT32, 1)]
203  pointCloudMsg.point_step = 4*3
204  pointCloudMsg.row_step = pointCloudMsg.point_step* pointCloudMsg.width
205  pointCloudMsg.data = self.fetchLaserValues(keyPrefix, scanNum)
206  return pointCloudMsg
207 
208  def createLaserMessage(self, frameID, keyPrefix, scanNum):
209  laserScanMsg = LaserScan()
210  laserScanMsg.header.frame_id = frameID
211  laserScanMsg.angle_min = self.PEPPER_LASER_MIN_ANGLE
212  laserScanMsg.angle_max = self.PEPPER_LASER_MAX_ANGLE
213  laserScanMsg.angle_increment = self.PEPPER_LASER_FOV/scanNum
214  laserScanMsg.range_min = self.PEPPER_LASER_MIN_RANGE
215  laserScanMsg.range_max = self.PEPPER_LASER_MAX_RANGE
216  return laserScanMsg
217 
218  # do it!
219  def run(self):
220  # start subscriber to laser sensor
221  #self.laserProxy.subscribe(self.PEPPER_LASER_SUB_NAME)
222 
223  # we publish 6 laser messages in total
224  # 1. shovel, 2. ground_left, 3. ground_right
225  # 4. srd_front 5. srd_left 6. srd_right
226  if self.pointcloud:
227  shovelPC = self.createPointCloudMessage(
228  self.laserShovelFrame,
231  groundLeftPC = self.createPointCloudMessage(
235  groundRightPC = self.createPointCloudMessage(
239  srdFrontPC = self.createPointCloudMessage(
240  self.laserSRDFrontFrame,
243  srdLeftPC = self.createPointCloudMessage(
244  self.laserSRDLeftFrame,
247  srdRightPC = self.createPointCloudMessage(
248  self.laserSRDRightFrame,
251 
252  if self.laserscan:
253  shovelScan = self.createLaserMessage(
254  self.laserShovelFrame,
257  groundLeftScan = self.createLaserMessage(
261  groundRightScan = self.createLaserMessage(
265  srdFrontScan = self.createLaserMessage(
266  self.laserSRDFrontFrame,
269  srdLeftScan = self.createLaserMessage(
270  self.laserSRDLeftFrame,
273  srdRightScan = self.createLaserMessage(
274  self.laserSRDRightFrame,
277 
278  while(self.is_looping()):
279 
280  if self.laserscan:
281  # fetch values
282  shovelScan.header.stamp = rospy.Time.now()
283  shovelScan.ranges = self.fetchLaserValues(
286  )
287 
288  groundLeftScan.header.stamp = rospy.Time.now()
289  groundLeftScan.ranges = self.fetchLaserValues(
292  )
293 
294  groundRightScan.header.stamp = rospy.Time.now()
295  groundRightScan.ranges = self.fetchLaserValues(
298  )
299 
300  srdFrontScan.header.stamp = rospy.Time.now()
301  srdFrontScan.ranges = self.fetchLaserValues(
304  )
305 
306  srdLeftScan.header.stamp = rospy.Time.now()
307  srdLeftScan.ranges = self.fetchLaserValues(
310  )
311 
312  srdRightScan.header.stamp = rospy.Time.now()
313  srdRightScan.ranges = self.fetchLaserValues(
316  )
317 
318  # publish messages
319  self.laserShovelPublisher.publish(shovelScan)
320  self.laserGroundLeftPublisher.publish(groundLeftScan)
321  self.laserGroundRightPublisher.publish(groundRightScan)
322  self.laserSRDFrontPublisher.publish(srdFrontScan)
323  self.laserSRDLeftPublisher.publish(srdLeftScan)
324  self.laserSRDRightPublisher.publish(srdRightScan)
325 
326 
327  if self.pointcloud:
328  # fetch values
329  shovelPC.header.stamp = rospy.Time.now()
330  shovelPC.data = self.fetchPCValues(
333  )
334 
335  groundLeftPC.header.stamp = rospy.Time.now()
336  groundLeftPC.data = self.fetchPCValues(
339  )
340 
341  groundRightPC.header.stamp = rospy.Time.now()
342  groundRightPC.data = self.fetchPCValues(
345  )
346 
347  srdFrontPC.header.stamp = rospy.Time.now()
348  srdFrontPC.data = self.fetchPCValues(
351  )
352 
353  srdLeftPC.header.stamp = rospy.Time.now()
354  srdLeftPC.data = self.fetchPCValues(
357  )
358 
359  srdRightPC.header.stamp = rospy.Time.now()
360  srdRightPC.data = self.fetchPCValues(
363  )
364 
365  # publish messages
366  self.pcShovelPublisher.publish(shovelPC)
367  self.pcGroundLeftPublisher.publish(groundLeftPC)
368  self.pcGroundRightPublisher.publish(groundRightPC)
369  self.pcSRDFrontPublisher.publish(srdFrontPC)
370  self.pcSRDLeftPublisher.publish(srdLeftPC)
371  self.pcSRDRightPublisher.publish(srdRightPC)
372 
373  #sleep
374  self.laserRate.sleep()
375 
376 
377 if __name__ == '__main__':
378 # from optparse import OptionParser
379 # parser = OptionParser()
380 # parser.add_option("--ppointcloud", dest="ppointcloud", default=True)
381 # parser.add_option("--plaser", dest="plaser", default=False)
382 #
383 # (options, args) = parser.parse_args()
384 # with_pc = options.ppointcloud
385 # with_laser = options.plaser
386 
387  with_pc = True
388  with_laser = True
389  laser = NaoqiLaser(with_pc, with_laser)
390  laser.start()
391 
392  rospy.spin()
393  exit(0)
string PARAM_LASER_SRD_FRONT_FRAME_DEFAULT
Definition: laser.py:81
int PEPPER_LASER_SRD_POINTS
Definition: laser.py:53
float PEPPER_LASER_MIN_RANGE
Definition: laser.py:45
string PARAM_LASER_SRD_RIGHT_FRAME
Definition: laser.py:86
laserSRDFrontPublisher
Definition: laser.py:143
pcGroundRightPublisher
Definition: laser.py:134
def fetchPCValues(self, keyPrefix, scanNum)
Definition: laser.py:179
int PEPPER_LASER_GROUND_LEFT_POINTS
Definition: laser.py:50
string PEPPER_MEM_KEY_GROUND_RIGHT
Definition: laser.py:60
string PARAM_LASER_GROUND_RIGHT_FRAME
Definition: laser.py:77
string PARAM_LASER_SRD_RIGHT_FRAME_DEFAULT
Definition: laser.py:87
string TOPIC_LASER_GROUND_RIGHT
Definition: laser.py:91
def run(self)
Definition: laser.py:219
laserSRDRightPublisher
Definition: laser.py:145
float PEPPER_LASER_MIN_ANGLE
Definition: laser.py:41
string PARAM_LASER_SRD_LEFT_FRAME_DEFAULT
Definition: laser.py:84
float PEPPER_LASER_MAX_RANGE
Definition: laser.py:46
string TOPIC_LASER_SHOVEL
Definition: laser.py:89
laserGroundRightPublisher
Definition: laser.py:142
string PARAM_LASER_GROUND_RIGHT_FRAME_DEFAULT
Definition: laser.py:78
int PEPPER_LASER_GROUND_RIGHT_POINTS
Definition: laser.py:51
string TOPIC_LASER_SRD_RIGHT
Definition: laser.py:94
string PARAM_LASER_SHOVEL_FRAME_DEFAULT
Definition: laser.py:72
PARAM_LASER_RATE_DEFAULT
Definition: laser.py:68
string PARAM_LASER_GROUND_LEFT_FRAME_DEFAULT
Definition: laser.py:75
string PARAM_LASER_SRD_FRONT_FRAME
Definition: laser.py:80
string TOPIC_LASER_SRD_FRONT
Definition: laser.py:92
string PEPPER_MEM_KEY_SRD_FRONT
Definition: laser.py:61
string PEPPER_MEM_KEY_GROUND_SHOVEL
Definition: laser.py:58
laserGroundLeftPublisher
Definition: laser.py:141
float PEPPER_LASER_MAX_ANGLE
Definition: laser.py:42
string PEPPER_MEM_KEY_SRD_LEFT
Definition: laser.py:62
def fetchLaserValues(self, keyPrefix, scanNum)
Definition: laser.py:163
string PEPPER_MEM_KEY_GROUND_LEFT
Definition: laser.py:59
laserSRDFrontPublisher_test
Definition: laser.py:147
string PARAM_LASER_SHOVEL_FRAME
Definition: laser.py:71
string PARAM_LASER_GROUND_LEFT_FRAME
Definition: laser.py:74
string PARAM_LASER_RATE
Definition: laser.py:67
string PEPPER_MEM_KEY_SRD_RIGHT
Definition: laser.py:63
def connectNaoQi(self)
Definition: laser.py:150
def createLaserMessage(self, frameID, keyPrefix, scanNum)
Definition: laser.py:208
int PEPPER_LASER_GROUND_SHOVEL_POINTS
Definition: laser.py:49
string TOPIC_LASER_GROUND_LEFT
Definition: laser.py:90
def get_proxy(self, name, warn=True)
string TOPIC_LASER_SRD_LEFT
Definition: laser.py:93
string PARAM_LASER_SRD_LEFT_FRAME
Definition: laser.py:83
def createPointCloudMessage(self, frameID, keyPrefix, scanNum)
Definition: laser.py:192
def __init__(self, pointcloud=True, laserscan=False)
Definition: laser.py:98


pepper_sensors_py
Author(s): Karsten Knese
autogenerated on Mon Jun 10 2019 14:18:56