diff --git a/Examples/PDBPicking/CMakeLists.txt b/Examples/PDBPicking/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..17355b81fce860db0699f5899fb289f6b03935e5
--- /dev/null
+++ b/Examples/PDBPicking/CMakeLists.txt
@@ -0,0 +1,37 @@
+###########################################################################
+#
+# Copyright (c) Kitware, Inc.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0.txt
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+###########################################################################
+if(iMSTK_USE_OpenHaptics)
+
+  project(Example-PBDPicking)
+
+  #-----------------------------------------------------------------------------
+  # Create executable
+  #-----------------------------------------------------------------------------
+  imstk_add_executable(${PROJECT_NAME} PBDPickingExample.cpp)
+
+  #-----------------------------------------------------------------------------
+  # Add the target to Examples folder
+  #-----------------------------------------------------------------------------
+  SET_TARGET_PROPERTIES (${PROJECT_NAME} PROPERTIES FOLDER Examples/Haptics)
+  
+  #-----------------------------------------------------------------------------
+  # Link libraries to executable
+  #-----------------------------------------------------------------------------
+  target_link_libraries(${PROJECT_NAME} SimulationManager apiUtilities)
+
+endif()
diff --git a/Examples/PDBPicking/PBDPickingExample.cpp b/Examples/PDBPicking/PBDPickingExample.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1a3037a43accfd1f76170fe2f7e0b78a34028cd9
--- /dev/null
+++ b/Examples/PDBPicking/PBDPickingExample.cpp
@@ -0,0 +1,264 @@
+/*=========================================================================
+
+   Library: iMSTK
+
+   Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
+   & Imaging in Medicine, Rensselaer Polytechnic Institute.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+=========================================================================*/
+
+#include "imstkCamera.h"
+#include "imstkCDObjectFactory.h"
+#include "imstkCollidingObject.h"
+#include "imstkCollisionData.h"
+#include "imstkCollisionGraph.h"
+#include "imstkCollisionPair.h"
+#include "imstkCollisionDetection.h"
+#include "imstkHapticDeviceClient.h"
+#include "imstkHapticDeviceManager.h"
+#include "imstkKeyboardDeviceClient.h"
+#include "imstkKeyboardSceneControl.h"
+#include "imstkLight.h"
+#include "imstkMouseSceneControl.h"
+#include "imstkNew.h"
+#include "imstkPlane.h"
+#include "imstkRenderMaterial.h"
+#include "imstkScene.h"
+#include "imstkSceneManager.h"
+#include "imstkSceneObjectController.h"
+#include "imstkSphere.h"
+#include "imstkVirtualCouplingCH.h"
+#include "imstkVisualModel.h"
+#include "imstkVTKViewer.h"
+
+#include "imstkLogger.h"
+#include "imstkPbdModel.h"
+#include "imstkPbdObject.h"
+#include "imstkSurfaceMesh.h"
+
+#include "imstkPBDPickingCH.h"
+#include "imstkPbdObjectPickingPair.h"
+
+// global variables
+const std::string phantomOmni1Name = "Default Device";
+
+using namespace imstk;
+
+// Parameters to play with
+const double width  = 50.0;
+const double height = 50.0;
+const int    nRows  = 16;
+const int    nCols  = 16;
+
+///
+/// \brief Creates cloth geometry
+///
+static std::shared_ptr<SurfaceMesh>
+makeClothGeometry(const double width,
+                  const double height,
+                  const int    nRows,
+                  const int    nCols)
+{
+    imstkNew<SurfaceMesh> clothMesh;
+
+    StdVectorOfVec3d vertList;
+    vertList.resize(nRows * nCols);
+    const double dy = width / (double)(nCols - 1);
+    const double dx = height / (double)(nRows - 1);
+    for (int i = 0; i < nRows; ++i)
+    {
+        for (int j = 0; j < nCols; j++)
+        {
+            vertList[i * nCols + j] = Vec3d((double)dx * i, 1.0, (double)dy * j);
+        }
+    }
+    clothMesh->setInitialVertexPositions(vertList);
+    clothMesh->setVertexPositions(vertList);
+
+    // Add connectivity data
+    std::vector<SurfaceMesh::TriangleArray> triangles;
+    for (std::size_t i = 0; i < nRows - 1; ++i)
+    {
+        for (std::size_t j = 0; j < nCols - 1; j++)
+        {
+            SurfaceMesh::TriangleArray tri[2];
+            const size_t               index1 = i * nCols + j;
+            const size_t               index2 = index1 + nCols;
+            const size_t               index3 = index1 + 1;
+            const size_t               index4 = index2 + 1;
+
+            // Interleave [/][\]
+            if (i % 2 ^ j % 2)
+            {
+                tri[0] = { { index1, index2, index3 } };
+                tri[1] = { { index4, index3, index2 } };
+            }
+            else
+            {
+                tri[0] = { { index2, index4, index1 } };
+                tri[1] = { { index4, index3, index1 } };
+            }
+            triangles.push_back(tri[0]);
+            triangles.push_back(tri[1]);
+        }
+    }
+
+    clothMesh->setTrianglesVertices(triangles);
+
+    return clothMesh;
+}
+
+///
+/// \brief Creates cloth object
+///
+static std::shared_ptr<PbdObject>
+makeClothObj(const std::string& name,
+             const double       width,
+             const double       height,
+             const int          nRows,
+             const int          nCols)
+{
+    imstkNew<PbdObject> clothObj(name);
+
+    // Setup the Geometry
+    std::shared_ptr<SurfaceMesh> clothMesh(makeClothGeometry(width, height, nRows, nCols));
+
+    // Setup the Parameters
+    imstkNew<PBDModelConfig> pbdParams;
+    pbdParams->enableConstraint(PbdConstraint::Type::Distance, 1.0e2);
+    pbdParams->enableConstraint(PbdConstraint::Type::Dihedral, 1.0e1);
+    pbdParams->m_fixedNodeIds     = { 0, static_cast<size_t>(nCols) - 1 };
+    pbdParams->m_uniformMassValue = width * height / ((double)nRows * (double)nCols);
+    pbdParams->m_gravity    = Vec3d(0.0, -9.8, 0.0);
+    pbdParams->m_defaultDt  = 0.005;
+    pbdParams->m_iterations = 5;
+
+    // Setup the Model
+    imstkNew<PbdModel> pbdModel;
+    pbdModel->setModelGeometry(clothMesh);
+    pbdModel->configure(pbdParams);
+
+    // Setup the VisualModel
+    imstkNew<RenderMaterial> material;
+    material->setBackFaceCulling(false);
+    material->setDisplayMode(RenderMaterial::DisplayMode::WireframeSurface);
+
+    imstkNew<VisualModel> visualModel(clothMesh);
+    visualModel->setRenderMaterial(material);
+
+    // Setup the Object
+    clothObj->addVisualModel(visualModel);
+    clothObj->setPhysicsGeometry(clothMesh);
+    clothObj->setCollidingGeometry(clothMesh);
+    clothObj->setDynamicalModel(pbdModel);
+
+    return clothObj;
+}
+
+///
+/// \brief This example demonstrates the concept of PBD picking
+/// for haptic interaction. NOTE: Requires GeoMagic Touch device
+///
+int
+main()
+{
+    // Setup logger (write to file and stdout)
+    Logger::startLogger();
+
+    // Scene
+    imstkNew<Scene> scene("PBDPicking");
+
+    // Create the virtual coupling object controller
+
+    // Device Server
+    imstkNew<HapticDeviceManager>       server;
+    std::shared_ptr<HapticDeviceClient> client = server->makeDeviceClient(phantomOmni1Name);
+
+    // Object
+    imstkNew<Sphere>            geom(Vec3d(0.0, 0.0, 0.0), 2.0);
+    imstkNew<CollidingObject> obj("VirtualObject");
+    obj->setVisualGeometry(geom);
+    obj->setCollidingGeometry(geom);
+    scene->addSceneObject(obj);
+
+    std::shared_ptr<PbdObject> clothObj = makeClothObj("Cloth", width, height, nRows, nCols);
+    scene->addSceneObject(clothObj);
+
+    // Create and add virtual coupling object controller in the scene
+    imstkNew<SceneObjectController> controller(obj, client);
+    scene->addController(controller);
+
+    // Add interaction pair for pbd picking
+    imstkNew<PbdObjectPickingPair> pair(clothObj, obj, CollisionDetection::Type::PointSetToSphere);
+    scene->getCollisionGraph()->addInteraction(pair);
+
+    // Camera
+    scene->getActiveCamera()->setPosition(Vec3d(200, 200, 200));
+    scene->getActiveCamera()->setFocalPoint(Vec3d(0, 0, 0));
+
+    // Light
+    imstkNew<DirectionalLight> light("light");
+    light->setFocalPoint(Vec3d(5.0, -8.0, -5.0));
+    light->setIntensity(1.0);
+    scene->addLight(light);
+
+    //Run the simulation
+    {
+        // Setup a viewer to render in its own thread
+        imstkNew<VTKViewer> viewer("Viewer");
+        viewer->setActiveScene(scene);
+
+        // Setup a scene manager to advance the scene in its own thread
+        imstkNew<SceneManager> sceneManager("Scene Manager");
+        sceneManager->setActiveScene(scene);
+        viewer->addChildThread(sceneManager); // SceneManager will start/stop with viewer
+
+        viewer->addChildThread(server);
+
+        // Add mouse and keyboard controls to the viewer
+        {
+            imstkNew<MouseSceneControl> mouseControl(viewer->getMouseDevice());
+            mouseControl->setSceneManager(sceneManager);
+            viewer->addControl(mouseControl);
+
+            imstkNew<KeyboardSceneControl> keyControl(viewer->getKeyboardDevice());
+            keyControl->setSceneManager(sceneManager);
+            keyControl->setViewer(viewer);
+            viewer->addControl(keyControl);
+        }
+        // Not perfectly thread safe movement lambda, ijkl movement instead of wasd because d is already used
+        std::shared_ptr<KeyboardDeviceClient> keyDevice = viewer->getKeyboardDevice();
+        connect<Event>(sceneManager, EventType::PreUpdate, [&](Event*)
+        {
+            std::shared_ptr<PBDPickingCH> ch = std::static_pointer_cast<PBDPickingCH>(pair->getCollisionHandlingA());
+            // Activate picking
+            if (keyDevice->getButton('i') == KEY_PRESS)
+            {
+                ch->activatePickConstraints();
+            }
+            // Unpick
+            if (keyDevice->getButton('u') == KEY_PRESS)
+            {
+                ch->removePickConstraints();
+            }
+        });
+
+        // Start viewer running, scene as paused
+        sceneManager->requestStatus(ThreadStatus::Paused);
+        viewer->start();
+    }
+
+    return 0;
+}
diff --git a/Source/CollisionHandling/imstkCollisionHandling.h b/Source/CollisionHandling/imstkCollisionHandling.h
index ec367199aa9ba16ed09e25de9e508a37a0084887..46ffed1cd6f0190cd4e5e9a5a5a4726f8b435c19 100644
--- a/Source/CollisionHandling/imstkCollisionHandling.h
+++ b/Source/CollisionHandling/imstkCollisionHandling.h
@@ -51,6 +51,7 @@ public:
         BoneDrilling,
         SPH,
         PBD,
