Skip to content

Commit

Permalink
Initial proof of concept
Browse files Browse the repository at this point in the history
  • Loading branch information
virtuald committed Jan 9, 2019
1 parent 49fe382 commit 5ec1c44
Show file tree
Hide file tree
Showing 28 changed files with 2,735 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
*.pyc
*.so
__pycache__

.project
.pydevproject
.vscode

*.egg-info
build
dist

rev/version.py
rev/_impl/autogen


docs/_build
docs/_sidebar.rst.inc
File renamed without changes.
5 changes: 5 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include LICENSE
include gen/*.j2 gen/*.yml gen/hooks.py
include rev/_impl/rev_roborio.cpp
include rev/_impl/wpilibc/frc/*.cpp rev/_impl/wpilibc/frc/*.h
include rev/_impl/autogen/*.cpp rev/_impl/autogen/*.hpp rev/_impl/autogen/*.inc
32 changes: 32 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
robotpy-rev
===========

This is a python wrapper around the REV Spark MAX API. The RobotPy project
is not associated with or endorsed by REV Robotics.

**WARNING**: THESE BINDINGS DO NOT WORK YET!!

Documentation
=============

* `Installation <http://robotpy.readthedocs.io/en/stable/install/rev.html>`_
* `Python API Documentation <http://robotpy.readthedocs.io/projects/rev/en/stable/api.html>`_
* `REV's SparkMAX software <https://www.revrobotics.com/sparkmax-software/>`_


Developers Notes
================

Notes for advanced users and developers can be found in develop.md in the git
repository.

License
=======

RobotPy specific bits are available under the Apache 2.0 license. The REV
specific pieces are available under a BSD license.

Author
======

Dustin Spicuzza (dustin@virtualroadside.com)
6 changes: 6 additions & 0 deletions rev/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from ._impl import CANSparkMax, MotorType, CANError

try:
from .version import __version__
except ImportError: # pragma: nocover
__version__ = "master"
29 changes: 29 additions & 0 deletions rev/_impl/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import hal


if hal.isSimulation():

import enum

class MotorType(enum.IntEnum):
kBrushed = 0
kBrushless = 1

class CANError(enum.IntEnum):
kOK = 0
kError = 1
kTimeout = 2

class CANSparkMax:
def __init__(self, value, type):
pass

def set(self, value):
raise NotImplementedError

def get(self):
raise NotImplementedError


else:
from .rev_roborio import CANSparkMax, MotorType, CANError
5 changes: 5 additions & 0 deletions rev/_impl/info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Info:
def module_info(self):
from .. import version

return "REV bindings", version.__version__, version.__rev_version__
27 changes: 27 additions & 0 deletions rev/_impl/rev_roborio.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

namespace py = pybind11;

// Use this to release the gil
typedef py::call_guard<py::gil_scoped_release> release_gil;

// REV includes
#include "rev/CANSparkMax.h"

PYBIND11_MODULE(rev_roborio, m) {
py::enum_<rev::CANSparkMax::MotorType>(m, "MotorType")
.value("kBrushed", rev::CANSparkMax::MotorType::kBrushed)
.value("kBrushless", rev::CANSparkMax::MotorType::kBrushless);

py::enum_<rev::CANError>(m, "CANError")
.value("kOK", rev::CANError::kOK)
.value("kError", rev::CANError::kError)
.value("kTimeout", rev::CANError::kTimeout);

py::class_<rev::CANSparkMax> cls(m, "CANSparkMax");
cls.def(py::init<int, rev::CANSparkMax::MotorType>(), release_gil())
.def("set", &rev::CANSparkMax::Set, release_gil())
.def("get", &rev::CANSparkMax::Get, release_gil());
}
60 changes: 60 additions & 0 deletions rev/_impl/wpilibc/SpeedController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2008-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/

#pragma once

#include "frc/PIDOutput.h"

namespace frc {

/**
* Interface for speed controlling devices.
*/
class SpeedController : public PIDOutput {
public:
virtual ~SpeedController() = default;

/**
* Common interface for setting the speed of a speed controller.
*
* @param speed The speed to set. Value should be between -1.0 and 1.0.
*/
virtual void Set(double speed) = 0;

/**
* Common interface for getting the current set speed of a speed controller.
*
* @return The current set speed. Value is between -1.0 and 1.0.
*/
virtual double Get() const = 0;

/**
* Common interface for inverting direction of a speed controller.
*
* @param isInverted The state of inversion, true is inverted.
*/
virtual void SetInverted(bool isInverted) = 0;

/**
* Common interface for returning the inversion state of a speed controller.
*
* @return isInverted The state of inversion, true is inverted.
*/
virtual bool GetInverted() const = 0;

/**
* Common interface for disabling a motor.
*/
virtual void Disable() = 0;

/**
* Common interface to stop the motor until Set is called again.
*/
virtual void StopMotor() = 0;
};

} // namespace frc
35 changes: 35 additions & 0 deletions rev/_impl/wpilibc/frc/Base.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2008-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/

