gaussian pose generator, no eye adaptation, docs update and other stereo gen tweaks

This commit is contained in:
Shital Shah 2017-07-08 21:46:06 -07:00
Родитель b2db2e0e31
Коммит ebc5e36532
11 изменённых файлов: 84 добавлений и 46 удалений

Просмотреть файл

@ -19,6 +19,11 @@ public:
{ {
} }
void seed(int val)
{
rand_.seed(val);
}
TReturn next() TReturn next()
{ {
return dist_(rand_); return dist_(rand_);

Просмотреть файл

@ -13,40 +13,38 @@ STRICT_MODE_ON
class RandomPointPoseGenerator { class RandomPointPoseGenerator {
public: public:
RandomPointPoseGenerator(msr::airlib::RpcLibClient* client) RandomPointPoseGenerator(msr::airlib::RpcLibClient* client, int random_seed)
: client_(client), : client_(client),
rand_xy_(-500.0f, 500.0f), rand_z_(-10.0f, -1.0f), rand_pitch_(-M_PIf / 2, M_PIf / 2), rand_xy_(0.0f, 150.0f), rand_z_(2.0f, 3.0f), rand_pitch_(0.0f, M_PIf / 2),
rand_yaw_(-M_PIf, M_PIf) rand_yaw_(0.0f, M_PIf)
{ {
rand_xy_.seed(random_seed);
rand_z_.seed(random_seed);
rand_pitch_.seed(random_seed);
rand_yaw_.seed(random_seed);
} }
void next() void next()
{ {
const auto& collision_info = client_->getCollisionInfo(); Vector3r position;
auto position = client_->getPosition(); Quaternionr orientation;
auto orientation = client_->getOrientation();
if (collision_info.has_collided) { position.x() = rand_xy_.next();
position = collision_info.position + collision_info.normal*2 + collision_info.normal * collision_info.penetration_depth * 2; position.y() = rand_xy_.next();
} position.z() = Utils::clip(rand_z_.next(), -10.0f, 0.0f);
else {
position.x() = rand_xy_.next();
position.y() = rand_xy_.next();
position.z() = rand_z_.next();
float pitch, roll, yaw; float pitch, roll, yaw;
VectorMath::toEulerianAngle(orientation, pitch, roll, yaw); VectorMath::toEulerianAngle(orientation, pitch, roll, yaw);
pitch = rand_pitch_.next(); pitch = rand_pitch_.next();
yaw = rand_yaw_.next(); yaw = rand_yaw_.next();
orientation = VectorMath::toQuaternion(pitch, 0, yaw);
}
orientation = VectorMath::toQuaternion(pitch, 0, yaw);
client_->simSetPosition(position); client_->simSetPosition(position);
client_->simSetOrientation(orientation); client_->simSetOrientation(orientation);
} }
private: private:
typedef common_utils::RandomGeneratorF RandomGeneratorF; typedef common_utils::RandomGeneratorGaussianF RandomGeneratorGaussianF;
typedef msr::airlib::Vector3r Vector3r; typedef msr::airlib::Vector3r Vector3r;
typedef msr::airlib::Quaternionr Quaternionr; typedef msr::airlib::Quaternionr Quaternionr;
typedef common_utils::Utils Utils; typedef common_utils::Utils Utils;
@ -54,7 +52,7 @@ private:
msr::airlib::RpcLibClient* client_; msr::airlib::RpcLibClient* client_;
RandomGeneratorF rand_xy_, rand_z_, rand_pitch_, rand_yaw_; RandomGeneratorGaussianF rand_xy_, rand_z_, rand_pitch_, rand_yaw_;
}; };
class RandomWalkPoseGenerator { class RandomWalkPoseGenerator {

Просмотреть файл

@ -29,20 +29,34 @@ public:
client.confirmConnection(); client.confirmConnection();
} }
void generate(int num_samples) int generate(int num_samples)
{ {
msr::airlib::ClockBase* clock = msr::airlib::ClockFactory::get(); msr::airlib::ClockBase* clock = msr::airlib::ClockFactory::get();
RandomPointPoseGenerator pose_generator(& client); RandomPointPoseGenerator pose_generator(& client, static_cast<int>(clock->nowNanos()));
std::ofstream file_list(FileSystem::combine(storage_dir_, "files_list.txt")); std::fstream file_list(FileSystem::combine(storage_dir_, "files_list.txt"),
std::ios::out | std::ios::in | std::ios_base::app);
for (int i = 0; i < num_samples; ++i) { int sample = 0;
std::string line;
while (std::getline(file_list, line))
++sample;
if (file_list.eof())
file_list.clear(); //otherwise we can't do any further I/O
else if (file_list.bad()) {
std::cout << "Error occured while reading files_list.txt";
return 1;
}
while(sample < num_samples) {
const auto& collision_info = client.getCollisionInfo(); const auto& collision_info = client.getCollisionInfo();
if (collision_info.has_collided) { if (collision_info.has_collided) {
std::cout << "Collison. Moving to next pose." << std::endl; std::cout << "Collison at " << VectorMath::toString(collision_info.position)
<< "Moving to next pose." << std::endl;
pose_generator.next(); pose_generator.next();
--i;
continue; continue;
} }
++sample;
auto start_nanos = clock->nowNanos(); auto start_nanos = clock->nowNanos();
@ -57,9 +71,9 @@ public:
continue; continue;
} }
std::string left_file_name = Utils::stringf("left_%06d.png", i); std::string left_file_name = Utils::stringf("left_%06d.png", sample);
std::string right_file_name = Utils::stringf("right_%06d.png", i); std::string right_file_name = Utils::stringf("right_%06d.png", sample);
std::string disparity_file_name = Utils::stringf("disparity_%06d.pfm", i); std::string disparity_file_name = Utils::stringf("disparity_%06d.pfm", sample);
saveImageToFile(response.at(0).image_data, saveImageToFile(response.at(0).image_data,
FileSystem::combine(storage_dir_, right_file_name)); FileSystem::combine(storage_dir_, right_file_name));
saveImageToFile(response.at(1).image_data, saveImageToFile(response.at(1).image_data,
@ -84,10 +98,12 @@ public:
file_list << left_file_name << "," << right_file_name << "," << disparity_file_name << std::endl; file_list << left_file_name << "," << right_file_name << "," << disparity_file_name << std::endl;
std::cout << "Image #" << i << " done in " << (clock->nowNanos() - start_nanos) / 1.0E6f << "ms" << std::endl; std::cout << "Image #" << sample << " done in " << (clock->nowNanos() - start_nanos) / 1.0E6f << "ms" << std::endl;
pose_generator.next(); pose_generator.next();
} }
return 0;
} }
private: private:

Просмотреть файл

@ -51,14 +51,14 @@ int runStandAlonePhysics(int argc, const char *argv[])
return 0; return 0;
} }
void runSteroImageGenerator(int num_samples) void runSteroImageGenerator(int num_samples, std::string storage_path)
{ {
StereoImageGenerator gen("c:\\temp\\stig"); StereoImageGenerator gen(storage_path);
gen.generate(num_samples); gen.generate(num_samples);
} }
int main(int argc, const char *argv[]) int main(int argc, const char *argv[])
{ {
runSteroImageGenerator(argc < 2 ? 50000 : std::stoi(argv[1])); runSteroImageGenerator(argc < 2 ? 50000 : std::stoi(argv[1]), argc < 3 ? "c:\\temp\\stig" : std::string(argv[2]));
} }

