diff --git a/CMakeLists.txt b/CMakeLists.txt
index c9df3a80847aac400ebca7725a98c3815a8cc889..6bfe35869e004c7aba00b02817a5f77bf5e0b158 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,6 +13,9 @@ enable_testing()
 
 option(WITH_PCL "Use PCL if available" ON)
 option(WITH_FIXSTARS "Use Fixstars libSGM if available" ON)
+option(BUILD_VISION "Enable the vision component" ON)
+option(BUILD_RECONSTRUCT "Enable the reconstruction component" ON)
+option(BUILD_RENDERER "Enable the renderer component" ON)
 
 set(THREADS_PREFER_PTHREAD_FLAG ON)
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
@@ -109,7 +112,7 @@ check_include_file_cxx("opencv2/cudastereo.hpp" HAVE_OPENCVCUDA)
 find_program(CPPCHECK_FOUND cppcheck)
 if (CPPCHECK_FOUND)
 	message(STATUS "Found cppcheck: will perform source checks")
-	set(CMAKE_CXX_CPPCHECK "cppcheck" "--enable=style" "--suppress=*:*catch.hpp" "--suppress=*:*json.hpp")
+	set(CMAKE_CXX_CPPCHECK "cppcheck" "--enable=style" "--suppress=*:*catch.hpp" "--suppress=*:*elas*" "--suppress=*:*json.hpp")
 endif()
 
 include_directories(${PROJECT_SOURCE_DIR}/common/cpp/include)
@@ -132,10 +135,20 @@ endif()
 SET(CMAKE_USE_RELATIVE_PATHS ON)
 
 add_subdirectory(common/cpp)
-add_subdirectory(renderer)
 add_subdirectory(net)
-add_subdirectory(vision)
-add_subdirectory(reconstruct)
+
+if (BUILD_RENDERER)
+	add_subdirectory(renderer)
+	set(HAVE_RENDER)
+endif()
+
+if (BUILD_VISION)
+	add_subdirectory(vision)
+endif()
+
+if (BUILD_RECONSTRUCT)
+	add_subdirectory(reconstruct)
+endif()
 
 ### Generate Build Configuration Files =========================================
 
diff --git a/common/cpp/include/ftl/config.h.in b/common/cpp/include/ftl/config.h.in
index 3972664ad516136958862583c446dce7414825ed..ca51cebb894ed858580b823201f859aaa5e1f675 100644
--- a/common/cpp/include/ftl/config.h.in
+++ b/common/cpp/include/ftl/config.h.in
@@ -7,6 +7,7 @@
 #cmakedefine HAVE_CUDA
 #cmakedefine HAVE_OPENCV
 #cmakedefine HAVE_PCL
+#cmakedefine HAVE_RENDER
 
 extern const char *FTL_VERSION_LONG;
 extern const char *FTL_VERSION;
