Esempio n. 1
0
    def process_observation(self, obs: Obs) -> Obs:
        z = obs.get_response_value('z')

        if not z:
            return obs

        d = obs.get_response_value('slopeDist')

        if not d:
            return obs

        k = 0.13  # Refraction coefficient.
        r = 6370000  # Earth radius.

        k_e = (d * d) / (2 * r)  # Correction of earth radius.
        k_r = k * k_e  # Correction of refraction.
        r = k_e - k_r

        self.logger.info('Updated height in observation "{}" of target "{}" '
                         'from {:3.4f} m to {:3.4f} m (refraction value: '
                         '{:3.5f} m)'.format(obs.get("name"),
                                             obs.get("target"), z, z + r, r))

        refraction = Obs.create_response_set('float', 'm', round(r, 6))
        z_new = Obs.create_response_set('float', 'm', round(z + r, 5))
        z_raw = Obs.create_response_set('float', 'm', z)

        obs.data['responseSets']['refraction'] = refraction
        obs.data['responseSets']['zRaw'] = z_raw
        obs.data['responseSets']['z'] = z_new

        return obs
Esempio n. 2
0
    def process_observation(self, obs: Obs) -> Obs:
        if not self._is_valid_sensor_type(obs):
            # Only total stations are supported.
            return obs

        hz = obs.get_response_value('hz')
        v = obs.get_response_value('v')
        dist = obs.get_response_value('slopeDist')

        if None in [hz, v, dist]:
            return obs

        # Calculate the horizontal distance.
        dist_hz = math.sin(v) * dist

        if self._is_fixed_point(obs):
            # Add measured Hz and calculated Hz to the fixed point.
            self._update_fixed_point(obs)
            self.logger.debug(f'Updated fixed point of target '
                              f'"{obs.get("target")}"')

        self.logger.debug(
            'Starting polar transformation of target "{}" (Hz = '
            '{:3.5f} gon, V = {:3.5f} gon, dist = {:4.5f} m)'.format(
                obs.get("target"), rad_to_gon(hz), rad_to_gon(v), dist_hz))

        if self._is_adjustment_enabled:
            # Add the adjustment value to the horizontal direction.
            adj = self._get_adjustment_value()
            self.logger.info('Calculated adjustment value for polar '
                             'transformation ({:3.5f} gon)'.format(
                                 rad_to_gon(adj)))
            hz += adj

        # Calculate the coordinates of the observation.
        x, y, z = self.transform(self._view_point.get('x'),
                                 self._view_point.get('y'),
                                 self._view_point.get('z'),
                                 self._azimuth_point.get('x'),
                                 self._azimuth_point.get('y'), hz, v, dist_hz)

        self.logger.info('Transformed target "{}" (X = {:3.4f}, Y = {:3.4f}, '
                         'Z = {:3.4f})'.format(obs.get("target"), x, y, z))

        # Add to observation data set.
        response_sets = obs.get('responseSets')
        response_sets['x'] = Obs.create_response_set('float', 'm', round(x, 5))
        response_sets['y'] = Obs.create_response_set('float', 'm', round(y, 5))
        response_sets['z'] = Obs.create_response_set('float', 'm', round(z, 5))

        if self._is_adjustment_enabled:
            response_sets['hzAdjusted'] = Obs.create_response_set(
                'float', 'rad', round(hz, 16))

        return obs
Esempio n. 3
0
    def _calculate_target_point(self, obs: Obs) -> Obs:
        """Calculates the coordinates of a target point and updates the
        given `Observation` object.

        Args:
            obs: `Observation` object.

        Returns:
            The `Observation` object with calculated coordinates.
        """
        hz = obs.get_response_value('hz')
        v = obs.get_response_value('v')
        dist = obs.get_response_value('slopeDist')

        if None in [hz, v, dist]:
            self.logger.warning(f'Hz, V, or distance missing in observation '
                                f'"{obs.get("name")}" of target '
                                f'"{obs.get("target")}"')
            return obs

        # Calculate the coordinates in the global system (X, Y, Z).
        x, y, z = self.calculate_point_coordinates(hz, v, dist,
                                                   self._view_point.get('x'),
                                                   self._view_point.get('y'),
                                                   self._view_point.get('z'),
                                                   self._a, self._o)

        self.logger.info('Calculated coordinates of target point "{}" '
                         '(X = {:4.5f}, Y = {:4.5f}, Z = {:4.5f})'.format(
                             obs.get("target"), x, y, z))

        # Do residual mismatch transformation.
        if self._is_residual:
            vx, vy = self._calculate_residual_mismatches(x, y)

            self.logger.debug('Calculated improvements for target point "{}" '
                              '(dX = {:4.5f} m, dY = {:4.5f} m)'.format(
                                  obs.get("target"), vx, vy))

            x += vx
            y += vy

            self.logger.debug('Updated coordinates of target point "{}" '
                              '(X = {:4.5f}, Y = {:4.5f})'.format(
                                  obs.get("target"), x, y))

        # Add response set.
        response_sets = obs.get('responseSets')
        response_sets['x'] = Obs.create_response_set('float', 'm', x)
        response_sets['y'] = Obs.create_response_set('float', 'm', y)
        response_sets['z'] = Obs.create_response_set('float', 'm', z)

        return obs
