16 |
16 |
*/
|
17 |
17 |
|
18 |
18 |
//WARNING: DO NOT CHANGE THIS; VELOCITYMODE IS NOT YET IMPLEMENTED
|
19 |
|
#define POSITION_CONTROL 1
|
|
19 |
#define POSITION_CONTROL 0
|
20 |
20 |
|
21 |
21 |
|
22 |
22 |
//! constructor
|
... | ... | |
45 |
45 |
enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_NECK_ROLL, ID_NECK_ROLL));
|
46 |
46 |
|
47 |
47 |
//EYES
|
48 |
|
enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_LEFT_LR, ID_EYES_LEFT_LR));
|
49 |
|
enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_RIGHT_LR, ID_EYES_RIGHT_LR));
|
|
48 |
enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_PAN, ID_EYES_LEFT_LR));
|
|
49 |
enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_VERGENCE, ID_EYES_RIGHT_LR));
|
50 |
50 |
enum_id_bimap.insert(enum_id_bimap_entry_t(ICUB_ID_EYES_BOTH_UD, ID_EYES_BOTH_UD));
|
51 |
51 |
|
52 |
52 |
//EYELIDS
|
... | ... | |
69 |
69 |
dd.view(ipos);
|
70 |
70 |
dd.view(ivel);
|
71 |
71 |
dd.view(ilimits);
|
|
72 |
dd.view(pid);
|
|
73 |
dd.view(amp);
|
72 |
74 |
|
73 |
|
if ( (!iencs) || (!ipos) || (!ilimits) || (!ivel)){
|
|
75 |
|
|
76 |
if ( (!iencs) || (!ipos) || (!ilimits) || (!ivel) || (!amp) || (!pid)){
|
74 |
77 |
printf("> ERROR: failed to open icub views\n");
|
75 |
78 |
exit(EXIT_FAILURE);
|
76 |
79 |
}
|
... | ... | |
92 |
95 |
ipos->setPositionMode();
|
93 |
96 |
}else{
|
94 |
97 |
ivel->setVelocityMode();
|
95 |
|
commands=1000000;
|
|
98 |
commands=100.0;
|
96 |
99 |
ivel->setRefAccelerations(commands.data());
|
97 |
100 |
}
|
98 |
101 |
|
... | ... | |
169 |
172 |
Bottle &cmd = emotion_port[0].prepare();
|
170 |
173 |
cmd.clear();
|
171 |
174 |
cmd.addString(buf);
|
172 |
|
emotion_port[0].write();
|
|
175 |
emotion_port[0].writeStrict();
|
173 |
176 |
}else{
|
174 |
177 |
printf("> ERROR: no icub emotion output\n");
|
175 |
178 |
exit(EXIT_FAILURE);
|
... | ... | |
227 |
230 |
Bottle &cmd = emotion_port[port_id].prepare();
|
228 |
231 |
cmd.clear();
|
229 |
232 |
cmd.addString(cmd_s);
|
230 |
|
emotion_port[port_id].write();
|
|
233 |
emotion_port[port_id].writeStrict();
|
231 |
234 |
}else{
|
232 |
235 |
printf("> ERROR: no icub emotion output\n");
|
233 |
236 |
exit(EXIT_FAILURE);
|
... | ... | |
252 |
255 |
if (id == ICUB_ID_NECK_PAN){
|
253 |
256 |
//PAN seems to be swapped
|
254 |
257 |
store_joint(ICUB_ID_NECK_PAN, -joint_target[e]);
|
255 |
|
}else if ((id == ICUB_ID_EYES_LEFT_LR) || ( id == ICUB_ID_EYES_RIGHT_LR)){
|
|
258 |
}else if ((id == ICUB_ID_EYES_PAN) || ( id == ICUB_ID_EYES_VERGENCE)){
|
256 |
259 |
//icub handles eyes differently, we have to set pan angle + vergence
|
257 |
260 |
float pan = (joint_target[ID_EYES_LEFT_LR] + joint_target[ID_EYES_RIGHT_LR]) / 2;
|
258 |
261 |
float vergence = (joint_target[ID_EYES_LEFT_LR] - joint_target[ID_EYES_RIGHT_LR]);
|
... | ... | |
283 |
286 |
printf("> ERROR: set_target_positionmode(id=%d, %3.2f) not supported for this id\n",id,value);
|
284 |
287 |
return;
|
285 |
288 |
}
|
286 |
|
#if 0
|
287 |
|
//set speed cacluated as in velocity + set position -> replicates smoothmotion from flobi?!
|
288 |
|
|
289 |
|
//first: calculate necessary speed to reach the given target within the next clock tick:
|
290 |
|
double distance = value - target_angle_previous[id];
|
291 |
|
//make the motion smooth: we want to reach 85% of the target in the next iteration:
|
292 |
|
//calculate speed for that:
|
293 |
|
double speed = 0.85 * distance * ((double)MAIN_LOOP_FREQUENCY);
|
294 |
289 |
|
295 |
|
//set up speed for controller:
|
296 |
|
ipos->setRefSpeed(id, speed);
|
297 |
|
#endif
|
298 |
|
//execute motion
|
|
290 |
// execute motion as position control cmd
|
299 |
291 |
ipos->positionMove(id, value);
|
|
292 |
|
300 |
293 |
}
|
301 |
294 |
|
302 |
295 |
//! execute a move in velocity mode
|
303 |
296 |
//! \param id of joint
|
304 |
297 |
//! \param angle
|
305 |
298 |
void iCubJointInterface::set_target_in_velocitymode(int id, double value){
|
|
299 |
// set speed cacluated as in velocity + set position -> replicates smoothmotion from flobi?!
|
306 |
300 |
//first: calculate necessary speed to reach the given target within the next clock tick:
|
307 |
301 |
double distance = value - target_angle_previous[id];
|
|
302 |
|
308 |
303 |
//make the motion smooth: we want to reach 85% of the target in the next iteration:
|
309 |
304 |
distance = 0.85 * distance;
|
|
305 |
|
|
306 |
//distance = -5.0 / 50.0;
|
|
307 |
|
310 |
308 |
//calculate speed
|
311 |
|
double speed = distance * ((double)MAIN_LOOP_FREQUENCY);
|
|
309 |
//double speed = distance * ((double)MAIN_LOOP_FREQUENCY);
|
|
310 |
|
|
311 |
|
|
312 |
|
|
313 |
int e = convert_motorid_to_enum(id);
|
|
314 |
double speed = joint_target_speed[e];
|
|
315 |
|
|
316 |
double max = 150.0;
|
|
317 |
if (speed > max) speed = max;
|
|
318 |
if (speed < -max) speed = -max;
|
|
319 |
|
|
320 |
//speed = -speed;
|
|
321 |
|
|
322 |
|
312 |
323 |
//execute:
|
313 |
|
ivel->velocityMove(id, speed);
|
314 |
|
//if (id == ICUB_ID_NECK_PAN) printf("> VEL now=%3.2f target=%3.2f --> dist=%3.2f speed=%3.2f\n",target_angle_previous[id],value,distance,speed);
|
|
324 |
//ivel->velocityMove(id, speed);
|
|
325 |
if ((id == ICUB_ID_NECK_PAN) || (id == ICUB_ID_EYES_BOTH_UD) || (id == ICUB_ID_NECK_TILT) || (id == ICUB_ID_EYES_BOTH_UD) || (id == ICUB_ID_NECK_TILT) ){
|
|
326 |
if (id == ICUB_ID_NECK_PAN) speed = -speed;
|
|
327 |
ivel->velocityMove(id, speed);
|
|
328 |
printf("> VEL now=%3.2f target=%3.2f --> dist=%3.2f speed=%3.2f\n",target_angle_previous[id],value,distance,speed);
|
|
329 |
}
|
315 |
330 |
|
316 |
331 |
target_angle_previous[id] = get_ts_position(convert_motorid_to_enum(id)).get_newest_value();
|
317 |
332 |
}
|
... | ... | |
416 |
431 |
Bottle &cmd = emotion_port[3].prepare();
|
417 |
432 |
cmd.clear();
|
418 |
433 |
cmd.addString(buf);
|
419 |
|
emotion_port[3].write();
|
|
434 |
emotion_port[3].writeStrict();
|
420 |
435 |
|
421 |
436 |
|
422 |
437 |
//store joint values which we do not handle on icub here:
|
... | ... | |
451 |
466 |
JointInterface::store_incoming_position(ID_EYES_RIGHT_LID_UPPER, lid_angle, timestamp);
|
452 |
467 |
break;
|
453 |
468 |
|
454 |
|
case(2):
|
|
469 |
case(ICUB_ID_NECK_PAN):
|
455 |
470 |
//PAN is inverted!
|
456 |
471 |
JointInterface::store_incoming_position(ID_NECK_PAN, -value, timestamp);
|
457 |
472 |
break;
|
458 |
473 |
|
459 |
|
case(0):
|
|
474 |
case(ICUB_ID_NECK_TILT):
|
460 |
475 |
JointInterface::store_incoming_position(ID_NECK_TILT, value, timestamp);
|
461 |
476 |
break;
|
462 |
477 |
|
463 |
|
case(1):
|
|
478 |
case(ICUB_ID_NECK_ROLL):
|
464 |
479 |
JointInterface::store_incoming_position(ID_NECK_ROLL, value, timestamp);
|
465 |
480 |
break;
|
466 |
481 |
|
467 |
|
case(3):
|
|
482 |
case(ICUB_ID_EYES_BOTH_UD):
|
468 |
483 |
JointInterface::store_incoming_position(ID_EYES_BOTH_UD, value, timestamp);
|
469 |
484 |
break;
|
470 |
485 |
|
471 |
486 |
//icub handles eyes differently, we have to set pan angle + vergence
|
472 |
|
case(4): {//pan
|
|
487 |
case(ICUB_ID_EYES_PAN): {//pan
|
473 |
488 |
last_pos_eye_pan = value;
|
474 |
489 |
float left = last_pos_eye_pan + last_pos_eye_vergence/2.0;
|
475 |
490 |
float right = last_pos_eye_pan - last_pos_eye_vergence/2.0;
|
... | ... | |
480 |
495 |
break;
|
481 |
496 |
}
|
482 |
497 |
|
483 |
|
case(5): { //vergence
|
|
498 |
case(ICUB_ID_EYES_VERGENCE): { //vergence
|
484 |
499 |
last_pos_eye_vergence = value;
|
485 |
500 |
float left = last_pos_eye_pan + last_pos_eye_vergence/2.0;
|
486 |
501 |
float right = last_pos_eye_pan - last_pos_eye_vergence/2.0;
|
... | ... | |
506 |
521 |
printf("> ERROR: unhandled joint id %d\n",id);
|
507 |
522 |
return;
|
508 |
523 |
|
509 |
|
case(2):
|
510 |
|
JointInterface::store_incoming_speed(ID_NECK_PAN, value, timestamp);
|
|
524 |
case(ICUB_ID_NECK_PAN):
|
|
525 |
//PAN IS INVERTED
|
|
526 |
JointInterface::store_incoming_speed(ID_NECK_PAN, -value, timestamp);
|
511 |
527 |
break;
|
512 |
528 |
|
513 |
|
case(0):
|
|
529 |
case(ICUB_ID_NECK_TILT):
|
514 |
530 |
JointInterface::store_incoming_speed(ID_NECK_TILT, value, timestamp);
|
515 |
531 |
break;
|
516 |
532 |
|
517 |
|
case(1):
|
|
533 |
case(ICUB_ID_NECK_ROLL):
|
518 |
534 |
JointInterface::store_incoming_speed(ID_NECK_ROLL, value, timestamp);
|
519 |
535 |
break;
|
520 |
536 |
|
521 |
|
case(3):
|
|
537 |
case(ICUB_ID_EYES_BOTH_UD):
|
522 |
538 |
JointInterface::store_incoming_speed(ID_EYES_BOTH_UD, value, timestamp);
|
523 |
539 |
break;
|
524 |
540 |
|
525 |
541 |
//icub handles eyes differently, we have to set pan angle + vergence
|
526 |
|
case(4): {//pan
|
|
542 |
case(ICUB_ID_EYES_PAN): {//pan
|
527 |
543 |
last_vel_eye_pan = value;
|
528 |
544 |
float left = last_vel_eye_pan + last_vel_eye_vergence/2.0;
|
529 |
545 |
float right = last_vel_eye_pan - last_vel_eye_vergence/2.0;
|
... | ... | |
534 |
550 |
break;
|
535 |
551 |
}
|
536 |
552 |
|
537 |
|
case(5): { //vergence
|
|
553 |
case(ICUB_ID_EYES_VERGENCE): { //vergence
|
538 |
554 |
last_vel_eye_pan = value;
|
539 |
555 |
float left = last_vel_eye_pan + last_vel_eye_vergence/2.0;
|
540 |
556 |
float right = last_vel_eye_pan - last_vel_eye_vergence/2.0;
|
... | ... | |
545 |
561 |
break;
|
546 |
562 |
}
|
547 |
563 |
}
|
548 |
|
/*
|
549 |
|
JointInterface::store_incoming_speed(ID_LIP_LEFT_UPPER, 0.0, timestamp);
|
550 |
|
JointInterface::store_incoming_speed(ID_LIP_LEFT_LOWER, 0.0, timestamp);
|
551 |
|
JointInterface::store_incoming_speed(ID_LIP_CENTER_UPPER, 0.0, timestamp);
|
552 |
|
JointInterface::store_incoming_speed(ID_LIP_CENTER_LOWER, 0.0, timestamp);
|
553 |
|
JointInterface::store_incoming_speed(ID_LIP_RIGHT_UPPER, 0.0, timestamp);
|
554 |
|
JointInterface::store_incoming_speed(ID_LIP_RIGHT_LOWER, 0.0, timestamp);
|
555 |
|
|
556 |
|
JointInterface::store_incoming_speed(ID_EYES_LEFT_LID_LOWER, 0.0, timestamp);
|
557 |
|
JointInterface::store_incoming_speed(ID_EYES_LEFT_LID_UPPER, 0.0, timestamp);
|
558 |
|
JointInterface::store_incoming_speed(ID_EYES_LEFT_BROW, 0.0, timestamp);
|
559 |
|
|
560 |
|
JointInterface::store_incoming_speed(ID_EYES_RIGHT_LID_LOWER, 0.0, timestamp);
|
561 |
|
JointInterface::store_incoming_speed(ID_EYES_RIGHT_LID_UPPER,0.0, timestamp);
|
562 |
|
JointInterface::store_incoming_speed(ID_EYES_RIGHT_BROW, 0.0, timestamp);*/
|
563 |
|
/*
|
564 |
|
//fetch enum id:
|
565 |
|
int e = convert_motorid_to_enum(device->get_device_id());
|
566 |
|
if (e == -1){
|
567 |
|
return; //we are not interested in that data, so we just return here
|
568 |
|
}
|
|
564 |
}
|
569 |
565 |
|
570 |
|
JointInterface::store_incoming_speed(e, device->get_register(XSC3_REGISTER_MOTORSPEED), timestamp);*/
|
|
566 |
void iCubJointInterface::set_joint_enable_state(int e, bool enable) {
|
|
567 |
int icub_jointid = -1;
|
571 |
568 |
|
572 |
|
}
|
573 |
|
/*
|
574 |
|
//! conversion table for humotion motor ids to our ids:
|
575 |
|
//! \param enum from JointInterface::JOINT_ID_ENUM
|
576 |
|
//! \return int value of motor id
|
577 |
|
int HumotionJointInterface::convert_enum_to_motorid(int e){
|
578 |
|
enum_id_bimap_t::right_const_iterator it = enum_id_bimap.right.find(e);
|
579 |
|
if(it == enum_id_bimap.right.end()) {
|
580 |
|
//key does not exists, we are not interested in that dataset, return -1
|
581 |
|
return -1;
|
582 |
|
}
|
|
569 |
switch(e){
|
|
570 |
default:
|
|
571 |
break;
|
583 |
572 |
|
584 |
|
return it->second;
|
585 |
|
}
|
|
573 |
case(ID_NECK_PAN):
|
|
574 |
icub_jointid = ICUB_ID_NECK_PAN;
|
|
575 |
break;
|
586 |
576 |
|
|
577 |
case(ID_NECK_TILT):
|
|
578 |
icub_jointid = ICUB_ID_NECK_TILT;
|
|
579 |
break;
|
587 |
580 |
|
588 |
|
//! conversion table for our ids to humotion motor ids:
|
589 |
|
//! \param int value of motor id
|
590 |
|
//! \return enum from JointInterface::JOINT_ID_ENUM
|
591 |
|
int HumotionJointInterface::convert_motorid_to_enum(int id){
|
592 |
|
enum_id_bimap_t::left_const_iterator it = enum_id_bimap.left.find(id);
|
593 |
|
if(it == enum_id_bimap.left.end()) {
|
594 |
|
//key does not exists, we are not interested in that dataset, return -1
|
595 |
|
return -1;
|
|
581 |
case(ID_NECK_ROLL):
|
|
582 |
icub_jointid = ICUB_ID_NECK_ROLL;
|
|
583 |
break;
|
|
584 |
|
|
585 |
case(ID_EYES_BOTH_UD):
|
|
586 |
icub_jointid = ICUB_ID_EYES_BOTH_UD;
|
|
587 |
break;
|
|
588 |
|
|
589 |
// icub handles eyes as pan angle + vergence...
|
|
590 |
// -> hack: left eye enables pan and right eye enables vergence
|
|
591 |
case(ID_EYES_LEFT_LR):
|
|
592 |
icub_jointid = ICUB_ID_EYES_PAN;
|
|
593 |
break;
|
|
594 |
|
|
595 |
case(ID_EYES_RIGHT_LR):
|
|
596 |
icub_jointid = ICUB_ID_EYES_VERGENCE;
|
|
597 |
break;
|
596 |
598 |
}
|
597 |
599 |
|
598 |
|
return it->second;
|
|
600 |
if (icub_jointid != -1) {
|
|
601 |
if (enable) {
|
|
602 |
amp->enableAmp(icub_jointid);
|
|
603 |
pid->enablePid(icub_jointid);
|
|
604 |
} else {
|
|
605 |
pid->disablePid(icub_jointid);
|
|
606 |
amp->disableAmp(icub_jointid);
|
|
607 |
}
|
|
608 |
}
|
599 |
609 |
}
|
600 |
|
*/
|
601 |
610 |
|
602 |
611 |
//! prepare and enable a joint
|
603 |
612 |
//! NOTE: this should also prefill the min/max positions for this joint
|
604 |
613 |
//! \param the enum id of a joint
|
605 |
614 |
void iCubJointInterface::enable_joint(int e){
|
606 |
|
//FIXME ADD THIS:
|
607 |
|
// enable the amplifier and the pid controller on each joint
|
608 |
|
/*for (i = 0; i < nj; i++) {
|
609 |
|
amp->enableAmp(i);
|
610 |
|
pid->enablePid(i);
|
611 |
|
}*/
|
612 |
|
|
613 |
|
|
614 |
|
//set up smooth motion controller
|
615 |
|
//step1: set up framerate
|
616 |
|
//dev->set_register_blocking(XSC3_REGISTER_PID_RAMP, framerate, true);
|
617 |
|
|
618 |
|
//step2: set controllertype:
|
619 |
|
//printf("> activating smooth motion control for joint id 0x%02X (%s)\n", motor_id, joint_name.c_str());
|
620 |
|
//dev->set_register_blocking(XSC3_REGISTER_PID_CONTROLLER, XSC3_PROTOCOL_PID_CONTROLLERTYPE_SMOOTH_PLAYBACK, true);
|
621 |
|
|
622 |
|
//step3: set pid controller:
|
623 |
|
/*if ((e == ID_LIP_LEFT_UPPER) || (e == ID_LIP_LEFT_LOWER) || (e == ID_LIP_CENTER_UPPER) || (e == ID_LIP_CENTER_LOWER) || (e == ID_LIP_RIGHT_UPPER) || (e == ID_LIP_RIGHT_LOWER)){
|
624 |
|
printf("> fixing PID i controller value for smooth motion (FIXME: restore old value!!)\n");
|
625 |
|
dev->set_register_blocking(XSC3_REGISTER_CONST_I, 10, true);
|
626 |
|
}*/
|
627 |
|
|
628 |
|
//uint16_t result = dev->get_register_blocking_raw(XSC3_REGISTER_PID_CONTROLLER);
|
629 |
|
|
630 |
|
//check if setting pid controllertype was successfull:
|
631 |
|
/*if (result != XSC3_PROTOCOL_PID_CONTROLLERTYPE_SMOOTH_PLAYBACK){
|
632 |
|
printf("> failed to set smooth motion controller for joint %s (res=0x%04X)\n",joint_name.c_str(),result);
|
633 |
|
exit(1);
|
634 |
|
}*/
|
635 |
|
|
636 |
|
//fetch min/max:
|
637 |
|
// init_joint(e);
|
638 |
|
|
639 |
|
//ok fine, now enable motor:
|
640 |
|
//printf("> enabling motor %s\n", joint_name.c_str());
|
641 |
|
//dev->set_register_blocking(XSC3_REGISTER_STATUS, XSC3_PROTOCOL_STATUS_BITMASK_MOTOR_ENABLE, true);
|
|
615 |
set_joint_enable_state(e, true);
|
|
616 |
}
|
642 |
617 |
|
|
618 |
//! shutdown and disable a joint
|
|
619 |
//! \param the enum id of a joint
|
|
620 |
void iCubJointInterface::disable_joint(int e){
|
|
621 |
set_joint_enable_state(e, false);
|
643 |
622 |
}
|
644 |
623 |
|
645 |
624 |
void iCubJointInterface::store_min_max(IControlLimits *ilimits, int id, int e){
|
... | ... | |
652 |
631 |
//! initialise a joint (set up controller mode etc)
|
653 |
632 |
//! \param joint enum
|
654 |
633 |
void iCubJointInterface::init_joints(){
|
655 |
|
store_min_max(ilimits, 0, ID_NECK_TILT);
|
656 |
|
store_min_max(ilimits, 1, ID_NECK_ROLL);
|
657 |
|
store_min_max(ilimits, 2, ID_NECK_PAN);
|
658 |
|
store_min_max(ilimits, 3, ID_EYES_BOTH_UD);
|
|
634 |
store_min_max(ilimits, ICUB_ID_NECK_TILT, ID_NECK_TILT);
|
|
635 |
store_min_max(ilimits, ICUB_ID_NECK_ROLL, ID_NECK_ROLL);
|
|
636 |
store_min_max(ilimits, ICUB_ID_NECK_PAN, ID_NECK_PAN);
|
|
637 |
store_min_max(ilimits, ICUB_ID_EYES_BOTH_UD, ID_EYES_BOTH_UD);
|
659 |
638 |
|
660 |
639 |
//icub handles eyes differently, we have to set pan angle + vergence
|
661 |
640 |
double pan_min, pan_max, vergence_min, vergence_max;
|
662 |
|
ilimits->getLimits(4, &pan_min, &pan_max);
|
663 |
|
ilimits->getLimits(5, &vergence_min, &vergence_max);
|
|
641 |
ilimits->getLimits(ICUB_ID_EYES_PAN, &pan_min, &pan_max);
|
|
642 |
ilimits->getLimits(ICUB_ID_EYES_VERGENCE, &vergence_min, &vergence_max);
|
664 |
643 |
|
665 |
644 |
//this is not 100% correct, should be fixed:
|
666 |
645 |
joint_min[ID_EYES_LEFT_LR] = pan_min; // - vergence_max/2;
|
... | ... | |
695 |
674 |
|
696 |
675 |
|
697 |
676 |
}
|
698 |
|
|
699 |
|
//! shutdown and disable a joint
|
700 |
|
//! \param the enum id of a joint
|
701 |
|
void iCubJointInterface::disable_joint(int e){
|
702 |
|
/*
|
703 |
|
//first: convert humotion enum to our enum:
|
704 |
|
int motor_id = convert_enum_to_motorid(e);
|
705 |
|
if (motor_id == -1){
|
706 |
|
return; //we are not interested in that data, so we just return here
|
707 |
|
}
|
708 |
|
|
709 |
|
//fetch device:
|
710 |
|
Device *dev = get_device(motor_id);
|
711 |
|
printf("> FIXME: ADD DISABLE CODE\n");
|
712 |
|
printf("> FIXME: ADD DISABLE CODE\n");
|
713 |
|
printf("> FIXME: ADD DISABLE CODE\n");
|
714 |
|
printf("> FIXME: ADD DISABLE CODE\n");
|
715 |
|
printf("> FIXME: ADD DISABLE CODE\n");
|
716 |
|
printf("> FIXME: ADD DISABLE CODE\n");
|
717 |
|
printf("> FIXME: ADD DISABLE CODE\n");
|
718 |
|
printf("> FIXME: ADD DISABLE CODE\n");
|
719 |
|
printf("> FIXME: ADD DISABLE CODE\n");
|
720 |
|
*/
|
721 |
|
}
|