25 #include "control_msgs/FollowJointTrajectoryActionFeedback.h" 27 #include "std_msgs/Int16MultiArray.h" 32 #include "icl_core_logging/Logging.h" 39 m_action_server(m_priv_nh,
"follow_joint_trajectory",
43 m_use_ros_control(false),
44 m_was_disabled(false),
46 m_homing_active(false),
47 m_nodes_initialized(false)
49 std::string can_device_name;
51 std::vector<std::string> chain_names;
52 std::map<std::string, std::vector<int> > chain_configuratuions;
54 sensor_msgs::JointState joint_msg;
55 bool autostart =
true;
59 m_priv_nh.
param<std::string>(
"can_device_name", can_device_name,
"auto");
71 m_controller = boost::make_shared<CanOpenController>(can_device_name);
81 char const* tmp = std::getenv(
"CANOPEN_RESOURCE_PATH");
87 "The environment variable 'CANOPEN_RESOURCE_PATH' could not be read. No Schunk specific error codes will be used." <<
endl);
91 std::string emcy_emergency_errors_filename = boost::filesystem::path(tmp / boost::filesystem::path(
"EMCY_schunk.ini")).string();
92 EMCY::addEmergencyErrorMap( emcy_emergency_errors_filename,
"schunk_error_codes");
100 for (
size_t i = 0; i < chain_names.size(); ++i)
102 std::string name =
"chain_" + chain_names[i];
105 std::vector<int> chain;
114 if (chain.size() == 0)
116 ROS_ERROR_STREAM(
"Did not find device list for chain " << chain_names[i] <<
". Make sure, that an entry " << name <<
" exists.");
121 name =
"chain_" + chain_names[i] +
"_type";
122 std::string chain_type =
"PowerBall";
133 name =
"chain_" + chain_names[i] +
"_transmission_factor";
134 double transmission_factor = 1.0;
138 if (chain_type !=
"PowerBall")
140 ROS_INFO_STREAM (
"Chain transmission factor is " << transmission_factor);
149 ROS_INFO_STREAM (
"Found chain with name " << chain_names[i] <<
" of type " << chain_type <<
" containing " << chain.size() <<
" nodes.");
150 chain_configuratuions[name] = chain;
151 for (
size_t j = 0; j < chain.size(); ++j)
153 if (chain_type ==
"DS402")
163 std::string joint_name =
"";
164 std::string mapping_key =
"~node_mapping_" + boost::lexical_cast<std::string>( chain[j]);
168 joint_msg.name.push_back(joint_name);
186 std_msgs::Int16MultiArray currents;
195 joint_msg.position.clear();
196 currents.data.clear();
203 const uint8_t& nr = it->second;
205 joint_msg.position.push_back(node->getTargetFeedback());
210 currents.data.push_back(node->getTPDOValue<
int16_t>(
"measured_torque"));
215 currents.data.push_back(0);
229 std_srvs::TriggerResponse& resp)
247 ROS_INFO (
"Going to shut down now");
253 ROS_INFO (
"Going to shut down now");
284 ROS_ERROR_STREAM (
"Caught ProtocolException while enabling nodes from chain " <<
316 ROS_INFO (
"Executing Trajectory action");
326 if (gh.
getGoal()->trajectory.joint_names.size() != gh.
getGoal()->trajectory.points[0].positions.size())
329 ") and joint states (" << gh.
getGoal()->trajectory.points.size() <<
") do not match! Aborting goal!");
335 ROS_WARN_STREAM (
"Sent a new goal while another goal was still running. Depending on the " <<
336 "device configuration this will either result in a queuing or the current trajectory " <<
337 "will be overwritten." 350 control_msgs::FollowJointTrajectoryActionResult result;
351 control_msgs::FollowJointTrajectoryActionFeedback feedback;
352 feedback.feedback.header = gh.
getGoal()->trajectory.header;
353 result.header = gh.
getGoal()->trajectory.header;
356 bool targets_reached =
true;
358 for (
size_t waypoint = 0; waypoint < gh.
getGoal()->trajectory.points.size(); ++waypoint)
360 feedback.feedback.desired.positions.clear();
361 feedback.feedback.joint_names.clear();
362 feedback.feedback.actual.positions.clear();
363 for (
size_t i = 0; i < gh.
getGoal()->trajectory.joint_names.size(); ++i)
367 float pos = boost::lexical_cast<
float>(gh.
getGoal()->trajectory.points[waypoint].positions[i]);
377 result.result.error_code = -2;
378 result.result.error_string = e.
what();
383 feedback.feedback.desired.positions.push_back(pos);
384 feedback.feedback.joint_names.push_back(gh.
getGoal()->trajectory.joint_names[i]);
387 pos = node->getTargetFeedback();
388 feedback.feedback.actual.positions.push_back(pos);
397 std::vector<bool> reached_vec;
402 while ( spent_time < max_time || max_time.
isZero() )
407 catch (
const std::exception& e)
415 bool waypoint_reached =
true;
416 for (
size_t i = 0; i < gh.
getGoal()->trajectory.joint_names.size(); ++i)
420 waypoint_reached &= node->isTargetReached();
421 float pos = node->getTargetFeedback();
425 feedback.feedback.actual.time_from_start = spent_time;
426 feedback.feedback.actual.positions.at(i) = (pos);
431 targets_reached = waypoint_reached;
435 if (waypoint_reached)
441 if (spent_time > max_time && !max_time.
isZero())
443 result.result.error_code = -5;
444 result.result.error_string =
"Did not reach targets in specified time";
449 if (boost::this_thread::interruption_requested() )
461 result.result.error_code = 0;
462 result.result.error_string =
"All targets successfully reached";
467 ROS_INFO (
"Not all targets reached" );
468 result.result.error_code = -5;
469 result.result.error_string =
"Did not reach targets in specified time";
479 ROS_INFO (
"Canceling Trajectory action");
482 ROS_INFO (
"Stopped trajectory thread");
496 control_msgs::FollowJointTrajectoryActionResult result;
497 result.result.error_code = 0;
498 result.result.error_string =
"Trajectory preempted by user";
530 elapsed_time = current_time - last_time;
531 last_time = current_time;
542 ROS_ERROR (
"Some nodes are in FAULT state! No commands will be sent. Once the fault is removed, call the enable_nodes service.");
549 ROS_INFO (
"Recovering from FAULT state. Resetting controller");
569 m_chain_handles[i]->setTarget(std::vector<float>(joint_msg.position.begin(), joint_msg.position.end()));
581 ROS_INFO (
"Shutting down ros_control_loop thread.");
622 ROS_INFO (
"Closed brakes for all nodes. For reenabling, please use the enable_nodes service. Thank you for your attention.");
632 ROS_INFO (
"Stopped trajectory thread");
649 ROS_INFO (
"Quick stopped all nodes. For reenabling, please use the enable_nodes service. Thank you for your attention.");
654 schunk_canopen_driver::HomeAllResponse& resp)
656 schunk_canopen_driver::HomeWithIDsRequest req_fwd;
657 schunk_canopen_driver::HomeWithIDsResponse resp_fwd;
662 resp.success = resp_fwd.success;
668 schunk_canopen_driver::HomeWithJointNamesResponse& resp)
670 schunk_canopen_driver::HomeWithIDsRequest req_fwd;
671 schunk_canopen_driver::HomeWithIDsResponse resp_fwd;
672 for (std::vector<std::string>::iterator it = req.joint_names.begin();
673 it != req.joint_names.end();
682 ROS_ERROR_STREAM (
"Could not find joint " << *it <<
". No homing will be performed for this joint.");
686 resp.success = resp_fwd.success;
692 schunk_canopen_driver::HomeWithIDsResponse& resp)
709 for (std::vector<uint8_t>::iterator it = req.node_ids.begin(); it != req.node_ids.end(); ++it)
728 m_homing_active =
false;
736 int main(
int argc,
char **argv)
void publishFeedback(const Feedback &feedback)
bool initialize(int &argc, char *argv[], bool remove_read_arguments)
bool homeAllNodes(schunk_canopen_driver::HomeAllRequest &req, schunk_canopen_driver::HomeAllResponse &resp)
Perform a reset offset for all nodes. You should call this service, after driving the devices to thei...
virtual const char * what() const _GLIBCXX_USE_NOEXCEPT
void publish(const boost::shared_ptr< M > &message) const
CanOpenController::Ptr m_controller
ros::ServiceServer m_enable_service
void goalCB(actionlib::ServerGoalHandle< control_msgs::FollowJointTrajectoryAction > gh)
actionlib::ActionServer< control_msgs::FollowJointTrajectoryAction > m_action_server
Basic CanOpen exception that contains the Object dictionary index and subindex.
std::vector< DS402Group::Ptr > m_chain_handles
This class gives a device specific interface for Schunk Powerballs, as they need some "special" treat...
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
std::string getName(void *handle)
boost::shared_ptr< SchunkCanopenHardwareInterface > m_hardware_interface
boost::shared_ptr< const Goal > getGoal() const
virtual const char * what() const _GLIBCXX_USE_NOEXCEPT
bool closeBrakes(std_srvs::TriggerRequest &req, std_srvs::TriggerResponse &resp)
Close the brakes on all nodes. Use this when the device is standing still for a longer time to reduce...
bool homeNodesCanIds(schunk_canopen_driver::HomeWithIDsRequest &req, schunk_canopen_driver::HomeWithIDsResponse &resp)
Perform a reset offset for a given list of nodes. You should call this service, after driving the dev...
The DS402Group class is the base class for canOpen devices implementing the DS402 device protocol (mo...
boost::thread m_ros_control_thread
bool quickStopNodes(std_srvs::TriggerRequest &req, std_srvs::TriggerResponse &resp)
Performs a quick stop on all nodes. You should prefer this service call to aborting the followJointTr...
void trajThread(actionlib::ServerGoalHandle< control_msgs::FollowJointTrajectoryAction > &gh)
Control loop thread when not using ros_control.
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
ros::ServiceServer m_quick_stop_service
bool use_blending
If set to true, the device will blend over to a new setpoint. Defaults to true.
PDO related exceptions go here.
void initDevices()
Function that actually initializes the devices. Will get called either on startup (if autostart is al...
void setCanceled(const Result &result=Result(), const std::string &text=std::string(""))
#define LOGGING_WARNING_C(streamname, classname, arg)
unsigned int sleep(unsigned int seconds)
The CanOpenController class is the main entry point for any calls to the canOpen System.
void setAccepted(const std::string &text=std::string(""))
ds402::ProfilePositionModeConfiguration m_ppm_config
bool initDevicesCb(std_srvs::TriggerRequest &req, std_srvs::TriggerResponse &resp)
Triggers initialization of the canopen devices.
int main(int argc, char **argv)
void setSucceeded(const Result &result=Result(), const std::string &text=std::string(""))
bool use_relative_targets
This parameter influences the interpretation of new set points. If set to true, new set point positio...
This exception is thrown if a requested node or node group does not exist.
float profile_acceleration
This will be used for both acceleration ramps.
ROSCPP_DECL bool get(const std::string &key, std::string &s)
ThreadStream & endl(ThreadStream &stream)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
ros::Publisher m_joint_pub
std::map< std::string, uint8_t > m_joint_name_mapping
ros::ServiceServer m_home_service_all
ros::ServiceServer m_init_service
ros::ServiceServer m_close_brakes_service
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool enableNodes(std_srvs::TriggerRequest &req, std_srvs::TriggerResponse &resp)
This service call enables the devices after a fault, a quick stop or simply when the brakes have been...
If something goes wrong with the host's CAN controller, this exception will be used.
#define ROS_WARN_STREAM(args)
ros::ServiceServer m_home_service_canopen_ids
void setAborted(const Result &result=Result(), const std::string &text=std::string(""))
void cancelCB(actionlib::ServerGoalHandle< control_msgs::FollowJointTrajectoryAction > gh)
boost::shared_ptr< controller_manager::ControllerManager > m_controller_manager
virtual const char * what() const _GLIBCXX_USE_NOEXCEPT
ros::Publisher m_current_pub
#define ROS_INFO_STREAM(args)
float profile_velocity
Final velocity.
This class defines a ros-control hardware interface.
bool getParam(const std::string &key, std::string &s) const
std::string m_traj_controller_name
bool homeNodesJointNames(schunk_canopen_driver::HomeWithJointNamesRequest &req, schunk_canopen_driver::HomeWithJointNamesResponse &resp)
Perform a reset offset for a given list of nodes. You should call this service, after driving the dev...
ros::ServiceServer m_home_service_joint_names
virtual const char * what() const _GLIBCXX_USE_NOEXCEPT
#define ROS_ERROR_STREAM(args)
void rosControlLoop()
When using ros_control this will perform the control loop in a separate thread.
bool change_set_immediately
If this is set to true the device will not ramp down at a setpoint if a following one is given...
ROSCPP_DECL void spinOnce()
Class that holds devices according to the DS402 (drives and motion control) specification.
ros::NodeHandle m_priv_nh
boost::thread m_traj_thread
int usleep(unsigned long useconds)