Skip to content

Commit 5ec1c44

Browse files
committed
Initial proof of concept
1 parent 49fe382 commit 5ec1c44

28 files changed

+2735
-0
lines changed

.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
*.pyc
2+
*.so
3+
__pycache__
4+
5+
.project
6+
.pydevproject
7+
.vscode
8+
9+
*.egg-info
10+
build
11+
dist
12+
13+
rev/version.py
14+
rev/_impl/autogen
15+
16+
17+
docs/_build
18+
docs/_sidebar.rst.inc

LICENSE.txt renamed to LICENSE

File renamed without changes.

MANIFEST.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
include LICENSE
2+
include gen/*.j2 gen/*.yml gen/hooks.py
3+
include rev/_impl/rev_roborio.cpp
4+
include rev/_impl/wpilibc/frc/*.cpp rev/_impl/wpilibc/frc/*.h
5+
include rev/_impl/autogen/*.cpp rev/_impl/autogen/*.hpp rev/_impl/autogen/*.inc

README.rst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
robotpy-rev
2+
===========
3+
4+
This is a python wrapper around the REV Spark MAX API. The RobotPy project
5+
is not associated with or endorsed by REV Robotics.
6+
7+
**WARNING**: THESE BINDINGS DO NOT WORK YET!!
8+
9+
Documentation
10+
=============
11+
12+
* `Installation <http://robotpy.readthedocs.io/en/stable/install/rev.html>`_
13+
* `Python API Documentation <http://robotpy.readthedocs.io/projects/rev/en/stable/api.html>`_
14+
* `REV's SparkMAX software <https://www.revrobotics.com/sparkmax-software/>`_
15+
16+
17+
Developers Notes
18+
================
19+
20+
Notes for advanced users and developers can be found in develop.md in the git
21+
repository.
22+
23+
License
24+
=======
25+
26+
RobotPy specific bits are available under the Apache 2.0 license. The REV
27+
specific pieces are available under a BSD license.
28+
29+
Author
30+
======
31+
32+
Dustin Spicuzza ([email protected])

rev/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from ._impl import CANSparkMax, MotorType, CANError
2+
3+
try:
4+
from .version import __version__
5+
except ImportError: # pragma: nocover
6+
__version__ = "master"

rev/_impl/__init__.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import hal
2+
3+
4+
if hal.isSimulation():
5+
6+
import enum
7+
8+
class MotorType(enum.IntEnum):
9+
kBrushed = 0
10+
kBrushless = 1
11+
12+
class CANError(enum.IntEnum):
13+
kOK = 0
14+
kError = 1
15+
kTimeout = 2
16+
17+
class CANSparkMax:
18+
def __init__(self, value, type):
19+
pass
20+
21+
def set(self, value):
22+
raise NotImplementedError
23+
24+
def get(self):
25+
raise NotImplementedError
26+
27+
28+
else:
29+
from .rev_roborio import CANSparkMax, MotorType, CANError

rev/_impl/info.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class Info:
2+
def module_info(self):
3+
from .. import version
4+
5+
return "REV bindings", version.__version__, version.__rev_version__

rev/_impl/rev_roborio.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
#include <pybind11/pybind11.h>
3+
#include <pybind11/stl.h>
4+
5+
namespace py = pybind11;
6+
7+
// Use this to release the gil
8+
typedef py::call_guard<py::gil_scoped_release> release_gil;
9+
10+
// REV includes
11+
#include "rev/CANSparkMax.h"
12+
13+
PYBIND11_MODULE(rev_roborio, m) {
14+
py::enum_<rev::CANSparkMax::MotorType>(m, "MotorType")
15+
.value("kBrushed", rev::CANSparkMax::MotorType::kBrushed)
16+
.value("kBrushless", rev::CANSparkMax::MotorType::kBrushless);
17+
18+
py::enum_<rev::CANError>(m, "CANError")
19+
.value("kOK", rev::CANError::kOK)
20+
.value("kError", rev::CANError::kError)
21+
.value("kTimeout", rev::CANError::kTimeout);
22+
23+
py::class_<rev::CANSparkMax> cls(m, "CANSparkMax");
24+
cls.def(py::init<int, rev::CANSparkMax::MotorType>(), release_gil())
25+
.def("set", &rev::CANSparkMax::Set, release_gil())
26+
.def("get", &rev::CANSparkMax::Get, release_gil());
27+
}

rev/_impl/wpilibc/SpeedController.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*----------------------------------------------------------------------------*/
2+
/* Copyright (c) 2008-2018 FIRST. All Rights Reserved. */
3+
/* Open Source Software - may be modified and shared by FRC teams. The code */
4+
/* must be accompanied by the FIRST BSD license file in the root directory of */
5+
/* the project. */
6+
/*----------------------------------------------------------------------------*/
7+
8+
#pragma once
9+
10+
#include "frc/PIDOutput.h"
11+
12+
namespace frc {
13+
14+
/**
15+
* Interface for speed controlling devices.
16+
*/
17+
class SpeedController : public PIDOutput {
18+
public:
19+
virtual ~SpeedController() = default;
20+
21+
/**
22+
* Common interface for setting the speed of a speed controller.
23+
*
24+
* @param speed The speed to set. Value should be between -1.0 and 1.0.
25+
*/
26+
virtual void Set(double speed) = 0;
27+
28+
/**
29+
* Common interface for getting the current set speed of a speed controller.
30+
*
31+
* @return The current set speed. Value is between -1.0 and 1.0.
32+
*/
33+
virtual double Get() const = 0;
34+
35+
/**
36+
* Common interface for inverting direction of a speed controller.
37+
*
38+
* @param isInverted The state of inversion, true is inverted.
39+
*/
40+
virtual void SetInverted(bool isInverted) = 0;
41+
42+
/**
43+
* Common interface for returning the inversion state of a speed controller.
44+
*
45+
* @return isInverted The state of inversion, true is inverted.
46+
*/
47+
virtual bool GetInverted() const = 0;
48+
49+
/**
50+
* Common interface for disabling a motor.
51+
*/
52+
virtual void Disable() = 0;
53+
54+
/**
55+
* Common interface to stop the motor until Set is called again.
56+
*/
57+
virtual void StopMotor() = 0;
58+
};
59+
60+
} // namespace frc

