11#include " camera/mock.hpp"
22
3+ #include < httplib.h>
4+
35#include < chrono>
46#include < thread>
57#include < optional>
1315#include " utilities/locks.hpp"
1416#include " utilities/rng.hpp"
1517#include " utilities/common.hpp"
18+ #include " utilities/base64.hpp"
1619
1720
1821MockCamera::MockCamera (CameraConfig config) : CameraInterface(config) {
19- std::ranges::for_each (
20- std::filesystem::directory_iterator{this ->config .mock .images_dir },
21- [this ](const auto & dir_entry) {
22- cv::Mat img = cv::imread (dir_entry.path ().string ());
23- // if the image is read
24- if (img.data != NULL ) {
25- std::optional<ImageTelemetry> telemetry =
26- this ->getTelemetryFromJsonFile (dir_entry.path ());
27-
28- ImageData img_data (
29- img,
30- 0 ,
31- telemetry);
32- this ->mock_images .push_back (img_data);
33- }
34- });
22+ LOG_F (INFO, " Grabbing images from port " + config.mock .not_stolen_port );
23+ httplib::Client cli (" localhost" , config.mock .not_stolen_port );
24+
25+ cli.set_read_timeout (10 );
26+
27+ for (int i = 0 ; i < config.mock .num_images ; i++) {
28+ httplib::Result res = cli.Get (" /generate?format=json" );
29+
30+ if (!res || res->status != 200 ) {
31+ LOG_F (ERROR, " Failed to query server for images" );
32+ continue ;
33+ }
34+
35+ nlohmann::json json = nlohmann::json::parse (res->body , nullptr , true , true );
36+
37+ std::string decoded_img = base64_decode (json[" image_base64" ]);
38+ std::vector<uchar> data (decoded_img.begin (), decoded_img.end ());
39+
40+ cv::Mat img = cv::imdecode (data, cv::IMREAD_COLOR);
41+
42+ if (img.data == NULL ) {
43+ LOG_F (ERROR, " Failed to decode image from server response" );
44+ continue ;
45+ }
46+
47+ ImageTelemetry telemetry = this ->getTelemetryFromJsonResponse (res->body ).value ();
48+
49+ ImageData img_data (
50+ img,
51+ 0 ,
52+ telemetry);
53+
54+ this ->mock_images .push_back (img_data);
55+ }
56+
57+ cli.stop ();
3558}
3659
3760MockCamera::~MockCamera () {
@@ -43,11 +66,12 @@ void MockCamera::connect() { return; }
4366bool MockCamera::isConnected () { return true ; }
4467
4568void MockCamera::startTakingPictures (const std::chrono::milliseconds& interval,
46- std::shared_ptr<MavlinkClient> mavlinkClient) {
69+ std::shared_ptr<MavlinkClient> mavlinkClient) {
4770 this ->isTakingPictures = true ;
4871 try {
4972 this ->captureThread = std::thread (&MockCamera::captureEvery, this , interval, mavlinkClient);
50- } catch (const std::exception& e) {
73+ }
74+ catch (const std::exception& e) {
5175 std::cerr << e.what () << std::endl;
5276 }
5377}
@@ -77,11 +101,11 @@ std::deque<ImageData> MockCamera::getAllImages() {
77101}
78102
79103void MockCamera::captureEvery (const std::chrono::milliseconds& interval,
80- std::shared_ptr<MavlinkClient> mavlinkClient) {
104+ std::shared_ptr<MavlinkClient> mavlinkClient) {
81105 loguru::set_thread_name (" mock camera" );
82106 while (this ->isTakingPictures ) {
83- LOG_F (INFO, " Taking picture with mock camera. Using images from %s " ,
84- this ->config .mock .images_dir . c_str () );
107+ LOG_F (INFO, " Taking picture with mock camera. Using images from port %d " ,
108+ this ->config .mock .not_stolen_port );
85109 auto imageData = this ->takePicture (interval, mavlinkClient);
86110
87111 if (!imageData.has_value ()) {
@@ -98,8 +122,8 @@ void MockCamera::captureEvery(const std::chrono::milliseconds& interval,
98122}
99123
100124std::optional<ImageData> MockCamera::takePicture (const std::chrono::milliseconds& timeout,
101- std::shared_ptr<MavlinkClient> mavlinkClient) {
102- int random_idx = randomInt (0 , this ->mock_images .size ()- 1 );
125+ std::shared_ptr<MavlinkClient> mavlinkClient) {
126+ int random_idx = randomInt (0 , this ->mock_images .size () - 1 );
103127
104128 ImageData img_data = this ->mock_images .at (random_idx);
105129 uint64_t timestamp = getUnixTime_s ().count ();
@@ -110,7 +134,7 @@ std::optional<ImageData> MockCamera::takePicture(const std::chrono::milliseconds
110134 img_data.TELEMETRY = queryMavlinkImageTelemetry (mavlinkClient);
111135 }
112136
113- ImageData imageData {
137+ ImageData imageData{
114138 .DATA = img_data.DATA ,
115139 .TIMESTAMP = timestamp,
116140 .TELEMETRY = img_data.TELEMETRY ,
@@ -121,22 +145,17 @@ std::optional<ImageData> MockCamera::takePicture(const std::chrono::milliseconds
121145
122146void MockCamera::startStreaming () {}
123147
124- std::optional<ImageTelemetry> MockCamera::getTelemetryFromJsonFile (std::filesystem::path img_path) {
125- img_path.replace_extension (" json" );
126- std::ifstream telemetry_stream (img_path);
127- if (!telemetry_stream.is_open ()) {
128- // no corresponding telemetry json found
129- return {};
130- }
131- nlohmann::json json = nlohmann::json::parse (telemetry_stream, nullptr , true , true );
132- return ImageTelemetry {
133- .latitude_deg = json[" latitude_deg" ],
134- .longitude_deg = json[" longitude_deg" ],
135- .altitude_agl_m = json[" altitude_agl_m" ],
136- .airspeed_m_s = json[" airspeed_m_s" ],
137- .heading_deg = json[" heading_deg" ],
138- .yaw_deg = json[" yaw_deg" ],
139- .pitch_deg = json[" pitch_deg" ],
140- .roll_deg = json[" roll_deg" ],
148+ std::optional<ImageTelemetry> MockCamera::getTelemetryFromJsonResponse (std::string json_response) {
149+ nlohmann::json json = nlohmann::json::parse (json_response, nullptr , true , true );
150+
151+ return ImageTelemetry{
152+ .latitude_deg = json[" background" ][" lat" ],
153+ .longitude_deg = json[" background" ][" lon" ],
154+ .altitude_agl_m = json[" altitude" ],
155+ .airspeed_m_s = 0.0 ,
156+ .heading_deg = json[" background" ][" heading_deg" ],
157+ .yaw_deg = 0.0 ,
158+ .pitch_deg = 0.0 ,
159+ .roll_deg = 0.0 ,
141160 };
142161}
0 commit comments