VisionServer  v2.1.1-1-g21dc5465
FRC vision library
config.cpp
Go to the documentation of this file.
1#include "config.h"
2
3#include <wpi/raw_ostream.h>
4#include <wpi/MemoryBuffer.h>
5#include <wpi/StringExtras.h>
6#include <networktables/NetworkTableInstance.h>
7
8#include "cpp-tools/src/resources.h"
9
10
11bool loadJson(wpi::json& j, const char* file) {
12 std::error_code ec;
13 std::unique_ptr<wpi::MemoryBuffer> file_buffer = wpi::MemoryBuffer::GetFile(file, ec);
14 if (file_buffer == nullptr || ec) {
15 wpi::errs() << "Could not open '" << file << "': " << ec.message() << newline;
16 return false;
17 }
18 try { j = wpi::json::parse(file_buffer->begin(), file_buffer->end()); }
19 catch (const wpi::json::parse_error& e) {
20 wpi::errs() << "Config error in " << file << /*": byte " << (int)e.byte <<*/ ": " << e.what() << newline;
21 return false;
22 }
23 if (!j.is_object()) {
24 wpi::errs() << "Config error in " << file << ": must be JSON object\n";
25 return false;
26 }
27 wpi::errs().flush();
28 return true;
29}
30bool initNT(const char* file) {
31
32 wpi::json j;
33 if(!loadJson(j, file)) { return false; }
34
35 if(j.count("ntmode") != 0) {
36 try {
37 std::string str = j.at("ntmode").get<std::string>();
38 if(wpi::equals_lower(str, "client")) {
39 wpi::outs() << "Setting up NetworkTables in CLIENT mode\n";
40 try {
41#if NT_CLIENT_VERSION == 4
42 nt::NetworkTableInstance::GetDefault().StartClient4("VisionServer");
43#else
44 nt::NetworkTableInstance::GetDefault().StartClient3("VisionServer");
45#endif
46 nt::NetworkTableInstance::GetDefault().SetServerTeam(j.at("team").get<unsigned int>());
47 nt::NetworkTableInstance::GetDefault().StartDSClient();
48 }
49 catch (const wpi::json::exception& e) {
50 wpi::errs() << "Config error in " << file << ": could not read team number: " << e.what() << newline;
51 return false;
52 }
53 } else if (wpi::equals_lower(str, "server")) {
54 wpi::outs() << "Setting up NetworkTables in SERVER mode\n";
55 nt::NetworkTableInstance::GetDefault().StartServer();
56 } else {
57 wpi::outs() << "Setting up NetworkTables for SIMULATION mode - host: " << str << newline;
58#if NT_CLIENT_VERSION == 4
59 nt::NetworkTableInstance::GetDefault().StartClient4("VisionServer");
60#else
61 nt::NetworkTableInstance::GetDefault().StartClient3("VisionServer");
62#endif
63 nt::NetworkTableInstance::GetDefault().SetServer(str.c_str());
64 }
65 } catch (const wpi::json::exception& e) {
66 wpi::errs() << "Config error in " << file << ": coud not read ntmode: " << e.what() << newline;
67 }
68 }
69 wpi::outs().flush();
70 return true;
71
72}
73bool initSimNT(const char* sim_ip) {
74
75 wpi::outs() << "Setting up NetworkTables for SIMULATION mode - host: " << sim_ip << newline;
76#if NT_CLIENT_VERSION == 4
77 nt::NetworkTableInstance::GetDefault().StartClient4("VisionServer");
78#else
79 nt::NetworkTableInstance::GetDefault().StartClient3("VisionServer");
80#endif
81 nt::NetworkTableInstance::GetDefault().SetServer(sim_ip);
82 wpi::outs().flush();
83 return true;
84
85}
86bool createCameras(std::vector<VisionCamera>& cameras, const char* file) {
87
88 wpi::json j;
89 if(!loadJson(j, file)) { return false; }
90
91 if(j.count("cameras") < 1) {
92 wpi::errs() << "Config error in " << file << ": no camera configs found, this program requires cameras to function\n";
93 } else {
94 try {
95 for(const wpi::json& camera : j.at("cameras")) {
96 if(camera.count("calibration") > 0 && j.count("calibrations") > 0) {
97 wpi::json calibration;
98 try {
99 calibration = j.at("calibrations").at(camera.at("calibration").get<std::string>());
100 cameras.emplace_back(camera, calibration);
101 //std::cout << "MAKING CAMERA:\n" << camera.dump() << newline;
102 } catch (const wpi::json::exception& e) {
103 wpi::errs() << "Config error in " << file << ": failed to get configuration object: " << e.what() << newline; // print out more info if needed
104 cameras.emplace_back(camera);
105 }
106 } else {
107 cameras.emplace_back(camera);
108 }
109#ifdef REMOVE_DISCONNECTED_CAMERAS
110 if(!cameras.back().IsConnected()) { cameras.pop_back(); }
111#endif
112 }
113 }
114 catch (const wpi::json::exception& e) {
115 wpi::errs() << "Config error in " << file << ": could not read cameras: " << e.what() << newline;
116 }
117 }
118 wpi::errs().flush();
119 return true;
120
121}
122bool createCameras(std::vector<VisionCamera>& cameras, CalibList calibrations, const char* file) {
123
124 wpi::json j;
125 if(!loadJson(j, file)) { return false; }
126
127 if(j.count("cameras") < 1) {
128 wpi::errs() << "Config error in " << file << ": no camera configs found, this program requires cameras to function\n";
129 } else {
130 try {
131 bool has_calibs = j.count("calibrations") > 0;
132 for(const wpi::json& camera : j.at("cameras")) {
133 cameras.emplace_back(camera);
134 if(camera.count("properties") && camera.at("properties").count("type")) {
135 try {
136 std::string type = camera.at("properties").at("type").get<std::string>();
137 // using SizeItem = std::pair<cv::Size2i, std::array<cv::Mat_<float>, 2> >;
138 // using TypeItem = std::pair<const char*, std::vector<SizeItem> >;
139 cv::Size2i sz = cameras.back().getResolution();
140 if(auto* cal = findCalib(type, sz, calibrations)) {
141 cameras.back().setCameraMatrix(cal->at(0));
142 cameras.back().setDistortionCoefs(cal->at(1));
143 }
144 // for(const TypeItem& item : calibrations) {
145 // if(wpi::equals_lower(type, item.first)) {
146 // for(const SizeItem& arr : item.second) {
147 // if(sz == arr.first) {
148 // cameras.back().setCameraMatrix(arr.second[0]);
149 // cameras.back().setDistortionCoefs(arr.second[1]);
150 // break;
151 // }
152 // }
153 // }
154 // }
155 } catch (const wpi::json::exception& e) {
156 wpi::errs() << "Config error in " << file << ": failed to get 'type' property: " << e.what() << newline; // print out more info if needed
157 }
158 } else if(has_calibs && camera.count("calibration") > 0) {
159 try {
160 wpi::json calibration = j.at("calibrations").at(camera.at("calibration").get<std::string>());
161 cameras.back().setCalibrationJson(calibration);
162 } catch (const wpi::json::exception& e) {
163 wpi::errs() << "Config error in " << file << ": failed to get configuration object: " << e.what() << newline; // print out more info if needed
164 }
165 }
166#ifdef REMOVE_DISCONNECTED_CAMERAS
167 if(!cameras.back().IsConnected()) { cameras.pop_back(); }
168#endif
169 }
170 }
171 catch (const wpi::json::exception& e) {
172 wpi::errs() << "Config error in " << file << ": could not read cameras: " << e.what() << newline;
173 }
174 }
175 wpi::errs().flush();
176 return true;
177
178}
179
180
181
182bool readConfig(std::vector<VisionCamera>& cameras, const char* file) {
183
184 wpi::json j;
185 if(!loadJson(j, file)) { return false; }
186
187 if(j.count("ntmode") != 0) {
188 try {
189 std::string str = j.at("ntmode").get<std::string>();
190 if(wpi::equals_lower(str, "client")) {
191 wpi::outs() << "Setting up NetworkTables in CLIENT mode\n";
192 try {
193#if NT_CLIENT_VERSION == 4
194 nt::NetworkTableInstance::GetDefault().StartClient4("VisionServer");
195#else
196 nt::NetworkTableInstance::GetDefault().StartClient3("VisionServer");
197#endif
198 nt::NetworkTableInstance::GetDefault().SetServerTeam(j.at("team").get<unsigned int>());
199 nt::NetworkTableInstance::GetDefault().StartDSClient();
200 }
201 catch (const wpi::json::exception& e) {
202 wpi::errs() << "Config error in " << file << ": could not read team number: " << e.what() << newline;
203 return false;
204 }
205 } else if (wpi::equals_lower(str, "server")) {
206 wpi::outs() << "Setting up NetworkTables in SERVER mode\n";
207 nt::NetworkTableInstance::GetDefault().StartServer();
208 } else {
209 wpi::outs() << "Setting up NetworkTables for SIMULATION mode - host: " << str << newline;
210#if NT_CLIENT_VERSION == 4
211 nt::NetworkTableInstance::GetDefault().StartClient4("VisionServer");
212#else
213 nt::NetworkTableInstance::GetDefault().StartClient3("VisionServer");
214#endif
215 nt::NetworkTableInstance::GetDefault().SetServer(str.c_str());
216 }
217 } catch (const wpi::json::exception& e) {
218 wpi::errs() << "Config error in " << file << ": coud not read ntmode: " << e.what() << newline;
219 }
220 }
221
222 if(j.count("cameras") < 1) {
223 wpi::errs() << "Config error in " << file << ": no camera configs found, this program requires cameras to function\n";
224 } else {
225 try {
226 for(const wpi::json& camera : j.at("cameras")) {
227 if(camera.count("calibration") > 0 && j.count("calibrations") > 0) {
228 wpi::json calibration;
229 try {
230 calibration = j.at("calibrations").at(camera.at("calibration").get<std::string>());
231 cameras.emplace_back(camera, calibration);
232 //std::cout << "MAKING CAMERA:\n" << camera.dump() << newline;
233 } catch (const wpi::json::exception& e) {
234 wpi::errs() << "Config error in " << file << ": failed to get configuration object: " << e.what() << newline; // print out more info if needed
235 cameras.emplace_back(camera);
236 }
237 } else {
238 cameras.emplace_back(camera);
239 }
240#ifdef REMOVE_DISCONNECTED_CAMERAS
241 if(!cameras.back().IsConnected()) { cameras.pop_back(); }
242#endif
243 }
244 }
245 catch (const wpi::json::exception& e) {
246 wpi::errs() << "Config error in " << file << ": could not read cameras: " << e.what() << newline;
247 }
248 }
249 // if(j.count("switched cameras") != 0) {
250 // try {
251 // for(const wpi::json::value_type& stream : j.at("switched cameras")) {
252 // cs::MjpegServer server;
253 // try { server = frc::CameraServer::GetInstance()->AddSwitchedCamera(stream.at("name").get<std::string>()); }
254 // catch (const wpi::json::exception& e) {
255 // wpi::errs() << "Could not read switched camera name: " << e.what() << newline;
256 // return false;
257 // }
258 // try { nt::NetworkTableInstance::GetDefault()
259 // .GetEntry(stream.at("key").get<std::string>())
260 // .AddListener(
261 // [server, cameras](const nt::EntryNotification& event) mutable {
262 // if(event.value->IsDouble()) {
263 // size_t i = event.value->GetDouble();
264 // if(i >= 0 && i < cameras.size()) {
265 // server.SetSource(cameras[i]);
266 // }
267 // } else if (event.value->IsString()) {
268 // wpi::StringRef str = event.value->GetString();
269 // for(size_t i = 0; i < cameras.size(); i++) {
270 // if(str == cameras[i].GetName()) {
271 // server.SetSource(cameras[i]);
272 // break;
273 // }
274 // }
275 // }
276 // },
277 // NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE
278 // );
279 // }
280 // catch (const wpi::json::exception& e) {
281 // wpi::errs() << "Config error in " << file << ": could not read key: " << e.what() << newline;
282 // return false;
283 // }
284 // }
285 // }
286 // catch (const wpi::json::exception& e) {
287 // wpi::errs() << "Config error in " << file << ": could not read switched cameras: " << e.what() << newline;
288 // return false;
289 // }
290 // }
291
292 wpi::outs().flush();
293 return true;
294}
const Set::Cal_T * findCalib(const cv::Size2i &sz, const Set &set)
Definition: calib.h:322
bool initNT(const char *file)
Definition: config.cpp:30
bool readConfig(std::vector< VisionCamera > &cameras, const char *file)
Definition: config.cpp:182
bool createCameras(std::vector< VisionCamera > &cameras, const char *file)
Definition: config.cpp:86
bool initSimNT(const char *sim_ip)
Definition: config.cpp:73
bool loadJson(wpi::json &j, const char *file)
Definition: config.cpp:11