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