Revision 32327f15

View differences:

CMakeLists.txt
170 170
    src/server/eyelid_motion_generator.cpp
171 171
    src/server/eyebrow_motion_generator.cpp
172 172
    src/server/neck_motion_generator.cpp
173
    ${DUMMY_HEADER_LIST} 
173
    src/timestamp.cpp
174 174
    src/timestamped_list.cpp
175
    ${DUMMY_HEADER_LIST}
175 176
)
176 177

  
177 178
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
include/humotion/gaze_state.h
27 27

  
28 28
#pragma once
29 29
#include <math.h>
30
#include "timestamp.h"
30 31

  
31 32
namespace humotion{
32 33
class GazeState{
......
49 50
        int gaze_type;
50 51

  
51 52
        //when was this target requested?
52
        double timestamp;
53
        Timestamp timestamp;
53 54

  
54 55
        //is this relative or
55 56
        enum GAZE_STATE_TYPE{
include/humotion/server/joint_interface.h
104 104

  
105 105
protected:
106 106

  
107
    void store_incoming_position(int joint_id, float position, double timestamp);
108
    void store_incoming_speed(int joint_id, float speed, double timestamp);
107
    void store_incoming_position(int joint_id, float position, Timestamp timestamp);
108
    void store_incoming_speed(int joint_id, float speed, Timestamp timestamp);
109 109

  
110 110
    virtual void enable_joint(int id) = 0;
111 111
    virtual void disable_joint(int id) = 0;
include/humotion/timestamp.h
1
/*
2
* This file is part of humotion
3
*
4
* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
5
* http://opensource.cit-ec.de/projects/humotion
6
*
7
* This file may be licensed under the terms of the
8
* GNU Lesser General Public License Version 3 (the ``LGPL''),
9
* or (at your option) any later version.
10
*
11
* Software distributed under the License is distributed
12
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13
* express or implied. See the LGPL for the specific language
14
* governing rights and limitations.
15
*
16
* You should have received a copy of the LGPL along with this
17
* program. If not, go to http://www.gnu.org/licenses/lgpl.html
18
* or write to the Free Software Foundation, Inc.,
19
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
*
21
* The development of this software was supported by the
22
* Excellence Cluster EXC 277 Cognitive Interaction Technology.
23
* The Excellence Cluster EXC 277 is a grant of the Deutsche
24
* Forschungsgemeinschaft (DFG) in the context of the German
25
* Excellence Initiative.
26
*/
27

  
28
#pragma once
29
#include <stdlib.h>
30
#include <stdio.h>
31
#include <unistd.h>
32
#include <string>
33

  
34
namespace humotion{
35

  
36
class Timestamp{
37
public:
38
    Timestamp(void);
39
    Timestamp(int32_t _sec, int32_t _nsec);
40
    void set(int32_t _sec, int32_t _nsec);
41

  
42
    double to_seconds(void);
43

  
44
    bool operator>  (Timestamp &cmp);
45
    bool operator<= (Timestamp &cmp);
46
    bool operator<  (Timestamp &cmp);
47
    bool operator>= (Timestamp &cmp);
48
    bool operator== (Timestamp &cmp);
49
    bool operator!= (Timestamp &cmp);
50

  
51
    int32_t sec;
52
    int32_t nsec;
53

  
54
};
55

  
56

  
57
}
include/humotion/timestamped_float.h
30 30
#include <stdio.h>
31 31
#include <unistd.h>
32 32
#include <string>
33
#include "timestamp.h"
33 34

  
34 35
namespace humotion{
35 36

  
36 37
class TimestampedFloat{
37 38
public:
38
    TimestampedFloat(){
39
		timestamp = 0.0;
39
    TimestampedFloat() : timestamp(0, 0){
40 40
		value = 0.0;
41 41
	}
42 42
	
43
    TimestampedFloat(double ts, float val){
43
    TimestampedFloat(Timestamp ts, float val){
44 44
		timestamp = ts;
45 45
		value = val;
46 46
	}
47 47
	
48
	static double get_timestamp(){
48
    /*static double get_timestamp(){
49 49
		//fetch time
50 50
		struct timespec tp;
51 51
		clock_gettime(CLOCK_REALTIME, &tp);
52 52
		return tp.tv_sec+tp.tv_nsec/1000000000.0;
53
	};
53
    };*/
54 54
	
55
	double timestamp;
55
    Timestamp timestamp;
56 56
    float value;
57 57
	
58 58
};
include/humotion/timestamped_list.h
29 29
#include "timestamped_float.h"
30 30
#include <boost/thread/mutex.hpp>
31 31
#include <list>
32
#include "timestamp.h"
32 33

  
33 34
namespace humotion{
34 35
class TimestampedList{
35 36
public:
36 37
    typedef std::list<TimestampedFloat> timestamped_float_list_t;
37 38

  
38
    TimestampedList( TimestampedList const &l);
39
	TimestampedList(unsigned int size=10);
40
    void insert(double ts, float val);
41
    float get_interpolated_value(double target_ts);
39
    TimestampedList(TimestampedList const &l);
40
    TimestampedList(unsigned int size=100);
41
    void insert(Timestamp ts, float val);
42
    float get_interpolated_value(Timestamp target_ts);
42 43
    float get_newest_value();
43 44
	static void run_tests();
44 45
    void copy_tsf_list_to(timestamped_float_list_t *target);
45
    double get_last_timestamp();
46
    Timestamp get_last_timestamp();
46 47

  
47 48
private:
48 49
    mutable boost::mutex access_mutex;
49
    float interpolate(TimestampedFloat a, TimestampedFloat b, double timestamp);
50
    float interpolate(TimestampedFloat a, TimestampedFloat b, Timestamp timestamp);
50 51
    timestamped_float_list_t tsf_list;
51 52
};
52 53

  
msg/gaze.msg
1 1
Header header
2 2

  
3 3
#type of pan/tilt/roll targets
4
time gaze_timestamp
4 5
int32 gaze_type
5 6
int32 GAZETYPE_ABSOLUTE=0
6 7
int32 GAZETYPE_RELATIVE=1
......
10 11
float32 roll
11 12
float32 vergence
12 13

  
13

  
14 14
float32 pan_offset
15 15
float32 tilt_offset
16 16
float32 roll_offset
src/gaze_state.cpp
56 56

  
57 57
void GazeState::dump(){
58 58
    //dump values to stdout:
59
    printf("> GAZE STATE: %4.2f [%2.1f] %4.2f [%2.1f] %4.2f [%2.1f] (PTR) vergence=%4.2f eyelid_opening=%4.2f/%4.2f eyebrows = %4.2f %4.2f type=%s eyeblink_requests=%d %d\n",
59
    printf("> GAZE STATE: %4.2f [%2.1f] %4.2f [%2.1f] %4.2f [%2.1f] (PTR) vergence=%4.2f eyelid_opening=%4.2f/%4.2f eyebrows = %4.2f %4.2f type=%s [ts=%.3f] eyeblink_requests=%d %d\n",
60 60
           pan, pan_offset, tilt, tilt_offset, roll, roll_offset, vergence,
61 61
           eyelid_opening_upper,eyelid_opening_lower,
62 62
           eyebrow_left, eyebrow_right,
63 63
           (gaze_type==GAZETYPE_ABSOLUTE?"absolute":(gaze_type==GAZETYPE_RELATIVE?"relative":(gaze_type==GAZETYPE_OVERRIDE?"override":"!INVALID!"))),
64
           timestamp.to_seconds(),
64 65
           eyeblink_request_left, eyeblink_request_right
65 66
           );
66 67
}
src/server/controller.cpp
31 31
#include "server/eyebrow_motion_generator.h"
32 32
#include "server/neck_motion_generator.h"
33 33
#include "server/mouth_motion_generator.h"
34
#include "timestamp.h"
34 35

  
35 36
using namespace std;
36 37
using namespace humotion;
......
92 93
    //incoming gaze state wants to set a relative gaze angle
93 94
    //in order to calc the new absolute gaze, we need to go back
94 95
    //in time and find out where the head was pointing at that specific time:
95
    double relative_target_timestamp = relative.timestamp;
96
    Timestamp relative_target_timestamp = relative.timestamp;
96 97

  
97 98
    //fetch head / camera pose during that timestamp:
98 99
    double neck_pan  = joint_interface->get_ts_position(JointInterface::ID_NECK_PAN).get_interpolated_value(relative_target_timestamp);
src/server/gaze_motion_generator.cpp
42 42

  
43 43

  
44 44
//! constructor
45
GazeMotionGenerator::GazeMotionGenerator(JointInterface *j, int dof, float t) : ReflexxesMotionGenerator(j, dof, t){
45
GazeMotionGenerator::GazeMotionGenerator(JointInterface *j, int dof, float t)
46
    : ReflexxesMotionGenerator(j, dof, t){
46 47
}
47 48

  
48 49
//! destructor
......
61 62
    float dist = fabs(requested_gaze_state.distance_pt_abs(new_gaze_target));
62 63

  
63 64
    //check requested speed
64
    float speed = fabs(requested_gaze_state.distance_pt_abs(new_gaze_target)) / (new_gaze_target.timestamp-requested_gaze_state.timestamp);
65
    float speed = fabs(requested_gaze_state.distance_pt_abs(new_gaze_target)) / (new_gaze_target.timestamp.to_seconds()-requested_gaze_state.timestamp.to_seconds());
65 66

  
66 67
    //check magnitude and speed of gaze change to detect eye-neck saccades:
67 68
    if (dist > NECK_SACCADE_THRESHOLD){
src/server/joint_interface.cpp
66 66
//! \param joint name
67 67
//! \param position
68 68
//! \param timestamp when the position was measured
69
void JointInterface::store_incoming_position(int joint_id, float position, double timestamp){
69
void JointInterface::store_incoming_position(int joint_id, float position, Timestamp timestamp){
70 70
    //lock the tsd_list for this access. by doing this we assure
71 71
    //that no other thread accessing this element can diturb the
72 72
    //following atomic instructions:
73 73
    mutex::scoped_lock scoped_lock(joint_ts_position_map_access_mutex);
74 74

  
75
    //printf("> humotion: incoming joint position for joint id 0x%02X = %4.2f (ts=%.2f)\n",joint_id,position,timestamp);
75
    //printf("> humotion: incoming joint position for joint id 0x%02X = %4.2f (ts=%.2f)\n",joint_id,position,timestamp.to_seconds());
76 76
    joint_ts_position_map[joint_id].insert(timestamp, position);
77 77

  
78 78
    incoming_position_count++;
......
91 91
//! \param joint name
92 92
//! \param speed
93 93
//! \param timestamp when the position was measured
94
void JointInterface::store_incoming_speed(int joint_id, float speed, double timestamp){
94
void JointInterface::store_incoming_speed(int joint_id, float speed, Timestamp timestamp){
95 95
    //lock the tsd_list for this access. by doing this we assure
96 96
    //that no other thread accessing this element can diturb the
97 97
    //following atomic instructions:
98 98
    mutex::scoped_lock scoped_lock(joint_ts_speed_map_access_mutex);
99 99

  
100
    //printf("> humotion: incoming joint speed for joint id 0x%02X = %4.2f (ts=%.2f)\n",joint_id,speed,timestamp);
100
    //printf("> humotion: incoming joint speed for joint id 0x%02X = %4.2f (ts=%.2f)\n",joint_id,speed,timestamp.to_seconds());
101 101
    joint_ts_speed_map[joint_id].insert(timestamp, speed);
102 102
}
103 103

  
src/server/middleware_ros.cpp
127 127
    }else{
128 128
        gaze_state.gaze_type = GazeState::GAZETYPE_RELATIVE;
129 129
    }
130
    gaze_state.timestamp = msg->header.stamp.toSec();
130

  
131
    gaze_state.timestamp.set(msg->gaze_timestamp.sec, msg->gaze_timestamp.nsec);
131 132

  
132 133
    controller->set_gaze_target(gaze_state);
133 134

  
src/timestamp.cpp
1
#include "timestamp.h"
2

  
3
using namespace std;
4
using namespace humotion;
5

  
6
Timestamp::Timestamp(void){
7
    //init of an empty timestamp will be assigned to the current system time
8
    struct timespec tp;
9
    clock_gettime(CLOCK_REALTIME, &tp);
10
    sec  = tp.tv_sec;
11
    nsec = tp.tv_nsec;
12
}
13

  
14
Timestamp::Timestamp(int32_t _sec, int32_t _nsec){
15
    set(_sec, _nsec);
16
}
17

  
18
void Timestamp::set(int32_t _sec, int32_t _nsec){
19
    sec  = _sec;
20
    nsec = _nsec;
21
}
22

  
23
double Timestamp::to_seconds(void){
24
    return sec + ((double)nsec)/1000000000.0;
25
}
26

  
27
bool Timestamp::operator<= (Timestamp &cmp){
28
    if (sec < cmp.sec){
29
        return true;
30
    }else if (sec > cmp.sec){
31
        return false;
32
    }else{ //(a.sec == b.sec)
33
        //seconds are equal, check nsec:
34
        return (nsec <= cmp.nsec);
35
    }
36
}
37

  
38
bool Timestamp::operator< (Timestamp &cmp){
39
    if (sec < cmp.sec){
40
        return true;
41
    }else if (sec > cmp.sec){
42
        return false;
43
    }else{ //(a.sec == b.sec)
44
        //seconds are equal, check nsec:
45
        return (nsec < cmp.nsec);
46
    }
47
}
48

  
49
bool Timestamp::operator>= (Timestamp &cmp){
50
    if (sec > cmp.sec){
51
        return true;
52
    }else if (sec < cmp.sec){
53
        return false;
54
    }else{ //(a.sec == b.sec)
55
        //seconds are equal, check nsec:
56
        return (nsec >= cmp.nsec);
57
    }
58
}
59

  
60
bool Timestamp::operator> (Timestamp &cmp){
61
    if (sec > cmp.sec){
62
        return true;
63
    }else if (sec < cmp.sec){
64
        return false;
65
    }else{ //(a.sec == b.sec)
66
        //seconds are equal, check nsec:
67
        return (nsec > cmp.nsec);
68
    }
69
}
70

  
71
bool Timestamp::operator== (Timestamp &cmp){
72
    return (sec == cmp.sec) && (nsec == cmp.nsec);
73
}
74

  
75
bool Timestamp::operator!= (Timestamp &cmp){
76
    return !(*this == cmp);
77
}
78

  
src/timestamped_list.cpp
57 57
    *target = tsf_list;
58 58
}
59 59

  
60
double TimestampedList::get_last_timestamp(){
60
Timestamp TimestampedList::get_last_timestamp(){
61 61
    //lock the tsf_list for this access. by doing this we assure
62 62
    //that no other thread accessing this element can diturb the
63 63
    //following atomic instructions:
64 64
    mutex::scoped_lock scoped_lock(access_mutex);
65 65

  
66 66
    if (tsf_list.empty()){
67
        return 0.0;
67
        return Timestamp(0,0);
68 68
    }
69 69

  
70 70
    timestamped_float_list_t::iterator it = tsf_list.end();
......
72 72
    return it->timestamp;
73 73
}
74 74

  
75
void TimestampedList::insert(double timestamp, float val){
75
void TimestampedList::insert(Timestamp timestamp, float val){
76 76
	//erase first element:
77 77
    tsf_list.pop_front();
78 78
    tsf_list.push_back(TimestampedFloat(timestamp, val));
......
86 86
    mutex::scoped_lock scoped_lock(access_mutex);
87 87

  
88 88
    if (tsf_list.empty()){
89
        printf("> WARNING: requested newest value from empty list, returning 0.0\n");
89 90
        return 0.0;
90 91
    }
91 92

  
......
94 95
	return it->value;
95 96
}
96 97

  
97
float TimestampedList::get_interpolated_value(double target_ts){
98
float TimestampedList::get_interpolated_value(Timestamp target_ts){
98 99
    //lock the tsf_list for this access. by doing this we assure
99 100
    //that no other thread accessing this element can diturb the
100 101
    //following atomic instructions:
......
103 104
    ///target_ts -= 0.001 * 4;
104 105
	
105 106
    TimestampedFloat previous;
106
    //printf("> latency %3.2fms\n", (TimestampedFloat::get_timestamp() - target_ts)*1000.0);
107
    //printf("> latency %3.2fms\n", (Timestamped().to_seconds() - target_ts.to_seconds())*1000.0);
107 108

  
108 109
    for ( timestamped_float_list_t::iterator it = tsf_list.begin(); it != tsf_list.end(); ++it ){
109 110
		if (it->timestamp >= target_ts){
110 111
			//ok found close target
111 112
            if (it == tsf_list.begin()){
112 113
				//no preceding element
113
                printf("> warning, timestamp %6.3f smaller than first element %6.3f in timestamped list. this should not happen (increase ts buffer?)\n",target_ts,tsf_list.begin()->timestamp);
114
                printf("> warning, timestamp %6.3f smaller than first element %6.3f in timestamped list. this should not happen (increase ts buffer?)\n",target_ts.to_seconds(),tsf_list.begin()->timestamp.to_seconds());
114 115
				return it->value;
115 116
			}else{
116 117
				//do interpolation
......
119 120
		}
120 121
		previous = *it;
121 122
	}
123

  
122 124
	//we reached the end, return the last value
123
	printf("> warning: found no timestamp bigger than %f in timestamped list...\n", target_ts);
125
    printf("> warning: found no timestamp bigger than %f in timestamped list...\n", target_ts.to_seconds());
124 126
	printf("           this should not happen as images will always be behind\n");
125
	printf("           the motor data. returning most recent value (ts=%f)\n", previous.timestamp);
127
    printf("           the motor data. returning most recent value (ts=%f)\n", previous.timestamp.to_seconds());
126 128
	
127 129
	return previous.value;
128 130
}
129 131

  
130
float TimestampedList::interpolate(TimestampedFloat a, TimestampedFloat b, double timestamp){
132
float TimestampedList::interpolate(TimestampedFloat a, TimestampedFloat b, Timestamp timestamp){
131 133
	//a->timestamp < timestamp <= b->timestamp
132
    double dist_a = timestamp - a.timestamp;
133
	double dist_b = b.timestamp - timestamp;
134
    double dist_a = timestamp.to_seconds() - a.timestamp.to_seconds();
135
    double dist_b = b.timestamp.to_seconds() - timestamp.to_seconds();
134 136
	double dist   = dist_a + dist_b;
135 137
	
136 138
    float interpolation = a.value + (dist_a / dist) * (b.value - a.value);
......
144 146
	TimestampedList list(size);
145 147
	
146 148
	for(int i=0; i<size; i++){
147
		list.insert(i * 100.0, i*10.0);
149
        list.insert(Timestamp(i * 100.0,0), i*10.0);
148 150
	}
149 151
	
150 152
	//test algorithm:
151 153
	
152 154
	//test exact match:
153 155
	for(int i=0; i<size; i++){
154
		printf("> testing get_interpolated_value(%f) == %f (value read back = %f)\n",i*100.0, i*10.0, list.get_interpolated_value(i*100.0));
155
		assert( list.get_interpolated_value(i*100.0) == i*10.0);
156
        Timestamp ts(i*100.0,0);
157
        printf("> testing get_interpolated_value(%f) == %f (value read back = %f)\n",ts.to_seconds(), i*10.0, list.get_interpolated_value(ts));
158
        assert( list.get_interpolated_value(ts) == i*10.0);
156 159
	}
157 160
	printf("passed test 1\n");
158 161
	
159
	assert(list.get_interpolated_value(0.0) == 0.0);
160
	assert(list.get_interpolated_value(110.0) == 11.0);
161
	assert(list.get_interpolated_value(150.0) == 15.0);
162
	assert(list.get_interpolated_value(999990.0) == 90.0);
162
    assert(list.get_interpolated_value(Timestamp(0.0,0)) == 0.0);
163
    assert(list.get_interpolated_value(Timestamp(110.0,0)) == 11.0);
164
    assert(list.get_interpolated_value(Timestamp(150.0,0)) == 15.0);
165
    assert(list.get_interpolated_value(Timestamp(999990.0,0)) == 90.0);
163 166
	
164 167
	printf("passed test 2\n");
165 168
	
166
	list.insert(1000.0, 200.0);
167
	list.insert(1300.0, -100.0);
168
	assert(list.get_interpolated_value(1100) == 100.0);
169
	assert(list.get_interpolated_value(1200) == 0.0);
170
	assert(list.get_interpolated_value(1300) == -100.0);
171
	assert(list.get_interpolated_value(1250) == -50.0);
169
    list.insert(Timestamp(1000.0 ,0), 200.0);
170
    list.insert(Timestamp(1300.0, 0), -100.0);
171
    assert(list.get_interpolated_value(Timestamp(1100, 0)) == 100.0);
172
    assert(list.get_interpolated_value(Timestamp(1200, 0)) == 0.0);
173
    assert(list.get_interpolated_value(Timestamp(1300, 0)) == -100.0);
174
    assert(list.get_interpolated_value(Timestamp(1250, 0)) == -50.0);
172 175
	
173 176
	printf("passed test 3\n");
174 177
	exit(0);

Also available in: Unified diff