diff --git a/.github/workflows/java-ci.yml b/.github/workflows/java-ci.yml new file mode 100644 index 0000000..25c4632 --- /dev/null +++ b/.github/workflows/java-ci.yml @@ -0,0 +1,49 @@ +name: Java CI + +on: + # Trigger the workflow on push or pull request, + # but only for the main branch + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + build: + runs-on: ubuntu-24.04 + permissions: + contents: write + pages: write + id-token: write + strategy: + matrix: + java: [ '17', '21', '25'] + name: JDK ${{ matrix.Java }} build + steps: + - uses: actions/checkout@v5.0.0 + - name: Set up Java + uses: actions/setup-java@v5.0.0 + with: + java-version: ${{ matrix.java }} + distribution: 'adopt' + cache: gradle + - name: Validate Gradle wrapper + uses: gradle/actions/wrapper-validation@v4.4.2 + - name: Build with Gradle headless + uses: coactions/setup-xvfb@v1.0.1 + with: + run: ./gradlew clean build jacocoTestReport + - name: Cleanup Gradle Cache + # Remove some files from the Gradle cache, so they aren't cached by GitHub Actions. + # Restoring these files from a GitHub Actions cache might cause problems for future builds. + run: | + rm -f ~/.gradle/caches/modules-2/modules-2.lock + rm -f ~/.gradle/caches/modules-2/gc.properties + - name: Test & publish code coverage + uses: qltysh/qlty-action/coverage@v2 + with: + oidc: true + files: ${{github.workspace}}/build/reports/jacoco/test/jacocoTestReport.xml + add-prefix: src/main/java/ diff --git a/.travis.yml b/.travis.yml index 1acf57b..698ff05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,15 +8,10 @@ services: jdk: - openjdk8 - openjdk9 -before_script: - - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter - - chmod +x ./cc-test-reporter - - ./cc-test-reporter before-build script: - ./gradlew clean build jacocoTestReport after_script: - JACOCO_SOURCE_PATH=src/main/java ./cc-test-reporter format-coverage ./build/reports/jacoco/test/jacocoTestReport.xml --input-type jacoco - - ./cc-test-reporter upload-coverage -r $CC_TEST_REPORTER_ID -notifications: + notifications: slack: secure: jSd9irNrMQ8TtXW9H7yl3qGlQXA5Zp6mzGtM5OONofL3x3DOdvIkBb75+S7zZiQJn7QdVzNrGnb6pVm/r6wGUupyRr2HvHlS3s19qwrCDwl6+vW46AGS6ZgdiqhGSdV5yQkhRRoxRlLpHOq+9KnZ4Sycr74VV6Kk9EzBFmdfCPOVi7+iQWKJHYm/AUNIKfFk8OR4vpitwAqEgYguMHKyhh7Edv4pNHzExRlL8p6jdkGL7Ul5UF1q44AQdVsSGY0ByudJJNiU1AxjfLYaCWiBpvlYMJz/rY8Q023dw/EdEfAcg5evzZnljcLiBmRc4Y3lVyQvzffGoHwsXPWiKac7ZhtJ+tD1Hl+UG/IQtkEp814Iule1e/cUqgZ3jlNZI++lfKLUdadXHeDP5bdIOj1XGLf3T68Z3lmLJkFaVsPElxGmMM+3Pi1R2gTufH8FFW+njZR1FpEqZHtHpTt0QYEP+jL1hFH5Xo4jRPoexfEOe1oe3n61QR1c0YjPtdkpHif1oRMpruD7evq8KhAFJNqMe/K3KRTK8hoKT8arl/lqU0NRonCR1gaNHPjyvyPZfnya+PtijpL1zFJcRtEV6rDlmnQ9xxHcT8yCBHgIB2N2oU0qZlz/oy2Lx53chzeH55o+ypQ9Fcx4ra2riGlOkTGRX2WrcOBi2CmA/DEiWPpF8RM= diff --git a/README.md b/README.md index 4b6b9b2..ecbe941 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -[![Build Status](https://travis-ci.org/CST-Group/meca.svg?branch=master)](https://travis-ci.org/CST-Group/meca) [![Maintainability](https://api.codeclimate.com/v1/badges/c24e46ebcdc9aa6a035e/maintainability)](https://codeclimate.com/github/CST-Group/meca/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/c24e46ebcdc9aa6a035e/test_coverage)](https://codeclimate.com/github/CST-Group/meca/test_coverage) +![](https://github.com/CST-Group/meca/actions/workflows/java-ci.yml/badge.svg) +[![Maintainability](https://api.codeclimate.com/v1/badges/c24e46ebcdc9aa6a035e/maintainability)](https://codeclimate.com/github/CST-Group/meca/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/c24e46ebcdc9aa6a035e/test_coverage)](https://codeclimate.com/github/CST-Group/meca/test_coverage) [![](https://jitpack.io/v/CST-Group/meca.svg?label=Release)](https://jitpack.io/#CST-Group/meca) # MECA @@ -28,7 +29,7 @@ Note: This library is still under development, and some concepts or features mig ``` dependencies { ... - implementation 'com.github.CST-Group:meca:0.2.1' + implementation 'com.github.CST-Group:meca:0.8.3' } ``` @@ -53,7 +54,7 @@ Sometimes, the version number (tag) in this README gets out of date, as maintain com.github.CST-Group meca - 0.2.1 + 0.8.3 ``` diff --git a/build.gradle b/build.gradle index 9f022ed..386e675 100644 --- a/build.gradle +++ b/build.gradle @@ -1,53 +1,128 @@ plugins { - id 'java-library-distribution' - id 'jacoco' - id 'maven' + id 'java-library-distribution' + id 'jacoco' + id 'maven-publish' } group = 'com.github.CST-Group' - description = "The Multipurpose Enhanced Cognitive Architecture (MECA)" -sourceCompatibility = 1.8 -targetCompatibility = 1.8 -version = '0.2.1' +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 -repositories { - mavenCentral() - maven { url 'https://jitpack.io' } - maven { - url "https://github.com/rosjava/rosjava_mvn_repo/raw/master" + toolchain { + languageVersion = JavaLanguageVersion.of(17) } - maven { - url "http://repository.springsource.com/maven/bundles/release" - } - maven { - url "http://repository.springsource.com/maven/bundles/external" +} + +version = '0.8.3' + +repositories { + // Local flat directories for custom jars + flatDir { + dirs '../cst-desktop/build/libs' } + + // Remote repositories + mavenCentral() + maven { url = 'https://jitpack.io' } + maven { url = "https://github.com/rosjava/rosjava_mvn_repo/raw/master" } + maven { url = 'https://cst-group.github.io/cst-dependencies/maven-repo/' } +} + +configurations { + extraLibs } dependencies { - api 'com.github.CST-Group:cst:0.3.1' - testImplementation group: 'junit', name: 'junit', version: '4.12' - testImplementation 'org.ros.rosjava_messages:std_msgs:0.5.11' - testImplementation 'org.ros.rosjava_messages:rosjava_test_msgs:0.3.0' + // CST Desktop API + api('com.github.CST-Group:cst-desktop:1.1.3') // This one is for production + //api(':cst-desktop:1.1.3-full') // This one is for new developments only + + // JUnit and testing + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.0' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.0' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + // ROS 2 Java bindings + implementation 'io.github.lambdaprime:jros2client:12.0' + implementation 'io.github.pinorobotics:jros2services:8.0' + //implementation 'io.github.lambdaprime:jrosmessages-std_msgs:12.0' // keep commented + + // Optional / logging + implementation 'ch.qos.logback:logback-classic:1.0.11' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.0' + + api 'org.ros.rosjava_messages:std_msgs:0.5.11' + testImplementation group: 'junit', name: 'junit', version: '4.12' + testImplementation 'org.ros.rosjava_messages:std_msgs:0.5.11' +} + +// forces all changing dependencies (i.e. SNAPSHOTs) to always download +configurations.all { + resolutionStrategy.cacheChangingModulesFor 0, 'seconds' +} + +jar { + manifest { + attributes( + 'Class-Path': configurations.runtimeClasspath.files.collect { it.getName() }.join(' ') + ) + } } task javadocJar(type: Jar) { - classifier = 'javadoc' + archiveClassifier = 'javadoc' from javadoc + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } + javadoc.options.addStringOption('Xdoclint:none', '-quiet') } + task sourcesJar(type: Jar) { - classifier = 'sources' + archiveClassifier = 'sources' from sourceSets.main.allSource + from { + configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } + } } -artifacts -{ - archives javadocJar, sourcesJar + +task uberJar(type: Jar) { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + archiveClassifier = 'full' + from sourceSets.main.output + dependsOn configurations.runtimeClasspath + from { + configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) } + } + exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA' +} + +artifacts { + archives javadocJar, sourcesJar, uberJar +} + +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + } + } } jacocoTestReport { reports { - xml.enabled true + xml.required = true } -} \ No newline at end of file +} + +uberJar { + dependsOn jar +} + +test { + useJUnitPlatform() + maxParallelForks = 1 +} diff --git a/gradle.properties b/gradle.properties index 8bd86f6..1d4c225 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,3 @@ org.gradle.jvmargs=-Xmx1536M +action.custom-1=uberJar +action.custom-1.args=uberJar diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 87b738c..1b33c55 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 44e7c4d..bad7c24 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index af6708f..23d15a9 100755 --- a/gradlew +++ b/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m"' +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,92 +132,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 0f8d593..5eed7ee 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,4 +1,22 @@ -@if "%DEBUG%" == "" @echo off +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -9,25 +27,29 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -35,48 +57,36 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 0000000..bbaedec --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,3 @@ +jdk: + - openjdk17 + diff --git a/settings.gradle b/settings.gradle index f68f70f..30029d9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,2 @@ -rootProject.name = 'meca' \ No newline at end of file +rootProject.name = 'meca' +//include 'cst-bindings' \ No newline at end of file diff --git a/src/main/java/br/unicamp/meca/memory/WorkingMemory.java b/src/main/java/br/unicamp/meca/memory/WorkingMemory.java index 635a82b..ebef889 100644 --- a/src/main/java/br/unicamp/meca/memory/WorkingMemory.java +++ b/src/main/java/br/unicamp/meca/memory/WorkingMemory.java @@ -14,7 +14,10 @@ import br.unicamp.cst.core.entities.Memory; import br.unicamp.cst.core.entities.MemoryContainer; -import br.unicamp.cst.core.entities.MemoryObject; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * This class represents the MECA's Working Memory. @@ -106,20 +109,22 @@ public class WorkingMemory { * The Working Memory Input constant. */ public static final String WORKING_MEMORY_INPUT = "WORKING_MEMORY_INPUT"; + + private Map wm = new HashMap(); private String id; - private Memory cueMemory; - private Memory plansMemory; - private Memory episodicRecallMemory; - private Memory globalWorkspaceMemory; - private Memory executivePlanMemory; - - private Memory imaginationsMemory; - private Memory goalsMemory; - private Memory currentPerceptionMemory; - private Memory predictedSituationMemory; - - private Memory nextActionMemory; +// private Memory cueMemory; +// private Memory plansMemory; +// private Memory episodicRecallMemory; +// private Memory globalWorkspaceMemory; +// private Memory executivePlanMemory; +// +// private Memory imaginationsMemory; +// private Memory goalsMemory; +// private Memory currentPerceptionMemory; +// private Memory predictedSituationMemory; +// +// private Memory nextActionMemory; /** * Creates the MECA's Working Memory. @@ -130,17 +135,28 @@ public class WorkingMemory { public WorkingMemory(String id) { setId(id); - setPlansMemory(new MemoryContainer()); - setEpisodicRecallMemory(new MemoryContainer()); - setGlobalWorkspaceMemory(new MemoryContainer()); - setImaginationsMemory(new MemoryContainer()); - setGoalsMemory(new MemoryContainer()); + setInternalMemory("PlansMemory",new MemoryContainer("PlansMemory")); + setInternalMemory("EpisodicRecallMemory",new MemoryContainer("EpisodicRecallMemory")); + setInternalMemory("GlobalWorkspaceMemory",new MemoryContainer("GlobalWorkspaceMemory")); + setInternalMemory("ImaginationsMemory",new MemoryContainer("ImaginationsMemory")); + setInternalMemory("GoalsMemory",new MemoryContainer("GoalsMemory")); + +// setPlansMemory(new MemoryContainer()); +// setEpisodicRecallMemory(new MemoryContainer()); +// setGlobalWorkspaceMemory(new MemoryContainer()); +// setImaginationsMemory(new MemoryContainer()); +// setGoalsMemory(new MemoryContainer()); - setCueMemory(new MemoryObject()); - setNextActionMemory(new MemoryObject()); - setExecutivePlanMemory(new MemoryObject()); - setCurrentPerceptionMemory(new MemoryObject()); - setPredictedSituationMemory(new MemoryObject()); + setInternalMemory("CueMemory",new MemoryContainer("CueMemory")); + setInternalMemory("NextActionMemory",new MemoryContainer("NextActionMemory")); + setInternalMemory("ExecutivePlanMemory",new MemoryContainer("ExecutivePlanMemory")); + setInternalMemory("CurrentPerceptionMemory",new MemoryContainer("CurrentPerceptionMemory")); + setInternalMemory("PredictedSituationMemory",new MemoryContainer("PredictedSituationMemory")); +// setCueMemory(new MemoryObject()); +// setNextActionMemory(new MemoryObject()); +// setExecutivePlanMemory(new MemoryObject()); +// setCurrentPerceptionMemory(new MemoryObject()); +// setPredictedSituationMemory(new MemoryObject()); } /** @@ -162,193 +178,223 @@ public void setId(String id) { this.id = id; } - /** - * Gets the Cue Memory. - * - * @return the Cue Memory. - */ - public Memory getCueMemory() { - return cueMemory; - } - - /** - * Sets the Cue Memory. - * - * @param cueMemory - * the Cue memory to set. - */ - public void setCueMemory(Memory cueMemory) { - this.cueMemory = cueMemory; - } - - /** - * Gets the Plans Memory. - * - * @return the Plans Memory. - */ - public Memory getPlansMemory() { - return plansMemory; - } - - /** - * Sets the Plans Memory. - * - * @param plansMemory - * the plans Memory to set. - */ - public void setPlansMemory(Memory plansMemory) { - this.plansMemory = plansMemory; - } - - /** - * Gets the Episodic Recall Memory. - * - * @return the Episodic Recall Memory. - */ - public Memory getEpisodicRecallMemory() { - return episodicRecallMemory; - } - - /** - * Sets the Episodic Recall Memory - * - * @param episodicRecallMemory - * the Episodic Recall Memory to set. - */ - public void setEpisodicRecallMemory(Memory episodicRecallMemory) { - this.episodicRecallMemory = episodicRecallMemory; - } - - /** - * Gets the Global Workspace Memory - * - * @return the Global Workspace Memory. - */ - public Memory getGlobalWorkspaceMemory() { - return globalWorkspaceMemory; - } - - /** - * Sets the Global Workspace Memory - * - * @param globalWorkspaceMemory - * the Global Workspace memory to set. - */ - public void setGlobalWorkspaceMemory(Memory globalWorkspaceMemory) { - this.globalWorkspaceMemory = globalWorkspaceMemory; - } - - /** - * Gets the Executive Plan Memory. - * - * @return the Executive Plan Memory. - */ - public Memory getExecutivePlanMemory() { - return executivePlanMemory; - } - - /** - * Sets the Executive Plan memory. - * - * @param executivePlanMemory - * the Executive Plan Memory to set. - */ - public void setExecutivePlanMemory(Memory executivePlanMemory) { - this.executivePlanMemory = executivePlanMemory; - } - - /** - * Gets the Imaginations Memory. - * - * @return the Imaginations Memory. - */ - public Memory getImaginationsMemory() { - return imaginationsMemory; - } - - /** - * Sets the Imaginations memory. - * - * @param imaginationsMemory - * the imaginations memory to set. - */ - public void setImaginationsMemory(Memory imaginationsMemory) { - this.imaginationsMemory = imaginationsMemory; - } - - /** - * Gets the Goals Memory. - * - * @return the Goals Memory. - */ - public Memory getGoalsMemory() { - return goalsMemory; - } - - /** - * Sets the Goals Memory. - * - * @param goalsMemory - * the Goals Memory to set. - */ - public void setGoalsMemory(Memory goalsMemory) { - this.goalsMemory = goalsMemory; - } - - /** - * Gets the Current Perception Memory. - * - * @return the current perception memory. - */ - public Memory getCurrentPerceptionMemory() { - return currentPerceptionMemory; - } - - /** - * Sets the current perception memory. - * - * @param currentPerceptionMemory - * the current perception memory to set. - */ - public void setCurrentPerceptionMemory(Memory currentPerceptionMemory) { - this.currentPerceptionMemory = currentPerceptionMemory; - } - - /** - * Gets the predicted situation memory. - * - * @return the predicte situation memory. - */ - public Memory getPredictedSituationMemory() { - return predictedSituationMemory; - } - - /** - * Sets the predicted situation memory. - * - * @param predictedSituationMemory - * the predicted situation memory to set. - */ - public void setPredictedSituationMemory(Memory predictedSituationMemory) { - this.predictedSituationMemory = predictedSituationMemory; - } - - /** - * Gets the next action memory. + /** + * Gets an Internal Sub Memory. * - * @return the next action memory. + * @param memName the name of the internal memory to get + * @return the Internal Memory. */ - public Memory getNextActionMemory() { - return nextActionMemory; + public Memory getInternalMemory(String memName) { + return(wm.get(memName)); } /** - * Sets the next action memory. + * Sets an Internal Memory. * - * @param nextActionMemory - * the next action memory to set. + * @param memName the name of the internal memory + * @param memory the memory to be set */ - public void setNextActionMemory(Memory nextActionMemory) { - this.nextActionMemory = nextActionMemory; + public void setInternalMemory(String memName, Memory memory) { + if (wm.containsKey(wm)) + wm.replace(memName, memory); + else wm.put(memName, memory); } + + public List getInternalMemoryNames() { + ArrayList imn = new ArrayList<>(); + for (String s : wm.keySet()) { + imn.add(s); + } + return imn; + } + +// /** +// * Gets the Cue Memory. +// * +// * @return the Cue Memory. +// */ +// public Memory getCueMemory() { +// return cueMemory; +// } +// +// /** +// * Sets the Cue Memory. +// * +// * @param cueMemory +// * the Cue memory to set. +// */ +// public void setCueMemory(Memory cueMemory) { +// this.cueMemory = cueMemory; +// } +// +// /** +// * Gets the Plans Memory. +// * +// * @return the Plans Memory. +// */ +// public Memory getPlansMemory() { +// return plansMemory; +// } +// +// /** +// * Sets the Plans Memory. +// * +// * @param plansMemory +// * the plans Memory to set. +// */ +// public void setPlansMemory(Memory plansMemory) { +// this.plansMemory = plansMemory; +// } +// +// /** +// * Gets the Episodic Recall Memory. +// * +// * @return the Episodic Recall Memory. +// */ +// public Memory getEpisodicRecallMemory() { +// return episodicRecallMemory; +// } +// +// /** +// * Sets the Episodic Recall Memory +// * +// * @param episodicRecallMemory +// * the Episodic Recall Memory to set. +// */ +// public void setEpisodicRecallMemory(Memory episodicRecallMemory) { +// this.episodicRecallMemory = episodicRecallMemory; +// } +// +// /** +// * Gets the Global Workspace Memory +// * +// * @return the Global Workspace Memory. +// */ +// public Memory getGlobalWorkspaceMemory() { +// return globalWorkspaceMemory; +// } +// +// /** +// * Sets the Global Workspace Memory +// * +// * @param globalWorkspaceMemory +// * the Global Workspace memory to set. +// */ +// public void setGlobalWorkspaceMemory(Memory globalWorkspaceMemory) { +// this.globalWorkspaceMemory = globalWorkspaceMemory; +// } +// +// /** +// * Gets the Executive Plan Memory. +// * +// * @return the Executive Plan Memory. +// */ +// public Memory getExecutivePlanMemory() { +// return executivePlanMemory; +// } +// +// /** +// * Sets the Executive Plan memory. +// * +// * @param executivePlanMemory +// * the Executive Plan Memory to set. +// */ +// public void setExecutivePlanMemory(Memory executivePlanMemory) { +// this.executivePlanMemory = executivePlanMemory; +// } +// +// /** +// * Gets the Imaginations Memory. +// * +// * @return the Imaginations Memory. +// */ +// public Memory getImaginationsMemory() { +// return imaginationsMemory; +// } +// +// /** +// * Sets the Imaginations memory. +// * +// * @param imaginationsMemory +// * the imaginations memory to set. +// */ +// public void setImaginationsMemory(Memory imaginationsMemory) { +// this.imaginationsMemory = imaginationsMemory; +// } +// +// /** +// * Gets the Goals Memory. +// * +// * @return the Goals Memory. +// */ +// public Memory getGoalsMemory() { +// return goalsMemory; +// } +// +// /** +// * Sets the Goals Memory. +// * +// * @param goalsMemory +// * the Goals Memory to set. +// */ +// public void setGoalsMemory(Memory goalsMemory) { +// this.goalsMemory = goalsMemory; +// } +// +// /** +// * Gets the Current Perception Memory. +// * +// * @return the current perception memory. +// */ +// public Memory getCurrentPerceptionMemory() { +// return currentPerceptionMemory; +// } +// +// /** +// * Sets the current perception memory. +// * +// * @param currentPerceptionMemory +// * the current perception memory to set. +// */ +// public void setCurrentPerceptionMemory(Memory currentPerceptionMemory) { +// this.currentPerceptionMemory = currentPerceptionMemory; +// } +// +// /** +// * Gets the predicted situation memory. +// * +// * @return the predicte situation memory. +// */ +// public Memory getPredictedSituationMemory() { +// return predictedSituationMemory; +// } +// +// /** +// * Sets the predicted situation memory. +// * +// * @param predictedSituationMemory +// * the predicted situation memory to set. +// */ +// public void setPredictedSituationMemory(Memory predictedSituationMemory) { +// this.predictedSituationMemory = predictedSituationMemory; +// } +// +// /** +// * Gets the next action memory. +// * +// * @return the next action memory. +// */ +// public Memory getNextActionMemory() { +// return nextActionMemory; +// } +// +// /** +// * Sets the next action memory. +// * +// * @param nextActionMemory +// * the next action memory to set. +// */ +// public void setNextActionMemory(Memory nextActionMemory) { +// this.nextActionMemory = nextActionMemory; +// } } diff --git a/src/main/java/br/unicamp/meca/mind/MecaMind.java b/src/main/java/br/unicamp/meca/mind/MecaMind.java index bead176..fb0b983 100644 --- a/src/main/java/br/unicamp/meca/mind/MecaMind.java +++ b/src/main/java/br/unicamp/meca/mind/MecaMind.java @@ -14,17 +14,20 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.UUID; import br.unicamp.cst.core.entities.Codelet; import br.unicamp.cst.core.entities.Memory; +import br.unicamp.cst.core.entities.MemoryContainer; import br.unicamp.cst.core.entities.MemoryObject; import br.unicamp.cst.core.entities.Mind; +import br.unicamp.cst.bindings.soar.PlansSubsystemModule; import br.unicamp.meca.memory.WorkingMemory; -import br.unicamp.meca.system1.codelets.ActionFromPerceptionCodelet; -import br.unicamp.meca.system1.codelets.ActionFromPlanningCodelet; +import br.unicamp.meca.system1.codelets.ActivityCodelet; +import br.unicamp.meca.system1.codelets.ActivityTrackingCodelet; import br.unicamp.meca.system1.codelets.AttentionCodelet; import br.unicamp.meca.system1.codelets.BehaviorCodelet; import br.unicamp.meca.system1.codelets.EmotionalCodelet; @@ -41,6 +44,7 @@ import br.unicamp.meca.system2.codelets.EpisodicRetrievalCodelet; import br.unicamp.meca.system2.codelets.ExpectationCodelet; import br.unicamp.meca.system2.codelets.GoalCodelet; +import br.unicamp.meca.system2.codelets.IPlanningCodelet; import br.unicamp.meca.system2.codelets.SoarCodelet; /** @@ -49,61 +53,45 @@ * * @author A. L. O. Paraense * @author E. Froes + * @author R. R. Gudwin * @see Mind */ public class MecaMind extends Mind { - public static final String ACTION_SEQUENCE_PLAN_ID = "ACTION_SEQUENCE_PLAN_ID"; - - public static final String ACTION_SEQUENCE_PLAN_REQUEST_ID = "ACTION_SEQUENCE_PLAN_REQUEST_ID"; + public static final String ACTION_SEQUENCE_PLAN_ID = "ExecutivePlan"; + public static final String ACTION_SEQUENCE_PLAN_REQUEST_ID = "PlanRequest"; /* * System 1 */ private List sensoryCodelets; - private List perceptualCodelets; - private List moodCodelets; - private List motivationalCodelets; - private AttentionCodelet attentionCodeletSystem1; - private List emotionalCodelets; - - private List actionFromPlanningCodelets; - - private List actionFromPerceptionCodelets; - + private List activityCodelets; private List behaviorCodelets; - - private List motorCodelets; - + private volatile List motorCodelets; private Memory actionSequencePlanMemoryContainer; - private Memory actionSequencePlanRequestMemoryContainer; + private ActivityTrackingCodelet activityTrackingCodelet; + private static HashMap memoryGroups = new HashMap(); + private PlansSubsystemModule plansSubsystemModule = new PlansSubsystemModule(); + /* * System 2 */ private List attentionCodeletsSystem2; - private EpisodicLearningCodelet episodicLearningCodelet; - private EpisodicRetrievalCodelet episodicRetrievalCodelet; - private ExpectationCodelet expectationCodelet; - private ConsciousnessCodelet consciousnessCodelet; - - private SoarCodelet soarCodelet; - - private GoalCodelet goalCodelet; - + private List goalCodelets; + private IPlanningCodelet planningCodelet; private AppraisalCodelet appraisalCodelet; - private WorkingMemory workingMemory; private String id; @@ -114,6 +102,28 @@ public class MecaMind extends Mind { public MecaMind() { setId(UUID.randomUUID().toString()); setWorkingMemory(new WorkingMemory(getId())); + createCodeletGroup("Sensory"); + createCodeletGroup("Motor"); + createCodeletGroup("Perception"); + createCodeletGroup("Activity"); + createCodeletGroup("Motivational"); + createCodeletGroup("Behavioral"); + createCodeletGroup("ActivityTracking"); + createCodeletGroup("Attention"); + createCodeletGroup("Planning"); + createCodeletGroup("Goal"); + createMemoryGroup("Sensors"); + createMemoryGroup("Actuators"); + createMemoryGroup("Percepts"); + createMemoryGroup("Drives"); + createMemoryGroup("Plans"); + createMemoryGroup("Goal"); + createMemoryGroup("Attention"); + createMemoryGroup("Planning"); + createMemoryGroup("Working"); + for (String s : getWorkingMemory().getInternalMemoryNames()) { + registerMemory(getWorkingMemory().getInternalMemory(s),"Working"); + } } /** @@ -125,6 +135,29 @@ public MecaMind() { public MecaMind(String id) { setId(id); setWorkingMemory(new WorkingMemory(getId())); + createCodeletGroup("Sensory"); + createCodeletGroup("Motor"); + createCodeletGroup("Perception"); + createCodeletGroup("Activity"); + createCodeletGroup("Motivational"); + createCodeletGroup("Behavioral"); + createCodeletGroup("ActivityTracking"); + createCodeletGroup("Attention"); + createCodeletGroup("Planning"); + createCodeletGroup("Goal"); + createCodeletGroup("Consciousness"); + createMemoryGroup("Sensors"); + createMemoryGroup("Actuators"); + createMemoryGroup("Percepts"); + createMemoryGroup("Drives"); + createMemoryGroup("Plans"); + createMemoryGroup("Goal"); + createMemoryGroup("Attention"); + createMemoryGroup("Planning"); + createMemoryGroup("Working"); + for (String s : getWorkingMemory().getInternalMemoryNames()) { + registerMemory(getWorkingMemory().getInternalMemory(s),"Working"); + } } /** @@ -137,63 +170,48 @@ public MecaMind(String id) { * This method must be called before running the MECA Agent. */ public void mountMecaMind() { - mountSensoryCodelets(); - mountPerceptualCodelets(); - mountMotorCodelets(); - mountAttentionCodelets(); - mountWorkingMemory(); - - mountSoarCodelet(); - + mountPlanningCodelet(); mountMotivationalCodelets(); - mountActionSequencePlanMemory(); - mountBehaviorCodelets(); - - mountActionFromPlanningCodelets(); - - mountActionFromPerceptionCodelets(); - + mountActivityTrackingCodelet(); + mountActivityCodelets(); + mountGoalCodelets(); + mountConsciousnessCodelet(); mountModules(); - + mountMemoryGroups(); } private void mountActionSequencePlanMemory() { - actionSequencePlanMemoryContainer = createMemoryContainer(ACTION_SEQUENCE_PLAN_ID); - actionSequencePlanRequestMemoryContainer = createMemoryContainer(ACTION_SEQUENCE_PLAN_REQUEST_ID); - } + + + private void mountMemoryGroups() { + Iterator it = memoryGroups.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry pair = (Map.Entry)it.next(); + registerMemory((String)pair.getKey(),(String)pair.getValue() ); + it.remove(); // avoids a ConcurrentModificationException + } + } private void mountModules() { - - if (getMotivationalCodelets() != null) { - if (getMotivationalCodelets().size() > 0) { - List mtcodelets = getMotivationalCodelets(); - getMotivationalSubsystemModule() - .setMotivationalCodelets((List) mtcodelets); - } - - } - - if (getSoarCodelet() != null) { - getPlansSubsystemModule().setjSoarCodelet(getSoarCodelet()); + if (getPlanningCodelet() != null && getPlanningCodelet() instanceof SoarCodelet) { + getPlansSubsystemModule().setjSoarCodelet((SoarCodelet) getPlanningCodelet()); } - } private void mountPerceptualCodelets() { if (perceptualCodelets != null) { for (PerceptualCodelet perceptualCodelet : perceptualCodelets) { if (perceptualCodelet != null && perceptualCodelet.getId() != null) { - insertCodelet(perceptualCodelet); /* * Inputs @@ -204,8 +222,7 @@ private void mountPerceptualCodelets() { ArrayList sensoryCodeletsIds = perceptualCodelet.getSensoryCodeletsIds(); if (sensoryCodeletsIds != null) { for (String sensoryCodeletId : sensoryCodeletsIds) { - if (sensoryCodeletId != null - && sensoryCodeletId.equalsIgnoreCase(sensoryCodelet.getId())) { + if (sensoryCodeletId != null && sensoryCodeletId.equalsIgnoreCase(sensoryCodelet.getId())) { perceptualCodelet.addInputs(sensoryCodelet.getOutputs()); } } @@ -218,7 +235,6 @@ private void mountPerceptualCodelets() { */ MemoryObject perceptualMemory = createMemoryObject(perceptualCodelet.getId()); perceptualCodelet.addOutput(perceptualMemory); - } } } @@ -226,17 +242,14 @@ private void mountPerceptualCodelets() { private void mountSensoryCodelets() { if (sensoryCodelets != null) { - for (ISensoryCodelet sensoryCodelet : sensoryCodelets) { if (sensoryCodelet != null && sensoryCodelet.getId() != null) { - insertCodelet((Codelet) sensoryCodelet); /* * Output */ MemoryObject sensoryMemory = createMemoryObject(sensoryCodelet.getId()); sensoryCodelet.addOutput(sensoryMemory); - } } } @@ -245,7 +258,6 @@ private void mountSensoryCodelets() { private void mountMotivationalCodelets() { if (getMotivationalCodelets() != null) { for (MotivationalCodelet motivationalCodelet : getMotivationalCodelets()) { - /* * Input Sensors */ @@ -256,45 +268,75 @@ private void mountMotivationalCodelets() { for (ISensoryCodelet sensoryCodelet : sensoryCodelets) { if (sensoryCodelet.getId().equals(sensoryId)) { motivationalCodelet.addInputs(sensoryCodelet.getOutputs()); - } } } } } - /* * Input Drives */ - if (motivationalCodelet.getMotivationalCodeletsIds() != null) { HashMap motivationalCodeletsIds = motivationalCodelet.getMotivationalCodeletsIds(); for (Map.Entry motivationalCodeletId : motivationalCodeletsIds.entrySet()) { - for (MotivationalCodelet motivationalCodeletInput : getMotivationalCodelets()) { if (motivationalCodeletInput.getId().equals(motivationalCodeletId.getKey())) { - HashMap driveRelevance = new HashMap<>(); driveRelevance.put(motivationalCodeletInput.getOutputDriveMO(), motivationalCodeletId.getValue()); - motivationalCodelet.addInput(this.createMemoryObject( motivationalCodeletInput.getOutputDriveMO().getName(), driveRelevance)); } } } } - /* * Output Drives */ - MemoryObject outputDrive = this.createMemoryObject(motivationalCodelet.getId() + "_DRIVE_MO"); + MemoryObject outputDrive = this.createMemoryObject(motivationalCodelet.getId() + "Drive"); motivationalCodelet.addOutput(outputDrive); - insertCodelet(motivationalCodelet); } } } + + private void mountActivityTrackingCodelet() { + + if (perceptualCodelets != null) { + ArrayList perceptualIds = new ArrayList<>(); + for (PerceptualCodelet perception : perceptualCodelets) + perceptualIds.add(perception.getId()); + activityTrackingCodelet = new ActivityTrackingCodelet("ActivityTracking", perceptualIds); + registerCodelet(activityTrackingCodelet, "ActivityTracking"); + registerMemory(ACTION_SEQUENCE_PLAN_ID,"Plans"); + registerMemory(ACTION_SEQUENCE_PLAN_REQUEST_ID,"Plans"); + } + + if (activityTrackingCodelet != null && activityTrackingCodelet.getId() != null + && activityTrackingCodelet.getPerceptualCodeletsIds() != null) { + /* + * Inputs + */ + activityTrackingCodelet.addInput(actionSequencePlanMemoryContainer); + + if(perceptualCodelets != null) { + for(PerceptualCodelet perceptualCodelet : perceptualCodelets) { + if(perceptualCodelet != null && perceptualCodelet.getId() != null) { + ArrayList perceptualCodeletsIds = activityTrackingCodelet.getPerceptualCodeletsIds(); + if(perceptualCodeletsIds != null) { + for(String perceptualCodeletId : perceptualCodeletsIds) { + if(perceptualCodeletId != null && perceptualCodelet.getId().equalsIgnoreCase(perceptualCodeletId)) { + activityTrackingCodelet.addInputs(perceptualCodelet.getOutputs()); + } + } + } + } + } + } + insertCodelet(activityTrackingCodelet); + } + + } private void mountBehaviorCodelets() { if (behaviorCodelets != null) { @@ -302,25 +344,21 @@ private void mountBehaviorCodelets() { if (behaviorCodelet != null && behaviorCodelet.getId() != null && behaviorCodelet.getMotivationalCodeletsIds() != null && behaviorCodelet.getPerceptualCodeletsIds() != null) { - /* * Outputs */ behaviorCodelet.addOutput(actionSequencePlanMemoryContainer); behaviorCodelet.addOutput(actionSequencePlanRequestMemoryContainer); - /* * Inputs */ if (motivationalCodelets != null) { for (MotivationalCodelet motivationalCodelet : motivationalCodelets) { if (motivationalCodelet != null && motivationalCodelet.getId() != null) { - ArrayList motivationalCodeletsIds = behaviorCodelet - .getMotivationalCodeletsIds(); + ArrayList motivationalCodeletsIds = behaviorCodelet.getMotivationalCodeletsIds(); if (motivationalCodeletsIds != null) { for (String motivationalCodeletId : motivationalCodeletsIds) { - if (motivationalCodeletId != null && motivationalCodelet.getId() - .equalsIgnoreCase(motivationalCodeletId)) { + if (motivationalCodeletId != null && motivationalCodelet.getId().equalsIgnoreCase(motivationalCodeletId)) { behaviorCodelet.addInputs(motivationalCodelet.getOutputs()); } } @@ -328,7 +366,6 @@ private void mountBehaviorCodelets() { } } } - if(perceptualCodelets != null) { for(PerceptualCodelet perceptualCodelet : perceptualCodelets) { if(perceptualCodelet != null && perceptualCodelet.getId() != null) { @@ -343,39 +380,33 @@ private void mountBehaviorCodelets() { } } } - - if (soarCodelet != null && soarCodelet.getId() != null && behaviorCodelet.getSoarCodeletId() != null) { - if (soarCodelet.getId().equalsIgnoreCase(behaviorCodelet.getSoarCodeletId())) { - behaviorCodelet.addBroadcasts(soarCodelet.getOutputs()); + if (planningCodelet != null && planningCodelet.getId() != null && behaviorCodelet.getPlanningCodeletId() != null) { + if (planningCodelet.getId().equalsIgnoreCase(behaviorCodelet.getPlanningCodeletId())) { + behaviorCodelet.addBroadcasts(planningCodelet.getOutputs()); } - } - insertCodelet(behaviorCodelet); - } } } } - - private void mountActionFromPerceptionCodelets() { - if (actionFromPerceptionCodelets != null) { - for (ActionFromPerceptionCodelet actionCodelet : actionFromPerceptionCodelets) { - if (actionCodelet != null && actionCodelet.getId() != null - && actionCodelet.getPerceptualCodeletsIds() != null - && actionCodelet.getMotivationalCodeletsIds() != null - && actionCodelet.getMotorCodeletId() != null) { - - insertCodelet(actionCodelet); + + private void mountActivityCodelets() { + if (activityCodelets != null) { + for (ActivityCodelet activityCodelet : activityCodelets) { + if (activityCodelet != null && activityCodelet.getId() != null + && activityCodelet.getPerceptualCodeletsIds() != null + && activityCodelet.getMotivationalCodeletsIds() != null + && activityCodelet.getMotorCodeletId() != null) { + insertCodelet(activityCodelet); /* * Outputs */ if (motorCodelets != null) { for (IMotorCodelet motorCodelet : motorCodelets) { if (motorCodelet != null && motorCodelet.getId() != null) { - if (motorCodelet.getId() - .equalsIgnoreCase(actionCodelet.getMotorCodeletId())) { - actionCodelet.addOutputs(motorCodelet.getInputs()); + if (motorCodelet.getId().equalsIgnoreCase(activityCodelet.getMotorCodeletId())) { + activityCodelet.addOutputs(motorCodelet.getInputs()); } } } @@ -383,102 +414,40 @@ private void mountActionFromPerceptionCodelets() { /* * Inputs */ - if (motivationalCodelets != null) { for (MotivationalCodelet motivationalCodelet : motivationalCodelets) { if (motivationalCodelet != null && motivationalCodelet.getId() != null) { - ArrayList motivationalCodeletsIds = actionCodelet - .getMotivationalCodeletsIds(); + ArrayList motivationalCodeletsIds = activityCodelet.getMotivationalCodeletsIds(); if (motivationalCodeletsIds != null) { for (String motivationalCodeletId : motivationalCodeletsIds) { - if (motivationalCodeletId != null && motivationalCodelet.getId() - .equalsIgnoreCase(motivationalCodeletId)) { - actionCodelet.addInputs(motivationalCodelet.getOutputs()); + if (motivationalCodeletId != null && motivationalCodelet.getId().equalsIgnoreCase(motivationalCodeletId)) { + activityCodelet.addInputs(motivationalCodelet.getOutputs()); } } } } } } - - if (perceptualCodelets != null) { - for (PerceptualCodelet perceptualCodelet : perceptualCodelets) { - if (perceptualCodelet != null && perceptualCodelet.getId() != null) { - ArrayList perceptualCodeletsIds = actionCodelet - .getPerceptualCodeletsIds(); - if (perceptualCodeletsIds != null) { - for (String perceptualCodeletId : perceptualCodeletsIds) { - if (perceptualCodeletId != null - && perceptualCodelet.getId().equalsIgnoreCase(perceptualCodeletId)) { - actionCodelet.addInputs(perceptualCodelet.getOutputs()); - } - } - } - } - } - } - - if (soarCodelet != null && soarCodelet.getId() != null && actionCodelet.getSoarCodeletId() != null) { - if (soarCodelet.getId().equalsIgnoreCase(actionCodelet.getSoarCodeletId())) { - actionCodelet.addBroadcasts(soarCodelet.getOutputs()); - } - - } - } - } - } - - } - - private void mountActionFromPlanningCodelets() { - if (actionFromPlanningCodelets != null) { - for (ActionFromPlanningCodelet actionCodelet : actionFromPlanningCodelets) { - if (actionCodelet != null && actionCodelet.getId() != null - && actionCodelet.getPerceptualCodeletsIds() != null - && actionCodelet.getMotorCodeletId() != null) { - - insertCodelet(actionCodelet); - /* - * Outputs - */ - if (motorCodelets != null) { - for (IMotorCodelet motorCodelet : motorCodelets) { - if (motorCodelet != null && motorCodelet.getId() != null) { - if (motorCodelet.getId() - .equalsIgnoreCase(actionCodelet.getMotorCodeletId())) { - actionCodelet.addOutputs(motorCodelet.getInputs()); - } - } - } - } - /* - * Inputs - */ if (perceptualCodelets != null) { for (PerceptualCodelet perceptualCodelet : perceptualCodelets) { if (perceptualCodelet != null && perceptualCodelet.getId() != null) { - ArrayList perceptualCodeletsIds = actionCodelet - .getPerceptualCodeletsIds(); + ArrayList perceptualCodeletsIds = activityCodelet.getPerceptualCodeletsIds(); if (perceptualCodeletsIds != null) { for (String perceptualCodeletId : perceptualCodeletsIds) { - if (perceptualCodeletId != null - && perceptualCodelet.getId().equalsIgnoreCase(perceptualCodeletId)) { - actionCodelet.addInputs(perceptualCodelet.getOutputs()); + if (perceptualCodeletId != null && perceptualCodelet.getId().equalsIgnoreCase(perceptualCodeletId)) { + activityCodelet.addInputs(perceptualCodelet.getOutputs()); } } } } } } - - if (soarCodelet != null && soarCodelet.getId() != null && actionCodelet.getSoarCodeletId() != null) { - if (soarCodelet.getId().equalsIgnoreCase(actionCodelet.getSoarCodeletId())) { - actionCodelet.addBroadcasts(soarCodelet.getOutputs()); + if (planningCodelet != null && planningCodelet.getId() != null && activityCodelet.getPlanningCodeletId() != null) { + if (planningCodelet.getId().equalsIgnoreCase(activityCodelet.getPlanningCodeletId())) { + activityCodelet.addBroadcasts(planningCodelet.getOutputs()); } - } - - actionCodelet.addInput(actionSequencePlanMemoryContainer); + activityCodelet.addInput(actionSequencePlanMemoryContainer); } } } @@ -501,14 +470,12 @@ private void mountMotorCodelets() { private void mountAttentionCodelets() { if (attentionCodeletSystem1 != null) { - /* * Inputs */ if (perceptualCodelets != null) { for (String inputPerceptualId : attentionCodeletSystem1.getPerceptualCodeletsIds()) { for (PerceptualCodelet perceptualCodelet : perceptualCodelets) { - if (inputPerceptualId.equals(perceptualCodelet.getId())) { attentionCodeletSystem1.addInputs(perceptualCodelet.getOutputs()); } @@ -518,31 +485,78 @@ private void mountAttentionCodelets() { /* * Outputs */ - Memory attentionMemoryOutput = createMemoryObject(attentionCodeletSystem1.getId()); + //Memory attentionMemoryOutput = createMemoryObject(attentionCodeletSystem1.getId()); + MemoryContainer currentperception = (MemoryContainer) workingMemory.getInternalMemory("CurrentPerceptionMemory"); + currentperception.setI(null,0d,attentionCodeletSystem1.getId()); + Memory attentionMemoryOutput = currentperception.getInternalMemory(attentionCodeletSystem1.getId()); attentionCodeletSystem1.addOutput(attentionMemoryOutput); attentionCodeletSystem1.setOutputFilteredPerceptsMO(attentionMemoryOutput); insertCodelet(attentionCodeletSystem1); } } - private void mountSoarCodelet() { - if (soarCodelet != null) { - soarCodelet.addInput(createMemoryObject(WorkingMemory.WORKING_MEMORY_INPUT, getWorkingMemory())); - soarCodelet.addOutput(createMemoryObject(soarCodelet.getId())); - insertCodelet(soarCodelet); + private void mountPlanningCodelet() { + if (planningCodelet != null) { + planningCodelet.addInput(createMemoryObject(WorkingMemory.WORKING_MEMORY_INPUT, getWorkingMemory())); + //planningCodelet.addOutput(createMemoryObject(planningCodelet.getId())); + planningCodelet.addOutput(getWorkingMemory().getInternalMemory("PlansMemory")); + insertCodelet((Codelet) planningCodelet); } - } private void mountWorkingMemory() { if (getWorkingMemory() != null) { - if (attentionCodeletSystem1 != null) { - getWorkingMemory().setCurrentPerceptionMemory(attentionCodeletSystem1.getOutputFilteredPerceptsMO()); + //getWorkingMemory().setCurrentPerceptionMemory(attentionCodeletSystem1.getOutputFilteredPerceptsMO()); + getWorkingMemory().setInternalMemory("CurrentPerceptionMemory",attentionCodeletSystem1.getOutputFilteredPerceptsMO()); } - } } + + private void mountGoalCodelets() { + if (getGoalCodelets() != null) { + if (goalCodelets != null) { + // Create the Goal Memory Container + //MemoryContainer goalMemoryContainer = createMemoryContainer("OUTPUT_GOAL_MEMORY"); + //MemoryContainer goalMemoryContainer = createMemoryContainer("Goals"); + //registerMemory(goalMemoryContainer,"Goal"); + MemoryContainer goalMemoryContainer = (MemoryContainer) workingMemory.getInternalMemory("GoalsMemory"); + //MemoryObject wmem = createMemoryObject("INPUT_HYPOTHETICAL_SITUATIONS_MEMORY"); + //registerMemory(wmem,"Goal"); + //wmem.setI(workingMemory.getCurrentPerceptionMemory().getI()); + for (GoalCodelet gc : goalCodelets) { + // Insert the Goal Codelet in the Coderack + insertCodelet(gc); + // Mount internal variables + gc.setActionSequencePlanRequestMemoryContainer(actionSequencePlanRequestMemoryContainer); + gc.setWm(workingMemory); + // Mount input + //gc.setInputHypotheticalSituationsMO(workingMemory.getCurrentPerceptionMemory()); + gc.setInputHypotheticalSituationsMO(workingMemory.getInternalMemory("CurrentPerceptionMemory")); + + //registerMemory(workingMemory.getCurrentPerceptionMemory(),"Goal"); + registerMemory(workingMemory.getInternalMemory("CurrentPerceptionMemory"),"Goal"); + gc.addInput(actionSequencePlanRequestMemoryContainer); + //gc.addInput(workingMemory.getCurrentPerceptionMemory()); + gc.addInput(workingMemory.getInternalMemory("CurrentPerceptionMemory")); + //gc.addInput(wmem); + // Mount output + + gc.setGoalMO(goalMemoryContainer); + goalMemoryContainer.setI(null,0.0,gc.getId()); + gc.addOutput(goalMemoryContainer); + //gc.addOutput(wmem); + } + } + } + } + + private void mountConsciousnessCodelet() { + if (consciousnessCodelet != null) { + registerCodelet(consciousnessCodelet,"Consciousness"); + insertCodelet(consciousnessCodelet); + } + } /** * Sets the Sensory Codelets. @@ -675,21 +689,24 @@ public void setConsciousnessCodelet(ConsciousnessCodelet consciousnessCodelet) { /** * Sets the Soar Codelet. * + * @deprecated instead, add the SoarCodelet using the setPlannningCodelet method. + * The SoarCodelet implements the IPlanningCodelet interface * @param soarCodelet * the soarCodelet to set */ + @Deprecated public void setSoarCodelet(SoarCodelet soarCodelet) { - this.soarCodelet = soarCodelet; + this.planningCodelet = soarCodelet; } /** * Sets the Goal Codelet. * - * @param goalCodelet - * the goalCodelet to set + * @param goalCodelets + * the set of goalCodelets to be mounted */ - public void setGoalCodelet(GoalCodelet goalCodelet) { - this.goalCodelet = goalCodelet; + public void setGoalCodelets(List goalCodelets) { + this.goalCodelets = goalCodelets; } /** @@ -702,27 +719,13 @@ public void setAppraisalCodelet(AppraisalCodelet appraisalCodelet) { this.appraisalCodelet = appraisalCodelet; } - /** - * @param actionFromPlanningCodelets the actionFromPlanningCodelets to set - */ - public void setActionFromPlanningCodelets(List actionFromPlanningCodelets) { - this.actionFromPlanningCodelets = actionFromPlanningCodelets; - } - - /** - * @param actionFromPerceptionCodelets the actionFromPerceptionCodelets to set - */ - public void setActionFromPerceptionCodelets(List actionFromPerceptionCodelets) { - this.actionFromPerceptionCodelets = actionFromPerceptionCodelets; - } - /** * @param behaviorCodelets the behaviorCodelets to set */ public void setBehaviorCodelets(List behaviorCodelets) { this.behaviorCodelets = behaviorCodelets; } - + /** * @param sensoryCodelets the sensoryCodelets to set */ @@ -788,8 +791,8 @@ public List getEmotionalCodelets() { * * @return the Goal Codelet. */ - public GoalCodelet getGoalCodelet() { - return goalCodelet; + public List getGoalCodelets() { + return goalCodelets; } /** @@ -902,12 +905,12 @@ public ConsciousnessCodelet getConsciousnessCodelet() { } /** - * Gets the Soar Codelet. + * Gets the Planning Codelet. * - * @return the soarCodelet. + * @return the planningCodelet. */ - public SoarCodelet getSoarCodelet() { - return soarCodelet; + public IPlanningCodelet getPlanningCodelet() { + return planningCodelet; } /** @@ -918,16 +921,45 @@ public List getBehaviorCodelets() { } /** - * @return the actionFromPlanningCodelets + * @return the activityTrackingCodelet + */ + public ActivityTrackingCodelet getActivityTrackingCodelet() { + return activityTrackingCodelet; + } + + /** + * @param activityTrackingCodelet the activityTrackingCodelet to set + */ + public void setActivityTrackingCodelet(ActivityTrackingCodelet activityTrackingCodelet) { + this.activityTrackingCodelet = activityTrackingCodelet; + } + + /** + * @return the activityCodelets + */ + public List getActivityCodelets() { + return activityCodelets; + } + + public void pregisterMemory(String memoryName, String memoryGroup) { + memoryGroups.put(memoryName, memoryGroup); + } + + /** + * @param activityCodelets the activityCodelets to set */ - public List getActionFromPlanningCodelets() { - return actionFromPlanningCodelets; + public void setActivityCodelets(List activityCodelets) { + this.activityCodelets = activityCodelets; } /** - * @return the actionFromPerceptionCodelets + * @param planningCodelet the planningCodelet to set */ - public List getActionFromPerceptionCodelets() { - return actionFromPerceptionCodelets; + public void setPlanningCodelet(IPlanningCodelet planningCodelet) { + this.planningCodelet = planningCodelet; } + + public PlansSubsystemModule getPlansSubsystemModule() { + return plansSubsystemModule; + } } diff --git a/src/main/java/br/unicamp/meca/models/ActionSequencePlan.java b/src/main/java/br/unicamp/meca/models/ActionSequencePlan.java index 4449b7a..77ea078 100644 --- a/src/main/java/br/unicamp/meca/models/ActionSequencePlan.java +++ b/src/main/java/br/unicamp/meca/models/ActionSequencePlan.java @@ -6,13 +6,13 @@ * http://www.gnu.org/licenses/lgpl.html * * * * Contributors: * - * R. R. Gudwin, A. L. O. Paraense, E. Froes, W. Gibaut, * - * and K. Raizer. * + * R. R. Gudwin, A. L. O. Paraense, E. Froes, W. Gibaut, * + * and K. Raizer. * * * ******************************************************************************/ package br.unicamp.meca.models; -import br.unicamp.meca.system1.codelets.ActionFromPlanningCodelet; +import br.unicamp.meca.system1.codelets.ActivityCodelet; /** * This class represents the MECA Action Sequence Plan. This Action Sequence Plan @@ -22,12 +22,12 @@ * them is the current action that should be undertaken in the plan. * * @author A. L. O. Paraense - * @see ActionFromPlanningCodelet + * @see ActivityCodelet * */ public class ActionSequencePlan { - private String[] actionIdSequence; + private ActionStep[] actionIdSequence; private int currentActionIdIndex = 0; @@ -39,31 +39,47 @@ public class ActionSequencePlan { * the list of ids of ActionFromPlanningCodelet(s) to be executed * in sequence following this plan. */ - public ActionSequencePlan(String[] actionIdSequence) { + public ActionSequencePlan(ActionStep[] actionIdSequence) { this.actionIdSequence = actionIdSequence; } /** - * Returns the id of the current ActionFromPlanningCodelet to be undertaken in the plan. + * Returns the ActionStep of the current ActionFromPlanningCodelet to be undertaken in the plan. * - * @return + * @return the current ActionStep */ - public String getCurrentActionId() { - return actionIdSequence[currentActionIdIndex]; + public ActionStep getCurrentActionStep() { + if (actionIdSequence != null && currentActionIdIndex < actionIdSequence.length) + return actionIdSequence[currentActionIdIndex]; + else return(null); + } + + /** + * Returns the ActionStep of the last ActionFromPlanningCodelet to be undertaken in the plan, or null if it is the first step. + * + * @return the last ActionStep + */ + public ActionStep getLastExecutedActionStep() { + if (currentActionIdIndex == 0) return(actionIdSequence[actionIdSequence.length-1]); + else return actionIdSequence[currentActionIdIndex-1]; } /** + * get the array of ActionSteps which are related to the ActionSequencePlan + * * @return the actionIdSequence */ - public String[] getActionIdSequence() { + public ActionStep[] getActionStepSequence() { return actionIdSequence; } /** - * @param actionIdSequence the actionIdSequence to set + * Forces a new actionStepSequence + * + * @param actionStepSequence the actionIdSequence to set */ - public void setActionIdSequence(String[] actionIdSequence) { - this.actionIdSequence = actionIdSequence; + public void setActionStepSequence(ActionStep[] actionStepSequence) { + this.actionIdSequence = actionStepSequence; } /** @@ -79,4 +95,36 @@ public int getCurrentActionIdIndex() { public void setCurrentActionIdIndex(int currentActionIdIndex) { this.currentActionIdIndex = currentActionIdIndex; } + + /** + * Go to next action. If the action is the last in the plan, go to the first action + */ + public void gotoNextAction() { + actionIdSequence[currentActionIdIndex].executed = true; + if (currentActionIdIndex < actionIdSequence.length-1) + currentActionIdIndex++; + else currentActionIdIndex = 0; + } + + public String toString() { + String output = "{"; + int i=0; + for (ActionStep a : actionIdSequence) { + output += a.toString(); + i++; + if (i < actionIdSequence.length) + output += ", "; + } + output += "}"; + return(output); + } + + /** + * Reset the plan. Set all the action steps executed flag to false. + */ + public void resetPlan() { + for (ActionStep as : actionIdSequence) { + as.executed = false; + } + } } diff --git a/src/main/java/br/unicamp/meca/models/ActionStep.java b/src/main/java/br/unicamp/meca/models/ActionStep.java new file mode 100644 index 0000000..d02b682 --- /dev/null +++ b/src/main/java/br/unicamp/meca/models/ActionStep.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2019 DCA-FEEC-UNICAMP and Ericsson Research * + * All rights reserved. This program and the accompanying materials * + * are made available under the terms of the GNU Lesser Public License v3 * + * which accompanies this distribution, and is available at * + * http://www.gnu.org/licenses/lgpl.html * + * * + * Contributors: * + * R. R. Gudwin, A. L. O. Paraense, E. Froes, W. Gibaut, * + * and K. Raizer. * + * * + ******************************************************************************/ +package br.unicamp.meca.models; + +import br.unicamp.cst.core.entities.Memory; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * + * @author rgudwin + */ +public abstract class ActionStep { + String actionId; + Map parameters; + public boolean needsConclusion = false; + public boolean executed = false; + + public ActionStep() { + actionId = ""; + parameters = new HashMap(); + } + + public ActionStep(String acId) { + this(); + actionId = acId; + } + + public ActionStep(String acId, Map par) { + this(); + actionId = acId; + parameters = par; + } + + public String getActionId() { + return actionId; + } + + public void setActionId(String id) { + actionId = id; + } + + public Object getParameter(String paramId) { + if (parameters == null) System.out.println("Parameters is null"); + return(parameters.get(paramId)); + } + + public void setParameter(String paramId, Object param) { + if (parameters.get(paramId) == null) + parameters.put(paramId, param); + else + parameters.replace(paramId, param); + } + + public Map getParameters() { + return(parameters); + } + + public void setParameters(Map par) { + parameters = par; + } + + public int getNumberOfParameters() { + if(parameters == null) return(-1); + return(parameters.size()); + } + + public void unsetParameter(String param) { + parameters.remove(param); + } + + public String toString() { + return(actionId); + } + + public abstract boolean stopCondition(List perception); + +} diff --git a/src/main/java/br/unicamp/meca/system1/codelets/ActionFromPerceptionCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/ActionFromPerceptionCodelet.java deleted file mode 100644 index 2223336..0000000 --- a/src/main/java/br/unicamp/meca/system1/codelets/ActionFromPerceptionCodelet.java +++ /dev/null @@ -1,261 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 DCA-FEEC-UNICAMP and Ericsson Research * - * All rights reserved. This program and the accompanying materials * - * are made available under the terms of the GNU Lesser Public License v3 * - * which accompanies this distribution, and is available at * - * http://www.gnu.org/licenses/lgpl.html * - * * - * Contributors: * - * R. R. Gudwin, A. L. O. Paraense, E. Froes, W. Gibaut, * - * and K. Raizer. * - * * - ******************************************************************************/ -package br.unicamp.meca.system1.codelets; - -import java.util.ArrayList; - -import br.unicamp.cst.core.entities.Codelet; -import br.unicamp.cst.core.entities.Memory; -import br.unicamp.cst.core.exceptions.CodeletActivationBoundsException; - -/** - * This class represents the MECA Action From Perception Codelet. This Action From Perception - * Codelet allows inputs from one or more of the PerceptualCodelets and - * inputs from one or more of the MotivationalCodelets. It outputs - * necessarily to a MotorCodelet. As the name suggests, the idea behind this - * action from perception codelet is to provide an action as a purely reaction to the environment in System 1. - *