Esempio n. 4
0
    def _update_fixed_point(self, obs: Obs) -> None:
        """Adds horizontal direction, vertical angle, and slope distance
        of the observation to a fixed point.

        Args:
            obs: `Observation` object.
        """
        hz = obs.get_response_value('hz')
        v = obs.get_response_value('v')
        dist = obs.get_response_value('slopeDist')

        if None in [hz, v, dist]:
            return

        # Calculate the coordinates of the fixed point if the Helmert
        # transformation has been done already. Otherwise, use the datum from
        # the configuration.
        fixed_point = self._fixed_points.get(obs.get('target'))

        if self._is_ready():
            # Calculate fixed point coordinates.
            x, y, z = self.calculate_point_coordinates(
                hz, v, dist, self._view_point.get('x'),
                self._view_point.get('y'), self._view_point.get('z'), self._a,
                self._o)

            self.logger.info('Calculated coordinates of fixed point "{}" '
                             '(X = {:3.5f}, Y = {:3.5f}, Z = {:3.5f})'.format(
                                 obs.get("target"), x, y, z))
        else:
            # Get the coordinates of the fixed point from the configuration.
            x = fixed_point.get('x')
            y = fixed_point.get('y')
            z = fixed_point.get('z')

        # Update the values.
        fixed_point['hz'] = hz
        fixed_point['v'] = v
        fixed_point['dist'] = dist
        fixed_point['lastUpdate'] = time.time()

        self.logger.debug(f'Updated fixed point of target '
                          f'"{obs.get("target")}"')

        # Add global Cartesian coordinates of the fixed point to the
        # observation.
        response_sets = obs.get('responseSets')
        response_sets['x'] = Obs.create_response_set('float', 'm', x)
        response_sets['y'] = Obs.create_response_set('float', 'm', y)
        response_sets['z'] = Obs.create_response_set('float', 'm', z)
Esempio n. 5
0
    def _update_fixed_point(self, obs: Obs) -> None:
        """Updates given fixed point.

        Args:
            obs: `Observation` object.
        """
        fixed_point = self._fixed_points.get(obs.get('target'))
        hz = obs.get_response_value('hz')

        azimuth = self.get_azimuth_angle(self._azimuth_angle,
                                         self._view_point.get('x'),
                                         self._view_point.get('y'),
                                         fixed_point.get('x'),
                                         fixed_point.get('y'))

        fixed_point['hz'] = hz
        fixed_point['azimuth'] = azimuth
        fixed_point['lastUpdate'] = time.time()

        # Calculate the orientation.
        delta_hz = azimuth - hz

        if delta_hz < 0:
            # Add 400 gon.
            delta_hz += 2 * math.pi

        fixed_point['deltaHz'] = delta_hz
Esempio n. 6
0
    def _update_meteorological_data(self, obs: Obs) -> None:
        """Updates the temperature, air pressure, and humidity attributes by
        using the measured data of a weather station."""
        # Update temperature.
        t = obs.get_response_value('temperature')

        if t is not None:
            self.temperature = t

        # Update pressure.
        p = obs.get_response_value('pressure')

        if p is not None:
            self.pressure = p

        # Update humidity.
        if (obs.has_response_value('humidity')
                and obs.has_response_type('humidity')):
            h = obs.get_response_value('humidity')
            u = obs.get_response_unit('humidity')

            self.humidity = h / 100 if u == '%' else h
Esempio n. 7
0
    def process_observation(self, obs: Obs) -> Obs:
        # Calculate the serial measurement of an observation in two faces.
        hz_0 = obs.get_response_value('hz0')
        hz_1 = obs.get_response_value('hz1')

        v_0 = obs.get_response_value('v0')
        v_1 = obs.get_response_value('v1')

        dist_0 = obs.get_response_value('slopeDist0')
        dist_1 = obs.get_response_value('slopeDist1')

        if None in [hz_0, hz_1, v_0, v_1, dist_0, dist_1]:
            return obs

        # Calculate new Hz, V, and slope distance.
        hz = hz_0 + hz_1

        if hz_0 > hz_1:
            hz += math.pi
        else:
            hz -= math.pi

        hz /= 2

        v = ((2 * math.pi) + (v_0 - v_1)) / 2
        dist = (dist_0 + dist_1) / 2

        # Save the calculated values.
        response_sets = obs.get('responseSets')
        response_sets['hz'] = Obs.create_response_set('float', 'rad', hz)
        response_sets['v'] = Obs.create_response_set('float', 'rad', v)
        response_sets['slopeDist'] = Obs.create_response_set('float' 'm', dist)

        self.logger.debug(f'Calculated serial measurement with two faces for '
                          f'observation "{obs.get("name")}" of target '
                          f'"{obs.get("target")}"')
        return obs
