Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GPIO states #156

Closed
domire8 opened this issue Feb 23, 2024 · 1 comment · Fixed by #172, #173 or #158
Closed

GPIO states #156

domire8 opened this issue Feb 23, 2024 · 1 comment · Fixed by #172, #173 or #158
Assignees

Comments

@domire8
Copy link
Member

domire8 commented Feb 23, 2024

state_representation comes with a variety of common state types, e.g. JointState, CartesianState, Parameter and more. As robotic applications become more and more complex, engineers are also confronted with GPIOs (General Purpose Input/Outputs). GPIOs are currently not supported with their own class. I would like to change that and I propose the following class name and interfaces

class GPIOGroup : public State {
public:
  /**
   * @brief Empty constructor for a GPIO group
   */
  GPIOGroup();

  /**
   * @brief Constructor with name and list of GPIO names provided
   * @param gpio_name The name of the associated GPIO group
   * @param gpio_names List of GPIO names
   */
  GPIOGroup(const std::string& group_name, const std::vector<std::string>& gpio_names);

  /**
   * @brief Getter of the size from the names attribute
   */
  unsigned int get_size() const;

  /**
   * @brief Getter of the names attribute
   * @return The vector of strings containing the GPIO names
   */
  const std::vector<std::string>& get_names() const;

  /**
   * @brief Get GPIO index by the name of the GPIO, if it exists
   * @param gpio_name The name of the desired GPIO
   * @throws GPIONotFoundException if the desired GPIO doesn't exist
   * @return The index of the GPIO, if it exists
   */
  unsigned int get_gpio_index(const std::string& gpio_name) const;

  /**
   * @brief Get the value of a GPIO by its name, if it exists
   * @param gpio_name The name of the GPIO
   * @throws GPIONotFoundException if the desired GPIO doesn't exist
   * @return The value of the GPIO, if it exists
   */
  double get_value(const std::string& gpio_name) const;

  /**
   * @brief Get the value of a GPIO by its index, if it exists
   * @param gpio_index The index of the GPIO
   * @throws GPIONotFoundException if the desired GPIO doesn't exist
   * @return The value of the GPIO, if it exists
   */
  double get_value(unsigned int gpio_index) const;

  /**
   * @brief Returns the data of the GPIO group
   * @return The data vector
   */
  Eigen::VectorXd data() const;

  /**
   * @brief Returns the data of the GPIO group an Eigen array
   * @return The data array
   */
  Eigen::ArrayXd array() const;

  /**
   * @brief Setter of the names attribute
   * @param names The vector of strings containing the GPIO names
   */
  void set_names(const std::vector<std::string>& names);

  /**
   * @brief Set the value of a GPIO by its name
   * @param value The value of the GPIO
   * @param gpio_name The name of the GPIO
   * @throws GPIONotFoundException if the desired GPIO doesn't exist
   */
  void set_value(double value, const std::string& gpio_name);

  /**
   * @brief Set the value of a GPIO by its index
   * @param value The value of the GPIO
   * @param gpio_index The index of the GPIO
   * @throws GPIONotFoundException if the desired GPIO doesn't exist
   */
  void set_value(double value, unsigned int gpio_index);

  /**
   * @brief Set the data of the GPIO group from a single Eigen vector
   * @param The data vector
   */
  void set_data(const Eigen::VectorXd& data) override;

  /**
   * @brief Set the data of the GPIO group from a single std vector
   * @param The data vector
   */
  void set_data(const std::vector<double>& data) override;

  /**
   * @copybrief State::reset
   */
  void reset() override;

  /**
   * @brief Check if the GPIO group is incompatible for operations with the state given as argument
   * @param state The state to check compatibility with
   */
  bool is_incompatible(const State& state) const override;

  /**
   * @brief Set the GPIO group to zero data
   */
  void set_zero();

  /**
   * @brief Return the GPIO data as a std vector
   * @return The GPIO data as a std vector
   */
  std::vector<double> to_std_vector() const;

private:
  std::vector<std::string> names_;///< names of the GPIOs
  Eigen::VectorXd data_;     ///< GPIO data
};

As one can see, I think of an GPIOGroup as a list of name-value GPIOs that are grouped under one state. A GPIO is rarely alone, most often a controller will have for example 4 or 8 digital inputs, indexed from 0 to 3 (7). Such a GPIO group would be constructed as GPIOGroup("digital_in", {"0", "1", "2", "3}).

The proposed class inherits from state_representation::State like all other classes and hence has all the well-known and proven interfaces like set_zero, set_data, is_incompatible as well as the standard getters and setters like set_value and get_value.

If this suggestion is approved, I would continue to implement these changes throughout the libraries, bindings and clproto such that a GPIOGroup object can be serialized and used in python just like any other class of state_representation.

@eeberhard
Copy link
Member

Completely agree, you know I was thinking about IO state years ago but we never knew how we would use it. Thanks for pushing on this.

As per our discussions, I think we should distinguish by bool and double value types and have methods accordingly. I would call two distinct classes DigitalIOState and AnalogIOState for bool and double respectively. They can derive from a templated GPIOState<T> which holds the std::map<std::string, T> and common methods.

The DigitalIOState should have methods is_false() / is_true() and set_false() / set_true() by name or index. The AnalogIOState should have methods get_value() and set_value() as you suggested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment