Revision ea068cf1
CMakeLists.txt | ||
---|---|---|
7 | 7 |
|
8 | 8 |
################################################################ |
9 | 9 |
# check for ROS support: |
10 |
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs sensor_msgs message_generation genmsg) |
|
10 |
find_package(catkin REQUIRED COMPONENTS |
|
11 |
roscpp |
|
12 |
std_msgs |
|
13 |
sensor_msgs |
|
14 |
message_generation |
|
15 |
genmsg |
|
16 |
dynamic_reconfigure |
|
17 |
) |
|
18 |
|
|
11 | 19 |
IF (NOT catkin_FOUND) |
12 | 20 |
MESSAGE(FATAL_ERROR "Error: could not find ROS middleware!") |
13 | 21 |
ENDIF (NOT catkin_FOUND) |
... | ... | |
57 | 65 |
humotion |
58 | 66 |
) |
59 | 67 |
|
68 |
# add dynamic reconfigure api |
|
69 |
generate_dynamic_reconfigure_options( |
|
70 |
cfg/humotion.cfg |
|
71 |
) |
|
60 | 72 |
|
61 | 73 |
# |
62 | 74 |
################################### |
... | ... | |
93 | 105 |
#link_directories (${Boost_LIBRARY_DIRS} ${REFLEXXES_LIBRARY_DIRS} ${catkin_LIBRARY_DIRS}) |
94 | 106 |
|
95 | 107 |
## Declare a cpp library |
96 |
add_library(humotion
|
|
108 |
add_library(${PROJECT_NAME}
|
|
97 | 109 |
src/mouth_state.cpp |
98 | 110 |
src/gaze_state.cpp |
99 | 111 |
|
... | ... | |
123 | 135 |
|
124 | 136 |
## Add cmake target dependencies of the executable/library |
125 | 137 |
## as an example, message headers may need to be generated before nodes |
126 |
add_dependencies(humotion ${catkin_EXPORTED_TARGETS} humotion_gencpp)
|
|
138 |
add_dependencies(${PROJECT_NAME} ${catkin_EXPORTED_TARGETS} ${PROJECT_NAME}_gencpp ${PROJECT_NAME}_gencfg)
|
|
127 | 139 |
|
128 | 140 |
## Specify libraries to link a library or executable target against |
129 |
target_link_libraries(humotion
|
|
141 |
target_link_libraries(${PROJECT_NAME}
|
|
130 | 142 |
${Boost_LIBRARIES} |
131 | 143 |
${catkin_LIBRARIES} |
132 | 144 |
${REFLEXXES_LIBRARY} |
133 | 145 |
) |
134 | 146 |
|
135 |
set_property(TARGET humotion PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|
147 |
set_property(TARGET ${PROJECT_NAME} PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|
136 | 148 |
|
137 | 149 |
############# |
138 | 150 |
## Install ## |
... | ... | |
149 | 161 |
# ) |
150 | 162 |
|
151 | 163 |
## Mark executables and/or libraries for installation |
152 |
install(TARGETS humotion
|
|
164 |
install(TARGETS ${PROJECT_NAME}
|
|
153 | 165 |
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} |
154 | 166 |
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} |
155 | 167 |
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} |
... | ... | |
197 | 209 |
${CMAKE_CURRENT_SOURCE_DIR}/src |
198 | 210 |
${CMAKE_CURRENT_SOURCE_DIR}/src |
199 | 211 |
${CMAKE_CURRENT_BINARY_DIR}/src) |
200 |
add_dependencies(humotion cpplint_src cpplint_include)
|
|
212 |
add_dependencies(${PROJECT_NAME} cpplint_src cpplint_include)
|
|
201 | 213 |
|
202 | 214 |
#workaround for qtcreator ide integration. do not remove! |
203 | 215 |
file(GLOB_RECURSE NODE_DUMMY_TARGETS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h *.cfg *.yaml *.xml *.launch) |
include/humotion/client/client.h | ||
---|---|---|
52 | 52 |
|
53 | 53 |
|
54 | 54 |
private: |
55 |
Middleware *middleware; |
|
55 |
Middleware *middleware_;
|
|
56 | 56 |
}; |
57 | 57 |
|
58 | 58 |
} // namespace client |
include/humotion/client/middleware.h | ||
---|---|---|
53 | 53 |
virtual void tick() = 0; |
54 | 54 |
|
55 | 55 |
protected: |
56 |
MouthState mouth_state; |
|
57 |
GazeState gaze_state; |
|
58 |
std::string base_scope; |
|
56 |
MouthState mouth_state_;
|
|
57 |
GazeState gaze_state_;
|
|
58 |
std::string base_scope_;
|
|
59 | 59 |
}; |
60 | 60 |
|
61 | 61 |
} // namespace client |
include/humotion/client/middleware_ros.h | ||
---|---|---|
48 | 48 |
void tick(); |
49 | 49 |
|
50 | 50 |
private: |
51 |
bool tick_necessary; |
|
51 |
bool tick_necessary_;
|
|
52 | 52 |
|
53 |
ros::Publisher mouth_target_publisher; |
|
54 |
ros::Publisher gaze_target_publisher; |
|
53 |
ros::Publisher mouth_target_publisher_;
|
|
54 |
ros::Publisher gaze_target_publisher_;
|
|
55 | 55 |
}; |
56 | 56 |
|
57 | 57 |
} // namespace client |
include/humotion/server/controller.h | ||
---|---|---|
53 | 53 |
void set_activated(void); |
54 | 54 |
|
55 | 55 |
private: |
56 |
bool activated; |
|
57 | 56 |
void add_motion_generator(MotionGenerator *m); |
58 | 57 |
GazeState relative_gaze_to_absolute_gaze(GazeState relative); |
59 | 58 |
|
60 | 59 |
typedef std::vector<MotionGenerator *> motion_generator_vector_t; |
61 |
motion_generator_vector_t motion_generator_vector; |
|
62 |
JointInterface *joint_interface; |
|
60 |
motion_generator_vector_t motion_generator_vector_; |
|
63 | 61 |
|
64 |
Timestamp last_known_absolute_timestamp; |
|
65 |
double last_known_absolute_target_pan; |
|
66 |
double last_known_absolute_target_tilt; |
|
67 |
double last_known_absolute_target_roll; |
|
62 |
JointInterface *joint_interface_; |
|
63 |
|
|
64 |
bool activated_; |
|
65 |
|
|
66 |
Timestamp last_known_absolute_timestamp_; |
|
67 |
double last_known_absolute_target_pan_; |
|
68 |
double last_known_absolute_target_tilt_; |
|
69 |
double last_known_absolute_target_roll_; |
|
68 | 70 |
}; |
69 | 71 |
|
70 | 72 |
} // namespace server |
include/humotion/server/eye_motion_generator.h | ||
---|---|---|
48 | 48 |
void setup_eyemotion(int dof, float target, float current_position, |
49 | 49 |
float current_velocity, Timestamp timestamp); |
50 | 50 |
|
51 |
TimestampedList tsl_gaze_target_pan; |
|
52 |
TimestampedList tsl_gaze_target_tilt; |
|
53 |
TimestampedList tsl_gaze_target_vergence; |
|
51 |
TimestampedList tsl_gaze_target_pan_;
|
|
52 |
TimestampedList tsl_gaze_target_tilt_;
|
|
53 |
TimestampedList tsl_gaze_target_vergence_;
|
|
54 | 54 |
}; |
55 | 55 |
|
56 | 56 |
} // namespace server |
include/humotion/server/eyelid_motion_generator.h | ||
---|---|---|
47 | 47 |
|
48 | 48 |
|
49 | 49 |
private: |
50 |
bool saccade_blink_active; |
|
51 |
bool saccade_blink_requested; |
|
52 |
|
|
53 |
enum SIDE_ID { |
|
54 |
LEFT = 0, |
|
55 |
RIGHT, |
|
56 |
SIDE_ID_SIZE |
|
57 |
}; |
|
58 |
|
|
59 |
bool eyeblink_active[SIDE_ID_SIZE]; |
|
60 |
bool eyelid_closed[SIDE_ID_SIZE]; |
|
61 |
|
|
62 | 50 |
void start_external_eyeblinks(int duration_left, int duration_right); |
63 | 51 |
void process_saccadic_eyeblinks(); |
64 | 52 |
void process_periodic_eyeblinks(); |
... | ... | |
69 | 57 |
|
70 | 58 |
void close_eyelid(int joint_id); |
71 | 59 |
|
60 |
enum SIDE_ID { |
|
61 |
LEFT = 0, |
|
62 |
RIGHT, |
|
63 |
SIDE_ID_SIZE |
|
64 |
}; |
|
65 |
|
|
66 |
bool saccade_blink_active_; |
|
67 |
bool saccade_blink_requested_; |
|
68 |
|
|
69 |
bool eyeblink_active_[SIDE_ID_SIZE]; |
|
70 |
bool eyelid_closed_[SIDE_ID_SIZE]; |
|
71 |
|
|
72 | 72 |
static const float SACCADE_SPEED_THRESHOLD; |
73 | 73 |
static const float EYEBLINK_DURATION_MS; |
74 | 74 |
static const float EYEBLINK_EYERY_MS_MIN; |
75 | 75 |
static const float EYEBLINK_EYERY_MS_MAX; |
76 | 76 |
static const float EYEBLINK_BLOCKING_TIME; |
77 | 77 |
|
78 |
boost::system_time periodic_blink_start_time; |
|
79 |
boost::system_time eyeblink_timeout[SIDE_ID_SIZE]; |
|
80 |
boost::system_time eyeblink_blocked_timeout; |
|
78 |
boost::system_time periodic_blink_start_time_;
|
|
79 |
boost::system_time eyeblink_timeout_[SIDE_ID_SIZE];
|
|
80 |
boost::system_time eyeblink_blocked_timeout_;
|
|
81 | 81 |
}; |
82 | 82 |
|
83 | 83 |
} // namespace server |
include/humotion/server/joint_interface.h | ||
---|---|---|
84 | 84 |
|
85 | 85 |
unsigned int get_and_clear_incoming_position_count(); |
86 | 86 |
|
87 |
enum JOINT_ID_ENUM {
|
|
87 |
enum JOINT_ID_ENUM{ |
|
88 | 88 |
ZERO = 0, |
89 | 89 |
ID_LIP_LEFT_UPPER, |
90 | 90 |
ID_LIP_LEFT_LOWER, |
... | ... | |
126 | 126 |
float joint_target_position_[JOINT_ID_ENUM_SIZE]; |
127 | 127 |
float joint_target_velocity_[JOINT_ID_ENUM_SIZE]; |
128 | 128 |
|
129 |
boost::mutex joint_ts_position_map_access_mutex; |
|
130 |
boost::mutex joint_ts_speed_map_access_mutex; |
|
131 |
joint_tsl_map_t joint_ts_position_map; |
|
132 |
joint_tsl_map_t joint_ts_speed_map; |
|
129 |
boost::mutex joint_ts_position_map_access_mutex_;
|
|
130 |
boost::mutex joint_ts_speed_map_access_mutex_;
|
|
131 |
joint_tsl_map_t joint_ts_position_map_;
|
|
132 |
joint_tsl_map_t joint_ts_speed_map_;
|
|
133 | 133 |
|
134 |
bool mouth_enabled; |
|
135 |
bool gaze_enabled; |
|
136 |
unsigned int incoming_position_count; |
|
134 |
bool mouth_enabled_;
|
|
135 |
bool gaze_enabled_;
|
|
136 |
unsigned int incoming_position_count_;
|
|
137 | 137 |
}; |
138 | 138 |
|
139 | 139 |
} // namespace server |
include/humotion/server/middleware.h | ||
---|---|---|
48 | 48 |
virtual void tick() = 0; |
49 | 49 |
|
50 | 50 |
protected: |
51 |
Controller *controller; |
|
52 |
std::string base_scope; |
|
51 |
Controller *controller_;
|
|
52 |
std::string base_scope_;
|
|
53 | 53 |
}; |
54 | 54 |
|
55 | 55 |
} // namespace server |
include/humotion/server/middleware_ros.h | ||
---|---|---|
29 | 29 |
#define INCLUDE_HUMOTION_SERVER_MIDDLEWARE_ROS_H_ |
30 | 30 |
|
31 | 31 |
#include <boost/shared_ptr.hpp> |
32 |
#include <dynamic_reconfigure/server.h> |
|
32 | 33 |
#include <ros/ros.h> |
34 |
|
|
33 | 35 |
#include <string> |
34 | 36 |
|
35 | 37 |
#include "humotion/gaze.h" |
38 |
#include "humotion/humotionConfig.h" |
|
36 | 39 |
#include "humotion/mouth.h" |
37 | 40 |
#include "humotion/server/middleware.h" |
38 | 41 |
|
... | ... | |
46 | 49 |
bool ok(); |
47 | 50 |
void tick(); |
48 | 51 |
|
52 |
void dynamic_reconfigure_callback(const humotion::humotionConfig &config, uint32_t level); |
|
53 |
|
|
49 | 54 |
private: |
50 |
bool tick_necessary; |
|
51 | 55 |
void incoming_mouth_target(const humotion::mouth::ConstPtr& msg); |
52 | 56 |
void incoming_gaze_target(const humotion::gaze::ConstPtr& msg); |
57 |
void attach_to_reconfiguration_server(ros::NodeHandle priv_nodehandle); |
|
58 |
|
|
59 |
|
|
60 |
bool tick_necessary_; |
|
53 | 61 |
|
54 |
ros::Subscriber mouth_target_subscriber; |
|
55 |
ros::Subscriber gaze_target_subscriber; |
|
62 |
ros::Subscriber mouth_target_subscriber_; |
|
63 |
ros::Subscriber gaze_target_subscriber_; |
|
64 |
dynamic_reconfigure::Server<humotion::humotionConfig> *reconf_server_; |
|
56 | 65 |
}; |
57 | 66 |
|
58 | 67 |
} // namespace server |
include/humotion/server/motion_generator.h | ||
---|---|---|
53 | 53 |
float get_current_speed(int joint_id); |
54 | 54 |
humotion::Timestamp get_timestamped_state(int joint_id, float *position, float *velocity); |
55 | 55 |
float limit_target(int joint_id, float val); |
56 |
bool mouth_target_input_active(); |
|
57 |
bool gaze_target_input_active(); |
|
56 | 58 |
|
57 |
JointInterface *joint_interface; |
|
59 |
JointInterface *joint_interface_;
|
|
58 | 60 |
|
59 | 61 |
// gaze |
60 |
GazeState requested_gaze_state; |
|
61 |
boost::system_time last_gaze_target_update; |
|
62 |
bool gaze_target_input_active(); |
|
62 |
GazeState requested_gaze_state_; |
|
63 |
boost::system_time last_gaze_target_update_; |
|
63 | 64 |
|
64 | 65 |
// mouth |
65 |
MouthState requested_mouth_target; |
|
66 |
boost::system_time last_mouth_target_update; |
|
67 |
bool mouth_target_input_active(); |
|
66 |
MouthState requested_mouth_target_; |
|
67 |
boost::system_time last_mouth_target_update_; |
|
68 | 68 |
}; |
69 | 69 |
|
70 | 70 |
} // namespace server |
include/humotion/server/neck_motion_generator.h | ||
---|---|---|
44 | 44 |
private: |
45 | 45 |
float get_breath_offset(); |
46 | 46 |
|
47 |
GazeState previous_neck_target; |
|
48 |
GazeState requested_neck_state; |
|
49 |
bool neck_saccade_reached_goal; |
|
50 |
bool neck_saccade_active; |
|
47 |
GazeState previous_neck_target_; |
|
48 |
GazeState requested_neck_state_; |
|
49 |
bool neck_saccade_reached_goal_; |
|
50 |
bool neck_saccade_active_; |
|
51 |
float breath_time_; |
|
51 | 52 |
|
52 | 53 |
static const float CONST_GUITTON87_A; |
53 | 54 |
static const float CONST_GUITTON87_B; |
54 | 55 |
|
55 |
float breath_time; |
|
56 | 56 |
static const float CONST_BREATH_PERIOD; |
57 | 57 |
static const float CONST_BREATH_AMPLITUDE; |
58 | 58 |
}; |
include/humotion/server/server.h | ||
---|---|---|
51 | 51 |
private: |
52 | 52 |
void start_motion_generation_thread(); |
53 | 53 |
void motion_generation_thread(); |
54 |
boost::thread *motion_generation_thread_ptr; |
|
54 |
boost::thread *motion_generation_thread_ptr_;
|
|
55 | 55 |
|
56 |
Middleware *middleware; |
|
57 |
Controller *controller; |
|
58 |
JointInterface *joint_interface; |
|
56 |
Middleware *middleware_;
|
|
57 |
Controller *controller_;
|
|
58 |
JointInterface *joint_interface_;
|
|
59 | 59 |
}; |
60 | 60 |
|
61 | 61 |
} // namespace server |
include/humotion/timestamped_list.h | ||
---|---|---|
53 | 53 |
Timestamp get_first_timestamp(); |
54 | 54 |
|
55 | 55 |
private: |
56 |
mutable boost::mutex access_mutex; |
|
56 |
mutable boost::mutex access_mutex_;
|
|
57 | 57 |
float interpolate(TimestampedFloat a, TimestampedFloat b, Timestamp timestamp); |
58 |
timestamped_float_list_t tsf_list; |
|
58 |
timestamped_float_list_t tsf_list_;
|
|
59 | 59 |
}; |
60 | 60 |
|
61 | 61 |
} // namespace humotion |
src/client/client.cpp | ||
---|---|---|
46 | 46 |
|
47 | 47 |
// start middleware |
48 | 48 |
if (mw == "ROS") { |
49 |
middleware = new humotion::client::MiddlewareROS(scope); |
|
49 |
middleware_ = new humotion::client::MiddlewareROS(scope);
|
|
50 | 50 |
} else { |
51 | 51 |
printf("> ERROR: invalid mw '%s' given. RSB support was droppd. please use ROS\n\n", |
52 | 52 |
mw.c_str()); |
... | ... | |
61 | 61 |
//! check if connection is ok |
62 | 62 |
//! \return true if conn is alive |
63 | 63 |
bool Client::ok() { |
64 |
return middleware->ok(); |
|
64 |
return middleware_->ok();
|
|
65 | 65 |
} |
66 | 66 |
|
67 | 67 |
//! do a single middleware tick: |
68 | 68 |
void Client::tick() { |
69 |
middleware->tick(); |
|
69 |
middleware_->tick();
|
|
70 | 70 |
} |
71 | 71 |
|
72 | 72 |
//! set mouth position |
73 | 73 |
//! \param MouthState m to set |
74 | 74 |
//! \param send data to server (optional, use manual call to send_*() to trigger update on server) |
75 | 75 |
void Client::update_mouth_target(MouthState m, bool send) { |
76 |
middleware->update_mouth_target(m, send); |
|
76 |
middleware_->update_mouth_target(m, send);
|
|
77 | 77 |
} |
78 | 78 |
|
79 | 79 |
//! set gaze direction |
80 | 80 |
//! \param GazeState m to set |
81 | 81 |
//! \param send data to server (optional, use manual call to send_*() to trigger update on server) |
82 | 82 |
void Client::update_gaze_target(GazeState s, bool send) { |
83 |
middleware->update_gaze_target(s, send); |
|
83 |
middleware_->update_gaze_target(s, send);
|
|
84 | 84 |
} |
85 | 85 |
|
86 | 86 |
|
87 | 87 |
//! send all targets to server |
88 | 88 |
void Client::send_all() { |
89 |
middleware->send_all(); |
|
89 |
middleware_->send_all();
|
|
90 | 90 |
} |
91 | 91 |
|
src/client/middleware.cpp | ||
---|---|---|
37 | 37 |
//! constructor |
38 | 38 |
//! open a new Middleware instance. |
39 | 39 |
Middleware::Middleware(std::string scope) { |
40 |
base_scope = scope; |
|
40 |
base_scope_ = scope;
|
|
41 | 41 |
} |
42 | 42 |
|
43 | 43 |
//! destructor |
... | ... | |
49 | 49 |
//! \param MouthState m to set |
50 | 50 |
//! \param send data to server (optional, use manual call to send_*() to trigger update on server) |
51 | 51 |
void Middleware::update_mouth_target(MouthState m, bool send) { |
52 |
mouth_state = m; |
|
52 |
mouth_state_ = m;
|
|
53 | 53 |
if (send) { |
54 | 54 |
send_mouth_target(); |
55 | 55 |
} |
... | ... | |
59 | 59 |
//! \param GazeState m to set |
60 | 60 |
//! \param send data to server (optional, use manual call to send_*() to trigger update on server) |
61 | 61 |
void Middleware::update_gaze_target(GazeState s, bool send) { |
62 |
gaze_state = s; |
|
62 |
gaze_state_ = s;
|
|
63 | 63 |
if (send) { |
64 | 64 |
send_gaze_target(); |
65 | 65 |
} |
src/client/middleware_ros.cpp | ||
---|---|---|
42 | 42 |
MiddlewareROS::MiddlewareROS(std::string scope) : Middleware(scope) { |
43 | 43 |
// start ros core |
44 | 44 |
if (!ros::isInitialized()) { |
45 |
tick_necessary = true; |
|
46 |
std::string node_name = "humotion_client__"+ base_scope; |
|
45 |
tick_necessary_ = true;
|
|
46 |
std::string node_name = "humotion_client__"+ base_scope_;
|
|
47 | 47 |
node_name.erase(std::remove(node_name.begin(), node_name.end(), '/'), node_name.end()); |
48 | 48 |
|
49 | 49 |
ros::M_string no_remapping; |
50 | 50 |
ros::init(no_remapping, node_name); |
51 | 51 |
} else { |
52 | 52 |
// another ros thread already takes care of spinning |
53 |
tick_necessary = false; |
|
53 |
tick_necessary_ = false;
|
|
54 | 54 |
} |
55 | 55 |
|
56 | 56 |
// create node handle |
57 | 57 |
ros::NodeHandle n; |
58 | 58 |
|
59 | 59 |
// set up publishers |
60 |
mouth_target_publisher = n.advertise<humotion::mouth>(base_scope +
|
|
60 |
mouth_target_publisher_ = n.advertise<humotion::mouth>(base_scope_ +
|
|
61 | 61 |
"/humotion/mouth/target", 100); |
62 |
gaze_target_publisher = n.advertise<humotion::gaze>(base_scope +
|
|
62 |
gaze_target_publisher_ = n.advertise<humotion::gaze>(base_scope_ +
|
|
63 | 63 |
"/humotion/gaze/target", 100); |
64 | 64 |
} |
65 | 65 |
|
... | ... | |
75 | 75 |
|
76 | 76 |
//! do a single tick |
77 | 77 |
void MiddlewareROS::tick() { |
78 |
if (tick_necessary) { |
|
78 |
if (tick_necessary_) {
|
|
79 | 79 |
ros::spinOnce(); |
80 | 80 |
} |
81 | 81 |
} |
... | ... | |
89 | 89 |
// set timestamp |
90 | 90 |
msg.header.stamp = ros::Time::now(); |
91 | 91 |
|
92 |
msg.position.left = mouth_state.position_left; |
|
93 |
msg.position.center = mouth_state.position_center; |
|
94 |
msg.position.right = mouth_state.position_right; |
|
92 |
msg.position.left = mouth_state_.position_left;
|
|
93 |
msg.position.center = mouth_state_.position_center;
|
|
94 |
msg.position.right = mouth_state_.position_right;
|
|
95 | 95 |
|
96 |
msg.opening.left = mouth_state.opening_left; |
|
97 |
msg.opening.center = mouth_state.opening_center; |
|
98 |
msg.opening.right = mouth_state.opening_right; |
|
96 |
msg.opening.left = mouth_state_.opening_left;
|
|
97 |
msg.opening.center = mouth_state_.opening_center;
|
|
98 |
msg.opening.right = mouth_state_.opening_right;
|
|
99 | 99 |
|
100 | 100 |
|
101 | 101 |
// add position to send queue |
102 |
mouth_target_publisher.publish(msg); |
|
102 |
mouth_target_publisher_.publish(msg);
|
|
103 | 103 |
|
104 | 104 |
// allow ros to handle data |
105 | 105 |
tick(); |
... | ... | |
113 | 113 |
// set timestamp |
114 | 114 |
msg.header.stamp = ros::Time::now(); |
115 | 115 |
|
116 |
msg.pan = gaze_state.pan; |
|
117 |
msg.tilt = gaze_state.tilt; |
|
118 |
msg.roll = gaze_state.roll; |
|
119 |
msg.vergence = gaze_state.vergence; |
|
116 |
msg.pan = gaze_state_.pan;
|
|
117 |
msg.tilt = gaze_state_.tilt;
|
|
118 |
msg.roll = gaze_state_.roll;
|
|
119 |
msg.vergence = gaze_state_.vergence;
|
|
120 | 120 |
|
121 |
msg.pan_offset = gaze_state.pan_offset; |
|
122 |
msg.tilt_offset = gaze_state.tilt_offset; |
|
123 |
msg.roll_offset = gaze_state.roll_offset; |
|
121 |
msg.pan_offset = gaze_state_.pan_offset;
|
|
122 |
msg.tilt_offset = gaze_state_.tilt_offset;
|
|
123 |
msg.roll_offset = gaze_state_.roll_offset;
|
|
124 | 124 |
|
125 |
msg.eyelid_opening_upper = gaze_state.eyelid_opening_upper; |
|
126 |
msg.eyelid_opening_lower = gaze_state.eyelid_opening_lower; |
|
125 |
msg.eyelid_opening_upper = gaze_state_.eyelid_opening_upper;
|
|
126 |
msg.eyelid_opening_lower = gaze_state_.eyelid_opening_lower;
|
|
127 | 127 |
|
128 |
msg.eyebrow_left = gaze_state.eyebrow_left; |
|
129 |
msg.eyebrow_right = gaze_state.eyebrow_right; |
|
128 |
msg.eyebrow_left = gaze_state_.eyebrow_left;
|
|
129 |
msg.eyebrow_right = gaze_state_.eyebrow_right;
|
|
130 | 130 |
|
131 |
msg.eyeblink_request_left = gaze_state.eyeblink_request_left; |
|
132 |
msg.eyeblink_request_right = gaze_state.eyeblink_request_right; |
|
131 |
msg.eyeblink_request_left = gaze_state_.eyeblink_request_left;
|
|
132 |
msg.eyeblink_request_right = gaze_state_.eyeblink_request_right;
|
|
133 | 133 |
|
134 |
if (gaze_state.gaze_type == GazeState::GAZETYPE_ABSOLUTE) { |
|
134 |
if (gaze_state_.gaze_type == GazeState::GAZETYPE_ABSOLUTE) {
|
|
135 | 135 |
msg.gaze_type = humotion::gaze::GAZETYPE_ABSOLUTE; |
136 | 136 |
} else { |
137 | 137 |
msg.gaze_type = humotion::gaze::GAZETYPE_RELATIVE; |
138 | 138 |
} |
139 |
msg.gaze_timestamp.sec = gaze_state.timestamp.sec; |
|
140 |
msg.gaze_timestamp.nsec = gaze_state.timestamp.nsec; |
|
139 |
msg.gaze_timestamp.sec = gaze_state_.timestamp.sec;
|
|
140 |
msg.gaze_timestamp.nsec = gaze_state_.timestamp.nsec;
|
|
141 | 141 |
|
142 | 142 |
// add position to send queue |
143 |
gaze_target_publisher.publish(msg); |
|
143 |
gaze_target_publisher_.publish(msg);
|
|
144 | 144 |
|
145 | 145 |
// allow ros to handle data |
146 | 146 |
tick(); |
src/server/controller.cpp | ||
---|---|---|
40 | 40 |
using humotion::server::Controller; |
41 | 41 |
|
42 | 42 |
//! constructor |
43 |
Controller::Controller(JointInterface *j) : activated(false) { |
|
44 |
joint_interface = j; |
|
43 |
Controller::Controller(JointInterface *j) { |
|
44 |
activated_ = false; |
|
45 |
joint_interface_ = j; |
|
45 | 46 |
} |
46 | 47 |
|
47 | 48 |
//! destructor |
... | ... | |
54 | 55 |
// (i.e. the neck generator must be added after the eye generator!) |
55 | 56 |
|
56 | 57 |
// eye motion generation: |
57 |
add_motion_generator(new EyeMotionGenerator(joint_interface)); |
|
58 |
add_motion_generator(new EyeMotionGenerator(joint_interface_));
|
|
58 | 59 |
|
59 | 60 |
// eyelid motion generator |
60 |
add_motion_generator(new EyelidMotionGenerator(joint_interface)); |
|
61 |
add_motion_generator(new EyelidMotionGenerator(joint_interface_));
|
|
61 | 62 |
|
62 | 63 |
// neck motion generator |
63 |
add_motion_generator(new NeckMotionGenerator(joint_interface)); |
|
64 |
add_motion_generator(new NeckMotionGenerator(joint_interface_));
|
|
64 | 65 |
|
65 | 66 |
// mouth motion generator |
66 |
add_motion_generator(new MouthMotionGenerator(joint_interface)); |
|
67 |
add_motion_generator(new MouthMotionGenerator(joint_interface_));
|
|
67 | 68 |
|
68 | 69 |
// eyebrow motion generator |
69 |
add_motion_generator(new EyebrowMotionGenerator(joint_interface)); |
|
70 |
add_motion_generator(new EyebrowMotionGenerator(joint_interface_));
|
|
70 | 71 |
} |
71 | 72 |
|
72 | 73 |
//! add a single motion genrator |
73 | 74 |
void Controller::add_motion_generator(MotionGenerator *m) { |
74 |
motion_generator_vector.push_back(m); |
|
75 |
motion_generator_vector_.push_back(m);
|
|
75 | 76 |
} |
76 | 77 |
|
77 | 78 |
//! calculate target angles for all motion generators: |
78 | 79 |
void Controller::calculate_targets() { |
79 | 80 |
Controller::motion_generator_vector_t::iterator it; |
80 |
for (it = motion_generator_vector.begin(); it < motion_generator_vector.end(); it++) {
|
|
81 |
for (it = motion_generator_vector_.begin(); it < motion_generator_vector_.end(); it++) {
|
|
81 | 82 |
(*it)->calculate_targets(); |
82 | 83 |
} |
83 | 84 |
} |
... | ... | |
86 | 87 |
//! NOTE: this is done in an extra loop to have a low delay between consequent sets: |
87 | 88 |
void Controller::publish_targets() { |
88 | 89 |
Controller::motion_generator_vector_t::iterator it; |
89 |
for (it = motion_generator_vector.begin(); it < motion_generator_vector.end(); it++) {
|
|
90 |
for (it = motion_generator_vector_.begin(); it < motion_generator_vector_.end(); it++) {
|
|
90 | 91 |
(*it)->publish_targets(); |
91 | 92 |
} |
92 | 93 |
} |
... | ... | |
102 | 103 |
|
103 | 104 |
// check if this timestamp allows a valid conversion: |
104 | 105 |
Timestamp history_begin = |
105 |
joint_interface->get_ts_position(JointInterface::ID_NECK_PAN).get_first_timestamp(); |
|
106 |
joint_interface_->get_ts_position(JointInterface::ID_NECK_PAN).get_first_timestamp();
|
|
106 | 107 |
// Timestamp history_end = |
107 | 108 |
// joint_interface->get_ts_position(JointInterface::ID_NECK_PAN).get_last_timestamp(); |
108 | 109 |
|
... | ... | |
115 | 116 |
// to do any guesswork and try to calculate a valid absolute target |
116 | 117 |
// therefore we will use the last known targets (see below) |
117 | 118 |
// in case we did not see this timestamp before, show a warning: |
118 |
if (last_known_absolute_timestamp != relative_target_timestamp) { |
|
119 |
if (last_known_absolute_timestamp_ != relative_target_timestamp) {
|
|
119 | 120 |
printf("> WARNING: restored/guessed absolute target for unknown timestamp %f " |
120 | 121 |
"[this should not happen]\n", relative_target_timestamp.to_seconds()); |
121 |
last_known_absolute_target_pan = 0.0; |
|
122 |
last_known_absolute_target_tilt = 0.0; |
|
123 |
last_known_absolute_target_roll = 0.0; |
|
122 |
last_known_absolute_target_pan_ = 0.0;
|
|
123 |
last_known_absolute_target_tilt_ = 0.0;
|
|
124 |
last_known_absolute_target_roll_ = 0.0;
|
|
124 | 125 |
} |
125 | 126 |
} else { |
126 | 127 |
// all fine, we can reconstruct the absolute target |
127 | 128 |
// fetch head / camera pose during that timestamp |
128 |
double neck_pan = joint_interface->get_ts_position( |
|
129 |
double neck_pan = joint_interface_->get_ts_position(
|
|
129 | 130 |
JointInterface::ID_NECK_PAN).get_interpolated_value(relative_target_timestamp); |
130 |
double eye_l_pan = joint_interface->get_ts_position( |
|
131 |
double eye_l_pan = joint_interface_->get_ts_position(
|
|
131 | 132 |
JointInterface::ID_EYES_LEFT_LR).get_interpolated_value(relative_target_timestamp); |
132 |
double eye_r_pan = joint_interface->get_ts_position( |
|
133 |
double eye_r_pan = joint_interface_->get_ts_position(
|
|
133 | 134 |
JointInterface::ID_EYES_RIGHT_LR).get_interpolated_value(relative_target_timestamp); |
134 |
last_known_absolute_target_pan = neck_pan + (eye_l_pan + eye_r_pan)/2.0; |
|
135 |
last_known_absolute_target_pan_ = neck_pan + (eye_l_pan + eye_r_pan)/2.0;
|
|
135 | 136 |
// |
136 |
double neck_tilt = joint_interface->get_ts_position( |
|
137 |
double neck_tilt = joint_interface_->get_ts_position(
|
|
137 | 138 |
JointInterface::ID_NECK_TILT).get_interpolated_value(relative_target_timestamp); |
138 |
double eye_tilt = joint_interface->get_ts_position( |
|
139 |
double eye_tilt = joint_interface_->get_ts_position(
|
|
139 | 140 |
JointInterface::ID_EYES_BOTH_UD).get_interpolated_value(relative_target_timestamp); |
140 |
last_known_absolute_target_tilt = neck_tilt + eye_tilt; |
|
141 |
last_known_absolute_target_tilt_ = neck_tilt + eye_tilt;
|
|
141 | 142 |
// |
142 |
last_known_absolute_target_roll = joint_interface->get_ts_position(
|
|
143 |
last_known_absolute_target_roll_ = joint_interface_->get_ts_position(
|
|
143 | 144 |
JointInterface::ID_NECK_ROLL).get_interpolated_value(relative_target_timestamp); |
144 | 145 |
|
145 | 146 |
// safe this timestamp as known: |
146 |
last_known_absolute_timestamp = relative_target_timestamp; |
|
147 |
last_known_absolute_timestamp_ = relative_target_timestamp;
|
|
147 | 148 |
} |
148 | 149 |
|
149 |
pan = last_known_absolute_target_pan; |
|
150 |
tilt = last_known_absolute_target_tilt; |
|
151 |
roll = last_known_absolute_target_roll; |
|
150 |
pan = last_known_absolute_target_pan_;
|
|
151 |
tilt = last_known_absolute_target_tilt_;
|
|
152 |
roll = last_known_absolute_target_roll_;
|
|
152 | 153 |
|
153 | 154 |
// substract offsets |
154 | 155 |
pan -= relative.pan_offset; |
... | ... | |
176 | 177 |
|
177 | 178 |
//! activate controller |
178 | 179 |
void Controller::set_activated(void) { |
179 |
activated = true; |
|
180 |
activated_ = true;
|
|
180 | 181 |
} |
181 | 182 |
|
182 | 183 |
//! update gaze target: |
183 | 184 |
//! \param GazeState with target values for the overall gaze |
184 | 185 |
void Controller::set_gaze_target(humotion::GazeState new_gaze_target) { |
185 |
if (!activated) { |
|
186 |
if (!activated_) {
|
|
186 | 187 |
// not yet initialized, ignore incoming targets |
187 | 188 |
return; |
188 | 189 |
} |
... | ... | |
200 | 201 |
} |
201 | 202 |
|
202 | 203 |
Controller::motion_generator_vector_t::iterator it; |
203 |
for (it = motion_generator_vector.begin(); it < motion_generator_vector.end(); it++) {
|
|
204 |
for (it = motion_generator_vector_.begin(); it < motion_generator_vector_.end(); it++) {
|
|
204 | 205 |
(*it)->set_gaze_target(target_gaze); |
205 | 206 |
} |
206 | 207 |
} |
... | ... | |
208 | 209 |
//! update mouth state: |
209 | 210 |
//! \param MouthState with target values for the mouth joints |
210 | 211 |
void Controller::set_mouth_target(MouthState s) { |
211 |
if (!activated) { |
|
212 |
if (!activated_) {
|
|
212 | 213 |
// not yet initialized, ignore incoming targets |
213 | 214 |
return; |
214 | 215 |
} |
215 | 216 |
|
216 | 217 |
Controller::motion_generator_vector_t::iterator it; |
217 |
for (it = motion_generator_vector.begin(); it < motion_generator_vector.end(); it++) {
|
|
218 |
for (it = motion_generator_vector_.begin(); it < motion_generator_vector_.end(); it++) {
|
|
218 | 219 |
(*it)->set_mouth_target(s); |
219 | 220 |
} |
220 | 221 |
} |
src/server/eye_motion_generator.cpp | ||
---|---|---|
75 | 75 |
//! calculate joint targets |
76 | 76 |
void EyeMotionGenerator::calculate_targets() { |
77 | 77 |
// use the target values for a faster response |
78 |
float neck_pan_now = joint_interface->get_target_position(JointInterface::ID_NECK_PAN); |
|
79 |
float neck_tilt_now = joint_interface->get_target_position(JointInterface::ID_NECK_TILT); |
|
78 |
float neck_pan_now = joint_interface_->get_target_position(JointInterface::ID_NECK_PAN);
|
|
79 |
float neck_tilt_now = joint_interface_->get_target_position(JointInterface::ID_NECK_TILT);
|
|
80 | 80 |
|
81 | 81 |
// calculate target angles for the eyes |
82 | 82 |
// right eye is dominant -> direct output |
83 |
float eye_pan_r_target = (requested_gaze_state.pan + requested_gaze_state.vergence/2.0)
|
|
83 |
float eye_pan_r_target = (requested_gaze_state_.pan + requested_gaze_state_.vergence/2.0)
|
|
84 | 84 |
- (neck_pan_now); |
85 | 85 |
|
86 | 86 |
// left eye is non dominant -> filtered output: TODO: activate low pass filtered output |
87 | 87 |
// FIXME: USE LOWPASS FILTER HERE --> output_angle[angle_names::EYE_PAN_L] |
88 | 88 |
// + 0.1 * (eye_pan_l_target - output_angle[angle_names::EYE_PAN_L]) etc; |
89 |
float eye_pan_l_target = (requested_gaze_state.pan - requested_gaze_state.vergence/2.0)
|
|
89 |
float eye_pan_l_target = (requested_gaze_state_.pan - requested_gaze_state_.vergence/2.0)
|
|
90 | 90 |
- (neck_pan_now); |
91 | 91 |
|
92 | 92 |
// tilt |
93 |
float eye_tilt_target = requested_gaze_state.tilt - (neck_tilt_now); |
|
93 |
float eye_tilt_target = requested_gaze_state_.tilt - (neck_tilt_now);
|
|
94 | 94 |
|
95 | 95 |
if (0) { |
96 | 96 |
eye_pan_r_target = 0.0; |
... | ... | |
133 | 133 |
reflexxes_calculate_profile(); |
134 | 134 |
|
135 | 135 |
// tell the joint about the new values |
136 |
joint_interface->set_target(JointInterface::ID_EYES_LEFT_LR, |
|
136 |
joint_interface_->set_target(JointInterface::ID_EYES_LEFT_LR,
|
|
137 | 137 |
reflexxes_position_output->NewPositionVector->VecData[0], |
138 | 138 |
reflexxes_position_output->NewVelocityVector->VecData[0]); |
139 |
joint_interface->set_target(JointInterface::ID_EYES_RIGHT_LR, |
|
139 |
joint_interface_->set_target(JointInterface::ID_EYES_RIGHT_LR,
|
|
140 | 140 |
reflexxes_position_output->NewPositionVector->VecData[1], |
141 | 141 |
reflexxes_position_output->NewVelocityVector->VecData[1]); |
142 |
joint_interface->set_target(JointInterface::ID_EYES_BOTH_UD, |
|
142 |
joint_interface_->set_target(JointInterface::ID_EYES_BOTH_UD,
|
|
143 | 143 |
reflexxes_position_output->NewPositionVector->VecData[2], |
144 | 144 |
reflexxes_position_output->NewVelocityVector->VecData[2]); |
145 | 145 |
} |
... | ... | |
149 | 149 |
void EyeMotionGenerator::publish_targets() { |
150 | 150 |
// publish values if there is an active gaze input within the last timerange |
151 | 151 |
if (gaze_target_input_active()) { |
152 |
joint_interface->publish_target(JointInterface::ID_EYES_LEFT_LR); |
|
153 |
joint_interface->publish_target(JointInterface::ID_EYES_RIGHT_LR); |
|
154 |
joint_interface->publish_target(JointInterface::ID_EYES_BOTH_UD); |
|
152 |
joint_interface_->publish_target(JointInterface::ID_EYES_LEFT_LR);
|
|
153 |
joint_interface_->publish_target(JointInterface::ID_EYES_RIGHT_LR);
|
|
154 |
joint_interface_->publish_target(JointInterface::ID_EYES_BOTH_UD);
|
|
155 | 155 |
} |
156 | 156 |
} |
src/server/eyebrow_motion_generator.cpp | ||
---|---|---|
46 | 46 |
//! calculate joint targets |
47 | 47 |
void EyebrowMotionGenerator::calculate_targets() { |
48 | 48 |
// printf("> humotion: calculating eyebrow targets\n"); |
49 |
float eyebrow_left_target = requested_gaze_state.eyebrow_left; |
|
50 |
float eyebrow_right_target = requested_gaze_state.eyebrow_right; |
|
49 |
float eyebrow_left_target = requested_gaze_state_.eyebrow_left;
|
|
50 |
float eyebrow_right_target = requested_gaze_state_.eyebrow_right;
|
|
51 | 51 |
|
52 | 52 |
// store targets |
53 |
joint_interface->set_target(JointInterface::ID_EYES_LEFT_BROW, eyebrow_left_target, 0.0); |
|
54 |
joint_interface->set_target(JointInterface::ID_EYES_RIGHT_BROW, eyebrow_right_target, 0.0); |
|
53 |
joint_interface_->set_target(JointInterface::ID_EYES_LEFT_BROW, eyebrow_left_target, 0.0);
|
|
54 |
joint_interface_->set_target(JointInterface::ID_EYES_RIGHT_BROW, eyebrow_right_target, 0.0);
|
|
55 | 55 |
} |
56 | 56 |
|
57 | 57 |
//! publish targets to motor boards: |
58 | 58 |
void EyebrowMotionGenerator::publish_targets() { |
59 | 59 |
// publish values if there is an active gaze input within the last timerange |
60 | 60 |
if (gaze_target_input_active()) { |
61 |
joint_interface->publish_target(JointInterface::ID_EYES_LEFT_BROW); |
|
62 |
joint_interface->publish_target(JointInterface::ID_EYES_RIGHT_BROW); |
|
61 |
joint_interface_->publish_target(JointInterface::ID_EYES_LEFT_BROW);
|
|
62 |
joint_interface_->publish_target(JointInterface::ID_EYES_RIGHT_BROW);
|
|
63 | 63 |
} |
64 | 64 |
} |
src/server/eyelid_motion_generator.cpp | ||
---|---|---|
47 | 47 |
|
48 | 48 |
//! constructor |
49 | 49 |
EyelidMotionGenerator::EyelidMotionGenerator(JointInterface *j) : EyeMotionGenerator(j) { |
50 |
saccade_blink_active = false; |
|
51 |
saccade_blink_requested = false; |
|
52 |
eyelid_closed[LEFT] = false; |
|
53 |
eyelid_closed[RIGHT] = false; |
|
50 |
saccade_blink_active_ = false;
|
|
51 |
saccade_blink_requested_ = false;
|
|
52 |
eyelid_closed_[LEFT] = false;
|
|
53 |
eyelid_closed_[RIGHT] = false;
|
|
54 | 54 |
|
55 |
eyeblink_blocked_timeout = boost::get_system_time(); |
|
55 |
eyeblink_blocked_timeout_ = boost::get_system_time();
|
|
56 | 56 |
} |
57 | 57 |
|
58 | 58 |
//! destructor |
... | ... | |
69 | 69 |
float eye_tilt_now = get_current_position(JointInterface::ID_EYES_BOTH_UD); |
70 | 70 |
|
71 | 71 |
// calculate left eyelid targets |
72 |
float eyelid_upper_left_target = eye_tilt_now + requested_gaze_state.eyelid_opening_upper; |
|
73 |
float eyelid_lower_left_target = eye_tilt_now - requested_gaze_state.eyelid_opening_lower; |
|
72 |
float eyelid_upper_left_target = eye_tilt_now + requested_gaze_state_.eyelid_opening_upper;
|
|
73 |
float eyelid_lower_left_target = eye_tilt_now - requested_gaze_state_.eyelid_opening_lower;
|
|
74 | 74 |
|
75 | 75 |
// calculate right eyelid targets |
76 |
float eyelid_upper_right_target = eye_tilt_now + requested_gaze_state.eyelid_opening_upper; |
|
77 |
float eyelid_lower_right_target = eye_tilt_now - requested_gaze_state.eyelid_opening_lower; |
|
76 |
float eyelid_upper_right_target = eye_tilt_now + requested_gaze_state_.eyelid_opening_upper;
|
|
77 |
float eyelid_lower_right_target = eye_tilt_now - requested_gaze_state_.eyelid_opening_lower;
|
|
78 | 78 |
|
79 | 79 |
// limit target angles |
80 | 80 |
eyelid_upper_left_target = limit_target(JointInterface::ID_EYES_LEFT_LID_UPPER, |
... | ... | |
87 | 87 |
eyelid_lower_right_target); |
88 | 88 |
|
89 | 89 |
// (temporarily) store the target |
90 |
joint_interface->set_target(JointInterface::ID_EYES_LEFT_LID_UPPER, |
|
90 |
joint_interface_->set_target(JointInterface::ID_EYES_LEFT_LID_UPPER,
|
|
91 | 91 |
eyelid_upper_left_target, 0.0); |
92 |
joint_interface->set_target(JointInterface::ID_EYES_LEFT_LID_LOWER, |
|
92 |
joint_interface_->set_target(JointInterface::ID_EYES_LEFT_LID_LOWER,
|
|
93 | 93 |
eyelid_lower_left_target, 0.0); |
94 |
joint_interface->set_target(JointInterface::ID_EYES_RIGHT_LID_UPPER, |
|
94 |
joint_interface_->set_target(JointInterface::ID_EYES_RIGHT_LID_UPPER,
|
|
95 | 95 |
eyelid_upper_right_target, 0.0); |
96 |
joint_interface->set_target(JointInterface::ID_EYES_RIGHT_LID_LOWER, |
|
96 |
joint_interface_->set_target(JointInterface::ID_EYES_RIGHT_LID_LOWER,
|
|
97 | 97 |
eyelid_lower_right_target, 0.0); |
98 | 98 |
|
99 | 99 |
// check for saccade |
100 | 100 |
check_for_saccade(); |
101 | 101 |
|
102 | 102 |
// is there a blink request? |
103 |
start_external_eyeblinks(requested_gaze_state.eyeblink_request_left, |
|
104 |
requested_gaze_state.eyeblink_request_right); |
|
103 |
start_external_eyeblinks(requested_gaze_state_.eyeblink_request_left,
|
|
104 |
requested_gaze_state_.eyeblink_request_right);
|
|
105 | 105 |
|
106 | 106 |
// do we have a saccade & do we want to exec an eyeblink? |
107 | 107 |
process_saccadic_eyeblinks(); |
... | ... | |
121 | 121 |
// manual eyeblinks will ALWAYs get executed as we use |
122 | 122 |
// a negative block timeout (=timeout has already passed) |
123 | 123 |
if ((duration_left != 0) || (duration_right != 0)) { |
124 |
eyeblink_blocked_timeout = boost::get_system_time() - boost::posix_time::seconds(100); |
|
124 |
eyeblink_blocked_timeout_ = boost::get_system_time() - boost::posix_time::seconds(100);
|
|
125 | 125 |
} |
126 | 126 |
|
127 | 127 |
|
... | ... | |
129 | 129 |
// nothing to do |
130 | 130 |
} else if (duration_left < 0) { |
131 | 131 |
// infinite sleep -> close |
132 |
eyelid_closed[LEFT] = true; |
|
132 |
eyelid_closed_[LEFT] = true;
|
|
133 | 133 |
} else { |
134 | 134 |
// timeout sleep |
135 | 135 |
start_eyeblink(LEFT, duration_left); |
136 |
eyelid_closed[LEFT] = false; |
|
136 |
eyelid_closed_[LEFT] = false;
|
|
137 | 137 |
} |
138 | 138 |
|
139 | 139 |
if (duration_right == 0) { |
140 | 140 |
// nothing to do |
141 | 141 |
} else if (duration_right < 0) { |
142 | 142 |
// infinite sleep -> close |
143 |
eyelid_closed[RIGHT] = true; |
|
143 |
eyelid_closed_[RIGHT] = true;
|
|
144 | 144 |
} else { |
145 | 145 |
// timeout sleep |
146 | 146 |
start_eyeblink(RIGHT, duration_right); |
147 |
eyelid_closed[RIGHT] = false; |
|
147 |
eyelid_closed_[RIGHT] = false;
|
|
148 | 148 |
} |
149 | 149 |
} |
150 | 150 |
|
151 | 151 |
//! process saccadic blink requests |
152 | 152 |
//! -> when we do a saccade, the chances to blink are much higher |
153 | 153 |
void EyelidMotionGenerator::process_saccadic_eyeblinks() { |
154 |
if (saccade_blink_requested) { |
|
154 |
if (saccade_blink_requested_) {
|
|
155 | 155 |
// every n-th's saccade requests an eyeblink |
156 | 156 |
// here: use 0.3 even though humans use bigger prob value (but that looks stupid on robot) |
157 | 157 |
if ((std::rand()%3) == 0) { |
... | ... | |
159 | 159 |
start_eyeblink(LEFT); |
160 | 160 |
start_eyeblink(RIGHT); |
161 | 161 |
} |
162 |
saccade_blink_requested = false; |
|
162 |
saccade_blink_requested_ = false;
|
|
163 | 163 |
} |
164 | 164 |
} |
165 | 165 |
|
166 | 166 |
//! process periodic blink requests |
167 | 167 |
//! -> we want to have an eyeblink every n...m seconds |
168 | 168 |
void EyelidMotionGenerator::process_periodic_eyeblinks() { |
169 |
if (eyeblink_active[LEFT] || eyeblink_active[RIGHT]) {
|
|
169 |
if (eyeblink_active_[LEFT] || eyeblink_active_[RIGHT]) {
|
|
170 | 170 |
// calculate next timeout for a new periodic eyeblink |
171 | 171 |
int milliseconds_to_next_blink = EYEBLINK_EYERY_MS_MIN |
172 | 172 |
+ (std::rand() % static_cast<int>(EYEBLINK_EYERY_MS_MAX-EYEBLINK_EYERY_MS_MIN)); |
173 |
periodic_blink_start_time = boost::get_system_time() |
|
173 |
periodic_blink_start_time_ = boost::get_system_time()
|
|
174 | 174 |
+ boost::posix_time::milliseconds(milliseconds_to_next_blink); |
175 | 175 |
} |
176 | 176 |
|
177 |
if (boost::get_system_time() > periodic_blink_start_time) { |
|
177 |
if (boost::get_system_time() > periodic_blink_start_time_) {
|
|
178 | 178 |
// printf("> periodic eyeblink:\n"); |
179 | 179 |
start_eyeblink(LEFT); |
180 | 180 |
start_eyeblink(RIGHT); |
... | ... | |
188 | 188 |
|
189 | 189 |
// take care of re-opening eye timeout |
190 | 190 |
for (int i=LEFT; i <= RIGHT; i++) { |
191 |
if (eyeblink_active[i]) { |
|
192 |
if (now >= eyeblink_timeout[i]) { |
|
193 |
eyeblink_active[i] = false; |
|
191 |
if (eyeblink_active_[i]) {
|
|
192 |
if (now >= eyeblink_timeout_[i]) {
|
|
193 |
eyeblink_active_[i] = false;
|
|
194 | 194 |
} |
195 | 195 |
} |
196 | 196 |
} |
197 | 197 |
|
198 | 198 |
// take care of blocking time |
199 |
if (eyeblink_active[LEFT] || eyeblink_active[RIGHT]) {
|
|
200 |
eyeblink_blocked_timeout = boost::get_system_time() |
|
199 |
if (eyeblink_active_[LEFT] || eyeblink_active_[RIGHT]) {
|
|
200 |
eyeblink_blocked_timeout_ = boost::get_system_time()
|
|
201 | 201 |
+ boost::posix_time::milliseconds(EYEBLINK_BLOCKING_TIME); |
202 | 202 |
} |
203 | 203 |
} |
... | ... | |
206 | 206 |
//! this will override (=close) the eyelids for all possible eyeblink requests |
207 | 207 |
void EyelidMotionGenerator::override_lids_for_eyeblink() { |
208 | 208 |
// close the requested eyelids |
209 |
if (eyeblink_active[LEFT] || eyelid_closed[LEFT]) {
|
|
209 |
if (eyeblink_active_[LEFT] || eyelid_closed_[LEFT]) {
|
|
210 | 210 |
close_eyelid(JointInterface::ID_EYES_LEFT_LID_UPPER); |
211 | 211 |
close_eyelid(JointInterface::ID_EYES_LEFT_LID_LOWER); |
212 | 212 |
} |
213 |
if (eyeblink_active[RIGHT] || eyelid_closed[RIGHT]) {
|
|
213 |
if (eyeblink_active_[RIGHT] || eyelid_closed_[RIGHT]) {
|
|
214 | 214 |
close_eyelid(JointInterface::ID_EYES_RIGHT_LID_UPPER); |
215 | 215 |
close_eyelid(JointInterface::ID_EYES_RIGHT_LID_LOWER); |
216 | 216 |
} |
... | ... | |
232 | 232 |
case(JointInterface::ID_EYES_LEFT_LID_UPPER): |
233 | 233 |
case(JointInterface::ID_EYES_LEFT_LID_LOWER): |
234 | 234 |
// use the upper value + 10 deg as close state: |
235 |
value = joint_interface->get_joint_min(JointInterface::ID_EYES_LEFT_LID_UPPER) + 10.0; |
|
235 |
value = joint_interface_->get_joint_min(JointInterface::ID_EYES_LEFT_LID_UPPER) + 10.0;
|
|
236 | 236 |
// overwrite last target_ |
237 |
joint_interface->set_target(joint_id, value, 0.0); |
|
237 |
joint_interface_->set_target(joint_id, value, 0.0);
|
|
238 | 238 |
break; |
239 | 239 |
|
240 | 240 |
case(JointInterface::ID_EYES_RIGHT_LID_UPPER): |
241 | 241 |
case(JointInterface::ID_EYES_RIGHT_LID_LOWER): |
242 | 242 |
// use the upper value + 10 deg as close state: |
243 |
value = joint_interface->get_joint_min(JointInterface::ID_EYES_RIGHT_LID_UPPER) + 10.0; |
|
243 |
value = joint_interface_->get_joint_min(JointInterface::ID_EYES_RIGHT_LID_UPPER) + 10.0;
|
|
244 | 244 |
// overwrite last target_ |
245 |
joint_interface->set_target(joint_id, value, 0.0); |
|
245 |
joint_interface_->set_target(joint_id, value, 0.0);
|
|
246 | 246 |
break; |
247 | 247 |
} |
248 | 248 |
} |
... | ... | |
252 | 252 |
//! \param int id of side (LEFT or RIGHT) |
253 | 253 |
void EyelidMotionGenerator::start_eyeblink(int side, int duration) { |
254 | 254 |
// cout << "BLOCKED UNTIL " << eyeblink_blocked_timeout << "\n"; |
255 |
if (boost::get_system_time() < eyeblink_blocked_timeout) { |
|
255 |
if (boost::get_system_time() < eyeblink_blocked_timeout_) {
|
|
256 | 256 |
// return if we are still in the block time |
257 | 257 |
return; |
258 | 258 |
} |
259 | 259 |
// request for n ms eyeblink: |
260 |
eyeblink_timeout[side] = boost::get_system_time() + boost::posix_time::milliseconds(duration); |
|
260 |
eyeblink_timeout_[side] = boost::get_system_time() + boost::posix_time::milliseconds(duration);
|
|
261 | 261 |
|
262 |
eyeblink_active[side] = true; |
|
262 |
eyeblink_active_[side] = true;
|
|
263 | 263 |
} |
264 | 264 |
|
265 | 265 |
//! check if there is an ongoing saccade: |
266 | 266 |
void EyelidMotionGenerator::check_for_saccade() { |
267 | 267 |
if (get_eye_saccade_active()) { |
268 | 268 |
// this is a saccade, check if not already in saccade: |
269 |
if (!saccade_blink_active) { |
|
269 |
if (!saccade_blink_active_) {
|
|
270 | 270 |
// this is a new saccade! restart blink timer |
271 |
saccade_blink_requested = true; |
|
272 |
saccade_blink_active = true; |
|
271 |
saccade_blink_requested_ = true;
|
|
272 |
saccade_blink_active_ = true;
|
|
273 | 273 |
} |
274 | 274 |
} else { |
275 |
saccade_blink_active = false; |
|
275 |
saccade_blink_active_ = false;
|
|
276 | 276 |
} |
277 | 277 |
} |
278 | 278 |
|
... | ... | |
281 | 281 |
void EyelidMotionGenerator::publish_targets() { |
282 | 282 |
// publish values if there is an active gaze input within the last timerange |
283 | 283 |
if (gaze_target_input_active()) { |
284 |
joint_interface->publish_target(JointInterface::ID_EYES_LEFT_LID_UPPER); |
|
285 |
joint_interface->publish_target(JointInterface::ID_EYES_LEFT_LID_LOWER); |
|
286 |
joint_interface->publish_target(JointInterface::ID_EYES_RIGHT_LID_UPPER); |
|
287 |
joint_interface->publish_target(JointInterface::ID_EYES_RIGHT_LID_LOWER); |
|
284 |
joint_interface_->publish_target(JointInterface::ID_EYES_LEFT_LID_UPPER);
|
|
285 |
joint_interface_->publish_target(JointInterface::ID_EYES_LEFT_LID_LOWER);
|
|
286 |
joint_interface_->publish_target(JointInterface::ID_EYES_RIGHT_LID_UPPER);
|
|
287 |
joint_interface_->publish_target(JointInterface::ID_EYES_RIGHT_LID_LOWER);
|
|
288 | 288 |
} |
289 | 289 |
} |
src/server/gaze_motion_generator.cpp | ||
---|---|---|
53 | 53 |
//! update gaze target: |
54 | 54 |
//! \param GazeState with target values for the overall gaze |
55 | 55 |
void GazeMotionGenerator::set_gaze_target(GazeState new_gaze_target) { |
56 |
if (requested_gaze_state.gaze_type == GazeState::GAZETYPE_RELATIVE) { |
|
56 |
if (requested_gaze_state_.gaze_type == GazeState::GAZETYPE_RELATIVE) {
|
|
57 | 57 |
printf("> ERROR: gaze targets should be converted to absolute before calling this\n"); |
58 | 58 |
exit(EXIT_FAILURE); |
59 | 59 |
} |
60 | 60 |
|
61 | 61 |
// check magnitude of gaze change to detect eye-neck saccades |
62 |
float dist = fabs(requested_gaze_state.distance_pt_abs(new_gaze_target)); |
|
62 |
float dist = fabs(requested_gaze_state_.distance_pt_abs(new_gaze_target));
|
|
63 | 63 |
|
64 | 64 |
// check requested speed |
65 |
float speed = fabs(requested_gaze_state.distance_pt_abs(new_gaze_target)) |
|
66 |
/ (new_gaze_target.timestamp.to_seconds()-requested_gaze_state.timestamp.to_seconds()); |
|
65 |
float speed = fabs(requested_gaze_state_.distance_pt_abs(new_gaze_target))
|
|
66 |
/ (new_gaze_target.timestamp.to_seconds()-requested_gaze_state_.timestamp.to_seconds());
|
|
67 | 67 |
|
68 | 68 |
// check magnitude and speed of gaze change to detect eye-neck saccades |
69 | 69 |
if (dist > NECK_SACCADE_THRESHOLD) { |
... | ... | |
78 | 78 |
// check for eye getting close to ocolomotor range |
79 | 79 |
// actually it makes more sense to trigger the neck saccade based on |
80 | 80 |
// the target getting out of the OMR |
81 |
float eye_target_l = joint_interface->get_target_position(JointInterface::ID_EYES_LEFT_LR); |
|
82 |
float eye_target_r = joint_interface->get_target_position(JointInterface::ID_EYES_RIGHT_LR); |
|
83 |
float eye_target_ud = joint_interface->get_target_position(JointInterface::ID_EYES_BOTH_UD); |
|
81 |
float eye_target_l = joint_interface_->get_target_position(JointInterface::ID_EYES_LEFT_LR);
|
|
82 |
float eye_target_r = joint_interface_->get_target_position(JointInterface::ID_EYES_RIGHT_LR);
|
|
83 |
float eye_target_ud = joint_interface_->get_target_position(JointInterface::ID_EYES_BOTH_UD);
|
|
84 | 84 |
|
85 | 85 |
// min/max bounds |
86 | 86 |
float left_min = OMR_LIMIT_TRIGGERS_NECK_SACCADE * |
87 |
joint_interface->get_joint_min(JointInterface::ID_EYES_LEFT_LR); |
|
87 |
joint_interface_->get_joint_min(JointInterface::ID_EYES_LEFT_LR);
|
|
88 | 88 |
float left_max = OMR_LIMIT_TRIGGERS_NECK_SACCADE * |
89 |
joint_interface->get_joint_max(JointInterface::ID_EYES_LEFT_LR); |
|
89 |
joint_interface_->get_joint_max(JointInterface::ID_EYES_LEFT_LR);
|
|
90 | 90 |
float right_min = OMR_LIMIT_TRIGGERS_NECK_SACCADE * |
91 |
joint_interface->get_joint_min(JointInterface::ID_EYES_RIGHT_LR); |
|
91 |
joint_interface_->get_joint_min(JointInterface::ID_EYES_RIGHT_LR);
|
|
92 | 92 |
float right_max = OMR_LIMIT_TRIGGERS_NECK_SACCADE * |
93 |
joint_interface->get_joint_max(JointInterface::ID_EYES_RIGHT_LR); |
|
93 |
joint_interface_->get_joint_max(JointInterface::ID_EYES_RIGHT_LR);
|
|
94 | 94 |
float ud_min = OMR_LIMIT_TRIGGERS_NECK_SACCADE * |
95 |
joint_interface->get_joint_min(JointInterface::ID_EYES_BOTH_UD); |
|
95 |
joint_interface_->get_joint_min(JointInterface::ID_EYES_BOTH_UD);
|
|
96 | 96 |
float ud_max = OMR_LIMIT_TRIGGERS_NECK_SACCADE * |
97 |
joint_interface->get_joint_max(JointInterface::ID_EYES_BOTH_UD); |
|
97 |
joint_interface_->get_joint_max(JointInterface::ID_EYES_BOTH_UD);
|
|
98 | 98 |
|
99 | 99 |
if ( |
100 | 100 |
(eye_target_l < left_min) || (eye_target_l > left_max) || |
... | ... | |
114 | 114 |
bool GazeMotionGenerator::get_eye_saccade_active() { |
115 | 115 |
bool saccade_active; |
116 | 116 |
|
117 |
float speed_left = joint_interface->get_ts_speed( |
|
117 |
float speed_left = joint_interface_->get_ts_speed(
|
|
118 | 118 |
JointInterface::ID_EYES_LEFT_LR).get_newest_value(); |
119 |
float speed_right = joint_interface->get_ts_speed( |
|
119 |
float speed_right = joint_interface_->get_ts_speed(
|
|
120 | 120 |
JointInterface::ID_EYES_RIGHT_LR).get_newest_value(); |
121 |
float speed_tilt = joint_interface->get_ts_speed( |
|
121 |
float speed_tilt = joint_interface_->get_ts_speed(
|
|
122 | 122 |
JointInterface::ID_EYES_BOTH_UD).get_newest_value(); |
123 | 123 |
|
124 | 124 |
float speed_total_l = sqrt(speed_left*speed_left + speed_tilt*speed_tilt); |
... | ... | |
139 | 139 |
//! get overall gaze |
140 | 140 |
humotion::GazeState GazeMotionGenerator::get_current_gaze() { |
141 | 141 |
// shortcut, makes the following easier to read |
142 |
JointInterface *j = joint_interface; |
|
142 |
JointInterface *j = joint_interface_;
|
|
143 | 143 |
|
144 |
GazeState gaze = requested_gaze_state; |
|
144 |
GazeState gaze = requested_gaze_state_;
|
|
145 | 145 |
|
146 | 146 |
gaze.pan = j->get_ts_position(JointInterface::ID_NECK_PAN).get_newest_value() + |
147 | 147 |
(j->get_ts_position(JointInterface::ID_EYES_LEFT_LR).get_newest_value() |
src/server/joint_interface.cpp | ||
---|---|---|
34 | 34 |
//! constructor |
35 | 35 |
JointInterface::JointInterface() { |
36 | 36 |
framerate = 50.0; |
37 |
mouth_enabled = false; |
|
38 |
gaze_enabled = false; |
|
37 |
mouth_enabled_ = false;
|
|
38 |
gaze_enabled_ = false;
|
|
39 | 39 |
} |
40 | 40 |
|
41 | 41 |
//! destructor |
... | ... | |
75 | 75 |
// lock the tsd_list for this access. by doing this we assure |
76 | 76 |
// that no other thread accessing this element can diturb the |
77 | 77 |
// following atomic instructions: |
78 |
mutex::scoped_lock sl(joint_ts_position_map_access_mutex); |
|
78 |
mutex::scoped_lock sl(joint_ts_position_map_access_mutex_);
|
|
79 | 79 |
|
80 | 80 |
// printf("> humotion: incoming joint position for joint id 0x%02X " |
81 | 81 |
// "= %4.2f (ts=%.2f)\n",joint_id,position,timestamp.to_seconds()); |
82 |
joint_ts_position_map[joint_id].insert(timestamp, position); |
|
82 |
joint_ts_position_map_[joint_id].insert(timestamp, position);
|
|
83 | 83 |
|
84 |
incoming_position_count++; |
|
84 |
incoming_position_count_++;
|
|
85 | 85 |
} |
86 | 86 |
|
87 | 87 |
//! return incoming position data count & clear this counter |
88 | 88 |
//! this can be used as a keep alive status check |
89 | 89 |
//! \return number of incoming joint positions since the last call |
90 | 90 |
unsigned int JointInterface::get_and_clear_incoming_position_count() { |
91 |
unsigned int i = incoming_position_count; |
|
92 |
incoming_position_count = 0; |
|
91 |
unsigned int i = incoming_position_count_;
|
|
92 |
incoming_position_count_ = 0;
|
|
93 | 93 |
return i; |
94 | 94 |
} |
95 | 95 |
|
... | ... | |
101 | 101 |
// lock the tsd_list for this access. by doing this we assure |
102 | 102 |
// that no other thread accessing this element can disturb the |
103 | 103 |
// following atomic instructions: |
104 |
mutex::scoped_lock scoped_lock(joint_ts_speed_map_access_mutex); |
|
104 |
mutex::scoped_lock scoped_lock(joint_ts_speed_map_access_mutex_);
|
|
105 | 105 |
|
106 | 106 |
// printf("> humotion: incoming joint velocity for joint id 0x%02X = %4.2f " |
107 | 107 |
// "(ts=%.2f)\n",joint_id,velocity,timestamp.to_seconds()); |
108 |
joint_ts_speed_map[joint_id].insert(timestamp, velocity); |
|
108 |
joint_ts_speed_map_[joint_id].insert(timestamp, velocity);
|
|
109 | 109 |
} |
110 | 110 |
|
111 | 111 |
//! return the timestamped float for the given joints position |
... | ... | |
113 | 113 |
// lock the tsd_list for this access. by doing this we assure |
114 | 114 |
// that no other thread accessing this element can disturb the |
115 | 115 |
// following atomic instructions |
116 |
mutex::scoped_lock sl(joint_ts_position_map_access_mutex); |
|
116 |
mutex::scoped_lock sl(joint_ts_position_map_access_mutex_);
|
|
117 | 117 |
|
118 | 118 |
// search map |
119 |
joint_tsl_map_t::iterator it = joint_ts_position_map.find(joint_id); |
|
119 |
joint_tsl_map_t::iterator it = joint_ts_position_map_.find(joint_id);
|
|
120 | 120 |
|
121 |
if (it == joint_ts_position_map.end()) { |
|
121 |
if (it == joint_ts_position_map_.end()) {
|
|
122 | 122 |
printf("> humotion: no ts_position for joint id 0x%02X found\n", joint_id); |
123 | 123 |
return TimestampedList(); |
124 | 124 |
} |
... | ... | |
132 | 132 |
// lock the tsd_list for this access. by doing this we assure |
133 | 133 |
// that no other thread accessing this element can diturb the |
134 | 134 |
// following atomic instructions |
135 |
mutex::scoped_lock sl(joint_ts_speed_map_access_mutex); |
|
135 |
mutex::scoped_lock sl(joint_ts_speed_map_access_mutex_);
|
|
136 | 136 |
|
137 | 137 |
// search map |
138 |
joint_tsl_map_t::iterator it = joint_ts_speed_map.find(joint_id); |
|
138 |
joint_tsl_map_t::iterator it = joint_ts_speed_map_.find(joint_id);
|
|
139 | 139 |
|
140 |
if (it == joint_ts_speed_map.end()) { |
|
140 |
if (it == joint_ts_speed_map_.end()) {
|
|
141 | 141 |
printf("> humotion: no ts_speed for joint id 0x%02X found\n", joint_id); |
142 | 142 |
return humotion::TimestampedList(); |
143 | 143 |
} |
... | ... | |
154 | 154 |
//! enable all mouth joints |
155 | 155 |
void JointInterface::enable_mouth_joints() { |
156 | 156 |
// already enabled? skip this |
157 |
if (mouth_enabled) { |
|
157 |
if (mouth_enabled_) {
|
|
158 | 158 |
return; |
159 | 159 |
} |
160 | 160 |
|
... | ... | |
165 | 165 |
enable_joint(ID_LIP_CENTER_LOWER); |
166 | 166 |
enable_joint(ID_LIP_RIGHT_UPPER); |
167 | 167 |
enable_joint(ID_LIP_RIGHT_LOWER); |
168 |
mouth_enabled = true; |
|
168 |
mouth_enabled_ = true;
|
|
169 | 169 |
} |
170 | 170 |
|
171 | 171 |
|
172 | 172 |
//! disable all mouth joints |
173 | 173 |
void JointInterface::disable_mouth_joints() { |
174 | 174 |
// already disabled? skip this |
175 |
if (!mouth_enabled) { |
|
175 |
if (!mouth_enabled_) {
|
|
176 | 176 |
return; |
177 | 177 |
} |
178 | 178 |
|
... | ... | |
183 | 183 |
disable_joint(ID_LIP_CENTER_LOWER); |
184 | 184 |
disable_joint(ID_LIP_RIGHT_UPPER); |
185 | 185 |
disable_joint(ID_LIP_RIGHT_LOWER); |
186 |
mouth_enabled = false; |
|
186 |
mouth_enabled_ = false;
|
|
187 | 187 |
} |
188 | 188 |
|
189 | 189 |
//! enable all gaze joints |
190 | 190 |
void JointInterface::enable_gaze_joints() { |
191 | 191 |
// already enabled? skip this |
192 |
if (gaze_enabled) { |
|
192 |
if (gaze_enabled_) {
|
|
193 | 193 |
return; |
194 | 194 |
} |
195 | 195 |
|
... | ... | |
210 | 210 |
enable_joint(ID_NECK_TILT); |
211 | 211 |
enable_joint(ID_NECK_ROLL); |
212 | 212 |
|
213 |
gaze_enabled = true; |
|
213 |
gaze_enabled_ = true;
|
|
214 | 214 |
} |
215 | 215 |
|
216 | 216 |
//! disable all gaze joints |
217 | 217 |
void JointInterface::disable_gaze_joints() { |
218 | 218 |
// already disabled? skip this |
219 |
if (!gaze_enabled) { |
|
219 |
if (!gaze_enabled_) {
|
|
220 | 220 |
return; |
221 | 221 |
} |
222 | 222 |
|
... | ... | |
237 | 237 |
disable_joint(ID_NECK_TILT); |
238 | 238 |
disable_joint(ID_NECK_ROLL); |
239 | 239 |
|
240 |
gaze_enabled = false; |
|
240 |
gaze_enabled_ = false;
|
|
241 | 241 |
} |
242 | 242 |
|
243 | 243 |
//! fetch maximum allowed joint position |
... | ... | |
257 | 257 |
//! check if joint position map is empty |
258 | 258 |
//! \return true if empty |
259 | 259 |
bool JointInterface::get_joint_position_map_empty() { |
260 |
return (joint_ts_position_map.empty()); |
|
260 |
return (joint_ts_position_map_.empty());
|
|
261 | 261 |
} |
262 | 262 |
|
263 | 263 |
//! call the virtual store function with given position and velocities |
src/server/middleware.cpp | ||
---|---|---|
34 | 34 |
//! constructor |
35 | 35 |
//! open a new Middleware instance. |
36 | 36 |
Middleware::Middleware(std::string scope, Controller *c) { |
37 |
controller = c; |
|
38 |
base_scope = scope; |
|
37 |
controller_ = c;
|
|
38 |
base_scope_ = scope;
|
|
39 | 39 |
} |
40 | 40 |
|
41 | 41 |
//! destructor |
src/server/middleware_ros.cpp | ||
---|---|---|
42 | 42 |
// start ros core? |
43 | 43 |
if (ros::isInitialized()) { |
44 | 44 |
// oh another process is doing ros comm, fine, we do not need to call it |
45 |
tick_necessary = false; |
|
45 |
tick_necessary_ = false;
|
|
46 | 46 |
} else { |
47 | 47 |
// we have to take care of ros |
48 | 48 |
printf("> no active ros middleware, calling ros::init() " |
... | ... | |
52 | 52 |
printf("> registering on ROS as node %s\n", node_name.c_str()); |
53 | 53 |
ros::M_string no_remapping; |
54 | 54 |
ros::init(no_remapping, node_name); |
55 |
tick_necessary = true; |
|
55 |
tick_necessary_ = true;
|
|
56 | 56 |
} |
57 | 57 |
|
58 | 58 |
// create node handle |
59 | 59 |
ros::NodeHandle n; |
60 |
ros::NodeHandle pnh("~"); |
|
60 | 61 |
|
61 | 62 |
// set up subscribers |
62 |
mouth_target_subscriber = n.subscribe(scope + "/humotion/mouth/target", 150, |
|
63 |
mouth_target_subscriber_ = n.subscribe(scope + "/humotion/mouth/target", 150,
|
|
63 | 64 |
&MiddlewareROS::incoming_mouth_target , |
64 | 65 |
this, ros::TransportHints().unreliable()); |
65 |
gaze_target_subscriber = n.subscribe(scope + "/humotion/gaze/target", 150, |
|
66 |
gaze_target_subscriber_ = n.subscribe(scope + "/humotion/gaze/target", 150,
|
|
66 | 67 |
&MiddlewareROS::incoming_gaze_target, |
67 | 68 |
this, ros::TransportHints().unreliable()); |
69 |
|
|
70 |
// set up dynamic reconfiguration service |
|
71 |
attach_to_reconfiguration_server(pnh); |
|
72 |
} |
|
73 |
|
|
74 |
//! callback for incoming dynamic reconfigure requests: |
|
75 |
void MiddlewareROS::dynamic_reconfigure_callback(const humotion::humotionConfig &config, |
|
76 |
uint32_t level) { |
|
77 |
/*// ignore incoming requests as long cam is not set up properly |
|
78 |
if (!hasValidHandle()) { |
|
79 |
return; |
|
80 |
} |
|
81 |
|
|
82 |
// use some tricks to iterate through all config entries: |
|
83 |
std::vector<ximea_camera::xiAPIConfig::AbstractParamDescriptionConstPtr>::const_iterator _i; |
|
84 |
for (_i = config.__getParamDescriptions__().begin(); |
|
85 |
_i != config.__getParamDescriptions__().end(); ++_i) { |
|
86 |
boost::any val; |
|
87 |
boost::shared_ptr<const ximea_camera::xiAPIConfig::AbstractParamDescription> |
|
88 |
description = *_i; |
|
89 |
|
|
90 |
// fetch actual value: |
|
91 |
description->getValue(config, val); |
|
92 |
|
|
93 |
// std::cout << description->name << " " << description->type << "\n"; |
|
94 |
|
|
95 |
// copy data to ximea api: |
|
96 |
if (description->type == "double") { |
|
97 |
dynamicReconfigureFloat(description->name.c_str(), |
|
98 |
static_cast<float>(boost::any_cast<double>(val))); |
|
99 |
} else if (description->type == "bool") { |
|
100 |
dynamicReconfigureInt(description->name.c_str(), (boost::any_cast<bool>(val))?1:0); |
|
101 |
} else if (description->type == "int") { |
|
102 |
dynamicReconfigureInt(description->name.c_str(), boost::any_cast<int>(val)); |
|
103 |
} else { |
|
104 |
std::cerr << "ERROR: unsupported config type " << description->type << "\n"; |
|
105 |
} |
|
106 |
}*/ |
|
107 |
} |
|
108 |
|
|
109 |
//! attach to dynamic reconfigure server |
|
110 |
void MiddlewareROS::attach_to_reconfiguration_server(ros::NodeHandle priv_nodehandle) { |
|
111 |
ROS_DEBUG("connecting to dynamic reconfiguration server"); |
|
112 |
ros::NodeHandle reconf_node(priv_nodehandle, "configuration"); |
|
113 |
|
|
114 |
reconf_server_ = new dynamic_reconfigure::Server<humotion::humotionConfig>(reconf_node); |
|
115 |
reconf_server_->setCallback(boost::bind( |
|
116 |
&MiddlewareROS::dynamic_reconfigure_callback, this, _1, _2)); |
|
68 | 117 |
} |
69 | 118 |
|
70 | 119 |
//! destructor |
... | ... | |
79 | 128 |
|
80 | 129 |
//! do a single tick |
81 | 130 |
void MiddlewareROS::tick() { |
82 |
if (tick_necessary) { |
|
131 |
if (tick_necessary_) {
|
|
83 | 132 |
ros::spinOnce(); |
84 | 133 |
} |
85 | 134 |
} |
... | ... | |
97 | 146 |
mouth_state.opening_center = msg->opening.center; |
98 | 147 |
mouth_state.opening_right = msg->opening.right; |
99 | 148 |
|
100 |
controller->set_mouth_target(mouth_state); |
|
149 |
controller_->set_mouth_target(mouth_state);
|
|
101 | 150 |
} |
102 | 151 |
|
103 | 152 |
|
... | ... | |
134 | 183 |
|
135 | 184 |
gaze_state.timestamp.set(msg->gaze_timestamp.sec, msg->gaze_timestamp.nsec); |
136 | 185 |
|
137 |
controller->set_gaze_target(gaze_state); |
|
186 |
controller_->set_gaze_target(gaze_state);
|
|
138 | 187 |
} |
139 | 188 |
|
Also available in: Unified diff