Statistics
| Branch: | Tag: | Revision:

humotion / examples / yarp_icub / src / icub_data_receiver.cpp @ 0c8d22a5

History | View | Annotate | Download (9.104 KB)

1 6a2d467f Simon Schulz
/*
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
#include <boost/format.hpp>
29 35b3ca25 Simon Schulz
#include <humotion/server/joint_interface.h>
30 8c6c1163 Simon Schulz
#include <yarp/os/Property.h>
31 6a2d467f Simon Schulz
32 a5cc61d4 sschulz
#include <string>
33
34 6a2d467f Simon Schulz
#include "humotion_yarp_icub/icub_data_receiver.h"
35 ad7b6f18 Simon Schulz
36 35b3ca25 Simon Schulz
using std::cout;
37 1f748ce7 Simon Schulz
using std::cerr;
38 35b3ca25 Simon Schulz
using std::string;
39
using humotion::server::JointInterface;
40
using yarp::dev::IEncodersTimed;
41
using yarp::sig::Vector;
42
43 ea29304b Simon Schulz
#define ICUB_DATA_RECEIVER_USE_ENCODERSPEED 0
44 ad7b6f18 Simon Schulz
#define ICUB_DATA_RECEIVER_DUMP_DATA 0
45 ea29304b Simon Schulz
46 ad7b6f18 Simon Schulz
//! constructor
47
//! \param period_ms for the yarp rate thread
48
//! \param icub_jointinterface
49
iCubDataReceiver::iCubDataReceiver(int period_ms, iCubJointInterface *icub_jointinterface)
50
    : yarp::os::RateThread(period_ms) {
51 35b3ca25 Simon Schulz
52
    // store pointer to icub jointinterface
53
    icub_jointinterface_ = icub_jointinterface;
54
55 6a2d467f Simon Schulz
    // fetch iencs view from yarp
56 35b3ca25 Simon Schulz
    yarp::dev::PolyDriver *poly_driver = icub_jointinterface->get_yarp_polydriver();
57 ea29304b Simon Schulz
    bool success = poly_driver->view(iencs_);
58 35b3ca25 Simon Schulz
    if (!success) {
59 1f748ce7 Simon Schulz
        cerr << "ERROR: polydriver failed to init iencs view\n";
60 35b3ca25 Simon Schulz
        exit(EXIT_FAILURE);
61
    }
62
63 ea29304b Simon Schulz
    // resize data storage vectors to match the number of axes
64 8c6c1163 Simon Schulz
    int joints;
65 ea29304b Simon Schulz
    iencs_->getAxes(&joints);
66
    positions_.resize(joints);
67
    velocities_.resize(joints);
68
    timestamps_.resize(joints);
69 8c6c1163 Simon Schulz
}
70
71 ad7b6f18 Simon Schulz
//! yarp rate thread initializer
72 35b3ca25 Simon Schulz
bool iCubDataReceiver::threadInit() {
73
    return true;
74 8c6c1163 Simon Schulz
}
75
76 ad7b6f18 Simon Schulz
//! yarp thread release function
77 35b3ca25 Simon Schulz
void iCubDataReceiver::threadRelease() {
78
}
79 7adf90be Simon Schulz
80 ad7b6f18 Simon Schulz
//! manully calculate joint velocities (instead of using joint encoder speeds)
81
//! \param positions vector with current encoder position
82
//! \param timestamps vector with the associated timestamps
83
//! \return velocities as vector
84 1f748ce7 Simon Schulz
Vector iCubDataReceiver::calculate_velocities(Vector positions, Vector timestamps) {
85
    Vector velocities;
86 ea29304b Simon Schulz
    velocities.resize(positions.size());
87
88 6a2d467f Simon Schulz
    if (previous_positions_.size() == 0) {
89 ea29304b Simon Schulz
        // first run, no valid old position available, return zero velocities
90
        // by setting all all elements to zero
91
        velocities = 0.0;
92 6a2d467f Simon Schulz
    } else {
93 ea29304b Simon Schulz
        // calculate speed based on positions:
94 6a2d467f Simon Schulz
        for (int i=0; i < positions.size(); i++) {
95 ea29304b Simon Schulz
            float diff = positions[i] - previous_positions_[i];
96
            float timediff = timestamps[i] - previous_timestamps_[i];
97
            // calc speed:
98
            velocities[i] = diff / timediff;
99
        }
100
    }
101
102
    previous_positions_ = positions;
103
    previous_timestamps_ = timestamps;
104
105
    return velocities;
106
}
107
108 ad7b6f18 Simon Schulz
//! main loop routine, called by yarp rate thread
109 35b3ca25 Simon Schulz
void iCubDataReceiver::run() {
110 ea29304b Simon Schulz
    float velocity;
111
112 6a2d467f Simon Schulz
    // grab pos+vel data:
113 ea29304b Simon Schulz
    iencs_->getEncodersTimed(positions_.data(), timestamps_.data());
114 8c6c1163 Simon Schulz
115 ea29304b Simon Schulz
    #if ICUB_DATA_RECEIVER_USE_ENCODERSPEED
116
    // fetch data from icub. NOTE: make sure to enable the vel broadcast in the ini file!
117 6a2d467f Simon Schulz
    if (!iencs_->getEncoderSpeeds(velocities_.data())) {
118 18e9b892 Simon Schulz
        cout << "Failed to fetch encoder speeds...\n";
119
        return;
120
    }
121 ea29304b Simon Schulz
    #else
122
    // manually calculate the speed based on old position:
123
    velocities_ = calculate_velocities(positions_, timestamps_);
124
    #endif
125
126
    // publish data to humotion
127 6a2d467f Simon Schulz
    for (int i = 0; i < positions_.size(); i++) {
128 ea29304b Simon Schulz
        // store position values
129
        store_incoming_position(i, positions_[i], timestamps_[i]);
130
        // store velocity
131
        store_incoming_velocity(i, velocities_[i], timestamps_[i]);
132 8c6c1163 Simon Schulz
    }
133 6a2d467f Simon Schulz
134
    // small hack to tell humotion to update the lid angle
135
    // fixme: use real id
136 ea29304b Simon Schulz
    store_incoming_position(100, 0.0, timestamps_[0]);
137 ad7b6f18 Simon Schulz
138
    #if ICUB_DATA_RECEIVER_DUMP_DATA
139
    dump_incoming_data();
140
    #endif
141 35b3ca25 Simon Schulz
}
142
143 ad7b6f18 Simon Schulz
//! store incoming position for a given icub joint
144
//! \param icub _id icub joint id
145
//! \param position
146
//! \param timestamp
147
void iCubDataReceiver::store_incoming_position(int icub_id, double position, double timestamp) {
148 a5cc61d4 sschulz
    // cout << "store_incoming_position(icub=" << icub_id << ", " << position << ")\n";
149 6c028e11 Simon Schulz
150 35b3ca25 Simon Schulz
    // store joint position in humotion backend
151
    if ((icub_id == iCubJointInterface::ICUB_ID_EYES_PAN) ||
152
            (icub_id == iCubJointInterface::ICUB_ID_EYES_VERGENCE)) {
153
        // the icub handles eyes differently
154
        // instead of using seperate left/right pan the icub uses
155
        // a combined pan angle and vergence. therfore we have to convert this here:
156
        if (icub_id == iCubJointInterface::ICUB_ID_EYES_PAN) {
157 ad7b6f18 Simon Schulz
            target_eye_pan_ = position;
158 35b3ca25 Simon Schulz
        } else {
159 ad7b6f18 Simon Schulz
            target_eye_vergence_ = -position;
160 35b3ca25 Simon Schulz
        }
161
162 18e9b892 Simon Schulz
        float right = target_eye_pan_ + target_eye_vergence_/2.0;
163
        float left  = target_eye_pan_ - target_eye_vergence_/2.0;
164 35b3ca25 Simon Schulz
165
        icub_jointinterface_->store_incoming_position(JointInterface::ID_EYES_LEFT_LR,
166
                                                     left, timestamp);
167
        icub_jointinterface_->store_incoming_position(JointInterface::ID_EYES_RIGHT_LR,
168
                                                     right, timestamp);
169
    } else if (icub_id == 100) {
170
        //HACK
171 a5cc61d4 sschulz
        // icub_jointinterface->store_incoming_position(ID_EYES_RIGHT_LID_UPPER,
172 35b3ca25 Simon Schulz
        //                                             lid_angle, timestamp);
173
    } else {
174 6c028e11 Simon Schulz
        if (icub_id == iCubJointInterface::ID_NECK_PAN) {
175
            // icub uses an inverted neck pan specification
176 ad7b6f18 Simon Schulz
            position = -position;
177 6c028e11 Simon Schulz
        }
178
179 35b3ca25 Simon Schulz
        // known configured mapping between joint ids
180
        int humotion_id = icub_jointinterface_->convert_icub_jointid_to_humotion(icub_id);
181 ad7b6f18 Simon Schulz
        icub_jointinterface_->store_incoming_position(humotion_id, position, timestamp);
182 35b3ca25 Simon Schulz
    }
183 8c6c1163 Simon Schulz
}
184 ea29304b Simon Schulz
185 ad7b6f18 Simon Schulz
//! store incoming velocity for a given icub joint
186
//! \param icub_id icub joint id
187
//! \param velocity
188
//! \param timestamp
189 ea29304b Simon Schulz
void iCubDataReceiver::store_incoming_velocity(int icub_id, double velocity, double timestamp) {
190 a5cc61d4 sschulz
    // cout << "store_incoming_velocity(icub=" << icub_id << ", " << velocity << ")\n";
191 ea29304b Simon Schulz
192
    // store joint position in humotion backend
193
    if ((icub_id == iCubJointInterface::ICUB_ID_EYES_PAN) ||
194
            (icub_id == iCubJointInterface::ICUB_ID_EYES_VERGENCE)) {
195
        // the icub handles eyes differently
196
        // instead of using seperate left/right pan the icub uses
197
        // a combined pan angle and vergence. therfore we have to convert this here:
198
        if (icub_id == iCubJointInterface::ICUB_ID_EYES_PAN) {
199
            target_eye_pan_velocity_ = velocity;
200
        } else {
201
            target_eye_vergence_velocity_ = -velocity;
202
        }
203
204 18e9b892 Simon Schulz
        float right = target_eye_pan_velocity_ + target_eye_vergence_velocity_/2.0;
205
        float left  = target_eye_pan_velocity_ - target_eye_vergence_velocity_/2.0;
206 ea29304b Simon Schulz
207
        icub_jointinterface_->store_incoming_velocity(JointInterface::ID_EYES_LEFT_LR,
208
                                                     left, timestamp);
209
        icub_jointinterface_->store_incoming_velocity(JointInterface::ID_EYES_RIGHT_LR,
210
                                                     right, timestamp);
211
    } else if (icub_id == 100) {
212
        //HACK
213 a5cc61d4 sschulz
        // icub_jointinterface->store_incoming_position(ID_EYES_RIGHT_LID_UPPER,
214 ea29304b Simon Schulz
        //                                             lid_angle, timestamp);
215
    } else {
216
        if (icub_id == iCubJointInterface::ID_NECK_PAN) {
217
            // icub uses an inverted neck pan specification
218
            velocity = -velocity;
219
        }
220
221
        // known configured mapping between joint ids
222
        int humotion_id = icub_jointinterface_->convert_icub_jointid_to_humotion(icub_id);
223
        icub_jointinterface_->store_incoming_velocity(humotion_id, velocity, timestamp);
224
    }
225
}
226
227 ad7b6f18 Simon Schulz
//! helper for debugging purposes, feed this data into gnuplot for visual inspection
228
void iCubDataReceiver::dump_incoming_data() {
229
    // use gnuplot for viz:
230
    // ./icub_humotion_server --robot icub | grep "INCOMING" |tee  log
231
    // @gnuplot: plot "log" using 0:1 w l t "p neck tilt", "log" using 0:2 w l t "v neck tilt", \
232
    //                "log" using 0:5 w l t "p neck pan", "log" using 0:6 w l t "v neck pan", \
233
    //                "log" using 0:7 w l t "p eyes ud", "log" using 0:8 w l t "v eyes ud", \
234 a5cc61d4 sschulz
    //                "log" using 0:9 w l t "p eyes vergence", "log" using 0:10 w l t "v eyes verg"
235 ad7b6f18 Simon Schulz
    cout << "\n";
236
            // publish data to humotion
237 a5cc61d4 sschulz
    for (int i = 0; i < positions_.size(); i++) {
238 ad7b6f18 Simon Schulz
        cout << positions_[i] << " ";
239
        cout << velocities_[i] << " ";
240
    }
241
    cout << " #INCOMING_DATA_DUMP\n";
242
}
243