Skip to content

Commit

Permalink
Add parameters component (#305)
Browse files Browse the repository at this point in the history
Adds a parameter registry, which allows:

* Declaring a parameter.
* Getting the value of a parameter.
* Setting the value of a parameter.
* Listing all parameters.

These operations can be done remotely with services
or locally using the parameters registry API.
Parameter types are defined as protobuf messages.

To simplify interaction with parameters, a parameters
client wrapper for sending requests to the services
and an `ign param` cli command are provided.

Signed-off-by: Ivan Santiago Paunovic <[email protected]>
Signed-off-by: Steve Peters <[email protected]>
Co-authored-by: Carlos Agüero <[email protected]>
Co-authored-by: Steve Peters <[email protected]>
  • Loading branch information
3 people authored Oct 26, 2022
1 parent 991dfe7 commit 2d0d1d0
Show file tree
Hide file tree
Showing 23 changed files with 2,387 additions and 3 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ ign_find_package(SQLite3
# Configure the build
#============================================================================
ign_configure_build(QUIT_IF_BUILD_ERRORS
COMPONENTS log)
COMPONENTS log parameters)

#============================================================================
# ign command line support
Expand Down
4 changes: 2 additions & 2 deletions log/include/ignition/transport/log/Recorder.hh
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ namespace ignition

/// \brief Begin recording topics
/// \param[in] _file path to log file
/// \return NO_ERROR if recording was successfully started. If the file
/// \return SUCCESS if recording was successfully started. If the file
/// already existed, this will return FAILED_TO_OPEN.
public: RecorderError Start(const std::string &_file);

Expand All @@ -86,7 +86,7 @@ namespace ignition
/// \param[in] _topic The exact topic name
/// \note This method attempts to subscribe to the topic immediately.
/// The subscription will be kept until this is destructed.
/// \return NO_ERROR if the subscription was created.
/// \return SUCCESS if the subscription was created.
public: RecorderError AddTopic(const std::string &_topic);

/// \brief Add a topic to be recorded (regex match)
Expand Down
2 changes: 2 additions & 0 deletions parameters/include/ignition/transport/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

ign_install_all_headers(COMPONENT parameters)
115 changes: 115 additions & 0 deletions parameters/include/ignition/transport/parameters/Client.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright (C) 2022 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifndef IGNITION_TRANSPORT_PARAMETERS_CLIENT_HH_
#define IGNITION_TRANSPORT_PARAMETERS_CLIENT_HH_

#include <memory>
#include <string>

#include "google/protobuf/message.h"

#include "ignition/msgs/parameter_declarations.pb.h"

#include "ignition/transport/config.hh"
#include "ignition/transport/Node.hh"
#include "ignition/transport/parameters/Export.hh"
#include "ignition/transport/parameters/Interface.hh"

namespace ignition
{
namespace transport
{
namespace parameters
{

// Inline bracket to help doxygen filtering.
inline namespace IGNITION_TRANSPORT_VERSION_NAMESPACE {

struct ParametersClientPrivate;

/// \brief Allow to get, set, declare or list parameters
/// \brief in a remote registry.
class IGNITION_TRANSPORT_PARAMETERS_VISIBLE ParametersClient
: public ParametersInterface
{
/// \brief Constructor.
/// \param[in] _serverNamespace Namespace of the parameters registry
/// services. The client will send requests to:
/// * /${_serverNamespace}/get_parameter
/// * /${_serverNamespace}/list_parameters
/// * /${_serverNamespace}/set_parameter
/// * /${_serverNamespace}/declare_parameter
/// \param[in] _timeoutMs Time to wait for the server to respond.
public: ParametersClient(
const std::string & _serverNamespace = "",
unsigned int _timeoutMs = kDefaultTimeoutMs);

/// \brief Destructor.
public: ~ParametersClient();

/// \brief No copy constructor.
public: ParametersClient(const ParametersClient &) = delete;
/// \brief No copy assignment.
public: ParametersClient & operator=(
const ParametersClient &) = delete;
/// \brief Default move constructor.
public: ParametersClient(ParametersClient &&);
/// \brief Default move assignment.
public: ParametersClient & operator=(
ParametersClient &&);

/// \brief Declare a new parameter.
/// See ParametersInterface::DeclareParameter().
public: ParameterResult DeclareParameter(
const std::string & _parameterName,
const google::protobuf::Message & _msg) final;

/// \brief Request the value of a parameter.
/// See ParametersInterface::Parameter().
public: ParameterResult Parameter(
const std::string & _parameterName,
google::protobuf::Message & _parameter) const final;

public: ParameterResult Parameter(
const std::string & _parameterName,
std::unique_ptr<google::protobuf::Message> & _parameter) const final;

/// \brief Set the value of a parameter.
/// See ParametersInterface::SetParameter().
public: ParameterResult SetParameter(
const std::string & _parameterName,
const google::protobuf::Message & _msg) final;

/// \brief List all parameters.
/// \return Protobuf message with a list of all declared parameter
/// names and their types.
public: ignition::msgs::ParameterDeclarations
ListParameters() const final;

private:
/// \brief Pointer to implementation.
private: std::unique_ptr<ParametersClientPrivate> dataPtr;

constexpr static inline unsigned int kDefaultTimeoutMs = 5000;
};
}
}
}
}

#endif
112 changes: 112 additions & 0 deletions parameters/include/ignition/transport/parameters/Interface.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright (C) 2022 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifndef IGNITION_TRANSPORT_PARAMETERS_INTERFACE_HH_
#define IGNITION_TRANSPORT_PARAMETERS_INTERFACE_HH_

#include <functional>
#include <memory>
#include <string>
#include <variant>

#include <google/protobuf/message.h>

#include <ignition/msgs/parameter_declarations.pb.h>

#include "ignition/transport/config.hh"
#include "ignition/transport/parameters/result.hh"
#include "ignition/transport/parameters/Export.hh"

namespace ignition
{
namespace transport
{
namespace parameters
{
// Inline bracket to help doxygen filtering.
inline namespace IGNITION_TRANSPORT_VERSION_NAMESPACE {

/// \brief Common interface, implemented by ParametersRegistry
/// (local updates) and by ParametersClients (remote requests).
class IGNITION_TRANSPORT_PARAMETERS_VISIBLE ParametersInterface
{
/// Default virtual destructor.
public: virtual ~ParametersInterface() = default;

/// \brief Declare a new parameter.
/// \param[in] _parameterName Name of the parameter to be declared.
/// \param[in] _msg Protobuf message to be used as the initial
/// parameter value.
/// \return A ParameterResult return code, can return error types:
/// - ParameterResultType::AlreadyDeclared if the parameter was already
/// declared.
/// - ParameterResultType::InvalidType if the parameter type is not
/// valid.
public: virtual ParameterResult DeclareParameter(
const std::string & _parameterName,
const google::protobuf::Message & _msg) = 0;

/// \brief Request the value of a parameter.
/// \param[in] _parameterName Name of the parameter to be requested.
/// \param[out] _parameter Output were the parameter value will be set.
/// \return A ParameterResult return code, can return error types:
/// - ParameterResultType::NotDeclared if the parameter was not
/// declared.
/// - ParameterResultType::InvalidType if the parameter type was
/// invalid.
/// - ParameterResultType::Unexpected, if an unexpected error happened.
public: virtual ParameterResult Parameter(
const std::string & _parameterName,
google::protobuf::Message & _parameter) const = 0;

/// \brief Request the value of a parameter.
/// Similar to the other overload, but it allocates a message of the
/// right type.
///
/// \param[in] _parameterName Name of the parameter to be requested.
/// \param[out] _parameter Output were the parameter value will be set.
/// \return A ParameterResult return code, can return error types:
/// - ParameterResultType::NotDeclared if the parameter was not
/// declared.
/// - ParameterResultType::Unexpected, if an unexpected error happened.
public: virtual ParameterResult Parameter(
const std::string & _parameterName,
std::unique_ptr<google::protobuf::Message> & _parameter) const = 0;

/// \brief Set the value of a parameter.
/// \param[in] _parameterName Name of the parameter to be set.
/// \param[in] _msg Protobuf message to be used as the parameter value.
/// \return A ParameterResult return code, can return error types:
/// - ParameterResultType::NotDeclared if the parameter was not
/// declared.
/// - ParameterResultType::InvalidType if the parameter type was
/// invalid.
public: virtual ParameterResult SetParameter(
const std::string & _parameterName,
const google::protobuf::Message & _msg) = 0;

/// \brief List all existing parameters.
/// \return The name and types of existing parameters.
public: virtual ignition::msgs::ParameterDeclarations
ListParameters() const = 0;
};
}
}
}
}

#endif
136 changes: 136 additions & 0 deletions parameters/include/ignition/transport/parameters/Registry.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* Copyright (C) 2022 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifndef IGNITION_TRANSPORT_PARAMETERS_REGISTRY_HH_
#define IGNITION_TRANSPORT_PARAMETERS_REGISTRY_HH_

#include <functional>
#include <memory>
#include <string>

#include <google/protobuf/message.h>

#include <ignition/msgs/parameter_declarations.pb.h>

#include "ignition/transport/config.hh"
#include "ignition/transport/parameters/result.hh"
#include "ignition/transport/parameters/Export.hh"
#include "ignition/transport/parameters/Interface.hh"

namespace ignition
{
namespace transport
{
namespace parameters
{
// Inline bracket to help doxygen filtering.
inline namespace IGNITION_TRANSPORT_VERSION_NAMESPACE {

struct ParametersRegistryPrivate;

/// \brief Provides a parameter registry.
/// Parameters can be declared, get or set in the registry.
/// It also provides services, so the parameters can be get, set or
/// listed from other processes.
///
/// Provided services:
/// * /${_parametersServicesNamespace}/get_parameter
/// * /${_parametersServicesNamespace}/list_parameters
/// * /${_parametersServicesNamespace}/set_parameter
/// * /${_parametersServicesNamespace}/declare_parameter
class IGNITION_TRANSPORT_PARAMETERS_VISIBLE ParametersRegistry
: public ParametersInterface
{
/// \brief Constructor.
/// \param[in] _parametersServicesNamespace Namespace that will be used
/// in all the created services names.
public: explicit ParametersRegistry(
const std::string & _parametersServicesNamespace);

/// \brief Destructor.
public: ~ParametersRegistry();

/// \brief No copy constructor.
public: ParametersRegistry(const ParametersRegistry &) = delete;
/// \brief No copy assignment.
public: ParametersRegistry &
operator=(const ParametersRegistry &) = delete;
/// \brief Default move constructor.
public: ParametersRegistry(ParametersRegistry &&);
/// \brief Default move assignment.
public: ParametersRegistry &
operator=(ParametersRegistry &&);

/// \brief Declare a new parameter.
/// See ParametersInterface::DeclareParameter().
public: ParameterResult DeclareParameter(
const std::string & _parameterName,
const google::protobuf::Message & _msg) final;

/// \brief Request the value of a parameter.
/// See ParametersInterface::Parameter().
public: ParameterResult Parameter(
const std::string & _parameterName,
google::protobuf::Message & _parameter) const final;

public: ParameterResult Parameter(
const std::string & _parameterName,
std::unique_ptr<google::protobuf::Message> & _parameter) const final;

/// \brief Set the value of a parameter.
/// See ParametersInterface::SetParameter().
public: ParameterResult SetParameter(
const std::string & _parameterName,
const google::protobuf::Message & _msg) final;

/// \brief List all parameters.
/// \return Protobuf message with a list of all declared parameter
/// names and their types.
public: ignition::msgs::ParameterDeclarations
ListParameters() const final;

/// \brief Declare a new parameter.
/// \param[in] _parameterName Name of the parameter.
/// \param[in] _initialValue The initial value of the parameter.
/// The parameter type will be deduced from the type of the message.
/// \throw std::invalid_argument if `_initialValue` is `nullptr`.
/// \throw ParameterAlreadyDeclaredException if a parameter with the
/// same name was declared before.
public: ParameterResult DeclareParameter(
const std::string & _parameterName,
std::unique_ptr<google::protobuf::Message> _initialValue);

/// \brief Set the value of a parameter.
/// \param[in] _parameterName Name of the parameter to set.
/// \param[in] _value The value of the parameter.
/// \throw ParameterNotDeclaredException if a parameter of that name
/// was not declared before.
/// \throw ParameterInvalidTypeException if the type does not match
/// the type of the parameter when it was declared.
public: ParameterResult SetParameter(
const std::string & _parameterName,
std::unique_ptr<google::protobuf::Message> _value);

/// \brief Pointer to implementation.
private: std::unique_ptr<ParametersRegistryPrivate> dataPtr;
};
}
}
}
}

#endif
Loading

0 comments on commit 2d0d1d0

Please sign in to comment.