Revision 2aa96942

View differences:

cfg/humotion.cfg
38 38

  
39 39
gen = ParameterGenerator()
40 40

  
41
debug_group = gen.add_group("debug")
42
add_entry_bool(debug_group, "publish_internals", "publish debugging data on different topics")
43

  
41 44
general_group = gen.add_group("thresholds")
42 45
add_entry(general_group, "threshold_velocity_eye_saccade", "velocity threshold for eye saccade detection (in deg/s)", 1.0, 30.0)
43 46
add_entry(general_group, "threshold_angle_neck_saccade", "magnitude of gaze change that triggers neck saccade (in deg)", 1.0, 30.0)
include/humotion/server/config.h
29 29
#ifndef INCLUDE_HUMOTION_SERVER_CONFIG_H_
30 30
#define INCLUDE_HUMOTION_SERVER_CONFIG_H_
31 31

  
32
#include <map>
33
#include <string>
34

  
32 35
namespace humotion {
33 36
namespace server {
34 37

  
38
typedef std::map<std::string, float> debug_data_t;
39

  
35 40
class Config {
36 41
 public:
37 42
    Config();
......
42 47
    // NOTE: See config.cpp for explanations and default values
43 48
    // ********************************************************
44 49

  
50
    // publish debug information
51
    bool publish_internals;
52

  
45 53
    // saccade detection thresholds
46 54
    float threshold_velocity_eye_saccade;
47 55
    float threshold_angle_neck_saccade;
include/humotion/server/controller.h
48 48
    void init_motion_generators();
49 49
    void calculate_targets();
50 50
    void publish_targets();
51
    debug_data_t get_debug_data();
51 52

  
52 53
    void set_gaze_target(GazeState s);
53 54
    void set_mouth_target(MouthState s);
include/humotion/server/middleware.h
30 30

  
31 31
#include <cstdint>
32 32
#include <cstdio>
33
#include <map>
33 34
#include <string>
35
#include <utility>
34 36

  
35 37
#include "humotion/gaze_state.h"
36 38
#include "humotion/mouth_state.h"
......
47 49
    virtual bool ok() = 0;
48 50
    virtual void tick() = 0;
49 51

  
52
    virtual void publish_debug_dataset(debug_data_t) = 0;
53

  
50 54
 protected:
51 55
    Controller *controller_;
52 56
    std::string base_scope_;
include/humotion/server/middleware_ros.h
32 32
#include <dynamic_reconfigure/server.h>
33 33
#include <ros/ros.h>
34 34

  
35
#include <map>
35 36
#include <string>
37
#include <utility>
36 38

  
37 39
#include "humotion/gaze.h"
38 40
#include "humotion/humotionConfig.h"
......
50 52
    void tick();
51 53

  
52 54
    void dynamic_reconfigure_callback(const humotion::humotionConfig &config, uint32_t level);
55
    void publish_debug_dataset(debug_data_t);
53 56

  
54 57
 private:
58
    void publish_debug_data(std::string name, float value);
59

  
55 60
    void incoming_mouth_target(const humotion::mouth::ConstPtr& msg);
56 61
    void incoming_gaze_target(const humotion::gaze::ConstPtr& msg);
57 62
    void attach_to_reconfiguration_server(ros::NodeHandle priv_nodehandle);
58

  
63
    void debug_initialize();
59 64

  
60 65
    bool tick_necessary_;
66
    bool debug_initialized_;
61 67

  
62 68
    ros::Subscriber mouth_target_subscriber_;
63 69
    ros::Subscriber gaze_target_subscriber_;
70

  
71
    ros::NodeHandle nh_;
72

  
73
    typedef std::map<std::string, ros::Publisher> debug_topic_map_t;
74
    debug_topic_map_t debug_topic_map;
75

  
64 76
    dynamic_reconfigure::Server<humotion::humotionConfig> *reconf_server_;
65 77
};
66 78

  
include/humotion/server/motion_generator.h
30 30

  
31 31
#include <boost/date_time/posix_time/posix_time.hpp>
32 32

  
33
#include <map>
33 34
#include <string>
34 35

  
35 36
#include "humotion/server/config.h"
......
49 50
    virtual void set_gaze_target(GazeState s);
50 51
    virtual void set_mouth_target(MouthState s);
51 52

  
53
    debug_data_t get_debug_data();
54

  
55

  
52 56
 protected:
53 57
    Config *config;
58
    debug_data_t debug_data;
59
    void store_debug_data(std::string name, float value);
54 60

  
55 61
    float get_current_position(int joint_id);
56 62
    float get_current_speed(int joint_id);
57 63
    humotion::Timestamp get_timestamped_state(int joint_id, float *position, float *velocity);
64

  
58 65
    float limit_target(int joint_id, float val);
59 66
    bool mouth_target_input_active();
60 67
    bool gaze_target_input_active();
src/server/config.cpp
38 38
}
39 39

  
40 40
void Config::init_defaults() {
41
    // publish internal debug data as topics?
42
    publish_internals = false;
43

  
41 44
    // saccade detection thresholds:
42 45
    // 1) velocity threshold, values above this value trigger an eye saccade
43 46
    //    value is given in deg/s
src/server/controller.cpp
39 39

  
40 40
using humotion::server::Controller;
41 41
using humotion::server::Config;
42
using humotion::server::debug_data_t;
42 43

  
43 44
//! constructor
44 45
Controller::Controller(JointInterface *j) {
......
82 83
void Controller::calculate_targets() {
83 84
    Controller::motion_generator_vector_t::iterator it;
84 85
    for (it = motion_generator_vector_.begin(); it < motion_generator_vector_.end(); it++) {
85
        (*it)->calculate_targets();
86
        MotionGenerator *mg = *it;
87
        // calculate targets
88
        mg->calculate_targets();
86 89
    }
87 90
}
88 91

  
92
debug_data_t Controller::get_debug_data() {
93
    debug_data_t debug_data;
94

  
95
    Controller::motion_generator_vector_t::iterator it;
96
    for (it = motion_generator_vector_.begin(); it < motion_generator_vector_.end(); it++) {
97
        MotionGenerator *mg = *it;
98
        // fetch and append debug data
99
        debug_data_t dataset = mg->get_debug_data();
100
        debug_data.insert(dataset.begin(), dataset.end());
101
    }
102

  
103
    return debug_data;
104
}
105

  
89 106
//! publish all target angles to the devices:
90 107
//! NOTE: this is done in an extra loop to have a low delay between consequent sets:
91 108
void Controller::publish_targets() {
src/server/eye_motion_generator.cpp
155 155
    joint_interface_->set_target(JointInterface::ID_EYES_BOTH_UD,
156 156
                                reflexxes_position_output->NewPositionVector->VecData[2],
157 157
                                reflexxes_position_output->NewVelocityVector->VecData[2]);
158

  
159
    // store debug data:
160
    store_debug_data("eye/neck_pan_now", neck_pan_now);
161
    store_debug_data("eye/neck_tilt_now", neck_tilt_now);
162
    store_debug_data("eye/eye_pan_r_target", eye_pan_r_target);
163
    store_debug_data("eye/eye_pan_l_target", eye_pan_l_target);
164
    store_debug_data("eye/eye_tilt_target", eye_tilt_target);
165

  
166
    store_debug_data("eye/gaze_target_pan", requested_gaze_state_.pan);
167
    store_debug_data("eye/gaze_target_tilt", requested_gaze_state_.tilt);
168

  
169
    store_debug_data("eye/eye_pan_r_now", eye_pan_r_now);
170
    store_debug_data("eye/eye_pan_l_now", eye_pan_l_now);
171
    store_debug_data("eye/eye_tilt_now", eye_tilt_now);
172

  
173
    store_debug_data("eye/output_l_lr", reflexxes_position_output->NewPositionVector->VecData[0]);
174
    store_debug_data("eye/output_r_lr", reflexxes_position_output->NewPositionVector->VecData[1]);
175
    store_debug_data("eye/output_ud",   reflexxes_position_output->NewPositionVector->VecData[2]);
158 176
}
159 177

  
160 178

  
src/server/middleware_ros.cpp
27 27

  
28 28
#include <boost/algorithm/string/classification.hpp>
29 29

  
30
#include <std_msgs/Float32.h>
30 31
#include <string>
31 32

  
32 33
#include "humotion/server/middleware_ros.h"
......
35 36

  
36 37
//! constructor
37 38
MiddlewareROS::MiddlewareROS(std::string scope, Controller *c)
38
    : Middleware(scope, c) {
39
    : Middleware(scope, c), nh_(scope + "/humotion") {
39 40
    ROS_DEBUG_STREAM_NAMED("MiddlewareROS", "will use ros middleware");
41
    debug_initialized_ = false;
40 42

  
41 43
    // start ros core?
42 44
    if (ros::isInitialized()) {
......
58 60
    }
59 61

  
60 62
    // create node handle
61
    ros::NodeHandle n;
62 63
    ros::NodeHandle pnh("~");
63 64

  
64 65
    // set up subscribers
65
    mouth_target_subscriber_ = n.subscribe(scope + "/humotion/mouth/target", 150,
66
    mouth_target_subscriber_ = nh_.subscribe("mouth/target", 150,
66 67
                                          &MiddlewareROS::incoming_mouth_target ,
67 68
                                          this, ros::TransportHints().unreliable());
68
    gaze_target_subscriber_  = n.subscribe(scope + "/humotion/gaze/target",  150,
69
    gaze_target_subscriber_  = nh_.subscribe("gaze/target",  150,
69 70
                                          &MiddlewareROS::incoming_gaze_target,
70 71
                                          this, ros::TransportHints().unreliable());
71 72

  
......
79 80
    // fetch config
80 81
    humotion::server::Config *config = controller_->get_config();
81 82

  
83
    // debug
84
    config->publish_internals = dyn_config.publish_internals;
85

  
82 86
    // saccade detection thresholds
83 87
    config->threshold_velocity_eye_saccade = dyn_config.threshold_velocity_eye_saccade;
84 88
    config->threshold_angle_neck_saccade = dyn_config.threshold_angle_neck_saccade;
85 89
    config->threshold_angle_omr_limit = dyn_config.threshold_angle_omr_limit;
86 90

  
87
    config->use_neck_target_instead_of_position_eye = dyn_config.use_neck_target_instead_of_position_eye;
91
    config->use_neck_target_instead_of_position_eye =
92
            dyn_config.use_neck_target_instead_of_position_eye;
88 93

  
89 94
    // neck motion generation configuration
90 95
    config->scale_velocity_neck = dyn_config.scale_velocity_neck;
......
141 146
    }
142 147
}
143 148

  
149
//! init debug dataset publishers
150
void MiddlewareROS::debug_initialize() {
151
    if (debug_initialized_) {
152
        return;
153
    }
154

  
155
    debug_initialized_ = true;
156
}
157

  
158
//! publish a debug dataset
159
void MiddlewareROS::publish_debug_dataset(debug_data_t debug_data) {
160
    if (!controller_->get_config()->publish_internals) {
161
        // no debugging data enabled, return
162
        return;
163
    }
164

  
165
    debug_initialize();
166

  
167
    // iterate over all debug variables and publish them
168
    debug_data_t::iterator it;
169
    for (it = debug_data.begin(); it != debug_data.end(); it++) {
170
        publish_debug_data(it->first, it->second);
171
    }
172
}
173

  
174
void MiddlewareROS::publish_debug_data(std::string name, float value) {
175
    debug_topic_map_t::iterator it = debug_topic_map.find(name);
176
    if (it == debug_topic_map.end()) {
177
        // we have no publisher for this dataset, create one:
178
        ROS_DEBUG_STREAM("creating debug output stream " << name);
179
        ros::Publisher pub =  nh_.advertise<std_msgs::Float32>("debug_data/" + name, 1000);
180

  
181
        std::pair<debug_topic_map_t::iterator, bool> ret;
182
        ret = debug_topic_map.insert(std::pair<std::string, ros::Publisher>(name, pub));
183
        it = ret.first;
184
    }
185

  
186
    // in any case, it is now the publisher we want  so publish data now
187
    std_msgs::Float32 msg;
188
    msg.data = value;
189

  
190
    // std::cout  << "DEBUG HUMOTION " << name << " " << value << std::endl;
191

  
192
    // send it
193
    it->second.publish(msg);
194
}
195

  
144 196
//! callback to handle incoming mouth  target
145 197
void MiddlewareROS::incoming_mouth_target(const humotion::mouth::ConstPtr& msg) {
146 198
    // printf("> incoming mouth_target\n");
src/server/motion_generator.cpp
26 26
*/
27 27

  
28 28
#include <boost/date_time/posix_time/posix_time.hpp>
29

  
30
#include <utility>
31

  
29 32
#include "humotion/server/motion_generator.h"
30 33

  
31 34
using humotion::server::MotionGenerator;
32 35
using humotion::server::Config;
36
using humotion::server::debug_data_t;
33 37

  
34 38
//! constructor
35 39
MotionGenerator::MotionGenerator(JointInterface *j, Config *cfg) {
......
44 48
MotionGenerator::~MotionGenerator() {
45 49
}
46 50

  
51
//! return all accumulated debug data
52
debug_data_t MotionGenerator::get_debug_data() {
53
    return debug_data;
54
}
55

  
56
//! store debug data
57
void MotionGenerator::store_debug_data(std::string name, float value) {
58
    debug_data[name] = value;
59
}
60

  
47 61
//! fetch the latest position and velocity and return the timestamp of that dataset
48 62
//! \param joint id
49 63
//! \param pointer to position variable
50
//! \param pointer to veolocity variable
64
//! \param pointer to velocity variable
51 65
//! \return Timestamp of this dataset
52 66
humotion::Timestamp MotionGenerator::get_timestamped_state(int joint_id,
53 67
                                                           float *position, float *velocity) {
54
    humotion::Timestamp stamp = joint_interface_->get_ts_position(joint_id).get_last_timestamp();
68
    humotion::Timestamp stamp_p = joint_interface_->get_ts_position(joint_id).get_last_timestamp();
69
    humotion::Timestamp stamp_v = joint_interface_->get_ts_speed(joint_id).get_last_timestamp();
70
    humotion::Timestamp stamp;
71

  
72
    if (stamp_v < stamp_p) {
73
        // right now there is no velocity with that timestamp yet, therefore use the velocity ts
74
        // for both:
75
        stamp = stamp_v;
76
    } else {
77
        // both are available at the position ts, use that one
78
        stamp = stamp_p;
79
    }
80

  
81
    // fetch data
55 82
    *position = joint_interface_->get_ts_position(joint_id).get_interpolated_value(stamp);
56 83
    *velocity = joint_interface_->get_ts_speed(joint_id).get_interpolated_value(stamp);
57 84
    return stamp;
src/server/neck_motion_generator.cpp
181 181
            get_current_gaze().pan,
182 182
            (get_current_position(JointInterface::ID_EYES_LEFT_LR) + get_current_position(JointInterface::ID_EYES_RIGHT_LR))/2.0,
183 183
            get_current_position(JointInterface::ID_NECK_PAN));*/
184

  
185
    // store debug data:
186
    store_debug_data("neck/neck_pan_now", neck_pan_now);
187
    store_debug_data("neck/neck_tilt_now", neck_tilt_now);
188
    store_debug_data("neck/neck_pan_target", neck_pan_target);
189
    store_debug_data("neck/neck_tilt_target", neck_tilt_target);
190

  
191
    store_debug_data("neck/gaze_target_pan", requested_gaze_state_.pan);
192
    store_debug_data("neck/gaze_target_tilt", requested_gaze_state_.tilt);
193

  
194
    store_debug_data("neck/output_pan", reflexxes_position_output->NewPositionVector->VecData[0]);
195
    store_debug_data("neck/output_tilt", reflexxes_position_output->NewPositionVector->VecData[1]);
184 196
}
185 197

  
186 198
//! publish targets to motor boards:
src/server/server.cpp
128 128
        // mw tick
129 129
        middleware_->tick();
130 130

  
131
        // do some logging
132
        // controller->dump_angles();
133 131

  
134 132
        // calculate all targets
135 133
        controller_->calculate_targets();
136 134

  
135
        // do some logging
136
        middleware_->publish_debug_dataset(controller_->get_debug_data());
137

  
137 138
        // publish data to joints
138 139
        controller_->publish_targets();
139 140

  

Also available in: Unified diff