00001 //================================================================================================= 00002 // Copyright (c) 2012, Johannes Meyer, TU Darmstadt 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 Flight Systems and Automatic Control group, 00013 // TU Darmstadt, nor the names of its contributors may be used to 00014 // endorse or promote products derived from this software without 00015 // specific prior written permission. 00016 00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00018 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00019 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00020 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 //================================================================================================= 00028 00029 #include <rosmatlab/publisher.h> 00030 #include <rosmatlab/exception.h> 00031 #include <rosmatlab/options.h> 00032 #include <rosmatlab/conversion.h> 00033 00034 #include <introspection/message.h> 00035 00036 #include <ros/topic_manager.h> 00037 00038 namespace rosmatlab { 00039 00040 template <> const char *Object<Publisher>::class_name_ = "ros.Publisher"; 00041 00042 Publisher::Publisher() 00043 : Object<Publisher>(this) 00044 { 00045 } 00046 00047 Publisher::Publisher(int nrhs, const mxArray *prhs[]) 00048 : Object<Publisher>(this) 00049 { 00050 if (nrhs > 0) advertise(nrhs, prhs); 00051 } 00052 00053 Publisher::~Publisher() { 00054 shutdown(); 00055 } 00056 00057 bool Publisher::advertise(int nrhs, const mxArray *prhs[]) 00058 { 00059 if (nrhs < 2) { 00060 throw Exception("Publisher: advertise needs at least two arguments"); 00061 } 00062 00063 options_ = ros::AdvertiseOptions(); 00064 for(int i = 0; i < nrhs; i++) { 00065 switch(i) { 00066 case 0: 00067 if (!Options::isString(prhs[i])) throw Exception("Publisher: need a topic as 1st argument"); 00068 options_.topic = Options::getString(prhs[i]); 00069 break; 00070 00071 case 1: 00072 if (!Options::isString(prhs[i])) throw Exception("Publisher: need a datatype as 2nd argument"); 00073 options_.datatype = Options::getString(prhs[i]); 00074 break; 00075 00076 case 2: 00077 if (!Options::isDoubleScalar(prhs[i])) throw Exception("Publisher: need a queue size as 3rd argument (optional)"); 00078 options_.queue_size = Options::getDoubleScalar(prhs[i]); 00079 break; 00080 00081 case 3: 00082 if (!Options::isLogicalScalar(prhs[i]) && !Options::isDoubleScalar(prhs[i])) throw Exception("Publisher: need logical latch as 4th argument (optional)"); 00083 options_.latch = Options::getLogicalScalar(prhs[i]); 00084 break; 00085 00086 default: 00087 throw Exception("Publisher: too many arguments"); 00088 } 00089 } 00090 00091 introspection_ = cpp_introspection::messageByDataType(options_.datatype); 00092 if (!introspection_) throw Exception("Publisher: unknown datatype '" + options_.datatype + "'"); 00093 options_.md5sum = introspection_->getMD5Sum(); 00094 options_.message_definition = introspection_->getDefinition(); 00095 options_.has_header = introspection_->hasHeader(); 00096 00097 *this = node_handle_.advertise(options_); 00098 return *this; 00099 } 00100 00101 static ros::SerializedMessage serialize(const cpp_introspection::MessagePtr& message) 00102 { 00103 // mexPrintf("Serializer called for a message of type %s...\n", message->getDataType()); 00104 return message->serialize(); 00105 } 00106 00107 00108 void Publisher::publish(int nrhs, const mxArray *prhs[]) 00109 { 00110 if (nrhs < 1) throw Exception("Publisher: publish needs at least one argument"); 00111 if (!introspection_) throw Exception("Publisher: unknown message type"); 00112 00113 std::size_t length = mxGetNumberOfElements(prhs[0]); 00114 MessagePtr message; 00115 ros::SerializedMessage m; 00116 m.type_info = &(introspection_->getTypeId()); 00117 Conversion conversion(introspection_); 00118 00119 for(std::size_t i = 0; i < length; ++i) { 00120 message = Conversion(introspection_).fromMatlab(prhs[0], i); 00121 if (!message) throw Exception("Publisher: failed to parse message of type " + options_.datatype); 00122 m.message = message->getConstInstance(); 00123 // mexPrintf("Publishing on topic %s...\n", ros::Publisher::getTopic().c_str()); 00124 ros::TopicManager::instance()->publish(ros::Publisher::getTopic(), boost::bind(&serialize, message), m); 00125 } 00126 00127 } 00128 00129 mxArray *Publisher::getTopic() const 00130 { 00131 return mxCreateString(ros::Publisher::getTopic().c_str()); 00132 } 00133 00134 mxArray *Publisher::getNumSubscribers() const 00135 { 00136 return mxCreateDoubleScalar(ros::Publisher::getNumSubscribers()); 00137 } 00138 00139 mxArray *Publisher::isLatched() const 00140 { 00141 throw Exception("ros::Publisher::isLatched is currently not implemented in roscpp (see https://github.com/ros/ros_comm/pull/1)"); 00142 // return mxCreateLogicalScalar(ros::Publisher::isLatched()); 00143 return mxCreateLogicalScalar(false); 00144 } 00145 00146 } // namespace rosmatlab