Commit 3f39e262 authored by Pierre Bürki's avatar Pierre Bürki
Browse files

Add HeadSpaceRS master from github

parent 7d6e48a0
Loading
Loading
Loading
Loading

.gitattributes

0 → 100644
+63 −0
Original line number Diff line number Diff line
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs     diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following 
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln       merge=binary
#*.csproj    merge=binary
#*.vbproj    merge=binary
#*.vcxproj   merge=binary
#*.vcproj    merge=binary
#*.dbproj    merge=binary
#*.fsproj    merge=binary
#*.lsproj    merge=binary
#*.wixproj   merge=binary
#*.modelproj merge=binary
#*.sqlproj   merge=binary
#*.wwaproj   merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg   binary
#*.png   binary
#*.gif   binary

###############################################################################
# diff behavior for common document formats
# 
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the 
# entries below.
###############################################################################
#*.doc   diff=astextplain
#*.DOC   diff=astextplain
#*.docx  diff=astextplain
#*.DOCX  diff=astextplain
#*.dot   diff=astextplain
#*.DOT   diff=astextplain
#*.pdf   diff=astextplain
#*.PDF   diff=astextplain
#*.rtf   diff=astextplain
#*.RTF   diff=astextplain

.gitignore

0 → 100644
+17 −0
Original line number Diff line number Diff line
obj/
bin/HeadRoomRS_debug.exp
*.db
.vs/
.vscode/
x64/
*.exp
bin/HeadSpaceRS.ipdb
bin/HeadSpaceRS.iobj
*.bag
bin/DLLS/
bin/fmodex64.dll
bin/fmodexL64.dll
bin/FreeImage.dll
bin/HeadSpaceRS*.*
HeadSpaceRS.vcxproj.user
icon.aps

Helper.cpp

0 → 100644
+459 −0
Original line number Diff line number Diff line
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.

#pragma once

#include <iostream>
#include <iomanip>
#include <map>
#include <utility>
#include <vector>
#include <librealsense2/rs.hpp>

/**
	The how_to class provides several functions for common usages of the sensor API
*/
class how_to
{
public:
	static rs2::device get_a_realsense_device()
	{
		// First, create a rs2::context.
		// The context represents the current platform with respect to connected devices
		rs2::context ctx;

		// Using the context we can get all connected devices in a device list
		rs2::device_list devices = ctx.query_devices();

		rs2::device selected_device;
		if (devices.size() == 0)
		{
			std::cerr << "No device connected, please connect a RealSense device" << std::endl;

			//To help with the boilerplate code of waiting for a device to connect
			//The SDK provides the rs2::device_hub class
			rs2::device_hub device_hub(ctx);

			//Using the device_hub we can block the program until a device connects
			selected_device = device_hub.wait_for_device();
		}
		else
		{
			std::cout << "Found the following devices:\n" << std::endl;

			// device_list is a "lazy" container of devices which allows
			//The device list provides 2 ways of iterating it
			//The first way is using an iterator (in this case hidden in the Range-based for loop)
			int index = 0;
			for (rs2::device device : devices)
			{
				std::cout << "  " << index++ << " : " << get_device_name(device) << std::endl;
			}

			uint32_t selected_device_index = get_user_selection("Select a device by index: ");

			// The second way is using the subscript ("[]") operator:
			if (selected_device_index >= devices.size())
			{
				throw std::out_of_range("Selected device index is out of range");
			}

			// Update the selected device
			selected_device = devices[selected_device_index];
		}

		return selected_device;
	}

	static void print_device_information(const rs2::device& dev)
	{
		// Each device provides some information on itself
		// The different types of available information are represented using the "RS2_CAMERA_INFO_*" enum

		std::cout << "Device information: " << std::endl;
		//The following code shows how to enumerate all of the RS2_CAMERA_INFO
		//Note that all enum types in the SDK start with the value of zero and end at the "*_COUNT" value
		for (int i = 0; i < static_cast<int>(RS2_CAMERA_INFO_COUNT); i++)
		{
			rs2_camera_info info_type = static_cast<rs2_camera_info>(i);
			//SDK enum types can be streamed to get a string that represents them
			std::cout << "  " << std::left << std::setw(20) << info_type << " : ";

			//A device might not support all types of RS2_CAMERA_INFO.
			//To prevent throwing exceptions from the "get_info" method we first check if the device supports this type of info
			if (dev.supports(info_type))
				std::cout << dev.get_info(info_type) << std::endl;
			else
				std::cout << "N/A" << std::endl;
		}
	}

