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 * example2_driver.cpp 00029 * 00030 * Created on: Nov 27, 2011 00031 * Author: Stephen Williams 00032 */ 00033 00034 00035 #include <actuator_array_example/example2_driver.h> 00036 00037 namespace actuator_array_example 00038 { 00039 00040 /* ******************************************************** */ 00041 Example2Driver::Example2Driver() 00042 { 00043 // For normal drivers, you would read custom configuration settings from the parameter 00044 // server here. Common examples include the port name over which you are communicating, 00045 // or the baud rate for the serial port. For this very simple example, we don't actually 00046 // need any additional configuration. 00047 00048 // For this example, we will call the convenience init() script of the base class. This 00049 // sets up the list of joints, subscribes to needed topics, advertises services, and 00050 // calls the custom init_actuator_ function each actuator 00051 ActuatorArrayDriver::init(); 00052 00053 // The creation of the array of actuators is now performed in the 'init_actuator_' function 00054 } 00055 00056 /* ******************************************************** */ 00057 Example2Driver::~Example2Driver() 00058 { 00059 } 00060 00061 /* ******************************************************** */ 00062 bool Example2Driver::init_actuator_(const std::string& joint_name, Example2JointProperties& joint_properties, XmlRpc::XmlRpcValue& joint_data){ 00063 // Read the additional actuator fields of 'channel' and 'home' 00064 // from the configuration file data, then create and store a dummy_servo 00065 // with those parameters 00066 00067 // Read custom data from the XMLRPC struct 00068 if (joint_data.hasMember("channel")) 00069 { 00070 joint_properties.channel = (int) joint_data["channel"]; 00071 } 00072 00073 if (joint_data.hasMember("home")) 00074 { 00075 joint_properties.home = (double) joint_data["home"]; 00076 } 00077 00078 // Create a dummy actuator object and store in a container 00079 // Here we are hard coding the min and max joint positions and max velocity. 00080 // In Example3, this will be read from the robot description. Alternatively, 00081 // we could have included additional properties in the YAML file and read them 00082 // as above 00083 actuators_[joint_properties.channel] = DummyActuator(-1.57, 1.57, 10.0, joint_properties.home); 00084 00085 return true; 00086 } 00087 00088 /* ******************************************************** */ 00089 bool Example2Driver::read_(ros::Time ts) 00090 { 00091 // Calculate the time from the last update 00092 double dt = (ts - previous_time_).toSec(); 00093 00094 // Loop through each joint and request the current status 00095 for (unsigned int i = 0; i < joint_state_msg_.name.size(); ++i) 00096 { 00097 // Look up the channel number from the JointProperties using the joint name 00098 int channel = joints_[command_msg_.name[i]].channel; 00099 00100 // Update the simulated state of each actuator by dt seconds 00101 actuators_[channel].update(dt); 00102 00103 // Query the current state of each actuator 00104 joint_state_msg_.position[i] = actuators_[channel].getPosition(); 00105 joint_state_msg_.velocity[i] = actuators_[channel].getVelocity(); 00106 joint_state_msg_.effort[i] = actuators_[channel].getMaxTorque(); 00107 } 00108 00109 joint_state_msg_.header.stamp = ts; 00110 previous_time_ = ts; 00111 00112 return true; 00113 } 00114 00115 /* ******************************************************** */ 00116 bool Example2Driver::command_() 00117 { 00118 // Loop through each joint in the command message and send the 00119 // corresponding servo the desired behavior 00120 for (unsigned int i = 0; i < command_msg_.name.size(); ++i) 00121 { 00122 // Look up the channel number from the JointProperties using the joint name 00123 int channel = joints_[command_msg_.name[i]].channel; 00124 00125 // Send the actuator the desired position and velocity 00126 actuators_[channel].setVelocity(command_msg_.velocity[i]); 00127 actuators_[channel].setPosition(command_msg_.position[i]); 00128 } 00129 00130 return true; 00131 } 00132 00133 /* ******************************************************** */ 00134 bool Example2Driver::stop_() 00135 { 00136 // Loop through each joint and send the stop command 00137 for (unsigned int i = 0; i < command_msg_.name.size(); ++i) 00138 { 00139 // Look up the channel number from the JointProperties using the joint name 00140 int channel = joints_[command_msg_.name[i]].channel; 00141 00142 // Tell the actuator to stop 00143 actuators_[channel].stop(); 00144 } 00145 00146 return true; 00147 } 00148 00149 /* ******************************************************** */ 00150 bool Example2Driver::home_() 00151 { 00152 // Loop through each joint and send the stop command 00153 for (unsigned int i = 0; i < command_msg_.name.size(); ++i) 00154 { 00155 // Look up the channel number from the JointProperties using the joint name 00156 int channel = joints_[command_msg_.name[i]].channel; 00157 00158 // Tell the actuator to go to the home position 00159 actuators_[channel].home(); 00160 } 00161 00162 return true; 00163 } 00164 00165 } // end namespace actuator_array_example 00166 00167 00168 00169 /* ******************************************************** */ 00170 int main(int argc, char** argv) 00171 { 00172 ros::init(argc, argv, "example2_driver"); 00173 00174 // Create an Example2 Driver Object 00175 actuator_array_example::Example2Driver driver; 00176 00177 // Put the driver in an infinite read-publish loop using the base class's 'spin' function 00178 driver.spin(); 00179 00180 return 0; 00181 }