Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

ergoCubEmotions module - stint 2 #87

Merged
merged 16 commits into from
Mar 29, 2023
Merged
79 changes: 79 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: C++ CI Workflow with conda dependencies

on:
push:
paths:
- 'src/**'
pull_request:
paths:
- 'src/**'
schedule:
# * is a special character in YAML so you have to quote this string
# Execute a "nightly" build at 2 AM UTC
- cron: '0 2 * * *'

jobs:
build:
name: '[${{ matrix.os }}@${{ matrix.build_type }}@conda]'
runs-on: ${{ matrix.os }}
strategy:
matrix:
build_type: [Release]
os: [ubuntu-latest, windows-2019, macos-latest]
fail-fast: false

steps:
- uses: actions/checkout@v2

- uses: conda-incubator/setup-miniconda@v2
with:
mamba-version: "*"
channels: conda-forge,robotology
channel-priority: true

- name: Dependencies
shell: bash -l {0}
run: |
# Workaround for https://github.com/conda-incubator/setup-miniconda/issues/186
conda config --remove channels defaults
# Compilation related dependencies
mamba install cmake compilers make ninja pkg-config
# Actual dependencies
mamba install ycm-cmake-modules yarp opencv

- name: Configure [Linux&macOS]
if: contains(matrix.os, 'macos') || contains(matrix.os, 'ubuntu')
shell: bash -l {0}
run: |
mkdir -p build
cd build
cmake -GNinja -DCMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/install \
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCOMPILE_ergoCubEmotions:BOOL=ON ..

- name: Configure [Windows]
if: contains(matrix.os, 'windows')
shell: bash -l {0}
run: |
mkdir -p build
cd build
cmake -G"Visual Studio 16 2019" -DCMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/install \
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCOMPILE_ergoCubEmotions:BOOL=ON ..

- name: Build
shell: bash -l {0}
run: |
cd build
cmake --build . --config ${{ matrix.build_type }}

- name: Install
shell: bash -l {0}
run: |
cd build
cmake --build . --config ${{ matrix.build_type }} --target install







7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ include(AddUninstallTarget)
option(ERGOCUB_MODEL_GENERATE_SIMMECHANICS "Generate models using the model generation pipeline from simmechanics" OFF)
option(ERGOCUB_MODEL_COPY_TO_SRC "Copy to sources the generated urdf files" OFF)
option(BUILD_TESTING "Run tests for the generated models" OFF)
option(COMPILE_ergoCubEmotions "Compile the module controlling the ergoCub emotions" OFF)

set(BUILD_PREFIX "ergoCub")
add_subdirectory(urdf)
Expand All @@ -31,3 +32,9 @@ if (BUILD_TESTING)
enable_testing()
add_subdirectory(tests)
endif()

if(COMPILE_ergoCubEmotions)
add_subdirectory(src)
endif()


16 changes: 12 additions & 4 deletions src/modules/ergoCubEmotions/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,23 @@ cmake_minimum_required(VERSION 3.12)

find_package(YARP 3.7.2 REQUIRED)
find_package(OpenCV 4.5.4 REQUIRED)
add_executable(${PROJECT_NAME})
target_sources(${PROJECT_NAME} PUBLIC ergoCubEmotions.cpp ergoCubEmotions.h main.cpp)

file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/images DESTINATION ${CMAKE_BINARY_DIR})
set(doc_files ${PROJECT_NAME}.xml)
yarp_add_idl(IDL_GEN_FILES idl.thrift)

source_group("IDL Files" FILES idl.thrift)
source_group("DOC Files" FILES ${doc_files})
add_executable(${PROJECT_NAME} ergoCubEmotions.cpp ergoCubEmotions.h main.cpp idl.thrift ${IDL_GEN_FILES} ${doc_files})

yarp_install(FILES config.ini DESTINATION ${YARP_CONTEXTS_INSTALL_DIR}/${PROJECT_NAME})
yarp_install(DIRECTORY expressions DESTINATION ${YARP_CONTEXTS_INSTALL_DIR}/${PROJECT_NAME})

# Link the application with YARP and OpenCV libraries
target_link_libraries(${PROJECT_NAME} YARP::YARP_os
YARP::YARP_dev
YARP::YARP_init
YARP::YARP_conf
opencv_core
opencv_highgui)
opencv_highgui
opencv_videoio)
install(TARGETS ${PROJECT_NAME} DESTINATION bin)
22 changes: 22 additions & 0 deletions src/modules/ergoCubEmotions/config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[general]
num_expressions 4

[expression_0]
name angry
type image
file /expressions/images/exp_img_0.png

[expression_1]
name happy
type image
file /expressions/images/exp_img_1.png

[expression_2]
name neutral
type image
file /expressions/images/exp_img_2.png

[expression_3]
name shy
type image
file /expressions/images/exp_img_3.png
165 changes: 71 additions & 94 deletions src/modules/ergoCubEmotions/ergoCubEmotions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@
* *
******************************************************************************/

#include <yarp/os/ResourceFinder.h>
#include <yarp/os/LogStream.h>
#include <yarp/os/Network.h>
#include <yarp/os/Bottle.h>
#include "ergoCubEmotions.h"

#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>

#include "ergoCubEmotions.h"

using namespace cv;
using namespace yarp::os;
using namespace cv;

ErgoCubEmotions::ErgoCubEmotions()
{
Expand All @@ -24,23 +26,50 @@ ErgoCubEmotions::~ErgoCubEmotions()
{
}

bool ErgoCubEmotions::configure(ResourceFinder& config)
bool ErgoCubEmotions::attach(RpcServer& source)
{
auto ret = rpcPort.open("/ergoCubEmotions/rpc");
attach(rpcPort);
return yarp().attachAsServer(source);
}

// set window properties
namedWindow("emotion", WINDOW_FULLSCREEN);
Mat start_img = imread("images/neu.png");
imshow("emotion", start_img);
waitKey(0);
bool ErgoCubEmotions::configure(ResourceFinder& rf)
{
cmdPort.open("/ergoCubEmotions/rpc");
attach(cmdPort);

path = rf.getHomeContextPath();
Bottle &bGroup = rf.findGroup("general");
nexpressions = bGroup.find("num_expressions").asInt32();
for (int i = 0; i < nexpressions; i++)
{
std::ostringstream expression_i;
expression_i << "expression_" << i;
Bottle &bExpression = rf.findGroup(expression_i.str());
std::string name = bExpression.find("name").asString();
std::string type = bExpression.find("type").asString();
std::string file = bExpression.find("file").asString();

std::pair<std::string, std::string> par = std::make_pair(name, type);
img_map[par] = file;
}

return ret;
namedWindow("emotion", WND_PROP_FULLSCREEN);
setWindowProperty("emotion", WND_PROP_FULLSCREEN, WINDOW_FULLSCREEN);
Mat start_img = imread(path + "/expressions/images/exp_img_2.png");
if(start_img.empty())
{
yDebug() << "Could not read the image!";
}

imshow("emotion", start_img);
waitKey(1000);

return true;
}

bool ErgoCubEmotions::close()
{
rpcPort.close();
cmdPort.close();
destroyAllWindows();
return true;
}

Expand All @@ -54,93 +83,41 @@ bool ErgoCubEmotions::updateModule()
return true;
}

bool ErgoCubEmotions::respond(const Bottle &cmd, Bottle &reply)
{
if(cmd.size() < 2)
{
yError() << "Invalid command size: it must be 2";
return false;
}

switch (cmd.get(0).asVocab32())
bool ErgoCubEmotions::setEmotion(const std::string& command)
{
std::lock_guard<std::mutex> lg(mtx);
for(auto it = img_map.cbegin(); it!= img_map.cend(); it++)
{
case EMOTION_VOCAB_HELP:
{
// implement
}

case EMOTION_VOCAB_SET:
{
reply.clear();

bool ok = false;
switch (cmd.get(1).asVocab32())
{
// it could be possible to create an array of vocabs and iterate over it
case EMOTION_VOCAB_ANGRY:
{
ok = getCommand(cmd.get(1).toString());
break;
}
case EMOTION_VOCAB_CUN:
{
ok = getCommand(cmd.get(1).toString());
break;
}
case EMOTION_VOCAB_EVIL:
{
ok = getCommand(cmd.get(1).toString());
break;
}
case EMOTION_VOCAB_HAPPY:
{
ok = getCommand(cmd.get(1).toString());
break;
}
case EMOTION_VOCAB_NEUTRAL:
{
ok = getCommand(cmd.get(1).toString());
break;
}
case EMOTION_VOCAB_SAD:
{
ok = getCommand(cmd.get(1).toString());
break;
}
case EMOTION_VOCAB_SHY:
{
ok = getCommand(cmd.get(1).toString());
break;
}
case EMOTION_VOCAB_SURPRISED:
if(it->first.first == command)
{
if(it->first.second == "image")
{
Mat img = imread(path + it->second);
if(img.empty())
{
ok = getCommand(cmd.get(1).toString());
break;
}
default:
{
yDebug() << "Command not recognized!";
break;
yDebug() << "Could not read the image!";
}

imshow("emotion", img);
pollKey();
}

reply.addVocab32(EMOTION_VOCAB_OK);
else if(it->first.second == "video")
{
// VideoCapture cap("images/video.mp4");
// while(1)
// {
// Mat frame;
// cap >> frame;
// imshow("emotion", frame);
// char c=(char)waitKey(25);
// if(c==27)
// break;
// }
// cap.release();
}
}
}
return true;
}

bool ErgoCubEmotions::getCommand(const std::string command)
{
Mat image = imread("images/" + command + ".png");

if(image.empty())
{
yDebug() << "Could not read the image!";
}

imshow("emotion", image);
waitKey(0);

return true;
}
Loading