rev/_impl/wpilibc/frc/Base.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*----------------------------------------------------------------------------*/
2+
/* Copyright (c) 2008-2018 FIRST. All Rights Reserved. */
3+
/* Open Source Software - may be modified and shared by FRC teams. The code */
4+
/* must be accompanied by the FIRST BSD license file in the root directory of */
5+
/* the project. */
6+
/*----------------------------------------------------------------------------*/
7+
8+
#pragma once
9+
10+
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 5
11+
static_assert(0,
12+
"GCC must be 5 or greater. If building for the roboRIO, please "
13+
"update to the 2018 toolchains.");
14+
#endif
15+
16+
#if defined(_MSC_VER) && _MSC_VER < 1900
17+
static_assert(0, "Visual Studio 2015 or greater required.");
18+
#endif
19+
20+
/** WPILib FRC namespace */
21+
namespace frc {
22+
23+
// A struct to use as a deleter when a std::shared_ptr must wrap a raw pointer
24+
// that is being deleted by someone else.
25+
template <class T>
26+
struct NullDeleter {
27+
void operator()(T*) const noexcept {};
28+
};
29+
30+
} // namespace frc
31+
32+
// For backwards compatibility
33+
#ifdef NO_NAMESPACED_WPILIB
34+
using namespace frc; // NOLINT
35+
#endif

