Beispiel #1
0
    def perform_scan(self):
        """Performs a 3d scan"""
        # Calculate 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):
                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()
Beispiel #2
0
    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(5, self.check_get_scan_timeout)
        time_out_thread.start()

        valid_scan_index = 0
        rotated_already = False
        #if not CCW:
        #angle_between_sweeps = -angle_between_sweeps
        # get_scans is coroutine-based generator returning scans ad infinitum
        for scan_count, scan in enumerate(self.device.get_scans()):
            Cloud_Points = []
            # note the arrival time
            scan_arrival_time = time.time()
            HEADER.stamp = rospy.Time.now()
            # 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

            # Catch scans that contain unordered samples and discard them
            # (this may indicate problem reading sync byte)
            if scan_utils.contains_unordered_samples(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)
            #if not CCW:
            #angle_between_sweeps = -angle_between_sweeps
            converted_coords = scan_utils.transform_scan_without_base(
                scan, self.settings.mount_angle, 0.0)
            for n, sample in enumerate(scan.samples):
                world_x = converted_coords[n, 0]
                world_y = converted_coords[n, 1]
                world_z = converted_coords[n, 2]
                self.exporter.writer.writerow({
                    'SCAN_INDEX':
                    valid_scan_index,
                    'X':
                    int(round(world_x)),
                    'Y':
                    int(round(world_y)),
                    'Z':
                    int(round(world_z)),
                    'SIGNAL_STRENGTH':
                    sample.signal_strength
                })
                #print "the samples!"
                row = []
                row.append(float(world_x) / 100)
                row.append(float(world_y) / 100)
                row.append(float(world_z) / 100)
                row.append(sample.signal_strength)
                Cloud_Points.append(row)

            # increment the scan index
            valid_scan_index = valid_scan_index + 1
            print "length of samples is %d" % len(scan.samples)
            # Wait for the device to reach the threshold angle for movement
            if len(scan.samples) > 0:
                point_cloud2 = pcl2.create_cloud(HEADER, FIELDS, Cloud_Points)
                #publish the point cloud message via ros
                self.cloud_publisher.publish(point_cloud2)
                # Move the base and report progress
                self.report_scan_progress(valid_scan_index)

            self.wait_until_deadzone(scan_arrival_time)

            # Move the base and report progress
            #self.base.move_steps(steps_per_move)
            self.report_scan_progress(valid_scan_index)

            # Exit after collecting the required number of 2D scans
            #if valid_scan_index >= num_sweeps:
            #   break

        # Stop scanning and report completion
        #time.sleep(1.0)
        #self.device.stop_scanning()
        self.report_scan_complete()
Beispiel #3
0
    def perform_scan(self):
        """Performs a complete 3d scan
        :param angular_range: the angular range for the base to cover during the scan (default 180)
        """
        # Calcualte the # of evenly spaced 2D sweeps (base movements) required
        # to match resolutions
        num_sweeps = int(
            round(self.settings.get_resolution() *
                  self.settings.get_scan_range()))

        # Caclulate the number of stepper steps covering the angular range
        num_stepper_steps = self.settings.get_scan_range(
        ) * self.base.get_steps_per_deg()

        # Calculate number of stepper steps per move (ie: between scans)
        num_stepper_steps_per_move = int(round(num_stepper_steps / num_sweeps))

        # Actual angle per move (between individual 2D scans)
        angle_between_sweeps = 1.0 * num_stepper_steps_per_move / \
            self.base.get_steps_per_deg()

        # correct the num_sweeps to account for the accumulated difference due
        # to rounding
        num_sweeps = math.floor(1.0 * self.settings.get_scan_range() /
                                angle_between_sweeps)

        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()
        })

        # Start Scanning
        self.device.start_scanning()

        # put a 3 second timeout on the get_scans() method in case it gets hung
        # up
        time_out_thread = threading.Timer(3, self.check_get_scan_timeout)
        time_out_thread.start()

        # get_scans is coroutine-based generator lazily returning scans ad
        # infinitum
        for scan_count, scan in enumerate(self.device.get_scans()):
            # 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 len(scan.samples) > self.settings.get_max_samples_per_scan():
                continue

            # Export the scan
            self.exporter.export_2D_scan(
                scan,
                scan_count,
                self.settings.get_mount_angle(),
                # base angle before move
                angle_between_sweeps * scan_count,
                # base angle after move
                angle_between_sweeps * (scan_count + 1),
                False)

            # Wait for the device to reach the threshold angle for movement
            time.sleep(self.settings.get_time_to_deadzone_sec())

            # Move the base
            self.base.move_steps(num_stepper_steps_per_move)

            output_json_message({
                'type':
                "update",
                'status':
                "scan",
                'msg':
                "Scan in Progress...",
                'duration':
                num_sweeps / self.settings.get_motor_speed(),
                'remaining':
                (num_sweeps - scan_count) / self.settings.get_motor_speed()
            })

            # Collect the appropriate number of 2D scans
            if scan_count == num_sweeps:
                break

        # Stop scanning
        self.device.stop_scanning()

        output_json_message({
            'type': "update",
            'status': "complete",
            'msg': "Finished scan!"
        })