diff --git a/common/cpp/src/configuration.cpp b/common/cpp/src/configuration.cpp
index d42d487e9cbb7db6d3351d57a74d42c1342dc4dd..a2674dcb08d101b73a4835dde91d31b97f6865e8 100644
--- a/common/cpp/src/configuration.cpp
+++ b/common/cpp/src/configuration.cpp
@@ -129,20 +129,36 @@ static bool mergeConfig(const string &path) {
  */
 static bool findConfiguration(const string &file, const vector<string> &paths,
 		const std::string &app) {
+	bool f = false;
 	bool found = false;
 	
-	found |= mergeConfig(FTL_GLOBAL_CONFIG_ROOT "/config.json");
-	found |= mergeConfig(FTL_LOCAL_CONFIG_ROOT "/config.json");
-	found |= mergeConfig("./config.json");
+	f = mergeConfig(FTL_GLOBAL_CONFIG_ROOT "/config.json");
+	found |= f;
+	if (f) LOG(INFO) << "Loaded config: " << FTL_GLOBAL_CONFIG_ROOT "/config.json";
+	f = mergeConfig(FTL_LOCAL_CONFIG_ROOT "/config.json");
+	found |= f;
+	if (f) LOG(INFO) << "Loaded config: " << FTL_LOCAL_CONFIG_ROOT "/config.json";
+	f = mergeConfig("./config.json");
+	found |= f;
+	if (f) LOG(INFO) << "Loaded config: " << "./config.json";
 	
 	for (auto p : paths) {
 		if (is_directory(p)) {
-			found |= mergeConfig(p+"/config.json");
+			f = mergeConfig(p+"/config.json");
+			found |= f;
+			if (f) LOG(INFO) << "Loaded config: " << p << "/config.json";
 		}
 	}
 	
 	if (file != "") {
-		found |= mergeConfig(file);
+		f = mergeConfig(file);
+		found |= f;
+
+		if (!f) {
+			LOG(ERROR) << "Specific config file (" << file << ") was not found";
+		} else {
+			LOG(INFO) << "Loaded config: " << file;
+		}
 	}
 
 	if (found) {
diff --git a/net/cpp/include/ftl/net/peer.hpp b/net/cpp/include/ftl/net/peer.hpp
index da30ee52011406d2ee8c3550aae6999c003ec718..339528ead285188c8448f9a9eeab45288ec039b0 100644
--- a/net/cpp/include/ftl/net/peer.hpp
+++ b/net/cpp/include/ftl/net/peer.hpp
@@ -298,7 +298,7 @@ int Peer::asyncCall(
 	
 	// Register the CB
 	callbacks_[rpcid] = std::make_unique<caller<T>>(cb);
-	
+
 	_send();
 	return rpcid;
 }
diff --git a/net/cpp/include/ftl/net/universe.hpp b/net/cpp/include/ftl/net/universe.hpp
index b29dc10ac5f2c39964ba43b54ba8cfa3bbe9e0a4..a92a67bbc84eabbbfd82beb76c747bbbc5b915da 100644
--- a/net/cpp/include/ftl/net/universe.hpp
+++ b/net/cpp/include/ftl/net/universe.hpp
@@ -56,7 +56,7 @@ class Universe {
 	 *
 	 * @param addr URI giving protocol, interface and port
 	 */
-	bool connect(const std::string &addr);
+	Peer *connect(const std::string &addr);
 	
 	int numberOfPeers() const { return peers_.size(); }
 	
@@ -126,6 +126,8 @@ class Universe {
 	bool createResource(const std::string &uri);
 
 	std::optional<ftl::UUID> findOwner(const std::string &res);
+
+	void setLocalID(const ftl::UUID &u) { this_peer = u; };
 	
 	private:
 	void _run();
@@ -138,6 +140,7 @@ class Universe {
 	
 	private:
 	bool active_;
+	ftl::UUID this_peer;
 	nlohmann::json config_;
 	std::mutex net_mutex_;
 	fd_set sfderror_;
@@ -199,7 +202,7 @@ std::optional<R> Universe::findOne(const std::string &name, ARGS... args) {
 
 	std::map<Peer*, int> record;
 	for (auto p : peers_) {
-		record[p] = p->asyncCall<std::optional<R>>(name, handler, std::forward<ARGS>(args)...);
+		record[p] = p->asyncCall<std::optional<R>>(name, handler, args...);
 	}
 	
 	{  // Block thread until async callback notifies us
diff --git a/net/cpp/src/dispatcher.cpp b/net/cpp/src/dispatcher.cpp
index 269db7a6d38de8be0ac8fe25d82b222db63f0c04..a2dfd5ad64ddc9f84b719f633fcd3ef3ab54d5f6 100644
--- a/net/cpp/src/dispatcher.cpp
+++ b/net/cpp/src/dispatcher.cpp
@@ -136,8 +136,8 @@ void ftl::net::Dispatcher::dispatch_notification(Peer &s, msgpack::object const
     if (binding) {
         try {
             auto result = (*binding)(args);
-        } catch (int e) {
-			throw e;
+        } catch (const int &e) {
+			throw &e;
 		}
     } else {
     	LOG(ERROR) << "Missing handler for incoming message";
diff --git a/net/cpp/src/peer.cpp b/net/cpp/src/peer.cpp
index 25a1721cb1af4efbb1341e2c43aeb28e61910f30..2032b5acfc07a0dd52da55e238d3953ce59ef29d 100644
--- a/net/cpp/src/peer.cpp
+++ b/net/cpp/src/peer.cpp
@@ -178,7 +178,8 @@ Peer::Peer(const char *pUri, Dispatcher *d) : uri_(pUri) {
 	scheme_ = uri.getProtocol();
 	if (uri.getProtocol() == URI::SCHEME_TCP) {
 		sock_ = tcpConnect(uri);
-		status_ = kConnecting;
+		if (sock_ != INVALID_SOCKET) status_ = kConnecting;
+		else status_ = kReconnecting;
 	} else if (uri.getProtocol() == URI::SCHEME_WS) {
 		LOG(INFO) << "Websocket connect " << uri.getPath();
 		sock_ = tcpConnect(uri);
diff --git a/net/cpp/src/universe.cpp b/net/cpp/src/universe.cpp
index f6d7e2acba34e6fde82b07a6db7064555512c303..7a09a9b4da86e2ab3b9b70f2b44581e5b8b6c3e4 100644
--- a/net/cpp/src/universe.cpp
+++ b/net/cpp/src/universe.cpp
@@ -18,12 +18,12 @@ using std::optional;
 using std::unique_lock;
 using std::mutex;
 
-Universe::Universe() : active_(true), thread_(Universe::__start, this) {
+Universe::Universe() : active_(true), this_peer(ftl::net::this_peer), thread_(Universe::__start, this) {
 	_installBindings();
 }
 
 Universe::Universe(nlohmann::json &config) :
-		active_(true), config_(config), thread_(Universe::__start, this) {
+		active_(true), this_peer(ftl::net::this_peer), config_(config), thread_(Universe::__start, this) {
 	if (config["listen"].is_array()) {
 		for (auto &l : config["listen"]) {
 			listen(l);
@@ -66,9 +66,9 @@ bool Universe::listen(const string &addr) {
 	return l->isListening();
 }
 
-bool Universe::connect(const string &addr) {
+Peer *Universe::connect(const string &addr) {
 	auto p = new Peer(addr.c_str(), &disp_);
-	if (!p) return false;
+	if (!p) return nullptr;
 	
 	if (p->status() != Peer::kInvalid) {
 		unique_lock<mutex> lk(net_mutex_);
@@ -81,7 +81,7 @@ bool Universe::connect(const string &addr) {
 		peer_ids_[p.id()] = &p;
 	});
 	
-	return p->status() == Peer::kConnecting;
+	return p;
 }
 
 int Universe::_setDescriptors() {
@@ -133,7 +133,7 @@ void Universe::_installBindings() {
 	
 	bind("__owner__", [this](const std::string &res) -> optional<UUID> {
 		LOG(INFO) << "SOMEONE ASKS FOR " << res;
-		if (owned_.count(res) > 0) return ftl::net::this_peer;
+		if (owned_.count(res) > 0) return this_peer;
 		else return {};
 	});
 }
@@ -179,7 +179,7 @@ bool Universe::_subscribe(const std::string &res) {
 	optional<UUID> pid = findOwner(res);
 	
 	if (pid) {
-		return call<bool>(*pid, "__subscribe__", ftl::net::this_peer, res);
+		return call<bool>(*pid, "__subscribe__", this_peer, res);
 	} else {
 		// No resource found
 		LOG(WARNING) << "Subscribe to unknown resource: " << res;
@@ -219,7 +219,7 @@ void Universe::_run() {
 
 		//Some kind of error occured, it is usually possible to recover from this.
 		if (selres < 0) {
-			std::cout << "SELECT ERROR " << selres << std::endl;
+			std::cout << "SELECT ERROR " << selres << " - " << strerror(errno) << std::endl;
 			//return false;
 			continue;
 		} else if (selres == 0) {
diff --git a/net/cpp/test/net_integration.cpp b/net/cpp/test/net_integration.cpp
index 34f01215a63d2ac371d51854b576a68f875ad454..87a23ee27a3d6cba311efcb39c4c87cb7880fd43 100644
--- a/net/cpp/test/net_integration.cpp
+++ b/net/cpp/test/net_integration.cpp
@@ -17,28 +17,31 @@ TEST_CASE("Universe::connect()", "[net]") {
 	Universe b;
 	
 	a.listen("tcp://localhost:7077");
-	sleep_for(milliseconds(100));
+	//sleep_for(milliseconds(100));
 
 	SECTION("valid tcp connection using ipv4") {
-		REQUIRE( b.connect("tcp://127.0.0.1:7077") );
+		auto p = b.connect("tcp://127.0.0.1:7077");
+		REQUIRE( p );
 		
-		sleep_for(milliseconds(200));
+		while (!p->isConnected()) sleep_for(milliseconds(20));
 		
 		REQUIRE( a.numberOfPeers() == 1 );
 		REQUIRE( b.numberOfPeers() == 1 );
 	}
 
 	SECTION("valid tcp connection using hostname") {
-		REQUIRE( b.connect("tcp://localhost:7077") );
+		auto p = b.connect("tcp://localhost:7077");
+		REQUIRE( p );
 		
-		sleep_for(milliseconds(200));
+		while (!p->isConnected()) sleep_for(milliseconds(20));
 		
 		REQUIRE( a.numberOfPeers() == 1 );
 		REQUIRE( b.numberOfPeers() == 1 );
 	}
 
 	SECTION("invalid protocol") {
-		REQUIRE( !b.connect("http://127.0.0.1:7077") );
+		auto p = b.connect("http://127.0.0.1:7077");
+		REQUIRE( !p->isValid() );
 		
 		sleep_for(milliseconds(100));
 		
@@ -88,6 +91,7 @@ TEST_CASE("Universe::broadcast()", "[net]") {
 		b.broadcast("done");
 		
 		sleep_for(milliseconds(100));
+		REQUIRE( !done );
 	}
 	
 	SECTION("no arguments to one peer") {
@@ -167,10 +171,23 @@ TEST_CASE("Universe::findOwner()", "") {
 	SECTION("three peers and one owner") {
 		Universe c;
 		c.connect("tcp://localhost:7077");
+		b.setLocalID(ftl::UUID(7));
 		while (a.numberOfPeers() < 2) sleep_for(milliseconds(20));
 
 		b.createResource("ftl://test");
-		REQUIRE( *(a.findOwner("ftl://test")) == ftl::net::this_peer );
+		REQUIRE( *(a.findOwner("ftl://test")) == ftl::UUID(7) );
+	}
+
+	SECTION("three peers and one owner (2)") {
+		Universe c;
+		c.connect("tcp://localhost:7077");
+		c.setLocalID(ftl::UUID(7));
+		while (a.numberOfPeers() < 2) sleep_for(milliseconds(20));
+
+		c.createResource("ftl://test");
+		auto r = a.findOwner("ftl://test");
+		REQUIRE( r );
+		REQUIRE( *r == ftl::UUID(7) );
 	}
 }
 
diff --git a/net/cpp/test/peer_unit.cpp b/net/cpp/test/peer_unit.cpp
index b7bebbcb1cf3b17db40d4dbc5250b792ec2164e2..583f615d4b9c77735342972116bb15a3bac461fb 100644
--- a/net/cpp/test/peer_unit.cpp
+++ b/net/cpp/test/peer_unit.cpp
@@ -185,7 +185,7 @@ TEST_CASE("Peer(int)", "[]") {
 		
 		sleep_for(milliseconds(50));
 		
-		REQUIRE( s.getFTLVersion() ==  (8 << 16) + (5 << 8) + 2 );
+		REQUIRE( (s.getFTLVersion() ==  (8 << 16) + (5 << 8) + 2) );
 	}
 	
 	SECTION("has correct peer id on full handshake") {
@@ -342,7 +342,7 @@ TEST_CASE("Peer::bind()", "[rpc]") {
 		sleep_for(milliseconds(50));
 		
 		REQUIRE( (done == 55) );
-		REQUIRE( readRPCReturn<int>(0) == 55 );
+		REQUIRE( (readRPCReturn<int>(0) == 55) );
 	}
 
 	SECTION("vector return value") {		
@@ -361,7 +361,7 @@ TEST_CASE("Peer::bind()", "[rpc]") {
 		REQUIRE( (done == 55) );
 
 		auto res = readRPCReturn<vector<int>>(0);
-		REQUIRE( res[1] == 45 );
+		REQUIRE( (res[1] == 45) );
 	}
 }
 
diff --git a/net/cpp/test/uri_unit.cpp b/net/cpp/test/uri_unit.cpp
index e11b320f4c18d599f64ff7361a2e91fcda6c5223..a9fde4e8080ef98732c15149e6bd824dd1b31723 100644
--- a/net/cpp/test/uri_unit.cpp
+++ b/net/cpp/test/uri_unit.cpp
@@ -21,8 +21,8 @@ SCENARIO( "URI() can parse valid URIs", "[utility]" ) {
 		REQUIRE( uri.isValid() );
 		REQUIRE( uri.getScheme() == URI::SCHEME_HTTP );
 		REQUIRE( uri.getHost() == "localhost" );
-		REQUIRE( uri.getPort() == 8080 );
-		REQUIRE (uri.getPath() == "/test/case.html" );
+		REQUIRE( (uri.getPort() == 8080) );
+		REQUIRE( uri.getPath() == "/test/case.html" );
 	}
 
 	GIVEN( "a valid scheme with path and query" ) {
@@ -85,7 +85,7 @@ SCENARIO( "URI::getAttribute() from query" ) {
 
 	GIVEN( "an integer value" ) {
 		URI uri("http://localhost:1000/hello?x=56");
-		REQUIRE( uri.getAttribute<int>("x") == 56 );
+		REQUIRE( (uri.getAttribute<int>("x") == 56) );
 	}
 }
 
diff --git a/reconstruct/src/main.cpp b/reconstruct/src/main.cpp
index 51c346da25e0f367247cc33234a63bbac957e251..6145a65a3689b1710574d12f39d08498a9126137 100644
--- a/reconstruct/src/main.cpp
+++ b/reconstruct/src/main.cpp
@@ -83,6 +83,8 @@ static void run() {
 	
 	while (disp.active()) {
 		Mat idepth;
+
+		net.broadcast("grab");
 		
 		unique_lock<mutex> lk(m);
 		if (depth.cols > 0) {
diff --git a/renderer/cpp/include/ftl/display.hpp b/renderer/cpp/include/ftl/display.hpp
index 58272fa6ae4d6bffce133312ddebdbcf9f4ed147..4301fa92254c271a2c11bcaea5def854c079e04b 100644
--- a/renderer/cpp/include/ftl/display.hpp
+++ b/renderer/cpp/include/ftl/display.hpp
@@ -22,6 +22,11 @@ namespace ftl {
  * Multiple local display options for disparity or point clouds.
  */
 class Display {
+	public:
+	enum style_t {
+		STYLE_NORMAL, STYLE_DISPARITY, STYLE_DEPTH
+	};
+
 	public:
 	explicit Display(nlohmann::json &config);
 	~Display();
@@ -33,6 +38,7 @@ class Display {
 #if defined HAVE_PCL
 	bool render(pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr);
 #endif  // HAVE_PCL
+	bool render(const cv::Mat &img, style_t s=STYLE_NORMAL);
 
 	bool active() const;
 	
diff --git a/renderer/cpp/src/display.cpp b/renderer/cpp/src/display.cpp
index a6cdbf9afaf38588795d8fa8f086a8e9e9d9df56..a908efa29a5618c37b3e0422d9d51db85242e734 100644
--- a/renderer/cpp/src/display.cpp
+++ b/renderer/cpp/src/display.cpp
@@ -157,6 +157,26 @@ bool Display::render(pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr pc) {
 	return true;
 }
 #endif  // HAVE_PCL
+bool Display::render(const cv::Mat &img, style_t s) {
+	if (s == STYLE_NORMAL) {
+		cv::imshow("Image", img);
+	} else if (s = STYLE_DISPARITY) {
+		Mat idepth;
+
+		if ((bool)config_["flip_vert"]) {
+			cv::flip(img, idepth, 0);
+		} else {
+			idepth = img;
+		}
+
+    	idepth.convertTo(idepth, CV_8U, 255.0f / 256.0f);
+
+    	applyColorMap(idepth, idepth, cv::COLORMAP_JET);
+		cv::imshow("Disparity", idepth);
+	}
+
+	return true;
+}
 
 void Display::wait(int ms) {
 	if (config_["points"] && q_.rows != 0) {
diff --git a/vision/include/ftl/calibrate.hpp b/vision/include/ftl/calibrate.hpp
index 79fb310b348db16bbebde7f259e95db17c83b9f8..83a2bd9c139bee3a1920545ff0c9244bae43a2bc 100644
--- a/vision/include/ftl/calibrate.hpp
+++ b/vision/include/ftl/calibrate.hpp
@@ -29,7 +29,12 @@ class Calibrate {
 	// TODO(nick) replace or remove this class.
 	class Settings {
 		public:
-		Settings() : goodInput(false) {}
+		Settings() : calibrationPattern(CHESSBOARD), squareSize(50.0f),
+			nrFrames(30), aspectRatio(1.0f), delay(100), writePoints(false), writeExtrinsics(true),
+			writeGrid(false), calibZeroTangentDist(false), calibFixPrincipalPoint(true),
+			flipVertical(false), showUndistorsed(true), useFisheye(false), fixK1(false),
+			fixK2(false), fixK3(false), fixK4(false), fixK5(false), cameraID(0), atImageList(0),
+			inputType(INVALID), goodInput(false), flag(0) {}
 		enum Pattern { NOT_EXISTING, CHESSBOARD, CIRCLES_GRID, ASYMMETRIC_CIRCLES_GRID };
 		enum InputType { INVALID, CAMERA, VIDEO_FILE, IMAGE_LIST };
 
diff --git a/vision/include/ftl/local.hpp b/vision/include/ftl/local.hpp
index 80b527cc74c50122274f9568c1ce8b5b9ad2b653..9a4204e65bab87eb71af8768decb12d116116b20 100644
--- a/vision/include/ftl/local.hpp
+++ b/vision/include/ftl/local.hpp
@@ -12,7 +12,7 @@ namespace cv {
 namespace ftl {
 class LocalSource {
 	public:
-	LocalSource(nlohmann::json &config);
+	explicit LocalSource(nlohmann::json &config);
 	LocalSource(const std::string &vid, nlohmann::json &config);
 	
 	bool left(cv::Mat &m);
diff --git a/vision/lib/elas/triangle.cpp b/vision/lib/elas/triangle.cpp
index 8de1557bc5c7192530d4594c03d0ef9e90eef72c..14d4a2d03c06537a24547bb8c6c44526964ab207 100644
--- a/vision/lib/elas/triangle.cpp
+++ b/vision/lib/elas/triangle.cpp
@@ -1419,27 +1419,27 @@ void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
   struct osub printsh;
   vertex printvertex;
 
-  printf("triangle x%lx with orientation %d:\n", (unsigned long long) t->tri,
+  printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
          t->orient);
   decode(t->tri[0], printtri);
   if (printtri.tri == m->dummytri) {
     printf("    [0] = Outer space\n");
   } else {
-    printf("    [0] = x%lx  %d\n", (unsigned long long) printtri.tri,
+    printf("    [0] = x%lx  %d\n", (unsigned long) printtri.tri,
            printtri.orient);
   }
   decode(t->tri[1], printtri);
   if (printtri.tri == m->dummytri) {
     printf("    [1] = Outer space\n");
   } else {
-    printf("    [1] = x%lx  %d\n", (unsigned long long) printtri.tri,
+    printf("    [1] = x%lx  %d\n", (unsigned long) printtri.tri,
            printtri.orient);
   }
   decode(t->tri[2], printtri);
   if (printtri.tri == m->dummytri) {
     printf("    [2] = Outer space\n");
   } else {
-    printf("    [2] = x%lx  %d\n", (unsigned long long) printtri.tri,
+    printf("    [2] = x%lx  %d\n", (unsigned long) printtri.tri,
            printtri.orient);
   }
 
@@ -1448,37 +1448,37 @@ void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
     printf("    Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
   else
     printf("    Origin[%d] = x%lx  (%.12g, %.12g)\n",
-           (t->orient + 1) % 3 + 3, (unsigned long long) printvertex,
+           (t->orient + 1) % 3 + 3, (unsigned long) printvertex,
            printvertex[0], printvertex[1]);
   dest(*t, printvertex);
   if (printvertex == (vertex) NULL)
     printf("    Dest  [%d] = NULL\n", (t->orient + 2) % 3 + 3);
   else
     printf("    Dest  [%d] = x%lx  (%.12g, %.12g)\n",
-           (t->orient + 2) % 3 + 3, (unsigned long long) printvertex,
+           (t->orient + 2) % 3 + 3, (unsigned long) printvertex,
            printvertex[0], printvertex[1]);
   apex(*t, printvertex);
   if (printvertex == (vertex) NULL)
     printf("    Apex  [%d] = NULL\n", t->orient + 3);
   else
     printf("    Apex  [%d] = x%lx  (%.12g, %.12g)\n",
-           t->orient + 3, (unsigned long long) printvertex,
+           t->orient + 3, (unsigned long) printvertex,
            printvertex[0], printvertex[1]);
 
   if (b->usesegments) {
     sdecode(t->tri[6], printsh);
     if (printsh.ss != m->dummysub) {
-      printf("    [6] = x%lx  %d\n", (unsigned long long) printsh.ss,
+      printf("    [6] = x%lx  %d\n", (unsigned long) printsh.ss,
              printsh.ssorient);
     }
     sdecode(t->tri[7], printsh);
     if (printsh.ss != m->dummysub) {
-      printf("    [7] = x%lx  %d\n", (unsigned long long) printsh.ss,
+      printf("    [7] = x%lx  %d\n", (unsigned long) printsh.ss,
              printsh.ssorient);
     }
     sdecode(t->tri[8], printsh);
     if (printsh.ss != m->dummysub) {
-      printf("    [8] = x%lx  %d\n", (unsigned long long) printsh.ss,
+      printf("    [8] = x%lx  %d\n", (unsigned long) printsh.ss,
              printsh.ssorient);
     }
   }
@@ -1506,19 +1506,19 @@ void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
   vertex printvertex;
 
   printf("subsegment x%lx with orientation %d and mark %d:\n",
-         (unsigned long long) s->ss, s->ssorient, mark(*s));
+         (unsigned long) s->ss, s->ssorient, mark(*s));
   sdecode(s->ss[0], printsh);
   if (printsh.ss == m->dummysub) {
     printf("    [0] = No subsegment\n");
   } else {
-    printf("    [0] = x%lx  %d\n", (unsigned long long) printsh.ss,
+    printf("    [0] = x%lx  %d\n", (unsigned long) printsh.ss,
            printsh.ssorient);
   }
   sdecode(s->ss[1], printsh);
   if (printsh.ss == m->dummysub) {
     printf("    [1] = No subsegment\n");
   } else {
-    printf("    [1] = x%lx  %d\n", (unsigned long long) printsh.ss,
+    printf("    [1] = x%lx  %d\n", (unsigned long) printsh.ss,
            printsh.ssorient);
   }
 
@@ -1527,28 +1527,28 @@ void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
     printf("    Origin[%d] = NULL\n", 2 + s->ssorient);
   else
     printf("    Origin[%d] = x%lx  (%.12g, %.12g)\n",
-           2 + s->ssorient, (unsigned long long) printvertex,
+           2 + s->ssorient, (unsigned long) printvertex,
            printvertex[0], printvertex[1]);
   sdest(*s, printvertex);
   if (printvertex == (vertex) NULL)
     printf("    Dest  [%d] = NULL\n", 3 - s->ssorient);
   else
     printf("    Dest  [%d] = x%lx  (%.12g, %.12g)\n",
-           3 - s->ssorient, (unsigned long long) printvertex,
+           3 - s->ssorient, (unsigned long) printvertex,
            printvertex[0], printvertex[1]);
 
   decode(s->ss[6], printtri);
   if (printtri.tri == m->dummytri) {
     printf("    [6] = Outer space\n");
   } else {
-    printf("    [6] = x%lx  %d\n", (unsigned long long) printtri.tri,
+    printf("    [6] = x%lx  %d\n", (unsigned long) printtri.tri,
            printtri.orient);
   }
   decode(s->ss[7], printtri);
   if (printtri.tri == m->dummytri) {
     printf("    [7] = Outer space\n");
   } else {
-    printf("    [7] = x%lx  %d\n", (unsigned long long) printtri.tri,
+    printf("    [7] = x%lx  %d\n", (unsigned long) printtri.tri,
            printtri.orient);
   }
 
@@ -1557,14 +1557,14 @@ void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
     printf("    Segment origin[%d] = NULL\n", 4 + s->ssorient);
   else
     printf("    Segment origin[%d] = x%lx  (%.12g, %.12g)\n",
-           4 + s->ssorient, (unsigned long long) printvertex,
+           4 + s->ssorient, (unsigned long) printvertex,
            printvertex[0], printvertex[1]);
   segdest(*s, printvertex);
   if (printvertex == (vertex) NULL)
     printf("    Segment dest  [%d] = NULL\n", 5 - s->ssorient);
   else
     printf("    Segment dest  [%d] = x%lx  (%.12g, %.12g)\n",
-           5 - s->ssorient, (unsigned long long) printvertex,
+           5 - s->ssorient, (unsigned long) printvertex,
            printvertex[0], printvertex[1]);
 }
 
diff --git a/vision/src/algorithms/elas.cpp b/vision/src/algorithms/elas.cpp
index ca37357442b2f7ecfcba7996601ae741cd463392..b99c309c96717739327a488efcdfd2e510c9bbe7 100644
--- a/vision/src/algorithms/elas.cpp
+++ b/vision/src/algorithms/elas.cpp
@@ -35,7 +35,7 @@ void ELAS::compute(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp) {
 	disp = Mat(cv::Size(l.cols, l.rows), CV_32F);
 	Mat dispr(cv::Size(l.cols, l.rows), CV_32F);
 	
-	const int32_t dims[3] = {l.cols,l.rows,lbw.step};
+	const int32_t dims[3] = {l.cols,l.rows,static_cast<int32_t>(lbw.step)};
 	
 	if (disp.step/sizeof(float) != lbw.step) LOG(WARNING) << "Incorrect disparity step";
 
diff --git a/vision/src/calibrate.cpp b/vision/src/calibrate.cpp
index 7151a01bb2dfab9fa7b480612c3839f344e666a7..e5025a9d85a0c2470e504e11e7a8ffaa146914e7 100644
--- a/vision/src/calibrate.cpp
+++ b/vision/src/calibrate.cpp
@@ -491,7 +491,7 @@ static double computeReprojectionErrors(
 		vector<float>& perViewErrors, bool fisheye) {
     vector<Point2f> imagePoints2;
     size_t totalPoints = 0;
-    double totalErr = 0, err;
+    double totalErr = 0;
     perViewErrors.resize(objectPoints.size());
 
     for (size_t i = 0; i < objectPoints.size(); ++i) {
@@ -502,7 +502,7 @@ static double computeReprojectionErrors(
             projectPoints(objectPoints[i], rvecs[i], tvecs[i], cameraMatrix,
             		distCoeffs, imagePoints2);
         }
-        err = norm(imagePoints[i], imagePoints2, NORM_L2);
+        double err = norm(imagePoints[i], imagePoints2, NORM_L2);
 
         size_t n = objectPoints[i].size();
         perViewErrors[i] = static_cast<float>(std::sqrt(err*err/n));
@@ -576,10 +576,6 @@ static bool _runCalibration(const Calibrate::Settings& s, Size& imageSize,
             tvecs.push_back(_tvecs.row(i));
         }
     } else {
-        int iFixedPoint = -1;
-        if (release_object)
-            iFixedPoint = s.boardSize.width - 1;
-
         rms = calibrateCamera(objectPoints, imagePoints, imageSize,
                                 cameraMatrix, distCoeffs, rvecs, tvecs,
                                 s.flag | CALIB_USE_LU);
diff --git a/vision/src/main.cpp b/vision/src/main.cpp
index 0665b797cdb017c09dbafdfcf5f0dd9011f5ead4..c71940a6c4a42b109a6e1bfdc41017eb593d579b 100644
--- a/vision/src/main.cpp
+++ b/vision/src/main.cpp
@@ -108,11 +108,24 @@ static void run(const string &file) {
 		return buf;
 	});
 
+	Mat l, r, disp;
+	bool grabbed = false;
+	mutex datam;
+	condition_variable datacv;
+
+	// Wait for grab message to sync camera capture
+	net.bind("grab", [&calibrate,&l,&r,&datam,&datacv,&grabbed]() -> void {
+		unique_lock<mutex> datalk(datam);
+		if (grabbed) return;
+		calibrate.rectified(l, r);
+		grabbed = true;
+		datacv.notify_one();
+	});
+
     // Choose and configure disparity algorithm
     auto disparity = Disparity::create(config["disparity"]);
     if (!disparity) LOG(FATAL) << "Unknown disparity algorithm : " << config["disparity"];
 
-	Mat l, r, disp;
 	Mat pl, pdisp;
 	vector<unsigned char> rgb_buf;
 	vector<unsigned char> d_buf;
@@ -130,23 +143,22 @@ static void run(const string &file) {
 		condition_variable cv;
 		int jobs = 0;
 
-		// Pipeline for disparity
-		pool.push([&](int id) {
-			auto start = std::chrono::high_resolution_clock::now();
-			// Read calibrated images.
+		// Fake grab if no peers to allow visualisation locally
+		if (net.numberOfPeers() == 0) {
+			grabbed = true;
 			calibrate.rectified(l, r);
+		}
 
-			// Feed into sync buffer and network forward
-			//sync->feed(ftl::LEFT, l, lsrc->getTimestamp());
-			//sync->feed(ftl::RIGHT, r, lsrc->getTimestamp());
-
-			// Read back from buffer
-			//sync->get(ftl::LEFT, l);
-			//sync->get(ftl::RIGHT, r);
+		// Pipeline for disparity
+		pool.push([&](int id) {
+			// Wait for image grab
+			unique_lock<mutex> datalk(datam);
+			datacv.wait(datalk, [&grabbed](){ return grabbed; });
+			grabbed = false;
 
-			LOG(INFO) << "PRE DISPARITY";
+			auto start = std::chrono::high_resolution_clock::now();
 		    disparity->compute(l, r, disp);
-			LOG(INFO) << "POST DISPARITY";
+			datalk.unlock();
 
 			unique_lock<mutex> lk(m);
 			jobs++;
@@ -158,50 +170,6 @@ static void run(const string &file) {
 			LOG(INFO) << "Disparity in " << elapsed.count() << "s";
 		});
 
-		// Pipeline for jpeg compression
-		/*pool.push([&](int id) {
-			auto start = std::chrono::high_resolution_clock::now();
-			if (pl.rows != 0) cv::imencode(".jpg", pl, rgb_buf);
-			unique_lock<mutex> lk(m);
-			jobs++;
-			lk.unlock();
-			cv.notify_one();
-
-			std::chrono::duration<double> elapsed =
-				std::chrono::high_resolution_clock::now() - start;
-			LOG(INFO) << "JPG in " << elapsed.count() << "s";
-		});*/
-
-		// Pipeline for zlib compression
-		/*pool.push([&](int id) {
-			auto start = std::chrono::high_resolution_clock::now();
-			if (pl.rows != 0) {
-				d_buf.resize(pdisp.step*pdisp.rows);
-				z_stream defstream;
-				defstream.zalloc = Z_NULL;
-				defstream.zfree = Z_NULL;
-				defstream.opaque = Z_NULL;
-				defstream.avail_in = pdisp.step*pdisp.rows;
-				defstream.next_in = (Bytef *)pdisp.data; // input char array
-				defstream.avail_out = (uInt)pdisp.step*pdisp.rows; // size of output
-				defstream.next_out = (Bytef *)d_buf.data(); // output char array
-				
-				deflateInit(&defstream, Z_BEST_COMPRESSION);
-				deflate(&defstream, Z_FINISH);
-				deflateEnd(&defstream);
-				
-				d_buf.resize(defstream.total_out);
-			}
-			unique_lock<mutex> lk(m);
-			jobs++;
-			lk.unlock();
-			cv.notify_one();
-
-			std::chrono::duration<double> elapsed =
-				std::chrono::high_resolution_clock::now() - start;
-			LOG(INFO) << "ZLIB in " << elapsed.count() << "s";
-		});*/
-
 		// Pipeline for stream compression
 		pool.push([&](int id) {
 			auto start = std::chrono::high_resolution_clock::now();