Esempio n. 8
0
    def process_observation(self, obs: Observation) -> Observation:
        """Checks, if responses are inside defined bounds.

        Args:
            obs: The observation object.

        Returns:
            The untouched observation object.
        """
        if not obs.get('name') in self._observations:
            self.logger.warning(f'Undefined observation "{obs.get("name")}" '
                                f'of target "{obs.get("target")}"')
            return obs

        response_sets = self._observations.get(obs.get('name'))

        for response_name, limits in response_sets.items():
            response_value = obs.get_response_value(response_name)

            if response_value is None or not self.is_number(response_value):
                self.logger.warning(f'Response value "{response_name}" in '
                                    f'observation "{obs.get("name")}" of '
                                    f'target "{obs.get("target")}" is not a '
                                    f'number')
                continue

            min_value = limits.get('min')
            max_value = limits.get('max')

            if min_value <= response_value <= max_value:
                self.logger.debug(f'Response value "{response_name}" in '
                                  f'observation "{obs.get("name")}" of target '
                                  f'"{obs.get("target")}" is within limits')
            elif response_value < min_value:
                self.logger.critical(f'Response value "{response_name}" in '
                                     f'observation "{obs.get("name")}" of '
                                     f'target "{obs.get("target")}" is less '
                                     f'than minimum ({response_value} < '
                                     f'{min_value})')
            elif response_value > max_value:
                self.logger.critical(
                    f'Response value "{response_name}" in '
                    f'observation "{obs.get("name")}" of '
                    f'target "{obs.get("target")}" is greater '
                    f'than maximum ({response_value} > '
                    f'{max_value})')

        return obs
Esempio n. 9
0
    def process_observation(self, obs: Obs) -> Obs:
        sensor_type = obs.get('sensorType')

        # Update atmospheric data if sensor is a weather station.
        if SensorType.is_weather_station(sensor_type):
            self._update_meteorological_data(obs)
            return obs

        # Check if sensor is of type "total station".
        if not SensorType.is_total_station(sensor_type):
            self.logger.warning(f'Sensor type "{sensor_type}" not supported')
            return obs

        # Check if atmospheric data has been set.
        if None in [self.temperature, self.pressure, not self.humidity]:
            self.logger.warning('Missing temperature, air pressure, or '
                                'humidity')
            return obs

        # Check the age of the atmospheric data.
        if self.last_update - time.time() > self._max_age:
            self.logger.warning(f'Atmospheric data is older than '
                                f'{int(self._max_age / 3600)} hour(s)')

        # Reduce the slope distance of the EDM measurement.
        dist = obs.get_response_value(self._distance_name)

        if dist is None:
            self.logger.error(f'No distance set in observation '
                              f'"{obs.get("name")}" of target '
                              f'"{obs.get("target")}"')
            return obs

        d_dist_1 = 0
        d_dist_2 = 0

        response_sets = obs.get('responseSets')

        # Calculate the atmospheric reduction of the distance.
        if self._is_atmospheric_correction:
            c = self.get_atmospheric_correction(self._temperature,
                                                self._pressure, self._humidity)
            d_dist_1 = dist * c * math.pow(10, -6)

            rs = Obs.create_response_set('float', 'none', round(c, 5))
            response_sets['atmosphericPpm'] = rs

        # Calculate the sea level reduction of the distance.
        if self._is_sea_level_correction:
            d_dist_2 = self.get_sea_level_correction(self._sensor_height)

            rs = Obs.create_response_set('float', 'm', round(d_dist_2, 5))
            response_sets['seaLevelDelta'] = rs

        # Add corrected distance to the observation set.
        if d_dist_1 != 0 or d_dist_2 != 0:
            r_dist = dist + d_dist_1 + d_dist_2
            self.logger.info('Reduced distance from {:0.5f} m to {:0.5f} m '
                             '(correction value: {:0.5f} m)'.format(
                                 dist, r_dist, d_dist_1 + d_dist_2))
            rs = Obs.create_response_set('float', 'm', round(r_dist, 5))

            response_sets[self._distance_name + 'Raw'] =\
                response_sets.get(self._distance_name)
            response_sets[self._distance_name] = rs

        return obs