Skip to content

Commit

Permalink
Sim run console command (#2996)
Browse files Browse the repository at this point in the history
* double fixed build.cmd

* Created API for running console commands. Unreal has many useful console commands, and user can create their own in the level blueprint.

* Delete AirSim.props

* Added docstring and example script.

* add collision view to consol cmd script, move weather and markers to environment/ dir

* bla

* more collision cmds in example script

* Added stub for new API in Unity.

* fix typo in unity non impl

* fix docstring syntax

Co-authored-by: Nicholas Gyde <[email protected]>
Co-authored-by: Ratnesh Madaan <[email protected]>
  • Loading branch information
3 people authored Sep 2, 2020
1 parent 045766d commit 8d80ccd
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 0 deletions.
2 changes: 2 additions & 0 deletions AirLib/include/api/RpcLibClientBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class RpcLibClientBase {

msr::airlib::GeoPoint getHomeGeoPoint(const std::string& vehicle_name = "") const;

bool simRunConsoleCommand(const std::string& command);

// sensor APIs
msr::airlib::LidarData getLidarData(const std::string& lidar_name = "", const std::string& vehicle_name = "") const;
msr::airlib::ImuBase::Output getImuData(const std::string& imu_name = "", const std::string& vehicle_name = "") const;
Expand Down
1 change: 1 addition & 0 deletions AirLib/include/api/WorldSimApiBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class WorldSimApiBase {
virtual Pose getObjectPose(const std::string& object_name) const = 0;
virtual Vector3r getObjectScale(const std::string& object_name) const = 0;
virtual bool setObjectPose(const std::string& object_name, const Pose& pose, bool teleport) = 0;
virtual bool runConsoleCommand(const std::string& command) = 0;
virtual bool setObjectScale(const std::string& object_name, const Vector3r& scale) = 0;

virtual std::unique_ptr<std::vector<std::string>> swapTextures(const std::string& tag, int tex_id = 0, int component_id = 0, int material_id = 0) = 0;
Expand Down
5 changes: 5 additions & 0 deletions AirLib/src/api/RpcLibClientBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,11 @@ void RpcLibClientBase::cancelLastTask(const std::string& vehicle_name)
pimpl_->client.call("cancelLastTask", vehicle_name);
}

bool RpcLibClientBase::simRunConsoleCommand(const std::string& command)
{
return pimpl_->client.call("simRunConsoleCommand", command).as<bool>();
}

//return value of last task. It should be true if task completed without
//cancellation or timeout
RpcLibClientBase* RpcLibClientBase::waitOnLastTask(bool* task_result, float timeout_sec)
Expand Down
4 changes: 4 additions & 0 deletions AirLib/src/api/RpcLibServerBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ RpcLibServerBase::RpcLibServerBase(ApiProvider* api_provider, const std::string&
return getVehicleApi(vehicle_name)->armDisarm(arm);
});

pimpl_->server.bind("simRunConsoleCommand", [&](const std::string& command) -> bool {
return getWorldSimApi()->runConsoleCommand(command);
});

pimpl_->server.bind("simGetImages", [&](const std::vector<RpcLibAdapatorsBase::ImageRequest>& request_adapter, const std::string& vehicle_name) ->
vector<RpcLibAdapatorsBase::ImageResponse> {
const auto& response = getVehicleSimApi(vehicle_name)->getImages(RpcLibAdapatorsBase::ImageRequest::to(request_adapter));
Expand Down
14 changes: 14 additions & 0 deletions PythonClient/airsim/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,20 @@ def simGetImages(self, requests, vehicle_name = ''):
"""
responses_raw = self.client.call('simGetImages', requests, vehicle_name)
return [ImageResponse.from_msgpack(response_raw) for response_raw in responses_raw]

def simRunConsoleCommand(self, command):
"""
Allows the client to execute a command in Unreal's native console, via an API.
Affords access to the countless built-in commands such as "stat unit", "stat fps", "open [map]", adjust any config settings, etc. etc.
Allows the user to create bespoke APIs very easily, by adding a custom event to the level blueprint, and then calling the console command "ce MyEventName [args]". No recompilation of AirSim needed!
Args:
command ([string]): Desired Unreal Engine Console command to run
Returns:
[bool]: Success
"""
return self.client.call('simRunConsoleCommand', command)

# gets the static meshes in the unreal scene
def simGetMeshPositionVertexBuffers(self):
Expand Down
File renamed without changes.
29 changes: 29 additions & 0 deletions PythonClient/environment/unreal_console_commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import airsim
import time

def RunConsoleCmd(client, cmd):
client.simRunConsoleCommand(cmd)
print(f"Running Unreal Console cmd '{cmd}' and sleeping for 1 second")
time.sleep(1.0)

def RunCmdList(client):
RunConsoleCmd(client, 'stat fps')
RunConsoleCmd(client, 'stat unit')
RunConsoleCmd(client, 'stat unitGraph')
RunConsoleCmd(client, 'show COLLISION')
RunConsoleCmd(client, 'show CollisionVisibility')
RunConsoleCmd(client, 'stat game')
RunConsoleCmd(client, 'show COLLISION')
RunConsoleCmd(client, 'show CollisionVisibility')
RunConsoleCmd(client, 'stat game')
RunConsoleCmd(client, 'stat unitGraph')
RunConsoleCmd(client, 'stat unit')
RunConsoleCmd(client, 'stat fps')

def main():
client = airsim.client.MultirotorClient()
client.confirmConnection()
RunCmdList(client)

if __name__ == "__main__":
main()
File renamed without changes.
7 changes: 7 additions & 0 deletions Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ bool WorldSimApi::setObjectPose(const std::string& object_name, const WorldSimAp
return SetPose(airSimPose, false, object_name.c_str());
}

bool WorldSimApi::runConsoleCommand(const std::string& command)
{
throw std::invalid_argument(common_utils::Utils::stringf(
"simrunConsoleCommand is not supported on unity").c_str());
return false;
}

void WorldSimApi::enableWeather(bool enable)
{
unused(enable);
Expand Down
2 changes: 2 additions & 0 deletions Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class WorldSimApi : public msr::airlib::WorldSimApiBase
virtual bool setObjectPose(const std::string& object_name, const Pose& pose, bool teleport) override;
virtual bool setObjectScale(const std::string& object_name, const Vector3r& scale) override;

virtual bool runConsoleCommand(const std::string& command) override;

//----------- Plotting APIs ----------/
virtual void simFlushPersistentMarkers() override;
virtual void simPlotPoints(const std::vector<Vector3r>& points, const std::vector<float>& color_rgba, float size, float duration, bool is_persistent) override;
Expand Down
8 changes: 8 additions & 0 deletions Unreal/Plugins/AirSim/Source/AirBlueprintLib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,14 @@ UObject* UAirBlueprintLib::GetMeshFromRegistry(const std::string& load_object)
return LoadObject;
}

bool UAirBlueprintLib::RunConsoleCommand(const AActor* context, const FString& command)
{
auto* playerController = UGameplayStatics::GetPlayerController(context->GetWorld(), 0);;
if (playerController != nullptr)
playerController->ConsoleCommand(command, true);
return playerController != nullptr;
}

bool UAirBlueprintLib::HasObstacle(const AActor* actor, const FVector& start, const FVector& end, const AActor* ignore_actor, ECollisionChannel collision_channel)
{
FCollisionQueryParams trace_params;
Expand Down
3 changes: 3 additions & 0 deletions Unreal/Plugins/AirSim/Source/AirBlueprintLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ class UAirBlueprintLib : public UBlueprintFunctionLibrary
static void GenerateAssetRegistryMap(const UObject* context, TMap<FString, FAssetData>& asset_map);
static void GenerateActorMap(const UObject* context, TMap<FString, AActor*>& scene_object_map);

UFUNCTION(BlueprintCallable, Category = "AirSim")
static bool RunConsoleCommand(const AActor* context, const FString& command);

static bool HasObstacle(const AActor* actor, const FVector& start, const FVector& end,
const AActor* ignore_actor = nullptr, ECollisionChannel collision_channel = ECC_Visibility);
static bool GetObstacle(const AActor* actor, const FVector& start, const FVector& end,
Expand Down
10 changes: 10 additions & 0 deletions Unreal/Plugins/AirSim/Source/WorldSimApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,16 @@ std::vector<std::string> WorldSimApi::listSceneObjects(const std::string& name_r
return result;
}

bool WorldSimApi::runConsoleCommand(const std::string& command)
{
bool succeeded = false;
UAirBlueprintLib::RunCommandOnGameThread([this, &command, &succeeded]() {
FString fStringCommand(command.c_str());
succeeded = UAirBlueprintLib::RunConsoleCommand(simmode_, fStringCommand);
}, true);
return succeeded;
}

WorldSimApi::Pose WorldSimApi::getObjectPose(const std::string& object_name) const
{
Pose result;
Expand Down
1 change: 1 addition & 0 deletions Unreal/Plugins/AirSim/Source/WorldSimApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class WorldSimApi : public msr::airlib::WorldSimApiBase {
virtual std::vector<std::string> listSceneObjects(const std::string& name_regex) const override;
virtual Pose getObjectPose(const std::string& object_name) const override;
virtual bool setObjectPose(const std::string& object_name, const Pose& pose, bool teleport) override;
virtual bool runConsoleCommand(const std::string& command) override;
virtual Vector3r getObjectScale(const std::string& object_name) const override;
virtual bool setObjectScale(const std::string& object_name, const Vector3r& scale) override;

Expand Down

0 comments on commit 8d80ccd

Please sign in to comment.