Skip to content

Commit

Permalink
Create repo from template
Browse files Browse the repository at this point in the history
  • Loading branch information
griswaldbrooks committed Oct 1, 2023
1 parent e619c90 commit b18046e
Show file tree
Hide file tree
Showing 13 changed files with 518 additions and 32 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
REPO=spanny
34 changes: 34 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: CI

on: [push, pull_request, workflow_dispatch]

jobs:
build:
name: ${{matrix.platform.name}} ${{matrix.type.name}} ${{matrix.config.name}}
runs-on: ${{matrix.platform.os}}

strategy:
fail-fast: false
matrix:
platform:
- { name: Linux, os: ubuntu-latest }
- { name: macOS, os: macos-latest }
type:
- { name: Shared, flags: "ON" }
- { name: Static, flags: "OFF" }
config:
- { name: Debug }
- { name: Release }

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Configure
run: cmake -B build -DBUILD_SHARED_LIBS=${{matrix.type.flags}} -DCMAKE_BUILD_TYPE=${{matrix.config.name}}

- name: Build
run: cmake --build build --config ${{matrix.config.name}}

- name: Test
run: ctest --test-dir build --output-on-failure --build-config ${{matrix.config.name}}
90 changes: 90 additions & 0 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: docker

on:
workflow_dispatch:
schedule:
- cron: '0 0 * * 0'
push:
paths:
- 'Dockerfile'
- '.github/workflows/docker.yaml'

jobs:
hadolint:
name: hadolint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: hadolint/[email protected]
with:
dockerfile: Dockerfile
verbose: true
- name: Update Pull Request
uses: actions/github-script@v6
if: github.event_name == 'pull_request'
with:
script: |
const output = `
#### Hadolint: \`${{ steps.hadolint.outcome }}\`
\`\`\`
${process.env.HADOLINT_RESULTS}
\`\`\`
`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
upstream:
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v3
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
- name: Login to Github Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
file: Dockerfile
push: true
target: upstream
tags: ghcr.io/griswaldbrooks/spanny:upstream
cache-from: type=gha
cache-to: type=gha,mode=max
development:
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v3
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
- name: Login to Github Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
file: Dockerfile
push: true
target: development
build-args: |
USER=ci-user
UID=1000
GID=1000
tags: ghcr.io/griswaldbrooks/spanny:ci-user-development
cache-from: type=gha
cache-to: type=gha,mode=max
38 changes: 7 additions & 31 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,32 +1,8 @@
# Prerequisites
*.d

# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod
*.smod

# Compiled Static libraries
*.lai
*.la
doc/html
doc/manifest.yaml
*.a
*.lib

# Executables
*.exe
*.out
*.app
Makefile
CMakeCache.txt
CMakeFiles/
filter_tests
build
4 changes: 4 additions & 0 deletions .hadolint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ignored:
- DL3007
- DL3008
- SC1091
20 changes: 20 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.16)
project(spanny CXX)

if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
add_compile_options(-Werror -Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion)
endif()