+        PBDPicking,
         RBD,
         LevelSet
     };
diff --git a/Source/CollisionHandling/imstkPBDPickingCH.cpp b/Source/CollisionHandling/imstkPBDPickingCH.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cae89764e5f8875749a2c3e7c005b948e592c002
--- /dev/null
+++ b/Source/CollisionHandling/imstkPBDPickingCH.cpp
@@ -0,0 +1,130 @@
+/*=========================================================================
+
+Library: iMSTK
+
+Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
+& Imaging in Medicine, Rensselaer Polytechnic Institute.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0.txt
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+=========================================================================*/
+
+#include "imstkPBDPickingCH.h"
+#include "imstkCollisionData.h"
+
+#include "imstkPbdModel.h"
+#include "imstkPbdObject.h"
+#include "imstkSphere.h"
+#include "imstkPointSet.h"
+
+namespace imstk
+{
+PBDPickingCH::PBDPickingCH(const CollisionHandling::Side&       side,
+                           const std::shared_ptr<CollisionData> colData,
+                           std::shared_ptr<PbdObject>           pbdObj,
+                           std::shared_ptr<CollidingObject>     pickObj) :
+    CollisionHandling(Type::PBDPicking, side, colData),
+    m_pbdObj(pbdObj),
+    m_pickObj(pickObj)
+{
+    m_isPicking = false;
+    m_pickedPtIdxOffset.clear();
+}
+
+void
+PBDPickingCH::processCollisionData()
+{
+    CHECK(m_pbdObj != nullptr && m_pickObj != nullptr)
+        << "PBDPickingCH::handleCollision error: "
+        << "no picking collision handling available the object";
+
+    if (m_isPicking)
+    {
+        this->updatePickConstraints();
+    }
+}
+
+void
+PBDPickingCH::updatePickConstraints()
+{
+    if (m_pickedPtIdxOffset.size() == 0)
+    {
+        this->removePickConstraints();
+        return;
+    }
+
+    std::shared_ptr<PbdModel> model = m_pbdObj->getPbdModel();
+    std::shared_ptr<Sphere> pickSphere = std::dynamic_pointer_cast<Sphere>(m_pickObj->getCollidingGeometry());
+    for (auto iter = m_pickedPtIdxOffset.begin(); iter != m_pickedPtIdxOffset.end(); iter++)
+    {
+        model->getCurrentState()->setVertexPosition(iter->first, pickSphere->getPosition() + iter->second);
+    }
+}
+
+void
+PBDPickingCH::addPickConstraints(std::shared_ptr<PbdObject> pbdObj, std::shared_ptr<CollidingObject> pickObj)
+{
+    if (m_colData->MAColData.isEmpty())
+    {
+        return;
+    }
+
+    CHECK(pbdObj != nullptr && pickObj != nullptr)
+        << "PBDPickingCH:addPickConstraints error: "
+        << "no pdb object or colliding object.";
+
+    std::shared_ptr<PbdModel> model = pbdObj->getPbdModel();
+
+    //TODO: extending to other types of geometry
+    std::shared_ptr<Sphere> pickSphere = std::dynamic_pointer_cast<Sphere>(pickObj->getCollidingGeometry());
+    CHECK(pickSphere != nullptr) << "Colliding geometry is not Sphere";
+
+    ParallelUtils::SpinLock lock;
+    ParallelUtils::parallelFor(m_colData->MAColData.getSize(),
+        [&](const size_t idx) {
+            const auto& cd = m_colData->MAColData[idx];
+            const auto& pv = cd.penetrationVector;
+            const auto& relativePos = -pickSphere->getRadius() * pv.normalized();
+
+            lock.lock();
+            m_pickedPtIdxOffset[cd.nodeIdx] = relativePos;
+            //model->setFixedPoint(cd.nodeIdx);
+            model->getCurrentState()->setVertexPosition(cd.nodeIdx, pickSphere->getPosition() + relativePos);
+            lock.unlock();
+    });
+}
+
+void
+PBDPickingCH::removePickConstraints()
+{
+    std::shared_ptr<PbdModel> model = m_pbdObj->getPbdModel();
+    m_isPicking = false;
+    for (auto iter = m_pickedPtIdxOffset.begin(); iter != m_pickedPtIdxOffset.end(); ++iter)
+    {
+        //model->setPointUnfixed(iter->first);
+        //CHECK(model->getInvMass(iter->first) > 0.0)
+        //    << "PBDPickingCH: unable to set invmasses back";
+    }
+    m_pickedPtIdxOffset.clear();
+}
+
+void
+PBDPickingCH::activatePickConstraints()
+{
+    if (!m_colData->MAColData.isEmpty())
+    {        
+        this->addPickConstraints(m_pbdObj, m_pickObj);
+        m_isPicking = true;
+    }
+}
+}
diff --git a/Source/CollisionHandling/imstkPBDPickingCH.h b/Source/CollisionHandling/imstkPBDPickingCH.h
new file mode 100644
index 0000000000000000000000000000000000000000..99fa77244bb2431315d726f43cedb20477a026c6
--- /dev/null
+++ b/Source/CollisionHandling/imstkPBDPickingCH.h
@@ -0,0 +1,89 @@
+/*=========================================================================
+
+   Library: iMSTK
+
+   Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
+   & Imaging in Medicine, Rensselaer Polytechnic Institute.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+=========================================================================*/
+
+#pragma once
+
+#include "imstkCollisionHandling.h"
+
+#include "imstkMath.h"
+namespace imstk
+{
+class CollidingObject;
+class PbdObject;
+struct CollisionData;
+
+///
+/// \class PBDPickingCH
+///
+/// \brief Implements nodal picking for PBD object
+///
+class PBDPickingCH : public CollisionHandling
+{
+public:
+
+    ///
+    /// \brief Constructor
+    ///
+    PBDPickingCH(const Side&                          side,
+                 const std::shared_ptr<CollisionData> colData,
+                 std::shared_ptr<PbdObject>           pbdObj,
+                 std::shared_ptr<CollidingObject>     pickObj);
+
+    PBDPickingCH() = delete;
+
+    ///
+    /// \brief Destructor
+    ///
+    virtual ~PBDPickingCH() override = default;
+
+    ///
+    /// \brief Compute forces based on collision data
+    ///
+    void processCollisionData() override;
+
+    ///
+    /// \brief Add picking constraints for the node that is picked
+    ///
+    void addPickConstraints(std::shared_ptr<PbdObject> pbdObj, std::shared_ptr<CollidingObject> pickObj);
+
+    ///
+    /// \brief Update picking constraints for the node that is picked
+    ///
+    void updatePickConstraints();
+
+    ///
+    /// \brief Remove picking constraints for the node that is picked
+    ///
+    void removePickConstraints();
+
+    ///
+    /// \brief Activate picking constraints for nodes in the collision data 
+    ///
+    void activatePickConstraints();
+
+
+private:
+    bool                                m_isPicking;
+    std::map<size_t, Vec3d>             m_pickedPtIdxOffset; ///> Map for picked nodes.
+    std::shared_ptr<PbdObject>          m_pbdObj;            ///> PBD object
+    std::shared_ptr<CollidingObject>    m_pickObj;           ///> Picking tool object
+};
+}
diff --git a/Source/DynamicalModels/ObjectModels/imstkPbdModel.cpp b/Source/DynamicalModels/ObjectModels/imstkPbdModel.cpp
index e95368d560fe689b565016ae2c1a86631c27a3c9..59e930ed8a700dd773742630873643e1da6f870d 100644
--- a/Source/DynamicalModels/ObjectModels/imstkPbdModel.cpp
+++ b/Source/DynamicalModels/ObjectModels/imstkPbdModel.cpp
@@ -41,6 +41,7 @@ namespace imstk
 PbdModel::PbdModel() : DynamicalModel(DynamicalModelType::PositionBasedDynamics),
     m_mass(std::make_shared<StdVectorOfReal>()),
     m_invMass(std::make_shared<StdVectorOfReal>()),
