def setup_device(self): """Setup the device""" reset_max_duration = 11.0 output_json_message({ 'type': "update", 'status': "setup", 'msg': "Resetting device.", 'duration': reset_max_duration }) # Reset the device self.device.reset() # sleep for at least the minimum time required to reset the device time.sleep(reset_max_duration) output_json_message({ 'type': "update", 'status': "setup", 'msg': "Adjusting device settings." }) # Set the sample rate self.device.set_sample_rate(self.settings.get_sample_rate()) # Set the motor speed self.device.set_motor_speed(self.settings.get_motor_speed())
def report_scan_complete(self): """ Reports the completion of a scan """ output_json_message({ 'type': "update", 'status': "complete", 'msg': "Finished scan!" })
def setup_base(self): """Setup the base""" output_json_message({ 'type': "update", 'status': "setup", 'msg': "Resetting base to home position." }) self.base.reset()
def report_scan_progress(self, num_sweeps, valid_scan_index): """ Reports the progress of a scan """ output_json_message({ 'type': "update", 'status': "scan", 'msg': "Scan in Progress...", 'duration': num_sweeps / self.settings.get_motor_speed(), 'remaining': (num_sweeps - valid_scan_index) / self.settings.get_motor_speed() })
def report_scan_initiated(self, num_sweeps): """ Reports that a scan has been initiated """ output_json_message({ 'type': "update", 'status': "scan", 'msg': "Initiating scan...", 'duration': num_sweeps / self.settings.get_motor_speed(), 'remaining': num_sweeps / self.settings.get_motor_speed() })
def main(arg_dict): """Creates a 3D scanner and gather a scan""" # Create a scan settings obj settings = scan_settings.ScanSettings( int(arg_dict['motor_speed']), # desired motor speed setting int(arg_dict['sample_rate']), # desired sample rate setting int(arg_dict['dead_zone']), # starting angle of deadzone int(arg_dict['angular_range']), # angular range of scan # mount angle of device relative to horizontal int(arg_dict['mount_angle'])) # Create an exporter exporter = scan_exporter.ScanExporter( file_name=socket.gethostname() + " - " + arg_dict['output'] + " " + " __ MS-" + str(arg_dict['motor_speed']) + " __ SR-" + str(arg_dict['sample_rate']) + " __ AR-" + str(arg_dict['angular_range']) + " __ MA-" + str(arg_dict['mount_angle']) + " __ DZ-" + str(arg_dict['dead_zone']) + ".csv") use_dummy = arg_dict['use_dummy'] # Create a scanner base base = scanner_base.ScannerBase(use_dummy=use_dummy) # Create sweep sensor, and perform scan with sweep_helpers.create_sweep_w_error('/dev/ttyUSB0', use_dummy) as (sweep, err): if err: output_json_message({ 'type': "update", 'status': "failed", 'msg': "Failed to connect to sweep device... make sure it is plugged in." }) time.sleep(0.1) return # Create a scanner object time.sleep(1.0) scanner = Scanner(device=sweep, base=base, settings=settings, exporter=exporter) # Setup the scanner scanner.setup() # Perform the scan scanner.perform_scan() # Stop the scanner time.sleep(1.0) scanner.idle()
def main(arg_dict): """Perform any requested routines""" if arg_dict['release_motor'] is True: release_motors(use_dummy=arg_dict['use_dummy']) if arg_dict['idle_sweep'] is True: idle_sweep(use_dummy=arg_dict['use_dummy']) output_json_message({ 'type': "update", 'status': "complete", 'msg': "Tasks completed successfully!" })
def release_motors(use_dummy=False): """Releases any stepper motors""" if not use_dummy: from Adafruit_MotorHAT import Adafruit_MotorHAT motor_hat = Adafruit_MotorHAT() motor_hat.getMotor(1).run(Adafruit_MotorHAT.RELEASE) motor_hat.getMotor(2).run(Adafruit_MotorHAT.RELEASE) motor_hat.getMotor(3).run(Adafruit_MotorHAT.RELEASE) motor_hat.getMotor(4).run(Adafruit_MotorHAT.RELEASE) output_json_message({ 'type': "update", 'status': "progress", 'msg': "Released Stepper Motors!" }) time.sleep(0.1)
def setup(self): """Setup the scanner according to the scan settings""" # setup the device, wait for it to calibrate self.setup_device() # wait until the device is ready, so as not to disrupt the calibration while True: if self.device.get_motor_ready() is True: break # Convey that the motor speed is still adjusting output_json_message({'type': "update", 'status': "setup", 'msg': "Waiting for calibration routine and motor speed to stabilize."}) time.sleep(0.5) # setup the base self.setup_base()
def idle_sweep(use_dummy=False): """Stops any active stream and sets the sweep to idle""" with sweep_helpers.create_sweep_w_error('/dev/ttyUSB0', use_dummy) as (sweep, err): if err: output_json_message({ 'type': "update", 'status': "failed", 'msg': err }) time.sleep(0.1) return sweep.set_motor_speed(sweep_helpers.MOTOR_SPEED_0_HZ) output_json_message({ 'type': "update", 'status': "progress", 'msg': "Set sweep to idle!" }) time.sleep(0.1)
def test_demo(use_dummy=False): """Performs a small test demo (prints message when switch is pressed)""" output_json_message({ 'type': "update", 'status': "instruction", 'msg': "Try pressing the limit switch... You have 10 seconds." }) # pause... give time for user to read directions time.sleep(.5) switch = LimitSwitch(pin=17, use_dummy=use_dummy) # run for 10 seconds for _ in itertools.repeat(None, 100): time.sleep(.1) if switch.is_pressed(): output_json_message({ 'type': "update", 'status': "progress", 'msg': "Pressed!" }) # pause to avoid accidentally flushing the previous message contents time.sleep(0.1) output_json_message({ 'type': "update", 'status': "complete", 'msg': "Finished test!" })
def test_demo(use_dummy=False): """Performs a small test demo (reset, and move base 90 degrees)""" output_json_message({ 'type': "update", 'status': "setup", 'msg': "Creating base!" }) base = ScannerBase(use_dummy=use_dummy) # pause to avoid accidentally flushing the previous message contents time.sleep(0.1) output_json_message({ 'type': "update", 'status': "progress", 'msg': "Resetting base..." }) base.reset() output_json_message({ 'type': "update", 'status': "progress", 'msg': "Moving base 90 degrees..." }) for _ in itertools.repeat(None, 90): base.move_degrees(1) time.sleep(.1) # sleep for 100 ms output_json_message({ 'type': "update", 'status': "complete", 'msg': "Finished test!" })
def main(arg_dict): """Tests the sweep's basic functions""" use_dummy = arg_dict['use_dummy'] with sweep_helpers.create_sweep_w_error('/dev/ttyUSB0', use_dummy) as (sweep, err): if err: output_json_message({ 'type': "update", 'status': "failed", 'msg': err }) time.sleep(0.1) return output_json_message({ 'type': "update", 'status': "setup", 'msg': "Testing motor ready." }) sweep.get_motor_ready() time.sleep(0.1) output_json_message({ 'type': "update", 'status': "setup", 'msg': "Adjusting sample rate." }) sweep.set_sample_rate(sweep_helpers.SAMPLE_RATE_500_HZ) time.sleep(0.1) output_json_message({ 'type': "update", 'status': "setup", 'msg': "Adjusting motor speed." }) sweep.set_motor_speed(sweep_helpers.MOTOR_SPEED_5_HZ) time.sleep(0.1) output_json_message({ 'type': "update", 'status': "setup", 'msg': "Testing motor ready." }) sweep.get_motor_ready() time.sleep(0.1) output_json_message({ 'type': "update", 'status': "setup", 'msg': "Starting data acquisition." }) sweep.start_scanning() time.sleep(0.1) desired_num_sweeps = 3 for scan_count, scan in enumerate(sweep.get_scans()): # note that a scan was received (used to avoid the timeout) output_json_message({ 'type': "update", 'status': "setup", 'msg': "Received Scan." }) if scan_count == desired_num_sweeps: break time.sleep(0.1) output_json_message({ 'type': "update", 'status': "setup", 'msg': "Stopping data acquisition." }) sweep.stop_scanning() time.sleep(0.1) output_json_message({ 'type': "update", 'status': "complete", 'msg': "Finished Test!" })
def perform_scan(self): """Performs a 3d scan""" # Calcualte some intermediate values num_sweeps, angle_between_sweeps, steps_per_move = self.calculate_scan_variables( ) # Report that the scan is initiating, and start scanning self.report_scan_initiated(num_sweeps) self.device.start_scanning() # put a 3 second timeout on the get_scans() method in case it hangs time_out_thread = threading.Timer(3, self.check_get_scan_timeout) time_out_thread.start() valid_scan_index = 0 rotated_already = False # get_scans is coroutine-based generator returning scans ad infinitum for scan_count, scan in enumerate(self.device.get_scans()): # note the arrival time scan_arrival_time = time.time() # note that a scan was received (used to avoid the timeout) self.received_scan = True # remove readings from unreliable distances scan_utils.remove_distance_extremes( scan, self.settings.get_min_range_val(), self.settings.get_max_range_val()) # Remove readings from the deadzone scan_utils.remove_angular_window( scan, self.settings.get_deadzone(), 360 - self.settings.get_deadzone()) if valid_scan_index >= num_sweeps - 2: # Avoid redundant data in last few partially overlapping scans scan_utils.remove_angular_window(scan, self.settings.get_deadzone(), 361) # Catch scans that contain unordered samples and discard them # (this may indicate problem reading sync byte) if scan_utils.contains_unordered_samples(scan): output_json_message({ 'type': "update", 'status': "scan", 'msg': "Bad sample encountered, continuing scan." }) continue # Edge case (discard 1st scan without base movement and move base) if not rotated_already: # Wait for the device to reach the threshold angle for movement self.wait_until_deadzone(scan_arrival_time) # Move the base and start again self.base.move_steps(steps_per_move) rotated_already = True continue # Export the scan self.exporter.export_2D_scan(scan, valid_scan_index, angle_between_sweeps, self.settings.get_mount_angle(), False) # increment the scan index valid_scan_index = valid_scan_index + 1 # Wait for the device to reach the threshold angle for movement self.wait_until_deadzone(scan_arrival_time) # Move the base and report progress self.base.move_steps(steps_per_move) self.report_scan_progress(num_sweeps, valid_scan_index) # Exit after collecting the required number of 2D scans if valid_scan_index >= num_sweeps: break # Stop scanning and report completion self.device.stop_scanning() self.report_scan_complete()