Skip to content

Commit d29b50c

Browse files
committed
salvage: prompt image save path only when images received
Invert empty-check so HelloDrone asks for a save path when simGetImages actually returned frames (not when the vector is empty). Salvage of #4658 by @webshared — rebased onto current main and re-verified. Spec: tools/aerial-drone-pr-campaign/specs/airsim/2026-07-16-salvage.md
1 parent d109f0d commit d29b50c

1 file changed

Lines changed: 148 additions & 148 deletions

File tree

HelloDrone/main.cpp

Lines changed: 148 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,148 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
2-
// Licensed under the MIT License.
3-
4-
#include "common/common_utils/StrictMode.hpp"
5-
STRICT_MODE_OFF
6-
#ifndef RPCLIB_MSGPACK
7-
#define RPCLIB_MSGPACK clmdep_msgpack
8-
#endif // !RPCLIB_MSGPACK
9-
#include "rpc/rpc_error.h"
10-
STRICT_MODE_ON
11-
12-
#include "vehicles/multirotor/api/MultirotorRpcLibClient.hpp"
13-
#include "common/common_utils/FileSystem.hpp"
14-
#include <iostream>
15-
#include <chrono>
16-
17-
int main()
18-
{
19-
using namespace msr::airlib;
20-
21-
msr::airlib::MultirotorRpcLibClient client;
22-
typedef ImageCaptureBase::ImageRequest ImageRequest;
23-
typedef ImageCaptureBase::ImageResponse ImageResponse;
24-
typedef ImageCaptureBase::ImageType ImageType;
25-
typedef common_utils::FileSystem FileSystem;
26-
27-
try {
28-
client.confirmConnection();
29-
30-
std::cout << "Press Enter to get FPV image" << std::endl;
31-
std::cin.get();
32-
const std::vector<ImageRequest> request{ ImageRequest("0", ImageType::Scene), ImageRequest("1", ImageType::DepthPlanar, true) };
33-
const std::vector<ImageResponse>& response = client.simGetImages(request);
34-
std::cout << "# of images received: " << response.size() << std::endl;
35-
36-
if (!response.size()) {
37-
std::cout << "Enter path with ending separator to save images (leave empty for no save)" << std::endl;
38-
std::string path;
39-
std::getline(std::cin, path);
40-
41-
for (const ImageResponse& image_info : response) {
42-
std::cout << "Image uint8 size: " << image_info.image_data_uint8.size() << std::endl;
43-
std::cout << "Image float size: " << image_info.image_data_float.size() << std::endl;
44-
45-
if (path != "") {
46-
std::string file_path = FileSystem::combine(path, std::to_string(image_info.time_stamp));
47-
if (image_info.pixels_as_float) {
48-
Utils::writePFMfile(image_info.image_data_float.data(), image_info.width, image_info.height, file_path + ".pfm");
49-
}
50-
else {
51-
std::ofstream file(file_path + ".png", std::ios::binary);
52-
file.write(reinterpret_cast<const char*>(image_info.image_data_uint8.data()), image_info.image_data_uint8.size());
53-
file.close();
54-
}
55-
}
56-
}
57-
}
58-
59-
std::cout << "Press Enter to arm the drone" << std::endl;
60-
std::cin.get();
61-
62-
client.enableApiControl(true);
63-
client.armDisarm(true);
64-
65-
auto barometer_data = client.getBarometerData();
66-
std::cout << "Barometer data \n"
67-
<< "barometer_data.time_stamp \t" << barometer_data.time_stamp << std::endl
68-
<< "barometer_data.altitude \t" << barometer_data.altitude << std::endl
69-
<< "barometer_data.pressure \t" << barometer_data.pressure << std::endl
70-
<< "barometer_data.qnh \t" << barometer_data.qnh << std::endl;
71-
72-
auto imu_data = client.getImuData();
73-
std::cout << "IMU data \n"
74-
<< "imu_data.time_stamp \t" << imu_data.time_stamp << std::endl
75-
<< "imu_data.orientation \t" << imu_data.orientation << std::endl
76-
<< "imu_data.angular_velocity \t" << imu_data.angular_velocity << std::endl
77-
<< "imu_data.linear_acceleration \t" << imu_data.linear_acceleration << std::endl;
78-
79-
auto gps_data = client.getGpsData();
80-
std::cout << "GPS data \n"
81-
<< "gps_data.time_stamp \t" << gps_data.time_stamp << std::endl
82-
<< "gps_data.gnss.time_utc \t" << gps_data.gnss.time_utc << std::endl
83-
<< "gps_data.gnss.geo_point \t" << gps_data.gnss.geo_point << std::endl
84-
<< "gps_data.gnss.eph \t" << gps_data.gnss.eph << std::endl
85-
<< "gps_data.gnss.epv \t" << gps_data.gnss.epv << std::endl
86-
<< "gps_data.gnss.velocity \t" << gps_data.gnss.velocity << std::endl
87-
<< "gps_data.gnss.fix_type \t" << gps_data.gnss.fix_type << std::endl;
88-
89-
auto magnetometer_data = client.getMagnetometerData();
90-
std::cout << "Magnetometer data \n"
91-
<< "magnetometer_data.time_stamp \t" << magnetometer_data.time_stamp << std::endl
92-
<< "magnetometer_data.magnetic_field_body \t" << magnetometer_data.magnetic_field_body << std::endl;
93-
// << "magnetometer_data.magnetic_field_covariance" << magnetometer_data.magnetic_field_covariance // not implemented in sensor
94-
95-
std::cout << "Press Enter to takeoff" << std::endl;
96-
std::cin.get();
97-
float takeoff_timeout = 5;
98-
client.takeoffAsync(takeoff_timeout)->waitOnLastTask();
99-
100-
// switch to explicit hover mode so that this is the fall back when
101-
// move* commands are finished.
102-
std::this_thread::sleep_for(std::chrono::duration<double>(5));
103-
client.hoverAsync()->waitOnLastTask();
104-
105-
std::cout << "Press Enter to fly in a 10m box pattern at 3 m/s velocity" << std::endl;
106-
std::cin.get();
107-
// moveByVelocityZ is an offboard operation, so we need to set offboard mode.
108-
client.enableApiControl(true);
109-
110-
auto position = client.getMultirotorState().getPosition();
111-
float z = position.z(); // current position (NED coordinate system).
112-
constexpr float speed = 3.0f;
113-
constexpr float size = 10.0f;
114-
constexpr float duration = size / speed;
115-
DrivetrainType drivetrain = DrivetrainType::ForwardOnly;
116-
YawMode yaw_mode(true, 0);
117-
118-
std::cout << "moveByVelocityZ(" << speed << ", 0, " << z << "," << duration << ")" << std::endl;
119-
client.moveByVelocityZAsync(speed, 0, z, duration, drivetrain, yaw_mode);
120-
std::this_thread::sleep_for(std::chrono::duration<double>(duration));
121-
std::cout << "moveByVelocityZ(0, " << speed << "," << z << "," << duration << ")" << std::endl;
122-
client.moveByVelocityZAsync(0, speed, z, duration, drivetrain, yaw_mode);
123-
std::this_thread::sleep_for(std::chrono::duration<double>(duration));
124-
std::cout << "moveByVelocityZ(" << -speed << ", 0, " << z << "," << duration << ")" << std::endl;
125-
client.moveByVelocityZAsync(-speed, 0, z, duration, drivetrain, yaw_mode);
126-
std::this_thread::sleep_for(std::chrono::duration<double>(duration));
127-
std::cout << "moveByVelocityZ(0, " << -speed << "," << z << "," << duration << ")" << std::endl;
128-
client.moveByVelocityZAsync(0, -speed, z, duration, drivetrain, yaw_mode);
129-
std::this_thread::sleep_for(std::chrono::duration<double>(duration));
130-
131-
client.hoverAsync()->waitOnLastTask();
132-
133-
std::cout << "Press Enter to land" << std::endl;
134-
std::cin.get();
135-
client.landAsync()->waitOnLastTask();
136-
137-
std::cout << "Press Enter to disarm" << std::endl;
138-
std::cin.get();
139-
client.armDisarm(false);
140-
}
141-
catch (rpc::rpc_error& e) {
142-
const auto msg = e.get_error().as<std::string>();
143-
std::cout << "Exception raised by the API, something went wrong." << std::endl
144-
<< msg << std::endl;
145-
}
146-
147-
return 0;
148-
}
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#include "common/common_utils/StrictMode.hpp"
5+
STRICT_MODE_OFF
6+
#ifndef RPCLIB_MSGPACK
7+
#define RPCLIB_MSGPACK clmdep_msgpack
8+
#endif // !RPCLIB_MSGPACK
9+
#include "rpc/rpc_error.h"
10+
STRICT_MODE_ON
11+
12+
#include "vehicles/multirotor/api/MultirotorRpcLibClient.hpp"
13+
#include "common/common_utils/FileSystem.hpp"
14+
#include <iostream>
15+
#include <chrono>
16+
17+
int main()
18+
{
19+
using namespace msr::airlib;
20+
21+
msr::airlib::MultirotorRpcLibClient client;
22+
typedef ImageCaptureBase::ImageRequest ImageRequest;
23+
typedef ImageCaptureBase::ImageResponse ImageResponse;
24+
typedef ImageCaptureBase::ImageType ImageType;
25+
typedef common_utils::FileSystem FileSystem;
26+
27+
try {
28+
client.confirmConnection();
29+
30+
std::cout << "Press Enter to get FPV image" << std::endl;
31+
std::cin.get();
32+
const std::vector<ImageRequest> request{ ImageRequest("0", ImageType::Scene), ImageRequest("1", ImageType::DepthPlanar, true) };
33+
const std::vector<ImageResponse>& response = client.simGetImages(request);
34+
std::cout << "# of images received: " << response.size() << std::endl;
35+
36+
if (response.size()) {
37+
std::cout << "Enter path with ending separator to save images (leave empty for no save)" << std::endl;
38+
std::string path;
39+
std::getline(std::cin, path);
40+
41+
for (const ImageResponse& image_info : response) {
42+
std::cout << "Image uint8 size: " << image_info.image_data_uint8.size() << std::endl;
43+
std::cout << "Image float size: " << image_info.image_data_float.size() << std::endl;
44+
45+
if (path != "") {
46+
std::string file_path = FileSystem::combine(path, std::to_string(image_info.time_stamp));
47+
if (image_info.pixels_as_float) {
48+
Utils::writePFMfile(image_info.image_data_float.data(), image_info.width, image_info.height, file_path + ".pfm");
49+
}
50+
else {
51+
std::ofstream file(file_path + ".png", std::ios::binary);
52+
file.write(reinterpret_cast<const char*>(image_info.image_data_uint8.data()), image_info.image_data_uint8.size());
53+
file.close();
54+
}
55+
}
56+
}
57+
}
58+
59+
std::cout << "Press Enter to arm the drone" << std::endl;
60+
std::cin.get();
61+
62+
client.enableApiControl(true);
63+
client.armDisarm(true);
64+
65+
auto barometer_data = client.getBarometerData();
66+
std::cout << "Barometer data \n"
67+
<< "barometer_data.time_stamp \t" << barometer_data.time_stamp << std::endl
68+
<< "barometer_data.altitude \t" << barometer_data.altitude << std::endl
69+
<< "barometer_data.pressure \t" << barometer_data.pressure << std::endl
70+
<< "barometer_data.qnh \t" << barometer_data.qnh << std::endl;
71+
72+
auto imu_data = client.getImuData();
73+
std::cout << "IMU data \n"
74+
<< "imu_data.time_stamp \t" << imu_data.time_stamp << std::endl
75+
<< "imu_data.orientation \t" << imu_data.orientation << std::endl
76+
<< "imu_data.angular_velocity \t" << imu_data.angular_velocity << std::endl
77+
<< "imu_data.linear_acceleration \t" << imu_data.linear_acceleration << std::endl;
78+
79+
auto gps_data = client.getGpsData();
80+
std::cout << "GPS data \n"
81+
<< "gps_data.time_stamp \t" << gps_data.time_stamp << std::endl
82+
<< "gps_data.gnss.time_utc \t" << gps_data.gnss.time_utc << std::endl
83+
<< "gps_data.gnss.geo_point \t" << gps_data.gnss.geo_point << std::endl
84+
<< "gps_data.gnss.eph \t" << gps_data.gnss.eph << std::endl
85+
<< "gps_data.gnss.epv \t" << gps_data.gnss.epv << std::endl
86+
<< "gps_data.gnss.velocity \t" << gps_data.gnss.velocity << std::endl
87+
<< "gps_data.gnss.fix_type \t" << gps_data.gnss.fix_type << std::endl;
88+
89+
auto magnetometer_data = client.getMagnetometerData();
90+
std::cout << "Magnetometer data \n"
91+
<< "magnetometer_data.time_stamp \t" << magnetometer_data.time_stamp << std::endl
92+
<< "magnetometer_data.magnetic_field_body \t" << magnetometer_data.magnetic_field_body << std::endl;
93+
// << "magnetometer_data.magnetic_field_covariance" << magnetometer_data.magnetic_field_covariance // not implemented in sensor
94+
95+
std::cout << "Press Enter to takeoff" << std::endl;
96+
std::cin.get();
97+
float takeoff_timeout = 5;
98+
client.takeoffAsync(takeoff_timeout)->waitOnLastTask();
99+
100+
// switch to explicit hover mode so that this is the fall back when
101+
// move* commands are finished.
102+
std::this_thread::sleep_for(std::chrono::duration<double>(5));
103+
client.hoverAsync()->waitOnLastTask();
104+
105+
std::cout << "Press Enter to fly in a 10m box pattern at 3 m/s velocity" << std::endl;
106+
std::cin.get();
107+
// moveByVelocityZ is an offboard operation, so we need to set offboard mode.
108+
client.enableApiControl(true);
109+
110+
auto position = client.getMultirotorState().getPosition();
111+
float z = position.z(); // current position (NED coordinate system).
112+
constexpr float speed = 3.0f;
113+
constexpr float size = 10.0f;
114+
constexpr float duration = size / speed;
115+
DrivetrainType drivetrain = DrivetrainType::ForwardOnly;
116+
YawMode yaw_mode(true, 0);
117+
118+
std::cout << "moveByVelocityZ(" << speed << ", 0, " << z << "," << duration << ")" << std::endl;
119+
client.moveByVelocityZAsync(speed, 0, z, duration, drivetrain, yaw_mode);
120+
std::this_thread::sleep_for(std::chrono::duration<double>(duration));
121+
std::cout << "moveByVelocityZ(0, " << speed << "," << z << "," << duration << ")" << std::endl;
122+
client.moveByVelocityZAsync(0, speed, z, duration, drivetrain, yaw_mode);
123+
std::this_thread::sleep_for(std::chrono::duration<double>(duration));
124+
std::cout << "moveByVelocityZ(" << -speed << ", 0, " << z << "," << duration << ")" << std::endl;
125+
client.moveByVelocityZAsync(-speed, 0, z, duration, drivetrain, yaw_mode);
126+
std::this_thread::sleep_for(std::chrono::duration<double>(duration));
127+
std::cout << "moveByVelocityZ(0, " << -speed << "," << z << "," << duration << ")" << std::endl;
128+
client.moveByVelocityZAsync(0, -speed, z, duration, drivetrain, yaw_mode);
129+
std::this_thread::sleep_for(std::chrono::duration<double>(duration));
130+
131+
client.hoverAsync()->waitOnLastTask();
132+
133+
std::cout << "Press Enter to land" << std::endl;
134+
std::cin.get();
135+
client.landAsync()->waitOnLastTask();
136+
137+
std::cout << "Press Enter to disarm" << std::endl;
138+
std::cin.get();
139+
client.armDisarm(false);
140+
}
141+
catch (rpc::rpc_error& e) {
142+
const auto msg = e.get_error().as<std::string>();
143+
std::cout << "Exception raised by the API, something went wrong." << std::endl
144+
<< msg << std::endl;
145+
}
146+
147+
return 0;
148+
}

0 commit comments

Comments
 (0)