	static std::string get_device_name(const rs2::device& dev)
	{
		// Each device provides some information on itself, such as name:
		std::string name = "Unknown Device";
		if (dev.supports(RS2_CAMERA_INFO_NAME))
			name = dev.get_info(RS2_CAMERA_INFO_NAME);

		// and the serial number of the device:
		std::string sn = "########";
		if (dev.supports(RS2_CAMERA_INFO_SERIAL_NUMBER))
			sn = std::string("#") + dev.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);

		return name + " " + sn;
	}

	static std::string get_sensor_name(const rs2::sensor& sensor)
	{
		// Sensors support additional information, such as a human readable name
		if (sensor.supports(RS2_CAMERA_INFO_NAME))
			return sensor.get_info(RS2_CAMERA_INFO_NAME);
		else
			return "Unknown Sensor";
	}

	static rs2::sensor get_a_sensor_from_a_device(const rs2::device& dev)
	{
		// A rs2::device is a container of rs2::sensors that have some correlation between them.
		// For example:
		//    * A device where all sensors are on a single board
		//    * A Robot with mounted sensors that share calibration information

		// Given a device, we can query its sensors using:
		std::vector<rs2::sensor> sensors = dev.query_sensors();

		std::cout << "Device consists of " << sensors.size() << " sensors:\n" << std::endl;
		int index = 0;
		// We can now iterate the sensors and print their names
		for (rs2::sensor sensor : sensors)
		{
			std::cout << "  " << index++ << " : " << get_sensor_name(sensor) << std::endl;
		}

		uint32_t selected_sensor_index = get_user_selection("Select a sensor by index: ");

		// The second way is using the subscript ("[]") operator:
		if (selected_sensor_index >= sensors.size())
		{
			throw std::out_of_range("Selected sensor index is out of range");
		}

		return  sensors[selected_sensor_index];
	}

	static rs2_option get_sensor_option(const rs2::sensor& sensor)
	{
		// Sensors usually have several options to control their properties
		//  such as Exposure, Brightness etc.

		std::cout << "Sensor supports the following options:\n" << std::endl;

		// The following loop shows how to iterate over all available options
		// Starting from 0 until RS2_OPTION_COUNT (exclusive)
		for (int i = 0; i < static_cast<int>(RS2_OPTION_COUNT); i++)
		{
			rs2_option option_type = static_cast<rs2_option>(i);
			//SDK enum types can be streamed to get a string that represents them
			std::cout << "  " << i << ": " << option_type;

			// To control an option, use the following api:

			// First, verify that the sensor actually supports this option
			if (sensor.supports(option_type))
			{
				std::cout << std::endl;

				// Get a human readable description of the option
				const char* description = sensor.get_option_description(option_type);
				std::cout << "       Description   : " << description << std::endl;

				// Get the current value of the option
				float current_value = sensor.get_option(option_type);
				std::cout << "       Current Value : " << current_value << std::endl;

				//To change the value of an option, please follow the change_sensor_option() function
			}
			else
			{
				std::cout << " is not supported" << std::endl;
			}
		}

		uint32_t selected_sensor_option = get_user_selection("Select an option by index: ");
		if (selected_sensor_option >= static_cast<int>(RS2_OPTION_COUNT))
		{
			throw std::out_of_range("Selected option is out of range");
		}
		return static_cast<rs2_option>(selected_sensor_option);
	}

	static float get_depth_units(const rs2::sensor& sensor)
	{
		//A Depth stream contains an image that is composed of pixels with depth information.
		//The value of each pixel is the distance from the camera, in some distance units.
		//To get the distance in units of meters, each pixel's value should be multiplied by the sensor's depth scale
		//Here is the way to grab this scale value for a "depth" sensor:
		if (rs2::depth_sensor dpt_sensor = sensor.as<rs2::depth_sensor>())
		{
			float scale = dpt_sensor.get_depth_scale();
			std::cout << "Scale factor for depth sensor is: " << scale << std::endl;
			return scale;
		}
		else
			throw std::runtime_error("Given sensor is not a depth sensor");
	}

	static void get_field_of_view(const rs2::stream_profile& stream)
	{
		// A sensor's stream (rs2::stream_profile) is in general a stream of data with no specific type.
		// For video streams (streams of images), the sensor that produces the data has a lens and thus has properties such
		//  as a focal point, distortion, and principal point.
		// To get these intrinsics parameters, we need to take a stream and first check if it is a video stream
		if (auto video_stream = stream.as<rs2::video_stream_profile>())
		{
			try
			{
				//If the stream is indeed a video stream, we can now simply call get_intrinsics()
				rs2_intrinsics intrinsics = video_stream.get_intrinsics();

				auto principal_point = std::make_pair(intrinsics.ppx, intrinsics.ppy);
				auto focal_length = std::make_pair(intrinsics.fx, intrinsics.fy);
				rs2_distortion model = intrinsics.model;

				std::cout << "Principal Point         : " << principal_point.first << ", " << principal_point.second << std::endl;
				std::cout << "Focal Length            : " << focal_length.first << ", " << focal_length.second << std::endl;
				std::cout << "Distortion Model        : " << model << std::endl;
				std::cout << "Distortion Coefficients : [" << intrinsics.coeffs[0] << "," << intrinsics.coeffs[1] << "," <<
					intrinsics.coeffs[2] << "," << intrinsics.coeffs[3] << "," << intrinsics.coeffs[4] << "]" << std::endl;
			}
			catch (const std::exception& e)
			{
				std::cerr << "Failed to get intrinsics for the given stream. " << e.what() << std::endl;
			}
		}
		else if (auto motion_stream = stream.as<rs2::motion_stream_profile>())
		{
			try
			{
				//If the stream is indeed a motion stream, we can now simply call get_motion_intrinsics()
				rs2_motion_device_intrinsic intrinsics = motion_stream.get_motion_intrinsics();

				std::cout << " Scale X      cross axis      cross axis  Bias X \n";
				std::cout << " cross axis    Scale Y        cross axis  Bias Y  \n";
				std::cout << " cross axis    cross axis     Scale Z     Bias Z  \n";
				for (int i = 0; i < 3; i++)
				{
					for (int j = 0; j < 4; j++)
					{
						std::cout << intrinsics.data[i][j] << "    ";
					}
					std::cout << "\n";
				}

				std::cout << "Variance of noise for X, Y, Z axis \n";
				for (int i = 0; i < 3; i++)
					std::cout << intrinsics.noise_variances[i] << " ";
				std::cout << "\n";

				std::cout << "Variance of bias for X, Y, Z axis \n";
				for (int i = 0; i < 3; i++)
					std::cout << intrinsics.bias_variances[i] << " ";
				std::cout << "\n";
			}
			catch (const std::exception& e)
			{
				std::cerr << "Failed to get intrinsics for the given stream. " << e.what() << std::endl;
			}
		}
		else
		{
			std::cerr << "Given stream profile has no intrinsics data" << std::endl;
		}
	}

	static void get_extrinsics(const rs2::stream_profile& from_stream, const rs2::stream_profile& to_stream)
	{
		// If the device/sensor that you are using contains more than a single stream, and it was calibrated
		// then the SDK provides a way of getting the transformation between any two streams (if such exists)
		try
		{
			// Given two streams, use the get_extrinsics_to() function to get the transformation from the stream to the other stream
			rs2_extrinsics extrinsics = from_stream.get_extrinsics_to(to_stream);
			std::cout << "Translation Vector : [" << extrinsics.translation[0] << "," << extrinsics.translation[1] << "," << extrinsics.translation[2] << "]\n";
			std::cout << "Rotation Matrix    : [" << extrinsics.rotation[0] << "," << extrinsics.rotation[3] << "," << extrinsics.rotation[6] << "]\n";
			std::cout << "                   : [" << extrinsics.rotation[1] << "," << extrinsics.rotation[4] << "," << extrinsics.rotation[7] << "]\n";
			std::cout << "                   : [" << extrinsics.rotation[2] << "," << extrinsics.rotation[5] << "," << extrinsics.rotation[8] << "]" << std::endl;
		}
		catch (const std::exception& e)
		{
			std::cerr << "Failed to get extrinsics for the given streams. " << e.what() << std::endl;
		}
	}

	static void change_sensor_option(const rs2::sensor& sensor, rs2_option option_type)
	{
		// Sensors usually have several options to control their properties
		//  such as Exposure, Brightness etc.

		// To control an option, use the following api:

		// First, verify that the sensor actually supports this option
		if (!sensor.supports(option_type))
		{
			std::cerr << "This option is not supported by this sensor" << std::endl;
			return;
		}

		// Each option provides its rs2::option_range to provide information on how it can be changed
		// To get the supported range of an option we do the following:

		std::cout << "Supported range for option " << option_type << ":" << std::endl;

		rs2::option_range range = sensor.get_option_range(option_type);
		float default_value = range.def;
		float maximum_supported_value = range.max;
		float minimum_supported_value = range.min;
		float difference_to_next_value = range.step;
		std::cout << "  Min Value     : " << minimum_supported_value << std::endl;
		std::cout << "  Max Value     : " << maximum_supported_value << std::endl;
		std::cout << "  Default Value : " << default_value << std::endl;
		std::cout << "  Step          : " << difference_to_next_value << std::endl;

		bool change_option = false;
		change_option = prompt_yes_no("Change option's value?");

		if (change_option)
		{
			std::cout << "Enter the new value for this option: ";
			float requested_value;
			std::cin >> requested_value;
			std::cout << std::endl;

			// To set an option to a different value, we can call set_option with a new value
			try
			{
				sensor.set_option(option_type, requested_value);
			}
			catch (const rs2::error& e)
			{
				// Some options can only be set while the camera is streaming,
				// and generally the hardware might fail so it is good practice to catch exceptions from set_option
				std::cerr << "Failed to set option " << option_type << ". (" << e.what() << ")" << std::endl;
			}
		}
	}

	static rs2::stream_profile choose_a_streaming_profile(const rs2::sensor& sensor)
	{
		// A Sensor is an object that is capable of streaming one or more types of data.
		// For example:
		//    * A stereo sensor with Left and Right Infrared streams that
		//        creates a stream of depth images
		//    * A motion sensor with an Accelerometer and Gyroscope that
		//        provides a stream of motion information

		// Using the sensor we can get all of its streaming profiles
		std::vector<rs2::stream_profile> stream_profiles = sensor.get_stream_profiles();

		// Usually a sensor provides one or more streams which are identifiable by their stream_type and stream_index
		// Each of these streams can have several profiles (e.g FHD/HHD/VGA/QVGA resolution, or 90/60/30 fps, etc..)
		//The following code shows how to go over a sensor's stream profiles, and group the profiles by streams.
		std::map<std::pair<rs2_stream, int>, int> unique_streams;
		for (auto&& sp : stream_profiles)
		{
			unique_streams[std::make_pair(sp.stream_type(), sp.stream_index())]++;
		}
		std::cout << "Sensor consists of " << unique_streams.size() << " streams: " << std::endl;
		for (size_t i = 0; i < unique_streams.size(); i++)
		{
			auto it = unique_streams.begin();
			std::advance(it, i);
			std::cout << "  - " << it->first.first << " #" << it->first.second << std::endl;
		}

		//Next, we go over all the stream profiles and print the details of each one
		std::cout << "Sensor provides the following stream profiles:" << std::endl;
		int profile_num = 0;
		for (rs2::stream_profile stream_profile : stream_profiles)
		{
			// A Stream is an abstraction for a sequence of data items of a
			//  single data type, which are ordered according to their time
			//  of creation or arrival.
			// The stream's data types are represented using the rs2_stream
			//  enumeration
			rs2_stream stream_data_type = stream_profile.stream_type();

			// The rs2_stream provides only types of data which are
			//  supported by the RealSense SDK
			// For example:
			//    * rs2_stream::RS2_STREAM_DEPTH describes a stream of depth images
			//    * rs2_stream::RS2_STREAM_COLOR describes a stream of color images
			//    * rs2_stream::RS2_STREAM_INFRARED describes a stream of infrared images

			// As mentioned, a sensor can have multiple streams.
			// In order to distinguish between streams with the same
			//  stream type we can use the following methods:

			// 1) Each stream type can have multiple occurances.
			//    All streams, of the same type, provided from a single
			//     device have distinct indices:
			int stream_index = stream_profile.stream_index();

			// 2) Each stream has a user-friendly name.
			//    The stream's name is not promised to be unique,
			//     rather a human readable description of the stream
			std::string stream_name = stream_profile.stream_name();

			// 3) Each stream in the system, which derives from the same
			//     rs2::context, has a unique identifier
			//    This identifier is unique across all streams, regardless of the stream type.
			int unique_stream_id = stream_profile.unique_id(); // The unique identifier can be used for comparing two streams
			std::cout << std::setw(3) << profile_num << ": " << stream_data_type << " #" << stream_index;

			// As noted, a stream is an abstraction.
			// In order to get additional data for the specific type of a
			//  stream, a mechanism of "Is" and "As" is provided:
			if (stream_profile.is<rs2::video_stream_profile>()) //"Is" will test if the type tested is of the type given
			{
				// "As" will try to convert the instance to the given type
				rs2::video_stream_profile video_stream_profile = stream_profile.as<rs2::video_stream_profile>();

				// After using the "as" method we can use the new data type
				//  for additinal operations:
				std::cout << " (Video Stream: " << video_stream_profile.format() << " " <<
					video_stream_profile.width() << "x" << video_stream_profile.height() << "@ " << video_stream_profile.fps() << "Hz)";
			}
			std::cout << std::endl;
			profile_num++;
		}

		uint32_t selected_profile_index = get_user_selection("Please select the desired streaming profile: ");
		if (selected_profile_index >= stream_profiles.size())
		{
			throw std::out_of_range("Requested profile index is out of range");
		}

		return stream_profiles[selected_profile_index];
	}

	static bool prompt_yes_no(const std::string& prompt_msg)
	{
		char ans;
		do
		{
			std::cout << prompt_msg << "[y/n]: ";
			std::cin >> ans;
			std::cout << std::endl;
		} while (!std::cin.fail() && ans != 'y' && ans != 'n');
		return ans == 'y';
	}

	static uint32_t get_user_selection(const std::string& prompt_message)
	{
		std::cout << "\n" << prompt_message;
		uint32_t input;
		std::cin >> input;
		std::cout << std::endl;
		return input;
	}
};
 No newline at end of file