#pragma once

#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 5
static_assert(0,
"GCC must be 5 or greater. If building for the roboRIO, please "
"update to the 2018 toolchains.");
#endif

#if defined(_MSC_VER) && _MSC_VER < 1900
static_assert(0, "Visual Studio 2015 or greater required.");
#endif

/** WPILib FRC namespace */
namespace frc {

// A struct to use as a deleter when a std::shared_ptr must wrap a raw pointer
// that is being deleted by someone else.
template <class T>
struct NullDeleter {
void operator()(T*) const noexcept {};
};

} // namespace frc

// For backwards compatibility
#ifdef NO_NAMESPACED_WPILIB
using namespace frc; // NOLINT
#endif
147 changes: 147 additions & 0 deletions rev/_impl/wpilibc/frc/CAN.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/

#include "frc/CAN.h"

#include <utility>

#include <hal/CAN.h>
#include <hal/CANAPI.h>
#include <hal/Errors.h>
#include <hal/FRCUsageReporting.h>
#include <hal/HALBase.h>

using namespace frc;

CAN::CAN(int deviceId) {
int32_t status = 0;
m_handle =
HAL_InitializeCAN(kTeamManufacturer, deviceId, kTeamDeviceType, &status);
if (status != 0) {
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
m_handle = HAL_kInvalidHandle;
return;
}

HAL_Report(HALUsageReporting::kResourceType_CAN, deviceId);
}

CAN::CAN(int deviceId, int deviceManufacturer, int deviceType) {
int32_t status = 0;
m_handle = HAL_InitializeCAN(
static_cast<HAL_CANManufacturer>(deviceManufacturer), deviceId,
static_cast<HAL_CANDeviceType>(deviceType), &status);
if (status != 0) {
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
m_handle = HAL_kInvalidHandle;
return;
}

HAL_Report(HALUsageReporting::kResourceType_CAN, deviceId);
}

CAN::~CAN() {
if (StatusIsFatal()) return;
if (m_handle != HAL_kInvalidHandle) {
HAL_CleanCAN(m_handle);
m_handle = HAL_kInvalidHandle;
}
}

CAN::CAN(CAN&& rhs) : ErrorBase(std::move(rhs)) {
std::swap(m_handle, rhs.m_handle);
}

CAN& CAN::operator=(CAN&& rhs) {
ErrorBase::operator=(std::move(rhs));

std::swap(m_handle, rhs.m_handle);

return *this;
}

void CAN::WritePacket(const uint8_t* data, int length, int apiId) {
int32_t status = 0;
HAL_WriteCANPacket(m_handle, data, length, apiId, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}

void CAN::WritePacketRepeating(const uint8_t* data, int length, int apiId,
int repeatMs) {
int32_t status = 0;
HAL_WriteCANPacketRepeating(m_handle, data, length, apiId, repeatMs, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}

void CAN::StopPacketRepeating(int apiId) {
int32_t status = 0;
HAL_StopCANPacketRepeating(m_handle, apiId, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}

bool CAN::ReadPacketNew(int apiId, CANData* data) {
int32_t status = 0;
HAL_ReadCANPacketNew(m_handle, apiId, data->data, &data->length,
&data->timestamp, &status);
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
}
if (status != 0) {
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
return false;
} else {
return true;
}
}

bool CAN::ReadPacketLatest(int apiId, CANData* data) {
int32_t status = 0;
HAL_ReadCANPacketLatest(m_handle, apiId, data->data, &data->length,
&data->timestamp, &status);
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
}
if (status != 0) {
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
return false;
} else {
return true;
}
}

bool CAN::ReadPacketTimeout(int apiId, int timeoutMs, CANData* data) {
int32_t status = 0;
HAL_ReadCANPacketTimeout(m_handle, apiId, data->data, &data->length,
&data->timestamp, timeoutMs, &status);
if (status == HAL_CAN_TIMEOUT ||
status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
}
if (status != 0) {
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
return false;
} else {
return true;
}
}

bool CAN::ReadPeriodicPacket(int apiId, int timeoutMs, int periodMs,
CANData* data) {
int32_t status = 0;
HAL_ReadCANPeriodicPacket(m_handle, apiId, data->data, &data->length,
&data->timestamp, timeoutMs, periodMs, &status);
if (status == HAL_CAN_TIMEOUT ||
status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
}
if (status != 0) {
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
return false;
} else {
return true;
}
}
Loading

0 comments on commit 5ec1c44

Please sign in to comment.