00001 /* 00002 * Copyright (c) 2011, A.M.Howard, S.Williams 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * * Redistributions of source code must retain the above copyright 00008 * notice, this list of conditions and the following disclaimer. 00009 * * Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * * Neither the name of the <organization> nor the 00013 * names of its contributors may be used to endorse or promote products 00014 * derived from this software without specific prior written permission. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00017 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00018 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 00020 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00021 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00022 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00023 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00025 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 /* 00028 * example3_driver.cpp 00029 * 00030 * Created on: Nov 27, 2011 00031 * Author: Stephen Williams 00032 */ 00033 00034 #include <actuator_array_example/example3_driver.h> 00035 00036 namespace actuator_array_example 00037 { 00038 00039 /* ******************************************************** */ 00040 Example3Driver::Example3Driver() 00041 { 00042 // For normal drivers, you would read custom configuration settings from the parameter 00043 // server here. Common examples include the port name over which you are communicating, 00044 // or the baud rate for the serial port. For this simple driver, no additional information 00045 // is required. 00046 00047 // For example purposes, we are going to call the base class methods manually. 00048 00049 // Create a private node handle to read parameter settings 00050 ros::NodeHandle node = ros::NodeHandle(); 00051 ros::NodeHandle private_node = ros::NodeHandle("~"); 00052 00053 // Get the robot_description parameter name from the parameter server 00054 private_node.param("robot_description_parameter", robot_description_parameter_, std::string("robot_description")); 00055 00056 // Read in additional joint information from the robot description and store it in the urdf model 00057 ActuatorArrayDriver::parse_urdf(node); 00058 00059 // Fill in the joints_ map from the 'joints' list on the parameter server 00060 ActuatorArrayDriver::parse_actuator_list(private_node); 00061 00062 // Advertise services and subscribe to topics 00063 ActuatorArrayDriver::advertise_and_subscribe(node); 00064 00065 } 00066 00067 /* ******************************************************** */ 00068 Example3Driver::~Example3Driver() 00069 { 00070 } 00071 00072 /* ******************************************************** */ 00073 bool Example3Driver::init_actuator_(const std::string& joint_name, Example3JointProperties& joint_properties, XmlRpc::XmlRpcValue& joint_data) 00074 { 00075 // Read the additional actuator fields of 'channel' and 'home' 00076 // from the configuration file data, then create and store a dummy_servo 00077 // with those parameters 00078 00079 // Read custom data from the XMLRPC struct 00080 if (joint_data.hasMember("channel")) 00081 { 00082 joint_properties.channel = (int) joint_data["channel"]; 00083 } 00084 00085 if (joint_data.hasMember("home")) 00086 { 00087 joint_properties.home = (double) joint_data["home"]; 00088 } 00089 00090 // Create a dummy actuator object and store in a container 00091 actuators_[joint_properties.channel] = DummyActuator(joint_properties.min_position, joint_properties.max_position, joint_properties.max_velocity, joint_properties.home); 00092 00093 return true; 00094 } 00095 00096 /* ******************************************************** */ 00097 bool Example3Driver::read_(ros::Time ts) 00098 { 00099 // Calculate the time from the last update 00100 double dt = (ts - previous_time_).toSec(); 00101 00102 // Loop through each joint and request the current status 00103 for (unsigned int i = 0; i < joint_state_msg_.name.size(); ++i) 00104 { 00105 // Look up the channel number from the JointProperties using the joint name 00106 int channel = joints_[command_msg_.name[i]].channel; 00107 00108 // Update the simulated state of each actuator by dt seconds 00109 actuators_[channel].update(dt); 00110 00111 // Query the current state of each actuator 00112 joint_state_msg_.position[i] = actuators_[channel].getPosition(); 00113 joint_state_msg_.velocity[i] = actuators_[channel].getVelocity(); 00114 joint_state_msg_.effort[i] = actuators_[channel].getMaxTorque(); 00115 } 00116 00117 joint_state_msg_.header.stamp = ts; 00118 previous_time_ = ts; 00119 00120 return true; 00121 } 00122 00123 /* ******************************************************** */ 00124 bool Example3Driver::command_() 00125 { 00126 // Loop through each joint in the command message and send the 00127 // corresponding servo the desired behavior 00128 for (unsigned int i = 0; i < command_msg_.name.size(); ++i) 00129 { 00130 // Look up the channel number from the JointProperties using the joint name 00131 int channel = joints_[command_msg_.name[i]].channel; 00132 00133 // Send the actuator the desired position and velocity 00134 actuators_[channel].setVelocity(command_msg_.velocity[i]); 00135 actuators_[channel].setPosition(command_msg_.position[i]); 00136 } 00137 00138 return true; 00139 } 00140 00141 /* ******************************************************** */ 00142 bool Example3Driver::stop_() 00143 { 00144 // Loop through each joint and send the stop command 00145 for (unsigned int i = 0; i < command_msg_.name.size(); ++i) 00146 { 00147 // Look up the channel number from the JointProperties using the joint name 00148 int channel = joints_[command_msg_.name[i]].channel; 00149 00150 // Tell the actuator to stop 00151 actuators_[channel].stop(); 00152 } 00153 00154 return true; 00155 } 00156 00157 /* ******************************************************** */ 00158 bool Example3Driver::home_() 00159 { 00160 // Loop through each joint and send the stop command 00161 for (unsigned int i = 0; i < command_msg_.name.size(); ++i) 00162 { 00163 // Look up the channel number from the JointProperties using the joint name 00164 int channel = joints_[command_msg_.name[i]].channel; 00165 00166 // Tell the actuator to go to the home position 00167 actuators_[channel].home(); 00168 } 00169 00170 return true; 00171 } 00172 00173 } // end namespace actuator_array_example_driver 00174 00175 00176 00177 /* ******************************************************** */ 00178 int main(int argc, char** argv) 00179 { 00180 ros::init(argc, argv, "example3_driver"); 00181 00182 // Create an Example2 Driver Object 00183 actuator_array_example::Example3Driver driver; 00184 00185 // Put the driver in an infinite read-publish loop using the base class's 'spin' function 00186 driver.spin(); 00187 00188 return 0; 00189 }