Coder Social home page Coder Social logo

atticusrussell / ros2_rpi_pwm_hardware_interface Goto Github PK

View Code? Open in Web Editor NEW
4.0 1.0 0.0 39 KB

hardware interface for PWM servos through Raspberry Pi's GPIO pins compatible with ros2_control framework

License: Apache License 2.0

CMake 15.46% C++ 69.43% C 11.53% Dockerfile 3.59%
gpio pwm raspberry-pi robotics ros ros2 ros2-control rpi3 rpi4 servo

ros2_rpi_pwm_hardware_interface's People

Contributors

atticusrussell avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar

ros2_rpi_pwm_hardware_interface's Issues

sync pre-commit and ament uncrustify formatting

pre-commit:

atticus@rospi-ssh-session [publish_ws] <5-sync-pre-commit-and-ament-uncrustify-formatting>
~/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface
check for added large files..............................................Passed
check python ast.....................................(no files to check)Skipped
check for case conflicts.................................................Passed
check docstring is first.............................(no files to check)Skipped
check for merge conflicts................................................Passed
check for broken symlinks................................................Passed
check xml................................................................Passed
check yaml...............................................................Passed
debug statements (python)............................(no files to check)Skipped
detect destroyed symlinks................................................Passed
detect private key.......................................................Passed
fix end of files.........................................................Failed
- hook id: end-of-file-fixer
- exit code: 1
- files were modified by this hook

Fixing include/rpi_pwm_hardware_interface/angular_servo.hpp

forbid submodules....................................(no files to check)Skipped
mixed line ending........................................................Passed
fix requirements.txt.................................(no files to check)Skipped
trim trailing whitespace.................................................Failed
- hook id: trailing-whitespace
- exit code: 1
- files were modified by this hook

Fixing README.md
Fixing src/angular_servo.cpp

fix utf-8 byte order marker..............................................Passed
pyupgrade............................................(no files to check)Skipped
pydocstyle...........................................(no files to check)Skipped
flake8...............................................(no files to check)Skipped
black................................................(no files to check)Skipped
clang-format.............................................................Failed
- hook id: clang-format
- files were modified by this hook
ament_cppcheck...........................................................Passed
ament_cpplint............................................................Failed
- hook id: ament_cpplint
- exit code: 1

Using '--root=/home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/include' argument

/home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/include/rpi_pwm_hardware_interface/angular_servo.hpp:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
/home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/include/rpi_pwm_hardware_interface/angular_servo.hpp:10:  Missing username in TODO; it should look like "// TODO(my_username): Stuff."  [readability/todo] [2]
Done processing /home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/include/rpi_pwm_hardware_interface/angular_servo.hpp

Done processing /home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp

Done processing /home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/include/rpi_pwm_hardware_interface/visibility_control.h

Using '--root=/home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/test' argument

Done processing /home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/test/test_rpi_pwm_hardware_interface.cpp

Category 'legal/copyright' errors found: 1
Category 'readability/todo' errors found: 1
Total errors found: 2
Using '--root=/home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/src' argument

/home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/src/angular_servo.cpp:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
/home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/src/angular_servo.cpp:8:  Do not use namespace using-directives.  Use using-declarations instead.  [build/namespaces] [5]
/home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/src/angular_servo.cpp:10:  Missing username in TODO; it should look like "// TODO(my_username): Stuff."  [readability/todo] [2]
Done processing /home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/src/angular_servo.cpp

/home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/src/rpi_pwm_hardware_interface.cpp:104:  Missing username in TODO; it should look like "// TODO(my_username): Stuff."  [readability/todo] [2]
Done processing /home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/src/rpi_pwm_hardware_interface.cpp

Category 'build/namespaces' errors found: 1
Category 'legal/copyright' errors found: 1
Category 'readability/todo' errors found: 2
Total errors found: 4

ament_lint_cmake.........................................................Passed
ament_copyright..........................................................Failed
- hook id: ament_copyright
- exit code: 1

No problems found, checked 1 files
No problems found, checked 1 files
include/rpi_pwm_hardware_interface/angular_servo.hpp: could not find copyright notice
src/angular_servo.cpp: could not find copyright notice
2 errors, checked 2 files
No problems found, checked 3 files

doc8.................................................(no files to check)Skipped
rst ``code`` is two backticks........................(no files to check)Skipped
rst directives end with two colons...................(no files to check)Skipped
rst ``inline code`` next to normal text..............(no files to check)Skipped
codespell................................................................Passed
pre-commit hook(s) made changes.
If you are seeing this message in CI, reproduce locally with: `pre-commit run --all-files`.
To run `pre-commit` as part of git workflow, use `pre-commit install`.
All changes made by hooks:
diff --git a/README.md b/README.md
index 18c4c59..3bb9a1b 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ ROS2 control hardware interface package for controlling a servo motor through a
 
 # Dependency on PiGPIO
 
-This hardware interface requires the pigpio library to interface with the pwm pins on the pi. The installation instructions for pigpio are: 
+This hardware interface requires the pigpio library to interface with the pwm pins on the pi. The installation instructions for pigpio are:
 wget https://github.com/joan2937/pigpio/archive/master.zip
 unzip master.zip
diff --git a/include/rpi_pwm_hardware_interface/angular_servo.hpp b/include/rpi_pwm_hardware_interface/angular_servo.hpp
index e584e52..c4ec773 100644
--- a/include/rpi_pwm_hardware_interface/angular_servo.hpp
+++ b/include/rpi_pwm_hardware_interface/angular_servo.hpp
@@ -1,31 +1,33 @@
 #pragma once
 
