34 from __future__
import with_statement
35 import roslib; roslib.load_manifest(
'pr2_camera_synchronizer')
36 from dynamic_reconfigure.client
import Client
as DynamicReconfigureClient
37 from dynamic_reconfigure.server
import Server
as DynamicReconfigureServer
38 from ethercat_trigger_controllers.srv
import SetMultiWaveform
as SetMultiWaveform
39 from ethercat_trigger_controllers.srv
import SetMultiWaveformRequest
as SetMultiWaveformRequest
40 from ethercat_trigger_controllers.msg
import MultiWaveform
as MultiWaveform
41 from ethercat_trigger_controllers.msg
import MultiWaveformTransition
as MultiWaveformTransition
42 import pr2_camera_synchronizer.cfg.CameraSynchronizerConfig
as Config
43 import wge100_camera.cfg.WGE100CameraConfig
as WGEConfig
51 from pr2_camera_synchronizer.cfg
import CameraSynchronizerConfig
as ConfigType
53 from diagnostic_msgs.msg
import DiagnosticStatus, KeyValue, DiagnosticArray
55 ETHERCAT_INTERVAL = 0.001
58 param_trig_mode =
"trig_mode" 59 camera_parameters = [ param_rate, param_trig_mode ]
61 param_proj_rate =
"projector_rate" 64 return ETHERCAT_INTERVAL * round(val / ETHERCAT_INTERVAL)
66 asynchronous_updaters = []
68 for updater
in asynchronous_updaters:
72 threading.Thread.__init__(self)
76 self.
cv = threading.Condition()
77 asynchronous_updaters.append(self)
106 self.
f(*allargs[0], **allargs[1])
107 except Exception
as e:
108 rospy.logerr(
"AsynchronousUpdater failed with exception: %s"%str(e))
123 return self.
name, interval
140 self.transitions.append(MultiWaveformTransition(time, value, topic))
145 service_name = self.
name+
"/set_waveform" 146 rospy.wait_for_service(service_name)
147 self.
service = rospy.ServiceProxy(service_name, SetMultiWaveform)
151 waveform = MultiWaveform(period, zero_offset, transitions)
155 rospy.logerr(
"Error setting waveform %s: %s"%(self.
name, rslt.status_message))
157 except KeyboardInterrupt:
158 print(
"Aborted trigger update on", self.
name)
167 def __init__(self, name, param, true_val, false_val):
168 MultiTriggerController.__init__(self, name)
178 MultiTriggerController.update(self)
182 MultiTriggerController.__init__(self, name)
190 if (self.proj.needed ==
False and self.proj.mode == Config.CameraSynchronizer_ProjectorAuto)
or \
191 self.proj.mode == Config.CameraSynchronizer_ProjectorOff:
193 for i
in range(0, len(self.proj.pulse_starts)):
195 self.
add_sample(self.proj.pulse_ends[i], 0xe,
'off_time')
196 MultiTriggerController.update(self)
200 MultiTriggerController.__init__(self, name)
204 if self.camera.reset_cameras:
208 if not self.camera.ext_trig:
212 self.
period = 2 * self.camera.period
214 first_pulse_start = self.camera.end_offset
215 second_pulse_start = self.camera.period + first_pulse_start
216 first_frame_end = first_pulse_start + self.camera.imager_period
217 extra_pulse_start = (first_pulse_start + first_frame_end) / 2
218 trigger_name =
"trigger" 219 self.
add_sample(first_pulse_start, 1, trigger_name)
220 self.
add_sample((first_pulse_start + extra_pulse_start) / 2, 0,
"-")
222 self.
add_sample((extra_pulse_start + first_frame_end) / 2, 0,
"-")
223 self.
add_sample(second_pulse_start, 1, trigger_name)
225 self.camera.trig_rising =
True 226 self.camera.trigger_name = self.
name+
"/"+trigger_name
229 MultiTriggerController.update(self)
236 MultiTriggerController.update(self)
240 SingleCameraTriggerController.__init__(self, name,
None)
244 if self.
cameras[0].reset_cameras
or self.
cameras[1].reset_cameras:
250 rospy.logerr(
"Cameras on same trigger have different period/imager_period settings.")
256 SingleCameraTriggerController.update(self)
263 self.cameras.reverse()
269 self.
cameras[0].trig_rising =
True 270 self.
cameras[1].trig_rising =
False 276 first_rise = self.
cameras[0].end_offset
277 first_fall = self.
cameras[1].end_offset
278 first_rise_end = first_rise + self.
cameras[0].imager_period
281 extra_rise = (2 * first_fall + first_rise_end) / 3
282 extra_fall = (first_fall + 2 * first_rise_end) / 3
284 trigger_name = [
"trigger_"+camera.name
for camera
in self.
cameras ]
285 self.
add_sample(first_rise, 1, trigger_name[0])
286 self.
add_sample(first_fall, 0, trigger_name[1])
289 self.
add_sample(second_rise, 1, trigger_name[0])
290 self.
add_sample(second_fall, 0, trigger_name[1])
292 self.
cameras[i].trigger_name = self.
name+
"/"+trigger_name[i]
296 MultiTriggerController.update(self)
311 if level & lvl_projector == 0:
314 base_period = 1.0 / config[
"projector_rate"]
316 pulse_shift = config[
"projector_pulse_shift"]
318 self.
mode = config[
"projector_mode"]
322 base_period = max(base_period, 4 * ETHERCAT_INTERVAL)
327 self.
pulse_length = min(self.
pulse_length, math.floor(base_period / ETHERCAT_INTERVAL / 2.0 - 1) * ETHERCAT_INTERVAL)
330 min_second_start = base_period
331 max_second_start = 2 * base_period - 2 * ETHERCAT_INTERVAL - 2 * self.
pulse_length 332 second_start = min_second_start * (1 - pulse_shift) + max_second_start * pulse_shift
334 config[
"projector_pulse_shift"] = (second_start - min_second_start) / (max_second_start - min_second_start)
340 2 * base_period + second_start + self.
pulse_length + 2 * ETHERCAT_INTERVAL
351 config[
"projector_rate"] = 1 / base_period
356 def __init__(self, node_name, proj, level, **paramnames):
387 projector_rate = config[param_proj_rate]
392 projector_limits_exposure =
True 394 trig_mode = self.
param(config, param_trig_mode)
396 if trig_mode == Config.CameraSynchronizer_InternalTrigger:
400 projector_limits_exposure =
False 402 if self.proj.mode == Config.CameraSynchronizer_ProjectorOff:
403 trig_mode = Config.CameraSynchronizer_IgnoreProjector
405 if trig_mode == Config.CameraSynchronizer_AlternateProjector
or trig_mode == Config.CameraSynchronizer_WithProjector:
406 self.proj.needed =
True 412 if trig_mode == Config.CameraSynchronizer_AlternateProjector:
413 n = round(self.
period / self.proj.repeat_period - 0.5)
415 self.
period = (n + 0.5) * self.proj.repeat_period
417 elif trig_mode == Config.CameraSynchronizer_IgnoreProjector:
420 n = round(2 * self.
period / self.proj.repeat_period - 1)
422 self.
period = (n + 1) * self.proj.repeat_period / 2.0
426 if trig_mode == Config.CameraSynchronizer_IgnoreProjector:
428 projector_limits_exposure =
False 429 if trig_mode == Config.CameraSynchronizer_AlternateProjector:
432 elif trig_mode == Config.CameraSynchronizer_WithProjector:
434 self.
register_set = WGEConfig.WGE100Camera_AlternateRegisterSet
439 if trig_mode == Config.CameraSynchronizer_IgnoreProjector:
442 self.
imager_period = self.proj.repeat_period / 2 - ETHERCAT_INTERVAL
445 if projector_limits_exposure:
453 self.
setparam(config, param_trig_mode, trig_mode)
463 self.reconfigure_client.update_configuration(reconfig_request)
466 except KeyboardInterrupt:
467 print(
"Aborted camera update on", self.
name)
472 "trig_rate" : 1.0 / self.
period,
477 "auto_exposure_alternate" :
False,
478 "exposure_alternate" : self.proj.proj_exposure_duration,
483 self.async_.update(reconfig_request)
503 stereo_camera_names = [
"narrow_stereo",
"wide_stereo" ]
504 forearm_camera_names = [
"forearm_r",
"forearm_l" ]
509 parameters = [ param_rate, param_trig_mode ]
510 camera_parameters = dict((name, dict((suffix, name+
"_"+suffix)
for suffix
in parameters))
for name
in self.
camera_names)
513 for camera
in stereo_camera_names:
514 camera_parameters[camera][param_rate] =
"stereo_rate" 515 camera_parameters[camera][
"node_name"] = camera+
"_both" 517 for camera
in forearm_camera_names:
518 camera_parameters[camera][
"node_name"] = camera[-1]+
"_forearm_cam" 520 camera_parameters[self.
camera_names[i]][
"level"] = 1 << i;
539 threads = threading.enumerate()
542 if not t.isDaemon()
and t != threading.currentThread():
546 print(
"Unknown thread ", t)
551 print(
"\nWaiting for all threads to die...")
555 print(
"\nStill waiting for all threads to die...")
562 self.projector.process_update(config, level)
563 self.prosilica_inhibit.process_update(config, level)
565 for camera
in self.cameras.values():
566 camera.process_update(config, level)
573 for camera
in self.cameras.values():
574 camera.apply_update()
580 da = DiagnosticArray()
581 ds = DiagnosticStatus()
582 ds.name = rospy.get_caller_id().lstrip(
'/') +
": Tasks" 584 longest_interval = 0;
585 for updater
in list(asynchronous_updaters):
586 (name, interval) = updater.getStatus()
590 in_progress = in_progress + 1
591 msg =
"Update in progress (%i s)"%interval
592 longest_interval = max(interval, longest_interval)
593 ds.values.append(KeyValue(name, msg))
597 ds.message =
"Updates in progress: %i"%in_progress
598 if longest_interval > 10:
600 ds.message =
"Update is taking too long: %i"%in_progress
601 ds.hardware_id =
"none" 603 da.header.stamp = rospy.get_rostime()
604 self.diagnostic_pub.publish(da)
610 rospy.loginfo(
"Camera synchronizer is running...")
611 controller_update_count = 0
612 while not rospy.is_shutdown():
613 if self.
config[
'camera_reset'] ==
True:
614 reset_count = reset_count + 1
616 self.server.update_configuration({
'camera_reset' :
False})
621 controller_update_count += 1
622 if controller_update_count >= 10:
623 controller_update_count = 0
628 rospy.signal_shutdown(
"Main thread exiting")
630 print(
"Main thread exiting")
def __init__(self, name, camera1, camera2)
def __init__(self, node_name, proj, level, paramnames)
def reconfigure(self, config, level)
def process_update(self, config, level)
def update(self, args, nargs)
def __init__(self, name, proj)
def async_update(self, period, zero_offset, transitions)
def process_update(self, config, level)
def add_sample(self, time, value, topic)
def param(self, config, name)
def setparam(self, config, name, value)
def __init__(self, f, name)
def __init__(self, forearm=True)
def __init__(self, name, camera)
def killAsynchronousUpdaters()
def async_apply_update(self, reconfig_request)
def __init__(self, name, param, true_val, false_val)
def update_diagnostics(self)
def process_update(self, config, level)