-
Notifications
You must be signed in to change notification settings - Fork 146
PSMoveService Update Walkthrough
* `m_request_handler.update()`
* `m_device_manager.update()`
* `m_network_manager.update()`
Update any async requests still waiting to complete. Iterate through m_connection_state_map
. If the connection state has a pending bluetooth request then update that. TODO: As pending bluetooth requests are unique to the controller, we may need to add functionality here for tracker and HMD.
DeviceManager::update()
calls each specific manager's .poll()
, .updateStateAndPredict()
, and .publish()
in a specific order. These methods are described in more detail in the sections below about the Device<Type>Manager
s.
Process incoming/outgoing networking requests.
ServerNetworkManagerImpl::poll()
calls start_udp_queued_data_frame_write()
(see below) and m_io_service.poll()
to handle the callbacks. This continues as long as has_queued_controller_data_frames_ready_to_start()
. TODO: Keep polling as long as there are ANY data frames ready to start, not just controller.
start_udp_queued_data_frame_write()
iterates through m_connections
, calling start_udp_write_queued_controller_data_frame()
on each one. TODO: start ALL device data frames.
ServerNetworkManagerImpl::start_udp_write_queued_controller_data_frame()
checks m_pending_dataframes
(currently device-specific) and if not empty, pulls out a ControllerDataFramePtr
, packs it, and sends it to async udp write with callback &ClientConnection::handle_udp_write_controller_data_frame_complete
. This just pops the frame from the queue if completed.
The ControllerDataFramePtr
gets added to the queue below (see add_controller_data_frame_to_write_queue(...)
). ControllerDataFramePtr
is a std::shared_ptr of PSMoveProtocol::ControllerDataFrame
, which is created by protobuf. See the wiki page about PSMoveProtocol.
During the application loop we call m_device_manager.update()
. We glossed over this above but we will go into more detail here. This function has the following contents.
m_controller_manager.poll(); // Update controller counts and poll button/IMU state
m_tracker_manager.poll(); // Update tracker count and poll video frames
m_hmd_manager.poll(); // Update HMD count and poll position/orientation state
m_tracker_manager.updateStateAndPredict(); // Get controller colors and update tracking blob positions/predictions
m_controller_manager.updateStateAndPredict(); // Compute pose/prediction of tracking blob+IMU state
m_hmd_manager.updateStateAndPredict(); // Get the pose + prediction for HMD
m_controller_manager.publish(); // publish controller state to any listening clients (common case)
m_tracker_manager.publish(); // publish tracker state to any listening clients (probably only used by ConfigTool)
m_hmd_manager.publish(); // publish hmd state to any listening clients (probably only used by ConfigTool)
Each m__manager is an instance of the respective DeviceManager, which is a child of DeviceTypeManager
.
Each m__manager.poll() is handled by the parent class method.
This calls poll_devices()
and update_connected_devices()
if sufficient time has elapsed (poll_interval
and reconnect_interval
). poll_devices()
simply iterates through each device in m_devices
and calls its poll()
. Each m_device is a pointer to a ServerDeviceView (see below). update_connected_devices()
adds/removes devices to the m_devices
list; this is device-type-specific.
This will derive a state from the data and update a model that allows prediction. This is just a wrapper around the (ServerDeviceViewPtr) device->updateStateAndPredict()
which is purely virtual and implemented by the device-specific views.
- Allocate a
DeviceEnumerator
(specific enumerator allocated by derivedDeviceTypeManager
) - Process device shuffling or attachments
- See if any devices shuffled order OR if any new devices were attached.
- Migrate open devices to a new temp list in the order that they appear in the device enumerator.
- Process device removal
- Close any remaining open controllers not listed in the device enumerator.
- Copy over any closed controllers to the temp.
- Copy the temp controller list back over top the original list.
-
send_device_list_changed_notification()
is device_type-agnostic.
-
- Free the device enumerator
- Send notification to connected clients if the device list changed
This simply iterates through each device in m_devices
and calls its publish()
.
Let's look at each derived DeviceTypeManager.
Derived DeviceTypeManager that manages all connected controller types. Creates a ControllerDeviceEnumerator
when scanning for connected controllers. Specific controller views can be accessed from this manager. Currently the only supported controller type is the PSMoveController.
Derived DeviceTypeManager that manages all connected camera types. Creates a TrackerDeviceEnumerator
when scanning for connected camera. Specific tracker views can be accessed from this manager. Controller connections can't be updated while a controller pairing request is running. Currently the only supported tracker type is the PS3EyeTracker.
Derived DeviceTypeManager that manages all connected HMD types. Creates a HMDDeviceEnumerator
when scanning for connected HMDs. Specific tracker views can be accessed from this manager. Currently the only supported tracker type is the DK2.
Next we will look at the device poll()
and publish()
methods of of the devices which are called during DeviceTypeManager::poll_devices()
and DeviceTypeManager::publish()
, respectively. These are called on the upcast form of the device so we call the generic ServerDeviceView
parent class methods.
This gets the (upcast) *IDeviceInterface
with getDevice()
then calls its ->poll()
method. If polling was successful, then we mark the device as having an unpublished state. IDeviceInterface::poll()
is virtual and must be implemented by each specific Interface (see below for details of the devices).
A wrapper around ServerDeviceView::publish_device_data_frame()
. This is device specific and is implemented by the child class. It will tell the instance of the ServerRequestHandler
to publish_<type>_data_frame
with a type-specific callback (e.g., &ServerControllerView::generate_controller_data_frame_for_stream
) that is called for each listening connection.
Let's look at the device-specific implementations, including updateStateAndPredict()
called during DeviceTypeManager::updateStateAndPredict()
.
Currently does nothing. TODO: Update state space model.
ServerRequestHandler::get_instance()->publish_controller_data_frame(...)
. For each connection id,state , get a new ControllerDataFramePtr and send it with the ServerControllerView through the callback to build the frame, then ServerNetworkManager::get_instance()->send_controller_data_frame(connection_id, data_frame)
to send it across the network.
Callback: ServerControllerView::generate_controller_data_frame_for_stream
calls generate_psmove_data_frame_for_stream
(or alternative for navi). This does all the work of actually filling out the data_frame to be transmitted with the current state information pulled from the hardware. This makes heavy use of PSMoveProtocol.
ServerNetworkManagerImpl::send_controller_data_frame(connection_id, data_frame)
finds the right connection, then connection->add_controller_data_frame_to_write_queue(data_frame)
which simply calls m_pending_dataframes.push_back(data_frame)
, and finally start_udp_queued_data_frame_write()
which we mentioned above.
This does all the work in communicating with the hardware and copying information to a state.
Currently does nothing.
TODO: Implement ServerRequestHandler::get_instance()->publish_tracker_data_frame(...)
. This will call ServerNetworkManager::get_instance()->send_tracker_data_frame(connection_id, data_frame);
TODO: TrackerDataFramePtr.
TODO: Implement ServerNetworkManager::send_tracker_data_frame
. Adds the frame to the write queue and starts the UDP write. Does this have to be device-type-specific? What about just overloading using the data_frame argument type?
TODO: Implement ServerTrackerView::generate_tracker_data_frame_for_stream
TODO: Implement PSMoveTracker in PSMoveTracker.cpp, including poll()
.
Currently does nothing.
TODO: Implement ServerRequestHandler::get_instance()->publish_tracker_data_frame(...)
. This will call ServerNetworkManager::get_instance()->send_hmd_data_frame(connection_id, data_frame);
TODO: Implement ServerNetworkManager::send_hmd_data_frame
.
TODO: Implement ServerTrackerView::generate_hmd_data_frame_for_stream
TODO: Implement PSMoveHMD in PSMoveHMD.cpp, including poll()
.