Просмотреть файл

@ -42,7 +42,7 @@ fps = 0
while True: while True:
# because this method returns std::vector<uint8>, msgpack decides to encode it as a string unfortunately. # because this method returns std::vector<uint8>, msgpack decides to encode it as a string unfortunately.
rawImage = client.getImageForCamera(0, cameraTypeMap[cameraType]) rawImage = client.simGetImage(0, cameraTypeMap[cameraType])
if (rawImage == None): if (rawImage == None):
print("Camera is not returning image, please check airsim for error messages") print("Camera is not returning image, please check airsim for error messages")
sys.exit(0) sys.exit(0)

Просмотреть файл

@ -22,7 +22,7 @@ help = False
while True: while True:
# this will return png width= 256, height= 144 # this will return png width= 256, height= 144
result = client.getImageForCamera(0, AirSimImageType.Depth) result = client.simGetImage(0, AirSimImageType.Depth)
if (result == "\0"): if (result == "\0"):
if (not help): if (not help):
help = True help = True

Двоичный файл не отображается.

Просмотреть файл

@ -85,6 +85,8 @@ void ASimModeWorldMultiRotor::setupVehiclesAndCamera()
} }
} }
if (usage_scenario == kUsageScenarioComputerVision)
fpv_vehicle_pawn_->EnablePassthroughOnCollisons = true;
fpv_vehicle_pawn_->initializeForBeginPlay(); fpv_vehicle_pawn_->initializeForBeginPlay();
CameraDirector->initializeForBeginPlay(getInitialViewMode(), fpv_vehicle_pawn_, external_camera); CameraDirector->initializeForBeginPlay(getInitialViewMode(), fpv_vehicle_pawn_, external_camera);
} }

Просмотреть файл

