5050#include < chrono> // for steady_clock, for duration
5151#include < utility> // for move
5252
53+ #include < json.hpp>
54+
55+ using json = nlohmann::json;
56+
5357#include " robot_msgs/bool_t.hpp"
5458#include " robot_msgs/pause_cmd.hpp" // for pause_cmd
5559#include " robot_msgs/trigger_t.hpp" // for trigger_t
@@ -62,6 +66,59 @@ using franka_driver::CommunicationInterface;
6266using franka_driver::PlanTimepoints;
6367using utils::PauseCommandType;
6468
69+ void trim (std::string& _string, const char * end_chars) {
70+ _string.erase (0 , _string.find_first_not_of (end_chars));
71+ _string.erase (_string.find_last_not_of (end_chars) + 1 );
72+ }
73+
74+ const Eigen::IOFormat VectorXdFmt (6 , 0 , " , " , " \n " , " [" , " ]" );
75+
76+ std::string to_string (Eigen::VectorXd const & ev) {
77+ return fmt::format (" {}" , ev.transpose ().format (VectorXdFmt));
78+ }
79+
80+ int64_t get_current_utime () {
81+ struct timeval tv;
82+ gettimeofday (&tv, NULL );
83+ int64_t current_utime = int64_t (tv.tv_sec * 1e6 + tv.tv_usec );
84+ return current_utime;
85+ }
86+
87+ std::vector<std::string> split_string (const std::string_view str) {
88+ std::vector<std::string> str_vec;
89+ std::string token;
90+ std::stringstream ss {str.data ()};
91+ while (std::getline (ss, token, ' ,' )) {
92+ str_vec.push_back (token);
93+ }
94+ return str_vec;
95+ }
96+
97+ std::vector<double > string_to_double_vector (
98+ const std::string_view str) {
99+ // works for vector string that looks like: [1, 2, 3, 4]
100+ // whitespace negligable
101+ try {
102+ std::string mutable_input {str};
103+ std::vector<double > output_vec;
104+
105+ // trim input string to just numbers with comma delimeter
106+ trim (mutable_input, " ' \"\t\n\r\f\v []" );
107+
108+ auto string_vector {split_string (mutable_input)};
109+
110+ for (const auto & num : string_vector) {
111+ output_vec.push_back (std::stod (num));
112+ }
113+
114+ return output_vec;
115+ } catch (std::exception& e) {
116+ dexai::log ()->error (
117+ " string_to_double_vector: failed to find vector in string '{}'" , str);
118+ return {};
119+ }
120+ }
121+
65122CommunicationInterface::CommunicationInterface (const RobotParameters& params,
66123 const double lcm_publish_rate,
67124 const bool simulated)
@@ -75,8 +132,14 @@ CommunicationInterface::CommunicationInterface(const RobotParameters& params,
75132 this );
76133 lcm_.subscribe (params_.lcm_compliant_push_req_channel ,
77134 &CommunicationInterface::HandleCompliantPushReq, this );
135+
78136 lcm_.subscribe (params_.lcm_sim_driver_event_trigger_channel ,
79137 &CommunicationInterface::HandleSimDriverEventTrigger, this );
138+ // lcm_.subscribe("SHOKUNIN_FRANKA_JOINT_CURRENT", &CommunicationInterface::HandleCurrentJoint, this);
139+
140+ // TODO(@anyone): define this in parameters file
141+ lcm_driver_status_channel_ = params_.robot_name + " _DRIVER_STATUS" ;
142+ lcm_compliant_push_req_channel_ = params_.robot_name + " _COMPLIANT_PUSH_REQ" ;
80143
81144 dexai::log ()->info (" Plan channel:\t\t\t\t {}" , params_.lcm_plan_channel );
82145 dexai::log ()->info (" Stop channel:\t\t\t\t {}" , params_.lcm_stop_channel );
@@ -270,6 +333,7 @@ void CommunicationInterface::PublishLcmAndPauseStatus() {
270333 while (running_) {
271334 auto time_start = std::chrono::steady_clock::now ();
272335 PublishRobotStatus ();
336+ PublishRobotCommands ();
273337
274338 // Sleep dynamically to achieve the desired print rate.
275339 auto time_end = std::chrono::steady_clock::now ();
@@ -288,6 +352,19 @@ void CommunicationInterface::PublishLcmAndPauseStatus() {
288352 }
289353}
290354
355+ void CommunicationInterface::PublishRobotCommands () {
356+ // Try to lock data to avoid read write collisions.
357+ std::unique_lock<std::mutex> lock {robot_data_mutex_};
358+
359+ robot_msgs::string_t msg;
360+ json json_payload;
361+ json_payload[" commanded_positions" ] = to_string (robot_data_.robot_plan_next_conf );
362+ msg.data = json_payload.dump ();
363+ msg.utime = get_current_utime ();
364+
365+ lcm_.publish (" SHOKUNIN_FRANKA_JOINT_COMMAND" , &msg);
366+ }
367+
291368void CommunicationInterface::PublishRobotStatus () {
292369 // Try to lock data to avoid read write collisions.
293370 std::unique_lock<std::mutex> lock {robot_data_mutex_};
@@ -598,6 +675,21 @@ void CommunicationInterface::HandlePlan(
598675 new_plan_buffer_.utime , ms_accept);
599676}
600677
678+ void CommunicationInterface::HandleCurrentJoint (
679+ const ::lcm::ReceiveBuffer*, const std::string&,
680+ const robot_msgs::string_t * curr_joint_msg) {
681+ try {
682+ json data = json::parse (curr_joint_msg->data );
683+ const std::string curr_joint_string {data[" current_joint_positions" ]};
684+ curr_joint_vector_ = string_to_double_vector (curr_joint_string);
685+ } catch (const std::exception& ex) {
686+ dexai::log ()->error (
687+ " MCD:HandleCurrentJoint: Caught exception " ,
688+ ex.what ());
689+ return ;
690+ }
691+ }
692+
601693void CommunicationInterface::HandlePause (
602694 const ::lcm::ReceiveBuffer*, const std::string&,
603695 const robot_msgs::pause_cmd* pause_cmd_msg) {
0 commit comments