test_camera.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # Software License Agreement (BSD License)
3 #
4 # Copyright (c) 2008, Willow Garage, Inc.
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 #
11 # * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above
14 # copyright notice, this list of conditions and the following
15 # disclaimer in the documentation and/or other materials provided
16 # with the distribution.
17 # * Neither the name of the Willow Garage nor the names of its
18 # contributors may be used to endorse or promote products derived
19 # from this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
33 #
34 
35 ## Gazebo test cameras validation
36 
37 PKG = 'pr2_gazebo'
38 NAME = 'test_camera'
39 
40 import math
41 import roslib
42 roslib.load_manifest(PKG)
43 roslib.load_manifest('rostest')
44 roslib.load_manifest('actionlib')
45 roslib.load_manifest('pr2_controllers_msgs')
46 
47 import sys, unittest
48 import os, os.path, threading, time
49 import rospy, rostest, string
50 from std_msgs.msg import Int32
51 from sensor_msgs.msg import Image as image_msg
52 from sensor_msgs.msg import CameraInfo as camerainfo_msg
53 from PIL import Image as pili
54 from PIL import ImageChops as pilic
55 from geometry_msgs.msg import PointStamped, Point, Vector3
56 from pr2_controllers_msgs.msg import PointHeadGoal, PointHeadAction
58 
59 #FRAME_TARGET = "cam_sen-0050.ppm"
60 FRAME_TARGET = "test_camera.valid.ppm"
61 FRAME_DIR = "test_camera_frames"
62 TOTAL_ERROR_TOL = 5
63 TEST_DURATION = 70
64 
65 class PollCameraThread(threading.Thread):
66  def __init__(self, target, dir):
67  super(PollCameraThread, self).__init__()
68  self.target = target
69  self.dir = dir
70 
71  def run(self):
72  while 1:
73  time.sleep(0.01)
74  if (os.path.isdir(self.dir)):
75  ls = os.listdir(self.dir)
76  #print "Dir: " + str(ls)
77  for file in ls:
78  if (file == FRAME_TARGET):
79  self.target.onTargetFrame()
80  return
81 
82 class TestCameras(unittest.TestCase):
83  def __init__(self, *args):
84  super(TestCameras, self).__init__(*args)
85  self.success = False
86  self.got_camerainfo = False
89 
90  def onTargetFrame(self):
91  time.sleep(0.5) #Safety, to make sure the image is really done being written.
92  ps = "diff -q " + FRAME_DIR + "/" + FRAME_TARGET + " test/test_camera.valid.ppm"
93  #print "CMD: " + ps + "\n"
94  result = os.system(ps)
95  if (result == 0):
96  self.success = True
97  #print "Success\n"
98  else:
99  self.success = False
100  #print "Failure\n"
101  rospy.signal_shutdown('test done')
102 
103  def images_are_the_same(self,i0,i1):
104  print "comparing images... "
105  error_count = 0
106  error_total = 0
107  pixel_tol = 0
108 
109  # thumbnail-ize images
110  size = 100,100
111  i0.thumbnail(size,pili.ANTIALIAS)
112  i1.thumbnail(size,pili.ANTIALIAS)
113  ic = pilic.difference(i0,i1)
114  i0.save("t_0.ppm")
115  i1.save("t_1.ppm")
116  ic.save("t_d.ppm")
117 
118  # get raw data for comparison
119  i0d = i0.getdata()
120  i1d = i1.getdata()
121 
122  # assert len(i0)==len(i1)
123  if len(i0d) != len(i1d):
124  print "lengths not equal ",len(i0d), len(i1d)
125  return False
126  print "thumbnail lengths ",len(i0d), len(i1d)
127 
128  #compare pixel by pixel for thumbnails
129  for i in range(len(i0d)):
130  (p0) = i0d[i]
131  (p1) = i1d[i]
132  if abs(p0-p1) > pixel_tol:
133  error_count = error_count + 1
134  error_total = error_total + abs(p0-p1)
135  error_avg = float(error_total)/float(len(i0d))
136  print "total error count:",error_count
137  print "average error: ",error_avg
138  if error_avg > TOTAL_ERROR_TOL:
139  return False
140  else:
141  return True
142 
143  def camerainfoInput(self,camerainfo):
144  self.got_camerainfo = True
145  self.camerainfo_width = camerainfo.width
146  self.camerainfo_height = camerainfo.height
147  print " got cam info (",camerainfo.width,"X",camerainfo.height,")"
148 
149  def imageInput(self,image):
150 
151  if (self.got_camerainfo):
152  print " got image and camerainfo from ROS, begin comparing images."
153  else:
154  print " got image but no camerainfo."
155  return
156 
157  print " - load validation image from file test_camera.valid.ppm "
158  fname = roslib.packages.get_pkg_dir('pr2_gazebo') + '/test/sensors/test_camera.valid.ppm'
159  if os.path.isfile(fname):
160  im0 = pili.open(fname)
161  else:
162  print "cannot find validation file: test_camera.valid.ppm"
163  self.success = False
164  return
165 
166  print " - load image from ROS "
167  size = self.camerainfo_width,self.camerainfo_height
168  im1 = pili.new("L",size)
169  im1 = pili.frombuffer("L",size,str(image.data));
170  im1 = im1.transpose(pili.FLIP_LEFT_RIGHT).rotate(180);
171  imc = pilic.difference(im0,im1)
172 
173 
174  print " - comparing images "
175  im1.save("test_1.ppm") # uncomment this line to capture a new valid frame when things change
176  im0.save("test_0.ppm")
177  imc.save("test_d.ppm")
178  #im1.show()
179  #im0.show()
180  #imc.show()
181  comp_result = self.images_are_the_same(im0,im1)
182  print "test comparison ", comp_result
183  #print "proofcomparison ", self.images_are_the_same(im1.getdata(),im1.getdata())
184  if (self.success == False): # test if we have not succeeded
185  if (comp_result == True):
186  print " - images are the Same "
187  self.success = True
188  else:
189  print " - images differ "
190  self.success = False
191 
192 
193  def test_camera(self):
194  rospy.init_node(NAME, anonymous=True)
195  head_action_client = actionlib.action_client.ActionClient('/head_traj_controller/point_head_action',PointHeadAction)
196  def send_head_goal(g):
197  g.target.header.stamp = rospy.get_rostime()
198  return head_action_client.send_goal(g)
199  head_goal = PointHeadGoal()
200  head_goal.target.header.frame_id = 'base_link'
201  head_goal.target.point = Point(10,0,0.55)
202 
203  projector_pub = rospy.Publisher("/projector_wg6802418_controller/projector", Int32, latch=True);
204  projector_pub.publish(Int32(0));
205 
206  print " subscribe stereo left image from ROS "
207  rospy.Subscriber("/narrow_stereo/left/image_raw", image_msg, self.imageInput) # this is a camera mounted on PR2 head (left stereo camera)
208  rospy.Subscriber("/narrow_stereo/left/camera_info", camerainfo_msg, self.camerainfoInput) # this is a camera mounted on PR2 head (left stereo camera)
209  timeout_t = time.time() + TEST_DURATION
210  while not rospy.is_shutdown() and not self.success and time.time() < timeout_t:
211  head_goal_status = send_head_goal(head_goal)
212  time.sleep(1.0)
213  self.assert_(self.success)
214 
215 
216 
217 
218 if __name__ == '__main__':
219  #while (os.path.isfile(FRAME_DIR + "/" + FRAME_TARGET)):
220  # print "Old test case still alive."
221  # time.sleep(1)
222 
223  print " starting test "
224  rostest.run(PKG, sys.argv[0], TestCameras, sys.argv)
225 
226 
def imageInput(self, image)
Definition: test_camera.py:149
def __init__(self, target, dir)
Definition: test_camera.py:66
def camerainfoInput(self, camerainfo)
Definition: test_camera.py:143
def __init__(self, args)
Definition: test_camera.py:83
def images_are_the_same(self, i0, i1)
Definition: test_camera.py:103


pr2_gazebo
Author(s): John Hsu
autogenerated on Fri May 3 2019 02:24:27