spi_sensor_read_controller.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2016, Shadow Robot Company, All rights reserved.
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 3.0 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library.
00016  */
00017 
00023 #include "sr_ronex_controllers/spi_sensor_read_controller.h"
00024 #include "pluginlib/class_list_macros.h"
00025 #include "std_msgs/Float64MultiArray.h"
00026 #include <utility>
00027 #include <stdexcept>
00028 #include <string>
00029 #include <vector>
00030 
00031 PLUGINLIB_EXPORT_CLASS(ronex::SPISensorReadController, controller_interface::ControllerBase)
00032 
00033 namespace ronex
00034 {
00035 const int SPISensorReadController::default_spi_channel_ = 1;
00036 const size_t SPISensorReadController::sensor_message_length_ = 2;
00037 const size_t SPISensorReadController::spi_mode_ = 1;
00038 const double SPISensorReadController::publish_rate_ = 100;
00039 
00040 
00041 bool SPISensorReadController::init(ros_ethercat_model::RobotStateInterface* robot, ros::NodeHandle &n)
00042 {
00043   if ( !pre_init_(robot, n) )
00044     return false;
00045   chip_select_masks_.resize(NUM_SPI_OUTPUTS);
00046   chip_select_masks_[0] = PIN_OUTPUT_STATE_CS_0;
00047   chip_select_masks_[1] = PIN_OUTPUT_STATE_CS_1;
00048   chip_select_masks_[2] = PIN_OUTPUT_STATE_CS_2;
00049   chip_select_masks_[3] = PIN_OUTPUT_STATE_CS_3;
00050   std::string ronex_id;
00051   node_.getParam("ronex_id", ronex_id);
00052   std::stringstream topic_name;
00053   topic_name << "sensor_message_" << ronex_id;
00054   standard_commands_.assign(NUM_SPI_OUTPUTS, SplittedSPICommand());
00055 
00056   if (!n.hasParam("SPI_sensor_channel"))
00057   {
00058     ROS_WARN_STREAM("No SPI channel is defined. Will assume a single channel " << default_spi_channel_);
00059     spi_channel_.push_back(default_spi_channel_);
00060   }
00061   else
00062   {
00063     n.getParam("SPI_sensor_channel", spi_channel_);
00064   }
00065   for (std::vector<int>::const_iterator channel_iter = spi_channel_.begin(); channel_iter != spi_channel_.end();
00066         ++channel_iter)
00067   {
00068     if (*channel_iter < 0 || *channel_iter > NUM_SPI_OUTPUTS)
00069     {
00070       ROS_FATAL("spi channel parameter should be larger than or equal 0 "
00071                 "and smaller than number of SPI outputs");
00072       return false;
00073     }
00074     standard_commands_[*channel_iter].packet.num_bytes = sensor_message_length_;
00075     topic_name << "_" << *channel_iter;
00076   }
00077 
00078   sensor_data_publisher_.init(n, topic_name.str(), 1);
00079   first_run_ = true;
00080 
00081   return true;
00082 }
00083 
00084 void SPISensorReadController::update(const ros::Time& time, const ros::Duration& dur)
00085 {
00086   if (first_run_)  // configuring the channel for communication
00087   {
00088     first_run_ = false;
00089     spi_->command_->command_type = static_cast<int16u>(1);
00090 
00091     // setting up spi
00092     for (std::vector<int>::const_iterator channel_iter = spi_channel_.begin(); channel_iter != spi_channel_.end();
00093           ++channel_iter)
00094     {
00095       standard_commands_[*channel_iter].packet.SPI_config = 1;
00096       standard_commands_[*channel_iter].packet.clock_divider = static_cast<int16u>(16);
00097       standard_commands_[*channel_iter].packet.SPI_config |= static_cast<int16u>(0);
00098       standard_commands_[*channel_iter].packet.SPI_config |= 0;
00099       standard_commands_[*channel_iter].packet.SPI_config |= 0;
00100       standard_commands_[*channel_iter].packet.inter_byte_gap = 0;
00101       cmd_pin_output_states_pre_ = 0;
00102       cmd_pin_output_states_post_ |= chip_select_masks_[*channel_iter];
00103     }
00104   }
00105   // the command will be sent at the end of the iteration,
00106   // removing the command from the queue but not freeing the
00107   // memory yet
00108   sensor_msg_.data.resize(spi_channel_.size());
00109   for (std::vector<int>::const_iterator channel_iter = spi_channel_.begin(); channel_iter != spi_channel_.end();
00110         ++channel_iter)
00111   {
00112     // Check if we need to update a status
00113     if (status_queue_[*channel_iter].size() > 0)
00114     {
00115       // check if two cycles has passed since the cmd was received so it contains its answer
00116       if (loop_count_ == status_queue_[*channel_iter].front().second.loop_number + 2 )
00117       {
00118         // the response has not been received. If the command type is NORMAL
00119         // then the response can be updated (it's INVALID until the SPI responds)
00120         if (spi_->state_->command_type == RONEX_COMMAND_02000002_COMMAND_TYPE_NORMAL)
00121         {
00122           status_queue_[*channel_iter].back().second.received = true;
00123           status_queue_[*channel_iter].back().second.packet =
00124               SPI_PACKET_IN(spi_->state_->info_type.status_data.spi_in[*channel_iter]);
00125           unsigned int high_byte =
00126               static_cast<unsigned int>(status_queue_[*channel_iter].back().second.packet.data_bytes[0] & 0x3F);
00127           unsigned int low_byte =
00128               static_cast<unsigned int>(status_queue_[*channel_iter].back().second.packet.data_bytes[1]);
00129           ROS_DEBUG_STREAM("sensor value is " << (high_byte << 8 | low_byte));
00130           // channel_iter - spi_channel_.begin() is the index of channel_iter in vector
00131           sensor_msg_.data[channel_iter - spi_channel_.begin()] =
00132               (static_cast<double>((high_byte << 8 | low_byte) *2.0*M_PI) / 16384);
00133           status_queue_[*channel_iter].pop();
00134         }
00135       }
00136     }
00137     try
00138     {
00139       standard_commands_[*channel_iter].packet.data_bytes[0] = 0xFF;
00140       standard_commands_[*channel_iter].packet.data_bytes[1] = 0xFF;
00141       command_queue_[*channel_iter].push(standard_commands_[*channel_iter]);
00142     }
00143     catch(...)
00144     {
00145       ROS_ERROR_STREAM("something bad happened");
00146     }
00147     try
00148     {
00149       status_queue_[*channel_iter].push(std::pair<SplittedSPICommand, SPIResponse>());
00150       status_queue_[*channel_iter].back().first = command_queue_[*channel_iter].front();
00151       status_queue_[*channel_iter].back().second.received = false;
00152       status_queue_[*channel_iter].back().second.loop_number = loop_count_;
00153 
00154       // now we copy the command to the hardware interface
00155       copy_splitted_to_cmd_(*channel_iter);
00156     }
00157     catch(...)
00158     {
00159       ROS_ERROR_STREAM("error while copy_splitted_to_cmd_");
00160     }
00161     command_queue_[*channel_iter].pop();
00162   }
00163 
00164   if (publish_rate_ > 0.0 && last_publish_time_ + ros::Duration(1.0/publish_rate_) < time)
00165   {
00166     if (sensor_data_publisher_.trylock())
00167     {
00168       last_publish_time_ = last_publish_time_ + ros::Duration(1.0/publish_rate_);
00169 
00170       sensor_data_publisher_.msg_ = sensor_msg_;
00171       sensor_data_publisher_.unlockAndPublish();
00172     }
00173   }
00174   loop_count_++;
00175 }
00176 std::vector<double> SPISensorReadController::get_sensor_value()
00177 {
00178   return sensor_msg_.data;
00179 }
00180 
00181 std::vector<int> SPISensorReadController::get_spi_channel()
00182 {
00183   return spi_channel_;
00184 }
00185 } /* namespace ronex */


sr_ronex_controllers
Author(s): Ugo Cupcic, Toni Oliver, Mark Pitchless
autogenerated on Thu Jun 6 2019 21:22:06