herald  2.0.0
distance_conversion.h
1 // Copyright 2021 Herald Project Contributors
2 // SPDX-License-Identifier: Apache-2.0
3 //
4 
5 #ifndef HERALD_DISTANCE_CONVERSION_H
6 #define HERALD_DISTANCE_CONVERSION_H
7 
8 #include <cmath>
9 
10 #include "aggregates.h"
11 #include "ranges.h"
12 #include "runner.h"
13 #include "sampling.h"
14 #include "../datatype/distance.h"
15 
16 // Debug only
17 // #include <iostream>
18 
19 namespace herald {
20 namespace analysis {
21 namespace algorithms {
22 namespace distance {
23 
24 using namespace herald::analysis::aggregates;
25 using namespace herald::analysis::sampling;
26 using namespace herald::datatype;
27 
28 struct FowlerBasic {
29  static constexpr int runs = 1;
30 
31  FowlerBasic(double intercept, double coefficient) : run(1), mode(), intercept(intercept), coefficient(coefficient) {}
32  ~FowlerBasic() = default;
33 
34  void beginRun(int thisRun) { // 1 indexed
35  run = thisRun;
36  mode.beginRun(thisRun);
37  }
38 
39  template <typename ValT>
40  void map(ValT value) {
41  mode.map(value);
42  }
43 
44  double reduce() {
45  double exponent = (mode.reduce() - intercept) / coefficient;
46  return std::pow(10, exponent); // distance
47  }
48 
49  void reset() {
50  run = 1;
51  mode.reset();
52  }
53 
54 private:
55  int run;
56  Mode mode; // cleaner to use the Mode rather than redo it in this class
57  double intercept;
58  double coefficient;
59 };
60 
62  using input_value_type = RSSI;
64 
66  FowlerBasicAnalyser() : interval(10), basic(-11,-0.4), lastRan(0) {}
67  FowlerBasicAnalyser(long interval, double intercept, double coefficient) : interval(interval), basic(intercept, coefficient), lastRan(0) {}
68  ~FowlerBasicAnalyser() = default;
69 
70  // Generic
71  // TODO consider removing this annoyance somehow...
72  template <typename SrcT, std::size_t SrcSz,typename DstT, std::size_t DstSz, typename CallableForNewSample>
73  bool analyse(Date timeNow, SampledID sampled, SampleList<Sample<SrcT>,SrcSz>& src, SampleList<Sample<DstT>,DstSz>& dst, CallableForNewSample& callable) {
74  return false; // no op - compiled out
75  }
76 
77  // Specialisation
78  template <std::size_t SrcSz,std::size_t DstSz, typename CallableForNewSample>
79  bool analyse(Date timeNow, SampledID sampled, SampleList<Sample<RSSI>,SrcSz>& src, SampleList<Sample<Distance>,DstSz>& dst, CallableForNewSample& callable) {
80  if (lastRan + interval >= timeNow) return false; // interval guard
81  // std::cout << "RUNNING FOWLER BASIC ANALYSIS at " << timeNow.secondsSinceUnixEpoch() << std::endl;
82 
83  herald::analysis::views::in_range valid(-99,-10);
84 
85  // Check that there has been any new data since the last run
86  herald::analysis::views::since sinceLastRun(lastRan);
87  auto newData = src
89  | herald::analysis::views::filter(sinceLastRun)
91  // if (newData.ended()) { // Doesn't work because the filter's are not applied until a data item is fetched
92  // lastRan = timeNow;
93  // return false;
94  // }
95 
96  basic.reset();
97 
98  auto values = src
100  | herald::analysis::views::filter(sinceLastRun)
102 
103  auto summary = newData
105 
106  auto count = summary.template get<Count>();
107  if (0.0 == count) {
108  // No actual new data after filtering has been applied
109  lastRan = timeNow;
110  return false;
111  }
112  auto mode = summary.template get<Mode>();
113  auto var = summary.template get<Variance>();
114  auto sd = std::sqrt(var);
115 
116  auto distance = src
120  mode - 2*sd, // NOTE: WE USE THE MODE FOR FILTER, BUT SD FOR BOUNDS - See website for the reasoning
121  mode + 2*sd
122  )
123  )
124  | aggregate(basic); // type actually <herald::analysis::algorithms::distance::FowlerBasic>
125 
126  auto agg = distance.template get<FowlerBasic>();
127  auto d = agg.reduce();
128 
129 
130  Date latestTime = values.latest();
131  lastRan = latestTime; // TODO move this logic to the caller not the analysis provider
132  // std::cout << "Latest value at time: " << latestTime.secondsSinceUnixEpoch() << std::endl;
133 
134  Sample<Distance> newSample((Date)latestTime,Distance(d));
135  dst.push(newSample);
136  callable(sampled,newSample);
137  return true;
138  }
139 
140 private:
141  TimeInterval interval;
142  FowlerBasic basic;
143  Date lastRan;
144 };
145 
146 }
147 }
148 }
149 }
150 
151 #endif
Definition: date.h:18
Definition: rssi.h:14
Definition: time_interval.h:19
A set of structs compatible with, but not reliant upon, views and ranges in Herald.
Definition: sampling.h:17
SampleIterator< T >::difference_type distance(SampleIterator< T > first, SampleIterator< T > last)
for std::distance
Definition: sampling.h:321
std::size_t SampledID
Definition: sampling.h:24
Contains all low-level Herald datatype implementations.
Definition: base64_string.h:14
Acts as a non-global memory arena for arbitrary classes.
Definition: aggregates.h:15
Definition: aggregates.h:82
A Variadic aggregation function requiring aggregations to be prior initialised (i....
Definition: aggregates.h:326
Definition: aggregates.h:484
FowlerBasicAnalyser()
default constructor required for array instantiation in manager AnalysisProviderManager
Definition: distance_conversion.h:66
Definition: distance_conversion.h:28
The Sample taken from an object with ID of type SampledID.
Definition: sampling.h:28
Definition: sampling.h:102
Definition: ranges.h:404
Definition: ranges.h:63
Definition: ranges.h:30
Definition: ranges.h:430
Definition: distance.h:15