LICENSE.md

0 → 100644
+22 −0
Original line number Diff line number Diff line
**kinectServer** is distributed under the [MIT License](https://en.wikipedia.org/wiki/MIT_License). This gives everyone the freedoms to use kinectServer in any context: commercial or non-commercial, public or private, open or closed source.

---

Copyright (c) 2014 - beamStreamer.com

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

---

kinectServer is based on openFrameworks and thus also ships with a mix of the following [libraries](docs/libraries.md), depending on your platform, which may have different licenses.

* [OpenGL](http://www.opengl.org/), [GLEW](http://glew.sourceforge.net/), [GLUT](http://www.opengl.org/resources/libraries/glut/), [libtess2](https://code.google.com/p/libtess2/) and [cairo](http://cairographics.org/) for graphics
* [rtAudio](http://www.music.mcgill.ca/~gary/rtaudio/), [PortAudio](http://www.portaudio.com/) or [FMOD](http://www.fmod.org/)  and [Kiss FFT](http://kissfft.sourceforge.net/) for audio input, output and analysis
* [FreeType](http://freetype.sourceforge.net/index2.html) for fonts
* [FreeImage](http://freeimage.sourceforge.net/) for image saving and loading
* [Quicktime](http://developer.apple.com/quicktime/), [Unicap](http://unicap-imaging.org/), [GStreamer](http://gstreamer.freedesktop.org/) and [videoInput](https://github.com/ofTheo/videoInput) for video playback and grabbing
* [Poco](http://pocoproject.org/) for a variety of utilities
 No newline at end of file

addons.make

0 → 100644
+5 −0
Original line number Diff line number Diff line
ofxGuiExtended
ofxNetwork
ofxOpenCv
ofxOsc
ofxRealSenseTwo
Loading