rev/_impl/wpilibc/frc/CAN.cpp

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*----------------------------------------------------------------------------*/
2+
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
3+
/* Open Source Software - may be modified and shared by FRC teams. The code */
4+
/* must be accompanied by the FIRST BSD license file in the root directory of */
5+
/* the project. */
6+
/*----------------------------------------------------------------------------*/
7+
8+
#include "frc/CAN.h"
9+
10+
#include <utility>
11+
12+
#include <hal/CAN.h>
13+
#include <hal/CANAPI.h>
14+
#include <hal/Errors.h>
15+
#include <hal/FRCUsageReporting.h>
16+
#include <hal/HALBase.h>
17+
18+
using namespace frc;
19+
20+
CAN::CAN(int deviceId) {
21+
int32_t status = 0;
22+
m_handle =
23+
HAL_InitializeCAN(kTeamManufacturer, deviceId, kTeamDeviceType, &status);
24+
if (status != 0) {
25+
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
26+
m_handle = HAL_kInvalidHandle;
27+
return;
28+
}
29+
30+
HAL_Report(HALUsageReporting::kResourceType_CAN, deviceId);
31+
}
32+
33+
CAN::CAN(int deviceId, int deviceManufacturer, int deviceType) {
34+
int32_t status = 0;
35+
m_handle = HAL_InitializeCAN(
36+
static_cast<HAL_CANManufacturer>(deviceManufacturer), deviceId,
37+
static_cast<HAL_CANDeviceType>(deviceType), &status);
38+
if (status != 0) {
39+
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
40+
m_handle = HAL_kInvalidHandle;
41+
return;
42+
}
43+
44+
HAL_Report(HALUsageReporting::kResourceType_CAN, deviceId);
45+
}
46+
47+
CAN::~CAN() {
48+
if (StatusIsFatal()) return;
49+
if (m_handle != HAL_kInvalidHandle) {
50+
HAL_CleanCAN(m_handle);
51+
m_handle = HAL_kInvalidHandle;
52+
}
53+
}
54+
55+
CAN::CAN(CAN&& rhs) : ErrorBase(std::move(rhs)) {
56+
std::swap(m_handle, rhs.m_handle);
57+
}
58+
59+
CAN& CAN::operator=(CAN&& rhs) {
60+
ErrorBase::operator=(std::move(rhs));
61+
62+
std::swap(m_handle, rhs.m_handle);
63+
64+
return *this;
65+
}
66+
67+
void CAN::WritePacket(const uint8_t* data, int length, int apiId) {
68+
int32_t status = 0;
69+
HAL_WriteCANPacket(m_handle, data, length, apiId, &status);
70+
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
71+
}
72+
73+
void CAN::WritePacketRepeating(const uint8_t* data, int length, int apiId,
74+
int repeatMs) {
75+
int32_t status = 0;
76+
HAL_WriteCANPacketRepeating(m_handle, data, length, apiId, repeatMs, &status);
77+
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
78+
}
79+
80+
void CAN::StopPacketRepeating(int apiId) {
81+
int32_t status = 0;
82+
HAL_StopCANPacketRepeating(m_handle, apiId, &status);
83+
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
84+
}
85+
86+
bool CAN::ReadPacketNew(int apiId, CANData* data) {
87+
int32_t status = 0;
88+
HAL_ReadCANPacketNew(m_handle, apiId, data->data, &data->length,
89+
&data->timestamp, &status);
90+
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
91+
return false;
92+
}
93+
if (status != 0) {
94+
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
95+
return false;
96+
} else {
97+
return true;
98+
}
99+
}
100+
101+
bool CAN::ReadPacketLatest(int apiId, CANData* data) {
102+
int32_t status = 0;
103+
HAL_ReadCANPacketLatest(m_handle, apiId, data->data, &data->length,
104+
&data->timestamp, &status);
105+
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
106+
return false;
107+
}
108+
if (status != 0) {
109+
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
110+
return false;
111+
} else {
112+
return true;
113+
}
114+
}
115+
116+
bool CAN::ReadPacketTimeout(int apiId, int timeoutMs, CANData* data) {
117+
int32_t status = 0;
118+
HAL_ReadCANPacketTimeout(m_handle, apiId, data->data, &data->length,
119+
&data->timestamp, timeoutMs, &status);
120+
if (status == HAL_CAN_TIMEOUT ||
121+
status == HAL_ERR_CANSessionMux_MessageNotFound) {
122+
return false;
123+
}
124+
if (status != 0) {
125+
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
126+
return false;
127+
} else {
128+
return true;
129+
}
130+
}
131+
132+
bool CAN::ReadPeriodicPacket(int apiId, int timeoutMs, int periodMs,
133+
CANData* data) {
134+
int32_t status = 0;
135+
HAL_ReadCANPeriodicPacket(m_handle, apiId, data->data, &data->length,
136+
&data->timestamp, timeoutMs, periodMs, &status);
137+
if (status == HAL_CAN_TIMEOUT ||
138+
status == HAL_ERR_CANSessionMux_MessageNotFound) {
139+
return false;
140+
}
141+
if (status != 0) {
142+
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
143+
return false;
144+
} else {
145+
return true;
146+
}
147+
}

0 commit comments

Comments
 (0)