carla/PythonAPI/source/libcarla/Actor.cpp

133 lines
4.2 KiB
C++

// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include <carla/client/Actor.h>
#include <carla/client/Image.h>
#include <carla/client/Sensor.h>
#include <carla/client/Vehicle.h>
#include <boost/python.hpp>
#include <ostream>
#include <iostream>
/// Aquires a lock on the Python's Global Interpreter Lock, necessary for
/// calling Python code from a different thread.
///
/// https://wiki.python.org/moin/GlobalInterpreterLock
class GILLockGuard {
public:
GILLockGuard()
: _state(PyGILState_Ensure()) {}
~GILLockGuard() {
PyGILState_Release(_state);
}
private:
PyGILState_STATE _state;
};
namespace carla {
namespace client {
std::ostream &operator<<(std::ostream &out, const Actor &actor) {
out << "Actor(id=" << actor.GetId() << ", type=" << actor.GetTypeId() << ')';
return out;
}
std::ostream &operator<<(std::ostream &out, const Vehicle &vehicle) {
out << "Vehicle(id=" << vehicle.GetId() << ", type=" << vehicle.GetTypeId() << ')';
return out;
}
std::ostream &operator<<(std::ostream &out, const Sensor &sensor) {
out << "Sensor(id=" << sensor.GetId() << ", type=" << sensor.GetTypeId() << ')';
return out;
}
} // namespace client
} // namespace carla
void export_actor() {
using namespace boost::python;
namespace cc = carla::client;
namespace cr = carla::rpc;
class_<cc::Image, boost::noncopyable, boost::shared_ptr<cc::Image>>("Image", no_init)
.add_property("frame_number", &cc::Image::GetFrameNumber)
.add_property("width", &cc::Image::GetWidth)
.add_property("height", &cc::Image::GetHeight)
.add_property("type", +[](const cc::Image &self) -> std::string {
return self.GetType();
})
.add_property("fov", &cc::Image::GetFOV)
.add_property("raw_data", +[](cc::Image &self) {
#if PYTHON3X
//NOTE(Andrei): python37
auto *ptr = PyMemoryView_FromMemory(reinterpret_cast<char *>(self.GetData()), self.GetSize(), PyBUF_READ);
#else
//NOTE(Andrei): python2.7
auto *ptr = PyBuffer_FromMemory(self.GetData(), self.GetSize());
#endif
return object(handle<>(ptr));
})
;
class_<cc::Actor, boost::noncopyable, boost::shared_ptr<cc::Actor>>("Actor", no_init)
.add_property("id", &cc::Actor::GetId)
.add_property("type_id", +[](const cc::Actor &self) -> std::string {
return self.GetTypeId();
})
.def("get_world", &cc::Actor::GetWorld)
.def("get_location", &cc::Actor::GetLocation)
.def("get_transform", &cc::Actor::GetTransform)
.def("set_location", &cc::Actor::SetLocation, (arg("location")))
.def("set_transform", &cc::Actor::SetTransform, (arg("transform")))
.def("destroy", &cc::Actor::Destroy)
.def(self_ns::str(self_ns::self))
;
class_<cc::Vehicle, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Vehicle>>("Vehicle", no_init)
.def("apply_control", &cc::Vehicle::ApplyControl, (arg("control")))
.def("set_autopilot", &cc::Vehicle::SetAutopilot, (arg("enabled")=true))
.def(self_ns::str(self_ns::self))
;
class_<cc::Sensor, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Sensor>>("Sensor", no_init)
.def("listen", +[](cc::Sensor &self, boost::python::object callback) {
// Make sure the callback is actually callable.
if (!PyCallable_Check(callback.ptr())) {
PyErr_SetString(PyExc_TypeError, "callback argument must be callable!");
throw_error_already_set();
return;
}
// Subscribe to the sensor.
self.Listen([callback](auto message) {
cc::SharedPtr<cc::Image> image;
try {
image = cc::Image::FromBuffer(message->buffer());
} catch (const std::exception &e) {
std::cerr << "exception while parsing the image: " << e.what() << std::endl;
return;
}
GILLockGuard gil_lock;
try {
boost::python::call<void>(callback.ptr(), boost::python::object(image));
} catch (const boost::python::error_already_set &e) {
PyErr_Print();
}
});
}, (arg("callback")))
.def(self_ns::str(self_ns::self))
;
}