LCOV - code coverage report
Current view: top level - src/Kinematics/RV2AJ - Driver.cpp (source / functions) Hit Total Coverage
Test: HLR Lines: 7 126 5.6 %
Date: 2018-01-10 08:35:30 Functions: 2 14 14.3 %

          Line data    Source code
       1             : #include "Driver.hpp"
       2             : 
       3             : #include <chrono>
       4             : #include <cstdint>
       5             : #include <sstream>
       6             : 
       7             : // robot ID and slot are both set to 1
       8             : // http://94.124.143.236/confluence/display/FRGDXL/Mitsubishi+RV-2AJ+limitaties+en+aansturing#MitsubishiRV-2AJlimitatiesenaansturing-Deelvraag5:Metwelkprotocolkanderobotarmaangestuurdworden?
       9           1 : static const std::string mb4_prefix = "1;1;";
      10             : 
      11           3 : static const std::string mb4_ctor = mb4_prefix + "RSTALRM\r" + mb4_prefix
      12           2 :                                     + "OPEN=usertool\r" + mb4_prefix
      13           2 :                                     + "CNTLON\r" + mb4_prefix + "SRVON\r";
      14             : 
      15           2 : static const std::string mb4_dtor =
      16           2 :     mb4_prefix + "CNTLOFF\r" + mb4_prefix + "SRVOFF\r";
      17             : 
      18             : namespace HLR
      19             : {
      20             : namespace Kinematics
      21             : {
      22             : namespace RV2AJ
      23             : {
      24           0 : Driver::Driver()
      25             : {
      26             :     // bind topics and services
      27           0 :     pub_mb4 =
      28           0 :         nh.advertise<std_msgs::String>("serial_request_topic", 1000, true);
      29           0 :     srv_continue =
      30           0 :         nh.advertiseService("rv2aj_driver_continue", &Driver::cont, this);
      31           0 :     srv_pause = nh.advertiseService("rv2aj_driver_pause", &Driver::pause, this);
      32           0 :     srv_clear = nh.advertiseService("rv2aj_driver_clear", &Driver::clear, this);
      33           0 :     srv_queue_count = nh.advertiseService(
      34           0 :         "rv2aj_driver_queue_count", &Driver::queue_count, this);
      35           0 :     srv_queue_add =
      36           0 :         nh.advertiseService("rv2aj_driver_queue_add", &Driver::queue_add, this);
      37             : 
      38             :     // init arm
      39             :     // TODO write to serial
      40           0 :     std_msgs::String mb4;
      41           0 :     mb4.data = mb4_ctor;
      42             : 
      43           0 :     ROS_INFO("BEFORE PUBLISH");
      44           0 :     pub_mb4.publish(mb4);
      45           0 :     ROS_INFO("AFTER PUBLISH");
      46             : 
      47             :     // spawn worker thread
      48           0 :     worker = std::thread([this] { work(); });
      49           0 : }
      50             : 
      51           0 : Driver::~Driver()
      52             : {
      53             :     // stop worker thread
      54           0 :     worker_state_m.lock();
      55           0 :     worker_state = State::exit;
      56           0 :     worker_state_m.unlock();
      57           0 :     commands_m.lock();
      58           0 :     commands_cv.notify_all();
      59           0 :     commands_m.unlock();
      60           0 :     worker.join();
      61             : 
      62             :     // stop arm
      63             :     // TODO write to serial
      64           0 :     std_msgs::String mb4;
      65           0 :     mb4.data = mb4_dtor;
      66           0 :     pub_mb4.publish(mb4);
      67           0 : }
      68             : 
      69           0 : bool Driver::cont(HLR::RV2AJDriverContinue::Request& req[[maybe_unused]],
      70             :                   HLR::RV2AJDriverContinue::Response& res[[maybe_unused]])
      71             : {
      72           0 :     std::lock_guard<std::mutex> l(worker_state_m);
      73           0 :     switch (worker_state)
      74             :     {
      75           0 :         case State::pause:
      76             :         {
      77           0 :             worker_state = State::cont;
      78           0 :             std::lock_guard<std::mutex> l_c(commands_m);
      79           0 :             commands_cv.notify_one();
      80           0 :             break;
      81             :         }
      82             : 
      83           0 :         case State::cont:
      84             :         case State::exit:
      85           0 :             return false;
      86             :     }
      87             : 
      88           0 :     return true;
      89             : }
      90             : 
      91           0 : bool Driver::pause(HLR::RV2AJDriverPause::Request& req[[maybe_unused]],
      92             :                    HLR::RV2AJDriverPause::Response& res[[maybe_unused]])
      93             : {
      94           0 :     std::lock_guard<std::mutex> l(worker_state_m);
      95           0 :     switch (worker_state)
      96             :     {
      97           0 :         case State::cont:
      98           0 :             worker_state = State::pause;
      99           0 :             break;
     100             : 
     101           0 :         case State::pause:
     102             :         case State::exit:
     103           0 :             return false;
     104             :     }
     105             : 
     106           0 :     return true;
     107             : }
     108             : 
     109           0 : bool Driver::clear(HLR::RV2AJDriverClear::Request& req[[maybe_unused]],
     110             :                    HLR::RV2AJDriverClear::Response& res[[maybe_unused]])
     111             : {
     112           0 :     std::lock_guard<std::mutex> l(commands_m);
     113           0 :     std::size_t i = commands.size();
     114           0 :     while (i > 0)
     115             :     {
     116           0 :         commands.pop();
     117           0 :         --i;
     118             :     }
     119             : 
     120           0 :     return true;
     121             : }
     122             : 
     123           0 : bool Driver::queue_count(
     124             :     HLR::RV2AJDriverQueueCount::Request& req[[maybe_unused]],
     125             :     HLR::RV2AJDriverQueueCount::Response& res)
     126             : {
     127           0 :     std::lock_guard<std::mutex> l(commands_m);
     128           0 :     res.count = commands.size();
     129             : 
     130           0 :     return true;
     131             : }
     132             : 
     133           0 : bool Driver::queue_add(HLR::RV2AJDriverQueueAdd::Request& req,
     134             :                        HLR::RV2AJDriverQueueAdd::Response& res[[maybe_unused]])
     135             : {
     136             :     // speed is a percentage, enforce it
     137             :     // note that 0% is also not a valid speed, must be > 0
     138           0 :     if (req.speed <= 0.0 || req.speed > 100.0)
     139             :     {
     140           0 :         return false;
     141             :     }
     142             : 
     143           0 :     std::lock_guard<std::mutex> l(commands_m);
     144             :     // note that J4 and J7 aren't used for RV-2AJ 5DOF
     145           0 :     commands.push({req.base,
     146           0 :                    req.shoulder,
     147           0 :                    req.elbow,
     148             :                    0.0,
     149           0 :                    req.wrist,
     150           0 :                    req.wrist_rotate,
     151             :                    0.0,
     152           0 :                    req.speed});
     153           0 :     commands_cv.notify_one();
     154             : 
     155           0 :     return true;
     156             : }
     157             : 
     158           0 : std::string Driver::Command::to_mb4() const
     159             : {
     160           0 :     std::ostringstream ss;
     161             : 
     162             :     // set angles
     163             :     // note that J4 and J7 aren't used for RV-2AJ 5DOF
     164             :     // they still must be set in the command string though
     165           0 :     ss << mb4_prefix << "EXECJCOSIROP=(";
     166           0 :     ss << base << ',';
     167           0 :     ss << shoulder << ',';
     168           0 :     ss << elbow << ',';
     169           0 :     ss << j4 << ',';
     170           0 :     ss << wrist << ',';
     171           0 :     ss << wrist_rotate << ',';
     172           0 :     ss << j7 << ")\r";
     173             : 
     174             :     // set speed
     175           0 :     ss << mb4_prefix << "EXECJOVRD " << speed << '\r';
     176             : 
     177             :     // exec move
     178           0 :     ss << mb4_prefix << "EXECMOV JCOSIROP\r";
     179             : 
     180           0 :     return ss.str();
     181             : }
     182             : 
     183           0 : void Driver::work()
     184             : {
     185             :     // worker state
     186             :     State state;
     187             :     // lock used for commands and waiting on notifications
     188           0 :     std::unique_lock<std::mutex> commands_ul(commands_m, std::defer_lock);
     189             :     // local copy for when popping commands from the queue
     190             :     Command cmd;
     191             :     // msg for MB4 topic containing converted MB4 string
     192           0 :     std_msgs::String mb4;
     193             : 
     194             :     // sync state
     195           0 :     worker_state_m.lock();
     196           0 :     state = worker_state;
     197           0 :     worker_state_m.unlock();
     198             : 
     199           0 :     commands_ul.lock();
     200           0 :     while (state != State::exit)
     201             :     {
     202             :         // wait for command to be queued or exit when requested
     203           0 :         commands_cv.wait(commands_ul, [this, &state] {
     204             :             // sync state
     205           0 :             worker_state_m.lock();
     206           0 :             state = worker_state;
     207           0 :             worker_state_m.unlock();
     208             : 
     209           0 :             return state != State::pause
     210           0 :                    && (!commands.empty() || state == State::exit);
     211             :         });
     212             : 
     213           0 :         do
     214             :         {
     215           0 :             switch (state)
     216             :             {
     217           0 :                 case State::cont:
     218           0 :                     cmd = commands.front();
     219           0 :                     commands.pop();
     220           0 :                     commands_ul.unlock();
     221           0 :                     mb4.data = cmd.to_mb4();
     222           0 :                     pub_mb4.publish(mb4);
     223             :                     // TODO write to serial
     224           0 :                     break;
     225             : 
     226             :                 // pause cannot happen, cover it anyway
     227           0 :                 case State::pause:
     228             :                 case State::exit:
     229           0 :                     commands_ul.unlock();
     230           0 :                     break;
     231             :             }
     232             : 
     233             :             // sync state
     234           0 :             worker_state_m.lock();
     235           0 :             state = worker_state;
     236           0 :             worker_state_m.unlock();
     237             : 
     238           0 :             commands_ul.lock();
     239           0 :         } while (!commands.empty() && state == State::cont);
     240             :     }
     241           0 :     commands_ul.unlock();
     242           0 : }
     243             : 
     244             : } // namespace RV2AJ
     245             : } // namespace Kinematics
     246           3 : } // namespace HLR

Generated by: LCOV version 1.12