add_library(spanny INTERFACE)
add_library(spanny::spanny ALIAS spanny)
target_include_directories(spanny INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
target_compile_features(spanny INTERFACE cxx_std_17)

if(NOT PROJECT_IS_TOP_LEVEL)
return()
endif()

include(CTest)
if(BUILD_TESTING)
add_subdirectory(test)
endif()
67 changes: 67 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# syntax=docker/dockerfile:1
FROM ubuntu:22.04 as upstream

# Prevent the interactive wizards from stopping the build
ARG DEBIAN_FRONTEND=noninteractive

# Get the basics
# hadolint ignore=DL3008
RUN --mount=type=cache,target=/var/cache/apt,id=apt \
apt-get update -y && apt-get install -q -y --no-install-recommends \
build-essential \
cmake \
lsb-core \
wget \
&& rm -rf /var/lib/apt/lists/*

FROM upstream AS development

ARG UID
ARG GID
ARG USER

# fail build if args are missing
# hadolint ignore=SC2028
RUN if [ -z "$UID" ]; then echo '\nERROR: UID not set. Run \n\n \texport UID=$(id -u) \n\n on host before building Dockerfile.\n'; exit 1; fi
# hadolint ignore=SC2028
RUN if [ -z "$GID" ]; then echo '\nERROR: GID not set. Run \n\n \texport GID=$(id -g) \n\n on host before building Dockerfile.\n'; exit 1; fi
# hadolint ignore=SC2028
RUN if [ -z "$USER" ]; then echo '\nERROR: USER not set. Run \n\n \texport USER=$(whoami) \n\n on host before building Dockerfile.\n'; exit 1; fi
# hadolint ignore=DL3008
RUN --mount=type=cache,target=/var/cache/apt,id=apt \
apt-get update && apt-get upgrade -y \
&& apt-get install -q -y --no-install-recommends \
git \
neovim \
python3 \
python3-pip \
sudo \
ssh \
vim \
wget \
&& rm -rf /var/lib/apt/lists/*

# install developer tools
RUN python3 -m pip install --no-cache-dir \
pre-commit==3.0.4

# install hadolint
RUN wget -q -O /bin/hadolint https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64 \
&& chmod +x /bin/hadolint

# Setup user home directory
# --no-log-init helps with excessively long UIDs
RUN groupadd --gid $GID $USER \
&& useradd --no-log-init --uid $GID --gid $UID -m $USER --groups sudo \
&& echo $USER ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USER \
&& chmod 0440 /etc/sudoers.d/$USER \
&& echo "source /opt/ros/${ROS_DISTRO}/setup.bash" >> /home/${USER}/.profile \
&& touch /home/${USER}/.bashrc \
&& chown -R ${GID}:${UID} /home/${USER}

USER $USER
ENV SHELL /bin/bash
ENTRYPOINT []

# Setup mixin
WORKDIR /home/${USER}/ws
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,24 @@
# spanny
# spanny
Robot arm project for lightening talk on mdspan.
Presented at CppCon 2023.

# Development Container
Build a new development image
```shell
mkdir -p ~/.spanny/ccache
export UID=$(id -u) export GID=$(id -g); docker compose -f compose.dev.yml build
```
Start an interactive development container
```shell
docker compose -f compose.dev.yml run development
```
Build the repository in the container
```shell
username@spanny-dev:~/ws$ cmake -S src/filter/ -B build
username@spanny-dev:~/ws$ cmake --build build
```

# Test
```shell
username@spanny-dev:~/ws$ ctest --test-dir build
```
31 changes: 31 additions & 0 deletions compose.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: '3.8'

services:
development:
build:
args:
UID: ${UID}
GID: ${GID}
USER: ${USER}
context: .
dockerfile: Dockerfile
command: bash -c "export PATH="/usr/lib/ccache:$PATH" &&
bash"
container_name: ${USER}-${REPO}-dev
environment:
- TERM=xterm-256color
extra_hosts:
- ${REPO}-dev:127.0.0.1
hostname: ${REPO}-dev
image: ${REPO}-dev:latest
network_mode: host
privileged: true
volumes:
- ~/.ssh:${HOME}/.ssh:ro
- ~/.gitconfig:${HOME}/.gitconfig:ro
- ${PWD}:${HOME}/ws/src/${REPO}
- ~/.${REPO}/ccache:${HOME}/.ccache
- /etc/group:/etc/group:ro
- /etc/passwd:/etc/passwd:ro
- /etc/shadow:/etc/shadow:ro
working_dir: ${HOME}/ws
74 changes: 74 additions & 0 deletions include/filter/linear_filter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#ifndef FILTER_LINEAR_FILTER_H_
#define FILTER_LINEAR_FILTER_H_

#include <deque> // For deque
#include <numeric> // For inner_product
#include <stdexcept> // For domain_error, length_error
#include <utility> // For move
#include <vector> // For vector

namespace gb::filter {

/// \tparam Coefficients number of filter elements
template <typename T>
class linear_filter {
public:
/// \brief Constructor for linear_filter.
/// \param b Feedforward coefficients for the input samples.
/// \param a Feedback coefficients for the output samples.
/// \note The number of coefficients is the order of the filter + 1.
/// \throws if \p b and \p a are of different lengths.
/// \throws if the first element of \p a is not 1.
linear_filter(std::vector<double> b, std::vector<double> a)
: b_{std::move(b)},
a_{std::move(a)},
x_(b_.size(), T{}),
y_(a_.size(), T{}) {
if (b_.size() != a_.size()) {
throw std::length_error{"Coefficients must have same length"};
}
if (a_.front() != 1.) {
throw std::domain_error{"First element of output coefficients must be 1"};
}
}

// \brief Finite impulse response constructor
linear_filter(std::vector<double> b)
: b_{std::move(b)},
x_(b_.size(), T{}) {}

/// \brief Filters value
/// \param value Input to be filtered.
/// \returns filtered value.
T& operator()(const T& value) {
// Remove the oldest elements.
x_.pop_back();
y_.pop_back();

// Add the new input pose to the vector of inputs.
x_.emplace_front(value);

// Update the new output with the rest of the values
const auto bx =
std::inner_product(b_.cbegin(), b_.cend(), x_.cbegin(), T{});
// Skip the first coefficient since it's always 1, which allows us to avoid
// zero initializing the new output.
const auto ay =
std::inner_product(a_.cbegin() + 1, a_.cend(), y_.cbegin(), T{});

// Initialize the new output and return
return y_.emplace_front(bx - ay);
}

private:
/// \brief Input coefficients
std::vector<double> b_;
/// \brief Output coefficients
std::vector<double> a_;
/// \brief Input taps
std::deque<T> x_;
/// \brief Previous output
std::deque<T> y_;
};
} // namespace gb::filter
#endif // FILTER_LINEAR_FILTER_H_
Loading

0 comments on commit b18046e

Please sign in to comment.