-class Servo {
-       public:
-               Servo(int pi, int pin);
-               int getPulseWidth();
-               void setPulseWidth(int pulseWidth);
+class Servo
+{
+public:
+  Servo(int pi, int pin);
+  int getPulseWidth();
+  void setPulseWidth(int pulseWidth);
 
-               int __pi; // TODO rename to indicate public, and pigpio pi
-       protected:
-               int __pin;
+  int __pi;  // TODO rename to indicate public, and pigpio pi
+protected:
+  int __pin;
 };
 
-class AngularServo : public Servo {
-       public:
-               AngularServo(int pi, int pin, float minAngle, float maxAngle, int minPulseWidthUs, int maxPulseWidthUs);
-               void setAngle(float angle);
-               int getAngle();
+class AngularServo : public Servo
+{
+public:
+  AngularServo(
+    int pi, int pin, float minAngle, float maxAngle, int minPulseWidthUs, int maxPulseWidthUs);
+  void setAngle(float angle);
+  int getAngle();
 
-       protected:
-               float __angle;
-               float __minAngle;
-               float __maxAngle;
-               int __minPulseWidthUs;
-               int __maxPulseWidthUs;
+protected:
+  float __angle;
+  float __minAngle;
+  float __maxAngle;
+  int __minPulseWidthUs;
+  int __maxPulseWidthUs;
 };
 
 bool isPigpiodRunning();
 void killPigpiod();
 void startPigpiod();
-
diff --git a/include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp b/include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp
index 6f96eac..3c95ac7 100644
--- a/include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp
+++ b/include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp
@@ -20,38 +20,37 @@
 #include <string>
 #include <vector>
 
-#include "rpi_pwm_hardware_interface/angular_servo.hpp"
-#include "rpi_pwm_hardware_interface/visibility_control.h"
-#include "hardware_interface/system_interface.hpp"
 #include "hardware_interface/handle.hpp"
 #include "hardware_interface/hardware_info.hpp"
+#include "hardware_interface/system_interface.hpp"
 #include "hardware_interface/types/hardware_interface_return_values.hpp"
 #include "rclcpp/macros.hpp"
 #include "rclcpp_lifecycle/state.hpp"
+#include "rpi_pwm_hardware_interface/angular_servo.hpp"
+#include "rpi_pwm_hardware_interface/visibility_control.h"
 
 namespace rpi_pwm_hardware_interface
 {
 class RPiPWMHardwareInterface : public hardware_interface::SystemInterface
 {
-
-struct ServoConfig
-{
-  std::string name = "";
-  int pin = 0;
-  int pi = 0;
-  float min_angle = 0.0;
-  float max_angle = 0.0;
-  int min_pulse_width_us = 0;
-  int max_pulse_width_us = 0;
-};
-
-struct ServoJoint
-{
-  std::string name = "";
-  std::unique_ptr<AngularServo> servo;
-  double pos = 0;
-  double cmd = 0;
-};
+  struct ServoConfig
+  {
+    std::string name = "";
+    int pin = 0;
+    int pi = 0;
+    float min_angle = 0.0;
+    float max_angle = 0.0;
+    int min_pulse_width_us = 0;
+    int max_pulse_width_us = 0;
+  };
+
+  struct ServoJoint
+  {
+    std::string name = "";
+    std::unique_ptr<AngularServo> servo;
+    double pos = 0;
+    double cmd = 0;
+  };
 
 public:
   TEMPLATES__ROS2_CONTROL__VISIBILITY_PUBLIC
diff --git a/src/angular_servo.cpp b/src/angular_servo.cpp
index 0ecbe12..34dbf15 100644
--- a/src/angular_servo.cpp
+++ b/src/angular_servo.cpp
@@ -1,114 +1,149 @@
-#include <iostream>
+#include "rpi_pwm_hardware_interface/angular_servo.hpp"
+#include <pigpiod_if2.h>
 #include <csignal>
 #include <cstdlib>
 #include <functional>
-#include <pigpiod_if2.h>
-#include "rpi_pwm_hardware_interface/angular_servo.hpp"
+#include <iostream>
 
 using namespace std;
 
-// TODO revisit private vs protected vars - maybe swap to private 
+// TODO revisit private vs protected vars - maybe swap to private
 
-Servo::Servo(int pi, int pin) {
-    __pi = pi;
-    __pin = pin;
-    int rc;
-    rc = set_mode(__pi, __pin, PI_OUTPUT);
-    if (rc < 0){
-        throw "Invalid GPIO pin or mode Error!";
-    }
-    
-    // initializing to zero with pigpio is no input
-    rc = set_servo_pulsewidth(__pi, __pin, 0);
-    if (rc < 0) {
-        throw "Invalid user GPIO pin or pulsewidth Error!";
-    }
+Servo::Servo(int pi, int pin)
+{
+  __pi = pi;
+  __pin = pin;
+  int rc;
+  rc = set_mode(__pi, __pin, PI_OUTPUT);
+  if (rc < 0)
+  {
+    throw "Invalid GPIO pin or mode Error!";
+  }
+
+  // initializing to zero with pigpio is no input
+  rc = set_servo_pulsewidth(__pi, __pin, 0);
+  if (rc < 0)
+  {
+    throw "Invalid user GPIO pin or pulsewidth Error!";
+  }
 }
 
-int Servo::getPulseWidth() {
-    int rc = get_servo_pulsewidth(__pi, __pin);
-    if (rc < 0) {
-        throw "Invalid user GPIO pin Error!";
-    }
-    return rc;
+int Servo::getPulseWidth()
+{
+  int rc = get_servo_pulsewidth(__pi, __pin);
+  if (rc < 0)
+  {
+    throw "Invalid user GPIO pin Error!";
+  }
+  return rc;
 }
 
-void Servo::setPulseWidth(int pulseWidth){
-    int rc = set_servo_pulsewidth(__pi, __pin, pulseWidth);
-    if (rc < 0) {
-        throw "Invalid user GPIO pin or pulsewidth Error!";
-    }
+void Servo::setPulseWidth(int pulseWidth)
+{
+  int rc = set_servo_pulsewidth(__pi, __pin, pulseWidth);
+  if (rc < 0)
+  {
+    throw "Invalid user GPIO pin or pulsewidth Error!";
+  }
 }
 
-AngularServo::AngularServo(int pi, int pin, float minAngle, float maxAngle, int minPulseWidthUs, int maxPulseWidthUs) : Servo(pi, pin) {
-            __minAngle = minAngle;
-            __maxAngle = maxAngle;
-            __minPulseWidthUs = minPulseWidthUs;
-            __maxPulseWidthUs = maxPulseWidthUs;
+AngularServo::AngularServo(
+  int pi, int pin, float minAngle, float maxAngle, int minPulseWidthUs, int maxPulseWidthUs)
+: Servo(pi, pin)
+{
+  __minAngle = minAngle;
+  __maxAngle = maxAngle;
+  __minPulseWidthUs = minPulseWidthUs;
+  __maxPulseWidthUs = maxPulseWidthUs;
 }
 
-void AngularServo::setAngle(float angle){
-    __angle = angle;
-    // make sure angle is within bounds
-    if (__angle < __minAngle){
-        __angle = __minAngle;
-    }
-    if (__angle > __maxAngle){
-        __angle = __maxAngle;
-    }
-    int pulseWidth = __minPulseWidthUs + (__angle - __minAngle) * (__maxPulseWidthUs - __minPulseWidthUs) / (__maxAngle - __minAngle);
+void AngularServo::setAngle(float angle)
+{
+  __angle = angle;
+  // make sure angle is within bounds
+  if (__angle < __minAngle)
+  {
+    __angle = __minAngle;
+  }
+  if (__angle > __maxAngle)
+  {
+    __angle = __maxAngle;
+  }
+  int pulseWidth = __minPulseWidthUs + (__angle - __minAngle) *
+                                         (__maxPulseWidthUs - __minPulseWidthUs) /
+                                         (__maxAngle - __minAngle);
 
-    setPulseWidth(pulseWidth);
+  setPulseWidth(pulseWidth);
 }
 
-int AngularServo::getAngle(){
-    int pulseWidth = getPulseWidth();
-    float angle = __minAngle + (pulseWidth - __minPulseWidthUs) * (__maxAngle - __minAngle) / (__maxPulseWidthUs - __minPulseWidthUs);
-    return angle;
+int AngularServo::getAngle()
+{
+  int pulseWidth = getPulseWidth();
+  float angle = __minAngle + (pulseWidth - __minPulseWidthUs) * (__maxAngle - __minAngle) /
+                               (__maxPulseWidthUs - __minPulseWidthUs);
+  return angle;
 }
 
-bool isPigpiodRunning() {
-    int result = system("pgrep pigpiod");
+bool isPigpiodRunning()
+{
+  int result = system("pgrep pigpiod");
 
-    if (result == 0) {
-        // pigpiod daemon is running
-        return true;
-    } else {
-        // pigpiod daemon is not running
-        return false;
-    }
+  if (result == 0)
+  {
+    // pigpiod daemon is running
+    return true;
+  }
+  else
+  {
+    // pigpiod daemon is not running
+    return false;
+  }
 }
 
-void killPigpiod() {
-    if (isPigpiodRunning()) {
-        int result = system("sudo killall pigpiod -q");
-
-        if (result == 0) {
-            // Successfully killed the pigpiod daemon
-            cout << "pigpiod daemon killed successfully" << endl;
-        } else {
-            // An error occurred while trying to kill the pigpiod daemon
-            cerr << "Error killing pigpiod daemon. Return code: " << result << endl;
-        }
-    } else {
-        cout << "pigpiod daemon is not running" << endl;
+void killPigpiod()
+{
+  if (isPigpiodRunning())
+  {
+    int result = system("sudo killall pigpiod -q");
+
+    if (result == 0)
+    {
+      // Successfully killed the pigpiod daemon
+      cout << "pigpiod daemon killed successfully" << endl;
+    }
+    else
+    {
+      // An error occurred while trying to kill the pigpiod daemon
+      cerr << "Error killing pigpiod daemon. Return code: " << result << endl;
     }
+  }
+  else
+  {
+    cout << "pigpiod daemon is not running" << endl;
+  }
 }
 
-void startPigpiod() {
-    if (!isPigpiodRunning()) {
-        cout << "pigpio daemon not running. attempting to start it." << endl;
-        system("sudo systemctl start pigpiod");
-        sleep(1);
-
-        if (isPigpiodRunning()) {
-            // Successfully started the pigpiod daemon
-            cout << "pigpiod daemon started successfully" << endl;
-        } else {
-            // An error occurred while trying to start the pigpiod daemon
-            cerr << "Error starting pigpiod daemon." << endl; 
-        }
-    } else {
-        cout << "pigpiod daemon is already running" << endl;
+void startPigpiod()
+{
+  if (!isPigpiodRunning())
+  {
+    cout << "pigpio daemon not running. attempting to start it." << endl;
+    system("sudo systemctl start pigpiod");
+    sleep(1);
+
+    if (isPigpiodRunning())
+    {
+      // Successfully started the pigpiod daemon
+      cout << "pigpiod daemon started successfully" << endl;
+    }
+    else
+    {
+      // An error occurred while trying to start the pigpiod daemon
+      cerr << "Error starting pigpiod daemon." << endl;
     }
+  }
+  else
+  {
+    cout << "pigpiod daemon is already running" << endl;
+  }
 }
diff --git a/src/rpi_pwm_hardware_interface.cpp b/src/rpi_pwm_hardware_interface.cpp
index 35af62d..92c574f 100644
--- a/src/rpi_pwm_hardware_interface.cpp
+++ b/src/rpi_pwm_hardware_interface.cpp
@@ -13,14 +13,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <limits>
 #include <pigpiod_if2.h>
 #include <unistd.h>
+#include <limits>
 #include <vector>
 
-#include "rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp"
 #include "hardware_interface/types/hardware_interface_type_values.hpp"
 #include "rclcpp/rclcpp.hpp"
+#include "rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp"
 
 namespace rpi_pwm_hardware_interface
 {
@@ -47,16 +47,20 @@ hardware_interface::CallbackReturn RPiPWMHardwareInterface::on_configure(
   const rclcpp_lifecycle::State & /*previous_state*/)
 {
   // TODO(anyone): prepare the robot to be ready for read calls and write calls of some interfaces
-  if (!isPigpiodRunning()) {
-        startPigpiod();
-    }
-
-  if (isPigpiodRunning()) {
-      // pigpiod daemon is running
-      return CallbackReturn::SUCCESS;
-  } else {
-      // pigpiod daemon is not running
-      return CallbackReturn::ERROR;
+  if (!isPigpiodRunning())
+  {
+    startPigpiod();
+  }
+
+  if (isPigpiodRunning())
+  {
+    // pigpiod daemon is running
+    return CallbackReturn::SUCCESS;
+  }
+  else
+  {
+    // pigpiod daemon is not running
+    return CallbackReturn::ERROR;
   }
 }
 
@@ -71,19 +75,20 @@ hardware_interface::CallbackReturn RPiPWMHardwareInterface::on_cleanup(
 std::vector<hardware_interface::StateInterface> RPiPWMHardwareInterface::export_state_interfaces()
 {
   std::vector<hardware_interface::StateInterface> state_interfaces;
-    state_interfaces.emplace_back(hardware_interface::StateInterface(
+  state_interfaces.emplace_back(hardware_interface::StateInterface(
     // TEST(anyone): insert correct interfaces
     rudder_joint_.name, hardware_interface::HW_IF_POSITION, &rudder_joint_.pos));
 
   return state_interfaces;
 }
 
-std::vector<hardware_interface::CommandInterface> RPiPWMHardwareInterface::export_command_interfaces()
+std::vector<hardware_interface::CommandInterface>
+RPiPWMHardwareInterface::export_command_interfaces()
 {
   std::vector<hardware_interface::CommandInterface> command_interfaces;
-    command_interfaces.emplace_back(hardware_interface::CommandInterface(
-      // TEST(anyone): insert correct interfaces
-      rudder_joint_.name, hardware_interface::HW_IF_POSITION, &rudder_joint_.cmd));
+  command_interfaces.emplace_back(hardware_interface::CommandInterface(
+    // TEST(anyone): insert correct interfaces
+    rudder_joint_.name, hardware_interface::HW_IF_POSITION, &rudder_joint_.cmd));
 
   return command_interfaces;
 }
@@ -94,12 +99,17 @@ hardware_interface::CallbackReturn RPiPWMHardwareInterface::on_activate(
   // TEST(anyone): prepare the robot to receive commands
   rudder_joint_.name = srv_cfg_.name;
   srv_cfg_.pi = pigpio_start(NULL, NULL);
-  if (srv_cfg_.pi < 0) {
-      // TODO maybe make ros log error
-      std::cerr << "Error initializing pigpio" << std::endl;
-      return CallbackReturn::ERROR;
-  } else {
-    rudder_joint_.servo = std::make_unique<AngularServo>(srv_cfg_.pi, srv_cfg_.pin, srv_cfg_.min_angle, srv_cfg_.max_angle, srv_cfg_.min_pulse_width_us, srv_cfg_.max_pulse_width_us);
+  if (srv_cfg_.pi < 0)
+  {
+    // TODO maybe make ros log error
+    std::cerr << "Error initializing pigpio" << std::endl;
+    return CallbackReturn::ERROR;
+  }
+  else
+  {
+    rudder_joint_.servo = std::make_unique<AngularServo>(
+      srv_cfg_.pi, srv_cfg_.pin, srv_cfg_.min_angle, srv_cfg_.max_angle,
+      srv_cfg_.min_pulse_width_us, srv_cfg_.max_pulse_width_us);
     return CallbackReturn::SUCCESS;
   }
 }

warning from building pigpio

Starting >>> rpi_pwm_hardware_interface
--- stderr: rpi_pwm_hardware_interface                                
/home/atticus/workspace/publish_ws/build/rpi_pwm_hardware_interface/pigpio-prefix/src/pigpio-build/setup.py:3: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives
  from distutils.core import setup
error: could not delete '/usr/local/lib/python3.10/dist-packages/pigpio.py': Permission denied
---
Finished <<< rpi_pwm_hardware_interface [22.1s]

Summary: 1 package finished [22.2s]
  1 package had stderr output: rpi_pwm_hardware_interface
/home/atticus/workspace/publish_ws

figure out or suppress in CMake or something.

format code according to ament uncrustify

doesn't pass colcon test's ament uncrustify. also need to work with pre-commit.

atticus@rospi-ssh-session [publish_ws] 
~/workspace/publish_ws
12:45:11 $ colcon test-result --verbose 

(omitting unrelated test failure)

- uncrustify
  <<< failure message
    -- run_test.py: invoking following command in '/home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface':
     - /opt/ros/humble/bin/ament_uncrustify --xunit-file /home/atticus/workspace/publish_ws/build/rpi_pwm_hardware_interface/test_results/rpi_pwm_hardware_interface/uncrustify.xunit.xml
    Code style divergence in file 'include/rpi_pwm_hardware_interface/angular_servo.hpp':
    
    --- include/rpi_pwm_hardware_interface/angular_servo.hpp
    +++ include/rpi_pwm_hardware_interface/angular_servo.hpp.uncrustify
    @@ -3,5 +3,6 @@
    -class Servo {
    -   public:
    -           Servo(int pi, int pin);
    -           int getPulseWidth();
    -           void setPulseWidth(int pulseWidth);
    +class Servo
    +{
    +public:
    +  Servo(int pi, int pin);
    +  int getPulseWidth();
    +  void setPulseWidth(int pulseWidth);
    @@ -9,3 +10,4 @@
    -           int __pi; // TODO rename to indicate public, and pigpio pi
    -   protected:
    -           int __pin;
    +  int __pi;               // TODO rename to indicate public, and pigpio pi
    +
    +protected:
    +  int __pin;
    @@ -14,5 +16,8 @@
    -class AngularServo : public Servo {
    -   public:
    -           AngularServo(int pi, int pin, float minAngle, float maxAngle, int minPulseWidthUs, int maxPulseWidthUs);
    -           void setAngle(float angle);
    -           int getAngle();
    +class AngularServo : public Servo
    +{
    +public:
    +  AngularServo(
    +    int pi, int pin, float minAngle, float maxAngle, int minPulseWidthUs,
    +    int maxPulseWidthUs);
    +  void setAngle(float angle);
    +  int getAngle();
    @@ -20,6 +25,6 @@
    -   protected:
    -           float __angle;
    -           float __minAngle;
    -           float __maxAngle;
    -           int __minPulseWidthUs;
    -           int __maxPulseWidthUs;
    +protected:
    +  float __angle;
    +  float __minAngle;
    +  float __maxAngle;
    +  int __minPulseWidthUs;
    +  int __maxPulseWidthUs;
    @@ -31 +35,0 @@
    -
    
    Code style divergence in file 'include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp':
    
    --- include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp
    +++ include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp.uncrustify
    @@ -37,10 +37,10 @@
    -struct ServoConfig
    -{
    -  std::string name = "";
    -  int pin = 0;
    -  int pi = 0;
    -  float min_angle = 0.0;
    -  float max_angle = 0.0;
    -  int min_pulse_width_us = 0;
    -  int max_pulse_width_us = 0;
    -};
    +  struct ServoConfig
    +  {
    +    std::string name = "";
    +    int pin = 0;
    +    int pi = 0;
    +    float min_angle = 0.0;
    +    float max_angle = 0.0;
    +    int min_pulse_width_us = 0;
    +    int max_pulse_width_us = 0;
    +  };
    @@ -48,7 +48,7 @@
    -struct ServoJoint
    -{
    -  std::string name = "";
    -  std::unique_ptr<AngularServo> servo;
    -  double pos = 0;
    -  double cmd = 0;
    -};
    +  struct ServoJoint
    +  {
    +    std::string name = "";
    +    std::unique_ptr<AngularServo> servo;
    +    double pos = 0;
    +    double cmd = 0;
    +  };
    
    Code style divergence in file 'src/angular_servo.cpp':
    
    --- src/angular_servo.cpp
    +++ src/angular_servo.cpp.uncrustify
    @@ -10 +10 @@
    -// TODO revisit private vs protected vars - maybe swap to private 
    +// TODO revisit private vs protected vars - maybe swap to private
    @@ -12,14 +12,15 @@
    -Servo::Servo(int pi, int pin) {
    -    __pi = pi;
    -    __pin = pin;
    -    int rc;
    -    rc = set_mode(__pi, __pin, PI_OUTPUT);
    -    if (rc < 0){
    -        throw "Invalid GPIO pin or mode Error!";
    -    }
    -    
    -    // initializing to zero with pigpio is no input
    -    rc = set_servo_pulsewidth(__pi, __pin, 0);
    -    if (rc < 0) {
    -        throw "Invalid user GPIO pin or pulsewidth Error!";
    -    }
    +Servo::Servo(int pi, int pin)
    +{
    +  __pi = pi;
    +  __pin = pin;
    +  int rc;
    +  rc = set_mode(__pi, __pin, PI_OUTPUT);
    +  if (rc < 0) {
    +    throw "Invalid GPIO pin or mode Error!";
    +  }
    +
    +  // initializing to zero with pigpio is no input
    +  rc = set_servo_pulsewidth(__pi, __pin, 0);
    +  if (rc < 0) {
    +    throw "Invalid user GPIO pin or pulsewidth Error!";
    +  }
    @@ -28,6 +29,7 @@
    -int Servo::getPulseWidth() {
    -    int rc = get_servo_pulsewidth(__pi, __pin);
    -    if (rc < 0) {
    -        throw "Invalid user GPIO pin Error!";
    -    }
    -    return rc;
    +int Servo::getPulseWidth()
    +{
    +  int rc = get_servo_pulsewidth(__pi, __pin);
    +  if (rc < 0) {
    +    throw "Invalid user GPIO pin Error!";
    +  }
    +  return rc;
    @@ -36,5 +38,6 @@
    -void Servo::setPulseWidth(int pulseWidth){
    -    int rc = set_servo_pulsewidth(__pi, __pin, pulseWidth);
    -    if (rc < 0) {
    -        throw "Invalid user GPIO pin or pulsewidth Error!";
    -    }
    +void Servo::setPulseWidth(int pulseWidth)
    +{
    +  int rc = set_servo_pulsewidth(__pi, __pin, pulseWidth);
    +  if (rc < 0) {
    +    throw "Invalid user GPIO pin or pulsewidth Error!";
    +  }
    @@ -43,5 +46,9 @@
    -AngularServo::AngularServo(int pi, int pin, float minAngle, float maxAngle, int minPulseWidthUs, int maxPulseWidthUs) : Servo(pi, pin) {
    -            __minAngle = minAngle;
    -            __maxAngle = maxAngle;
    -            __minPulseWidthUs = minPulseWidthUs;
    -            __maxPulseWidthUs = maxPulseWidthUs;
    +AngularServo::AngularServo(
    +  int pi, int pin, float minAngle, float maxAngle, int minPulseWidthUs,
    +  int maxPulseWidthUs)
    +: Servo(pi, pin)
    +{
    +  __minAngle = minAngle;
    +  __maxAngle = maxAngle;
    +  __minPulseWidthUs = minPulseWidthUs;
    +  __maxPulseWidthUs = maxPulseWidthUs;
    @@ -50,10 +57,12 @@
    -void AngularServo::setAngle(float angle){
    -    __angle = angle;
    -    // make sure angle is within bounds
    -    if (__angle < __minAngle){
    -        __angle = __minAngle;
    -    }
    -    if (__angle > __maxAngle){
    -        __angle = __maxAngle;
    -    }
    -    int pulseWidth = __minPulseWidthUs + (__angle - __minAngle) * (__maxPulseWidthUs - __minPulseWidthUs) / (__maxAngle - __minAngle);
    +void AngularServo::setAngle(float angle)
    +{
    +  __angle = angle;
    +  // make sure angle is within bounds
    +  if (__angle < __minAngle) {
    +    __angle = __minAngle;
    +  }
    +  if (__angle > __maxAngle) {
    +    __angle = __maxAngle;
    +  }
    +  int pulseWidth = __minPulseWidthUs + (__angle - __minAngle) *
    +    (__maxPulseWidthUs - __minPulseWidthUs) / (__maxAngle - __minAngle);
    @@ -61 +70 @@
    -    setPulseWidth(pulseWidth);
    +  setPulseWidth(pulseWidth);
    @@ -64,4 +73,6 @@
    -int AngularServo::getAngle(){
    -    int pulseWidth = getPulseWidth();
    -    float angle = __minAngle + (pulseWidth - __minPulseWidthUs) * (__maxAngle - __minAngle) / (__maxPulseWidthUs - __minPulseWidthUs);
    -    return angle;
    +int AngularServo::getAngle()
    +{
    +  int pulseWidth = getPulseWidth();
    +  float angle = __minAngle + (pulseWidth - __minPulseWidthUs) * (__maxAngle - __minAngle) /
    +    (__maxPulseWidthUs - __minPulseWidthUs);
    +  return angle;
    @@ -70,2 +81,17 @@
    -bool isPigpiodRunning() {
    -    int result = system("pgrep pigpiod");
    +bool isPigpiodRunning()
    +{
    +  int result = system("pgrep pigpiod");
    +
    +  if (result == 0) {
    +    // pigpiod daemon is running
    +    return true;
    +  } else {
    +    // pigpiod daemon is not running
    +    return false;
    +  }
    +}
    +
    +void killPigpiod()
    +{
    +  if (isPigpiodRunning()) {
    +    int result = system("sudo killall pigpiod -q");
    @@ -74,2 +100,2 @@
    -        // pigpiod daemon is running
    -        return true;
    +      // Successfully killed the pigpiod daemon
    +      cout << "pigpiod daemon killed successfully" << endl;
    @@ -77,2 +103,2 @@
    -        // pigpiod daemon is not running
    -        return false;
    +      // An error occurred while trying to kill the pigpiod daemon
    +      cerr << "Error killing pigpiod daemon. Return code: " << result << endl;
    @@ -79,0 +106,3 @@
    +  } else {
    +    cout << "pigpiod daemon is not running" << endl;
    +  }
    @@ -82 +111,7 @@
    -void killPigpiod() {
    +void startPigpiod()
    +{
    +  if (!isPigpiodRunning()) {
    +    cout << "pigpio daemon not running. attempting to start it." << endl;
    +    system("sudo systemctl start pigpiod");
    +    sleep(1);
    +
    @@ -84,9 +119,2 @@
    -        int result = system("sudo killall pigpiod -q");
    -
    -        if (result == 0) {
    -            // Successfully killed the pigpiod daemon
    -            cout << "pigpiod daemon killed successfully" << endl;
    -        } else {
    -            // An error occurred while trying to kill the pigpiod daemon
    -            cerr << "Error killing pigpiod daemon. Return code: " << result << endl;
    -        }
    +      // Successfully started the pigpiod daemon
    +      cout << "pigpiod daemon started successfully" << endl;
    @@ -94 +122,2 @@
    -        cout << "pigpiod daemon is not running" << endl;
    +      // An error occurred while trying to start the pigpiod daemon
    +      cerr << "Error starting pigpiod daemon." << endl;
    @@ -95,0 +125,3 @@
    +  } else {
    +    cout << "pigpiod daemon is already running" << endl;
    +  }
    @@ -97,18 +128,0 @@
    -
    -void startPigpiod() {
    -    if (!isPigpiodRunning()) {
    -        cout << "pigpio daemon not running. attempting to start it." << endl;
    -        system("sudo systemctl start pigpiod");
    -        sleep(1);
    -
    -        if (isPigpiodRunning()) {
    -            // Successfully started the pigpiod daemon
    -            cout << "pigpiod daemon started successfully" << endl;
    -        } else {
    -            // An error occurred while trying to start the pigpiod daemon
    -            cerr << "Error starting pigpiod daemon." << endl; 
    -        }
    -    } else {
    -        cout << "pigpiod daemon is already running" << endl;
    -    }
    -}
    
    Code style divergence in file 'src/rpi_pwm_hardware_interface.cpp':
    
    --- src/rpi_pwm_hardware_interface.cpp
    +++ src/rpi_pwm_hardware_interface.cpp.uncrustify
    @@ -30,2 +30 @@
    -  if (hardware_interface::SystemInterface::on_init(info) != CallbackReturn::SUCCESS)
    -  {
    +  if (hardware_interface::SystemInterface::on_init(info) != CallbackReturn::SUCCESS) {
    @@ -51,2 +50,2 @@
    -        startPigpiod();
    -    }
    +    startPigpiod();
    +  }
    @@ -55,2 +54,2 @@
    -      // pigpiod daemon is running
    -      return CallbackReturn::SUCCESS;
    +    // pigpiod daemon is running
    +    return CallbackReturn::SUCCESS;
    @@ -58,2 +57,2 @@
    -      // pigpiod daemon is not running
    -      return CallbackReturn::ERROR;
    +    // pigpiod daemon is not running
    +    return CallbackReturn::ERROR;
    @@ -74,3 +73,4 @@
    -    state_interfaces.emplace_back(hardware_interface::StateInterface(
    -    // TEST(anyone): insert correct interfaces
    -    rudder_joint_.name, hardware_interface::HW_IF_POSITION, &rudder_joint_.pos));
    +  state_interfaces.emplace_back(
    +    hardware_interface::StateInterface(
    +      // TEST(anyone): insert correct interfaces
    +      rudder_joint_.name, hardware_interface::HW_IF_POSITION, &rudder_joint_.pos));
    @@ -84 +84,2 @@
    -    command_interfaces.emplace_back(hardware_interface::CommandInterface(
    +  command_interfaces.emplace_back(
    +    hardware_interface::CommandInterface(
    @@ -98,3 +99,3 @@
    -      // TODO maybe make ros log error
    -      std::cerr << "Error initializing pigpio" << std::endl;
    -      return CallbackReturn::ERROR;
    +    // TODO maybe make ros log error
    +    std::cerr << "Error initializing pigpio" << std::endl;
    +    return CallbackReturn::ERROR;
    @@ -102 +103,5 @@
    -    rudder_joint_.servo = std::make_unique<AngularServo>(srv_cfg_.pi, srv_cfg_.pin, srv_cfg_.min_angle, srv_cfg_.max_angle, srv_cfg_.min_pulse_width_us, srv_cfg_.max_pulse_width_us);
    +    rudder_joint_.servo = std::make_unique<AngularServo>(
    +      srv_cfg_.pi, srv_cfg_.pin,
    +      srv_cfg_.min_angle, srv_cfg_.max_angle,
    +      srv_cfg_.min_pulse_width_us,
    +      srv_cfg_.max_pulse_width_us);
    
    Code style divergence in file 'test/test_rpi_pwm_hardware_interface.cpp':
    
    --- test/test_rpi_pwm_hardware_interface.cpp
    +++ test/test_rpi_pwm_hardware_interface.cpp.uncrustify
    @@ -56 +56 @@
    -              ros2_control_test_assets::urdf_tail;
    +    ros2_control_test_assets::urdf_tail;
    
    5 files with code style divergence
    No code style divergence in file 'include/rpi_pwm_hardware_interface/visibility_control.h'
    
    -- run_test.py: return code 1
    -- run_test.py: verify result file '/home/atticus/workspace/publish_ws/build/rpi_pwm_hardware_interface/test_results/rpi_pwm_hardware_interface/uncrustify.xunit.xml'
  >>>
build/rpi_pwm_hardware_interface/test_results/rpi_pwm_hardware_interface/test_rpi_pwm_hardware_interface.gtest.xml: 1 test, 0 errors, 1 failure, 0 skipped
- rpi_pwm_hardware_interface.TestRPiPWMHardwareInterface load_rpi_pwm_hardware_interface_2dof
  <<< failure message
    /home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/test/test_rpi_pwm_hardware_interface.cpp:57
    Expected: hardware_interface::ResourceManager rm(urdf) doesn't throw an exception.
      Actual: it throws.
  >>>
build/rpi_pwm_hardware_interface/test_results/rpi_pwm_hardware_interface/uncrustify.xunit.xml: 6 tests, 0 errors, 5 failures, 0 skipped
- rpi_pwm_hardware_interface.uncrustify include/rpi_pwm_hardware_interface/angular_servo.hpp
  <<< failure message
    Diff with 51 lines
  >>>
- rpi_pwm_hardware_interface.uncrustify include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp
  <<< failure message
    Diff with 38 lines
  >>>
- rpi_pwm_hardware_interface.uncrustify src/angular_servo.cpp
  <<< failure message
    Diff with 195 lines
  >>>
- rpi_pwm_hardware_interface.uncrustify src/rpi_pwm_hardware_interface.cpp
  <<< failure message
    Diff with 47 lines
  >>>
- rpi_pwm_hardware_interface.uncrustify test/test_rpi_pwm_hardware_interface.cpp
  <<< failure message
    Diff with 5 lines
  >>>

Summary: 21 tests, 0 errors, 8 failures, 0 skipped

investigate system vs actuator

ros2_control provides types of system, sensor, actuator, etc. Currently this hw interface is a system. Maybe it should be an actuator

Fix pre-commit format

Run pre-commit/[email protected]
with:
extra_args: --all-files --hook-stage manual
env:
pythonLocation: /opt/hostedtoolcache/Python/3.10.12/x64
PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.10.12/x64/lib/pkgconfig
Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.10.12/x64
Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.10.12/x64
Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.10.12/x64
LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.10.12/x64/lib
Run python -m pip install pre-commit
python -m pip install pre-commit
shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
env:
pythonLocation: /opt/hostedtoolcache/Python/3.10.12/x64
PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.10.12/x64/lib/pkgconfig
Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.10.12/x64
Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.10.12/x64
Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.10.12/x64
LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.10.12/x64/lib
Collecting pre-commit
Downloading pre_commit-3.3.3-py2.py3-none-any.whl (202 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 202.8/202.8 kB 5.0 MB/s eta 0:00:00
Collecting cfgv>=2.0.0 (from pre-commit)
Downloading cfgv-3.3.1-py2.py3-none-any.whl (7.3 kB)
Collecting identify>=1.0.0 (from pre-commit)
Downloading identify-2.5.24-py2.py3-none-any.whl (98 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 98.8/98.8 kB 29.1 MB/s eta 0:00:00
Collecting nodeenv>=0.11.1 (from pre-commit)
Downloading nodeenv-1.8.0-py2.py3-none-any.whl (22 kB)
Collecting pyyaml>=5.1 (from pre-commit)
Downloading PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (682 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 682.2/682.2 kB 70.6 MB/s eta 0:00:00
Collecting virtualenv>=20.10.0 (from pre-commit)
Downloading virtualenv-20.23.1-py3-none-any.whl (3.3 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.3/3.3 MB 83.9 MB/s eta 0:00:00
Requirement already satisfied: setuptools in /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages (from nodeenv>=0.11.1->pre-commit) (65.5.0)
Collecting distlib<1,>=0.3.6 (from virtualenv>=20.10.0->pre-commit)
Downloading distlib-0.3.6-py2.py3-none-any.whl (468 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 468.5/468.5 kB 65.4 MB/s eta 0:00:00
Collecting filelock<4,>=3.12 (from virtualenv>=20.10.0->pre-commit)
Downloading filelock-3.12.2-py3-none-any.whl (10 kB)
Collecting platformdirs<4,>=3.5.1 (from virtualenv>=20.10.0->pre-commit)
Downloading platformdirs-3.6.0-py3-none-any.whl (16 kB)
Installing collected packages: distlib, pyyaml, platformdirs, nodeenv, identify, filelock, cfgv, virtualenv, pre-commit
Successfully installed cfgv-3.3.1 distlib-0.3.6 filelock-3.12.2 identify-2.5.24 nodeenv-1.8.0 platformdirs-3.6.0 pre-commit-3.3.3 pyyaml-6.0 virtualenv-20.23.1

Notice: A new release of pip is available: 23.0.1 -> 23.1.2
Notice: To update, run: pip install --upgrade pip
Run python -m pip freeze --local
cfgv==3.3.1
distlib==0.3.6
filelock==3.12.2
identify==2.5.24
nodeenv==1.8.0
platformdirs==3.6.0
pre-commit==3.3.3
PyYAML==6.0
virtualenv==20.23.1
Run actions/cache@v3
Cache not found for input keys: pre-commit-3|/opt/hostedtoolcache/Python/3.10.12/x64|c3e4a1bde9ae55329964a421b1735288bc9ce860f8e42e80b00c0574341d580c
Run pre-commit run --show-diff-on-failure --color=always --all-files --hook-stage manual
[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Initializing environment for https://github.com/asottile/pyupgrade.
[INFO] Initializing environment for https://github.com/PyCQA/pydocstyle.
[INFO] Initializing environment for https://github.com/pycqa/flake8.
[INFO] Initializing environment for https://github.com/psf/black.
[INFO] Initializing environment for https://github.com/pre-commit/mirrors-clang-format.
[INFO] Initializing environment for https://github.com/PyCQA/doc8.
[INFO] Initializing environment for https://github.com/pre-commit/pygrep-hooks.
[INFO] Initializing environment for https://github.com/codespell-project/codespell.
[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/asottile/pyupgrade.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/PyCQA/pydocstyle.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/pycqa/flake8.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/psf/black.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/pre-commit/mirrors-clang-format.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/PyCQA/doc8.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/codespell-project/codespell.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
check for added large files..............................................Passed
check python ast.....................................(no files to check)Skipped
check for case conflicts.................................................Passed
check docstring is first.............................(no files to check)Skipped
check for merge conflicts................................................Passed
check for broken symlinks................................................Passed
check xml................................................................Passed
check yaml...............................................................Passed
debug statements (python)............................(no files to check)Skipped
detect destroyed symlinks................................................Passed
detect private key.......................................................Passed
fix end of files.........................................................Failed

  • hook id: end-of-file-fixer
  • exit code: 1
  • files were modified by this hook

Fixing include/rpi_pwm_hardware_interface/angular_servo.hpp

forbid submodules....................................(no files to check)Skipped
mixed line ending........................................................Passed
fix requirements.txt.................................(no files to check)Skipped
trim trailing whitespace.................................................Failed

  • hook id: trailing-whitespace
  • exit code: 1
  • files were modified by this hook

Fixing README.md
Fixing src/angular_servo.cpp

fix utf-8 byte order marker..............................................Passed
pyupgrade............................................(no files to check)Skipped
pydocstyle...........................................(no files to check)Skipped
flake8...............................................(no files to check)Skipped
black................................................(no files to check)Skipped
clang-format.............................................................Failed

  • hook id: clang-format
  • files were modified by this hook
    doc8.................................................(no files to check)Skipped
    rst code is two backticks........................(no files to check)Skipped
    rst directives end with two colons...................(no files to check)Skipped
    rst inline code next to normal text..............(no files to check)Skipped
    codespell................................................................Passed
    pre-commit hook(s) made changes.
    If you are seeing this message in CI, reproduce locally with: pre-commit run --all-files.
    To run pre-commit as part of git workflow, use pre-commit install.
    All changes made by hooks:
    diff --git a/README.md b/README.md
    index 18c4c59..3bb9a1b 100644
    --- a/README.md
    +++ b/README.md
    @@ -7,7 +7,7 @@ ROS2 control hardware interface package for controlling a servo motor through a

Dependency on PiGPIO

-This hardware interface requires the pigpio library to interface with the pwm pins on the pi. The installation instructions for pigpio are:
+This hardware interface requires the pigpio library to interface with the pwm pins on the pi. The installation instructions for pigpio are:

wget https://github.com/joan2937/pigpio/archive/master.zip
unzip master.zip
diff --git a/include/rpi_pwm_hardware_interface/angular_servo.hpp b/include/rpi_pwm_hardware_interface/angular_servo.hpp
index e584e52..c4ec773 100644
--- a/include/rpi_pwm_hardware_interface/angular_servo.hpp
+++ b/include/rpi_pwm_hardware_interface/angular_servo.hpp
@@ -1,31 +1,33 @@
#pragma once

-class Servo {
-	public:
-		Servo(int pi, int pin);
-		int getPulseWidth();
-		void setPulseWidth(int pulseWidth);
+class Servo
+{
+public:
+  Servo(int pi, int pin);
+  int getPulseWidth();
+  void setPulseWidth(int pulseWidth);

-		int __pi; // TODO rename to indicate public, and pigpio pi
-	protected:
-		int __pin;
+  int __pi;  // TODO rename to indicate public, and pigpio pi
+protected:
+  int __pin;
};

-class AngularServo : public Servo {
-	public:
-		AngularServo(int pi, int pin, float minAngle, float maxAngle, int minPulseWidthUs, int maxPulseWidthUs);
-		void setAngle(float angle);
-		int getAngle();
+class AngularServo : public Servo
+{
+public:
+  AngularServo(
+    int pi, int pin, float minAngle, float maxAngle, int minPulseWidthUs, int maxPulseWidthUs);
+  void setAngle(float angle);
+  int getAngle();

-	protected:
-		float __angle;
-		float __minAngle;
-		float __maxAngle;
-		int __minPulseWidthUs;
-		int __maxPulseWidthUs;
+protected:
+  float __angle;
+  float __minAngle;
+  float __maxAngle;
+  int __minPulseWidthUs;
+  int __maxPulseWidthUs;
};

bool isPigpiodRunning();
void killPigpiod();
void startPigpiod();
-
diff --git a/include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp b/include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp
index 6f96eac..3c95ac7 100644
--- a/include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp
+++ b/include/rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp
@@ -20,38 +20,37 @@
#include <string>
#include <vector>

-#include "rpi_pwm_hardware_interface/angular_servo.hpp"
-#include "rpi_pwm_hardware_interface/visibility_control.h"
-#include "hardware_interface/system_interface.hpp"
#include "hardware_interface/handle.hpp"
#include "hardware_interface/hardware_info.hpp"
+#include "hardware_interface/system_interface.hpp"
#include "hardware_interface/types/hardware_interface_return_values.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp_lifecycle/state.hpp"
+#include "rpi_pwm_hardware_interface/angular_servo.hpp"
+#include "rpi_pwm_hardware_interface/visibility_control.h"

namespace rpi_pwm_hardware_interface
{
class RPiPWMHardwareInterface : public hardware_interface::SystemInterface
{
-
-struct ServoConfig
-{
-  std::string name = "";
-  int pin = 0;
-  int pi = 0;
-  float min_angle = 0.0;
-  float max_angle = 0.0;
-  int min_pulse_width_us = 0;
-  int max_pulse_width_us = 0;
-};
-
-struct ServoJoint
-{
-  std::string name = "";
-  std::unique_ptr<AngularServo> servo;
-  double pos = 0;
-  double cmd = 0;
-};
+  struct ServoConfig
+  {
+    std::string name = "";
+    int pin = 0;
+    int pi = 0;
+    float min_angle = 0.0;
+    float max_angle = 0.0;
+    int min_pulse_width_us = 0;
+    int max_pulse_width_us = 0;
+  };
+
+  struct ServoJoint
+  {
+    std::string name = "";
+    std::unique_ptr<AngularServo> servo;
+    double pos = 0;
+    double cmd = 0;
+  };

public:
  TEMPLATES__ROS2_CONTROL__VISIBILITY_PUBLIC
diff --git a/src/angular_servo.cpp b/src/angular_servo.cpp
index 0ecbe12..34dbf15 100644
--- a/src/angular_servo.cpp
+++ b/src/angular_servo.cpp
@@ -1,114 +1,149 @@
-#include <iostream>
+#include "rpi_pwm_hardware_interface/angular_servo.hpp"
+#include <pigpiod_if2.h>
#include <csignal>
#include <cstdlib>
#include <functional>
-#include <pigpiod_if2.h>
-#include "rpi_pwm_hardware_interface/angular_servo.hpp"
+#include <iostream>

using namespace std;

-// TODO revisit private vs protected vars - maybe swap to private 
+// TODO revisit private vs protected vars - maybe swap to private

-Servo::Servo(int pi, int pin) {
-    __pi = pi;
-    __pin = pin;
-    int rc;
-    rc = set_mode(__pi, __pin, PI_OUTPUT);
-    if (rc < 0){
-        throw "Invalid GPIO pin or mode Error!";
-    }
-    
-    // initializing to zero with pigpio is no input
-    rc = set_servo_pulsewidth(__pi, __pin, 0);
-    if (rc < 0) {
-        throw "Invalid user GPIO pin or pulsewidth Error!";
-    }
+Servo::Servo(int pi, int pin)
+{
+  __pi = pi;
+  __pin = pin;
+  int rc;
+  rc = set_mode(__pi, __pin, PI_OUTPUT);
+  if (rc < 0)
+  {
+    throw "Invalid GPIO pin or mode Error!";
+  }
+
+  // initializing to zero with pigpio is no input
+  rc = set_servo_pulsewidth(__pi, __pin, 0);
+  if (rc < 0)
+  {
+    throw "Invalid user GPIO pin or pulsewidth Error!";
+  }
}

-int Servo::getPulseWidth() {
-    int rc = get_servo_pulsewidth(__pi, __pin);
-    if (rc < 0) {
-        throw "Invalid user GPIO pin Error!";
-    }
-    return rc;
+int Servo::getPulseWidth()
+{
+  int rc = get_servo_pulsewidth(__pi, __pin);
+  if (rc < 0)
+  {
+    throw "Invalid user GPIO pin Error!";
+  }
+  return rc;
}

-void Servo::setPulseWidth(int pulseWidth){
-    int rc = set_servo_pulsewidth(__pi, __pin, pulseWidth);
-    if (rc < 0) {
-        throw "Invalid user GPIO pin or pulsewidth Error!";
-    }
+void Servo::setPulseWidth(int pulseWidth)
+{
+  int rc = set_servo_pulsewidth(__pi, __pin, pulseWidth);
+  if (rc < 0)
+  {
+    throw "Invalid user GPIO pin or pulsewidth Error!";
+  }
}

-AngularServo::AngularServo(int pi, int pin, float minAngle, float maxAngle, int minPulseWidthUs, int maxPulseWidthUs) : Servo(pi, pin) {
-            __minAngle = minAngle;
-            __maxAngle = maxAngle;
-            __minPulseWidthUs = minPulseWidthUs;
-            __maxPulseWidthUs = maxPulseWidthUs;
+AngularServo::AngularServo(
+  int pi, int pin, float minAngle, float maxAngle, int minPulseWidthUs, int maxPulseWidthUs)
+: Servo(pi, pin)
+{
+  __minAngle = minAngle;
+  __maxAngle = maxAngle;
+  __minPulseWidthUs = minPulseWidthUs;
+  __maxPulseWidthUs = maxPulseWidthUs;
}

-void AngularServo::setAngle(float angle){
-    __angle = angle;
-    // make sure angle is within bounds
-    if (__angle < __minAngle){
-        __angle = __minAngle;
-    }
-    if (__angle > __maxAngle){
-        __angle = __maxAngle;
-    }
-    int pulseWidth = __minPulseWidthUs + (__angle - __minAngle) * (__maxPulseWidthUs - __minPulseWidthUs) / (__maxAngle - __minAngle);
+void AngularServo::setAngle(float angle)
+{
+  __angle = angle;
+  // make sure angle is within bounds
+  if (__angle < __minAngle)
+  {
+    __angle = __minAngle;
+  }
+  if (__angle > __maxAngle)
+  {
+    __angle = __maxAngle;
+  }
+  int pulseWidth = __minPulseWidthUs + (__angle - __minAngle) *
+                                         (__maxPulseWidthUs - __minPulseWidthUs) /
+                                         (__maxAngle - __minAngle);

-    setPulseWidth(pulseWidth);
+  setPulseWidth(pulseWidth);
}

-int AngularServo::getAngle(){
-    int pulseWidth = getPulseWidth();
-    float angle = __minAngle + (pulseWidth - __minPulseWidthUs) * (__maxAngle - __minAngle) / (__maxPulseWidthUs - __minPulseWidthUs);
-    return angle;
+int AngularServo::getAngle()
+{
+  int pulseWidth = getPulseWidth();
+  float angle = __minAngle + (pulseWidth - __minPulseWidthUs) * (__maxAngle - __minAngle) /
+                               (__maxPulseWidthUs - __minPulseWidthUs);
+  return angle;
}

-bool isPigpiodRunning() {
-    int result = system("pgrep pigpiod");
+bool isPigpiodRunning()
+{
+  int result = system("pgrep pigpiod");

-    if (result == 0) {
-        // pigpiod daemon is running
-        return true;
-    } else {
-        // pigpiod daemon is not running
-        return false;
-    }
+  if (result == 0)
+  {
+    // pigpiod daemon is running
+    return true;
+  }
+  else
+  {
+    // pigpiod daemon is not running
+    return false;
+  }
}

-void killPigpiod() {
-    if (isPigpiodRunning()) {
-        int result = system("sudo killall pigpiod -q");
-
-        if (result == 0) {
-            // Successfully killed the pigpiod daemon
-            cout << "pigpiod daemon killed successfully" << endl;
-        } else {
-            // An error occurred while trying to kill the pigpiod daemon
-            cerr << "Error killing pigpiod daemon. Return code: " << result << endl;
-        }
-    } else {
-        cout << "pigpiod daemon is not running" << endl;
+void killPigpiod()
+{
+  if (isPigpiodRunning())
+  {
+    int result = system("sudo killall pigpiod -q");
+
+    if (result == 0)
+    {
+      // Successfully killed the pigpiod daemon
+      cout << "pigpiod daemon killed successfully" << endl;
+    }
+    else
+    {
+      // An error occurred while trying to kill the pigpiod daemon
+      cerr << "Error killing pigpiod daemon. Return code: " << result << endl;
    }
+  }
+  else
+  {
+    cout << "pigpiod daemon is not running" << endl;
+  }
}

-void startPigpiod() {
-    if (!isPigpiodRunning()) {
-        cout << "pigpio daemon not running. attempting to start it." << endl;
-        system("sudo systemctl start pigpiod");
-        sleep(1);
-
-        if (isPigpiodRunning()) {
-            // Successfully started the pigpiod daemon
-            cout << "pigpiod daemon started successfully" << endl;
-        } else {
-            // An error occurred while trying to start the pigpiod daemon
-            cerr << "Error starting pigpiod daemon." << endl; 
-        }
-    } else {
-        cout << "pigpiod daemon is already running" << endl;
+void startPigpiod()
+{
+  if (!isPigpiodRunning())
+  {
+    cout << "pigpio daemon not running. attempting to start it." << endl;
+    system("sudo systemctl start pigpiod");
+    sleep(1);
+
+    if (isPigpiodRunning())
+    {
+      // Successfully started the pigpiod daemon
+      cout << "pigpiod daemon started successfully" << endl;
+    }
+    else
+    {
+      // An error occurred while trying to start the pigpiod daemon
+      cerr << "Error starting pigpiod daemon." << endl;
    }
+  }
+  else
+  {
+    cout << "pigpiod daemon is already running" << endl;
+  }
}
diff --git a/src/rpi_pwm_hardware_interface.cpp b/src/rpi_pwm_hardware_interface.cpp
index 35af62d..92c574f 100644
--- a/src/rpi_pwm_hardware_interface.cpp
+++ b/src/rpi_pwm_hardware_interface.cpp
@@ -[13](https://github.com/atticusrussell/ros2_rpi_pwm_hardware_interface/actions/runs/5304266181/jobs/9600463013#step:5:14),[14](https://github.com/atticusrussell/ros2_rpi_pwm_hardware_interface/actions/runs/5304266181/jobs/9600463013#step:5:15) +13,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.

-#include <limits>
#include <pigpiod_if2.h>
#include <unistd.h>
+#include <limits>
#include <vector>

-#include "rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp"
#include "hardware_interface/types/hardware_interface_type_values.hpp"
#include "rclcpp/rclcpp.hpp"
+#include "rpi_pwm_hardware_interface/rpi_pwm_hardware_interface.hpp"

namespace rpi_pwm_hardware_interface
{
@@ -47,[16](https://github.com/atticusrussell/ros2_rpi_pwm_hardware_interface/actions/runs/5304266181/jobs/9600463013#step:5:17) +47,20 @@ hardware_interface::CallbackReturn RPiPWMHardwareInterface::on_configure(
  const rclcpp_lifecycle::State & /*previous_state*/)
{
  // TODO(anyone): prepare the robot to be ready for read calls and write calls of some interfaces
-  if (!isPigpiodRunning()) {
-        startPigpiod();
-    }
-
-  if (isPigpiodRunning()) {
-      // pigpiod daemon is running
-      return CallbackReturn::SUCCESS;
-  } else {
-      // pigpiod daemon is not running
-      return CallbackReturn::ERROR;
+  if (!isPigpiodRunning())
+  {
+    startPigpiod();
+  }
+
+  if (isPigpiodRunning())
+  {
+    // pigpiod daemon is running
+    return CallbackReturn::SUCCESS;
+  }
+  else
+  {
+    // pigpiod daemon is not running
+    return CallbackReturn::ERROR;
  }
}

@@ -71,19 +75,20 @@ hardware_interface::CallbackReturn RPiPWMHardwareInterface::on_cleanup(
std::vector<hardware_interface::StateInterface> RPiPWMHardwareInterface::export_state_interfaces()
{
  std::vector<hardware_interface::StateInterface> state_interfaces;
-    state_interfaces.emplace_back(hardware_interface::StateInterface(
+  state_interfaces.emplace_back(hardware_interface::StateInterface(
    // TEST(anyone): insert correct interfaces
    rudder_joint_.name, hardware_interface::HW_IF_POSITION, &rudder_joint_.pos));

  return state_interfaces;
}

-std::vector<hardware_interface::CommandInterface> RPiPWMHardwareInterface::export_command_interfaces()
+std::vector<hardware_interface::CommandInterface>
+RPiPWMHardwareInterface::export_command_interfaces()
{
  std::vector<hardware_interface::CommandInterface> command_interfaces;
-    command_interfaces.emplace_back(hardware_interface::CommandInterface(
-      // TEST(anyone): insert correct interfaces
-      rudder_joint_.name, hardware_interface::HW_IF_POSITION, &rudder_joint_.cmd));
+  command_interfaces.emplace_back(hardware_interface::CommandInterface(
+    // TEST(anyone): insert correct interfaces
+    rudder_joint_.name, hardware_interface::HW_IF_POSITION, &rudder_joint_.cmd));

  return command_interfaces;
}
@@ -94,12 +99,[17](https://github.com/atticusrussell/ros2_rpi_pwm_hardware_interface/actions/runs/5304266181/jobs/9600463013#step:5:18) @@ hardware_interface::CallbackReturn RPiPWMHardwareInterface::on_activate(
  // TEST(anyone): prepare the robot to receive commands
  rudder_joint_.name = srv_cfg_.name;
  srv_cfg_.pi = pigpio_start(NULL, NULL);
-  if (srv_cfg_.pi < 0) {
-      // TODO maybe make ros log error
-      std::cerr << "Error initializing pigpio" << std::endl;
-      return CallbackReturn::ERROR;
-  } else {
-    rudder_joint_.servo = std::make_unique<AngularServo>(srv_cfg_.pi, srv_cfg_.pin, srv_cfg_.min_angle, srv_cfg_.max_angle, srv_cfg_.min_pulse_width_us, srv_cfg_.max_pulse_width_us);
+  if (srv_cfg_.pi < 0)
+  {
+    // TODO maybe make ros log error
+    std::cerr << "Error initializing pigpio" << std::endl;
+    return CallbackReturn::ERROR;
+  }
+  else
+  {
+    rudder_joint_.servo = std::make_unique<AngularServo>(
+      srv_cfg_.pi, srv_cfg_.pin, srv_cfg_.min_angle, srv_cfg_.max_angle,
+      srv_cfg_.min_pulse_width_us, srv_cfg_.max_pulse_width_us);
    return CallbackReturn::SUCCESS;
  }
}
Error: Process completed with exit code 1.

fix unused warning

$ cb
[0.474s] WARNING:colcon.colcon_ros.prefix_path.ament:The path '/home/atticus/workspace/publish_ws/install/rpi_pwm_hardware_interface' in the environment variable AMENT_PREFIX_PATH doesn't exist
[0.475s] WARNING:colcon.colcon_ros.prefix_path.catkin:The path '/home/atticus/workspace/publish_ws/install/rpi_pwm_hardware_interface' in the environment variable CMAKE_PREFIX_PATH doesn't exist
Starting >>> rpi_pwm_hardware_interface
--- stderr: rpi_pwm_hardware_interface                                
/home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/src/angular_servo.cpp: In function ‘void startPigpiod()’:
/home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/src/angular_servo.cpp:122:11: warning: ignoring return value of ‘int system(const char*)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  122 |     system("sudo systemctl start pigpiod");
      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---
Finished <<< rpi_pwm_hardware_interface [25.1s]

Summary: 1 package finished [25.3s]
  1 package had stderr output: rpi_pwm_hardware_interface
/home/atticus/workspace/publish_ws

generalize hardware interface code

the hardware interface code is currently specific to the specific application of PWM and the variable names talk about things like "rudder" which is overly specific. Abstract the code more, and make it friendly to adopt for other developer's needs and projects

fix pgpiod_if2 missing dependency

$ cb
Starting >>> rpi_pwm_hardware_interface
--- stderr: rpi_pwm_hardware_interface
CMake Error at CMakeLists.txt:15 (find_library):
  Could not find PIGPIO_IF2_LIB using the following names: pigpiod_if2


---
Failed   <<< rpi_pwm_hardware_interface [8.68s, exited with code 1]

Summary: 0 packages finished [9.44s]
  1 package failed: rpi_pwm_hardware_interface
  1 package had stderr output: rpi_pwm_hardware_interface

test hardware error

Fix the RTW auto-generated test file test/test_rpi_pwm_hardware_interface.cpp so that it works with the implemented hardware interface

atticus@rospi-ssh-session [publish_ws] 
~/workspace/publish_ws
12:45:11 $ colcon test-result --verbose 
build/rpi_pwm_hardware_interface/Testing/20230527-1641/Test.xml: 5 tests, 0 errors, 2 failures, 0 skipped
- test_rpi_pwm_hardware_interface
  <<< failure message
    -- run_test.py: invoking following command in '/home/atticus/workspace/publish_ws/build/rpi_pwm_hardware_interface':
     - /home/atticus/workspace/publish_ws/build/rpi_pwm_hardware_interface/test_rpi_pwm_hardware_interface --gtest_output=xml:/home/atticus/workspace/publish_ws/build/rpi_pwm_hardware_interface/test_results/rpi_pwm_hardware_interface/test_rpi_pwm_hardware_interface.gtest.xml
    Running main() from gmock_main.cc
    [==========] Running 1 test from 1 test suite.
    [----------] Global test environment set-up.
    [----------] 1 test from TestRPiPWMHardwareInterface
    [ RUN      ] TestRPiPWMHardwareInterface.load_rpi_pwm_hardware_interface_2dof
    [NON-XML-CHAR-0x1B][0m[INFO] [1685205696.057814547] [resource_manager]: Loading hardware 'RPiPWMHardwareInterface2dof' [NON-XML-CHAR-0x1B][0m
    [NON-XML-CHAR-0x1B][0m[INFO] [1685205696.094570106] [resource_manager]: Initialize hardware 'RPiPWMHardwareInterface2dof' [NON-XML-CHAR-0x1B][0m
    /home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/test/test_rpi_pwm_hardware_interface.cpp:57: Failure
    Expected: hardware_interface::ResourceManager rm(urdf) doesn't throw an exception.
      Actual: it throws.
    [  FAILED  ] TestRPiPWMHardwareInterface.load_rpi_pwm_hardware_interface_2dof (59 ms)
    [----------] 1 test from TestRPiPWMHardwareInterface (59 ms total)
    
    [----------] Global test environment tear-down
    [==========] 1 test from 1 test suite ran. (59 ms total)
    [  PASSED  ] 0 tests.
    [  FAILED  ] 1 test, listed below:
    [  FAILED  ] TestRPiPWMHardwareInterface.load_rpi_pwm_hardware_interface_2dof
    
     1 FAILED TEST
    -- run_test.py: return code 1
    -- run_test.py: inject classname prefix into gtest result file '/home/atticus/workspace/publish_ws/build/rpi_pwm_hardware_interface/test_results/rpi_pwm_hardware_interface/test_rpi_pwm_hardware_interface.gtest.xml'
    -- run_test.py: verify result file '/home/atticus/workspace/publish_ws/build/rpi_pwm_hardware_interface/test_results/rpi_pwm_hardware_interface/test_rpi_pwm_hardware_interface.gtest.xml'
  >>>  

...
(non-testing errors)
...

build/rpi_pwm_hardware_interface/test_results/rpi_pwm_hardware_interface/test_rpi_pwm_hardware_interface.gtest.xml: 1 test, 0 errors, 1 failure, 0 skipped
- rpi_pwm_hardware_interface.TestRPiPWMHardwareInterface load_rpi_pwm_hardware_interface_2dof
  <<< failure message
    /home/atticus/workspace/publish_ws/src/ros2_rpi_pwm_hardware_interface/test/test_rpi_pwm_hardware_interface.cpp:57
    Expected: hardware_interface::ResourceManager rm(urdf) doesn't throw an exception.
      Actual: it throws.
  >>>

format based on ament_uncrustify

Format the code in accordance with ament_uncrustify that is run with colcon test. Possibly can have ament uncrustify automatically modify code like pre-commit does with .clang-format.

I thought I liked the custom formatting rules I defined, but I was mistaken.

ros-tooling/setup-ros action is slow

the CI build action is really slow.

  • looks to be installing snaps and firefox for some reason???
  • industrial_ci is much faster, but had issues with git and CMake on the docker image
  • use of the docker image vs installing the OS likely explains the speed difference.
  • maybe fork industrial_ci and use a docker image with git already installed?

add ci

implement a bunch of stuff from ros2_control

make devcontainer

this should have an associated devcontainer. Partially so that it can be run on a non-RPi with the pigpio stuff, partially so I get practice, also because I want to play more with codespaces

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.