Skip to content

Commit

Permalink
gaussian pose generator, no eye adaptation, docs update and other ste…
Browse files Browse the repository at this point in the history
…reo gen tweaks
  • Loading branch information
sytelus committed Jul 9, 2017
1 parent b2db2e0 commit ebc5e36
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 46 deletions.
5 changes: 5 additions & 0 deletions AirLib/include/common/common_utils/RandomGenerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ class RandomGenerator {
{
}

void seed(int val)
{
rand_.seed(val);
}

TReturn next()
{
return dist_(rand_);
Expand Down
42 changes: 20 additions & 22 deletions Examples/PoseGenerators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,46 @@ STRICT_MODE_ON

class RandomPointPoseGenerator {
public:
RandomPointPoseGenerator(msr::airlib::RpcLibClient* client)
RandomPointPoseGenerator(msr::airlib::RpcLibClient* client, int random_seed)
: client_(client),
rand_xy_(-500.0f, 500.0f), rand_z_(-10.0f, -1.0f), rand_pitch_(-M_PIf / 2, M_PIf / 2),
rand_yaw_(-M_PIf, M_PIf)
rand_xy_(0.0f, 150.0f), rand_z_(2.0f, 3.0f), rand_pitch_(0.0f, M_PIf / 2),
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()
{
const auto& collision_info = client_->getCollisionInfo();
auto position = client_->getPosition();
auto orientation = client_->getOrientation();

if (collision_info.has_collided) {
position = collision_info.position + collision_info.normal*2 + collision_info.normal * collision_info.penetration_depth * 2;
}
else {
position.x() = rand_xy_.next();
position.y() = rand_xy_.next();
position.z() = rand_z_.next();
Vector3r position;
Quaternionr orientation;

float pitch, roll, yaw;
VectorMath::toEulerianAngle(orientation, pitch, roll, yaw);
pitch = rand_pitch_.next();
yaw = rand_yaw_.next();
position.x() = rand_xy_.next();
position.y() = rand_xy_.next();
position.z() = Utils::clip(rand_z_.next(), -10.0f, 0.0f);

orientation = VectorMath::toQuaternion(pitch, 0, yaw);
}
float pitch, roll, yaw;
VectorMath::toEulerianAngle(orientation, pitch, roll, yaw);
pitch = rand_pitch_.next();
yaw = rand_yaw_.next();

orientation = VectorMath::toQuaternion(pitch, 0, yaw);

client_->simSetPosition(position);
client_->simSetOrientation(orientation);
}
private:
typedef common_utils::RandomGeneratorF RandomGeneratorF;
typedef common_utils::RandomGeneratorGaussianF RandomGeneratorGaussianF;
typedef msr::airlib::Vector3r Vector3r;
typedef msr::airlib::Quaternionr Quaternionr;
typedef common_utils::Utils Utils;
typedef msr::airlib::VectorMath VectorMath;


msr::airlib::RpcLibClient* client_;
RandomGeneratorF rand_xy_, rand_z_, rand_pitch_, rand_yaw_;
RandomGeneratorGaussianF rand_xy_, rand_z_, rand_pitch_, rand_yaw_;
};

class RandomWalkPoseGenerator {
Expand Down
36 changes: 26 additions & 10 deletions Examples/StereoImageGenerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,34 @@ class StereoImageGenerator {
client.confirmConnection();
}

void generate(int num_samples)
int generate(int num_samples)
{
msr::airlib::ClockBase* clock = msr::airlib::ClockFactory::get();
RandomPointPoseGenerator pose_generator(& client);
std::ofstream file_list(FileSystem::combine(storage_dir_, "files_list.txt"));
RandomPointPoseGenerator pose_generator(& client, static_cast<int>(clock->nowNanos()));
std::fstream file_list(FileSystem::combine(storage_dir_, "files_list.txt"),
std::ios::out | std::ios::in | std::ios_base::app);

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;
}

for (int i = 0; i < num_samples; ++i) {
while(sample < num_samples) {
const auto& collision_info = client.getCollisionInfo();
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();
--i;
continue;
}
++sample;

auto start_nanos = clock->nowNanos();

Expand All @@ -57,9 +71,9 @@ class StereoImageGenerator {
continue;
}

std::string left_file_name = Utils::stringf("left_%06d.png", i);
std::string right_file_name = Utils::stringf("right_%06d.png", i);
std::string disparity_file_name = Utils::stringf("disparity_%06d.pfm", i);
std::string left_file_name = Utils::stringf("left_%06d.png", sample);
std::string right_file_name = Utils::stringf("right_%06d.png", sample);
std::string disparity_file_name = Utils::stringf("disparity_%06d.pfm", sample);
saveImageToFile(response.at(0).image_data,
FileSystem::combine(storage_dir_, right_file_name));
saveImageToFile(response.at(1).image_data,
Expand All @@ -84,10 +98,12 @@ class StereoImageGenerator {

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();
}

return 0;
}

private:
Expand Down
6 changes: 3 additions & 3 deletions Examples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ int runStandAlonePhysics(int argc, const char *argv[])
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);
}

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]));
}

2 changes: 1 addition & 1 deletion PythonClient/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def printUsage():

while True:
# 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):
print("Camera is not returning image, please check airsim for error messages")
sys.exit(0)
Expand Down
2 changes: 1 addition & 1 deletion PythonClient/navigate.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

while True:
# this will return png width= 256, height= 144
result = client.getImageForCamera(0, AirSimImageType.Depth)
result = client.simGetImage(0, AirSimImageType.Depth)
if (result == "\0"):
if (not help):
help = True
Expand Down
Binary file modified Unreal/Plugins/AirSim/Content/Blueprints/BP_PIPCamera.uasset
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ void ASimModeWorldMultiRotor::setupVehiclesAndCamera()
}
}

if (usage_scenario == kUsageScenarioComputerVision)
fpv_vehicle_pawn_->EnablePassthroughOnCollisons = true;
fpv_vehicle_pawn_->initializeForBeginPlay();
CameraDirector->initializeForBeginPlay(getInitialViewMode(), fpv_vehicle_pawn_, external_camera);
}
Expand Down
25 changes: 22 additions & 3 deletions docs/apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ Note: We would not recommend interrupting takeoff/land on a real drone, of cours


## 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.
See [Camera Views](camera_views.md) for information on the camera views and how to change them.
Here's a sample code to get a single image:

```
int playWithImages()
Expand All @@ -73,11 +72,31 @@ int playWithImages()
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
}
```

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?
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).
Expand Down
8 changes: 3 additions & 5 deletions docs/camera_views.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# Camera Views

The camera views that are shown on screen are the camera views you can fetch via the DroneControllerBase::getImageTypeForCamera API.
Note that getImageForCamera returns .png compressed images.
The camera views that are shown on screen are the camera views you can fetch via the [simGetImage API](apis.md).

![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
getImageForCamera to work. In fact getImageForCamera will make them visible if they are not already.
From left to right is the depth view, segmentation view and the FPV view.

## Depth View

Expand All @@ -30,7 +28,7 @@ main game view if the user presses '[' or ']'.

## 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)

Expand Down
2 changes: 1 addition & 1 deletion docs/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ help = False
while True:
# 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 (not help):
help = True
Expand Down

0 comments on commit ebc5e36

Please sign in to comment.