forked from Archive/PX4-Autopilot
453 lines
11 KiB
C++
453 lines
11 KiB
C++
/****************************************************************************
|
||
*
|
||
* Copyright (c) 2018 PX4 Development Team. All rights reserved.
|
||
*
|
||
* Redistribution and use in source and binary forms, with or without
|
||
* modification, are permitted provided that the following conditions
|
||
* are met:
|
||
*
|
||
* 1. Redistributions of source code must retain the above copyright
|
||
* notice, this list of conditions and the following disclaimer.
|
||
* 2. Redistributions in binary form must reproduce the above copyright
|
||
* notice, this list of conditions and the following disclaimer in
|
||
* the documentation and/or other materials provided with the
|
||
* distribution.
|
||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||
* used to endorse or promote products derived from this software
|
||
* without specific prior written permission.
|
||
*
|
||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
* POSSIBILITY OF SUCH DAMAGE.
|
||
*
|
||
****************************************************************************/
|
||
|
||
/**
|
||
* @file param.h
|
||
*
|
||
* C++ Parameter class
|
||
*/
|
||
|
||
#pragma once
|
||
|
||
#include "param_macros.h"
|
||
#include <float.h>
|
||
#include <math.h>
|
||
|
||
#include <parameters/px4_parameters.hpp>
|
||
|
||
#define _DEFINE_SINGLE_PARAMETER(x) \
|
||
do_not_explicitly_use_this_namespace::PAIR(x);
|
||
|
||
#define _CALL_UPDATE(x) \
|
||
STRIP(x).update();
|
||
|
||
// define the parameter update method, which will update all parameters.
|
||
// It is marked as 'final', so that wrong usages lead to a compile error (see below)
|
||
#define _DEFINE_PARAMETER_UPDATE_METHOD(...) \
|
||
protected: \
|
||
void updateParamsImpl() final { \
|
||
APPLY_ALL(_CALL_UPDATE, __VA_ARGS__) \
|
||
} \
|
||
private:
|
||
|
||
// Define a list of parameters. This macro also creates code to update parameters.
|
||
// If you get a compile error like:
|
||
// error: virtual function ‘virtual void <class>::updateParamsImpl()’
|
||
// It means you have a custom inheritance tree (at least one class with params that inherits from another
|
||
// class with params) and you need to use DEFINE_PARAMETERS_CUSTOM_PARENT() for **all** classes in
|
||
// that tree.
|
||
#define DEFINE_PARAMETERS(...) \
|
||
APPLY_ALL(_DEFINE_SINGLE_PARAMETER, __VA_ARGS__) \
|
||
_DEFINE_PARAMETER_UPDATE_METHOD(__VA_ARGS__)
|
||
|
||
|
||
#define _DEFINE_PARAMETER_UPDATE_METHOD_CUSTOM_PARENT(parent_class, ...) \
|
||
protected: \
|
||
void updateParamsImpl() override { \
|
||
parent_class::updateParamsImpl(); \
|
||
APPLY_ALL(_CALL_UPDATE, __VA_ARGS__) \
|
||
} \
|
||
private:
|
||
|
||
#define DEFINE_PARAMETERS_CUSTOM_PARENT(parent_class, ...) \
|
||
APPLY_ALL(_DEFINE_SINGLE_PARAMETER, __VA_ARGS__) \
|
||
_DEFINE_PARAMETER_UPDATE_METHOD_CUSTOM_PARENT(parent_class, __VA_ARGS__)
|
||
|
||
|
||
|
||
// This namespace never needs to be used directly. Use the DEFINE_PARAMETERS_CUSTOM_PARENT and
|
||
// DEFINE_PARAMETERS macros instead (the Param classes don't depend on using the macro, the macro just
|
||
// makes sure that update() is automatically called).
|
||
namespace do_not_explicitly_use_this_namespace
|
||
{
|
||
|
||
template<typename T, px4::params p>
|
||
class Param
|
||
{
|
||
};
|
||
|
||
// We use partial template specialization for each param type. This is only supported for classes, not individual methods,
|
||
// which is why we have to repeat the whole class
|
||
template<px4::params p>
|
||
class Param<float, p>
|
||
{
|
||
public:
|
||
// static type-check
|
||
static_assert(px4::parameters_type[(int)p] == PARAM_TYPE_FLOAT, "parameter type must be float");
|
||
|
||
Param()
|
||
{
|
||
//param_set_used(handle());
|
||
update();
|
||
}
|
||
|
||
float get() const { return _val; }
|
||
|
||
const float &reference() const { return _val; }
|
||
|
||
/// Store the parameter value to the parameter storage (@see param_set())
|
||
bool commit() const
|
||
{
|
||
return true; // TODO
|
||
//return param_set(handle(), &_val) == 0;
|
||
}
|
||
|
||
/// Store the parameter value to the parameter storage, w/o notifying the system (@see param_set_no_notification())
|
||
bool commit_no_notification() const
|
||
{
|
||
return true; // TODO
|
||
//return param_set_no_notification(handle(), &_val) == 0;
|
||
}
|
||
|
||
/// Set and commit a new value. Returns true if the value changed.
|
||
bool commit_no_notification(float val)
|
||
{
|
||
if (fabsf(val - _val) > FLT_EPSILON) {
|
||
set(val);
|
||
commit_no_notification();
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
void set(float val) { _val = val; }
|
||
|
||
void reset()
|
||
{
|
||
//param_reset_no_notification(handle()); // TODO
|
||
update();
|
||
}
|
||
|
||
bool update()
|
||
{
|
||
return true; // TODO
|
||
//return param_get(handle(), &_val) == 0;
|
||
}
|
||
|
||
//param_t handle() const { return param_handle(p); }
|
||
private:
|
||
float _val;
|
||
};
|
||
|
||
// external version
|
||
template<px4::params p>
|
||
class Param<float &, p>
|
||
{
|
||
public:
|
||
// static type-check
|
||
static_assert(px4::parameters_type[(int)p] == PARAM_TYPE_FLOAT, "parameter type must be float");
|
||
|
||
Param(float &external_val)
|
||
: _val(external_val)
|
||
{
|
||
//param_set_used(handle()); // TODO
|
||
update();
|
||
}
|
||
|
||
float get() const { return _val; }
|
||
|
||
const float &reference() const { return _val; }
|
||
|
||
/// Store the parameter value to the parameter storage (@see param_set())
|
||
bool commit() const
|
||
{
|
||
//return param_set(handle(), &_val) == 0; // TODO
|
||
return true;
|
||
}
|
||
|
||
/// Store the parameter value to the parameter storage, w/o notifying the system (@see param_set_no_notification())
|
||
bool commit_no_notification() const
|
||
{
|
||
return true;
|
||
//return param_set_no_notification(handle(), &_val) == 0;
|
||
}
|
||
|
||
/// Set and commit a new value. Returns true if the value changed.
|
||
bool commit_no_notification(float val)
|
||
{
|
||
if (fabsf(val - _val) > FLT_EPSILON) {
|
||
set(val);
|
||
commit_no_notification();
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
void set(float val) { _val = val; }
|
||
|
||
void reset()
|
||
{
|
||
//param_reset_no_notification(handle());
|
||
update();
|
||
}
|
||
|
||
bool update()
|
||
{
|
||
return true;
|
||
//return param_get(handle(), &_val) == 0;
|
||
}
|
||
|
||
//param_t handle() const { return param_handle(p); }
|
||
private:
|
||
float &_val;
|
||
};
|
||
|
||
template<px4::params p>
|
||
class Param<int32_t, p>
|
||
{
|
||
public:
|
||
// static type-check
|
||
static_assert(px4::parameters_type[(int)p] == PARAM_TYPE_INT32, "parameter type must be int32_t");
|
||
|
||
Param()
|
||
{
|
||
//param_set_used(handle());
|
||
update();
|
||
}
|
||
|
||
int32_t get() const { return _val; }
|
||
|
||
const int32_t &reference() const { return _val; }
|
||
|
||
/// Store the parameter value to the parameter storage (@see param_set())
|
||
bool commit() const
|
||
{
|
||
return true;
|
||
//return param_set(handle(), &_val) == 0;
|
||
}
|
||
|
||
/// Store the parameter value to the parameter storage, w/o notifying the system (@see param_set_no_notification())
|
||
bool commit_no_notification() const
|
||
{
|
||
//return param_set_no_notification(handle(), &_val) == 0;
|
||
return true;
|
||
}
|
||
|
||
/// Set and commit a new value. Returns true if the value changed.
|
||
bool commit_no_notification(int32_t val)
|
||
{
|
||
if (val != _val) {
|
||
set(val);
|
||
commit_no_notification();
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
void set(int32_t val) { _val = val; }
|
||
|
||
void reset()
|
||
{
|
||
//param_reset_no_notification(handle());
|
||
update();
|
||
}
|
||
|
||
bool update()
|
||
{
|
||
//return param_get(handle(), &_val) == 0;
|
||
return true;
|
||
}
|
||
|
||
//param_t handle() const { return param_handle(p); }
|
||
private:
|
||
int32_t _val;
|
||
};
|
||
|
||
//external version
|
||
template<px4::params p>
|
||
class Param<int32_t &, p>
|
||
{
|
||
public:
|
||
// static type-check
|
||
static_assert(px4::parameters_type[(int)p] == PARAM_TYPE_INT32, "parameter type must be int32_t");
|
||
|
||
Param(int32_t &external_val)
|
||
: _val(external_val)
|
||
{
|
||
//param_set_used(handle());
|
||
update();
|
||
}
|
||
|
||
int32_t get() const { return _val; }
|
||
|
||
const int32_t &reference() const { return _val; }
|
||
|
||
/// Store the parameter value to the parameter storage (@see param_set())
|
||
bool commit() const
|
||
{
|
||
return true;
|
||
//return param_set(handle(), &_val) == 0;
|
||
}
|
||
|
||
/// Store the parameter value to the parameter storage, w/o notifying the system (@see param_set_no_notification())
|
||
bool commit_no_notification() const
|
||
{
|
||
return true;
|
||
//return param_set_no_notification(handle(), &_val) == 0;
|
||
}
|
||
|
||
/// Set and commit a new value. Returns true if the value changed.
|
||
bool commit_no_notification(int32_t val)
|
||
{
|
||
if (val != _val) {
|
||
set(val);
|
||
commit_no_notification();
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
void set(int32_t val) { _val = val; }
|
||
|
||
void reset()
|
||
{
|
||
//param_reset_no_notification(handle());
|
||
update();
|
||
}
|
||
|
||
bool update()
|
||
{
|
||
//return param_get(handle(), &_val) == 0;
|
||
return true;
|
||
}
|
||
|
||
//param_t handle() const { return param_handle(p); }
|
||
private:
|
||
int32_t &_val;
|
||
};
|
||
|
||
template<px4::params p>
|
||
class Param<bool, p>
|
||
{
|
||
public:
|
||
// static type-check
|
||
static_assert(px4::parameters_type[(int)p] == PARAM_TYPE_INT32, "parameter type must be int32_t");
|
||
|
||
Param()
|
||
{
|
||
//param_set_used(handle());
|
||
update();
|
||
}
|
||
|
||
bool get() const { return _val; }
|
||
|
||
const bool &reference() const { return _val; }
|
||
|
||
/// Store the parameter value to the parameter storage (@see param_set())
|
||
bool commit() const
|
||
{
|
||
int32_t value_int = (int32_t)_val;
|
||
//return param_set(handle(), &value_int) == 0;
|
||
return true;
|
||
}
|
||
|
||
/// Store the parameter value to the parameter storage, w/o notifying the system (@see param_set_no_notification())
|
||
bool commit_no_notification() const
|
||
{
|
||
int32_t value_int = (int32_t)_val;
|
||
//return param_set_no_notification(handle(), &value_int) == 0;
|
||
return true;
|
||
}
|
||
|
||
/// Set and commit a new value. Returns true if the value changed.
|
||
bool commit_no_notification(bool val)
|
||
{
|
||
if (val != _val) {
|
||
set(val);
|
||
commit_no_notification();
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
void set(bool val) { _val = val; }
|
||
|
||
void reset()
|
||
{
|
||
//param_reset_no_notification(handle());
|
||
update();
|
||
}
|
||
|
||
bool update()
|
||
{
|
||
int32_t value_int;
|
||
int ret = 0;//param_get(handle(), &value_int);
|
||
|
||
if (ret == 0) {
|
||
_val = value_int != 0;
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
//param_t handle() const { return param_handle(p); }
|
||
private:
|
||
bool _val;
|
||
};
|
||
|
||
template <px4::params p>
|
||
using ParamFloat = Param<float, p>;
|
||
|
||
template <px4::params p>
|
||
using ParamInt = Param<int32_t, p>;
|
||
|
||
template <px4::params p>
|
||
using ParamExtFloat = Param<float &, p>;
|
||
|
||
template <px4::params p>
|
||
using ParamExtInt = Param<int32_t &, p>;
|
||
|
||
template <px4::params p>
|
||
using ParamBool = Param<bool, p>;
|
||
|
||
} /* namespace do_not_explicitly_use_this_namespace */
|
||
|
||
|
||
// Raise an appropriate compile error if a Param class is used directly (just to simplify debugging)
|
||
template<px4::params p>
|
||
class ParamInt
|
||
{
|
||
static_assert((int)p &&false, "Do not use this class directly, use the DEFINE_PARAMETERS macro instead");
|
||
};
|
||
template<px4::params p>
|
||
class ParamFloat
|
||
{
|
||
static_assert((int)p &&false, "Do not use this class directly, use the DEFINE_PARAMETERS macro instead");
|
||
};
|