- * Usually, Action From Perception Codelets are application-specific, and the MECA - * software implementation just provides basic template class, which is a - * wrapper to CST's {@link Codelet}, to be reused while building an application - * using MECA. - * - * @author A. L. O. Paraense - * - */ -public abstract class ActionFromPerceptionCodelet extends Codelet { - - protected String id; - - protected ArrayList perceptualCodeletsIds; - protected ArrayList perceptualMemories; - - protected ArrayList motivationalCodeletsIds; - protected ArrayList driveMemories; - - protected String soarCodeletId; - protected Memory broadcastMemory; - - protected String motorCodeletId; - protected Memory motorMemory; - - /** - * - * Creates a MECA Action From Perception Codelet. - * - * @param id - * the id of the Action From Perception Codelet. Must be unique per - * Action From Perception Codelet. - * @param perceptualCodeletsIds - * the list of ids of the Perceptual Codelets whose outputs will - * be read by this Action From Perception Codelet. - * @param motivationalCodeletsIds - * the list of ids of the Motivational Codelets whose outputs will - * be read by this Action From Perception Codelet. - * @param motorCodeletId - * the id of the Motor Codelet which will read the outputs of - * this Action From Perception Codelet. - * @param soarCodeletId - * the id of the Soar Codelet whose outputs will be read by this - * Action From Perception Codelet. - */ - public ActionFromPerceptionCodelet(String id, ArrayList perceptualCodeletsIds, ArrayList motivationalCodeletsIds, String motorCodeletId, - String soarCodeletId) { - super(); - setName(id); - this.id = id; - this.motorCodeletId = motorCodeletId; - this.perceptualCodeletsIds = perceptualCodeletsIds; - this.soarCodeletId = soarCodeletId; - this.motivationalCodeletsIds = motivationalCodeletsIds; - } - - @Override - public void accessMemoryObjects() { - - int index=0; - - if(perceptualMemories == null || perceptualMemories.size() == 0) { - - perceptualMemories = new ArrayList<>(); - - if(perceptualCodeletsIds != null) { - - for(String perceptualCodeletId : perceptualCodeletsIds) { - Memory perceptualMemory = this.getInput(perceptualCodeletId, index); - perceptualMemories.add(perceptualMemory); - } - } - } - - if(driveMemories == null || driveMemories.size() == 0) - { - driveMemories = new ArrayList<>(); - - if(motivationalCodeletsIds!=null){ - - for(String motivationalCodeletsId : motivationalCodeletsIds) - { - Memory inputDrive = this.getInput(motivationalCodeletsId + "_DRIVE_MO"); - driveMemories.add(inputDrive); - } - } - } - - if(broadcastMemory == null) { - broadcastMemory = this.getBroadcast(soarCodeletId, index); - } - - - if(motorMemory==null && motorCodeletId!=null) - motorMemory = this.getOutput(motorCodeletId, index); - } - - @Override - public void calculateActivation() { - - double activation = 0; - - if (driveMemories!=null && driveMemories.size() > 0){ - - for (Memory driveMO: driveMemories) { - activation += driveMO.getEvaluation(); - } - - activation /= driveMemories.size(); - - } - - try { - - if(activation<0.0d) - activation=0.0d; - - if(activation>1.0d) - activation=1.0d; - - setActivation(activation); - - } catch (CodeletActivationBoundsException e) { - e.printStackTrace(); - } - - } - - @Override - public void proc() { - - proc(perceptualMemories, broadcastMemory, motorMemory); - } - - /** - * Main method of the Action From Perception Codelet called passing all input and output necessary memories. - * - * @param perceptualMemories - * the input memories coming from perception. - * @param broadcastMemory - * the input memory coming from the conscious planner broadcast. - * @param motorMemory - * the output motor memory. - */ - public abstract void proc(ArrayList perceptualMemories, Memory broadcastMemory, Memory motorMemory); - - /** - * Returns the id of the Soar Codelet whose outputs will be read by this - * Action From Perception Codelet. - * - * @return the soarCodeletId - */ - public String getSoarCodeletId() { - return soarCodeletId; - } - - /** - * Sets the id of the Soar Codelet whose outputs will be read by this - * Action From Perception Codelet. - * - * @param soarCodeletId - * the soarCodeletId to set - */ - public void setSoarCodeletId(String soarCodeletId) { - this.soarCodeletId = soarCodeletId; - } - - /** - * Returns the list of the Perceptual Codelet's ids whose outputs will be - * read by this Action From Perception Codelet. - * - * @return the perceptualCodeletsIds - */ - public ArrayList getPerceptualCodeletsIds() { - return perceptualCodeletsIds; - } - - /** - * Sets the list of the Perceptual Codelet's ids whose outputs will be read - * by this Action From Perception Codelet. - * - * @param perceptualCodeletsIds - * the perceptualCodeletsIds to set - */ - public void setPerceptualCodeletsIds(ArrayList perceptualCodeletsIds) { - this.perceptualCodeletsIds = perceptualCodeletsIds; - } - - /** - * Returns the id of this Action From Perception Codelet. - * - * @return the id - */ - public String getId() { - return id; - } - - /** - * Sets the id of this Action From Perception Codelet. - * - * @param id - * the id to set - */ - public void setId(String id) { - this.id = id; - } - - /** - * Returns the id of the Motor Codelet which will read the outputs of this - * Action From Perception Codelet. - * - * @return the motorCodeletId - */ - public String getMotorCodeletId() { - return motorCodeletId; - } - - /** - * Sets the id of the Motor Codelet which will read the outputs of this - * Action From Perception Codelet. - * - * @param motorCodeletId - * the motorCodeletId to set - */ - public void setMotorCodeletId(String motorCodeletId) { - this.motorCodeletId = motorCodeletId; - } - - /** - * @return the motivationalCodeletsIds - */ - public ArrayList getMotivationalCodeletsIds() { - return motivationalCodeletsIds; - } -} diff --git a/src/main/java/br/unicamp/meca/system1/codelets/ActionFromPlanningCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/ActionFromPlanningCodelet.java deleted file mode 100644 index 242ce85..0000000 --- a/src/main/java/br/unicamp/meca/system1/codelets/ActionFromPlanningCodelet.java +++ /dev/null @@ -1,237 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2018 DCA-FEEC-UNICAMP and Ericsson Research * - * All rights reserved. This program and the accompanying materials * - * are made available under the terms of the GNU Lesser Public License v3 * - * which accompanies this distribution, and is available at * - * http://www.gnu.org/licenses/lgpl.html * - * * - * Contributors: * - * R. R. Gudwin, A. L. O. Paraense, E. Froes, W. Gibaut, S. de Paula, * - * E. Castro, V. Figueredo and K. Raizer * - * * - ******************************************************************************/ -package br.unicamp.meca.system1.codelets; - -import java.util.ArrayList; - -import br.unicamp.cst.core.entities.Codelet; -import br.unicamp.cst.core.entities.Memory; -import br.unicamp.cst.core.exceptions.CodeletActivationBoundsException; -import br.unicamp.meca.mind.MecaMind; -import br.unicamp.meca.models.ActionSequencePlan; - -/** - * This class represents the MECA Action From Planning Codelet. This Action From Planning - * Codelet allows inputs from one or more of the PerceptualCodelets and the ActionSequencePlan - * with greatest activation. It outputs - * necessarily to a MotorCodelet. As the name suggests, the idea behind this - * action from planning codelet is to provide an action following a specific plan from the behavior generator in System 1. - *

