def play(self, repeat=True, pause=30): # pause should be equivalent to the ghost tail length in liveview, if that's what you're using this for repetitions = 1 if repeat is True: repetitions = 1000000 elif repeat is False: repetitions = 1 else: repetitions = repeat rep = 0 while rep < repetitions and not rospy.is_shutdown(): rep += 1 r = rospy.Rate(self.fps) for frame in range(self.trajectory.length): if rospy.is_shutdown(): break acquire_stamp = rospy.Time.now() position = self.trajectory.positions[frame,:] velocity = self.trajectory.velocities[frame,:] flydra_object = msgs.flydra_object( self.trajectory.obj_id, geometry_msgs.Point(position[0], position[1], position[2]), geometry_msgs.Vector3(velocity[0], velocity[1], velocity[2]), self.posvel_covariance_diagonal) flydra_objects = [flydra_object] framenumber = frame reconstruction_stamp = rospy.Time.now() objects = flydra_objects flydra_mainbrain_packet = msgs.flydra_mainbrain_packet(framenumber, reconstruction_stamp, acquire_stamp, objects) flydra_mainbrain_super_packet = msgs.flydra_mainbrain_super_packet([flydra_mainbrain_packet]) print rep, frame self.pub.publish(flydra_mainbrain_super_packet) r.sleep() for i in range(pause): if rospy.is_shutdown(): break acquire_stamp = rospy.Time.now() position = self.trajectory.positions[-1,:] velocity = self.trajectory.velocities[-1,:] flydra_object = msgs.flydra_object( self.trajectory.obj_id, geometry_msgs.Point(position[0], position[1], position[2]), geometry_msgs.Vector3(velocity[0], velocity[1], velocity[2]), self.posvel_covariance_diagonal) flydra_objects = [flydra_object] framenumber = frame reconstruction_stamp = rospy.Time.now() objects = flydra_objects flydra_mainbrain_packet = msgs.flydra_mainbrain_packet(framenumber, reconstruction_stamp, acquire_stamp, objects) flydra_mainbrain_super_packet = msgs.flydra_mainbrain_super_packet([flydra_mainbrain_packet]) print rep, frame self.pub.publish(flydra_mainbrain_super_packet) r.sleep()
def enqueue_finished_tracked_object(self, tracked_object): # this is from called within the realtime coords thread if self.main_brain.is_saving_data(): self.main_brain.queue_data3d_kalman_estimates.put(( tracked_object.obj_id, tracked_object.frames, tracked_object.xhats, tracked_object.Ps, tracked_object.timestamps, tracked_object.observations_frames, tracked_object.MLE_position, tracked_object.observations_2d, tracked_object.MLE_Lcoords, )) # send a ROS message that this object is dead this_ros_object = flydra_object( obj_id=tracked_object.obj_id, position=Point(numpy.nan, numpy.nan, numpy.nan), ) try: reconstruction_stamp = rospy.Time.now() acquire_stamp = rospy.Time.from_sec(0) except rospy.exceptions.ROSInitException as err: pass else: ros_packet = flydra_mainbrain_packet( framenumber=tracked_object.current_frameno, reconstruction_stamp=reconstruction_stamp, acquire_stamp=acquire_stamp, objects=[this_ros_object]) self.realtime_ros_packets_pub.publish( flydra_mainbrain_super_packet([ros_packet])) if self.debug_level.isSet(): LOG.debug('killing obj_id %d:' % tracked_object.obj_id)
def get_objects(self): acquire_stamp = rospy.Time.now() self.framenumber = self.framenumber + 1 time.sleep(self.latency) birth_check = np.random.random() if birth_check < self.prob_birth: if len(self.objects) < self.max_num_objects: self.newest_object = self.newest_object+1 self.objects.append(DummyObject(self.newest_object)) death_check = np.random.random() if death_check < self.prob_death: if len(self.objects) > 1: del self.objects [np.random.randint(0,len(self.objects))] # package with mainbrain message format flydra_objects = [] for i in range(len(self.objects)): obj_id, position, velocity, posvel_covariance_diagonal = self.objects[i].get_state() flydra_object = msgs.flydra_object(obj_id, geometry_msgs.Point(position[0], position[1], position[2]), geometry_msgs.Vector3(velocity[0], velocity[1], velocity[2]), posvel_covariance_diagonal) flydra_objects.append(flydra_object) framenumber = self.framenumber reconstruction_stamp = rospy.Time.now() objects = flydra_objects flydra_mainbrain_packet = msgs.flydra_mainbrain_packet(framenumber, reconstruction_stamp, acquire_stamp, objects) flydra_mainbrain_super_packet = msgs.flydra_mainbrain_super_packet([flydra_mainbrain_packet]) self.pub.publish(flydra_mainbrain_super_packet) return flydra_mainbrain_super_packet
def get_objects(self): acquire_stamp = rospy.Time.now() self.framenumber = self.framenumber + 1 time.sleep(self.latency) birth_check = np.random.random() if birth_check < self.prob_birth and len(self.point_list) < self.max_num_objects: if verbose_mode: print "\nGenerating new object..." self.newest_object = self.newest_object+1 self.point_list.append(DummyPoint(self.newest_object)) if verbose_mode: print "Now %d total objects." % len(self.point_list) death_check = np.random.random() if death_check < self.prob_death and len(self.point_list) > 1: ind_to_kill = np.random.randint(0,len(self.point_list)) if verbose_mode: print "\nKilling object %d (at index %d)..." % (self.point_list[ind_to_kill].get_id(), ind_to_kill) del self.point_list[ind_to_kill] # package with mainbrain message format flydra_objects = [] for i in range(len(self.point_list)): obj_id, position, velocity, posvel_covariance_diagonal = self.point_list[i].get_state() flydra_object = msgs.flydra_object(obj_id, geometry_msgs.Point(position[0], position[1], position[2]), geometry_msgs.Vector3(velocity[0], velocity[1], velocity[2]), posvel_covariance_diagonal) flydra_objects.append(flydra_object) framenumber = self.framenumber reconstruction_stamp = rospy.Time.now() objects = flydra_objects flydra_mainbrain_packet = msgs.flydra_mainbrain_packet(framenumber, reconstruction_stamp, acquire_stamp, objects) flydra_mainbrain_super_packet = msgs.flydra_mainbrain_super_packet([flydra_mainbrain_packet]) self.pub.publish(flydra_mainbrain_super_packet) return flydra_mainbrain_super_packet
def _process_parsed_data( self, cam_idx, camn_received_time, absolute_cam_no, n_pts, cam_id, raw_framenumber, new_data_framenumbers, points_in_pluecker_coords_meters, points_distorted, points_undistorted, deferred_2d_data, ): # Note: this must be called with self.all_data_lock acquired. timestamp_check_dict = self.timestamp_check_dict convert_format = flydra_kalman_utils.convert_format # shorthand realtime_coord_dict = self.realtime_coord_dict oldest_timestamp_by_corrected_framenumber = self.oldest_timestamp_by_corrected_framenumber realtime_kalman_coord_dict = self.realtime_kalman_coord_dict if 1: if 1: if 1: if 1: # Use camn_received_time to determine sync # info. This avoids 2 potential problems: # * using raw_timestamp can fail if the # camera drivers don't provide useful data # * using time.time() can fail if the network # latency jitter is on the order of the # inter frame interval. corrected_framenumber, did_frame_offset_change = \ self.register_frame(cam_id,raw_framenumber) trigger_timestamp = self.main_brain.trigger_device.framestamp2timestamp( corrected_framenumber) if did_frame_offset_change: self.OnSynchronize(cam_idx, cam_id, raw_framenumber, trigger_timestamp) new_data_framenumbers.clear() self.last_timestamps[cam_idx] = trigger_timestamp self.last_framenumbers_delay[cam_idx] = raw_framenumber self.main_brain.framenumber = corrected_framenumber if self.main_brain.is_saving_data(): for point_tuple in points_distorted: # Save 2D data (even when no point found) to allow # temporal correlation of movie frames to 2D data. frame_pt_idx = point_tuple[ PT_TUPLE_IDX_FRAME_PT_IDX] cur_val = point_tuple[PT_TUPLE_IDX_CUR_VAL_IDX] mean_val = point_tuple[ PT_TUPLE_IDX_MEAN_VAL_IDX] sumsqf_val = point_tuple[ PT_TUPLE_IDX_SUMSQF_VAL_IDX] if corrected_framenumber is None: # don't bother saving if we don't know when it was from continue deferred_2d_data.append(( absolute_cam_no, # defer saving to later corrected_framenumber, trigger_timestamp, camn_received_time) + point_tuple[:5] + (frame_pt_idx, cur_val, mean_val, sumsqf_val)) # save new frame data if corrected_framenumber not in realtime_coord_dict: realtime_coord_dict[corrected_framenumber] = {} timestamp_check_dict[corrected_framenumber] = {} # For hypothesis testing: attempt 3D reconstruction of 1st point from each 2D view realtime_coord_dict[corrected_framenumber][ cam_id] = points_undistorted[0] #timestamp_check_dict[corrected_framenumber][cam_id]= camn_received_time timestamp_check_dict[corrected_framenumber][ cam_id] = trigger_timestamp if len(points_in_pluecker_coords_meters): # save all 3D Pluecker coordinates for Kalman filtering realtime_kalman_coord_dict[corrected_framenumber][ absolute_cam_no] = ( points_in_pluecker_coords_meters) if n_pts: inc_val = 1 else: inc_val = 0 if corrected_framenumber in oldest_timestamp_by_corrected_framenumber: orig_timestamp, n = oldest_timestamp_by_corrected_framenumber[ corrected_framenumber] if orig_timestamp is None: oldest = trigger_timestamp # this may also be None, but eventually won't be else: oldest = min(trigger_timestamp, orig_timestamp) oldest_timestamp_by_corrected_framenumber[ corrected_framenumber] = (oldest, n + inc_val) del oldest, n, orig_timestamp else: oldest_timestamp_by_corrected_framenumber[ corrected_framenumber] = trigger_timestamp, inc_val new_data_framenumbers.add( corrected_framenumber) # insert into set finished_corrected_framenumbers = [] # for quick deletion ######################################################################## # Now we've grabbed all data waiting on network. Now it's # time to calculate 3D info. # XXX could go for latest data first to minimize latency # on that data. ######################################################################## for corrected_framenumber in new_data_framenumbers: oldest_camera_timestamp, n = oldest_timestamp_by_corrected_framenumber[ corrected_framenumber] if oldest_camera_timestamp is None: #LOG.info('no latency estimate available -- skipping 3D reconstruction') continue if (time.time() - oldest_camera_timestamp ) > self.max_reconstruction_latency_sec: #LOG.info('maximum reconstruction latency exceeded -- skipping 3D reconstruction') continue data_dict = realtime_coord_dict[corrected_framenumber] if len(data_dict) == len( self.cam_ids): # all camera data arrived if self.debug_level.isSet(): LOG.debug('frame %d' % (corrected_framenumber)) # mark for deletion out of data queue finished_corrected_framenumbers.append( corrected_framenumber) if self.reconstructor is None: # can't do any 3D math without calibration information self.main_brain.best_realtime_data = None continue if not self.main_brain.trigger_device.have_estimate(): # acquire_stamp (the proximate error, however latency estimates for the same reason) # cannot be calculated unless the triggerbox has a clock model continue if 1: with self.tracker_lock: if self.tracker is None: # tracker isn't instantiated yet... self.main_brain.best_realtime_data = None continue pluecker_coords_by_camn = realtime_kalman_coord_dict[ corrected_framenumber] if self.save_profiling_data: dumps = pickle.dumps( pluecker_coords_by_camn) self.data_dict_queue.append( ('gob', (corrected_framenumber, dumps, self.camn2cam_id))) pluecker_coords_by_camn = self.tracker.calculate_a_posteriori_estimates( corrected_framenumber, pluecker_coords_by_camn, self.camn2cam_id, debug2=self.debug_level.isSet()) if self.debug_level.isSet(): LOG.debug( '%d live objects:' % self.tracker.how_many_are_living()) results = self.tracker.get_most_recent_data( ) for result in results: if result is None: continue obj_id, last_xhat, P = result Pmean = numpy.sqrt( numpy.sum([ P[i, i]**2 for i in range(3) ])) LOG.debug( 'obj_id %d: (%.3f, %.3f, %.3f), Pmean: %.3f' % (obj_id, last_xhat[0], last_xhat[1], last_xhat[2], Pmean)) if self.save_profiling_data: self.data_dict_queue.append( ('ntrack', self.tracker.how_many_are_living())) now = time.time() if self.show_overall_latency.isSet(): oldest_camera_timestamp, n = oldest_timestamp_by_corrected_framenumber[ corrected_framenumber] if n > 0: if 0: LOG.info( 'overall latency %d: %.1f msec (oldest: %s now: %s)' % ( n, (now - oldest_camera_timestamp) * 1e3, repr( oldest_camera_timestamp ), repr(now), )) else: LOG.info( 'overall latency (%d camera detected 2d points): %.1f msec (note: may exclude camera->camera computer latency)' % ( n, (now - oldest_camera_timestamp) * 1e3, )) if 1: # The above calls # self.enqueue_finished_tracked_object() # when a tracked object is no longer # tracked. # Now, tracked objects have been updated (and their 2D data points # removed from consideration), so we can use old flydra # "hypothesis testing" algorithm on remaining data to see if there # are new objects. results = self.tracker.get_most_recent_data( ) Xs = [] for result in results: if result is None: continue obj_id, last_xhat, P = result X = last_xhat[0], last_xhat[ 1], last_xhat[2] Xs.append(X) if len(Xs): self.main_brain.best_realtime_data = Xs, 0.0 else: self.main_brain.best_realtime_data = None # Convert to format accepted by find_best_3d() found_data_dict, first_idx_by_cam_id = convert_format( pluecker_coords_by_camn, self.camn2cam_id, area_threshold=0.0, only_likely=True) if len(found_data_dict) >= 2: # Can't do any 3D math without at least 2 cameras giving good # data. max_error = \ self.tracker.kalman_model['hypothesis_test_max_acceptable_error'] with_water = self.reconstructor.wateri is not None try: ( this_observation_3d, this_observation_Lcoords, cam_ids_used, min_mean_dist ) = ru.hypothesis_testing_algorithm__find_best_3d( self.reconstructor, found_data_dict, max_error, max_n_cams=self. max_N_hypothesis_test, with_water=with_water, ) except ru.NoAcceptablePointFound: pass else: this_observation_camns = [ self.cam_id2cam_no[cam_id] for cam_id in cam_ids_used ] this_observation_idxs = [ first_idx_by_cam_id[cam_id] for cam_id in cam_ids_used ] #################################### # Now join found point into Tracker if self.save_profiling_data: self.data_dict_queue.append( ('join', (corrected_framenumber, this_observation_3d, this_observation_Lcoords, this_observation_camns, this_observation_idxs))) # test for novelty believably_new = self.tracker.is_believably_new( this_observation_3d) if believably_new: self.tracker.join_new_obj( corrected_framenumber, this_observation_3d, this_observation_Lcoords, this_observation_camns, this_observation_idxs) if 1: if self.tracker.how_many_are_living(): #publish state to ROS results = self.tracker.get_most_recent_data( ) ros_objects = [] for result in results: if result is None: continue obj_id, xhat, P = result this_ros_object = flydra_object( obj_id=obj_id, position=Point(*xhat[:3]), velocity=Vector3(*xhat[3:6]), posvel_covariance_diagonal=numpy .diag(P)[:6].tolist()) ros_objects.append(this_ros_object) ros_packet = flydra_mainbrain_packet( framenumber=corrected_framenumber, reconstruction_stamp=rospy.Time. from_sec(now), acquire_stamp=rospy.Time.from_sec( oldest_camera_timestamp), objects=ros_objects) self.realtime_ros_packets_pub.publish( flydra_mainbrain_super_packet( [ros_packet])) for finished in finished_corrected_framenumbers: #check that timestamps are in reasonable agreement (low priority) diff_from_start = [] for cam_id, tmp_trigger_timestamp in timestamp_check_dict[ finished].iteritems(): diff_from_start.append(tmp_trigger_timestamp) timestamps_by_cam_id = numpy.array(diff_from_start) if self.show_sync_errors: if len(timestamps_by_cam_id): if numpy.max( abs(timestamps_by_cam_id - timestamps_by_cam_id[0])) > 0.005: LOG.warn( 'timestamps off by more than 5 msec -- synchronization error' ) self.main_brain.error_ros_msgs_pub.publish( FlydraError(FlydraError.CAM_TIMESTAMPS_OFF, "")) del realtime_coord_dict[finished] del timestamp_check_dict[finished] try: del realtime_kalman_coord_dict[finished] except KeyError: pass # Clean up old frame records to save RAM. # This is only needed when multiple cameras are not # synchronized, (When camera-camera frame # correspondences are unknown.) if len(realtime_coord_dict) > 100: #dont spam the console at startup (i.e. before a sync has been attemted) if self.ever_synchronized: LOG.warn( 'Cameras not synchronized or network dropping packets -- unmatched 2D data accumulating' ) self.main_brain.error_ros_msgs_pub.publish( FlydraError(FlydraError.NOT_SYNCHRONIZED, "")) k = realtime_coord_dict.keys() k.sort() # get one sample corrected_framenumber = k[0] data_dict = realtime_coord_dict[corrected_framenumber] this_cam_ids = data_dict.keys() missing_cam_id_guess = list( set(self.cam_ids) - set(this_cam_ids)) if len(missing_cam_id_guess) and self.ever_synchronized: delta = list(set(self.cam_ids) - set(this_cam_ids)) LOG.warn('a guess at missing cam_id(s): %r' % delta) for d in delta: self.main_brain.error_ros_msgs_pub.publish( FlydraError(FlydraError.MISSING_DATA, d)) for ki in k[:-50]: del realtime_coord_dict[ki] del timestamp_check_dict[ki] if len(realtime_kalman_coord_dict) > 100: LOG.warn( 'deleting unused 3D data (this should be a rare occurrance)' ) self.main_brain.error_ros_msgs_pub.publish( FlydraError(FlydraError.UNUSED_3D_DATA, "")) k = realtime_kalman_coord_dict.keys() k.sort() for ki in k[:-50]: del realtime_kalman_coord_dict[ki] if len(oldest_timestamp_by_corrected_framenumber) > 100: k = oldest_timestamp_by_corrected_framenumber.keys() k.sort() for ki in k[:-50]: del oldest_timestamp_by_corrected_framenumber[ki] if len(deferred_2d_data): self.main_brain.queue_data2d.put(deferred_2d_data)