Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deviceBundler #3079

Merged
merged 3 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading