Der Name des default branch ist ab jetzt für neue Repositories main. The name of the default branch for new repositories is from now on main.

Commit f25210bd authored by Michael Kingston's avatar Michael Kingston Committed by Daniel Müller
Browse files

Interface for use with hmrobot

parent 60b44162
......@@ -18,6 +18,10 @@ find_package(catkin REQUIRED COMPONENTS
#set the default path for built libraries to the "lib" directory
#set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
#set cpp 14 standard
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# Use OGRE from ROS
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} /usr/share/OGRE/cmake/modules)
......@@ -56,6 +60,15 @@ add_message_files(
DisplayImageFile.msg
)
## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
catkin_python_setup()
generate_messages(
DEPENDENCIES
std_msgs
......
......@@ -36,6 +36,13 @@
#include <string>
#include <vector>
#include <pulse/error.h>
#include <pulse/gccmacro.h>
#include <pulse/simple.h>
#include <homer_robot_face/Config.h>
#include <ros/package.h>
class pa_simple;
/**
......
......@@ -22,11 +22,14 @@
#ifndef TALKING_HEAD_INCLUDE_IMAGEDISPLAY_H_
#define TALKING_HEAD_INCLUDE_IMAGEDISPLAY_H_
#include <memory>
#include <queue>
#include <string>
#include <QPainter>
#include <QTimer>
#include <QWidget>
#include <cv.h>
#include <cv_bridge/cv_bridge.h>
#include <ros/ros.h>
......@@ -35,6 +38,7 @@
#include <homer_robot_face/DisplayImage.h> //for stream data
#include <homer_robot_face/DisplayImageFile.h> //for file from harddisk
/**
* @class ImageDisplay
* @brief Displays an image or image stream for visualization in robot_face framework (complete
......@@ -73,7 +77,7 @@ protected:
private:
/** @brief queue to buffer images (necessary if the frequency of incoming images is higher than
* the display frequency)*/
std::queue<QImage*> image_queue_;
std::queue<std::unique_ptr<QImage>> image_queue_;
/** @brief timer to specify the duration of painting the current image*/
QTimer* reset_timer_; // no smart pointer when using parenting of Qt
......
......@@ -26,6 +26,8 @@
#include <ros/ros.h>
//#include "tools/loadRosConfig.h"
#include <homer_robot_face/Config.h>
#if USE_FESTIVAL
#include <homer_robot_face/FestivalGenerator.h>
#endif
......@@ -33,6 +35,12 @@
#include <homer_robot_face/TalkingHead.h>
#include <homer_robot_face/TextOutDisplay.h>
#include <sstream>
#include <string>
#include <vector>
#include <memory>
/**
* @class MainWindow
* @brief Controls and displays Widgets
......@@ -57,12 +65,12 @@ public:
EXP
};
TalkingHead* getFaceWidget();
TextOutDisplay* getTextWidget(textdisplay type);
std::shared_ptr<TalkingHead> getFaceWidget();
std::shared_ptr<TextOutDisplay> getTextWidget(textdisplay type);
#if USE_FESTIVAL
FestivalGenerator* getGenerator();
std::shared_ptr<FestivalGenerator> getGenerator();
#endif
ImageDisplay* getImageStream();
std::shared_ptr<ImageDisplay> getImageStream();
// ImageDisplay* getImageDisplayer();
......@@ -73,23 +81,20 @@ private:
float windowHeight_;
float windowWidth_;
TalkingHead* talking_head_;
std::shared_ptr<TalkingHead> talking_head_;
TextOutDisplay* expc_inp_display_;
TextOutDisplay* text_out_display_;
TextOutDisplay* text_rec_display_;
std::shared_ptr<TextOutDisplay> expc_inp_display_;
std::shared_ptr<TextOutDisplay> text_out_display_;
std::shared_ptr<TextOutDisplay> text_rec_display_;
#if USE_FESTIVAL
FestivalGenerator* festival_generator_;
std::shared_ptr<FestivalGenerator> festival_generator_;
#endif
ImageDisplay* image_stream_display_;
// ImageDisplay* image_display_;
std::shared_ptr<ImageDisplay> image_stream_display_;
/** Load parameter from ROS config */
// void loadParameterInTalkingHead();
/** Initialize qt widgets for talking head, image display, text display, image stream display */
int init();
QBoxLayout* center_layout;
QBoxLayout* main_layout;
QBoxLayout* h_layout;
QWidget* center_widget;
};
#endif // TALKING_HEAD_INCLUDE_MAINWINDOW_H_
......@@ -33,6 +33,10 @@
#include <image_transport/image_transport.h>
#include <string.h>
#include <memory>
#include <homer_robot_face/MainWindow.h>
#include <homer_robot_face/TalkingHead.h>
class MainWindow;
......@@ -52,17 +56,17 @@ public:
/// Instead of ros::spin(), start this thread with the start() method
/// to run the event loop of ros
QtRosNode(
int argc, char* argv[], const char* node_name, MainWindow* main_window, QApplication* app);
int argc, char* argv[], const char* node_name, std::shared_ptr<MainWindow> main_window, std::shared_ptr<QApplication> app);
~QtRosNode();
ros::NodeHandle* getNodeHandle() { return node_handle_; }
std::shared_ptr<ros::NodeHandle> getNodeHandle() { return node_handle_; }
/** @brief This method contains the ROS event loop. Feel free to modify */
void run();
/** @brief returning the window that displays the face stuff */
const MainWindow* getMainWindow() { return main_window_; }
const std::shared_ptr<MainWindow> getMainWindow() { return main_window_; }
void callbackTalkingFinished(const std_msgs::String::ConstPtr& msg);
......@@ -78,9 +82,9 @@ private:
bool quit_from_gui;
bool talking_finished_;
ros::NodeHandle* node_handle_;
ros::NodeHandle* text_out_node_handle_;
ros::NodeHandle* tf_node_handle_;
std::shared_ptr<ros::NodeHandle> node_handle_;
std::unique_ptr<ros::NodeHandle> text_out_node_handle_;
std::unique_ptr<ros::NodeHandle> tf_node_handle_;
ros::CallbackQueue text_out_callback_queue_;
ros::CallbackQueue tf_callback_queue_;
......@@ -109,8 +113,8 @@ private:
std::string tf_text_;
MainWindow* main_window_;
QApplication* application_;
std::shared_ptr<MainWindow> main_window_;
std::shared_ptr<QApplication> application_;
/// subscribe to topics here
void subscribeTopics();
......
......@@ -23,6 +23,7 @@
#define TALKING_HEAD_INCLUDE_ROTATIONLABEL_H_
#include <QLabel>
#include <QPainter>
/**
* @class RotationLabel
......
......@@ -51,6 +51,8 @@
#include <map>
#include <string>
#include <vector>
#include <utility>
#include <memory>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/imgproc/imgproc.hpp>
......@@ -58,6 +60,18 @@
#include <sensor_msgs/image_encodings.h>
#include <homer_robot_face/TextProcessor.h>
//#include "MainWindow.h" //needed for checking on processed images for visualize stream
#if defined(Q_WS_WIN)
#include <windows.h> // needed for WindowFromDC()
#else
#include <QX11Info>
#include <X11/Xlib.h>
#endif
/**
* @class TalkingHead
* @brief Displays a TalkingHead
......@@ -115,6 +129,7 @@ private:
/// Ogre::Scene
Ogre::Root* root_;
Ogre::LogManager* log_manager_;
Ogre::Camera* camera_;
Ogre::Viewport* viewport_;
Ogre::SceneManager* scene_manager_;
......
......@@ -27,6 +27,11 @@
#include <QWidget>
#include <QLabel>
#include <QPainter>
#include <QTimer>
#include <QVBoxLayout>
#include <ros/ros.h>
#include <std_msgs/String.h>
......@@ -87,6 +92,8 @@ private:
int type_;
TextProcessor text_processor_;
QBoxLayout* layout_;
};
#endif // TALKING_HEAD_INCLUDE_TEXTOUTDISPLAY_H_
## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD
from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup
# fetch values from package.xml
setup_args = generate_distutils_setup(
packages=['homer_robot_face'],
package_dir={'': 'src'}
)
setup(**setup_args)
......@@ -19,8 +19,6 @@
* MA 02110-1301 USA or see <http://www.gnu.org/licenses/>.
*******************************************************************************/
#include <string>
#include <homer_robot_face/FestivalGenerator.h>
FestivalGenerator::FestivalGenerator(QObject* parent)
......
......@@ -19,15 +19,7 @@
* MA 02110-1301 USA or see <http://www.gnu.org/licenses/>.
*******************************************************************************/
#include <pulse/error.h>
#include <pulse/gccmacro.h>
#include <pulse/simple.h>
#include <string>
#include <homer_robot_face/Config.h>
#include <homer_robot_face/FestivalSynthesizer.h>
#include <ros/package.h>
FestivalSynthesizer::FestivalSynthesizer()
: festival_initialized_(false)
......
......@@ -21,8 +21,6 @@
#include <homer_robot_face/ImageDisplay.h>
#include <QPainter>
#include <cv.h>
#define MAX_QUEUE_SIZE 5 // maximum number of images to be buffered
......@@ -53,10 +51,7 @@ ImageDisplay::~ImageDisplay()
void ImageDisplay::pop_image_from_queue()
{
QImage* image = image_queue_.front();
image_queue_.pop();
if (image)
delete image;
}
void ImageDisplay::showImage(const unsigned int milliseconds)
......@@ -86,12 +81,12 @@ void ImageDisplay::paintEvent(QPaintEvent*)
case 1:
// if there is only one element in the queue we do not remove it here, because we have to
// wait until the timer fires;
rotateAndDrawImage(&qpainter, image_queue_.front());
rotateAndDrawImage(&qpainter, image_queue_.front().get());
break;
default:
// more than one image in the queue, paint the image at the front of the queue and pop it
// then
rotateAndDrawImage(&qpainter, image_queue_.front());
rotateAndDrawImage(&qpainter, image_queue_.front().get());
pop_image_from_queue();
break;
}
......@@ -144,14 +139,14 @@ inline void ImageDisplay::scaleAndAddImageToQueue(const QImage& image)
}
// scale image to the greater value of height or width to fit in widget
QImage* image_ptr;
std::unique_ptr<QImage> image_ptr;
if (image.height() > image.width())
{
image_ptr = new QImage(image.scaledToHeight(max_image_height_));
image_ptr = std::make_unique<QImage>(image.scaledToHeight(max_image_height_));
}
else
{
image_ptr = new QImage(image.scaledToWidth(max_image_width_));
image_ptr = std::make_unique<QImage>(image.scaledToWidth(max_image_width_));
}
// forcing a deep copy
......@@ -160,7 +155,7 @@ inline void ImageDisplay::scaleAndAddImageToQueue(const QImage& image)
image_ptr->detach();
}
image_queue_.push(image_ptr);
image_queue_.push(std::move(image_ptr));
}
/// Convert function from
......@@ -219,46 +214,27 @@ void ImageDisplay::processImageData(const homer_robot_face::DisplayImage::ConstP
ROS_ERROR("cv_bridge exception: %s", e.what());
return;
}
// scale image to fit in (max_image_width_, max_image_height_)
cv::Mat resized_img_mat;
unsigned int width;
unsigned int height;
// if(image.height() > image.width())
// {
// image_ptr = new QImage(image.scaledToHeight(max_image_height_));
// } else {
// image_ptr = new QImage(image.scaledToWidth(max_image_width_));
// }
// cols == width
// rows == height
// if(sensor_img_cv->image.cols > sensor_img_cv->image.rows)
// {
// cv::resize( sensor_img_cv->image, resized_img_mat, cv::Size(sensor_img_cv->image.cols,
// max_image_height_),0,0, cv::INTER_AREA);
// }
if (sensor_img_cv->image.cols > max_image_width_)
// and from OpenCV to QImage
auto imageQ = std::make_unique<QImage>(cvMatToQImage(sensor_img_cv->image));
// scale image to the greater value of height or width to fit in widget
std::unique_ptr<QImage> image_ptr;
if (imageQ->height() > imageQ->width())
{
width = max_image_width_;
image_ptr = std::make_unique<QImage>(imageQ->scaledToHeight(max_image_height_));
}
else
{
width = sensor_img_cv->image.cols;
image_ptr = std::make_unique<QImage>(imageQ->scaledToWidth(max_image_width_));
}
// height = max_image_height_;
// CV_INTER_AREA looks best for shrinked images
cv::resize(sensor_img_cv->image, resized_img_mat, cv::Size(width, max_image_height_), 0, 0,
cv::INTER_AREA);
// and from OpenCV to QImage
QImage* image_converted = new QImage(cvMatToQImage(resized_img_mat));
image_queue_.push(image_converted);
// forcing a deep copy
if (!image_ptr->isDetached())
{
image_ptr->detach();
}
image_queue_.push(std::move(image_ptr));
}
void ImageDisplay::callbackImageDisplay(const homer_robot_face::DisplayImage::ConstPtr& image_msg)
......
......@@ -20,16 +20,9 @@
*******************************************************************************/
#include <homer_robot_face/MainWindow.h>
#include <sstream>
#include <string>
#include <vector>
//#include "tools/loadRosConfig.h"
#include <homer_robot_face/Config.h>
MainWindow::MainWindow(QWidget* parent)
: QWidget(parent, Qt::FramelessWindowHint)
, talking_head_(0)
, initialized_(false)
{
ROS_INFO("Creating MainWindow..");
......@@ -43,10 +36,6 @@ MainWindow::MainWindow(QWidget* parent)
int height = 800;
int window_rotation = 0;
QBoxLayout* center_layout;
QBoxLayout* main_layout;
QBoxLayout* h_layout;
int max_width = width;
int max_height = height;
int min_width = width;
......@@ -68,7 +57,7 @@ MainWindow::MainWindow(QWidget* parent)
window_rotation = cfg.get("Window Rotation");
assert(window_rotation == 0 || window_rotation == 90 || window_rotation == 180
|| window_rotation == 270);
talking_head_ = new TalkingHead(this, mesh_filename, material_colors, window_rotation);
talking_head_ = std::make_unique<TalkingHead>(this, mesh_filename, material_colors, window_rotation);
std::cout << "Mesh Filename : " << mesh_filename << std::endl;
}
......@@ -129,27 +118,27 @@ MainWindow::MainWindow(QWidget* parent)
center_layout->setContentsMargins(0, 0, 0, 0);
#if USE_FESTIVAL
festival_generator_ = new FestivalGenerator();
festival_generator_ = std::make_shared<FestivalGenerator>();
#endif
// ImageStreamDisplay
image_stream_display_
= new ImageDisplay(window_rotation, windowWidth_, windowHeight_ - 60, this);
= std::make_shared<ImageDisplay>(window_rotation, windowWidth_, windowHeight_ - 60, this);
image_stream_display_->setMinimumSize(width, height - 60);
image_stream_display_->setMaximumSize(min_width, min_height - 60);
// ExpectedInputDisplay
expc_inp_display_ = new TextOutDisplay(0, 20, ::EXP, window_rotation, this);
expc_inp_display_ = std::make_shared<TextOutDisplay>(0, 20, ::EXP, window_rotation, this);
custom_palette.setColor(QPalette::WindowText, QColor(150, 150, 200));
expc_inp_display_->setPalette(custom_palette);
expc_inp_display_->setMaximumSize(width, height);
// TextOutputDisplay
text_out_display_ = new TextOutDisplay(0, 26, ::OUT, window_rotation, this);
text_out_display_ = std::make_shared<TextOutDisplay>(0, 26, ::OUT, window_rotation, this);
text_out_display_->setMaximumSize(width, height);
// TextRecognitionDisplay
text_rec_display_ = new TextOutDisplay(0, 20, ::REC, window_rotation, this);
text_rec_display_ = std::make_shared<TextOutDisplay>(0, 20, ::REC, window_rotation, this);
custom_palette.setColor(QPalette::WindowText, QColor(200, 150, 150));
text_rec_display_->setPalette(custom_palette);
text_rec_display_->setMaximumSize(width, height);
......@@ -160,26 +149,26 @@ MainWindow::MainWindow(QWidget* parent)
if (window_rotation == 0 || window_rotation == 270)
{
center_layout->addWidget(expc_inp_display_);
center_layout->addWidget(expc_inp_display_.get());
center_layout->addStretch();
center_layout->addWidget(text_out_display_);
center_layout->addWidget(text_out_display_.get());
center_layout->addStretch();
center_layout->addWidget(text_rec_display_);
center_layout->addWidget(text_rec_display_.get());
center_layout->setStretchFactor(text_out_display_, 1);
center_layout->setStretchFactor(text_out_display_.get(), 1);
// center_widget->setMinimumSize( width, height );
center_widget->setMaximumSize(width, height);
center_widget->setLayout(center_layout);
main_layout->addWidget(talking_head_);
main_layout->addWidget(talking_head_.get());
talking_head_->setMinimumSize(width, height);
talking_head_->setMaximumSize(min_width, min_height);
main_layout->setStretchFactor(talking_head_, 1);
main_layout->setStretchFactor(talking_head_.get(), 1);
main_layout->addWidget(image_stream_display_); // comment in
main_layout->setStretchFactor(image_stream_display_, 1); // comment in
main_layout->addWidget(image_stream_display_.get()); // comment in
main_layout->setStretchFactor(image_stream_display_.get(), 1); // comment in
h_layout->setSpacing(0);
h_layout->setContentsMargins(0, 0, 0, 0);
......@@ -195,13 +184,13 @@ MainWindow::MainWindow(QWidget* parent)
}
else // if( window_rotation == 90 || window_rotation == 180 )
{
center_layout->addWidget(text_rec_display_);
center_layout->addWidget(text_rec_display_.get());
center_layout->addStretch();
center_layout->addWidget(text_out_display_);
center_layout->addWidget(text_out_display_.get());
center_layout->addStretch();
center_layout->addWidget(expc_inp_display_);
center_layout->addWidget(expc_inp_display_.get());
center_layout->setStretchFactor(text_out_display_, 1);
center_layout->setStretchFactor(text_out_display_.get(), 1);
// center_widget->setMinimumSize( width, height );
center_widget->setMaximumSize(width, height);
......@@ -218,40 +207,41 @@ MainWindow::MainWindow(QWidget* parent)
main_layout->addLayout(h_layout);
main_layout->addStretch();
main_layout->addWidget(talking_head_);
main_layout->addWidget(talking_head_.get());
talking_head_->setMinimumSize(width, height);
talking_head_->setMaximumSize(min_width, min_height);
main_layout->setStretchFactor(talking_head_, 1);
main_layout->setStretchFactor(talking_head_.get(), 1);
main_layout->addWidget(image_stream_display_);
main_layout->setStretchFactor(image_stream_display_, 1);
main_layout->addWidget(image_stream_display_.get());
main_layout->setStretchFactor(image_stream_display_.get(), 1);
}
// main_layout->setSizeConstraint(QLayout::SetFixedSize); //TODO: toProve
setLayout(main_layout);
std::cout << "end of main window constructor" << std::endl;
std::ostringstream next_command;
next_command << "Info: " << qApp->desktop()->screenNumber(talking_head_) << endl;
next_command << "Info: " << qApp->desktop()->screenNumber(talking_head_.get()) << endl;
ROS_INFO("%s", next_command.str().c_str());
}
MainWindow::~MainWindow()
{
if (talking_head_)
delete talking_head_;
#if USE_FESTIVAL
if (festival_generator_)
delete festival_generator_;
#endif
if (image_stream_display_)
delete image_stream_display_;
if (text_out_display_)
delete text_out_display_;
if (text_rec_display_)
delete text_rec_display_;
if (expc_inp_display_)
delete expc_inp_display_;
// if( image_display_ ) delete image_display_;
if (center_layout)
{
delete center_layout;
}
if (main_layout)
{
delete main_layout;
}
if (h_layout)
{
delete h_layout;
}
if (center_widget)
{
delete center_widget;
}
}
// void MainWindow::loadParameterInTalkingHead()
......@@ -307,216 +297,13 @@ MainWindow::~MainWindow()
// talking_head_ = new TalkingHead( this, mesh_filename, material_colors, window_rotation );
//}
int MainWindow::init()
{
if (initialized_)
ROS_WARN("MainWindow has been already initialized. Reinitialize..");
ROS_INFO("Initialize MainWindow..");
// this->loadParameterInTalkingHead();