Skip to content

Add Candlewick runtime (executable) #37

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 10 additions & 1 deletion examples/Visualizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,33 @@
#include <CLI/Formatter.hpp>
#include <CLI/Config.hpp>

namespace cdw = candlewick;
using namespace candlewick::multibody;
using std::chrono::steady_clock;

int main(int argc, char **argv) {
CLI::App app{"Visualizer example"};
argv = app.ensure_utf8(argv);
std::vector<Uint32> window_dims{1920u, 1080u};
double fps;

app.add_option("--dims", window_dims, "Window dimensions.")
->capture_default_str();
app.add_option<double, unsigned int>("--fps", fps, "Framerate")
->default_val(60);

CLI11_PARSE(app, argc, argv);

if (window_dims.size() != 2) {
cdw::terminate_with_message("Expected only two values for argument --dims");
}

pin::Model model;
pin::GeometryModel geom_model;
robot_descriptions::loadModelsFromToml("ur.toml", "ur5_gripper", model,
&geom_model, NULL);

Visualizer visualizer{{1920, 1280}, model, geom_model};
Visualizer visualizer{{window_dims[0], window_dims[1]}, model, geom_model};
assert(!visualizer.hasExternalData());
visualizer.addFrameViz(model.getFrameId("elbow_joint"));
visualizer.addFrameViz(model.getFrameId("ee_link"));
Expand Down
9 changes: 9 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Copyright (c) 2024-2025 ManifoldFR

find_package(ZeroMQ REQUIRED)

add_library(
candlewick_core
SHARED
Expand Down Expand Up @@ -111,6 +113,13 @@ if(BUILD_PINOCCHIO_VISUALIZER)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

find_package(cppzmq)
add_executable(candlewick_visualizer candlewick/runtime/main.cpp)
target_link_libraries(
candlewick_visualizer
PRIVATE cppzmq candlewick_multibody
)
endif()

# install headers
Expand Down
13 changes: 13 additions & 0 deletions src/candlewick/multibody/VisualizerClient.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include "Multibody.h"
#include <pinocchio/visualizers/base-visualizer.hpp>
#include <zmq.h>

namespace candlewick {
namespace multibody {
class VisualizerClient final : public pin::visualizers::BaseVisualizer {
public:
};
} // namespace multibody
} // namespace candlewick
63 changes: 63 additions & 0 deletions src/candlewick/runtime/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include <zmq.hpp>
#include <zmq_addon.hpp>
#include "candlewick/multibody/Multibody.h"
#include "candlewick/multibody/Visualizer.h"

#include <pinocchio/serialization/model.hpp>
#include <pinocchio/serialization/geometry.hpp>

#include <CLI/App.hpp>
#include <CLI/Formatter.hpp>
#include <CLI/Config.hpp>

namespace cdw = candlewick;
namespace pin = pinocchio;
using cdw::multibody::Visualizer;

int main(int argc, char **argv) {
CLI::App app{"Candlewick visualizer runtime"};
argv = app.ensure_utf8(argv);

std::vector<Uint32> window_dims{1920u, 1080u};
app.add_option("--dims", window_dims, "Window dimensions.")
->capture_default_str();

CLI11_PARSE(app, argc, argv);

if (window_dims.size() != 2) {
cdw::terminate_with_message("Expected only two values for argument --dims");
}

zmq::context_t ctx;
zmq::socket_t sock{ctx, zmq::socket_type::pull};
sock.bind("tcp://127.0.0.1:12000");
const std::string endpoint = sock.get(zmq::sockopt::last_endpoint);
printf("ZMQ endpoint: %s\n", endpoint.c_str());

pin::Model model;
pin::GeometryModel geom_model;

std::vector<zmq::message_t> recv_models;

printf("Receiving Model and GeometryModel...\n");

const auto ret = zmq::recv_multipart(sock, std::back_inserter(recv_models));
assert(*ret == 2);
printf("Received %zu messages\n", ret.value());

model.loadFromString(recv_models[0].to_string());
geom_model.loadFromString(recv_models[1].to_string());

Visualizer::Config config;
config.width = window_dims[0];
config.height = window_dims[1];
Visualizer viz{config, model, geom_model};

Eigen::VectorXd q0 = pin::neutral(model);

while (!viz.shouldExit()) {
viz.display(q0);
}

return 0;
}
19 changes: 19 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import pinocchio as pin
import example_robot_data as erd
import zmq


PORT = 12000

ctx = zmq.Context.instance()
sock: zmq.Socket = ctx.socket(zmq.SocketType.PUSH)
sock.connect(f"tcp://127.0.0.1:{PORT}")

robot: pin.RobotWrapper = erd.load("solo12")
model = robot.model
geom_model = robot.visual_model

model_str = model.saveToString()
geom_str = geom_model.saveToString()
sock.send_multipart([model_str.encode(), geom_str.encode()])
print("Sent")
Loading