blob: 3cbd714f23a937bc4df4f7ae8985f8cd6639a3e0 [file] [log] [blame]
Josh Lehande745422020-11-07 02:14:09 -08001#pragma once
2
3#include "pid.hpp"
4
5#include <chrono>
6#include <cstring>
7#include <fstream>
8#include <iostream>
9#include <string>
10
11namespace pid_control
12{
13namespace ec
14{
15
16// Trivial class for information exported from core PID loop function
17struct PidCoreContext
18{
19 double input;
20 double setpoint;
21 double error;
22
23 double proportionalTerm;
24 double integralTerm1;
25 double integralTerm2;
26
27 double derivativeTerm;
28
29 double feedFwdTerm;
30 double output1;
31 double output2;
32
33 double minOut;
34 double maxOut;
35
36 double integralTerm3;
37 double output3;
38
39 double integralTerm;
40 double output;
41
42 bool operator!=(const PidCoreContext& rhs) const = default;
43 bool operator==(const PidCoreContext& rhs) const = default;
44};
45
46// Optional decorator class for each PID loop, to support logging
47// Although this is a trivial class, it ended up needing the Six Horsemen
48struct PidCoreLog
49{
50 std::string nameOriginal;
51 std::string nameClean;
52 std::ofstream fileContext;
53 std::ofstream fileCoeffs;
54 std::chrono::milliseconds lastLog;
55 PidCoreContext lastContext;
56 bool moved;
57
58 PidCoreLog() :
59 nameOriginal(), nameClean(), fileContext(), fileCoeffs(), lastLog(),
60 lastContext(), moved(false)
61 {}
62
63 PidCoreLog(const PidCoreLog& copy) = delete;
64
65 PidCoreLog& operator=(const PidCoreLog& copy) = delete;
66
67 PidCoreLog(PidCoreLog&& move)
68 {
69 // Reuse assignment operator below
70 *this = std::move(move);
71 }
72
73 PidCoreLog& operator=(PidCoreLog&& move)
74 {
75 if (this != &move)
76 {
77 *this = std::move(move);
78
79 // Mark the moved object, so destructor knows it was moved
80 move.moved = true;
81 }
82 return *this;
83 }
84
85 ~PidCoreLog()
86 {
87 // Do not close files if ownership was moved to another object
88 if (!moved)
89 {
90 fileContext.close();
91 fileCoeffs.close();
92 }
93 }
94};
95
96// Initializes logging files, call once per PID loop initialization
97void LogInit(const std::string& name, pid_info_t* pidinfoptr);
98
99// Returns PidCoreLog pointer, or nullptr if this PID loop not being logged
100PidCoreLog* LogPeek(const std::string& name);
101
102// Logs a line of logging, if different, or it has been long enough
103void LogContext(PidCoreLog& pidLog, const std::chrono::milliseconds& msNow,
104 const PidCoreContext& coreLog);
105
106// Takes a timestamp, suitable for column 1 of logging file output
107std::chrono::milliseconds LogTimestamp(void);
108
109} // namespace ec
110} // namespace pid_control