133 lines
4.2 KiB
C++
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))
|
|
;
|
|
}
|