diff --git a/data/RobotAPI/VariantInfo-RobotAPI.xml b/data/RobotAPI/VariantInfo-RobotAPI.xml index f4faf8ef47366c0837c1c78c285eeb8be29f14ca..34de6dfffd308bba91f6ad70ca2de2024020af20 100644 --- a/data/RobotAPI/VariantInfo-RobotAPI.xml +++ b/data/RobotAPI/VariantInfo-RobotAPI.xml @@ -42,6 +42,22 @@ propertyName="TCPControlUnitName" propertyIsOptional="true" propertyDefaultValue="TCPControlUnit" /> + <Proxy include="RobotAPI/interface/units/HapticUnit.h" + humanName="Haptic Unit Observer" + typeName="HapticUnitObserverInterfacePrx" + memberName="hapticObserver" + getterName="getHapticObserver" + propertyName="HapticUnitObserverName" + propertyIsOptional="true" + propertyDefaultValue="HapticUnitObserver" /> + <Proxy include="RobotAPI/interface/units/WeissHapticUnit.h" + humanName="Weiss Haptic Unit" + typeName="WeissHapticUnitInterfacePrx" + memberName="weissHapticUnit" + getterName="getWeissHapticUnit" + propertyName="WeissHapticUnitName" + propertyIsOptional="true" + propertyDefaultValue="WeissHapticUnit" /> <Proxy include="RobotAPI/interface/core/RobotState.h" humanName="Robot State Component" typeName="RobotStateComponentInterfacePrx" diff --git a/scenarios/tests/WeissHapticSensorsUnitTest/CMakeLists.txt b/scenarios/tests/WeissHapticSensorsUnitTest/CMakeLists.txt index 4d3f9b968efe4fc1217eef767d7ed8f436f223c4..b94e569387e346dc6b9001c8a0a9cb66af8de1d2 100644 --- a/scenarios/tests/WeissHapticSensorsUnitTest/CMakeLists.txt +++ b/scenarios/tests/WeissHapticSensorsUnitTest/CMakeLists.txt @@ -1,15 +1,16 @@ +set(SCENARIO_CONFIG_COMPONENTS + config/RobotControl.cfg + config/WeissHapticUnitApp.cfg + config/XMLRemoteStateOfferer.WeissHapticGroup.cfg + config/SystemObserver.cfg + config/ConditionHandler.cfg -set(SCENARIO_COMPONENTS - WeissHapticSensorsUnitApp - #WeissHapticSensorApp - HapticObserverApp) + #WeissHapticUnitApp + #WeissHapticSensorApp + #HapticObserverApp +) -# optional 3rd parameter: "path/to/global/config.cfg" -armarx_scenario("WeissHapticSensorsUnitTest" "${SCENARIO_COMPONENTS}") -#set(SCENARIO_CONFIGS -# config/ComponentName.optionalString.cfg -# ) # optional 3rd parameter: "path/to/global/config.cfg" -#armarx_scenario_from_configs("WeissHapticSensorsUnitTest" "${SCENARIO_CONFIGS}") +armarx_scenario_from_configs("WeissHapticSensorsUnitTest" "${SCENARIO_CONFIG_COMPONENTS}") diff --git a/scenarios/tests/WeissHapticSensorsUnitTest/config/ConditionHandler.cfg b/scenarios/tests/WeissHapticSensorsUnitTest/config/ConditionHandler.cfg new file mode 100644 index 0000000000000000000000000000000000000000..75f5b78f40cc1f83f2e59a4e1add7bf7d6235e98 --- /dev/null +++ b/scenarios/tests/WeissHapticSensorsUnitTest/config/ConditionHandler.cfg @@ -0,0 +1,100 @@ +# ================================================================== +# ArmarX properties +# ================================================================== + +# ArmarX.CachePath: Path for cache files +# Attributes: +# - Default: ${HOME}/.armarx/mongo/.cache +# - Case sensitivity: no +# - Required: no +# ArmarX.CachePath = ${HOME}/.armarx/mongo/.cache + + +# ArmarX.DataPath: Semicolon-separated search list for data files +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.DataPath = "" + + +# ArmarX.Verbosity: Global logging level for whole application +# Attributes: +# - Default: Verbose +# - Case sensitivity: no +# - Required: no +# - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning} +# ArmarX.Verbosity = Verbose + + +# ArmarX.DisableLogging: Turn logging off in whole application +# Attributes: +# - Default: 0 +# - Case sensitivity: no +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +# ArmarX.DisableLogging = 0 + + +# ArmarX.ApplicationName: Application name +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.ApplicationName = "" + + +# ArmarX.DependenciesConfig: Path to the (usually generated) config file containing all data paths of all dependent projects. This property usually does not need to be edited. +# Attributes: +# - Default: ./config/dependencies.cfg +# - Case sensitivity: no +# - Required: no +# ArmarX.DependenciesConfig = ./config/dependencies.cfg + + +# ArmarX.Config: Comma-separated list of configuration files +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.Config = "" + + +# ================================================================== +# ArmarX.ConditionHandler properties +# ================================================================== + +# ArmarX.ConditionHandler.HistoryLength: Length of condition history kept by the conditionhandler +# Attributes: +# - Default: 1000 +# - Case sensitivity: no +# - Required: no +# ArmarX.ConditionHandler.HistoryLength = 1000 + + +# ArmarX.ConditionHandler.Observers: Comma seperated observer list +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.ConditionHandler.Observers = "" + + +# ArmarX.ConditionHandler.MinimumLoggingLevel: Local logging level only for this component +# Attributes: +# - Default: Undefined +# - Case sensitivity: no +# - Required: no +# - Possible values: {Error, Fatal, Info, Undefined, Verbose, Warning} +# ArmarX.ConditionHandler.MinimumLoggingLevel = Undefined + + +# ArmarX.ConditionHandler.ObjectName: Name of IceGrid well-known object +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.ConditionHandler.ObjectName = "" + + + diff --git a/scenarios/tests/WeissHapticSensorsUnitTest/config/RobotControl.cfg b/scenarios/tests/WeissHapticSensorsUnitTest/config/RobotControl.cfg new file mode 100644 index 0000000000000000000000000000000000000000..08183f785f9ff82363676cbaa0206c66ad98ee6f --- /dev/null +++ b/scenarios/tests/WeissHapticSensorsUnitTest/config/RobotControl.cfg @@ -0,0 +1,117 @@ +# ================================================================== +# ArmarX properties +# ================================================================== + +# ArmarX.CachePath: Path for cache files +# Attributes: +# - Default: ${HOME}/.armarx/mongo/.cache +# - Case sensitivity: no +# - Required: no +# ArmarX.CachePath = ${HOME}/.armarx/mongo/.cache + + +# ArmarX.DataPath: Semicolon-separated search list for data files +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.DataPath = "" + + +# ArmarX.Verbosity: Global logging level for whole application +# Attributes: +# - Default: Verbose +# - Case sensitivity: no +# - Required: no +# - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning} +# ArmarX.Verbosity = Verbose + + +# ArmarX.DisableLogging: Turn logging off in whole application +# Attributes: +# - Default: 0 +# - Case sensitivity: no +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +# ArmarX.DisableLogging = 0 + + +# ArmarX.ApplicationName: Application name +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.ApplicationName = "" + + +# ArmarX.DatapathConfig: Path to the (usually generated) config file containing all data paths of all dependent projects. This property usually does not need to be edited. +# Attributes: +# - Default: ./config/datapath.cfg +# - Case sensitivity: no +# - Required: no +# ArmarX.DatapathConfig = ./config/datapath.cfg + + +# ArmarX.Config: Comma-separated list of configuration files +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.Config = "" + + +# ================================================================== +# ArmarX.RobotControlStateOfferer properties +# ================================================================== + +# ArmarX.RobotControlStateOfferer.stateName: name of the state to load +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +ArmarX.RobotControlStateOfferer.stateName = "WeissHapticSensorTest" + + +# ArmarX.RobotControlStateOfferer.proxyName: name of the proxy to load +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +ArmarX.RobotControlStateOfferer.proxyName = "WeissHapticGroupRemoteStateOfferer" + + +# ArmarX.RobotControlStateOfferer.logstates: +# Attributes: +# - Default: Comma seperated list with state names to log. If not set, all transitions will be logged +# - Case sensitivity: no +# - Required: no +# ArmarX.RobotControlStateOfferer.logstates = Comma seperated list with state names to log. If not set, all transitions will be logged + + +# ArmarX.RobotControlStateOfferer.enableStatechartLogger: disable/enable statechart logger +# Attributes: +# - Default: 0 +# - Case sensitivity: no +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +# ArmarX.RobotControlStateOfferer.enableStatechartLogger = 0 + + +# ArmarX.RobotControlStateOfferer.MinimumLoggingLevel: Local logging level only for this component +# Attributes: +# - Default: Undefined +# - Case sensitivity: no +# - Required: no +# - Possible values: {Error, Fatal, Info, Undefined, Verbose, Warning} +# ArmarX.RobotControlStateOfferer.MinimumLoggingLevel = Undefined + + +# ArmarX.RobotControlStateOfferer.ObjectName: Name of IceGrid well-known object +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.RobotControlStateOfferer.ObjectName = "" + + + diff --git a/scenarios/tests/WeissHapticSensorsUnitTest/config/SystemObserver.cfg b/scenarios/tests/WeissHapticSensorsUnitTest/config/SystemObserver.cfg new file mode 100644 index 0000000000000000000000000000000000000000..f8cf074d1b8f678fc7d01f930487e2e71904d6f6 --- /dev/null +++ b/scenarios/tests/WeissHapticSensorsUnitTest/config/SystemObserver.cfg @@ -0,0 +1,84 @@ +# ================================================================== +# ArmarX properties +# ================================================================== + +# ArmarX.CachePath: Path for cache files +# Attributes: +# - Default: ${HOME}/.armarx/mongo/.cache +# - Case sensitivity: no +# - Required: no +# ArmarX.CachePath = ${HOME}/.armarx/mongo/.cache + + +# ArmarX.DataPath: Semicolon-separated search list for data files +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.DataPath = "" + + +# ArmarX.Verbosity: Global logging level for whole application +# Attributes: +# - Default: Verbose +# - Case sensitivity: no +# - Required: no +# - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning} +# ArmarX.Verbosity = Verbose + + +# ArmarX.DisableLogging: Turn logging off in whole application +# Attributes: +# - Default: 0 +# - Case sensitivity: no +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +# ArmarX.DisableLogging = 0 + + +# ArmarX.ApplicationName: Application name +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.ApplicationName = "" + + +# ArmarX.DependenciesConfig: Path to the (usually generated) config file containing all data paths of all dependent projects. This property usually does not need to be edited. +# Attributes: +# - Default: ./config/dependencies.cfg +# - Case sensitivity: no +# - Required: no +# ArmarX.DependenciesConfig = ./config/dependencies.cfg + + +# ArmarX.Config: Comma-separated list of configuration files +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.Config = "" + + +# ================================================================== +# ArmarX.SystemObserver properties +# ================================================================== + +# ArmarX.SystemObserver.MinimumLoggingLevel: Local logging level only for this component +# Attributes: +# - Default: Undefined +# - Case sensitivity: no +# - Required: no +# - Possible values: {Error, Fatal, Info, Undefined, Verbose, Warning} +# ArmarX.SystemObserver.MinimumLoggingLevel = Undefined + + +# ArmarX.SystemObserver.ObjectName: Name of IceGrid well-known object +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.SystemObserver.ObjectName = "" + + + diff --git a/scenarios/tests/WeissHapticSensorsUnitTest/config/WeissHapticUnitApp.cfg b/scenarios/tests/WeissHapticSensorsUnitTest/config/WeissHapticUnitApp.cfg new file mode 100644 index 0000000000000000000000000000000000000000..b8777df3dda7e5e6a369d2d71531ed9e217a0ea0 --- /dev/null +++ b/scenarios/tests/WeissHapticSensorsUnitTest/config/WeissHapticUnitApp.cfg @@ -0,0 +1,121 @@ +# ================================================================== +# ArmarX properties +# ================================================================== + +# ArmarX.CachePath: Path for cache files +# Attributes: +# - Default: ${HOME}/.armarx/mongo/.cache +# - Case sensitivity: no +# - Required: no +# ArmarX.CachePath = ${HOME}/.armarx/mongo/.cache + + +# ArmarX.DataPath: Semicolon-separated search list for data files +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.DataPath = "" + + +# ArmarX.Verbosity: Global logging level for whole application +# Attributes: +# - Default: Verbose +# - Case sensitivity: no +# - Required: no +# - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning} +# ArmarX.Verbosity = Verbose + + +# ArmarX.DisableLogging: Turn logging off in whole application +# Attributes: +# - Default: 0 +# - Case sensitivity: no +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +# ArmarX.DisableLogging = 0 + + +# ArmarX.ApplicationName: Application name +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.ApplicationName = "" + + +# ArmarX.DependenciesConfig: Path to the (usually generated) config file containing all data paths of all dependent projects. This property usually does not need to be edited. +# Attributes: +# - Default: ./config/dependencies.cfg +# - Case sensitivity: no +# - Required: no +# ArmarX.DependenciesConfig = ./config/dependencies.cfg + + +# ArmarX.Config: Comma-separated list of configuration files +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.Config = "" + + +# ================================================================== +# ArmarX.HapticUnit properties +# ================================================================== + +# ArmarX.HapticUnit.HapticTopicName: Name of the Haptic Topic. +# Attributes: +# - Default: HapticValues +# - Case sensitivity: no +# - Required: no +# ArmarX.HapticUnit.HapticTopicName = HapticValues + + +# ArmarX.HapticUnit.MinimumLoggingLevel: Local logging level only for this component +# Attributes: +# - Default: Undefined +# - Case sensitivity: no +# - Required: no +# - Possible values: {Error, Fatal, Info, Undefined, Verbose, Warning} +# ArmarX.HapticUnit.MinimumLoggingLevel = Undefined + + +# ArmarX.HapticUnit.ObjectName: Name of IceGrid well-known object +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +ArmarX.HapticUnit.ObjectName = "WeissHapticUnit" + + +# ================================================================== +# ArmarX.HapticUnitObserver properties +# ================================================================== + +# ArmarX.HapticUnitObserver.HapticTopicName: Name of the HapticUnit Topic +# Attributes: +# - Default: HapticValues +# - Case sensitivity: no +# - Required: no +# ArmarX.HapticUnitObserver.HapticTopicName = HapticValues + + +# ArmarX.HapticUnitObserver.MinimumLoggingLevel: Local logging level only for this component +# Attributes: +# - Default: Undefined +# - Case sensitivity: no +# - Required: no +# - Possible values: {Error, Fatal, Info, Undefined, Verbose, Warning} +# ArmarX.HapticUnitObserver.MinimumLoggingLevel = Undefined + + +# ArmarX.HapticUnitObserver.ObjectName: Name of IceGrid well-known object +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.HapticUnitObserver.ObjectName = "" + + + diff --git a/scenarios/tests/WeissHapticSensorsUnitTest/config/XMLRemoteStateOfferer.WeissHapticGroup.cfg b/scenarios/tests/WeissHapticSensorsUnitTest/config/XMLRemoteStateOfferer.WeissHapticGroup.cfg new file mode 100644 index 0000000000000000000000000000000000000000..caedd0eae1f142775184efe42a31195f80d7caa6 --- /dev/null +++ b/scenarios/tests/WeissHapticSensorsUnitTest/config/XMLRemoteStateOfferer.WeissHapticGroup.cfg @@ -0,0 +1,91 @@ +# ================================================================== +# ArmarX properties +# ================================================================== + +# ArmarX.CachePath: Path for cache files +# Attributes: +# - Default: ${HOME}/.armarx/mongo/.cache +# - Case sensitivity: no +# - Required: no +# ArmarX.CachePath = ${HOME}/.armarx/mongo/.cache + + +# ArmarX.DataPath: Semicolon-separated search list for data files +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.DataPath = "" + + +# ArmarX.Verbosity: Global logging level for whole application +# Attributes: +# - Default: Verbose +# - Case sensitivity: no +# - Required: no +# - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning} +# ArmarX.Verbosity = Verbose + + +# ArmarX.DisableLogging: Turn logging off in whole application +# Attributes: +# - Default: 0 +# - Case sensitivity: no +# - Required: no +# - Possible values: {0, 1, false, no, true, yes} +# ArmarX.DisableLogging = 0 + + +# ArmarX.ApplicationName: Application name +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +ArmarX.ApplicationName = "XMLStateComponentWeissHapticGroup" + + +# ArmarX.DependenciesConfig: Path to the (usually generated) config file containing all data paths of all dependent projects. This property usually does not need to be edited. +# Attributes: +# - Default: ./config/dependencies.cfg +# - Case sensitivity: no +# - Required: no +# ArmarX.DependenciesConfig = ./config/dependencies.cfg + + +# ArmarX.Config: Comma-separated list of configuration files +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +# ArmarX.Config = "" + + +# ================================================================== +# ArmarX.XMLStateComponent properties +# ================================================================== + +# ArmarX.XMLStateComponent.XMLStatechartGroupDefinitionFile: Path to statechart group definition file (*.scgxml) - relative to projects source dir +# Attributes: +# - Case sensitivity: no +# - Required: yes +ArmarX.XMLStateComponent.XMLStatechartGroupDefinitionFile = RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroup.scgxml + + +# ArmarX.XMLStateComponent.MinimumLoggingLevel: Local logging level only for this component +# Attributes: +# - Default: Undefined +# - Case sensitivity: no +# - Required: no +# - Possible values: {Error, Fatal, Info, Undefined, Verbose, Warning} +# ArmarX.XMLStateComponent.MinimumLoggingLevel = Undefined + + +# ArmarX.XMLStateComponent.ObjectName: Name of IceGrid well-known object +# Attributes: +# - Default: "" +# - Case sensitivity: no +# - Required: no +ArmarX.XMLStateComponent.ObjectName = "XMLStateComponentWeissHapticGroup" + + + diff --git a/scenarios/tests/WeissHapticSensorsUnitTest/startGui.sh b/scenarios/tests/WeissHapticSensorsUnitTest/startGui.sh deleted file mode 100755 index e2f4b07c6fc3db3a101c1ccfee1d6576e35b8b69..0000000000000000000000000000000000000000 --- a/scenarios/tests/WeissHapticSensorsUnitTest/startGui.sh +++ /dev/null @@ -1,8 +0,0 @@ -export CORE_PATH=../../../Core -export GUI_PATH=../../../Gui - -export SCRIPT_PATH=$CORE_PATH/build/bin -export GUI_BIN_PATH=$GUI_PATH/build/bin - -# Gui -$SCRIPT_PATH/startApplication.sh $GUI_BIN_PATH/ArmarXGuiRun & diff --git a/scenarios/tests/WeissHapticSensorsUnitTest/tactile.html b/scenarios/tests/WeissHapticSensorsUnitTest/tactile.html index ace11468986c6f332d36237c411da536fa9e78b7..5703a051b31ebdbd184d24262a1b1b25a0cc37bd 100755 --- a/scenarios/tests/WeissHapticSensorsUnitTest/tactile.html +++ b/scenarios/tests/WeissHapticSensorsUnitTest/tactile.html @@ -10,6 +10,12 @@ sensors = []; </script> <script src="ttyACM0.js"></script> <script src="ttyACM1.js"></script> +<script src="ttyACM2.js"></script> +<script src="ttyACM3.js"></script> +<script src="ttyACM4.js"></script> +<script src="ttyACM5.js"></script> +<script src="ttyACM6.js"></script> +<script src="ttyACM7.js"></script> <style type="text/css"> #out { font-size: 10px; diff --git a/source/RobotAPI/applications/CMakeLists.txt b/source/RobotAPI/applications/CMakeLists.txt index 6aa836f2e77b2de7ad076cce8d003f2a84cd2905..01bd7549a8ceae418036ba78a1dd44a89d8da769 100644 --- a/source/RobotAPI/applications/CMakeLists.txt +++ b/source/RobotAPI/applications/CMakeLists.txt @@ -3,8 +3,8 @@ add_subdirectory(ForceTorqueObserver) add_subdirectory(HeadIKUnit) add_subdirectory(TCPControlUnit) -add_subdirectory(WeissHapticSensorsUnit) -add_subdirectory(WeissHapticSensor) +add_subdirectory(WeissHapticUnit) +#add_subdirectory(WeissHapticSensor) add_subdirectory(HapticObserver) diff --git a/source/RobotAPI/applications/HapticObserver/CMakeLists.txt b/source/RobotAPI/applications/HapticObserver/CMakeLists.txt index f1b7f7073f1873cb27033d76e8c8b99774d81b7b..f9205fbe4da5b3f0cfb440f7e9e68ca8f661c356 100644 --- a/source/RobotAPI/applications/HapticObserver/CMakeLists.txt +++ b/source/RobotAPI/applications/HapticObserver/CMakeLists.txt @@ -8,7 +8,7 @@ if (Eigen3_FOUND) ${Eigen3_INCLUDE_DIR}) endif() -set(COMPONENT_LIBS WeissHapticSensorListener RobotAPIUnits) +set(COMPONENT_LIBS RobotAPIUnits) set(EXE_SOURCE main.cpp HapticObserverApp.h) diff --git a/source/RobotAPI/applications/WeissHapticSensorsUnit/CMakeLists.txt b/source/RobotAPI/applications/WeissHapticUnit/CMakeLists.txt similarity index 71% rename from source/RobotAPI/applications/WeissHapticSensorsUnit/CMakeLists.txt rename to source/RobotAPI/applications/WeissHapticUnit/CMakeLists.txt index ffc1889bb5753b0acf7cc6544ec0553928f12b97..3708373ea73b863f58052ffa6dc214e14e7f078b 100644 --- a/source/RobotAPI/applications/WeissHapticSensorsUnit/CMakeLists.txt +++ b/source/RobotAPI/applications/WeissHapticUnit/CMakeLists.txt @@ -1,4 +1,4 @@ -armarx_component_set_name("WeissHapticSensorsUnitApp") +armarx_component_set_name("WeissHapticUnitApp") find_package(Eigen3 QUIET) armarx_build_if(Eigen3_FOUND "Eigen3 not available") @@ -10,6 +10,6 @@ endif() set(COMPONENT_LIBS RobotAPIUnits WeissHapticSensor ) -set(EXE_SOURCE main.cpp WeissHapticSensorsUnitApp.h) +set(EXE_SOURCE main.cpp WeissHapticUnitApp.h) armarx_add_component_executable("${EXE_SOURCE}") diff --git a/source/RobotAPI/applications/WeissHapticSensorsUnit/WeissHapticSensorsUnitApp.h b/source/RobotAPI/applications/WeissHapticUnit/WeissHapticUnitApp.h similarity index 66% rename from source/RobotAPI/applications/WeissHapticSensorsUnit/WeissHapticSensorsUnitApp.h rename to source/RobotAPI/applications/WeissHapticUnit/WeissHapticUnitApp.h index 7c1d806ae0111ad4d4a32fcc3e42376d2e4d5058..4466a3b0e17882e97de29656ef6618e29e713425 100644 --- a/source/RobotAPI/applications/WeissHapticSensorsUnit/WeissHapticSensorsUnitApp.h +++ b/source/RobotAPI/applications/WeissHapticUnit/WeissHapticUnitApp.h @@ -14,31 +14,29 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * - * @package RobotAPI::application::WeissHapticSensorsUnit + * @package RobotAPI::application::WeissHapticUnit * @author Simon Ottenhaus ( simon dot ottenhaus at kit dot edu ) * @date 2014 * @copyright http://www.gnu.org/licenses/gpl.txt * GNU General Public License */ -#ifndef _ARMARX_APPLICATION_RobotAPI_WeissHapticSensorsUnit_H -#define _ARMARX_APPLICATION_RobotAPI_WeissHapticSensorsUnit_H - - -// #include <RobotAPI/components/@MyComponent@.h> +#ifndef _ARMARX_APPLICATION_RobotAPI_WeissHapticUnit_H +#define _ARMARX_APPLICATION_RobotAPI_WeissHapticUnit_H #include <Core/core/application/Application.h> -#include <RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensorsUnit.h> +#include <RobotAPI/components/units/HapticObserver.h> +#include <RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticUnit.h> namespace armarx { /** - * @class WeissHapticSensorsUnitApp - * @brief A brief description + * @class WeissHapticUnitApp + * @brief Joint Application for WeissHapticUnit and HapticObserver. * - * Detailed Description + * This Application runs both the WeissHapticUnit and the HapticObserver in one executable to avoid TCP communication. */ - class WeissHapticSensorsUnitApp : + class WeissHapticUnitApp : virtual public armarx::Application { /** @@ -47,7 +45,8 @@ namespace armarx void setup(const ManagedIceObjectRegistryInterfacePtr& registry, Ice::PropertiesPtr properties) { - registry->addObject( Component::create<WeissHapticSensorsUnit>(properties) ); + registry->addObject( Component::create<WeissHapticUnit>(properties) ); + registry->addObject( Component::create<HapticObserver>(properties) ); } }; } diff --git a/source/RobotAPI/applications/WeissHapticSensorsUnit/main.cpp b/source/RobotAPI/applications/WeissHapticUnit/main.cpp similarity index 84% rename from source/RobotAPI/applications/WeissHapticSensorsUnit/main.cpp rename to source/RobotAPI/applications/WeissHapticUnit/main.cpp index d2dffa82773301e9539add9c743338a94a70265d..488f764ec81279f8a74391c1f34f3ccf02ac0f7b 100644 --- a/source/RobotAPI/applications/WeissHapticSensorsUnit/main.cpp +++ b/source/RobotAPI/applications/WeissHapticUnit/main.cpp @@ -14,20 +14,20 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * - * @package RobotAPI::application::WeissHapticSensorsUnit + * @package RobotAPI::application::WeissHapticUnit * @author Simon Ottenhaus ( simon dot ottenhaus at kit dot edu ) * @date 2014 * @copyright http://www.gnu.org/licenses/gpl.txt * GNU General Public License */ -#include "WeissHapticSensorsUnitApp.h" +#include "WeissHapticUnitApp.h" #include <Core/core/logging/Logging.h> int main(int argc, char* argv[]) { - armarx::ApplicationPtr app = armarx::Application::createInstance < armarx::WeissHapticSensorsUnitApp > (); - app->setName("WeissHapticSensorsUnit"); + armarx::ApplicationPtr app = armarx::Application::createInstance < armarx::WeissHapticUnitApp > (); + app->setName("WeissHapticUnit"); return app->main(argc, argv); } diff --git a/source/RobotAPI/components/CMakeLists.txt b/source/RobotAPI/components/CMakeLists.txt index 278fe5e3f4df51d33277469499d09273f0a40eaa..8e093e38bd854f9eda7d03309749fd663000e23a 100644 --- a/source/RobotAPI/components/CMakeLists.txt +++ b/source/RobotAPI/components/CMakeLists.txt @@ -1,6 +1,6 @@ add_subdirectory(units) -add_subdirectory(WeissHapticSensorListener) +#add_subdirectory(WeissHapticSensorListener) add_subdirectory(DebugDrawer) add_subdirectory(MMMPlayer) add_subdirectory(robotstate) diff --git a/source/RobotAPI/components/units/HapticObserver.cpp b/source/RobotAPI/components/units/HapticObserver.cpp index 8f5d8293318f8518b978c448cd503816dd7be34f..9bb402e9665847f305f0bac5bd318e298bf84c7a 100644 --- a/source/RobotAPI/components/units/HapticObserver.cpp +++ b/source/RobotAPI/components/units/HapticObserver.cpp @@ -67,6 +67,7 @@ void HapticObserver::reportSensorValues(const std::string& device, const std::st offerDataFieldWithDefault(channelName, "mean", Variant(mean), "Mean value"); offerDataFieldWithDefault(channelName, "timestamp", timestampPtr, "Timestamp"); offerDataFieldWithDefault(channelName, "rate", Variant(0.0f), "Sample rate"); + ARMARX_INFO << "Offering new channel: " << channelName; } else { diff --git a/source/RobotAPI/components/units/HapticObserver.h b/source/RobotAPI/components/units/HapticObserver.h index bec65d205749f93552d8e04712b07fbe33505444..4e167780a5f638c0302a97264df33501c536eadf 100644 --- a/source/RobotAPI/components/units/HapticObserver.h +++ b/source/RobotAPI/components/units/HapticObserver.h @@ -31,6 +31,7 @@ #include <Core/util/variants/eigen3/Eigen3VariantObjectFactories.h> #include <Core/core/services/tasks/PeriodicTask.h> + namespace armarx { diff --git a/source/RobotAPI/components/units/TCPControlUnit.cpp b/source/RobotAPI/components/units/TCPControlUnit.cpp index 2e6b02a6da616825e31b6ae27e9fd7277c92abc3..6b3b01d37b6cc5a9322da46287f87a559c217d67 100644 --- a/source/RobotAPI/components/units/TCPControlUnit.cpp +++ b/source/RobotAPI/components/units/TCPControlUnit.cpp @@ -250,6 +250,10 @@ namespace armarx void TCPControlUnit::periodicExec() { + + + + { ScopedTryLock lock(dataMutex); @@ -274,10 +278,10 @@ namespace armarx RemoteRobot::synchronizeLocalClone(localRobot,robotStateComponentPrx); //ARMARX_DEBUG << "RN TCP R pose2:" << localRobot->getRobotNode("TCP R")->getGlobalPose(); - calculationRunning = true; } } + calculationRunning = true; if (requested) { @@ -344,7 +348,7 @@ namespace armarx { //ARMARX_DEBUG << deactivateSpam(1) << "orientationVelocity before ChangeFrame: " << data.orientationVelocity->output(); data.orientationVelocity = FramedVector3::ChangeFrame(localRobot, *data.orientationVelocity, refFrame); - ARMARX_INFO << deactivateSpam(1) << "Orientation in " << refFrame << ": " << data.orientationVelocity->output(); + ARMARX_INFO << "Orientation in " << refFrame << ": " << data.orientationVelocity->output(); Eigen::Matrix3f rot; rot = Eigen::AngleAxisf(data.orientationVelocity->z*cycleTime*0.001, Eigen::Vector3f::UnitZ()) * Eigen::AngleAxisf(data.orientationVelocity->y*cycleTime*0.001, Eigen::Vector3f::UnitY()) @@ -668,7 +672,7 @@ namespace armarx for (unsigned int i=0; i<nodes.size();i++) { - ARMARX_DEBUG << VAROUT(nodes[i]->getJointValue()) << VAROUT(dTheta[i]); + ARMARX_INFO_S << VAROUT(nodes[i]->getJointValue()) << VAROUT(dTheta[i]); jv[i] = (nodes[i]->getJointValue() + dTheta[i]); if (boost::math::isnan(jv[i]) || boost::math::isinf(jv[i])) { @@ -684,7 +688,7 @@ namespace armarx VectorXf newJointValues; rns->getJointValues(newJointValues); resultJointDelta = newJointValues - oldJointValues; -// ARMARX_DEBUG << "joint angle deltas:\n" << dThetaSum; +// ARMARX_INFO << "joint angle deltas:\n" << dThetaSum; // check tolerances if (checkTolerances()) @@ -696,12 +700,12 @@ namespace armarx float d = dTheta.norm(); float posDist = getMeanErrorPosition(); float oriErr = getErrorRotation(rns->getTCP()); - if (dTheta.norm()<mininumChange) - { -// if (verbose) - ARMARX_INFO << deactivateSpam(1) << "Could not improve result any more (dTheta.norm()=" << d << "), loop:" << step << " Resulting error: pos " << posDist << " orientation: " << oriErr << endl; - break; - } +// if (dTheta.norm()<mininumChange) +// { +//// if (verbose) +// ARMARX_INFO << deactivateSpam(1) << "Could not improve result any more (dTheta.norm()=" << d << "), loop:" << step << " Resulting error: pos " << posDist << " orientation: " << oriErr << endl; +// break; +// } if (checkImprovement && posDist>lastDist) { @@ -803,7 +807,7 @@ namespace armarx // applyDOFWeightsToJacobian(Jacobian); ARMARX_DEBUG << VAROUT(Jacobian); MatrixXf pseudo = computePseudoInverseJacobianMatrix(Jacobian); - ARMARX_DEBUG << VAROUT(Jacobian); + ARMARX_DEBUG << VAROUT(pseudo); ARMARX_DEBUG << VAROUT(error); return pseudo * error; } diff --git a/source/RobotAPI/gui_plugins/HandUnitPlugin/HandUnitGuiPlugin.cpp b/source/RobotAPI/gui_plugins/HandUnitPlugin/HandUnitGuiPlugin.cpp index 7a6601400684e28806902cac3f9653d04a2de4ce..41d7d68b6116d476855e372273366e86755a0df2 100644 --- a/source/RobotAPI/gui_plugins/HandUnitPlugin/HandUnitGuiPlugin.cpp +++ b/source/RobotAPI/gui_plugins/HandUnitPlugin/HandUnitGuiPlugin.cpp @@ -24,10 +24,13 @@ HandUnitGuiPlugin::HandUnitGuiPlugin() HandUnitWidget::HandUnitWidget() : handName("NOT SET YET"), - handUnitProxyName("") + handUnitProxyName(""), + setJointAnglesFlag(false) { // init gui ui.setupUi(getWidget()); + + jointAngleUpdateTask = new PeriodicTask<HandUnitWidget>(this, &HandUnitWidget::setJointAngles, 50); } @@ -41,6 +44,8 @@ void HandUnitWidget::onInitComponent() void HandUnitWidget::onConnectComponent() { connectSlots(); + jointAngleUpdateTask->start(); + handUnitProxy = getProxy<HandUnitInterfacePrx>(handUnitProxyName); handName = handUnitProxy->getHandName(); @@ -61,9 +66,15 @@ void HandUnitWidget::onConnectComponent() std::string shape = ((preshapeStrings->getVariant(i))->get<std::string>()); list << QString::fromStdString(shape); } + ui.comboPreshapes->clear(); ui.comboPreshapes->addItems(list); } +void HandUnitWidget::onDisconnectComponent() +{ + jointAngleUpdateTask->stop(); +} + void HandUnitWidget::onExitComponent() { } @@ -86,12 +97,23 @@ void HandUnitWidget::configured() void HandUnitWidget::preshapeHand() { - ARMARX_INFO << "Setting new hand shape: " << ui.comboPreshapes->currentText().toUtf8().data(); - handUnitProxy->setShape(ui.comboPreshapes->currentText().toUtf8().data()); + setPreshape(ui.comboPreshapes->currentText().toUtf8().data()); } void HandUnitWidget::setJointAngles() { + if(!handUnitProxy) + { + ARMARX_WARNING << "invalid proxy"; + return; + } + + if(!setJointAnglesFlag) + { + return; + } + setJointAnglesFlag = false; + NameValueMap ja; if(handName == "Hand L" || handName == "TCP L") @@ -132,6 +154,37 @@ void HandUnitWidget::setJointAngles() handUnitProxy->setJointAngles(ja); } +void HandUnitWidget::requestSetJointAngles() +{ + setJointAnglesFlag = true; +} + +void HandUnitWidget::openHand() +{ + setPreshape("Open"); +} + +void HandUnitWidget::closeHand() +{ + setPreshape("Close"); +} + +void HandUnitWidget::closeThumb() +{ + setPreshape("Thumb"); +} + +void HandUnitWidget::relaxHand() +{ + setPreshape("Relax"); +} + +void HandUnitWidget::setPreshape(std::string preshape) +{ + ARMARX_INFO << "Setting new hand shape: " << preshape; + handUnitProxy->setShape(preshape); +} + void HandUnitWidget::loadSettings(QSettings *settings) { handUnitProxyName = settings->value("handUnitProxyName", QString::fromStdString(handUnitProxyName)).toString().toStdString(); @@ -147,11 +200,21 @@ void HandUnitWidget::saveSettings(QSettings *settings) void HandUnitWidget::connectSlots() { - //connect(ui.buttonOpen, SIGNAL(clicked()), this, SLOT(openHand())); - //connect(ui.buttonClose, SIGNAL(clicked()), this, SLOT(closeHand())); connect(ui.buttonPreshape, SIGNAL(clicked()), this, SLOT(preshapeHand())); + connect(ui.buttonOpenHand, SIGNAL(clicked()), this, SLOT(openHand())); + connect(ui.buttonCloseHand, SIGNAL(clicked()), this, SLOT(closeHand())); + connect(ui.buttonCloseThumb, SIGNAL(clicked()), this, SLOT(closeThumb())); + connect(ui.buttonRelaxHand, SIGNAL(clicked()), this, SLOT(relaxHand())); //connect(ui.comboPreshapes, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(selectPreshape(const QString&))); - connect(ui.buttonSetJointAngles, SIGNAL(clicked()), this, SLOT(setJointAngles())); + connect(ui.buttonSetJointAngles, SIGNAL(clicked()), this, SLOT(requestSetJointAngles())); + connect(ui.horizontalSliderIndexJ0, SIGNAL(sliderMoved(int)), this, SLOT(requestSetJointAngles())); + connect(ui.horizontalSliderIndexJ1, SIGNAL(sliderMoved(int)), this, SLOT(requestSetJointAngles())); + connect(ui.horizontalSliderMiddleJ0, SIGNAL(sliderMoved(int)), this, SLOT(requestSetJointAngles())); + connect(ui.horizontalSliderMiddleJ1, SIGNAL(sliderMoved(int)), this, SLOT(requestSetJointAngles())); + connect(ui.horizontalSliderRinky, SIGNAL(sliderMoved(int)), this, SLOT(requestSetJointAngles())); + connect(ui.horizontalSliderPalm, SIGNAL(sliderMoved(int)), this, SLOT(requestSetJointAngles())); + connect(ui.horizontalSliderThumbJ0, SIGNAL(sliderMoved(int)), this, SLOT(requestSetJointAngles())); + connect(ui.horizontalSliderThumbJ1, SIGNAL(sliderMoved(int)), this, SLOT(requestSetJointAngles())); } diff --git a/source/RobotAPI/gui_plugins/HandUnitPlugin/HandUnitGuiPlugin.h b/source/RobotAPI/gui_plugins/HandUnitPlugin/HandUnitGuiPlugin.h index 20c38b2e46de5d70b10547a61cdbbb234eaf7125..5c3ac80b240f27214542111830c78ed145e4ad99 100644 --- a/source/RobotAPI/gui_plugins/HandUnitPlugin/HandUnitGuiPlugin.h +++ b/source/RobotAPI/gui_plugins/HandUnitPlugin/HandUnitGuiPlugin.h @@ -38,6 +38,8 @@ #include <string> +#include <Core/core/services/tasks/PeriodicTask.h> + namespace armarx { @@ -87,6 +89,7 @@ namespace armarx // inherited from Component virtual void onInitComponent(); virtual void onConnectComponent(); + virtual void onDisconnectComponent(); virtual void onExitComponent(); // HandUnitListener interface @@ -107,6 +110,14 @@ namespace armarx void preshapeHand(); void setJointAngles(); + void requestSetJointAngles(); + void openHand(); + void closeHand(); + void closeThumb(); + void relaxHand(); + + private: + void setPreshape(std::string preshape); protected: void connectSlots(); @@ -123,6 +134,9 @@ namespace armarx //QPointer<QWidget> __widget; QPointer<HandUnitConfigDialog> dialog; + PeriodicTask<HandUnitWidget>::pointer_type jointAngleUpdateTask; + bool setJointAnglesFlag; + // HandUnitListener interface public: diff --git a/source/RobotAPI/gui_plugins/HandUnitPlugin/HandUnitGuiPlugin.ui b/source/RobotAPI/gui_plugins/HandUnitPlugin/HandUnitGuiPlugin.ui index 35eed4df97e671feb01ae2ffddc8c78e9ce4b616..bda4f4ae305f68c0b8b31a63850f6b8e79e07fdd 100644 --- a/source/RobotAPI/gui_plugins/HandUnitPlugin/HandUnitGuiPlugin.ui +++ b/source/RobotAPI/gui_plugins/HandUnitPlugin/HandUnitGuiPlugin.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>518</width> + <width>637</width> <height>396</height> </rect> </property> @@ -20,7 +20,14 @@ <string>Form</string> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="2" column="1" colspan="2"> + <item row="1" column="3"> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + </widget> + </item> + <item row="2" column="1" colspan="7"> <widget class="QFrame" name="frame"> <property name="frameShape"> <enum>QFrame::StyledPanel</enum> @@ -29,10 +36,27 @@ <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_2"> - <item row="1" column="0"> - <widget class="QLabel" name="label_2"> + <item row="7" column="0"> + <widget class="QLabel" name="label_8"> <property name="text"> - <string>Thumb J0</string> + <string>Rinky</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Thumb J1</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QSlider" name="horizontalSliderThumbJ1"> + <property name="maximum"> + <number>90</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> </property> </widget> </item> @@ -46,6 +70,13 @@ </property> </widget> </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>Middle J1</string> + </property> + </widget> + </item> <item row="5" column="0"> <widget class="QLabel" name="label_6"> <property name="text"> @@ -53,18 +84,15 @@ </property> </widget> </item> - <item row="6" column="1"> - <widget class="QSlider" name="horizontalSliderMiddleJ1"> - <property name="maximum"> - <number>90</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> + <item row="4" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Index J1</string> </property> </widget> </item> - <item row="0" column="1"> - <widget class="QSlider" name="horizontalSliderPalm"> + <item row="6" column="1"> + <widget class="QSlider" name="horizontalSliderMiddleJ1"> <property name="maximum"> <number>90</number> </property> @@ -73,8 +101,8 @@ </property> </widget> </item> - <item row="2" column="1"> - <widget class="QSlider" name="horizontalSliderThumbJ1"> + <item row="5" column="1"> + <widget class="QSlider" name="horizontalSliderMiddleJ0"> <property name="maximum"> <number>90</number> </property> @@ -83,8 +111,8 @@ </property> </widget> </item> - <item row="4" column="1"> - <widget class="QSlider" name="horizontalSliderIndexJ1"> + <item row="1" column="1"> + <widget class="QSlider" name="horizontalSliderThumbJ0"> <property name="maximum"> <number>90</number> </property> @@ -93,22 +121,22 @@ </property> </widget> </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_5"> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> <property name="text"> - <string>Index J1</string> + <string>Thumb J0</string> </property> </widget> </item> - <item row="7" column="0"> - <widget class="QLabel" name="label_8"> + <item row="3" column="0"> + <widget class="QLabel" name="label_4"> <property name="text"> - <string>Rinky</string> + <string>Index J0</string> </property> </widget> </item> - <item row="5" column="1"> - <widget class="QSlider" name="horizontalSliderMiddleJ0"> + <item row="0" column="1"> + <widget class="QSlider" name="horizontalSliderPalm"> <property name="maximum"> <number>90</number> </property> @@ -117,20 +145,6 @@ </property> </widget> </item> - <item row="6" column="0"> - <widget class="QLabel" name="label_7"> - <property name="text"> - <string>Middle J1</string> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>Index J0</string> - </property> - </widget> - </item> <item row="3" column="1"> <widget class="QSlider" name="horizontalSliderIndexJ0"> <property name="maximum"> @@ -141,15 +155,8 @@ </property> </widget> </item> - <item row="0" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Palm</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSlider" name="horizontalSliderThumbJ0"> + <item row="4" column="1"> + <widget class="QSlider" name="horizontalSliderIndexJ1"> <property name="maximum"> <number>90</number> </property> @@ -158,13 +165,6 @@ </property> </widget> </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Thumb J1</string> - </property> - </widget> - </item> <item row="3" column="2" rowspan="2"> <widget class="QPushButton" name="buttonSetJointAngles"> <property name="maximumSize"> @@ -178,9 +178,30 @@ </property> </widget> </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Palm</string> + </property> + </widget> + </item> </layout> </widget> </item> + <item row="1" column="7"> + <widget class="QPushButton" name="buttonRelaxHand"> + <property name="text"> + <string>Relax</string> + </property> + </widget> + </item> + <item row="1" column="5"> + <widget class="QPushButton" name="buttonCloseThumb"> + <property name="text"> + <string>Thumb</string> + </property> + </widget> + </item> <item row="1" column="1"> <widget class="QComboBox" name="comboPreshapes"/> </item> @@ -197,7 +218,21 @@ </property> </widget> </item> - <item row="0" column="1" colspan="2"> + <item row="1" column="6"> + <widget class="QPushButton" name="buttonCloseHand"> + <property name="text"> + <string>Close</string> + </property> + </widget> + </item> + <item row="1" column="4"> + <widget class="QPushButton" name="buttonOpenHand"> + <property name="text"> + <string>Open</string> + </property> + </widget> + </item> + <item row="0" column="1" colspan="7"> <widget class="QLabel" name="labelInfo"> <property name="maximumSize"> <size> diff --git a/source/RobotAPI/gui_plugins/HapticUnitPlugin/CMakeLists.txt b/source/RobotAPI/gui_plugins/HapticUnitPlugin/CMakeLists.txt index 85ec3418868f863d69b838f78ce7d6c8ce566e13..9caeeee68f7beded8305dce337f2fa83c8c02904 100644 --- a/source/RobotAPI/gui_plugins/HapticUnitPlugin/CMakeLists.txt +++ b/source/RobotAPI/gui_plugins/HapticUnitPlugin/CMakeLists.txt @@ -15,17 +15,25 @@ include_directories(${Eigen3_INCLUDE_DIR}) include(${QT_USE_FILE}) -file(GLOB SOURCES HapticUnitGuiPlugin.cpp - HapticUnitConfigDialog.cpp - MatrixDisplayWidget.cpp) -file(GLOB HEADERS HapticUnitGuiPlugin.h - HapticUnitConfigDialog.h - MatrixDisplayWidget.h) +file(GLOB SOURCES + HapticUnitGuiPlugin.cpp + HapticUnitConfigDialog.cpp + MatrixDisplayWidget.cpp + MatrixDatafieldDisplayWidget.cpp +) + +file(GLOB HEADERS + HapticUnitGuiPlugin.h + HapticUnitConfigDialog.h + MatrixDisplayWidget.h + MatrixDatafieldDisplayWidget.h +) set(GUI_MOC_HDRS HapticUnitGuiPlugin.h HapticUnitConfigDialog.h MatrixDisplayWidget.h + MatrixDatafieldDisplayWidget.h ) set(GUI_UIS diff --git a/source/RobotAPI/gui_plugins/HapticUnitPlugin/HapticUnitGuiPlugin.cpp b/source/RobotAPI/gui_plugins/HapticUnitPlugin/HapticUnitGuiPlugin.cpp index ff77ae283299e3c2a62e1d9f632443c0a9e1ed19..75a989ad1f3197ac935b6d8bd93fc937f7ff7248 100644 --- a/source/RobotAPI/gui_plugins/HapticUnitPlugin/HapticUnitGuiPlugin.cpp +++ b/source/RobotAPI/gui_plugins/HapticUnitPlugin/HapticUnitGuiPlugin.cpp @@ -34,7 +34,6 @@ HapticUnitWidget::HapticUnitWidget() hapticObserverProxyName = "HapticUnitObserver"; updateTimer = new QTimer(this); - layout = new QGridLayout(getWidget()); @@ -102,15 +101,15 @@ void HapticUnitWidget::configured() void HapticUnitWidget::updateData() { - for(std::pair<std::string, MatrixDisplayWidget*> pair : matrixDisplays) + for(std::pair<std::string, MatrixDatafieldDisplayWidget*> pair : matrixDisplays) { - MatrixFloatPtr matrix = VariantPtr::dynamicCast(hapticObserverProxy->getDataField(new DataFieldIdentifier(hapticObserverProxyName, pair.first, "matrix")))->get<MatrixFloat>(); + //MatrixFloatPtr matrix = VariantPtr::dynamicCast(hapticObserverProxy->getDataField(new DataFieldIdentifier(hapticObserverProxyName, pair.first, "matrix")))->get<MatrixFloat>(); std::string name = hapticObserverProxy->getDataField(new DataFieldIdentifier(hapticObserverProxyName, pair.first, "name"))->getString(); - float rate = hapticObserverProxy->getDataField(new DataFieldIdentifier(hapticObserverProxyName, pair.first, "rate"))->getFloat(); + std::string deviceName = hapticObserverProxy->getDataField(new DataFieldIdentifier(hapticObserverProxyName, pair.first, "device"))->getString(); + //float rate = hapticObserverProxy->getDataField(new DataFieldIdentifier(hapticObserverProxyName, pair.first, "rate"))->getFloat(); TimestampVariantPtr timestamp = VariantPtr::dynamicCast(hapticObserverProxy->getDataField(new DataFieldIdentifier(hapticObserverProxyName, pair.first, "timestamp")))->get<TimestampVariant>(); - MatrixDisplayWidget* matrixDisplay = pair.second; - matrixDisplay->setData(matrix->toEigen().cast<double>()); - matrixDisplay->setInfoOverlay(QString::fromStdString(pair.first) + ": " + QString::fromStdString(name) + " " + QString::fromStdString(timestamp->toTime().toDateTime()) + " " + QString::number(rate, 'g', 4) + " Frames/s"); + MatrixDatafieldDisplayWidget* matrixDisplay = pair.second; + matrixDisplay->setInfoOverlay(QString::fromStdString(deviceName) + ": " + QString::fromStdString(name) + "\n" + QString::fromStdString(timestamp->toTime().toDateTime())); matrixDisplay->invokeUpdate(); } @@ -119,18 +118,19 @@ void HapticUnitWidget::updateData() void HapticUnitWidget::onContextMenu(QPoint point) { QMenu* contextMenu = new QMenu(getWidget()); - MatrixDisplayWidget* matrixDisplay = qobject_cast<MatrixDisplayWidget*>(sender()); + MatrixDatafieldDisplayWidget* matrixDisplay = qobject_cast<MatrixDatafieldDisplayWidget*>(sender()); if(!matrixDisplay) return; QAction* setDeviceTag = contextMenu->addAction(tr("Set Device Tag")); QAction* action = contextMenu->exec(matrixDisplay->mapToGlobal(point)); - std::string deviceName = reverseMap.at(matrixDisplay); + std::string channelName = channelNameReverseMap.at(matrixDisplay); + std::string deviceName = deviceNameReverseMap.at(matrixDisplay); if(action == setDeviceTag) { - std::string tag = hapticObserverProxy->getDataField(new DataFieldIdentifier(hapticObserverProxyName, deviceName, "name"))->getString(); + std::string tag = hapticObserverProxy->getDataField(new DataFieldIdentifier(hapticObserverProxyName, channelName, "name"))->getString(); bool ok; QString newTag = QInputDialog::getText(getWidget(), tr("Set Device Tag"), @@ -138,6 +138,7 @@ void HapticUnitWidget::onContextMenu(QPoint point) QString::fromStdString(tag), &ok); if (ok && !newTag.isEmpty()) { + ARMARX_IMPORTANT_S << "requesting to set new device tag for " << deviceName << ": " << newTag.toStdString(); weissHapticUnit->setDeviceTag(deviceName, newTag.toStdString()); } } @@ -160,18 +161,19 @@ void HapticUnitWidget::connectSlots() { connect(this, SIGNAL(doUpdateDisplayWidgets()), SLOT(updateDisplayWidgets()), Qt::QueuedConnection); connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateData())); + connect(ui.checkBoxOffsetFilter, SIGNAL(stateChanged(int)), this, SLOT(onCheckBoxOffsetFilterStateChanged(int))); } void HapticUnitWidget::createMatrixWidgets() { - ARMARX_LOG << "HapticUnitWidget::createMatrixWidgets()"; + //ARMARX_LOG << "HapticUnitWidget::createMatrixWidgets()"; emit doUpdateDisplayWidgets(); } void HapticUnitWidget::updateDisplayWidgets() { QLayoutItem *child; - while ((child = layout->takeAt(0)) != 0) { + while ((child = ui.gridLayoutDisplay->takeAt(0)) != 0) { delete child; } @@ -179,18 +181,28 @@ void HapticUnitWidget::updateDisplayWidgets() ChannelRegistry channels = hapticObserverProxy->getAvailableChannels(false); for(std::pair<std::string, ChannelRegistryEntry> pair : channels) { - - ARMARX_LOG << pair.first; - MatrixDisplayWidget* matrixDisplay = new MatrixDisplayWidget(getWidget()); + std::string channelName = pair.first; + MatrixDatafieldDisplayWidget* matrixDisplay = new MatrixDatafieldDisplayWidget(new DatafieldRef(hapticObserverProxy, channelName, "matrix"), hapticObserverProxy, getWidget()); matrixDisplay->setRange(0, 4095); matrixDisplay->setContextMenuPolicy(Qt::CustomContextMenu); connect(matrixDisplay, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onContextMenu(QPoint))); matrixDisplays.insert(std::make_pair(pair.first, matrixDisplay)); - reverseMap.insert(std::make_pair(matrixDisplay, pair.first)); - layout->addWidget(matrixDisplay, 0, i); + std::string deviceName = hapticObserverProxy->getDataField(new DataFieldIdentifier(hapticObserverProxyName, channelName, "device"))->getString(); + channelNameReverseMap.insert(std::make_pair(matrixDisplay, channelName)); + deviceNameReverseMap.insert(std::make_pair(matrixDisplay, deviceName)); + ui.gridLayoutDisplay->addWidget(matrixDisplay, 0, i); i++; } } +void HapticUnitWidget::onCheckBoxOffsetFilterStateChanged(int state) +{ + //ARMARX_IMPORTANT << "onCheckBoxOffsetFilterToggled: " << state; + for(std::pair<std::string, MatrixDatafieldDisplayWidget*> pair : matrixDisplays) + { + pair.second->enableOffsetFilter(ui.checkBoxOffsetFilter->isChecked()); + } +} + Q_EXPORT_PLUGIN2(robotapi_gui_HapticUnitGuiPlugin, HapticUnitGuiPlugin) diff --git a/source/RobotAPI/gui_plugins/HapticUnitPlugin/HapticUnitGuiPlugin.h b/source/RobotAPI/gui_plugins/HapticUnitPlugin/HapticUnitGuiPlugin.h index 77d8f64a940707b2542b3ae5eb97d1f4e14ce8f3..e4e215cafccb09061befac7f9ae4871d98713f35 100644 --- a/source/RobotAPI/gui_plugins/HapticUnitPlugin/HapticUnitGuiPlugin.h +++ b/source/RobotAPI/gui_plugins/HapticUnitPlugin/HapticUnitGuiPlugin.h @@ -39,7 +39,7 @@ #include <string> #include <QLayout> -#include "MatrixDisplayWidget.h" +#include "MatrixDatafieldDisplayWidget.h" namespace armarx @@ -103,6 +103,7 @@ namespace armarx private slots: void updateDisplayWidgets(); + void onCheckBoxOffsetFilterStateChanged(int state); protected: void connectSlots(); @@ -124,10 +125,9 @@ namespace armarx QTimer* updateTimer; - QGridLayout* layout; - - std::map<std::string, MatrixDisplayWidget*> matrixDisplays; - std::map<MatrixDisplayWidget*, std::string> reverseMap; + std::map<std::string, MatrixDatafieldDisplayWidget*> matrixDisplays; + std::map<MatrixDatafieldDisplayWidget*, std::string> channelNameReverseMap; + std::map<MatrixDatafieldDisplayWidget*, std::string> deviceNameReverseMap; }; //typedef boost::shared_ptr<HapticUnitWidget> HapticUnitGuiPluginPtr; diff --git a/source/RobotAPI/gui_plugins/HapticUnitPlugin/HapticUnitGuiPlugin.ui b/source/RobotAPI/gui_plugins/HapticUnitPlugin/HapticUnitGuiPlugin.ui index 51d71fb847c535cabeb8d0444aaa11139030ad81..fca3ad93b092cf943002ae51bb86408db0ad92d7 100644 --- a/source/RobotAPI/gui_plugins/HapticUnitPlugin/HapticUnitGuiPlugin.ui +++ b/source/RobotAPI/gui_plugins/HapticUnitPlugin/HapticUnitGuiPlugin.ui @@ -19,6 +19,20 @@ <property name="windowTitle"> <string>Form</string> </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBoxOffsetFilter"> + <property name="text"> + <string>Offset Filter</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QWidget" name="widgetDisplay" native="true"> + <layout class="QGridLayout" name="gridLayoutDisplay"/> + </widget> + </item> + </layout> </widget> <resources/> <connections/> diff --git a/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDatafieldDisplayWidget.cpp b/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDatafieldDisplayWidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..655237021a4aa994631d08be2a760feb7eea6ab1 --- /dev/null +++ b/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDatafieldDisplayWidget.cpp @@ -0,0 +1,123 @@ +#include "MatrixDatafieldDisplayWidget.h" +//#include "ui_MatrixDatafieldDisplayWidget.h" + +#include <QPainter> +#include <pthread.h> +#include <iostream> + +#include <RobotAPI/libraries/core/observerfilters/MatrixFilters.h> +#include <RobotAPI/libraries/core/observerfilters/OffsetFilter.h> + +using namespace std; +using namespace armarx; + +void MatrixDatafieldDisplayWidget::updateRequested() +{ + mtx.lock(); + this->data = matrixDatafieldOffsetFiltered->getDataField()->get<MatrixFloat>()->toEigen(); + this->percentiles = percentilesDatafield->getDataField()->get<MatrixFloat>()->toVector(); + mtx.unlock(); + update(); +} + +MatrixDatafieldDisplayWidget::MatrixDatafieldDisplayWidget(DatafieldRefBasePtr matrixDatafield, ObserverInterfacePrx observer, QWidget *parent) : + QWidget(parent) +{ + this->matrixDatafield = DatafieldRefPtr::dynamicCast(matrixDatafield); + this->observer = observer; + this->min = 0; + this->max = 1; + this->data = MatrixXf(1, 1); + this->data(0, 0) = 0; + enableOffsetFilter(false); + QColor c[] = {QColor::fromHsv(0, 0, 0), QColor::fromHsv(240, 255, 255), QColor::fromHsv(270, 255, 255), QColor::fromHsv(300, 255, 255), + QColor::fromHsv(0, 255, 255), QColor::fromHsv(30, 255, 255), QColor::fromHsv(60, 255, 255)}; + this->colors = std::valarray<QColor>(c, sizeof c / sizeof c[0]); + + //connect(this, SIGNAL(updateData(MatrixXf)), SLOT(setData(MatrixXf)), Qt::QueuedConnection); + connect(this, SIGNAL(doUpdate()), SLOT(updateRequested()), Qt::QueuedConnection); +} + +MatrixDatafieldDisplayWidget::~MatrixDatafieldDisplayWidget() +{ + //delete ui; +} + +void MatrixDatafieldDisplayWidget::paintEvent(QPaintEvent *) +{ + mtx.lock(); + + int paddingBottom = 40; + QPainter painter(this); + painter.fillRect(rect(), QColor::fromRgb(0,0,0)); + int matrixHeight = (height() - paddingBottom) * 8 / 10; + int percentilesHeight = (height() - paddingBottom) - matrixHeight; + drawMatrix(QRect(0, 0, width(), matrixHeight), painter); + drawPercentiles(QRect(0, matrixHeight, width() - 1, percentilesHeight), painter); + + painter.setPen(QColor(Qt::GlobalColor::gray)); + painter.setFont(QFont("Arial", 12)); + painter.drawText(rect(), Qt::AlignBottom | Qt::AlignRight, infoOverlay); + + mtx.unlock(); +} + +void MatrixDatafieldDisplayWidget::enableOffsetFilter(bool enabled) +{ + if(enabled) + { + this->matrixDatafieldOffsetFiltered = DatafieldRefPtr::dynamicCast(observer->createFilteredDatafield(DatafieldFilterBasePtr(new filters::OffsetFilter()), matrixDatafield)); + } + else + { + this->matrixDatafieldOffsetFiltered = this->matrixDatafield; + } + this->percentilesDatafield = DatafieldRefPtr::dynamicCast(observer->createFilteredDatafield(DatafieldFilterBasePtr(new filters::MatrixPercentilesFilter(50)), matrixDatafieldOffsetFiltered)); +} + +QColor MatrixDatafieldDisplayWidget::getColor(float value, float min, float max) +{ + value = (value - min) / (max - min) * (colors.size() - 1); + if(value < 0) return colors[0]; + if(value >= colors.size() - 1) return colors[colors.size() - 1]; + int i = (int)value; + float f2 = value - i; + float f1 = 1- f2; + QColor c1 = colors[i]; + QColor c2 = colors[i + 1]; + return QColor((int)(c1.red() * f1 + c2.red() * f2), (int)(c1.green() * f1 + c2.green() * f2), (int)(c1.blue() * f1 + c2.blue() * f2)); +} + +void MatrixDatafieldDisplayWidget::drawMatrix(const QRect &target, QPainter &painter) +{ + int pixelSize = std::min(target.width() / data.cols(), target.height() / data.rows()); + int dx = (target.width() - pixelSize * data.cols()) / 2; + int dy = (target.height() - pixelSize * data.rows()) / 2; + painter.setFont(QFont("Arial", 8)); + painter.setPen(QColor(Qt::GlobalColor::gray)); + + for(int x = 0; x < data.cols(); x++) + { + for(int y = 0; y < data.rows(); y++) + { + QRect target = QRect(dx + x * pixelSize, dy + y * pixelSize, pixelSize, pixelSize); + painter.fillRect(target, getColor(data(y, x), min, max)); + painter.drawText(target, Qt::AlignCenter, QString::number(data(y, x))); + } + } +} + +void MatrixDatafieldDisplayWidget::drawPercentiles(const QRect &target, QPainter &painter) +{ + painter.setPen(QColor(Qt::GlobalColor::gray)); + painter.drawRect(target); + painter.setPen(QColor(Qt::GlobalColor::red)); + for(int i = 0; i < (int)percentiles.size() - 1; i++) + { + int x1 = i * target.width() / (percentiles.size() - 1); + int x2 = (i + 1) * target.width() / (percentiles.size() - 1); + float y1 = (percentiles.at(i) - min) / (max - min) * target.height(); + float y2 = (percentiles.at(i + 1) - min) / (max - min) * target.height(); + painter.drawLine(target.left() + x1, target.bottom() - (int)y1, target.left() + x2, target.bottom() - (int)y2); + } +} diff --git a/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDatafieldDisplayWidget.h b/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDatafieldDisplayWidget.h new file mode 100644 index 0000000000000000000000000000000000000000..edc77d914906d094e59a2a89a28dc14f7ae33b75 --- /dev/null +++ b/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDatafieldDisplayWidget.h @@ -0,0 +1,73 @@ +#ifndef MATRIXDISPLAYWIDGET_H +#define MATRIXDISPLAYWIDGET_H + +#include <QWidget> +#include <QMutex> +#include <eigen3/Eigen/Dense> +#include <valarray> +#include <Core/interface/observers/ObserverInterface.h> +#include <Core/observers/variant/DatafieldRef.h> + + +using Eigen::MatrixXf; + +namespace Ui { +class MatrixDatafieldDisplayWidget; +} + +namespace armarx +{ + class MatrixDatafieldDisplayWidget : public QWidget + { + Q_OBJECT + + signals: + void doUpdate(); + + private slots: + void updateRequested(); + + public: + explicit MatrixDatafieldDisplayWidget(DatafieldRefBasePtr matrixDatafield, ObserverInterfacePrx observer, QWidget *parent = 0); + ~MatrixDatafieldDisplayWidget(); + void paintEvent(QPaintEvent *); + + + void setRange(float min, float max) + { + this->min = min; + this->max = max; + } + void enableOffsetFilter(bool enabled); + QColor getColor(float value, float min, float max); + + void invokeUpdate(){ + emit doUpdate(); + } + void setInfoOverlay(QString infoOverlay) + { + mtx.lock(); + this->infoOverlay = infoOverlay; + mtx.unlock(); + } + + private: + void drawMatrix(const QRect &target, QPainter &painter); + void drawPercentiles(const QRect &target, QPainter &painter); + + private: + Ui::MatrixDatafieldDisplayWidget *ui; + MatrixXf data; + std::vector<float> percentiles; + float min, max; + std::valarray<QColor> colors; + QMutex mtx; + QString infoOverlay; + DatafieldRefPtr matrixDatafield; + DatafieldRefPtr matrixDatafieldOffsetFiltered; + DatafieldRefPtr percentilesDatafield; + ObserverInterfacePrx observer; + }; +} + +#endif // MATRIXDISPLAYWIDGET_H diff --git a/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDisplayWidget.cpp b/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDisplayWidget.cpp index 102a023af65fb93cbd109abf85b02f1fb2e5c866..dc1124675d390a9ba43e9a57726cc3321e67f998 100644 --- a/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDisplayWidget.cpp +++ b/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDisplayWidget.cpp @@ -15,13 +15,13 @@ MatrixDisplayWidget::MatrixDisplayWidget(QWidget *parent) : ui->setupUi(this); this->min = 0; this->max = 1; - this->data = MatrixXd(1, 1); + this->data = MatrixXf(1, 1); this->data(0, 0) = 0; QColor c[] = {QColor::fromHsv(0, 0, 0), QColor::fromHsv(240, 255, 255), QColor::fromHsv(270, 255, 255), QColor::fromHsv(300, 255, 255), QColor::fromHsv(0, 255, 255), QColor::fromHsv(30, 255, 255), QColor::fromHsv(60, 255, 255)}; this->colors = std::valarray<QColor>(c, sizeof c / sizeof c[0]); - //connect(this, SIGNAL(updateData(MatrixXd)), SLOT(setData(MatrixXd)), Qt::QueuedConnection); + //connect(this, SIGNAL(updateData(MatrixXf)), SLOT(setData(MatrixXf)), Qt::QueuedConnection); connect(this, SIGNAL(doUpdate()), SLOT(update()), Qt::QueuedConnection); } @@ -33,7 +33,7 @@ MatrixDisplayWidget::~MatrixDisplayWidget() void MatrixDisplayWidget::paintEvent(QPaintEvent *) { mtx.lock(); - MatrixXd data = this->data; + MatrixXf data = this->data; //cout << "[" << pthread_self() << "] MatrixDisplayWidget::paintEvent" << endl; @@ -59,14 +59,14 @@ void MatrixDisplayWidget::paintEvent(QPaintEvent *) mtx.unlock(); } -QColor MatrixDisplayWidget::getColor(double value, double min, double max) +QColor MatrixDisplayWidget::getColor(float value, float min, float max) { value = (value - min) / (max - min) * (colors.size() - 1); if(value < 0) return colors[0]; if(value >= colors.size() - 1) return colors[colors.size() - 1]; int i = (int)value; - double f2 = value - i; - double f1 = 1- f2; + float f2 = value - i; + float f1 = 1- f2; QColor c1 = colors[i]; QColor c2 = colors[i + 1]; return QColor((int)(c1.red() * f1 + c2.red() * f2), (int)(c1.green() * f1 + c2.green() * f2), (int)(c1.blue() * f1 + c2.blue() * f2)); diff --git a/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDisplayWidget.h b/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDisplayWidget.h index 2978adac43164649a7cb317d1b4201d7c738b022..33480b6a827ba490812895638a9ca7febca3124c 100644 --- a/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDisplayWidget.h +++ b/source/RobotAPI/gui_plugins/HapticUnitPlugin/MatrixDisplayWidget.h @@ -6,7 +6,7 @@ #include <eigen3/Eigen/Dense> #include <valarray> -using Eigen::MatrixXd; +using Eigen::MatrixXf; namespace Ui { class MatrixDisplayWidget; @@ -22,7 +22,7 @@ namespace armarx void doUpdate(); public slots: - void setData(MatrixXd data) + void setData(MatrixXf data) { mtx.lock(); this->data = data; @@ -37,12 +37,12 @@ namespace armarx - void setRange(double min, double max) + void setRange(float min, float max) { this->min = min; this->max = max; } - QColor getColor(double value, double min, double max); + QColor getColor(float value, float min, float max); void invokeUpdate(){ emit doUpdate(); @@ -56,8 +56,8 @@ namespace armarx private: Ui::MatrixDisplayWidget *ui; - MatrixXd data; - double min, max; + MatrixXf data; + float min, max; std::valarray<QColor> colors; QMutex mtx; QString infoOverlay; diff --git a/source/RobotAPI/interface/observers/ObserverFilters.ice b/source/RobotAPI/interface/observers/ObserverFilters.ice index 02dee61eb985df72a78dd9f73674aad77966bae0..ed2ef8b3f7fa1253619036e7e2c4cb86a29195a0 100644 --- a/source/RobotAPI/interface/observers/ObserverFilters.ice +++ b/source/RobotAPI/interface/observers/ObserverFilters.ice @@ -43,21 +43,35 @@ module armarx }; ["cpp:virtual"] - class MatrixMaxFilterBase extends DatafieldFilterBase + class MatrixMinFilterBase extends DatafieldFilterBase { }; ["cpp:virtual"] - class MatrixMinFilterBase extends DatafieldFilterBase + class MatrixAvgFilterBase extends DatafieldFilterBase { }; ["cpp:virtual"] - class MatrixAvgFilterBase extends DatafieldFilterBase + class MatrixPercentileFilterBase extends DatafieldFilterBase { + float percentile; + }; + ["cpp:virtual"] + class MatrixPercentilesFilterBase extends DatafieldFilterBase + { + int percentiles; + }; + + ["cpp:virtual"] + class MatrixCumulativeFrequencyFilterBase extends DatafieldFilterBase + { + float min; + float max; + int bins; }; }; diff --git a/source/RobotAPI/libraries/core/RobotAPIObjectFactories.h b/source/RobotAPI/libraries/core/RobotAPIObjectFactories.h index 70a8707b3836c23daa287a710719d028783badea..fdb7d914cf9e07b0430e7f77692f26c8d5045fbe 100644 --- a/source/RobotAPI/libraries/core/RobotAPIObjectFactories.h +++ b/source/RobotAPI/libraries/core/RobotAPIObjectFactories.h @@ -174,6 +174,9 @@ namespace armarx add<armarx::MatrixMaxFilterBase, armarx::filters::MatrixMaxFilter>(map); add<armarx::MatrixMinFilterBase, armarx::filters::MatrixMinFilter>(map); add<armarx::MatrixAvgFilterBase, armarx::filters::MatrixAvgFilter>(map); + add<armarx::MatrixPercentileFilterBase, armarx::filters::MatrixPercentileFilter>(map); + add<armarx::MatrixPercentilesFilterBase, armarx::filters::MatrixPercentilesFilter>(map); + add<armarx::MatrixCumulativeFrequencyFilterBase, armarx::filters::MatrixCumulativeFrequencyFilter>(map); return map; } diff --git a/source/RobotAPI/libraries/core/observerfilters/MatrixFilters.h b/source/RobotAPI/libraries/core/observerfilters/MatrixFilters.h index ba5cf8ce90c279e80085353869c8a3ba25a9693b..801e0c24b90a3a914369e90b9cd7de180ef6a6f5 100644 --- a/source/RobotAPI/libraries/core/observerfilters/MatrixFilters.h +++ b/source/RobotAPI/libraries/core/observerfilters/MatrixFilters.h @@ -27,7 +27,7 @@ #include <Core/observers/filters/DatafieldFilter.h> #include <RobotAPI/interface/observers/ObserverFilters.h> #include <Core/util/variants/eigen3/MatrixVariant.h> - +#include <algorithm> namespace armarx { @@ -39,10 +39,17 @@ namespace armarx public DatafieldFilter { public: - MatrixMaxFilter() { } + MatrixMaxFilter() + { + this->windowFilterSize = 1; + } VariantBasePtr calculate(const Ice::Current &) const { + if(dataHistory.size() == 0) + { + return new Variant(new MatrixFloat(1, 1)); + } VariantPtr currentValue = VariantPtr::dynamicCast(dataHistory.rbegin()->second); MatrixFloatPtr matrix = MatrixFloatPtr::dynamicCast(currentValue->get<MatrixFloat>()); return new Variant(matrix->toEigen().maxCoeff()); @@ -60,10 +67,17 @@ namespace armarx public DatafieldFilter { public: - MatrixMinFilter() { } + MatrixMinFilter() + { + this->windowFilterSize = 1; + } VariantBasePtr calculate(const Ice::Current &) const { + if(dataHistory.size() == 0) + { + return new Variant(new MatrixFloat(1, 1)); + } VariantPtr currentValue = VariantPtr::dynamicCast(dataHistory.rbegin()->second); MatrixFloatPtr matrix = MatrixFloatPtr::dynamicCast(currentValue->get<MatrixFloat>()); return new Variant(matrix->toEigen().minCoeff()); @@ -81,10 +95,17 @@ namespace armarx public DatafieldFilter { public: - MatrixAvgFilter() { } + MatrixAvgFilter() + { + this->windowFilterSize = 1; + } VariantBasePtr calculate(const Ice::Current &) const { + if(dataHistory.size() == 0) + { + return new Variant(new MatrixFloat(1, 1)); + } VariantPtr currentValue = VariantPtr::dynamicCast(dataHistory.rbegin()->second); MatrixFloatPtr matrix = MatrixFloatPtr::dynamicCast(currentValue->get<MatrixFloat>()); return new Variant(matrix->toEigen().mean()); @@ -97,6 +118,167 @@ namespace armarx } }; + class MatrixPercentileFilter : + public MatrixPercentileFilterBase, + public DatafieldFilter + { + public: + MatrixPercentileFilter() + { + this->windowFilterSize = 1; + } + MatrixPercentileFilter(float percentile) + { + this->percentile = percentile; + this->windowFilterSize = 1; + } + + VariantBasePtr calculate(const Ice::Current &) const + { + if(dataHistory.size() == 0) + { + return new Variant(new MatrixFloat(1, 1)); + } + VariantPtr currentValue = VariantPtr::dynamicCast(dataHistory.rbegin()->second); + MatrixFloatPtr matrix = MatrixFloatPtr::dynamicCast(currentValue->get<MatrixFloat>()); + std::vector<float> vector = matrix->toVector(); + std::sort(vector.begin(), vector.end()); + return new Variant(GetPercentile(vector, percentile)); + } + ParameterTypeList getSupportedTypes(const Ice::Current &) const + { + ParameterTypeList result; + result.push_back(VariantType::MatrixFloat); + return result; + } + + static float GetPercentile(const std::vector<float> &sortedData, float percentile) + { + if(sortedData.size() == 0) + { + throw LocalException("GetPercentile not possible for empty vector"); + } + float indexf = (sortedData.size() - 1) * percentile; + indexf = std::max(0.f, std::min(sortedData.size() - 1.f, indexf)); + int index = (int)indexf; + float f = indexf - index; + if(index == (int)sortedData.size() - 1) + { + return sortedData.at(sortedData.size() - 1); + } + return sortedData.at(index) * (1 - f) + sortedData.at(index + 1) * f; + } + }; + + class MatrixPercentilesFilter : + public MatrixPercentilesFilterBase, + public DatafieldFilter + { + public: + MatrixPercentilesFilter() + { + this->windowFilterSize = 1; + this->percentiles = 10; + } + MatrixPercentilesFilter(int percentiles) + { + this->percentiles = percentiles; + this->windowFilterSize = 1; + } + + VariantBasePtr calculate(const Ice::Current &) const + { + if(dataHistory.size() == 0) + { + ARMARX_IMPORTANT_S << "no data"; + return new Variant(new MatrixFloat(1, 1)); + } + VariantPtr currentValue = VariantPtr::dynamicCast(dataHistory.rbegin()->second); + MatrixFloatPtr matrix = MatrixFloatPtr::dynamicCast(currentValue->get<MatrixFloat>()); + std::vector<float> vector = matrix->toVector(); + std::sort(vector.begin(), vector.end()); + std::vector<float> result; + result.push_back(vector.at(0)); + for(int i = 1; i < percentiles; i++) + { + result.push_back(MatrixPercentileFilter::GetPercentile(vector, 1.f / percentiles * i)); + } + result.push_back(vector.at(vector.size() - 1)); + return new Variant(new MatrixFloat(1, result.size(), result)); + } + ParameterTypeList getSupportedTypes(const Ice::Current &) const + { + ParameterTypeList result; + result.push_back(VariantType::MatrixFloat); + return result; + } + }; + + class MatrixCumulativeFrequencyFilter : + public MatrixCumulativeFrequencyFilterBase, + public DatafieldFilter + { + public: + MatrixCumulativeFrequencyFilter() + { + this->windowFilterSize = 1; + } + MatrixCumulativeFrequencyFilter(float min, float max, int bins) + { + this->min = min; + this->max = max; + this->bins = bins; + this->windowFilterSize = 1; + } + VariantBasePtr calculate(const Ice::Current &) const + { + if(dataHistory.size() == 0) + { + return new Variant(new MatrixFloat(1, 1)); + } + VariantPtr currentValue = VariantPtr::dynamicCast(dataHistory.rbegin()->second); + MatrixFloatPtr matrix = MatrixFloatPtr::dynamicCast(currentValue->get<MatrixFloat>()); + std::vector<float> vector = matrix->toVector(); + std::sort(vector.begin(), vector.end()); + std::vector<int> result = Calculate(vector, min, max, bins); + std::vector<float> resultF; + for(int v : result) + { + resultF.push_back(v); + } + + return new Variant(new MatrixFloat(1, resultF.size(), resultF)); + } + ParameterTypeList getSupportedTypes(const Ice::Current &) const + { + ParameterTypeList result; + result.push_back(VariantType::MatrixFloat); + return result; + } + static std::vector<int> Calculate(const std::vector<float> &sortedData, float min, float max, int bins) + { + std::vector<int> result; + float val = min; + int nr = 0; + int lastCount = 0; + for(size_t i = 0; i < sortedData.size(); i++) + { + if(sortedData.at(i) > val && nr < bins) + { + result.push_back(i); + nr++; + val = min + (max - min) * nr / bins; + lastCount = i; + } + } + while((int)result.size() < bins) + { + result.push_back(lastCount); + } + return result; + } + + }; } } diff --git a/source/RobotAPI/libraries/drivers/WeissHapticSensor/CMakeLists.txt b/source/RobotAPI/libraries/drivers/WeissHapticSensor/CMakeLists.txt index ea86aacfe1fcc31c23923373a307a0a4fbb5a040..69c5f8a2b3968cf42865d9755d9ee15c585dd829 100644 --- a/source/RobotAPI/libraries/drivers/WeissHapticSensor/CMakeLists.txt +++ b/source/RobotAPI/libraries/drivers/WeissHapticSensor/CMakeLists.txt @@ -16,7 +16,7 @@ set(LIB_SOVERSION 0) set(LIBS RobotAPIUnits ArmarXCoreObservers ArmarXCoreEigen3Variants) set(LIB_FILES - WeissHapticSensorsUnit.cpp + WeissHapticUnit.cpp WeissHapticSensor.cpp AbstractInterface.cpp BinaryLogger.cpp @@ -28,7 +28,7 @@ set(LIB_FILES CalibrationHelper.cpp ) set(LIB_HEADERS - WeissHapticSensorsUnit.h + WeissHapticUnit.h WeissHapticSensor.h AbstractInterface.h BinaryLogger.h diff --git a/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensor.cpp b/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensor.cpp index 9bd5cf3dae8beb73974b7d9126ebc7dabe1d679e..32b44ac4749e7ad76dae442406d97fef4211889c 100644 --- a/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensor.cpp +++ b/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensor.cpp @@ -5,8 +5,8 @@ using namespace armarx; -WeissHapticSensor::WeissHapticSensor(std::string device) - : device(device), connected(false), setDeviceTagScheduled(false) +WeissHapticSensor::WeissHapticSensor(std::string device, int minimumReportIntervalMs) + : device(device), connected(false), setDeviceTagScheduled(false), minimumReportIntervalMs(minimumReportIntervalMs) { sensorTask = new RunningTask<WeissHapticSensor>(this, &WeissHapticSensor::frameAcquisitionTaskLoop); boost::smatch match; @@ -17,9 +17,9 @@ WeissHapticSensor::WeissHapticSensor(std::string device) void WeissHapticSensor::connect() { - //cout << "Open Serial" << endl; + ARMARX_INFO << "Open Serial" << endl; this->interface.reset(new SerialInterface(device.c_str(), 115200)); - interface->startLogging(deviceFileName + ".transmission.log"); + //interface->startLogging(deviceFileName + ".transmission.log"); interface->open(); //cout << *interface << endl; this->sensor.reset(new TactileSensor(interface)); @@ -66,11 +66,13 @@ void WeissHapticSensor::connect() sensor->setAquisitionWindow(1, 1, mi.res_x, mi.res_y); sensor->setFrontEndGain(255); + ARMARX_LOG << "[" << device << "] Front end gain set to " << (int)sensor->getFrontEndGain(); - ARMARX_LOG << "Front end gain set to " << (int)sensor->getFrontEndGain(); + sensor->setThreshold(0); + ARMARX_LOG << "[" << device << "] threshold set to " << (int)sensor->getThreshold(); connected = true; - cout << this << ": Connect done, Interface=" << sensor->getInterfaceInfo() << endl; + ARMARX_LOG << device << ": Connect done, Interface=" << sensor->getInterfaceInfo(); } void WeissHapticSensor::disconnect() @@ -86,7 +88,7 @@ void WeissHapticSensor::setListenerPrx(HapticUnitListenerPrx listenerPrx) void WeissHapticSensor::startSampling() { - cout << this << ": startSampling" << endl; + ARMARX_LOG << device << ": startSampling" << endl; sensorTask->start(); } @@ -104,13 +106,18 @@ void WeissHapticSensor::scheduleSetDeviceTag(string tag) void WeissHapticSensor::frameAcquisitionTaskLoop() { - cout << this << ": readAndReportSensorValues" << endl; + ARMARX_LOG << device << ": readAndReportSensorValues"; //bool periodic = false; - cout << sensor->getInterfaceInfo() << endl; + ARMARX_LOG << device << ": Interface Info: " << sensor->getInterfaceInfo(); - cout << this << ": startPeriodicFrameAcquisition" << endl; + ARMARX_LOG << device << this << ": startPeriodicFrameAcquisition"; sensor->startPeriodicFrameAcquisition(0); + IceUtil::Time lastFrameTime = IceUtil::Time::now(); + + math::SlidingWindowVectorMedian slidingMedian(mi.res_x * mi.res_y, 21); // inter sample dely ~= 3,7ms, 11 samples ~== 40ms delay + + while(!sensorTask->isStopped()) { //ARMARX_INFO << deactivateSpam(1) << this << ": receicePeriodicFrame"; @@ -122,6 +129,25 @@ void WeissHapticSensor::frameAcquisitionTaskLoop() //long end = TimestampVariant::nowLong(); //cout << end - start << endl; + std::vector<float> sensorValues; + for(int i = 0; i < mi.res_x * mi.res_y; i++) + { + sensorValues.push_back(data.data->at(i)); + } + slidingMedian.addEntry(sensorValues); + + MatrixFloatPtr matrix = new MatrixFloat(mi.res_y, mi.res_x); + std::vector<float> filteredSensorValues = slidingMedian.getMedian(); + for (int y = 0; y < mi.res_y; y++) + { + for (int x = 0; x < mi.res_x; x++) + { + (*matrix)(y, x) = filteredSensorValues.at(y * mi.res_x + x); + } + } + + + /* MatrixFloatPtr matrix = new MatrixFloat(mi.res_y, mi.res_x); for (int y = 0; y < mi.res_y; y++) { @@ -131,10 +157,19 @@ void WeissHapticSensor::frameAcquisitionTaskLoop() (*matrix)(y, x) = val; } } + */ - TimestampVariantPtr now = TimestampVariant::nowPtr(); - writeMatrixToJs(matrix, now); - listenerPrx->reportSensorValues(device, tag, matrix, now); + IceUtil::Time now = IceUtil::Time::now(); + + TimestampVariantPtr nowTimestamp = new TimestampVariant(now); + writeMatrixToJs(matrix, nowTimestamp); + + IceUtil::Time interval = now - lastFrameTime; + if(interval.toMilliSeconds() >= minimumReportIntervalMs) + { + listenerPrx->reportSensorValues(device, tag, matrix, nowTimestamp); + lastFrameTime = now; + } } catch(ChecksumErrorException) { @@ -149,7 +184,7 @@ void WeissHapticSensor::frameAcquisitionTaskLoop() ARMARX_INFO << "[" << device << "] Stopping periodic frame aquisition to set new device tag"; sensor->stopPeriodicFrameAcquisition(); - ARMARX_INFO << "[" << device << "] Setting new device tag '" << setDeviceTagValue << "'"; + ARMARX_IMPORTANT << "[" << device << "] Setting new device tag '" << setDeviceTagValue << "'"; sensor->setDeviceTag(setDeviceTagValue); this->tag = setDeviceTagValue; @@ -162,7 +197,7 @@ void WeissHapticSensor::frameAcquisitionTaskLoop() //usleep(1000000); } - cout << this << ": stopPeriodicFrameAcquisition" << endl; + ARMARX_LOG << device << ": stopPeriodicFrameAcquisition"; sensor->stopPeriodicFrameAcquisition(); } diff --git a/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensor.h b/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensor.h index 44eb078d0c08d15a9fff0fa421553178f1b045a1..884c946e7ee9632bc4f8f8f4a63d13eb3bdb70f9 100644 --- a/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensor.h +++ b/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensor.h @@ -10,6 +10,7 @@ //#include <Core/util/variants/eigen3/Eigen3LibRegistry.h> #include "TextWriter.h" #include <Core/observers/variant/TimestampVariant.h> +#include <Core/util/math/SlidingWindowVectorMedian.h> #include <Core/util/variants/eigen3/MatrixVariant.h> #include <boost/thread/mutex.hpp> @@ -22,7 +23,7 @@ namespace armarx class WeissHapticSensor : public Logging { public: - WeissHapticSensor(std::string device); + WeissHapticSensor(std::string device, int minimumReportIntervalMs); void connect(); void disconnect(); @@ -51,6 +52,7 @@ namespace armarx std::string setDeviceTagValue; boost::mutex mutex; + int minimumReportIntervalMs; }; } diff --git a/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensorsUnit.cpp b/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticUnit.cpp old mode 100755 new mode 100644 similarity index 53% rename from source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensorsUnit.cpp rename to source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticUnit.cpp index 1c7085f5b15176f75e10fb685e5864bcb703423b..24c1edda1132ec2290eba62c5ca4252e5a5906dc --- a/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensorsUnit.cpp +++ b/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticUnit.cpp @@ -21,7 +21,7 @@ * GNU General Public License */ -#include "WeissHapticSensorsUnit.h" +#include "WeissHapticUnit.h" #include <boost/regex.hpp> #include <boost/filesystem.hpp> @@ -29,54 +29,19 @@ using namespace armarx; -void WeissHapticSensorsUnit::onInitHapticUnit() +void WeissHapticUnit::onInitHapticUnit() { - // Read pipe Id property - /*int firstPipeID = getProperty<int>("FirstPipeID").getValue(); - if(firstPipeID < 0) - { - throw UserException("Value of FirstPipeID must be bigger than 0"); - }*/ - - // Read pipe base name property - // std::string pipeBaseName = getProperty<std::string>("PipeBaseName").getValue(); - - // Read logfile property - //std::string logfile = getProperty<std::string>("Logfile").getValue(); - - //std::vector<std::string> sensors; - //sensors.push_back("RightSole.HapticMatrix"); - //hapticProtocol.defineSensorCategory(250, sensors); - - // TODO: The task frequency needs to be adapted when the underlying sensor frequency changes - //sensorTask = new RunningTask<WeissHapticSensorsUnit>(this, &WeissHapticSensorsUnit::readAndReportSensorValues); - - //remoteSystemReady = false; - /* - if(!hapticProtocol.openPipes(firstPipeID, firstPipeID + 1, false, true, pipeBaseName)) - { - throw UserException("Failed to open pipes"); - } - - if(!hapticProtocol.openLogfile(logfile)) - { - throw UserException("Failed to open logfile"); - }*/ std::vector<std::string> devices = getDevices(); - /*boost::shared_ptr<WeissHapticSensor> sensor(new WeissHapticSensor(devices.front())); - this->sensors.push_back(sensor);*/ for(std::vector<std::string>::iterator it = devices.begin(); it != devices.end(); ++it) { - WeissHapticSensorPtr sensor(new WeissHapticSensor(*it)); + WeissHapticSensorPtr sensor(new WeissHapticSensor(*it, 20)); // minimumReportIntervalMs = 20, limit to maximum 50 frames/s this->sensors.push_back(sensor); } std::cout << "Connect Interfaces" << std::endl; - //sensors.front()->connect(); - for(std::vector<boost::shared_ptr<WeissHapticSensor> >::iterator it = sensors.begin(); it != sensors.end(); ++it) { (*it)->connect(); @@ -84,7 +49,7 @@ void WeissHapticSensorsUnit::onInitHapticUnit() } -std::vector< std::string > WeissHapticSensorsUnit::getDevices() +std::vector< std::string > WeissHapticUnit::getDevices() { const std::string target_path( "/dev/" ); const boost::regex my_filter( "ttyACM[0-9]+" ); @@ -108,37 +73,47 @@ std::vector< std::string > WeissHapticSensorsUnit::getDevices() } std::sort(files.begin(), files.end()); - std::cout << "Detected ACM-Interfaces: " << std::endl; - for(std::vector<std::string>::iterator it = files.begin(); it != files.end(); ++it) + if(files.size() == 0) { - std::cout << *it << std::endl; + ARMARX_WARNING << "No ACM-Interfaces found"; + } + else + { + ARMARX_INFO << "Detected ACM-Interfaces: " << files.size(); + for(std::string file : files) + { + ARMARX_INFO << "Found device: " << file; + } } return files; } -void WeissHapticSensorsUnit::setDeviceTag(const string &deviceName, const string &tag, const Ice::Current &) +void WeissHapticUnit::setDeviceTag(const string &deviceName, const string &tag, const Ice::Current &) { for(WeissHapticSensorPtr sensor : sensors) { if(sensor->getDeviceName() == deviceName) { + ARMARX_IMPORTANT << "scheduling to set new device tag for " << deviceName << ": " << tag; sensor->scheduleSetDeviceTag(tag); + return; } } + ARMARX_WARNING << "device not found: " << deviceName; } -void WeissHapticSensorsUnit::startLogging(const Ice::Current &) +void WeissHapticUnit::startLogging(const Ice::Current &) { // @@@ TODO NotImplemented } -void WeissHapticSensorsUnit::stopLogging(const Ice::Current &) +void WeissHapticUnit::stopLogging(const Ice::Current &) { // @@@ TODO NotImplemented } -void WeissHapticSensorsUnit::onStartHapticUnit() +void WeissHapticUnit::onStartHapticUnit() { for(std::vector<boost::shared_ptr<WeissHapticSensor> >::iterator it = sensors.begin(); it != sensors.end(); ++it) @@ -149,7 +124,7 @@ void WeissHapticSensorsUnit::onStartHapticUnit() } -void WeissHapticSensorsUnit::onExitHapticUnit() +void WeissHapticUnit::onExitHapticUnit() { for(std::vector<boost::shared_ptr<WeissHapticSensor> >::iterator it = sensors.begin(); it != sensors.end(); ++it) { @@ -157,18 +132,18 @@ void WeissHapticSensorsUnit::onExitHapticUnit() } } -/*void WeissHapticSensorsUnit::onConnectComponent() +/*void WeissHapticUnit::onConnectComponent() { }*/ -void WeissHapticSensorsUnit::onDisconnectComponent() +void WeissHapticUnit::onDisconnectComponent() { } -PropertyDefinitionsPtr WeissHapticSensorsUnit::createPropertyDefinitions() +PropertyDefinitionsPtr WeissHapticUnit::createPropertyDefinitions() { - return PropertyDefinitionsPtr(new WeissHapticSensorsUnitPropertyDefinitions(getConfigIdentifier())); + return PropertyDefinitionsPtr(new WeissHapticUnitPropertyDefinitions(getConfigIdentifier())); } diff --git a/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensorsUnit.h b/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticUnit.h old mode 100755 new mode 100644 similarity index 89% rename from source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensorsUnit.h rename to source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticUnit.h index 1a0f955718658b8760e56366896ec657da47dc1e..ff24168d0b939d42bb3e48755ba206e9331827fb --- a/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticSensorsUnit.h +++ b/source/RobotAPI/libraries/drivers/WeissHapticSensor/WeissHapticUnit.h @@ -33,21 +33,21 @@ namespace armarx { - class WeissHapticSensorsUnitPropertyDefinitions : public HapticUnitPropertyDefinitions + class WeissHapticUnitPropertyDefinitions : public HapticUnitPropertyDefinitions { public: - WeissHapticSensorsUnitPropertyDefinitions(std::string prefix): + WeissHapticUnitPropertyDefinitions(std::string prefix): HapticUnitPropertyDefinitions(prefix) { } }; - class WeissHapticSensorsUnit : + class WeissHapticUnit : virtual public WeissHapticUnitInterface, virtual public HapticUnit { public: - virtual std::string getDefaultName() { return "WeissHapticSensorsUnit"; } + virtual std::string getDefaultName() { return "WeissHapticUnit"; } virtual void onInitHapticUnit(); virtual void onStartHapticUnit(); diff --git a/source/RobotAPI/libraries/drivers/WeissHapticSensor/um_wts0614-34_04-2013_en.pdf b/source/RobotAPI/libraries/drivers/WeissHapticSensor/um_wts0614-34_04-2013_en.pdf new file mode 100755 index 0000000000000000000000000000000000000000..73181a124343bfd66c6f5e94c81300b4db698f7e Binary files /dev/null and b/source/RobotAPI/libraries/drivers/WeissHapticSensor/um_wts0614-34_04-2013_en.pdf differ diff --git a/source/RobotAPI/libraries/drivers/WeissHapticSensor/wts_command_set_reference_manual.pdf b/source/RobotAPI/libraries/drivers/WeissHapticSensor/wts_command_set_reference_manual.pdf new file mode 100755 index 0000000000000000000000000000000000000000..9b259fb180986e1f48da7151511f028cd53af457 Binary files /dev/null and b/source/RobotAPI/libraries/drivers/WeissHapticSensor/wts_command_set_reference_manual.pdf differ diff --git a/source/RobotAPI/statecharts/CMakeLists.txt b/source/RobotAPI/statecharts/CMakeLists.txt index ef16919a0b64586cfe6fffc0d42ffd55bcccfe1a..17fa472e974f7c24c540105e8aab23fa842e6191 100644 --- a/source/RobotAPI/statecharts/CMakeLists.txt +++ b/source/RobotAPI/statecharts/CMakeLists.txt @@ -1,2 +1,4 @@ add_subdirectory(operations) + +add_subdirectory(WeissHapticGroup) \ No newline at end of file diff --git a/source/RobotAPI/statecharts/WeissHapticGroup/CMakeLists.txt b/source/RobotAPI/statecharts/WeissHapticGroup/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..1bb8a3e825f4e4af96ddd3666d76d9b5a21094fc --- /dev/null +++ b/source/RobotAPI/statecharts/WeissHapticGroup/CMakeLists.txt @@ -0,0 +1,48 @@ +armarx_component_set_name("WeissHapticGroup") + +#find_package(MyLib QUIET) +#armarx_build_if(MyLib_FOUND "MyLib not available") +# +# all include_directories must be guarded by if(Xyz_FOUND) +# for multiple libraries write: if(X_FOUND AND Y_FOUND).... +#if(MyLib_FOUND) +# include_directories(${MyLib_INCLUDE_DIRS}) +#endif() + +find_package(Eigen3 QUIET) +find_package(Simox QUIET) + + +armarx_build_if(Eigen3_FOUND "Eigen3 not available") +armarx_build_if(Simox_FOUND "Simox-VirtualRobot not available") + + +if (Eigen3_FOUND AND Simox_FOUND) + include_directories( + ${Eigen3_INCLUDE_DIR} + ${Simox_INCLUDE_DIRS} + ) +endif() + +set(COMPONENT_LIBS + RobotAPIInterfaces RobotAPICore RobotAPIUnits + ArmarXInterfaces ArmarXCore ArmarXCoreStatechart ArmarXCoreObservers) + +# Sources + +set(SOURCES +WeissHapticGroupRemoteStateOfferer.cpp +./WeissHapticSensorTest.cpp +#@TEMPLATE_LINE@@COMPONENT_PATH@/@COMPONENT_NAME@.cpp +) + +set(HEADERS +WeissHapticGroupRemoteStateOfferer.h +WeissHapticGroupStatechartContext.generated.h +./WeissHapticSensorTest.h +#@TEMPLATE_LINE@@COMPONENT_PATH@/@COMPONENT_NAME@.h +./WeissHapticSensorTest.generated.h +#@TEMPLATE_LINE@@COMPONENT_PATH@/@COMPONENT_NAME@.generated.h +) + +armarx_add_component("${SOURCES}" "${HEADERS}") diff --git a/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroup.scgxml b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroup.scgxml new file mode 100644 index 0000000000000000000000000000000000000000..d030a3d328389657a297a2573b5b900ec46d84fe --- /dev/null +++ b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroup.scgxml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<StatechartGroup name="WeissHapticGroup" package="RobotAPI" generateContext="true"> + <Proxies> + <Proxy value="RobotAPICore.hapticObserver"/> + <Proxy value="RobotAPICore.weissHapticUnit"/> + </Proxies> + <State filename="WeissHapticSensorTest.xml" visibility="public"/> +</StatechartGroup> + diff --git a/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroupRemoteStateOfferer.cpp b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroupRemoteStateOfferer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8f0c6b0e2bb73a32a26da3ba4a23afef190c40c --- /dev/null +++ b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroupRemoteStateOfferer.cpp @@ -0,0 +1,66 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::WeissHapticGroup::WeissHapticGroupRemoteStateOfferer + * @author Simon Ottenhaus ( simon dot ottenhaus at kit dot edu ) + * @date 2015 + * @copyright http://www.gnu.org/licenses/gpl.txt + * GNU General Public License + */ + +#include "WeissHapticGroupRemoteStateOfferer.h" + +using namespace armarx; +using namespace WeissHapticGroup; + +// DO NOT EDIT NEXT LINE +WeissHapticGroupRemoteStateOfferer::SubClassRegistry WeissHapticGroupRemoteStateOfferer::Registry(WeissHapticGroupRemoteStateOfferer::GetName(), &WeissHapticGroupRemoteStateOfferer::CreateInstance); + + + +WeissHapticGroupRemoteStateOfferer::WeissHapticGroupRemoteStateOfferer(StatechartGroupXmlReaderPtr reader) : + XMLRemoteStateOfferer < WeissHapticGroupStatechartContext > (reader) +{ +} + +void WeissHapticGroupRemoteStateOfferer::onInitXMLRemoteStateOfferer() +{ + +} + +void WeissHapticGroupRemoteStateOfferer::onConnectXMLRemoteStateOfferer() +{ + +} + +void WeissHapticGroupRemoteStateOfferer::onExitXMLRemoteStateOfferer() +{ + +} + +// DO NOT EDIT NEXT FUNCTION +std::string WeissHapticGroupRemoteStateOfferer::GetName() +{ + return "WeissHapticGroupRemoteStateOfferer"; +} + +// DO NOT EDIT NEXT FUNCTION +XMLStateOffererFactoryBasePtr WeissHapticGroupRemoteStateOfferer::CreateInstance(StatechartGroupXmlReaderPtr reader) +{ + return XMLStateOffererFactoryBasePtr(new WeissHapticGroupRemoteStateOfferer(reader)); +} + + + diff --git a/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroupRemoteStateOfferer.h b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroupRemoteStateOfferer.h new file mode 100644 index 0000000000000000000000000000000000000000..232ed4f3261a52cfb2ea1d2b6c3d3479a488bc74 --- /dev/null +++ b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroupRemoteStateOfferer.h @@ -0,0 +1,54 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::WeissHapticGroup + * @author Simon Ottenhaus ( simon dot ottenhaus at kit dot edu ) + * @date 2015 + * @copyright http://www.gnu.org/licenses/gpl.txt + * GNU General Public License + */ + +#ifndef _ARMARX_XMLUSERCODE_RobotAPI_WeissHapticGroup_REMOTESTATEOFFERER_H +#define _ARMARX_XMLUSERCODE_RobotAPI_WeissHapticGroup_REMOTESTATEOFFERER_H + +#include <Core/statechart/xmlstates/XMLRemoteStateOfferer.h> +#include "WeissHapticGroupStatechartContext.generated.h" + +namespace armarx +{ + namespace WeissHapticGroup + { + class WeissHapticGroupRemoteStateOfferer : + virtual public XMLRemoteStateOfferer < WeissHapticGroupStatechartContext > // Change this statechart context if you need another context (dont forget to change in the constructor as well) + { + public: + WeissHapticGroupRemoteStateOfferer(StatechartGroupXmlReaderPtr reader); + + // inherited from RemoteStateOfferer + void onInitXMLRemoteStateOfferer(); + void onConnectXMLRemoteStateOfferer(); + void onExitXMLRemoteStateOfferer(); + + // static functions for AbstractFactory Method + static std::string GetName(); + static XMLStateOffererFactoryBasePtr CreateInstance(StatechartGroupXmlReaderPtr reader); + static SubClassRegistry Registry; + + + }; + } +} + +#endif diff --git a/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroupStatechartContext.generated.h b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroupStatechartContext.generated.h new file mode 100644 index 0000000000000000000000000000000000000000..947ae7ed0391362ec7e483b4003c67748d58e4b3 --- /dev/null +++ b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticGroupStatechartContext.generated.h @@ -0,0 +1,59 @@ +#ifndef ARMARX_COMPONENT_ARMARX_WEISSHAPTICGROUP_WEISSHAPTICGROUPSTATECHARTCONTEXT_H +#define ARMARX_COMPONENT_ARMARX_WEISSHAPTICGROUP_WEISSHAPTICGROUPSTATECHARTCONTEXT_H + +#include <Core/core/Component.h> +#include <Core/core/system/ImportExportComponent.h> +#include <Core/statechart/StatechartContext.h> +#include <RobotAPI/interface/units/HapticUnit.h> +#include <RobotAPI/interface/units/WeissHapticUnit.h> + +namespace armarx +{ + namespace WeissHapticGroup + { + class WeissHapticGroupStatechartContext + : virtual public StatechartContext + { + protected: + class PropertyDefinitions + : public StatechartContextPropertyDefinitions + { + public: + PropertyDefinitions(std::string prefix) + : StatechartContextPropertyDefinitions(prefix) + { + defineOptionalProperty<std::string>("HapticUnitObserverName", "HapticUnitObserver", "Name of the haptic unit observer that should be used"); + defineOptionalProperty<std::string>("WeissHapticUnitName", "WeissHapticUnit", "Name of the weiss haptic unit that should be used"); + } + }; // class PropertyDefinitions + + private: + HapticUnitObserverInterfacePrx hapticObserver; + WeissHapticUnitInterfacePrx weissHapticUnit; + + public: + std::string getDefaultName() const + { + return "WeissHapticGroupStatechartContext"; + } + virtual void onInitStatechartContext() + { + usingProxy(getProperty<std::string>("HapticUnitObserverName").getValue()); + usingProxy(getProperty<std::string>("WeissHapticUnitName").getValue()); + } + virtual void onConnectStatechartContext() + { + hapticObserver = getProxy<HapticUnitObserverInterfacePrx>(getProperty<std::string>("HapticUnitObserverName").getValue()); + weissHapticUnit = getProxy<WeissHapticUnitInterfacePrx>(getProperty<std::string>("WeissHapticUnitName").getValue()); + } + HapticUnitObserverInterfacePrx getHapticObserver() const { return hapticObserver; } + WeissHapticUnitInterfacePrx getWeissHapticUnit() const { return weissHapticUnit; } + virtual PropertyDefinitionsPtr createPropertyDefinitions() + { + return PropertyDefinitionsPtr(new WeissHapticGroupStatechartContext::PropertyDefinitions(getConfigIdentifier())); + } + }; // class WeissHapticGroupStatechartContext + } // namespace WeissHapticGroup +} // namespace armarx + +#endif // ARMARX_COMPONENT_ARMARX_WEISSHAPTICGROUP_WEISSHAPTICGROUPSTATECHARTCONTEXT_H diff --git a/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticSensorTest.cpp b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticSensorTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac0edd94540c762281d997bea5684cc08bf3fb58 --- /dev/null +++ b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticSensorTest.cpp @@ -0,0 +1,112 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::WeissHapticGroup + * @author Simon Ottenhaus ( simon dot ottenhaus at kit dot edu ) + * @date 2015 + * @copyright http://www.gnu.org/licenses/gpl.txt + * GNU General Public License + */ + +#include "WeissHapticSensorTest.h" + +#include <RobotAPI/libraries/core/observerfilters/MatrixFilters.h> +#include <RobotAPI/libraries/core/observerfilters/OffsetFilter.h> + +using namespace armarx; +using namespace WeissHapticGroup; + +// DO NOT EDIT NEXT LINE +WeissHapticSensorTest::SubClassRegistry WeissHapticSensorTest::Registry(WeissHapticSensorTest::GetName(), &WeissHapticSensorTest::CreateInstance); + + + +WeissHapticSensorTest::WeissHapticSensorTest(const XMLStateConstructorParams& stateData) : + XMLStateTemplate<WeissHapticSensorTest>(stateData), WeissHapticSensorTestGeneratedBase<WeissHapticSensorTest>(stateData) +{ +} + +void WeissHapticSensorTest::onEnter() +{ + WeissHapticGroupStatechartContext* context = getContext<WeissHapticGroupStatechartContext>(); + HapticUnitObserverInterfacePrx hapticObserver = context->getHapticObserver(); + ChannelRegistry channels = hapticObserver->getAvailableChannels(false); + std::map<std::string, DatafieldRefPtr> tactileDatafields_MaximumValueMap; + if(channels.size() == 0) + { + ARMARX_WARNING << "No tactile pads found"; + } + else + { + ARMARX_INFO << "Creating tactile channels"; + for(std::pair<std::string, ChannelRegistryEntry> pair : channels) + { + std::string tactilePad = pair.first; + DatafieldRefBasePtr matrixDatafield = new DatafieldRef(hapticObserver, tactilePad, "matrix"); + DatafieldRefBasePtr matrixNulled = hapticObserver->createFilteredDatafield(DatafieldFilterBasePtr(new filters::OffsetFilter()), matrixDatafield); + DatafieldRefBasePtr matrixMax = hapticObserver->createFilteredDatafield(DatafieldFilterBasePtr(new filters::MatrixMaxFilter()), matrixNulled); + tactileDatafields_MaximumValueMap.insert(std::make_pair(tactilePad, DatafieldRefPtr::dynamicCast(matrixMax))); + } + } + local.setTactileDatafields_MaximumValue(tactileDatafields_MaximumValueMap); + + +} + +void WeissHapticSensorTest::run() +{ + std::map<std::string, DatafieldRefPtr> tactileDatafields_MaximumValueMap = local.getTactileDatafields_MaximumValue(); + + while (!isRunningTaskStopped()) // stop run function if returning true + { + std::stringstream ss; + std::stringstream ssNames; + int max = 0; + for(std::pair<std::string, DatafieldRefPtr> pair : tactileDatafields_MaximumValueMap) + { + std::string tactilePad = pair.first; + DatafieldRefPtr matrixMax = pair.second; + int padMax = (int)matrixMax->getDataField()->getFloat(); + ss << padMax << "; "; + ssNames << tactilePad << "; "; + max = std::max(max, padMax); + } + ARMARX_IMPORTANT << "tactile max value: " << max << "; \n\n" << ss.str() << "\n" << ssNames.str(); + + usleep(10000); // 100ms + } + +} + +void WeissHapticSensorTest::onBreak() +{ + // put your user code for the breaking point here + // execution time should be short (<100ms) +} + +void WeissHapticSensorTest::onExit() +{ + // put your user code for the exit point here + // execution time should be short (<100ms) + +} + + +// DO NOT EDIT NEXT FUNCTION +XMLStateFactoryBasePtr WeissHapticSensorTest::CreateInstance(XMLStateConstructorParams stateData) +{ + return XMLStateFactoryBasePtr(new WeissHapticSensorTest(stateData)); +} + diff --git a/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticSensorTest.generated.h b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticSensorTest.generated.h new file mode 100644 index 0000000000000000000000000000000000000000..a4cd708d5e6efbb5207bf86e3fe58518bb58d65e --- /dev/null +++ b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticSensorTest.generated.h @@ -0,0 +1,120 @@ +#ifndef _ARMARX_XMLUSERCODE_ARMARX_WEISSHAPTICGROUP_WEISSHAPTICSENSORTESTGENERATEDBASE_H +#define _ARMARX_XMLUSERCODE_ARMARX_WEISSHAPTICGROUP_WEISSHAPTICSENSORTESTGENERATEDBASE_H + +#include <Core/statechart/xmlstates/XMLState.h> +#include "WeissHapticGroupStatechartContext.generated.h" +#include <Core/observers/ObserverObjectFactories.h> +#include <RobotAPI/interface/units/HapticUnit.h> +#include <RobotAPI/interface/units/WeissHapticUnit.h> + +namespace armarx +{ + namespace WeissHapticGroup + { + template<typename StateType> + class WeissHapticSensorTestGeneratedBase + : virtual public XMLStateTemplate < StateType >, + public XMLStateFactoryBase + { + protected: + class WeissHapticSensorTestIn + { + private: + WeissHapticSensorTestGeneratedBase<StateType> *parent; + + public: + WeissHapticSensorTestIn(WeissHapticSensorTestGeneratedBase<StateType> *parent) + : parent(parent) + { + } + }; // class WeissHapticSensorTestIn + + class WeissHapticSensorTestLocal + { + private: + WeissHapticSensorTestGeneratedBase<StateType> *parent; + + public: + WeissHapticSensorTestLocal(WeissHapticSensorTestGeneratedBase<StateType> *parent) + : parent(parent) + { + } + + public: + std::map<std::string, ::armarx::DatafieldRefPtr> getTactileDatafields_MaximumValue() const + { + return parent->State::getLocal< ::armarx::StringValueMap>("TactileDatafields_MaximumValue")->::armarx::StringValueMap::toStdMap< ::armarx::DatafieldRefPtr>(); + } + void setTactileDatafields_MaximumValue(const std::map<std::string, ::armarx::DatafieldRefPtr> & value) const + { + ::armarx::StringValueMapPtr container = ::armarx::StringValueMap::FromStdMap< ::armarx::DatafieldRefPtr>(value); + parent->State::setLocal("TactileDatafields_MaximumValue", *container); + } + bool isTactileDatafields_MaximumValueSet() const + { + return parent->State::isLocalParameterSet("TactileDatafields_MaximumValue"); + } + }; // class WeissHapticSensorTestLocal + + class WeissHapticSensorTestOut + { + private: + WeissHapticSensorTestGeneratedBase<StateType> *parent; + + public: + WeissHapticSensorTestOut(WeissHapticSensorTestGeneratedBase<StateType> *parent) + : parent(parent) + { + } + }; // class WeissHapticSensorTestOut + + protected: + const WeissHapticSensorTestIn in; + const WeissHapticSensorTestLocal local; + const WeissHapticSensorTestOut out; + + public: + WeissHapticSensorTestGeneratedBase(const XMLStateConstructorParams& stateData) + : XMLStateTemplate < StateType > (stateData), + in(WeissHapticSensorTestIn(this)), + local(WeissHapticSensorTestLocal(this)), + out(WeissHapticSensorTestOut(this)) + { + } + WeissHapticSensorTestGeneratedBase(const WeissHapticSensorTestGeneratedBase &source) + : IceUtil::Shared(source), + armarx::StateIceBase(source), + armarx::StateBase(source), + armarx::StateController(source), + armarx::State(source), + XMLStateTemplate < StateType > (source), + in(WeissHapticSensorTestIn(this)), + local(WeissHapticSensorTestLocal(this)), + out(WeissHapticSensorTestOut(this)) + { + } + + public: + HapticUnitObserverInterfacePrx getHapticObserver() const + { + return StateBase::getContext<WeissHapticGroupStatechartContext>()->getHapticObserver(); + } + WeissHapticUnitInterfacePrx getWeissHapticUnit() const + { + return StateBase::getContext<WeissHapticGroupStatechartContext>()->getWeissHapticUnit(); + } + static std::string GetName() + { + return "WeissHapticSensorTest"; + } + void __forceLibLoading() + { + // Do not call this method. + // The sole purpose of this method is to force the compiler/linker to include all libraries. + ::armarx::DatafieldRef type1; + } + }; // class WeissHapticSensorTestGeneratedBase + } // namespace WeissHapticGroup +} // namespace armarx + +#endif // _ARMARX_XMLUSERCODE_ARMARX_WEISSHAPTICGROUP_WEISSHAPTICSENSORTESTGENERATEDBASE_H diff --git a/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticSensorTest.h b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticSensorTest.h new file mode 100644 index 0000000000000000000000000000000000000000..34b84f98978965e66af0c0f79a2c9322ca177df3 --- /dev/null +++ b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticSensorTest.h @@ -0,0 +1,55 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::WeissHapticGroup + * @author Simon Ottenhaus ( simon dot ottenhaus at kit dot edu ) + * @date 2015 + * @copyright http://www.gnu.org/licenses/gpl.txt + * GNU General Public License + */ + +#ifndef _ARMARX_XMLUSERCODE_RobotAPI_WeissHapticGroup_WeissHapticSensorTest_H +#define _ARMARX_XMLUSERCODE_RobotAPI_WeissHapticGroup_WeissHapticSensorTest_H + +#include "WeissHapticSensorTest.generated.h" + +namespace armarx +{ + namespace WeissHapticGroup + { + class WeissHapticSensorTest : + public WeissHapticSensorTestGeneratedBase<WeissHapticSensorTest> + { + public: + WeissHapticSensorTest(const XMLStateConstructorParams& stateData); + + // inherited from StateBase + void onEnter(); + void run(); + void onBreak(); + void onExit(); + + // static functions for AbstractFactory Method + static XMLStateFactoryBasePtr CreateInstance(XMLStateConstructorParams stateData); + static SubClassRegistry Registry; + + // DO NOT INSERT ANY CLASS MEMBERS, + // use stateparameters instead, + // if classmember are neccessary nonetheless, reset them in onEnter + }; + } +} + +#endif diff --git a/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticSensorTest.xml b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticSensorTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..d44dc26ac48b7524c6ef53fcff2728aa6496aa64 --- /dev/null +++ b/source/RobotAPI/statecharts/WeissHapticGroup/WeissHapticSensorTest.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<State version="1.0" name="WeissHapticSensorTest" uuid="B8841E3D-97C6-468F-86D9-6370D5F89BB4" width="800" height="600"> + <InputParameters/> + <OutputParameters/> + <LocalParameters> + <Parameter name="TactileDatafields_MaximumValue" type="::armarx::StringValueMapBase(::armarx::DatafieldRefBase)" optional="no"/> + </LocalParameters> + <Substates/> + <Events/> + <Transitions/> +</State> +