Skip to content

Commit

Permalink
Merge pull request #3079 from randaz81/deviceBundler
Browse files Browse the repository at this point in the history
deviceBundler
  • Loading branch information
randaz81 authored Feb 6, 2024
2 parents c09c9f6 + 6d2f382 commit 55d8319
Show file tree
Hide file tree
Showing 15 changed files with 569 additions and 69 deletions.
10 changes: 9 additions & 1 deletion doc/release/master.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
-----
Expand All @@ -31,4 +32,11 @@ Fixes
New Features
------------

* Added new command line tool `yarpDeviceParamParserGenerator`. See official yarp documentation (cmd_yarpDeviceParamParserGenerator.dox)
* 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
1 change: 1 addition & 0 deletions src/devices/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
53 changes: 53 additions & 0 deletions src/devices/deviceBundler/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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()
100 changes: 100 additions & 0 deletions src/devices/deviceBundler/DeviceBundler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* SPDX-FileCopyrightText: 2024-2024 Istituto Italiano di Tecnologia (IIT)
* SPDX-License-Identifier: BSD-3-Clause
*/

#include "DeviceBundler.h"

#include <yarp/os/Log.h>
#include <yarp/os/LogComponent.h>
#include <yarp/os/LogStream.h>

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;
}
48 changes: 48 additions & 0 deletions src/devices/deviceBundler/DeviceBundler.h
Original file line number Diff line number Diff line change
@@ -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 <yarp/dev/DeviceDriver.h>
#include <yarp/dev/PolyDriver.h>
#include <yarp/dev/IWrapper.h>
#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
134 changes: 134 additions & 0 deletions src/devices/deviceBundler/DeviceBundler_ParamsParser.cpp
Original file line number Diff line number Diff line change
@@ -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 <yarp/os/LogStream.h>
#include <yarp/os/Value.h>

namespace {
YARP_LOG_COMPONENT(DeviceBundlerParamsCOMPONENT, "yarp.device.DeviceBundler")
}


std::vector<std::string> DeviceBundler_ParamsParser::getListOfParams() const
{
std::vector<std::string> 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: "<<it->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;
}
Loading

0 comments on commit 55d8319

Please sign in to comment.