@ -62,8 +62,7 @@ Note: We would not recommend interrupting takeoff/land on a real drone, of cours
## How to get images from drone? ## How to get images from drone?
Here's a sample code. For more information, please see [DroneControlBase](https://github.com/Microsoft/AirSim/blob/master/AirLib/include/controllers/DroneControllerBase.hpp) class. Here's a sample code to get a single image:
See [Camera Views](camera_views.md) for information on the camera views and how to change them.
``` ```
int playWithImages() int playWithImages()
@ -73,11 +72,31 @@ int playWithImages()
msr::airlib::RpcLibClient client; msr::airlib::RpcLibClient client;
vector<uint8_t> image = client.getImageForCamera(0, DroneControlBase::ImageType::Depth); vector<uint8_t> image = client.simGetImage(0, DroneControlBase::ImageType::Depth);
//do something with images //do something with images
} }
``` ```
You can also get multiple images using API `simGetImages` which is slighly more complex to use than `simGetImage`. For example, you can get left camera view, right camera view and depth image from left camera - all at once! For sample code please see [sample code in HelloDrone project](https://github.com/Microsoft/AirSim/blob/master/HelloDrone/main.cpp). We also have [complete code](https://github.com/Microsoft/AirSim/blob/master/Examples/StereoImageGenerator.hpp) that generates specified number of stereo images and ground truth depth with normalization to camera plan, computation of disparity image and saving it to pfm format.
Unlike `simGetImage`, the `simGetImages` API also allows you to get uncompressed images as well as floating point single channel images (instead of 3 channel (RGB), each 8 bit).
You can also use Python to get images. For sample code please see [PythonClient project](https://github.com/Microsoft/AirSim/tree/master/PythonClient) and [Python example doc](python.md).
Furthermore, if your work involves computer vision experiments and if you don't care about drone dynamics then you can use our so called "ComputerVision" mode. Please see next section for the details.
## Can I use AirSim just for computer vision? I don't care about drones, physics etc.
Yes, now you can! Simply go to settings.json that you can find in your Documents\AirSim folder (or ~/Documents/AirSim on Linux). Add following setting at root level:
```
{
"FpvVehicleName": "SimpleFlight",
"UsageScenario": "ComputerVision"
}
```
Now when you start AirSim, you won't be able to move drone using remote control, there is no drone dynamics and physics engine is disabled in this mode. Think of this mode as that justs you move around cameras, not drone. You can use keyboard to move around (use F1 to see help on keys) and call APIs to get images. You can also use two additional APIs `simSetPosition` and `simGetPosition` to set position of drone programatically. Then use can image APIs as described in above section to get images for your desired pose. Please see [complete code](https://github.com/Microsoft/AirSim/blob/master/Examples/StereoImageGenerator.hpp) that generates specified number of stereo images and ground truth depth with normalization to camera plan, computation of disparity image and saving it to pfm format in this mode.
## Can I run above code on real quadrotors as well? ## Can I run above code on real quadrotors as well?
Absolutely! The AirLib is self-contained library that you can put on an offboard computing module such as the Gigabyte barebone Mini PC. Absolutely! The AirLib is self-contained library that you can put on an offboard computing module such as the Gigabyte barebone Mini PC.
This module then can talk to the flight controllers such as Pixhawk using exact same code and MavLink protocol (or DJI protocol). This module then can talk to the flight controllers such as Pixhawk using exact same code and MavLink protocol (or DJI protocol).

Просмотреть файл

@ -1,12 +1,10 @@
# Camera Views # Camera Views
The camera views that are shown on screen are the camera views you can fetch via the DroneControllerBase::getImageTypeForCamera API. The camera views that are shown on screen are the camera views you can fetch via the [simGetImage API](apis.md).
Note that getImageForCamera returns .png compressed images.
![Cameras](images/cameras.png) ![Cameras](images/cameras.png)
From left to right is the depth view, segmentation view and the FPV view. These views must be visible in order for From left to right is the depth view, segmentation view and the FPV view.
getImageForCamera to work. In fact getImageForCamera will make them visible if they are not already.
## Depth View ## Depth View
@ -30,7 +28,7 @@ main game view if the user presses '[' or ']'.
## Performance ## Performance
Now rendering these views does impact the FPS performance of the game, since this is additional work for the GPU. The following shows the impact on FPS when you open these views. The impact is higher when fetching the images via python calling getImageForCamera because this is an additional render request for each frame. Now rendering these views does impact the FPS performance of the game, since this is additional work for the GPU. The following shows the impact on FPS when you open these views.
![fps](images/fps_views.png) ![fps](images/fps_views.png)

Просмотреть файл

@ -103,7 +103,7 @@ help = False
while True: while True:
# because this method returns std::vector<uint8>, msgpack decides to encode it as a string unfortunately. # because this method returns std::vector<uint8>, msgpack decides to encode it as a string unfortunately.
result = client.getImageForCamera(0, AirSimImageType.Depth) result = client.simGetImage(0, AirSimImageType.Depth)
if (result == "\0"): if (result == "\0"):
if (not help): if (not help):
help = True help = True