LCOV - code coverage report
Current view: top level - src/Kinematics/RV2AJ - Driver.cpp (source / functions) Hit Total Coverage
Test: HLR Lines: 7 119 5.9 %
Date: 2018-01-16 12:39:55 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             :     // std_msgs::String mb4;
      41             :     // mb4.data = mb4_ctor;
      42             :     // pub_mb4.publish(mb4);
      43             : 
      44             :     // spawn worker thread
      45           0 :     worker = std::thread([this] { work(); });
      46           0 : }
      47             : 
      48           0 : Driver::~Driver()
      49             : {
      50             :     // stop worker thread
      51           0 :     worker_state_m.lock();
      52           0 :     worker_state = State::exit;
      53           0 :     worker_state_m.unlock();
      54           0 :     commands_m.lock();
      55           0 :     commands_cv.notify_all();
      56           0 :     commands_m.unlock();
      57           0 :     worker.join();
      58             : 
      59             :     // stop arm
      60             :     // TODO write to serial
      61           0 :     std_msgs::String mb4;
      62           0 :     mb4.data = mb4_dtor;
      63           0 :     pub_mb4.publish(mb4);
      64           0 : }
      65             : 
      66           0 : bool Driver::cont(HLR::RV2AJDriverContinue::Request& req[[maybe_unused]],
      67             :                   HLR::RV2AJDriverContinue::Response& res[[maybe_unused]])
      68             : {
      69           0 :     std::lock_guard<std::mutex> l(worker_state_m);
      70           0 :     switch (worker_state)
      71             :     {
      72           0 :         case State::pause:
      73             :         {
      74           0 :             worker_state = State::cont;
      75           0 :             std::lock_guard<std::mutex> l_c(commands_m);
      76           0 :             commands_cv.notify_one();
      77           0 :             break;
      78             :         }
      79             : 
      80           0 :         case State::cont:
      81             :         case State::exit:
      82           0 :             return false;
      83             :     }
      84             : 
      85           0 :     return true;
      86             : }
      87             : 
      88           0 : bool Driver::pause(HLR::RV2AJDriverPause::Request& req[[maybe_unused]],
      89             :                    HLR::RV2AJDriverPause::Response& res[[maybe_unused]])
      90             : {
      91           0 :     std::lock_guard<std::mutex> l(worker_state_m);
      92           0 :     switch (worker_state)
      93             :     {
      94           0 :         case State::cont:
      95           0 :             worker_state = State::pause;
      96           0 :             break;
      97             : 
      98           0 :         case State::pause:
      99             :         case State::exit:
     100           0 :             return false;
     101             :     }
     102             : 
     103           0 :     return true;
     104             : }
     105             : 
     106           0 : bool Driver::clear(HLR::RV2AJDriverClear::Request& req[[maybe_unused]],
     107             :                    HLR::RV2AJDriverClear::Response& res[[maybe_unused]])
     108             : {
     109           0 :     std::lock_guard<std::mutex> l(commands_m);
     110           0 :     std::size_t i = commands.size();
     111           0 :     while (i > 0)
     112             :     {
     113           0 :         commands.pop();
     114           0 :         --i;
     115             :     }
     116             : 
     117           0 :     return true;
     118             : }
     119             : 
     120           0 : bool Driver::queue_count(
     121             :     HLR::RV2AJDriverQueueCount::Request& req[[maybe_unused]],
     122             :     HLR::RV2AJDriverQueueCount::Response& res)
     123             : {
     124           0 :     std::lock_guard<std::mutex> l(commands_m);
     125           0 :     res.count = commands.size();
     126             : 
     127           0 :     return true;
     128             : }
     129             : 
     130           0 : bool Driver::queue_add(HLR::RV2AJDriverQueueAdd::Request& req,
     131             :                        HLR::RV2AJDriverQueueAdd::Response& res[[maybe_unused]])
     132             : {
     133             :     // speed is a percentage, enforce it
     134             :     // note that 0% is also not a valid speed, must be > 0
     135           0 :     if (req.speed <= 0.0 || req.speed > 100.0)
     136             :     {
     137           0 :         return false;
     138             :     }
     139             : 
     140           0 :     std::lock_guard<std::mutex> l(commands_m);
     141             :     // note that J4 and J7 aren't used for RV-2AJ 5DOF
     142           0 :     commands.push({req.base,
     143           0 :                    req.shoulder,
     144           0 :                    req.elbow,
     145             :                    0.0,
     146           0 :                    req.wrist,
     147           0 :                    req.wrist_rotate,
     148             :                    0.0,
     149           0 :                    req.speed});
     150           0 :     commands_cv.notify_one();
     151             : 
     152           0 :     return true;
     153             : }
     154             : 
     155           0 : std::string Driver::Command::to_mb4() const
     156             : {
     157           0 :     std::ostringstream ss;
     158             : 
     159             :     // set angles
     160             :     // note that J4 and J7 aren't used for RV-2AJ 5DOF
     161             :     // they still must be set in the command string though
     162           0 :     ss << mb4_prefix << "EXECJCOSIROP=(";
     163           0 :     ss << base << ',';
     164           0 :     ss << shoulder << ',';
     165           0 :     ss << elbow << ',';
     166           0 :     ss << j4 << ',';
     167           0 :     ss << wrist << ',';
     168           0 :     ss << wrist_rotate << ',';
     169           0 :     ss << j7 << ")\r";
     170             : 
     171             :     // set speed
     172             :     // ss << mb4_prefix << "EXECJOVRD " << speed << '\r';
     173             : 
     174             :     // exec move
     175             :     // ss << mb4_prefix << "EXECMOV JCOSIROP\r";
     176             : 
     177           0 :     return ss.str();
     178             : }
     179             : 
     180           0 : void Driver::work()
     181             : {
     182             :     // worker state
     183             :     State state;
     184             :     // lock used for commands and waiting on notifications
     185           0 :     std::unique_lock<std::mutex> commands_ul(commands_m, std::defer_lock);
     186             :     // local copy for when popping commands from the queue
     187             :     Command cmd;
     188             :     // msg for MB4 topic containing converted MB4 string
     189           0 :     std_msgs::String mb4;
     190             : 
     191             :     // sync state
     192           0 :     worker_state_m.lock();
     193           0 :     state = worker_state;
     194           0 :     worker_state_m.unlock();
     195             : 
     196           0 :     commands_ul.lock();
     197           0 :     while (state != State::exit)
     198             :     {
     199             :         // wait for command to be queued or exit when requested
     200           0 :         commands_cv.wait(commands_ul, [this, &state] {
     201             :             // sync state
     202           0 :             worker_state_m.lock();
     203           0 :             state = worker_state;
     204           0 :             worker_state_m.unlock();
     205             : 
     206           0 :             return state != State::pause
     207           0 :                    && (!commands.empty() || state == State::exit);
     208             :         });
     209             : 
     210           0 :         do
     211             :         {
     212           0 :             switch (state)
     213             :             {
     214           0 :                 case State::cont:
     215           0 :                     cmd = commands.front();
     216           0 :                     commands.pop();
     217           0 :                     commands_ul.unlock();
     218           0 :                     mb4.data = cmd.to_mb4();
     219           0 :                     pub_mb4.publish(mb4);
     220             :                     // TODO write to serial
     221           0 :                     break;
     222             : 
     223             :                 // pause cannot happen, cover it anyway
     224           0 :                 case State::pause:
     225             :                 case State::exit:
     226           0 :                     commands_ul.unlock();
     227           0 :                     break;
     228             :             }
     229             : 
     230             :             // sync state
     231           0 :             worker_state_m.lock();
     232           0 :             state = worker_state;
     233           0 :             worker_state_m.unlock();
     234             : 
     235           0 :             commands_ul.lock();
     236           0 :         } while (!commands.empty() && state == State::cont);
     237             :     }
     238           0 :     commands_ul.unlock();
     239           0 : }
     240             : 
     241             : } // namespace RV2AJ
     242             : } // namespace Kinematics
     243           3 : } // namespace HLR

Generated by: LCOV version 1.12