In the first example, a simple sine movement is implemented as CCA component (C++) that is locally connected to the Oncilla CCA Interface. The example can be executed by opening the world file Example2.wbt installed by the Oncilla Project Wizard.
In order to move the robot, the component has eight ports of JointAngles type, that are connected to the appropriate ports of the Oncilla CCA Interface to move the four L1 and L2 (hip and knee) joints of oncilla.
Single steps:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | #include <iostream>
#include <fstream>
#include <stdlib.h>
#include <math.h>
#include <rsc/misc/langutils.h>
#include <cca/timing/PeriodicBeat.h>
#include <cca/processing/all.h>
#include <rci/dto/JointAngles.h>
#include "cca-oncilla/CCAOncilla.h"
#define TIME_STEP 6 // Webots control step in ms
using namespace std;
using namespace boost;
using namespace rci;
using namespace rci::oncilla;
using namespace cca;
using namespace cca::oncilla;
/**
* Sine Movement Component
*
* The sine movement component generates a sine movement in its processing
* method that is called by the CCA framework. Generated joint angles for the
* eight L1 and L2 joint of Oncilla are published in processing step over the
* eight according output ports of the component
*/
class SimpleSineMovement: public cca::Node {
public:
SimpleSineMovement(double ampl, double freq) :
Node("SimpleSineMovement"), OUT_LF_HIP(), OUT_RF_HIP(),
OUT_LH_HIP(), OUT_RH_HIP(), OUT_LF_KNEE(), OUT_RF_KNEE(),
OUT_LH_KNEE(), OUT_RH_KNEE(),
hip_amplitude(ampl), fore_hip_offset(0), hind_hip_offset(0),
fore_knee_amplitude(.1), fore_knee_offset(.2),
hind_knee_amplitude(.1), hind_knee_offset(.2),
fore_hip_knee_phase_lag(-0.2), hind_hip_knee_phase_lag(0),
frequency(freq), time_s(0), phase(0), antiphase(0) {
// Create ports
OUT_LF_HIP = OutputPort<JointAngles>::create();
registerPort("out_lf_hip", OUT_LF_HIP);
OUT_RF_HIP = OutputPort<JointAngles>::create();
registerPort("out_rf_hip", OUT_RF_HIP);
OUT_LH_HIP = OutputPort<JointAngles>::create();
registerPort("out_lh_hip", OUT_LH_HIP);
OUT_RH_HIP = OutputPort<JointAngles>::create();
registerPort("out_rh_hip", OUT_RH_HIP);
OUT_LF_KNEE = OutputPort<JointAngles>::create();
registerPort("out_lf_knee", OUT_LF_KNEE);
OUT_RF_KNEE = OutputPort<JointAngles>::create();
registerPort("out_rf_knee", OUT_RF_KNEE);
OUT_LH_KNEE = OutputPort<JointAngles>::create();
registerPort("out_lh_knee", OUT_LH_KNEE);
OUT_RH_KNEE = OutputPort<JointAngles>::create();
registerPort("out_rh_knee", OUT_RH_KNEE);
}
~SimpleSineMovement() {
}
void onProcess() {
// The time is our phase - TODO: Use virtual / simulated time
time_s = rsc::misc::currentTimeMillis() / 1000.0;
phase = std::fmod(time_s * frequency * 2 * M_PI, 2 * M_PI);
antiphase = std::fmod(phase + M_PI, 2 * M_PI);
OUT_LF_HIP->publish(
JointAngles::fromDeg(
hip_position(phase, hip_amplitude, fore_hip_offset)));
OUT_RF_HIP->publish(
JointAngles::fromDeg(
hip_position(antiphase, hip_amplitude,
fore_hip_offset)));
OUT_LH_HIP->publish(
JointAngles::fromDeg(
hip_position(antiphase, hip_amplitude,
hind_hip_offset)));
OUT_RH_HIP->publish(
JointAngles::fromDeg(
hip_position(phase, hip_amplitude, hind_hip_offset)));
OUT_LF_KNEE->publish(
JointAngles::fromRad(
knee_position(phase, fore_hip_knee_phase_lag,
fore_knee_amplitude, fore_knee_offset)));
OUT_RF_KNEE->publish(
JointAngles::fromRad(
knee_position(antiphase, fore_hip_knee_phase_lag,
fore_knee_amplitude, fore_knee_offset)));
OUT_LH_KNEE->publish(
JointAngles::fromRad(
knee_position(antiphase, hind_hip_knee_phase_lag,
hind_knee_amplitude, hind_knee_offset)));
OUT_RH_KNEE->publish(
JointAngles::fromRad(
knee_position(phase, hind_hip_knee_phase_lag,
hind_knee_amplitude, hind_knee_offset)));
}
OutputPort<JointAngles>::Ptr OUT_LF_HIP, OUT_RF_HIP, OUT_LH_HIP, OUT_RH_HIP;
OutputPort<JointAngles>::Ptr OUT_LF_KNEE, OUT_RF_KNEE, OUT_LH_KNEE,
OUT_RH_KNEE;
private:
double hip_position(double phase, double amplitude, double offset) {
return amplitude * std::cos(phase) + offset;
}
double knee_position(double phase, double phase_lag, double amplitude,
double offset) {
return amplitude * ((phase + phase_lag) > M_PI ? 1.0 : 0.0) + offset;
}
double hip_amplitude, fore_hip_offset, hind_hip_offset, fore_knee_amplitude,
fore_knee_offset, hind_knee_amplitude, hind_knee_offset,
fore_hip_knee_phase_lag, hind_hip_knee_phase_lag, frequency;
double time_s, phase, antiphase;
};
/**
* The main routine of this example instantiates the Oncilla robot interface
* and the sine movement component. It connects the component to the interface
* by configuring the output ports of the sine component to match the input
* (command) ports of the robot.
*/
int main() {
// Create a general beat for our system
BeatPtr heartbeat = PeriodicBeat::create(TIME_STEP); // TIME_STEP ms
// Instantiate the Oncilla representation in CCA
CCAOncilla oncilla = CCAOncilla(heartbeat, PortConfiguration::CCALocal);
// Create the component that send commands
SimpleSineMovement *s = new SimpleSineMovement(10, 1.6);
NodePtr sine = NodePtr(s);
sine->setProcessingStrategy(Timed::samplerate(1));
// Configure ports of the sine movement component to connect to the robot
sine->configureOutputPort("out_lf_hip",
PortConfiguration::LOCAL("/oncilla/cmd/pos/lf/l1"));
sine->configureOutputPort("out_rf_hip",
PortConfiguration::LOCAL("/oncilla/cmd/pos/rf/l1"));
sine->configureOutputPort("out_lh_hip",
PortConfiguration::LOCAL("/oncilla/cmd/pos/lh/l1"));
sine->configureOutputPort("out_rh_hip",
PortConfiguration::LOCAL("/oncilla/cmd/pos/rh/l1"));
sine->configureOutputPort("out_lf_knee",
PortConfiguration::LOCAL("/oncilla/cmd/pos/lf/l2"));
sine->configureOutputPort("out_rf_knee",
PortConfiguration::LOCAL("/oncilla/cmd/pos/rf/l2"));
sine->configureOutputPort("out_lh_knee",
PortConfiguration::LOCAL("/oncilla/cmd/pos/lh/l2"));
sine->configureOutputPort("out_rh_knee",
PortConfiguration::LOCAL("/oncilla/cmd/pos/rh/l2"));
// Register the sine movement component to the beat
heartbeat->registerReceiver(sine);
printf("*** Note:\n");
printf("*** This is a dummy walking example to show the basic usage of the\n");
printf("*** simulator with API Level 1! Adapt the example to your own needs.\n");
// Run the beat
heartbeat->run();
return EXIT_SUCCESS;
}
|