Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
034b8fd
Add some files, and CMake dependencies
ManifoldFR Apr 10, 2025
1896c86
Dummy pull/push system: transfer models over zmq
ManifoldFR Apr 11, 2025
9e5cf7c
src/CMakeLists.txt : add msgpack-cxx
ManifoldFR Jul 9, 2025
6cccdbc
poc sending models + matrices over zmq + msgpack
ManifoldFR Jul 9, 2025
84e1d52
src/CMakeLists.txt : change runtime executable name
ManifoldFR Jul 10, 2025
1e8b99a
Split sockets
ManifoldFR Jul 10, 2025
84dc777
multibody/Visualizer : remove redundant inner struct EnvStatus
ManifoldFR Jul 10, 2025
9cfb329
runtime : fix first message handler (send response only when models l…
ManifoldFR Jul 10, 2025
274ba55
runtime : add context and sockets to application context
ManifoldFR Jul 10, 2025
3f36c01
runtime : working example of talking to the pub/sub socket
ManifoldFR Jul 10, 2025
a9a2ff0
multibody/Visualizer : move removeFramesViz() impl
ManifoldFR Jul 11, 2025
63ddc6e
external/imgui : sync submodule
ManifoldFR Jul 11, 2025
5addcf4
cmake : sync submodule
ManifoldFR Jul 11, 2025
5503f15
bindings/python : expose resetCamera()
ManifoldFR Jul 11, 2025
0bf6afd
multibody/Visualizer.h : streamline callback
ManifoldFR Jul 11, 2025
a904aed
multibody/Visualizer.h : move camera enable flag into params
ManifoldFR Jul 11, 2025
dfafb92
runtime : pass hostname and port as cli
ManifoldFR Jul 11, 2025
df14f19
runtime : add camera pose endpoint, and for `viz.clean()`
ManifoldFR Jul 11, 2025
9596327
pre-commit config : autoupdate
ManifoldFR Jul 11, 2025
b65bb9b
bindings/python : Implement AsyncVisualizer, add async_visualizer.py
ManifoldFR Jul 11, 2025
1435ebd
pixi : add new dependencies for Pinocchio features
ManifoldFR Jul 11, 2025
81f96af
pixi : Forgot to add cli11 dependency, split up runtime feature
ManifoldFR Jul 11, 2025
6ea2d8b
[cmake] Add install directive for runtime, add option to build visual…
ManifoldFR Jul 11, 2025
cdbc48a
examples/python : wrap importing some dependencies in try/except
ManifoldFR Jul 11, 2025
5998360
Update CHANGELOG
ManifoldFR Jul 11, 2025
feb7053
Update README
ManifoldFR Jul 11, 2025
ef72a25
CMake : change option `BUILD_PYTHON_BINDINGS` to `BUILD_PYTHON_INTERF…
ManifoldFR Jul 11, 2025
3f23445
examples/python : fix inv_pendulum_mj.py for upcoming pinocchio 4.x
ManifoldFR Jul 11, 2025
66c2580
pre-commit config : ignore hard linebreak linespace for markdown
ManifoldFR Jul 11, 2025
db34707
Embed Inter Medium font into the application
ManifoldFR Jul 11, 2025
2874388
multibody/Visualizer.cpp : fix formatting error message for SDL_Init
ManifoldFR Jul 15, 2025
2d26c21
core/GuiSystem : set imgui font size to 13px
ManifoldFR Jul 15, 2025
a83320f
core/Device.cpp : remove unused include
ManifoldFR Jul 15, 2025
a2b2229
multibody/Visualizer.cpp : log the current video driver
ManifoldFR Jul 15, 2025
4b02ab1
runtime/main.cpp : add macro for defining commands
ManifoldFR Jul 21, 2025
c1efe23
multibody : add RobotLoader.h
ManifoldFR Jul 21, 2025
9f6f3d4
Remove dependency on robot_descriptions_cpp
ManifoldFR Jul 21, 2025
440b9ef
examples : always compile GenHeightfield.cpp for ExamplesCommon target
ManifoldFR Jul 21, 2025
564a0bc
runtime : add Messages.h header
ManifoldFR Jul 21, 2025
d2b39b5
runtime/main.cpp : fix command name for state_update
ManifoldFR Jul 21, 2025
82596eb
Add recording to visualizer runtime and commands
ManifoldFR Jul 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ci:
submodules: true
repos:
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v20.1.0
rev: v20.1.8
hooks:
- id: clang-format
types_or: []
Expand All @@ -15,6 +15,7 @@ repos:
rev: v5.0.0
hooks:
- id: check-added-large-files
args: ['--maxkb=1800']
- id: check-case-conflict
- id: check-yaml
exclude: ^packaging/conda/
Expand All @@ -23,17 +24,18 @@ repos:
- id: mixed-line-ending
- id: check-merge-conflict
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
exclude: |
(?x)^(
doc/doxygen-awesome.*
)$
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.11.4'
rev: 'v0.12.3'
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format
- repo: https://github.com/BlankSpruce/gersemi
rev: 0.19.2
rev: 0.20.1
hooks:
- id: gersemi
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Added tools for loading models from a given description struct `RobotSpec` (https://github.com/Simple-Robotics/candlewick/pull/37)
- Added Candlewick visualizer runtime, to be used to (up)load Pinocchio models and submit states to be displayed asynchronously. (https://github.com/Simple-Robotics/candlewick/pull/37)
- Embed Inter Medium font into the application (https://github.com/Simple-Robotics/candlewick/pull/37)

### Changed

- CMake : sync jrl-cmakemodules to new release 1.0.0 (https://github.com/Simple-Robotics/candlewick/pull/37)
- CMake : change option `BUILD_PYTHON_BINDINGS` to `BUILD_PYTHON_INTERFACE` (https://github.com/Simple-Robotics/candlewick/pull/37)
- multibody/Visualizer : `stopRecording()` now returns a flag (https://github.com/Simple-Robotics/candlewick/pull/37)

### Fixed

- `core/Device.h` : fix release() function
- Python examples : wrap some import statements in try/except statements (https://github.com/Simple-Robotics/candlewick/pull/37)

### Removed

- Remove dependency on `robot_descriptions_cpp` (https://github.com/Simple-Robotics/candlewick/pull/37)

## [0.7.0] - 2025-07-04

### Added
Expand Down
12 changes: 9 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,19 @@ set(AWESOME_CSS_DIR ${PROJECT_SOURCE_DIR}/doc/doxygen-awesome-css)

option(BUILD_EXAMPLES "Build examples." OFF)
option(BUILD_PINOCCHIO_VISUALIZER "Build the Pinocchio visualizer." ON)
cmake_dependent_option(
BUILD_VISUALIZER_RUNTIME
"Build the visualizer runtime which is used to have a persistent visualizer (e.g. for async clients)."
OFF
BUILD_PINOCCHIO_VISUALIZER
OFF
)

option(BUILD_PYTHON_BINDINGS "Build Python bindings." OFF)
cmake_dependent_option(
GENERATE_PYTHON_STUBS
"Generate the Python stubs associated to the Python library"
OFF
BUILD_PYTHON_BINDINGS
BUILD_PYTHON_INTERFACE
OFF
)

Expand Down Expand Up @@ -133,7 +139,7 @@ if(BUILD_TESTING)
add_subdirectory(tests)
endif()

if(BUILD_PYTHON_BINDINGS)
if(BUILD_PYTHON_INTERFACE)
add_subdirectory(bindings/python)
# WIP nanobind bindings
# add_subdirectory(bindings/nanobind)
Expand Down
145 changes: 109 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
[![Conda package](https://img.shields.io/conda/vn/conda-forge/candlewick.svg)](https://anaconda.org/conda-forge/candlewick)


# Candlewick: a WIP renderer based on SDL_gpu
# Candlewick: a modern, cross-platform real-time renderer for robotics based on SDL3

> [!WARNING]
> Candlewick is still under **active** development. Support will be limited, and the API might break unexpectedly and repeatedly.


Candlewick is a WIP library for a renderer based on SDL3's new [GPU API](https://wiki.libsdl.org/SDL3/CategoryGPU).
Candlewick is a cross-platform framework for real-time visualization in robotics, based on SDL3's [graphics API](https://wiki.libsdl.org/SDL3/CategoryGPU).

## Features
![go2 standing](doc/go2_standing_example.png)

Candlewick comes with a set of graphical, interaction, and utility features.
## Features

### Graphical features

Expand Down Expand Up @@ -55,67 +55,130 @@ with create_recorder_context(viz, "ur10_video.mp4"):
viz.display(q0)
```

![ur10](doc/ur10_with_gui_example.png)

#### Candlewick visualizer runtime and client

## Installation
The runtime allows users to persist a visualizer window and keep interacting with it asynchronously, *even when display commands are not being submitted*.

### Dependencies
To build the runtime, users must set the `BUILD_VISUALIZER_RUNTIME` CMake option.

Launch the candlewick runtime:

```bash
candlewick-visualizer # --help
```

The corresponding asynchronous visualizer client is used as follows:

```python
from candlewick.async_visualizer import AsyncVisualizer

viz = AsyncVisualizer(model, geom_model)
viz.initViewer(hostname="127.0.0.1", port=12000)
viz.loadViewerModel()
# use as any other Pinocchio visualizer class
```

Check out the [corresponding example](examples/python/ur3_async_runtime.py).


## Dependencies

### Core dependencies

Candlewick depends mainly on:

* [SDL3](https://github.com/libsdl-org/SDL/) for windowing, processing input events, and of course SDL GPU.
* [EnTT](https://github.com/skypjack/entt/) for the entity-component system (ECS)
* [nlohmann/json](https://github.com/nlohmann/json) for processing JSON files
* the [Eigen](https://gitlab.com/libeigen/eigen/) linear algebra template library
* the [Coal](https://github.com/coal-library/coal) collision algorithms library
* [magic_enum](https://github.com/Neargye/magic_enum) (enum reflection library)
* [Open Asset Importer Library (assimp)](https://assimp-docs.readthedocs.io/en/latest/) for loading meshes
* [SDL3](https://github.com/libsdl-org/SDL/) - Graphics backend, windowing, user input
* [Assimp](https://assimp-docs.readthedocs.io/en/latest/) - Loading meshes and importing 3D assets
* [EnTT](https://github.com/skypjack/entt/) - Implementing the Entity-Component System
* [nlohmann_json](https://github.com/nlohmann/json) - JSON parsing (used internally for shader reflection)
* [Eigen](https://gitlab.com/libeigen/eigen/) - Linear algebra
* [Coal](https://github.com/coal-library/coal) - Collision detection, geometry primitives
* [magic_enum](https://github.com/Neargye/magic_enum) - Enum reflection utilities

These dependencies can be installed from Conda as follows:
```bash
conda install -c conda-forge sdl3 eigen coal magic_enum assimp entt nlohmann_json
```

#### Optional dependencies
Additionally, candlewick depends on the following bundled dependencies:

* [ImGui](https://github.com/ocornut/imgui/) - immediate-mode GUI

### Optional dependencies

#### Python bindings

* [eigenpy](https://github.com/stack-of-tasks/eigenpy) for Python bindings.
* [FFmpeg](https://ffmpeg.org/) for support for recording videos from the rendered graphics. The CMake finder module also requires pkg-config.
```bash
conda install ffmpeg pkg-config
```

*Python runtime dependencies:* `numpy`

#### Pinocchio support

Required for the `candlewick::multibody` classes and functions:

* [Pinocchio](https://github.com/stack-of-tasks/pinocchio), **must** be built with collision support.
`conda install -c conda-forge pinocchio`

*Python runtime dependencies:* `pinocchio` (Python bindings)

Additional dependencies for the `candlewick-visualizer` runtime:

* [cppzmq](https://github.com/zeromq/cppzmq) - C++ ZeroMQ bindings
* [msgpack-cxx](https://github.com/msgpack/msgpack-c/tree/cpp_master) - MessagePack serialization

*Python runtime dependencies:* `pyzmq msgspec`

#### Video recording

* [FFmpeg](https://ffmpeg.org/) for support for recording videos from the rendered graphics. | `conda install ffmpeg pkg-config` | The following components are required:
* `libavformat` - Container format handling
* `libavcodec` - Video encoding/decoding
* `libswscale` - Image scaling and format conversion

#### Development dependencies (tests, examples)

* [GoogleTest](https://github.com/google/googletest) for the tests | `conda install gtest`
* [CLI11](https://github.com/CLIUtils/CLI11) for the examples and tests | `conda install cli11`
* The [Pinocchio](https://github.com/stack-of-tasks/pinocchio) rigid-body dynamics library (required for the `candlewick::multibody` classes and functions). Pinocchio must be built with collision support. | `conda install -c conda-forge pinocchio`
* With Pinocchio support activated, building the tests requires [example-robot-data](https://github.com/Gepetto/example-robot-data) | `conda install -c conda-forge example-robot-data`
* <u>With Pinocchio support</u>: building the C++ examples requires [example-robot-data](https://github.com/Gepetto/example-robot-data).
`conda install -c conda-forge example-robot-data`

The optional dependencies can be installed from conda:
```bash
conda install -c conda-forge
gtest \ # for testing
ffmpeg pkg-config \ # for FFmpeg support
cli11 \ # for the examples
pinocchio \ # for multibody/Pinocchio support
example-robot-data # for the examples, with the above
```

### Building
## Building Candlewick

For building the library, you will need [CMake](https://cmake.org/) (version at least 3.20) and a C++20-compliant compiler. These can also be obtained through Conda.
For building the library, you will need [CMake](https://cmake.org/) (version at least 3.26) and a C++20-compliant compiler. These can also be obtained through Conda.

In the directory where you have checked out the code, perform the following steps:
```bash
# 1. Create a CMake build directory
cmake -S . -B build/ -DCMAKE_BUILD_TYPE=Release \
cmake -S . -B build/ \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_PINOCCHIO_VISUALIZER:BOOL=ON \ # For Pinocchio support
-DBUILD_PYTHON_BINDINGS:BOOL=ON \ # For Python bindings
-DBUILD_VISUALIZER_RUNTIME:BOOL=ON \ # Async visualizer runtime
-DBUILD_PYTHON_INTERFACE:BOOL=ON \ # For Python bindings
-DGENERATE_PYTHON_STUBS:BOOL=ON \ # Python binding type stubs
-GNinja \ # or -G"Unix Makefiles" to use Make
-DBUILD_TESTING=OFF \ # or ON not build the tests
-DCMAKE_INSTALL_PREFIX=<your-install-prefix> # e.g. ~/.local/, or $CONDA_PREFIX
-DCMAKE_INSTALL_PREFIX=<your-install-prefix> \ # e.g. ~/.local/, or $CONDA_PREFIX
<other-options...>
# 2. Move into it and build (generator-independent)
cd build/ && cmake --build . -j<num-parallel-jobs>
cd build/
cmake --build . -j<num-parallel-jobs>
# 3. Install
cmake --install .
```

### A summary of build options

| Build Option | Default | Description | Additional Dependencies | Requires |
|-------------|---------|-------------|------------------------|----------|
| `BUILD_PYTHON_INTERFACE` | `ON` | Build Python bindings | eigenpy | - |
| `BUILD_PINOCCHIO_VISUALIZER` | `ON` | Enable Pinocchio robot visualization | pinocchio >= 3.5 | - |
| `BUILD_VISUALIZER_RUNTIME` | `OFF` | Build `candlewick-visualizer` executable | cppzmq, msgpack-cxx | `BUILD_PINOCCHIO_VISUALIZER=ON` |
| `BUILD_WITH_FFMPEG_SUPPORT` | `OFF` | Enable video recording capabilities | FFmpeg | - |
| `GENERATE_PYTHON_STUBS` | `OFF` | Generate Python type stubs | *(handled by cmake submodule)* | `BUILD_PYTHON_INTERFACE=ON` |


## Credits

Many of the design choices of this library are heavily inspired by other, more mature work in the open-source 3D graphics middleware space.
Expand All @@ -125,3 +188,13 @@ Here are some of the resources I've looked at:
* the [Magnum](https://magnum.graphics/) graphics middleware (the design ideas around mesh layouts, how to load geometry primitives, and the type-erased `MeshData` type)
* [bgfx](https://github.com/bkaradzic/bgfx/)
* Sascha Willems' Vulkan examples: https://github.com/SaschaWillems/Vulkan/


### Font Credit/License

Candlewick embeds the **Inter Medium** font as part of its source code:

**Inter-Medium.ttf**, by Rasmus Andersson.
SIL OPEN FONT LICENSE Version 1.1
Copyright (c) 2016 The Inter Project Authors
https://rsms.me/inter
2 changes: 1 addition & 1 deletion bindings/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ if(GENERATE_PYTHON_STUBS)
)
endif(GENERATE_PYTHON_STUBS)

set(PYTHON_FILES __init__.py video_context.py)
set(PYTHON_FILES __init__.py async_visualizer.py video_context.py)

foreach(pyfile ${PYTHON_FILES})
PYTHON_INSTALL_ON_SITE(${PROJECT_NAME} ${pyfile})
Expand Down
Loading
Loading