diff --git a/doc/release/master.md b/doc/release/master.md index a8317fccdfe..f646cf6762c 100644 --- a/doc/release/master.md +++ b/doc/release/master.md @@ -22,6 +22,7 @@ Deprecations and removals * Removed library `libYARP_wire_rep_utils`. * Removed `extern/md5` * Removed `extern/ros` messages and examples. +* The syntax yarpdev --device xxx --subdevice yyy has been deprecated. See discussion: https://github.com/robotology/yarp/discussions/3078 Fixes ----- @@ -31,4 +32,11 @@ Fixes New Features ------------ -* Added new command line tool `yarpDeviceParamParserGenerator`. See official yarp documentation (cmd_yarpDeviceParamParserGenerator.dox) \ No newline at end of file +* Added new command line tool `yarpDeviceParamParserGenerator`. See official yarp documentation (cmd_yarpDeviceParamParserGenerator.dox) + +### Devices + +#### deviceBundler + +* Added new device `deviceBundler` which can be useful to open two devices and attach them while using a single yarpdev command line. + See https://github.com/robotology/yarp/discussions/3078 \ No newline at end of file diff --git a/src/devices/CMakeLists.txt b/src/devices/CMakeLists.txt index 6e39e66e95f..45196492a03 100644 --- a/src/devices/CMakeLists.txt +++ b/src/devices/CMakeLists.txt @@ -17,6 +17,7 @@ yarp_begin_plugin_library(yarpmod add_subdirectory(audioFromFileDevice) add_subdirectory(audioToFileDevice) + add_subdirectory(deviceBundler) add_subdirectory(openNI2DepthCamera) add_subdirectory(frameTransformClient) add_subdirectory(frameTransformGet) diff --git a/src/devices/deviceBundler/CMakeLists.txt b/src/devices/deviceBundler/CMakeLists.txt new file mode 100644 index 00000000000..0bf7de2efb5 --- /dev/null +++ b/src/devices/deviceBundler/CMakeLists.txt @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT) +# SPDX-License-Identifier: BSD-3-Clause + +yarp_prepare_plugin(deviceBundler + CATEGORY device + TYPE DeviceBundler + INCLUDE DeviceBundler.h + DEFAULT ON +) + +if(NOT SKIP_deviceBundler) + yarp_add_plugin(yarp_deviceBundler) + + generateDeviceParamsParser(DeviceBundler) + + target_sources(yarp_deviceBundler + PRIVATE + DeviceBundler.cpp + DeviceBundler.h + DeviceBundler_ParamsParser.cpp + DeviceBundler_ParamsParser.h + ) + + target_link_libraries(yarp_deviceBundler + PRIVATE + YARP::YARP_os + YARP::YARP_sig + YARP::YARP_dev + ) + list(APPEND YARP_${YARP_PLUGIN_MASTER}_PRIVATE_DEPS + YARP_os + YARP_sig + YARP_dev + ) + + yarp_install( + TARGETS yarp_deviceBundler + EXPORT YARP_${YARP_PLUGIN_MASTER} + COMPONENT ${YARP_PLUGIN_MASTER} + LIBRARY DESTINATION ${YARP_DYNAMIC_PLUGINS_INSTALL_DIR} + ARCHIVE DESTINATION ${YARP_STATIC_PLUGINS_INSTALL_DIR} + YARP_INI DESTINATION ${YARP_PLUGIN_MANIFESTS_INSTALL_DIR} + ) + + set(YARP_${YARP_PLUGIN_MASTER}_PRIVATE_DEPS ${YARP_${YARP_PLUGIN_MASTER}_PRIVATE_DEPS} PARENT_SCOPE) + + set_property(TARGET yarp_deviceBundler PROPERTY FOLDER "Plugins/Device") + + if(YARP_COMPILE_TESTS) + add_subdirectory(tests) + endif() + +endif() diff --git a/src/devices/deviceBundler/DeviceBundler.cpp b/src/devices/deviceBundler/DeviceBundler.cpp new file mode 100644 index 00000000000..010b379aa91 --- /dev/null +++ b/src/devices/deviceBundler/DeviceBundler.cpp @@ -0,0 +1,100 @@ +/* + * SPDX-FileCopyrightText: 2024-2024 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "DeviceBundler.h" + +#include +#include +#include + +namespace { +YARP_LOG_COMPONENT(DEVICEBUNDLER, "yarp.device.DeviceBundler") +} + +DeviceBundler::DeviceBundler() +{ +} + +DeviceBundler::~DeviceBundler() +{ +} + +bool DeviceBundler::open(yarp::os::Searchable& config) +{ + if (!this->parseParams(config)) {return false;} + + std::string s = config.toString(); + + bool ret = true; + + //open wrapper device + yarp::os::Property config_wrap (config.toString().c_str()); + config_wrap.unput("device"); + config_wrap.put("device", m_wrapper_device); + std::string sw = config_wrap.toString(); + ret = m_pdev_wrapper.open(config_wrap); + if (!ret || !m_pdev_wrapper.isValid()) + { + yCError(DEVICEBUNDLER, "Unable to open device:%s", m_wrapper_device.c_str()); + return false; + } + + //open secondary device + yarp::os::Property config_sub(config.toString().c_str()); + config_sub.unput("device"); + config_sub.put("device", m_attached_device); + std::string ss = config_sub.toString(); + ret = m_pdev_subdevice.open(config_sub); + if (!ret || !m_pdev_subdevice.isValid()) + { + yCError(DEVICEBUNDLER, "Unable to open subdevice:%s", m_attached_device.c_str()); + return false; + } + + if (m_doNotAttach) + { + yCInfo(DEVICEBUNDLER, "doNotAttach option found. Device will not be attached."); + return true; + } + + //Attach operations below + ret = m_pdev_wrapper.view(m_iWrapper); + if (!ret) + { + yCError(DEVICEBUNDLER, "Unable to open iWrapper interface. Maybe %s is not a wrapper device?", m_wrapper_device.c_str()); + return false; + } + + ret = m_iWrapper->attach(&m_pdev_subdevice); + if (!ret) + { + yCError(DEVICEBUNDLER, "Unable to attach the two devices: %s and %s", m_wrapper_device.c_str(), m_attached_device.c_str()); + return false; + } + + yCDebug(DEVICEBUNDLER, "Attach operation between %s and %s completed.", m_wrapper_device.c_str(), m_attached_device.c_str()); + return true; +} + +bool DeviceBundler::close() +{ + if (m_iWrapper) + { + m_iWrapper->detach(); + m_iWrapper = nullptr; + } + + if (m_pdev_wrapper.isValid()) + { + m_pdev_wrapper.close(); + } + + if (m_pdev_subdevice.isValid()) + { + m_pdev_subdevice.close(); + } + + return true; +} diff --git a/src/devices/deviceBundler/DeviceBundler.h b/src/devices/deviceBundler/DeviceBundler.h new file mode 100644 index 00000000000..35a2a832fff --- /dev/null +++ b/src/devices/deviceBundler/DeviceBundler.h @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2024-2024 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef YARP_DEVICEBUNDLER_H +#define YARP_DEVICEBUNDLER_H + +#include +#include +#include +#include "DeviceBundler_ParamsParser.h" + +/** +* @ingroup dev_impl_wrapper +* +* \brief `DeviceBundler`: A device capable of opening two additional devices, specified by the user, and +* perform an attach operation. +* +* This device is typically used by yarpdev executable to open a wrapper and subdevice using a single command line. +* For more complex operations, such as opening and attaching more than two devices, it is recommended to +* use yarprobotinterface instead. +* +* Parameters required by this device are shown in class: DeviceBundler_ParamsParser +*/ + +class DeviceBundler : public yarp::dev::DeviceDriver, + public DeviceBundler_ParamsParser +{ +public: + DeviceBundler(); + DeviceBundler(const DeviceBundler&) = delete; + DeviceBundler(DeviceBundler&&) = delete; + DeviceBundler& operator=(const DeviceBundler&) = delete; + DeviceBundler& operator=(DeviceBundler&&) = delete; + + ~DeviceBundler() override; + + bool open(yarp::os::Searchable& config) override; + bool close() override; + +private: + yarp::dev::PolyDriver m_pdev_wrapper; + yarp::dev::PolyDriver m_pdev_subdevice; + yarp::dev::IWrapper* m_iWrapper=nullptr; +}; + +#endif // YARP_DEVICEBUNDLER_H diff --git a/src/devices/deviceBundler/DeviceBundler_ParamsParser.cpp b/src/devices/deviceBundler/DeviceBundler_ParamsParser.cpp new file mode 100644 index 00000000000..84cf2c1d4f0 --- /dev/null +++ b/src/devices/deviceBundler/DeviceBundler_ParamsParser.cpp @@ -0,0 +1,134 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + + +// Generated by yarpDeviceParamParserGenerator (1.0) +// This is an automatically generated file. Please do not edit it. +// It will be re-generated if the cmake flag ALLOW_DEVICE_PARAM_PARSER_GERNERATION is ON. + +// Generated on: Mon Feb 5 19:57:52 2024 + + +#include "DeviceBundler_ParamsParser.h" +#include +#include + +namespace { + YARP_LOG_COMPONENT(DeviceBundlerParamsCOMPONENT, "yarp.device.DeviceBundler") +} + + +std::vector DeviceBundler_ParamsParser::getListOfParams() const +{ + std::vector params; + params.push_back("wrapper_device"); + params.push_back("attached_device"); + params.push_back("doNotAttach"); + return params; +} + + +bool DeviceBundler_ParamsParser::parseParams(const yarp::os::Searchable & config) +{ + //Check for --help option + if (config.check("help")) + { + yCInfo(DeviceBundlerParamsCOMPONENT) << getDocumentationOfDeviceParams(); + } + + std::string config_string = config.toString(); + yarp::os::Property prop_check(config_string.c_str()); + //Parser of parameter wrapper_device + { + if (config.check("wrapper_device")) + { + m_wrapper_device = config.find("wrapper_device").asString(); + yCInfo(DeviceBundlerParamsCOMPONENT) << "Parameter 'wrapper_device' using value:" << m_wrapper_device; + } + else + { + yCError(DeviceBundlerParamsCOMPONENT) << "Mandatory parameter 'wrapper_device' not found!"; + yCError(DeviceBundlerParamsCOMPONENT) << "Description of the parameter: Name of the wrapper device"; + return false; + } + prop_check.unput("wrapper_device"); + } + + //Parser of parameter attached_device + { + if (config.check("attached_device")) + { + m_attached_device = config.find("attached_device").asString(); + yCInfo(DeviceBundlerParamsCOMPONENT) << "Parameter 'attached_device' using value:" << m_attached_device; + } + else + { + yCError(DeviceBundlerParamsCOMPONENT) << "Mandatory parameter 'attached_device' not found!"; + yCError(DeviceBundlerParamsCOMPONENT) << "Description of the parameter: Name of the subdevice that will be attached to the wrapper device"; + return false; + } + prop_check.unput("attached_device"); + } + + //Parser of parameter doNotAttach + { + if (config.check("doNotAttach")) + { + m_doNotAttach = config.find("doNotAttach").asBool(); + yCInfo(DeviceBundlerParamsCOMPONENT) << "Parameter 'doNotAttach' using value:" << m_doNotAttach; + } + else + { + yCInfo(DeviceBundlerParamsCOMPONENT) << "Parameter 'doNotAttach' using DEFAULT value:" << m_doNotAttach; + } + prop_check.unput("doNotAttach"); + } + + /* + //This code check if the user set some parameter which are not check by the parser + //If the parser is set in strict mode, this will generate an error + if (prop_check.size() > 0) + { + bool extra_params_found = false; + for (auto it=prop_check.begin(); it!=prop_check.end(); it++) + { + if (m_parser_is_strict) + { + yCError(DeviceBundlerParamsCOMPONENT) << "User asking for parameter: "<name <<" which is unknown to this parser!"; + extra_params_found = true; + } + else + { + yCWarning(DeviceBundlerParamsCOMPONENT) << "User asking for parameter: "<< it->name <<" which is unknown to this parser!"; + } + } + + if (m_parser_is_strict && extra_params_found) + { + return false; + } + } + */ + return true; +} + + +std::string DeviceBundler_ParamsParser::getDocumentationOfDeviceParams() const +{ + std::string doc; + doc = doc + std::string("\n=============================================\n"); + doc = doc + std::string("This is the help for device: DeviceBundler\n"); + doc = doc + std::string("\n"); + doc = doc + std::string("This is the list of the parameters accepted by the device:\n"); + doc = doc + std::string("'wrapper_device': Name of the wrapper device\n"); + doc = doc + std::string("'attached_device': Name of the subdevice that will be attached to the wrapper device\n"); + doc = doc + std::string("'doNotAttach': If set to true, the two devices are opened, but not attached\n"); + doc = doc + std::string("\n"); + doc = doc + std::string("Here are some examples of invocation command with yarpdev, with all params:\n"); + doc = doc + " yarpdev --device DeviceBundler --wrapper_device device_name1 --attached_device device_name2 --doNotAttach false\n"; + doc = doc + std::string("Using only mandatory params:\n"); + doc = doc + " yarpdev --device DeviceBundler --wrapper_device device_name1 --attached_device device_name2\n"; + doc = doc + std::string("=============================================\n"); return doc; +} diff --git a/src/devices/deviceBundler/DeviceBundler_ParamsParser.h b/src/devices/deviceBundler/DeviceBundler_ParamsParser.h new file mode 100644 index 00000000000..b9c363c5f62 --- /dev/null +++ b/src/devices/deviceBundler/DeviceBundler_ParamsParser.h @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + + +// Generated by yarpDeviceParamParserGenerator (1.0) +// This is an automatically generated file. Please do not edit it. +// It will be re-generated if the cmake flag ALLOW_DEVICE_PARAM_PARSER_GERNERATION is ON. + +// Generated on: Mon Feb 5 19:57:52 2024 + + +#ifndef DEVICEBUNDLER_PARAMSPARSER_H +#define DEVICEBUNDLER_PARAMSPARSER_H + +#include +#include +#include + +/** +* This class is the parameters parser for class DeviceBundler. +* +* These are the used parameters: +* | Group name | Parameter name | Type | Units | Default Value | Required | Description | Notes | +* |:----------:|:---------------:|:------:|:-----:|:-------------:|:--------:|:-----------------------------------------------------------------:|:----------------------------------------------------:| +* | - | wrapper_device | string | - | device_name1 | 1 | Name of the wrapper device | This device must derive from yarp::dev::IWrapper | +* | - | attached_device | string | - | device_name2 | 1 | Name of the subdevice that will be attached to the wrapper device | - | +* | - | doNotAttach | bool | - | false | 0 | If set to true, the two devices are opened, but not attached | It should not be used, except for debugging purposes | +* +* The device can be launched by yarpdev using one of the following examples: +* \code{.unparsed} +* yarpdev --device DeviceBundler --wrapper_device device_name1 --attached_device device_name2 --doNotAttach false +* \endcode +* +* \code{.unparsed} +* yarpdev --device DeviceBundler --wrapper_device device_name1 --attached_device device_name2 +* \endcode +* +*/ + +class DeviceBundler_ParamsParser : public yarp::dev::IDeviceDriverParams +{ +public: + ~DeviceBundler_ParamsParser() override = default; + +public: + const std::string m_device_type = {"DeviceBundler"}; + bool m_parser_is_strict = false; + struct parser_version_type + { + int major = 1; + int minor = 0; + }; + const parser_version_type m_parser_version; + std::string m_wrapper_device = {"device_name1"}; + std::string m_attached_device = {"device_name2"}; + bool m_doNotAttach = {false}; + + bool parseParams(const yarp::os::Searchable & config) override; + std::string getDeviceType() const override { return m_device_type; } + std::string getDocumentationOfDeviceParams() const override; + std::vector getListOfParams() const override; +}; + +#endif diff --git a/src/devices/deviceBundler/DeviceBundler_params.md b/src/devices/deviceBundler/DeviceBundler_params.md new file mode 100644 index 00000000000..86cfb220bf0 --- /dev/null +++ b/src/devices/deviceBundler/DeviceBundler_params.md @@ -0,0 +1,5 @@ + | Group name | Parameter name | Type | Units | Default Value | Required | Description | Notes | + |:----------:|:---------------:|:------:|:-----:|:--------------:|:--------:|:---------------------------------------------------------------------:|:-----------------------------------------------------:| + | | wrapper_device | string | - | device_name1 | Yes | Name of the wrapper device | This device must derive from yarp::dev::IWrapper | + | | attached_device | string | - | device_name2 | Yes | Name of the subdevice that will be attached to the wrapper device | | + | | doNotAttach | bool | - | false | No | If set to true, the two devices are opened, but not attached | It should not be used, except for debugging purposes | diff --git a/src/devices/deviceBundler/tests/CMakeLists.txt b/src/devices/deviceBundler/tests/CMakeLists.txt new file mode 100644 index 00000000000..b1b0dd773ab --- /dev/null +++ b/src/devices/deviceBundler/tests/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2024 Istituto Italiano di Tecnologia (IIT) +# SPDX-License-Identifier: BSD-3-Clause + +create_device_test(DeviceBundler) diff --git a/src/devices/deviceBundler/tests/DeviceBundler_test.cpp b/src/devices/deviceBundler/tests/DeviceBundler_test.cpp new file mode 100644 index 00000000000..faaed472cf0 --- /dev/null +++ b/src/devices/deviceBundler/tests/DeviceBundler_test.cpp @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT) + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include + +TEST_CASE("dev::DeviceBundlerTest", "[yarp::dev]") +{ + YARP_REQUIRE_PLUGIN("deviceBundler", "device"); + YARP_REQUIRE_PLUGIN("fakeBattery", "device"); + YARP_REQUIRE_PLUGIN("battery_nws_yarp", "device"); + + yarp::os::Network::setLocalMode(true); + const bool verboseDebug = true; + + SECTION("Test the DeviceBundler") + { + yarp::dev::PolyDriver pd; + yarp::os::Property p; + + p.put("device", "deviceBundler"); + p.put("wrapper_device", "battery_nws_yarp"); + p.put("name", "/battery_nws_yarp"); + p.put("attached_device", "fakeBattery"); + REQUIRE(pd.open(p)); + yarp::os::Time::delay(1.0); + REQUIRE(pd.close()); + } + + yarp::os::Network::setLocalMode(false); +} diff --git a/src/devices/map2DStorage/map2DStorage.h b/src/devices/map2DStorage/map2DStorage.h index 9594a87f47b..da88da87b65 100644 --- a/src/devices/map2DStorage/map2DStorage.h +++ b/src/devices/map2DStorage/map2DStorage.h @@ -47,9 +47,6 @@ * |:--------------:|:--------------:|:-------:|:--------------:|:----------------:|:-----------: |:-----------------------------------------------------------------:|:-----:| * | name | - | string | - | /mapServer/rpc | No | Full name of the rpc port opened by the Map2DServer device. | | * | mapCollection | - | string | - | - | No | The name of .ini file containing a map collection. | | - - * \section Notes: - * Integration with ROS map server is currently under development. */ class Map2DStorage : diff --git a/src/libYARP_dev/src/yarp/dev/Drivers.cpp b/src/libYARP_dev/src/yarp/dev/Drivers.cpp index 66caac19cfb..88d60503548 100644 --- a/src/libYARP_dev/src/yarp/dev/Drivers.cpp +++ b/src/libYARP_dev/src/yarp/dev/Drivers.cpp @@ -412,8 +412,23 @@ int Drivers::yarpdev(int argc, char *argv[]) { return 0; } - // ask for a wrapped, remotable device rather than raw device - options.put("wrapped","1"); + //The following syntax is deprecated: generate an error! + if (options.check("device") && options.check("subdevice")) + { + std::string dev_name = options.find("device").asString(); + std::string subdev_name = options.find("subdevice").asString(); + yCError(DRIVERS, "The syntax:"); + yCError(DRIVERS, "yarpdev --device %s --subdevice %s", dev_name.c_str(), subdev_name.c_str()); + yCError(DRIVERS, "has been deprecated."); + yCError(DRIVERS, "Use the following command line instead:"); + yCError(DRIVERS, "yarpdev --device deviceBundler --wrapper_device %s --attached_device %s", dev_name.c_str(), subdev_name.c_str()); + return 0; + } + + //yarpdev enables the wrapping mechanism, which is not enabled by default if, + //for example a device is opened from the code, using PolyDriver.open() + //When enabled, it asks for a wrapped, remotable device rather than raw device + options.put("wrapping_enabled","1"); //YarpDevMonitor monitor; if (options.check("verbose")) { diff --git a/src/libYARP_dev/src/yarp/dev/PolyDriver.cpp b/src/libYARP_dev/src/yarp/dev/PolyDriver.cpp index ea452917ffb..afa30202b8b 100644 --- a/src/libYARP_dev/src/yarp/dev/PolyDriver.cpp +++ b/src/libYARP_dev/src/yarp/dev/PolyDriver.cpp @@ -44,23 +44,23 @@ class PolyDriver::Private PolyDriver::PolyDriver() : DeviceDriver(), - dd(nullptr), - mPriv(nullptr) + m_dd(nullptr), + m_Priv(nullptr) { } PolyDriver::PolyDriver(const std::string& txt) : DeviceDriver(), - dd(nullptr), - mPriv(nullptr) + m_dd(nullptr), + m_Priv(nullptr) { open(txt); } PolyDriver::PolyDriver(yarp::os::Searchable& config) : DeviceDriver(), - dd(nullptr), - mPriv(nullptr) + m_dd(nullptr), + m_Priv(nullptr) { open(config); } @@ -68,8 +68,8 @@ PolyDriver::PolyDriver(yarp::os::Searchable& config) : PolyDriver::~PolyDriver() { close(); - yCAssert(POLYDRIVER, dd == nullptr); - yCAssert(POLYDRIVER, mPriv == nullptr); + yCAssert(POLYDRIVER, m_dd == nullptr); + yCAssert(POLYDRIVER, m_Priv == nullptr); } @@ -88,13 +88,13 @@ bool PolyDriver::open(yarp::os::Searchable& config) // already open - should close first return false; } - if (mPriv==nullptr) { - mPriv = new PolyDriver::Private; + if (m_Priv==nullptr) { + m_Priv = new PolyDriver::Private; } - yCAssert(POLYDRIVER, mPriv != nullptr); + yCAssert(POLYDRIVER, m_Priv != nullptr); coreOpen(config); - mPriv->info.fromString(config.toString()); + m_Priv->info.fromString(config.toString()); return isValid(); } @@ -103,29 +103,29 @@ bool PolyDriver::open(yarp::os::Searchable& config) bool PolyDriver::close() { bool result = false; - if (mPriv!=nullptr) { - int ct = mPriv->removeRef(); + if (m_Priv !=nullptr) { + int ct = m_Priv->removeRef(); if (ct==0) { - yCAssert(POLYDRIVER, mPriv != nullptr); - delete mPriv; - mPriv = nullptr; - if (dd!=nullptr) { - result = dd->close(); - delete dd; - dd = nullptr; + yCAssert(POLYDRIVER, m_Priv != nullptr); + delete m_Priv; + m_Priv = nullptr; + if (m_dd !=nullptr) { + result = m_dd->close(); + delete m_dd; + m_dd = nullptr; } else { result = true; } } - dd = nullptr; - mPriv = nullptr; + m_dd = nullptr; + m_Priv = nullptr; } return result; } bool PolyDriver::isValid() const { - return dd != nullptr; + return m_dd != nullptr; } bool PolyDriver::link(PolyDriver& alt) @@ -136,18 +136,18 @@ bool PolyDriver::link(PolyDriver& alt) if (isValid()) { return false; } - dd = alt.dd; - if (mPriv!=nullptr) { - int ct = mPriv->removeRef(); + m_dd = alt.m_dd; + if (m_Priv !=nullptr) { + int ct = m_Priv->removeRef(); if (ct==0) { - yCAssert(POLYDRIVER, mPriv != nullptr); - delete mPriv; + yCAssert(POLYDRIVER, m_Priv != nullptr); + delete m_Priv; } } - mPriv = alt.mPriv; - yCAssert(POLYDRIVER, dd != nullptr); - yCAssert(POLYDRIVER, mPriv != nullptr); - mPriv->addRef(); + m_Priv = alt.m_Priv; + yCAssert(POLYDRIVER, m_dd != nullptr); + yCAssert(POLYDRIVER, m_Priv != nullptr); + m_Priv->addRef(); return true; } @@ -165,55 +165,84 @@ bool PolyDriver::coreOpen(yarp::os::Searchable& prop) DeviceDriver *driver = nullptr; DriverCreator *creator = Drivers::factory().find(str.c_str()); - if (creator!=nullptr) { + if (creator!=nullptr) + { Value *val; - if (config->check("wrapped",val) && (!creator->getWrapper().empty())) { + //if the device has a wrapper.. + if (config->check("wrapping_enabled",val) && (!creator->getWrapper().empty())) + { std::string wrapper = creator->getWrapper(); - DriverCreator *wrapCreator = - Drivers::factory().find(wrapper.c_str()); - if (wrapCreator!=nullptr) { + DriverCreator *wrapCreator = Drivers::factory().find(wrapper.c_str()); + // and this wrapper exists.. + if (wrapCreator!=nullptr) + { p.fromString(config->toString()); - p.unput("wrapped"); + p.unput("wrapping_enabled"); config = &p; - if (wrapCreator!=creator) { - p.put("subdevice", str); - p.put("device", wrapper); + //and this wrapper is not the device itself.. + if (wrapCreator!=creator) + { + //..than open the wrapper instead of the device. + //this operation is done using the deviceBundler plugin, and passing to it + //the name of devices that it has to open and attach. + p.put("attached_device", str); + p.put("wrapper_device", wrapper); + p.put("device", "deviceBundler"); driver = wrapCreator->create(); creator = wrapCreator; - } else { - // already wrapped + } + else + { + //otherwise the device itself is already the wrapper driver = creator->create(); } } - } else { + } + //..the device does not have a wrapper + else + { driver = creator->create(); } - } else { + } + else + { // FIXME do not use yarpdev here yCIError(POLYDRIVER, id(), "Could not find device <%s>", str.c_str()); return false; } - if (driver!=nullptr) { + if (driver!=nullptr) + { PolyDriver *manager = creator->owner(); - if (manager!=nullptr) { + if (manager!=nullptr) + { link(*manager); return true; } yCIDebug(POLYDRIVER, id(), "Parameters are %s", config->toString().c_str()); driver->setId(id()); + //try to open the device: bool ok = driver->open(*config); - if (!ok) { + //if the device did not open successfully + if (!ok) + { yCIError(POLYDRIVER, id(), "Driver <%s> was found but could not open", config->find("device").toString().c_str()); delete driver; driver = nullptr; - } else { + } + //if the device opened successfully + else + { + //if the device is deprecated... yarp::dev::DeprecatedDeviceDriver *ddd = nullptr; driver->view(ddd); - if(ddd) { + if(ddd) + { + //but the user requested it explicitly, than just print a warning if(config->check("allow-deprecated-devices")) { yCIWarning(POLYDRIVER, id(), R"(Device "%s" is deprecated. Opening since the "allow-deprecated-devices" option was passed in the configuration.)", str.c_str()); + //if it is not requested explicitly, then close it with an error } else { yCIError(POLYDRIVER, id(), R"(Device "%s" is deprecated. Pass the "allow-deprecated-devices" option in the configuration if you want to open it anyway.)", str.c_str()); driver->close(); @@ -221,6 +250,7 @@ bool PolyDriver::coreOpen(yarp::os::Searchable& prop) return false; } } + //print some info std::string name = creator->getName(); std::string wrapper = creator->getWrapper(); std::string code = creator->getCode(); @@ -229,7 +259,7 @@ bool PolyDriver::coreOpen(yarp::os::Searchable& prop) name.c_str(), code.c_str()); } - dd = driver; + m_dd = driver; return true; } @@ -240,22 +270,22 @@ bool PolyDriver::coreOpen(yarp::os::Searchable& prop) DeviceDriver *PolyDriver::take() { // this is not very careful - DeviceDriver *result = dd; - dd = nullptr; + DeviceDriver *result = m_dd; + m_dd = nullptr; return result; } bool PolyDriver::give(DeviceDriver *dd, bool own) { close(); - this->dd = dd; + this->m_dd = dd; if (dd!=nullptr) { - if (mPriv==nullptr) { - mPriv = new PolyDriver::Private; + if (m_Priv ==nullptr) { + m_Priv = new PolyDriver::Private; } - yCAssert(POLYDRIVER, mPriv != nullptr); + yCAssert(POLYDRIVER, m_Priv != nullptr); if (!own) { - mPriv->addRef(); + m_Priv->addRef(); } } return true; @@ -264,7 +294,7 @@ bool PolyDriver::give(DeviceDriver *dd, bool own) DeviceDriver* PolyDriver::getImplementation() { if(isValid()) { - return dd->getImplementation(); + return m_dd->getImplementation(); } else { return nullptr; } diff --git a/src/libYARP_dev/src/yarp/dev/PolyDriver.h b/src/libYARP_dev/src/yarp/dev/PolyDriver.h index d2acaaaffa4..73b755774b5 100644 --- a/src/libYARP_dev/src/yarp/dev/PolyDriver.h +++ b/src/libYARP_dev/src/yarp/dev/PolyDriver.h @@ -108,13 +108,13 @@ class YARP_dev_API PolyDriver : DeviceDriver *getImplementation() override; private: - DeviceDriver *dd; + DeviceDriver *m_dd; bool coreOpen(yarp::os::Searchable& config); #ifndef DOXYGEN_SHOULD_SKIP_THIS class Private; - Private* mPriv; + Private* m_Priv; #endif }; diff --git a/src/libYARP_dev/tests/PolyDriverTest.cpp b/src/libYARP_dev/tests/PolyDriverTest.cpp index bc3f46e3879..f15df1bbe8f 100644 --- a/src/libYARP_dev/tests/PolyDriverTest.cpp +++ b/src/libYARP_dev/tests/PolyDriverTest.cpp @@ -111,7 +111,7 @@ TEST_CASE("dev::PolyDriverTest", "[yarp::dev]") Property p; p.put("device","devicedrivertest"); p.put("verbose",1); - p.put("wrapped",1); + p.put("wrapping_enabled",1); for (int i=0; i<5; i++) { PolyDriver *dd = new PolyDriver(p); delete dd;