+    m_fixedNodeInvMass(std::make_shared<std::map<size_t, double>>()),
     m_constraints(std::make_shared<PBDConstraintVector>()),
     m_partitionedConstraints(std::make_shared<std::vector<PBDConstraintVector>>()),
     m_parameters(std::make_shared<PBDModelConfig>())
@@ -663,13 +664,27 @@ PbdModel::setParticleMass(const double val, const size_t idx)
 void
 PbdModel::setFixedPoint(const size_t idx)
 {
-    StdVectorOfReal& invMasses = *m_invMass;
+    StdVectorOfReal&          invMasses = *m_invMass;
+    std::map<size_t, double>& fixedNodeInvMass = *m_fixedNodeInvMass;
     if (idx < m_mesh->getNumVertices())
     {
+        fixedNodeInvMass[idx] = invMasses[idx];
         invMasses[idx] = 0.0;
     }
 }
 
+void
+PbdModel::setPointUnfixed(const size_t idx)
+{
+    StdVectorOfReal&          invMasses = *m_invMass;
+    std::map<size_t, double>& fixedNodeInvMass = *m_fixedNodeInvMass;
+    if (fixedNodeInvMass.find(idx) != fixedNodeInvMass.end())
+    {
+        invMasses[idx] = fixedNodeInvMass[idx];
+        fixedNodeInvMass.erase(idx);
+    }
+}
+
 void
 PbdModel::integratePosition()
 {
diff --git a/Source/DynamicalModels/ObjectModels/imstkPbdModel.h b/Source/DynamicalModels/ObjectModels/imstkPbdModel.h
index 641797c75ed9dcb577a1acda8f5a3a78caaf068e..e560e65e9fcfa3509a556c207b66f65fc4776f6a 100644
--- a/Source/DynamicalModels/ObjectModels/imstkPbdModel.h
+++ b/Source/DynamicalModels/ObjectModels/imstkPbdModel.h
@@ -26,6 +26,8 @@
 #include "imstkPbdFEMConstraint.h"
 #include "imstkPbdState.h"
 
+#include <map>
+
 namespace imstk
 {
 class PointSet;
@@ -209,10 +211,15 @@ public:
     void setParticleMass(const double val, const size_t idx);
 
     ///
-    /// \brief Se the node as fixed
+    /// \brief Set the node as fixed
     ///
     void setFixedPoint(const size_t idx);
 
+    ///
+    /// \brief Set the node as unfixed
+    ///
+    void setPointUnfixed(const size_t idx);
+
     ///
     /// \brief Get the inverse of mass of a certain node
     ///
@@ -273,10 +280,11 @@ protected:
     bool   m_partitioned = false;                                                         /// \todo this is used in initialize() as a temporary fix to problems on linux
     size_t m_partitionThreshold = 16;                                                     ///> Threshold for constraint partitioning
 
-    std::shared_ptr<PbdSolver>       m_pbdSolver = nullptr;                               ///> PBD solver
-    std::shared_ptr<PointSet>        m_mesh      = nullptr;                               ///> PointSet on which the pbd model operates on
-    std::shared_ptr<StdVectorOfReal> m_mass      = nullptr;                               ///> Mass of nodes
-    std::shared_ptr<StdVectorOfReal> m_invMass   = nullptr;                               ///> Inverse of mass of nodes
+    std::shared_ptr<PbdSolver>                m_pbdSolver = nullptr;                      ///> PBD solver
+    std::shared_ptr<PointSet>                 m_mesh      = nullptr;                      ///> PointSet on which the pbd model operates on
+    std::shared_ptr<StdVectorOfReal>          m_mass      = nullptr;                      ///> Mass of nodes
+    std::shared_ptr<StdVectorOfReal>          m_invMass   = nullptr;                      ///> Inverse of mass of nodes
+    std::shared_ptr<std::map<size_t, double>> m_fixedNodeInvMass = nullptr;               ///> Map for archiving fixed nodes' mass.
 
     std::shared_ptr<PBDConstraintVector> m_constraints = nullptr;                         ///> List of pbd constraints
     std::shared_ptr<std::vector<PBDConstraintVector>> m_partitionedConstraints = nullptr; ///> List of pbd constraints
diff --git a/Source/Scene/imstkObjectInteractionFactory.cpp b/Source/Scene/imstkObjectInteractionFactory.cpp
index 34b4fc302311904e70c426cd03f89fc47fb91d72..80b9cd1ece2734e9f346739e61373aea98e776ea 100644
--- a/Source/Scene/imstkObjectInteractionFactory.cpp
+++ b/Source/Scene/imstkObjectInteractionFactory.cpp
@@ -26,6 +26,8 @@ limitations under the License.
 #include "imstkFeDeformableObject.h"
 #include "imstkPbdObject.h"
 #include "imstkPbdObjectCollisionPair.h"
+#include "imstkPbdObjectPickingPair.h"
+#include "imstkPBDPickingCH.h"
 #include "imstkPenaltyCH.h"
 #include "imstkPickingCH.h"
 #include "imstkImplicitGeometryToPointSetCD.h"
@@ -51,6 +53,10 @@ makeObjectInteractionPair(std::shared_ptr<CollidingObject> obj1, std::shared_ptr
     {
         results = std::make_shared<PbdObjectCollisionPair>(std::dynamic_pointer_cast<PbdObject>(obj1), std::dynamic_pointer_cast<PbdObject>(obj2), cdType);
     }
+    else if (intType == InteractionType::PbdObjToCollidingObjPicking && isType<PbdObject>(obj1))
+    {
+        results = std::make_shared<PbdObjectPickingPair>(std::dynamic_pointer_cast<PbdObject>(obj1), std::dynamic_pointer_cast<CollidingObject>(obj2), cdType);
+    }
     //else if (intType == InteractionType::PbdObjToCollidingObjCollision && isType<PbdObject>(obj1))
     //{
     //    results = std::make_shared<PbdCollidingObjCollisionPair>(
diff --git a/Source/Scene/imstkObjectInteractionFactory.h b/Source/Scene/imstkObjectInteractionFactory.h
index 1f3fec2c58f3a7d69e4a2b0efee21f34aa24c97a..4d097cc78839948e682b329efc71e53feca2f0d3 100644
--- a/Source/Scene/imstkObjectInteractionFactory.h
+++ b/Source/Scene/imstkObjectInteractionFactory.h
@@ -32,6 +32,7 @@ class ObjectInteractionPair;
 enum class InteractionType
 {
     PbdObjToPbdObjCollision,
+    PbdObjToCollidingObjPicking,
 
     PbdObjToCollidingObjCollision,
     SphObjToCollidingObjCollision,
diff --git a/Source/Scene/imstkPbdObjectPickingPair.cpp b/Source/Scene/imstkPbdObjectPickingPair.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7fb9f26039e786eac0bdcace7f5f85476b064d53
--- /dev/null
+++ b/Source/Scene/imstkPbdObjectPickingPair.cpp
@@ -0,0 +1,52 @@
+/*=========================================================================
+
+Library: iMSTK
+
+Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
+& Imaging in Medicine, Rensselaer Polytechnic Institute.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0.txt
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+=========================================================================*/
+
+#include "imstkPbdObjectPickingPair.h"
+#include "imstkCDObjectFactory.h"
+#include "imstkCollisionData.h"
+#include "imstkPBDPickingCH.h"
+#include "imstkPbdModel.h"
+#include "imstkPbdObject.h"
+#include "imstkPbdSolver.h"
+#include "imstkTaskGraph.h"
+
+namespace imstk
+{
+// Pbd Collision will be tested before any step of pbd, then resolved after the solve steps of the two objects
+PbdObjectPickingPair::PbdObjectPickingPair(std::shared_ptr<PbdObject> obj1, std::shared_ptr<CollidingObject> obj2,
+                                               CollisionDetection::Type cdType) : CollisionPair(obj1, obj2)
+{
+    // Setup the CD
+    m_colData = std::make_shared<CollisionData>();
+    setCollisionDetection(makeCollisionDetectionObject(cdType, obj1->getCollidingGeometry(), obj2->getCollidingGeometry(), m_colData));
+
+    // Setup the handler
+    std::shared_ptr<PBDPickingCH> ch = std::make_shared<PBDPickingCH>(CollisionHandling::Side::A, m_colData, obj1, obj2);
+    setCollisionHandlingA(ch);
+}
+
+void
+PbdObjectPickingPair::apply()
+{
+    // Add the collision interaction
+    CollisionPair::apply();
+}
+}
\ No newline at end of file
diff --git a/Source/Scene/imstkPbdObjectPickingPair.h b/Source/Scene/imstkPbdObjectPickingPair.h
new file mode 100644
index 0000000000000000000000000000000000000000..1cbc91a9931cd188c7ea9da34737744ba6e3f9fa
--- /dev/null
+++ b/Source/Scene/imstkPbdObjectPickingPair.h
@@ -0,0 +1,52 @@
+/*=========================================================================
+
+Library: iMSTK
+
+Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
+& Imaging in Medicine, Rensselaer Polytechnic Institute.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0.txt
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+=========================================================================*/
+
+#pragma once
+
+#include "imstkCollisionPair.h"
+#include "imstkCollisionDetection.h"
+
+namespace imstk
+{
+class PbdObject;
+class PbdSolver;
+
+///
+/// \class PbdObjectCollisionPair
+///
+/// \brief This class defines a collision interaction between two PbdObjects
+///
+class PbdObjectPickingPair : public CollisionPair
+{
+public:
+    PbdObjectPickingPair(std::shared_ptr<PbdObject> obj1, std::shared_ptr<CollidingObject> obj2,
+                         CollisionDetection::Type cdType = CollisionDetection::Type::PointSetToSphere);
+
+    virtual ~PbdObjectPickingPair() override = default;
+
+    void apply() override;
+
+private:
+    // Pbd defines two interactions (one at CD and one at solver)
+    Inputs  m_solveNodeInputs;
+    Outputs m_solveNodeOutputs;
+};
+}
\ No newline at end of file