{"action":"created","comment":{"url":"https://api.github.com/repos/personalrobotics/prpy/pulls/comments/78287022","id":78287022,"diff_hunk":"@@ -2129,3 +2129,50 @@ def GetPointFrom(focus):\n         raise ValueError('Focus of the point is an unknown object')\n \n     return coord\n+\n+def concatenateTrajectories(traj_list):\n+    \"\"\"\n+    Given a list of trajectories for a single manipulator,\n+    concatenate them into a single trajectory\n+\n+    @param traj_list List of consective trajectories for a given manipulator\n+    @return base_traj Combined trajectory\n+    \"\"\"\n+    from planning.base import Tags\n+\n+    if len(traj_list) == 0:\n+        raise ValueError('Trajectory list is empty')\n+\n+    base_traj = traj_list[0]\n+    base_cspec = base_traj.GetConfigurationSpecification()\n+    base_robot = base_cspec.ExtractUsedBodies(base_traj.GetEnv())[0]\n+    traj_indices = GetTrajectoryIndices(base_traj)\n+\n+    offset = base_traj.GetNumWaypoints()\n+    for i in xrange(1, len(traj_list)):\n+        traj_i = traj_list[i]\n+        cspec_i = traj_i.GetConfigurationSpecification()\n+        robot_i = cspec_i.ExtractUsedBodies(traj_i.GetEnv())[0]\n+        if robot_i != base_robot:\n+            raise ValueError('Trajectories are not on the same robot')\n+\n+        sub = numpy.subtract(GetTrajectoryIndices(traj_i), traj_indices)\n+        if sub.sum() != 0:\n+            raise ValueError('Trajectories are not on the same manipulator.')\n+\n+        tags_i = GetTrajectoryTags(traj_i)\n+        # If one segment is not smooth, the entire trajectory is not (?)\n+        if 'smooth' in tags_i and not tags_i['smooth']:\n+            SetTrajectoryTags(base_traj, {TAGS.SMOOTH: True}, append=True)\n+\n+        # The entire trajectory gets tagged as constrained if one of \n+        # the segments is constrained.\n+        if 'constrained' in tags_i and tags_i['constrained']:\n+            SetTrajectoryTags(base_traj, {TAGS.CONSTRAINED: True}, append=True)","path":"src/prpy/util.py","position":43,"original_position":43,"commit_id":"50b59026a5157f475f42198213c6061a20fcc3dd","original_commit_id":"50b59026a5157f475f42198213c6061a20fcc3dd","user":{"login":"mkoval","id":142251,"avatar_url":"https://avatars.githubusercontent.com/u/142251?v=3","gravatar_id":"","url":"https://api.github.com/users/mkoval","html_url":"https://github.com/mkoval","followers_url":"https://api.github.com/users/mkoval/followers","following_url":"https://api.github.com/users/mkoval/following{/other_user}","gists_url":"https://api.github.com/users/mkoval/gists{/gist_id}","starred_url":"https://api.github.com/users/mkoval/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mkoval/subscriptions","organizations_url":"https://api.github.com/users/mkoval/orgs","repos_url":"https://api.github.com/users/mkoval/repos","events_url":"https://api.github.com/users/mkoval/events{/privacy}","received_events_url":"https://api.github.com/users/mkoval/received_events","type":"User","site_admin":false},"body":"Replace these repeated calls to `SetTrajectoryTags` with one call at the end. The current logic is incorrect because it will tag a trajectory as `SMOOTH` if *any* of its components are smooth, instead of only when *all* of its components are smooth.\r\n\r\nWe're also missing a few cases. To be complete, here are all of the tags we should handle:\r\n\r\n- `SMOOTH`: `True` if *all* trajectories have this flag set\r\n- `CONSTRAINED`: `True` if *any* trajectory has this flag set\r\n- `DETERMINISTIC_TRAJECTORY`: `True` if *all* trajectories have this flag set\r\n- `DETERMINISTIC_ENDPOINT`: `True` if *the last* trajectory has this flag set\r\n\r\nAll of the flags should default to `False` if they are not set on a trajectory.\r\n\r\nAlso, note that setting these tags is a surprisingly expensive operation. It requires parsing XML, parsing JSON, re-serializing JSON, and re-serializing XML.","created_at":"2016-09-11T02:50:32Z","updated_at":"2016-09-11T02:50:32Z","html_url":"https://github.com/personalrobotics/prpy/pull/354#discussion_r78287022","pull_request_url":"https://api.github.com/repos/personalrobotics/prpy/pulls/354","_links":{"self":{"href":"https://api.github.com/repos/personalrobotics/prpy/pulls/comments/78287022"},"html":{"href":"https://github.com/personalrobotics/prpy/pull/354#discussion_r78287022"},"pull_request":{"href":"https://api.github.com/repos/personalrobotics/prpy/pulls/354"}}},"pull_request":{"url":"https://api.github.com/repos/personalrobotics/prpy/pulls/354","id":83175969,"html_url":"https://github.com/personalrobotics/prpy/pull/354","diff_url":"https://github.com/personalrobotics/prpy/pull/354.diff","patch_url":"https://github.com/personalrobotics/prpy/pull/354.patch","issue_url":"https://api.github.com/repos/personalrobotics/prpy/issues/354","number":354,"state":"open","locked":false,"title":"Feature/concatenate trajs","user":{"login":"rachelholladay","id":8390650,"avatar_url":"https://avatars.githubusercontent.com/u/8390650?v=3","gravatar_id":"","url":"https://api.github.com/users/rachelholladay","html_url":"https://github.com/rachelholladay","followers_url":"https://api.github.com/users/rachelholladay/followers","following_url":"https://api.github.com/users/rachelholladay/following{/other_user}","gists_url":"https://api.github.com/users/rachelholladay/gists{/gist_id}","starred_url":"https://api.github.com/users/rachelholladay/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rachelholladay/subscriptions","organizations_url":"https://api.github.com/users/rachelholladay/orgs","repos_url":"https://api.github.com/users/rachelholladay/repos","events_url":"https://api.github.com/users/rachelholladay/events{/privacy}","received_events_url":"https://api.github.com/users/rachelholladay/received_events","type":"User","site_admin":false},"body":"Util functionality to concatenate a list of trajectories into one trajectory by appending them onto each other. \r\n\r\nRequested by @gilwoolee ","created_at":"2016-08-29T22:04:01Z","updated_at":"2016-09-11T02:50:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b9f1a07d88e1050640b93cff73de3b60c28d5b4f","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/personalrobotics/prpy/pulls/354/commits","review_comments_url":"https://api.github.com/repos/personalrobotics/prpy/pulls/354/comments","review_comment_url":"https://api.github.com/repos/personalrobotics/prpy/pulls/comments{/number}","comments_url":"https://api.github.com/repos/personalrobotics/prpy/issues/354/comments","statuses_url":"https://api.github.com/repos/personalrobotics/prpy/statuses/50b59026a5157f475f42198213c6061a20fcc3dd","head":{"label":"personalrobotics:feature/concatenate_trajs","ref":"feature/concatenate_trajs","sha":"50b59026a5157f475f42198213c6061a20fcc3dd","user":{"login":"personalrobotics","id":4705918,"avatar_url":"https://avatars.githubusercontent.com/u/4705918?v=3","gravatar_id":"","url":"https://api.github.com/users/personalrobotics","html_url":"https://github.com/personalrobotics","followers_url":"https://api.github.com/users/personalrobotics/followers","following_url":"https://api.github.com/users/personalrobotics/following{/other_user}","gists_url":"https://api.github.com/users/personalrobotics/gists{/gist_id}","starred_url":"https://api.github.com/users/personalrobotics/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/personalrobotics/subscriptions","organizations_url":"https://api.github.com/users/personalrobotics/orgs","repos_url":"https://api.github.com/users/personalrobotics/repos","events_url":"https://api.github.com/users/personalrobotics/events{/privacy}","received_events_url":"https://api.github.com/users/personalrobotics/received_events","type":"Organization","site_admin":false},"repo":{"id":21152391,"name":"prpy","full_name":"personalrobotics/prpy","owner":{"login":"personalrobotics","id":4705918,"avatar_url":"https://avatars.githubusercontent.com/u/4705918?v=3","gravatar_id":"","url":"https://api.github.com/users/personalrobotics","html_url":"https://github.com/personalrobotics","followers_url":"https://api.github.com/users/personalrobotics/followers","following_url":"https://api.github.com/users/personalrobotics/following{/other_user}","gists_url":"https://api.github.com/users/personalrobotics/gists{/gist_id}","starred_url":"https://api.github.com/users/personalrobotics/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/personalrobotics/subscriptions","organizations_url":"https://api.github.com/users/personalrobotics/orgs","repos_url":"https://api.github.com/users/personalrobotics/repos","events_url":"https://api.github.com/users/personalrobotics/events{/privacy}","received_events_url":"https://api.github.com/users/personalrobotics/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/personalrobotics/prpy","description":"Python utilities used by the Personal Robotics Laboratory.","fork":false,"url":"https://api.github.com/repos/personalrobotics/prpy","forks_url":"https://api.github.com/repos/personalrobotics/prpy/forks","keys_url":"https://api.github.com/repos/personalrobotics/prpy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/personalrobotics/prpy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/personalrobotics/prpy/teams","hooks_url":"https://api.github.com/repos/personalrobotics/prpy/hooks","issue_events_url":"https://api.github.com/repos/personalrobotics/prpy/issues/events{/number}","events_url":"https://api.github.com/repos/personalrobotics/prpy/events","assignees_url":"https://api.github.com/repos/personalrobotics/prpy/assignees{/user}","branches_url":"https://api.github.com/repos/personalrobotics/prpy/branches{/branch}","tags_url":"https://api.github.com/repos/personalrobotics/prpy/tags","blobs_url":"https://api.github.com/repos/personalrobotics/prpy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/personalrobotics/prpy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/personalrobotics/prpy/git/refs{/sha}","trees_url":"https://api.github.com/repos/personalrobotics/prpy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/personalrobotics/prpy/statuses/{sha}","languages_url":"https://api.github.com/repos/personalrobotics/prpy/languages","stargazers_url":"https://api.github.com/repos/personalrobotics/prpy/stargazers","contributors_url":"https://api.github.com/repos/personalrobotics/prpy/contributors","subscribers_url":"https://api.github.com/repos/personalrobotics/prpy/subscribers","subscription_url":"https://api.github.com/repos/personalrobotics/prpy/subscription","commits_url":"https://api.github.com/repos/personalrobotics/prpy/commits{/sha}","git_commits_url":"https://api.github.com/repos/personalrobotics/prpy/git/commits{/sha}","comments_url":"https://api.github.com/repos/personalrobotics/prpy/comments{/number}","issue_comment_url":"https://api.github.com/repos/personalrobotics/prpy/issues/comments{/number}","contents_url":"https://api.github.com/repos/personalrobotics/prpy/contents/{+path}","compare_url":"https://api.github.com/repos/personalrobotics/prpy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/personalrobotics/prpy/merges","archive_url":"https://api.github.com/repos/personalrobotics/prpy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/personalrobotics/prpy/downloads","issues_url":"https://api.github.com/repos/personalrobotics/prpy/issues{/number}","pulls_url":"https://api.github.com/repos/personalrobotics/prpy/pulls{/number}","milestones_url":"https://api.github.com/repos/personalrobotics/prpy/milestones{/number}","notifications_url":"https://api.github.com/repos/personalrobotics/prpy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/personalrobotics/prpy/labels{/name}","releases_url":"https://api.github.com/repos/personalrobotics/prpy/releases{/id}","deployments_url":"https://api.github.com/repos/personalrobotics/prpy/deployments","created_at":"2014-06-24T04:44:39Z","updated_at":"2016-04-25T14:58:47Z","pushed_at":"2016-09-11T01:20:50Z","git_url":"git://github.com/personalrobotics/prpy.git","ssh_url":"git@github.com:personalrobotics/prpy.git","clone_url":"https://github.com/personalrobotics/prpy.git","svn_url":"https://github.com/personalrobotics/prpy","homepage":"","size":1700,"stargazers_count":6,"watchers_count":6,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":9,"mirror_url":null,"open_issues_count":56,"forks":9,"open_issues":56,"watchers":6,"default_branch":"master"}},"base":{"label":"personalrobotics:master","ref":"master","sha":"19d718454d6c1ceb4c1d9a5bea62d76cb09548e8","user":{"login":"personalrobotics","id":4705918,"avatar_url":"https://avatars.githubusercontent.com/u/4705918?v=3","gravatar_id":"","url":"https://api.github.com/users/personalrobotics","html_url":"https://github.com/personalrobotics","followers_url":"https://api.github.com/users/personalrobotics/followers","following_url":"https://api.github.com/users/personalrobotics/following{/other_user}","gists_url":"https://api.github.com/users/personalrobotics/gists{/gist_id}","starred_url":"https://api.github.com/users/personalrobotics/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/personalrobotics/subscriptions","organizations_url":"https://api.github.com/users/personalrobotics/orgs","repos_url":"https://api.github.com/users/personalrobotics/repos","events_url":"https://api.github.com/users/personalrobotics/events{/privacy}","received_events_url":"https://api.github.com/users/personalrobotics/received_events","type":"Organization","site_admin":false},"repo":{"id":21152391,"name":"prpy","full_name":"personalrobotics/prpy","owner":{"login":"personalrobotics","id":4705918,"avatar_url":"https://avatars.githubusercontent.com/u/4705918?v=3","gravatar_id":"","url":"https://api.github.com/users/personalrobotics","html_url":"https://github.com/personalrobotics","followers_url":"https://api.github.com/users/personalrobotics/followers","following_url":"https://api.github.com/users/personalrobotics/following{/other_user}","gists_url":"https://api.github.com/users/personalrobotics/gists{/gist_id}","starred_url":"https://api.github.com/users/personalrobotics/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/personalrobotics/subscriptions","organizations_url":"https://api.github.com/users/personalrobotics/orgs","repos_url":"https://api.github.com/users/personalrobotics/repos","events_url":"https://api.github.com/users/personalrobotics/events{/privacy}","received_events_url":"https://api.github.com/users/personalrobotics/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/personalrobotics/prpy","description":"Python utilities used by the Personal Robotics Laboratory.","fork":false,"url":"https://api.github.com/repos/personalrobotics/prpy","forks_url":"https://api.github.com/repos/personalrobotics/prpy/forks","keys_url":"https://api.github.com/repos/personalrobotics/prpy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/personalrobotics/prpy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/personalrobotics/prpy/teams","hooks_url":"https://api.github.com/repos/personalrobotics/prpy/hooks","issue_events_url":"https://api.github.com/repos/personalrobotics/prpy/issues/events{/number}","events_url":"https://api.github.com/repos/personalrobotics/prpy/events","assignees_url":"https://api.github.com/repos/personalrobotics/prpy/assignees{/user}","branches_url":"https://api.github.com/repos/personalrobotics/prpy/branches{/branch}","tags_url":"https://api.github.com/repos/personalrobotics/prpy/tags","blobs_url":"https://api.github.com/repos/personalrobotics/prpy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/personalrobotics/prpy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/personalrobotics/prpy/git/refs{/sha}","trees_url":"https://api.github.com/repos/personalrobotics/prpy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/personalrobotics/prpy/statuses/{sha}","languages_url":"https://api.github.com/repos/personalrobotics/prpy/languages","stargazers_url":"https://api.github.com/repos/personalrobotics/prpy/stargazers","contributors_url":"https://api.github.com/repos/personalrobotics/prpy/contributors","subscribers_url":"https://api.github.com/repos/personalrobotics/prpy/subscribers","subscription_url":"https://api.github.com/repos/personalrobotics/prpy/subscription","commits_url":"https://api.github.com/repos/personalrobotics/prpy/commits{/sha}","git_commits_url":"https://api.github.com/repos/personalrobotics/prpy/git/commits{/sha}","comments_url":"https://api.github.com/repos/personalrobotics/prpy/comments{/number}","issue_comment_url":"https://api.github.com/repos/personalrobotics/prpy/issues/comments{/number}","contents_url":"https://api.github.com/repos/personalrobotics/prpy/contents/{+path}","compare_url":"https://api.github.com/repos/personalrobotics/prpy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/personalrobotics/prpy/merges","archive_url":"https://api.github.com/repos/personalrobotics/prpy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/personalrobotics/prpy/downloads","issues_url":"https://api.github.com/repos/personalrobotics/prpy/issues{/number}","pulls_url":"https://api.github.com/repos/personalrobotics/prpy/pulls{/number}","milestones_url":"https://api.github.com/repos/personalrobotics/prpy/milestones{/number}","notifications_url":"https://api.github.com/repos/personalrobotics/prpy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/personalrobotics/prpy/labels{/name}","releases_url":"https://api.github.com/repos/personalrobotics/prpy/releases{/id}","deployments_url":"https://api.github.com/repos/personalrobotics/prpy/deployments","created_at":"2014-06-24T04:44:39Z","updated_at":"2016-04-25T14:58:47Z","pushed_at":"2016-09-11T01:20:50Z","git_url":"git://github.com/personalrobotics/prpy.git","ssh_url":"git@github.com:personalrobotics/prpy.git","clone_url":"https://github.com/personalrobotics/prpy.git","svn_url":"https://github.com/personalrobotics/prpy","homepage":"","size":1700,"stargazers_count":6,"watchers_count":6,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":9,"mirror_url":null,"open_issues_count":56,"forks":9,"open_issues":56,"watchers":6,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/personalrobotics/prpy/pulls/354"},"html":{"href":"https://github.com/personalrobotics/prpy/pull/354"},"issue":{"href":"https://api.github.com/repos/personalrobotics/prpy/issues/354"},"comments":{"href":"https://api.github.com/repos/personalrobotics/prpy/issues/354/comments"},"review_comments":{"href":"https://api.github.com/repos/personalrobotics/prpy/pulls/354/comments"},"review_comment":{"href":"https://api.github.com/repos/personalrobotics/prpy/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/personalrobotics/prpy/pulls/354/commits"},"statuses":{"href":"https://api.github.com/repos/personalrobotics/prpy/statuses/50b59026a5157f475f42198213c6061a20fcc3dd"}}}}
{"actor":{"display_login":"mkoval"}}