00001
00002
00003
00004
00012 #include "../include/GazeboTaskboard.h"
00013 #include <boost/bind.hpp>
00014 #include <stdio.h>
00015 #include <math.h>
00016 #include <common/Events.hh>
00017 #include <std_msgs/String.h>
00018 #include <math/Angle.hh>
00019 #include <math/Pose.hh>
00020 #include <msgs/MessageTypes.hh>
00021
00022 using namespace gazebo;
00023 using namespace gazebo_taskboard;
00024
00026 const double POWER_COVER_JOINT_THRESHOLD = M_PI/4;
00027
00029 const std::string LED_MATERIAL_OFF = "Gazebo/Grey";
00031 const std::string LED_MATERIAL_GREEN = "Gazebo/GreenGlow";
00033 const std::string LED_MATERIAL_BLUE = "Gazebo/BlueGlow";
00034
00036 const double SIMPLE_LED_LENGTH = 0.0004;
00038 const double SIMPLE_LED_RADIUS = 0.003;
00040 const double NUMPAD_LED_LENGTH = 0.0004;
00042 const double NUMPAD_LED_RADIUS = 0.0095;
00043
00045 const double LED_HIDE_OFFSET = 100.0;
00047 const double LED_HIDE_OFFSET2 = 105.0;
00048
00050 const double SAFE_TOGGLE_UPPER_LIMIT_ANGLE = 0.0;
00052 const double SAFE_TOGGLE_LOWER_LIMIT_ANGLE = -0.94;
00054 const double SAFE_TOGGLE_MIDDLE_LIMIT_ANGLE = -0.47;
00056 const double SAFE_TOGGLE_HALF_ANGLE = 0.47;
00057
00059 const math::Vector3 ZERO_VECTOR = math::Vector3(0, 0, 0);
00060
00062 enum LedColor
00063 {
00064 eLedColor_Green,
00065 eLedColor_Blue
00066 };
00067
00077 struct GazeboTaskboardSlot1::Led
00078 {
00080 bool isOn;
00081
00082
00083
00085 physics::ModelPtr onModel;
00087 physics::ModelPtr offModel;
00088
00089
00091 std::string onModelName;
00093 std::string offModelName;
00095 std::string onLinkName;
00097 std::string offLinkName;
00098
00099
00100
00102 int index;
00104 bool numPadLed;
00106 LedColor color;
00108 math::Pose pose;
00109
00111 Led();
00113 Led(int index_, bool numPadLed_, LedColor color_, math::Pose pose_);
00115 void CreateModel(physics::WorldPtr world);
00117 void SetupModel(physics::WorldPtr world);
00118 };
00119
00128 struct GazeboTaskboardSlot1::TaskboardLeds
00129 {
00131 Led powerSwitchLed;
00133 Led rockerSwitchUpLed;
00135 Led rockerSwitchDownLed;
00137 Led numPadLeds[NUM_PAD_BUTTONS_COUNT];
00139 Led toggleA03Led;
00141 Led toggleA04TopLed;
00143 Led toggleA04BottomLed;
00145 Led toggleA05Led;
00146
00148 TaskboardLeds(const math::Pose& pose);
00149
00151 void CreateModels(physics::WorldPtr world);
00152
00154 void SetupModels(physics::WorldPtr world);
00155 };
00156
00163 struct GazeboTaskboardSlot1::TaskboardSlot1State
00164 {
00166 bool isCoverOpen;
00167
00169 TwoWayToggleSwitchState powerSwitchState;
00170
00172 ThreeWayToggleSwitchState rockerSwitchA01State;
00173
00175 bool numPadButtonsSelectedState[NUM_PAD_BUTTONS_COUNT];
00176
00178 bool isSafeToggleOut[SAFE_TOGGLES_COUNT];
00179
00182 TwoWayToggleSwitchState toggleA03State;
00183
00186 ThreeWayToggleSwitchState toggleA04State;
00187
00190 TwoWayToggleSwitchState toggleA05State;
00191
00195 TaskboardSlot1State()
00196 {
00197 for (int i = 0; i < NUM_PAD_BUTTONS_COUNT; i++)
00198 {
00199 numPadButtonsSelectedState[i] = false;
00200 }
00201 for (int i = 0; i < SAFE_TOGGLES_COUNT; i++)
00202 {
00203 isSafeToggleOut[i] = false;
00204 }
00205 isCoverOpen = false;
00206 powerSwitchState = eTwoWayState_Down;
00207 rockerSwitchA01State = eThreeWayState_Center;
00208 toggleA03State = eTwoWayState_Down;
00209 toggleA04State = eThreeWayState_Center;
00210 toggleA05State = eTwoWayState_Down;
00211 }
00212 };
00213
00220 struct BaseManipulationState
00221 {
00223 double startTime;
00225 double duration;
00226
00228 BaseManipulationState()
00229 : startTime(0.0)
00230 , duration(0.0)
00231 {}
00232 };
00234 struct PowerCoverManipulationState : BaseManipulationState
00235 {
00237 math::Vector3 angularVelocity;
00238 };
00240 struct PowerSwitchManipulationState : BaseManipulationState
00241 {
00243 math::Vector3 angularVelocity;
00244 };
00246 struct RockerSwitchManipulationState : BaseManipulationState
00247 {
00249 math::Vector3 torque;
00250 };
00252 struct NumPadButtonManipulationState : BaseManipulationState
00253 {
00255 math::Vector3 force;
00256 };
00258 struct SafeToggleManipulationState : BaseManipulationState
00259 {
00261 double value;
00262
00264 SafeToggleManipulationState()
00265 : value(0.0)
00266 {}
00267 };
00268
00280 struct GazeboTaskboardSlot1::ManipulationState
00281 {
00283 PowerCoverManipulationState powerCover;
00285 PowerSwitchManipulationState powerSwitch;
00287 RockerSwitchManipulationState rockerSwitch;
00289 NumPadButtonManipulationState numPadButtons[NUM_PAD_BUTTONS_COUNT];
00291 SafeToggleManipulationState safeToggles[SAFE_TOGGLES_COUNT][2];
00292 };
00293
00300 inline double deg2rad(double degrees)
00301 {
00302 return M_PI / 180.0 * degrees;
00303 }
00304
00305
00309 GazeboTaskboardSlot1::GazeboTaskboardSlot1()
00310 : firstFrameInitializationDone(false)
00311 , ledsReady(false)
00312 , node("taskboard")
00313 {}
00314
00320 GazeboTaskboardSlot1::~GazeboTaskboardSlot1()
00321 {
00322 if (updateConnection)
00323 {
00324 event::Events::DisconnectWorldUpdateStart(updateConnection);
00325 updateConnection.reset();
00326 }
00327 }
00328
00335 void GazeboTaskboardSlot1::Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf)
00336 {
00337 model = _parent;
00338 if (!model)
00339 {
00340 ROS_FATAL("No model is provided for GazeboTaskboard model plugin");
00341 return;
00342 }
00343
00344 if (!InitLinks() || !InitJoints())
00345 {
00346 return;
00347 }
00348
00349
00350 updateConnection = event::Events::ConnectWorldUpdateStart(
00351 boost::bind(&GazeboTaskboardSlot1::OnUpdate, this));
00352
00353
00354 srv_manipulatePowerCover = node.advertiseService("manipulate_power_cover",
00355 &GazeboTaskboardSlot1::ManipulatePowerCover, this);
00356 srv_manipulatePowerSwitch = node.advertiseService("manipulate_power_switch",
00357 &GazeboTaskboardSlot1::ManipulatePowerSwitch, this);
00358 srv_manipulateRockerSwitch = node.advertiseService("manipulate_rocker_switch_a01",
00359 &GazeboTaskboardSlot1::ManipulateRockerSwitch, this);
00360 srv_manipulateNumPad = node.advertiseService("manipulate_numpad",
00361 &GazeboTaskboardSlot1::ManipulateNumPad, this);
00362 srv_manipulateSafeToggle = node.advertiseService("manipulate_safe_toggle",
00363 &GazeboTaskboardSlot1::ManipulateSafeToggle, this);
00364
00365
00366 const int queueSize = 128;
00367 publisher = node.advertise<TaskboardPanelA>("TaskboardPanelA", queueSize);
00368
00369
00370 manipulationState.reset(new ManipulationState);
00371
00372
00373 leds.reset(new TaskboardLeds(model->GetWorldPose()));
00374
00375
00376 state.reset(new TaskboardSlot1State);
00377 DeriveStateFromModel();
00378 }
00379
00390 static physics::LinkPtr getLink(physics::ModelPtr model, const std::string& linkName)
00391 {
00392 physics::LinkPtr link = model->GetLink(linkName);
00393 if (!link)
00394 {
00395 ROS_FATAL("Failed to get %s link from the model", linkName.c_str());
00396 }
00397 return link;
00398 }
00399
00405 bool GazeboTaskboardSlot1::InitLinks()
00406 {
00407 struct
00408 {
00409 physics::LinkPtr& linkRef;
00410 std::string linkName;
00411 } linksInfo[] =
00412 {
00413 { linkPowerCover , "taskboard_slot1_switch1_cover" },
00414 { linkPowerSwitch , "taskboard_slot1_switch1" },
00415 { linkA01Switch , "taskboard_slot1_switch" },
00416 { linksNumPad[0] , "taskboard_slot1_A1" },
00417 { linksNumPad[1] , "taskboard_slot1_A2" },
00418 { linksNumPad[2] , "taskboard_slot1_A3" },
00419 { linksNumPad[3] , "taskboard_slot1_B1" },
00420 { linksNumPad[4] , "taskboard_slot1_B2" },
00421 { linksNumPad[5] , "taskboard_slot1_B3" },
00422 { linksNumPad[6] , "taskboard_slot1_C1" },
00423 { linksNumPad[7] , "taskboard_slot1_C2" },
00424 { linksNumPad[8] , "taskboard_slot1_C3" },
00425 { linksBaseSafeToggle[0], "taskboard_slot1_switch2_pullout" },
00426 { linksBaseSafeToggle[1], "taskboard_slot1_switch3_pullout" },
00427 { linksBaseSafeToggle[2], "taskboard_slot1_switch4_pullout" },
00428 { linksSafeToggle[0] , "taskboard_slot1_switch2" },
00429 { linksSafeToggle[1] , "taskboard_slot1_switch3" },
00430 { linksSafeToggle[2] , "taskboard_slot1_switch4" }
00431 };
00432 const int numLinks = sizeof(linksInfo) / sizeof(linksInfo[0]);
00433 for (int i = 0; i < numLinks; i++)
00434 {
00435 linksInfo[i].linkRef = getLink(model, linksInfo[i].linkName);
00436 if (!linksInfo[i].linkRef)
00437 {
00438 return false;
00439 }
00440 }
00441 return true;
00442 }
00443
00454 static physics::JointPtr getJoint(physics::ModelPtr model, const std::string& jointName)
00455 {
00456 physics::JointPtr joint = model->GetJoint(jointName);
00457 if (!joint)
00458 {
00459 ROS_FATAL("Failed to get %s joint from the model", jointName.c_str());
00460 }
00461 return joint;
00462 }
00463
00469 bool GazeboTaskboardSlot1::InitJoints()
00470 {
00471 struct
00472 {
00473 physics::JointPtr& jointRef;
00474 std::string jointName;
00475 } jointsInfo[] =
00476 {
00477 { safeTogglesRevoluteJoints[0] , "taskboard_lower/taskboard_slot1_switch2" },
00478 { safeTogglesRevoluteJoints[1] , "taskboard_lower/taskboard_slot1_switch3" },
00479 { safeTogglesRevoluteJoints[2] , "taskboard_lower/taskboard_slot1_switch4" }
00480 };
00481 const int numJoints = sizeof(jointsInfo) / sizeof(jointsInfo[0]);
00482 for (int i = 0; i < numJoints; i++)
00483 {
00484 jointsInfo[i].jointRef = getJoint(model, jointsInfo[i].jointName);
00485 if (!jointsInfo[i].jointRef)
00486 {
00487 return false;
00488 }
00489 }
00490 return true;
00491 }
00492
00500 void GazeboTaskboardSlot1::DeriveStateFromModel()
00501 {
00502
00503 math::Pose pose = linkPowerCover->GetRelativePose();
00504 double angle = pose.rot.GetRoll();
00505 state->isCoverOpen = (angle < POWER_COVER_JOINT_THRESHOLD);
00506
00507
00508
00509 pose = linkPowerSwitch->GetRelativePose();
00510 angle = pose.rot.GetRoll();
00511 state->powerSwitchState = (angle < M_PI_2) ? eTwoWayState_Up : eTwoWayState_Down;
00512
00513
00514 pose = linksSafeToggle[0]->GetRelativePose();
00515 angle = pose.rot.GetRoll();
00516 state->toggleA03State = (angle < M_PI_2) ? eTwoWayState_Up : eTwoWayState_Down;
00517
00518
00519 pose = linksSafeToggle[1]->GetRelativePose();
00520 angle = pose.rot.GetRoll();
00521 if (angle < M_PI_2 - SAFE_TOGGLE_HALF_ANGLE/2)
00522 {
00523 state->toggleA04State = eThreeWayState_Up;
00524 }
00525 else if (angle < M_PI_2 + SAFE_TOGGLE_HALF_ANGLE/2)
00526 {
00527 state->toggleA04State = eThreeWayState_Center;
00528 }
00529 else
00530 {
00531 state->toggleA04State = eThreeWayState_Down;
00532 }
00533
00534
00535 pose = linksSafeToggle[2]->GetRelativePose();
00536 angle = pose.rot.GetRoll();
00537 state->toggleA05State = (angle < M_PI_2) ? eTwoWayState_Up : eTwoWayState_Down;
00538 }
00539
00546 void GazeboTaskboardSlot1::OnUpdate()
00547 {
00548
00549
00550 if (firstFrameInitializationDone && !ledsReady)
00551 {
00552 leds->SetupModels(model->GetWorld());
00553 TurnOnLeds();
00554 ledsReady = true;
00555 return;
00556 }
00557
00558
00559 if (!firstFrameInitializationDone)
00560 {
00561 leds->CreateModels(model->GetWorld());
00562 firstFrameInitializationDone = true;
00563 return;
00564 }
00565
00566
00567 MonitorPowerCoverStateChanges();
00568 MonitorPowerSwitchStateChanges();
00569 MonitorRockerSwitchA01StateChanges();
00570 MonitorNumpadStateChanges();
00571 MonitorSafeTogglesStateChanges();
00572
00573
00574 HandleManipulation();
00575
00576
00577 ros::spinOnce();
00578 }
00579
00583 void GazeboTaskboardSlot1::MonitorPowerCoverStateChanges()
00584 {
00585 math::Pose pose = linkPowerCover->GetRelativePose();
00586 const double angle = pose.rot.GetRoll();
00587 const double threshold = deg2rad(1.0);
00588
00589 if (angle > threshold && angle < M_PI_2 - threshold)
00590 {
00591 math::Vector3 torque = computeEmpiricalTorque(angle - POWER_COVER_JOINT_THRESHOLD, 1.0, 1.0, 1.5, 15);
00592 linkPowerCover->SetTorque(torque);
00593 }
00594 else if (angle <= threshold)
00595 {
00596 if (!state->isCoverOpen)
00597 {
00598 state->isCoverOpen = true;
00599 PublishState();
00600
00601 linkPowerCover->SetAngularVel(ZERO_VECTOR);
00602 linkPowerCover->SetTorque(ZERO_VECTOR);
00603 }
00604 }
00605 else if (angle >= M_PI_2 - threshold)
00606 {
00607 if (state->isCoverOpen)
00608 {
00609 state->isCoverOpen = false;
00610 PublishState();
00611
00612 linkPowerCover->SetAngularVel(ZERO_VECTOR);
00613 linkPowerCover->SetTorque(ZERO_VECTOR);
00614 }
00615 }
00616 }
00617
00621 void GazeboTaskboardSlot1::MonitorPowerSwitchStateChanges()
00622 {
00623 const double halfAngle = 0.419;
00624 const double upDirLimit = M_PI/2 - halfAngle;
00625 const double downDirLimit = M_PI/2 + halfAngle;
00626 const double threshold = deg2rad(1.0);
00627
00628 math::Pose pose = linkPowerSwitch->GetRelativePose();
00629 const double angle = pose.rot.GetRoll();
00630
00631 if (angle > upDirLimit + threshold && angle < downDirLimit - threshold)
00632 {
00633 math::Vector3 torque = computeEmpiricalTorque(angle - M_PI_2, 1.0, 1.0, 1.3, 20);
00634 linkPowerSwitch->SetTorque(torque);
00635 }
00636 else if (angle <= upDirLimit + threshold)
00637 {
00638 if (state->powerSwitchState == eTwoWayState_Down)
00639 {
00640 state->powerSwitchState = eTwoWayState_Up;
00641 TurnOnLeds();
00642 PublishState();
00643
00644 linkPowerSwitch->SetAngularVel(ZERO_VECTOR);
00645 linkPowerSwitch->SetTorque(ZERO_VECTOR);
00646 }
00647 }
00648 else if (angle >= downDirLimit - threshold)
00649 {
00650 if (state->powerSwitchState == eTwoWayState_Up)
00651 {
00652 state->powerSwitchState = eTwoWayState_Down;
00653 TurnOffAllLeds();
00654 PublishState();
00655
00656 linkPowerSwitch->SetAngularVel(ZERO_VECTOR);
00657 linkPowerSwitch->SetTorque(ZERO_VECTOR);
00658 }
00659 }
00660 }
00661
00665 void GazeboTaskboardSlot1::MonitorRockerSwitchA01StateChanges()
00666 {
00667 const double halfAngle = 0.5;
00668 const double upStateLimit = M_PI_2 - halfAngle;
00669 const double downStateLimit = M_PI_2 + halfAngle;
00670 const double threshold = deg2rad(2.0);
00671
00672 math::Pose pose = linkA01Switch->GetRelativePose();
00673 double angle = pose.rot.GetRoll();
00674
00675 if (angle < M_PI_2 - threshold || angle > M_PI_2 + threshold)
00676 {
00677
00678 const double sign = (angle < M_PI_2) ? 1.0 : -1.0;
00679 const double deviationAngle = sign * std::max(halfAngle - fabs(angle - M_PI_2), 0.0);
00680 math::Vector3 torque = computeEmpiricalTorque(deviationAngle, 8.5, 4.0, 2.5, 7);
00681 linkA01Switch->SetTorque(torque);
00682
00683
00684 if (state->rockerSwitchA01State == eThreeWayState_Center)
00685 {
00686 if (angle < upStateLimit + threshold)
00687 {
00688 state->rockerSwitchA01State = eThreeWayState_Up;
00689 SetLedState(leds->rockerSwitchUpLed, true);
00690 PublishState();
00691 }
00692 else if (angle > downStateLimit - threshold)
00693 {
00694 state->rockerSwitchA01State = eThreeWayState_Down;
00695 SetLedState(leds->rockerSwitchDownLed, true);
00696 PublishState();
00697 }
00698 }
00699 }
00700 else
00701 {
00702
00703 if (state->rockerSwitchA01State != eThreeWayState_Center)
00704 {
00705 if (leds->rockerSwitchUpLed.isOn)
00706 {
00707 SetLedState(leds->rockerSwitchUpLed, false);
00708 }
00709 else if (leds->rockerSwitchDownLed.isOn)
00710 {
00711 SetLedState(leds->rockerSwitchDownLed, false);
00712 }
00713 linkA01Switch->SetAngularVel(ZERO_VECTOR);
00714 state->rockerSwitchA01State = eThreeWayState_Center;
00715 PublishState();
00716 }
00717 }
00718 }
00719
00723 void GazeboTaskboardSlot1::MonitorNumpadStateChanges()
00724 {
00725 const double selRelOffset = -0.4811;
00726 const double epsilon = 0.0003;
00727
00728
00729
00730 for (int i = 0; i < NUM_PAD_BUTTONS_COUNT; i++)
00731 {
00732 linksNumPad[i]->SetForce(ZERO_VECTOR);
00733 linksNumPad[i]->AddRelativeForce(math::Vector3(0, 0, 5));
00734 }
00735
00736 for (int i = 0; i < NUM_PAD_BUTTONS_COUNT; i++)
00737 {
00738 const double offset = linksNumPad[i]->GetRelativePose().pos.y;
00739
00740 bool selected = (offset < selRelOffset + epsilon);
00741 if (selected ^ state->numPadButtonsSelectedState[i])
00742 {
00743 state->numPadButtonsSelectedState[i] = selected;
00744 if (selected)
00745 {
00746 SetLedState(leds->numPadLeds[i], !leds->numPadLeds[i].isOn);
00747 }
00748 PublishState();
00749 }
00750 }
00751 }
00752
00763 bool GazeboTaskboardSlot1::UpdateTransitionFromOutState2Way(
00764 physics::LinkPtr link, physics::JointPtr joint, TwoWayToggleSwitchState& state) const
00765 {
00766 const double halfAngle = 0.47;
00767 const double threshold = deg2rad(1.0);
00768 const double upDirLimit = M_PI_2 - halfAngle;
00769 const double downDirLimit = M_PI_2 + halfAngle;
00770
00771 math::Pose pose = link->GetRelativePose();
00772 const double angle = pose.rot.GetRoll();
00773
00774 if (angle > upDirLimit + threshold && angle < downDirLimit - threshold)
00775 {
00776 math::Vector3 torque = computeEmpiricalTorque(angle - M_PI_2, 0.8, 1.0, 1.5, 15);
00777 link->SetTorque(torque);
00778 return false;
00779 }
00780 if (angle <= upDirLimit + threshold)
00781 {
00782 state = eTwoWayState_Up;
00783
00784 joint->SetHighStop(0, math::Angle(SAFE_TOGGLE_LOWER_LIMIT_ANGLE + threshold));
00785 joint->SetLowStop(0, math::Angle(SAFE_TOGGLE_LOWER_LIMIT_ANGLE - threshold));
00786 }
00787 else
00788 {
00789 state = eTwoWayState_Down;
00790
00791 joint->SetHighStop(0, math::Angle(SAFE_TOGGLE_UPPER_LIMIT_ANGLE + threshold));
00792 joint->SetLowStop(0, math::Angle(SAFE_TOGGLE_UPPER_LIMIT_ANGLE - threshold));
00793 }
00794 return true;
00795 }
00796
00807 bool GazeboTaskboardSlot1::UpdateTransitionFromOutState3Way(
00808 physics::LinkPtr link, physics::JointPtr joint, ThreeWayToggleSwitchState& state) const
00809 {
00810 const double halfAngle = 0.47;
00811 const double upDirLimit = M_PI/2 - halfAngle;
00812 const double downDirLimit = M_PI/2 + halfAngle;
00813 const double threshold = deg2rad(1.0);
00814
00815 math::Pose pose = link->GetRelativePose();
00816 double angle = pose.rot.GetRoll();
00817
00818 if (angle > upDirLimit + threshold && angle < M_PI_2 - threshold)
00819 {
00820 math::Vector3 torque = computeEmpiricalTorque(angle - (M_PI_2 - halfAngle/2), 0.8, 1.0, 1.5, 15);
00821 link->SetTorque(torque);
00822 return false;
00823 }
00824 else if (angle > M_PI_2 + threshold && angle < downDirLimit - threshold)
00825 {
00826 math::Vector3 torque = computeEmpiricalTorque(angle - (M_PI_2 + halfAngle/2), 0.8, 1.0, 1.5, 15);
00827 link->SetTorque(torque);
00828 return false;
00829 }
00830 if (angle <= upDirLimit + threshold)
00831 {
00832 state = eThreeWayState_Up;
00833
00834 joint->SetHighStop(0, math::Angle(SAFE_TOGGLE_LOWER_LIMIT_ANGLE + threshold));
00835 joint->SetLowStop(0, math::Angle(SAFE_TOGGLE_LOWER_LIMIT_ANGLE - threshold));
00836 link->SetTorque(ZERO_VECTOR);
00837 }
00838 else if (angle >= downDirLimit - threshold)
00839 {
00840 state = eThreeWayState_Down;
00841
00842 joint->SetHighStop(0, math::Angle(SAFE_TOGGLE_UPPER_LIMIT_ANGLE + threshold));
00843 joint->SetLowStop(0, math::Angle(SAFE_TOGGLE_UPPER_LIMIT_ANGLE - threshold));
00844 link->SetTorque(ZERO_VECTOR);
00845 }
00846 else
00847 {
00848 state = eThreeWayState_Center;
00849
00850 joint->SetHighStop(0, math::Angle(SAFE_TOGGLE_MIDDLE_LIMIT_ANGLE + threshold));
00851 joint->SetLowStop(0, math::Angle(SAFE_TOGGLE_MIDDLE_LIMIT_ANGLE - threshold));
00852 link->SetTorque(ZERO_VECTOR);
00853 }
00854 return true;
00855 }
00856
00860 void GazeboTaskboardSlot1::MonitorSafeTogglesStateChanges()
00861 {
00862
00863 const double pullOutDistance = 0.002;
00864
00865 const double delta = 0.0004;
00866
00867
00868 bool isOut[SAFE_TOGGLES_COUNT];
00869 float offsets[SAFE_TOGGLES_COUNT];
00870 for (int i = 0; i < SAFE_TOGGLES_COUNT; i++)
00871 {
00872 const math::Pose outPose = linksBaseSafeToggle[i]->GetRelativePose();
00873 const math::Pose pose = linksSafeToggle[i]->GetRelativePose();
00874 offsets[i] = std::max(pullOutDistance - outPose.CoordPositionSub(pose).z, 0.0);
00875 isOut[i] = (offsets[i] > pullOutDistance - delta);
00876 }
00877
00878 for (int i = 0; i < SAFE_TOGGLES_COUNT; i++)
00879 {
00880 if (!state->isSafeToggleOut[i] && isOut[i])
00881 {
00882 state->isSafeToggleOut[i] = true;
00883
00884
00885 safeTogglesRevoluteJoints[i]->SetHighStop(0, math::Angle(SAFE_TOGGLE_UPPER_LIMIT_ANGLE));
00886 safeTogglesRevoluteJoints[i]->SetLowStop(0, math::Angle(SAFE_TOGGLE_LOWER_LIMIT_ANGLE));
00887
00888
00889 switch (i)
00890 {
00891 case 0:
00892 SetLedState(leds->toggleA03Led, false);
00893 break;
00894 case 1:
00895 SetLedState(leds->toggleA04TopLed, false);
00896 SetLedState(leds->toggleA04BottomLed, false);
00897 break;
00898 case 2:
00899 SetLedState(leds->toggleA05Led, false);
00900 break;
00901 }
00902 PublishState();
00903 }
00904 }
00905
00906 if (state->isSafeToggleOut[0] && offsets[0] < pullOutDistance - 2*delta)
00907 {
00908 bool transitionDone = UpdateTransitionFromOutState2Way(
00909 linksSafeToggle[0], safeTogglesRevoluteJoints[0], state->toggleA03State);
00910 if (transitionDone)
00911 {
00912 state->isSafeToggleOut[0] = false;
00913 SetLedState(leds->toggleA03Led, state->toggleA03State == eTwoWayState_Up);
00914 PublishState();
00915 }
00916 }
00917 if (state->isSafeToggleOut[2] && offsets[2] < pullOutDistance - 2*delta)
00918 {
00919 bool transitionDone = UpdateTransitionFromOutState2Way(
00920 linksSafeToggle[2], safeTogglesRevoluteJoints[2], state->toggleA05State);
00921 if (transitionDone)
00922 {
00923 state->isSafeToggleOut[2] = false;
00924 SetLedState(leds->toggleA05Led, state->toggleA05State == eTwoWayState_Up);
00925 PublishState();
00926 }
00927 }
00928
00929 if (state->isSafeToggleOut[1] && offsets[1] < pullOutDistance - 2*delta)
00930 {
00931 bool transitionDone = UpdateTransitionFromOutState3Way(
00932 linksSafeToggle[1], safeTogglesRevoluteJoints[1], state->toggleA04State);
00933 if (transitionDone)
00934 {
00935 state->isSafeToggleOut[1] = false;
00936 SetLedState(leds->toggleA04TopLed, state->toggleA04State == eThreeWayState_Up);
00937 SetLedState(leds->toggleA04BottomLed, state->toggleA04State == eThreeWayState_Down);
00938 PublishState();
00939 }
00940 }
00941
00942 for (int i = 0; i < SAFE_TOGGLES_COUNT; i++)
00943 {
00944 if (state->isSafeToggleOut[i] || offsets[i] > delta)
00945 {
00946 linksSafeToggle[i]->SetForce(ZERO_VECTOR);
00947 linksSafeToggle[i]->AddRelativeForce(math::Vector3(0, 0, -2));
00948 }
00949 else if (offsets[i] <= delta/2)
00950 {
00951 linksSafeToggle[i]->SetForce(ZERO_VECTOR);
00952 linksSafeToggle[i]->SetLinearVel(ZERO_VECTOR);
00953 linksSafeToggle[i]->SetAngularVel(ZERO_VECTOR);
00954 }
00955 }
00956 }
00957
00963 void GazeboTaskboardSlot1::PublishState()
00964 {
00965 const std::string UP = "UP";
00966 const std::string DOWN = "DOWN";
00967 const std::string CENTER = "CENTER";
00968 const std::string ON = "ON";
00969 const std::string OFF = "OFF";
00970 const std::string SEL = "SEL";
00971 const std::string UNSEL = "UNSEL";
00972 const std::string OUT = "OUT";
00973
00974
00975 TaskboardPanelA msg;
00976
00977 msg.PANEL_POWER_COVER = state->isCoverOpen ? UP : DOWN;
00978 msg.PANEL_POWER_SWITCH = state->powerSwitchState == eTwoWayState_Up ? UP : DOWN;
00979 msg.PANEL_POWER_LED = leds->powerSwitchLed.isOn ? ON : OFF;
00980
00981 msg.A01_ROCKER_SWITCH = state->rockerSwitchA01State == eThreeWayState_Center
00982 ? CENTER
00983 : (state->rockerSwitchA01State == eThreeWayState_Up ? UP : DOWN);
00984
00985 msg.A01_ROCKER_LED_TOP = leds->rockerSwitchUpLed.isOn ? ON : OFF;
00986 msg.A01_ROCKER_LED_BOTTOM = leds->rockerSwitchDownLed.isOn ? ON : OFF;
00987
00988 msg.A02_LED_NUM_PAD_A1 = leds->numPadLeds[0].isOn ? ON : OFF;
00989 msg.A02_LED_NUM_PAD_A2 = leds->numPadLeds[1].isOn ? ON : OFF;
00990 msg.A02_LED_NUM_PAD_A3 = leds->numPadLeds[2].isOn ? ON : OFF;
00991 msg.A02_LED_NUM_PAD_B1 = leds->numPadLeds[3].isOn ? ON : OFF;
00992 msg.A02_LED_NUM_PAD_B2 = leds->numPadLeds[4].isOn ? ON : OFF;
00993 msg.A02_LED_NUM_PAD_B3 = leds->numPadLeds[5].isOn ? ON : OFF;
00994 msg.A02_LED_NUM_PAD_C1 = leds->numPadLeds[6].isOn ? ON : OFF;
00995 msg.A02_LED_NUM_PAD_C2 = leds->numPadLeds[7].isOn ? ON : OFF;
00996 msg.A02_LED_NUM_PAD_C3 = leds->numPadLeds[8].isOn ? ON : OFF;
00997
00998 msg.A02_NUM_PAD_A1 = state->numPadButtonsSelectedState[0] ? SEL : UNSEL;
00999 msg.A02_NUM_PAD_A2 = state->numPadButtonsSelectedState[1] ? SEL : UNSEL;
01000 msg.A02_NUM_PAD_A3 = state->numPadButtonsSelectedState[2] ? SEL : UNSEL;
01001 msg.A02_NUM_PAD_B1 = state->numPadButtonsSelectedState[3] ? SEL : UNSEL;
01002 msg.A02_NUM_PAD_B2 = state->numPadButtonsSelectedState[4] ? SEL : UNSEL;
01003 msg.A02_NUM_PAD_B3 = state->numPadButtonsSelectedState[5] ? SEL : UNSEL;
01004 msg.A02_NUM_PAD_C1 = state->numPadButtonsSelectedState[6] ? SEL : UNSEL;
01005 msg.A02_NUM_PAD_C2 = state->numPadButtonsSelectedState[7] ? SEL : UNSEL;
01006 msg.A02_NUM_PAD_C3 = state->numPadButtonsSelectedState[8] ? SEL : UNSEL;
01007
01008 msg.A03_LED = leds->toggleA03Led.isOn ? ON : OFF;
01009 msg.A04_LED_TOP = leds->toggleA04TopLed.isOn ? ON : OFF;
01010 msg.A04_LED_BOTTOM = leds->toggleA04BottomLed.isOn ? ON : OFF;
01011 msg.A05_LED = leds->toggleA05Led.isOn ? ON : OFF;
01012
01013 msg.A03_TOGGLE = state->isSafeToggleOut[0]
01014 ? OUT
01015 : (state->toggleA03State == eTwoWayState_Up ? UP : DOWN);
01016
01017 msg.A04_TOGGLE = state->isSafeToggleOut[1]
01018 ? OUT
01019 : (state->toggleA04State == eThreeWayState_Center
01020 ? CENTER
01021 : (state->toggleA04State == eThreeWayState_Up ? UP : DOWN));
01022
01023 msg.A05_TOGGLE = state->isSafeToggleOut[2]
01024 ? OUT
01025 : (state->toggleA05State == eTwoWayState_Up ? UP : DOWN);
01026
01027
01028 publisher.publish(msg);
01029 }
01030
01037 void GazeboTaskboardSlot1::SetLedState(Led& led, bool on)
01038 {
01039
01040 if (led.isOn == on)
01041 {
01042 return;
01043 }
01044
01045 if (state->powerSwitchState != eTwoWayState_Up && on)
01046 {
01047 return;
01048 }
01049
01050
01051 math::Pose pose = led.onModel->GetRelativePose();
01052 math::Pose pose2 = led.offModel->GetRelativePose();
01053
01054
01055 if (on)
01056 {
01057 pose.pos.z -= LED_HIDE_OFFSET;
01058 pose2.pos.z += LED_HIDE_OFFSET2;
01059 }
01060 else
01061 {
01062 pose.pos.z += LED_HIDE_OFFSET;
01063 pose2.pos.z -= LED_HIDE_OFFSET2;
01064 }
01065 led.onModel->SetLinkWorldPose(pose, led.onLinkName);
01066 led.offModel->SetLinkWorldPose(pose2, led.offLinkName);
01067 led.isOn = on;
01068 }
01069
01073 void GazeboTaskboardSlot1::TurnOnLeds()
01074 {
01075 if (state->powerSwitchState == eTwoWayState_Up)
01076 {
01077
01078 SetLedState(leds->powerSwitchLed, true);
01079
01080
01081 if (state->rockerSwitchA01State == eThreeWayState_Up)
01082 {
01083 SetLedState(leds->rockerSwitchUpLed, true);
01084 }
01085 else if (state->rockerSwitchA01State == eThreeWayState_Down)
01086 {
01087 SetLedState(leds->rockerSwitchDownLed, true);
01088 }
01089
01090 if (state->toggleA03State == eTwoWayState_Up)
01091 {
01092 SetLedState(leds->toggleA03Led, true);
01093 }
01094
01095 if (state->toggleA05State == eTwoWayState_Up)
01096 {
01097 SetLedState(leds->toggleA05Led, true);
01098 }
01099
01100 if (state->toggleA04State == eThreeWayState_Up)
01101 {
01102 SetLedState(leds->toggleA04TopLed, true);
01103 }
01104 else if (state->toggleA04State == eThreeWayState_Down)
01105 {
01106 SetLedState(leds->toggleA04BottomLed, true);
01107 }
01108 }
01109 }
01110
01114 void GazeboTaskboardSlot1::TurnOffAllLeds()
01115 {
01116 SetLedState(leds->powerSwitchLed, false);
01117 SetLedState(leds->rockerSwitchUpLed, false);
01118 SetLedState(leds->rockerSwitchDownLed, false);
01119 SetLedState(leds->toggleA03Led, false);
01120 SetLedState(leds->toggleA05Led, false);
01121 SetLedState(leds->toggleA04TopLed, false);
01122 SetLedState(leds->toggleA04BottomLed, false);
01123
01124 for (int i = 0; i < NUM_PAD_BUTTONS_COUNT; i++)
01125 {
01126 SetLedState(leds->numPadLeds[i], false);
01127 }
01128 }
01129
01130
01131
01132
01143 bool GazeboTaskboardSlot1::ManipulatePowerCover(
01144 ManipulatePowerCover::Request& request, ManipulatePowerCover::Response& response)
01145 {
01146 math::Pose globalPose = model->GetWorldPose();
01147 const double velocity = request.angle / request.duration;
01148
01149 PowerCoverManipulationState &manipState = manipulationState->powerCover;
01150
01151 manipState.duration = request.duration;
01152 manipState.startTime = GetTime();
01153 manipState.angularVelocity = globalPose.rot * math::Vector3(velocity, 0, 0);
01154
01155 linkPowerCover->SetAngularVel(manipState.angularVelocity);
01156 return true;
01157 }
01158
01169 bool GazeboTaskboardSlot1::ManipulatePowerSwitch(
01170 ManipulatePowerSwitch::Request& request, ManipulatePowerSwitch::Response& response)
01171 {
01172 math::Pose globalPose = model->GetWorldPose();
01173 const double velocity = request.angle / request.duration;
01174
01175 PowerSwitchManipulationState &manipState = manipulationState->powerSwitch;
01176
01177 manipState.duration = request.duration;
01178 manipState.startTime = GetTime();
01179 manipState.angularVelocity = globalPose.rot * math::Vector3(velocity, 0, 0);
01180
01181 linkPowerSwitch->SetAngularVel(manipState.angularVelocity);
01182 return true;
01183 }
01184
01195 bool GazeboTaskboardSlot1::ManipulateRockerSwitch(
01196 ManipulateRockerSwitch::Request& request, ManipulateRockerSwitch::Response& response)
01197 {
01198 math::Pose globalPose = model->GetWorldPose();
01199
01200 RockerSwitchManipulationState &manipState = manipulationState->rockerSwitch;
01201
01202 manipState.startTime = GetTime();
01203 manipState.duration = request.duration;
01204 manipState.torque = globalPose.rot * math::Vector3(request.torque, 0, 0);
01205
01206 linkA01Switch->SetTorque(manipState.torque);
01207 return true;
01208 }
01209
01220 bool GazeboTaskboardSlot1::ManipulateNumPad(
01221 ManipulateNumPad::Request& request, ManipulateNumPad::Response& response)
01222 {
01223 if (request.index < 0 || request.index >= NUM_PAD_BUTTONS_COUNT)
01224 {
01225 return false;
01226 }
01227 NumPadButtonManipulationState &manipState = manipulationState->numPadButtons[request.index];
01228
01229 manipState.startTime = GetTime();
01230 manipState.duration = request.duration;
01231 manipState.force = math::Vector3(0, 0, -request.force);
01232
01233 linksNumPad[request.index]->AddRelativeForce(manipState.force);
01234 return true;
01235 }
01236
01248 bool GazeboTaskboardSlot1::ManipulateSafeToggle(
01249 ManipulateSafeToggle::Request& request, ManipulateSafeToggle::Response& response)
01250 {
01251 if (request.index < 0 || request.index >= SAFE_TOGGLES_COUNT)
01252 {
01253 return false;
01254 }
01255 if (request.mode < 0 || request.mode >= 2)
01256 {
01257 return false;
01258 }
01259 SafeToggleManipulationState &manipState = manipulationState->safeToggles[request.index][request.mode];
01260
01261 manipState.startTime = GetTime();
01262 manipState.duration = request.duration;
01263 manipState.value = request.value;
01264
01265 physics::LinkPtr link = linksSafeToggle[request.index];
01266 if (request.mode == 0)
01267 {
01268 link->SetForce(ZERO_VECTOR);
01269 link->AddRelativeForce(math::Vector3(0, 0, manipState.value));
01270 }
01271 else
01272 {
01273 const double velocity = manipState.value / manipState.duration;
01274 math::Pose basePose = model->GetWorldPose();
01275 math::Vector3 angularVelocity = basePose.rot * math::Vector3(velocity, 0, 0);
01276 link->SetAngularVel(angularVelocity);
01277 }
01278 return true;
01279 }
01280
01284 void GazeboTaskboardSlot1::HandleManipulation()
01285 {
01286 const double time = GetTime();
01287
01288 if (manipulationState->powerCover.startTime)
01289 {
01290 const double elapsedTime = time - manipulationState->powerCover.startTime;
01291 if (elapsedTime >= manipulationState->powerCover.duration)
01292 {
01293 linkPowerCover->SetAngularVel(ZERO_VECTOR);
01294 manipulationState->powerCover.startTime = 0.0;
01295 }
01296 else
01297 {
01298 linkPowerCover->SetAngularVel(manipulationState->powerCover.angularVelocity);
01299 }
01300 }
01301
01302 if (manipulationState->powerSwitch.startTime)
01303 {
01304 const double elapsedTime = time - manipulationState->powerSwitch.startTime;
01305 if (elapsedTime >= manipulationState->powerSwitch.duration)
01306 {
01307 linkPowerSwitch->SetAngularVel(ZERO_VECTOR);
01308 manipulationState->powerSwitch.startTime = 0.0;
01309 }
01310 else
01311 {
01312 linkPowerSwitch->SetAngularVel(manipulationState->powerSwitch.angularVelocity);
01313 }
01314 }
01315
01316 if (manipulationState->rockerSwitch.startTime)
01317 {
01318 const double elapsedTime = time - manipulationState->rockerSwitch.startTime;
01319 if (elapsedTime >= manipulationState->rockerSwitch.duration)
01320 {
01321 linkA01Switch->SetTorque(ZERO_VECTOR);
01322 manipulationState->rockerSwitch.startTime = 0.0;
01323 }
01324 else
01325 {
01326 linkA01Switch->SetTorque(manipulationState->rockerSwitch.torque);
01327 }
01328 }
01329
01330 for (int i = 0; i < NUM_PAD_BUTTONS_COUNT; i++)
01331 {
01332 NumPadButtonManipulationState &manipState = manipulationState->numPadButtons[i];
01333 if (manipState.startTime)
01334 {
01335 const double elapsedTime = time - manipState.startTime;
01336 if (elapsedTime >= manipState.duration)
01337 {
01338 manipState.startTime = 0.0;
01339 }
01340 else
01341 {
01342 linksNumPad[i]->AddRelativeForce(manipState.force);
01343 }
01344 }
01345 }
01346
01347 for (int i = 0; i < SAFE_TOGGLES_COUNT; i++)
01348 {
01349 SafeToggleManipulationState &manipState = manipulationState->safeToggles[i][0];
01350 if (manipState.startTime)
01351 {
01352 physics::LinkPtr link = linksSafeToggle[i];
01353 const double elapsedTime = time - manipState.startTime;
01354 if (elapsedTime >= manipState.duration)
01355 {
01356 link->SetForce(ZERO_VECTOR);
01357 manipState.startTime = 0.0;
01358 }
01359 else
01360 {
01361 link->SetForce(ZERO_VECTOR);
01362 link->AddRelativeForce(math::Vector3(0, 0, manipState.value));
01363 }
01364 }
01365 SafeToggleManipulationState &manipState2 = manipulationState->safeToggles[i][1];
01366 if (manipState2.startTime)
01367 {
01368 physics::LinkPtr link = linksSafeToggle[i];
01369 const double elapsedTime = time - manipState2.startTime;
01370 if (elapsedTime >= manipState2.duration)
01371 {
01372 link->SetAngularVel(ZERO_VECTOR);
01373 link->SetLinearVel(ZERO_VECTOR);
01374 manipState2.startTime = 0.0;
01375 }
01376 else
01377 {
01378 const double velocity = manipState2.value / manipState2.duration;
01379 math::Pose basePose = model->GetWorldPose();
01380 math::Vector3 angularVelocity = basePose.rot * math::Vector3(velocity, 0, 0);
01381 link->SetAngularVel(angularVelocity);
01382 }
01383 }
01384 }
01385 }
01386
01398 math::Vector3 GazeboTaskboardSlot1::computeEmpiricalTorque(
01399 double deviationAngle, double initialValue,
01400 double snapCoeff, double snapExp, double torqueCoeff) const
01401 {
01402
01403 const math::Vector3 axis = model->GetWorldPose().rot * math::Vector3(1, 0, 0);
01404
01405 const double sign = (deviationAngle < 0) ? 1.0 : -1.0;
01406
01407 const double torqueValue = (initialValue + pow(snapCoeff * fabs(deviationAngle), snapExp)) * sign * torqueCoeff;
01408 return axis * torqueValue;
01409 }
01410
01416 double GazeboTaskboardSlot1::GetTime() const
01417 {
01418 return model->GetWorld()->GetSimTime().Double();
01419 }
01420
01421
01425 GazeboTaskboardSlot1::Led::Led()
01426 : isOn(false)
01427 , index(-1)
01428 , color(eLedColor_Green)
01429 {}
01430
01439 GazeboTaskboardSlot1::Led::Led(int index_, bool numPadLed_, LedColor color_, math::Pose pose_)
01440 : isOn(false)
01441 , index(index_)
01442 , numPadLed(numPadLed_)
01443 , color(color_)
01444 , pose(pose_)
01445 {}
01446
01452 void GazeboTaskboardSlot1::Led::CreateModel(physics::WorldPtr world)
01453 {
01454 const std::string sdfTemplate =
01455 "<gazebo version ='1.0'>\
01456 <model name ='MODELNAME' static='1'>\
01457 <origin pose='%1% %2% ZPOS %3% %4% %5%'/>\
01458 <link name ='LINKNAME' kinematic='1'>\
01459 <collision name='COLLISIONNAME'>\
01460 <geometry>GEOMETRY</geometry>\
01461 </collision>\
01462 <visual name='VISUALNAME'>\
01463 <geometry>GEOMETRY</geometry>\
01464 <material script='MATERIAL'/>\
01465 </visual>\
01466 <inertial mass='0.5'> \
01467 <inertia ixx='1' ixy='0.0' ixz='0.0' iyy='1' iyz='0.0' izz='1'/>\
01468 </inertial>\
01469 </link>\
01470 </model>\
01471 </gazebo>";
01472
01473
01474 const std::string material = (color == eLedColor_Green) ? LED_MATERIAL_GREEN
01475 : LED_MATERIAL_BLUE;
01476
01477 const std::string ledNameBase = boost::str(boost::format("taskboardLed%1%") % index);
01478 const std::string ledLinkNameBase = boost::str(boost::format("taskboardLedLink%1%") % index);
01479 const std::string ledCollisionNameBase = boost::str(boost::format("taskboardLedCollision%1%") % index);
01480 const std::string ledVisualNameBase = boost::str(boost::format("taskboardLedVisual%1%") % index);
01481
01482 const std::string ledName = ledNameBase + "_ON";
01483 const std::string ledName2 = ledNameBase + "_OFF";
01484 const std::string ledLinkName = ledLinkNameBase + "_ON";
01485 const std::string ledLinkName2 = ledLinkNameBase + "_OFF";
01486 const std::string ledCollisionName = ledCollisionNameBase + "_ON";
01487 const std::string ledCollisionName2 = ledCollisionNameBase + "_OFF";
01488 const std::string ledVisualName = ledVisualNameBase + "_ON";
01489 const std::string ledVisualName2 = ledVisualNameBase + "_OFF";
01490
01491
01492 std::string ledModel;
01493 ledModel = boost::str(boost::format("<cylinder length='%1%' radius='%2%'/>")
01494 % (numPadLed ? NUMPAD_LED_LENGTH : SIMPLE_LED_LENGTH)
01495 % (numPadLed ? NUMPAD_LED_RADIUS : SIMPLE_LED_RADIUS));
01496
01497
01498 double roll = pose.rot.GetRoll();
01499 double pitch = pose.rot.GetPitch();
01500 double yaw = pose.rot.GetYaw();
01501 std::string xml = boost::str(boost::format(sdfTemplate)
01502 % pose.pos.x % pose.pos.y
01503 % roll % pitch % yaw);
01504 std::string xml2 = xml;
01505
01506
01507 boost::replace_all(xml, "MODELNAME", ledName);
01508 boost::replace_all(xml, "ZPOS", boost::str(boost::format("%1%") % (pose.pos.z + LED_HIDE_OFFSET)));
01509 boost::replace_all(xml, "LINKNAME", ledLinkName);
01510 boost::replace_all(xml, "COLLISIONNAME", ledCollisionName);
01511 boost::replace_all(xml, "VISUALNAME", ledVisualName);
01512 boost::replace_all(xml, "GEOMETRY", ledModel);
01513 boost::replace_all(xml, "MATERIAL", material);
01514
01515
01516 boost::replace_all(xml2, "MODELNAME", ledName2);
01517 boost::replace_all(xml2, "ZPOS", boost::str(boost::format("%1%") % (pose.pos.z + LED_HIDE_OFFSET2)));
01518 boost::replace_all(xml2, "LINKNAME", ledLinkName2);
01519 boost::replace_all(xml2, "COLLISIONNAME", ledCollisionName2);
01520 boost::replace_all(xml2, "VISUALNAME", ledVisualName2);
01521 boost::replace_all(xml2, "GEOMETRY", ledModel);
01522 boost::replace_all(xml2, "MATERIAL", LED_MATERIAL_OFF);
01523
01524
01525 sdf::SDF ledSDF;
01526 ledSDF.SetFromString(xml);
01527
01528 sdf::SDF ledSDF2;
01529 ledSDF2.SetFromString(xml2);
01530
01531 #if ROS_VERSION_MINIMUM(1, 9, 0)
01532
01533 world->InsertModelSDF(ledSDF);
01534 world->InsertModelSDF(ledSDF2);
01535 #else
01536
01537 world->InsertModel(ledSDF);
01538 world->InsertModel(ledSDF2);
01539 #endif
01540
01541
01542
01543
01544 onModelName = ledName;
01545 onLinkName = ledLinkName;
01546 offModelName = ledName2;
01547 offLinkName = ledLinkName2;
01548 }
01549
01555 void GazeboTaskboardSlot1::Led::SetupModel(physics::WorldPtr world)
01556 {
01557 if (!onModel)
01558 {
01559 onModel = world->GetModel(onModelName);
01560 if (!onModel)
01561 {
01562 ROS_FATAL("SetupModel: failed to get model %s", onModelName.c_str());
01563 return;
01564 }
01565 onModel->SetCollideMode("none");
01566
01567 offModel = world->GetModel(offModelName);
01568 if (!offModel)
01569 {
01570 ROS_FATAL("SetupModel: failed to get model %s", offModelName.c_str());
01571 return;
01572 }
01573 offModel->SetCollideMode("none");
01574
01575 math::Pose pose2 = offModel->GetRelativePose();
01576 pose2.pos.z -= LED_HIDE_OFFSET2;
01577 offModel->SetWorldPose(pose2);
01578 }
01579 }
01580
01581
01589 GazeboTaskboardSlot1::TaskboardLeds::TaskboardLeds(const math::Pose& modelPose)
01590 {
01591 struct LedsInfo {
01592 Led& led;
01593 bool numPadLed;
01594 LedColor color;
01595 math::Vector3 offset;
01596 } ledsInfo[] = {
01597 { powerSwitchLed, false, eLedColor_Green, math::Vector3(0.3250, -0.4720, 1.4110) },
01598 { rockerSwitchUpLed, false, eLedColor_Green, math::Vector3(0.3245, -0.4720, 1.3340) },
01599 { rockerSwitchDownLed, false, eLedColor_Blue, math::Vector3(0.3245, -0.4720, 1.2834) },
01600 { numPadLeds[0], true, eLedColor_Blue, math::Vector3(0.4496, -0.4755, 1.3358) },
01601 { numPadLeds[1], true, eLedColor_Green, math::Vector3(0.4230, -0.4755, 1.3358) },
01602 { numPadLeds[2], true, eLedColor_Blue, math::Vector3(0.3964, -0.4755, 1.3358) },
01603 { numPadLeds[3], true, eLedColor_Green, math::Vector3(0.4496, -0.4755, 1.3095) },
01604 { numPadLeds[4], true, eLedColor_Blue, math::Vector3(0.4230, -0.4755, 1.3095) },
01605 { numPadLeds[5], true, eLedColor_Green, math::Vector3(0.3964, -0.4755, 1.3095) },
01606 { numPadLeds[6], true, eLedColor_Blue, math::Vector3(0.4496, -0.4755, 1.2833) },
01607 { numPadLeds[7], true, eLedColor_Green, math::Vector3(0.4230, -0.4755, 1.2833) },
01608 { numPadLeds[8], true, eLedColor_Blue, math::Vector3(0.3964, -0.4755, 1.2833) },
01609 { toggleA03Led, false, eLedColor_Green, math::Vector3(0.4449, -0.4720, 1.2365) },
01610 { toggleA04TopLed, false, eLedColor_Green, math::Vector3(0.3812, -0.4720, 1.2365) },
01611 { toggleA04BottomLed, false, eLedColor_Blue, math::Vector3(0.3812, -0.4720, 1.1855) },
01612 { toggleA05Led, false, eLedColor_Green, math::Vector3(0.3185, -0.4720, 1.2365) }
01613 };
01614 const int ledsCount = sizeof(ledsInfo) / sizeof(ledsInfo[0]);
01615 const math::Quaternion rot = math::Quaternion(0.707, 0.707, 0, 0);
01616
01617 for (int i = 0; i < ledsCount; i++)
01618 {
01619 const LedsInfo &info = ledsInfo[i];
01620 const math::Pose pose(modelPose.pos + modelPose.rot * info.offset, modelPose.rot * rot);
01621 info.led = Led(i, info.numPadLed, info.color, pose);
01622 }
01623 }
01624
01633 void GazeboTaskboardSlot1::TaskboardLeds::CreateModels(physics::WorldPtr world)
01634 {
01635 for (int i = 0; i < NUM_PAD_BUTTONS_COUNT; i++)
01636 {
01637 numPadLeds[i].CreateModel(world);
01638 }
01639 powerSwitchLed.CreateModel(world);
01640 rockerSwitchUpLed.CreateModel(world);
01641 rockerSwitchDownLed.CreateModel(world);
01642 toggleA03Led.CreateModel(world);
01643 toggleA04TopLed.CreateModel(world);
01644 toggleA04BottomLed.CreateModel(world);
01645 toggleA05Led.CreateModel(world);
01646 }
01647
01653 void GazeboTaskboardSlot1::TaskboardLeds::SetupModels(physics::WorldPtr world)
01654 {
01655 for (int i = 0; i < NUM_PAD_BUTTONS_COUNT; i++)
01656 {
01657 numPadLeds[i].SetupModel(world);
01658 }
01659 powerSwitchLed.SetupModel(world);
01660 rockerSwitchUpLed.SetupModel(world);
01661 rockerSwitchDownLed.SetupModel(world);
01662 toggleA03Led.SetupModel(world);
01663 toggleA04TopLed.SetupModel(world);
01664 toggleA04BottomLed.SetupModel(world);
01665 toggleA05Led.SetupModel(world);
01666 }