- * Usually, Action From Planning Codelets are application-specific, and the MECA - * software implementation just provides basic template class, which is a - * wrapper to CST's {@link Codelet}, to be reused while building an application - * using MECA. - * - * @author A. L. O. Paraense - * - */ -public abstract class ActionFromPlanningCodelet extends Codelet { - - protected String id; - - protected ArrayList perceptualCodeletsIds; - protected ArrayList perceptualMemories; - - protected String soarCodeletId; - protected Memory broadcastMemory; - - protected Memory actionSequencePlanMemoryContainer; - - protected String motorCodeletId; - protected Memory motorMemory; - - /** - * Creates a MECA Action From Planning Codelet. - * - * @param id - * the id of the Action From Planning Codelet. Must be unique per - * Reactive Behavioral Codelet. - * @param perceptualCodeletsIds - * the list of ids of the Perceptual Codelets whose outputs will - * be read by this Action From Planning Codelet. - * @param motorCodeletId - * the id of the Motor Codelet which will read the outputs of - * this Action From Planning Codelet. - * @param soarCodeletId - * the id of the Soar Codelet whose outputs will be read by this - * Action From Planning Codelet. - */ - public ActionFromPlanningCodelet(String id, ArrayList perceptualCodeletsIds, String motorCodeletId, - String soarCodeletId) { - super(); - setName(id); - this.id = id; - this.motorCodeletId = motorCodeletId; - this.perceptualCodeletsIds = perceptualCodeletsIds; - this.soarCodeletId = soarCodeletId; - } - - @Override - public void accessMemoryObjects() { - - int index=0; - - if(perceptualMemories == null || perceptualMemories.size() == 0) { - - perceptualMemories = new ArrayList<>(); - - if(perceptualCodeletsIds != null) { - - for(String perceptualCodeletId : perceptualCodeletsIds) { - Memory perceptualMemory = this.getInput(perceptualCodeletId, index); - perceptualMemories.add(perceptualMemory); - } - } - } - - if(broadcastMemory == null) { - broadcastMemory = this.getBroadcast(soarCodeletId, index); - } - - if(actionSequencePlanMemoryContainer == null) - actionSequencePlanMemoryContainer = this.getInput(MecaMind.ACTION_SEQUENCE_PLAN_ID, index); - - if(motorMemory==null && motorCodeletId!=null) - motorMemory = this.getOutput(motorCodeletId, index); - - } - - @Override - public void calculateActivation() { - - try { - if(actionSequencePlanMemoryContainer != null && actionSequencePlanMemoryContainer.getI() != null && actionSequencePlanMemoryContainer.getI() instanceof ActionSequencePlan) { - - ActionSequencePlan actionSequencePlan = (ActionSequencePlan) actionSequencePlanMemoryContainer.getI(); - String currentActionId = actionSequencePlan.getCurrentActionId(); - - if(currentActionId != null && currentActionId.equalsIgnoreCase(id)) { - setActivation(actionSequencePlanMemoryContainer.getEvaluation()); - }else { - setActivation(0.0d); - } - } - - } catch (CodeletActivationBoundsException e) { - e.printStackTrace(); - } - } - - @Override - public void proc() { - - if(actionSequencePlanMemoryContainer != null && actionSequencePlanMemoryContainer.getI() != null && actionSequencePlanMemoryContainer.getI() instanceof ActionSequencePlan) { - - ActionSequencePlan actionSequencePlan = (ActionSequencePlan) actionSequencePlanMemoryContainer.getI(); - String currentActionId = actionSequencePlan.getCurrentActionId(); - - if(currentActionId != null && currentActionId.equalsIgnoreCase(id)) { - proc(perceptualMemories, broadcastMemory, motorMemory); - } - } - } - - /** - * Main method of this Action From Planning Codelet called passing all the input and output memories necessary. - * - * @param perceptualMemories - * the input memories coming from perception. - * @param broadcastMemory - * the input memories coming from the conscious broadcast of the planner. - * @param motorMemory - * the output motor memory to be dispatched to the actuators. - */ - public abstract void proc(ArrayList perceptualMemories, Memory broadcastMemory, Memory motorMemory); - - /** - * Returns the id of the Soar Codelet whose outputs will be read by this - * Action From Planning Codelet. - * - * @return the soarCodeletId - */ - public String getSoarCodeletId() { - return soarCodeletId; - } - - /** - * Sets the id of the Soar Codelet whose outputs will be read by this - * Action From Planning Codelet. - * - * @param soarCodeletId - * the soarCodeletId to set - */ - public void setSoarCodeletId(String soarCodeletId) { - this.soarCodeletId = soarCodeletId; - } - - /** - * Returns the list of the Perceptual Codelet's ids whose outputs will be - * read by this Action From Planning Codelet. - * - * @return the perceptualCodeletsIds - */ - public ArrayList getPerceptualCodeletsIds() { - return perceptualCodeletsIds; - } - - /** - * Sets the list of the Perceptual Codelet's ids whose outputs will be read - * by this Action From Planning Codelet. - * - * @param perceptualCodeletsIds - * the perceptualCodeletsIds to set - */ - public void setPerceptualCodeletsIds(ArrayList perceptualCodeletsIds) { - this.perceptualCodeletsIds = perceptualCodeletsIds; - } - - /** - * Returns the id of this Action From Planning Codelet. - * - * @return the id - */ - public String getId() { - return id; - } - - /** - * Sets the id of this Action From Planning Codelet. - * - * @param id - * the id to set - */ - public void setId(String id) { - this.id = id; - } - - /** - * Returns the id of the Motor Codelet which will read the outputs of this - * Action From Planning Codelet. - * - * @return the motorCodeletId - */ - public String getMotorCodeletId() { - return motorCodeletId; - } - - /** - * Sets the id of the Motor Codelet which will read the outputs of this - * Action From Planning Codelet. - * - * @param motorCodeletId - * the motorCodeletId to set - */ - public void setMotorCodeletId(String motorCodeletId) { - this.motorCodeletId = motorCodeletId; - } -} diff --git a/src/main/java/br/unicamp/meca/system1/codelets/ActivityCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/ActivityCodelet.java new file mode 100644 index 0000000..05570fe --- /dev/null +++ b/src/main/java/br/unicamp/meca/system1/codelets/ActivityCodelet.java @@ -0,0 +1,329 @@ +/** + * + */ +package br.unicamp.meca.system1.codelets; + +import java.util.ArrayList; + +import br.unicamp.cst.core.entities.Codelet; +import br.unicamp.cst.core.entities.Memory; +import br.unicamp.cst.core.exceptions.CodeletActivationBoundsException; +import br.unicamp.meca.mind.MecaMind; +import br.unicamp.meca.models.ActionSequencePlan; +import br.unicamp.meca.models.ActionStep; + +/** + * This class represents the MECA Activity Codelet. This Activity + * Codelet allows inputs from one or more of the PerceptualCodelets, + * inputs from one or more of the MotivationalCodelets and the ActionSequencePlan + * with greatest activation. It outputs + * necessarily to a MotorCodelet. As the name suggests, the idea behind this + * activity codelet is to provide an action as a purely reaction to the environment + * or else based on a plan in System 1. + *

+ * Usually, Activity Codelets are application-specific, and the MECA + * software implementation just provides basic template class, which is a + * wrapper to CST's {@link Codelet}, to be reused while building an application + * using MECA. + * + * @author A. L. O. Paraense + * + */ +public abstract class ActivityCodelet extends Codelet { + + protected String id; + + protected ArrayList perceptualCodeletsIds; + protected ArrayList perceptualMemories; + + protected ArrayList motivationalCodeletsIds; + protected ArrayList driveMemories; + + protected String planningCodeletId; + protected Memory broadcastMemory; + + protected Memory actionSequencePlanMemoryContainer; + + protected String motorCodeletId; + protected Memory motorMemory; + + /** + * + * Creates a MECA Activity Codelet. + * + * @param id + * the id of the Activity Codelet. Must be unique per + * Activity Codelet. + * @param perceptualCodeletsIds + * the list of ids of the Perceptual Codelets whose outputs will + * be read by this Activity Codelet. + * @param motivationalCodeletsIds + * the list of ids of the Motivational Codelets whose outputs will + * be read by this Activity Codelet. + * @param motorCodeletId + * the id of the Motor Codelet which will read the outputs of + * this Activity Codelet. + * @param planningCodeletId + * the id of the Planning Codelet whose outputs will be read by this + * Activity Codelet. + */ + public ActivityCodelet( + String id, + ArrayList perceptualCodeletsIds, + ArrayList motivationalCodeletsIds, + String motorCodeletId, + String planningCodeletId) { + setName(id); + this.id = id; + this.motorCodeletId = motorCodeletId; + this.perceptualCodeletsIds = perceptualCodeletsIds; + this.planningCodeletId = planningCodeletId; + this.motivationalCodeletsIds = motivationalCodeletsIds; + } + + @Override + public void accessMemoryObjects() { + int index=0; + + if(perceptualMemories == null || perceptualMemories.size() == 0) { + + perceptualMemories = new ArrayList<>(); + + if(perceptualCodeletsIds != null) { + + for(String perceptualCodeletId : perceptualCodeletsIds) { + Memory perceptualMemory = this.getInput(perceptualCodeletId, index); + if (perceptualMemory != null) + perceptualMemories.add(perceptualMemory); + } + } + } + + if(driveMemories == null || driveMemories.size() == 0) + { + driveMemories = new ArrayList<>(); + + if(motivationalCodeletsIds!=null){ + + for(String motivationalCodeletsId : motivationalCodeletsIds) + { + Memory inputDrive = this.getInput(motivationalCodeletsId + "Drive"); + if (inputDrive != null) + driveMemories.add(inputDrive); + } + } + } + + if(broadcastMemory == null) { + broadcastMemory = this.getBroadcast(planningCodeletId, index); + } + + + if(motorMemory==null && motorCodeletId!=null) + motorMemory = this.getOutput(motorCodeletId, index); + + if(actionSequencePlanMemoryContainer == null) + actionSequencePlanMemoryContainer = this.getInput(MecaMind.ACTION_SEQUENCE_PLAN_ID, index); + } + + @Override + public void calculateActivation() { + double activation = 0; + + if(actionSequencePlanMemoryContainer != null && actionSequencePlanMemoryContainer.getI() != null && actionSequencePlanMemoryContainer.getI() instanceof ActionSequencePlan) { + + ActionSequencePlan actionSequencePlan = (ActionSequencePlan) actionSequencePlanMemoryContainer.getI(); + ActionStep currentActionId = actionSequencePlan.getCurrentActionStep(); + + if(currentActionId != null && currentActionId.getActionId().equalsIgnoreCase(id)) { + activation = actionSequencePlanMemoryContainer.getEvaluation(); + }else { + activation = 0.0d; + } + }else if (driveMemories!=null && driveMemories.size() > 0){ + + for (Memory driveMO: driveMemories) { + activation += driveMO.getEvaluation(); + } + + activation /= driveMemories.size(); + + } + + try { + + if(activation<0.0d) + activation=0.0d; + + if(activation>1.0d) + activation=1.0d; + + setActivation(activation); + + } catch (CodeletActivationBoundsException e) { + e.printStackTrace(); + } + + } + + @Override + public void proc() { + // This is the case when this ActivityCodelet is following a plan - there is a plan available + if(actionSequencePlanMemoryContainer != null && actionSequencePlanMemoryContainer.getI() != null && actionSequencePlanMemoryContainer.getI() instanceof ActionSequencePlan) { + ActionSequencePlan actionSequencePlan = (ActionSequencePlan) actionSequencePlanMemoryContainer.getI(); + ActionStep currentAction = actionSequencePlan.getCurrentActionStep(); + ActionStep lastActionStep = actionSequencePlan.getLastExecutedActionStep(); + String lastActionId; + if (lastActionStep != null) { + lastActionId = lastActionStep.getActionId(); + if (lastActionId != null && lastActionId.equalsIgnoreCase(id) && lastActionStep.needsConclusion) { + doConclusion(perceptualMemories, broadcastMemory, motorMemory); + lastActionStep.needsConclusion = false; + } + } + String currentActionId; + if (currentAction != null) { + currentActionId = currentAction.getActionId(); + if(currentActionId != null && currentActionId.equalsIgnoreCase(id) && currentAction.executed == false) { + proc(perceptualMemories, broadcastMemory, motorMemory); + } + } + }else { // This is the case when there is NO plan available, and the ActivityCodelet should be run only with Perception + proc(perceptualMemories, broadcastMemory, motorMemory); + } + } + + /** + * Main method of the Activity Codelet called passing all input and output necessary memories. + * + * @param perceptualMemories + * the input memories coming from perception. + * @param broadcastMemory + * the input memory coming from the conscious planner broadcast. + * @param motorMemory + * the output motor memory. + */ + public abstract void proc(ArrayList perceptualMemories, Memory broadcastMemory, Memory motorMemory); + + /** + * Method to be called to do the Conclusion of an ActionStep, after its activities are over. + * Similar to the proc method, but to be called one last time to clean whatever needs to be cleaned at the motorMemory + * + * @param perceptualMemories + * the input memories coming from perception. + * @param broadcastMemory + * the input memory coming from the conscious planner broadcast. + * @param motorMemory + * the output motor memory. + */ + public abstract void doConclusion(ArrayList perceptualMemories, Memory broadcastMemory, Memory motorMemory); + + /** + * Returns the id of the Planning Codelet whose outputs will be read by this + * Activity Codelet. + * + * @return the planningCodeletId + */ + public String getPlanningCodeletId() { + return planningCodeletId; + } + + /** + * Sets the id of the Planning Codelet whose outputs will be read by this + * Activity Codelet. + * + * @param planningCodeletId + * the planningCodeletId to set + */ + public void setPlanningCodeletId(String planningCodeletId) { + this.planningCodeletId = planningCodeletId; + } + + /** + * Returns the list of the Perceptual Codelet's ids whose outputs will be + * read by this Activity Codelet. + * + * @return the perceptualCodeletsIds + */ + public ArrayList getPerceptualCodeletsIds() { + return perceptualCodeletsIds; + } + + /** + * Sets the list of the Perceptual Codelet's ids whose outputs will be read + * by this Activity Codelet. + * + * @param perceptualCodeletsIds + * the perceptualCodeletsIds to set + */ + public void setPerceptualCodeletsIds(ArrayList perceptualCodeletsIds) { + this.perceptualCodeletsIds = perceptualCodeletsIds; + } + + /** + * Returns the id of this Activity Codelet. + * + * @return the id + */ + public String getId() { + return id; + } + + /** + * Sets the id of this Activity Codelet. + * + * @param id + * the id to set + */ + public void setId(String id) { + this.id = id; + } + + /** + * Returns the id of the Motor Codelet which will read the outputs of this + * Activity Codelet. + * + * @return the motorCodeletId + */ + public String getMotorCodeletId() { + return motorCodeletId; + } + + /** + * Sets the id of the Motor Codelet which will read the outputs of this + * Activity Codelet. + * + * @param motorCodeletId + * the motorCodeletId to set + */ + public void setMotorCodeletId(String motorCodeletId) { + this.motorCodeletId = motorCodeletId; + } + + /** + * @return the motivationalCodeletsIds + */ + public ArrayList getMotivationalCodeletsIds() { + return motivationalCodeletsIds; + } + + public ArrayList getPerceptionMemories() { + return(perceptualMemories); + } + + public ArrayList getDriveMemories() { + return(driveMemories); + } + + public Memory getBroadcastMemory() { + return(broadcastMemory); + } + + public Memory getActionSequencePlanMemoryContainer() { + return(actionSequencePlanMemoryContainer); + } + + public Memory getMotorMemory() { + return(motorMemory); + } +} diff --git a/src/main/java/br/unicamp/meca/system1/codelets/ActivityTrackingCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/ActivityTrackingCodelet.java new file mode 100644 index 0000000..d3a3858 --- /dev/null +++ b/src/main/java/br/unicamp/meca/system1/codelets/ActivityTrackingCodelet.java @@ -0,0 +1,164 @@ +/** + * + */ +package br.unicamp.meca.system1.codelets; + +import java.util.ArrayList; + +import br.unicamp.cst.core.entities.Codelet; +import br.unicamp.cst.core.entities.Memory; +import br.unicamp.cst.core.exceptions.CodeletActivationBoundsException; +import br.unicamp.meca.mind.MecaMind; +import br.unicamp.meca.models.ActionSequencePlan; +import br.unicamp.meca.models.ActionStep; + +/** + * This class represents the MECA Activity Tracking Codelet. This + * Activity Tracking Codelet allows inputs from one or more of the Perceptual Codelets. The idea behind + * this codelet is to track the steps of an Action Sequence Plan in System 1. + *

+ * Usually, Activity Tracking Codelets are application-specific, and the + * MECA software implementation just provides basic template class, which is a + * wrapper to CST's {@link Codelet}, to be reused while building an application + * using MECA. + * + * @author A. L. O. Paraense + * + */ +public class ActivityTrackingCodelet extends Codelet { + + protected String id; + + protected ArrayList perceptualCodeletsIds; + protected ArrayList perceptualMemories; + + protected Memory actionSequencePlanMemoryContainer; + + protected ActionSequencePlan actionSequencePlan; + + /** + * Creates a MECA Activity Tracking Codelet. + * + * @param id + * the id of the Activity Tracking. Must be unique + * per Activity Tracking. + * @param perceptualCodeletsIds + * the list of ids of the Perceptual Codelets whose outputs + * will be read by this Activity Tracking. + * @see Codelet + * @see ActionSequencePlan + */ + public ActivityTrackingCodelet(String id, ArrayList perceptualCodeletsIds) { + super(); + setName(id); + this.id = id; + this.perceptualCodeletsIds = perceptualCodeletsIds; + } + + @Override + public void accessMemoryObjects() { + int index=0; + + if(perceptualMemories == null || perceptualMemories.size() == 0) { + + perceptualMemories = new ArrayList<>(); + + if(perceptualCodeletsIds != null) { + + for(String perceptualCodeletId : perceptualCodeletsIds) { + Memory perceptualMemory = this.getInput(perceptualCodeletId, index); + perceptualMemories.add(perceptualMemory); + } + } + } + + if(actionSequencePlanMemoryContainer == null) + actionSequencePlanMemoryContainer = this.getInput(MecaMind.ACTION_SEQUENCE_PLAN_ID, index); + + } + + @Override + public void calculateActivation() { + try { + setActivation(0.0d); + } catch (CodeletActivationBoundsException e) { + e.printStackTrace(); + } + } + + /** + * Track and advance actions in the sequence plan. + * + * @param actionSequencePlan + * the ActionSequencePlan. + * @param perceptualMemories + * the list Perceptual Memories coming from Perceptual Codelets. + */ + public void trackActionSequencePlan(ArrayList perceptualMemories, ActionSequencePlan actionSequencePlan) { + if(actionSequencePlan != null && + actionSequencePlan.getActionStepSequence() != null && + perceptualMemories != null && + perceptualMemories.size() > 0) { + ActionStep currentActionStep = actionSequencePlan.getCurrentActionStep(); + ActionStep lastActionStep = actionSequencePlan.getLastExecutedActionStep(); + if ((actionSequencePlan.getCurrentActionIdIndex() == 0 + || lastActionStep.needsConclusion == false) // you can go to next step if it is the first step of the plan or if the last step is clear + && (currentActionStep != null // then just check if current ActionStep is not null to avoid breaking the next tests + && currentActionStep.executed == false // the ActionStep was not already executed + && currentActionStep.stopCondition(perceptualMemories)) ) { // and the ActionStep reached its final destination + currentActionStep.needsConclusion = true; + actionSequencePlan.gotoNextAction(); + } + } + } + + @Override + public void proc() { + if (actionSequencePlanMemoryContainer != null) { + actionSequencePlan = (ActionSequencePlan) actionSequencePlanMemoryContainer.getI(); + trackActionSequencePlan(perceptualMemories, actionSequencePlan); + } + } + + /** + * @return the id + */ + public String getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(String id) { + this.id = id; + } + + /** + * @return the perceptualCodeletsIds + */ + public ArrayList getPerceptualCodeletsIds() { + return perceptualCodeletsIds; + } + + /** + * @param perceptualCodeletsIds the perceptualCodeletsIds to set + */ + public void setPerceptualCodeletsIds(ArrayList perceptualCodeletsIds) { + this.perceptualCodeletsIds = perceptualCodeletsIds; + } + + /** + * @return the actionSequencePlanMemoryContainer + */ + public Memory getActionSequencePlanMemoryContainer() { + return actionSequencePlanMemoryContainer; + } + + /** + * @param actionSequencePlanMemoryContainer the actionSequencePlanMemoryContainer to set + */ + public void setActionSequencePlanMemoryContainer(Memory actionSequencePlanMemoryContainer) { + this.actionSequencePlanMemoryContainer = actionSequencePlanMemoryContainer; + } +} diff --git a/src/main/java/br/unicamp/meca/system1/codelets/AttentionCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/AttentionCodelet.java index 157892d..c1d34ea 100644 --- a/src/main/java/br/unicamp/meca/system1/codelets/AttentionCodelet.java +++ b/src/main/java/br/unicamp/meca/system1/codelets/AttentionCodelet.java @@ -18,7 +18,7 @@ import br.unicamp.cst.core.entities.Codelet; import br.unicamp.cst.core.entities.Memory; import br.unicamp.cst.core.exceptions.CodeletActivationBoundsException; -import br.unicamp.cst.representation.owrl.AbstractObject; +import br.unicamp.cst.representation.idea.Idea; /** * This class represents a MECA Attention Codelet in System 1. Attention @@ -44,8 +44,8 @@ public abstract class AttentionCodelet extends Codelet { private Memory inputPerceptsMO; private Memory outputFilteredPerceptsMO; - private List inputPercepts; - private AbstractObject outputFilteredPercepts; + private List inputPercepts; + private Idea outputFilteredPercepts; private List perceptualCodeletsIds; /** @@ -62,7 +62,7 @@ public AttentionCodelet(String id, ArrayList perceptualCodeletsIds) { setName(id); setId(id); setPerceptualCodeletsIds(perceptualCodeletsIds); - setInputPercepts(new ArrayList()); + setInputPercepts(new ArrayList()); } @Override @@ -70,7 +70,7 @@ public void accessMemoryObjects() { if (getInputPerceptsMO() == null) { for (Memory perceptualMO : this.getInputs()) { - getInputPercepts().add((AbstractObject) perceptualMO.getI()); + getInputPercepts().add((Idea) perceptualMO.getI()); } } @@ -96,13 +96,13 @@ public void proc() { } /** - * Generates a filtered percept as an AbstractObject. + * Generates a filtered percept as an Idea. * * @param inputPercepts * the list of input percepts. - * @return filtered percept as an AbstractObject. + * @return filtered percept as an Idea. */ - public abstract AbstractObject generateFilteredPercepts(List inputPercepts); + public abstract Idea generateFilteredPercepts(List inputPercepts); /** * Gets the input Percept as a Memory Object. @@ -147,7 +147,7 @@ public void setOutputFilteredPerceptsMO(Memory outputFilteredPerceptsMO) { * * @return the list of input percepts. */ - public List getInputPercepts() { + public List getInputPercepts() { return inputPercepts; } @@ -157,7 +157,7 @@ public List getInputPercepts() { * @param inputPercepts * the list of input percepts. */ - public void setInputPercepts(List inputPercepts) { + public void setInputPercepts(List inputPercepts) { this.inputPercepts = inputPercepts; } @@ -166,7 +166,7 @@ public void setInputPercepts(List inputPercepts) { * * @return the output filtered percepts. */ - public AbstractObject getOutputFilteredPercepts() { + public Idea getOutputFilteredPercepts() { return outputFilteredPercepts; } @@ -176,7 +176,7 @@ public AbstractObject getOutputFilteredPercepts() { * @param outputFilteredPercepts * the output filtered percepts. */ - public void setOutputFilteredPercepts(AbstractObject outputFilteredPercepts) { + public void setOutputFilteredPercepts(Idea outputFilteredPercepts) { this.outputFilteredPercepts = outputFilteredPercepts; } diff --git a/src/main/java/br/unicamp/meca/system1/codelets/BehaviorCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/BehaviorCodelet.java index 366337a..3728a80 100644 --- a/src/main/java/br/unicamp/meca/system1/codelets/BehaviorCodelet.java +++ b/src/main/java/br/unicamp/meca/system1/codelets/BehaviorCodelet.java @@ -46,7 +46,7 @@ public abstract class BehaviorCodelet extends Codelet { protected ArrayList motivationalCodeletsIds; protected ArrayList driveMemories; - protected String soarCodeletId; + protected String planningCodeletId; protected Memory broadcastMemory; protected ActionSequencePlan actionSequencePlan; @@ -67,36 +67,21 @@ public abstract class BehaviorCodelet extends Codelet { * @param motivationalCodeletsIds * the list of ids of the Motivational Codelets whose outputs * will be read by this Behavior Codelet. - * @param soarCodeletId - * the id of the Soar Codelet whose outputs will be read by this + * @param planningCodeletId + * the id of the Planning Codelet whose outputs will be read by this * Behavior Codelet. - * @param actionSequencePlan - * the ActionSequencePlan that this Behavior Codelet will provide * @see Codelet - * @see ActionSequencePlan */ public BehaviorCodelet(String id, ArrayList perceptualCodeletsIds, ArrayList motivationalCodeletsIds, - String soarCodeletId, ActionSequencePlan actionSequencePlan) { + String planningCodeletId) { super(); setName(id); this.id = id; this.perceptualCodeletsIds = perceptualCodeletsIds; this.motivationalCodeletsIds = motivationalCodeletsIds; - this.soarCodeletId = soarCodeletId; - this.actionSequencePlan = actionSequencePlan; + this.planningCodeletId = planningCodeletId; } - - /** - * Track and advance actions in the sequence plan. To be implemented in each object of this class, - * according to its action sequence plan. - * - * @param actionSequencePlan - * the ActionSequencePlan that this Behavior Codelet provides. - * @param perceptualMemories - * the list Perceptual Memories coming from Perceptual Codelets. - */ - public abstract void trackActionSequencePlan(ArrayList perceptualMemories, ActionSequencePlan actionSequencePlan); - + @Override public void accessMemoryObjects() { @@ -123,14 +108,14 @@ public void accessMemoryObjects() { for(String motivationalCodeletsId : motivationalCodeletsIds) { - Memory inputDrive = this.getInput(motivationalCodeletsId + "_DRIVE_MO"); + Memory inputDrive = this.getInput(motivationalCodeletsId + "Drive"); driveMemories.add(inputDrive); } } } if(broadcastMemory == null) { - broadcastMemory = this.getBroadcast(soarCodeletId, index); + broadcastMemory = this.getBroadcast(planningCodeletId, index); } if(actionSequencePlanMemoryContainer == null) @@ -172,39 +157,51 @@ public void calculateActivation() { } + /** + * Builds the action sequence plan to be outputed by this BehaviorCodelet + * + * @param perceptualMemories the Perceptual Memories coming from Perceptual Codelets. + * @return the action sequence plan to be followed. + */ + protected abstract ActionSequencePlan buildActionSequencePlan(ArrayList perceptualMemories); + @Override public void proc() { - trackActionSequencePlan(perceptualMemories,actionSequencePlan); + actionSequencePlan = buildActionSequencePlan(perceptualMemories); + + if(broadcastMemory != null && broadcastMemory.getI()!= null && broadcastMemory.getI() instanceof ActionSequencePlan) + actionSequencePlan = (ActionSequencePlan) broadcastMemory.getI(); if(actionSequencePlan != null) { ((MemoryContainer) actionSequencePlanMemoryContainer).setI(actionSequencePlan,getActivation(),id); - ((MemoryContainer) actionSequencePlanRequestMemoryContainer).setI(null,0.0d,id); + ((MemoryContainer) actionSequencePlanRequestMemoryContainer).setI(null,0.0d,"R_"+id); }else { ((MemoryContainer) actionSequencePlanMemoryContainer).setI(null,0.0d,id); - ((MemoryContainer) actionSequencePlanRequestMemoryContainer).setI(id,getActivation(),id); + ((MemoryContainer) actionSequencePlanRequestMemoryContainer).setI(id,getActivation(),"R_"+id); } } + /** - * Returns the id of the Soar Codelet whose outputs will be read by this + * Returns the id of the Planning Codelet whose outputs will be read by this * Behavior Codelet. * - * @return the soarCodeletId + * @return the planningCodeletId */ - public String getSoarCodeletId() { - return soarCodeletId; + public String getPlanningCodeletId() { + return planningCodeletId; } /** - * Sets the id of the Soar Codelet whose outputs will be read by this + * Sets the id of the Planning Codelet whose outputs will be read by this * Behavior Codelet. * - * @param soarCodeletId - * the soarCodeletId to set + * @param planningCodeletId + * the planningCodeletId to set */ - public void setSoarCodeletId(String soarCodeletId) { - this.soarCodeletId = soarCodeletId; + public void setPlanningCodeletId(String planningCodeletId) { + this.planningCodeletId = planningCodeletId; } /** diff --git a/src/main/java/br/unicamp/meca/system1/codelets/MotivationalCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/MotivationalCodelet.java index ec55198..6307783 100644 --- a/src/main/java/br/unicamp/meca/system1/codelets/MotivationalCodelet.java +++ b/src/main/java/br/unicamp/meca/system1/codelets/MotivationalCodelet.java @@ -73,14 +73,14 @@ public void accessMemoryObjects() { if (getSensoryVariables().size() == 0) { for (Memory sensoryMO : getInputs()) { - if (!sensoryMO.getName().contains("DRIVE")) + if (!sensoryMO.getName().contains("Drive")) getSensoryVariables().add(sensoryMO); } } if (getDrivesRelevance().size() == 0) { for (Memory driveMO : getInputs()) { - if (driveMO.getName().contains("DRIVE")) { + if (driveMO.getName().contains("Drive")) { getDrivesRelevance().putAll((Map) driveMO.getI()); } } diff --git a/src/main/java/br/unicamp/meca/system1/codelets/MotorCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/MotorCodelet.java index c92f7e3..a22d794 100644 --- a/src/main/java/br/unicamp/meca/system1/codelets/MotorCodelet.java +++ b/src/main/java/br/unicamp/meca/system1/codelets/MotorCodelet.java @@ -34,7 +34,7 @@ public abstract class MotorCodelet extends Codelet implements IMotorCodelet{ protected String id; - protected Memory motorMemory; + protected volatile Memory motorMemory; /** * Creates a MECA Motor Codelet. diff --git a/src/main/java/br/unicamp/meca/system1/codelets/Ros2ServiceClientMotorCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/Ros2ServiceClientMotorCodelet.java new file mode 100644 index 0000000..f232042 --- /dev/null +++ b/src/main/java/br/unicamp/meca/system1/codelets/Ros2ServiceClientMotorCodelet.java @@ -0,0 +1,55 @@ +/** + * + */ +package br.unicamp.meca.system1.codelets; + +import java.net.URI; +import br.unicamp.cst.bindings.ros2java.RosServiceClientCodelet; +import id.jrosmessages.Message; +import pinorobotics.jrosservices.msgs.ServiceDefinition; + +/** + * A Wrapper of the CST's RosServiceClientCodelet implementing the IMotorCodelet interface, + * adapted for ROS 2 (jros2client), to be mounted on the MecaMind. + * + * @author andre + * @author jrborelli - ROS2 + * + * @param Service Message Request - Ex: AddTwoIntsRequest + * @param Service Message Response - Ex: AddTwoIntsResponse + */ + + +public abstract class Ros2ServiceClientMotorCodelet + extends RosServiceClientCodelet implements IMotorCodelet { + + protected String id; + + /** + * Constructor for the RosServiceClientMotorCodelet. + * + * @param id the id of this Motor Codelet, to be used in mounting MECA Mind. + * @param serviceName the ROS 2 service name. Ex: "add_two_ints" + * @param serviceDefinition the service definition object + */ + + public Ros2ServiceClientMotorCodelet(String id, String serviceName, + ServiceDefinition serviceDefinition) { + super(serviceName, serviceDefinition); + this.id = id; + } + + /** + * Returns the id of this RosServiceClientMotorCodelet. + */ + public String getId() { + return id; + } + + /** + * Sets the id of this RosServiceClientMotorCodelet. + */ + public void setId(String id) { + this.id = id; + } +} \ No newline at end of file diff --git a/src/main/java/br/unicamp/meca/system1/codelets/Ros2TopicOneShotPublisherMotorCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/Ros2TopicOneShotPublisherMotorCodelet.java new file mode 100644 index 0000000..b4eefbf --- /dev/null +++ b/src/main/java/br/unicamp/meca/system1/codelets/Ros2TopicOneShotPublisherMotorCodelet.java @@ -0,0 +1,54 @@ +/** + * + */ + +package br.unicamp.meca.system1.codelets; + +import br.unicamp.cst.bindings.ros2java.RosTopicOneShotPublisherCodelet; +import br.unicamp.cst.core.entities.Memory; +import id.jrosmessages.Message; + +/** + * A Wrapper of the CST's RosTopicOneShotPublisherCodelet implementing the IMotorCodelet interface, + * in order to be able to be mounted on the MecaMind. + * + * @author andre + * @author jrborelli - ROS2. + * + * @param The ROS Message Type - Ex: std_msgs.String from ROS standard messages + */ +public abstract class Ros2TopicOneShotPublisherMotorCodelet + extends RosTopicOneShotPublisherCodelet implements IMotorCodelet { + + protected String id; + + /** + * Constructor for the RosTopicOneShotPublisherMotorCodelet. + * + * @param id the id of this Motor Codelet, to be used in mounting MECA Mind. + * @param topic the name of the ROS topic this node will be publishing to. + * @param messageType the ROS message class type. Ex: std_msgs.String.class + */ + public Ros2TopicOneShotPublisherMotorCodelet(String id, String topic, Class messageType) { + super(id, topic, messageType); + this.id = id; + } + + /** + * Returns the id of this RosTopicOneShotPublisherMotorCodelet. + * + * @return the id + */ + public String getId() { + return id; + } + + /** + * Sets the id of this RosTopicOneShotPublisherMotorCodelet. + * + * @param id the id to set + */ + public void setId(String id) { + this.id = id; + } +} diff --git a/src/main/java/br/unicamp/meca/system1/codelets/Ros2TopicPublisherMotorCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/Ros2TopicPublisherMotorCodelet.java new file mode 100644 index 0000000..527fe56 --- /dev/null +++ b/src/main/java/br/unicamp/meca/system1/codelets/Ros2TopicPublisherMotorCodelet.java @@ -0,0 +1,50 @@ +package br.unicamp.meca.system1.codelets; + +import br.unicamp.cst.bindings.ros2java.RosTopicPublisherCodelet; +import br.unicamp.cst.core.entities.Memory; +import id.jrosmessages.Message; + +/** + * A Wrapper of the CST's RosTopicPublisherCodelet implementing the IMotorCodelet interface, + * in order to be able to be mounted on the MecaMind. + * + * @author andre + * @author jrborelli - ROS2. + * + * @param The ROS Message Type - Ex: std_msgs.String from ROS standard messages + */ +public abstract class Ros2TopicPublisherMotorCodelet + extends RosTopicPublisherCodelet implements IMotorCodelet { + + protected String id; + + /** + * Constructor for the RosTopicPublisherMotorCodelet. + * + * @param id the id of this Motor Codelet, to be used in mounting MECA Mind. + * @param topic the name of the ROS topic this node will be publishing to. + * @param messageType the ROS message class type. Ex: std_msgs.String.class + */ + public Ros2TopicPublisherMotorCodelet(String id, String topic, Class messageType) { + super(id,topic, messageType); + this.id = id; + } + + /** + * Returns the id of this RosTopicPublisherMotorCodelet. + * + * @return the id + */ + public String getId() { + return id; + } + + /** + * Sets the id of this RosTopicPublisherMotorCodelet. + * + * @param id the id to set + */ + public void setId(String id) { + this.id = id; + } +} diff --git a/src/main/java/br/unicamp/meca/system1/codelets/Ros2TopicSubscriberSensoryCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/Ros2TopicSubscriberSensoryCodelet.java new file mode 100644 index 0000000..4f141df --- /dev/null +++ b/src/main/java/br/unicamp/meca/system1/codelets/Ros2TopicSubscriberSensoryCodelet.java @@ -0,0 +1,49 @@ +package br.unicamp.meca.system1.codelets; + +import br.unicamp.cst.bindings.ros2java.RosTopicSubscriberCodelet; +import id.jrosmessages.Message; + +/** + * A Wrapper of the CST's RosTopicSubscriberCodelet implementing the ISensoryCodelet interface, + * in order to be able to be mounted on the MecaMind. + * + * @author andre + * @author jrborelli - ROS2. + * + * @param The ROS Message Type - Ex: std_msgs.String from ROS standard messages + */ +public abstract class Ros2TopicSubscriberSensoryCodelet + extends RosTopicSubscriberCodelet implements ISensoryCodelet { + + protected String id; + + /** + * Constructor for the RosTopicSubscriberSensoryCodelet. + * + * @param id the id of this Sensory Codelet, to be used in mounting MECA Mind. + * @param topic the name of the ROS topic this node will be subscribing to. + * @param messageType the ROS message class type. Ex: std_msgs.String.class + */ + public Ros2TopicSubscriberSensoryCodelet(String id, String topic, Class messageType) { + super(id,topic, messageType); + this.id = id; + } + + /** + * Returns the id of this RosTopicSubscriberSensoryCodelet. + * + * @return the id + */ + public String getId() { + return id; + } + + /** + * Sets the id of this RosTopicSubscriberSensoryCodelet. + * + * @param id the id to set + */ + public void setId(String id) { + this.id = id; + } +} \ No newline at end of file diff --git a/src/main/java/br/unicamp/meca/system1/codelets/RosTopicOneShotPublisherMotorCodelet.java b/src/main/java/br/unicamp/meca/system1/codelets/RosTopicOneShotPublisherMotorCodelet.java new file mode 100644 index 0000000..2f9d27a --- /dev/null +++ b/src/main/java/br/unicamp/meca/system1/codelets/RosTopicOneShotPublisherMotorCodelet.java @@ -0,0 +1,54 @@ +/** + * + */ +package br.unicamp.meca.system1.codelets; + +import br.unicamp.cst.bindings.rosjava.RosTopicOneShotPublisherCodelet; +import java.net.URI; + + +/** + * A Wrapper of the CST's RosTopicPublisherCodelet implementing the IMotorCodelet interface, + * in order to be able to be mounted on the MecaMind. + * + * @author andre + * + * @param The ROS Message Type - Ex: std_msgs.String from ROS standard messages + */ +public abstract class RosTopicOneShotPublisherMotorCodelet extends RosTopicOneShotPublisherCodelet implements IMotorCodelet{ + + protected String id; + + /** + * Constructor for the RosTopicPublisherMotorCodelet. + * + * @param id the id of this Motor Codelet, to be used in mounting MECA Mind. Also the name of this ROS node. + * @param topic the name of the ROS topic this node will be publishing to. + * @param messageType the ROS message type. Ex: "std_msgs.String". + * @param host the host IP where to run. Ex: "127.0.0.1". + * @param masterURI the URI of the master ROS node. Ex: new URI("http://127.0.0.1:11311"). + */ + public RosTopicOneShotPublisherMotorCodelet(String id, String topic, String messageType, String host, URI masterURI) { + super(id, topic, messageType, host, masterURI); + this.id = id; + } + + /** + * Returns the id of this RosTopicPublisherMotorCodelet. + * + * @return the id + */ + public String getId() { + return id; + } + + /** + * Sets the id of this RosTopicPublisherMotorCodelet. + * + * @param id + * the id to set + */ + public void setId(String id) { + this.id = id; + } +} diff --git a/src/main/java/br/unicamp/meca/system2/codelets/GoalCodelet.java b/src/main/java/br/unicamp/meca/system2/codelets/GoalCodelet.java index 1935283..4bd6a7f 100644 --- a/src/main/java/br/unicamp/meca/system2/codelets/GoalCodelet.java +++ b/src/main/java/br/unicamp/meca/system2/codelets/GoalCodelet.java @@ -12,6 +12,11 @@ ******************************************************************************/ package br.unicamp.meca.system2.codelets; +import br.unicamp.cst.core.entities.Memory; +import br.unicamp.cst.core.entities.MemoryContainer; +import br.unicamp.cst.representation.idea.Idea; +import br.unicamp.meca.memory.WorkingMemory; + /** * This class represents MECA's Goal Codelet. Goals are created in MECA by the * Goal Codelet. The Goal Codelet uses the Current Perception in order to @@ -25,6 +30,9 @@ */ public abstract class GoalCodelet extends br.unicamp.cst.motivational.GoalCodelet { + private Memory actionSequencePlanRequestMemoryContainer; + private WorkingMemory wm; + /** * Creates a MECA's Goal Codelet. * @@ -33,5 +41,47 @@ public abstract class GoalCodelet extends br.unicamp.cst.motivational.GoalCodele */ public GoalCodelet(String id) { super(id); + setName(id); } + + @Override + public void proc() { + if (isInit()) { + setHypotheticalSituation((Idea) getInputHypotheticalSituationsMO().getI()); + setGoal(goalGeneration(getHypotheticalSituation())); + ((MemoryContainer)getGoalMO()).setI(getGoal(),getActivation(),getId()); + } + + setInit(true); + } + + /** + * @return the actionSequencePlanRequestMemoryContainer + */ + public Memory getActionSequencePlanRequestMemoryContainer() { + return actionSequencePlanRequestMemoryContainer; + } + + /** + * @param actionSequencePlanRequestMemoryContainer the actionSequencePlanRequestMemoryContainer to set + */ + public void setActionSequencePlanRequestMemoryContainer(Memory actionSequencePlanRequestMemoryContainer) { + this.actionSequencePlanRequestMemoryContainer = actionSequencePlanRequestMemoryContainer; + } + + /** + * @return the wm + */ + public WorkingMemory getWm() { + return wm; + } + + /** + * @param wm the wm to set + */ + public void setWm(WorkingMemory wm) { + this.wm = wm; + } + + } diff --git a/src/main/java/br/unicamp/meca/system2/codelets/IPlanningCodelet.java b/src/main/java/br/unicamp/meca/system2/codelets/IPlanningCodelet.java new file mode 100644 index 0000000..1931e3a --- /dev/null +++ b/src/main/java/br/unicamp/meca/system2/codelets/IPlanningCodelet.java @@ -0,0 +1,53 @@ +/** + * + */ +package br.unicamp.meca.system2.codelets; + +import java.util.List; + +import br.unicamp.cst.core.entities.Memory; + +/** + * @author andre + * + */ +public interface IPlanningCodelet { + + /** + * Returns the id of this Planning Codelet. + * + * @return the id + */ + String getId(); + + /** + * Gets the list of output memories. + * + * @return the outputs. + */ + List getOutputs(); + + /** + * Add a memory to the output list. + * + * @param memory + * one output to set. + */ + void addOutput(Memory memory); + + /** + * Gets the input memories list. + * + * @return the inputs. + */ + List getInputs(); + + /** + * Add one memory to the input list. + * + * @param memory + * one input to set. + */ + void addInput(Memory memory); + +} diff --git a/src/main/java/br/unicamp/meca/system2/codelets/SoarCodelet.java b/src/main/java/br/unicamp/meca/system2/codelets/SoarCodelet.java index 4dd8dd1..7907250 100644 --- a/src/main/java/br/unicamp/meca/system2/codelets/SoarCodelet.java +++ b/src/main/java/br/unicamp/meca/system2/codelets/SoarCodelet.java @@ -18,9 +18,7 @@ import java.util.List; import br.unicamp.cst.core.entities.Memory; -import br.unicamp.cst.motivational.Goal; -import br.unicamp.cst.representation.owrl.AbstractObject; -import br.unicamp.cst.representation.owrl.Property; +import br.unicamp.cst.representation.idea.Idea; import br.unicamp.meca.memory.WorkingMemory; /** @@ -32,7 +30,7 @@ * @author W. Gibaut * @see br.unicamp.cst.bindings.soar.JSoarCodelet */ -public abstract class SoarCodelet extends br.unicamp.cst.bindings.soar.JSoarCodelet { +public abstract class SoarCodelet extends br.unicamp.cst.bindings.soar.JSoarCodelet implements IPlanningCodelet { private String id; @@ -110,11 +108,11 @@ public void accessMemoryObjects() { @Override public void proc() { - AbstractObject il = processWorkingMemoryInput(); - if (il.getCompositeList().size() == 0) + Idea il = processWorkingMemoryInput(); + if (il.getL().size() == 0) return; - setInputLinkAO(il); + this.setInputLinkIdea(il); if (getDebugState() == 0) getJsoar().step(); @@ -124,7 +122,8 @@ public void proc() { if (commandList != null) { Collections.addAll(rawPlan, commandList); - workingMemory.getPlansMemory().setI(rawPlan); + //workingMemory.getPlansMemory().setI(rawPlan); + workingMemory.getInternalMemory("PlansMemory").setI(rawPlan); workingMemoryOutputMO.setI(workingMemory); @@ -147,44 +146,49 @@ public void proc() { * * @return an abstract object represent an Input link. */ - public AbstractObject processWorkingMemoryInput() { + public Idea processWorkingMemoryInput() { - AbstractObject il = new AbstractObject("InputLink"); + Idea il = Idea.createIdea("InputLink","",0); - AbstractObject currentPerceptionWO = (AbstractObject) workingMemory.getCurrentPerceptionMemory().getI() != null - ? convertToAbstractObject((AbstractObject) workingMemory.getCurrentPerceptionMemory().getI(), + //AbstractObject currentPerceptionWO = (AbstractObject) workingMemory.getCurrentPerceptionMemory().getI() != null + Idea currentPerceptionWO = (Idea) workingMemory.getInternalMemory("CurrentPerceptionMemory").getI() != null + ? convertToIdea((Idea) workingMemory.getInternalMemory("CurrentPerceptionMemory").getI(), "CURRENT_PERCEPTION") : null; - AbstractObject imaginationsWO = (List) workingMemory.getImaginationsMemory().getI() != null - ? convertToAbstractObject((List) workingMemory.getImaginationsMemory().getI(), + //AbstractObject imaginationsWO = (List) workingMemory.getImaginationsMemory().getI() != null + Idea imaginationsWO = (List) workingMemory.getInternalMemory("ImaginationsMemory").getI() != null + ? convertToIdea((List) workingMemory.getInternalMemory("ImaginationsMemory").getI(), "IMAGINATION") : null; - AbstractObject goalsWO = (List) workingMemory.getGoalsMemory().getI() != null - ? goalToAbstractObject((List) workingMemory.getGoalsMemory().getI()) : null; + //AbstractObject goalsWO = (List) workingMemory.getGoalsMemory().getI() != null + Idea goalsWO = (List) workingMemory.getInternalMemory("GoalsMemory").getI() != null + ? goalToIdea((List) workingMemory.getInternalMemory("GoalsMemory").getI()) : null; - AbstractObject globalWO = (List) workingMemory.getGlobalWorkspaceMemory().getI() != null - ? globalWorkspaceToAbstractObject((List) workingMemory.getGlobalWorkspaceMemory().getI()) + //AbstractObject globalWO = (List) workingMemory.getGlobalWorkspaceMemory().getI() != null + Idea globalWO = (List) workingMemory.getInternalMemory("GlobalWorkspaceMemory").getI() != null + ? globalWorkspaceToIdea((List) workingMemory.getInternalMemory("GlobalWorkspaceMemory").getI()) : null; - AbstractObject epRecallWO = (List) workingMemory.getEpisodicRecallMemory().getI() != null - ? epRecallToAbstractObject((List) workingMemory.getEpisodicRecallMemory().getI()) : null; + //AbstractObject epRecallWO = (List) workingMemory.getEpisodicRecallMemory().getI() != null + Idea epRecallWO = (List) workingMemory.getInternalMemory("EpisodicRecallMemory").getI() != null + ? epRecallToIdea((List) workingMemory.getInternalMemory("EpisodicRecallMemory").getI()) : null; if (currentPerceptionWO != null) - il.addCompositePart(currentPerceptionWO); + il.add(currentPerceptionWO); if (imaginationsWO != null) - il.addCompositePart(imaginationsWO); + il.add(imaginationsWO); if (goalsWO != null) - il.addCompositePart(goalsWO); + il.add(goalsWO); if (globalWO != null) - il.addCompositePart(globalWO); + il.add(globalWO); if (epRecallWO != null) - il.addCompositePart(epRecallWO); + il.add(epRecallWO); return il; } @@ -198,11 +202,11 @@ public AbstractObject processWorkingMemoryInput() { * the node name. * @return the abstract object. */ - public AbstractObject convertToAbstractObject(AbstractObject abstractObject, String nodeName) { + public Idea convertToIdea(Idea abstractObject, String nodeName) { - AbstractObject abs = new AbstractObject(nodeName); + Idea abs = Idea.createIdea(nodeName,"",0); - abs.addCompositePart(abstractObject); + abs.add(abstractObject); return abs; } @@ -210,18 +214,18 @@ public AbstractObject convertToAbstractObject(AbstractObject abstractObject, Str /** * Converts to abstract object. * - * @param abstractObjects + * @param ideas * the list of input abstract objects. * @param nodeNameTemplate * the node name template. * @return the abstract object. */ - public AbstractObject convertToAbstractObject(List abstractObjects, String nodeNameTemplate) { + public Idea convertToIdea(List ideas, String nodeNameTemplate) { - AbstractObject configs = new AbstractObject(abstractObjects.toString()); + Idea configs = Idea.createIdea(ideas.toString(),"",0); - for (AbstractObject abs : abstractObjects) { - configs.addAggregatePart(convertToAbstractObject(abs, nodeNameTemplate)); + for (Idea abs : ideas) { + configs.add(convertToIdea(abs, nodeNameTemplate)); } return configs; } @@ -233,15 +237,16 @@ public AbstractObject convertToAbstractObject(List abstractObjec * the list of goals. * @return the Abstract Object representing the Goals. */ - public AbstractObject goalToAbstractObject(List goals) { + public Idea goalToIdea(List goals) { - AbstractObject go = new AbstractObject("Goals"); + Idea go = Idea.createIdea("Goals","",0); - for (Goal goal : goals) { + for (Idea goal : goals) { - AbstractObject temp = convertToAbstractObject(goal.getGoalAbstractObjects(), "GOAL"); - temp.addProperty(new Property(goal.getId())); - go.addAggregatePart(temp); + //Idea temp = convertToIdea(goal.getGoalIdeas(), "GOAL"); + //temp.add(new Idea(goal.getId())); + //go.add(temp); + go.add(goal); } return go; } @@ -253,17 +258,17 @@ public AbstractObject goalToAbstractObject(List goals) { * the list of memories * @return the abstract object representing global workspace */ - public AbstractObject globalWorkspaceToAbstractObject(List global) { + public Idea globalWorkspaceToIdea(List global) { - List globalAbstractObjects = null; + List globalIdeass = null; List globalStrings = null; for (Memory mem : global) { - if (isAbstractObject(mem.getI())) { + if (isIdea(mem.getI())) { - globalAbstractObjects.add((AbstractObject) mem.getI()); + globalIdeass.add((Idea) mem.getI()); } } @@ -275,11 +280,11 @@ public AbstractObject globalWorkspaceToAbstractObject(List global) { } } - AbstractObject gAbs = convertToAbstractObject(globalAbstractObjects, "GLOBAL_WORKSPACE"); + Idea gAbs = convertToIdea(globalIdeass, "GLOBAL_WORKSPACE"); for (String st : globalStrings) { - gAbs.addAggregatePart(new AbstractObject(st)); + gAbs.add(Idea.createIdea(st,"",0)); } return gAbs; @@ -292,19 +297,19 @@ public AbstractObject globalWorkspaceToAbstractObject(List global) { * the list of memories representing the episodic recall. * @return the Abstract Object representing an episodic recall. */ - public AbstractObject epRecallToAbstractObject(List episodicRecall) { + public Idea epRecallToIdea(List episodicRecall) { - List epConfigurations = null; + List epConfigurations = null; for (Memory mem : episodicRecall) { - if (isAbstractObject(mem.getI())) { + if (isIdea(mem.getI())) { - epConfigurations.add((AbstractObject) mem.getI()); + epConfigurations.add((Idea) mem.getI()); } } - AbstractObject gConf = convertToAbstractObject(epConfigurations, "EPISODIC_RECALL_MEMORY"); + Idea gConf = convertToIdea(epConfigurations, "EPISODIC_RECALL_MEMORY"); return gConf; } @@ -316,9 +321,9 @@ public AbstractObject epRecallToAbstractObject(List episodicRecall) { * the object to be tested * @return true if the obj is an abstract object. */ - public boolean isAbstractObject(Object obj) { + public boolean isIdea(Object obj) { - if (obj.getClass() == AbstractObject.class) + if (obj.getClass() == Idea.class) return true; else return false; diff --git a/src/test/java/br/unicamp/meca/mind/MecaMindTest.java b/src/test/java/br/unicamp/meca/mind/MecaMindTest.java index 4e789c2..f9bc024 100644 --- a/src/test/java/br/unicamp/meca/mind/MecaMindTest.java +++ b/src/test/java/br/unicamp/meca/mind/MecaMindTest.java @@ -9,32 +9,35 @@ import java.util.HashMap; import java.util.List; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.Test; import br.unicamp.cst.core.entities.Codelet; +import br.unicamp.cst.core.entities.Memory; import br.unicamp.cst.core.entities.MemoryContainer; import br.unicamp.cst.core.exceptions.CodeletActivationBoundsException; -import br.unicamp.cst.util.MindViewer; -import br.unicamp.meca.mind.action.Test1ActionFromPerceptionCodelet; -import br.unicamp.meca.mind.action.Test1ActionFromPlanningCodelet; -import br.unicamp.meca.mind.action.Test2ActionFromPlanningCodelets; +import br.unicamp.cst.util.viewer.MindViewer; +import br.unicamp.meca.mind.action.Test1ActivityCodelet; +import br.unicamp.meca.mind.action.Test2ActivityCodelet; +import br.unicamp.meca.mind.action.Test3ActivityCodelet; import br.unicamp.meca.mind.behavior.Test1AndTest2BehaviorCodelet; import br.unicamp.meca.mind.motivational.TestMotivationalFromPerceptionCodelet; import br.unicamp.meca.mind.motivational.TestMotivationalFromPlanningCodelet; import br.unicamp.meca.mind.motor.TestMotorCodelet; import br.unicamp.meca.mind.perceptual.TestPerceptualCodelet; +import br.unicamp.meca.mind.planning.TestSoarCodelet; import br.unicamp.meca.mind.sensory.TestPerceptionSensoryCodelet; import br.unicamp.meca.mind.sensory.TestPlanningSensoryCodelet; import br.unicamp.meca.models.ActionSequencePlan; -import br.unicamp.meca.system1.codelets.ActionFromPerceptionCodelet; -import br.unicamp.meca.system1.codelets.ActionFromPlanningCodelet; +import br.unicamp.meca.system1.codelets.ActivityCodelet; +import br.unicamp.meca.system1.codelets.ActivityTrackingCodelet; import br.unicamp.meca.system1.codelets.BehaviorCodelet; import br.unicamp.meca.system1.codelets.IMotorCodelet; import br.unicamp.meca.system1.codelets.ISensoryCodelet; import br.unicamp.meca.system1.codelets.MotivationalCodelet; import br.unicamp.meca.system1.codelets.PerceptualCodelet; +import br.unicamp.meca.system2.codelets.IPlanningCodelet; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; /** * @author andre @@ -51,28 +54,35 @@ public class MecaMindTest { private static TestPlanningSensoryCodelet testPlanningSensoryCodelet; private static TestMotorCodelet testMotorCodelet; - - @BeforeClass + + private static List perceptualCodelets; + + private static List sensoryCodelets; + + private static List motivationalCodelets; + + private static List activityCodelets; + + private static IPlanningCodelet planningCodelet; + + @BeforeAll public static void setup() throws InterruptedException { mecaMind = new MecaMind("MecaMind"); /* Sensory codelets we are about to create for this Meca mind*/ - List sensoryCodelets = new ArrayList<>(); + sensoryCodelets = new ArrayList<>(); /* Lists that will hold the codelets ids. This is important * for the MECA mind mounting algorithm be able to glue the * codelets according to the reference architecture * */ - ArrayList sensoryCodeletsIds = new ArrayList<>(); - + ArrayList sensoryPerceptionCodeletsIds = new ArrayList<>(); + testPerceptionSensoryCodelet = new TestPerceptionSensoryCodelet("TestPerceptionSensoryCodelet"); sensoryCodelets.add(testPerceptionSensoryCodelet); - sensoryCodeletsIds.add(testPerceptionSensoryCodelet.getId()); + sensoryPerceptionCodeletsIds.add(testPerceptionSensoryCodelet.getId()); - testPlanningSensoryCodelet = new TestPlanningSensoryCodelet("TestPlanningSensoryCodelet"); - sensoryCodelets.add(testPlanningSensoryCodelet); - sensoryCodeletsIds.add(testPlanningSensoryCodelet.getId()); /* * Now it is a good time to create the motor codelets, before the Behavioral ones, @@ -90,26 +100,27 @@ public static void setup() throws InterruptedException { * This codelet must receive the ids of the sensory codelets, * in order to be glued to them, receiving their inputs. */ - List perceptualCodelets = new ArrayList<>(); - ArrayList perceptualCodeletsIds = new ArrayList<>(); + perceptualCodelets = new ArrayList<>(); + ArrayList perceptualPerceptionCodeletsIds = new ArrayList<>(); - TestPerceptualCodelet testPerceptualCodelet = new TestPerceptualCodelet("TestPerceptualCodelet", sensoryCodeletsIds); - perceptualCodeletsIds.add(testPerceptualCodelet.getId()); + TestPerceptualCodelet testPerceptualCodelet = new TestPerceptualCodelet("TestPerceptualCodelet", sensoryPerceptionCodeletsIds); + perceptualPerceptionCodeletsIds.add(testPerceptualCodelet.getId()); perceptualCodelets.add(testPerceptualCodelet); + /* * Next step is to create the motivational codelets. * This codelets must receive the ids of the sensory codelets, * in order to be glued to them, receiving their inputs. */ - List motivationalCodelets = new ArrayList<>(); + motivationalCodelets = new ArrayList<>(); ArrayList testMotivationalFromPerceptionCodeletIds = new ArrayList<>(); TestMotivationalFromPerceptionCodelet testMotivationalFromPerceptionCodelet; try { - testMotivationalFromPerceptionCodelet = new TestMotivationalFromPerceptionCodelet("TestMotivationalFromPerceptionCodelet", 0, 0.45, 0.9, sensoryCodeletsIds, new HashMap()); + testMotivationalFromPerceptionCodelet = new TestMotivationalFromPerceptionCodelet("TestMotivationalFromPerceptionCodelet", 0, 0.45, 0.9, sensoryPerceptionCodeletsIds, new HashMap()); testMotivationalFromPerceptionCodeletIds.add(testMotivationalFromPerceptionCodelet.getId()); motivationalCodelets.add(testMotivationalFromPerceptionCodelet); @@ -117,45 +128,20 @@ public static void setup() throws InterruptedException { e.printStackTrace(); } - ArrayList testMotivationalFromPlanningCodeletIds = new ArrayList<>(); - - TestMotivationalFromPlanningCodelet testMotivationalFromPlanningCodelet; - - try { - - testMotivationalFromPlanningCodelet = new TestMotivationalFromPlanningCodelet("TestMotivationalFromPlanningCodelet", 0, 0.5, 0.9, sensoryCodeletsIds, new HashMap()); - testMotivationalFromPlanningCodeletIds.add(testMotivationalFromPlanningCodelet.getId()); - motivationalCodelets.add(testMotivationalFromPlanningCodelet); - } catch (CodeletActivationBoundsException e) { - e.printStackTrace(); - } - /* * Last step is to create the behavioral codelets, * They receive the ids of the perceptual codelets and * motor codelets, in order to be glued to them, according * to the reference architecture. */ + + activityCodelets = new ArrayList<>(); - List actionFromPerceptionCodelets = new ArrayList<>(); - - Test1ActionFromPerceptionCodelet test1ActionFromPerceptionCodelet = new Test1ActionFromPerceptionCodelet("Test1ActionFromPerceptionCodelet", perceptualCodeletsIds, testMotivationalFromPerceptionCodeletIds, testMotorCodelet.getId(), null); - actionFromPerceptionCodelets.add(test1ActionFromPerceptionCodelet); - - List actionFromPlanningCodelets = new ArrayList<>(); - - Test1ActionFromPlanningCodelet test1ActionFromPlanningCodelet = new Test1ActionFromPlanningCodelet("Test1ActionFromPlanningCodelet", perceptualCodeletsIds, testMotorCodelet.getId(), null); - actionFromPlanningCodelets.add(test1ActionFromPlanningCodelet); - - Test2ActionFromPlanningCodelets test2ActionFromPlanningCodelets = new Test2ActionFromPlanningCodelets("Test2ActionFromPlanningCodelets", perceptualCodeletsIds, testMotorCodelet.getId(), null); - actionFromPlanningCodelets.add(test2ActionFromPlanningCodelets); - - List behaviorCodelets = new ArrayList<>(); - - ActionSequencePlan test1Test2ActionSequence = new ActionSequencePlan(new String[] {"Test1ActionFromPlanningCodelet","Test2ActionFromPlanningCodelets"}); - - Test1AndTest2BehaviorCodelet test1AndTest2BehaviorCodelet = new Test1AndTest2BehaviorCodelet("Test1AndTest2BehaviorCodelet", perceptualCodeletsIds, testMotivationalFromPlanningCodeletIds, null, test1Test2ActionSequence); - behaviorCodelets.add(test1AndTest2BehaviorCodelet); + Test1ActivityCodelet test1ActivityCodelet = new Test1ActivityCodelet("Test1Activity", perceptualPerceptionCodeletsIds, testMotivationalFromPerceptionCodeletIds, testMotorCodelet.getId(), null); + activityCodelets.add(test1ActivityCodelet); + + planningCodelet = new TestSoarCodelet("soar"); + /* * Inserting the System 1 codelets inside MECA mind @@ -164,10 +150,22 @@ public static void setup() throws InterruptedException { mecaMind.setIMotorCodelets(motorCodelets); mecaMind.setPerceptualCodelets(perceptualCodelets); mecaMind.setMotivationalCodelets(motivationalCodelets); - mecaMind.setActionFromPerceptionCodelets(actionFromPerceptionCodelets); - mecaMind.setActionFromPlanningCodelets(actionFromPlanningCodelets); - mecaMind.setBehaviorCodelets(behaviorCodelets); + mecaMind.setActivityCodelets(activityCodelets); + mecaMind.setPlanningCodelet(planningCodelet); + + + } + + @AfterAll + public static void tearDown() { + mv.setVisible(false); + mecaMind.shutDown(); + } + + @Test + public void testMecaMindMountActivityReactWin() throws InterruptedException { + /* * After passing references to the codelets, we call the method 'MecaMind.mountMecaMind()', which * is responsible for wiring the MecaMind altogether according to the reference architecture, including @@ -190,40 +188,24 @@ public static void setup() throws InterruptedException { * codelets, which activation has a pivotal role. */ List listOfCodelets = new ArrayList<>(); - listOfCodelets.addAll(mecaMind.getActionFromPerceptionCodelets()); - listOfCodelets.addAll(mecaMind.getActionFromPlanningCodelets()); - listOfCodelets.addAll(mecaMind.getBehaviorCodelets()); + listOfCodelets.addAll(mecaMind.getActivityCodelets()); mv = new MindViewer(mecaMind, "MECA Mind Inspection - "+mecaMind.getId(), listOfCodelets); mv.setVisible(true); Thread.sleep(1000); - } - - @AfterClass - public static void tearDown() { - - mv.setVisible(false); - mecaMind.shutDown(); - } - - @Test - public void testMecaMindMountActionFromPerceptionWin() throws InterruptedException { - //do something String contentInTheEnvironment = "Something"; testPerceptionSensoryCodelet.setSensoryContents(contentInTheEnvironment); - testPlanningSensoryCodelet.setSensoryContents(null); - Thread.sleep(1000); //test something - String messageExpected = "Test1ActionFromPerception - A black dog"; + String messageExpected = "Test1Activity - A black dog"; MemoryContainer motorMemory = (MemoryContainer) testMotorCodelet.getInput("TestMotorCodelet"); @@ -235,8 +217,92 @@ public void testMecaMindMountActionFromPerceptionWin() throws InterruptedExcepti } @Test - public void testMecaMindMountActionFromPlanningWin() throws InterruptedException { + public void testMecaMindMountActivityFromPlanningWin() throws InterruptedException { + + ArrayList sensoryPlanningCodeletsIds = new ArrayList<>(); + testPlanningSensoryCodelet = new TestPlanningSensoryCodelet("TestPlanningSensoryCodelet"); + sensoryCodelets.add(testPlanningSensoryCodelet); + sensoryPlanningCodeletsIds.add(testPlanningSensoryCodelet.getId()); + + ArrayList perceptualPlanningCodeletsIds = new ArrayList<>(); + TestPerceptualCodelet testPlanningCodelet = new TestPerceptualCodelet("TestPlanningCodelet", sensoryPlanningCodeletsIds); + perceptualPlanningCodeletsIds.add(testPlanningCodelet.getId()); + perceptualCodelets.add(testPlanningCodelet); + + ArrayList testMotivationalFromPlanningCodeletIds = new ArrayList<>(); + + TestMotivationalFromPlanningCodelet testMotivationalFromPlanningCodelet; + + try { + + testMotivationalFromPlanningCodelet = new TestMotivationalFromPlanningCodelet("TestMotivationalFromPlanningCodelet", 0, 0.5, 0.9, sensoryPlanningCodeletsIds, new HashMap()); + testMotivationalFromPlanningCodeletIds.add(testMotivationalFromPlanningCodelet.getId()); + motivationalCodelets.add(testMotivationalFromPlanningCodelet); + } catch (CodeletActivationBoundsException e) { + e.printStackTrace(); + } + + Test2ActivityCodelet test2ActivityCodelet = new Test2ActivityCodelet("Test2Activity", perceptualPlanningCodeletsIds, testMotivationalFromPlanningCodeletIds, testMotorCodelet.getId(), null); + activityCodelets.add(test2ActivityCodelet); + + Test3ActivityCodelet test3ActivityCodelets = new Test3ActivityCodelet("Test3Activity", perceptualPlanningCodeletsIds, testMotivationalFromPlanningCodeletIds, testMotorCodelet.getId(), null); + activityCodelets.add(test3ActivityCodelets); + + ActivityTrackingCodelet activityTrackingCodelet = new ActivityTrackingCodelet("ActivityTrackingCodelet", perceptualPlanningCodeletsIds) { + + @Override + public void trackActionSequencePlan(ArrayList perceptualMemories, ActionSequencePlan actionSequencePlan) { + + if(actionSequencePlan == null || actionSequencePlan.getActionStepSequence() == null) { + return; + } + + actionSequencePlan.setCurrentActionIdIndex(0); + + //In this test, will never go on to the second action. We could have limit on perceptual memory to move on, though. + } + }; + + + List behaviorCodelets = new ArrayList<>(); + + Test1AndTest2BehaviorCodelet test1AndTest2BehaviorCodelet = new Test1AndTest2BehaviorCodelet("Test1AndTest2BehaviorCodelet", perceptualPlanningCodeletsIds, testMotivationalFromPlanningCodeletIds, null); + behaviorCodelets.add(test1AndTest2BehaviorCodelet); + + mecaMind.setBehaviorCodelets(behaviorCodelets); + mecaMind.setActivityTrackingCodelet(activityTrackingCodelet); + + /* + * After passing references to the codelets, we call the method 'MecaMind.mountMecaMind()', which + * is responsible for wiring the MecaMind altogether according to the reference architecture, including + * the creation of memory objects and containers which glue them together. This method is of pivotal + * importance and inside it resides all the value from the reference architecture created - the idea is + * that the user only has to create the codelets, put them inside lists of differente types and call + * this method, which transparently glue the codelets together accordingly to the MECA reference + * architecture. + */ + mecaMind.mountMecaMind(); + + /* + * Starting the mind + */ + mecaMind.start(); + + /* + * Instead of inserting the sensory codelets in the + * CST visualization tool, let's insert the behaviroal + * codelets, which activation has a pivotal role. + */ + List listOfCodelets = new ArrayList<>(); + listOfCodelets.addAll(mecaMind.getActivityCodelets()); + listOfCodelets.addAll(mecaMind.getBehaviorCodelets()); + + mv = new MindViewer(mecaMind, "MECA Mind Inspection - "+mecaMind.getId(), listOfCodelets); + mv.setVisible(true); + + Thread.sleep(1000); + //do something String contentInTheEnvironment = "Something"; @@ -249,7 +315,7 @@ public void testMecaMindMountActionFromPlanningWin() throws InterruptedException //test something - String messageExpected = "Test1ActionFromPlanning - A black dog"; + String messageExpected = "Test2Activity - A black dog"; MemoryContainer motorMemory = (MemoryContainer) testMotorCodelet.getInput("TestMotorCodelet"); diff --git a/src/test/java/br/unicamp/meca/mind/action/Test1ActionFromPlanningCodelet.java b/src/test/java/br/unicamp/meca/mind/action/Test1ActionFromPlanningCodelet.java deleted file mode 100644 index 1ed9c58..0000000 --- a/src/test/java/br/unicamp/meca/mind/action/Test1ActionFromPlanningCodelet.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * - */ -package br.unicamp.meca.mind.action; - -import java.util.ArrayList; - -import br.unicamp.cst.core.entities.Memory; -import br.unicamp.cst.core.entities.MemoryContainer; -import br.unicamp.meca.system1.codelets.ActionFromPlanningCodelet; - -/** - * @author andre - * - */ -public class Test1ActionFromPlanningCodelet extends ActionFromPlanningCodelet { - - public Test1ActionFromPlanningCodelet(String id, ArrayList perceptualCodeletsIds, String motorCodeletId, - String soarCodeletId) { - super(id, perceptualCodeletsIds, motorCodeletId, soarCodeletId); - } - - @Override - public void proc(ArrayList perceptualMemories, Memory broadcastMemory, Memory motorMemory) { - if(perceptualMemories == null || perceptualMemories.size() == 0) { - return; - } - - motorMemory.setI(null); - - for(Memory memory: perceptualMemories) { - if(memory.getI()!=null && memory.getI() instanceof String) { - String perceptualContent = (String) memory.getI(); - - ((MemoryContainer) motorMemory).setI("Test1ActionFromPlanning - "+perceptualContent,getActivation(),id); - } - } - } -} diff --git a/src/test/java/br/unicamp/meca/mind/action/Test1ActivityCodelet.java b/src/test/java/br/unicamp/meca/mind/action/Test1ActivityCodelet.java new file mode 100644 index 0000000..89b2d77 --- /dev/null +++ b/src/test/java/br/unicamp/meca/mind/action/Test1ActivityCodelet.java @@ -0,0 +1,52 @@ +/** + * + */ +package br.unicamp.meca.mind.action; + +import java.util.ArrayList; + +import br.unicamp.cst.core.entities.Memory; +import br.unicamp.cst.core.entities.MemoryContainer; +import br.unicamp.meca.system1.codelets.ActivityCodelet; + +/** + * @author andre + * + */ +public class Test1ActivityCodelet extends ActivityCodelet { + + /** + * @param id + * @param perceptualCodeletsIds + * @param motivationalCodeletsIds + * @param motorCodeletId + * @param soarCodeletId + */ + public Test1ActivityCodelet(String id, ArrayList perceptualCodeletsIds, + ArrayList motivationalCodeletsIds, String motorCodeletId, String soarCodeletId) { + super(id, perceptualCodeletsIds, motivationalCodeletsIds, motorCodeletId, soarCodeletId); + } + + @Override + public void doConclusion(ArrayList perceptualMemories, Memory broadcastMemory, Memory motorMemory) { + System.out.println("Concluding "+id); + ((MemoryContainer) motorMemory).setI(id+" - concluded",getActivation(),id); + } + + @Override + public void proc(ArrayList perceptualMemories, Memory broadcastMemory, Memory motorMemory) { + if(perceptualMemories == null || perceptualMemories.size() == 0) { + return; + } + + ((MemoryContainer) motorMemory).setI(null,0.0,id); + + for(Memory memory: perceptualMemories) { + if(memory.getI()!=null && memory.getI() instanceof String) { + String perceptualContent = (String) memory.getI(); + + ((MemoryContainer) motorMemory).setI(id+" - "+perceptualContent,getActivation(),id); + } + } + } +} diff --git a/src/test/java/br/unicamp/meca/mind/action/Test2ActionFromPlanningCodelets.java b/src/test/java/br/unicamp/meca/mind/action/Test2ActionFromPlanningCodelets.java deleted file mode 100644 index ece7ea5..0000000 --- a/src/test/java/br/unicamp/meca/mind/action/Test2ActionFromPlanningCodelets.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * - */ -package br.unicamp.meca.mind.action; - -import java.util.ArrayList; - -import br.unicamp.cst.core.entities.Memory; -import br.unicamp.cst.core.entities.MemoryContainer; -import br.unicamp.meca.system1.codelets.ActionFromPlanningCodelet; - -/** - * @author andre - * - */ -public class Test2ActionFromPlanningCodelets extends ActionFromPlanningCodelet { - - public Test2ActionFromPlanningCodelets(String id, ArrayList perceptualCodeletsIds, String motorCodeletId, - String soarCodeletId) { - super(id, perceptualCodeletsIds, motorCodeletId, soarCodeletId); - } - - @Override - public void proc(ArrayList perceptualMemories, Memory broadcastMemory, Memory motorMemory) { - if(perceptualMemories == null || perceptualMemories.size() == 0) { - return; - } - - motorMemory.setI(null); - - for(Memory memory: perceptualMemories) { - if(memory.getI()!=null && memory.getI() instanceof String) { - String perceptualContent = (String) memory.getI(); - - ((MemoryContainer) motorMemory).setI("Test2ActionFromPlanning - "+perceptualContent,getActivation(),id); - } - } - - } - -} diff --git a/src/test/java/br/unicamp/meca/mind/action/Test2ActivityCodelet.java b/src/test/java/br/unicamp/meca/mind/action/Test2ActivityCodelet.java new file mode 100644 index 0000000..22ad0bc --- /dev/null +++ b/src/test/java/br/unicamp/meca/mind/action/Test2ActivityCodelet.java @@ -0,0 +1,51 @@ +/** + * + */ +package br.unicamp.meca.mind.action; + +import java.util.ArrayList; + +import br.unicamp.cst.core.entities.Memory; +import br.unicamp.cst.core.entities.MemoryContainer; +import br.unicamp.meca.system1.codelets.ActivityCodelet; + +/** + * @author andre + * + */ +public class Test2ActivityCodelet extends ActivityCodelet { + + /** + * @param id + * @param perceptualCodeletsIds + * @param motivationalCodeletsIds + * @param motorCodeletId + * @param soarCodeletId + */ + public Test2ActivityCodelet(String id, ArrayList perceptualCodeletsIds, + ArrayList motivationalCodeletsIds, String motorCodeletId, String soarCodeletId) { + super(id, perceptualCodeletsIds, motivationalCodeletsIds, motorCodeletId, soarCodeletId); + } + + @Override + public void doConclusion(ArrayList perceptualMemories, Memory broadcastMemory, Memory motorMemory) { + System.out.println("Concluding Test2Activity"); + } + + @Override + public void proc(ArrayList perceptualMemories, Memory broadcastMemory, Memory motorMemory) { + if(perceptualMemories == null || perceptualMemories.size() == 0) { + return; + } + + ((MemoryContainer) motorMemory).setI(null,0.0,id); + + for(Memory memory: perceptualMemories) { + if(memory.getI()!=null && memory.getI() instanceof String) { + String perceptualContent = (String) memory.getI(); + + ((MemoryContainer) motorMemory).setI("Test2Activity - "+perceptualContent,getActivation(),id); + } + } + } +} diff --git a/src/test/java/br/unicamp/meca/mind/action/Test1ActionFromPerceptionCodelet.java b/src/test/java/br/unicamp/meca/mind/action/Test3ActivityCodelet.java similarity index 52% rename from src/test/java/br/unicamp/meca/mind/action/Test1ActionFromPerceptionCodelet.java rename to src/test/java/br/unicamp/meca/mind/action/Test3ActivityCodelet.java index 6262a3a..01ba847 100644 --- a/src/test/java/br/unicamp/meca/mind/action/Test1ActionFromPerceptionCodelet.java +++ b/src/test/java/br/unicamp/meca/mind/action/Test3ActivityCodelet.java @@ -7,35 +7,45 @@ import br.unicamp.cst.core.entities.Memory; import br.unicamp.cst.core.entities.MemoryContainer; -import br.unicamp.meca.system1.codelets.ActionFromPerceptionCodelet; +import br.unicamp.meca.system1.codelets.ActivityCodelet; /** * @author andre * */ -public class Test1ActionFromPerceptionCodelet extends ActionFromPerceptionCodelet { +public class Test3ActivityCodelet extends ActivityCodelet { - public Test1ActionFromPerceptionCodelet(String id, ArrayList perceptualCodeletsIds, + /** + * @param id + * @param perceptualCodeletsIds + * @param motivationalCodeletsIds + * @param motorCodeletId + * @param soarCodeletId + */ + public Test3ActivityCodelet(String id, ArrayList perceptualCodeletsIds, ArrayList motivationalCodeletsIds, String motorCodeletId, String soarCodeletId) { super(id, perceptualCodeletsIds, motivationalCodeletsIds, motorCodeletId, soarCodeletId); } + + @Override + public void doConclusion(ArrayList perceptualMemories, Memory broadcastMemory, Memory motorMemory) { + System.out.println("Concluding Test3Activity"); + } @Override public void proc(ArrayList perceptualMemories, Memory broadcastMemory, Memory motorMemory) { - if(perceptualMemories == null || perceptualMemories.size() == 0) { return; } - motorMemory.setI(null); + ((MemoryContainer) motorMemory).setI(null,0.0,id); for(Memory memory: perceptualMemories) { if(memory.getI()!=null && memory.getI() instanceof String) { String perceptualContent = (String) memory.getI(); - ((MemoryContainer) motorMemory).setI("Test1ActionFromPerception - "+perceptualContent,getActivation(),id); + ((MemoryContainer) motorMemory).setI("Test3Activity - "+perceptualContent,getActivation(),id); } } } - } diff --git a/src/test/java/br/unicamp/meca/mind/action/TestActivityCodelet.java b/src/test/java/br/unicamp/meca/mind/action/TestActivityCodelet.java new file mode 100644 index 0000000..2ac06f3 --- /dev/null +++ b/src/test/java/br/unicamp/meca/mind/action/TestActivityCodelet.java @@ -0,0 +1,152 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package br.unicamp.meca.mind.action; + +import br.unicamp.cst.core.entities.MemoryContainer; +import br.unicamp.cst.core.entities.MemoryObject; +import br.unicamp.meca.mind.MecaMind; +import br.unicamp.meca.mind.motor.TestMotorCodelet; +import br.unicamp.meca.mind.perceptual.TestPerceptualCodelet; +import br.unicamp.meca.mind.sensory.TestPerceptionSensoryCodelet; +import br.unicamp.meca.models.ActionSequencePlan; +import br.unicamp.meca.models.ActionStep; +import br.unicamp.meca.models.ActionStepTest; +import br.unicamp.meca.system1.codelets.ActivityCodelet; +import br.unicamp.meca.system1.codelets.MotorCodelet; +import br.unicamp.meca.system1.codelets.PerceptualCodelet; +import br.unicamp.meca.system1.codelets.SensoryCodelet; +import java.util.ArrayList; +import static org.junit.Assert.assertEquals; +import org.junit.jupiter.api.Test; + +/** + * + * @author rgudwin + */ +public class TestActivityCodelet { + + SensoryCodelet sc; + PerceptualCodelet pc; + ActivityCodelet ac; + + @Test + public void testAccessMemoryObjects() { + ArrayList lsc = new ArrayList(); + lsc.add("m1"); + lsc.add("m2"); + lsc.add("m3"); + ac = new Test1ActivityCodelet("teste",lsc,lsc,null,null); + ac.accessMemoryObjects(); + assertEquals(ac.getPerceptionMemories().size(),0); + MemoryObject mo = new MemoryObject(); + mo.setType("m1"); + ac.addInput(mo); + mo = new MemoryObject(); + mo.setType("m2"); + ac.addInput(mo); + mo = new MemoryObject(); + mo.setType("m3"); + ac.addInput(mo); + ac.accessMemoryObjects(); + assertEquals(ac.getPerceptionMemories().size(),3); + mo = new MemoryObject(); + mo.setType("m1Drive"); + ac.addInput(mo); + mo = new MemoryObject(); + mo.setType("m2Drive"); + ac.addInput(mo); + mo = new MemoryObject(); + mo.setType("m3Drive"); + ac.addInput(mo); + ac.accessMemoryObjects(); + assertEquals(ac.getDriveMemories().size(),3); + ac = new Test1ActivityCodelet("teste",null,null,"motor","soar"); + mo = new MemoryObject(); + mo.setType("motor"); + ac.addOutput(mo); + ac.accessMemoryObjects(); + assertEquals(ac.getMotorMemory(),mo); + mo = new MemoryObject(); + mo.setType("soar"); + ac.addBroadcast(mo); + ac.accessMemoryObjects(); + assertEquals(ac.getBroadcastMemory(),mo); + MemoryContainer mc = new MemoryContainer(); + mc.setType(MecaMind.ACTION_SEQUENCE_PLAN_ID); + ac.addInput(mc); + ac.accessMemoryObjects(); + assertEquals(ac.getActionSequencePlanMemoryContainer(),mc); + } + + @Test + public void testActivityCodelet() { + sc = new TestPerceptionSensoryCodelet("sensory"); + ArrayList lsc = new ArrayList(); + lsc.add("sensory"); + pc = new TestPerceptualCodelet("perception",lsc); + lsc = new ArrayList(); + ac = new Test1ActivityCodelet("teste",null,null,null,null); + ac.accessMemoryObjects(); + ac.proc(); + ac.calculateActivation(); + + ac = new Test1ActivityCodelet("teste",lsc,lsc,null,null); + ac.accessMemoryObjects(); + ac.proc(); + ac.calculateActivation(); + + ac = new Test1ActivityCodelet("teste",lsc,lsc,"motor",null); + ac.accessMemoryObjects(); + ac.proc(); + ac.calculateActivation(); + + MotorCodelet mc = new TestMotorCodelet("motor"); + ac.accessMemoryObjects(); + ac.proc(); + ac.calculateActivation(); + + } + + @Test + public void testCalculateActivation() { + ArrayList lsc = new ArrayList(); + lsc.add("m1"); + lsc.add("m2"); + lsc.add("m3"); + ac = new Test1ActivityCodelet("teste",null,lsc,null,null); + MemoryObject mo = new MemoryObject(); + mo.setType("m1Drive"); + mo.setEvaluation(0.5); + ac.addInput(mo); + mo = new MemoryObject(); + mo.setType("m2Drive"); + mo.setEvaluation(0.6); + ac.addInput(mo); + mo = new MemoryObject(); + mo.setType("m3Drive"); + ac.addInput(mo); + mo.setEvaluation(0.8); + ac.accessMemoryObjects(); + ac.calculateActivation(); + double presumedActivation = (0.5+0.6+0.8)/3; + assertEquals(ac.getActivation(),presumedActivation,0); + MemoryContainer mc = new MemoryContainer(); + mc.setType(MecaMind.ACTION_SEQUENCE_PLAN_ID); + ActionStep as[] = new ActionStep[1]; + ActionSequencePlan asp = new ActionSequencePlan(as); + mc.setI(asp,0.2); + ac.addInput(mc); + ac.accessMemoryObjects(); + ac.calculateActivation(); + // Because the ActionStep is null, the evaluation is 0 + assertEquals(ac.getActivation(),0,0); + as[0] = new ActionStepTest("teste"); + // Now that there is an action step with the same name as the ActivityCodelet, it should be 0.2 + ac.calculateActivation(); + assertEquals(ac.getActivation(),0.2,0); + } + +} diff --git a/src/test/java/br/unicamp/meca/mind/behavior/Test1AndTest2BehaviorCodelet.java b/src/test/java/br/unicamp/meca/mind/behavior/Test1AndTest2BehaviorCodelet.java index e522225..13b88a0 100644 --- a/src/test/java/br/unicamp/meca/mind/behavior/Test1AndTest2BehaviorCodelet.java +++ b/src/test/java/br/unicamp/meca/mind/behavior/Test1AndTest2BehaviorCodelet.java @@ -7,6 +7,8 @@ import br.unicamp.cst.core.entities.Memory; import br.unicamp.meca.models.ActionSequencePlan; +import br.unicamp.meca.models.ActionStep; +import br.unicamp.meca.models.ActionStepTest; import br.unicamp.meca.system1.codelets.BehaviorCodelet; /** @@ -14,22 +16,24 @@ * */ public class Test1AndTest2BehaviorCodelet extends BehaviorCodelet { + + private ActionSequencePlan actionSequencePlan; public Test1AndTest2BehaviorCodelet(String id, ArrayList perceptualCodeletsIds, - ArrayList motivationalCodeletsIds, String soarCodeletId, ActionSequencePlan actionSequencePlan) { - super(id, perceptualCodeletsIds, motivationalCodeletsIds, soarCodeletId, actionSequencePlan); + ArrayList motivationalCodeletsIds, String soarCodeletId) { + super(id, perceptualCodeletsIds, motivationalCodeletsIds, soarCodeletId); } @Override - public void trackActionSequencePlan(ArrayList perceptualMemories, ActionSequencePlan actionSequencePlan) { + protected ActionSequencePlan buildActionSequencePlan(ArrayList perceptualMemories) { - if(actionSequencePlan == null || actionSequencePlan.getActionIdSequence() == null) { - return; + if(actionSequencePlan == null) { + ActionStep as1 = new ActionStepTest("Test2Activity"); + ActionStep as2 = new ActionStepTest("Test3Activity"); + actionSequencePlan = new ActionSequencePlan(new ActionStep[] {as1,as2}); } - - actionSequencePlan.setCurrentActionIdIndex(0); - - //In this test, will never go on to the second action. We could have limit on perceptual memory to move on, though. + + return actionSequencePlan; } } diff --git a/src/test/java/br/unicamp/meca/mind/planning/TestSoarCodelet.java b/src/test/java/br/unicamp/meca/mind/planning/TestSoarCodelet.java new file mode 100644 index 0000000..dc6dfe7 --- /dev/null +++ b/src/test/java/br/unicamp/meca/mind/planning/TestSoarCodelet.java @@ -0,0 +1,49 @@ +/** + * + */ +package br.unicamp.meca.mind.planning; + +import java.io.File; + +import br.unicamp.meca.system2.codelets.SoarCodelet; + +/** + * @author andre + * + */ +public class TestSoarCodelet extends SoarCodelet { + + /** + * @param id + */ + public TestSoarCodelet(String id) { + super(id); + // TODO Auto-generated constructor stub + } + + /** + * @param id + * @param path_to_commands + * @param _agentName + * @param _productionPath + * @param startSOARDebugger + */ + public TestSoarCodelet(String id, String path_to_commands, String _agentName, File _productionPath, + Boolean startSOARDebugger) { + super(id, path_to_commands, _agentName, _productionPath, startSOARDebugger); + // TODO Auto-generated constructor stub + } + + @Override + public void fromPlanToAction() { + // TODO Auto-generated method stub + + } + + @Override + public void calculateActivation() { + // TODO Auto-generated method stub + + } + +} diff --git a/src/test/java/br/unicamp/meca/mind/tracking/testActivityTrackingCodelet.java b/src/test/java/br/unicamp/meca/mind/tracking/testActivityTrackingCodelet.java new file mode 100644 index 0000000..6a1e967 --- /dev/null +++ b/src/test/java/br/unicamp/meca/mind/tracking/testActivityTrackingCodelet.java @@ -0,0 +1,259 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package br.unicamp.meca.mind.tracking; + +import br.unicamp.cst.core.entities.MemoryContainer; +import br.unicamp.cst.core.entities.MemoryObject; +import br.unicamp.meca.mind.MecaMind; +import br.unicamp.meca.mind.action.Test1ActivityCodelet; +import br.unicamp.meca.models.ActionSequencePlan; +import br.unicamp.meca.models.ActionStep; +import br.unicamp.meca.models.ActionStepTest; +import br.unicamp.meca.system1.codelets.ActivityCodelet; +import br.unicamp.meca.system1.codelets.ActivityTrackingCodelet; +import java.util.ArrayList; +import static org.junit.Assert.assertEquals; +import org.junit.jupiter.api.Test; + +/** + * + * @author rgudwin + */ +public class testActivityTrackingCodelet { + ActivityTrackingCodelet atc; + ActivityCodelet actc1; + ActivityCodelet actc2; + + @Test + public void testActivityTrackingCodelet() { + atc = new ActivityTrackingCodelet("tracking",null); + atc.accessMemoryObjects(); + atc.calculateActivation(); + // This tests the case when there is still no sequence plan to be tracked + atc.proc(); + // Now let's introduce an empty perception list + ArrayList lop = new ArrayList(); + atc = new ActivityTrackingCodelet("tracking",lop); + atc.accessMemoryObjects(); + atc.calculateActivation(); + atc.proc(); + // Now let's define an inexistent perception + lop.add("perception"); + atc.accessMemoryObjects(); + atc.calculateActivation(); + atc.proc(); + // Now, still without perception, let's introduce a sequence plan + MemoryContainer mc = new MemoryContainer(); + mc.setType(MecaMind.ACTION_SEQUENCE_PLAN_ID); + atc.addInput(mc); + atc.accessMemoryObjects(); + // Now there is a memory object, but still no sequence plan + atc.accessMemoryObjects(); + atc.calculateActivation(); + atc.proc(); + // Now let's include a plan, but still without any action step + ActionStep as[] = new ActionStep[3]; + ActionSequencePlan asp = new ActionSequencePlan(as); + mc.setI(asp,0.2); + atc.accessMemoryObjects(); + atc.calculateActivation(); + atc.proc(); + // Finally, let's include the action steps + ActionStep as1 = new ActionStepTest("tracking"); + as[0] = as1; + ActionStep as2 = new ActionStepTest("tracking"); + as[1] = as2; + ActionStep as3 = new ActionStepTest("tracking"); + as[2] = as3; + atc.accessMemoryObjects(); + atc.calculateActivation(); + atc.proc(); + assertEquals(asp.getCurrentActionIdIndex(),0); + // Now let's introduce a Perception Memory to track + // And now finally let's provide an existent perception, still without info + MemoryObject per = new MemoryObject(); + per.setType("perception"); + atc = new ActivityTrackingCodelet("tracking",lop); + atc.addInput(per); + atc.addInput(mc); + atc.accessMemoryObjects(); + atc.calculateActivation(); + atc.proc(); + assertEquals(asp.getCurrentActionIdIndex(),0); + // Now, let's create the conditions for the codelet decide to move to its 2nd step + per.setEvaluation(1.0); + atc.addInput(per); + //as[0].needsConclusion = true; + atc.accessMemoryObjects(); + atc.calculateActivation(); + assertEquals(as[0].executed,false); + atc.proc(); + // Now, because there are conditions for move to the second step of the plan, the index should be 1 + assertEquals(as[0].executed,true); + // Because the ActionStep 0 was executed, now it needs conclusion + assertEquals(as[0].needsConclusion,true); + assertEquals(asp.getCurrentActionIdIndex(),1); + assertEquals(as[1].executed,false); + atc.proc(); + // Now let's play a little ... because the conclusion didn't come, this proc will not move to the 3rd action step + assertEquals(as[1].executed,false); + // Let's then conclude the action step 0 e see what happens + as[0].needsConclusion = false; + atc.proc(); + // Now, this allows the execution of action step 1 + assertEquals(as[1].executed,true); + assertEquals(asp.getCurrentActionIdIndex(),2); + assertEquals(as[2].executed,false); + assertEquals(as[1].needsConclusion,true); + as[1].needsConclusion = false; + atc.proc(); + assertEquals(as[2].needsConclusion,true); + assertEquals(asp.getCurrentActionIdIndex(),0); + assertEquals(as[2].executed,true); + } + + @Test + public void testDoConclusion() { + // Creation of the Perception Memory + ArrayList lop = new ArrayList(); + MemoryObject per = new MemoryObject(); + per.setType("perception"); + per.setI("perception"); + lop.add("perception"); + atc = new ActivityTrackingCodelet("tracking",lop); + atc.addInput(per); + // Creation of the ActionSequencePlan + MemoryContainer planContainer = new MemoryContainer(); + planContainer.setType(MecaMind.ACTION_SEQUENCE_PLAN_ID); + ActionStep as1 = new ActionStepTest("activity1"); + ActionStep as2 = new ActionStepTest("activity2"); + ActionSequencePlan asp = new ActionSequencePlan(new ActionStep[] {as1,as2}); + planContainer.setI(asp,0.2,"plan"); + atc.addInput(planContainer); + // Creation of the MotorMemory + MemoryContainer motorMemory = new MemoryContainer(); + motorMemory.setType("motor"); + // Now creating the ActivityCodelets which will serve the ActionStep + actc1 = new Test1ActivityCodelet("activity1",lop,null,"motor",null); + actc1.addInput(per); + actc1.addInput(planContainer); + actc1.addOutput(motorMemory); + actc2 = new Test1ActivityCodelet("activity2",lop,null,"motor",null); + actc2.addInput(per); + actc2.addInput(planContainer); + actc2.addOutput(motorMemory); + // Execute the 1st time step + step(); + // Verifying if the activity1 modified the motor codelet + assertEquals(motorMemory.getI(),"activity1 - perception"); + // now let's cause the ActivityTrackingCodelet to conclude step 1 and move to step 2 + per.setEvaluation(1.0); + // And change the activation to a lower value than activity1 ... + // if activity1 is not concluded by doConclusion, it will stay at the motor codelet and ruin the output of motorCodelet + planContainer.setI(asp,0.1,"plan"); + step(); + // Let's first verify if the plan was advanced to step 2 + assertEquals(asp.getCurrentActionIdIndex(),1); + // Let's verify if activity2 modified the motor codelet + assertEquals(motorMemory.getI(),"activity2 - perception"); + // Let's verify if activity1 was concluded + assertEquals(motorMemory.getI(0),"activity1 - concluded"); + // Now let's do one more step to conclude the plan + step(); + // And verify the plan is back to step 1 and executed + assertEquals(asp.getCurrentActionIdIndex(),0); + assertEquals(asp.getCurrentActionStep().executed,true); + assertEquals(asp.getLastExecutedActionStep().executed,true); + // Let's do a final step and check if everything remains the same + step(); + assertEquals(asp.getCurrentActionIdIndex(),0); + assertEquals(asp.getCurrentActionStep().executed,true); + assertEquals(asp.getLastExecutedActionStep().executed,true); + + } + + @Test + public void testTwoActionStepsOfSameType() { + // Creation of the Perception Memory + ArrayList lop = new ArrayList(); + MemoryObject per = new MemoryObject(); + per.setType("perception"); + per.setI("perception"); + lop.add("perception"); + atc = new ActivityTrackingCodelet("tracking",lop); + atc.addInput(per); + // Creation of the ActionSequencePlan + MemoryContainer planContainer = new MemoryContainer(); + planContainer.setType(MecaMind.ACTION_SEQUENCE_PLAN_ID); + ActionStep as1 = new ActionStepTest("activity1"); + ActionStep as2 = new ActionStepTest("activity1"); // The 2nd actionstep is treated by the same ActivityCodelet + ActionSequencePlan asp = new ActionSequencePlan(new ActionStep[] {as1,as2}); + planContainer.setI(asp,0.2,"plan"); + atc.addInput(planContainer); + // Creation of the MotorMemory + MemoryContainer motorMemory = new MemoryContainer(); + motorMemory.setType("motor"); + // Now creating the ActivityCodelet which will serve the ActionStep + actc1 = new Test1ActivityCodelet("activity1",lop,null,"motor",null); + actc1.addInput(per); + actc1.addInput(planContainer); + actc1.addOutput(motorMemory); + // Execute the 1st time step + step2(); + // Verifying if the activity1 modified the motor codelet + assertEquals(motorMemory.getI(),"activity1 - perception"); + // now let's cause the ActivityTrackingCodelet to conclude step 1 and move to step 2 + per.setEvaluation(1.0); + // And change the activation to a lower value than activity1 ... + // if activity1 is not concluded by doConclusion, it will stay at the motor codelet and ruin the output of motorCodelet + planContainer.setI(asp,0.1,"plan"); + step2(); + // Let's first verify if the plan was advanced to step 2 + assertEquals(asp.getCurrentActionIdIndex(),1); + // The conclusion of step1 can only be verified by the log, as the motorMemory is immediately rewritten by step2 + // A "Concluding activity1" message should have appeared in the log + // But we can still check the needsConclusion flag, which should be cleared + assertEquals(asp.getLastExecutedActionStep().needsConclusion,false); + // Now let's do one more step to conclude the plan + step2(); + // And verify the plan is back to step 1 and executed + assertEquals(asp.getCurrentActionIdIndex(),0); + assertEquals(asp.getCurrentActionStep().needsConclusion,false); + assertEquals(asp.getCurrentActionStep().executed,true); + assertEquals(asp.getLastExecutedActionStep().needsConclusion,false); + assertEquals(asp.getLastExecutedActionStep().executed,true); + // Let's do a final step and check if everything remains the same + step2(); + assertEquals(asp.getCurrentActionIdIndex(),0); + assertEquals(asp.getCurrentActionStep().needsConclusion,false); + assertEquals(asp.getCurrentActionStep().executed,true); + assertEquals(asp.getLastExecutedActionStep().needsConclusion,false); + assertEquals(asp.getLastExecutedActionStep().executed,true); + } + + private void step() { + atc.accessMemoryObjects(); + atc.calculateActivation(); + atc.proc(); + actc1.accessMemoryObjects(); + actc1.calculateActivation(); + actc1.proc(); + actc2.accessMemoryObjects(); + actc2.calculateActivation(); + actc2.proc(); + } + + + private void step2() { + atc.accessMemoryObjects(); + atc.calculateActivation(); + atc.proc(); + actc1.accessMemoryObjects(); + actc1.calculateActivation(); + actc1.proc(); + } + +} diff --git a/src/test/java/br/unicamp/meca/models/ActionSequencePlanTest.java b/src/test/java/br/unicamp/meca/models/ActionSequencePlanTest.java index 3a20afc..4b3f4e4 100644 --- a/src/test/java/br/unicamp/meca/models/ActionSequencePlanTest.java +++ b/src/test/java/br/unicamp/meca/models/ActionSequencePlanTest.java @@ -5,27 +5,98 @@ import static org.junit.Assert.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * @author andre * */ public class ActionSequencePlanTest { + + ActionStep as1 = new ActionStepTest("Land"); + ActionStep as2 = new ActionStepTest("Stop"); + ActionSequencePlan landAndStopSequencePlan = new ActionSequencePlan(new ActionStep[] {as1,as2}); public void setUp() { System.out.println("########## Action Sequence Plan TESTS ##########"); } + + @Test + public void testGetCurrentActionIdIndex() { + landAndStopSequencePlan.setCurrentActionIdIndex(0); + int currentStep = landAndStopSequencePlan.getCurrentActionIdIndex(); + assertEquals(currentStep,0); + landAndStopSequencePlan.setCurrentActionIdIndex(1); + currentStep = landAndStopSequencePlan.getCurrentActionIdIndex(); + assertEquals(currentStep,1); + } @Test public void testGetCurrentActionId() { - - ActionSequencePlan landAndStopSequencePlan = new ActionSequencePlan(new String[] {"Land","Stop"}); - - assertEquals(landAndStopSequencePlan.getCurrentActionId(), "Land"); - + landAndStopSequencePlan.setCurrentActionIdIndex(0); + assertEquals(landAndStopSequencePlan.getCurrentActionStep().getActionId(), "Land"); + landAndStopSequencePlan.setCurrentActionIdIndex(1); - - assertEquals(landAndStopSequencePlan.getCurrentActionId(), "Stop"); + assertEquals(landAndStopSequencePlan.getCurrentActionStep().getActionId(), "Stop"); + } + + @Test + public void testGetCurrentActionStep() { + landAndStopSequencePlan.setCurrentActionIdIndex(0); + ActionStep as = landAndStopSequencePlan.getCurrentActionStep(); + assertEquals(as,as1); + landAndStopSequencePlan.setCurrentActionIdIndex(1); + as = landAndStopSequencePlan.getCurrentActionStep(); + assertEquals(as,as2); + } + + @Test + public void testLastActionStep() { + landAndStopSequencePlan.setCurrentActionIdIndex(0); + ActionStep lastAS = landAndStopSequencePlan.getLastExecutedActionStep(); + assertEquals(lastAS,as2); + assertEquals(lastAS.executed,false); + assertEquals(lastAS.needsConclusion,false); + + landAndStopSequencePlan.setCurrentActionIdIndex(1); + lastAS = landAndStopSequencePlan.getLastExecutedActionStep(); + assertEquals(lastAS,as1); + assertEquals(lastAS.executed,false); + assertEquals(lastAS.needsConclusion,false); + } + + @Test + public void testGoToNextAction() { + landAndStopSequencePlan.setCurrentActionIdIndex(0); + ActionStep as = landAndStopSequencePlan.getCurrentActionStep(); + assertEquals(as,as1); + assertEquals(as1.executed,false); + + landAndStopSequencePlan.gotoNextAction(); + as = landAndStopSequencePlan.getCurrentActionStep(); + assertEquals(as,as2); + assertEquals(as1.executed,true); + assertEquals(as2.executed,false); + landAndStopSequencePlan.gotoNextAction(); + as = landAndStopSequencePlan.getCurrentActionStep(); + assertEquals(as,as1); + assertEquals(as2.executed,true); + } + + @Test + public void testResetPlan() { + as1.executed = true; + as2.executed = true; + landAndStopSequencePlan.resetPlan(); + for (ActionStep ass : landAndStopSequencePlan.getActionStepSequence()) { + assertEquals(ass.executed,false); + assertEquals(ass.needsConclusion,false); + } + } + + @Test + public void testToString() { + String s = landAndStopSequencePlan.toString(); + assertEquals(s,"{Land, Stop}"); } } diff --git a/src/test/java/br/unicamp/meca/models/ActionStepTest.java b/src/test/java/br/unicamp/meca/models/ActionStepTest.java new file mode 100644 index 0000000..488e3f1 --- /dev/null +++ b/src/test/java/br/unicamp/meca/models/ActionStepTest.java @@ -0,0 +1,36 @@ +package br.unicamp.meca.models; + +import br.unicamp.cst.core.entities.Memory; +import br.unicamp.meca.models.ActionStep; +import java.util.List; + +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +public class ActionStepTest extends ActionStep { + + public ActionStepTest() { + + } + + public ActionStepTest(String s) { + super(s); + } + + public void setUp() { + System.out.println("########## ActionStep TESTS ##########"); + } + + @Override + public boolean stopCondition(List perceptions) { + if (perceptions != null && perceptions.size() > 0) { + Memory perceptionMemory = perceptions.get(0); + if (perceptionMemory != null && perceptionMemory.getEvaluation() > 0.5) return(true); + else return(false); + } + return(false); + } + +} \ No newline at end of file diff --git a/src/test/java/br/unicamp/meca/models/ActionStepTester.java b/src/test/java/br/unicamp/meca/models/ActionStepTester.java new file mode 100644 index 0000000..0f4fde7 --- /dev/null +++ b/src/test/java/br/unicamp/meca/models/ActionStepTester.java @@ -0,0 +1,38 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package br.unicamp.meca.models; +import static org.junit.Assert.assertEquals; +import org.junit.jupiter.api.Test; + +/** + * + * @author rgudwin + */ +public class ActionStepTester { + + public void setUp() { + System.out.println("########## ActionStep TESTS ##########"); + } + + @Test + public void testActionStepTester() { + ActionStep as1 = new ActionStepTest(); + assertEquals(as1.getNumberOfParameters(),0); + ActionStep as2 = new ActionStepTest("TestAction"); + assertEquals(as2.getNumberOfParameters(),0); + assertEquals(as2.getActionId(),"TestAction"); + as2.setParameter("param", "value"); + assertEquals(as2.getNumberOfParameters(),1); + assertEquals(as2.getParameter("param"),"value"); + as2.setParameter("param", "value2"); + assertEquals(as2.getParameter("param"),"value2"); + as2.unsetParameter("param"); + assertEquals(as2.getNumberOfParameters(),0); + } + + + +} diff --git a/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntROS1ServiceClient.java b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntROS1ServiceClient.java new file mode 100644 index 0000000..a0ccea2 --- /dev/null +++ b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntROS1ServiceClient.java @@ -0,0 +1,75 @@ +/** + * + */ +package br.unicamp.meca.system1.codelets.rosservice; + +import java.net.URI; + +import br.unicamp.cst.core.entities.Memory; +import br.unicamp.cst.support.TimeStamp; +import br.unicamp.meca.system1.codelets.RosServiceClientMotorCodelet; +import rosjava_test_msgs.AddTwoIntsRequest; +import rosjava_test_msgs.AddTwoIntsResponse; + +/** + * @author andre + * + */ +public class AddTwoIntROS1ServiceClient extends RosServiceClientMotorCodelet { + + private volatile Integer a,b; + private volatile Integer sum; + private volatile long tsreq=0, tsresp=0; + + public AddTwoIntROS1ServiceClient(String host, URI masterURI) { + super("AddTwoIntServiceClient", "add_two_ints", rosjava_test_msgs.AddTwoInts._TYPE, host, masterURI); + } + + @Override + public boolean formatServiceRequest(Memory motorMemory, AddTwoIntsRequest serviceMessageRequest) { + if(motorMemory == null || motorMemory.getI() == null) { + return false; + } + + Integer[] numsToSum = (Integer[]) motorMemory.getI(); + a = numsToSum[0]; + b = numsToSum[1]; + serviceMessageRequest.setA(numsToSum[0]); + serviceMessageRequest.setB(numsToSum[1]); + tsreq = System.currentTimeMillis(); + System.out.println("REQUEST a = "+a+" b = "+b+" at "+TimeStamp.getStringTimeStamp(tsreq)+" with data from "+TimeStamp.getStringTimeStamp(motorMemory.getTimestamp())); + + return true; + } + + @Override + public void processServiceResponse(AddTwoIntsResponse serviceMessageResponse) { + sum = (int) serviceMessageResponse.getSum(); + tsresp = System.currentTimeMillis(); + System.out.println("RESPONSE Sum = "+sum+" at "+TimeStamp.getStringTimeStamp(tsresp)); + } + + /** + * @return the sum + */ + public synchronized Integer getSum() { + return sum; + } + + /** + * + * @return timestamp + */ + public synchronized long getTSReq() { + return tsreq; + } + + /** + * + * @return timestamp + */ + public synchronized long getTSResp() { + return tsresp; + } + +} diff --git a/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntService.java b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntROS1ServiceProvider.java similarity index 92% rename from src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntService.java rename to src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntROS1ServiceProvider.java index 59c1e34..6a91bb2 100644 --- a/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntService.java +++ b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntROS1ServiceProvider.java @@ -12,7 +12,7 @@ * @author andre * */ -public class AddTwoIntService extends AbstractNodeMain { +public class AddTwoIntROS1ServiceProvider extends AbstractNodeMain { @Override public GraphName getDefaultNodeName() { diff --git a/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntROS2ServiceClient.java b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntROS2ServiceClient.java new file mode 100644 index 0000000..6e588eb --- /dev/null +++ b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntROS2ServiceClient.java @@ -0,0 +1,92 @@ + +package br.unicamp.meca.system1.codelets.rosservice; + +import br.unicamp.cst.core.entities.Memory; +import br.unicamp.meca.system1.codelets.Ros2ServiceClientMotorCodelet; +import br.unicamp.cst.support.TimeStamp; +import troca_ros.AddTwoIntsRequestMessage; +import troca_ros.AddTwoIntsResponseMessage; +import troca_ros.AddTwoIntsServiceDefinition; + +/** + * ROS2 version of AddTwoIntServiceClient for MECA + * + * @author jrborelli + * + */ +public class AddTwoIntROS2ServiceClient extends Ros2ServiceClientMotorCodelet { + + private volatile Integer a, b; + private volatile Integer sum; + private volatile long tsReq = 0, tsResp = 0; + public boolean processing = false; + + public AddTwoIntROS2ServiceClient(String codeletName, String serviceName) { + super(codeletName, serviceName, new AddTwoIntsServiceDefinition()); + // The following line is necessary because the RosServiceClientCodelet from cst-bindings expect the Memory created by mountMecaMind to have the same name as the codelet. + // But mountMecaMind uses the id from Ros2ServiceClientMotorCodelet to create the memory. So, the id and the name must be the same + setName(codeletName); + } + + @Override + protected AddTwoIntsRequestMessage createNewRequest() { + return new AddTwoIntsRequestMessage(); + } + + @Override + protected boolean formatServiceRequest(Memory motorMemory, AddTwoIntsRequestMessage request) { + processing = true; + //System.out.println("Request"); + if (motorMemory == null || motorMemory.getI() == null) { + if (motorMemory == null) System.out.println("motorMemory is null"); + else { + if (motorMemory.getI() == null) System.out.println("motorMemory.getI() is null"); + } + return false; + } + //System.out.println("Arrived here"); + Integer[] numsToSum = (Integer[]) motorMemory.getI(); + a = numsToSum[0]; + b = numsToSum[1]; + request.withA(a).withB(b); + tsReq = System.currentTimeMillis(); + + System.out.println("REQUEST a=" + a + " b=" + b + + " at " + TimeStamp.getStringTimeStamp(tsReq) + + " with data from " + TimeStamp.getStringTimeStamp(motorMemory.getTimestamp())); + + return true; + } + + @Override + protected void processServiceResponse(AddTwoIntsResponseMessage response) { + //System.out.println("Response"); + if (response != null) { + sum = response.sum; + tsResp = System.currentTimeMillis(); + System.out.println("Using a: "+a+" b: "+b+" from "+TimeStamp.getStringTimeStamp(tsReq)); + System.out.println("RESPONSE Sum=" + sum + " at " + TimeStamp.getStringTimeStamp(tsResp)); + } + processing = false; + } + + public synchronized Integer getSum() { + return sum; + } + + public synchronized long getTSReq() { + return tsReq; + } + + public synchronized long getTSResp() { + return tsResp; + } + + @Override + public void stop() { + while(processing) { + try{Thread.sleep(100);} catch(Exception e){} + } + super.stop(); + } +} \ No newline at end of file diff --git a/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntServiceClient.java b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntServiceClient.java deleted file mode 100644 index f87cc34..0000000 --- a/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntServiceClient.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * - */ -package br.unicamp.meca.system1.codelets.rosservice; - -import java.net.URI; - -import br.unicamp.cst.core.entities.Memory; -import br.unicamp.meca.system1.codelets.RosServiceClientMotorCodelet; -import rosjava_test_msgs.AddTwoIntsRequest; -import rosjava_test_msgs.AddTwoIntsResponse; - -/** - * @author andre - * - */ -public class AddTwoIntServiceClient extends RosServiceClientMotorCodelet { - - private Integer sum; - - public AddTwoIntServiceClient(String host, URI masterURI) { - super("AddTwoIntServiceClient", "add_two_ints", rosjava_test_msgs.AddTwoInts._TYPE, host, masterURI); - } - - @Override - public void formatServiceRequest(Memory motorMemory, AddTwoIntsRequest serviceMessageRequest) { - if(motorMemory != null && motorMemory.getI() != null) { - Integer[] numsToSum = (Integer[]) motorMemory.getI(); - serviceMessageRequest.setA(numsToSum[0]); - serviceMessageRequest.setB(numsToSum[1]); - } - } - - @Override - public void processServiceResponse(AddTwoIntsResponse serviceMessageResponse) { - sum = (int) serviceMessageResponse.getSum(); - System.out.println("Sum = "+sum); - } - - /** - * @return the sum - */ - public Integer getSum() { - return sum; - } - -} diff --git a/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntsROS2ServiceProvider.java b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntsROS2ServiceProvider.java new file mode 100644 index 0000000..7a793fa --- /dev/null +++ b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/AddTwoIntsROS2ServiceProvider.java @@ -0,0 +1,70 @@ +package br.unicamp.meca.system1.codelets.rosservice; + +import id.jros2client.JRos2Client; +import id.jros2client.JRos2ClientFactory; +import pinorobotics.jros2services.JRos2Service; +import pinorobotics.jros2services.JRos2ServicesFactory; +import pinorobotics.jros2services.ServiceHandler; +import troca_ros.AddTwoIntsRequestMessage; +import troca_ros.AddTwoIntsResponseMessage; +import troca_ros.AddTwoIntsServiceDefinition; + +/** + * + * @author jrborelli + */ + +public class AddTwoIntsROS2ServiceProvider implements Runnable { + + volatile boolean stopflag = false; + private Thread thread; + JRos2ClientFactory clientFactory; + JRos2ServicesFactory serviceClientFactory; + ServiceHandler proc; + JRos2Client client; + JRos2Service service; + public boolean running = false; + + public AddTwoIntsROS2ServiceProvider() { + proc = new ServiceHandler<>() { + @Override + public AddTwoIntsResponseMessage execute(AddTwoIntsRequestMessage request) { + //System.out.println("Received new request " + request); + var response = new AddTwoIntsResponseMessage(request.a + request.b); + //System.out.println("Result " + response); + return response; + + } + }; + } + + @Override + public void run() { + running = true; + clientFactory = new JRos2ClientFactory(); + serviceClientFactory = new JRos2ServicesFactory(); + + client = clientFactory.createClient(); + service = serviceClientFactory.createService(client,new AddTwoIntsServiceDefinition(),"add_two_ints",proc); + service.start(); + System.out.println("Service started..."); + while(stopflag == false) { + + } + service.close(); + client.close(); + System.out.println("Service finished ..."); + running = false; + } + + public void start() { + if (thread == null) { + thread = new Thread(this); + thread.start(); + } + } + + public void stop() { + stopflag = true; + } +} \ No newline at end of file diff --git a/src/test/java/br/unicamp/meca/system1/codelets/rosservice/ROS1_ServiceClientTest.java b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/ROS1_ServiceClientTest.java new file mode 100644 index 0000000..49f7d89 --- /dev/null +++ b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/ROS1_ServiceClientTest.java @@ -0,0 +1,181 @@ +/** + * + */ +package br.unicamp.meca.system1.codelets.rosservice; + +//import static org.junit.Assert.assertEquals; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; + +import org.ros.RosCore; +import org.ros.node.DefaultNodeMainExecutor; +import org.ros.node.NodeConfiguration; +import org.ros.node.NodeMainExecutor; + +import br.unicamp.cst.core.entities.Memory; +import br.unicamp.cst.core.entities.MemoryContainer; +import br.unicamp.cst.support.TimeStamp; +import br.unicamp.meca.mind.MecaMind; +import br.unicamp.meca.system1.codelets.IMotorCodelet; +import java.util.logging.Level; +import java.util.logging.Logger; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.slf4j.LoggerFactory; + +/** + * @author andre + * + */ +public class ROS1_ServiceClientTest { + + private static RosCore rosCore; + private volatile Memory motorMemory; + + @BeforeAll + public static void beforeAllTestMethods() { + rosCore = RosCore.newPublic("127.0.0.1",11311); + rosCore.start(); + try{Thread.sleep(1000);} catch(Exception e){e.printStackTrace();} + } + + @AfterAll + public static void afterAllTestMethods() { + rosCore.shutdown(); + } + + public void SilenceLoggers() { + ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger("httpclient")).setLevel(ch.qos.logback.classic.Level.OFF); + ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger("org.apache")).setLevel(ch.qos.logback.classic.Level.OFF); + ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger("org.ros")).setLevel(ch.qos.logback.classic.Level.OFF); + Logger.getLogger("Simulation").setLevel(Level.SEVERE); + } + + @Test + public void testRosService() throws URISyntaxException, InterruptedException { + + AddTwoIntROS1ServiceProvider addTwoIntService = new AddTwoIntROS1ServiceProvider(); + NodeMainExecutor nodeMainExecutor = DefaultNodeMainExecutor.newDefault(); + NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic("127.0.0.1",new URI("http://127.0.0.1:11311")); + nodeMainExecutor.execute(addTwoIntService, nodeConfiguration); + + + Thread.sleep(2000); + + MecaMind mecaMind = new MecaMind("RosServiceClient"); + + List motorCodelets = new ArrayList<>(); + + AddTwoIntROS1ServiceClient addTwoIntServiceClient = new AddTwoIntROS1ServiceClient("127.0.0.1",new URI("http://127.0.0.1:11311")); + motorCodelets.add(addTwoIntServiceClient); + + mecaMind.setIMotorCodelets(motorCodelets); + mecaMind.mountMecaMind(); + mecaMind.start(); + + Thread.sleep(5000); + + motorMemory = addTwoIntServiceClient.getInput(addTwoIntServiceClient.getId()); + + Integer expectedSum = 5; + + Integer[] numsToSum = new Integer[] {2,3}; + motorMemory.setI(numsToSum); + System.out.println("Nums to sum were changed to {2,3}"); + + Thread.sleep(2000); + + assertEquals(expectedSum, addTwoIntServiceClient.getSum()); + + nodeMainExecutor.shutdownNodeMain(addTwoIntService); + + mecaMind.shutDown(); + + } + + @Test + public void testRosServiceCallTwice() throws URISyntaxException, InterruptedException { + + SilenceLoggers(); + AddTwoIntROS1ServiceProvider addTwoIntService = new AddTwoIntROS1ServiceProvider(); + NodeMainExecutor nodeMainExecutor = DefaultNodeMainExecutor.newDefault(); + NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic("127.0.0.1",new URI("http://127.0.0.1:11311")); + nodeMainExecutor.execute(addTwoIntService, nodeConfiguration); + + Thread.sleep(2000); + + MecaMind mecaMind = new MecaMind("RosServiceClient"); + + List motorCodelets = new ArrayList<>(); + + AddTwoIntROS1ServiceClient addTwoIntServiceClient = new AddTwoIntROS1ServiceClient("127.0.0.1",new URI("http://127.0.0.1:11311")); + motorCodelets.add(addTwoIntServiceClient); + + mecaMind.setIMotorCodelets(motorCodelets); + mecaMind.mountMecaMind(); + mecaMind.start(); + + Thread.sleep(5000); + + MemoryContainer mc=null; + motorMemory = addTwoIntServiceClient.getInput(addTwoIntServiceClient.getId()); + // Be careful ... at this point motorMemory is a MemoryContainer, and it is empty + if (motorMemory instanceof MemoryContainer) + mc = (MemoryContainer) motorMemory; + Integer expectedSum = 5; + + Integer[] numsToSum = new Integer[] {2,3}; + int id = motorMemory.setI(numsToSum); + // At this point, motorMemory has 1 internal MemoryObject and id should be 0 + System.out.println("id: "+id); + System.out.println("\n\nNums to sum were changed to {2,3} at "+TimeStamp.getStringTimeStamp(motorMemory.getTimestamp())); + long tsstartreq = addTwoIntServiceClient.getTSReq(); + long tsstopreq = tsstartreq; + long tsstartresp = addTwoIntServiceClient.getTSResp(); + long tsstopresp = tsstartresp; + System.out.println("Service situation - req:"+TimeStamp.getStringTimeStamp(tsstartreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstartresp)); + while (tsstartreq == tsstopreq || tsstartresp == tsstopresp ) { + tsstopresp = addTwoIntServiceClient.getTSResp(); + tsstopreq = addTwoIntServiceClient.getTSReq(); + System.out.println("startreq: "+TimeStamp.getStringTimeStamp(tsstartreq)+" stopreq: "+TimeStamp.getStringTimeStamp(tsstopreq)); + System.out.println("startresp: "+TimeStamp.getStringTimeStamp(tsstartresp)+" stopreq: "+TimeStamp.getStringTimeStamp(tsstopresp)); + Thread.sleep(100); + } + System.out.println("Finished process - req:"+TimeStamp.getStringTimeStamp(tsstopreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstopresp)); + //Thread.sleep(5000); + + assertEquals(expectedSum, addTwoIntServiceClient.getSum()); + + expectedSum = 6; + + numsToSum = new Integer[] {3,3}; + // This is the tricker part ... instead of calling setI from motorMemory, we should use its MemoryContainer counterpart + mc.setI(numsToSum,0); + System.out.println("\n\nNums to sum were changed to {3,3} at "+TimeStamp.getStringTimeStamp(motorMemory.getTimestamp())); + tsstartreq = addTwoIntServiceClient.getTSReq(); + tsstopreq = tsstartreq; + tsstartresp = addTwoIntServiceClient.getTSResp(); + tsstopresp = tsstartresp; + System.out.println("Service situation - req:"+TimeStamp.getStringTimeStamp(tsstartreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstartresp)); + while (tsstartreq == tsstopreq || tsstartresp == tsstopresp ) { + tsstopresp = addTwoIntServiceClient.getTSResp(); + tsstopreq = addTwoIntServiceClient.getTSReq(); + System.out.println("tsstartreq: "+TimeStamp.getStringTimeStamp(tsstartreq)+" tsstopreq: "+TimeStamp.getStringTimeStamp(tsstopreq)); + System.out.println("tsstartresp: "+TimeStamp.getStringTimeStamp(tsstartresp)+" tsstopreq: "+TimeStamp.getStringTimeStamp(tsstopresp)); + System.out.println("motorMemory: "+TimeStamp.getStringTimeStamp(motorMemory.getTimestamp())); + Thread.sleep(100); + } + System.out.println("Finished process - req:"+TimeStamp.getStringTimeStamp(tsstopreq)+" resp"+TimeStamp.getStringTimeStamp(tsstopresp)); + assertEquals(expectedSum, addTwoIntServiceClient.getSum()); + + nodeMainExecutor.shutdownNodeMain(addTwoIntService); + + mecaMind.shutDown(); + + } +} diff --git a/src/test/java/br/unicamp/meca/system1/codelets/rosservice/ROS2_ServiceClientTest.java b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/ROS2_ServiceClientTest.java new file mode 100644 index 0000000..ef3228c --- /dev/null +++ b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/ROS2_ServiceClientTest.java @@ -0,0 +1,350 @@ + +package br.unicamp.meca.system1.codelets.rosservice; + + +import br.unicamp.cst.core.entities.Memory; +import br.unicamp.cst.core.entities.MemoryContainer; +import br.unicamp.cst.support.TimeStamp; +import br.unicamp.meca.mind.MecaMind; +import br.unicamp.meca.system1.codelets.IMotorCodelet; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +//import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +/** + * ROS2 version of the MECA ROS1 RosServiceClientTest + * + * @author jrborelli + */ + + +public class ROS2_ServiceClientTest { + + private static final Logger LOGGER = Logger.getLogger(ROS2_ServiceClientTest.class.getName()); + private static MecaMind mecaMind; + private volatile Memory motorMemory; + private static AddTwoIntsROS2ServiceProvider serviceProvider; + + private static void SilenceLoggers() { + Logger.getLogger("pinorobotics.rtpstalk").setLevel(Level.OFF); + Logger.getLogger("id.jros2client").setLevel(Level.OFF); + } + + @BeforeAll + public static void setup() { + SilenceLoggers(); + mecaMind = new MecaMind("ROS2_RosServiceClientTest"); + serviceProvider = new AddTwoIntsROS2ServiceProvider(); + serviceProvider.start(); + } + + @AfterAll + public static void cleanup() { + if (mecaMind != null) mecaMind.shutDown(); + serviceProvider.stop(); + } + + @Test + public void testROS2_RosServiceCallOnce() throws InterruptedException { + System.out.println("\nStarting the RosServiceCallOnce test"); + Thread.sleep(5000); //Necessary, so that the mind can shutdown. + + AddTwoIntROS2ServiceClient clientSync = new AddTwoIntROS2ServiceClient("AddTwoInts", "add_two_ints"); + //clientSync.setName("AddTwoInts"); + System.out.println("The default name of the codelet is "+clientSync.getName()); + + List motorCodelets = new ArrayList<>(); + motorCodelets.add(clientSync); + mecaMind.setIMotorCodelets(motorCodelets); + mecaMind.mountMecaMind(); + List lm = clientSync.getInputs(); + System.out.println("The number of inputs is "+lm.size()); + for (Memory m :lm) { + System.out.println("The name of memory is "+m.getName()); + } + mecaMind.start(); + + + motorMemory = clientSync.getInput(clientSync.getId()); + + Integer expectedSum = 5; + + Integer[] numsToSum = new Integer[] {2,3}; + motorMemory.setI(numsToSum); + + System.out.println("Nums to sum were changed to {2,3}"); + + long tsstartreq = System.currentTimeMillis(); //clientSync.getTSReq(); + long tsstopreq = tsstartreq; + long tsstartresp = System.currentTimeMillis(); //clientSync.getTSResp(); + long tsstopresp = tsstartresp; + //int id = motorMemory.setI(numsToSum); + // At this point, motorMemory has 1 internal MemoryObject and id should be 0 + //System.out.println("id: "+id); + System.out.println("\n\nNums to sum were changed to {2,3} at "+TimeStamp.getStringTimeStamp(motorMemory.getTimestamp())); + System.out.println("Service situation - req:"+TimeStamp.getStringTimeStamp(tsstartreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstartresp)); + + while (clientSync.getSum()== null || tsstartreq == tsstopreq || tsstartresp == tsstopresp || tsstopresp <= tsstopreq ) { + tsstopresp = clientSync.getTSResp(); + tsstopreq = clientSync.getTSReq(); + clientSync.getSum(); + } + + mecaMind.shutDown(); + + System.out.println("Finished process - req:"+TimeStamp.getStringTimeStamp(tsstopreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstopresp)); + System.out.println("I took "+TimeStamp.getStringTimeStamp(tsstopresp-tsstartreq,"mm:ss.SSS")+ " s to attend the service request !!"); + + assertEquals(expectedSum, clientSync.getSum()); + + System.out.println("The test was finished!"); + } + + public String cvr(long t) { + return TimeStamp.getStringTimeStamp(t,"hh:mm:ss.SSS"); + } + + @Test + public void testROS2_RosServiceCallTwice() throws InterruptedException { + System.out.println("\nStarting the RosServiceCallTwice test"); + + AddTwoIntROS2ServiceClient clientSync = new AddTwoIntROS2ServiceClient("AddTwoInts","add_two_ints"); + + List motorCodelets = new ArrayList<>(); + motorCodelets.add(clientSync); + mecaMind.setIMotorCodelets(motorCodelets); + mecaMind.mountMecaMind(); + mecaMind.start(); + + MemoryContainer mc=null; + motorMemory = clientSync.getInput(clientSync.getId()); + + if (motorMemory instanceof MemoryContainer) + mc = (MemoryContainer) motorMemory; + Integer expectedSum = 5; + + // First request + Integer[] numsToSum = new Integer[]{2, 3}; + + long tsstartreq = System.currentTimeMillis(); //clientSync.getTSReq(); + long tsstopreq = tsstartreq; + long tsstartresp = System.currentTimeMillis(); //clientSync.getTSResp(); + long tsstopresp = tsstartresp; + int id = motorMemory.setI(numsToSum); + // At this point, motorMemory has 1 internal MemoryObject and id should be 0 + System.out.println("id: "+id); + System.out.println("\n\nNums to sum were changed to {2,3} at "+TimeStamp.getStringTimeStamp(motorMemory.getTimestamp())); + System.out.println("Service situation - req:"+TimeStamp.getStringTimeStamp(tsstartreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstartresp)); + + while (clientSync.getSum()== null || tsstartreq == tsstopreq || tsstartresp == tsstopresp || tsstopresp <= tsstopreq ) { + tsstopresp = clientSync.getTSResp(); + tsstopreq = clientSync.getTSReq(); + clientSync.getSum(); + System.out.print("."); + } + + System.out.println("\nFinished process - req:"+TimeStamp.getStringTimeStamp(tsstopreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstopresp)); + + System.out.println("I took "+TimeStamp.getStringTimeStamp(tsstopresp-tsstartreq,"mm:ss.SSS")+ " s to attend the service request !!"); + + assertEquals(expectedSum, clientSync.getSum()); + + expectedSum = 6; + + numsToSum = new Integer[] {3,3}; + // This is the tricker part ... instead of calling setI from motorMemory, we should use its MemoryContainer counterpart + mc.setI(numsToSum,0); + System.out.println("\n\nNums to sum were changed to {3,3} at "+TimeStamp.getStringTimeStamp(motorMemory.getTimestamp())); + tsstartreq = clientSync.getTSReq(); + tsstopreq = tsstartreq; + tsstartresp = clientSync.getTSResp(); + tsstopresp = tsstartresp; + System.out.println("Service situation - req:"+TimeStamp.getStringTimeStamp(tsstartreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstartresp)); + + while (clientSync.getSum()== null || tsstartreq == tsstopreq || tsstartresp == tsstopresp || tsstopresp <= tsstopreq ) { + tsstopresp = clientSync.getTSResp(); + tsstopreq = clientSync.getTSReq(); + clientSync.getSum(); + System.out.print("."); + } + + motorMemory.setI(null); + motorMemory = null; + mc.setI(null,0); + mc = null; + mecaMind.shutDown(); + + System.out.println("\nFinished process - req:"+TimeStamp.getStringTimeStamp(tsstopreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstopresp)); + System.out.println("I took "+TimeStamp.getStringTimeStamp(tsstopresp-tsstartreq,"mm:ss.SSS")+ " s to attend the service request !!"); + + assertEquals(expectedSum, clientSync.getSum()); + + System.out.println("The test was finished!"); + } +} + +/* +@Test + public void testROS2_RosServiceCallOnce() throws InterruptedException { + System.out.println("\nStarting the RosServiceCallOnce test"); + //SilenceLoggers(); + //setup(); + // Start ROS2 service provider +// AddTwoIntsROS2ServiceProvider serviceProvider = new AddTwoIntsROS2ServiceProvider(); +// serviceProvider.start(); +// Thread.sleep(500); // give service time to start + + // Create memory object for inputs + //Memory memory = mecaMind.createMemoryObject("add_two_ints"); + + // Instantiate ROS2 synchronous client + //AddTwoIntsServiceClientSyncRos2 clientSync = new AddTwoIntsServiceClientSyncRos2("add_two_ints"); + AddTwoIntROS2ServiceClient clientSync = new AddTwoIntROS2ServiceClient("add_two_ints"); + //clientSync.start(); + + // Insert client codelet in mind (for consistency) + List motorCodelets = new ArrayList<>(); + motorCodelets.add(clientSync); + mecaMind.setIMotorCodelets(motorCodelets); + mecaMind.mountMecaMind(); + mecaMind.start(); + + //Thread.sleep(5000); + + motorMemory = clientSync.getInput(clientSync.getId()); + + Integer expectedSum = 5; + + Integer[] numsToSum = new Integer[] {2,3}; + motorMemory.setI(numsToSum); + System.out.println("Nums to sum were changed to {2,3}"); + + //Thread.sleep(2000); + long tsstartreq = System.currentTimeMillis(); //clientSync.getTSReq(); + long tsstopreq = tsstartreq; + long tsstartresp = System.currentTimeMillis(); //clientSync.getTSResp(); + long tsstopresp = tsstartresp; + int id = motorMemory.setI(numsToSum); + // At this point, motorMemory has 1 internal MemoryObject and id should be 0 + System.out.println("id: "+id); + System.out.println("\n\nNums to sum were changed to {2,3} at "+TimeStamp.getStringTimeStamp(motorMemory.getTimestamp())); + System.out.println("Service situation - req:"+TimeStamp.getStringTimeStamp(tsstartreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstartresp)); + while (tsstartreq == tsstopreq || tsstartresp == tsstopresp || tsstopresp <= tsstopreq ) { + tsstopresp = clientSync.getTSResp(); + tsstopreq = clientSync.getTSReq(); + //System.out.println("startreq: "+TimeStamp.getStringTimeStamp(tsstartreq)+" stopreq: "+TimeStamp.getStringTimeStamp(tsstopreq)); + //System.out.println("startresp: "+TimeStamp.getStringTimeStamp(tsstartresp)+" stopresp: "+TimeStamp.getStringTimeStamp(tsstopresp)); + Thread.sleep(100); + } + System.out.println("Finished process - req:"+TimeStamp.getStringTimeStamp(tsstopreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstopresp)); + System.out.println("I took "+TimeStamp.getStringTimeStamp(tsstopresp-tsstartreq,"mm:ss.SSS")+ " s to attend the service request !!"); + + assertEquals(expectedSum, clientSync.getSum()); + + // Cleanup + //clientSync.stop(); + mecaMind.shutDown(); + //Thread.sleep(5000); + //clientSync.stop(); + //serviceProvider.stop(); + //while (serviceProvider.running) Thread.sleep(100); + System.out.println("The test was finished!"); + } + + public String cvr(long t) { + return TimeStamp.getStringTimeStamp(t,"hh:mm:ss.SSS"); + } + + @Test + public void testROS2_RosServiceCallTwice() throws InterruptedException { + System.out.println("\nStarting the RosServiceCallTwice test"); + SilenceLoggers(); + //setup(); + // Start ROS2 service provider +// AddTwoIntsROS2ServiceProvider serviceProvider = new AddTwoIntsROS2ServiceProvider(); +// serviceProvider.start(); +// Thread.sleep(500); + + //Memory memory = mecaMind.createMemoryObject("add_two_ints"); + + AddTwoIntROS2ServiceClient clientSync = new AddTwoIntROS2ServiceClient("add_two_ints"); + //clientSync.start(); + + List motorCodelets = new ArrayList<>(); + motorCodelets.add(clientSync); + mecaMind.setIMotorCodelets(motorCodelets); + mecaMind.mountMecaMind(); + mecaMind.start(); + + MemoryContainer mc=null; + motorMemory = clientSync.getInput(clientSync.getId()); + if (motorMemory instanceof MemoryContainer) + mc = (MemoryContainer) motorMemory; + Integer expectedSum = 5; + + // First request + Integer[] numsToSum = new Integer[]{2, 3}; + + long tsstartreq = System.currentTimeMillis(); //clientSync.getTSReq(); + long tsstopreq = tsstartreq; + long tsstartresp = System.currentTimeMillis(); //clientSync.getTSResp(); + long tsstopresp = tsstartresp; + int id = motorMemory.setI(numsToSum); + // At this point, motorMemory has 1 internal MemoryObject and id should be 0 + System.out.println("id: "+id); + System.out.println("\n\nNums to sum were changed to {2,3} at "+TimeStamp.getStringTimeStamp(motorMemory.getTimestamp())); + System.out.println("Service situation - req:"+TimeStamp.getStringTimeStamp(tsstartreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstartresp)); + while (tsstartreq == tsstopreq || tsstartresp == tsstopresp || tsstopresp <= tsstopreq ) { + tsstopresp = clientSync.getTSResp(); + tsstopreq = clientSync.getTSReq(); + System.out.print("."); + //System.out.println("req: "+cvr(tsstartreq)+" "+cvr(tsstopreq)); + //System.out.println("resp: "+cvr(tsstartresp)+" "+cvr(tsstopresp)); + Thread.sleep(100); + } + System.out.println("\nFinished process - req:"+TimeStamp.getStringTimeStamp(tsstopreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstopresp)); + //Thread.sleep(5000); + System.out.println("I took "+TimeStamp.getStringTimeStamp(tsstopresp-tsstartreq,"mm:ss.SSS")+ " s to attend the service request !!"); + + assertEquals(expectedSum, clientSync.getSum()); + + expectedSum = 6; + + numsToSum = new Integer[] {3,3}; + // This is the tricker part ... instead of calling setI from motorMemory, we should use its MemoryContainer counterpart + mc.setI(numsToSum,0); + System.out.println("\n\nNums to sum were changed to {3,3} at "+TimeStamp.getStringTimeStamp(motorMemory.getTimestamp())); + tsstartreq = clientSync.getTSReq(); + tsstopreq = tsstartreq; + tsstartresp = clientSync.getTSResp(); + tsstopresp = tsstartresp; + System.out.println("Service situation - req:"+TimeStamp.getStringTimeStamp(tsstartreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstartresp)); + while (tsstartreq == tsstopreq || tsstartresp == tsstopresp || tsstopresp <= tsstopreq ) { + tsstopresp = clientSync.getTSResp(); + tsstopreq = clientSync.getTSReq(); + //System.out.println("tsstartreq: "+TimeStamp.getStringTimeStamp(tsstartreq)+" tsstopreq: "+TimeStamp.getStringTimeStamp(tsstopreq)); + //System.out.println("tsstartresp: "+TimeStamp.getStringTimeStamp(tsstartresp)+" tsstopresp: "+TimeStamp.getStringTimeStamp(tsstopresp)); + //System.out.println("motorMemory: "+TimeStamp.getStringTimeStamp(motorMemory.getTimestamp())); + System.out.print("."); + Thread.sleep(100); + } + System.out.println("\nFinished process - req:"+TimeStamp.getStringTimeStamp(tsstopreq)+" resp:"+TimeStamp.getStringTimeStamp(tsstopresp)); + System.out.println("I took "+TimeStamp.getStringTimeStamp(tsstopresp-tsstartreq,"mm:ss.SSS")+ " s to attend the service request !!"); + + assertEquals(expectedSum, clientSync.getSum()); + mecaMind.shutDown(); + //clientSync.stop(); + //Thread.sleep(5000); + //serviceProvider.stop(); + //while (serviceProvider.running) Thread.sleep(100); + //Thread.sleep(5000); + System.out.println("The test was finished!"); + } +*/ \ No newline at end of file diff --git a/src/test/java/br/unicamp/meca/system1/codelets/rosservice/RosServiceClientTest.java b/src/test/java/br/unicamp/meca/system1/codelets/rosservice/RosServiceClientTest.java deleted file mode 100644 index a6bd043..0000000 --- a/src/test/java/br/unicamp/meca/system1/codelets/rosservice/RosServiceClientTest.java +++ /dev/null @@ -1,136 +0,0 @@ -/** - * - */ -package br.unicamp.meca.system1.codelets.rosservice; - -import static org.junit.Assert.assertEquals; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.List; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.ros.RosCore; -import org.ros.node.DefaultNodeMainExecutor; -import org.ros.node.NodeConfiguration; -import org.ros.node.NodeMainExecutor; - -import br.unicamp.cst.core.entities.Memory; -import br.unicamp.meca.mind.MecaMind; -import br.unicamp.meca.system1.codelets.IMotorCodelet; - -/** - * @author andre - * - */ -public class RosServiceClientTest { - - private static RosCore rosCore; - - @BeforeClass - public static void beforeAllTestMethods() { - rosCore = RosCore.newPublic("127.0.0.1",11311); - rosCore.start(); - } - - @AfterClass - public static void afterAllTestMethods() { - rosCore.shutdown(); - } - - @Test - public void testRosService() throws URISyntaxException, InterruptedException { - - AddTwoIntService addTwoIntService = new AddTwoIntService(); - NodeMainExecutor nodeMainExecutor = DefaultNodeMainExecutor.newDefault(); - NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic("127.0.0.1",new URI("http://127.0.0.1:11311")); - nodeMainExecutor.execute(addTwoIntService, nodeConfiguration); - - Thread.sleep(2000); - - MecaMind mecaMind = new MecaMind("RosServiceClient"); - - List motorCodelets = new ArrayList<>(); - - AddTwoIntServiceClient addTwoIntServiceClient = new AddTwoIntServiceClient("127.0.0.1",new URI("http://127.0.0.1:11311")); - motorCodelets.add(addTwoIntServiceClient); - - mecaMind.setIMotorCodelets(motorCodelets); - - mecaMind.mountMecaMind(); - - mecaMind.start(); - - Thread.sleep(5000); - - Memory motorMemory = addTwoIntServiceClient.getInput(addTwoIntServiceClient.getId()); - - Integer expectedSum = 5; - - Integer[] numsToSum = new Integer[] {2,3}; - motorMemory.setI(numsToSum); - - Thread.sleep(2000); - - assertEquals(expectedSum, addTwoIntServiceClient.getSum()); - - nodeMainExecutor.shutdownNodeMain(addTwoIntService); - - mecaMind.shutDown(); - - } - - @Test - public void testRosServiceCallTwice() throws URISyntaxException, InterruptedException { - - AddTwoIntService addTwoIntService = new AddTwoIntService(); - NodeMainExecutor nodeMainExecutor = DefaultNodeMainExecutor.newDefault(); - NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic("127.0.0.1",new URI("http://127.0.0.1:11311")); - nodeMainExecutor.execute(addTwoIntService, nodeConfiguration); - - Thread.sleep(2000); - - MecaMind mecaMind = new MecaMind("RosServiceClient"); - - List motorCodelets = new ArrayList<>(); - - AddTwoIntServiceClient addTwoIntServiceClient = new AddTwoIntServiceClient("127.0.0.1",new URI("http://127.0.0.1:11311")); - motorCodelets.add(addTwoIntServiceClient); - - mecaMind.setIMotorCodelets(motorCodelets); - - mecaMind.mountMecaMind(); - - mecaMind.start(); - - Thread.sleep(5000); - - Memory motorMemory = addTwoIntServiceClient.getInput(addTwoIntServiceClient.getId()); - - Integer expectedSum = 5; - - Integer[] numsToSum = new Integer[] {2,3}; - motorMemory.setI(numsToSum); - - Thread.sleep(2000); - - assertEquals(expectedSum, addTwoIntServiceClient.getSum()); - - expectedSum = 6; - - numsToSum = new Integer[] {3,3}; - motorMemory.setI(numsToSum); - - Thread.sleep(2000); - - assertEquals(expectedSum, addTwoIntServiceClient.getSum()); - - nodeMainExecutor.shutdownNodeMain(addTwoIntService); - - mecaMind.shutDown(); - - } -} diff --git a/src/test/java/br/unicamp/meca/system1/codelets/rostopic/ROS2_ChatterTopicPublisher.java b/src/test/java/br/unicamp/meca/system1/codelets/rostopic/ROS2_ChatterTopicPublisher.java new file mode 100644 index 0000000..562692c --- /dev/null +++ b/src/test/java/br/unicamp/meca/system1/codelets/rostopic/ROS2_ChatterTopicPublisher.java @@ -0,0 +1,34 @@ +package br.unicamp.meca.system1.codelets.rostopic; + +import br.unicamp.cst.core.entities.Memory; +import id.jrosmessages.std_msgs.StringMessage; +import br.unicamp.meca.system1.codelets.Ros2TopicPublisherMotorCodelet; + +/** + * + * @author jrborelli + */ + +public class ROS2_ChatterTopicPublisher extends Ros2TopicPublisherMotorCodelet { + + public ROS2_ChatterTopicPublisher(String name, String topic) { + super(name, topic, StringMessage.class); + } + + @Override + protected StringMessage createNewMessage() { + return new StringMessage(); + } + + @Override + protected void fillMessageToBePublished(Memory motorMemory, StringMessage message) { + if (motorMemory == null || message == null) return; + + Object data = motorMemory.getI(); + if (data instanceof String) { + message.withData((String) data); + } else { + message.withData(""); + } + } +} \ No newline at end of file diff --git a/src/test/java/br/unicamp/meca/system1/codelets/rostopic/ROS2_ChatterTopicSubscriber.java b/src/test/java/br/unicamp/meca/system1/codelets/rostopic/ROS2_ChatterTopicSubscriber.java new file mode 100644 index 0000000..dba9b50 --- /dev/null +++ b/src/test/java/br/unicamp/meca/system1/codelets/rostopic/ROS2_ChatterTopicSubscriber.java @@ -0,0 +1,34 @@ + +package br.unicamp.meca.system1.codelets.rostopic; + +import br.unicamp.cst.core.entities.Memory; +import id.jrosmessages.std_msgs.StringMessage; +import br.unicamp.meca.system1.codelets.Ros2TopicSubscriberSensoryCodelet; + +/** + * ROS2 version of ChatterTopicSubscriber for MECA + * + * @author jrborelli + */ +public class ROS2_ChatterTopicSubscriber extends Ros2TopicSubscriberSensoryCodelet { + + public ROS2_ChatterTopicSubscriber(String name, String topic) { + super(name, topic, StringMessage.class); + } + + @Override + public void fillMemoryWithReceivedMessage(StringMessage message, Memory sensoryMemory) { + if (message == null || sensoryMemory == null) { + if (sensoryMemory != null) sensoryMemory.setI(null); + return; + } + + String data = message.data; + if (data == null) { + sensoryMemory.setI(null); + } else { + System.out.println("I heard: \"" + data + "\""); + sensoryMemory.setI(data); + } + } +} \ No newline at end of file diff --git a/src/test/java/br/unicamp/meca/system1/codelets/rostopic/ROS2_RosTopicPublisherSubscriberTest.java b/src/test/java/br/unicamp/meca/system1/codelets/rostopic/ROS2_RosTopicPublisherSubscriberTest.java new file mode 100644 index 0000000..80a1b4d --- /dev/null +++ b/src/test/java/br/unicamp/meca/system1/codelets/rostopic/ROS2_RosTopicPublisherSubscriberTest.java @@ -0,0 +1,99 @@ + +package br.unicamp.meca.system1.codelets.rostopic; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import br.unicamp.cst.core.entities.Memory; +import br.unicamp.meca.mind.MecaMind; +import br.unicamp.meca.system1.codelets.IMotorCodelet; +import br.unicamp.meca.system1.codelets.ISensoryCodelet; + +import java.util.ArrayList; +import java.util.List; + +import java.util.logging.Level; +import java.util.logging.Logger; + + +/** + * Fully asynchronous ROS2 Publisher-Subscriber test using CompletableFuture. + * Reacts immediately when the message arrives. + * + * Author: jrborelli + */ +public class ROS2_RosTopicPublisherSubscriberTest { + + private static final Logger LOGGER = Logger.getLogger(ROS2_RosTopicPublisherSubscriberTest.class.getName()); + private static MecaMind mecaMind; + + // optionally silence noisy loggers here if you want: + private static void SilenceLoggers() { + Logger.getLogger("pinorobotics.rtpstalk").setLevel(Level.OFF); + Logger.getLogger("id.jros2client").setLevel(Level.OFF); + } + + @BeforeAll + public static void setup() { + SilenceLoggers(); + LOGGER.info("Setting up MecaMind for ROS2 Publisher/Subscriber test..."); + mecaMind = new MecaMind("ROS2_RosTopicPublisherSubscriber"); + + } + + @AfterAll + public static void teardown() { + LOGGER.info("Tearing down MecaMind..."); + if (mecaMind != null) { + mecaMind.shutDown(); + } + } + + @Test + public void testRos2Topics() throws InterruptedException { + + List motorCodelets = new ArrayList<>(); + ROS2_ChatterTopicPublisher chatterTopicPublisher = new ROS2_ChatterTopicPublisher("chatter", "chatter"); + motorCodelets.add(chatterTopicPublisher); + + List sensoryCodelets = new ArrayList<>(); + ROS2_ChatterTopicSubscriber chatterTopicSubscriber = new ROS2_ChatterTopicSubscriber("chatter","chatter"); + sensoryCodelets.add(chatterTopicSubscriber); + + mecaMind.setIMotorCodelets(motorCodelets); + mecaMind.setISensoryCodelets(sensoryCodelets); + mecaMind.mountMecaMind(); + + mecaMind.start(); + LOGGER.info("MECA Mind started — waiting for topic bridge..."); + + // Give time for nodes to start + Thread.sleep(1000); + + String messageExpected = "Hello World"; + Memory motorMemory = chatterTopicPublisher.getInput(chatterTopicPublisher.getId()); + motorMemory.setI(messageExpected); + + final long timeoutMillis = 50000L; + //final long pollIntervalMs = 50L; + final long start = System.currentTimeMillis(); + long timeFinished = 0; + + Memory sensoryMemory = chatterTopicSubscriber.getOutput(chatterTopicSubscriber.getId()); + String messageActual = null; + + while(messageActual==null && (System.currentTimeMillis() - start < timeoutMillis)){ + messageActual = (String) sensoryMemory.getI(); + } + + timeFinished = System.currentTimeMillis() - start; + + LOGGER.log(Level.INFO, "Expected = \"{0}\", Actual = \"{1}\"", new Object[]{messageExpected, messageActual}); + assertEquals(messageExpected, messageActual); + LOGGER.log(Level.INFO, "Message received in {0} seconds", new Object[]{timeFinished}); + + mecaMind.shutDown(); // Already in @AfterAll + } +} diff --git a/src/test/java/br/unicamp/meca/system1/codelets/rostopic/RosTopicPublisherSubscriberTest.java b/src/test/java/br/unicamp/meca/system1/codelets/rostopic/RosTopicPublisherSubscriberTest.java index 5c0cb83..11e9793 100644 --- a/src/test/java/br/unicamp/meca/system1/codelets/rostopic/RosTopicPublisherSubscriberTest.java +++ b/src/test/java/br/unicamp/meca/system1/codelets/rostopic/RosTopicPublisherSubscriberTest.java @@ -3,16 +3,18 @@ */ package br.unicamp.meca.system1.codelets.rostopic; -import static org.junit.Assert.assertEquals; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +//import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + import org.ros.RosCore; import br.unicamp.cst.core.entities.Memory; @@ -28,13 +30,14 @@ public class RosTopicPublisherSubscriberTest { private static RosCore rosCore; - @BeforeClass + @BeforeAll public static void beforeAllTestMethods() { rosCore = RosCore.newPublic("127.0.0.1",11311); rosCore.start(); + try{Thread.sleep(1000);} catch(Exception e){e.printStackTrace();} } - @AfterClass + @AfterAll public static void afterAllTestMethods() { rosCore.shutdown(); } diff --git a/src/test/java/troca_ros/AddTwoIntsRequestMessage.java b/src/test/java/troca_ros/AddTwoIntsRequestMessage.java new file mode 100644 index 0000000..89ab34a --- /dev/null +++ b/src/test/java/troca_ros/AddTwoIntsRequestMessage.java @@ -0,0 +1,56 @@ +package troca_ros; + +import id.jrosmessages.Message; +import id.jrosmessages.MessageMetadata; +import id.jrosmessages.RosInterfaceType; +import id.xfunction.XJson; +import java.util.Objects; + +/** + * Definition for example_interfaces/AddTwoInts_Request + * + * @author lambdaprime intid@protonmail.com + */ +@MessageMetadata( + name = AddTwoIntsRequestMessage.NAME, + fields = {"a", "b"}, + interfaceType = RosInterfaceType.SERVICE) +public class AddTwoIntsRequestMessage implements Message { + + static final String NAME = "troca_ros/AddTwoIntsServiceRequest"; + public int a; + public int b; + + public AddTwoIntsRequestMessage() {} + + public AddTwoIntsRequestMessage(int a, int b) { + this.a = a; + this.b = b; + } + + public AddTwoIntsRequestMessage withA(int a) { + this.a = a; + return this; + } + + public AddTwoIntsRequestMessage withB(int b) { + this.b = b; + return this; + } + + @Override + public int hashCode() { + return Objects.hash(a, b); + } + + @Override + public boolean equals(Object obj) { + var other = (AddTwoIntsRequestMessage) obj; + return Objects.equals(a, other.b) && Objects.equals(a, other.b); + } + + @Override + public String toString() { + return XJson.asString("a", a,"b", b); + } +} \ No newline at end of file diff --git a/src/test/java/troca_ros/AddTwoIntsResponseMessage.java b/src/test/java/troca_ros/AddTwoIntsResponseMessage.java new file mode 100644 index 0000000..b1116ad --- /dev/null +++ b/src/test/java/troca_ros/AddTwoIntsResponseMessage.java @@ -0,0 +1,42 @@ +package troca_ros; + +import id.jrosmessages.Message; +import id.jrosmessages.MessageMetadata; +import id.jrosmessages.RosInterfaceType; +import id.xfunction.XJson; +import java.util.Objects; + +/** + * Definition for example_interfaces/AddTwoInts_Response + * + * @author lambdaprime intid@protonmail.com + */ +@MessageMetadata(name = AddTwoIntsResponseMessage.NAME, interfaceType = RosInterfaceType.SERVICE) +public class AddTwoIntsResponseMessage implements Message { + + static final String NAME = "troca_ros/AddTwoIntsServiceResponse"; + + public int sum; + + public AddTwoIntsResponseMessage() {} + + public AddTwoIntsResponseMessage(int sum) { + this.sum = sum; + } + + @Override + public int hashCode() { + return Objects.hash(sum); + } + + @Override + public boolean equals(Object obj) { + var other = (AddTwoIntsResponseMessage) obj; + return sum == other.sum; + } + + @Override + public String toString() { + return XJson.asString("sum", sum); + } +} \ No newline at end of file diff --git a/src/test/java/troca_ros/AddTwoIntsServiceDefinition.java b/src/test/java/troca_ros/AddTwoIntsServiceDefinition.java new file mode 100644 index 0000000..3390072 --- /dev/null +++ b/src/test/java/troca_ros/AddTwoIntsServiceDefinition.java @@ -0,0 +1,23 @@ +package troca_ros; + +import id.jrosmessages.MessageDescriptor; +import pinorobotics.jrosservices.msgs.ServiceDefinition; + +/** + * @author lambdaprime intid@protonmail.com + */ +public class AddTwoIntsServiceDefinition implements ServiceDefinition { + + private static final MessageDescriptor REQUEST_MESSAGE_DESCRIPTOR = new MessageDescriptor<>(AddTwoIntsRequestMessage.class); + private static final MessageDescriptor RESPONSE_MESSAGE_DESCRIPTOR = new MessageDescriptor<>(AddTwoIntsResponseMessage.class); + + @Override + public MessageDescriptor getServiceRequestMessage() { + return REQUEST_MESSAGE_DESCRIPTOR; + } + + @Override + public MessageDescriptor getServiceResponseMessage() { + return RESPONSE_MESSAGE_DESCRIPTOR; + } +} \ No newline at end of file